PokeLance
client
¶
ClientBase
¶
ClientBase(
*, http: _HTTPClientT_co, **kwargs: Unpack[ClientConfig]
)
Bases: Generic[_HTTPClientT_co]
Shared base logic for PokeLanceAsyncClient and PokeLanceSyncClient.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
http
|
AsyncHttpClient | SyncHttpClient
|
The HTTP client used to make requests to the PokeAPI. |
required |
**kwargs
|
Unpack[ClientConfig]
|
Optional client configuration options. |
{}
|
Attributes:
| Name | Type | Description |
|---|---|---|
http |
AsyncHttpClient | SyncHttpClient
|
The HTTP client used to make requests to the PokeAPI. |
cache_endpoints |
bool
|
Whether to pre-populate endpoint caches. |
image_cache_size |
int
|
The size of the image cache. |
audio_cache_size |
int
|
The size of the audio cache. |
ext_tasks |
list[tuple[Callable, str]]
|
A list of setup callables/coroutines to load extension data. |
Source code in pokelance/client/_base.py
def __init__(
self,
*,
http: _HTTPClientT_co,
**kwargs: Unpack[ClientConfig],
) -> None:
if kwargs.get("setup_logging", True):
setup_logging(
log_level=kwargs.get("log_level", logging.INFO),
structured=kwargs.get("structured_logging", False),
file_logging=kwargs.get("file_logging", False),
log_dir=kwargs.get("log_dir", "logs"),
set_excepthook=kwargs.get("set_excepthook", True),
)
self._http = http
self._cache_endpoints = kwargs.get("cache_endpoints", True)
self._ext_tasks = []
self._image_cache_size = kwargs.get("image_cache_size", 128)
self._audio_cache_size = kwargs.get("audio_cache_size", 128)
ext_tasks
property
¶
A list of setup callables/coroutines to load extension data.
setup_hook
¶
setup_hook(ext_pkg: str) -> None
Dynamically loads extensions from the specified package directory.
Source code in pokelance/client/_base.py
def setup_hook(self, ext_pkg: str) -> None:
"""Dynamically loads extensions from the specified package directory."""
logger.info(f"Using cache size: {self._http.cache_manager.max_size}")
if not self.EXTENSIONS.exists():
logger.warning(f"Extensions directory '{self.EXTENSIONS}' does not exist.")
return
for extension in self.EXTENSIONS.iterdir():
if extension.is_file() and extension.suffix == ".py" and "_" not in extension.stem:
module = __import__(f"{ext_pkg}.{extension.stem}", fromlist=["setup"])
module.setup(self)
logger.debug(f"Loaded extension module: {extension.stem}")
logger.info("Setup complete")
add_extension
¶
add_extension(
name: str, extension: BaseExtension[_HTTPClientT_co]
) -> None
Adds an extension to the client.
ClientConfig
¶
Bases: TypedDict
Configuration options for PokeLance clients.
Attributes:
| Name | Type | Description |
|---|---|---|
audio_cache_size |
int
|
Max entries in the audio LRU cache. |
image_cache_size |
int
|
Max entries in the image LRU cache. |
cache_endpoints |
bool
|
Whether to eagerly cache the name/id registries on client startup. |
setup_logging |
bool
|
Whether PokeLance should configure default terminal logging. |
log_level |
int
|
Log severity level filter. |
structured_logging |
bool
|
Output logs as structured JSON rather than ANSI-colored plain text. |
file_logging |
bool
|
Whether to write timestamped log files under |
log_dir |
str | Path
|
Directory destination when |
set_excepthook |
bool
|
Whether to install a custom exception hook for unhandled exceptions. |
PokeLanceAsyncClient
¶
PokeLanceAsyncClient(
*,
cache_size: int = 100,
session: AsyncSession | None = None,
**kwargs: Unpack[ClientConfig],
)
Bases: ClientBase[AsyncHttpClient]
Main asynchronous client to interact with the PokeAPI.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cache_size
|
int
|
The maximum cache size for the HTTP client. |
100
|
session
|
AsyncSession | None
|
An optional custom AsyncSession to use for requests. |
None
|
**kwargs
|
Unpack[ClientConfig]
|
Additional configuration options. |
{}
|
Attributes:
| Name | Type | Description |
|---|---|---|
http |
AsyncHttpClient
|
The HTTP client used to make requests to the PokeAPI. |
cache_endpoints |
bool
|
Whether to pre-populate endpoint caches. Defaults to True. |
berry |
Berry
|
The berry extension. |
contest |
Contest
|
The contest extension. |
encounter |
Encounter
|
The encounter extension. |
evolution |
Evolution
|
The evolution extension. |
game |
Game
|
The game extension. |
item |
Item
|
The item extension. |
location |
Location
|
The location extension. |
machine |
Machine
|
The machine extension. |
move |
Move
|
The move extension. |
pokemon |
Pokemon
|
The pokemon extension. |
utility |
Utility
|
The utility extension. |
Examples:
import asyncio
from pokelance import PokeLanceAsyncClient
async def main() -> None:
async with PokeLanceAsyncClient() as client:
pokemon = await client.pokemon.get_pokemon("pikachu")
print(f"{pokemon.name} (ID: {pokemon.id})")
asyncio.run(main())
Source code in pokelance/client/async_client.py
def __init__(
self,
*,
cache_size: int = 100,
session: niquests.AsyncSession | None = None,
**kwargs: Unpack[ClientConfig],
) -> None:
super().__init__(
http=AsyncHttpClient(client=self, session=session, cache_size=cache_size),
**kwargs,
)
self.get_image.set_size(self._image_cache_size)
self.get_audio.set_size(self._audio_cache_size)
self.setup_hook("pokelance.ext._async")
ping
async
¶
ping() -> float
Pings the PokeAPI and returns the latency in seconds.
Returns:
| Type | Description |
|---|---|
float
|
The round-trip latency in seconds. |
Examples:
Source code in pokelance/client/async_client.py
close
async
¶
Closes the underlying HTTP client session.
Examples:
getch_data
async
¶
getch_data(
ext: ExtensionEnum | ExtensionsL | str,
category: str,
id_: int | str | None = None,
) -> BaseModelT
Looks up an object from cache first, fetching from PokeAPI if not cached.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ext
|
ExtensionEnum | ExtensionsL | str
|
The extension name (e.g. 'pokemon', 'berry', 'item'). |
required |
category
|
str
|
The category name within the extension (e.g. 'pokemon', 'berry'). |
required |
id_
|
int | str | None
|
The ID or name of the resource to look up. |
None
|
Returns:
| Type | Description |
|---|---|
BaseModelT
|
The retrieved model instance or sequence of models. |
Examples:
from pokelance.constants import ExtensionEnum
# Using string identifiers
pokemon = await client.getch_data("pokemon", "pokemon", "pikachu")
# Using ExtensionEnum for type safety
berry = await client.getch_data(ExtensionEnum.Berry, "berry", 1)
Source code in pokelance/client/async_client.py
async def getch_data(
self,
ext: ExtensionEnum | ExtensionsL | str,
category: str,
id_: int | str | None = None,
) -> BaseModelT: # pyright: ignore[reportInvalidTypeVarUse]
"""Looks up an object from cache first, fetching from PokeAPI if not cached.
Parameters
----------
ext : ExtensionEnum | ExtensionsL | str
The extension name (e.g. 'pokemon', 'berry', 'item').
category : str
The category name within the extension (e.g. 'pokemon', 'berry').
id_ : int | str | None, optional
The ID or name of the resource to look up.
Returns
-------
BaseModelT
The retrieved model instance or sequence of models.
Examples
--------
```python
from pokelance.constants import ExtensionEnum
# Using string identifiers
pokemon = await client.getch_data("pokemon", "pokemon", "pikachu")
# Using ExtensionEnum for type safety
berry = await client.getch_data(ExtensionEnum.Berry, "berry", 1)
```
"""
ext_instance, resolved_category = self._resolve_extension_category(ext, category)
get_ = getattr(ext_instance, f"get_{resolved_category}")
fetch_ = getattr(ext_instance, f"fetch_{resolved_category}")
params = (id_,) if id_ is not None else ()
return t.cast("BaseModelT", get_(*params) or await fetch_(*params))
from_url
async
¶
from_url(url: str) -> BaseModelT
Constructs a request from any valid PokeAPI resource URL.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The PokeAPI resource URL (e.g. 'https://pokeapi.co/api/v2/pokemon/25/'). |
required |
Returns:
| Type | Description |
|---|---|
BaseModelT
|
The corresponding model instance for the URL resource. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the provided URL is not a valid PokeAPI endpoint. |
Examples:
pokemon = await client.from_url("https://pokeapi.co/api/v2/pokemon/25/")
print(pokemon.name) # pikachu
Source code in pokelance/client/async_client.py
async def from_url(self, url: str) -> BaseModelT: # pyright: ignore[reportInvalidTypeVarUse]
"""Constructs a request from any valid PokeAPI resource URL.
Parameters
----------
url : str
The PokeAPI resource URL (e.g. 'https://pokeapi.co/api/v2/pokemon/25/').
Returns
-------
BaseModelT
The corresponding model instance for the URL resource.
Raises
------
ValueError
If the provided URL is not a valid PokeAPI endpoint.
Examples
--------
```python
pokemon = await client.from_url("https://pokeapi.co/api/v2/pokemon/25/")
print(pokemon.name) # pikachu
```
"""
if params := ExtensionEnum.validate_url(url):
return await self.getch_data(params.extension, params.category, params.value)
raise ValueError(f"Invalid URL: {url}")
get_image
async
¶
Downloads image sprite bytes from a URL with LRU caching.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The image sprite URL. |
required |
Returns:
| Type | Description |
|---|---|
bytes
|
The raw image file bytes. |
Examples:
import io
pokemon = await client.pokemon.get_pokemon("pikachu")
if pokemon.sprites.front_default:
sprite_bytes = await client.get_image(pokemon.sprites.front_default)
# Use in-memory buffer without blocking async IO
buffer = io.BytesIO(sprite_bytes)
Source code in pokelance/client/async_client.py
@alru_cache(maxsize=128, typed=True)
async def get_image(self, /, url: str) -> bytes:
"""Downloads image sprite bytes from a URL with LRU caching.
Parameters
----------
url : str
The image sprite URL.
Returns
-------
bytes
The raw image file bytes.
Examples
--------
```python
import io
pokemon = await client.pokemon.get_pokemon("pikachu")
if pokemon.sprites.front_default:
sprite_bytes = await client.get_image(pokemon.sprites.front_default)
# Use in-memory buffer without blocking async IO
buffer = io.BytesIO(sprite_bytes)
```
"""
return await self._http.load_image(url)
get_audio
async
¶
Downloads audio cry bytes from a URL with LRU caching.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The audio cry URL. |
required |
Returns:
| Type | Description |
|---|---|
bytes
|
The raw audio file bytes. |
Examples:
import io
pokemon = await client.pokemon.get_pokemon("pikachu")
if pokemon.cries.latest:
cry_bytes = await client.get_audio(pokemon.cries.latest)
# Use in-memory buffer without blocking async IO
buffer = io.BytesIO(cry_bytes)
Source code in pokelance/client/async_client.py
@alru_cache(maxsize=128, typed=True)
async def get_audio(self, /, url: str) -> bytes:
"""Downloads audio cry bytes from a URL with LRU caching.
Parameters
----------
url : str
The audio cry URL.
Returns
-------
bytes
The raw audio file bytes.
Examples
--------
```python
import io
pokemon = await client.pokemon.get_pokemon("pikachu")
if pokemon.cries.latest:
cry_bytes = await client.get_audio(pokemon.cries.latest)
# Use in-memory buffer without blocking async IO
buffer = io.BytesIO(cry_bytes)
```
"""
return await self._http.load_audio(url)
wait_until_ready
async
¶
Waits until all background endpoint caches are pre-populated.
Examples:
client = PokeLanceAsyncClient()
await client.wait_until_ready()
# All background caches are now loaded
Source code in pokelance/client/async_client.py
async def wait_until_ready(self) -> None:
"""Waits until all background endpoint caches are pre-populated.
Examples
--------
```python
client = PokeLanceAsyncClient()
await client.wait_until_ready()
# All background caches are now loaded
```
"""
await self._http.connect()
logger.info("Waiting until ready...")
await self._http.loader.wait_until_ready()
logger.info("Ready!")
PokeLanceSyncClient
¶
PokeLanceSyncClient(
*,
cache_size: int = 100,
session: Session | None = None,
**kwargs: Unpack[ClientConfig],
)
Bases: ClientBase[SyncHttpClient]
Main synchronous client to interact with the PokeAPI.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cache_size
|
int
|
The maximum cache size for the HTTP client. |
100
|
session
|
Session | None
|
An optional custom Session to use for requests. |
None
|
**kwargs
|
Unpack[ClientConfig]
|
Additional configuration options. |
{}
|
Attributes:
| Name | Type | Description |
|---|---|---|
http |
SyncHttpClient
|
The HTTP client used to make requests to the PokeAPI. |
cache_endpoints |
bool
|
Whether to pre-populate endpoint caches. Defaults to True. |
berry |
Berry
|
The berry extension. |
contest |
Contest
|
The contest extension. |
encounter |
Encounter
|
The encounter extension. |
evolution |
Evolution
|
The evolution extension. |
game |
Game
|
The game extension. |
item |
Item
|
The item extension. |
location |
Location
|
The location extension. |
machine |
Machine
|
The machine extension. |
move |
Move
|
The move extension. |
pokemon |
Pokemon
|
The pokemon extension. |
utility |
Utility
|
The utility extension. |
Examples:
from pokelance import PokeLanceSyncClient
with PokeLanceSyncClient() as client:
pokemon = client.pokemon.get_pokemon("pikachu")
print(f"{pokemon.name} (ID: {pokemon.id})")
Source code in pokelance/client/sync_client.py
def __init__(
self,
*,
cache_size: int = 100,
session: niquests.Session | None = None,
**kwargs: Unpack[ClientConfig],
) -> None:
super().__init__(
http=SyncHttpClient(client=self, session=session, cache_size=cache_size),
**kwargs,
)
self._cached_get_image = functools.lru_cache(maxsize=self._image_cache_size)(self._http.load_image)
self._cached_get_audio = functools.lru_cache(maxsize=self._audio_cache_size)(self._http.load_audio)
self.setup_hook("pokelance.ext.sync")
ping
¶
ping() -> float
Pings the PokeAPI and returns the latency in seconds.
Returns:
| Type | Description |
|---|---|
float
|
The round-trip latency in seconds. |
Examples:
Source code in pokelance/client/sync_client.py
close
¶
getch_data
¶
getch_data(
ext: ExtensionEnum | ExtensionsL | str,
category: str,
id_: int | str | None = None,
) -> BaseModelT
Looks up an object from cache first, fetching from PokeAPI if not cached.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ext
|
ExtensionEnum | ExtensionsL | str
|
The extension name (e.g. 'pokemon', 'berry', 'item'). |
required |
category
|
str
|
The category name within the extension (e.g. 'pokemon', 'berry'). |
required |
id_
|
int | str | None
|
The ID or name of the resource to look up. |
None
|
Returns:
| Type | Description |
|---|---|
BaseModelT
|
The retrieved model instance or sequence of models. |
Examples:
from pokelance.constants import ExtensionEnum
# Using string identifiers
pokemon = client.getch_data("pokemon", "pokemon", "pikachu")
# Using ExtensionEnum for type safety
berry = client.getch_data(ExtensionEnum.Berry, "berry", 1)
Source code in pokelance/client/sync_client.py
def getch_data(
self,
ext: ExtensionEnum | ExtensionsL | str,
category: str,
id_: int | str | None = None,
) -> BaseModelT: # pyright: ignore[reportInvalidTypeVarUse]
"""Looks up an object from cache first, fetching from PokeAPI if not cached.
Parameters
----------
ext : ExtensionEnum | ExtensionsL | str
The extension name (e.g. 'pokemon', 'berry', 'item').
category : str
The category name within the extension (e.g. 'pokemon', 'berry').
id_ : int | str | None, optional
The ID or name of the resource to look up.
Returns
-------
BaseModelT
The retrieved model instance or sequence of models.
Examples
--------
```python
from pokelance.constants import ExtensionEnum
# Using string identifiers
pokemon = client.getch_data("pokemon", "pokemon", "pikachu")
# Using ExtensionEnum for type safety
berry = client.getch_data(ExtensionEnum.Berry, "berry", 1)
```
"""
ext_instance, resolved_category = self._resolve_extension_category(ext, category)
get_ = getattr(ext_instance, f"get_{resolved_category}")
fetch_ = getattr(ext_instance, f"fetch_{resolved_category}")
params = (id_,) if id_ is not None else ()
return t.cast("BaseModelT", get_(*params) or fetch_(*params))
from_url
¶
from_url(url: str) -> BaseModelT
Constructs a request from any valid PokeAPI resource URL.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The PokeAPI resource URL (e.g. 'https://pokeapi.co/api/v2/pokemon/25/'). |
required |
Returns:
| Type | Description |
|---|---|
BaseModelT
|
The corresponding model instance for the URL resource. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the provided URL is not a valid PokeAPI endpoint. |
Examples:
Source code in pokelance/client/sync_client.py
def from_url(self, url: str) -> BaseModelT: # pyright: ignore[reportInvalidTypeVarUse]
"""Constructs a request from any valid PokeAPI resource URL.
Parameters
----------
url : str
The PokeAPI resource URL (e.g. 'https://pokeapi.co/api/v2/pokemon/25/').
Returns
-------
BaseModelT
The corresponding model instance for the URL resource.
Raises
------
ValueError
If the provided URL is not a valid PokeAPI endpoint.
Examples
--------
```python
pokemon = client.from_url("https://pokeapi.co/api/v2/pokemon/25/")
print(pokemon.name) # pikachu
```
"""
if params := ExtensionEnum.validate_url(url):
return self.getch_data(params.extension, params.category, params.value)
raise ValueError(f"Invalid URL: {url}")
get_image
¶
Downloads image sprite bytes from a URL with LRU caching.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The image sprite URL. |
required |
Returns:
| Type | Description |
|---|---|
bytes
|
The raw image file bytes. |
Examples:
pokemon = client.pokemon.get_pokemon("pikachu")
if pokemon.sprites.front_default:
image_bytes = client.get_image(pokemon.sprites.front_default)
Source code in pokelance/client/sync_client.py
def get_image(self, url: str) -> bytes:
"""Downloads image sprite bytes from a URL with LRU caching.
Parameters
----------
url : str
The image sprite URL.
Returns
-------
bytes
The raw image file bytes.
Examples
--------
```python
pokemon = client.pokemon.get_pokemon("pikachu")
if pokemon.sprites.front_default:
image_bytes = client.get_image(pokemon.sprites.front_default)
```
"""
return self._cached_get_image(url)
get_audio
¶
Downloads audio cry bytes from a URL with LRU caching.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The audio cry URL. |
required |
Returns:
| Type | Description |
|---|---|
bytes
|
The raw audio file bytes. |
Examples:
pokemon = client.pokemon.get_pokemon("pikachu")
if pokemon.cries.latest:
cry_bytes = client.get_audio(pokemon.cries.latest)
Source code in pokelance/client/sync_client.py
def get_audio(self, url: str) -> bytes:
"""Downloads audio cry bytes from a URL with LRU caching.
Parameters
----------
url : str
The audio cry URL.
Returns
-------
bytes
The raw audio file bytes.
Examples
--------
```python
pokemon = client.pokemon.get_pokemon("pikachu")
if pokemon.cries.latest:
cry_bytes = client.get_audio(pokemon.cries.latest)
```
"""
return self._cached_get_audio(url)
wait_until_ready
¶
Waits until all background endpoint caches are pre-populated.
Examples:
Source code in pokelance/client/sync_client.py
def wait_until_ready(self) -> None:
"""Waits until all background endpoint caches are pre-populated.
Examples
--------
```python
client = PokeLanceSyncClient()
client.wait_until_ready()
# All background caches are now loaded
```
"""
self._http.connect()
logger.info("Waiting until ready...")
self._http.loader.wait_until_ready()
logger.info("Ready!")