From 02baf0b3ef2f6706f032095e9f43bf3a2da899bd Mon Sep 17 00:00:00 2001 From: FallenDeity <61227305+FallenDeity@users.noreply.github.com> Date: Sat, 3 Feb 2024 00:15:39 +0530 Subject: [PATCH 1/2] feat: :sparkles: Add pokemon cries Add pokemon cries resource field to pokemon endpoint --- data/v2/build.py | 40 +++++++++++++++++++++- pokemon_v2/migrations/0015_pokemoncries.py | 25 ++++++++++++++ pokemon_v2/models.py | 5 +++ pokemon_v2/serializers.py | 6 ++++ pokemon_v2/tests.py | 29 ++++++++++++++++ 5 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 pokemon_v2/migrations/0015_pokemoncries.py diff --git a/data/v2/build.py b/data/v2/build.py index 76561b22f..e44e74f25 100644 --- a/data/v2/build.py +++ b/data/v2/build.py @@ -36,8 +36,16 @@ "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/", ) ) +SOUND_DIR = "{prefix}{{file_name}}".format( + prefix=os.environ.get( + "POKEAPI_CRIES_PREFIX", + "https://raw.githubusercontent.com/PokeAPI/cries/main/cries/", + ) +) IMAGE_DIR = os.getcwd() + "/data/v2/sprites/sprites/" +CRIES_DIR = os.getcwd() + "/data/v2/cries/cries/" RESOURCE_IMAGES = [] +RESOURCE_CRIES = [] for root, dirs, files in os.walk(IMAGE_DIR): for file in files: @@ -45,8 +53,18 @@ image_path = image_path.replace("\\", "/") # convert Windows-style path to Unix RESOURCE_IMAGES.append(image_path) +for root, dirs, files in os.walk(CRIES_DIR): + for file in files: + cry_path = os.path.join(root.replace(CRIES_DIR, ""), file) + cry_path = cry_path.replace("\\", "/") # convert Windows-style path to Unix + RESOURCE_CRIES.append(cry_path) -def file_path_or_none(file_name): + +def file_path_or_none(file_name, image_file=True): + if not image_file: + return ( + SOUND_DIR.format(file_name=file_name) if file_name in RESOURCE_CRIES else None + ) return ( MEDIA_DIR.format(file_name=file_name) if file_name in RESOURCE_IMAGES else None ) @@ -1931,6 +1949,26 @@ def csv_record_to_objects(info): build_generic((PokemonSprites,), "pokemon.csv", csv_record_to_objects) + def try_cry_names(path, info, extension): + file_name = "%s.%s" % (info[0], extension) + return file_path_or_none(path + file_name, image_file=False) + + def csv_record_to_objects(info): + poke_cries = "pokemon" + latest = f"{poke_cries}/latest/" + legacy = f"{poke_cries}/legacy/" + cries = { + "latest": try_cry_names(latest, info, "ogg"), + "legacy": try_cry_names(legacy, info, "ogg"), + } + yield PokemonCries( + id=int(info[0]), + pokemon=Pokemon.objects.get(pk=int(info[0])), + cries=cries, + ) + + build_generic((PokemonCries,), "pokemon.csv", csv_record_to_objects) + def csv_record_to_objects(info): yield PokemonAbility( pokemon_id=int(info[0]), diff --git a/pokemon_v2/migrations/0015_pokemoncries.py b/pokemon_v2/migrations/0015_pokemoncries.py new file mode 100644 index 000000000..da262976c --- /dev/null +++ b/pokemon_v2/migrations/0015_pokemoncries.py @@ -0,0 +1,25 @@ +# Generated by Django 3.2.23 on 2024-02-02 18:02 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('pokemon_v2', '0014_auto_20231121_1209'), + ] + + operations = [ + migrations.CreateModel( + name='PokemonCries', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('cries', models.JSONField()), + ('pokemon', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='pokemoncries', to='pokemon_v2.pokemon')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/pokemon_v2/models.py b/pokemon_v2/models.py index ed6622dc3..afcddffd8 100644 --- a/pokemon_v2/models.py +++ b/pokemon_v2/models.py @@ -1796,3 +1796,8 @@ class PokemonTypePast(HasPokemon, HasType, HasGeneration): class PokemonSprites(HasPokemon): sprites = models.JSONField() + + +class PokemonCries(HasPokemon): + cries = models.JSONField() + diff --git a/pokemon_v2/serializers.py b/pokemon_v2/serializers.py index b1acff77c..381dd7cfb 100644 --- a/pokemon_v2/serializers.py +++ b/pokemon_v2/serializers.py @@ -2722,6 +2722,7 @@ class PokemonDetailSerializer(serializers.ModelSerializer): held_items = serializers.SerializerMethodField("get_pokemon_held_items") location_area_encounters = serializers.SerializerMethodField("get_encounters") sprites = serializers.SerializerMethodField("get_pokemon_sprites") + cries = serializers.SerializerMethodField("get_pokemon_cries") class Meta: model = Pokemon @@ -2742,6 +2743,7 @@ class Meta: "moves", "species", "sprites", + "cries", "stats", "types", "past_types", @@ -2750,6 +2752,10 @@ class Meta: def get_pokemon_sprites(self, obj): sprites_object = PokemonSprites.objects.get(pokemon_id=obj) return sprites_object.sprites + + def get_pokemon_cries(self, obj): + cries_object = PokemonCries.objects.get(pokemon_id=obj) + return cries_object.cries def get_pokemon_moves(self, obj): version_objects = VersionGroup.objects.all() diff --git a/pokemon_v2/tests.py b/pokemon_v2/tests.py index 57ef4a14b..00f68145a 100644 --- a/pokemon_v2/tests.py +++ b/pokemon_v2/tests.py @@ -1724,6 +1724,20 @@ def setup_pokemon_sprites_data( pokemon_sprites.save() return pokemon_sprites + + @classmethod + def setup_pokemon_cries_data(cls, pokemon, latest=True, legacy=False): + cries_path = "https://raw.githubusercontent.com/PokeAPI/cries/main/cries/pokemon/%s.ogg" + cries = { + "latest": cries_path % f"latest/{pokemon.id}" if latest else None, + "legacy": cries_path % f"legacy/{pokemon.id}" if legacy else None, + } + pokemon_cries = PokemonCries.objects.create( + pokemon=pokemon, + cries=json.dumps(cries) + ) + pokemon_cries.save() + return pokemon_cries # Evolution Data @classmethod @@ -4596,6 +4610,7 @@ def test_pokemon_species_api(self): pokemon_species=pokemon_species, name="pkm for base pkmn spcs" ) self.setup_pokemon_sprites_data(pokemon) + self.setup_pokemon_cries_data(pokemon) response = self.client.get( "{}/pokemon-species/{}/".format(API_V2, pokemon_species.pk), @@ -4816,6 +4831,7 @@ def test_pokemon_api(self): ) pokemon_item = self.setup_pokemon_item_data(pokemon=pokemon) pokemon_sprites = self.setup_pokemon_sprites_data(pokemon=pokemon) + pokemon_cries = self.setup_pokemon_cries_data(pokemon, latest=True, legacy=True) pokemon_game_index = self.setup_pokemon_game_index_data( pokemon=pokemon, game_index=10 ) @@ -5052,7 +5068,9 @@ def test_pokemon_api(self): ) sprites_data = json.loads(pokemon_sprites.sprites) + cries_data = json.loads(pokemon_cries.cries) response_sprites_data = json.loads(response.data["sprites"]) + response_cries_data = json.loads(response.data["cries"]) # sprite params self.assertEqual( @@ -5070,6 +5088,17 @@ def test_pokemon_api(self): response_sprites_data["other"]["showdown"]["back_default"], ) + # cries params + self.assertEqual( + cries_data["latest"], + "{}".format(cries_data["latest"]), + ) + self.assertEqual( + cries_data["legacy"], + "{}".format(cries_data["legacy"]), + ) + + def test_pokemon_form_api(self): pokemon_species = self.setup_pokemon_species_data() pokemon = self.setup_pokemon_data(pokemon_species=pokemon_species) From 4828b938603d5f09f4d686f6ab5afd287f38551e Mon Sep 17 00:00:00 2001 From: FallenDeity <61227305+FallenDeity@users.noreply.github.com> Date: Sat, 3 Feb 2024 00:32:51 +0530 Subject: [PATCH 2/2] style: Run black formatter on source --- data/v2/build.py | 4 ++- pokemon_v2/migrations/0015_pokemoncries.py | 30 +++++++++++++++++----- pokemon_v2/models.py | 1 - pokemon_v2/serializers.py | 2 +- pokemon_v2/tests.py | 10 ++++---- 5 files changed, 32 insertions(+), 15 deletions(-) diff --git a/data/v2/build.py b/data/v2/build.py index e44e74f25..4c3eae767 100644 --- a/data/v2/build.py +++ b/data/v2/build.py @@ -63,7 +63,9 @@ def file_path_or_none(file_name, image_file=True): if not image_file: return ( - SOUND_DIR.format(file_name=file_name) if file_name in RESOURCE_CRIES else None + SOUND_DIR.format(file_name=file_name) + if file_name in RESOURCE_CRIES + else None ) return ( MEDIA_DIR.format(file_name=file_name) if file_name in RESOURCE_IMAGES else None diff --git a/pokemon_v2/migrations/0015_pokemoncries.py b/pokemon_v2/migrations/0015_pokemoncries.py index da262976c..05099ce1c 100644 --- a/pokemon_v2/migrations/0015_pokemoncries.py +++ b/pokemon_v2/migrations/0015_pokemoncries.py @@ -5,21 +5,37 @@ class Migration(migrations.Migration): - dependencies = [ - ('pokemon_v2', '0014_auto_20231121_1209'), + ("pokemon_v2", "0014_auto_20231121_1209"), ] operations = [ migrations.CreateModel( - name='PokemonCries', + name="PokemonCries", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('cries', models.JSONField()), - ('pokemon', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='pokemoncries', to='pokemon_v2.pokemon')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("cries", models.JSONField()), + ( + "pokemon", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="pokemoncries", + to="pokemon_v2.pokemon", + ), + ), ], options={ - 'abstract': False, + "abstract": False, }, ), ] diff --git a/pokemon_v2/models.py b/pokemon_v2/models.py index afcddffd8..d7d0e48a1 100644 --- a/pokemon_v2/models.py +++ b/pokemon_v2/models.py @@ -1800,4 +1800,3 @@ class PokemonSprites(HasPokemon): class PokemonCries(HasPokemon): cries = models.JSONField() - diff --git a/pokemon_v2/serializers.py b/pokemon_v2/serializers.py index 381dd7cfb..c7a4773c8 100644 --- a/pokemon_v2/serializers.py +++ b/pokemon_v2/serializers.py @@ -2752,7 +2752,7 @@ class Meta: def get_pokemon_sprites(self, obj): sprites_object = PokemonSprites.objects.get(pokemon_id=obj) return sprites_object.sprites - + def get_pokemon_cries(self, obj): cries_object = PokemonCries.objects.get(pokemon_id=obj) return cries_object.cries diff --git a/pokemon_v2/tests.py b/pokemon_v2/tests.py index 00f68145a..e458f467c 100644 --- a/pokemon_v2/tests.py +++ b/pokemon_v2/tests.py @@ -1724,17 +1724,18 @@ def setup_pokemon_sprites_data( pokemon_sprites.save() return pokemon_sprites - + @classmethod def setup_pokemon_cries_data(cls, pokemon, latest=True, legacy=False): - cries_path = "https://raw.githubusercontent.com/PokeAPI/cries/main/cries/pokemon/%s.ogg" + cries_path = ( + "https://raw.githubusercontent.com/PokeAPI/cries/main/cries/pokemon/%s.ogg" + ) cries = { "latest": cries_path % f"latest/{pokemon.id}" if latest else None, "legacy": cries_path % f"legacy/{pokemon.id}" if legacy else None, } pokemon_cries = PokemonCries.objects.create( - pokemon=pokemon, - cries=json.dumps(cries) + pokemon=pokemon, cries=json.dumps(cries) ) pokemon_cries.save() return pokemon_cries @@ -5098,7 +5099,6 @@ def test_pokemon_api(self): "{}".format(cries_data["legacy"]), ) - def test_pokemon_form_api(self): pokemon_species = self.setup_pokemon_species_data() pokemon = self.setup_pokemon_data(pokemon_species=pokemon_species)