Skip to content

Commit

Permalink
feat: add ability to clear/cap cache size (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
tlambert03 authored Feb 6, 2025
1 parent 82e5515 commit 1c27e48
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 5 deletions.
4 changes: 4 additions & 0 deletions src/pyconify/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
__author__ = "Talley Lambert"
__email__ = "[email protected]"
__all__ = [
"clear_api_cache",
"clear_cache",
"collection",
"collections",
Expand All @@ -21,12 +22,14 @@
"keywords",
"last_modified",
"search",
"set_api_cache_maxsize",
"svg",
"svg_path",
]

from ._cache import clear_cache, get_cache_directory
from .api import (
clear_api_cache,
collection,
collections,
css,
Expand All @@ -35,6 +38,7 @@
keywords,
last_modified,
search,
set_api_cache_maxsize,
svg,
svg_path,
)
Expand Down
53 changes: 48 additions & 5 deletions src/pyconify/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import warnings
from contextlib import suppress
from pathlib import Path
from typing import TYPE_CHECKING, Literal, overload
from typing import TYPE_CHECKING, Any, Literal, Protocol, cast, overload

from ._cache import CACHE_DISABLED, _SVGCache, cache_key, svg_cache

Expand All @@ -20,6 +20,11 @@

import requests

class _lru_cache_wrapper(Protocol):
__wrapped__: Callable[..., Any]

def cache_clear(self) -> None: ...

F = TypeVar("F", bound=Callable)

from .iconify_types import (
Expand All @@ -35,6 +40,44 @@

ROOT = "https://api.iconify.design"

API_FUNCTIONS: set[str] = {"collections", "collection", "last_modified", "css"}


def clear_api_cache() -> None:
"""Clear all cached responses to the iconify API from this session."""
for func_name in API_FUNCTIONS:
wrapper = cast("_lru_cache_wrapper", globals()[func_name])
wrapper.cache_clear()


def set_api_cache_maxsize(maxsize: int | None) -> None:
"""Set the `lru_cache` maxsize for all calls to the iconify API.
This is NOT the same thing as the on-disk SVG cache
This will also clear all cached responses to the iconify API from this session.
"""
import pyconify

if maxsize is not None:
if not isinstance(maxsize, int): # pragma: no cover
raise TypeError(
f"maxsize must be an integer, not {type(maxsize).__name__}."
)
if maxsize < 1: # pragma: no cover
maxsize = 0

for func_name in API_FUNCTIONS:
# get the lrue_cache-wrapped function and clear it
wrapper = cast("_lru_cache_wrapper", globals()[func_name])
wrapper.cache_clear()
# get the original function and wrap it with the new maxsize
func = wrapper.__wrapped__
new_func = functools.lru_cache(maxsize=maxsize)(func)
# update the names in both this module and top-level pyconify
globals()[func_name] = new_func
setattr(pyconify, func_name, new_func)


@functools.cache
def _session() -> requests.Session:
Expand All @@ -46,7 +89,7 @@ def _session() -> requests.Session:
return session


@functools.cache
@functools.lru_cache(maxsize=128)
def collections(*prefixes: str) -> dict[str, IconifyInfo]:
"""Return collections where key is icon set prefix, value is IconifyInfo object.
Expand All @@ -67,7 +110,7 @@ def collections(*prefixes: str) -> dict[str, IconifyInfo]:
return resp.json() # type: ignore


@functools.cache
@functools.lru_cache(maxsize=128)
def collection(
prefix: str,
info: bool = False,
Expand Down Expand Up @@ -260,7 +303,7 @@ def _cached_svg_path(svg_cache_key: str) -> Path | None:
return None # pragma: no cover


@functools.cache
@functools.lru_cache(maxsize=128)
def svg_path(
*key: str,
color: str | None = None,
Expand Down Expand Up @@ -327,7 +370,7 @@ def _remove_tmp_svg() -> None:
return Path(tmp_name)


@functools.cache
@functools.lru_cache(maxsize=128)
def css(
*keys: str,
selector: str | None = None,
Expand Down
11 changes: 11 additions & 0 deletions tests/test_pyconify.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,14 @@ def test_search() -> None:

def test_iconify_version() -> None:
assert isinstance(pyconify.iconify_version(), str)


def test_clear_api_cache() -> None:
assert pyconify.collections.cache_info().currsize > 0
assert pyconify.collections.cache_info().maxsize == 128

pyconify.clear_api_cache()
pyconify.set_api_cache_maxsize(10)

assert pyconify.collections.cache_info().currsize == 0
assert pyconify.collections.cache_info().maxsize == 10

0 comments on commit 1c27e48

Please sign in to comment.