Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
Zope
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
Zope
Commits
a7f7b252
Commit
a7f7b252
authored
Apr 10, 2005
by
Jim Fulton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added a helper function to set (or clear) the __get__ slot depending
on whether a class has an __of__ definition.
parent
113fc84a
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
123 additions
and
19 deletions
+123
-19
lib/python/ExtensionClass/_ExtensionClass.c
lib/python/ExtensionClass/_ExtensionClass.c
+53
-19
lib/python/ExtensionClass/tests.py
lib/python/ExtensionClass/tests.py
+70
-0
No files found.
lib/python/ExtensionClass/_ExtensionClass.c
View file @
a7f7b252
...
@@ -301,10 +301,42 @@ EC_new(PyTypeObject *self, PyObject *args, PyObject *kw)
...
@@ -301,10 +301,42 @@ EC_new(PyTypeObject *self, PyObject *args, PyObject *kw)
return
result
;
return
result
;
}
}
/* set up __get__, if necessary */
static
int
EC_init_of
(
PyTypeObject
*
self
)
{
PyObject
*
__of__
;
__of__
=
PyObject_GetAttr
(
OBJECT
(
self
),
str__of__
);
if
(
__of__
)
{
Py_DECREF
(
__of__
);
if
(
self
->
tp_descr_get
)
{
if
(
self
->
tp_descr_get
!=
of_get
)
{
PyErr_SetString
(
PyExc_TypeError
,
"Can't mix __of__ and descriptors"
);
return
-
1
;
}
}
else
self
->
tp_descr_get
=
of_get
;
}
else
{
PyErr_Clear
();
if
(
self
->
tp_descr_get
==
of_get
)
self
->
tp_descr_get
=
NULL
;
}
return
0
;
}
static
int
static
int
EC_init
(
PyTypeObject
*
self
,
PyObject
*
args
,
PyObject
*
kw
)
EC_init
(
PyTypeObject
*
self
,
PyObject
*
args
,
PyObject
*
kw
)
{
{
PyObject
*
__class_init__
,
*
__of__
,
*
r
;
PyObject
*
__class_init__
,
*
r
;
if
(
PyType_Type
.
tp_init
(
OBJECT
(
self
),
args
,
kw
)
<
0
)
if
(
PyType_Type
.
tp_init
(
OBJECT
(
self
),
args
,
kw
)
<
0
)
return
-
1
;
return
-
1
;
...
@@ -318,24 +350,8 @@ EC_init(PyTypeObject *self, PyObject *args, PyObject *kw)
...
@@ -318,24 +350,8 @@ EC_init(PyTypeObject *self, PyObject *args, PyObject *kw)
return
-
1
;
return
-
1
;
}
}
/* set up __get__, if necessary */
if
(
EC_init_of
(
self
)
<
0
)
if
(
self
->
tp_descr_get
!=
of_get
)
return
-
1
;
{
__of__
=
PyObject_GetAttr
(
OBJECT
(
self
),
str__of__
);
if
(
__of__
)
{
Py_DECREF
(
__of__
);
if
(
self
->
tp_descr_get
)
{
PyErr_SetString
(
PyExc_TypeError
,
"Can't mix __of__ and descriptors"
);
return
-
1
;
}
self
->
tp_descr_get
=
of_get
;
}
else
PyErr_Clear
();
}
/* Call __class_init__ */
/* Call __class_init__ */
__class_init__
=
PyObject_GetAttr
(
OBJECT
(
self
),
str__class_init__
);
__class_init__
=
PyObject_GetAttr
(
OBJECT
(
self
),
str__class_init__
);
...
@@ -635,10 +651,28 @@ debug(PyObject *self, PyObject *o)
...
@@ -635,10 +651,28 @@ debug(PyObject *self, PyObject *o)
return
Py_None
;
return
Py_None
;
}
}
static
PyObject
*
pmc_init_of
(
PyObject
*
self
,
PyObject
*
args
)
{
PyObject
*
o
;
if
(
!
PyArg_ParseTuple
(
args
,
"O!"
,
(
PyObject
*
)
&
ExtensionClassType
,
&
o
))
return
NULL
;
if
(
EC_init_of
((
PyTypeObject
*
)
o
)
<
0
)
return
NULL
;
Py_INCREF
(
Py_None
);
return
Py_None
;
}
/* List of methods defined in the module */
/* List of methods defined in the module */
static
struct
PyMethodDef
ec_methods
[]
=
{
static
struct
PyMethodDef
ec_methods
[]
=
{
{
"debug"
,
(
PyCFunction
)
debug
,
METH_O
,
""
},
{
"debug"
,
(
PyCFunction
)
debug
,
METH_O
,
""
},
{
"pmc_init_of"
,
(
PyCFunction
)
pmc_init_of
,
METH_VARARGS
,
"Initialize __get__ for classes that define __of__"
},
{
NULL
,
(
PyCFunction
)
NULL
,
0
,
NULL
}
/* sentinel */
{
NULL
,
(
PyCFunction
)
NULL
,
0
,
NULL
}
/* sentinel */
};
};
...
...
lib/python/ExtensionClass/tests.py
View file @
a7f7b252
...
@@ -736,6 +736,76 @@ def test___of___w_metaclass_instance():
...
@@ -736,6 +736,76 @@ def test___of___w_metaclass_instance():
"""
"""
def
test___of__set_after_creation
():
"""We may need to set __of__ after a class is created.
Normally, in a class's __init__, the initialization code checks for
an __of__ method and, if it isn't already set, sets __get__.
If a class is persistent and loaded from the database, we want
this to happen in __setstate__. The pmc_init_of function allws us
to do that.
We'll create an extension class without a __of__. We'll also give
it a special meta class, just to make sure that this works with
funny metaclasses too:
>>> import ExtensionClass
>>> class M(ExtensionClass.ExtensionClass):
... "A meta class"
>>> class B(ExtensionClass.Base):
... __metaclass__ = M
... def __init__(self, name):
... self.name = name
... def __repr__(self):
... return self.name
>>> B.__class__ is M
True
>>> x = B('x')
>>> x.y = B('y')
>>> x.y
y
We define a __of__ method for B after the fact:
>>> def __of__(self, other):
... print '__of__(%r, %r)' % (self, other)
... return self
>>> B.__of__ = __of__
We see that this has no effect:
>>> x.y
y
Until we use pmc_init_of:
>>> ExtensionClass.pmc_init_of(B)
>>> x.y
__of__(y, x)
y
Note that there is no harm in calling pmc_init_of multiple times:
>>> ExtensionClass.pmc_init_of(B)
>>> ExtensionClass.pmc_init_of(B)
>>> ExtensionClass.pmc_init_of(B)
>>> x.y
__of__(y, x)
y
If we remove __of__, we'll go back to the behavior we had before:
>>> del B.__of__
>>> ExtensionClass.pmc_init_of(B)
>>> x.y
y
"""
from
zope.testing.doctest
import
DocTestSuite
from
zope.testing.doctest
import
DocTestSuite
import
unittest
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