[Zope-Checkins] SVN: Zope/branches/philikon-aq/lib/python/Acquisition/ Merged from old philikon-aq-and-__parent__ branch:

2007-07-24 Thread Philipp von Weitershausen
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:

2007-07-24 Thread Philipp von Weitershausen
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