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
6cc20dbd
Commit
6cc20dbd
authored
Dec 06, 1996
by
Jim Fulton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Major speed enhancements for attribute lookup and calling special
methods.
parent
4bf47247
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1910 additions
and
608 deletions
+1910
-608
lib/Components/ExtensionClass/ExtensionClass.c
lib/Components/ExtensionClass/ExtensionClass.c
+955
-304
lib/Components/ExtensionClass/src/ExtensionClass.c
lib/Components/ExtensionClass/src/ExtensionClass.c
+955
-304
No files found.
lib/Components/ExtensionClass/ExtensionClass.c
View file @
6cc20dbd
/*
$Id: ExtensionClass.c,v 1.
3 1996/10/24 21:07:4
9 jim Exp $
$Id: ExtensionClass.c,v 1.
4 1996/12/06 17:12:2
9 jim Exp $
Extension Class
...
...
@@ -56,6 +56,10 @@
(540) 371-6909
$Log: ExtensionClass.c,v $
Revision 1.4 1996/12/06 17:12:29 jim
Major speed enhancements for attribute lookup and calling special
methods.
Revision 1.3 1996/10/24 21:07:49 jim
Fixed bug in returning __bases__ for base classes.
Added missing PyErr_Clear() call.
...
...
@@ -84,7 +88,7 @@ static char ExtensionClass_module_documentation[] =
" - They provide access to unbound methods,
\n
"
" - They can be called to create instances.
\n
"
"
\n
"
"$Id: ExtensionClass.c,v 1.
3 1996/10/24 21:07:4
9 jim Exp $
\n
"
"$Id: ExtensionClass.c,v 1.
4 1996/12/06 17:12:2
9 jim Exp $
\n
"
;
#include "Python.h"
...
...
@@ -102,6 +106,72 @@ typedef struct { PyObject_HEAD } Dataless;
#include "ExtensionClass.h"
staticforward
PyExtensionClass
CCLtype
;
#define PyExtensionClass_Check(O) ((O)->ob_type == (PyTypeObject*)&CCLtype)
#define PyExtensionInstance_Check(O) \
((O)->ob_type->ob_type == (PyTypeObject*)&CCLtype)
#define AsPyExtensionClass(O) ((PyExtensionClass*)(O))
#define PyExtensionClassOf(O) ((PyExtensionClass*)((O)->ob_type))
#define AsPyObject(O) ((PyObject*)(O))
static
PyObject
*
py__add__
,
*
py__sub__
,
*
py__mul__
,
*
py__div__
,
*
py__mod__
,
*
py__pow__
,
*
py__divmod__
,
*
py__lshift__
,
*
py__rshift__
,
*
py__and__
,
*
py__or__
,
*
py__xor__
,
*
py__coerce__
,
*
py__neg__
,
*
py__pos__
,
*
py__abs__
,
*
py__nonzero__
,
*
py__inv__
,
*
py__int__
,
*
py__long__
,
*
py__float__
,
*
py__oct__
,
*
py__hex__
,
*
py__getitem__
,
*
py__setitem__
,
*
py__getslice__
,
*
py__setslice__
,
*
py__concat__
,
*
py__repeat__
,
*
py__len__
,
*
py__bind_to_object__
,
*
py__call__
,
*
py__getattr__
,
*
py__setattr__
,
*
py__del__
,
*
py__repr__
,
*
py__str__
,
*
py__hash__
,
*
py__cmp__
,
*
py__var_size__
,
*
py__init__
;
static
void
init_py_names
()
{
#define INIT_PY_NAME(N) py ## N = PyString_FromString(#N)
INIT_PY_NAME
(
__add__
);
INIT_PY_NAME
(
__sub__
);
INIT_PY_NAME
(
__mul__
);
INIT_PY_NAME
(
__div__
);
INIT_PY_NAME
(
__mod__
);
INIT_PY_NAME
(
__pow__
);
INIT_PY_NAME
(
__divmod__
);
INIT_PY_NAME
(
__lshift__
);
INIT_PY_NAME
(
__rshift__
);
INIT_PY_NAME
(
__and__
);
INIT_PY_NAME
(
__or__
);
INIT_PY_NAME
(
__xor__
);
INIT_PY_NAME
(
__coerce__
);
INIT_PY_NAME
(
__neg__
);
INIT_PY_NAME
(
__pos__
);
INIT_PY_NAME
(
__abs__
);
INIT_PY_NAME
(
__nonzero__
);
INIT_PY_NAME
(
__inv__
);
INIT_PY_NAME
(
__int__
);
INIT_PY_NAME
(
__long__
);
INIT_PY_NAME
(
__float__
);
INIT_PY_NAME
(
__oct__
);
INIT_PY_NAME
(
__hex__
);
INIT_PY_NAME
(
__getitem__
);
INIT_PY_NAME
(
__setitem__
);
INIT_PY_NAME
(
__getslice__
);
INIT_PY_NAME
(
__setslice__
);
INIT_PY_NAME
(
__concat__
);
INIT_PY_NAME
(
__repeat__
);
INIT_PY_NAME
(
__len__
);
INIT_PY_NAME
(
__bind_to_object__
);
INIT_PY_NAME
(
__call__
);
INIT_PY_NAME
(
__getattr__
);
INIT_PY_NAME
(
__setattr__
);
INIT_PY_NAME
(
__del__
);
INIT_PY_NAME
(
__repr__
);
INIT_PY_NAME
(
__str__
);
INIT_PY_NAME
(
__hash__
);
INIT_PY_NAME
(
__cmp__
);
INIT_PY_NAME
(
__var_size__
);
INIT_PY_NAME
(
__init__
);
#undef INIT_PY_NAME
}
/* CMethod objects: */
typedef
struct
{
...
...
@@ -116,6 +186,40 @@ typedef struct {
staticforward
PyTypeObject
CMethodType
;
#define CMethod_Check(O) ((O)->ob_type==&CMethodType)
#define UnboundCMethod_Check(O) \
((O)->ob_type==&CMethodType && ! ((CMethod*)(O))->self)
#define AsCMethod(O) ((CMethod*)(O))
static
int
CMethod_issubclass
(
PyExtensionClass
*
sub
,
PyExtensionClass
*
type
)
{
int
i
,
l
;
PyObject
*
t
;
if
(
sub
==
type
)
return
1
;
if
(
!
sub
->
bases
)
return
0
;
l
=
PyTuple_Size
(
sub
->
bases
);
for
(
i
=
0
;
i
<
l
;
i
++
)
{
t
=
PyTuple_GET_ITEM
(
sub
->
bases
,
i
);
if
(
t
==
(
PyObject
*
)
type
)
return
1
;
if
(
PyExtensionClass_Check
(
t
)
&&
AsPyExtensionClass
(
t
)
->
bases
&&
CMethod_issubclass
(
AsPyExtensionClass
(
t
),
type
)
)
return
1
;
}
return
0
;
}
#define Subclass_Check(C1,C2) \
CMethod_issubclass((PyExtensionClass *)(C1), (PyExtensionClass *)(C2))
#define SubclassInstance_Check(C1,C2) \
CMethod_issubclass((PyExtensionClass *)((C1)->ob_type), \
(PyExtensionClass *)(C2))
static
CMethod
*
newCMethod
(
PyTypeObject
*
type
,
char
*
name
,
PyCFunction
meth
,
int
flags
,
char
*
doc
)
...
...
@@ -139,6 +243,15 @@ bindCMethod(CMethod *m, PyObject *inst)
{
CMethod
*
self
;
UNLESS
(
inst
->
ob_type
==
m
->
type
||
(
PyExtensionInstance_Check
(
inst
)
&&
SubclassInstance_Check
(
inst
,
m
->
type
))
)
{
Py_INCREF
(
m
);
return
m
;
}
UNLESS
(
self
=
PyObject_NEW
(
CMethod
,
&
CMethodType
))
return
NULL
;
Py_INCREF
(
inst
);
...
...
@@ -153,8 +266,7 @@ bindCMethod(CMethod *m, PyObject *inst)
}
static
void
CMethod_dealloc
(
self
)
CMethod
*
self
;
CMethod_dealloc
(
CMethod
*
self
)
{
Py_DECREF
(
self
->
type
);
Py_XDECREF
(
self
->
self
);
...
...
@@ -162,11 +274,7 @@ CMethod_dealloc(self)
}
static
PyObject
*
call_cmethod
(
self
,
inst
,
args
,
kw
)
CMethod
*
self
;
PyObject
*
inst
;
PyObject
*
args
;
PyObject
*
kw
;
call_cmethod
(
CMethod
*
self
,
PyObject
*
inst
,
PyObject
*
args
,
PyObject
*
kw
)
{
if
(
!
(
self
->
flags
&
METH_VARARGS
))
{
int
size
=
PyTuple_Size
(
args
);
...
...
@@ -189,31 +297,9 @@ call_cmethod(self, inst, args, kw)
}
}
static
int
CMethod_issubclass
(
PyExtensionClass
*
sub
,
PyExtensionClass
*
type
)
{
int
i
,
l
;
PyObject
*
t
;
if
(
!
sub
->
bases
)
return
0
;
l
=
PyTuple_Size
(
sub
->
bases
);
for
(
i
=
0
;
i
<
l
;
i
++
)
{
t
=
PyTuple_GET_ITEM
(
sub
->
bases
,
i
);
if
(
t
==
(
PyObject
*
)
type
)
return
1
;
if
(
t
->
ob_type
==
(
PyTypeObject
*
)
&
CCLtype
&&
((
PyExtensionClass
*
)
t
)
->
bases
&&
CMethod_issubclass
((
PyExtensionClass
*
)
t
,
type
)
)
return
1
;
}
return
0
;
}
static
PyObject
*
CMethod_call
(
self
,
args
,
kw
)
CMethod
*
self
;
PyObject
*
args
;
PyObject
*
kw
;
CMethod_call
(
CMethod
*
self
,
PyObject
*
args
,
PyObject
*
kw
)
{
int
size
;
char
*
buf
;
...
...
@@ -227,10 +313,10 @@ CMethod_call(self,args,kw)
UNLESS
(
first
=
PyTuple_GET_ITEM
(
args
,
0
))
return
NULL
;
if
(
first
->
ob_type
==
self
->
type
||
(
first
->
ob_type
->
ob_type
==
(
PyTypeObject
*
)
&
CCLtype
(
PyExtensionInstance_Check
(
first
)
&&
CMethod_issubclass
(
(
PyExtensionClass
*
)(
first
->
ob_type
),
(
PyExtensionClass
*
)
(
self
->
type
))
CMethod_issubclass
(
PyExtensionClassOf
(
first
),
AsPyExtensionClass
(
self
->
type
))
)
);
{
...
...
@@ -253,9 +339,7 @@ CMethod_call(self,args,kw)
}
static
PyObject
*
CMethod_getattr
(
self
,
name
)
CMethod
*
self
;
char
*
name
;
CMethod_getattr
(
CMethod
*
self
,
char
*
name
)
{
PyObject
*
r
;
...
...
@@ -299,7 +383,7 @@ static PyTypeObject CMethodType = {
/* methods */
(
destructor
)
CMethod_dealloc
,
/*tp_dealloc*/
(
printfunc
)
0
,
/*tp_print*/
(
getattrfunc
)
0
,
/*tp_getattr*/
(
getattrfunc
)
CMethod_getattr
,
/*tp_getattr*/
(
setattrfunc
)
0
,
/*tp_setattr*/
(
cmpfunc
)
0
,
/*tp_compare*/
(
reprfunc
)
0
,
/*tp_repr*/
...
...
@@ -316,23 +400,32 @@ static PyTypeObject CMethodType = {
/* Documentation string */
};
/* P
m
ethod objects: */
/* P
M
ethod objects: */
typedef
struct
{
PyObject_HEAD
PyTypeObject
*
type
;
PyObject
*
self
;
PyObject
*
meth
;
}
Pmethod
;
}
PMethod
;
staticforward
PyTypeObject
PMethodType
;
#define PMethod_Check(O) ((O)->ob_type==&PMethodType)
#define UnboundPMethod_Check(O) \
((O)->ob_type==&PMethodType && ! ((PMethod*)(O))->self)
staticforward
PyTypeObject
PmethodType
;
#define UnboundEMethod_Check(O) \
(((O)->ob_type==&PMethodType ||(O)->ob_type==&CMethodType) \
&& ! ((PMethod*)(O))->self)
static
Pmethod
*
newPmethod
(
PyTypeObject
*
type
,
PyObject
*
meth
)
static
PMethod
*
newPMethod
(
PyTypeObject
*
type
,
PyObject
*
meth
)
{
P
m
ethod
*
self
;
P
M
ethod
*
self
;
UNLESS
(
self
=
PyObject_NEW
(
P
method
,
&
Pm
ethodType
))
return
NULL
;
UNLESS
(
self
=
PyObject_NEW
(
P
Method
,
&
PM
ethodType
))
return
NULL
;
Py_INCREF
(
type
);
Py_INCREF
(
meth
);
self
->
type
=
type
;
...
...
@@ -341,12 +434,20 @@ newPmethod(PyTypeObject *type, PyObject *meth)
return
self
;
}
static
P
m
ethod
*
bindP
method
(
Pm
ethod
*
m
,
PyObject
*
inst
)
static
P
M
ethod
*
bindP
Method
(
PM
ethod
*
m
,
PyObject
*
inst
)
{
Pmethod
*
self
;
PMethod
*
self
;
UNLESS
(
PyExtensionInstance_Check
(
inst
))
{
PyErr_SetString
(
PyExc_TypeError
,
"attempt to wrap extension method using an object that
\n
"
"is not an extension class instance."
);
return
NULL
;
}
UNLESS
(
self
=
PyObject_NEW
(
P
method
,
&
Pm
ethodType
))
return
NULL
;
UNLESS
(
self
=
PyObject_NEW
(
P
Method
,
&
PM
ethodType
))
return
NULL
;
Py_INCREF
(
inst
);
Py_INCREF
(
m
->
type
);
...
...
@@ -357,8 +458,7 @@ bindPmethod(Pmethod *m, PyObject *inst)
}
static
void
Pmethod_dealloc
(
self
)
Pmethod
*
self
;
PMethod_dealloc
(
PMethod
*
self
)
{
Py_DECREF
(
self
->
type
);
Py_XDECREF
(
self
->
self
);
...
...
@@ -366,11 +466,7 @@ Pmethod_dealloc(self)
}
static
PyObject
*
call_pmethod
(
self
,
inst
,
args
,
kw
)
Pmethod
*
self
;
PyObject
*
inst
;
PyObject
*
args
;
PyObject
*
kw
;
call_PMethod
(
PMethod
*
self
,
PyObject
*
inst
,
PyObject
*
args
,
PyObject
*
kw
)
{
PyObject
*
a
;
...
...
@@ -381,16 +477,13 @@ call_pmethod(self, inst, args, kw)
}
static
PyObject
*
Pmethod_call
(
self
,
args
,
kw
)
Pmethod
*
self
;
PyObject
*
args
;
PyObject
*
kw
;
PMethod_call
(
PMethod
*
self
,
PyObject
*
args
,
PyObject
*
kw
)
{
int
size
;
char
*
buf
;
PyObject
*
s
;
if
(
self
->
self
)
return
call_
pm
ethod
(
self
,
self
->
self
,
args
,
kw
);
if
(
self
->
self
)
return
call_
PM
ethod
(
self
,
self
->
self
,
args
,
kw
);
if
((
size
=
PyTuple_Size
(
args
))
>
0
)
{
...
...
@@ -398,16 +491,16 @@ Pmethod_call(self,args,kw)
UNLESS
(
first
=
PyTuple_GET_ITEM
(
args
,
0
))
return
NULL
;
if
(
first
->
ob_type
==
self
->
type
||
(
first
->
ob_type
->
ob_type
==
(
PyTypeObject
*
)
&
CCLtype
(
PyExtensionInstance_Check
(
first
)
&&
CMethod_issubclass
(
(
PyExtensionClass
*
)(
first
->
ob_type
),
(
PyExtensionClass
*
)
(
self
->
type
))
CMethod_issubclass
(
PyExtensionClassOf
(
first
),
AsPyExtensionClass
(
self
->
type
))
)
);
{
PyObject
*
rest
=
0
;
UNLESS
(
rest
=
PySequence_GetSlice
(
args
,
1
,
size
))
return
NULL
;
return
call_
pm
ethod
(
self
,
first
,
rest
,
kw
);
return
call_
PM
ethod
(
self
,
first
,
rest
,
kw
);
}
}
...
...
@@ -424,9 +517,7 @@ Pmethod_call(self,args,kw)
}
static
PyObject
*
Pmethod_getattr
(
self
,
name
)
Pmethod
*
self
;
char
*
name
;
PMethod_getattr
(
PMethod
*
self
,
char
*
name
)
{
PyObject
*
r
;
...
...
@@ -455,16 +546,16 @@ Pmethod_getattr(self,name)
}
}
static
PyTypeObject
P
m
ethodType
=
{
static
PyTypeObject
P
M
ethodType
=
{
PyObject_HEAD_INIT
(
&
PyType_Type
)
0
,
/*ob_size*/
"Python Method"
,
/*tp_name*/
sizeof
(
P
m
ethod
),
/*tp_basicsize*/
sizeof
(
P
M
ethod
),
/*tp_basicsize*/
0
,
/*tp_itemsize*/
/* methods */
(
destructor
)
P
m
ethod_dealloc
,
/*tp_dealloc*/
(
destructor
)
P
M
ethod_dealloc
,
/*tp_dealloc*/
(
printfunc
)
0
,
/*tp_print*/
(
getattrfunc
)
0
,
/*tp_getattr*/
(
getattrfunc
)
PMethod_getattr
,
/*tp_getattr*/
(
setattrfunc
)
0
,
/*tp_setattr*/
(
cmpfunc
)
0
,
/*tp_compare*/
(
reprfunc
)
0
,
/*tp_repr*/
...
...
@@ -472,7 +563,7 @@ static PyTypeObject PmethodType = {
0
,
/*tp_as_sequence*/
0
,
/*tp_as_mapping*/
(
hashfunc
)
0
,
/*tp_hash*/
(
ternaryfunc
)
P
m
ethod_call
,
/*tp_call*/
(
ternaryfunc
)
P
M
ethod_call
,
/*tp_call*/
(
reprfunc
)
0
,
/*tp_str*/
/* Space for future expansion */
...
...
@@ -537,6 +628,28 @@ setattr_by_name(PyObject *self, PyObject *args)
return
Py_None
;
}
#if PYTHON_API_VERSION >= 1005
static
PyObject
*
getattro_by_name
(
PyObject
*
self
,
PyObject
*
args
)
{
PyObject
*
name
;
UNLESS
(
PyArg_Parse
(
args
,
"O"
,
&
name
))
return
NULL
;
return
self
->
ob_type
->
tp_getattro
(
self
,
name
);
}
static
PyObject
*
setattro_by_name
(
PyObject
*
self
,
PyObject
*
args
)
{
PyObject
*
name
;
PyObject
*
v
;
UNLESS
(
PyArg_Parse
(
args
,
"OO"
,
&
name
,
&
v
))
return
NULL
;
UNLESS
(
-
1
!=
self
->
ob_type
->
tp_setattro
(
self
,
name
,
v
))
return
NULL
;
Py_INCREF
(
Py_None
);
return
Py_None
;
}
#endif
static
PyObject
*
length_by_name
(
PyObject
*
self
,
PyObject
*
args
)
...
...
@@ -725,6 +838,12 @@ getBaseDictionary(PyExtensionClass *type)
FILLENTRY
(
type
->
tp
,
compare
,
comp
,
0
,
"compare with another object"
);
FILLENTRY
(
type
->
tp
,
getattr
,
getattr
,
0
,
"Get an attribute"
);
FILLENTRY
(
type
->
tp
,
setattr
,
setattr
,
0
,
"Set an attribute"
);
#if PYTHON_API_VERSION >= 1005
FILLENTRY
(
type
->
tp
,
getattro
,
getattr
,
0
,
"Get an attribute"
);
FILLENTRY
(
type
->
tp
,
setattro
,
setattr
,
0
,
"Set an attribute"
);
#endif
if
(
sm
=
type
->
tp_as_sequence
)
{
FILLENTRY
(
sm
->
sq
,
length
,
len
,
0
,
"Get the object length"
);
...
...
@@ -837,8 +956,7 @@ initializeBaseExtensionClass(PyExtensionClass *self)
}
static
void
CCL_dealloc
(
self
)
PyExtensionClass
*
self
;
CCL_dealloc
(
PyExtensionClass
*
self
)
{
Py_XDECREF
(
self
->
class_dictionary
);
Py_XDECREF
(
self
->
bases
);
...
...
@@ -849,9 +967,8 @@ CCL_dealloc(self)
static
PyObject
*
CCL_getattr
();
static
PyObject
*
ExtensionClass_FindInstanceAttribute
(
inst
,
name
)
PyObject
*
inst
;
char
*
name
;
ExtensionClass_FindInstanceAttribute
(
PyObject
*
inst
,
PyObject
*
oname
,
char
*
name
)
{
/* Look up an attribute for an instance from:
...
...
@@ -862,6 +979,8 @@ ExtensionClass_FindInstanceAttribute(inst,name)
PyObject
*
r
=
0
;
PyExtensionClass
*
self
;
if
(
!
name
)
return
NULL
;
self
=
(
PyExtensionClass
*
)(
inst
->
ob_type
);
if
(
*
name
==
'_'
&&
name
[
1
]
==
'_'
)
...
...
@@ -882,25 +1001,25 @@ ExtensionClass_FindInstanceAttribute(inst,name)
if
(
self
->
bases
)
{
r
=
INSTANCE_DICT
(
inst
);
r
=
Py
Mapping_GetItemString
(
r
,
name
);
r
=
Py
Object_GetItem
(
r
,
o
name
);
}
UNLESS
(
r
)
{
PyErr_Clear
();
UNLESS
(
r
=
CCL_getattr
(
self
,
name
))
return
NULL
;
UNLESS
(
r
=
CCL_getattr
(
self
,
oname
,
name
))
return
NULL
;
/* We got something from our class, maybe its an unbound method. */
if
(
r
->
ob_type
==&
CMethodType
)
if
(
UnboundCMethod_Check
(
r
)
)
{
UNLESS_ASSIGN
(
r
,(
PyObject
*
)
bindCMethod
((
CMethod
*
)
r
,
inst
))
return
NULL
;
}
if
(
r
->
ob_type
==&
PmethodType
)
else
if
(
UnboundPMethod_Check
(
r
)
)
{
PyObject
*
m
;
m
=
((
P
m
ethod
*
)
r
)
->
meth
;
if
(
m
->
ob_type
->
ob_type
==
(
PyTypeObject
*
)
&
CCLtype
&&
(
((
PyExtensionClass
*
)
m
->
ob_type
)
->
class_flags
&
m
=
((
P
M
ethod
*
)
r
)
->
meth
;
if
(
PyExtensionInstance_Check
(
m
)
&&
(
PyExtensionClassOf
(
m
)
->
class_flags
&
EXTENSIONCLASS_BINDABLE_FLAG
)
)
...
...
@@ -911,7 +1030,7 @@ ExtensionClass_FindInstanceAttribute(inst,name)
}
else
{
UNLESS_ASSIGN
(
r
,(
PyObject
*
)
bindP
method
((
Pm
ethod
*
)
r
,
inst
))
UNLESS_ASSIGN
(
r
,(
PyObject
*
)
bindP
Method
((
PM
ethod
*
)
r
,
inst
))
return
NULL
;
}
}
...
...
@@ -921,19 +1040,47 @@ ExtensionClass_FindInstanceAttribute(inst,name)
}
static
PyObject
*
CCL_getattr
(
self
,
name
)
PyExtensionClass
*
self
;
char
*
name
;
EC_findiattrs
(
PyObject
*
self
,
char
*
name
)
{
PyObject
*
s
,
*
r
;
UNLESS
(
s
=
PyString_FromString
(
name
))
return
NULL
;
r
=
ExtensionClass_FindInstanceAttribute
(
self
,
s
,
name
);
Py_DECREF
(
s
);
return
r
;
}
static
PyObject
*
EC_findiattro
(
PyObject
*
self
,
PyObject
*
name
)
{
return
ExtensionClass_FindInstanceAttribute
(
self
,
name
,
PyString_AsString
(
name
));
}
static
int
subclass_simple_setattr
(
PyObject
*
self
,
char
*
name
,
PyObject
*
v
);
static
PyObject
*
CCL_getattr
(
PyExtensionClass
*
self
,
PyObject
*
oname
,
char
*
name
)
{
PyObject
*
r
;
int
local
=
1
;
char
*
n
;
if
(
*
name
==
'.'
&&
name
[
1
]
==
0
)
return
(
PyObject
*
)
ExtensionClass_FindInstanceAttribute
;
if
(
!
name
)
return
NULL
;
if
(
*
name
==
'.'
)
{
n
=
name
+
1
;
if
(
*
n
==
0
)
return
(
PyObject
*
)
EC_findiattrs
;
if
(
*
n
==
'o'
&&
n
[
1
]
==
0
)
return
(
PyObject
*
)
EC_findiattro
;
if
(
*
n
==
's'
&&
n
[
1
]
==
0
)
return
(
PyObject
*
)
subclass_simple_setattr
;
}
if
(
*
name
==
'_'
&&
name
[
1
]
==
'_'
)
{
char
*
n
;
n
=
name
+
2
;
if
(
strcmp
(
n
,
"doc__"
)
==
0
&&
self
->
tp_doc
)
return
PyString_FromString
(
self
->
tp_doc
);
...
...
@@ -956,7 +1103,7 @@ CCL_getattr(self, name)
}
}
r
=
Py
Mapping_GetItemString
(
self
->
class_dictionary
,
name
);
r
=
Py
Object_GetItem
(
self
->
class_dictionary
,
o
name
);
UNLESS
(
r
)
{
local
=
0
;
...
...
@@ -970,7 +1117,7 @@ CCL_getattr(self, name)
{
PyErr_Clear
();
c
=
PyTuple_GET_ITEM
(
self
->
bases
,
i
);
if
(
r
=
PyObject_GetAttr
String
(
c
,
name
))
break
;
if
(
r
=
PyObject_GetAttr
(
c
,
o
name
))
break
;
}
}
UNLESS
(
r
)
...
...
@@ -979,9 +1126,7 @@ CCL_getattr(self, name)
char
*
s
;
PyErr_Fetch
(
&
t
,
&
v
,
&
tb
);
if
(
t
==
PyExc_KeyError
&&
PyString_Check
(
v
)
&&
(
s
=
PyString_AsString
(
v
))
&&
strcmp
(
s
,
name
)
==
0
)
if
(
t
==
PyExc_KeyError
&&
PyObject_Compare
(
v
,
oname
)
==
0
)
{
Py_DECREF
(
t
);
t
=
PyExc_AttributeError
;
...
...
@@ -993,25 +1138,46 @@ CCL_getattr(self, name)
}
if
(
PyFunction_Check
(
r
)
||
(
r
->
ob_type
->
ob_type
==
(
PyTypeObject
*
)
&
CCLtype
&&
(
((
PyExtensionClass
*
)
r
->
ob_type
)
->
class_flags
&
(
PyExtensionInstance_Check
(
r
)
&&
(
PyExtensionClassOf
(
r
)
->
class_flags
&
EXTENSIONCLASS_BINDABLE_FLAG
)
)
)
UNLESS_ASSIGN
(
r
,(
PyObject
*
)
newPmethod
((
PyTypeObject
*
)
self
,
r
))
{
UNLESS_ASSIGN
(
r
,(
PyObject
*
)
newPMethod
((
PyTypeObject
*
)
self
,
r
))
return
NULL
;
if
(
PyMethod_Check
(
r
)
&&
!
PyMethod_Self
(
r
))
UNLESS_ASSIGN
(
r
,(
PyObject
*
)
newPmethod
((
PyTypeObject
*
)
self
,
}
else
if
(
PyMethod_Check
(
r
)
&&
!
PyMethod_Self
(
r
))
{
UNLESS_ASSIGN
(
r
,(
PyObject
*
)
newPMethod
((
PyTypeObject
*
)
self
,
PyMethod_Function
(
r
)))
return
NULL
;
}
else
local
=
0
;
if
(
local
)
/* We have a PMethod that we built from our dict, cache it */
{
UNLESS
(
-
1
!=
PyObject_SetItem
(
self
->
class_dictionary
,
oname
,
r
))
PyErr_Clear
();
/* Oh well */
}
return
r
;
}
PyObject
*
CCL_getattrs
(
PyExtensionClass
*
self
,
char
*
name
)
{
PyObject
*
s
,
*
r
;
UNLESS
(
s
=
PyString_FromString
(
name
))
return
NULL
;
r
=
CCL_getattr
(
self
,
s
,
name
);
Py_DECREF
(
s
);
return
r
;
}
static
int
CCL_setattr
(
self
,
name
,
v
)
CCL_setattr
s
(
self
,
name
,
v
)
PyExtensionClass
*
self
;
char
*
name
;
PyObject
*
v
;
...
...
@@ -1019,10 +1185,138 @@ CCL_setattr(self, name, v)
return
PyMapping_SetItemString
(
self
->
class_dictionary
,
name
,
v
);
}
PyObject
*
CCL_getattro
(
PyExtensionClass
*
self
,
PyObject
*
name
)
{
return
CCL_getattr
(
self
,
name
,
PyString_AsString
(
name
));
}
static
int
CCL_setattro
(
PyExtensionClass
*
self
,
PyObject
*
name
,
PyObject
*
v
)
{
if
(
UnboundCMethod_Check
(
v
))
{
char
*
n
;
PyNumberMethods
*
nm
;
PySequenceMethods
*
s
,
*
ms
;
PyMappingMethods
*
m
,
*
mm
;
UNLESS
(
n
=
PyString_AsString
(
name
))
return
-
1
;
if
(
*
n
==
'_'
&&
n
[
1
]
==
'_'
)
{
n
+=
2
;
#define SET_SPECIAL(C,P) \
if(strcmp(n,#P "__")==0 \
&& AsCMethod(v)->meth==(PyCFunction)C ## _by_name \
&& Subclass_Check(self,AsCMethod(v)->type)) { \
self->tp_ ## C=AsCMethod(v)->type->tp_ ## C; \
return PyObject_SetItem(self->class_dictionary, name, v); }
/*
SET_SPECIAL(setattr,setattr);
SET_SPECIAL(setattro,setattr);
*/
SET_SPECIAL
(
compare
,
cmp
);
SET_SPECIAL
(
hash
,
hash
);
SET_SPECIAL
(
repr
,
repr
);
SET_SPECIAL
(
call
,
call
);
SET_SPECIAL
(
str
,
str
);
#undef SET_SPECIAL
#define SET_SPECIAL(C,P) \
if(strcmp(n,#P "__")==0 && AsCMethod(v)->meth==C ## _by_name \
&& Subclass_Check(self,AsCMethod(v)->type) \
&& (nm=self->tp_as_number)) { \
nm->nb_ ## C=AsCMethod(v)->type->tp_as_number->nb_ ## C; \
return PyObject_SetItem(self->class_dictionary, name, v); }
SET_SPECIAL
(
add
,
add
);
SET_SPECIAL
(
subtract
,
sub
);
SET_SPECIAL
(
multiply
,
mult
);
SET_SPECIAL
(
divide
,
div
);
SET_SPECIAL
(
remainder
,
mod
);
SET_SPECIAL
(
power
,
pow
);
SET_SPECIAL
(
divmod
,
divmod
);
SET_SPECIAL
(
lshift
,
lshift
);
SET_SPECIAL
(
rshift
,
rshift
);
SET_SPECIAL
(
and
,
and
);
SET_SPECIAL
(
or
,
or
);
SET_SPECIAL
(
xor
,
xor
);
SET_SPECIAL
(
coerce
,
coerce
);
SET_SPECIAL
(
negative
,
neg
);
SET_SPECIAL
(
positive
,
pos
);
SET_SPECIAL
(
absolute
,
abs
);
SET_SPECIAL
(
nonzero
,
nonzero
);
SET_SPECIAL
(
invert
,
inv
);
SET_SPECIAL
(
int
,
int
);
SET_SPECIAL
(
long
,
long
);
SET_SPECIAL
(
float
,
float
);
SET_SPECIAL
(
oct
,
oct
);
SET_SPECIAL
(
hex
,
hex
);
#undef SET_SPECIAL
if
(
strcmp
(
n
,
"len__"
)
==
0
&&
AsCMethod
(
v
)
->
meth
==
length_by_name
&&
Subclass_Check
(
self
,
AsCMethod
(
v
)
->
type
))
{
if
((
s
=
self
->
tp_as_sequence
)
&&
(
ms
=
AsCMethod
(
v
)
->
type
->
tp_as_sequence
)
&&
ms
->
sq_length
)
s
->
sq_length
=
ms
->
sq_length
;
if
((
m
=
self
->
tp_as_mapping
)
&&
(
mm
=
AsCMethod
(
v
)
->
type
->
tp_as_mapping
)
&&
mm
->
mp_length
)
m
->
mp_length
=
mm
->
mp_length
;
return
PyObject_SetItem
(
self
->
class_dictionary
,
name
,
v
);
}
if
(
strcmp
(
n
,
"getitem__"
)
==
0
&&
AsCMethod
(
v
)
->
meth
==
getitem_by_name
&&
Subclass_Check
(
self
,
AsCMethod
(
v
)
->
type
))
{
if
((
s
=
self
->
tp_as_sequence
)
&&
(
ms
=
AsCMethod
(
v
)
->
type
->
tp_as_sequence
)
&&
ms
->
sq_item
)
s
->
sq_item
=
ms
->
sq_item
;
if
((
m
=
self
->
tp_as_mapping
)
&&
(
mm
=
AsCMethod
(
v
)
->
type
->
tp_as_mapping
)
&&
mm
->
mp_subscript
)
m
->
mp_subscript
=
mm
->
mp_subscript
;
return
PyObject_SetItem
(
self
->
class_dictionary
,
name
,
v
);
}
if
(
strcmp
(
n
,
"setitem__"
)
==
0
&&
AsCMethod
(
v
)
->
meth
==
(
PyCFunction
)
setitem_by_name
&&
Subclass_Check
(
self
,
AsCMethod
(
v
)
->
type
))
{
if
((
s
=
self
->
tp_as_sequence
)
&&
(
ms
=
AsCMethod
(
v
)
->
type
->
tp_as_sequence
)
&&
ms
->
sq_ass_item
)
s
->
sq_ass_item
=
ms
->
sq_ass_item
;
if
((
m
=
self
->
tp_as_mapping
)
&&
(
mm
=
AsCMethod
(
v
)
->
type
->
tp_as_mapping
)
&&
mm
->
mp_ass_subscript
)
m
->
mp_ass_subscript
=
mm
->
mp_ass_subscript
;
return
PyObject_SetItem
(
self
->
class_dictionary
,
name
,
v
);
}
#define SET_SPECIAL(C,P) \
if(strcmp(n,#P "__")==0 \
&& AsCMethod(v)->meth==(PyCFunction)C ## _by_name \
&& Subclass_Check(self,AsCMethod(v)->type) \
&& (s=self->tp_as_sequence)) { \
s->sq_ ## C=AsCMethod(v)->type->tp_as_sequence->sq_ ## C; \
return PyObject_SetItem(self->class_dictionary, name, v); }
SET_SPECIAL
(
slice
,
getslice
);
SET_SPECIAL
(
ass_slice
,
setslice
);
SET_SPECIAL
(
concat
,
concat
);
SET_SPECIAL
(
repeat
,
repeat
);
#undef SET_SPECIAL
}
}
return
PyObject_SetItem
(
self
->
class_dictionary
,
name
,
v
);
}
static
PyObject
*
CCL_call
(
self
,
arg
,
kw
)
PyExtensionClass
*
self
;
PyObject
*
arg
,
*
kw
;
CCL_call
(
PyExtensionClass
*
self
,
PyObject
*
arg
,
PyObject
*
kw
)
{
PyObject
*
inst
=
0
,
*
init
=
0
,
*
args
=
0
;
int
check
;
...
...
@@ -1045,7 +1339,7 @@ CCL_call(self, arg, kw)
PyObject
*
var_size
;
int
size
;
if
(
var_size
=
CCL_getattr
(
self
,
"__var_size__"
))
if
(
var_size
=
CCL_getattr
o
(
self
,
py__var_size__
))
{
UNLESS_ASSIGN
(
var_size
,
PyObject_CallObject
(
var_size
,
args
))
return
NULL
;
...
...
@@ -1093,7 +1387,7 @@ CCL_call(self, arg, kw)
if
(
init
=
CCL_getattr
(
self
,
"__init__"
))
if
(
init
=
CCL_getattr
o
(
self
,
py__init__
))
{
UNLESS
(
args
=
Py_BuildValue
(
"(O)"
,
inst
))
goto
err
;
if
(
arg
)
UNLESS_ASSIGN
(
args
,
PySequence_Concat
(
args
,
arg
))
goto
err
;
...
...
@@ -1113,8 +1407,7 @@ err:
}
static
PyObject
*
CCL_repr
(
self
)
PyExtensionClass
*
self
;
CCL_repr
(
PyExtensionClass
*
self
)
{
PyObject
*
s
;
int
l
;
...
...
@@ -1124,7 +1417,7 @@ CCL_repr(self)
l
=
strlen
(
self
->
ob_type
->
tp_name
)
+
strlen
(
p
);
UNLESS
(
s
=
PyString_FromStringAndSize
(
NULL
,
l
+
22
))
return
NULL
;
buf
=
PyString_AsString
(
s
);
sprintf
(
buf
,
"<extension class %s at %p>"
,
self
->
tp_name
);
sprintf
(
buf
,
"<extension class %s at %p>"
,
self
->
tp_name
,
self
);
return
s
;
}
...
...
@@ -1137,8 +1430,8 @@ static PyTypeObject CCLtype_class = {
/* methods */
(
destructor
)
CCL_dealloc
,
/*tp_dealloc*/
(
printfunc
)
0
,
/*tp_print*/
(
getattrfunc
)
CCL_getattr
,
/*tp_getattr*/
(
setattrfunc
)
CCL_setattr
,
/*tp_setattr*/
(
getattrfunc
)
CCL_getattr
s
,
/*tp_getattr*/
(
setattrfunc
)
CCL_setattr
s
,
/*tp_setattr*/
(
cmpfunc
)
0
,
/*tp_compare*/
(
reprfunc
)
CCL_repr
,
/*tp_repr*/
0
,
/*tp_as_number*/
...
...
@@ -1147,9 +1440,14 @@ static PyTypeObject CCLtype_class = {
(
hashfunc
)
0
,
/*tp_hash*/
(
ternaryfunc
)
CCL_call
,
/*tp_call*/
(
reprfunc
)
0
,
/*tp_str*/
#if PYTHON_API_VERSION >= 1005
(
getattrofunc
)
CCL_getattro
,
/*tp_getattr with object key*/
(
setattrofunc
)
CCL_setattro
,
/*tp_setattr with object key*/
#else
/* Space for future expansion */
0L
,
0L
,
0L
,
0L
,
0L
,
0L
,
#endif
0L
,
0L
,
"Class of C classes"
/* Documentation string */
};
...
...
@@ -1158,20 +1456,90 @@ static PyTypeObject CCLtype_class = {
/* subclassing code: */
static
PyObject
*
subclass_getspecial
(
PyObject
*
inst
,
PyObject
*
oname
)
{
PyObject
*
r
=
0
;
PyExtensionClass
*
self
;
self
=
(
PyExtensionClass
*
)(
inst
->
ob_type
);
r
=
INSTANCE_DICT
(
inst
);
r
=
PyObject_GetItem
(
r
,
oname
);
UNLESS
(
r
)
{
PyErr_Clear
();
r
=
CCL_getattr
(
self
,
oname
,
""
);
}
return
r
;
}
static
PyObject
*
subclass_getattro
(
PyObject
*
self
,
PyObject
*
name
)
{
PyObject
*
r
=
0
;
if
(
!
name
)
return
NULL
;
UNLESS
(
r
=
EC_findiattro
(
self
,
name
))
{
PyErr_Clear
();
UNLESS
(
r
=
EC_findiattro
(
self
,
py__getattr__
))
return
NULL
;
UNLESS_ASSIGN
(
r
,
PyObject_CallFunction
(
r
,
"O"
,
name
))
return
NULL
;
}
return
r
;
}
static
PyObject
*
subclass_getattrs
(
PyObject
*
self
,
char
*
name
)
{
return
subclass_getattro
(
self
,
PyString_FromString
(
name
));
}
static
int
subclass_setattr
(
PyObject
*
self
,
char
*
name
,
PyObject
*
v
)
subclass_simple_setattro
(
PyObject
*
self
,
PyObject
*
name
,
PyObject
*
v
)
{
Py_INCREF
(
v
);
return
PyDict_SetItem
(
INSTANCE_DICT
(
self
),
name
,
v
);
}
static
int
subclass_simple_setattr
(
PyObject
*
self
,
char
*
name
,
PyObject
*
v
)
{
Py_INCREF
(
v
);
return
PyDict_SetItemString
(
INSTANCE_DICT
(
self
),
name
,
v
);
}
static
int
subclass_setattr
(
PyObject
*
self
,
PyObject
*
oname
,
char
*
name
,
PyObject
*
v
)
{
PyObject
*
m
=
0
,
*
et
,
*
ev
,
*
etb
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__setattr__"
))
if
(
!
name
)
return
-
1
;
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__setattr__
))
goto
default_setattr
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
setattr_by_name
)
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
setattr_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS
(
-
1
!=
((
CMethod
*
)
m
)
->
type
->
tp_setattr
(
self
,
name
,
v
))
UNLESS
(
-
1
!=
AsCMethod
(
m
)
->
type
->
tp_setattr
(
self
,
name
,
v
))
goto
dictionary_setattr
;
return
0
;
}
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"sO"
,
name
,
v
))
return
-
1
;
#if PYTHON_API_VERSION >= 1005
else
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
setattro_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS
(
-
1
!=
AsCMethod
(
m
)
->
type
->
tp_setattro
(
self
,
oname
,
v
))
goto
dictionary_setattr
;
return
0
;
}
#endif
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"OOO"
,
self
,
oname
,
v
))
return
-
1
;
}
else
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"OO"
,
oname
,
v
))
return
-
1
;
Py_DECREF
(
m
);
return
0
;
...
...
@@ -1203,24 +1571,46 @@ default_setattr:
PyErr_Clear
();
UNLESS
(
-
1
!=
PyMapping_SetItemString
(
INSTANCE_DICT
(
self
),
name
,
v
))
return
-
1
;
return
subclass_simple_setattro
(
self
,
oname
,
v
);
}
return
0
;
static
int
subclass_setattrs
(
PyObject
*
self
,
char
*
name
,
PyObject
*
v
)
{
PyObject
*
s
;
int
r
;
UNLESS
(
s
=
PyString_FromString
(
name
))
return
-
1
;
r
=
subclass_setattr
(
self
,
s
,
name
,
v
);
Py_DECREF
(
s
);
return
r
;
}
static
int
subclass_setattro
(
PyObject
*
self
,
PyObject
*
name
,
PyObject
*
v
)
{
return
subclass_setattr
(
self
,
name
,
PyString_AsString
(
name
),
v
);
}
static
int
subclass_compare
(
PyObject
*
self
,
PyObject
*
v
)
{
PyObject
*
m
;
long
r
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__cmp__"
))
return
-
1
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
compare_by_name
)
r
=
((
CMethod
*
)
m
)
->
type
->
tp_compare
(
self
,
v
);
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__cmp__
))
return
-
1
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
compare_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
r
=
AsCMethod
(
m
)
->
type
->
tp_compare
(
self
,
v
);
else
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"O"
,
v
))
return
-
1
;
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"OO"
,
self
,
v
))
return
-
1
;
}
else
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"O"
,
v
))
return
-
1
;
r
=
PyInt_AsLong
(
m
);
}
Py_DECREF
(
m
);
...
...
@@ -1233,12 +1623,18 @@ subclass_hash(PyObject *self)
PyObject
*
m
;
long
r
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__hash__"
))
return
-
1
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
hash_by_name
)
r
=
((
CMethod
*
)
m
)
->
type
->
tp_hash
(
self
);
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__hash__
))
return
-
1
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
hash_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
r
=
AsCMethod
(
m
)
->
type
->
tp_hash
(
self
);
else
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
""
))
return
-
1
;
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"O"
,
self
))
return
-
1
;
}
else
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
""
))
return
-
1
;
r
=
PyInt_AsLong
(
m
);
}
Py_DECREF
(
m
);
...
...
@@ -1250,7 +1646,7 @@ subclass_repr(PyObject *self)
{
PyObject
*
m
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__repr__"
))
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__repr__
))
{
int
l
;
char
*
buf
,
p
[
64
];
...
...
@@ -1263,13 +1659,19 @@ subclass_repr(PyObject *self)
sprintf
(
buf
,
"<%s instance at %s>"
,
self
->
ob_type
->
tp_name
,
p
);
return
m
;
}
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
repr_by_name
)
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
repr_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS_ASSIGN
(
m
,
((
CMethod
*
)
m
)
->
type
->
tp_repr
(
self
))
return
NULL
;
UNLESS_ASSIGN
(
m
,
AsCMethod
(
m
)
->
type
->
tp_repr
(
self
))
return
NULL
;
}
else
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
""
))
return
NULL
;
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"O"
,
self
))
return
NULL
;
}
else
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
""
))
return
NULL
;
}
return
m
;
}
...
...
@@ -1277,18 +1679,29 @@ subclass_repr(PyObject *self)
static
PyObject
*
subclass_call
(
PyObject
*
self
,
PyObject
*
args
,
PyObject
*
kw
)
{
PyObject
*
m
;
PyObject
*
m
,
*
a
=
0
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__call__"
))
return
NULL
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
(
PyCFunction
)
call_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__call__
))
return
NULL
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
(
PyCFunction
)
call_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS_ASSIGN
(
m
,
((
CMethod
*
)
m
)
->
type
->
tp_call
(
self
,
args
,
kw
))
return
NULL
;
UNLESS_ASSIGN
(
m
,
AsCMethod
(
m
)
->
type
->
tp_call
(
self
,
args
,
kw
))
return
NULL
;
}
else
{
UNLESS_ASSIGN
(
m
,
PyEval_CallObjectWithKeywords
(
m
,
args
,
kw
))
return
NULL
;
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS
(
a
=
Py_BuildValue
(
"(O)"
,
self
))
goto
err
;
UNLESS_ASSIGN
(
a
,
PySequence_Concat
(
a
,
args
))
goto
err
;
args
=
a
;
}
UNLESS_ASSIGN
(
m
,
PyEval_CallObjectWithKeywords
(
m
,
args
,
kw
))
goto
err
;
}
Py_XDECREF
(
a
);
return
m
;
err:
Py_XDECREF
(
m
);
Py_XDECREF
(
a
);
}
static
PyObject
*
...
...
@@ -1296,18 +1709,24 @@ subclass_str(PyObject *self)
{
PyObject
*
m
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__str__"
))
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__str__
))
{
PyErr_Clear
();
return
subclass_repr
(
self
);
}
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
str_by_name
)
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
str_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS_ASSIGN
(
m
,
((
CMethod
*
)
m
)
->
type
->
tp_str
(
self
))
return
NULL
;
UNLESS_ASSIGN
(
m
,
AsCMethod
(
m
)
->
type
->
tp_str
(
self
))
return
NULL
;
}
else
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
""
))
return
NULL
;
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"O"
,
self
))
return
NULL
;
}
else
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
""
))
return
NULL
;
}
return
m
;
}
...
...
@@ -1317,15 +1736,21 @@ static PyObject * \
subclass_ ## M(PyObject *self, PyObject *v) \
{ \
PyObject *m; \
UNLESS(m=PyObject_GetAttrString(self,"__" # M "__")) return NULL; \
if(m->ob_type==&CMethodType && ((CMethod*)m)->meth==M ## _by_name) \
UNLESS(m=subclass_getspecial(self,py__ ## N ## __)) return NULL; \
if(UnboundCMethod_Check(m) && AsCMethod(m)->meth==M ## _by_name \
&& SubclassInstance_Check(self,AsCMethod(m)->type)) \
{ \
UNLESS_ASSIGN(m,PyNumber_ ## A(self,v)) \
return NULL; \
} \
else \
{ \
UNLESS_ASSIGN(m,PyObject_CallFunction(m,"O",v)) return NULL; \
if(UnboundEMethod_Check(m)) \
{ \
UNLESS_ASSIGN(m,PyObject_CallFunction(m,"OO",self,v)) \
return NULL; \
} \
else UNLESS_ASSIGN(m,PyObject_CallFunction(m,"O",v)) return NULL; \
} \
return m; \
}
...
...
@@ -1340,15 +1765,21 @@ static PyObject *
subclass_power
(
PyObject
*
self
,
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
m
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__pow__"
))
return
NULL
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
power_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__pow__
))
return
NULL
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
power_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS_ASSIGN
(
m
,
((
CMethod
*
)
m
)
->
type
->
tp_as_number
->
nb_power
(
self
,
v
,
w
))
UNLESS_ASSIGN
(
m
,
AsCMethod
(
m
)
->
type
->
tp_as_number
->
nb_power
(
self
,
v
,
w
))
return
NULL
;
}
else
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"OO"
,
v
,
w
))
return
NULL
;
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"OOO"
,
self
,
v
,
w
))
return
NULL
;
}
else
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"OO"
,
v
,
w
))
return
NULL
;
}
return
m
;
}
...
...
@@ -1368,12 +1799,18 @@ subclass_coerce(PyObject **self, PyObject **v)
PyObject
*
m
;
int
r
;
UNLESS
(
m
=
PyObject_GetAttrString
(
*
self
,
"__coerce__"
))
return
-
1
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
coerce_by_name
)
r
=
((
CMethod
*
)
m
)
->
type
->
tp_as_number
->
nb_coerce
(
self
,
v
);
UNLESS
(
m
=
subclass_getspecial
(
*
self
,
py__coerce__
))
return
-
1
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
coerce_by_name
&&
SubclassInstance_Check
(
*
self
,
AsCMethod
(
m
)
->
type
))
r
=
AsCMethod
(
m
)
->
type
->
tp_as_number
->
nb_coerce
(
self
,
v
);
else
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"OO"
,
*
self
,
*
v
))
return
-
1
;
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"OO"
,
*
self
,
v
))
return
NULL
;
}
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"O"
,
*
v
))
return
-
1
;
if
(
m
==
Py_None
)
r
=-
1
;
else
{
...
...
@@ -1392,15 +1829,21 @@ static PyObject * \
subclass_ ## M(PyObject *self) \
{ \
PyObject *m; \
UNLESS(m=PyObject_GetAttrString(self,"__" # M "__")) return NULL; \
if(m->ob_type==&CMethodType && ((CMethod*)m)->meth==M ## _by_name) \
UNLESS(m=subclass_getspecial(self,py__ ## N ## __)) return NULL; \
if(UnboundCMethod_Check(m) && AsCMethod(m)->meth==M ## _by_name \
&& SubclassInstance_Check(self,AsCMethod(m)->type)) \
{ \
UNLESS_ASSIGN(m,
((CMethod*)
m)->type->tp_as_number->nb_ ## M(self)) \
UNLESS_ASSIGN(m,
AsCMethod(
m)->type->tp_as_number->nb_ ## M(self)) \
return NULL; \
} \
else \
{ \
UNLESS_ASSIGN(m,PyObject_CallFunction(m,"O")) return NULL; \
if(UnboundEMethod_Check(m)) \
{ \
UNLESS_ASSIGN(m,PyObject_CallFunction(m,"O",self)) \
return NULL; \
} \
else UNLESS_ASSIGN(m,PyObject_CallFunction(m,"")) return NULL; \
} \
return m; \
}
...
...
@@ -1415,12 +1858,18 @@ subclass_nonzero(PyObject *self)
PyObject
*
m
;
long
r
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__nonzero__"
))
return
-
1
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
nonzero_by_name
)
r
=
((
CMethod
*
)
m
)
->
type
->
tp_as_number
->
nb_nonzero
(
self
);
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__nonzero__
))
return
-
1
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
nonzero_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
r
=
AsCMethod
(
m
)
->
type
->
tp_as_number
->
nb_nonzero
(
self
);
else
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
""
))
return
-
1
;
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"O"
,
self
))
return
-
1
;
}
else
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
""
))
return
-
1
;
r
=
PyInt_AsLong
(
m
);
}
Py_DECREF
(
m
);
...
...
@@ -1471,10 +1920,11 @@ subclass_length(PyObject *self)
long
r
;
PyExtensionClass
*
t
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__len__"
))
return
-
1
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
length_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__len__
))
return
-
1
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
length_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
t
=
(
PyExtensionClass
*
)
((
CMethod
*
)
m
)
->
type
;
t
=
(
PyExtensionClass
*
)
AsCMethod
(
m
)
->
type
;
Py_DECREF
(
m
);
if
(
t
->
tp_as_sequence
)
return
t
->
tp_as_sequence
->
sq_length
(
self
);
...
...
@@ -1496,10 +1946,11 @@ subclass_item(PyObject *self, int index)
PyObject
*
m
;
PyExtensionClass
*
t
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__getitem__"
))
return
NULL
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
getitem_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__getitem__
))
return
NULL
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
getitem_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
t
=
(
PyExtensionClass
*
)
((
CMethod
*
)
m
)
->
type
;
t
=
(
PyExtensionClass
*
)
AsCMethod
(
m
)
->
type
;
if
(
t
->
tp_as_sequence
&&
t
->
tp_as_sequence
->
sq_item
)
{
Py_DECREF
(
m
);
...
...
@@ -1520,11 +1971,12 @@ subclass_ass_item(PyObject *self, int index, PyObject *v)
PyObject
*
m
;
PyExtensionClass
*
t
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__setitem__"
))
return
-
1
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
(
PyCFunction
)
setitem_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__setitem__
))
return
-
1
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
(
PyCFunction
)
setitem_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
t
=
(
PyExtensionClass
*
)
((
CMethod
*
)
m
)
->
type
;
t
=
(
PyExtensionClass
*
)
AsCMethod
(
m
)
->
type
;
if
(
t
->
tp_as_sequence
&&
t
->
tp_as_sequence
->
sq_ass_item
)
{
Py_DECREF
(
m
);
...
...
@@ -1545,10 +1997,11 @@ subclass_slice(PyObject *self, int i1, int i2)
{
PyObject
*
m
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__getslice__"
))
return
NULL
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
slice_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__getslice__
))
return
NULL
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
slice_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS_ASSIGN
(
m
,
((
CMethod
*
)
m
)
->
type
->
tp_as_sequence
->
sq_slice
(
self
,
i1
,
i2
))
UNLESS_ASSIGN
(
m
,
AsCMethod
(
m
)
->
type
->
tp_as_sequence
->
sq_slice
(
self
,
i1
,
i2
))
return
NULL
;
}
else
...
...
@@ -1564,10 +2017,11 @@ subclass_ass_slice(PyObject *self, int i1, int i2, PyObject *v)
PyObject
*
m
;
long
r
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__setslice__"
))
return
-
1
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
(
PyCFunction
)
ass_slice_by_name
)
r
=
((
CMethod
*
)
m
)
->
type
->
tp_as_sequence
->
sq_ass_slice
(
self
,
i1
,
i2
,
v
);
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__setslice__
))
return
-
1
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
(
PyCFunction
)
ass_slice_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
r
=
AsCMethod
(
m
)
->
type
->
tp_as_sequence
->
sq_ass_slice
(
self
,
i1
,
i2
,
v
);
else
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"iiO"
,
i1
,
i2
,
v
))
return
-
1
;
...
...
@@ -1582,21 +2036,22 @@ subclass_concat(PyObject *self, PyObject *v)
{
PyObject
*
m
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__concat__"
))
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__concat__
))
{
/* Maybe we should check for __add__ */
PyObject
*
am
;
PyErr_Clear
();
UNLESS
(
am
=
PyObject_GetAttrString
(
self
,
"__add__"
))
return
NULL
;
if
(
m
=
PyObject_GetAttrString
(
self
,
"__coerce__"
))
UNLESS
(
am
=
subclass_getspecial
(
self
,
py__add__
))
return
NULL
;
if
(
m
=
subclass_getspecial
(
self
,
py__coerce__
))
{
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
coerce_by_name
)
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
coerce_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
PyObject
*
x
,
*
y
;
x
=
self
;
y
=
v
;
if
(
0
==
((
CMethod
*
)
m
)
->
type
->
tp_as_number
->
nb_coerce
(
&
x
,
&
y
))
if
(
0
==
AsCMethod
(
m
)
->
type
->
tp_as_number
->
nb_coerce
(
&
x
,
&
y
))
{
Py_DECREF
(
am
);
if
(
x
->
ob_type
->
tp_as_number
)
...
...
@@ -1616,9 +2071,10 @@ subclass_concat(PyObject *self, PyObject *v)
"No __add__ or __concat__ methods, or maybe I'm just being stupid."
);
return
NULL
;
}
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
concat_by_name
)
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
concat_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS_ASSIGN
(
m
,
((
CMethod
*
)
m
)
->
type
->
tp_as_sequence
->
sq_concat
(
self
,
v
))
UNLESS_ASSIGN
(
m
,
AsCMethod
(
m
)
->
type
->
tp_as_sequence
->
sq_concat
(
self
,
v
))
return
NULL
;
}
else
...
...
@@ -1633,10 +2089,11 @@ subclass_repeat(PyObject *self, int v)
{
PyObject
*
m
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__repeat__"
))
return
NULL
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
repeat_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__repeat__
))
return
NULL
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
repeat_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS_ASSIGN
(
m
,
((
CMethod
*
)
m
)
->
type
->
tp_as_sequence
->
sq_repeat
(
self
,
v
))
UNLESS_ASSIGN
(
m
,
AsCMethod
(
m
)
->
type
->
tp_as_sequence
->
sq_repeat
(
self
,
v
))
return
NULL
;
}
else
...
...
@@ -1662,11 +2119,12 @@ subclass_subscript(PyObject *self, PyObject *key)
PyObject
*
m
;
PyExtensionClass
*
t
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__getitem__"
))
return
NULL
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
(
PyCFunction
)
getitem_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__getitem__
))
return
NULL
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
(
PyCFunction
)
getitem_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
t
=
(
PyExtensionClass
*
)
((
CMethod
*
)
m
)
->
type
;
t
=
(
PyExtensionClass
*
)
AsCMethod
(
m
)
->
type
;
if
(
t
->
tp_as_mapping
&&
t
->
tp_as_mapping
->
mp_subscript
)
{
Py_DECREF
(
m
);
...
...
@@ -1687,11 +2145,12 @@ subclass_ass_subscript(PyObject *self, PyObject *index, PyObject *v)
PyObject
*
m
;
PyExtensionClass
*
t
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__setitem__"
))
return
-
1
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
(
PyCFunction
)
setitem_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__setitem__
))
return
-
1
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
(
PyCFunction
)
setitem_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
t
=
(
PyExtensionClass
*
)
((
CMethod
*
)
m
)
->
type
;
t
=
(
PyExtensionClass
*
)
AsCMethod
(
m
)
->
type
;
if
(
t
->
tp_as_sequence
&&
t
->
tp_as_mapping
->
mp_ass_subscript
)
{
Py_DECREF
(
m
);
...
...
@@ -1723,11 +2182,11 @@ dealloc_base(PyObject *inst, PyExtensionClass* self)
for
(
i
=
0
;
i
<
l
;
i
++
)
{
t
=
PyTuple_GET_ITEM
(
self
->
bases
,
i
);
if
(
t
->
ob_type
==
(
PyTypeObject
*
)
&
CCLtype
)
if
(
PyExtensionClass_Check
(
t
)
)
{
if
(
((
PyExtensionClass
*
)
t
)
->
bases
)
if
(
AsPyExtensionClass
(
t
)
->
bases
)
{
if
(
dealloc_base
(
inst
,
(
PyExtensionClass
*
)
t
))
return
1
;
if
(
dealloc_base
(
inst
,
AsPyExtensionClass
(
t
)
))
return
1
;
}
else
{
...
...
@@ -1749,7 +2208,7 @@ subclass_dealloc(PyObject *self)
PyErr_Fetch
(
&
t
,
&
v
,
&
tb
);
if
(
m
=
PyObject_GetAttrString
(
self
,
"__del__"
))
if
(
m
=
subclass_getspecial
(
self
,
py__del__
))
PyObject_CallFunction
(
m
,
""
);
PyErr_Clear
();
...
...
@@ -1775,14 +2234,14 @@ datafull_baseclasses(PyExtensionClass *type)
for
(
i
=
0
;
i
<
l
;
i
++
)
{
base
=
PyTuple_GET_ITEM
(
type
->
bases
,
i
);
if
(
base
->
ob_type
==
(
PyTypeObject
*
)
&
CCLtype
)
if
(
PyExtensionClass_Check
(
base
)
)
{
if
(
((
PyExtensionClass
*
)
base
->
ob_typ
e
)
->
bases
)
n
+=
datafull_baseclasses
(
(
PyExtensionClass
*
)
base
);
if
(
AsPyExtensionClass
(
bas
e
)
->
bases
)
n
+=
datafull_baseclasses
(
AsPyExtensionClass
(
base
)
);
else
{
if
(
((
PyExtensionClass
*
)
base
)
->
tp_basicsize
>
sizeof
(
Dataless
)
||
((
PyExtensionClass
*
)
base
)
->
tp_itemsize
>
0
)
if
(
AsPyExtensionClass
(
base
)
->
tp_basicsize
>
sizeof
(
Dataless
)
||
AsPyExtensionClass
(
base
)
->
tp_itemsize
>
0
)
n
++
;
}
}
...
...
@@ -1803,17 +2262,17 @@ datafull_baseclass(PyExtensionClass *type)
for
(
i
=
0
;
i
<
l
;
i
++
)
{
base
=
PyTuple_GET_ITEM
(
type
->
bases
,
i
);
if
(
base
->
ob_type
==
(
PyTypeObject
*
)
&
CCLtype
)
if
(
PyExtensionClass_Check
(
base
)
)
{
if
(
((
PyExtensionClass
*
)
base
->
ob_typ
e
)
->
bases
)
if
(
AsPyExtensionClass
(
bas
e
)
->
bases
)
{
if
(
dbase
=
datafull_baseclass
(
(
PyExtensionClass
*
)
base
))
if
(
dbase
=
datafull_baseclass
(
AsPyExtensionClass
(
base
)
))
return
dbase
;
}
else
{
if
(
((
PyExtensionClass
*
)
base
)
->
tp_basicsize
>
sizeof
(
Dataless
)
||
((
PyExtensionClass
*
)
base
)
->
tp_itemsize
>
0
)
if
(
AsPyExtensionClass
(
base
)
->
tp_basicsize
>
sizeof
(
Dataless
)
||
AsPyExtensionClass
(
base
)
->
tp_itemsize
>
0
)
return
base
;
}
}
...
...
@@ -1822,11 +2281,11 @@ datafull_baseclass(PyExtensionClass *type)
}
static
int
subclass_hasattr
(
PyExtensionClass
*
type
,
char
*
name
)
subclass_hasattr
(
PyExtensionClass
*
type
,
PyObject
*
name
)
{
PyObject
*
o
;
if
(
o
=
CCL_getattr
(
type
,
name
))
if
(
o
=
CCL_getattr
o
(
type
,
name
))
{
Py_DECREF
(
o
);
return
1
;
...
...
@@ -1838,56 +2297,135 @@ subclass_hasattr(PyExtensionClass *type, char *name)
static
int
has_number_methods
(
PyExtensionClass
*
type
)
{
return
(
subclass_hasattr
(
type
,
"__add__"
)
||
subclass_hasattr
(
type
,
"__sub__"
)
||
subclass_hasattr
(
type
,
"__mul__"
)
||
subclass_hasattr
(
type
,
"__div__"
)
||
subclass_hasattr
(
type
,
"__mod__"
)
||
subclass_hasattr
(
type
,
"__pow__"
)
||
subclass_hasattr
(
type
,
"__divmod__"
)
||
subclass_hasattr
(
type
,
"__lshift__"
)
||
subclass_hasattr
(
type
,
"__rshift__"
)
||
subclass_hasattr
(
type
,
"__and__"
)
||
subclass_hasattr
(
type
,
"__or__"
)
||
subclass_hasattr
(
type
,
"__xor__"
)
||
subclass_hasattr
(
type
,
"__coerce__"
)
||
subclass_hasattr
(
type
,
"__neg__"
)
||
subclass_hasattr
(
type
,
"__pos__"
)
||
subclass_hasattr
(
type
,
"__abs__"
)
||
subclass_hasattr
(
type
,
"__nonzero__"
)
||
subclass_hasattr
(
type
,
"__inv__"
)
||
subclass_hasattr
(
type
,
"__int__"
)
||
subclass_hasattr
(
type
,
"__long__"
)
||
subclass_hasattr
(
type
,
"__float__"
)
||
subclass_hasattr
(
type
,
"__oct__"
)
||
subclass_hasattr
(
type
,
"__hex__"
)
return
(
subclass_hasattr
(
type
,
py__add__
)
||
subclass_hasattr
(
type
,
py__sub__
)
||
subclass_hasattr
(
type
,
py__mul__
)
||
subclass_hasattr
(
type
,
py__div__
)
||
subclass_hasattr
(
type
,
py__mod__
)
||
subclass_hasattr
(
type
,
py__pow__
)
||
subclass_hasattr
(
type
,
py__divmod__
)
||
subclass_hasattr
(
type
,
py__lshift__
)
||
subclass_hasattr
(
type
,
py__rshift__
)
||
subclass_hasattr
(
type
,
py__and__
)
||
subclass_hasattr
(
type
,
py__or__
)
||
subclass_hasattr
(
type
,
py__xor__
)
||
subclass_hasattr
(
type
,
py__coerce__
)
||
subclass_hasattr
(
type
,
py__neg__
)
||
subclass_hasattr
(
type
,
py__pos__
)
||
subclass_hasattr
(
type
,
py__abs__
)
||
subclass_hasattr
(
type
,
py__nonzero__
)
||
subclass_hasattr
(
type
,
py__inv__
)
||
subclass_hasattr
(
type
,
py__int__
)
||
subclass_hasattr
(
type
,
py__long__
)
||
subclass_hasattr
(
type
,
py__float__
)
||
subclass_hasattr
(
type
,
py__oct__
)
||
subclass_hasattr
(
type
,
py__hex__
)
);
}
static
int
has_collection_methods
(
PyExtensionClass
*
type
)
{
return
(
subclass_hasattr
(
type
,
"__getitem__"
)
||
subclass_hasattr
(
type
,
"__setitem__"
)
||
subclass_hasattr
(
type
,
"__getslice__"
)
||
subclass_hasattr
(
type
,
"__setslice__"
)
||
subclass_hasattr
(
type
,
"__concat__"
)
||
subclass_hasattr
(
type
,
"__repeat__"
)
||
subclass_hasattr
(
type
,
"__len__"
)
return
(
subclass_hasattr
(
type
,
py__getitem__
)
||
subclass_hasattr
(
type
,
py__setitem__
)
||
subclass_hasattr
(
type
,
py__getslice__
)
||
subclass_hasattr
(
type
,
py__setslice__
)
||
subclass_hasattr
(
type
,
py__concat__
)
||
subclass_hasattr
(
type
,
py__repeat__
)
||
subclass_hasattr
(
type
,
py__len__
)
);
}
static
void
subclass_init_getattr
(
PyExtensionClass
*
self
,
PyObject
*
methods
)
{
PyObject
*
m
;
if
((
m
=
CCL_getattr
(
self
,
py__getattr__
,
"__getattr__"
)))
{
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
getattr_by_name
&&
Subclass_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
self
->
tp_getattr
=
AsCMethod
(
m
)
->
type
->
tp_getattr
;
}
#if PYTHON_API_VERSION >= 1005
else
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
getattro_by_name
&&
Subclass_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
self
->
tp_getattro
=
AsCMethod
(
m
)
->
type
->
tp_getattro
;
}
#endif
else
{
PyDict_SetItem
(
methods
,
py__getattr__
,
m
);
#if PYTHON_API_VERSION >= 1005
self
->
tp_getattro
=
subclass_getattro
;
#else
self
->
tp_getattr
=
subclass_getattr
;
#endif
}
}
else
{
PyErr_Clear
();
#if PYTHON_API_VERSION >= 1005
self
->
tp_getattro
=
EC_findiattro
;
#else
self
->
tp_getattr
=
EC_findiattrs
;
#endif
}
}
static
void
subclass_init_setattr
(
PyExtensionClass
*
self
,
PyObject
*
methods
)
{
PyObject
*
m
;
if
((
m
=
CCL_getattr
(
self
,
py__setattr__
,
"__setattr__"
)))
{
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
setattr_by_name
&&
Subclass_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
self
->
tp_setattr
=
AsCMethod
(
m
)
->
type
->
tp_setattr
;
}
#if PYTHON_API_VERSION >= 1005
else
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
setattro_by_name
&&
Subclass_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
self
->
tp_setattro
=
AsCMethod
(
m
)
->
type
->
tp_setattro
;
}
#endif
else
{
PyDict_SetItem
(
methods
,
py__setattr__
,
m
);
#if PYTHON_API_VERSION >= 1005
self
->
tp_setattro
=
subclass_setattro
;
#else
self
->
tp_setattr
=
subclass_setattr
;
#endif
}
}
else
{
PyErr_Clear
();
#if PYTHON_API_VERSION >= 1005
self
->
tp_setattro
=
subclass_simple_setattro
;
#else
self
->
tp_setattro
=
subclass_simple_setattr
;
#endif
}
}
/* Constructor for building subclasses of C classes.
That is, we want to build a C class object that described a
subclass of a built-in type.
*/
static
PyObject
*
subclass__init__
(
self
,
args
)
PyExtensionClass
*
self
;
PyObject
*
args
;
subclass__init__
(
PyExtensionClass
*
self
,
PyObject
*
args
)
{
PyObject
*
bases
,
*
methods
;
PyObject
*
bases
,
*
methods
,
*
class_init
;
PyExtensionClass
*
type
;
char
*
name
;
int
dynamic
=
1
;
...
...
@@ -1932,9 +2470,10 @@ subclass__init__(self,args)
copy_member
(
tp_itemsize
);
copy_member
(
tp_print
);
copy_member
(
tp_getattr
);
self
->
tp_dealloc
=
subclass_dealloc
;
self
->
tp_setattr
=
subclass_setattr
;
subclass_init_getattr
(
self
,
methods
);
subclass_init_setattr
(
self
,
methods
);
#define subclass_set(OP,N) \
self->tp_ ##OP = subclass_ ##OP
...
...
@@ -1942,8 +2481,8 @@ subclass__init__(self,args)
subclass_set
(
compare
,
cmp
);
subclass_set
(
repr
,
repr
);
if
(
subclass_hasattr
(
self
,
"__bind_to_object__"
)
&&
subclass_hasattr
(
self
,
"__call__"
))
if
(
subclass_hasattr
(
self
,
py__bind_to_object__
)
&&
subclass_hasattr
(
self
,
py__call__
))
self
->
class_flags
|=
EXTENSIONCLASS_BINDABLE_FLAG
;
if
(
dynamic
||
has_number_methods
(
self
))
...
...
@@ -1965,6 +2504,19 @@ subclass__init__(self,args)
subclass_set
(
call
,
call
);
subclass_set
(
str
,
str
);
self
->
tp_doc
=
0
;
/* Check for and use __class_init__ */
if
(
class_init
=
PyObject_GetAttrString
(
AsPyObject
(
self
),
"__class_init__"
))
{
UNLESS_ASSIGN
(
class_init
,
PyObject_GetAttrString
(
class_init
,
"im_func"
))
return
NULL
;
UNLESS_ASSIGN
(
class_init
,
PyObject_CallFunction
(
class_init
,
"O"
,
self
))
return
NULL
;
Py_DECREF
(
class_init
);
}
else
PyErr_Clear
();
Py_INCREF
(
Py_None
);
return
Py_None
;
}
...
...
@@ -1985,8 +2537,8 @@ static PyExtensionClass CCLtype = {
/* methods */
(
destructor
)
CCL_dealloc
,
/*tp_dealloc*/
(
printfunc
)
0
,
/*tp_print*/
(
getattrfunc
)
CCL_getattr
,
/*tp_getattr*/
(
setattrfunc
)
CCL_setattr
,
/*tp_setattr*/
(
getattrfunc
)
CCL_getattr
s
,
/*tp_getattr*/
(
setattrfunc
)
CCL_setattr
s
,
/*tp_setattr*/
(
cmpfunc
)
0
,
/*tp_compare*/
(
reprfunc
)
CCL_repr
,
/*tp_repr*/
0
,
/*tp_as_number*/
...
...
@@ -1995,9 +2547,14 @@ static PyExtensionClass CCLtype = {
(
hashfunc
)
0
,
/*tp_hash*/
(
ternaryfunc
)
CCL_call
,
/*tp_call*/
(
reprfunc
)
0
,
/*tp_str*/
#if PYTHON_API_VERSION >= 1005
(
getattrofunc
)
CCL_getattro
,
/*tp_getattr with object key*/
(
setattrofunc
)
CCL_setattro
,
/*tp_setattr with object key*/
#else
/* Space for future expansion */
0L
,
0L
,
0L
,
0L
,
0L
,
0L
,
#endif
0L
,
0L
,
"C classes"
,
/* Documentation string */
METHOD_CHAIN
(
ExtensionClass_methods
)
};
...
...
@@ -2011,7 +2568,7 @@ static PyExtensionClass Basetype = {
/* methods */
(
destructor
)
0
,
/*tp_dealloc*/
(
printfunc
)
0
,
/*tp_print*/
(
getattrfunc
)
E
xtensionClass_FindInstanceAttribute
,
/*tp_getattr*/
(
getattrfunc
)
E
C_findiattrs
,
/*tp_getattr*/
(
setattrfunc
)
0
,
/*tp_setattr*/
(
cmpfunc
)
0
,
/*tp_compare*/
(
reprfunc
)
0
,
/*tp_repr*/
...
...
@@ -2021,9 +2578,14 @@ static PyExtensionClass Basetype = {
(
hashfunc
)
0
,
/*tp_hash*/
(
ternaryfunc
)
0
,
/*tp_call*/
(
reprfunc
)
0
,
/*tp_str*/
#if PYTHON_API_VERSION >= 1005
(
getattrofunc
)
EC_findiattro
,
/*tp_getattr with object key*/
(
setattrofunc
)
0
,
/*tp_setattr with object key*/
#else
/* Space for future expansion */
0L
,
0L
,
0L
,
0L
,
0L
,
0L
,
#endif
0L
,
0L
,
"Base -- a do nothing base class
\n
"
"
\n
"
"A trivial base class that doesn't have any inheritable
\n
"
...
...
@@ -2032,6 +2594,79 @@ static PyExtensionClass Basetype = {
{
NULL
,
NULL
}
};
static
PyObject
*
bind_to_object
(
PyObject
*
self
,
PyObject
*
args
)
{
PyObject
*
inst
;
PMethod
*
r
;
UNLESS
(
PyArg_Parse
(
args
,
"O"
,
&
inst
))
return
NULL
;
UNLESS
(
PyExtensionInstance_Check
(
inst
))
{
PyErr_SetString
(
PyExc_TypeError
,
"attempt to wrap extension method using an object that
\n
"
"is not an extension class instance."
);
return
NULL
;
}
UNLESS
(
r
=
PyObject_NEW
(
PMethod
,
&
PMethodType
))
return
NULL
;
Py_INCREF
(
inst
);
Py_INCREF
(
inst
->
ob_type
);
r
->
type
=
inst
->
ob_type
;
r
->
self
=
inst
;
r
->
meth
=
self
;
return
AsPyObject
(
r
);
}
struct
PyMethodDef
Method_methods
[]
=
{
{
"__bind_to_object__"
,(
PyCFunction
)
bind_to_object
,
0
,
""
},
{
NULL
,
NULL
}
/* sentinel */
};
static
PyExtensionClass
Methodtype
=
{
PyObject_HEAD_INIT
(
&
PyType_Type
)
0
,
/*ob_size*/
"Method"
,
/*tp_name*/
sizeof
(
Dataless
),
/*tp_basicsize*/
0
,
/*tp_itemsize*/
/* methods */
(
destructor
)
0
,
/*tp_dealloc*/
(
printfunc
)
0
,
/*tp_print*/
(
getattrfunc
)
EC_findiattrs
,
/*tp_getattr*/
(
setattrfunc
)
0
,
/*tp_setattr*/
(
cmpfunc
)
0
,
/*tp_compare*/
(
reprfunc
)
0
,
/*tp_repr*/
0
,
/*tp_as_number*/
0
,
/*tp_as_sequence*/
0
,
/*tp_as_mapping*/
(
hashfunc
)
0
,
/*tp_hash*/
(
ternaryfunc
)
0
,
/*tp_call*/
(
reprfunc
)
0
,
/*tp_str*/
#if PYTHON_API_VERSION >= 1005
(
getattrofunc
)
EC_findiattro
,
/*tp_getattr with object key*/
(
setattrofunc
)
0
,
/*tp_setattr with object key*/
#else
/* Space for future expansion */
0L
,
0L
,
#endif
0L
,
0L
,
"Base class for objects that want to be treated as methods
\n
"
"
\n
"
"The method class provides a method, __bind_to_object__, that
\n
"
"binds an object to an instance. If a method is a subobject
\n
"
"of an extension-class instance, the the method will be bound
\n
"
"to the instance and when the resulting object is called, it
\n
"
"will call the method and pass the instance in addition to
\n
"
"other arguments. It is the responsibility of Method objects
\n
"
"to implement (or inherit) a __call__ method.
\n
"
,
METHOD_CHAIN
(
Method_methods
)
};
PyObject
*
MetaTypeUndefinedMethod
()
...
...
@@ -2063,14 +2698,30 @@ initExtensionClass()
/* Add some symbolic constants to the module */
d
=
PyModule_GetDict
(
m
);
init_py_names
();
initializeBaseExtensionClass
(
&
CCLtype
);
PyDict_SetItemString
(
d
,
"ExtensionClassType"
,
(
PyObject
*
)
&
CCLtype
);
initializeBaseExtensionClass
(
&
Basetype
);
PyDict_SetItemString
(
d
,
"Base"
,
(
PyObject
*
)
&
Basetype
);
initializeBaseExtensionClass
(
&
Methodtype
);
PyDict_SetItemString
(
d
,
"Method"
,
(
PyObject
*
)
&
Methodtype
);
#ifdef Py_COBJECT_H
/* Export C attribute lookup API */
PyDict_SetItemString
(
d
,
"_PyEC_getattrs"
,
PyCObject_FromVoidPtr
(
EC_findiattrs
,
NULL
));
PyDict_SetItemString
(
d
,
"_PyEC_getattro"
,
PyCObject_FromVoidPtr
(
EC_findiattro
,
NULL
));
PyDict_SetItemString
(
d
,
"_PyEC_setattrs"
,
PyCObject_FromVoidPtr
(
subclass_simple_setattr
,
NULL
));
PyDict_SetItemString
(
d
,
"_PyEC_setattro"
,
PyCObject_FromVoidPtr
(
subclass_simple_setattro
,
NULL
));
#endif
/* Check for errors */
if
(
PyErr_Occurred
())
Py_FatalError
(
"can't initialize module ExtensionClass"
);
}
lib/Components/ExtensionClass/src/ExtensionClass.c
View file @
6cc20dbd
/*
$Id: ExtensionClass.c,v 1.
3 1996/10/24 21:07:4
9 jim Exp $
$Id: ExtensionClass.c,v 1.
4 1996/12/06 17:12:2
9 jim Exp $
Extension Class
...
...
@@ -56,6 +56,10 @@
(540) 371-6909
$Log: ExtensionClass.c,v $
Revision 1.4 1996/12/06 17:12:29 jim
Major speed enhancements for attribute lookup and calling special
methods.
Revision 1.3 1996/10/24 21:07:49 jim
Fixed bug in returning __bases__ for base classes.
Added missing PyErr_Clear() call.
...
...
@@ -84,7 +88,7 @@ static char ExtensionClass_module_documentation[] =
" - They provide access to unbound methods,
\n
"
" - They can be called to create instances.
\n
"
"
\n
"
"$Id: ExtensionClass.c,v 1.
3 1996/10/24 21:07:4
9 jim Exp $
\n
"
"$Id: ExtensionClass.c,v 1.
4 1996/12/06 17:12:2
9 jim Exp $
\n
"
;
#include "Python.h"
...
...
@@ -102,6 +106,72 @@ typedef struct { PyObject_HEAD } Dataless;
#include "ExtensionClass.h"
staticforward
PyExtensionClass
CCLtype
;
#define PyExtensionClass_Check(O) ((O)->ob_type == (PyTypeObject*)&CCLtype)
#define PyExtensionInstance_Check(O) \
((O)->ob_type->ob_type == (PyTypeObject*)&CCLtype)
#define AsPyExtensionClass(O) ((PyExtensionClass*)(O))
#define PyExtensionClassOf(O) ((PyExtensionClass*)((O)->ob_type))
#define AsPyObject(O) ((PyObject*)(O))
static
PyObject
*
py__add__
,
*
py__sub__
,
*
py__mul__
,
*
py__div__
,
*
py__mod__
,
*
py__pow__
,
*
py__divmod__
,
*
py__lshift__
,
*
py__rshift__
,
*
py__and__
,
*
py__or__
,
*
py__xor__
,
*
py__coerce__
,
*
py__neg__
,
*
py__pos__
,
*
py__abs__
,
*
py__nonzero__
,
*
py__inv__
,
*
py__int__
,
*
py__long__
,
*
py__float__
,
*
py__oct__
,
*
py__hex__
,
*
py__getitem__
,
*
py__setitem__
,
*
py__getslice__
,
*
py__setslice__
,
*
py__concat__
,
*
py__repeat__
,
*
py__len__
,
*
py__bind_to_object__
,
*
py__call__
,
*
py__getattr__
,
*
py__setattr__
,
*
py__del__
,
*
py__repr__
,
*
py__str__
,
*
py__hash__
,
*
py__cmp__
,
*
py__var_size__
,
*
py__init__
;
static
void
init_py_names
()
{
#define INIT_PY_NAME(N) py ## N = PyString_FromString(#N)
INIT_PY_NAME
(
__add__
);
INIT_PY_NAME
(
__sub__
);
INIT_PY_NAME
(
__mul__
);
INIT_PY_NAME
(
__div__
);
INIT_PY_NAME
(
__mod__
);
INIT_PY_NAME
(
__pow__
);
INIT_PY_NAME
(
__divmod__
);
INIT_PY_NAME
(
__lshift__
);
INIT_PY_NAME
(
__rshift__
);
INIT_PY_NAME
(
__and__
);
INIT_PY_NAME
(
__or__
);
INIT_PY_NAME
(
__xor__
);
INIT_PY_NAME
(
__coerce__
);
INIT_PY_NAME
(
__neg__
);
INIT_PY_NAME
(
__pos__
);
INIT_PY_NAME
(
__abs__
);
INIT_PY_NAME
(
__nonzero__
);
INIT_PY_NAME
(
__inv__
);
INIT_PY_NAME
(
__int__
);
INIT_PY_NAME
(
__long__
);
INIT_PY_NAME
(
__float__
);
INIT_PY_NAME
(
__oct__
);
INIT_PY_NAME
(
__hex__
);
INIT_PY_NAME
(
__getitem__
);
INIT_PY_NAME
(
__setitem__
);
INIT_PY_NAME
(
__getslice__
);
INIT_PY_NAME
(
__setslice__
);
INIT_PY_NAME
(
__concat__
);
INIT_PY_NAME
(
__repeat__
);
INIT_PY_NAME
(
__len__
);
INIT_PY_NAME
(
__bind_to_object__
);
INIT_PY_NAME
(
__call__
);
INIT_PY_NAME
(
__getattr__
);
INIT_PY_NAME
(
__setattr__
);
INIT_PY_NAME
(
__del__
);
INIT_PY_NAME
(
__repr__
);
INIT_PY_NAME
(
__str__
);
INIT_PY_NAME
(
__hash__
);
INIT_PY_NAME
(
__cmp__
);
INIT_PY_NAME
(
__var_size__
);
INIT_PY_NAME
(
__init__
);
#undef INIT_PY_NAME
}
/* CMethod objects: */
typedef
struct
{
...
...
@@ -116,6 +186,40 @@ typedef struct {
staticforward
PyTypeObject
CMethodType
;
#define CMethod_Check(O) ((O)->ob_type==&CMethodType)
#define UnboundCMethod_Check(O) \
((O)->ob_type==&CMethodType && ! ((CMethod*)(O))->self)
#define AsCMethod(O) ((CMethod*)(O))
static
int
CMethod_issubclass
(
PyExtensionClass
*
sub
,
PyExtensionClass
*
type
)
{
int
i
,
l
;
PyObject
*
t
;
if
(
sub
==
type
)
return
1
;
if
(
!
sub
->
bases
)
return
0
;
l
=
PyTuple_Size
(
sub
->
bases
);
for
(
i
=
0
;
i
<
l
;
i
++
)
{
t
=
PyTuple_GET_ITEM
(
sub
->
bases
,
i
);
if
(
t
==
(
PyObject
*
)
type
)
return
1
;
if
(
PyExtensionClass_Check
(
t
)
&&
AsPyExtensionClass
(
t
)
->
bases
&&
CMethod_issubclass
(
AsPyExtensionClass
(
t
),
type
)
)
return
1
;
}
return
0
;
}
#define Subclass_Check(C1,C2) \
CMethod_issubclass((PyExtensionClass *)(C1), (PyExtensionClass *)(C2))
#define SubclassInstance_Check(C1,C2) \
CMethod_issubclass((PyExtensionClass *)((C1)->ob_type), \
(PyExtensionClass *)(C2))
static
CMethod
*
newCMethod
(
PyTypeObject
*
type
,
char
*
name
,
PyCFunction
meth
,
int
flags
,
char
*
doc
)
...
...
@@ -139,6 +243,15 @@ bindCMethod(CMethod *m, PyObject *inst)
{
CMethod
*
self
;
UNLESS
(
inst
->
ob_type
==
m
->
type
||
(
PyExtensionInstance_Check
(
inst
)
&&
SubclassInstance_Check
(
inst
,
m
->
type
))
)
{
Py_INCREF
(
m
);
return
m
;
}
UNLESS
(
self
=
PyObject_NEW
(
CMethod
,
&
CMethodType
))
return
NULL
;
Py_INCREF
(
inst
);
...
...
@@ -153,8 +266,7 @@ bindCMethod(CMethod *m, PyObject *inst)
}
static
void
CMethod_dealloc
(
self
)
CMethod
*
self
;
CMethod_dealloc
(
CMethod
*
self
)
{
Py_DECREF
(
self
->
type
);
Py_XDECREF
(
self
->
self
);
...
...
@@ -162,11 +274,7 @@ CMethod_dealloc(self)
}
static
PyObject
*
call_cmethod
(
self
,
inst
,
args
,
kw
)
CMethod
*
self
;
PyObject
*
inst
;
PyObject
*
args
;
PyObject
*
kw
;
call_cmethod
(
CMethod
*
self
,
PyObject
*
inst
,
PyObject
*
args
,
PyObject
*
kw
)
{
if
(
!
(
self
->
flags
&
METH_VARARGS
))
{
int
size
=
PyTuple_Size
(
args
);
...
...
@@ -189,31 +297,9 @@ call_cmethod(self, inst, args, kw)
}
}
static
int
CMethod_issubclass
(
PyExtensionClass
*
sub
,
PyExtensionClass
*
type
)
{
int
i
,
l
;
PyObject
*
t
;
if
(
!
sub
->
bases
)
return
0
;
l
=
PyTuple_Size
(
sub
->
bases
);
for
(
i
=
0
;
i
<
l
;
i
++
)
{
t
=
PyTuple_GET_ITEM
(
sub
->
bases
,
i
);
if
(
t
==
(
PyObject
*
)
type
)
return
1
;
if
(
t
->
ob_type
==
(
PyTypeObject
*
)
&
CCLtype
&&
((
PyExtensionClass
*
)
t
)
->
bases
&&
CMethod_issubclass
((
PyExtensionClass
*
)
t
,
type
)
)
return
1
;
}
return
0
;
}
static
PyObject
*
CMethod_call
(
self
,
args
,
kw
)
CMethod
*
self
;
PyObject
*
args
;
PyObject
*
kw
;
CMethod_call
(
CMethod
*
self
,
PyObject
*
args
,
PyObject
*
kw
)
{
int
size
;
char
*
buf
;
...
...
@@ -227,10 +313,10 @@ CMethod_call(self,args,kw)
UNLESS
(
first
=
PyTuple_GET_ITEM
(
args
,
0
))
return
NULL
;
if
(
first
->
ob_type
==
self
->
type
||
(
first
->
ob_type
->
ob_type
==
(
PyTypeObject
*
)
&
CCLtype
(
PyExtensionInstance_Check
(
first
)
&&
CMethod_issubclass
(
(
PyExtensionClass
*
)(
first
->
ob_type
),
(
PyExtensionClass
*
)
(
self
->
type
))
CMethod_issubclass
(
PyExtensionClassOf
(
first
),
AsPyExtensionClass
(
self
->
type
))
)
);
{
...
...
@@ -253,9 +339,7 @@ CMethod_call(self,args,kw)
}
static
PyObject
*
CMethod_getattr
(
self
,
name
)
CMethod
*
self
;
char
*
name
;
CMethod_getattr
(
CMethod
*
self
,
char
*
name
)
{
PyObject
*
r
;
...
...
@@ -299,7 +383,7 @@ static PyTypeObject CMethodType = {
/* methods */
(
destructor
)
CMethod_dealloc
,
/*tp_dealloc*/
(
printfunc
)
0
,
/*tp_print*/
(
getattrfunc
)
0
,
/*tp_getattr*/
(
getattrfunc
)
CMethod_getattr
,
/*tp_getattr*/
(
setattrfunc
)
0
,
/*tp_setattr*/
(
cmpfunc
)
0
,
/*tp_compare*/
(
reprfunc
)
0
,
/*tp_repr*/
...
...
@@ -316,23 +400,32 @@ static PyTypeObject CMethodType = {
/* Documentation string */
};
/* P
m
ethod objects: */
/* P
M
ethod objects: */
typedef
struct
{
PyObject_HEAD
PyTypeObject
*
type
;
PyObject
*
self
;
PyObject
*
meth
;
}
Pmethod
;
}
PMethod
;
staticforward
PyTypeObject
PMethodType
;
#define PMethod_Check(O) ((O)->ob_type==&PMethodType)
#define UnboundPMethod_Check(O) \
((O)->ob_type==&PMethodType && ! ((PMethod*)(O))->self)
staticforward
PyTypeObject
PmethodType
;
#define UnboundEMethod_Check(O) \
(((O)->ob_type==&PMethodType ||(O)->ob_type==&CMethodType) \
&& ! ((PMethod*)(O))->self)
static
Pmethod
*
newPmethod
(
PyTypeObject
*
type
,
PyObject
*
meth
)
static
PMethod
*
newPMethod
(
PyTypeObject
*
type
,
PyObject
*
meth
)
{
P
m
ethod
*
self
;
P
M
ethod
*
self
;
UNLESS
(
self
=
PyObject_NEW
(
P
method
,
&
Pm
ethodType
))
return
NULL
;
UNLESS
(
self
=
PyObject_NEW
(
P
Method
,
&
PM
ethodType
))
return
NULL
;
Py_INCREF
(
type
);
Py_INCREF
(
meth
);
self
->
type
=
type
;
...
...
@@ -341,12 +434,20 @@ newPmethod(PyTypeObject *type, PyObject *meth)
return
self
;
}
static
P
m
ethod
*
bindP
method
(
Pm
ethod
*
m
,
PyObject
*
inst
)
static
P
M
ethod
*
bindP
Method
(
PM
ethod
*
m
,
PyObject
*
inst
)
{
Pmethod
*
self
;
PMethod
*
self
;
UNLESS
(
PyExtensionInstance_Check
(
inst
))
{
PyErr_SetString
(
PyExc_TypeError
,
"attempt to wrap extension method using an object that
\n
"
"is not an extension class instance."
);
return
NULL
;
}
UNLESS
(
self
=
PyObject_NEW
(
P
method
,
&
Pm
ethodType
))
return
NULL
;
UNLESS
(
self
=
PyObject_NEW
(
P
Method
,
&
PM
ethodType
))
return
NULL
;
Py_INCREF
(
inst
);
Py_INCREF
(
m
->
type
);
...
...
@@ -357,8 +458,7 @@ bindPmethod(Pmethod *m, PyObject *inst)
}
static
void
Pmethod_dealloc
(
self
)
Pmethod
*
self
;
PMethod_dealloc
(
PMethod
*
self
)
{
Py_DECREF
(
self
->
type
);
Py_XDECREF
(
self
->
self
);
...
...
@@ -366,11 +466,7 @@ Pmethod_dealloc(self)
}
static
PyObject
*
call_pmethod
(
self
,
inst
,
args
,
kw
)
Pmethod
*
self
;
PyObject
*
inst
;
PyObject
*
args
;
PyObject
*
kw
;
call_PMethod
(
PMethod
*
self
,
PyObject
*
inst
,
PyObject
*
args
,
PyObject
*
kw
)
{
PyObject
*
a
;
...
...
@@ -381,16 +477,13 @@ call_pmethod(self, inst, args, kw)
}
static
PyObject
*
Pmethod_call
(
self
,
args
,
kw
)
Pmethod
*
self
;
PyObject
*
args
;
PyObject
*
kw
;
PMethod_call
(
PMethod
*
self
,
PyObject
*
args
,
PyObject
*
kw
)
{
int
size
;
char
*
buf
;
PyObject
*
s
;
if
(
self
->
self
)
return
call_
pm
ethod
(
self
,
self
->
self
,
args
,
kw
);
if
(
self
->
self
)
return
call_
PM
ethod
(
self
,
self
->
self
,
args
,
kw
);
if
((
size
=
PyTuple_Size
(
args
))
>
0
)
{
...
...
@@ -398,16 +491,16 @@ Pmethod_call(self,args,kw)
UNLESS
(
first
=
PyTuple_GET_ITEM
(
args
,
0
))
return
NULL
;
if
(
first
->
ob_type
==
self
->
type
||
(
first
->
ob_type
->
ob_type
==
(
PyTypeObject
*
)
&
CCLtype
(
PyExtensionInstance_Check
(
first
)
&&
CMethod_issubclass
(
(
PyExtensionClass
*
)(
first
->
ob_type
),
(
PyExtensionClass
*
)
(
self
->
type
))
CMethod_issubclass
(
PyExtensionClassOf
(
first
),
AsPyExtensionClass
(
self
->
type
))
)
);
{
PyObject
*
rest
=
0
;
UNLESS
(
rest
=
PySequence_GetSlice
(
args
,
1
,
size
))
return
NULL
;
return
call_
pm
ethod
(
self
,
first
,
rest
,
kw
);
return
call_
PM
ethod
(
self
,
first
,
rest
,
kw
);
}
}
...
...
@@ -424,9 +517,7 @@ Pmethod_call(self,args,kw)
}
static
PyObject
*
Pmethod_getattr
(
self
,
name
)
Pmethod
*
self
;
char
*
name
;
PMethod_getattr
(
PMethod
*
self
,
char
*
name
)
{
PyObject
*
r
;
...
...
@@ -455,16 +546,16 @@ Pmethod_getattr(self,name)
}
}
static
PyTypeObject
P
m
ethodType
=
{
static
PyTypeObject
P
M
ethodType
=
{
PyObject_HEAD_INIT
(
&
PyType_Type
)
0
,
/*ob_size*/
"Python Method"
,
/*tp_name*/
sizeof
(
P
m
ethod
),
/*tp_basicsize*/
sizeof
(
P
M
ethod
),
/*tp_basicsize*/
0
,
/*tp_itemsize*/
/* methods */
(
destructor
)
P
m
ethod_dealloc
,
/*tp_dealloc*/
(
destructor
)
P
M
ethod_dealloc
,
/*tp_dealloc*/
(
printfunc
)
0
,
/*tp_print*/
(
getattrfunc
)
0
,
/*tp_getattr*/
(
getattrfunc
)
PMethod_getattr
,
/*tp_getattr*/
(
setattrfunc
)
0
,
/*tp_setattr*/
(
cmpfunc
)
0
,
/*tp_compare*/
(
reprfunc
)
0
,
/*tp_repr*/
...
...
@@ -472,7 +563,7 @@ static PyTypeObject PmethodType = {
0
,
/*tp_as_sequence*/
0
,
/*tp_as_mapping*/
(
hashfunc
)
0
,
/*tp_hash*/
(
ternaryfunc
)
P
m
ethod_call
,
/*tp_call*/
(
ternaryfunc
)
P
M
ethod_call
,
/*tp_call*/
(
reprfunc
)
0
,
/*tp_str*/
/* Space for future expansion */
...
...
@@ -537,6 +628,28 @@ setattr_by_name(PyObject *self, PyObject *args)
return
Py_None
;
}
#if PYTHON_API_VERSION >= 1005
static
PyObject
*
getattro_by_name
(
PyObject
*
self
,
PyObject
*
args
)
{
PyObject
*
name
;
UNLESS
(
PyArg_Parse
(
args
,
"O"
,
&
name
))
return
NULL
;
return
self
->
ob_type
->
tp_getattro
(
self
,
name
);
}
static
PyObject
*
setattro_by_name
(
PyObject
*
self
,
PyObject
*
args
)
{
PyObject
*
name
;
PyObject
*
v
;
UNLESS
(
PyArg_Parse
(
args
,
"OO"
,
&
name
,
&
v
))
return
NULL
;
UNLESS
(
-
1
!=
self
->
ob_type
->
tp_setattro
(
self
,
name
,
v
))
return
NULL
;
Py_INCREF
(
Py_None
);
return
Py_None
;
}
#endif
static
PyObject
*
length_by_name
(
PyObject
*
self
,
PyObject
*
args
)
...
...
@@ -725,6 +838,12 @@ getBaseDictionary(PyExtensionClass *type)
FILLENTRY
(
type
->
tp
,
compare
,
comp
,
0
,
"compare with another object"
);
FILLENTRY
(
type
->
tp
,
getattr
,
getattr
,
0
,
"Get an attribute"
);
FILLENTRY
(
type
->
tp
,
setattr
,
setattr
,
0
,
"Set an attribute"
);
#if PYTHON_API_VERSION >= 1005
FILLENTRY
(
type
->
tp
,
getattro
,
getattr
,
0
,
"Get an attribute"
);
FILLENTRY
(
type
->
tp
,
setattro
,
setattr
,
0
,
"Set an attribute"
);
#endif
if
(
sm
=
type
->
tp_as_sequence
)
{
FILLENTRY
(
sm
->
sq
,
length
,
len
,
0
,
"Get the object length"
);
...
...
@@ -837,8 +956,7 @@ initializeBaseExtensionClass(PyExtensionClass *self)
}
static
void
CCL_dealloc
(
self
)
PyExtensionClass
*
self
;
CCL_dealloc
(
PyExtensionClass
*
self
)
{
Py_XDECREF
(
self
->
class_dictionary
);
Py_XDECREF
(
self
->
bases
);
...
...
@@ -849,9 +967,8 @@ CCL_dealloc(self)
static
PyObject
*
CCL_getattr
();
static
PyObject
*
ExtensionClass_FindInstanceAttribute
(
inst
,
name
)
PyObject
*
inst
;
char
*
name
;
ExtensionClass_FindInstanceAttribute
(
PyObject
*
inst
,
PyObject
*
oname
,
char
*
name
)
{
/* Look up an attribute for an instance from:
...
...
@@ -862,6 +979,8 @@ ExtensionClass_FindInstanceAttribute(inst,name)
PyObject
*
r
=
0
;
PyExtensionClass
*
self
;
if
(
!
name
)
return
NULL
;
self
=
(
PyExtensionClass
*
)(
inst
->
ob_type
);
if
(
*
name
==
'_'
&&
name
[
1
]
==
'_'
)
...
...
@@ -882,25 +1001,25 @@ ExtensionClass_FindInstanceAttribute(inst,name)
if
(
self
->
bases
)
{
r
=
INSTANCE_DICT
(
inst
);
r
=
Py
Mapping_GetItemString
(
r
,
name
);
r
=
Py
Object_GetItem
(
r
,
o
name
);
}
UNLESS
(
r
)
{
PyErr_Clear
();
UNLESS
(
r
=
CCL_getattr
(
self
,
name
))
return
NULL
;
UNLESS
(
r
=
CCL_getattr
(
self
,
oname
,
name
))
return
NULL
;
/* We got something from our class, maybe its an unbound method. */
if
(
r
->
ob_type
==&
CMethodType
)
if
(
UnboundCMethod_Check
(
r
)
)
{
UNLESS_ASSIGN
(
r
,(
PyObject
*
)
bindCMethod
((
CMethod
*
)
r
,
inst
))
return
NULL
;
}
if
(
r
->
ob_type
==&
PmethodType
)
else
if
(
UnboundPMethod_Check
(
r
)
)
{
PyObject
*
m
;
m
=
((
P
m
ethod
*
)
r
)
->
meth
;
if
(
m
->
ob_type
->
ob_type
==
(
PyTypeObject
*
)
&
CCLtype
&&
(
((
PyExtensionClass
*
)
m
->
ob_type
)
->
class_flags
&
m
=
((
P
M
ethod
*
)
r
)
->
meth
;
if
(
PyExtensionInstance_Check
(
m
)
&&
(
PyExtensionClassOf
(
m
)
->
class_flags
&
EXTENSIONCLASS_BINDABLE_FLAG
)
)
...
...
@@ -911,7 +1030,7 @@ ExtensionClass_FindInstanceAttribute(inst,name)
}
else
{
UNLESS_ASSIGN
(
r
,(
PyObject
*
)
bindP
method
((
Pm
ethod
*
)
r
,
inst
))
UNLESS_ASSIGN
(
r
,(
PyObject
*
)
bindP
Method
((
PM
ethod
*
)
r
,
inst
))
return
NULL
;
}
}
...
...
@@ -921,19 +1040,47 @@ ExtensionClass_FindInstanceAttribute(inst,name)
}
static
PyObject
*
CCL_getattr
(
self
,
name
)
PyExtensionClass
*
self
;
char
*
name
;
EC_findiattrs
(
PyObject
*
self
,
char
*
name
)
{
PyObject
*
s
,
*
r
;
UNLESS
(
s
=
PyString_FromString
(
name
))
return
NULL
;
r
=
ExtensionClass_FindInstanceAttribute
(
self
,
s
,
name
);
Py_DECREF
(
s
);
return
r
;
}
static
PyObject
*
EC_findiattro
(
PyObject
*
self
,
PyObject
*
name
)
{
return
ExtensionClass_FindInstanceAttribute
(
self
,
name
,
PyString_AsString
(
name
));
}
static
int
subclass_simple_setattr
(
PyObject
*
self
,
char
*
name
,
PyObject
*
v
);
static
PyObject
*
CCL_getattr
(
PyExtensionClass
*
self
,
PyObject
*
oname
,
char
*
name
)
{
PyObject
*
r
;
int
local
=
1
;
char
*
n
;
if
(
*
name
==
'.'
&&
name
[
1
]
==
0
)
return
(
PyObject
*
)
ExtensionClass_FindInstanceAttribute
;
if
(
!
name
)
return
NULL
;
if
(
*
name
==
'.'
)
{
n
=
name
+
1
;
if
(
*
n
==
0
)
return
(
PyObject
*
)
EC_findiattrs
;
if
(
*
n
==
'o'
&&
n
[
1
]
==
0
)
return
(
PyObject
*
)
EC_findiattro
;
if
(
*
n
==
's'
&&
n
[
1
]
==
0
)
return
(
PyObject
*
)
subclass_simple_setattr
;
}
if
(
*
name
==
'_'
&&
name
[
1
]
==
'_'
)
{
char
*
n
;
n
=
name
+
2
;
if
(
strcmp
(
n
,
"doc__"
)
==
0
&&
self
->
tp_doc
)
return
PyString_FromString
(
self
->
tp_doc
);
...
...
@@ -956,7 +1103,7 @@ CCL_getattr(self, name)
}
}
r
=
Py
Mapping_GetItemString
(
self
->
class_dictionary
,
name
);
r
=
Py
Object_GetItem
(
self
->
class_dictionary
,
o
name
);
UNLESS
(
r
)
{
local
=
0
;
...
...
@@ -970,7 +1117,7 @@ CCL_getattr(self, name)
{
PyErr_Clear
();
c
=
PyTuple_GET_ITEM
(
self
->
bases
,
i
);
if
(
r
=
PyObject_GetAttr
String
(
c
,
name
))
break
;
if
(
r
=
PyObject_GetAttr
(
c
,
o
name
))
break
;
}
}
UNLESS
(
r
)
...
...
@@ -979,9 +1126,7 @@ CCL_getattr(self, name)
char
*
s
;
PyErr_Fetch
(
&
t
,
&
v
,
&
tb
);
if
(
t
==
PyExc_KeyError
&&
PyString_Check
(
v
)
&&
(
s
=
PyString_AsString
(
v
))
&&
strcmp
(
s
,
name
)
==
0
)
if
(
t
==
PyExc_KeyError
&&
PyObject_Compare
(
v
,
oname
)
==
0
)
{
Py_DECREF
(
t
);
t
=
PyExc_AttributeError
;
...
...
@@ -993,25 +1138,46 @@ CCL_getattr(self, name)
}
if
(
PyFunction_Check
(
r
)
||
(
r
->
ob_type
->
ob_type
==
(
PyTypeObject
*
)
&
CCLtype
&&
(
((
PyExtensionClass
*
)
r
->
ob_type
)
->
class_flags
&
(
PyExtensionInstance_Check
(
r
)
&&
(
PyExtensionClassOf
(
r
)
->
class_flags
&
EXTENSIONCLASS_BINDABLE_FLAG
)
)
)
UNLESS_ASSIGN
(
r
,(
PyObject
*
)
newPmethod
((
PyTypeObject
*
)
self
,
r
))
{
UNLESS_ASSIGN
(
r
,(
PyObject
*
)
newPMethod
((
PyTypeObject
*
)
self
,
r
))
return
NULL
;
if
(
PyMethod_Check
(
r
)
&&
!
PyMethod_Self
(
r
))
UNLESS_ASSIGN
(
r
,(
PyObject
*
)
newPmethod
((
PyTypeObject
*
)
self
,
}
else
if
(
PyMethod_Check
(
r
)
&&
!
PyMethod_Self
(
r
))
{
UNLESS_ASSIGN
(
r
,(
PyObject
*
)
newPMethod
((
PyTypeObject
*
)
self
,
PyMethod_Function
(
r
)))
return
NULL
;
}
else
local
=
0
;
if
(
local
)
/* We have a PMethod that we built from our dict, cache it */
{
UNLESS
(
-
1
!=
PyObject_SetItem
(
self
->
class_dictionary
,
oname
,
r
))
PyErr_Clear
();
/* Oh well */
}
return
r
;
}
PyObject
*
CCL_getattrs
(
PyExtensionClass
*
self
,
char
*
name
)
{
PyObject
*
s
,
*
r
;
UNLESS
(
s
=
PyString_FromString
(
name
))
return
NULL
;
r
=
CCL_getattr
(
self
,
s
,
name
);
Py_DECREF
(
s
);
return
r
;
}
static
int
CCL_setattr
(
self
,
name
,
v
)
CCL_setattr
s
(
self
,
name
,
v
)
PyExtensionClass
*
self
;
char
*
name
;
PyObject
*
v
;
...
...
@@ -1019,10 +1185,138 @@ CCL_setattr(self, name, v)
return
PyMapping_SetItemString
(
self
->
class_dictionary
,
name
,
v
);
}
PyObject
*
CCL_getattro
(
PyExtensionClass
*
self
,
PyObject
*
name
)
{
return
CCL_getattr
(
self
,
name
,
PyString_AsString
(
name
));
}
static
int
CCL_setattro
(
PyExtensionClass
*
self
,
PyObject
*
name
,
PyObject
*
v
)
{
if
(
UnboundCMethod_Check
(
v
))
{
char
*
n
;
PyNumberMethods
*
nm
;
PySequenceMethods
*
s
,
*
ms
;
PyMappingMethods
*
m
,
*
mm
;
UNLESS
(
n
=
PyString_AsString
(
name
))
return
-
1
;
if
(
*
n
==
'_'
&&
n
[
1
]
==
'_'
)
{
n
+=
2
;
#define SET_SPECIAL(C,P) \
if(strcmp(n,#P "__")==0 \
&& AsCMethod(v)->meth==(PyCFunction)C ## _by_name \
&& Subclass_Check(self,AsCMethod(v)->type)) { \
self->tp_ ## C=AsCMethod(v)->type->tp_ ## C; \
return PyObject_SetItem(self->class_dictionary, name, v); }
/*
SET_SPECIAL(setattr,setattr);
SET_SPECIAL(setattro,setattr);
*/
SET_SPECIAL
(
compare
,
cmp
);
SET_SPECIAL
(
hash
,
hash
);
SET_SPECIAL
(
repr
,
repr
);
SET_SPECIAL
(
call
,
call
);
SET_SPECIAL
(
str
,
str
);
#undef SET_SPECIAL
#define SET_SPECIAL(C,P) \
if(strcmp(n,#P "__")==0 && AsCMethod(v)->meth==C ## _by_name \
&& Subclass_Check(self,AsCMethod(v)->type) \
&& (nm=self->tp_as_number)) { \
nm->nb_ ## C=AsCMethod(v)->type->tp_as_number->nb_ ## C; \
return PyObject_SetItem(self->class_dictionary, name, v); }
SET_SPECIAL
(
add
,
add
);
SET_SPECIAL
(
subtract
,
sub
);
SET_SPECIAL
(
multiply
,
mult
);
SET_SPECIAL
(
divide
,
div
);
SET_SPECIAL
(
remainder
,
mod
);
SET_SPECIAL
(
power
,
pow
);
SET_SPECIAL
(
divmod
,
divmod
);
SET_SPECIAL
(
lshift
,
lshift
);
SET_SPECIAL
(
rshift
,
rshift
);
SET_SPECIAL
(
and
,
and
);
SET_SPECIAL
(
or
,
or
);
SET_SPECIAL
(
xor
,
xor
);
SET_SPECIAL
(
coerce
,
coerce
);
SET_SPECIAL
(
negative
,
neg
);
SET_SPECIAL
(
positive
,
pos
);
SET_SPECIAL
(
absolute
,
abs
);
SET_SPECIAL
(
nonzero
,
nonzero
);
SET_SPECIAL
(
invert
,
inv
);
SET_SPECIAL
(
int
,
int
);
SET_SPECIAL
(
long
,
long
);
SET_SPECIAL
(
float
,
float
);
SET_SPECIAL
(
oct
,
oct
);
SET_SPECIAL
(
hex
,
hex
);
#undef SET_SPECIAL
if
(
strcmp
(
n
,
"len__"
)
==
0
&&
AsCMethod
(
v
)
->
meth
==
length_by_name
&&
Subclass_Check
(
self
,
AsCMethod
(
v
)
->
type
))
{
if
((
s
=
self
->
tp_as_sequence
)
&&
(
ms
=
AsCMethod
(
v
)
->
type
->
tp_as_sequence
)
&&
ms
->
sq_length
)
s
->
sq_length
=
ms
->
sq_length
;
if
((
m
=
self
->
tp_as_mapping
)
&&
(
mm
=
AsCMethod
(
v
)
->
type
->
tp_as_mapping
)
&&
mm
->
mp_length
)
m
->
mp_length
=
mm
->
mp_length
;
return
PyObject_SetItem
(
self
->
class_dictionary
,
name
,
v
);
}
if
(
strcmp
(
n
,
"getitem__"
)
==
0
&&
AsCMethod
(
v
)
->
meth
==
getitem_by_name
&&
Subclass_Check
(
self
,
AsCMethod
(
v
)
->
type
))
{
if
((
s
=
self
->
tp_as_sequence
)
&&
(
ms
=
AsCMethod
(
v
)
->
type
->
tp_as_sequence
)
&&
ms
->
sq_item
)
s
->
sq_item
=
ms
->
sq_item
;
if
((
m
=
self
->
tp_as_mapping
)
&&
(
mm
=
AsCMethod
(
v
)
->
type
->
tp_as_mapping
)
&&
mm
->
mp_subscript
)
m
->
mp_subscript
=
mm
->
mp_subscript
;
return
PyObject_SetItem
(
self
->
class_dictionary
,
name
,
v
);
}
if
(
strcmp
(
n
,
"setitem__"
)
==
0
&&
AsCMethod
(
v
)
->
meth
==
(
PyCFunction
)
setitem_by_name
&&
Subclass_Check
(
self
,
AsCMethod
(
v
)
->
type
))
{
if
((
s
=
self
->
tp_as_sequence
)
&&
(
ms
=
AsCMethod
(
v
)
->
type
->
tp_as_sequence
)
&&
ms
->
sq_ass_item
)
s
->
sq_ass_item
=
ms
->
sq_ass_item
;
if
((
m
=
self
->
tp_as_mapping
)
&&
(
mm
=
AsCMethod
(
v
)
->
type
->
tp_as_mapping
)
&&
mm
->
mp_ass_subscript
)
m
->
mp_ass_subscript
=
mm
->
mp_ass_subscript
;
return
PyObject_SetItem
(
self
->
class_dictionary
,
name
,
v
);
}
#define SET_SPECIAL(C,P) \
if(strcmp(n,#P "__")==0 \
&& AsCMethod(v)->meth==(PyCFunction)C ## _by_name \
&& Subclass_Check(self,AsCMethod(v)->type) \
&& (s=self->tp_as_sequence)) { \
s->sq_ ## C=AsCMethod(v)->type->tp_as_sequence->sq_ ## C; \
return PyObject_SetItem(self->class_dictionary, name, v); }
SET_SPECIAL
(
slice
,
getslice
);
SET_SPECIAL
(
ass_slice
,
setslice
);
SET_SPECIAL
(
concat
,
concat
);
SET_SPECIAL
(
repeat
,
repeat
);
#undef SET_SPECIAL
}
}
return
PyObject_SetItem
(
self
->
class_dictionary
,
name
,
v
);
}
static
PyObject
*
CCL_call
(
self
,
arg
,
kw
)
PyExtensionClass
*
self
;
PyObject
*
arg
,
*
kw
;
CCL_call
(
PyExtensionClass
*
self
,
PyObject
*
arg
,
PyObject
*
kw
)
{
PyObject
*
inst
=
0
,
*
init
=
0
,
*
args
=
0
;
int
check
;
...
...
@@ -1045,7 +1339,7 @@ CCL_call(self, arg, kw)
PyObject
*
var_size
;
int
size
;
if
(
var_size
=
CCL_getattr
(
self
,
"__var_size__"
))
if
(
var_size
=
CCL_getattr
o
(
self
,
py__var_size__
))
{
UNLESS_ASSIGN
(
var_size
,
PyObject_CallObject
(
var_size
,
args
))
return
NULL
;
...
...
@@ -1093,7 +1387,7 @@ CCL_call(self, arg, kw)
if
(
init
=
CCL_getattr
(
self
,
"__init__"
))
if
(
init
=
CCL_getattr
o
(
self
,
py__init__
))
{
UNLESS
(
args
=
Py_BuildValue
(
"(O)"
,
inst
))
goto
err
;
if
(
arg
)
UNLESS_ASSIGN
(
args
,
PySequence_Concat
(
args
,
arg
))
goto
err
;
...
...
@@ -1113,8 +1407,7 @@ err:
}
static
PyObject
*
CCL_repr
(
self
)
PyExtensionClass
*
self
;
CCL_repr
(
PyExtensionClass
*
self
)
{
PyObject
*
s
;
int
l
;
...
...
@@ -1124,7 +1417,7 @@ CCL_repr(self)
l
=
strlen
(
self
->
ob_type
->
tp_name
)
+
strlen
(
p
);
UNLESS
(
s
=
PyString_FromStringAndSize
(
NULL
,
l
+
22
))
return
NULL
;
buf
=
PyString_AsString
(
s
);
sprintf
(
buf
,
"<extension class %s at %p>"
,
self
->
tp_name
);
sprintf
(
buf
,
"<extension class %s at %p>"
,
self
->
tp_name
,
self
);
return
s
;
}
...
...
@@ -1137,8 +1430,8 @@ static PyTypeObject CCLtype_class = {
/* methods */
(
destructor
)
CCL_dealloc
,
/*tp_dealloc*/
(
printfunc
)
0
,
/*tp_print*/
(
getattrfunc
)
CCL_getattr
,
/*tp_getattr*/
(
setattrfunc
)
CCL_setattr
,
/*tp_setattr*/
(
getattrfunc
)
CCL_getattr
s
,
/*tp_getattr*/
(
setattrfunc
)
CCL_setattr
s
,
/*tp_setattr*/
(
cmpfunc
)
0
,
/*tp_compare*/
(
reprfunc
)
CCL_repr
,
/*tp_repr*/
0
,
/*tp_as_number*/
...
...
@@ -1147,9 +1440,14 @@ static PyTypeObject CCLtype_class = {
(
hashfunc
)
0
,
/*tp_hash*/
(
ternaryfunc
)
CCL_call
,
/*tp_call*/
(
reprfunc
)
0
,
/*tp_str*/
#if PYTHON_API_VERSION >= 1005
(
getattrofunc
)
CCL_getattro
,
/*tp_getattr with object key*/
(
setattrofunc
)
CCL_setattro
,
/*tp_setattr with object key*/
#else
/* Space for future expansion */
0L
,
0L
,
0L
,
0L
,
0L
,
0L
,
#endif
0L
,
0L
,
"Class of C classes"
/* Documentation string */
};
...
...
@@ -1158,20 +1456,90 @@ static PyTypeObject CCLtype_class = {
/* subclassing code: */
static
PyObject
*
subclass_getspecial
(
PyObject
*
inst
,
PyObject
*
oname
)
{
PyObject
*
r
=
0
;
PyExtensionClass
*
self
;
self
=
(
PyExtensionClass
*
)(
inst
->
ob_type
);
r
=
INSTANCE_DICT
(
inst
);
r
=
PyObject_GetItem
(
r
,
oname
);
UNLESS
(
r
)
{
PyErr_Clear
();
r
=
CCL_getattr
(
self
,
oname
,
""
);
}
return
r
;
}
static
PyObject
*
subclass_getattro
(
PyObject
*
self
,
PyObject
*
name
)
{
PyObject
*
r
=
0
;
if
(
!
name
)
return
NULL
;
UNLESS
(
r
=
EC_findiattro
(
self
,
name
))
{
PyErr_Clear
();
UNLESS
(
r
=
EC_findiattro
(
self
,
py__getattr__
))
return
NULL
;
UNLESS_ASSIGN
(
r
,
PyObject_CallFunction
(
r
,
"O"
,
name
))
return
NULL
;
}
return
r
;
}
static
PyObject
*
subclass_getattrs
(
PyObject
*
self
,
char
*
name
)
{
return
subclass_getattro
(
self
,
PyString_FromString
(
name
));
}
static
int
subclass_setattr
(
PyObject
*
self
,
char
*
name
,
PyObject
*
v
)
subclass_simple_setattro
(
PyObject
*
self
,
PyObject
*
name
,
PyObject
*
v
)
{
Py_INCREF
(
v
);
return
PyDict_SetItem
(
INSTANCE_DICT
(
self
),
name
,
v
);
}
static
int
subclass_simple_setattr
(
PyObject
*
self
,
char
*
name
,
PyObject
*
v
)
{
Py_INCREF
(
v
);
return
PyDict_SetItemString
(
INSTANCE_DICT
(
self
),
name
,
v
);
}
static
int
subclass_setattr
(
PyObject
*
self
,
PyObject
*
oname
,
char
*
name
,
PyObject
*
v
)
{
PyObject
*
m
=
0
,
*
et
,
*
ev
,
*
etb
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__setattr__"
))
if
(
!
name
)
return
-
1
;
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__setattr__
))
goto
default_setattr
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
setattr_by_name
)
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
setattr_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS
(
-
1
!=
((
CMethod
*
)
m
)
->
type
->
tp_setattr
(
self
,
name
,
v
))
UNLESS
(
-
1
!=
AsCMethod
(
m
)
->
type
->
tp_setattr
(
self
,
name
,
v
))
goto
dictionary_setattr
;
return
0
;
}
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"sO"
,
name
,
v
))
return
-
1
;
#if PYTHON_API_VERSION >= 1005
else
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
setattro_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS
(
-
1
!=
AsCMethod
(
m
)
->
type
->
tp_setattro
(
self
,
oname
,
v
))
goto
dictionary_setattr
;
return
0
;
}
#endif
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"OOO"
,
self
,
oname
,
v
))
return
-
1
;
}
else
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"OO"
,
oname
,
v
))
return
-
1
;
Py_DECREF
(
m
);
return
0
;
...
...
@@ -1203,24 +1571,46 @@ default_setattr:
PyErr_Clear
();
UNLESS
(
-
1
!=
PyMapping_SetItemString
(
INSTANCE_DICT
(
self
),
name
,
v
))
return
-
1
;
return
subclass_simple_setattro
(
self
,
oname
,
v
);
}
return
0
;
static
int
subclass_setattrs
(
PyObject
*
self
,
char
*
name
,
PyObject
*
v
)
{
PyObject
*
s
;
int
r
;
UNLESS
(
s
=
PyString_FromString
(
name
))
return
-
1
;
r
=
subclass_setattr
(
self
,
s
,
name
,
v
);
Py_DECREF
(
s
);
return
r
;
}
static
int
subclass_setattro
(
PyObject
*
self
,
PyObject
*
name
,
PyObject
*
v
)
{
return
subclass_setattr
(
self
,
name
,
PyString_AsString
(
name
),
v
);
}
static
int
subclass_compare
(
PyObject
*
self
,
PyObject
*
v
)
{
PyObject
*
m
;
long
r
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__cmp__"
))
return
-
1
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
compare_by_name
)
r
=
((
CMethod
*
)
m
)
->
type
->
tp_compare
(
self
,
v
);
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__cmp__
))
return
-
1
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
compare_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
r
=
AsCMethod
(
m
)
->
type
->
tp_compare
(
self
,
v
);
else
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"O"
,
v
))
return
-
1
;
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"OO"
,
self
,
v
))
return
-
1
;
}
else
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"O"
,
v
))
return
-
1
;
r
=
PyInt_AsLong
(
m
);
}
Py_DECREF
(
m
);
...
...
@@ -1233,12 +1623,18 @@ subclass_hash(PyObject *self)
PyObject
*
m
;
long
r
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__hash__"
))
return
-
1
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
hash_by_name
)
r
=
((
CMethod
*
)
m
)
->
type
->
tp_hash
(
self
);
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__hash__
))
return
-
1
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
hash_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
r
=
AsCMethod
(
m
)
->
type
->
tp_hash
(
self
);
else
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
""
))
return
-
1
;
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"O"
,
self
))
return
-
1
;
}
else
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
""
))
return
-
1
;
r
=
PyInt_AsLong
(
m
);
}
Py_DECREF
(
m
);
...
...
@@ -1250,7 +1646,7 @@ subclass_repr(PyObject *self)
{
PyObject
*
m
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__repr__"
))
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__repr__
))
{
int
l
;
char
*
buf
,
p
[
64
];
...
...
@@ -1263,13 +1659,19 @@ subclass_repr(PyObject *self)
sprintf
(
buf
,
"<%s instance at %s>"
,
self
->
ob_type
->
tp_name
,
p
);
return
m
;
}
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
repr_by_name
)
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
repr_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS_ASSIGN
(
m
,
((
CMethod
*
)
m
)
->
type
->
tp_repr
(
self
))
return
NULL
;
UNLESS_ASSIGN
(
m
,
AsCMethod
(
m
)
->
type
->
tp_repr
(
self
))
return
NULL
;
}
else
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
""
))
return
NULL
;
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"O"
,
self
))
return
NULL
;
}
else
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
""
))
return
NULL
;
}
return
m
;
}
...
...
@@ -1277,18 +1679,29 @@ subclass_repr(PyObject *self)
static
PyObject
*
subclass_call
(
PyObject
*
self
,
PyObject
*
args
,
PyObject
*
kw
)
{
PyObject
*
m
;
PyObject
*
m
,
*
a
=
0
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__call__"
))
return
NULL
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
(
PyCFunction
)
call_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__call__
))
return
NULL
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
(
PyCFunction
)
call_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS_ASSIGN
(
m
,
((
CMethod
*
)
m
)
->
type
->
tp_call
(
self
,
args
,
kw
))
return
NULL
;
UNLESS_ASSIGN
(
m
,
AsCMethod
(
m
)
->
type
->
tp_call
(
self
,
args
,
kw
))
return
NULL
;
}
else
{
UNLESS_ASSIGN
(
m
,
PyEval_CallObjectWithKeywords
(
m
,
args
,
kw
))
return
NULL
;
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS
(
a
=
Py_BuildValue
(
"(O)"
,
self
))
goto
err
;
UNLESS_ASSIGN
(
a
,
PySequence_Concat
(
a
,
args
))
goto
err
;
args
=
a
;
}
UNLESS_ASSIGN
(
m
,
PyEval_CallObjectWithKeywords
(
m
,
args
,
kw
))
goto
err
;
}
Py_XDECREF
(
a
);
return
m
;
err:
Py_XDECREF
(
m
);
Py_XDECREF
(
a
);
}
static
PyObject
*
...
...
@@ -1296,18 +1709,24 @@ subclass_str(PyObject *self)
{
PyObject
*
m
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__str__"
))
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__str__
))
{
PyErr_Clear
();
return
subclass_repr
(
self
);
}
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
str_by_name
)
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
str_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS_ASSIGN
(
m
,
((
CMethod
*
)
m
)
->
type
->
tp_str
(
self
))
return
NULL
;
UNLESS_ASSIGN
(
m
,
AsCMethod
(
m
)
->
type
->
tp_str
(
self
))
return
NULL
;
}
else
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
""
))
return
NULL
;
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"O"
,
self
))
return
NULL
;
}
else
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
""
))
return
NULL
;
}
return
m
;
}
...
...
@@ -1317,15 +1736,21 @@ static PyObject * \
subclass_ ## M(PyObject *self, PyObject *v) \
{ \
PyObject *m; \
UNLESS(m=PyObject_GetAttrString(self,"__" # M "__")) return NULL; \
if(m->ob_type==&CMethodType && ((CMethod*)m)->meth==M ## _by_name) \
UNLESS(m=subclass_getspecial(self,py__ ## N ## __)) return NULL; \
if(UnboundCMethod_Check(m) && AsCMethod(m)->meth==M ## _by_name \
&& SubclassInstance_Check(self,AsCMethod(m)->type)) \
{ \
UNLESS_ASSIGN(m,PyNumber_ ## A(self,v)) \
return NULL; \
} \
else \
{ \
UNLESS_ASSIGN(m,PyObject_CallFunction(m,"O",v)) return NULL; \
if(UnboundEMethod_Check(m)) \
{ \
UNLESS_ASSIGN(m,PyObject_CallFunction(m,"OO",self,v)) \
return NULL; \
} \
else UNLESS_ASSIGN(m,PyObject_CallFunction(m,"O",v)) return NULL; \
} \
return m; \
}
...
...
@@ -1340,15 +1765,21 @@ static PyObject *
subclass_power
(
PyObject
*
self
,
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
m
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__pow__"
))
return
NULL
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
power_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__pow__
))
return
NULL
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
power_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS_ASSIGN
(
m
,
((
CMethod
*
)
m
)
->
type
->
tp_as_number
->
nb_power
(
self
,
v
,
w
))
UNLESS_ASSIGN
(
m
,
AsCMethod
(
m
)
->
type
->
tp_as_number
->
nb_power
(
self
,
v
,
w
))
return
NULL
;
}
else
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"OO"
,
v
,
w
))
return
NULL
;
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"OOO"
,
self
,
v
,
w
))
return
NULL
;
}
else
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"OO"
,
v
,
w
))
return
NULL
;
}
return
m
;
}
...
...
@@ -1368,12 +1799,18 @@ subclass_coerce(PyObject **self, PyObject **v)
PyObject
*
m
;
int
r
;
UNLESS
(
m
=
PyObject_GetAttrString
(
*
self
,
"__coerce__"
))
return
-
1
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
coerce_by_name
)
r
=
((
CMethod
*
)
m
)
->
type
->
tp_as_number
->
nb_coerce
(
self
,
v
);
UNLESS
(
m
=
subclass_getspecial
(
*
self
,
py__coerce__
))
return
-
1
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
coerce_by_name
&&
SubclassInstance_Check
(
*
self
,
AsCMethod
(
m
)
->
type
))
r
=
AsCMethod
(
m
)
->
type
->
tp_as_number
->
nb_coerce
(
self
,
v
);
else
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"OO"
,
*
self
,
*
v
))
return
-
1
;
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"OO"
,
*
self
,
v
))
return
NULL
;
}
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"O"
,
*
v
))
return
-
1
;
if
(
m
==
Py_None
)
r
=-
1
;
else
{
...
...
@@ -1392,15 +1829,21 @@ static PyObject * \
subclass_ ## M(PyObject *self) \
{ \
PyObject *m; \
UNLESS(m=PyObject_GetAttrString(self,"__" # M "__")) return NULL; \
if(m->ob_type==&CMethodType && ((CMethod*)m)->meth==M ## _by_name) \
UNLESS(m=subclass_getspecial(self,py__ ## N ## __)) return NULL; \
if(UnboundCMethod_Check(m) && AsCMethod(m)->meth==M ## _by_name \
&& SubclassInstance_Check(self,AsCMethod(m)->type)) \
{ \
UNLESS_ASSIGN(m,
((CMethod*)
m)->type->tp_as_number->nb_ ## M(self)) \
UNLESS_ASSIGN(m,
AsCMethod(
m)->type->tp_as_number->nb_ ## M(self)) \
return NULL; \
} \
else \
{ \
UNLESS_ASSIGN(m,PyObject_CallFunction(m,"O")) return NULL; \
if(UnboundEMethod_Check(m)) \
{ \
UNLESS_ASSIGN(m,PyObject_CallFunction(m,"O",self)) \
return NULL; \
} \
else UNLESS_ASSIGN(m,PyObject_CallFunction(m,"")) return NULL; \
} \
return m; \
}
...
...
@@ -1415,12 +1858,18 @@ subclass_nonzero(PyObject *self)
PyObject
*
m
;
long
r
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__nonzero__"
))
return
-
1
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
nonzero_by_name
)
r
=
((
CMethod
*
)
m
)
->
type
->
tp_as_number
->
nb_nonzero
(
self
);
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__nonzero__
))
return
-
1
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
nonzero_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
r
=
AsCMethod
(
m
)
->
type
->
tp_as_number
->
nb_nonzero
(
self
);
else
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
""
))
return
-
1
;
if
(
UnboundEMethod_Check
(
m
))
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"O"
,
self
))
return
-
1
;
}
else
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
""
))
return
-
1
;
r
=
PyInt_AsLong
(
m
);
}
Py_DECREF
(
m
);
...
...
@@ -1471,10 +1920,11 @@ subclass_length(PyObject *self)
long
r
;
PyExtensionClass
*
t
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__len__"
))
return
-
1
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
length_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__len__
))
return
-
1
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
length_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
t
=
(
PyExtensionClass
*
)
((
CMethod
*
)
m
)
->
type
;
t
=
(
PyExtensionClass
*
)
AsCMethod
(
m
)
->
type
;
Py_DECREF
(
m
);
if
(
t
->
tp_as_sequence
)
return
t
->
tp_as_sequence
->
sq_length
(
self
);
...
...
@@ -1496,10 +1946,11 @@ subclass_item(PyObject *self, int index)
PyObject
*
m
;
PyExtensionClass
*
t
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__getitem__"
))
return
NULL
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
getitem_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__getitem__
))
return
NULL
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
getitem_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
t
=
(
PyExtensionClass
*
)
((
CMethod
*
)
m
)
->
type
;
t
=
(
PyExtensionClass
*
)
AsCMethod
(
m
)
->
type
;
if
(
t
->
tp_as_sequence
&&
t
->
tp_as_sequence
->
sq_item
)
{
Py_DECREF
(
m
);
...
...
@@ -1520,11 +1971,12 @@ subclass_ass_item(PyObject *self, int index, PyObject *v)
PyObject
*
m
;
PyExtensionClass
*
t
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__setitem__"
))
return
-
1
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
(
PyCFunction
)
setitem_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__setitem__
))
return
-
1
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
(
PyCFunction
)
setitem_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
t
=
(
PyExtensionClass
*
)
((
CMethod
*
)
m
)
->
type
;
t
=
(
PyExtensionClass
*
)
AsCMethod
(
m
)
->
type
;
if
(
t
->
tp_as_sequence
&&
t
->
tp_as_sequence
->
sq_ass_item
)
{
Py_DECREF
(
m
);
...
...
@@ -1545,10 +1997,11 @@ subclass_slice(PyObject *self, int i1, int i2)
{
PyObject
*
m
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__getslice__"
))
return
NULL
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
slice_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__getslice__
))
return
NULL
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
slice_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS_ASSIGN
(
m
,
((
CMethod
*
)
m
)
->
type
->
tp_as_sequence
->
sq_slice
(
self
,
i1
,
i2
))
UNLESS_ASSIGN
(
m
,
AsCMethod
(
m
)
->
type
->
tp_as_sequence
->
sq_slice
(
self
,
i1
,
i2
))
return
NULL
;
}
else
...
...
@@ -1564,10 +2017,11 @@ subclass_ass_slice(PyObject *self, int i1, int i2, PyObject *v)
PyObject
*
m
;
long
r
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__setslice__"
))
return
-
1
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
(
PyCFunction
)
ass_slice_by_name
)
r
=
((
CMethod
*
)
m
)
->
type
->
tp_as_sequence
->
sq_ass_slice
(
self
,
i1
,
i2
,
v
);
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__setslice__
))
return
-
1
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
(
PyCFunction
)
ass_slice_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
r
=
AsCMethod
(
m
)
->
type
->
tp_as_sequence
->
sq_ass_slice
(
self
,
i1
,
i2
,
v
);
else
{
UNLESS_ASSIGN
(
m
,
PyObject_CallFunction
(
m
,
"iiO"
,
i1
,
i2
,
v
))
return
-
1
;
...
...
@@ -1582,21 +2036,22 @@ subclass_concat(PyObject *self, PyObject *v)
{
PyObject
*
m
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__concat__"
))
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__concat__
))
{
/* Maybe we should check for __add__ */
PyObject
*
am
;
PyErr_Clear
();
UNLESS
(
am
=
PyObject_GetAttrString
(
self
,
"__add__"
))
return
NULL
;
if
(
m
=
PyObject_GetAttrString
(
self
,
"__coerce__"
))
UNLESS
(
am
=
subclass_getspecial
(
self
,
py__add__
))
return
NULL
;
if
(
m
=
subclass_getspecial
(
self
,
py__coerce__
))
{
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
coerce_by_name
)
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
coerce_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
PyObject
*
x
,
*
y
;
x
=
self
;
y
=
v
;
if
(
0
==
((
CMethod
*
)
m
)
->
type
->
tp_as_number
->
nb_coerce
(
&
x
,
&
y
))
if
(
0
==
AsCMethod
(
m
)
->
type
->
tp_as_number
->
nb_coerce
(
&
x
,
&
y
))
{
Py_DECREF
(
am
);
if
(
x
->
ob_type
->
tp_as_number
)
...
...
@@ -1616,9 +2071,10 @@ subclass_concat(PyObject *self, PyObject *v)
"No __add__ or __concat__ methods, or maybe I'm just being stupid."
);
return
NULL
;
}
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
concat_by_name
)
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
concat_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS_ASSIGN
(
m
,
((
CMethod
*
)
m
)
->
type
->
tp_as_sequence
->
sq_concat
(
self
,
v
))
UNLESS_ASSIGN
(
m
,
AsCMethod
(
m
)
->
type
->
tp_as_sequence
->
sq_concat
(
self
,
v
))
return
NULL
;
}
else
...
...
@@ -1633,10 +2089,11 @@ subclass_repeat(PyObject *self, int v)
{
PyObject
*
m
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__repeat__"
))
return
NULL
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
repeat_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__repeat__
))
return
NULL
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
repeat_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
UNLESS_ASSIGN
(
m
,
((
CMethod
*
)
m
)
->
type
->
tp_as_sequence
->
sq_repeat
(
self
,
v
))
UNLESS_ASSIGN
(
m
,
AsCMethod
(
m
)
->
type
->
tp_as_sequence
->
sq_repeat
(
self
,
v
))
return
NULL
;
}
else
...
...
@@ -1662,11 +2119,12 @@ subclass_subscript(PyObject *self, PyObject *key)
PyObject
*
m
;
PyExtensionClass
*
t
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__getitem__"
))
return
NULL
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
(
PyCFunction
)
getitem_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__getitem__
))
return
NULL
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
(
PyCFunction
)
getitem_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
t
=
(
PyExtensionClass
*
)
((
CMethod
*
)
m
)
->
type
;
t
=
(
PyExtensionClass
*
)
AsCMethod
(
m
)
->
type
;
if
(
t
->
tp_as_mapping
&&
t
->
tp_as_mapping
->
mp_subscript
)
{
Py_DECREF
(
m
);
...
...
@@ -1687,11 +2145,12 @@ subclass_ass_subscript(PyObject *self, PyObject *index, PyObject *v)
PyObject
*
m
;
PyExtensionClass
*
t
;
UNLESS
(
m
=
PyObject_GetAttrString
(
self
,
"__setitem__"
))
return
-
1
;
if
(
m
->
ob_type
==&
CMethodType
&&
((
CMethod
*
)
m
)
->
meth
==
(
PyCFunction
)
setitem_by_name
)
UNLESS
(
m
=
subclass_getspecial
(
self
,
py__setitem__
))
return
-
1
;
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
(
PyCFunction
)
setitem_by_name
&&
SubclassInstance_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
t
=
(
PyExtensionClass
*
)
((
CMethod
*
)
m
)
->
type
;
t
=
(
PyExtensionClass
*
)
AsCMethod
(
m
)
->
type
;
if
(
t
->
tp_as_sequence
&&
t
->
tp_as_mapping
->
mp_ass_subscript
)
{
Py_DECREF
(
m
);
...
...
@@ -1723,11 +2182,11 @@ dealloc_base(PyObject *inst, PyExtensionClass* self)
for
(
i
=
0
;
i
<
l
;
i
++
)
{
t
=
PyTuple_GET_ITEM
(
self
->
bases
,
i
);
if
(
t
->
ob_type
==
(
PyTypeObject
*
)
&
CCLtype
)
if
(
PyExtensionClass_Check
(
t
)
)
{
if
(
((
PyExtensionClass
*
)
t
)
->
bases
)
if
(
AsPyExtensionClass
(
t
)
->
bases
)
{
if
(
dealloc_base
(
inst
,
(
PyExtensionClass
*
)
t
))
return
1
;
if
(
dealloc_base
(
inst
,
AsPyExtensionClass
(
t
)
))
return
1
;
}
else
{
...
...
@@ -1749,7 +2208,7 @@ subclass_dealloc(PyObject *self)
PyErr_Fetch
(
&
t
,
&
v
,
&
tb
);
if
(
m
=
PyObject_GetAttrString
(
self
,
"__del__"
))
if
(
m
=
subclass_getspecial
(
self
,
py__del__
))
PyObject_CallFunction
(
m
,
""
);
PyErr_Clear
();
...
...
@@ -1775,14 +2234,14 @@ datafull_baseclasses(PyExtensionClass *type)
for
(
i
=
0
;
i
<
l
;
i
++
)
{
base
=
PyTuple_GET_ITEM
(
type
->
bases
,
i
);
if
(
base
->
ob_type
==
(
PyTypeObject
*
)
&
CCLtype
)
if
(
PyExtensionClass_Check
(
base
)
)
{
if
(
((
PyExtensionClass
*
)
base
->
ob_typ
e
)
->
bases
)
n
+=
datafull_baseclasses
(
(
PyExtensionClass
*
)
base
);
if
(
AsPyExtensionClass
(
bas
e
)
->
bases
)
n
+=
datafull_baseclasses
(
AsPyExtensionClass
(
base
)
);
else
{
if
(
((
PyExtensionClass
*
)
base
)
->
tp_basicsize
>
sizeof
(
Dataless
)
||
((
PyExtensionClass
*
)
base
)
->
tp_itemsize
>
0
)
if
(
AsPyExtensionClass
(
base
)
->
tp_basicsize
>
sizeof
(
Dataless
)
||
AsPyExtensionClass
(
base
)
->
tp_itemsize
>
0
)
n
++
;
}
}
...
...
@@ -1803,17 +2262,17 @@ datafull_baseclass(PyExtensionClass *type)
for
(
i
=
0
;
i
<
l
;
i
++
)
{
base
=
PyTuple_GET_ITEM
(
type
->
bases
,
i
);
if
(
base
->
ob_type
==
(
PyTypeObject
*
)
&
CCLtype
)
if
(
PyExtensionClass_Check
(
base
)
)
{
if
(
((
PyExtensionClass
*
)
base
->
ob_typ
e
)
->
bases
)
if
(
AsPyExtensionClass
(
bas
e
)
->
bases
)
{
if
(
dbase
=
datafull_baseclass
(
(
PyExtensionClass
*
)
base
))
if
(
dbase
=
datafull_baseclass
(
AsPyExtensionClass
(
base
)
))
return
dbase
;
}
else
{
if
(
((
PyExtensionClass
*
)
base
)
->
tp_basicsize
>
sizeof
(
Dataless
)
||
((
PyExtensionClass
*
)
base
)
->
tp_itemsize
>
0
)
if
(
AsPyExtensionClass
(
base
)
->
tp_basicsize
>
sizeof
(
Dataless
)
||
AsPyExtensionClass
(
base
)
->
tp_itemsize
>
0
)
return
base
;
}
}
...
...
@@ -1822,11 +2281,11 @@ datafull_baseclass(PyExtensionClass *type)
}
static
int
subclass_hasattr
(
PyExtensionClass
*
type
,
char
*
name
)
subclass_hasattr
(
PyExtensionClass
*
type
,
PyObject
*
name
)
{
PyObject
*
o
;
if
(
o
=
CCL_getattr
(
type
,
name
))
if
(
o
=
CCL_getattr
o
(
type
,
name
))
{
Py_DECREF
(
o
);
return
1
;
...
...
@@ -1838,56 +2297,135 @@ subclass_hasattr(PyExtensionClass *type, char *name)
static
int
has_number_methods
(
PyExtensionClass
*
type
)
{
return
(
subclass_hasattr
(
type
,
"__add__"
)
||
subclass_hasattr
(
type
,
"__sub__"
)
||
subclass_hasattr
(
type
,
"__mul__"
)
||
subclass_hasattr
(
type
,
"__div__"
)
||
subclass_hasattr
(
type
,
"__mod__"
)
||
subclass_hasattr
(
type
,
"__pow__"
)
||
subclass_hasattr
(
type
,
"__divmod__"
)
||
subclass_hasattr
(
type
,
"__lshift__"
)
||
subclass_hasattr
(
type
,
"__rshift__"
)
||
subclass_hasattr
(
type
,
"__and__"
)
||
subclass_hasattr
(
type
,
"__or__"
)
||
subclass_hasattr
(
type
,
"__xor__"
)
||
subclass_hasattr
(
type
,
"__coerce__"
)
||
subclass_hasattr
(
type
,
"__neg__"
)
||
subclass_hasattr
(
type
,
"__pos__"
)
||
subclass_hasattr
(
type
,
"__abs__"
)
||
subclass_hasattr
(
type
,
"__nonzero__"
)
||
subclass_hasattr
(
type
,
"__inv__"
)
||
subclass_hasattr
(
type
,
"__int__"
)
||
subclass_hasattr
(
type
,
"__long__"
)
||
subclass_hasattr
(
type
,
"__float__"
)
||
subclass_hasattr
(
type
,
"__oct__"
)
||
subclass_hasattr
(
type
,
"__hex__"
)
return
(
subclass_hasattr
(
type
,
py__add__
)
||
subclass_hasattr
(
type
,
py__sub__
)
||
subclass_hasattr
(
type
,
py__mul__
)
||
subclass_hasattr
(
type
,
py__div__
)
||
subclass_hasattr
(
type
,
py__mod__
)
||
subclass_hasattr
(
type
,
py__pow__
)
||
subclass_hasattr
(
type
,
py__divmod__
)
||
subclass_hasattr
(
type
,
py__lshift__
)
||
subclass_hasattr
(
type
,
py__rshift__
)
||
subclass_hasattr
(
type
,
py__and__
)
||
subclass_hasattr
(
type
,
py__or__
)
||
subclass_hasattr
(
type
,
py__xor__
)
||
subclass_hasattr
(
type
,
py__coerce__
)
||
subclass_hasattr
(
type
,
py__neg__
)
||
subclass_hasattr
(
type
,
py__pos__
)
||
subclass_hasattr
(
type
,
py__abs__
)
||
subclass_hasattr
(
type
,
py__nonzero__
)
||
subclass_hasattr
(
type
,
py__inv__
)
||
subclass_hasattr
(
type
,
py__int__
)
||
subclass_hasattr
(
type
,
py__long__
)
||
subclass_hasattr
(
type
,
py__float__
)
||
subclass_hasattr
(
type
,
py__oct__
)
||
subclass_hasattr
(
type
,
py__hex__
)
);
}
static
int
has_collection_methods
(
PyExtensionClass
*
type
)
{
return
(
subclass_hasattr
(
type
,
"__getitem__"
)
||
subclass_hasattr
(
type
,
"__setitem__"
)
||
subclass_hasattr
(
type
,
"__getslice__"
)
||
subclass_hasattr
(
type
,
"__setslice__"
)
||
subclass_hasattr
(
type
,
"__concat__"
)
||
subclass_hasattr
(
type
,
"__repeat__"
)
||
subclass_hasattr
(
type
,
"__len__"
)
return
(
subclass_hasattr
(
type
,
py__getitem__
)
||
subclass_hasattr
(
type
,
py__setitem__
)
||
subclass_hasattr
(
type
,
py__getslice__
)
||
subclass_hasattr
(
type
,
py__setslice__
)
||
subclass_hasattr
(
type
,
py__concat__
)
||
subclass_hasattr
(
type
,
py__repeat__
)
||
subclass_hasattr
(
type
,
py__len__
)
);
}
static
void
subclass_init_getattr
(
PyExtensionClass
*
self
,
PyObject
*
methods
)
{
PyObject
*
m
;
if
((
m
=
CCL_getattr
(
self
,
py__getattr__
,
"__getattr__"
)))
{
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
getattr_by_name
&&
Subclass_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
self
->
tp_getattr
=
AsCMethod
(
m
)
->
type
->
tp_getattr
;
}
#if PYTHON_API_VERSION >= 1005
else
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
getattro_by_name
&&
Subclass_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
self
->
tp_getattro
=
AsCMethod
(
m
)
->
type
->
tp_getattro
;
}
#endif
else
{
PyDict_SetItem
(
methods
,
py__getattr__
,
m
);
#if PYTHON_API_VERSION >= 1005
self
->
tp_getattro
=
subclass_getattro
;
#else
self
->
tp_getattr
=
subclass_getattr
;
#endif
}
}
else
{
PyErr_Clear
();
#if PYTHON_API_VERSION >= 1005
self
->
tp_getattro
=
EC_findiattro
;
#else
self
->
tp_getattr
=
EC_findiattrs
;
#endif
}
}
static
void
subclass_init_setattr
(
PyExtensionClass
*
self
,
PyObject
*
methods
)
{
PyObject
*
m
;
if
((
m
=
CCL_getattr
(
self
,
py__setattr__
,
"__setattr__"
)))
{
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
setattr_by_name
&&
Subclass_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
self
->
tp_setattr
=
AsCMethod
(
m
)
->
type
->
tp_setattr
;
}
#if PYTHON_API_VERSION >= 1005
else
if
(
UnboundCMethod_Check
(
m
)
&&
AsCMethod
(
m
)
->
meth
==
setattro_by_name
&&
Subclass_Check
(
self
,
AsCMethod
(
m
)
->
type
))
{
self
->
tp_setattro
=
AsCMethod
(
m
)
->
type
->
tp_setattro
;
}
#endif
else
{
PyDict_SetItem
(
methods
,
py__setattr__
,
m
);
#if PYTHON_API_VERSION >= 1005
self
->
tp_setattro
=
subclass_setattro
;
#else
self
->
tp_setattr
=
subclass_setattr
;
#endif
}
}
else
{
PyErr_Clear
();
#if PYTHON_API_VERSION >= 1005
self
->
tp_setattro
=
subclass_simple_setattro
;
#else
self
->
tp_setattro
=
subclass_simple_setattr
;
#endif
}
}
/* Constructor for building subclasses of C classes.
That is, we want to build a C class object that described a
subclass of a built-in type.
*/
static
PyObject
*
subclass__init__
(
self
,
args
)
PyExtensionClass
*
self
;
PyObject
*
args
;
subclass__init__
(
PyExtensionClass
*
self
,
PyObject
*
args
)
{
PyObject
*
bases
,
*
methods
;
PyObject
*
bases
,
*
methods
,
*
class_init
;
PyExtensionClass
*
type
;
char
*
name
;
int
dynamic
=
1
;
...
...
@@ -1932,9 +2470,10 @@ subclass__init__(self,args)
copy_member
(
tp_itemsize
);
copy_member
(
tp_print
);
copy_member
(
tp_getattr
);
self
->
tp_dealloc
=
subclass_dealloc
;
self
->
tp_setattr
=
subclass_setattr
;
subclass_init_getattr
(
self
,
methods
);
subclass_init_setattr
(
self
,
methods
);
#define subclass_set(OP,N) \
self->tp_ ##OP = subclass_ ##OP
...
...
@@ -1942,8 +2481,8 @@ subclass__init__(self,args)
subclass_set
(
compare
,
cmp
);
subclass_set
(
repr
,
repr
);
if
(
subclass_hasattr
(
self
,
"__bind_to_object__"
)
&&
subclass_hasattr
(
self
,
"__call__"
))
if
(
subclass_hasattr
(
self
,
py__bind_to_object__
)
&&
subclass_hasattr
(
self
,
py__call__
))
self
->
class_flags
|=
EXTENSIONCLASS_BINDABLE_FLAG
;
if
(
dynamic
||
has_number_methods
(
self
))
...
...
@@ -1965,6 +2504,19 @@ subclass__init__(self,args)
subclass_set
(
call
,
call
);
subclass_set
(
str
,
str
);
self
->
tp_doc
=
0
;
/* Check for and use __class_init__ */
if
(
class_init
=
PyObject_GetAttrString
(
AsPyObject
(
self
),
"__class_init__"
))
{
UNLESS_ASSIGN
(
class_init
,
PyObject_GetAttrString
(
class_init
,
"im_func"
))
return
NULL
;
UNLESS_ASSIGN
(
class_init
,
PyObject_CallFunction
(
class_init
,
"O"
,
self
))
return
NULL
;
Py_DECREF
(
class_init
);
}
else
PyErr_Clear
();
Py_INCREF
(
Py_None
);
return
Py_None
;
}
...
...
@@ -1985,8 +2537,8 @@ static PyExtensionClass CCLtype = {
/* methods */
(
destructor
)
CCL_dealloc
,
/*tp_dealloc*/
(
printfunc
)
0
,
/*tp_print*/
(
getattrfunc
)
CCL_getattr
,
/*tp_getattr*/
(
setattrfunc
)
CCL_setattr
,
/*tp_setattr*/
(
getattrfunc
)
CCL_getattr
s
,
/*tp_getattr*/
(
setattrfunc
)
CCL_setattr
s
,
/*tp_setattr*/
(
cmpfunc
)
0
,
/*tp_compare*/
(
reprfunc
)
CCL_repr
,
/*tp_repr*/
0
,
/*tp_as_number*/
...
...
@@ -1995,9 +2547,14 @@ static PyExtensionClass CCLtype = {
(
hashfunc
)
0
,
/*tp_hash*/
(
ternaryfunc
)
CCL_call
,
/*tp_call*/
(
reprfunc
)
0
,
/*tp_str*/
#if PYTHON_API_VERSION >= 1005
(
getattrofunc
)
CCL_getattro
,
/*tp_getattr with object key*/
(
setattrofunc
)
CCL_setattro
,
/*tp_setattr with object key*/
#else
/* Space for future expansion */
0L
,
0L
,
0L
,
0L
,
0L
,
0L
,
#endif
0L
,
0L
,
"C classes"
,
/* Documentation string */
METHOD_CHAIN
(
ExtensionClass_methods
)
};
...
...
@@ -2011,7 +2568,7 @@ static PyExtensionClass Basetype = {
/* methods */
(
destructor
)
0
,
/*tp_dealloc*/
(
printfunc
)
0
,
/*tp_print*/
(
getattrfunc
)
E
xtensionClass_FindInstanceAttribute
,
/*tp_getattr*/
(
getattrfunc
)
E
C_findiattrs
,
/*tp_getattr*/
(
setattrfunc
)
0
,
/*tp_setattr*/
(
cmpfunc
)
0
,
/*tp_compare*/
(
reprfunc
)
0
,
/*tp_repr*/
...
...
@@ -2021,9 +2578,14 @@ static PyExtensionClass Basetype = {
(
hashfunc
)
0
,
/*tp_hash*/
(
ternaryfunc
)
0
,
/*tp_call*/
(
reprfunc
)
0
,
/*tp_str*/
#if PYTHON_API_VERSION >= 1005
(
getattrofunc
)
EC_findiattro
,
/*tp_getattr with object key*/
(
setattrofunc
)
0
,
/*tp_setattr with object key*/
#else
/* Space for future expansion */
0L
,
0L
,
0L
,
0L
,
0L
,
0L
,
#endif
0L
,
0L
,
"Base -- a do nothing base class
\n
"
"
\n
"
"A trivial base class that doesn't have any inheritable
\n
"
...
...
@@ -2032,6 +2594,79 @@ static PyExtensionClass Basetype = {
{
NULL
,
NULL
}
};
static
PyObject
*
bind_to_object
(
PyObject
*
self
,
PyObject
*
args
)
{
PyObject
*
inst
;
PMethod
*
r
;
UNLESS
(
PyArg_Parse
(
args
,
"O"
,
&
inst
))
return
NULL
;
UNLESS
(
PyExtensionInstance_Check
(
inst
))
{
PyErr_SetString
(
PyExc_TypeError
,
"attempt to wrap extension method using an object that
\n
"
"is not an extension class instance."
);
return
NULL
;
}
UNLESS
(
r
=
PyObject_NEW
(
PMethod
,
&
PMethodType
))
return
NULL
;
Py_INCREF
(
inst
);
Py_INCREF
(
inst
->
ob_type
);
r
->
type
=
inst
->
ob_type
;
r
->
self
=
inst
;
r
->
meth
=
self
;
return
AsPyObject
(
r
);
}
struct
PyMethodDef
Method_methods
[]
=
{
{
"__bind_to_object__"
,(
PyCFunction
)
bind_to_object
,
0
,
""
},
{
NULL
,
NULL
}
/* sentinel */
};
static
PyExtensionClass
Methodtype
=
{
PyObject_HEAD_INIT
(
&
PyType_Type
)
0
,
/*ob_size*/
"Method"
,
/*tp_name*/
sizeof
(
Dataless
),
/*tp_basicsize*/
0
,
/*tp_itemsize*/
/* methods */
(
destructor
)
0
,
/*tp_dealloc*/
(
printfunc
)
0
,
/*tp_print*/
(
getattrfunc
)
EC_findiattrs
,
/*tp_getattr*/
(
setattrfunc
)
0
,
/*tp_setattr*/
(
cmpfunc
)
0
,
/*tp_compare*/
(
reprfunc
)
0
,
/*tp_repr*/
0
,
/*tp_as_number*/
0
,
/*tp_as_sequence*/
0
,
/*tp_as_mapping*/
(
hashfunc
)
0
,
/*tp_hash*/
(
ternaryfunc
)
0
,
/*tp_call*/
(
reprfunc
)
0
,
/*tp_str*/
#if PYTHON_API_VERSION >= 1005
(
getattrofunc
)
EC_findiattro
,
/*tp_getattr with object key*/
(
setattrofunc
)
0
,
/*tp_setattr with object key*/
#else
/* Space for future expansion */
0L
,
0L
,
#endif
0L
,
0L
,
"Base class for objects that want to be treated as methods
\n
"
"
\n
"
"The method class provides a method, __bind_to_object__, that
\n
"
"binds an object to an instance. If a method is a subobject
\n
"
"of an extension-class instance, the the method will be bound
\n
"
"to the instance and when the resulting object is called, it
\n
"
"will call the method and pass the instance in addition to
\n
"
"other arguments. It is the responsibility of Method objects
\n
"
"to implement (or inherit) a __call__ method.
\n
"
,
METHOD_CHAIN
(
Method_methods
)
};
PyObject
*
MetaTypeUndefinedMethod
()
...
...
@@ -2063,14 +2698,30 @@ initExtensionClass()
/* Add some symbolic constants to the module */
d
=
PyModule_GetDict
(
m
);
init_py_names
();
initializeBaseExtensionClass
(
&
CCLtype
);
PyDict_SetItemString
(
d
,
"ExtensionClassType"
,
(
PyObject
*
)
&
CCLtype
);
initializeBaseExtensionClass
(
&
Basetype
);
PyDict_SetItemString
(
d
,
"Base"
,
(
PyObject
*
)
&
Basetype
);
initializeBaseExtensionClass
(
&
Methodtype
);
PyDict_SetItemString
(
d
,
"Method"
,
(
PyObject
*
)
&
Methodtype
);
#ifdef Py_COBJECT_H
/* Export C attribute lookup API */
PyDict_SetItemString
(
d
,
"_PyEC_getattrs"
,
PyCObject_FromVoidPtr
(
EC_findiattrs
,
NULL
));
PyDict_SetItemString
(
d
,
"_PyEC_getattro"
,
PyCObject_FromVoidPtr
(
EC_findiattro
,
NULL
));
PyDict_SetItemString
(
d
,
"_PyEC_setattrs"
,
PyCObject_FromVoidPtr
(
subclass_simple_setattr
,
NULL
));
PyDict_SetItemString
(
d
,
"_PyEC_setattro"
,
PyCObject_FromVoidPtr
(
subclass_simple_setattro
,
NULL
));
#endif
/* Check for errors */
if
(
PyErr_Occurred
())
Py_FatalError
(
"can't initialize module ExtensionClass"
);
}
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