[Zope-Checkins] SVN: Zope/branches/philikon-aq/lib/python/Acquisition/ Merged from old philikon-aq-and-__parent__ branch:
Log message for revision 78314: Merged from old philikon-aq-and-__parent__ branch: Log message for revision 71221: Step 2: Make aq_acquire aware of __parent__ pointers, even if the object isn't acquisition wrapped. Log message for revision 71223: Add another test that tests acquisition wrappers with containers that have __parent__. Log message for revision 71225: Cosmetics: adjust a piece of code that I added earlier to the indentation style of the overall file Log message for revision 71226: Cleanup: * no need to introduce another variable where we check for a __parent__ attribute * clean up after failed getattr (it throws an AttributeError) * properly DECREF the __parent__ attribute when it's no longer needed and the wrapper that is temporarily created from the __parent__ attribute. Log message for revision 75578: Added a test to Acquisition that shows the current segmentation fault problem, when Acquisition goes in circles. Log message for revision 76140: First attempt to fix 'Acquisition problem' when encountering cyclic hierarchies via __parent__ pointers. [hannosch, nouri] In addition, Hanno and Nouri's fix was expanded to not only cover circular __parent__ pointers but also to cover a mixture of circular __parent__ and aq_parent pointers (which can occur when old Implicit acquisition meets new __parent__ pointer code). Also cleaned up much of the comments and added more comments. Changed: U Zope/branches/philikon-aq/lib/python/Acquisition/_Acquisition.c U Zope/branches/philikon-aq/lib/python/Acquisition/tests.py -=- Modified: Zope/branches/philikon-aq/lib/python/Acquisition/_Acquisition.c === --- Zope/branches/philikon-aq/lib/python/Acquisition/_Acquisition.c 2007-07-24 14:41:47 UTC (rev 78313) +++ Zope/branches/philikon-aq/lib/python/Acquisition/_Acquisition.c 2007-07-24 19:40:28 UTC (rev 78314) @@ -38,7 +38,8 @@ *py__long__, *py__float__, *py__oct__, *py__hex__, *py__getitem__, *py__setitem__, *py__delitem__, *py__getslice__, *py__setslice__, *py__delslice__, *py__contains__, - *py__len__, *py__of__, *py__call__, *py__repr__, *py__str__, *py__cmp__; + *py__len__, *py__of__, *py__call__, *py__repr__, *py__str__, *py__cmp__, + *py__parent__; static PyObject *Acquired=0; @@ -82,7 +83,7 @@ INIT_PY_NAME(__repr__); INIT_PY_NAME(__str__); INIT_PY_NAME(__cmp__); - + INIT_PY_NAME(__parent__); #undef INIT_PY_NAME } @@ -414,6 +415,23 @@ Wrapper_findattr(Wrapper *self, PyObject *oname, PyObject *filter, PyObject *extra, PyObject *orig, int sob, int sco, int explicit, int containment) +/* + Parameters: + + sob +Search self-obj for the 'oname' attribute + + sco +Search self-container for the 'oname' attribute + + explicit +Explicitly acquire 'oname' attribute from container (assumed with +implicit acquisition wrapper) + + containment +Use the innermost wrapper (aq_inner) for looking up the 'oname' +attribute. +*/ { PyObject *r, *v, *tb; char *name=; @@ -486,6 +504,7 @@ Py_XDECREF(r); Py_XDECREF(v); Py_XDECREF(tb); r=NULL; } + /* normal attribute lookup */ else if ((r=PyObject_GetAttr(self-obj,oname))) { if (r==Acquired) @@ -520,6 +539,7 @@ PyErr_Clear(); } + /* Lookup has failed, acquire it from parent. */ if (sco (*name != '_' || explicit)) return Wrapper_acquire(self, oname, filter, extra, orig, explicit, containment); @@ -533,24 +553,35 @@ PyObject *filter, PyObject *extra, PyObject *orig, int explicit, int containment) { - PyObject *r; + PyObject *r, *v, *tb; int sob=1, sco=1; if (self-container) { + /* If the container has an acquisition wrapper itself, we'll use + Wrapper_findattr to progress further. */ if (isWrapper(self-container)) { if (self-obj isWrapper(self-obj)) { - /* Try to optimize search by recognizing repeated obs in path */ + /* Try to optimize search by recognizing repeated + objects in path. */ if (WRAPPER(self-obj)-container== WRAPPER(self-container)-container) sco=0; else if (WRAPPER(self-obj)-container== WRAPPER(self-container)-obj) sob=0; - } + } + /* Don't search the container when the container of the + container is the same object as 'self'. */ + if (WRAPPER(self-container)-container == WRAPPER(self)-obj) +{ + sco=0; + containment=1; +} + r=Wrapper_findattr((Wrapper*)self-container, oname, filter, extra,
[Zope-Checkins] SVN: Zope/branches/philikon-aq/lib/python/Acquisition/ Merged from old philikon-aq-and-__parent__ branch:
Log message for revision 78318: 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. Changed: U Zope/branches/philikon-aq/lib/python/Acquisition/_Acquisition.c U Zope/branches/philikon-aq/lib/python/Acquisition/tests.py -=- Modified: Zope/branches/philikon-aq/lib/python/Acquisition/_Acquisition.c === --- Zope/branches/philikon-aq/lib/python/Acquisition/_Acquisition.c 2007-07-24 20:46:33 UTC (rev 78317) +++ Zope/branches/philikon-aq/lib/python/Acquisition/_Acquisition.c 2007-07-24 21:02:03 UTC (rev 78318) @@ -1422,8 +1422,7 @@ 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); @@ -1437,8 +1436,8 @@ /* 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)) { @@ -1486,13 +1485,35 @@ 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) { @@ -1658,7 +1679,7 @@ static PyObject * capi_aq_chain(PyObject *self, int containment) { - PyObject *result; + PyObject *result, *v, *tb; UNLESS (result=PyList_New(0)) return NULL; @@ -1681,9 +1702,28 @@ } } 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; } Modified: Zope/branches/philikon-aq/lib/python/Acquisition/tests.py === --- Zope/branches/philikon-aq/lib/python/Acquisition/tests.py 2007-07-24 20:46:33 UTC (rev 78317) +++ Zope/branches/philikon-aq/lib/python/Acquisition/tests.py 2007-07-24 21:02:03 UTC (rev 78318) @@ -1725,14 +1725,26 @@ 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