Migrations
Upgrade guides for breaking changes to the cachetta PyPI package. Each entry is required to include all five sections below. Write “None.” if a section truly has no content, so reviewers know it was considered.
v0.7 → v0.8
Summary
The skip_self option has been removed. It existed so that decorating an instance/class method wouldn’t fold the receiver (self/cls) into the cache key, but it worked by blindly stripping the first positional argument whenever set — with no check that the call was actually a method, so setting it on a plain function silently discarded a real argument. Receiver exclusion is now automatic: the decorator detects method binding via the descriptor protocol and strips the receiver from key/path resolution while still passing it to the wrapped function. Plain functions keep all of their positional arguments. Because detection is automatic and correct, the flag is no longer needed and passing it raises TypeError.
Required changes
| Before | After | |——–|——-| | @Cachetta(path=fn, skip_self=True)def method(self, x): ... | @Cachetta(path=fn)def method(self, x): ...
receiver excluded automatically | | cache = Cachetta(path=..., skip_self=True) | cache = Cachetta(path=...) | | cache.copy(skip_self=True) | cache.copy() |
Deprecations removed
- The
skip_selffield onCachetta(and theskip_self=keyword to its constructor,copy, and per-decoration overrides). It was never deprecated with a warning; it is removed outright.
Behavior changes without code changes
- Decorating an instance/class method now excludes the receiver from the cache key by default. Code that previously relied on the old default (
skip_self=False) to key on the receiver — e.g. a callablepathorhashed=Truewhose key intentionally varied per instance — will now share cache entries across instances for equal arguments. This was almost never intentional (object identity is not stable across runs), but if you need per-instance partitioning, key on an explicit instance attribute via a callablepath.
Verification
- After upgrading, confirm the receiver no longer reaches a callable path:
from cachetta import Cachetta seen = [] cache = Cachetta(path=lambda x: seen.append(x) or f"/tmp/{x}.dat") class Svc: @cache def get(self, x): return x Svc().get("a") assert seen == ["a"] # the path callable saw "a", not (self, "a")Pre-upgrade (without
skip_self=True) this raisedTypeErrorbecause the lambda receivedselfas an extra positional argument.
v0.6 → v0.7
Summary
The implicit “sibling-hash” behavior has been removed. When path was a str or Path, cachetta used to silently rewrite the filename into a {stem}-{hash}{ext} sibling whenever the wrapped function received arguments. That default collided across functions that happened to share a stem in the same folder, left a dead stem prefix on every file name, and gave callers no clean way to organize multiple cache kinds under one root. path=str|Path now means exactly that: cachetta writes to the literal path you gave it, regardless of arguments.
Required changes
| Before | After | |——–|——-| | @Cachetta(path="cache/llm.pkl")def call(prompt): ...
wrote to cache/llm-<hash>.pkl | @Cachetta(path=lambda prompt: f"cache/llm/{prompt}.pkl")def call(prompt): ...
explicit per-arg path callable | | cache = Cachetta(path="cache.json")cache.invalidate("a")
removed cache-<hash>.json | cache = Cachetta(path=lambda x: f"cache/{x}.json")cache.invalidate("a")
removes the path you actually wrote |
If a single literal file is what you actually want, no change is needed — that’s the new default.
Deprecations removed
- The implicit
{stem}-{hash}{ext}sibling rewrite inCachetta._get_pathwhenpathis astrorPath.
Behavior changes without code changes
Cachetta(path="cache.json")decorating a function with arguments now writes every call tocache.json(last write wins) instead of fanning out into per-args sibling files. Existing on-diskcache-<hash>.jsonfiles written by older versions are no longer read; delete or migrate them by hand if you need their contents.
Verification
- After upgrading, run:
from cachetta import Cachetta cache = Cachetta(path="/tmp/cachetta_check.pkl") assert str(cache._get_path("anything")) == "/tmp/cachetta_check.pkl"The assertion should succeed; pre-upgrade it produced a path of the form
/tmp/cachetta_check-<hash>.pkl.