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
bb3bf699
Commit
bb3bf699
authored
Apr 11, 1997
by
Jim Fulton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Got rid of class attributes.
Added method hooks.
parent
d864f6e4
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
498 additions
and
198 deletions
+498
-198
lib/Components/ExtensionClass/ExtensionClass.c
lib/Components/ExtensionClass/ExtensionClass.c
+205
-92
lib/Components/ExtensionClass/ExtensionClass.h
lib/Components/ExtensionClass/ExtensionClass.h
+44
-7
lib/Components/ExtensionClass/src/ExtensionClass.c
lib/Components/ExtensionClass/src/ExtensionClass.c
+205
-92
lib/Components/ExtensionClass/src/ExtensionClass.h
lib/Components/ExtensionClass/src/ExtensionClass.h
+44
-7
No files found.
lib/Components/ExtensionClass/ExtensionClass.c
View file @
bb3bf699
/*
$Id: ExtensionClass.c,v 1.
8 1997/03/08 12:44:31
jim Exp $
$Id: ExtensionClass.c,v 1.
9 1997/04/11 21:47:05
jim Exp $
Extension Class
Copyright
Copyright 1996 Digital Creations, L.C., 910 Princess Anne
...
...
@@ -50,45 +49,11 @@
If you have questions regarding this software,
contact:
Jim Fulton, jim@digicool.com
Digital Creations L.C.
info@digicool.com
(540) 371-6909
$Log: ExtensionClass.c,v $
Revision 1.8 1997/03/08 12:44:31 jim
Moved INSTANCE_DICT macro to public interface.
Revision 1.7 1997/02/24 23:17:47 jim
Fixed bug in subclass_nonzero.
Revision 1.6 1997/02/24 15:43:57 jim
Added __version__ string.
Revision 1.5 1997/02/17 16:27:53 jim
Many changes.
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.
Revision 1.2 1996/10/23 18:36:56 jim
Changed a bunch of single quotes to double and got rid of
some superfluous semicolns that caused warning on SGI.
Fixed bug in CCL_getattr when getting the __base__ attribute of a base
class.
Fixed a doc string.
Revision 1.1 1996/10/22 22:26:08 jim
*** empty log message ***
*/
static
char
ExtensionClass_module_documentation
[]
=
...
...
@@ -100,7 +65,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.
8 1997/03/08 12:44:31
jim Exp $
\n
"
"$Id: ExtensionClass.c,v 1.
9 1997/04/11 21:47:05
jim Exp $
\n
"
;
#include <stdio.h>
...
...
@@ -118,7 +83,6 @@ PyVar_Assign(PyObject **v, PyObject *e)
#define UNLESS(E) if(!(E))
#define UNLESS_ASSIGN(V,E) ASSIGN(V,E); UNLESS(V)
/* Declarations for objects of type ExtensionClass */
#include "ExtensionClass.h"
...
...
@@ -134,15 +98,20 @@ staticforward PyExtensionClass ECType;
((O)->ob_type->ob_type == (PyTypeObject*)&ECType && \
(((PyExtensionClass*)((O)->ob_type))->class_flags & \
EXTENSIONCLASS_BINDABLE_FLAG))
#define HasMethodHook(O) \
((O)->ob_type->ob_type == (PyTypeObject*)&ECType && \
(((PyExtensionClass*)((O)->ob_type))->class_flags & \
EXTENSIONCLASS_METHODHOOK_FLAG))
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__of__
,
*
py__call__
,
*
py__call_method__
,
*
py__getitem__
,
*
py__setitem__
,
*
py__delitem__
,
*
py__getslice__
,
*
py__setslice__
,
*
py__delslice__
,
*
py__concat__
,
*
py__repeat__
,
*
py__len__
,
*
py__of__
,
*
py__call__
,
*
py__concat__
,
*
py__repeat__
,
*
py__len__
,
*
py__getattr__
,
*
py__setattr__
,
*
py__delattr__
,
*
py__del__
,
*
py__repr__
,
*
py__str__
,
*
py__class__
,
*
py__hash__
,
*
py__cmp__
,
*
py__var_size__
,
*
py__init__
,
*
py__getinitargs__
,
...
...
@@ -186,6 +155,7 @@ init_py_names()
INIT_PY_NAME
(
__len__
);
INIT_PY_NAME
(
__of__
);
INIT_PY_NAME
(
__call__
);
INIT_PY_NAME
(
__call_method__
);
INIT_PY_NAME
(
__getattr__
);
INIT_PY_NAME
(
__setattr__
);
INIT_PY_NAME
(
__delattr__
);
...
...
@@ -348,12 +318,54 @@ call_cmethod(CMethod *self, PyObject *inst, PyObject *args, PyObject *kw)
}
}
static
char
*
hook_mark
=
"C method being called through a hook."
;
static
PyObject
*
callCMethodWithHook
(
CMethod
*
self
,
PyObject
*
inst
,
PyObject
*
args
,
PyObject
*
kw
)
{
PyObject
*
hook
,
*
m
;
UNLESS
(
m
=
newCMethod
(
AsExtensionClass
(
self
->
type
),
inst
,
self
->
name
,
self
->
meth
,
self
->
flags
,
hook_mark
))
return
NULL
;
if
(
hook
=
PyObject_GetAttr
(
inst
,
py__call_method__
))
{
if
(
CMethod_Check
(
hook
)
&&
((
CMethod
*
)
hook
)
->
meth
==
self
->
meth
)
{
/* Oops, we are already calling the hook! */
Py_DECREF
(
hook
);
return
PyEval_CallObjectWithKeywords
(
m
,
args
,
kw
);
}
if
(
kw
)
ASSIGN
(
hook
,
PyObject_CallFunction
(
hook
,
"OOO"
,
m
,
args
,
kw
));
else
ASSIGN
(
hook
,
PyObject_CallFunction
(
hook
,
"OO"
,
m
,
args
));
}
else
{
PyErr_Clear
();
hook
=
PyEval_CallObjectWithKeywords
(
m
,
args
,
kw
);
}
Py_DECREF
(
m
);
return
hook
;
}
static
PyObject
*
CMethod_call
(
CMethod
*
self
,
PyObject
*
args
,
PyObject
*
kw
)
{
int
size
;
if
(
self
->
self
)
return
call_cmethod
(
self
,
self
->
self
,
args
,
kw
);
if
(
self
->
self
)
{
if
(
HasMethodHook
(
self
->
self
)
&&
self
->
doc
!=
hook_mark
/* This check prevents infinite recursion */
)
return
callCMethodWithHook
(
self
,
self
->
self
,
args
,
kw
);
return
call_cmethod
(
self
,
self
->
self
,
args
,
kw
);
}
if
((
size
=
PyTuple_Size
(
args
))
>
0
)
{
...
...
@@ -369,6 +381,10 @@ CMethod_call(CMethod *self, PyObject *args, PyObject *kw)
);
{
PyObject
*
rest
=
0
;
if
(
HasMethodHook
(
first
)
&&
self
->
doc
!=
hook_mark
/* This check prevents infinite recursion */
)
return
callCMethodWithHook
(
self
,
first
,
args
,
kw
);
UNLESS
(
rest
=
PySequence_GetSlice
(
args
,
1
,
size
))
return
NULL
;
ASSIGN
(
rest
,
call_cmethod
(
self
,
first
,
rest
,
kw
));
return
rest
;
...
...
@@ -527,6 +543,32 @@ PMethod_dealloc(PMethod *self)
#endif
}
static
PyObject
*
callMethodWithPossibleHook
(
PyObject
*
inst
,
PyObject
*
meth
,
PyObject
*
args
,
PyObject
*
kw
)
{
if
(
HasMethodHook
(
inst
))
{
PyObject
*
hook
;
if
(
hook
=
PyObject_GetAttr
(
inst
,
py__call_method__
))
{
if
(
PMethod_Check
(
hook
)
&&
((
PMethod
*
)
hook
)
->
meth
==
meth
)
{
/* Oops, we are already calling the hook! */
Py_DECREF
(
hook
);
return
PyEval_CallObjectWithKeywords
(
meth
,
args
,
kw
);
}
if
(
kw
)
ASSIGN
(
hook
,
PyObject_CallFunction
(
hook
,
"OOO"
,
meth
,
args
,
kw
));
else
ASSIGN
(
hook
,
PyObject_CallFunction
(
hook
,
"OO"
,
meth
,
args
));
return
hook
;
}
PyErr_Clear
();
}
return
PyEval_CallObjectWithKeywords
(
meth
,
args
,
kw
);
}
static
PyObject
*
call_PMethod
(
PMethod
*
self
,
PyObject
*
inst
,
PyObject
*
args
,
PyObject
*
kw
)
{
...
...
@@ -534,7 +576,7 @@ call_PMethod(PMethod *self, PyObject *inst, PyObject *args, PyObject *kw)
a
=
Py_BuildValue
(
"(O)"
,
inst
);
if
(
a
)
ASSIGN
(
a
,
PySequence_Concat
(
a
,
args
));
if
(
a
)
ASSIGN
(
a
,
PyEval_CallObjectWithKeywords
(
self
->
meth
,
a
,
kw
));
if
(
a
)
ASSIGN
(
a
,
callMethodWithPossibleHook
(
inst
,
self
->
meth
,
a
,
kw
));
return
a
;
}
...
...
@@ -571,12 +613,12 @@ PMethod_call(PMethod *self, PyObject *args, PyObject *kw)
Py_DECREF
(
r
);
return
NULL
;
}
ASSIGN
(
r
,
PyEval_CallObjectWithKeywords
(
r
,
rest
,
kw
));
ASSIGN
(
r
,
callMethodWithPossibleHook
(
first
,
r
,
rest
,
kw
));
Py_DECREF
(
rest
);
return
r
;
}
Py_DECREF
(
ftype
);
return
PyEval_CallObjectWithKeywords
(
self
->
meth
,
args
,
kw
);
return
callMethodWithPossibleHook
(
first
,
self
->
meth
,
args
,
kw
);
}
Py_XDECREF
(
ftype
);
}
...
...
@@ -695,7 +737,7 @@ setattr_by_name(PyObject *self, PyObject *args)
{
char
*
name
;
PyObject
*
v
;
UNLESS
(
PyArg_Parse
(
args
,
"sO"
,
&
name
,
&
v
))
return
NULL
;
UNLESS
(
PyArg_Parse
Tuple
(
args
,
"sO"
,
&
name
,
&
v
))
return
NULL
;
UNLESS
(
-
1
!=
self
->
ob_type
->
tp_setattr
(
self
,
name
,
v
))
return
NULL
;
Py_INCREF
(
Py_None
);
return
Py_None
;
...
...
@@ -714,7 +756,7 @@ setattro_by_name(PyObject *self, PyObject *args)
{
PyObject
*
name
;
PyObject
*
v
;
UNLESS
(
PyArg_Parse
(
args
,
"OO"
,
&
name
,
&
v
))
return
NULL
;
UNLESS
(
PyArg_Parse
Tuple
(
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
;
...
...
@@ -763,7 +805,7 @@ setitem_by_name(PyObject *self, PyObject *args)
PyObject
*
key
,
*
v
;
long
r
;
UNLESS
(
PyArg_Parse
(
args
,
"OO"
,
&
key
,
&
v
))
return
NULL
;
UNLESS
(
PyArg_Parse
Tuple
(
args
,
"OO"
,
&
key
,
&
v
))
return
NULL
;
if
(
self
->
ob_type
->
tp_as_mapping
)
r
=
self
->
ob_type
->
tp_as_mapping
->
mp_ass_subscript
(
self
,
key
,
v
);
else
...
...
@@ -785,7 +827,7 @@ slice_by_name(PyObject *self, PyObject *args)
{
int
i1
,
i2
;
UNLESS
(
PyArg_Parse
(
args
,
"ii"
,
&
i1
,
&
i2
))
return
NULL
;
UNLESS
(
PyArg_Parse
Tuple
(
args
,
"ii"
,
&
i1
,
&
i2
))
return
NULL
;
return
self
->
ob_type
->
tp_as_sequence
->
sq_slice
(
self
,
i1
,
i2
);
}
...
...
@@ -796,7 +838,7 @@ ass_slice_by_name(PyObject *self, PyObject *args)
PyObject
*
v
;
long
r
;
UNLESS
(
PyArg_Parse
(
args
,
"iiO"
,
&
i1
,
&
i2
,
&
v
))
return
NULL
;
UNLESS
(
PyArg_Parse
Tuple
(
args
,
"iiO"
,
&
i1
,
&
i2
,
&
v
))
return
NULL
;
r
=
self
->
ob_type
->
tp_as_sequence
->
sq_ass_slice
(
self
,
i1
,
i2
,
v
);
if
(
r
<
0
)
return
NULL
;
Py_INCREF
(
Py_None
);
...
...
@@ -914,9 +956,9 @@ getBaseDictionary(PyExtensionClass *type)
FILLENTRY
(
type
->
tp
,
call
,
call
,
2
,
"call as a function"
);
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"
);
FILLENTRY
(
type
->
tp
,
setattr
,
setattr
,
1
,
"Set an attribute"
);
FILLENTRY
(
type
->
tp
,
getattro
,
getattr
,
0
,
"Get an attribute"
);
FILLENTRY
(
type
->
tp
,
setattro
,
setattr
,
0
,
"Set an attribute"
);
FILLENTRY
(
type
->
tp
,
setattro
,
setattr
,
1
,
"Set an attribute"
);
if
(
sm
=
type
->
tp_as_sequence
)
{
...
...
@@ -926,9 +968,9 @@ getBaseDictionary(PyExtensionClass *type)
FILLENTRY
(
sm
->
sq
,
repeat
,
repeat
,
0
,
"Get a new object that is the object repeated."
);
FILLENTRY
(
sm
->
sq
,
item
,
getitem
,
0
,
"Get an item"
);
FILLENTRY
(
sm
->
sq
,
slice
,
getslice
,
0
,
"Get a slice"
);
FILLENTRY
(
sm
->
sq
,
ass_item
,
setitem
,
0
,
"Assign an item"
);
FILLENTRY
(
sm
->
sq
,
ass_slice
,
setslice
,
0
,
"Assign a slice"
);
FILLENTRY
(
sm
->
sq
,
slice
,
getslice
,
1
,
"Get a slice"
);
FILLENTRY
(
sm
->
sq
,
ass_item
,
setitem
,
1
,
"Assign an item"
);
FILLENTRY
(
sm
->
sq
,
ass_slice
,
setslice
,
1
,
"Assign a slice"
);
}
if
(
mm
=
type
->
tp_as_mapping
)
...
...
@@ -1025,24 +1067,33 @@ err:
}
static
PyObject
*
inheritedAttribute
(
Py
ExtensionClass
*
self
,
PyObject
*
name
)
inheritedAttribute
(
Py
Object
*
self
,
PyObject
*
args
)
{
UNLESS
(
name
)
return
PyErr_Format
(
PyExc_TypeError
,
"expected one argument, and none given"
,
NULL
);
return
CCL_getattr
(
self
,
name
,
1
);
}
PyObject
*
cls
,
*
name
;
static
PyObject
*
inheritedClassAttribute
(
PyExtensionClass
*
self
,
PyObject
*
name
)
{
UNLESS
(
name
)
return
PyErr_Format
(
PyExc_TypeError
,
"expected one argument, and none given"
,
NULL
);
UNLESS
(
name
=
PySequence_Concat
(
pyclass_
,
name
))
return
NULL
;
UNLESS_ASSIGN
(
name
,
CCL_getattr
(
self
,
name
,
1
))
return
NULL
;
if
(
UnboundPMethod_Check
(
name
))
ASSIGN
(
name
,
bindPMethod
((
PMethod
*
)
name
,(
PyObject
*
)
self
));
UNLESS
(
PyArg_ParseTuple
(
args
,
"OO"
,
&
cls
,
&
name
));
UNLESS
(
ExtensionClass_Check
(
cls
))
{
PyErr_SetString
(
PyExc_TypeError
,
"inheritedAttribute must be called with an extension "
"class first argument"
);
return
NULL
;
}
UNLESS
(
PyString_Check
(
name
))
{
PyErr_SetString
(
PyExc_TypeError
,
"inheritedAttribute must be called with a "
"string second argument"
);
return
NULL
;
}
UNLESS
(
name
=
CCL_getattr
(
AsExtensionClass
(
cls
),
name
,
1
))
return
NULL
;
/* We got something from our class, maybe its an unbound method. */
if
(
UnboundCMethod_Check
(
name
))
ASSIGN
(
name
,(
PyObject
*
)
bindCMethod
((
CMethod
*
)
name
,
self
));
else
if
(
UnboundPMethod_Check
(
name
))
ASSIGN
(
name
,
bindPMethod
((
PMethod
*
)
name
,
self
));
return
name
;
}
...
...
@@ -1050,6 +1101,21 @@ struct PyMethodDef ECI_methods[] = {
{
"__reduce__"
,(
PyCFunction
)
EC_reduce
,
0
,
"__reduce__() -- Reduce an instance into it's class and creation data"
},
{
"inheritedAttribute"
,(
PyCFunction
)
inheritedAttribute
,
1
,
"inheritedAttribute(class,name) -- Get an inherited attribute
\n\n
"
"Get an attribute that would be inherited if the given (extension)
\n
"
"class did not define it. This method is used when overriding
\n
"
"inherited methods. It provides 2 advantages over accessing
\n
"
"
\n
"
"attributes directly through a superclass:
\n
"
"
\n
"
"1. The superclass need not be known,
\n
"
"
\n
"
"2. The superclass may be a Python class. Without this method, it would
\n
"
" be possible to override methods inherited from python classes because
\n
"
" unbound methods gotten from Python classes cannot be called with
\n
"
" extension class instances.
\n
"
},
{
NULL
,
NULL
}
/* sentinel */
};
...
...
@@ -1165,7 +1231,7 @@ ExtensionClass_FindInstanceAttribute(PyObject *inst, PyObject *oname,
Py_INCREF
(
self
);
return
(
PyObject
*
)
self
;
}
if
(
self
->
bases
&&
*
n
==
'd'
&&
strcmp
(
n
,
"dict__"
)
==
0
)
if
(
ClassHasInstDict
(
self
)
&&
*
n
==
'd'
&&
strcmp
(
n
,
"dict__"
)
==
0
)
{
r
=
INSTANCE_DICT
(
inst
);
Py_INCREF
(
r
);
...
...
@@ -1173,7 +1239,7 @@ ExtensionClass_FindInstanceAttribute(PyObject *inst, PyObject *oname,
}
}
if
(
self
->
bases
)
if
(
ClassHasInstDict
(
self
)
)
{
r
=
INSTANCE_DICT
(
inst
);
if
((
r
=
PyObject_GetItem
(
r
,
oname
))
&&
NeedsToBeBound
(
r
))
...
...
@@ -1278,6 +1344,15 @@ CCL_reduce(PyExtensionClass *self, PyObject *args)
return
PyString_FromString
(
self
->
tp_name
);
}
static
PyObject
*
obsolete_inheritedAttribute
(
PyExtensionClass
*
self
,
PyObject
*
name
)
{
UNLESS
(
name
)
return
PyErr_Format
(
PyExc_TypeError
,
"expected one argument, and none given"
,
NULL
);
return
CCL_getattr
(
self
,
name
,
1
);
}
PyObject
*
CCL_getattro
(
PyExtensionClass
*
self
,
PyObject
*
name
)
{
...
...
@@ -1330,19 +1405,11 @@ CCL_getattro(PyExtensionClass *self, PyObject *name)
if
(
strcmp
(
nm
,
"inheritedAttribute"
)
==
0
)
{
return
newCMethod
(
self
,(
PyObject
*
)
self
,
"inheritedAttribute"
,(
PyCFunction
)
inheritedAttribute
,
0
,
"inheritedAttribute"
,
(
PyCFunction
)
obsolete_inheritedAttribute
,
0
,
"look up an attribute in a class's super classes"
);
}
if
(
nm
&&
*
nm
++==
'c'
&&
*
nm
++==
'l'
&&
*
nm
++==
'a'
&&
*
nm
++==
's'
&&
*
nm
++==
's'
&&
*
nm
==
'_'
)
{
UNLESS
(
r
=
CCL_getattr
(
self
,
name
,
0
))
return
NULL
;
if
(
UnboundPMethod_Check
(
r
))
ASSIGN
(
r
,
bindPMethod
((
PMethod
*
)
r
,(
PyObject
*
)
self
));
return
r
;
}
if
(
r
=
CCL_getattr
(
self
,
name
,
0
))
return
r
;
return
NULL
;
...
...
@@ -1532,10 +1599,9 @@ CCL_call(PyExtensionClass *self, PyObject *arg, PyObject *kw)
}
Py_INCREF
(
self
);
if
(
self
->
bases
)
{
if
(
ClassHasInstDict
(
self
))
UNLESS
(
INSTANCE_DICT
(
inst
)
=
PyDict_New
())
goto
err
;
}
if
(
init
=
CCL_getattr
(
self
,
py__init__
,
0
))
{
...
...
@@ -2637,7 +2703,7 @@ subclass__init__(PyExtensionClass *self, PyObject *args)
char
*
name
,
*
p
;
int
dynamic
=
1
,
l
;
UNLESS
(
PyArg_Parse
(
args
,
"(sOO)
"
,
&
name
,
&
bases
,
&
methods
))
return
NULL
;
UNLESS
(
PyArg_Parse
Tuple
(
args
,
"sOO
"
,
&
name
,
&
bases
,
&
methods
))
return
NULL
;
l
=
strlen
(
name
)
+
1
;
UNLESS
(
p
=
(
char
*
)
malloc
(
l
*
sizeof
(
char
)))
return
PyErr_NoMemory
();
memcpy
(
p
,
name
,
l
);
...
...
@@ -2661,7 +2727,6 @@ subclass__init__(PyExtensionClass *self, PyObject *args)
UNLESS
(
type
=
(
PyExtensionClass
*
)
datafull_baseclass
(
self
))
UNLESS
(
type
=
(
PyExtensionClass
*
)
extension_baseclass
(
self
))
return
NULL
;
self
->
tp_name
=
name
;
UNLESS
(
self
->
class_dictionary
=
CopyMethods
(
type
,
methods
))
return
NULL
;
...
...
@@ -2696,6 +2761,12 @@ subclass__init__(PyExtensionClass *self, PyObject *args)
if
(
subclass_hasattr
(
self
,
py__of__
))
self
->
class_flags
|=
EXTENSIONCLASS_BINDABLE_FLAG
;
if
(
subclass_hasattr
(
self
,
py__call_method__
))
self
->
class_flags
|=
EXTENSIONCLASS_METHODHOOK_FLAG
;
UNLESS
(
self
->
class_flags
&
EXTENSIONCLASS_NOINSTDICT_FLAG
)
self
->
class_flags
|=
EXTENSIONCLASS_INSTDICT_FLAG
;
if
(
dynamic
||
has_number_methods
(
self
))
{
self
->
tp_as_number
=
(
PyNumberMethods
*
)
malloc
(
sizeof
(
PyNumberMethods
));
...
...
@@ -2727,9 +2798,11 @@ subclass__init__(PyExtensionClass *self, PyObject *args)
self
->
tp_doc
=
0
;
/* Check for and use __class_init__ */
if
(
class_init
=
PyObject_GetAttrString
(
AsPyObject
(
self
),
"
class_
_init__"
))
if
(
class_init
=
PyObject_GetAttrString
(
AsPyObject
(
self
),
"
__class
_init__"
))
{
UNLESS_ASSIGN
(
class_init
,
PyObject_CallObject
(
class_init
,
NULL
))
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
);
}
...
...
@@ -2741,7 +2814,7 @@ subclass__init__(PyExtensionClass *self, PyObject *args)
}
struct
PyMethodDef
ExtensionClass_methods
[]
=
{
{
"__init__"
,(
PyCFunction
)
subclass__init__
,
0
,
""
},
{
"__init__"
,(
PyCFunction
)
subclass__init__
,
1
,
""
},
{
NULL
,
NULL
}
/* sentinel */
};
...
...
@@ -2802,7 +2875,7 @@ void
initExtensionClass
()
{
PyObject
*
m
,
*
d
;
char
*
rev
=
"$Revision: 1.
8
$"
;
char
*
rev
=
"$Revision: 1.
9
$"
;
PURE_MIXIN_CLASS
(
Base
,
"Minimalbase class for Extension Classes"
,
NULL
);
PMethodType
.
ob_type
=&
PyType_Type
;
...
...
@@ -2836,3 +2909,43 @@ initExtensionClass()
CHECK_FOR_ERRORS
(
"can't initialize module ExtensionClass"
);
}
/****************************************************************************
$Log: ExtensionClass.c,v $
Revision 1.9 1997/04/11 21:47:05 jim
Got rid of class attributes.
Added method hooks.
Revision 1.8 1997/03/08 12:44:31 jim
Moved INSTANCE_DICT macro to public interface.
Revision 1.7 1997/02/24 23:17:47 jim
Fixed bug in subclass_nonzero.
Revision 1.6 1997/02/24 15:43:57 jim
Added __version__ string.
Revision 1.5 1997/02/17 16:27:53 jim
Many changes.
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.
Revision 1.2 1996/10/23 18:36:56 jim
Changed a bunch of single quotes to double and got rid of
some superfluous semicolns that caused warning on SGI.
Fixed bug in CCL_getattr when getting the __base__ attribute of a base
class.
Fixed a doc string.
Revision 1.1 1996/10/22 22:26:08 jim
*** empty log message ***
****************************************************************************/
lib/Components/ExtensionClass/ExtensionClass.h
View file @
bb3bf699
/*
$Id: ExtensionClass.h,v 1.
5 1997/03/08 12:44:13
jim Exp $
$Id: ExtensionClass.h,v 1.
6 1997/04/11 21:47:51
jim Exp $
Extension Class Definitions
...
...
@@ -113,6 +113,10 @@
$Log: ExtensionClass.h,v $
Revision 1.6 1997/04/11 21:47:51 jim
Got rid of class attributes.
Added method hooks.
Revision 1.5 1997/03/08 12:44:13 jim
Moved INSTANCE_DICT macro to public interface.
...
...
@@ -188,13 +192,33 @@ typedef struct {
*/
PyMethodChain
methods
;
/* You may set certain flags here. Only two flags are
defined at this point, the first of which is not currently
used.
*/
/* You may set certain flags here. */
long
class_flags
;
#define EXTENSIONCLASS_DYNAMIC_FLAG 1
#define EXTENSIONCLASS_BINDABLE_FLAG 2
/* The following flags are used by ExtensionClass */
#define EXTENSIONCLASS_DYNAMIC_FLAG 1 << 0
#define EXTENSIONCLASS_BINDABLE_FLAG 1 << 2
#define EXTENSIONCLASS_METHODHOOK_FLAG 1 << 3
#define EXTENSIONCLASS_INSTDICT_FLAG 1 << 4
#define EXTENSIONCLASS_NOINSTDICT_FLAG 1 << 5
/* The following flags are for use by extension class developers. */
#define EXTENSIONCLASS_USER_FLAG1 1 << 16
#define EXTENSIONCLASS_USER_FLAG2 1 << 17
#define EXTENSIONCLASS_USER_FLAG3 1 << 18
#define EXTENSIONCLASS_USER_FLAG4 1 << 19
#define EXTENSIONCLASS_USER_FLAG5 1 << 20
#define EXTENSIONCLASS_USER_FLAG6 1 << 21
#define EXTENSIONCLASS_USER_FLAG7 1 << 22
#define EXTENSIONCLASS_USER_FLAG8 1 << 23
#define EXTENSIONCLASS_USER_FLAG9 1 << 24
#define EXTENSIONCLASS_USER_FLAG10 1 << 25
#define EXTENSIONCLASS_USER_FLAG11 1 << 26
#define EXTENSIONCLASS_USER_FLAG12 1 << 27
#define EXTENSIONCLASS_USER_FLAG13 1 << 28
#define EXTENSIONCLASS_USER_FLAG14 1 << 29
#define EXTENSIONCLASS_USER_FLAG15 1 << 30
#define EXTENSIONCLASS_USER_FLAG16 1 << 31
/* This is the class dictionary, which is normally created for you.
If you wish, you can provide your own class dictionary object.
...
...
@@ -282,6 +306,10 @@ typedef struct {
/* Export an Extension Base class in a given module dictionary with a
given name and ExtensionClass structure.
*/
#define ExtensionClassImported \
(PyExtensionClassCAPI=PyCObject_Import("ExtensionClass","CAPI"))
#define PyExtensionClass_Export(D,N,T) \
if(PyExtensionClassCAPI || \
(PyExtensionClassCAPI= PyCObject_Import("ExtensionClass","CAPI"))) \
...
...
@@ -353,11 +381,20 @@ static PyExtensionClass NAME ## Type = { PyObject_HEAD_INIT(NULL) \
(((PyExtensionClass*)((O)->ob_type))->class_flags & \
EXTENSIONCLASS_BINDABLE_FLAG))
/* The following macros are used to check whether an instance
or a class' instanses have instance dictionaries: */
#define HasInstDict(O) \
((((PyExtensionClass*)((O)->ob_type))->class_flags & \
EXTENSIONCLASS_INSTDICT_FLAG))
#define ClassHasInstDict(O) (O->class_flags & EXTENSIONCLASS_INSTDICT_FLAG)
/* Get an object's instance dictionary. Use with caution */
#define INSTANCE_DICT(inst) \
*(((PyObject**)inst) + (inst->ob_type->tp_basicsize/sizeof(PyObject*) - 1))
/*****************************************************************************
WARNING: EVERYTHING BELOW HERE IS PRIVATE TO THE EXTENSION CLASS INTERFACE
...
...
lib/Components/ExtensionClass/src/ExtensionClass.c
View file @
bb3bf699
/*
$Id: ExtensionClass.c,v 1.
8 1997/03/08 12:44:31
jim Exp $
$Id: ExtensionClass.c,v 1.
9 1997/04/11 21:47:05
jim Exp $
Extension Class
Copyright
Copyright 1996 Digital Creations, L.C., 910 Princess Anne
...
...
@@ -50,45 +49,11 @@
If you have questions regarding this software,
contact:
Jim Fulton, jim@digicool.com
Digital Creations L.C.
info@digicool.com
(540) 371-6909
$Log: ExtensionClass.c,v $
Revision 1.8 1997/03/08 12:44:31 jim
Moved INSTANCE_DICT macro to public interface.
Revision 1.7 1997/02/24 23:17:47 jim
Fixed bug in subclass_nonzero.
Revision 1.6 1997/02/24 15:43:57 jim
Added __version__ string.
Revision 1.5 1997/02/17 16:27:53 jim
Many changes.
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.
Revision 1.2 1996/10/23 18:36:56 jim
Changed a bunch of single quotes to double and got rid of
some superfluous semicolns that caused warning on SGI.
Fixed bug in CCL_getattr when getting the __base__ attribute of a base
class.
Fixed a doc string.
Revision 1.1 1996/10/22 22:26:08 jim
*** empty log message ***
*/
static
char
ExtensionClass_module_documentation
[]
=
...
...
@@ -100,7 +65,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.
8 1997/03/08 12:44:31
jim Exp $
\n
"
"$Id: ExtensionClass.c,v 1.
9 1997/04/11 21:47:05
jim Exp $
\n
"
;
#include <stdio.h>
...
...
@@ -118,7 +83,6 @@ PyVar_Assign(PyObject **v, PyObject *e)
#define UNLESS(E) if(!(E))
#define UNLESS_ASSIGN(V,E) ASSIGN(V,E); UNLESS(V)
/* Declarations for objects of type ExtensionClass */
#include "ExtensionClass.h"
...
...
@@ -134,15 +98,20 @@ staticforward PyExtensionClass ECType;
((O)->ob_type->ob_type == (PyTypeObject*)&ECType && \
(((PyExtensionClass*)((O)->ob_type))->class_flags & \
EXTENSIONCLASS_BINDABLE_FLAG))
#define HasMethodHook(O) \
((O)->ob_type->ob_type == (PyTypeObject*)&ECType && \
(((PyExtensionClass*)((O)->ob_type))->class_flags & \
EXTENSIONCLASS_METHODHOOK_FLAG))
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__of__
,
*
py__call__
,
*
py__call_method__
,
*
py__getitem__
,
*
py__setitem__
,
*
py__delitem__
,
*
py__getslice__
,
*
py__setslice__
,
*
py__delslice__
,
*
py__concat__
,
*
py__repeat__
,
*
py__len__
,
*
py__of__
,
*
py__call__
,
*
py__concat__
,
*
py__repeat__
,
*
py__len__
,
*
py__getattr__
,
*
py__setattr__
,
*
py__delattr__
,
*
py__del__
,
*
py__repr__
,
*
py__str__
,
*
py__class__
,
*
py__hash__
,
*
py__cmp__
,
*
py__var_size__
,
*
py__init__
,
*
py__getinitargs__
,
...
...
@@ -186,6 +155,7 @@ init_py_names()
INIT_PY_NAME
(
__len__
);
INIT_PY_NAME
(
__of__
);
INIT_PY_NAME
(
__call__
);
INIT_PY_NAME
(
__call_method__
);
INIT_PY_NAME
(
__getattr__
);
INIT_PY_NAME
(
__setattr__
);
INIT_PY_NAME
(
__delattr__
);
...
...
@@ -348,12 +318,54 @@ call_cmethod(CMethod *self, PyObject *inst, PyObject *args, PyObject *kw)
}
}
static
char
*
hook_mark
=
"C method being called through a hook."
;
static
PyObject
*
callCMethodWithHook
(
CMethod
*
self
,
PyObject
*
inst
,
PyObject
*
args
,
PyObject
*
kw
)
{
PyObject
*
hook
,
*
m
;
UNLESS
(
m
=
newCMethod
(
AsExtensionClass
(
self
->
type
),
inst
,
self
->
name
,
self
->
meth
,
self
->
flags
,
hook_mark
))
return
NULL
;
if
(
hook
=
PyObject_GetAttr
(
inst
,
py__call_method__
))
{
if
(
CMethod_Check
(
hook
)
&&
((
CMethod
*
)
hook
)
->
meth
==
self
->
meth
)
{
/* Oops, we are already calling the hook! */
Py_DECREF
(
hook
);
return
PyEval_CallObjectWithKeywords
(
m
,
args
,
kw
);
}
if
(
kw
)
ASSIGN
(
hook
,
PyObject_CallFunction
(
hook
,
"OOO"
,
m
,
args
,
kw
));
else
ASSIGN
(
hook
,
PyObject_CallFunction
(
hook
,
"OO"
,
m
,
args
));
}
else
{
PyErr_Clear
();
hook
=
PyEval_CallObjectWithKeywords
(
m
,
args
,
kw
);
}
Py_DECREF
(
m
);
return
hook
;
}
static
PyObject
*
CMethod_call
(
CMethod
*
self
,
PyObject
*
args
,
PyObject
*
kw
)
{
int
size
;
if
(
self
->
self
)
return
call_cmethod
(
self
,
self
->
self
,
args
,
kw
);
if
(
self
->
self
)
{
if
(
HasMethodHook
(
self
->
self
)
&&
self
->
doc
!=
hook_mark
/* This check prevents infinite recursion */
)
return
callCMethodWithHook
(
self
,
self
->
self
,
args
,
kw
);
return
call_cmethod
(
self
,
self
->
self
,
args
,
kw
);
}
if
((
size
=
PyTuple_Size
(
args
))
>
0
)
{
...
...
@@ -369,6 +381,10 @@ CMethod_call(CMethod *self, PyObject *args, PyObject *kw)
);
{
PyObject
*
rest
=
0
;
if
(
HasMethodHook
(
first
)
&&
self
->
doc
!=
hook_mark
/* This check prevents infinite recursion */
)
return
callCMethodWithHook
(
self
,
first
,
args
,
kw
);
UNLESS
(
rest
=
PySequence_GetSlice
(
args
,
1
,
size
))
return
NULL
;
ASSIGN
(
rest
,
call_cmethod
(
self
,
first
,
rest
,
kw
));
return
rest
;
...
...
@@ -527,6 +543,32 @@ PMethod_dealloc(PMethod *self)
#endif
}
static
PyObject
*
callMethodWithPossibleHook
(
PyObject
*
inst
,
PyObject
*
meth
,
PyObject
*
args
,
PyObject
*
kw
)
{
if
(
HasMethodHook
(
inst
))
{
PyObject
*
hook
;
if
(
hook
=
PyObject_GetAttr
(
inst
,
py__call_method__
))
{
if
(
PMethod_Check
(
hook
)
&&
((
PMethod
*
)
hook
)
->
meth
==
meth
)
{
/* Oops, we are already calling the hook! */
Py_DECREF
(
hook
);
return
PyEval_CallObjectWithKeywords
(
meth
,
args
,
kw
);
}
if
(
kw
)
ASSIGN
(
hook
,
PyObject_CallFunction
(
hook
,
"OOO"
,
meth
,
args
,
kw
));
else
ASSIGN
(
hook
,
PyObject_CallFunction
(
hook
,
"OO"
,
meth
,
args
));
return
hook
;
}
PyErr_Clear
();
}
return
PyEval_CallObjectWithKeywords
(
meth
,
args
,
kw
);
}
static
PyObject
*
call_PMethod
(
PMethod
*
self
,
PyObject
*
inst
,
PyObject
*
args
,
PyObject
*
kw
)
{
...
...
@@ -534,7 +576,7 @@ call_PMethod(PMethod *self, PyObject *inst, PyObject *args, PyObject *kw)
a
=
Py_BuildValue
(
"(O)"
,
inst
);
if
(
a
)
ASSIGN
(
a
,
PySequence_Concat
(
a
,
args
));
if
(
a
)
ASSIGN
(
a
,
PyEval_CallObjectWithKeywords
(
self
->
meth
,
a
,
kw
));
if
(
a
)
ASSIGN
(
a
,
callMethodWithPossibleHook
(
inst
,
self
->
meth
,
a
,
kw
));
return
a
;
}
...
...
@@ -571,12 +613,12 @@ PMethod_call(PMethod *self, PyObject *args, PyObject *kw)
Py_DECREF
(
r
);
return
NULL
;
}
ASSIGN
(
r
,
PyEval_CallObjectWithKeywords
(
r
,
rest
,
kw
));
ASSIGN
(
r
,
callMethodWithPossibleHook
(
first
,
r
,
rest
,
kw
));
Py_DECREF
(
rest
);
return
r
;
}
Py_DECREF
(
ftype
);
return
PyEval_CallObjectWithKeywords
(
self
->
meth
,
args
,
kw
);
return
callMethodWithPossibleHook
(
first
,
self
->
meth
,
args
,
kw
);
}
Py_XDECREF
(
ftype
);
}
...
...
@@ -695,7 +737,7 @@ setattr_by_name(PyObject *self, PyObject *args)
{
char
*
name
;
PyObject
*
v
;
UNLESS
(
PyArg_Parse
(
args
,
"sO"
,
&
name
,
&
v
))
return
NULL
;
UNLESS
(
PyArg_Parse
Tuple
(
args
,
"sO"
,
&
name
,
&
v
))
return
NULL
;
UNLESS
(
-
1
!=
self
->
ob_type
->
tp_setattr
(
self
,
name
,
v
))
return
NULL
;
Py_INCREF
(
Py_None
);
return
Py_None
;
...
...
@@ -714,7 +756,7 @@ setattro_by_name(PyObject *self, PyObject *args)
{
PyObject
*
name
;
PyObject
*
v
;
UNLESS
(
PyArg_Parse
(
args
,
"OO"
,
&
name
,
&
v
))
return
NULL
;
UNLESS
(
PyArg_Parse
Tuple
(
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
;
...
...
@@ -763,7 +805,7 @@ setitem_by_name(PyObject *self, PyObject *args)
PyObject
*
key
,
*
v
;
long
r
;
UNLESS
(
PyArg_Parse
(
args
,
"OO"
,
&
key
,
&
v
))
return
NULL
;
UNLESS
(
PyArg_Parse
Tuple
(
args
,
"OO"
,
&
key
,
&
v
))
return
NULL
;
if
(
self
->
ob_type
->
tp_as_mapping
)
r
=
self
->
ob_type
->
tp_as_mapping
->
mp_ass_subscript
(
self
,
key
,
v
);
else
...
...
@@ -785,7 +827,7 @@ slice_by_name(PyObject *self, PyObject *args)
{
int
i1
,
i2
;
UNLESS
(
PyArg_Parse
(
args
,
"ii"
,
&
i1
,
&
i2
))
return
NULL
;
UNLESS
(
PyArg_Parse
Tuple
(
args
,
"ii"
,
&
i1
,
&
i2
))
return
NULL
;
return
self
->
ob_type
->
tp_as_sequence
->
sq_slice
(
self
,
i1
,
i2
);
}
...
...
@@ -796,7 +838,7 @@ ass_slice_by_name(PyObject *self, PyObject *args)
PyObject
*
v
;
long
r
;
UNLESS
(
PyArg_Parse
(
args
,
"iiO"
,
&
i1
,
&
i2
,
&
v
))
return
NULL
;
UNLESS
(
PyArg_Parse
Tuple
(
args
,
"iiO"
,
&
i1
,
&
i2
,
&
v
))
return
NULL
;
r
=
self
->
ob_type
->
tp_as_sequence
->
sq_ass_slice
(
self
,
i1
,
i2
,
v
);
if
(
r
<
0
)
return
NULL
;
Py_INCREF
(
Py_None
);
...
...
@@ -914,9 +956,9 @@ getBaseDictionary(PyExtensionClass *type)
FILLENTRY
(
type
->
tp
,
call
,
call
,
2
,
"call as a function"
);
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"
);
FILLENTRY
(
type
->
tp
,
setattr
,
setattr
,
1
,
"Set an attribute"
);
FILLENTRY
(
type
->
tp
,
getattro
,
getattr
,
0
,
"Get an attribute"
);
FILLENTRY
(
type
->
tp
,
setattro
,
setattr
,
0
,
"Set an attribute"
);
FILLENTRY
(
type
->
tp
,
setattro
,
setattr
,
1
,
"Set an attribute"
);
if
(
sm
=
type
->
tp_as_sequence
)
{
...
...
@@ -926,9 +968,9 @@ getBaseDictionary(PyExtensionClass *type)
FILLENTRY
(
sm
->
sq
,
repeat
,
repeat
,
0
,
"Get a new object that is the object repeated."
);
FILLENTRY
(
sm
->
sq
,
item
,
getitem
,
0
,
"Get an item"
);
FILLENTRY
(
sm
->
sq
,
slice
,
getslice
,
0
,
"Get a slice"
);
FILLENTRY
(
sm
->
sq
,
ass_item
,
setitem
,
0
,
"Assign an item"
);
FILLENTRY
(
sm
->
sq
,
ass_slice
,
setslice
,
0
,
"Assign a slice"
);
FILLENTRY
(
sm
->
sq
,
slice
,
getslice
,
1
,
"Get a slice"
);
FILLENTRY
(
sm
->
sq
,
ass_item
,
setitem
,
1
,
"Assign an item"
);
FILLENTRY
(
sm
->
sq
,
ass_slice
,
setslice
,
1
,
"Assign a slice"
);
}
if
(
mm
=
type
->
tp_as_mapping
)
...
...
@@ -1025,24 +1067,33 @@ err:
}
static
PyObject
*
inheritedAttribute
(
Py
ExtensionClass
*
self
,
PyObject
*
name
)
inheritedAttribute
(
Py
Object
*
self
,
PyObject
*
args
)
{
UNLESS
(
name
)
return
PyErr_Format
(
PyExc_TypeError
,
"expected one argument, and none given"
,
NULL
);
return
CCL_getattr
(
self
,
name
,
1
);
}
PyObject
*
cls
,
*
name
;
static
PyObject
*
inheritedClassAttribute
(
PyExtensionClass
*
self
,
PyObject
*
name
)
{
UNLESS
(
name
)
return
PyErr_Format
(
PyExc_TypeError
,
"expected one argument, and none given"
,
NULL
);
UNLESS
(
name
=
PySequence_Concat
(
pyclass_
,
name
))
return
NULL
;
UNLESS_ASSIGN
(
name
,
CCL_getattr
(
self
,
name
,
1
))
return
NULL
;
if
(
UnboundPMethod_Check
(
name
))
ASSIGN
(
name
,
bindPMethod
((
PMethod
*
)
name
,(
PyObject
*
)
self
));
UNLESS
(
PyArg_ParseTuple
(
args
,
"OO"
,
&
cls
,
&
name
));
UNLESS
(
ExtensionClass_Check
(
cls
))
{
PyErr_SetString
(
PyExc_TypeError
,
"inheritedAttribute must be called with an extension "
"class first argument"
);
return
NULL
;
}
UNLESS
(
PyString_Check
(
name
))
{
PyErr_SetString
(
PyExc_TypeError
,
"inheritedAttribute must be called with a "
"string second argument"
);
return
NULL
;
}
UNLESS
(
name
=
CCL_getattr
(
AsExtensionClass
(
cls
),
name
,
1
))
return
NULL
;
/* We got something from our class, maybe its an unbound method. */
if
(
UnboundCMethod_Check
(
name
))
ASSIGN
(
name
,(
PyObject
*
)
bindCMethod
((
CMethod
*
)
name
,
self
));
else
if
(
UnboundPMethod_Check
(
name
))
ASSIGN
(
name
,
bindPMethod
((
PMethod
*
)
name
,
self
));
return
name
;
}
...
...
@@ -1050,6 +1101,21 @@ struct PyMethodDef ECI_methods[] = {
{
"__reduce__"
,(
PyCFunction
)
EC_reduce
,
0
,
"__reduce__() -- Reduce an instance into it's class and creation data"
},
{
"inheritedAttribute"
,(
PyCFunction
)
inheritedAttribute
,
1
,
"inheritedAttribute(class,name) -- Get an inherited attribute
\n\n
"
"Get an attribute that would be inherited if the given (extension)
\n
"
"class did not define it. This method is used when overriding
\n
"
"inherited methods. It provides 2 advantages over accessing
\n
"
"
\n
"
"attributes directly through a superclass:
\n
"
"
\n
"
"1. The superclass need not be known,
\n
"
"
\n
"
"2. The superclass may be a Python class. Without this method, it would
\n
"
" be possible to override methods inherited from python classes because
\n
"
" unbound methods gotten from Python classes cannot be called with
\n
"
" extension class instances.
\n
"
},
{
NULL
,
NULL
}
/* sentinel */
};
...
...
@@ -1165,7 +1231,7 @@ ExtensionClass_FindInstanceAttribute(PyObject *inst, PyObject *oname,
Py_INCREF
(
self
);
return
(
PyObject
*
)
self
;
}
if
(
self
->
bases
&&
*
n
==
'd'
&&
strcmp
(
n
,
"dict__"
)
==
0
)
if
(
ClassHasInstDict
(
self
)
&&
*
n
==
'd'
&&
strcmp
(
n
,
"dict__"
)
==
0
)
{
r
=
INSTANCE_DICT
(
inst
);
Py_INCREF
(
r
);
...
...
@@ -1173,7 +1239,7 @@ ExtensionClass_FindInstanceAttribute(PyObject *inst, PyObject *oname,
}
}
if
(
self
->
bases
)
if
(
ClassHasInstDict
(
self
)
)
{
r
=
INSTANCE_DICT
(
inst
);
if
((
r
=
PyObject_GetItem
(
r
,
oname
))
&&
NeedsToBeBound
(
r
))
...
...
@@ -1278,6 +1344,15 @@ CCL_reduce(PyExtensionClass *self, PyObject *args)
return
PyString_FromString
(
self
->
tp_name
);
}
static
PyObject
*
obsolete_inheritedAttribute
(
PyExtensionClass
*
self
,
PyObject
*
name
)
{
UNLESS
(
name
)
return
PyErr_Format
(
PyExc_TypeError
,
"expected one argument, and none given"
,
NULL
);
return
CCL_getattr
(
self
,
name
,
1
);
}
PyObject
*
CCL_getattro
(
PyExtensionClass
*
self
,
PyObject
*
name
)
{
...
...
@@ -1330,19 +1405,11 @@ CCL_getattro(PyExtensionClass *self, PyObject *name)
if
(
strcmp
(
nm
,
"inheritedAttribute"
)
==
0
)
{
return
newCMethod
(
self
,(
PyObject
*
)
self
,
"inheritedAttribute"
,(
PyCFunction
)
inheritedAttribute
,
0
,
"inheritedAttribute"
,
(
PyCFunction
)
obsolete_inheritedAttribute
,
0
,
"look up an attribute in a class's super classes"
);
}
if
(
nm
&&
*
nm
++==
'c'
&&
*
nm
++==
'l'
&&
*
nm
++==
'a'
&&
*
nm
++==
's'
&&
*
nm
++==
's'
&&
*
nm
==
'_'
)
{
UNLESS
(
r
=
CCL_getattr
(
self
,
name
,
0
))
return
NULL
;
if
(
UnboundPMethod_Check
(
r
))
ASSIGN
(
r
,
bindPMethod
((
PMethod
*
)
r
,(
PyObject
*
)
self
));
return
r
;
}
if
(
r
=
CCL_getattr
(
self
,
name
,
0
))
return
r
;
return
NULL
;
...
...
@@ -1532,10 +1599,9 @@ CCL_call(PyExtensionClass *self, PyObject *arg, PyObject *kw)
}
Py_INCREF
(
self
);
if
(
self
->
bases
)
{
if
(
ClassHasInstDict
(
self
))
UNLESS
(
INSTANCE_DICT
(
inst
)
=
PyDict_New
())
goto
err
;
}
if
(
init
=
CCL_getattr
(
self
,
py__init__
,
0
))
{
...
...
@@ -2637,7 +2703,7 @@ subclass__init__(PyExtensionClass *self, PyObject *args)
char
*
name
,
*
p
;
int
dynamic
=
1
,
l
;
UNLESS
(
PyArg_Parse
(
args
,
"(sOO)
"
,
&
name
,
&
bases
,
&
methods
))
return
NULL
;
UNLESS
(
PyArg_Parse
Tuple
(
args
,
"sOO
"
,
&
name
,
&
bases
,
&
methods
))
return
NULL
;
l
=
strlen
(
name
)
+
1
;
UNLESS
(
p
=
(
char
*
)
malloc
(
l
*
sizeof
(
char
)))
return
PyErr_NoMemory
();
memcpy
(
p
,
name
,
l
);
...
...
@@ -2661,7 +2727,6 @@ subclass__init__(PyExtensionClass *self, PyObject *args)
UNLESS
(
type
=
(
PyExtensionClass
*
)
datafull_baseclass
(
self
))
UNLESS
(
type
=
(
PyExtensionClass
*
)
extension_baseclass
(
self
))
return
NULL
;
self
->
tp_name
=
name
;
UNLESS
(
self
->
class_dictionary
=
CopyMethods
(
type
,
methods
))
return
NULL
;
...
...
@@ -2696,6 +2761,12 @@ subclass__init__(PyExtensionClass *self, PyObject *args)
if
(
subclass_hasattr
(
self
,
py__of__
))
self
->
class_flags
|=
EXTENSIONCLASS_BINDABLE_FLAG
;
if
(
subclass_hasattr
(
self
,
py__call_method__
))
self
->
class_flags
|=
EXTENSIONCLASS_METHODHOOK_FLAG
;
UNLESS
(
self
->
class_flags
&
EXTENSIONCLASS_NOINSTDICT_FLAG
)
self
->
class_flags
|=
EXTENSIONCLASS_INSTDICT_FLAG
;
if
(
dynamic
||
has_number_methods
(
self
))
{
self
->
tp_as_number
=
(
PyNumberMethods
*
)
malloc
(
sizeof
(
PyNumberMethods
));
...
...
@@ -2727,9 +2798,11 @@ subclass__init__(PyExtensionClass *self, PyObject *args)
self
->
tp_doc
=
0
;
/* Check for and use __class_init__ */
if
(
class_init
=
PyObject_GetAttrString
(
AsPyObject
(
self
),
"
class_
_init__"
))
if
(
class_init
=
PyObject_GetAttrString
(
AsPyObject
(
self
),
"
__class
_init__"
))
{
UNLESS_ASSIGN
(
class_init
,
PyObject_CallObject
(
class_init
,
NULL
))
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
);
}
...
...
@@ -2741,7 +2814,7 @@ subclass__init__(PyExtensionClass *self, PyObject *args)
}
struct
PyMethodDef
ExtensionClass_methods
[]
=
{
{
"__init__"
,(
PyCFunction
)
subclass__init__
,
0
,
""
},
{
"__init__"
,(
PyCFunction
)
subclass__init__
,
1
,
""
},
{
NULL
,
NULL
}
/* sentinel */
};
...
...
@@ -2802,7 +2875,7 @@ void
initExtensionClass
()
{
PyObject
*
m
,
*
d
;
char
*
rev
=
"$Revision: 1.
8
$"
;
char
*
rev
=
"$Revision: 1.
9
$"
;
PURE_MIXIN_CLASS
(
Base
,
"Minimalbase class for Extension Classes"
,
NULL
);
PMethodType
.
ob_type
=&
PyType_Type
;
...
...
@@ -2836,3 +2909,43 @@ initExtensionClass()
CHECK_FOR_ERRORS
(
"can't initialize module ExtensionClass"
);
}
/****************************************************************************
$Log: ExtensionClass.c,v $
Revision 1.9 1997/04/11 21:47:05 jim
Got rid of class attributes.
Added method hooks.
Revision 1.8 1997/03/08 12:44:31 jim
Moved INSTANCE_DICT macro to public interface.
Revision 1.7 1997/02/24 23:17:47 jim
Fixed bug in subclass_nonzero.
Revision 1.6 1997/02/24 15:43:57 jim
Added __version__ string.
Revision 1.5 1997/02/17 16:27:53 jim
Many changes.
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.
Revision 1.2 1996/10/23 18:36:56 jim
Changed a bunch of single quotes to double and got rid of
some superfluous semicolns that caused warning on SGI.
Fixed bug in CCL_getattr when getting the __base__ attribute of a base
class.
Fixed a doc string.
Revision 1.1 1996/10/22 22:26:08 jim
*** empty log message ***
****************************************************************************/
lib/Components/ExtensionClass/src/ExtensionClass.h
View file @
bb3bf699
/*
$Id: ExtensionClass.h,v 1.
5 1997/03/08 12:44:13
jim Exp $
$Id: ExtensionClass.h,v 1.
6 1997/04/11 21:47:51
jim Exp $
Extension Class Definitions
...
...
@@ -113,6 +113,10 @@
$Log: ExtensionClass.h,v $
Revision 1.6 1997/04/11 21:47:51 jim
Got rid of class attributes.
Added method hooks.
Revision 1.5 1997/03/08 12:44:13 jim
Moved INSTANCE_DICT macro to public interface.
...
...
@@ -188,13 +192,33 @@ typedef struct {
*/
PyMethodChain
methods
;
/* You may set certain flags here. Only two flags are
defined at this point, the first of which is not currently
used.
*/
/* You may set certain flags here. */
long
class_flags
;
#define EXTENSIONCLASS_DYNAMIC_FLAG 1
#define EXTENSIONCLASS_BINDABLE_FLAG 2
/* The following flags are used by ExtensionClass */
#define EXTENSIONCLASS_DYNAMIC_FLAG 1 << 0
#define EXTENSIONCLASS_BINDABLE_FLAG 1 << 2
#define EXTENSIONCLASS_METHODHOOK_FLAG 1 << 3
#define EXTENSIONCLASS_INSTDICT_FLAG 1 << 4
#define EXTENSIONCLASS_NOINSTDICT_FLAG 1 << 5
/* The following flags are for use by extension class developers. */
#define EXTENSIONCLASS_USER_FLAG1 1 << 16
#define EXTENSIONCLASS_USER_FLAG2 1 << 17
#define EXTENSIONCLASS_USER_FLAG3 1 << 18
#define EXTENSIONCLASS_USER_FLAG4 1 << 19
#define EXTENSIONCLASS_USER_FLAG5 1 << 20
#define EXTENSIONCLASS_USER_FLAG6 1 << 21
#define EXTENSIONCLASS_USER_FLAG7 1 << 22
#define EXTENSIONCLASS_USER_FLAG8 1 << 23
#define EXTENSIONCLASS_USER_FLAG9 1 << 24
#define EXTENSIONCLASS_USER_FLAG10 1 << 25
#define EXTENSIONCLASS_USER_FLAG11 1 << 26
#define EXTENSIONCLASS_USER_FLAG12 1 << 27
#define EXTENSIONCLASS_USER_FLAG13 1 << 28
#define EXTENSIONCLASS_USER_FLAG14 1 << 29
#define EXTENSIONCLASS_USER_FLAG15 1 << 30
#define EXTENSIONCLASS_USER_FLAG16 1 << 31
/* This is the class dictionary, which is normally created for you.
If you wish, you can provide your own class dictionary object.
...
...
@@ -282,6 +306,10 @@ typedef struct {
/* Export an Extension Base class in a given module dictionary with a
given name and ExtensionClass structure.
*/
#define ExtensionClassImported \
(PyExtensionClassCAPI=PyCObject_Import("ExtensionClass","CAPI"))
#define PyExtensionClass_Export(D,N,T) \
if(PyExtensionClassCAPI || \
(PyExtensionClassCAPI= PyCObject_Import("ExtensionClass","CAPI"))) \
...
...
@@ -353,11 +381,20 @@ static PyExtensionClass NAME ## Type = { PyObject_HEAD_INIT(NULL) \
(((PyExtensionClass*)((O)->ob_type))->class_flags & \
EXTENSIONCLASS_BINDABLE_FLAG))
/* The following macros are used to check whether an instance
or a class' instanses have instance dictionaries: */
#define HasInstDict(O) \
((((PyExtensionClass*)((O)->ob_type))->class_flags & \
EXTENSIONCLASS_INSTDICT_FLAG))
#define ClassHasInstDict(O) (O->class_flags & EXTENSIONCLASS_INSTDICT_FLAG)
/* Get an object's instance dictionary. Use with caution */
#define INSTANCE_DICT(inst) \
*(((PyObject**)inst) + (inst->ob_type->tp_basicsize/sizeof(PyObject*) - 1))
/*****************************************************************************
WARNING: EVERYTHING BELOW HERE IS PRIVATE TO THE EXTENSION CLASS INTERFACE
...
...
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