Skip to content

Commit

Permalink
Merged from old philikon-aq-and-__parent__ branch:
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
philikon committed Jul 24, 2007
1 parent 755cb12 commit b74b92b
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 23 deletions.
60 changes: 50 additions & 10 deletions _Acquisition.c
Original file line number Diff line number Diff line change
Expand Up @@ -1422,8 +1422,7 @@ capi_aq_acquire(PyObject *self, PyObject *name, PyObject *filter,
WRAPPER(self)->ob_type==(PyTypeObject*)&Wrappertype,
explicit, containment);
/* Not wrapped; check if we have a __parent__ pointer. If that's
the case, we create a wrapper and pretend it's business as
usual */
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);
Expand All @@ -1437,8 +1436,8 @@ capi_aq_acquire(PyObject *self, PyObject *name, PyObject *filter,
/* No wrapper and no __parent__, so just getattr. */
else
{
/* We need to clean up the AttributeError from the previous
getattr (because it has clearly failed). */
/* Clean up the AttributeError from the previous getattr
(because it has clearly failed). */
PyErr_Fetch(&result,&v,&tb);
if (result && (result != PyExc_AttributeError))
{
Expand Down Expand Up @@ -1486,13 +1485,35 @@ module_aq_acquire(PyObject *ignored, PyObject *args, PyObject *kw)
static PyObject *
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 */
if (isWrapper(self))
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
result=PyObject_GetAttr(self, name);
{
/* 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);
}

if (! result && defalt)
{
Expand Down Expand Up @@ -1658,7 +1679,7 @@ module_aq_inner(PyObject *ignored, PyObject *args)
static PyObject *
capi_aq_chain(PyObject *self, int containment)
{
PyObject *result;
PyObject *result, *v, *tb;

UNLESS (result=PyList_New(0)) return NULL;

Expand All @@ -1681,8 +1702,27 @@ capi_aq_chain(PyObject *self, int containment)
}
}
else
if (PyList_Append(result, self) < 0)
goto err;
{
if (PyList_Append(result, self) < 0)
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;
}
Expand Down
105 changes: 92 additions & 13 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1725,14 +1725,26 @@ def test___parent__no_wrappers():
>>> Acquisition.aq_acquire(x, 'bar')
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
True
>>> Acquisition.aq_parent(y) is z
True
TODO aq_chain
as well as ``aq_chain``:
>>> Acquisition.aq_chain(x) == [x, y, z]
True
"""

def test_implicit_wrapper_as___parent__():
Expand Down Expand Up @@ -1769,13 +1781,27 @@ def test_implicit_wrapper_as___parent__():
>>> Acquisition.aq_acquire(x, 'bar')
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
True
>>> Acquisition.aq_parent(y) is z
True
as well as ``aq_chain``:
>>> Acquisition.aq_chain(x) == [x, y, z]
True
Note that also the (implicit) acquisition wrapper has a __parent__
pointer, which is automatically computed from the acquisition
container (it's identical to aq_parent):
Expand All @@ -1800,8 +1826,6 @@ def test_implicit_wrapper_as___parent__():
Traceback (most recent call last):
...
AttributeError: __parent__
TODO aq_chain
"""

def test_explicit_wrapper_as___parent__():
Expand Down Expand Up @@ -1836,13 +1860,27 @@ def test_explicit_wrapper_as___parent__():
>>> Acquisition.aq_acquire(x, 'bar')
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
True
>>> Acquisition.aq_parent(y) is z
True
as well as ``aq_chain``:
>>> Acquisition.aq_chain(x) == [x, y, z]
True
Note that also the (explicit) acquisition wrapper has a __parent__
pointer, which is automatically computed from the acquisition
container (it's identical to aq_parent):
Expand All @@ -1867,8 +1905,6 @@ def test_explicit_wrapper_as___parent__():
Traceback (most recent call last):
...
AttributeError: __parent__
TODO aq_chain
"""

def test_implicit_wrapper_has_nonwrapper_as_aq_parent():
Expand All @@ -1888,7 +1924,7 @@ def test_implicit_wrapper_has_nonwrapper_as_aq_parent():
... hello = 'world'
>>> x = Impl().__of__(y)
Again, acquiring objects work as usual:
Again, acquiring objects works as usual:
>>> Acquisition.aq_acquire(x, 'hello')
'world'
Expand All @@ -1897,13 +1933,33 @@ def test_implicit_wrapper_has_nonwrapper_as_aq_parent():
>>> Acquisition.aq_acquire(x, 'bar')
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
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
Because the outmost object, ``x``, is wrapped in an implicit
acquisition wrapper, we can also use direct attribute access:
Expand All @@ -1913,8 +1969,6 @@ def test_implicit_wrapper_has_nonwrapper_as_aq_parent():
42
>>> x.bar
3.145
TODO aq_parent, aq_chain
"""

def test_explicit_wrapper_has_nonwrapper_as_aq_parent():
Expand Down Expand Up @@ -1943,7 +1997,32 @@ def test_explicit_wrapper_has_nonwrapper_as_aq_parent():
>>> Acquisition.aq_acquire(x, 'bar')
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():
Expand Down

0 comments on commit b74b92b

Please sign in to comment.