Skip to content

Commit 1c27e48

Browse files
authored
feat: add ability to clear/cap cache size (#31)
1 parent 82e5515 commit 1c27e48

File tree

3 files changed

+63
-5
lines changed

3 files changed

+63
-5
lines changed

src/pyconify/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
__author__ = "Talley Lambert"
1111
__email__ = "talley.lambert@gmail.com"
1212
__all__ = [
13+
"clear_api_cache",
1314
"clear_cache",
1415
"collection",
1516
"collections",
@@ -21,12 +22,14 @@
2122
"keywords",
2223
"last_modified",
2324
"search",
25+
"set_api_cache_maxsize",
2426
"svg",
2527
"svg_path",
2628
]
2729

2830
from ._cache import clear_cache, get_cache_directory
2931
from .api import (
32+
clear_api_cache,
3033
collection,
3134
collections,
3235
css,
@@ -35,6 +38,7 @@
3538
keywords,
3639
last_modified,
3740
search,
41+
set_api_cache_maxsize,
3842
svg,
3943
svg_path,
4044
)

src/pyconify/api.py

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import warnings
1111
from contextlib import suppress
1212
from pathlib import Path
13-
from typing import TYPE_CHECKING, Literal, overload
13+
from typing import TYPE_CHECKING, Any, Literal, Protocol, cast, overload
1414

1515
from ._cache import CACHE_DISABLED, _SVGCache, cache_key, svg_cache
1616

@@ -20,6 +20,11 @@
2020

2121
import requests
2222

23+
class _lru_cache_wrapper(Protocol):
24+
__wrapped__: Callable[..., Any]
25+
26+
def cache_clear(self) -> None: ...
27+
2328
F = TypeVar("F", bound=Callable)
2429

2530
from .iconify_types import (
@@ -35,6 +40,44 @@
3540

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

43+
API_FUNCTIONS: set[str] = {"collections", "collection", "last_modified", "css"}
44+
45+
46+
def clear_api_cache() -> None:
47+
"""Clear all cached responses to the iconify API from this session."""
48+
for func_name in API_FUNCTIONS:
49+
wrapper = cast("_lru_cache_wrapper", globals()[func_name])
50+
wrapper.cache_clear()
51+
52+
53+
def set_api_cache_maxsize(maxsize: int | None) -> None:
54+
"""Set the `lru_cache` maxsize for all calls to the iconify API.
55+
56+
This is NOT the same thing as the on-disk SVG cache
57+
58+
This will also clear all cached responses to the iconify API from this session.
59+
"""
60+
import pyconify
61+
62+
if maxsize is not None:
63+
if not isinstance(maxsize, int): # pragma: no cover
64+
raise TypeError(
65+
f"maxsize must be an integer, not {type(maxsize).__name__}."
66+
)
67+
if maxsize < 1: # pragma: no cover
68+
maxsize = 0
69+
70+
for func_name in API_FUNCTIONS:
71+
# get the lrue_cache-wrapped function and clear it
72+
wrapper = cast("_lru_cache_wrapper", globals()[func_name])
73+
wrapper.cache_clear()
74+
# get the original function and wrap it with the new maxsize
75+
func = wrapper.__wrapped__
76+
new_func = functools.lru_cache(maxsize=maxsize)(func)
77+
# update the names in both this module and top-level pyconify
78+
globals()[func_name] = new_func
79+
setattr(pyconify, func_name, new_func)
80+
3881

3982
@functools.cache
4083
def _session() -> requests.Session:
@@ -46,7 +89,7 @@ def _session() -> requests.Session:
4689
return session
4790

4891

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

69112

70-
@functools.cache
113+
@functools.lru_cache(maxsize=128)
71114
def collection(
72115
prefix: str,
73116
info: bool = False,
@@ -260,7 +303,7 @@ def _cached_svg_path(svg_cache_key: str) -> Path | None:
260303
return None # pragma: no cover
261304

262305

263-
@functools.cache
306+
@functools.lru_cache(maxsize=128)
264307
def svg_path(
265308
*key: str,
266309
color: str | None = None,
@@ -327,7 +370,7 @@ def _remove_tmp_svg() -> None:
327370
return Path(tmp_name)
328371

329372

330-
@functools.cache
373+
@functools.lru_cache(maxsize=128)
331374
def css(
332375
*keys: str,
333376
selector: str | None = None,

tests/test_pyconify.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,14 @@ def test_search() -> None:
112112

113113
def test_iconify_version() -> None:
114114
assert isinstance(pyconify.iconify_version(), str)
115+
116+
117+
def test_clear_api_cache() -> None:
118+
assert pyconify.collections.cache_info().currsize > 0
119+
assert pyconify.collections.cache_info().maxsize == 128
120+
121+
pyconify.clear_api_cache()
122+
pyconify.set_api_cache_maxsize(10)
123+
124+
assert pyconify.collections.cache_info().currsize == 0
125+
assert pyconify.collections.cache_info().maxsize == 10

0 commit comments

Comments
 (0)