diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml new file mode 100644 index 000000000..cfdf18885 --- /dev/null +++ b/.github/workflows/docker-build.yml @@ -0,0 +1,42 @@ +name: Build Docker image + +on: + pull_request: + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: pokeapi/pokeapi + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v3 + - name: Inspect builder + run: | + echo "Name: ${{ steps.buildx.outputs.name }}" + echo "Endpoint: ${{ steps.buildx.outputs.endpoint }}" + echo "Status: ${{ steps.buildx.outputs.status }}" + echo "Flags: ${{ steps.buildx.outputs.flags }}" + echo "Platforms: ${{ steps.buildx.outputs.platforms }}" + - name: Build + id: docker_build + uses: docker/build-push-action@v5 + with: + context: . + file: ./Resources/docker/app/Dockerfile + push: false + platforms: local + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + - name: Image digest + run: echo ${{ steps.docker_build.outputs.digest }} diff --git a/Makefile b/Makefile index d5e03209e..61964bc99 100755 --- a/Makefile +++ b/Makefile @@ -70,6 +70,9 @@ docker-stop: # (Docker) Stop containers docker-down: # (Docker) Stop and removes containers and networks docker-compose down +docker-test: # (Docker) Run tests + docker-compose exec -T app python manage.py test ${local_config} + docker-prod: docker-compose -f docker-compose.yml -f docker-compose.override.yml -f Resources/compose/docker-compose-prod-graphql.yml up -d diff --git a/__init__.py b/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/config/docker-compose.py b/config/docker-compose.py index e13860050..896854be6 100644 --- a/config/docker-compose.py +++ b/config/docker-compose.py @@ -24,6 +24,5 @@ } DEBUG = False -TASTYPIE_FULL_DEBUG = False ALLOWED_HOSTS = ["*"] diff --git a/config/docker.py b/config/docker.py index 707510deb..663974929 100755 --- a/config/docker.py +++ b/config/docker.py @@ -24,4 +24,3 @@ } DEBUG = True -TASTYPIE_FULL_DEBUG = True diff --git a/config/local.py b/config/local.py index 4f1f3c221..42f070e38 100755 --- a/config/local.py +++ b/config/local.py @@ -14,4 +14,3 @@ } DEBUG = True -TASTYPIE_FULL_DEBUG = True diff --git a/config/settings.py b/config/settings.py index 64cd60be8..5a1e7f2bb 100755 --- a/config/settings.py +++ b/config/settings.py @@ -86,10 +86,7 @@ "SECRET_KEY", "ubx+22!jbo(^x2_scm-o$*py3e@-awu-n^hipkm%2l$sw$&2l#" ) -CUSTOM_APPS = ( - "tastypie", - "pokemon_v2", -) +CUSTOM_APPS = ("pokemon_v2",) INSTALLED_APPS = ( "django.contrib.auth", @@ -97,6 +94,7 @@ "django.contrib.sessions", "django.contrib.sites", "django.contrib.admin", + "django.contrib.messages", "django.contrib.humanize", "corsheaders", "rest_framework", @@ -106,8 +104,6 @@ API_LIMIT_PER_PAGE = 1 -TASTYPIE_DEFAULT_FORMATS = ["json"] - CORS_ORIGIN_ALLOW_ALL = True CORS_ALLOW_METHODS = "GET" @@ -115,9 +111,26 @@ CORS_URLS_REGEX = r"^/api/.*$" REST_FRAMEWORK = { - "DEFAULT_RENDERER_CLASSES": ("drf_ujson.renderers.UJSONRenderer",), - "DEFAULT_PARSER_CLASSES": ("drf_ujson.renderers.UJSONRenderer",), + "DEFAULT_RENDERER_CLASSES": ("rest_framework.renderers.JSONRenderer",), + "DEFAULT_PARSER_CLASSES": ("rest_framework.renderers.JSONRenderer",), "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination", "PAGE_SIZE": 20, "PAGINATE_BY": 20, } + + +TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + ], + }, + }, +] diff --git a/data/v2/build.py b/data/v2/build.py index 586e701c3..a9b7e5e17 100644 --- a/data/v2/build.py +++ b/data/v2/build.py @@ -499,9 +499,7 @@ def csv_record_to_objects(info): item_sprites = "items/{0}" sprites = {"default": file_path_or_none(item_sprites.format(file_name))} - yield ItemSprites( - id=int(info[0]), item_id=int(info[0]), sprites=json.dumps(sprites) - ) + yield ItemSprites(id=int(info[0]), item_id=int(info[0]), sprites=sprites) build_generic((ItemSprites,), "items.csv", csv_record_to_objects) @@ -1901,7 +1899,7 @@ def csv_record_to_objects(info): yield PokemonSprites( id=int(info[0]), pokemon=Pokemon.objects.get(pk=int(info[0])), - sprites=json.dumps(sprites), + sprites=sprites, ) build_generic((PokemonSprites,), "pokemon.csv", csv_record_to_objects) @@ -2024,7 +2022,7 @@ def csv_record_to_objects(info): ), } yield PokemonFormSprites( - id=int(info[0]), pokemon_form_id=int(info[0]), sprites=json.dumps(sprites) + id=int(info[0]), pokemon_form_id=int(info[0]), sprites=sprites ) build_generic((PokemonFormSprites,), "pokemon_forms.csv", csv_record_to_objects) diff --git a/pokemon_v2/migrations/0014_auto_20231121_1209.py b/pokemon_v2/migrations/0014_auto_20231121_1209.py new file mode 100644 index 000000000..ffdb93ba1 --- /dev/null +++ b/pokemon_v2/migrations/0014_auto_20231121_1209.py @@ -0,0 +1,27 @@ +# Generated by Django 3.1.14 on 2023-11-21 12:09 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("pokemon_v2", "0013_pokemonabilitypast"), + ] + + operations = [ + migrations.AlterField( + model_name="itemsprites", + name="sprites", + field=models.JSONField(), + ), + migrations.AlterField( + model_name="pokemonsprites", + name="sprites", + field=models.JSONField(), + ), + migrations.AlterField( + model_name="pokemonformsprites", + name="sprites", + field=models.JSONField(), + ), + ] diff --git a/pokemon_v2/models.py b/pokemon_v2/models.py index 4bd349c88..ed6622dc3 100644 --- a/pokemon_v2/models.py +++ b/pokemon_v2/models.py @@ -882,7 +882,7 @@ class ItemGameIndex(HasItem, HasGeneration, HasGameIndex): class ItemSprites(HasItem): - sprites = models.CharField(max_length=1000) + sprites = models.JSONField() #################### @@ -1716,7 +1716,7 @@ class PokemonFormName(HasPokemonForm, IsName): class PokemonFormSprites(HasPokemonForm): - sprites = models.CharField(max_length=1000) + sprites = models.JSONField() class PokemonGameIndex(HasPokemon, HasGameIndex, HasVersion): @@ -1795,4 +1795,4 @@ class PokemonTypePast(HasPokemon, HasType, HasGeneration): class PokemonSprites(HasPokemon): - sprites = models.CharField(max_length=20000) + sprites = models.JSONField() diff --git a/pokemon_v2/serializers.py b/pokemon_v2/serializers.py index 40821c323..b1acff77c 100644 --- a/pokemon_v2/serializers.py +++ b/pokemon_v2/serializers.py @@ -1417,10 +1417,7 @@ def get_item_machines(self, obj): def get_item_sprites(self, obj): sprites_object = ItemSprites.objects.get(item_id=obj) - sprites_data = ItemSpritesSerializer(sprites_object, context=self.context).data - sprites_data = json.loads(sprites_data["sprites"]) - - return sprites_data + return sprites_object.sprites def get_item_attributes(self, obj): item_attribute_maps = ItemAttributeMap.objects.filter(item=obj) @@ -2518,12 +2515,7 @@ def get_pokemon_form_pokemon_names(self, obj): def get_pokemon_form_sprites(self, obj): sprites_object = PokemonFormSprites.objects.get(pokemon_form_id=obj) - sprites_data = PokemonFormSpritesSerializer( - sprites_object, context=self.context - ).data - sprites_data = json.loads(sprites_data["sprites"]) - - return sprites_data + return sprites_object.sprites def get_pokemon_form_types(self, obj): form_type_objects = PokemonFormType.objects.filter(pokemon_form=obj) @@ -2713,12 +2705,6 @@ class Meta: fields = ("game_index", "version") -class PokemonSpritesSerializer(serializers.ModelSerializer): - class Meta: - model = PokemonSprites - fields = ("sprites",) - - class PokemonDetailSerializer(serializers.ModelSerializer): abilities = serializers.SerializerMethodField("get_pokemon_abilities") past_abilities = serializers.SerializerMethodField("get_past_pokemon_abilities") @@ -2763,11 +2749,7 @@ class Meta: def get_pokemon_sprites(self, obj): sprites_object = PokemonSprites.objects.get(pokemon_id=obj) - sprites_data = PokemonSpritesSerializer( - sprites_object, context=self.context - ).data - - return json.loads(sprites_data["sprites"]) + return sprites_object.sprites def get_pokemon_moves(self, obj): version_objects = VersionGroup.objects.all() diff --git a/pokemon_v2/tests.py b/pokemon_v2/tests.py index 994a51f48..32d406d2c 100644 --- a/pokemon_v2/tests.py +++ b/pokemon_v2/tests.py @@ -2588,8 +2588,6 @@ def test_item_api(self): item_attribute_map = ItemAttributeMap(item=item, item_attribute=item_attribute) item_attribute_map.save() - sprites_data = json.loads(item_sprites.sprites) - response = self.client.get( "{}/item/{}/".format(API_V2, item.pk), HTTP_HOST="testserver" ) @@ -2708,9 +2706,12 @@ def test_item_api(self): response.data["baby_trigger_for"]["url"], "{}{}/evolution-chain/{}/".format(TEST_HOST, API_V2, evolution_chain.pk), ) + + sprites_data = json.loads(response.data["sprites"]) + # sprites self.assertEqual( - response.data["sprites"]["default"], + sprites_data["default"], "{}".format(sprites_data["default"]), ) @@ -4837,8 +4838,6 @@ def test_pokemon_api(self): "{}/pokemon/{}/".format(API_V2, pokemon.pk), HTTP_HOST="testserver" ) - sprites_data = json.loads(pokemon_sprites.sprites) - self.assertEqual(response.status_code, status.HTTP_200_OK) # base params @@ -5024,12 +5023,15 @@ def test_pokemon_api(self): response.data["forms"][0]["url"], "{}{}/pokemon-form/{}/".format(TEST_HOST, API_V2, pokemon_form.pk), ) + + sprites_data = json.loads(pokemon_sprites.sprites) + # sprite params self.assertEqual( - response.data["sprites"]["front_default"], + sprites_data["front_default"], "{}".format(sprites_data["front_default"]), ) - self.assertEqual(response.data["sprites"]["back_default"], None) + self.assertEqual(sprites_data["back_default"], None) def test_pokemon_form_api(self): pokemon_species = self.setup_pokemon_species_data() @@ -5040,8 +5042,6 @@ def test_pokemon_form_api(self): pokemon_form_sprites = self.setup_pokemon_form_sprites_data(pokemon_form) pokemon_form_type = self.setup_pokemon_form_type_data(pokemon_form) - sprites_data = json.loads(pokemon_form_sprites.sprites) - response = self.client.get( "{}/pokemon-form/{}/".format(API_V2, pokemon_form.pk), HTTP_HOST="testserver", @@ -5074,12 +5074,15 @@ def test_pokemon_form_api(self): TEST_HOST, API_V2, pokemon_form.version_group.pk ), ) + + sprites_data = json.loads(pokemon_form_sprites.sprites) + # sprite params self.assertEqual( - response.data["sprites"]["front_default"], + sprites_data["front_default"], "{}".format(sprites_data["front_default"]), ) - self.assertEqual(response.data["sprites"]["back_default"], None) + self.assertEqual(sprites_data["back_default"], None) # type params self.assertEqual(response.data["types"][0]["slot"], pokemon_form_type.slot) self.assertEqual( diff --git a/requirements.txt b/requirements.txt index 78ab0f703..ad52ef4de 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,18 +1,13 @@ -Django==2.1.15 +Django==3.1.14 Unipath==1.1 coverage==4.5.1 -django-appconf==1.0.4 -django-cors-headers==2.5.3 +django-cors-headers==3.11.0 django-discover-runner==1.0 -django-redis==4.10.0 +django-redis==4.12.1 django-cachalot==2.3.5 -django-tastypie==0.14.3 -djangorestframework==3.9.4 -drf-ujson==1.2.0 +djangorestframework==3.14.0 gunicorn==20.1.0 mimeparse==0.1.3 psycopg2-binary==2.9.5 python-dateutil==2.8.1 python-mimeparse==1.6.0 -simplejson==3.17.2 -six==1.15.0