Merged from old philikon-aq-and-__parent__ branch:

Log message for revision 71227:
  Step 4: Make aq_get aware of __parent__ pointers.
  (Also some comment cosmetics in _Acquisition.c)

Log message for revision 71228:
  Test aq_parent property as well (in addition to aq_parent function)

Log message for revision 71229:
  Step 5: Make aq_chain aware of __parent__ pointers.
parent 49a0c565
...@@ -1422,8 +1422,7 @@ capi_aq_acquire(PyObject *self, PyObject *name, PyObject *filter, ...@@ -1422,8 +1422,7 @@ capi_aq_acquire(PyObject *self, PyObject *name, PyObject *filter,
WRAPPER(self)->ob_type==(PyTypeObject*)&Wrappertype, WRAPPER(self)->ob_type==(PyTypeObject*)&Wrappertype,
explicit, containment); explicit, containment);
/* Not wrapped; check if we have a __parent__ pointer. If that's /* Not wrapped; check if we have a __parent__ pointer. If that's
the case, we create a wrapper and pretend it's business as the case, create a wrapper and pretend it's business as usual. */
usual */
else if ((result = PyObject_GetAttr(self, py__parent__))) else if ((result = PyObject_GetAttr(self, py__parent__)))
{ {
self = newWrapper(self, result, (PyTypeObject*)&Wrappertype); self = newWrapper(self, result, (PyTypeObject*)&Wrappertype);
...@@ -1437,8 +1436,8 @@ capi_aq_acquire(PyObject *self, PyObject *name, PyObject *filter, ...@@ -1437,8 +1436,8 @@ capi_aq_acquire(PyObject *self, PyObject *name, PyObject *filter,
/* No wrapper and no __parent__, so just getattr. */ /* No wrapper and no __parent__, so just getattr. */
else else
{ {
/* We need to clean up the AttributeError from the previous /* Clean up the AttributeError from the previous getattr
getattr (because it has clearly failed). */ (because it has clearly failed). */
PyErr_Fetch(&result,&v,&tb); PyErr_Fetch(&result,&v,&tb);
if (result && (result != PyExc_AttributeError)) if (result && (result != PyExc_AttributeError))
{ {
...@@ -1486,13 +1485,35 @@ module_aq_acquire(PyObject *ignored, PyObject *args, PyObject *kw) ...@@ -1486,13 +1485,35 @@ module_aq_acquire(PyObject *ignored, PyObject *args, PyObject *kw)
static PyObject * static PyObject *
capi_aq_get(PyObject *self, PyObject *name, PyObject *defalt, int containment) capi_aq_get(PyObject *self, PyObject *name, PyObject *defalt, int containment)
{ {
PyObject *result = NULL; PyObject *result = NULL, *v, *tb;
/* We got a wrapped object, so business as usual */ /* We got a wrapped object, so business as usual */
if (isWrapper(self)) if (isWrapper(self))
result=Wrapper_findattr(WRAPPER(self), name, 0, 0, OBJECT(self), 1, 1, 1, result=Wrapper_findattr(WRAPPER(self), name, 0, 0, OBJECT(self), 1, 1, 1,
containment); containment);
/* Not wrapped; check if we have a __parent__ pointer. If that's
the case, create a wrapper and pretend it's business as usual. */
else if ((result = PyObject_GetAttr(self, py__parent__)))
{
self=newWrapper(self, result, (PyTypeObject*)&Wrappertype);
Py_DECREF(result); /* don't need __parent__ anymore */
result=Wrapper_findattr(WRAPPER(self), name, 0, 0, OBJECT(self),
1, 1, 1, containment);
Py_DECREF(self); /* Get rid of temporary wrapper. */
}
else else
{
/* Clean up the AttributeError from the previous getattr
(because it has clearly failed). */
PyErr_Fetch(&result,&v,&tb);
if (result && (result != PyExc_AttributeError))
{
PyErr_Restore(result,v,tb);
return NULL;
}
Py_XDECREF(result); Py_XDECREF(v); Py_XDECREF(tb);
result=PyObject_GetAttr(self, name); result=PyObject_GetAttr(self, name);
}
if (! result && defalt) if (! result && defalt)
{ {
...@@ -1658,7 +1679,7 @@ module_aq_inner(PyObject *ignored, PyObject *args) ...@@ -1658,7 +1679,7 @@ module_aq_inner(PyObject *ignored, PyObject *args)
static PyObject * static PyObject *
capi_aq_chain(PyObject *self, int containment) capi_aq_chain(PyObject *self, int containment)
{ {
PyObject *result; PyObject *result, *v, *tb;
UNLESS (result=PyList_New(0)) return NULL; UNLESS (result=PyList_New(0)) return NULL;
...@@ -1681,9 +1702,28 @@ capi_aq_chain(PyObject *self, int containment) ...@@ -1681,9 +1702,28 @@ capi_aq_chain(PyObject *self, int containment)
} }
} }
else else
{
if (PyList_Append(result, self) < 0) if (PyList_Append(result, self) < 0)
goto err; goto err;
if ((self=PyObject_GetAttr(self, py__parent__)))
{
Py_DECREF(self); /* We don't need our own reference. */
if (self!=Py_None)
continue;
}
else
{
PyErr_Fetch(&self,&v,&tb);
if (self && (self != PyExc_AttributeError))
{
PyErr_Restore(self,v,tb);
return NULL;
}
Py_XDECREF(self); Py_XDECREF(v); Py_XDECREF(tb);
}
}
break; break;
} }
......
...@@ -1725,14 +1725,26 @@ def test___parent__no_wrappers(): ...@@ -1725,14 +1725,26 @@ def test___parent__no_wrappers():
>>> Acquisition.aq_acquire(x, 'bar') >>> Acquisition.aq_acquire(x, 'bar')
3.145 3.145
as does ``aq_parent``: as does ``aq_get``:
>>> Acquisition.aq_get(x, 'hello')
'world'
>>> Acquisition.aq_get(x, 'foo')
42
>>> Acquisition.aq_get(x, 'bar')
3.145
and ``aq_parent``:
>>> Acquisition.aq_parent(x) is y >>> Acquisition.aq_parent(x) is y
True True
>>> Acquisition.aq_parent(y) is z >>> Acquisition.aq_parent(y) is z
True True
TODO aq_chain as well as ``aq_chain``:
>>> Acquisition.aq_chain(x) == [x, y, z]
True
""" """
def test_implicit_wrapper_as___parent__(): def test_implicit_wrapper_as___parent__():
...@@ -1769,13 +1781,27 @@ def test_implicit_wrapper_as___parent__(): ...@@ -1769,13 +1781,27 @@ def test_implicit_wrapper_as___parent__():
>>> Acquisition.aq_acquire(x, 'bar') >>> Acquisition.aq_acquire(x, 'bar')
3.145 3.145
as does ``aq_parent``: as does ``aq_get``:
>>> Acquisition.aq_get(x, 'hello')
'world'
>>> Acquisition.aq_get(x, 'foo')
42
>>> Acquisition.aq_get(x, 'bar')
3.145
and ``aq_parent``:
>>> Acquisition.aq_parent(x) is y >>> Acquisition.aq_parent(x) is y
True True
>>> Acquisition.aq_parent(y) is z >>> Acquisition.aq_parent(y) is z
True True
as well as ``aq_chain``:
>>> Acquisition.aq_chain(x) == [x, y, z]
True
Note that also the (implicit) acquisition wrapper has a __parent__ Note that also the (implicit) acquisition wrapper has a __parent__
pointer, which is automatically computed from the acquisition pointer, which is automatically computed from the acquisition
container (it's identical to aq_parent): container (it's identical to aq_parent):
...@@ -1800,8 +1826,6 @@ def test_implicit_wrapper_as___parent__(): ...@@ -1800,8 +1826,6 @@ def test_implicit_wrapper_as___parent__():
Traceback (most recent call last): Traceback (most recent call last):
... ...
AttributeError: __parent__ AttributeError: __parent__
TODO aq_chain
""" """
def test_explicit_wrapper_as___parent__(): def test_explicit_wrapper_as___parent__():
...@@ -1836,13 +1860,27 @@ def test_explicit_wrapper_as___parent__(): ...@@ -1836,13 +1860,27 @@ def test_explicit_wrapper_as___parent__():
>>> Acquisition.aq_acquire(x, 'bar') >>> Acquisition.aq_acquire(x, 'bar')
3.145 3.145
as does ``aq_parent``: as does ``aq_get``:
>>> Acquisition.aq_get(x, 'hello')
'world'
>>> Acquisition.aq_get(x, 'foo')
42
>>> Acquisition.aq_get(x, 'bar')
3.145
and ``aq_parent``:
>>> Acquisition.aq_parent(x) is y >>> Acquisition.aq_parent(x) is y
True True
>>> Acquisition.aq_parent(y) is z >>> Acquisition.aq_parent(y) is z
True True
as well as ``aq_chain``:
>>> Acquisition.aq_chain(x) == [x, y, z]
True
Note that also the (explicit) acquisition wrapper has a __parent__ Note that also the (explicit) acquisition wrapper has a __parent__
pointer, which is automatically computed from the acquisition pointer, which is automatically computed from the acquisition
container (it's identical to aq_parent): container (it's identical to aq_parent):
...@@ -1867,8 +1905,6 @@ def test_explicit_wrapper_as___parent__(): ...@@ -1867,8 +1905,6 @@ def test_explicit_wrapper_as___parent__():
Traceback (most recent call last): Traceback (most recent call last):
... ...
AttributeError: __parent__ AttributeError: __parent__
TODO aq_chain
""" """
def test_implicit_wrapper_has_nonwrapper_as_aq_parent(): def test_implicit_wrapper_has_nonwrapper_as_aq_parent():
...@@ -1888,7 +1924,7 @@ def test_implicit_wrapper_has_nonwrapper_as_aq_parent(): ...@@ -1888,7 +1924,7 @@ def test_implicit_wrapper_has_nonwrapper_as_aq_parent():
... hello = 'world' ... hello = 'world'
>>> x = Impl().__of__(y) >>> x = Impl().__of__(y)
Again, acquiring objects work as usual: Again, acquiring objects works as usual:
>>> Acquisition.aq_acquire(x, 'hello') >>> Acquisition.aq_acquire(x, 'hello')
'world' 'world'
...@@ -1897,13 +1933,33 @@ def test_implicit_wrapper_has_nonwrapper_as_aq_parent(): ...@@ -1897,13 +1933,33 @@ def test_implicit_wrapper_has_nonwrapper_as_aq_parent():
>>> Acquisition.aq_acquire(x, 'bar') >>> Acquisition.aq_acquire(x, 'bar')
3.145 3.145
as does ``aq_parent``: as does ``aq_get``:
>>> Acquisition.aq_get(x, 'hello')
'world'
>>> Acquisition.aq_get(x, 'foo')
42
>>> Acquisition.aq_get(x, 'bar')
3.145
and ``aq_parent``:
>>> Acquisition.aq_parent(x) == y >>> Acquisition.aq_parent(x) == y
True True
>>> x.aq_parent == y
True
>>> x.aq_parent.aq_parent == z
True
>>> Acquisition.aq_parent(y) is z >>> Acquisition.aq_parent(y) is z
True True
as well as ``aq_chain``:
>>> Acquisition.aq_chain(x) == [x, y, z]
True
>>> x.aq_chain == [x, y, z]
True
Because the outmost object, ``x``, is wrapped in an implicit Because the outmost object, ``x``, is wrapped in an implicit
acquisition wrapper, we can also use direct attribute access: acquisition wrapper, we can also use direct attribute access:
...@@ -1913,8 +1969,6 @@ def test_implicit_wrapper_has_nonwrapper_as_aq_parent(): ...@@ -1913,8 +1969,6 @@ def test_implicit_wrapper_has_nonwrapper_as_aq_parent():
42 42
>>> x.bar >>> x.bar
3.145 3.145
TODO aq_parent, aq_chain
""" """
def test_explicit_wrapper_has_nonwrapper_as_aq_parent(): def test_explicit_wrapper_has_nonwrapper_as_aq_parent():
...@@ -1943,7 +1997,32 @@ def test_explicit_wrapper_has_nonwrapper_as_aq_parent(): ...@@ -1943,7 +1997,32 @@ def test_explicit_wrapper_has_nonwrapper_as_aq_parent():
>>> Acquisition.aq_acquire(x, 'bar') >>> Acquisition.aq_acquire(x, 'bar')
3.145 3.145
TODO aq_chain as does ``aq_get``:
>>> Acquisition.aq_get(x, 'hello')
'world'
>>> Acquisition.aq_get(x, 'foo')
42
>>> Acquisition.aq_get(x, 'bar')
3.145
and ``aq_parent``:
>>> Acquisition.aq_parent(x) == y
True
>>> x.aq_parent == y
True
>>> x.aq_parent.aq_parent == z
True
>>> Acquisition.aq_parent(y) is z
True
as well as ``aq_chain``:
>>> Acquisition.aq_chain(x) == [x, y, z]
True
>>> x.aq_chain == [x, y, z]
True
""" """
def test___parent__aq_parent_circles(): def test___parent__aq_parent_circles():
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment