meta: cache: rework cache clear (MR 2252)

This makes a looot more sense. Add a disable method too for use in
tests.

Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
This commit is contained in:
Caleb Connolly 2024-06-13 05:57:38 +02:00 committed by Oliver Smith
parent 0365438134
commit 2cf44da301
No known key found for this signature in database
GPG key ID: 5AE7F5513E0885CB
3 changed files with 11 additions and 33 deletions

View file

@ -79,9 +79,9 @@ def zap(confirm=True, dry=False, pkgs_local=False, http=False,
pmb.config.workdir.clean() pmb.config.workdir.clean()
# Chroots were zapped, so no repo lists exist anymore # Chroots were zapped, so no repo lists exist anymore
Cache.clear_cache(pmb.chroot.apk.update_repository_list) pmb.chroot.apk.update_repository_list.cache_clear()
# Let chroot.init be called again # Let chroot.init be called again
Cache.clear_cache(pmb.chroot.init) pmb.chroot.init.cache_clear()
# Print amount of cleaned up space # Print amount of cleaned up space
if dry: if dry:

View file

@ -47,7 +47,7 @@ def replace_apkbuild(args: PmbArgs, pkgname, key, new, in_quotes=False):
replace(path, "\n" + line_old + "\n", "\n" + line_new + "\n") replace(path, "\n" + line_old + "\n", "\n" + line_new + "\n")
# Verify # Verify
Cache.clear_cache(pmb.parse.apkbuild) pmb.parse.apkbuild.cache_clear()
apkbuild = pmb.parse.apkbuild(path) apkbuild = pmb.parse.apkbuild(path)
if apkbuild[key] != str(new): if apkbuild[key] != str(new):
raise RuntimeError("Failed to set '{}' for pmaport '{}'. Make sure" raise RuntimeError("Failed to set '{}' for pmaport '{}'. Make sure"

View file

@ -9,9 +9,9 @@ class Wrapper:
def __init__(self, cache: "Cache", func: Callable): def __init__(self, cache: "Cache", func: Callable):
self.cache = cache self.cache = cache
self.func = func self.func = func
self.disabled = False
self.__module__ = func.__module__ self.__module__ = func.__module__
self.__name__ = func.__name__ self.__name__ = func.__name__
self.fhash = hash(func)
# When someone attempts to call a cached function, they'll # When someone attempts to call a cached function, they'll
@ -19,13 +19,14 @@ class Wrapper:
# result and if not then we do the actual function call and # result and if not then we do the actual function call and
# cache it if applicable # cache it if applicable
def __call__(self, *args, **kwargs): def __call__(self, *args, **kwargs):
#print(f"Cache.wrapper({args}, {kwargs})") if self.disabled:
return self.func(*args, **kwargs)
# Build the cache key from the function arguments that we # Build the cache key from the function arguments that we
# care about, which might be none of them # care about, which might be none of them
key = self.cache.build_key(self.func, *args, **kwargs) key = self.cache.build_key(self.func, *args, **kwargs)
# Don't cache # Don't cache
if key is None: if key is None:
# print(f"Cache: {func.__name__} NULL key!")
return self.func(*args, **kwargs) return self.func(*args, **kwargs)
if key not in self.cache.cache: if key not in self.cache.cache:
@ -39,14 +40,11 @@ class Wrapper:
#print(f"Cache: {func.__name__}({key})") #print(f"Cache: {func.__name__}({key})")
return self.cache.cache[key] return self.cache.cache[key]
def cache_clear(self):
self.cache.clear()
# This is a hacky workaround to let us fetch the hash of the def cache_disable(self):
# underlying function, since hash(cached_func()) would just get self.disabled = True
# the hash of the wrapper
def __getattribute__(self, name: str):
if name == "@realhash":
return self.fhash
return super(Wrapper, self).__getattribute__(name)
class Cache: class Cache:
@ -56,7 +54,6 @@ class Cache:
:param kwargs: these are arguments where we should only cache if the :param kwargs: these are arguments where we should only cache if the
function is called with the given value. For example, in pmb.build._package function is called with the given value. For example, in pmb.build._package
we never want to use the cached result when called with force=True.""" we never want to use the cached result when called with force=True."""
_cache: Dict[int, "Cache"] = {}
def __init__(self, *args, cache_deepcopy=False, **kwargs): def __init__(self, *args, cache_deepcopy=False, **kwargs):
for a in args: for a in args:
@ -66,7 +63,6 @@ class Cache:
if len(args) != len(set(args)): if len(args) != len(set(args)):
raise ValueError("Duplicate cache key properties") raise ValueError("Duplicate cache key properties")
# print(f"Cache.__init__({args})")
self.cache = {} self.cache = {}
self.params = args self.params = args
self.kwargs = kwargs self.kwargs = kwargs
@ -81,7 +77,6 @@ class Cache:
if not self.params and not self.kwargs: if not self.params and not self.kwargs:
return key return key
#print(f"Cache.build_key({func}, {args}, {kwargs})")
argnames = list(func.__code__.co_varnames)[:func.__code__.co_argcount] argnames = list(func.__code__.co_varnames)[:func.__code__.co_argcount]
# Build a dictionary of the arguments passed to the function and their values # Build a dictionary of the arguments passed to the function and their values
@ -127,10 +122,6 @@ class Cache:
def __call__(self, func: Callable): def __call__(self, func: Callable):
fhash = hash(func)
Cache._cache[fhash] = self
# print(f"Cache: {func.__module__}.{func.__name__} hash {fhash}")
# print(f"Cache.__call__({func})")
argnames = func.__code__.co_varnames argnames = func.__code__.co_varnames
for a in self.params: for a in self.params:
if a not in argnames: if a not in argnames:
@ -141,16 +132,3 @@ class Cache:
def clear(self): def clear(self):
self.cache.clear() self.cache.clear()
@staticmethod
def clear_cache(func: Callable):
key = None
try:
key = getattr(func, "@realhash")
except AttributeError:
return
cache = getattr(Cache, "_cache")
if key not in cache:
return
cache[key].clear()