Use this file to discover all available pages before exploring further.
mapres includes a built-in LRU (Least Recently Used) cache that memoizes resolution results keyed on the input text and context kwargs. When a template string and its associated context have been resolved before, the cached result is returned immediately — skipping the pipeline, syntax providers, and map substitution entirely.
Pass cache=True to the MapResolver constructor. Use cache_size to control how many distinct entries the cache can hold before it starts evicting the oldest ones (default is 1024):
from mapres import MapResolverresolver = MapResolver(cache=True, cache_size=2048)# First call — resolved normally and stored in cacheresult = resolver.res("Hello, {name}!", name="Alice")# Second call with identical text + context — served from cacheresult = resolver.res("Hello, {name}!", name="Alice")
Set cache_size to match the number of distinct template strings your application uses. Over-sizing wastes memory; under-sizing causes frequent evictions that reduce the benefit of caching.
The cache key is a tuple of the raw input text and the sorted context items:
key = (text, tuple(sorted(ctx.items())))
This means two calls with the same template and the same kwargs — regardless of kwarg insertion order — share a single cache entry.However, calls that use extra_maps or override_mapsbypass the cache entirely. Looking at the res() implementation:
def res(self, text, *, extra_maps=None, override_maps=None, **ctx) -> str: if override_maps is not None: temp = LayerStack([Layer("override", override_maps, priority=0)]) return self._recursive(text, ctx, temp) # no cache check if extra_maps: temp = self.layers.clone() temp.add_layer(Layer("extra", extra_maps, priority=999)) return self._recursive(text, ctx, temp) # no cache check if self.cache_enabled: key = (text, tuple(sorted(ctx.items()))) cached = self.cache.get(key) if cached is not None: return cached ...
If you rely on extra_maps or override_maps frequently, caching will not benefit those calls.
When the cache is full, the entry at the front of the internal dict (the oldest insertion) is removed to make room. LRUCache is not part of the public API and you should not need to interact with it directly — MapResolver manages it for you.
Caching works best when the same template strings appear repeatedly with the same context values, and when your maps hold static data:
from mapres import MapResolver, datamap@datamapclass Phrases: greeting: str = "Hello" farewell: str = "Goodbye"resolver = MapResolver( layers=[], cache=True, cache_size=256,)# Called thousands of times with a small set of distinct inputsfor user in users: msg = resolver.res("{greeting}, {name}!", name=user)
Do not enable caching when your LayerStack contains TimeMap or any mode='dynamic'DataMap. The cache will return stale values — for example, a timestamp captured on the first call — on every subsequent identical call.
There is no explicit cache-clearing API on MapResolver. If your maps change or you need a fresh cache, create a new resolver instance:
from mapres import MapResolver# Old resolver — may have stale cached entriesold_resolver = MapResolver(cache=True)# Fresh resolver — empty cache, picks up any new map datafresh_resolver = MapResolver(cache=True, cache_size=1024)
Because resolvers are lightweight objects, constructing a new one is inexpensive and is the recommended invalidation strategy.