Repository navigation
v5.8.0
The package is now imported as diskcache_community, so it installs next to the upstream diskcache package instead of replacing it. The cache.db schema, the file layout, the serialization modes, the memoize key format and the persisted settings are unchanged, so a 5.6.3 process opens a directory written by 5.8.0 and the reverse. SafeDisk stays opt-in and gains an allowlist for your own classes, a process-wide default disk selects it for caches that libraries create, and caches can treat unreadable entries as missing.
Security
SafeDisk.with_types(*types, modules=())returns aSafeDisksubclass whose allowlist adds the given classes, matched by identity, and every class defined in the named modules or below them. A module name may only reach a class defined in that module: a dotted name such asos.system, reached through a module that importsos, a class the module merely imports, a module and a dunder attribute are refused, and reading never imports a module, so a pickle cannot run a module's top-level code. numpy classes are refused (UNSAFE_MODULES), because numpy restores a dtype's flags from the pickle without checking them and a crafted array pickle can corrupt memory. Writes stay exact: a value outside the standard-library types is pickled and the names its pickle looks up are checked against the same allowlist, so a value the reader would refuse raisesTypeErrornaming the class before anything is written. Callingwith_typesagain adds to the allowlist, and aCache,FanoutCache,Deque,IndexorDjangoCacheusing the returned class pickles as before. The plainSafeDiskis unchanged (PR #23).
Docs
SECURITY.mddescribes what 5.8.0 adds for CVE-2025-69872 and links the steps (PR #28).- Two new pages: "Fix CVE-2025-69872 in diskcache" gives the steps to read caches with
SafeDisk, including caches that libraries create, your own classes and entries already in the cache, and lists what any restricted disk has to cover; "Migrating from diskcache 5.6.3" covers the dependency, imports, Django settings, running next to upstreamdiskcache, the behaviour changes since 5.6.3 and going back. Both open the documentation and are linked from the README (PR #27). - A new benchmarks page, measured on 2026-10-12, compares diskcache-community with diskcache 5.6.3, memcached, Redis, lmdb, sqlitedict, shelve and the Django cache backends, with four charts. The scripts that produce it are in
tests/benchmarks(driver.pyruns the stores,report.pywrites the page and charts from the JSON results). The 2019 pages from upstream stay as the old benchmarks, labelled as such and linked from the new page, and the README header, features and documentation list link to the new page (PR #26). - Shared links show a project card: a social preview image in
.github/, and Open Graph tags on the documentation throughsphinxext-opengraph(PR #21). - A logo: the README opens with a centered header (logo, name, tagline, links, badges) in the style of the other community forks, and the documentation shows the logo and a favicon (PR #20).
- The README is rewritten in Markdown around install, usage and the fork story; the comparison tables move to a new
comparisonspage in the documentation, which gets its own landing page, and the 2016 testimonials are dropped (PR #19). - The documentation is published on Read the Docs at https://diskcache-community.readthedocs.io/, built from
masteron every push; the README links point there instead of at the.rstsources (PR #18).
Features
Disk.with_options(on_error='miss')returns a disk type, on any disk class includingSafeDiskand the classeswith_typesreturns, whose caches delete an entry they find but cannot read back (a corrupt or stale pickle, a refused type, a path outside the cache, an undecodable text file) and treat it as missing:getreturns its default,cache[key]raisesKeyError,pop,pull,peekandpeekitemmove on, and iteration skips unreadable keys.Index.items()andvalues()skip such entries too. The first such entry per cache is logged as a warning on thediskcache_communitylogger; a read-only cache does not delete it, and itspeekandpeekitemraise. A missing value file,MemoryErrorandRecursionErrorare never treated as unreadable. The default,on_error='raise', keeps raising as before, and the option is a class attribute that is never persisted (PR #25).configure(disk)sets the disk type of everyCache,FanoutCache,Deque,IndexandDjangoCachecreated afterwards without a disk, anddefault_disk()returns the type in effect. Withoutconfigure, the environment decides:DISKCACHE_DISK=safeselectsSafeDisk, withDISKCACHE_SAFE_TYPESandDISKCACHE_SAFE_MODULESpassed toSafeDisk.with_types, andDISKCACHE_DISKalso takesdefaultor the import path of a disk class. A disk passed explicitly always wins, so libraries that choose their own disk keep it; caches that already exist keep theirs, and nothing is persisted. Thediskarguments now default toNone, meaning that type (PR #24).
Packaging
- Breaking: the package is imported as
diskcache_communityinstead ofdiskcache, so it installs next to the upstreamdiskcachedistribution without overwriting it, and a project can move to the fork while other dependencies still requirediskcache. The public API, thecache.dbschema, the file layout and the serialization are unchanged, so cache directories are shared with 5.6.3 in both directions. Django settings namediskcache_community.DjangoCacheanddiskcache_community.SafeDisk. The import-time warning about an upstreamdiskcacheinstalled in the same environment is gone, and a CI job installs both distributions together, runs the golden tests in both directions and checks that uninstalling either leaves the other working (PR #22). LICENSEnow holds the full Apache License 2.0 text instead of the short boilerplate notice, so GitHub and package indexes detect the license; the copyright and fork notice stay inNOTICE(PR #21).