Skip to content

Commit 23b7129

Browse files
committed
Use apeye for caching and API access.
1 parent cec1b94 commit 23b7129

File tree

6 files changed

+10
-175
lines changed

6 files changed

+10
-175
lines changed

.isort.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use_parentheses = True
1313
remove_redundant_aliases = True
1414
default_section = THIRDPARTY
1515
known_third_party =
16+
apeye
1617
appdirs
1718
beautifulsoup4
1819
coverage

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
apeye
12
appdirs>=1.4.4
23
domdf_python_tools>=0.4.10
34
importlib_resources
45
packaging>=20.4
56
requests>=2.24.0
6-
slumber>=0.7.1
77
sphinx>=3.0.3

seed_intersphinx_mapping/cache.py

Lines changed: 2 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -26,117 +26,9 @@
2626
# OR OTHER DEALINGS IN THE SOFTWARE.
2727
#
2828

29-
# stdlib
30-
import inspect
31-
import json
32-
import shutil
33-
import warnings
34-
from functools import wraps
35-
from typing import Any, Callable, Dict, Iterable, Optional
36-
3729
# 3rd party
38-
from appdirs import user_cache_dir
39-
from domdf_python_tools.paths import PathPlus
40-
from domdf_python_tools.utils import posargs2kwargs
41-
42-
__all__ = ["Cache"]
43-
44-
45-
class Cache:
46-
47-
def __init__(self, app_name: str):
48-
self.app_name: str = str(app_name)
49-
self.cache_dir = PathPlus(user_cache_dir(f"{self.app_name}_cache"))
50-
self.cache_dir.maybe_make(parents=True)
51-
52-
# Mapping of function names to their caches
53-
self.caches: Dict[str, Dict[str, Any]] = {}
54-
55-
def clear(self, func: Optional[Callable] = None) -> bool:
56-
"""
57-
Clear the cache.
58-
59-
:param func: Optional function to clear the cache for.
60-
By default, the whole cache is cleared.
61-
:no-default func:
62-
63-
:returns: True to indicate success. False otherwise.
64-
"""
65-
66-
try:
67-
if func is None:
68-
shutil.rmtree(self.cache_dir)
69-
self.cache_dir.maybe_make()
70-
for function in self.caches:
71-
del self.caches[function]
72-
self.caches[function] = {}
73-
else:
74-
function_name = func.__name__
75-
cache_file = self.cache_dir / f"{function_name}.json"
76-
if cache_file.is_file():
77-
cache_file.unlink()
78-
79-
if function_name in self.caches:
80-
del self.caches[function_name]
81-
self.caches[function_name] = {}
82-
83-
return True
84-
85-
except Exception as e: # pragma: no cover
86-
warnings.warn(f"Could not remove cache. The error was: {e}")
87-
return False
88-
89-
def load_cache(self, func: Callable) -> None:
90-
"""
91-
Loads the cache for the given function
92-
93-
:param func:
94-
"""
95-
96-
cache_file: PathPlus = self.cache_dir / f"{func.__name__}.json"
97-
98-
if cache_file.is_file():
99-
cache = json.loads(cache_file.read_text())
100-
else:
101-
cache = {}
102-
103-
self.caches[func.__name__] = cache
104-
return cache
105-
106-
def __call__(self, func: Callable):
107-
"""
108-
Decorator to cache the return values of a function based on its inputs.
109-
110-
:param func:
111-
"""
112-
113-
function_name = func.__name__
114-
posargs: Iterable[str] = inspect.getfullargspec(func).args
115-
cache_file: PathPlus = self.cache_dir / f"{function_name}.json"
116-
self.load_cache(func)
117-
118-
@wraps(func)
119-
def wrapper(*args, **kwargs):
120-
kwargs: Dict[str, Any] = posargs2kwargs(args, posargs, kwargs) # type: ignore
121-
key: str = json.dumps(kwargs)
122-
response: Any
123-
124-
cache = self.caches[function_name]
125-
if key in cache:
126-
# Return cached response
127-
response = json.loads(cache[key])
128-
else:
129-
response = func(**kwargs)
130-
131-
if response is not None:
132-
# Don't cache None values.
133-
cache[key] = json.dumps(response)
134-
135-
cache_file.write_text(json.dumps(cache))
136-
137-
return response
138-
139-
return wrapper
30+
from apeye.cache import Cache
14031

32+
__all__ = ["cache"]
14133

14234
cache = Cache("seed_intersphinx_mapping")

seed_intersphinx_mapping/core.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,17 @@
3535
# 3rd party
3636
import importlib_resources
3737
import requests
38-
import slumber
38+
from apeye.url import SlumberURL
3939
from domdf_python_tools.typing import PathLike
4040

4141
# this package
4242
from seed_intersphinx_mapping.cache import cache
4343
from seed_intersphinx_mapping.requirements_parsers import parse_requirements_txt
4444

45-
__all__ = ["search_dict", "get_sphinx_doc_url", "fallback_mapping", "seed_intersphinx_mapping"]
45+
__all__ = ["search_dict", "get_sphinx_doc_url", "fallback_mapping", "seed_intersphinx_mapping", "pypi_api"]
4646

47-
pypi_simple = slumber.API("https://pypi.org/pypi/")
47+
#: :class:`apeye.url.SlumberURL` for the PyPI REST API endpoint.
48+
pypi_api = SlumberURL("https://pypi.org/pypi/")
4849

4950

5051
def search_dict(dictionary: Dict[str, Any], regex: Union[str, Pattern]) -> Dict[str, Any]:
@@ -86,7 +87,7 @@ def get_sphinx_doc_url(pypi_name: str) -> str:
8687
| :exc:`slumber.exceptions.HttpNotFoundError` if the project could not be found on PyPI.
8788
"""
8889

89-
pypi_data = getattr(pypi_simple, pypi_name).json.get()
90+
pypi_data = (pypi_api / pypi_name / "json").get()
9091

9192
if "project_urls" in pypi_data["info"]:
9293
docs_dict = search_dict(pypi_data["info"]["project_urls"], r"^[dD]oc(s|umentation)")

tests/test_cache.py

Lines changed: 0 additions & 59 deletions
This file was deleted.

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ commands =
150150

151151
[flake8]
152152
max-line-length = 120
153-
select = E301 E303 E304 E305 E306 E502 W291 W293 W391 E226 E225 E241 E231 W292 E265 E101 E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E227 E228 E242 E251 E261 E262 E271 E272 E402 E703 E711 E712 E713 E714 E721 W504 E302 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT004 PT005 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q000 Q001 Q002 Q003 A001 A002 A003 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000
153+
select = E301 E303 E304 E305 E306 E502 W291 W293 W391 E226 E225 E241 E231 W292 E265 E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E227 E228 E242 E251 E261 E262 E271 E272 E402 E703 E711 E712 E713 E714 E721 W504 E302 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT004 PT005 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q000 Q001 Q002 Q003 A001 A002 A003 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000
154154
exclude = .git,__pycache__,doc-source,old,build,dist,make_conda_recipe.py,__pkginfo__.py,setup.py
155155
rst-roles =
156156
class

0 commit comments

Comments
 (0)