Install & Compatibility
Where this runs
tested against v6.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.910 runs
installs and imports cleanly · install 0.0s · import 0.000s · 17.9MB
glibcpy 3.10–3.910 runs
installs and imports cleanly · install 1.8s · import 0.000s · 18MB
19MB installed
● package 19MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
CachedProperty
✓ from zope.cachedescriptors.property import CachedProperty
✗ from zope.cachedescriptors import CachedProperty
CachedProperty is located in the 'property' submodule.
cached
✓ from zope.cachedescriptors.method import cached
✗ from zope.cachedescriptors import cached
The cached decorator is located in the 'method' submodule.
Demonstrates basic usage of `CachedProperty` and `cached` decorators, including how to access cached values and perform explicit invalidation for both properties and methods. Note the distinct invalidation patterns for each.
from zope.cachedescriptors.property import CachedProperty
from zope.cachedescriptors.method import cached
import time
class DataFetcher:
def __init__(self, id_val):
self.id = id_val
self._fetch_count = 0
@CachedProperty
def expensive_property(self):
self._fetch_count += 1
print(f" [Property] Fetching data for {self.id}... (call {self._fetch_count})")
time.sleep(0.1) # Simulate network delay
return f"Data for {self.id}-{time.time()}"
@cached
def expensive_method(self, param):
self._fetch_count += 1
print(f" [Method] Fetching data for {self.id} with param {param}... (call {self._fetch_count})")
time.sleep(0.1) # Simulate network delay
return f"Result for {self.id}-{param}-{time.time()}"
# Example Usage
fetcher = DataFetcher("user123")
print("--- CachedProperty Demo ---")
result1 = fetcher.expensive_property
print(f"Property 1: {result1}")
result2 = fetcher.expensive_property # Should be cached
print(f"Property 2: {result2}")
assert result1 == result2
# Invalidate the property cache by deleting the attribute
del fetcher.expensive_property
result3 = fetcher.expensive_property # Should re-calculate
print(f"Property 3 (after invalidation): {result3}")
assert result1 != result3
print("\n--- CachedMethod Demo ---")
method_result1 = fetcher.expensive_method("report_a")
print(f"Method 1: {method_result1}")
method_result2 = fetcher.expensive_method("report_a") # Should be cached
print(f"Method 2: {method_result2}")
assert method_result1 == method_result2
# Invalidate a specific method call with arguments
fetcher.expensive_method.invalidate(fetcher, "report_a")
method_result3 = fetcher.expensive_method("report_a") # Should re-calculate
print(f"Method 3 (after invalidation): {method_result3}")
assert method_result1 != method_result3
method_result4 = fetcher.expensive_method("report_b") # New argument, new cache entry
print(f"Method 4: {method_result4}")
Errors
Common errors & fixes
AttributeError: 'CachedProperty' object has no attribute 'invalidate'
Attempting to invalidate a `CachedProperty` using a method-style invalidation call (like `obj.prop.invalidate()`) which is meant for `cached` methods.
fixCached properties are invalidated by deleting the attribute: `del obj.your_property`.
TypeError: cached() missing 1 required positional argument: 'func'
Trying to use `@cached()` without parentheses for the decorator, or trying to call the `cached` decorator directly without providing a function.
fix`@cached` is a decorator without arguments, so use `@cached` (no parentheses). Ensure it's placed directly above a method definition.
ImportError: cannot import name 'CachedProperty' from 'zope.cachedescriptors'
Incorrect import path. `CachedProperty` and `cached` are in specific submodules, not directly under `zope.cachedescriptors`.
fixUse the correct import paths: `from zope.cachedescriptors.property import CachedProperty` and `from zope.cachedescriptors.method import cached`.
Upgrade
Version history
6.0latest on PyPI · released Sep 12, 2025
Audit
Dependencies
zope.interfacerequiredRequired for core functionality and introspection within the Zope ecosystem.
zope.securityrequiredRequired for security integration, especially when used in Zope applications. Considered a core dependency.