Repository: arnavb/pypokedex

Issue:
Add Support for Sprites
This pokedex has pretty much every detail you need other than sprites. Adding sprite support shouldn't be too hard and will complete this project.

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/arnavb/pypokedex/pull/7?src=pr&el=h1) Report
> Merging [#7](https://codecov.io/gh/arnavb/pypokedex/pull/7?src=pr&el=desc) into [master](https://codecov.io/gh/arnavb/pypokedex/commit/1963ea43da7ca5d4dcec4c47b286d0992cd9895e?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/arnavb/pypokedex/pull/7/graphs/tree.svg?width=650&token=IdN3HmvKEy&height=150&src=pr)](https://codecov.io/gh/arnavb/pypokedex/pull/7?src=pr&el=tree)

```diff
@@          Coverage Diff          @@
##           master     #7   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files           4      4           
  Lines         104    104           
  Branches       18     18           
=====================================
  Hits          104    104
```



------

[Continue to review full report at Codecov](https://codecov.io/gh/arnavb/pypokedex/pull/7?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/arnavb/pypokedex/pull/7?src=pr&el=footer). Last update [1963ea4...9b83485](https://codecov.io/gh/arnavb/pypokedex/pull/7?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/.gitignore b/.gitignore
index 80aa5ff..38f584a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -132,3 +132,4 @@ pip-selfcheck.json
 # End of https://www.gitignore.io/api/python
 
 .vscode/
+.DS_Store
diff --git a/README.md b/README.md
index e358894..6832374 100644
--- a/README.md
+++ b/README.md
@@ -95,6 +95,8 @@ members are provided for its consumption:
     current move (according to PokeAPI).
   - `level` (`int`): The level the current Pokemon learns the current move if
     `learn_method` is `level-up`, `None` otherwise.
+- `sprites` (`Sprites`): Contains two dictionaries, `front` and `back` representing the respective
+  sprites of the current Pokemon. The keys in the dictionary are [Pokeapi sprite keys](https://pokeapi.co/docs/v2.html#pokemonsprites) without the direction prefix (e.g `back_default` is just `default` in the `back` dictionary).
 
 ### Member Functions
 
diff --git a/pypokedex/pokemon.py b/pypokedex/pokemon.py
index b3d1e1d..9188180 100644
--- a/pypokedex/pokemon.py
+++ b/pypokedex/pokemon.py
@@ -1,6 +1,6 @@
 from collections import defaultdict
 
-from typing import DefaultDict, List, NamedTuple
+from typing import DefaultDict, List, NamedTuple, Dict
 
 from pypokedex.exceptions import PyPokedexError
 
@@ -25,10 +25,14 @@ class Move(NamedTuple):
     level: int
 
 
+class Sprites(NamedTuple):
+    front: Dict[str, str]
+    back: Dict[str, str]
+
+
 class Pokemon:
     def __init__(self, json_data) -> None:
         """Loads and stores required pokemon data"""
-        # self._json_data = json_data # Store for repr
         try:
             self.dex = json_data["id"]
 
@@ -73,9 +77,18 @@ class Pokemon:
                         Move(move_name, learn_method, learn_level)
                     )
 
+            self.sprites: Sprites = Sprites(front={}, back={})
+            for sprite, url in json_data["sprites"].items():
+                sprite_direction, sprite_type = sprite.split("_", 1)
+
+                if sprite_direction == "front":
+                    self.sprites.front[sprite_type] = url
+                else:
+                    self.sprites.back[sprite_type] = url
+
         except KeyError as error:
             raise PyPokedexError(
-                "A required piece of data was not found for" "the current Pokemon!"
+                "A required piece of data was not found for the current Pokemon!"
             ) from error
 
     def exists_in(self, game: str) -> bool:
@@ -87,7 +100,9 @@ class Pokemon:
         in the specified game."""
         if not self.exists_in(game):
             raise PyPokedexError(
-                f"{self.name} is not " f"obtainable in {game}!"  # type: ignore
+                # pylint: disable=no-member
+                f"{self.name} is not "  # type: ignore
+                f"obtainable in {game}!"
             )
 
         for move in self.moves[game]:
@@ -100,6 +115,7 @@ class Pokemon:
 
     def __str__(self) -> str:
         """Returns a human-readable represenation of the current Pokemon."""
+        # pylint: disable=no-member
         return f"Pokemon(dex={self.dex}, name='{self.name}')"  # type: ignore
 
     def __eq__(self, other) -> bool:


Test patch:
diff --git a/tests/test_pypokedex.py b/tests/test_pypokedex.py
index 66c5a2d..3dc9d61 100644
--- a/tests/test_pypokedex.py
+++ b/tests/test_pypokedex.py
@@ -1,3 +1,5 @@
+# pylint: disable=redefined-outer-name
+
 from copy import deepcopy
 
 import pytest
@@ -44,10 +46,20 @@ sample_pokemon = {
             ],
         }
     ],
+    "sprites": {
+        "back_default": "default_back_url",
+        "back_female": None,
+        "back_shiny": "shiny_back_url",
+        "back_shiny_female": None,
+        "front_default": "default_front_url",
+        "front_female": None,
+        "front_shiny": "front_shiny_url",
+        "front_shiny_female": None,
+    },
 }
 
 
-def _is_valid_sample_pokemon(pokemon: pypokedex.pokemon.Pokemon):
+def _is_properly_initialized_pokemon_object(pokemon: pypokedex.pokemon.Pokemon):
     return (
         pokemon.dex == 999
         and pokemon.name == "sample"
@@ -68,6 +80,21 @@ def _is_valid_sample_pokemon(pokemon: pypokedex.pokemon.Pokemon):
         == pypokedex.pokemon.Move("move_1", "tutor", None)
         and pokemon.moves["game_2"][0]  # noqa
         == pypokedex.pokemon.Move("move_1", "level-up", 5)
+        and pokemon.sprites
+        == pypokedex.pokemon.Sprites(
+            front={
+                "default": "default_front_url",
+                "female": None,
+                "shiny": "front_shiny_url",
+                "shiny_female": None,
+            },
+            back={
+                "default": "default_back_url",
+                "female": None,
+                "shiny": "shiny_back_url",
+                "shiny_female": None,
+            },
+        )
     )  # noqa
 
 
@@ -115,7 +142,7 @@ def test_get_pokemon_by_name(responses):
 
     pokemon = pypokedex.get(name="sample")
 
-    assert _is_valid_sample_pokemon(pokemon)
+    assert _is_properly_initialized_pokemon_object(pokemon)
 
 
 def test_get_pokemon_by_dex(responses):
@@ -128,7 +155,7 @@ def test_get_pokemon_by_dex(responses):
 
     pokemon = pypokedex.get(dex=999)
 
-    assert _is_valid_sample_pokemon(pokemon)
+    assert _is_properly_initialized_pokemon_object(pokemon)
 
 
 def test_pokemon_existence_in_games(responses):