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
089f8741
Commit
089f8741
authored
May 06, 2005
by
Jim Fulton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added cyclic garbage collection support to Acquisition wrappers.
parent
d9f085b9
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
195 additions
and
75 deletions
+195
-75
_Acquisition.c
_Acquisition.c
+123
-73
tests.py
tests.py
+72
-2
No files found.
_Acquisition.c
View file @
089f8741
...
...
@@ -87,7 +87,7 @@ init_py_names(void)
static
PyObject
*
CallMethodO
(
PyObject
*
self
,
PyObject
*
name
,
PyObject
*
args
,
PyObject
*
kw
)
PyObject
*
args
,
PyObject
*
kw
)
{
if
(
!
args
&&
PyErr_Occurred
())
return
NULL
;
UNLESS
(
name
=
PyObject_GetAttr
(
self
,
name
))
{
...
...
@@ -115,25 +115,35 @@ staticforward PyExtensionClass Wrappertype, XaqWrappertype;
(O)->ob_type==(PyTypeObject*)&XaqWrappertype)
#define WRAPPER(O) ((Wrapper*)(O))
static
PyObject
*
Wrapper__init__
(
Wrapper
*
self
,
PyObject
*
args
)
static
int
Wrapper__init__
(
Wrapper
*
self
,
PyObject
*
args
,
PyObject
*
kwargs
)
{
PyObject
*
obj
,
*
container
;
UNLESS
(
PyArg_Parse
(
args
,
"(OO)"
,
&
obj
,
&
container
))
return
NULL
;
if
(
kwargs
&&
PyDict_Size
(
kwargs
)
!=
0
)
{
PyErr_SetString
(
PyExc_TypeError
,
"kwyword arguments not allowed"
);
return
-
1
;
}
UNLESS
(
PyArg_ParseTuple
(
args
,
"OO:__init__"
,
&
obj
,
&
container
))
return
-
1
;
if
(
self
==
WRAPPER
(
obj
))
{
PyErr_SetString
(
PyExc_ValueError
,
"Cannot wrap acquisition wrapper in itself (Wrapper__init__)"
);
return
NULL
;
return
-
1
;
}
Py_INCREF
(
obj
);
Py_INCREF
(
container
);
self
->
obj
=
obj
;
self
->
container
=
container
;
Py_INCREF
(
Py_None
);
return
Py_None
;
if
(
container
!=
Py_None
)
{
Py_INCREF
(
container
);
self
->
container
=
container
;
}
return
0
;
}
/* ---------------------------------------------------------------- */
...
...
@@ -150,8 +160,7 @@ __of__(PyObject *inst, PyObject *parent)
PyTuple_SET_ITEM
(
t
,
0
,
NULL
);
Py_DECREF
(
t
);
if
(
r
&&
r
->
ob_refcnt
==
1
if
(
r
!=
NULL
&&
isWrapper
(
r
)
&&
WRAPPER
(
r
)
->
container
&&
isWrapper
(
WRAPPER
(
r
)
->
container
)
)
...
...
@@ -160,9 +169,21 @@ __of__(PyObject *inst, PyObject *parent)
WRAPPER
(
WRAPPER
(
r
)
->
container
)
->
obj
)
)
{
/* Simplify wrapper */
Py_XINCREF
(
WRAPPER
(
WRAPPER
(
r
)
->
obj
)
->
obj
);
ASSIGN
(
WRAPPER
(
r
)
->
obj
,
WRAPPER
(
WRAPPER
(
r
)
->
obj
)
->
obj
);
if
(
r
->
ob_refcnt
!=
1
)
{
t
=
PyObject_CallFunctionObjArgs
((
PyObject
*
)(
r
->
ob_type
),
WRAPPER
(
r
)
->
obj
,
WRAPPER
(
r
)
->
container
,
NULL
);
Py_DECREF
(
r
);
if
(
t
==
NULL
)
return
NULL
;
r
=
t
;
}
/* Simplify wrapper */
Py_XINCREF
(
WRAPPER
(
WRAPPER
(
r
)
->
obj
)
->
obj
);
ASSIGN
(
WRAPPER
(
r
)
->
obj
,
WRAPPER
(
WRAPPER
(
r
)
->
obj
)
->
obj
);
}
return
r
;
...
...
@@ -171,62 +192,64 @@ err:
return
NULL
;
}
static
Wrapper
*
freeWrappers
=
0
;
static
int
nWrappers
=
0
;
#define MAX_CACHED_WRAPPERS 200
static
PyObject
*
newWrapper
(
PyObject
*
obj
,
PyObject
*
container
,
PyTypeObject
*
Wrappertype
)
Wrapper_descrget
(
Wrapper
*
self
,
PyObject
*
inst
,
PyObject
*
cls
)
{
Wrapper
*
self
;
if
(
freeWrappers
)
{
self
=
freeWrappers
;
freeWrappers
=
(
Wrapper
*
)
self
->
obj
;
_Py_NewReference
((
PyObject
*
)
self
);
assert
(
self
->
ob_refcnt
==
1
);
self
->
ob_type
=
Wrappertype
;
nWrappers
--
;
}
else
if
(
inst
==
NULL
)
{
UNLESS
(
self
=
PyObject_NEW
(
Wrapper
,
Wrappertype
))
return
NULL
;
Py_INCREF
(
self
);
return
(
PyObject
*
)
self
;
}
return
__of__
((
PyObject
*
)
self
,
inst
);
}
if
(
self
==
WRAPPER
(
obj
))
{
PyErr_SetString
(
PyExc_ValueError
,
"Cannot wrap acquisition wrapper in itself (newWrapper)"
);
Py_DECREF
(
self
);
return
NULL
;
}
Py_INCREF
(
Wrappertype
);
Py_XINCREF
(
obj
);
Py_XINCREF
(
container
);
self
->
obj
=
obj
;
self
->
container
=
container
;
return
OBJECT
(
self
);
}
#define newWrapper(obj, container, Wrappertype) \
PyObject_CallFunctionObjArgs(OBJECT(Wrappertype), obj, container, NULL)
static
void
Wrapper_
dealloc
(
Wrapper
*
self
)
static
int
Wrapper_
traverse
(
Wrapper
*
self
,
visitproc
visit
,
void
*
arg
)
{
Py_XDECREF
(
self
->
obj
);
Py_XDECREF
(
self
->
container
);
Py_DECREF
(
self
->
ob_type
);
int
vret
;
if
(
nWrappers
<
MAX_CACHED_WRAPPERS
)
{
self
->
obj
=
OBJECT
(
freeWrappers
);
freeWrappers
=
self
;
nWrappers
++
;
if
(
self
->
obj
)
{
vret
=
visit
(
self
->
obj
,
arg
);
if
(
vret
!=
0
)
return
vret
;
}
else
{
PyObject_DEL
(
self
);
if
(
self
->
container
)
{
vret
=
visit
(
self
->
container
,
arg
);
if
(
vret
!=
0
)
return
vret
;
}
return
0
;
}
static
int
Wrapper_clear
(
Wrapper
*
self
)
{
PyObject
*
tmp
;
tmp
=
self
->
obj
;
self
->
obj
=
NULL
;
Py_XDECREF
(
tmp
);
tmp
=
self
->
container
;
self
->
container
=
NULL
;
Py_XDECREF
(
tmp
);
return
0
;
}
static
void
Wrapper_dealloc
(
Wrapper
*
self
)
{
Wrapper_clear
(
self
);
self
->
ob_type
->
tp_free
((
PyObject
*
)
self
);
}
static
PyObject
*
...
...
@@ -1113,10 +1136,7 @@ Wrappers_are_not_picklable(PyObject *wrapper, PyObject *args)
return
NULL
;
}
static
struct
PyMethodDef
Wrapper_methods
[]
=
{
{
"__init__"
,
(
PyCFunction
)
Wrapper__init__
,
0
,
"Initialize an Acquirer Wrapper"
},
{
"acquire"
,
(
PyCFunction
)
Wrapper_acquire_method
,
METH_VARARGS
|
METH_KEYWORDS
,
"Get an attribute, acquiring it if necessary"
},
...
...
@@ -1155,12 +1175,27 @@ static PyExtensionClass Wrappertype = {
(
reprfunc
)
Wrapper_str
,
/*tp_str*/
(
getattrofunc
)
Wrapper_getattro
,
/*tp_getattr with object key*/
(
setattrofunc
)
Wrapper_setattro
,
/*tp_setattr with object key*/
/* Space for future expansion */
0L
,
0L
,
/* tp_as_buffer */
0
,
/* tp_flags */
Py_TPFLAGS_DEFAULT
|
Py_TPFLAGS_BASETYPE
|
Py_TPFLAGS_HAVE_GC
,
"Wrapper object for implicit acquisition"
,
/* Documentation string */
METHOD_CHAIN
(
Wrapper_methods
),
(
void
*
)(
EXTENSIONCLASS_BINDABLE_FLAG
),
/* tp_traverse */
(
traverseproc
)
Wrapper_traverse
,
/* tp_clear */
(
inquiry
)
Wrapper_clear
,
/* tp_richcompare */
(
richcmpfunc
)
0
,
/* tp_weaklistoffset */
(
long
)
0
,
/* tp_iter */
(
getiterfunc
)
0
,
/* tp_iternext */
(
iternextfunc
)
0
,
/* tp_methods */
Wrapper_methods
,
/* tp_members */
0
,
/* tp_getset */
0
,
/* tp_base */
0
,
/* tp_dict */
0
,
/* tp_descr_get */
(
descrgetfunc
)
Wrapper_descrget
,
/* tp_descr_set */
0
,
/* tp_dictoffset */
0
,
/* tp_init */
(
initproc
)
Wrapper__init__
,
};
static
PyExtensionClass
XaqWrappertype
=
{
...
...
@@ -1184,12 +1219,27 @@ static PyExtensionClass XaqWrappertype = {
(
reprfunc
)
Wrapper_str
,
/*tp_str*/
(
getattrofunc
)
Xaq_getattro
,
/*tp_getattr with object key*/
(
setattrofunc
)
Wrapper_setattro
,
/*tp_setattr with object key*/
/* Space for future expansion */
0L
,
0L
,
"Wrapper object for explicit acquisition"
,
/* Documentation string */
METHOD_CHAIN
(
Wrapper_methods
),
(
void
*
)(
EXTENSIONCLASS_BINDABLE_FLAG
),
/* tp_as_buffer */
0
,
/* tp_flags */
Py_TPFLAGS_DEFAULT
|
Py_TPFLAGS_BASETYPE
|
Py_TPFLAGS_HAVE_GC
,
"Wrapper object for implicit acquisition"
,
/* Documentation string */
/* tp_traverse */
(
traverseproc
)
Wrapper_traverse
,
/* tp_clear */
(
inquiry
)
Wrapper_clear
,
/* tp_richcompare */
(
richcmpfunc
)
0
,
/* tp_weaklistoffset */
(
long
)
0
,
/* tp_iter */
(
getiterfunc
)
0
,
/* tp_iternext */
(
iternextfunc
)
0
,
/* tp_methods */
Wrapper_methods
,
/* tp_members */
0
,
/* tp_getset */
0
,
/* tp_base */
0
,
/* tp_dict */
0
,
/* tp_descr_get */
(
descrgetfunc
)
Wrapper_descrget
,
/* tp_descr_set */
0
,
/* tp_dictoffset */
0
,
/* tp_init */
(
initproc
)
Wrapper__init__
,
};
static
PyObject
*
...
...
@@ -1262,7 +1312,7 @@ capi_aq_acquire(PyObject *self, PyObject *name, PyObject *filter,
if
(
!
filter
)
return
PyObject_GetAttr
(
self
,
name
);
/* Crap, we've got to construct a wrapper so we can use Wrapper_findattr */
UNLESS
(
self
=
newWrapper
(
self
,
NULL
,
(
PyTypeObject
*
)
&
Wrappertype
))
UNLESS
(
self
=
newWrapper
(
self
,
Py_None
,
(
PyTypeObject
*
)
&
Wrappertype
))
return
NULL
;
result
=
Wrapper_findattr
(
WRAPPER
(
self
),
name
,
filter
,
extra
,
OBJECT
(
self
),
...
...
tests.py
View file @
089f8741
...
...
@@ -369,6 +369,7 @@ def test_unwrapped():
Traceback (most recent call last):
...
AttributeError: id
>>> Acquisition.aq_acquire(c, 'id',
... lambda searched, parent, name, ob, extra: extra,
... 1)
...
...
@@ -1386,7 +1387,7 @@ def test_creating_wrappers_directly():
>>> w = ImplicitAcquisitionWrapper(a.b)
Traceback (most recent call last):
...
TypeError:
argument must be 2-item sequence, not B
TypeError:
__init__() takes exactly 2 arguments (1 given)
We can reassign aq_parent
...
...
@@ -1399,8 +1400,12 @@ def test_creating_wrappers_directly():
>>> w = ImplicitAcquisitionWrapper()
Traceback (most recent call last):
...
TypeError:
function takes at least one argument
TypeError:
__init__() takes exactly 2 arguments (0 given)
>>> w = ImplicitAcquisitionWrapper(obj=1)
Traceback (most recent call last):
...
TypeError: kwyword arguments not allowed
"""
def
test_cant_pickle_acquisition_wrappers_classic
():
...
...
@@ -1524,6 +1529,71 @@ def showaq(m_self, indent=''):
rval
=
rval
+
indent
+
id
+
"
\
n
"
return
rval
def
test_Basic_gc
():
"""Test to make sure that EC instances participate in GC
>>> from ExtensionClass import Base
>>> import gc
>>> thresholds = gc.get_threshold()
>>> gc.set_threshold(0)
>>> for B in I, E:
... class C1(B):
... pass
...
... class C2(Base):
... def __del__(self):
... print 'removed'
...
... a=C1('a')
... a.b = C1('a.b')
... a.b.a = a
... a.b.c = C2()
... ignore = gc.collect()
... del a
... removed = gc.collect()
... print removed > 0
removed
True
removed
True
>>> gc.set_threshold(*thresholds)
"""
def
test_Wrapper_gc
():
"""Test to make sure that EC instances participate in GC
>>> import gc
>>> thresholds = gc.get_threshold()
>>> gc.set_threshold(0)
>>> for B in I, E:
... class C:
... def __del__(self):
... print 'removed'
...
... a=B('a')
... a.b = B('b')
... a.a_b = a.b # circ ref through wrapper
... a.b.c = C()
... ignored = gc.collect()
... del a
... removed = gc.collect()
... removed > 0
removed
True
removed
True
>>> gc.set_threshold(*thresholds)
"""
import
unittest
...
...
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