|
|
|
@@ -0,0 +1,697 @@
|
|
|
|
|
Metadata-Version: 1.1
|
|
|
|
|
Name: Acquisition
|
|
|
|
|
Version: 4.5
|
|
|
|
|
Summary: Acquisition is a mechanism that allows objects to obtain attributes from the containment hierarchy they're in.
|
|
|
|
|
Home-page: https://github.com/zopefoundation/Acquisition
|
|
|
|
|
Author: Zope Foundation and Contributors
|
|
|
|
|
Author-email: zope-dev@zope.org
|
|
|
|
|
License: ZPL 2.1
|
|
|
|
|
Description: Environmental Acquisiton
|
|
|
|
|
========================
|
|
|
|
|
|
|
|
|
|
This package implements "environmental acquisiton" for Python, as
|
|
|
|
|
proposed in the OOPSLA96_ paper by Joseph Gil and David H. Lorenz:
|
|
|
|
|
|
|
|
|
|
We propose a new programming paradigm, environmental acquisition in
|
|
|
|
|
the context of object aggregation, in which objects acquire
|
|
|
|
|
behaviour from their current containers at runtime. The key idea is
|
|
|
|
|
that the behaviour of a component may depend upon its enclosing
|
|
|
|
|
composite(s). In particular, we propose a form of feature sharing in
|
|
|
|
|
which an object "inherits" features from the classes of objects in
|
|
|
|
|
its environment. By examining the declaration of classes, it is
|
|
|
|
|
possible to determine which kinds of classes may contain a
|
|
|
|
|
component, and which components must be contained in a given kind of
|
|
|
|
|
composite. These relationships are the basis for language constructs
|
|
|
|
|
that supports acquisition.
|
|
|
|
|
|
|
|
|
|
.. _OOPSLA96: http://www.cs.virginia.edu/~lorenz/papers/oopsla96/>`_:
|
|
|
|
|
|
|
|
|
|
.. contents::
|
|
|
|
|
|
|
|
|
|
Introductory Example
|
|
|
|
|
--------------------
|
|
|
|
|
|
|
|
|
|
Zope implements acquisition with "Extension Class" mix-in classes. To
|
|
|
|
|
use acquisition your classes must inherit from an acquisition base
|
|
|
|
|
class. For example::
|
|
|
|
|
|
|
|
|
|
>>> import ExtensionClass, Acquisition
|
|
|
|
|
|
|
|
|
|
>>> class C(ExtensionClass.Base):
|
|
|
|
|
... color = 'red'
|
|
|
|
|
|
|
|
|
|
>>> class A(Acquisition.Implicit):
|
|
|
|
|
... def report(self):
|
|
|
|
|
... print(self.color)
|
|
|
|
|
...
|
|
|
|
|
>>> a = A()
|
|
|
|
|
>>> c = C()
|
|
|
|
|
>>> c.a = a
|
|
|
|
|
|
|
|
|
|
>>> c.a.report()
|
|
|
|
|
red
|
|
|
|
|
|
|
|
|
|
>>> d = C()
|
|
|
|
|
>>> d.color = 'green'
|
|
|
|
|
>>> d.a = a
|
|
|
|
|
|
|
|
|
|
>>> d.a.report()
|
|
|
|
|
green
|
|
|
|
|
|
|
|
|
|
>>> try:
|
|
|
|
|
... a.report()
|
|
|
|
|
... except AttributeError:
|
|
|
|
|
... pass
|
|
|
|
|
... else:
|
|
|
|
|
... raise AssertionError('AttributeError not raised.')
|
|
|
|
|
|
|
|
|
|
The class ``A`` inherits acquisition behavior from
|
|
|
|
|
``Acquisition.Implicit``. The object, ``a``, "has" the color of
|
|
|
|
|
objects ``c`` and d when it is accessed through them, but it has no
|
|
|
|
|
color by itself. The object ``a`` obtains attributes from its
|
|
|
|
|
environment, where its environment is defined by the access path used
|
|
|
|
|
to reach ``a``.
|
|
|
|
|
|
|
|
|
|
Acquisition Wrappers
|
|
|
|
|
--------------------
|
|
|
|
|
|
|
|
|
|
When an object that supports acquisition is accessed through an
|
|
|
|
|
extension class instance, a special object, called an acquisition
|
|
|
|
|
wrapper, is returned. In the example above, the expression ``c.a``
|
|
|
|
|
returns an acquisition wrapper that contains references to both ``c``
|
|
|
|
|
and ``a``. It is this wrapper that performs attribute lookup in ``c``
|
|
|
|
|
when an attribute cannot be found in ``a``.
|
|
|
|
|
|
|
|
|
|
Acquisition wrappers provide access to the wrapped objects through the
|
|
|
|
|
attributes ``aq_parent``, ``aq_self``, ``aq_base``. Continue the
|
|
|
|
|
example from above::
|
|
|
|
|
|
|
|
|
|
>>> c.a.aq_parent is c
|
|
|
|
|
True
|
|
|
|
|
>>> c.a.aq_self is a
|
|
|
|
|
True
|
|
|
|
|
|
|
|
|
|
Explicit and Implicit Acquisition
|
|
|
|
|
---------------------------------
|
|
|
|
|
|
|
|
|
|
Two styles of acquisition are supported: implicit and explicit
|
|
|
|
|
acquisition.
|
|
|
|
|
|
|
|
|
|
Implicit acquisition
|
|
|
|
|
--------------------
|
|
|
|
|
|
|
|
|
|
Implicit acquisition is so named because it searches for attributes
|
|
|
|
|
from the environment automatically whenever an attribute cannot be
|
|
|
|
|
obtained directly from an object or through inheritance.
|
|
|
|
|
|
|
|
|
|
An attribute can be implicitly acquired if its name does not begin
|
|
|
|
|
with an underscore.
|
|
|
|
|
|
|
|
|
|
To support implicit acquisition, your class should inherit from the
|
|
|
|
|
mix-in class ``Acquisition.Implicit``.
|
|
|
|
|
|
|
|
|
|
Explicit Acquisition
|
|
|
|
|
--------------------
|
|
|
|
|
|
|
|
|
|
When explicit acquisition is used, attributes are not automatically
|
|
|
|
|
obtained from the environment. Instead, the method aq_acquire must be
|
|
|
|
|
used. For example::
|
|
|
|
|
|
|
|
|
|
>>> print(c.a.aq_acquire('color'))
|
|
|
|
|
red
|
|
|
|
|
|
|
|
|
|
To support explicit acquisition, your class should inherit from the
|
|
|
|
|
mix-in class ``Acquisition.Explicit``.
|
|
|
|
|
|
|
|
|
|
Controlling Acquisition
|
|
|
|
|
-----------------------
|
|
|
|
|
|
|
|
|
|
A class (or instance) can provide attribute by attribute control over
|
|
|
|
|
acquisition. Your should subclass from ``Acquisition.Explicit``, and set
|
|
|
|
|
all attributes that should be acquired to the special value
|
|
|
|
|
``Acquisition.Acquired``. Setting an attribute to this value also allows
|
|
|
|
|
inherited attributes to be overridden with acquired ones. For example::
|
|
|
|
|
|
|
|
|
|
>>> class C(Acquisition.Explicit):
|
|
|
|
|
... id = 1
|
|
|
|
|
... secret = 2
|
|
|
|
|
... color = Acquisition.Acquired
|
|
|
|
|
... __roles__ = Acquisition.Acquired
|
|
|
|
|
|
|
|
|
|
The only attributes that are automatically acquired from containing
|
|
|
|
|
objects are color, and ``__roles__``. Note that the ``__roles__``
|
|
|
|
|
attribute is acquired even though its name begins with an
|
|
|
|
|
underscore. In fact, the special ``Acquisition.Acquired`` value can be
|
|
|
|
|
used in ``Acquisition.Implicit`` objects to implicitly acquire
|
|
|
|
|
selected objects that smell like private objects.
|
|
|
|
|
|
|
|
|
|
Sometimes, you want to dynamically make an implicitly acquiring object
|
|
|
|
|
acquire explicitly. You can do this by getting the object's
|
|
|
|
|
aq_explicit attribute. This attribute provides the object with an
|
|
|
|
|
explicit wrapper that replaces the original implicit wrapper.
|
|
|
|
|
|
|
|
|
|
Filtered Acquisition
|
|
|
|
|
--------------------
|
|
|
|
|
|
|
|
|
|
The acquisition method, ``aq_acquire``, accepts two optional
|
|
|
|
|
arguments. The first of the additional arguments is a "filtering"
|
|
|
|
|
function that is used when considering whether to acquire an
|
|
|
|
|
object. The second of the additional arguments is an object that is
|
|
|
|
|
passed as extra data when calling the filtering function and which
|
|
|
|
|
defaults to ``None``. The filter function is called with five
|
|
|
|
|
arguments:
|
|
|
|
|
|
|
|
|
|
* The object that the aq_acquire method was called on,
|
|
|
|
|
|
|
|
|
|
* The object where an object was found,
|
|
|
|
|
|
|
|
|
|
* The name of the object, as passed to aq_acquire,
|
|
|
|
|
|
|
|
|
|
* The object found, and
|
|
|
|
|
|
|
|
|
|
* The extra data passed to aq_acquire.
|
|
|
|
|
|
|
|
|
|
If the filter returns a true object that the object found is returned,
|
|
|
|
|
otherwise, the acquisition search continues.
|
|
|
|
|
|
|
|
|
|
Here's an example::
|
|
|
|
|
|
|
|
|
|
>>> from Acquisition import Explicit
|
|
|
|
|
|
|
|
|
|
>>> class HandyForTesting(object):
|
|
|
|
|
... def __init__(self, name):
|
|
|
|
|
... self.name = name
|
|
|
|
|
... def __str__(self):
|
|
|
|
|
... return "%s(%s)" % (self.name, self.__class__.__name__)
|
|
|
|
|
... __repr__=__str__
|
|
|
|
|
...
|
|
|
|
|
>>> class E(Explicit, HandyForTesting): pass
|
|
|
|
|
...
|
|
|
|
|
>>> class Nice(HandyForTesting):
|
|
|
|
|
... isNice = 1
|
|
|
|
|
... def __str__(self):
|
|
|
|
|
... return HandyForTesting.__str__(self)+' and I am nice!'
|
|
|
|
|
... __repr__ = __str__
|
|
|
|
|
...
|
|
|
|
|
>>> a = E('a')
|
|
|
|
|
>>> a.b = E('b')
|
|
|
|
|
>>> a.b.c = E('c')
|
|
|
|
|
>>> a.p = Nice('spam')
|
|
|
|
|
>>> a.b.p = E('p')
|
|
|
|
|
|
|
|
|
|
>>> def find_nice(self, ancestor, name, object, extra):
|
|
|
|
|
... return hasattr(object,'isNice') and object.isNice
|
|
|
|
|
|
|
|
|
|
>>> print(a.b.c.aq_acquire('p', find_nice))
|
|
|
|
|
spam(Nice) and I am nice!
|
|
|
|
|
|
|
|
|
|
The filtered acquisition in the last line skips over the first
|
|
|
|
|
attribute it finds with the name ``p``, because the attribute doesn't
|
|
|
|
|
satisfy the condition given in the filter.
|
|
|
|
|
|
|
|
|
|
Filtered acquisition is rarely used in Zope.
|
|
|
|
|
|
|
|
|
|
Acquiring from Context
|
|
|
|
|
----------------------
|
|
|
|
|
|
|
|
|
|
Normally acquisition allows objects to acquire data from their
|
|
|
|
|
containers. However an object can acquire from objects that aren't its
|
|
|
|
|
containers.
|
|
|
|
|
|
|
|
|
|
Most of the examples we've seen so far show establishing of an
|
|
|
|
|
acquisition context using getattr semantics. For example, ``a.b`` is a
|
|
|
|
|
reference to ``b`` in the context of ``a``.
|
|
|
|
|
|
|
|
|
|
You can also manually set acquisition context using the ``__of__``
|
|
|
|
|
method. For example::
|
|
|
|
|
|
|
|
|
|
>>> from Acquisition import Implicit
|
|
|
|
|
>>> class C(Implicit): pass
|
|
|
|
|
...
|
|
|
|
|
>>> a = C()
|
|
|
|
|
>>> b = C()
|
|
|
|
|
>>> a.color = "red"
|
|
|
|
|
>>> print(b.__of__(a).color)
|
|
|
|
|
red
|
|
|
|
|
|
|
|
|
|
In this case, ``a`` does not contain ``b``, but it is put in ``b``'s
|
|
|
|
|
context using the ``__of__`` method.
|
|
|
|
|
|
|
|
|
|
Here's another subtler example that shows how you can construct an
|
|
|
|
|
acquisition context that includes non-container objects::
|
|
|
|
|
|
|
|
|
|
>>> from Acquisition import Implicit
|
|
|
|
|
|
|
|
|
|
>>> class C(Implicit):
|
|
|
|
|
... def __init__(self, name):
|
|
|
|
|
... self.name = name
|
|
|
|
|
|
|
|
|
|
>>> a = C("a")
|
|
|
|
|
>>> a.b = C("b")
|
|
|
|
|
>>> a.b.color = "red"
|
|
|
|
|
>>> a.x = C("x")
|
|
|
|
|
|
|
|
|
|
>>> print(a.b.x.color)
|
|
|
|
|
red
|
|
|
|
|
|
|
|
|
|
Even though ``b`` does not contain ``x``, ``x`` can acquire the color
|
|
|
|
|
attribute from ``b``. This works because in this case, ``x`` is accessed
|
|
|
|
|
in the context of ``b`` even though it is not contained by ``b``.
|
|
|
|
|
|
|
|
|
|
Here acquisition context is defined by the objects used to access
|
|
|
|
|
another object.
|
|
|
|
|
|
|
|
|
|
Containment Before Context
|
|
|
|
|
--------------------------
|
|
|
|
|
|
|
|
|
|
If in the example above suppose both a and b have an color attribute::
|
|
|
|
|
|
|
|
|
|
>>> a = C("a")
|
|
|
|
|
>>> a.color = "green"
|
|
|
|
|
>>> a.b = C("b")
|
|
|
|
|
>>> a.b.color = "red"
|
|
|
|
|
>>> a.x = C("x")
|
|
|
|
|
|
|
|
|
|
>>> print(a.b.x.color)
|
|
|
|
|
green
|
|
|
|
|
|
|
|
|
|
Why does ``a.b.x.color`` acquire color from ``a`` and not from ``b``?
|
|
|
|
|
The answer is that an object acquires from its containers before
|
|
|
|
|
non-containers in its context.
|
|
|
|
|
|
|
|
|
|
To see why consider this example in terms of expressions using the
|
|
|
|
|
``__of__`` method::
|
|
|
|
|
|
|
|
|
|
a.x -> x.__of__(a)
|
|
|
|
|
|
|
|
|
|
a.b -> b.__of__(a)
|
|
|
|
|
|
|
|
|
|
a.b.x -> x.__of__(a).__of__(b.__of__(a))
|
|
|
|
|
|
|
|
|
|
Keep in mind that attribute lookup in a wrapper is done by trying to
|
|
|
|
|
look up the attribute in the wrapped object first and then in the
|
|
|
|
|
parent object. So in the expressions above proceeds from left to
|
|
|
|
|
right.
|
|
|
|
|
|
|
|
|
|
The upshot of these rules is that attributes are looked up by
|
|
|
|
|
containment before context.
|
|
|
|
|
|
|
|
|
|
This rule holds true also for more complex examples. For example,
|
|
|
|
|
``a.b.c.d.e.f.g.attribute`` would search for attribute in ``g`` and
|
|
|
|
|
all its containers first. (Containers are searched in order from the
|
|
|
|
|
innermost parent to the outermost container.) If the attribute is not
|
|
|
|
|
found in ``g`` or any of its containers, then the search moves to
|
|
|
|
|
``f`` and all its containers, and so on.
|
|
|
|
|
|
|
|
|
|
Additional Attributes and Methods
|
|
|
|
|
---------------------------------
|
|
|
|
|
|
|
|
|
|
You can use the special method ``aq_inner`` to access an object
|
|
|
|
|
wrapped only by containment. So in the example above,
|
|
|
|
|
``a.b.x.aq_inner`` is equivalent to ``a.x``.
|
|
|
|
|
|
|
|
|
|
You can find out the acquisition context of an object using the
|
|
|
|
|
aq_chain method like so:
|
|
|
|
|
|
|
|
|
|
>>> [obj.name for obj in a.b.x.aq_chain]
|
|
|
|
|
['x', 'b', 'a']
|
|
|
|
|
|
|
|
|
|
You can find out if an object is in the containment context of another
|
|
|
|
|
object using the ``aq_inContextOf`` method. For example:
|
|
|
|
|
|
|
|
|
|
>>> a.b.aq_inContextOf(a)
|
|
|
|
|
True
|
|
|
|
|
|
|
|
|
|
.. Note: as of this writing the aq_inContextOf examples don't work the
|
|
|
|
|
way they should be working. According to Jim, this is because
|
|
|
|
|
aq_inContextOf works by comparing object pointer addresses, which
|
|
|
|
|
(because they are actually different wrapper objects) doesn't give
|
|
|
|
|
you the expected results. He acknowledges that this behavior is
|
|
|
|
|
controversial, and says that there is a collector entry to change
|
|
|
|
|
it so that you would get the answer you expect in the above. (We
|
|
|
|
|
just need to get to it).
|
|
|
|
|
|
|
|
|
|
Acquisition Module Functions
|
|
|
|
|
----------------------------
|
|
|
|
|
|
|
|
|
|
In addition to using acquisition attributes and methods directly on
|
|
|
|
|
objects you can use similar functions defined in the ``Acquisition``
|
|
|
|
|
module. These functions have the advantage that you don't need to
|
|
|
|
|
check to make sure that the object has the method or attribute before
|
|
|
|
|
calling it.
|
|
|
|
|
|
|
|
|
|
``aq_acquire(object, name [, filter, extra, explicit, default, containment])``
|
|
|
|
|
Acquires an object with the given name.
|
|
|
|
|
|
|
|
|
|
This function can be used to explictly acquire when using explicit
|
|
|
|
|
acquisition and to acquire names that wouldn't normally be
|
|
|
|
|
acquired.
|
|
|
|
|
|
|
|
|
|
The function accepts a number of optional arguments:
|
|
|
|
|
|
|
|
|
|
``filter``
|
|
|
|
|
A callable filter object that is used to decide if an object
|
|
|
|
|
should be acquired.
|
|
|
|
|
|
|
|
|
|
The filter is called with five arguments:
|
|
|
|
|
|
|
|
|
|
* The object that the aq_acquire method was called on,
|
|
|
|
|
|
|
|
|
|
* The object where an object was found,
|
|
|
|
|
|
|
|
|
|
* The name of the object, as passed to aq_acquire,
|
|
|
|
|
|
|
|
|
|
* The object found, and
|
|
|
|
|
|
|
|
|
|
* The extra argument passed to aq_acquire.
|
|
|
|
|
|
|
|
|
|
If the filter returns a true object that the object found is
|
|
|
|
|
returned, otherwise, the acquisition search continues.
|
|
|
|
|
|
|
|
|
|
``extra``
|
|
|
|
|
Extra data to be passed as the last argument to the filter.
|
|
|
|
|
|
|
|
|
|
``explicit``
|
|
|
|
|
A flag (boolean value) indicating whether explicit acquisition
|
|
|
|
|
should be used. The default value is true. If the flag is
|
|
|
|
|
true, then acquisition will proceed regardless of whether
|
|
|
|
|
wrappers encountered in the search of the acquisition
|
|
|
|
|
hierarchy are explicit or implicit wrappers. If the flag is
|
|
|
|
|
false, then parents of explicit wrappers are not searched.
|
|
|
|
|
|
|
|
|
|
This argument is useful if you want to apply a filter without
|
|
|
|
|
overriding explicit wrappers.
|
|
|
|
|
|
|
|
|
|
``default``
|
|
|
|
|
A default value to return if no value can be acquired.
|
|
|
|
|
|
|
|
|
|
``containment``
|
|
|
|
|
A flag indicating whether the search should be limited to the
|
|
|
|
|
containment hierarchy.
|
|
|
|
|
|
|
|
|
|
In addition, arguments can be provided as keywords.
|
|
|
|
|
|
|
|
|
|
``aq_base(object)``
|
|
|
|
|
Return the object with all wrapping removed.
|
|
|
|
|
|
|
|
|
|
``aq_chain(object [, containment])``
|
|
|
|
|
Return a list containing the object and it's acquisition
|
|
|
|
|
parents. The optional argument, containment, controls whether the
|
|
|
|
|
containment or access hierarchy is used.
|
|
|
|
|
|
|
|
|
|
``aq_get(object, name [, default, containment])``
|
|
|
|
|
Acquire an attribute, name. A default value can be provided, as
|
|
|
|
|
can a flag that limits search to the containment hierarchy.
|
|
|
|
|
|
|
|
|
|
``aq_inner(object)``
|
|
|
|
|
Return the object with all but the innermost layer of wrapping
|
|
|
|
|
removed.
|
|
|
|
|
|
|
|
|
|
``aq_parent(object)``
|
|
|
|
|
Return the acquisition parent of the object or None if the object
|
|
|
|
|
is unwrapped.
|
|
|
|
|
|
|
|
|
|
``aq_self(object)``
|
|
|
|
|
Return the object with one layer of wrapping removed, unless the
|
|
|
|
|
object is unwrapped, in which case the object is returned.
|
|
|
|
|
|
|
|
|
|
In most cases it is more convenient to use these module functions
|
|
|
|
|
instead of the acquisition attributes and methods directly.
|
|
|
|
|
|
|
|
|
|
Acquisition and Methods
|
|
|
|
|
-----------------------
|
|
|
|
|
|
|
|
|
|
Python methods of objects that support acquisition can use acquired
|
|
|
|
|
attributes. When a Python method is called on an object that is
|
|
|
|
|
wrapped by an acquisition wrapper, the wrapper is passed to the method
|
|
|
|
|
as the first argument. This rule also applies to user-defined method
|
|
|
|
|
types and to C methods defined in pure mix-in classes.
|
|
|
|
|
|
|
|
|
|
Unfortunately, C methods defined in extension base classes that define
|
|
|
|
|
their own data structures, cannot use aquired attributes at this
|
|
|
|
|
time. This is because wrapper objects do not conform to the data
|
|
|
|
|
structures expected by these methods. In practice, you will seldom
|
|
|
|
|
find this a problem.
|
|
|
|
|
|
|
|
|
|
Conclusion
|
|
|
|
|
----------
|
|
|
|
|
|
|
|
|
|
Acquisition provides a powerful way to dynamically share information
|
|
|
|
|
between objects. Zope 2 uses acquisition for a number of its key
|
|
|
|
|
features including security, object publishing, and DTML variable
|
|
|
|
|
lookup. Acquisition also provides an elegant solution to the problem
|
|
|
|
|
of circular references for many classes of problems. While acquisition
|
|
|
|
|
is powerful, you should take care when using acquisition in your
|
|
|
|
|
applications. The details can get complex, especially with the
|
|
|
|
|
differences between acquiring from context and acquiring from
|
|
|
|
|
containment.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Changelog
|
|
|
|
|
=========
|
|
|
|
|
|
|
|
|
|
4.5 (2018-10-05)
|
|
|
|
|
----------------
|
|
|
|
|
|
|
|
|
|
- Avoid deprecation warnings by using current API.
|
|
|
|
|
|
|
|
|
|
- Add support for Python 3.7.
|
|
|
|
|
|
|
|
|
|
4.4.4 (2017-11-24)
|
|
|
|
|
------------------
|
|
|
|
|
|
|
|
|
|
- Add Appveyor configuration to automate building Windows eggs.
|
|
|
|
|
|
|
|
|
|
4.4.3 (2017-11-23)
|
|
|
|
|
------------------
|
|
|
|
|
|
|
|
|
|
- Fix the extremely rare potential for a crash when the C extensions
|
|
|
|
|
are in use. See `issue 21 <https://github.com/zopefoundation/Acquisition/issues/21>`_.
|
|
|
|
|
|
|
|
|
|
4.4.2 (2017-05-12)
|
|
|
|
|
------------------
|
|
|
|
|
|
|
|
|
|
- Fix C capsule name to fix import errors.
|
|
|
|
|
|
|
|
|
|
- Ensure our dependencies match our expactations about C extensions.
|
|
|
|
|
|
|
|
|
|
4.4.1 (2017-05-04)
|
|
|
|
|
------------------
|
|
|
|
|
|
|
|
|
|
- Fix C code under Python 3.4, with missing Py_XSETREF.
|
|
|
|
|
|
|
|
|
|
4.4.0 (2017-05-04)
|
|
|
|
|
------------------
|
|
|
|
|
|
|
|
|
|
- Enable the C extension under Python 3.
|
|
|
|
|
|
|
|
|
|
- Drop support for Python 3.3.
|
|
|
|
|
|
|
|
|
|
4.3.0 (2017-01-20)
|
|
|
|
|
------------------
|
|
|
|
|
|
|
|
|
|
- Make tests compatible with ExtensionClass 4.2.0.
|
|
|
|
|
|
|
|
|
|
- Drop support for Python 2.6 and 3.2.
|
|
|
|
|
|
|
|
|
|
- Add support for Python 3.5 and 3.6.
|
|
|
|
|
|
|
|
|
|
4.2.2 (2015-05-19)
|
|
|
|
|
------------------
|
|
|
|
|
|
|
|
|
|
- Make the pure-Python Acquirer objects cooperatively use the
|
|
|
|
|
superclass ``__getattribute__`` method, like the C implementation.
|
|
|
|
|
See https://github.com/zopefoundation/Acquisition/issues/7.
|
|
|
|
|
|
|
|
|
|
- The pure-Python implicit acquisition wrapper allows wrapped objects
|
|
|
|
|
to use ``object.__getattribute__(self, name)``. This differs from
|
|
|
|
|
the C implementation, but is important for compatibility with the
|
|
|
|
|
pure-Python versions of libraries like ``persistent``. See
|
|
|
|
|
https://github.com/zopefoundation/Acquisition/issues/9.
|
|
|
|
|
|
|
|
|
|
4.2.1 (2015-04-23)
|
|
|
|
|
------------------
|
|
|
|
|
|
|
|
|
|
- Correct several dangling pointer uses in the C extension,
|
|
|
|
|
potentially fixing a few interpreter crashes. See
|
|
|
|
|
https://github.com/zopefoundation/Acquisition/issues/5.
|
|
|
|
|
|
|
|
|
|
4.2 (2015-04-04)
|
|
|
|
|
----------------
|
|
|
|
|
|
|
|
|
|
- Add support for PyPy, PyPy3, and Python 3.2, 3.3, and 3.4.
|
|
|
|
|
|
|
|
|
|
4.1 (2014-12-18)
|
|
|
|
|
----------------
|
|
|
|
|
|
|
|
|
|
- Bump dependency on ``ExtensionClass`` to match current release.
|
|
|
|
|
|
|
|
|
|
4.0.3 (2014-11-02)
|
|
|
|
|
------------------
|
|
|
|
|
|
|
|
|
|
- Skip readme.rst tests when tests are run outside a source checkout.
|
|
|
|
|
|
|
|
|
|
4.0.2 (2014-11-02)
|
|
|
|
|
------------------
|
|
|
|
|
|
|
|
|
|
- Include ``*.rst`` files in the release.
|
|
|
|
|
|
|
|
|
|
4.0.1 (2014-10-30)
|
|
|
|
|
------------------
|
|
|
|
|
|
|
|
|
|
- Tolerate Unicode attribute names (ASCII only). LP #143358.
|
|
|
|
|
|
|
|
|
|
- Make module-level ``aq_acquire`` API respect the ``default`` parameter.
|
|
|
|
|
LP #1387363.
|
|
|
|
|
|
|
|
|
|
- Don't raise an attribute error for ``__iter__`` if the fallback to
|
|
|
|
|
``__getitem__`` succeeds. LP #1155760.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4.0 (2013-02-24)
|
|
|
|
|
----------------
|
|
|
|
|
|
|
|
|
|
- Added trove classifiers to project metadata.
|
|
|
|
|
|
|
|
|
|
4.0a1 (2011-12-13)
|
|
|
|
|
------------------
|
|
|
|
|
|
|
|
|
|
- Raise `RuntimeError: Recursion detected in acquisition wrapper` if an object
|
|
|
|
|
with a `__parent__` pointer points to a wrapper that in turn points to the
|
|
|
|
|
original object.
|
|
|
|
|
|
|
|
|
|
- Prevent wrappers to be created while accessing `__parent__` on types derived
|
|
|
|
|
from Explicit or Implicit base classes.
|
|
|
|
|
|
|
|
|
|
2.13.9 (2015-02-17)
|
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
|
|
- Tolerate Unicode attribute names (ASCII only). LP #143358.
|
|
|
|
|
|
|
|
|
|
- Make module-level ``aq_acquire`` API respect the ``default`` parameter.
|
|
|
|
|
LP #1387363.
|
|
|
|
|
|
|
|
|
|
- Don't raise an attribute error for ``__iter__`` if the fallback to
|
|
|
|
|
``__getitem__`` succeeds. LP #1155760.
|
|
|
|
|
|
|
|
|
|
2.13.8 (2011-06-11)
|
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
|
|
- Fixed a segfault on 64bit platforms when providing the `explicit` argument to
|
|
|
|
|
the aq_acquire method of an Acquisition wrapper. Thx to LP #675064 for the
|
|
|
|
|
hint to the solution. The code passed an int instead of a pointer into a
|
|
|
|
|
function.
|
|
|
|
|
|
|
|
|
|
2.13.7 (2011-03-02)
|
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
|
|
- Fixed bug: When an object did not implement ``__unicode__``, calling
|
|
|
|
|
``unicode(wrapped)`` was calling ``__str__`` with an unwrapped ``self``.
|
|
|
|
|
|
|
|
|
|
2.13.6 (2011-02-19)
|
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
|
|
- Add ``aq_explicit`` to ``IAcquisitionWrapper``.
|
|
|
|
|
|
|
|
|
|
- Fixed bug: ``unicode(wrapped)`` was not calling a ``__unicode__``
|
|
|
|
|
method on wrapped objects.
|
|
|
|
|
|
|
|
|
|
2.13.5 (2010-09-29)
|
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
|
|
- Fixed unit tests that failed on 64bit Python on Windows machines.
|
|
|
|
|
|
|
|
|
|
2.13.4 (2010-08-31)
|
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
|
|
- LP 623665: Fixed typo in Acquisition.h.
|
|
|
|
|
|
|
|
|
|
2.13.3 (2010-04-19)
|
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
|
|
- Use the doctest module from the standard library and no longer depend on
|
|
|
|
|
zope.testing.
|
|
|
|
|
|
|
|
|
|
2.13.2 (2010-04-04)
|
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
|
|
- Give both wrapper classes a ``__getnewargs__`` method, which causes the ZODB
|
|
|
|
|
optimization to fail and create persistent references using the ``_p_oid``
|
|
|
|
|
alone. This happens to be the persistent oid of the wrapped object. This lets
|
|
|
|
|
these objects to be persisted correctly, even though they are passed to the
|
|
|
|
|
ZODB in a wrapped state.
|
|
|
|
|
|
|
|
|
|
- Added failing tests for http://dev.plone.org/plone/ticket/10318. This shows
|
|
|
|
|
an edge-case where AQ wrappers can be pickled using the specific combination
|
|
|
|
|
of cPickle, pickle protocol one and a custom Pickler class with an
|
|
|
|
|
``inst_persistent_id`` hook. Unfortunately this is the exact combination used
|
|
|
|
|
by ZODB3.
|
|
|
|
|
|
|
|
|
|
2.13.1 (2010-02-23)
|
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
|
|
- Update to include ExtensionClass 2.13.0.
|
|
|
|
|
|
|
|
|
|
- Fix the ``tp_name`` of the ImplicitAcquisitionWrapper and
|
|
|
|
|
ExplicitAcquisitionWrapper to match their Python visible names and thus have
|
|
|
|
|
a correct ``__name__``.
|
|
|
|
|
|
|
|
|
|
- Expand the ``tp_name`` of our extension types to hold the fully qualified
|
|
|
|
|
name. This ensures classes have their ``__module__`` set correctly.
|
|
|
|
|
|
|
|
|
|
2.13.0 (2010-02-14)
|
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
|
|
- Added support for method cache in Acquisition. Patch contributed by
|
|
|
|
|
Yoshinori K. Okuji. See https://bugs.launchpad.net/zope2/+bug/486182.
|
|
|
|
|
|
|
|
|
|
2.12.4 (2009-10-29)
|
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
|
|
- Fix iteration proxying to pass `self` acquisition-wrapped into both
|
|
|
|
|
`__iter__` as well as `__getitem__` (this fixes
|
|
|
|
|
https://bugs.launchpad.net/zope2/+bug/360761).
|
|
|
|
|
|
|
|
|
|
- Add tests for the __getslice__ proxying, including open-ended slicing.
|
|
|
|
|
|
|
|
|
|
2.12.3 (2009-08-08)
|
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
|
|
- More 64-bit fixes in Py_BuildValue calls.
|
|
|
|
|
|
|
|
|
|
- More 64-bit issues fixed: Use correct integer size for slice operations.
|
|
|
|
|
|
|
|
|
|
2.12.2 (2009-08-02)
|
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
|
|
- Fixed 64-bit compatibility issues for Python 2.5.x / 2.6.x. See
|
|
|
|
|
http://www.python.org/dev/peps/pep-0353/ for details.
|
|
|
|
|
|
|
|
|
|
2.12.1 (2009-04-15)
|
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
|
|
- Update for iteration proxying: The proxy for `__iter__` must not rely on the
|
|
|
|
|
object to have an `__iter__` itself, but also support fall-back iteration via
|
|
|
|
|
`__getitem__` (this fixes https://bugs.launchpad.net/zope2/+bug/360761).
|
|
|
|
|
|
|
|
|
|
2.12 (2009-01-25)
|
|
|
|
|
-----------------
|
|
|
|
|
|
|
|
|
|
- Release as separate package.
|
|
|
|
|
|
|
|
|
|
Platform: UNKNOWN
|
|
|
|
|
Classifier: Development Status :: 6 - Mature
|
|
|
|
|
Classifier: Environment :: Web Environment
|
|
|
|
|
Classifier: Framework :: Zope2
|
|
|
|
|
Classifier: License :: OSI Approved :: Zope Public License
|
|
|
|
|
Classifier: Operating System :: OS Independent
|
|
|
|
|
Classifier: Programming Language :: Python
|
|
|
|
|
Classifier: Programming Language :: Python :: 2
|
|
|
|
|
Classifier: Programming Language :: Python :: 2.7
|
|
|
|
|
Classifier: Programming Language :: Python :: 3
|
|
|
|
|
Classifier: Programming Language :: Python :: 3.4
|
|
|
|
|
Classifier: Programming Language :: Python :: 3.5
|
|
|
|
|
Classifier: Programming Language :: Python :: 3.6
|
|
|
|
|
Classifier: Programming Language :: Python :: 3.7
|
|
|
|
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
|
|
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|