{"id":7894,"library":"acquisition","title":"Acquisition","description":"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.","status":"active","version":"6.2","language":"en","source_language":"en","source_url":"https://github.com/zopefoundation/Acquisition","tags":["zope","acquisition","containment","context","object-oriented","attribute lookup","hierarchy"],"install":[{"cmd":"pip install Acquisition","lang":"bash","label":"Install via pip"}],"dependencies":[],"imports":[{"note":"Common mistake is to try and import 'Implicit' directly as a submodule rather than from the Acquisition package.","wrong":"import Acquisition.Implicit","symbol":"Implicit","correct":"from Acquisition import Implicit"},{"note":"While 'obj.aq_acquire' is a method on an acquirable object, 'aq_acquire' can also be imported as a module function for explicit acquisition calls.","wrong":"obj.aq_acquire","symbol":"aq_acquire","correct":"from Acquisition import aq_acquire"}],"quickstart":{"code":"from Acquisition import Implicit\n\nclass C(Implicit):\n    pass\n\na = C()\nb = C()\n\na.color = \"red\"\n\n# 'b' acquires 'color' from 'a' because 'a' is put into b's context\nprint(b.__of__(a).color)\n\nclass X(Implicit):\n    pass\n\nx = X().__of__(b.__of__(a))\n\n# 'x' acquires 'color' from 'a' through 'b'\nprint(x.color)","lang":"python","description":"This example demonstrates basic implicit acquisition. An object `b` acquires attributes from `a` when `a` is set as its context using `__of__`. Subsequent objects in the context chain can also acquire attributes from higher up the hierarchy."},"warnings":[{"fix":"Avoid using Acquisition with C methods in extension base classes that rely on specific internal data structures. Consider refactoring to use Python methods or explicitly unwrapping the object (`obj.aq_base`) before calling C methods, though this removes acquisition capabilities for that call.","message":"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.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Carefully review the official documentation on explicit vs. implicit acquisition and the roles of `__of__` (context) and object containment. Debug acquisition paths using `obj.aq_chain()` to visualize the hierarchy and `obj.aq_base` to get the unwrapped object.","message":"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.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Use acquisition judiciously for genuinely hierarchical patterns. For critical paths or where clarity is paramount, consider more explicit dependency injection or passing attributes directly rather than relying solely on the acquisition chain.","message":"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.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Inspect 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.","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.","error":"AttributeError: 'ClassName' object has no attribute 'attribute_name'"},{"fix":"Install the library using pip: `pip install Acquisition`. If using a virtual environment, ensure it is activated before installation and execution.","cause":"The 'Acquisition' library is not installed in the current Python environment, or the environment is not correctly activated.","error":"ModuleNotFoundError: No module named 'Acquisition'"},{"fix":"Ensure 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`.","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.","error":"TypeError: descriptor '__of__' requires a 'ClassName' object but received a 'AnotherClass' object"}]}