Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Acquisition
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
Acquisition
Commits
ca40e281
Commit
ca40e281
authored
Apr 26, 2008
by
Hanno Schlichting
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Merged philikon-aq branch into trunk, yeah!
parent
da7c511c
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
769 additions
and
104 deletions
+769
-104
_Acquisition.c
_Acquisition.c
+263
-89
tests.py
tests.py
+506
-15
No files found.
_Acquisition.c
View file @
ca40e281
...
...
@@ -38,7 +38,8 @@ static PyObject *py__add__, *py__sub__, *py__mul__, *py__div__,
*
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_names(void)
INIT_PY_NAME
(
__repr__
);
INIT_PY_NAME
(
__str__
);
INIT_PY_NAME
(
__cmp__
);
INIT_PY_NAME
(
__parent__
);
#undef INIT_PY_NAME
}
...
...
@@ -414,23 +415,49 @@ static PyObject *
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
=
""
;
if
(
PyString_Check
(
oname
))
name
=
PyString_AS_STRING
(
oname
);
if
(
*
name
==
'a'
&&
name
[
1
]
==
'q'
&&
name
[
2
]
==
'_'
)
if
((
r
=
Wrapper_special
(
self
,
name
+
3
,
oname
)))
{
if
(
filter
)
switch
(
apply_filter
(
filter
,
OBJECT
(
self
),
oname
,
r
,
extra
,
orig
))
{
case
-
1
:
return
NULL
;
case
1
:
return
r
;
}
else
return
r
;
}
else
PyErr_Clear
();
if
((
*
name
==
'a'
&&
name
[
1
]
==
'q'
&&
name
[
2
]
==
'_'
)
||
(
strcmp
(
name
,
"__parent__"
)
==
0
))
{
/* __parent__ is an alias to aq_parent */
if
(
strcmp
(
name
,
"__parent__"
)
==
0
)
name
=
"parent"
;
else
name
=
name
+
3
;
if
((
r
=
Wrapper_special
(
self
,
name
,
oname
)))
{
if
(
filter
)
switch
(
apply_filter
(
filter
,
OBJECT
(
self
),
oname
,
r
,
extra
,
orig
))
{
case
-
1
:
return
NULL
;
case
1
:
return
r
;
}
else
return
r
;
}
else
PyErr_Clear
();
}
else
if
(
*
name
==
'_'
&&
name
[
1
]
==
'_'
&&
(
strcmp
(
name
+
2
,
"reduce__"
)
==
0
||
strcmp
(
name
+
2
,
"reduce_ex__"
)
==
0
||
...
...
@@ -477,6 +504,7 @@ Wrapper_findattr(Wrapper *self, PyObject *oname,
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
)
...
...
@@ -511,6 +539,7 @@ Wrapper_findattr(Wrapper *self, PyObject *oname,
PyErr_Clear
();
}
/* Lookup has failed, acquire it from parent. */
if
(
sco
&&
(
*
name
!=
'_'
||
explicit
))
return
Wrapper_acquire
(
self
,
oname
,
filter
,
extra
,
orig
,
explicit
,
containment
);
...
...
@@ -524,23 +553,34 @@ Wrapper_acquire(Wrapper *self, PyObject *oname,
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
,
orig
,
sob
,
sco
,
explicit
,
...
...
@@ -549,8 +589,46 @@ Wrapper_acquire(Wrapper *self, PyObject *oname,
if
(
r
&&
has__of__
(
r
))
ASSIGN
(
r
,
__of__
(
r
,
OBJECT
(
self
)));
return
r
;
}
/* If the container has a __parent__ pointer, we create an
acquisition wrapper for it accordingly. Then we can proceed
with Wrapper_findattr, just as if the container had an
acquisition wrapper in the first place (see above). */
else
if
((
r
=
PyObject_GetAttr
(
self
->
container
,
py__parent__
)))
{
ASSIGN
(
self
->
container
,
newWrapper
(
self
->
container
,
r
,
(
PyTypeObject
*
)
&
Wrappertype
));
/* Don't search the container when the parent of the parent
is the same object as 'self' */
if
(
WRAPPER
(
r
)
->
obj
==
WRAPPER
(
self
)
->
obj
)
sco
=
0
;
Py_DECREF
(
r
);
/* don't need __parent__ anymore */
r
=
Wrapper_findattr
((
Wrapper
*
)
self
->
container
,
oname
,
filter
,
extra
,
orig
,
sob
,
sco
,
explicit
,
containment
);
/* There's no need to DECREF the wrapper here because it's
not stored in self->container, thus 'self' owns its
reference now */
return
r
;
}
/* The container is the end of the acquisition chain; if we
can't look up the attribute here, we can't look it up at
all. */
else
{
/* We need to clean up the AttributeError from the previous
getattr (because it has clearly failed). */
PyErr_Fetch
(
&
r
,
&
v
,
&
tb
);
if
(
r
&&
(
r
!=
PyExc_AttributeError
))
{
PyErr_Restore
(
r
,
v
,
tb
);
return
NULL
;
}
Py_XDECREF
(
r
);
Py_XDECREF
(
v
);
Py_XDECREF
(
tb
);
r
=
NULL
;
if
((
r
=
PyObject_GetAttr
(
self
->
container
,
oname
)))
{
if
(
r
==
Acquired
)
{
Py_DECREF
(
r
);
...
...
@@ -618,8 +696,8 @@ Wrapper_setattro(Wrapper *self, PyObject *oname, PyObject *v)
/* Allow assignment to parent, to change context. */
if
(
PyString_Check
(
oname
))
name
=
PyString_AS_STRING
(
oname
);
if
(
*
name
==
'a'
&&
name
[
1
]
==
'q'
&&
name
[
2
]
==
'_'
&&
strcmp
(
name
+
3
,
"parent"
)
==
0
)
if
(
(
*
name
==
'a'
&&
name
[
1
]
==
'q'
&&
name
[
2
]
==
'_'
&&
strcmp
(
name
+
3
,
"parent"
)
==
0
)
||
(
strcmp
(
name
,
"__parent__"
)
==
0
)
)
{
Py_XINCREF
(
v
);
ASSIGN
(
self
->
container
,
v
);
...
...
@@ -1112,57 +1190,18 @@ Wrapper_acquire_method(Wrapper *self, PyObject *args, PyObject *kw)
# endif
}
/* forward declaration so that we can use it in Wrapper_inContextOf */
static
PyObject
*
capi_aq_inContextOf
(
PyObject
*
self
,
PyObject
*
o
,
int
inner
);
static
PyObject
*
Wrapper_inContextOf
(
Wrapper
*
self
,
PyObject
*
args
)
{
PyObject
*
subob
,
*
o
,
*
c
;
int
inner
=
1
;
PyObject
*
o
;
int
inner
=
1
;
UNLESS
(
PyArg_ParseTuple
(
args
,
"O|i"
,
&
o
,
&
inner
))
return
NULL
;
if
(
inner
)
{
/* subob = self */
subob
=
OBJECT
(
self
);
/* o = aq_base(o) */
while
(
isWrapper
(
o
)
&&
WRAPPER
(
o
)
->
obj
)
o
=
WRAPPER
(
o
)
->
obj
;
/* while 1: */
while
(
1
)
{
/* if aq_base(subob) is o: return 1 */
c
=
subob
;
while
(
isWrapper
(
c
)
&&
WRAPPER
(
c
)
->
obj
)
c
=
WRAPPER
(
c
)
->
obj
;
if
(
c
==
o
)
return
PyInt_FromLong
(
1
);
/* self = aq_inner(subob) */
/* if self is None: break */
if
(
isWrapper
(
subob
))
{
self
=
WRAPPER
(
subob
);
while
(
self
->
obj
&&
isWrapper
(
self
->
obj
))
self
=
WRAPPER
(
self
->
obj
);
}
else
break
;
/* subob = aq_parent(self) */
/* if subob is None: break */
if
(
self
->
container
)
subob
=
self
->
container
;
else
break
;
}
}
else
{
/* Follow wrappers instead. */
c
=
OBJECT
(
self
);
while
(
1
)
{
if
(
c
==
o
)
return
PyInt_FromLong
(
1
);
if
(
c
&&
isWrapper
(
c
))
c
=
WRAPPER
(
c
)
->
container
;
else
break
;
}
}
return
PyInt_FromLong
(
0
);
return
capi_aq_inContextOf
((
PyObject
*
)
self
,
o
,
inner
);
}
PyObject
*
...
...
@@ -1332,8 +1371,7 @@ static PyObject *
capi_aq_acquire
(
PyObject
*
self
,
PyObject
*
name
,
PyObject
*
filter
,
PyObject
*
extra
,
int
explicit
,
PyObject
*
defalt
,
int
containment
)
{
PyObject
*
result
;
PyObject
*
result
,
*
v
,
*
tb
;
if
(
filter
==
Py_None
)
filter
=
0
;
...
...
@@ -1343,22 +1381,46 @@ capi_aq_acquire(PyObject *self, PyObject *name, PyObject *filter,
WRAPPER
(
self
),
name
,
filter
,
extra
,
OBJECT
(
self
),
1
,
explicit
||
WRAPPER
(
self
)
->
ob_type
==
(
PyTypeObject
*
)
&
Wrappertype
,
explicit
,
containment
);
/* Not wrapped and no filter, so just getattr */
if
(
!
filter
)
return
PyObject_GetAttr
(
self
,
name
);
explicit
,
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
,
filter
,
extra
,
OBJECT
(
self
),
1
,
1
,
explicit
,
containment
);
/* Get rid of temporary wrapper */
Py_DECREF
(
self
);
return
result
;
}
/* No wrapper and no __parent__, so just getattr. */
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
);
/* Crap, we've got to construct a wrapper so we can use Wrapper_findattr */
UNLESS
(
self
=
newWrapper
(
self
,
Py_None
,
(
PyTypeObject
*
)
&
Wrappertype
))
return
NULL
;
result
=
Wrapper_findattr
(
WRAPPER
(
self
),
name
,
filter
,
extra
,
OBJECT
(
self
),
1
,
1
,
explicit
,
containment
);
if
(
!
filter
)
return
PyObject_GetAttr
(
self
,
name
);
/* get rid of temp wrapper */
Py_DECREF
(
self
);
/* Crap, we've got to construct a wrapper so we can use
Wrapper_findattr */
UNLESS
(
self
=
newWrapper
(
self
,
Py_None
,
(
PyTypeObject
*
)
&
Wrappertype
))
return
NULL
;
result
=
Wrapper_findattr
(
WRAPPER
(
self
),
name
,
filter
,
extra
,
OBJECT
(
self
),
1
,
1
,
explicit
,
containment
);
return
result
;
/* Get rid of temporary wrapper */
Py_DECREF
(
self
);
return
result
;
}
}
static
PyObject
*
...
...
@@ -1384,13 +1446,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
)
{
...
...
@@ -1453,13 +1537,34 @@ module_aq_base(PyObject *ignored, PyObject *args)
static
PyObject
*
capi_aq_parent
(
PyObject
*
self
)
{
PyObject
*
result
=
Py_None
;
PyObject
*
result
,
*
v
,
*
tb
;
if
(
isWrapper
(
self
)
&&
WRAPPER
(
self
)
->
container
)
result
=
WRAPPER
(
self
)
->
container
;
{
result
=
WRAPPER
(
self
)
->
container
;
Py_INCREF
(
result
);
return
result
;
}
else
if
((
result
=
PyObject_GetAttr
(
self
,
py__parent__
)))
/* We already own the reference to result (PyObject_GetAttr gives
it to us), no need to INCREF here */
return
result
;
else
{
/* We need to 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
);
Py_INCREF
(
result
);
return
result
;
result
=
Py_None
;
Py_INCREF
(
result
);
return
result
;
}
}
static
PyObject
*
...
...
@@ -1535,7 +1640,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
;
...
...
@@ -1558,8 +1663,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
;
}
...
...
@@ -1582,6 +1706,53 @@ module_aq_chain(PyObject *ignored, PyObject *args)
return
capi_aq_chain
(
self
,
containment
);
}
static
PyObject
*
capi_aq_inContextOf
(
PyObject
*
self
,
PyObject
*
o
,
int
inner
)
{
PyObject
*
next
,
*
c
;
/* next = self
o = aq_base(o) */
next
=
self
;
while
(
isWrapper
(
o
)
&&
WRAPPER
(
o
)
->
obj
)
o
=
WRAPPER
(
o
)
->
obj
;
while
(
1
)
{
/* if aq_base(next) is o: return 1 */
c
=
next
;
while
(
isWrapper
(
c
)
&&
WRAPPER
(
c
)
->
obj
)
c
=
WRAPPER
(
c
)
->
obj
;
if
(
c
==
o
)
return
PyInt_FromLong
(
1
);
if
(
inner
)
{
self
=
capi_aq_inner
(
next
);
Py_DECREF
(
self
);
/* We're not holding on to the inner wrapper */
if
(
self
==
Py_None
)
break
;
}
else
self
=
next
;
next
=
capi_aq_parent
(
self
);
Py_DECREF
(
next
);
/* We're not holding on to the parent */
if
(
next
==
Py_None
)
break
;
}
return
PyInt_FromLong
(
0
);
}
static
PyObject
*
module_aq_inContextOf
(
PyObject
*
ignored
,
PyObject
*
args
)
{
PyObject
*
self
,
*
o
;
int
inner
=
1
;
UNLESS
(
PyArg_ParseTuple
(
args
,
"OO|i"
,
&
self
,
&
o
,
&
inner
))
return
NULL
;
return
capi_aq_inContextOf
(
self
,
o
,
inner
);
}
static
struct
PyMethodDef
methods
[]
=
{
{
"aq_acquire"
,
(
PyCFunction
)
module_aq_acquire
,
METH_VARARGS
|
METH_KEYWORDS
,
"aq_acquire(ob, name [, filter, extra, explicit]) -- "
...
...
@@ -1599,10 +1770,13 @@ static struct PyMethodDef methods[] = {
"aq_self(ob) -- Get the object with the outermost wrapper removed"
},
{
"aq_inner"
,
(
PyCFunction
)
module_aq_inner
,
METH_VARARGS
,
"aq_inner(ob) -- "
"Get the object with all
l
but the innermost wrapper removed"
},
"Get the object with all but the innermost wrapper removed"
},
{
"aq_chain"
,
(
PyCFunction
)
module_aq_chain
,
METH_VARARGS
,
"aq_chain(ob [, containment]) -- "
"Get a list of objects in the acquisition environment"
},
{
"aq_inContextOf"
,
(
PyCFunction
)
module_aq_inContextOf
,
METH_VARARGS
,
"aq_inContextOf(base, ob [, inner]) -- "
"Determine whether the object is in the acquisition context of base."
},
{
NULL
,
NULL
}
};
...
...
tests.py
View file @
ca40e281
...
...
@@ -357,6 +357,11 @@ def test_unwrapped():
...
AttributeError: aq_parent
>>> c.__parent__
Traceback (most recent call last):
...
AttributeError: __parent__
>>> Acquisition.aq_acquire(c, 'id')
'unwrapped'
>>> Acquisition.aq_acquire(c, 'x')
...
...
@@ -452,6 +457,13 @@ def test_simple():
>>> a.b.c.aq_inContextOf(a.b.c)
1
>>> Acquisition.aq_inContextOf(a.b.c, a)
1
>>> Acquisition.aq_inContextOf(a.b.c, a.b)
1
>>> Acquisition.aq_inContextOf(a.b.c, a.b.c)
1
>>> a.b.c.aq_acquire('y')
42
...
...
@@ -533,6 +545,13 @@ def test_simple():
>>> show(Acquisition.aq_self(a.b.c))
c
A wrapper's __parent__ attribute (which is equivalent to its
aq_parent attribute) points to the Acquisition parent.
>>> a.b.c.__parent__ == a.b.c.aq_parent
True
>>> a.b.c.__parent__ == a.b
True
"""
def
test__of__exception
():
...
...
@@ -1201,7 +1220,7 @@ def test_mixed_explicit_and_explicit():
"""
def
old_tests
():
def
test_aq_inContextOf
():
"""
>>> from ExtensionClass import Base
>>> import Acquisition
...
...
@@ -1213,6 +1232,9 @@ def old_tests():
... def hi(self):
... print "%s()" % self.__class__.__name__, self.color
>>> class Location(object):
... __parent__ = None
>>> b=B()
>>> b.a=A()
>>> b.a.hi()
...
...
@@ -1242,25 +1264,52 @@ def old_tests():
>>> b.c == c
1
>>> l = Location()
>>> l.__parent__ = b.c
>>> def checkContext(self, o):
... # Python equivalent to aq_inContextOf
... from Acquisition import aq_base, aq_parent, aq_inner
...
subob
= self
...
next
= self
... o = aq_base(o)
... while 1:
... if aq_base(subob) is o: return 1
... self = aq_inner(subob)
... if self is None: break
... subob = aq_parent(self)
... if subob is None: break
... if aq_base(next) is o:
... return 1
... self = aq_inner(next)
... if self is None:
... break
... next = aq_parent(self)
... if next is None:
... break
... return 0
>>> checkContext(b.c, b)
1
>>> not checkContext(b.c, b.a)
1
>>> checkContext(l, b)
1
>>> checkContext(l, b.c)
1
>>> not checkContext(l, b.a)
1
Acquisition.aq_inContextOf works the same way:
>>> Acquisition.aq_inContextOf(b.c, b)
1
>>> Acquisition.aq_inContextOf(b.c, b.a)
0
>>> Acquisition.aq_inContextOf(l, b)
1
>>> Acquisition.aq_inContextOf(l, b.c)
1
>>> Acquisition.aq_inContextOf(l, b.a)
0
>>> b.a.aq_inContextOf(b)
1
>>> b.c.aq_inContextOf(b)
...
...
@@ -1271,12 +1320,12 @@ def old_tests():
1
>>> b.c.d.aq_inContextOf(b.c)
1
>>>
not
b.c.aq_inContextOf(foo)
1
>>>
not
b.c.aq_inContextOf(b.a)
1
>>>
not
b.a.aq_inContextOf('somestring')
1
>>> b.c.aq_inContextOf(foo)
0
>>> b.c.aq_inContextOf(b.a)
0
>>> b.a.aq_inContextOf('somestring')
0
"""
def
test_AqAlg
():
...
...
@@ -1389,7 +1438,7 @@ def test_creating_wrappers_directly():
...
TypeError: __init__() takes exactly 2 arguments (1 given)
We can reassign aq_parent
We can reassign aq_parent
/ __parent__ on a wrapper:
>>> x = B()
>>> x.color = 'green'
...
...
@@ -1397,6 +1446,20 @@ def test_creating_wrappers_directly():
>>> w.color
'green'
>>> y = B()
>>> y.color = 'blue'
>>> w.__parent__ = y
>>> w.color
'blue'
Note that messing with the wrapper won't in any way affect the
wrapped object:
>>> Acquisition.aq_base(w).__parent__
Traceback (most recent call last):
...
AttributeError: __parent__
>>> w = ImplicitAcquisitionWrapper()
Traceback (most recent call last):
...
...
...
@@ -1664,6 +1727,434 @@ def test_proxying():
"""
class
Location
(
object
):
__parent__
=
None
class
ECLocation
(
ExtensionClass
.
Base
):
__parent__
=
None
def
test___parent__no_wrappers
():
"""
Acquisition also works with objects that aren't wrappers, as long
as they have __parent__ pointers. Let's take a hierarchy like
z --isParent--> y --isParent--> x:
>>> x = Location()
>>> y = Location()
>>> z = Location()
>>> x.__parent__ = y
>>> y.__parent__ = z
and some attributes that we want to acquire:
>>> x.hello = 'world'
>>> y.foo = 42
>>> z.foo = 43 # this should not be found
>>> z.bar = 3.145
``aq_acquire`` works as we know it from implicit/acquisition
wrappers:
>>> Acquisition.aq_acquire(x, 'hello')
'world'
>>> Acquisition.aq_acquire(x, 'foo')
42
>>> Acquisition.aq_acquire(x, 'bar')
3.145
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
"""
def
test_implicit_wrapper_as___parent__
():
"""
Let's do the same test again, only now not all objects are of the
same kind and link to each other via __parent__ pointers. The
root is a stupid ExtensionClass object:
>>> class Root(ExtensionClass.Base):
... bar = 3.145
>>> z = Root()
The intermediate parent is an object that supports implicit
acquisition. We bind it to the root via the __of__ protocol:
>>> class Impl(Acquisition.Implicit):
... foo = 42
>>> y = Impl().__of__(z)
The child object is again a simple object with a simple __parent__
pointer:
>>> x = Location()
>>> x.hello = 'world'
>>> x.__parent__ = y
``aq_acquire`` works as expected from implicit/acquisition
wrappers:
>>> Acquisition.aq_acquire(x, 'hello')
'world'
>>> Acquisition.aq_acquire(x, 'foo')
42
>>> Acquisition.aq_acquire(x, 'bar')
3.145
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):
>>> y.__parent__ is z
True
Just as much as you can assign to aq_parent, you can also assign
to __parent__ to change the acquisition context of the wrapper:
>>> newroot = Root()
>>> y.__parent__ = newroot
>>> y.__parent__ is z
False
>>> y.__parent__ is newroot
True
Note that messing with the wrapper won't in any way affect the
wrapped object:
>>> Acquisition.aq_base(y).__parent__
Traceback (most recent call last):
...
AttributeError: __parent__
"""
def
test_explicit_wrapper_as___parent__
():
"""
Let's do this test yet another time, with an explicit wrapper:
>>> class Root(ExtensionClass.Base):
... bar = 3.145
>>> z = Root()
The intermediate parent is an object that supports implicit
acquisition. We bind it to the root via the __of__ protocol:
>>> class Expl(Acquisition.Explicit):
... foo = 42
>>> y = Expl().__of__(z)
The child object is again a simple object with a simple __parent__
pointer:
>>> x = Location()
>>> x.hello = 'world'
>>> x.__parent__ = y
``aq_acquire`` works as expected from implicit/acquisition
wrappers:
>>> Acquisition.aq_acquire(x, 'hello')
'world'
>>> Acquisition.aq_acquire(x, 'foo')
42
>>> Acquisition.aq_acquire(x, 'bar')
3.145
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):
>>> y.__parent__ is z
True
Just as much as you can assign to aq_parent, you can also assign
to __parent__ to change the acquisition context of the wrapper:
>>> newroot = Root()
>>> y.__parent__ = newroot
>>> y.__parent__ is z
False
>>> y.__parent__ is newroot
True
Note that messing with the wrapper won't in any way affect the
wrapped object:
>>> Acquisition.aq_base(y).__parent__
Traceback (most recent call last):
...
AttributeError: __parent__
"""
def
test_implicit_wrapper_has_nonwrapper_as_aq_parent
():
"""Let's do this the other way around: The root and the
intermediate parent is an object that doesn't support acquisition,
>>> y = ECLocation()
>>> z = Location()
>>> y.__parent__ = z
>>> y.foo = 42
>>> z.foo = 43 # this should not be found
>>> z.bar = 3.145
only the outmost object does:
>>> class Impl(Acquisition.Implicit):
... hello = 'world'
>>> x = Impl().__of__(y)
Again, acquiring objects works as usual:
>>> Acquisition.aq_acquire(x, 'hello')
'world'
>>> Acquisition.aq_acquire(x, 'foo')
42
>>> Acquisition.aq_acquire(x, 'bar')
3.145
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:
>>> x.hello
'world'
>>> x.foo
42
>>> x.bar
3.145
"""
def
test_explicit_wrapper_has_nonwrapper_as_aq_parent
():
"""Let's do this the other way around: The root and the
intermediate parent is an object that doesn't support acquisition,
>>> y = ECLocation()
>>> z = Location()
>>> y.__parent__ = z
>>> y.foo = 42
>>> z.foo = 43 # this should not be found
>>> z.bar = 3.145
only the outmost object does:
>>> class Expl(Acquisition.Explicit):
... hello = 'world'
>>> x = Expl().__of__(y)
Again, acquiring objects works as usual:
>>> Acquisition.aq_acquire(x, 'hello')
'world'
>>> Acquisition.aq_acquire(x, 'foo')
42
>>> Acquisition.aq_acquire(x, 'bar')
3.145
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
():
"""
As a general safety belt, Acquisition won't follow a mixture of
circular __parent__ pointers and aq_parent wrappers. These can
occurr when code that uses implicit acquisition wrappers meets
code that uses __parent__ pointers.
>>> class Impl(Acquisition.Implicit):
... hello = 'world'
>>> class Impl2(Acquisition.Implicit):
... hello = 'world2'
... only = 'here'
>>> x = Impl()
>>> y = Impl2().__of__(x)
>>> x.__parent__ = y
>>> x.__parent__.aq_base is y.aq_base
True
>>> x.__parent__.__parent__ is x
True
>>> x.hello
'world'
>>> Acquisition.aq_acquire(x, 'hello')
'world'
>>> x.only
Traceback (most recent call last):
...
AttributeError: only
>>> Acquisition.aq_acquire(x, 'only')
'here'
>>> Acquisition.aq_acquire(x, 'non_existant_attr')
Traceback (most recent call last):
...
AttributeError: non_existant_attr
>>> Acquisition.aq_acquire(y, 'non_existant_attr')
Traceback (most recent call last):
...
AttributeError: non_existant_attr
>>> x.non_existant_attr
Traceback (most recent call last):
...
AttributeError: non_existant_attr
>>> y.non_existant_attr
Traceback (most recent call last):
...
AttributeError: non_existant_attr
"""
def
test___parent__parent__circles
():
"""
Acquisition won't follow circular __parent__ references:
>>> class Impl(Acquisition.Implicit):
... hello = 'world'
>>> class Impl2(Acquisition.Implicit):
... hello = 'world2'
... only = 'here'
>>> x = Impl()
>>> y = Impl2()
>>> x.__parent__ = y
>>> y.__parent__ = x
>>> x.__parent__.__parent__ is x
True
>>> Acquisition.aq_acquire(x, 'hello')
'world'
>>> Acquisition.aq_acquire(x, 'only')
'here'
>>> Acquisition.aq_acquire(x, 'non_existant_attr')
Traceback (most recent call last):
...
AttributeError: non_existant_attr
>>> Acquisition.aq_acquire(y, 'non_existant_attr')
Traceback (most recent call last):
...
AttributeError: non_existant_attr
"""
import
unittest
from
zope.testing.doctest
import
DocTestSuite
,
DocFileSuite
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment