Acquisition
Acquisition is a mechanism that allows objects to obtain attributes from the containment hierarchy they're in. This foundational Zope library, currently at version 6.2, facilitates dynamic attribute lookup based on an object's position within a hierarchy or explicitly set context. While it does not have a fixed release cadence, it is actively maintained by the Zope Foundation.
Common errors
-
AttributeError: 'ClassName' object has no attribute 'attribute_name'
cause The requested attribute 'attribute_name' could not be found on the object itself, nor was it successfully acquired from its containment hierarchy or explicit context. This often means the attribute is missing, or the acquisition path is not correctly configured.fixInspect the object's acquisition chain using `obj.aq_chain()` to verify the available parents and their attributes. Ensure the attribute exists on one of the objects in the expected acquisition path. Use `obj.aq_acquire(attribute_name, default=None)` to safely test for acquirable attributes. -
ModuleNotFoundError: No module named 'Acquisition'
cause The 'Acquisition' library is not installed in the current Python environment, or the environment is not correctly activated.fixInstall the library using pip: `pip install Acquisition`. If using a virtual environment, ensure it is activated before installation and execution. -
TypeError: descriptor '__of__' requires a 'ClassName' object but received a 'AnotherClass' object
cause The `__of__` method, used to set acquisition context, expects an instance of an Acquisition-aware class (e.g., one that inherits from `Acquisition.Implicit` or `Acquisition.Explicit`). Providing an object of a different type will raise a TypeError.fixEnsure that both the object on which `__of__` is called and the object passed as its argument are instances of classes that properly support Acquisition, typically by inheriting from `Acquisition.Implicit` or `Acquisition.Explicit`.
Warnings
- gotcha C methods defined in extension base classes that define their own data structures cannot use acquired attributes. This is because acquisition wrapper objects do not conform to the data structures expected by these methods, leading to potential `AttributeError` or `TypeError` if invoked on an wrapped object.
- gotcha The behavior of acquisition can become complex due to subtle differences between 'acquiring from context' and 'acquiring from containment'. Misunderstanding these distinctions can lead to unexpected attribute resolution or attributes not being found.
- gotcha Over-reliance on implicit acquisition can make code harder to reason about and debug, as attribute sources are not immediately obvious. This can lead to unexpected side effects or performance overhead from dynamic lookups.
Install
-
pip install Acquisition
Imports
- Implicit
import Acquisition.Implicit
from Acquisition import Implicit
- aq_acquire
obj.aq_acquire
from Acquisition import aq_acquire
Quickstart
from Acquisition import Implicit
class C(Implicit):
pass
a = C()
b = C()
a.color = "red"
# 'b' acquires 'color' from 'a' because 'a' is put into b's context
print(b.__of__(a).color)
class X(Implicit):
pass
x = X().__of__(b.__of__(a))
# 'x' acquires 'color' from 'a' through 'b'
print(x.color)