diff options
author | James Henstridge <james@daa.com.au> | 2001-09-28 23:43:47 +0000 |
---|---|---|
committer | James Henstridge <jamesh@src.gnome.org> | 2001-09-28 23:43:47 +0000 |
commit | e0ef227e050134d9b0d9397865dd3c5053ba8d8f (patch) | |
tree | 1da46f929fc547582755dfc50cde016f04245299 | |
parent | c6a29df6dd65bbede61d2253637886789bebda51 (diff) | |
download | pygtk-e0ef227e050134d9b0d9397865dd3c5053ba8d8f.tar.gz |
use pyg_type_from_object instead. Based on patch from Elliot.
2001-09-29 James Henstridge <james@daa.com.au>
* gtk/pygtktreemodel.c (pygtk_tree_model_get_column_type): use
pyg_type_from_object instead. Based on patch from Elliot.
* gtk/gtk.override (_wrap_gtk_selection_data__get_data): convert
getter to a function to match codegen changes.
* : merge in python22-branch (see changelog entries below).
-rw-r--r-- | ChangeLog | 139 | ||||
-rw-r--r-- | ExtensionClass.c | 3490 | ||||
-rw-r--r-- | ExtensionClass.h | 471 | ||||
-rw-r--r-- | ExtensionClass.stx | 714 | ||||
-rw-r--r-- | Makefile.am | 11 | ||||
-rw-r--r-- | codegen/codegen.py | 223 | ||||
-rw-r--r-- | configure.in | 18 | ||||
-rw-r--r-- | gobject/gobjectmodule.c | 536 | ||||
-rw-r--r-- | gobject/pygobject.h | 17 | ||||
-rw-r--r-- | gobjectmodule.c | 536 | ||||
-rw-r--r-- | gtk/__init__.py | 4 | ||||
-rw-r--r-- | gtk/gdk.override | 114 | ||||
-rw-r--r-- | gtk/gtk-types.c | 4 | ||||
-rw-r--r-- | gtk/gtk.override | 270 | ||||
-rw-r--r-- | gtk/libglade.override | 8 | ||||
-rw-r--r-- | gtk/libglademodule.c | 1 | ||||
-rw-r--r-- | gtk/pygtk.h | 2 | ||||
-rw-r--r-- | gtk/pygtktreemodel.c | 2 | ||||
-rw-r--r-- | pango.override | 15 | ||||
-rw-r--r-- | pygobject.h | 17 |
20 files changed, 986 insertions, 5606 deletions
@@ -1,3 +1,142 @@ +2001-09-29 James Henstridge <james@daa.com.au> + + * gtk/pygtktreemodel.c (pygtk_tree_model_get_column_type): use + pyg_type_from_object instead. Based on patch from Elliot. + + * gtk/gtk.override (_wrap_gtk_selection_data__get_data): convert + getter to a function to match codegen changes. + + * : merge in python22-branch (see changelog entries below). + +2001-09-25 James Henstridge <james@daa.com.au> + + * gobjectmodule.c (pygobject_get_dict): getter for __dict__ on + GObject wrappers. + (PyGObject_Type): include getsets list. + + * codegen/codegen.py (write_getsets): change "struct getsets" to + PyGetSetDef to match recent changes in python. + + * gtk/gdk.override (_wrap_gdk_device__get_axes): change to getter. + (_wrap_gdk_device__get_keys): turn into a getter. + (_wrap_gdk_drag_context__get_targets): same here. + + * gtk/gtk.override (_wrap_gtk_clist__get_selection): turn into a + getter. + (_wrap_gtk_ctree__get_selection): turn into a getter. + + * codegen/codegen.py (write_getsets): rename to write_getsets, and + don't allow overriding the whole routine, as it is implemented as + a number of smaller routines now. + (gettertmpl): rename from getattrtmpl. Refactor for handling + single attribute. + (write_getsets): finish conversion over to using getsets. + (write_class): call write_getsets instead. + (typetmpl): substitute %(getsets)s rather than %(getattr)s. + +2001-09-23 James Henstridge <james@daa.com.au> + + * gtk/__init__.py: don't import ExtensionClass. + + * gobjectmodule.c (object_gc_free): new function to free an GC + managed object. + (PyGObject_Type): use object_gc_free for the tp_free slot. + + * codegen/codegen.py (write_class): don't write getattr routine. + This is a temporary hack to see if things work. + + * gobjectmodule.c (pygobject_dealloc): handle case of destruction + when self->obj == NULL. + + * gtk/gtk.override (_wrap_gtk_clist_new_with_titles): return an + int. + (_wrap_gtk_tree_view_get_path_at_pos): same here. + (_wrap_gtk_button_new): same here. + (_wrap_gtk_toggle_button_new): same here. + (_wrap_gtk_check_button_new): same here. + (_wrap_gtk_radio_button_new): same here. + (_wrap_gtk_list_item_new): same here. + (_wrap_gtk_menu_item_new): same here. + (_wrap_gtk_check_menu_item_new): same here. + (_wrap_gtk_radio_menu_item_new): same here. + (_wrap_gtk_ctree_new_with_titles): same here. + (_wrap_gtk_dialog_new_with_buttons): same here. + (_wrap_gtk_message_dialog_new): same here. + (_wrap_gtk_message_dialog_new): same here. + + * gtk/gdk.override (_wrap_gdk_cursor_new): return an int. + + * pango.override (_wrap_pango_font_description_new): constructors + return ints. + + * codegen/codegen.py (write_constructor): small hack to convert + "return NULL;" to "return -1;" in constructors, as they should + return ints. + (write_boxed_constructor): same here. + +2001-09-22 James Henstridge <james@daa.com.au> + + * gtk/pygtk.h: remove traces of ExtensionClass. + + * gtk/libglade.override: s/PyExtensionClass/PyTypeObject/. + + * gtk/gtk-types.c (_pygtk_register_boxed_types): get rid of + mentions of ExtensionClass. + + * gtk/gdk.override: s/PyExtensionClass/PyTypeObject/. + + * gtk/gtk.override: s/PyExtensionClass/PyTypeObject/. + + * gobjectmodule.c (pygobject_traverse): implement a traverse + function for PyGObject. + (PyGObject_Type): add GC support. + (object_free): use PyObject_GC_Del to delete the memory. + (pygobject_dealloc): stop GC tracking the object here. + (pygobject_register_class): set a few more type fields here. + (pygobject_new): use PyObject_GC_New to allocate the object here. + (pygobject_dealloc): readd the 1-1 object/wrapper hack. It should + work as expected since adding GC support. + + * pango.override: s/PyExtensionClass/PyTypeObject/ + + * codegen/codegen.py (consttmpl): constructor template returns an + int. + (noconstructor): return int rather than PyObject. + (typetmpl): change def to be a PyTypeObject, with extra fields. + (interfacetypetmpl): same here. + (boxedconsttmpl): return int rather than pyobject. + (boxedtmpl): change def to PyTypeObject. + (write_class): put the constructor in the right place. + (write_boxed): put the constructor in the right place. + (write_source): don't include ExtensionClass.h, forward declare + type objects as PyTypeObjects, rather than PyExtensionClasses. + + * gobjectmodule.c (pygobject_register_class): set type->ob_type. + (pyg_register_boxed): same here. + (pyg_register_interface): same here. + (initgobject): set the ob_type member of PyGInterface_Type and + PyGBoxed_Type. + (pygobject__gobject_init__): add __gobject_init__ method, that + just calls pygobject_init. + (pygobject_methods): readd __gobject_init__ method. + +2001-09-21 James Henstridge <james@daa.com.au> + + * gobjectmodule.c (pygobject_register_class): convert to use + PyTypeObjects instead of ExtensionClass. + (pygobject_new): don't need to set inst_dict. Python takes care + of that for us. + (pyg_register_boxed): convert to 2.2. + (pyg_boxed_new): convert to 2.2. + (pyg_value_from_pyobject): get rid of ExtensionClass calls. + (pygobject_init): convert to 2.2. + + * pygobject.h: don't include ExtensionClass.h + + * configure.in (AM_PATH_PYTHON): require python 2.2. + + * Makefile.am: remove ExtensionClass. + 2001-09-28 Matt Wilson <msw@redhat.com> * gtk/gtk.defs (gtk_progress_bar_new_with_adjustment): mark as diff --git a/ExtensionClass.c b/ExtensionClass.c deleted file mode 100644 index d444ed10..00000000 --- a/ExtensionClass.c +++ /dev/null @@ -1,3490 +0,0 @@ -/* - - Copyright (c) 1996-1998, Digital Creations, Fredericksburg, VA, USA. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - o Redistributions of source code must retain the above copyright - notice, this list of conditions, and the disclaimer that follows. - - o Redistributions in binary form must reproduce the above copyright - notice, this list of conditions, and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - o Neither the name of Digital Creations nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - - THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS - IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL - CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - DAMAGE. - - $Id$ - - If you have questions regarding this software, - contact: - - Digital Creations L.C. - info@digicool.com - - (540) 371-6909 - -*/ - -static char ExtensionClass_module_documentation[] = -"ExtensionClass - Classes implemented in c\n" -"\n" -"Built-in C classes are like Built-in types except that\n" -"they provide some of the behavior of Python classes:\n" -"\n" -" - They provide access to unbound methods,\n" -" - They can be called to create instances.\n" -"\n" -"$Id$\n" -; - -#include <stdio.h> -#include "ExtensionClass.h" - -static void -PyVar_Assign(PyObject **v, PyObject *e) -{ - Py_XDECREF(*v); - *v=e; -} - -#define ASSIGN(V,E) PyVar_Assign(&(V),(E)) -#define UNLESS(E) if (!(E)) -#define UNLESS_ASSIGN(V,E) ASSIGN(V,E); UNLESS(V) -#define OBJECT(O) ((PyObject*)O) - -/* Declarations for objects of type ExtensionClass */ - -staticforward PyExtensionClass ECType; - -#define ExtensionClass_Check(O) ((O)->ob_type == (PyTypeObject*)&ECType) -#define ExtensionInstance_Check(O) \ - ((O)->ob_type->ob_type == (PyTypeObject*)&ECType) -#define AsExtensionClass(O) ((PyExtensionClass*)(O)) -#define ExtensionClassOf(O) ((PyExtensionClass*)((O)->ob_type)) -#define AsPyObject(O) ((PyObject*)(O)) -#define NeedsToBeBound(O) \ - ((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)) - -#define ALLOC_FREE(T) \ - if (free ## T) { \ - self=free ## T; \ - free ## T=(T*)self->self; \ - self->ob_refcnt=1; \ - } \ - else UNLESS(self = PyObject_NEW(T, & T ## Type)) return NULL; - -#define METH_BY_NAME (2 << 16) - -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__len__, - *py__getattr__, *py__setattr__, *py__delattr__, - *py__del__, *py__repr__, *py__str__, *py__class__, *py__name__, - *py__hash__, *py__cmp__, *py__var_size__, *py__init__, *py__getinitargs__, - *py__getstate__, *py__setstate__, *py__dict__, *pyclass_, - *py__module__; - -static PyObject *concat_fmt=0; -static PyObject *subclass_watcher=0; /* Object that subclass events */ - -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(__delitem__); - INIT_PY_NAME(__getslice__); - INIT_PY_NAME(__setslice__); - INIT_PY_NAME(__delslice__); - 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__); - INIT_PY_NAME(__del__); - INIT_PY_NAME(__repr__); - INIT_PY_NAME(__str__); - INIT_PY_NAME(__class__); - INIT_PY_NAME(__name__); - INIT_PY_NAME(__hash__); - INIT_PY_NAME(__cmp__); - INIT_PY_NAME(__var_size__); - INIT_PY_NAME(__init__); - INIT_PY_NAME(__getinitargs__); - INIT_PY_NAME(__getstate__); - INIT_PY_NAME(__setstate__); - INIT_PY_NAME(__dict__); - INIT_PY_NAME(class_); - INIT_PY_NAME(__module__); - -#undef INIT_PY_NAME -} - -static PyObject * -CallMethodO(PyObject *self, PyObject *name, - PyObject *args, PyObject *kw) -{ - if (! args && PyErr_Occurred()) return NULL; - UNLESS(name=PyObject_GetAttr(self,name)) return NULL; - ASSIGN(name,PyEval_CallObjectWithKeywords(name,args,kw)); - if (args) Py_DECREF(args); - return name; -} - -#define Build Py_BuildValue - -/* CMethod objects: */ - -typedef struct { - PyObject_HEAD - PyTypeObject *type; - PyObject *self; - char *name; - PyCFunction meth; - int flags; - char *doc; -} CMethod; - -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)) -#define CMETHOD(O) ((CMethod*)(O)) - - -#define PMethod PyECMethodObject -#define PMethodType PyECMethodObjectType - -staticforward PyTypeObject PMethodType; - -#define PMethod_Check(O) ((O)->ob_type==&PMethodType) -#define UnboundPMethod_Check(O) \ - ((O)->ob_type==&PMethodType && ! ((PMethod*)(O))->self) - -#define UnboundEMethod_Check(O) \ - (((O)->ob_type==&PMethodType ||(O)->ob_type==&CMethodType) \ - && ! ((PMethod*)(O))->self) - -#define PMETHOD(O) ((PMethod*)(O)) - - - -static PyObject * -#ifdef HAVE_STDARG_PROTOTYPES -/* VARARGS 2 */ -JimErr_Format(PyObject *ErrType, char *stringformat, char *format, ...) -#else -/* VARARGS */ -JimErr_Format(va_alist) va_dcl -#endif -{ - va_list va; - PyObject *args=0, *retval=0; -#ifdef HAVE_STDARG_PROTOTYPES - va_start(va, format); -#else - PyObject *ErrType; - char *stringformat, *format; - va_start(va); - ErrType = va_arg(va, PyObject *); - stringformat = va_arg(va, char *); - format = va_arg(va, char *); -#endif - - if (format) args = Py_VaBuildValue(format, va); - va_end(va); - if (format && ! args) return NULL; - if (stringformat && !(retval=PyString_FromString(stringformat))) return NULL; - - if (retval) - { - if (args) - { - PyObject *v; - v=PyString_Format(retval, args); - Py_DECREF(retval); - Py_DECREF(args); - if (! v) return NULL; - retval=v; - } - } - else - if (args) retval=args; - else - { - PyErr_SetObject(ErrType,Py_None); - return NULL; - } - PyErr_SetObject(ErrType,retval); - Py_DECREF(retval); - return NULL; -} - - -static PyObject * -#ifdef HAVE_STDARG_PROTOTYPES -/* VARARGS 2 */ -JimString_Build(char *out_format, char *build_format, ...) -#else -/* VARARGS */ -JimString_Build(va_alist) va_dcl -#endif -{ - va_list va; - PyObject *args, *retval, *fmt; -#ifdef HAVE_STDARG_PROTOTYPES - va_start(va, build_format); -#else - char *build_format; - char *out_format; - va_start(va); - out_format = va_arg(va, char *); - build_format = va_arg(va, char *); -#endif - - if (build_format) - args = Py_VaBuildValue(build_format, va); - else - args = PyTuple_New(0); - - va_end(va); - - if (! args) - return NULL; - - if (! PyTuple_Check(args)) - { - PyObject *a; - - a=PyTuple_New(1); - if (! a) - return NULL; - - if (PyTuple_SetItem(a,0,args) == -1) - return NULL; - - args=a; - } - - fmt = PyString_FromString(out_format); - - retval = PyString_Format(fmt, args); - - Py_DECREF(args); - Py_DECREF(fmt); - - return retval; -} - - - -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 (ExtensionClass_Check(t) - && AsExtensionClass(t)->bases - && CMethod_issubclass(AsExtensionClass(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 *freeCMethod=0; - -static PyObject * -newCMethod(PyExtensionClass *type, PyObject *inst, - char *name, PyCFunction meth, int flags, char *doc) -{ - CMethod *self; - - ALLOC_FREE(CMethod); - - Py_INCREF(type); - Py_XINCREF(inst); - self->type=(PyTypeObject*)type; - self->self=inst; - self->name=name; - self->meth=meth; - self->flags=flags; - self->doc=doc; - return (PyObject*)self; -} - -static CMethod * -bindCMethod(CMethod *m, PyObject *inst) -{ - CMethod *self; - - UNLESS(inst->ob_type==m->type - || (ExtensionInstance_Check(inst) - && SubclassInstance_Check(inst,m->type)) - || ((m->flags & METH_CLASS_METHOD) && ExtensionClass_Check(inst)) - ) - { - Py_INCREF(m); - return m; - } - - ALLOC_FREE(CMethod); - - Py_INCREF(inst); - Py_INCREF(m->type); - self->type=m->type; - self->self=inst; - self->name=m->name; - self->meth=m->meth; - self->flags=m->flags; - self->doc=m->doc; - return self; -} - -static void -CMethod_dealloc(CMethod *self) -{ -#ifdef TRACE_DEALLOC - fprintf(stderr,"Deallocating C method %s\n", self->name); -#endif - Py_XDECREF(self->type); - Py_XDECREF(self->self); - self->self=(PyObject*)freeCMethod; - freeCMethod=self; -} - -typedef PyObject *(*call_by_name_type)(PyObject*,PyObject*,PyObject*, - PyTypeObject*); -typedef PyObject *(*by_name_type)(PyObject*,PyObject*, - PyTypeObject*); -static PyObject * -call_cmethod(CMethod *self, PyObject *inst, PyObject *args, PyObject *kw) -{ - if (!(self->flags & METH_VARARGS)) - { - int size = PyTuple_Size(args); - if (size == 1) args = PyTuple_GET_ITEM(args, 0); - else if (size == 0) args = NULL; - } - if (self->flags & METH_KEYWORDS) - { - if (self->flags & METH_BY_NAME) - return (*(call_by_name_type)self->meth)(inst, args, kw, - self->type); - else - return (*(PyCFunctionWithKeywords)self->meth)(inst, args, kw); - } - else if (self->flags & METH_BY_NAME) - return (*(by_name_type)self->meth)(inst, args, self->type); - else - { - if (kw != NULL && PyDict_Size(kw) != 0) - { - PyErr_SetString(PyExc_TypeError, - "this function takes no keyword arguments"); - return NULL; - } - return (*self->meth)(inst, args); - } -} - -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) - || - (PMethod_Check(hook) - && CMethod_Check(PMETHOD(hook)->meth) - && CMETHOD(PMETHOD(hook)->meth)->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) - { - 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) - { - PyObject *first=0; - - UNLESS(first=PyTuple_GET_ITEM(args, 0)) return NULL; - if ( - first->ob_type==self->type - || - (ExtensionInstance_Check(first) - && - CMethod_issubclass(ExtensionClassOf(first), - AsExtensionClass(self->type)) - ) - ) - { - 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; - } - } - - return JimErr_Format(PyExc_TypeError, - "unbound C method must be called with %s 1st argument", - "s", self->type->tp_name); -} - -static PyObject * -CMethod_getattro(CMethod *self, PyObject *oname) -{ - PyObject *r; - - if (PyString_Check(oname)) - { - char *name; - - UNLESS(name=PyString_AsString(oname)) return NULL; - - if (name[0] != '_' && name[0] && name[1] != '_' && - PyEval_GetRestricted()) - { - PyErr_SetString(PyExc_RuntimeError, - "function attributes not accessible in restricted mode"); - return NULL; - } - - if (strcmp(name,"__name__")==0 || strcmp(name,"func_name")==0 ) - return PyString_FromString(self->name); - if (strcmp(name,"func_code")==0 || - strcmp(name,"im_func")==0) - { - Py_INCREF(self); - return (PyObject *)self; - } - if (strcmp(name,"__doc__")==0 || - strcmp(name,"func_doc")==0) - { - if (self->doc) - return PyString_FromString(self->doc); - else - return PyString_FromString(""); - } - if (strcmp(name,"im_class")==0) - { - Py_INCREF(self->type); - return (PyObject *)self->type; - } - if (strcmp(name,"im_self")==0) - { - if (self->self) r=self->self; - else r=Py_None; - Py_INCREF(r); - return r; - } - } - - if (self->self) /* Psuedo attributes */ - { - UNLESS(oname=Py_BuildValue("sO", self->name, oname)) return NULL; - UNLESS_ASSIGN(oname,PyString_Format(concat_fmt, oname)) return NULL; - r=PyObject_GetAttr(self->self, oname); - Py_DECREF(oname); - return r; - } - - PyErr_SetObject(PyExc_AttributeError, oname); - return NULL; -} - -static int -CMethod_setattro(CMethod *self, PyObject *oname, PyObject *v) -{ - int r; - - if (self->self && ! PyEval_GetRestricted()) /* Psuedo attributes */ - { - UNLESS(oname=Py_BuildValue("sO", self->name, oname)) return -1; - UNLESS_ASSIGN(oname,PyString_Format(concat_fmt, oname)) return -1; - r=PyObject_SetAttr(self->self, oname, v); - Py_DECREF(oname); - return r; - } - - PyErr_SetObject(PyExc_AttributeError, oname); - return -1; -} - -static PyTypeObject CMethodType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "CMethod", /*tp_name*/ - sizeof(CMethod), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)CMethod_dealloc, /*tp_dealloc*/ - (printfunc)0, /*tp_print*/ - 0, /*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)CMethod_call, /*tp_call*/ - (reprfunc)0, /*tp_str*/ - (getattrofunc)CMethod_getattro, /* tp_getattro */ - (setattrofunc)CMethod_setattro, /* tp_setattro */ - - /* Space for future expansion */ - 0L,0L, - "Storage manager for unbound C function PyObject data" - /* Documentation string */ -}; - -/* PMethod objects: */ - -static PMethod *freePMethod=0; - -static PyObject * -newPMethod(PyExtensionClass *type, PyObject *meth) -{ - PMethod *self; - - ALLOC_FREE(PMethod); - - Py_INCREF(type); - Py_INCREF(meth); - self->type=(PyTypeObject*)type; - self->self=NULL; - self->meth=meth; - return (PyObject*)self; -} - -static PyObject * -bindPMethod(PMethod *m, PyObject *inst) -{ - PMethod *self; - - if (NeedsToBeBound(m->meth)) - return CallMethodO(m->meth, py__of__, Build("(O)", inst), NULL); - if (m->ob_refcnt==1) - { - Py_INCREF(inst); - ASSIGN(m->self, inst); - Py_INCREF(m); - return (PyObject*)m; - } - - ALLOC_FREE(PMethod); - - Py_INCREF(inst); - Py_INCREF(m->type); - self->type=m->type; - self->self=inst; - self->meth=m->meth; - return (PyObject*)self; -} - -static PyObject * -PMethod_New(PyObject *meth, PyObject *inst) -{ - if (PMethod_Check(meth)) return bindPMethod((PMethod*)meth,inst); - UNLESS(ExtensionInstance_Check(inst)) - return JimErr_Format(PyExc_TypeError, - "Attempt to use %s as method for %s, which is " - "not an extension class instance.", - "OO",meth,inst); - if ((meth=newPMethod(ExtensionClassOf(inst), meth))) - UNLESS_ASSIGN(((PMethod*)meth)->self,inst) return NULL; - Py_INCREF(inst); - return meth; -} - -static void -PMethod_dealloc(PMethod *self) -{ -#ifdef TRACE_DEALLOC - fprintf(stderr,"Deallocating PM ... "); -#endif - Py_XDECREF(self->type); - Py_XDECREF(self->self); - self->self=(PyObject*)freePMethod; - freePMethod=self; -#ifdef TRACE_DEALLOC - fprintf(stderr," Done Deallocating PM\n"); -#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) -{ - PyObject *a; - - if (CMethod_Check(self->meth) - && CMETHOD(self->meth)->type->tp_basicsize == sizeof(PyPureMixinObject) - && ! (CMETHOD(self->meth)->self) - ) - { - /* Special HACK^H^H^Hcase: - we are wrapping an abstract unbound CMethod */ - if (HasMethodHook(inst) && - /* This check prevents infinite recursion: */ - CMETHOD(self->meth)->doc != hook_mark - ) - return callCMethodWithHook(CMETHOD(self->meth),inst,args,kw); - return call_cmethod(CMETHOD(self->meth),inst,args,kw); - - } - else - { - a=Py_BuildValue("(O)",inst); - if (a) ASSIGN(a,PySequence_Concat(a,args)); - if (a) ASSIGN(a,callMethodWithPossibleHook(inst,self->meth,a,kw)); - return a; - } -} - -static PyObject * -PMethod_call(PMethod *self, PyObject *args, PyObject *kw) -{ - int size; - - if (self->self) return call_PMethod(self,self->self,args,kw); - - if ((size=PyTuple_Size(args)) > 0) - { - PyObject *first=0, *ftype=0; - UNLESS(first=PyTuple_GET_ITEM(args, 0)) return NULL; - if (! self->type || - ((ftype=PyObject_GetAttr(first,py__class__)) && - (ftype==(PyObject*)self->type || - (ExtensionClass_Check(ftype) && - CMethod_issubclass(AsExtensionClass(ftype), - AsExtensionClass(self->type)) - ) - ) - ) - ) - { - if (NeedsToBeBound(self->meth)) - { - PyObject *r, *rest; - UNLESS(r=CallMethodO(self->meth,py__of__,Build("(O)", first), - NULL)) - return NULL; - UNLESS(rest=PySequence_GetSlice(args,1,size)) - { - Py_DECREF(r); - return NULL; - } - ASSIGN(r,callMethodWithPossibleHook(first,r,rest,kw)); - Py_DECREF(rest); - return r; - } - Py_DECREF(ftype); - return callMethodWithPossibleHook(first,self->meth,args,kw); - } - Py_XDECREF(ftype); - } - - return JimErr_Format(PyExc_TypeError, - "unbound Python method must be called with %s" - " 1st argument", - "s", self->type->tp_name); -} - -static PyObject * -PMethod_getattro(PMethod *self, PyObject *oname) -{ - PyObject *r; - - if (PyString_Check(oname)) - { - char *name; - - UNLESS(name=PyString_AsString(oname)) return NULL; - - if (name[0]=='_' && name[1]=='_') - { - if (strcmp(name+2,"name__")==0) - return PyObject_GetAttrString(self->meth,"__name__"); - if (strcmp(name+2,"doc__")==0) - return PyObject_GetAttrString(self->meth,"__doc__"); - } - else if (PyEval_GetRestricted()) - { - PyErr_SetString(PyExc_RuntimeError, - "function attributes not accessible in restricted mode"); - return NULL; - } - else if (name[0]=='f' && name[1]=='u' && name[2]=='n' && name[3]=='c' - && name[4]=='_') - { - if (strcmp(name+5,"name")==0 ) - return PyObject_GetAttrString(self->meth,"__name__"); - if (strcmp(name+5,"doc")==0) - return PyObject_GetAttrString(self->meth,"__doc__"); - } - - if (*name++=='i' && *name++=='m' && *name++=='_') - { - if (strcmp(name,"func")==0) - { - Py_INCREF(self->meth); - return self->meth; - } - if (strcmp(name,"class")==0) - { - Py_INCREF(self->type); - return (PyObject *)self->type; - } - if (strcmp(name,"self")==0) - { - if (self->self) r=self->self; - else r=Py_None; - Py_INCREF(r); - return r; - } - } - } - - if (self->meth) - { - if ((r=PyObject_GetAttr(self->meth, oname))) return r; - PyErr_Clear(); - - if (self->self) /* Psuedo attrs */ - { - PyObject *myname; - - UNLESS(myname=PyObject_GetAttr(self->meth, py__name__)) return NULL; - oname=Py_BuildValue("OO", myname, oname); - Py_DECREF(myname); - UNLESS(oname) return NULL; - UNLESS_ASSIGN(oname,PyString_Format(concat_fmt, oname)) return NULL; - r=PyObject_GetAttr(self->self, oname); - Py_DECREF(oname); - return r; - } - } - - PyErr_SetObject(PyExc_AttributeError, oname); - return NULL; - - return PyObject_GetAttr(self->meth, oname); -} - -static int -PMethod_setattro(PMethod *self, PyObject *oname, PyObject *v) -{ - int r; - PyObject *spam; - - if (self->meth) - { - if ((spam=PyObject_GetAttr(self->meth, oname))) - { - Py_DECREF(spam); - PyErr_SetString(PyExc_TypeError, - "Attempt to overwrite shared method attribute"); - return -1; - } - else PyErr_Clear(); - - if (self->self && ! PyEval_GetRestricted()) /* Psuedo attrs */ - { - PyObject *myname; - - UNLESS(myname=PyObject_GetAttr(self->meth, py__name__)) return -1; - oname=Py_BuildValue("OO", myname, oname); - Py_DECREF(myname); - UNLESS(oname) return -1; - UNLESS_ASSIGN(oname,PyString_Format(concat_fmt, oname)) return -1; - r=PyObject_SetAttr(self->self, oname, v); - Py_DECREF(oname); - return r; - } - } - - PyErr_SetObject(PyExc_AttributeError, oname); - return -1; -} - -static PyTypeObject PMethodType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "Python Method", /*tp_name*/ - sizeof(PMethod), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)PMethod_dealloc, /*tp_dealloc*/ - (printfunc)0, /*tp_print*/ - 0, /*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)PMethod_call, /*tp_call*/ - (reprfunc)0, /*tp_str*/ - (getattrofunc)PMethod_getattro, /*tp_getattro*/ - (setattrofunc)PMethod_setattro, /* tp_setattro */ - - /* Space for future expansion */ - 0L,0L, - "Storage manager for unbound C function PyObject data" - /* Documentation string */ -}; - -static PyObject *CCL_getattr(PyExtensionClass*,PyObject*,int); - -/* Special Methods */ - -#define UNARY_OP(OP) \ -static PyObject * \ -OP ## _by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) { \ - UNLESS(PyArg_ParseTuple(args,"")) return NULL; \ - return ob_type->tp_ ## OP(self); \ -} - -UNARY_OP(repr) -UNARY_OP(str) - -static PyObject * -hash_by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) { - long r; - UNLESS(PyArg_ParseTuple(args,"")) return NULL; - UNLESS(-1 != (r=ob_type->tp_hash(self))) return NULL; - return PyInt_FromLong(r); -} - -static PyObject * -call_by_name(PyObject *self, PyObject *args, PyObject *kw, - PyTypeObject *ob_type) -{ - return ob_type->tp_call(self,args,kw); -} - -static PyObject * -compare_by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) -{ - PyObject *other; - - UNLESS(PyArg_ParseTuple(args,"O", &other)) return NULL; - return PyInt_FromLong(ob_type->tp_compare(self,other)); -} - -static PyObject * -getattr_by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) -{ - char *name; - UNLESS(PyArg_ParseTuple(args,"s",&name)) return NULL; - return ob_type->tp_getattr(self,name); -} - -static PyObject * -setattr_by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) -{ - char *name; - PyObject *v; - UNLESS(PyArg_ParseTuple(args,"sO",&name,&v)) return NULL; - UNLESS(-1 != ob_type->tp_setattr(self,name,v)) return NULL; - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -getattro_by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) -{ - PyObject *name; - UNLESS(PyArg_ParseTuple(args,"O",&name)) return NULL; - return ob_type->tp_getattro(self,name); -} - -static PyObject * -setattro_by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) -{ - PyObject *name; - PyObject *v; - UNLESS(PyArg_ParseTuple(args,"OO",&name,&v)) return NULL; - UNLESS(-1 != ob_type->tp_setattro(self,name,v)) return NULL; - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -length_by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) -{ - long r; - UNLESS(PyArg_ParseTuple(args,"")) return NULL; - if (ob_type->tp_as_sequence) - { - UNLESS(-1 != (r=ob_type->tp_as_sequence->sq_length(self))) - return NULL; - } - else - { - UNLESS(-1 != (r=ob_type->tp_as_mapping->mp_length(self))) - return NULL; - } - return PyInt_FromLong(r); -} - -static PyObject * -getitem_by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) -{ - PyObject *key; - - UNLESS(PyArg_ParseTuple(args,"O",&key)) return NULL; - if (ob_type->tp_as_mapping) - return ob_type->tp_as_mapping->mp_subscript(self,key); - else - { - int index; - UNLESS(-1 != (index=PyInt_AsLong(key))) return NULL; - return ob_type->tp_as_sequence->sq_item(self,index); - } -} - -static PyCFunction item_by_name=(PyCFunction)getitem_by_name; -static PyCFunction subscript_by_name=(PyCFunction)getitem_by_name; - -static PyObject * -setitem_by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) -{ - PyObject *key, *v; - long r; - - UNLESS(PyArg_ParseTuple(args,"OO",&key,&v)) return NULL; - if (ob_type->tp_as_mapping) - r=ob_type->tp_as_mapping->mp_ass_subscript(self,key,v); - else - { - int index; - UNLESS(-1 != (index=PyInt_AsLong(key))) return NULL; - r=ob_type->tp_as_sequence->sq_ass_item(self,index,v); - } - if (r < 0) return NULL; - Py_INCREF(Py_None); - return Py_None; -} - -static PyCFunction ass_item_by_name=(PyCFunction)setitem_by_name; -static PyCFunction ass_subscript_by_name=(PyCFunction)setitem_by_name; - -static PyObject * -slice_by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) -{ - int i1,i2; - - UNLESS(PyArg_ParseTuple(args,"ii",&i1,&i2)) return NULL; - return ob_type->tp_as_sequence->sq_slice(self,i1,i2); -} - -static PyObject * -ass_slice_by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) -{ - int i1,i2; - PyObject *v; - long r; - - UNLESS(PyArg_ParseTuple(args,"iiO",&i1,&i2,&v)) return NULL; - r=ob_type->tp_as_sequence->sq_ass_slice(self,i1,i2,v); - if (r<0) return NULL; - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -concat_by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) -{ - PyObject *other; - UNLESS(PyArg_ParseTuple(args,"O",&other)) return NULL; - return ob_type->tp_as_sequence->sq_concat(self,other); -} - -static PyObject * -repeat_by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) -{ - int r; - UNLESS(PyArg_ParseTuple(args,"i",&r)) return NULL; - return ob_type->tp_as_sequence->sq_repeat(self,r); -} - -#define BINOP(OP,AOP) \ -static PyObject * \ -OP ## _by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) { \ - PyObject *v; \ - UNLESS(PyArg_ParseTuple(args,"O",&v)) return NULL; \ - return ob_type->tp_as_number->nb_ ## OP(self, v); \ -} - -BINOP(add,Add) -BINOP(subtract,Subtract) -BINOP(multiply,Multiply) -BINOP(divide,Divide) -BINOP(remainder,Remainder) -BINOP(divmod,Divmod) - -static PyObject * -power_by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) -{ - PyObject *v, *z=NULL; - UNLESS(PyArg_ParseTuple(args,"O|O",&v,&z)) return NULL; - return ob_type->tp_as_number->nb_power(self,v,z); -} - -#define UNOP(OP) \ -static PyObject * \ -OP ## _by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) { \ - UNLESS(PyArg_ParseTuple(args,"")) return NULL; \ - return ob_type->tp_as_number->nb_ ## OP(self); \ -} - -UNOP(negative) -UNOP(positive) -UNOP(absolute) - -static PyObject * -nonzero_by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) { - long r; - UNLESS(PyArg_ParseTuple(args,"")) return NULL; - UNLESS(-1 != (r=ob_type->tp_as_number->nb_nonzero(self))) return NULL; - return PyInt_FromLong(r); -} - -UNOP(invert) - -BINOP(lshift,Lshift) -BINOP(rshift,Rshift) -BINOP(and,And) -BINOP(or,Or) -BINOP(xor,Xor) - -static PyObject * -coerce_by_name(PyObject *self, PyObject *args, PyTypeObject *ob_type) -{ - PyObject *v; - int r; - UNLESS(PyArg_ParseTuple(args,"O", &v)) return NULL; - UNLESS(-1 != (r=ob_type->tp_as_number->nb_coerce(&self,&v))) - { - Py_INCREF(Py_None); - return Py_None; - } - args=Py_BuildValue("OO",self,v); - Py_DECREF(self); - Py_DECREF(v); - return args; -} - -UNOP(long) -UNOP(int) -UNOP(float) -UNOP(oct) -UNOP(hex) - -#define FILLENTRY(T,MN,N,F,D) if (T ## _ ## MN) { \ - UNLESS(-1 != PyMapping_SetItemString(dict,"__" # N "__", \ - newCMethod(type, NULL, "__" # N "__", \ - (PyCFunction)MN ## _by_name, F | METH_BY_NAME, # D))) \ - goto err; } - -static PyObject * -getBaseDictionary(PyExtensionClass *type) -{ - PyNumberMethods *nm; - PySequenceMethods *sm; - PyMappingMethods *mm; - PyObject *dict; - - UNLESS(dict=type->class_dictionary) - UNLESS(dict=PyDict_New()) return NULL; - - FILLENTRY(type->tp, repr, repr, METH_VARARGS, - "convert to an expression string"); - FILLENTRY(type->tp, hash, hash, METH_VARARGS, "compute a hash value"); - FILLENTRY(type->tp, call, call, METH_VARARGS | METH_KEYWORDS, - "call as a function"); - FILLENTRY(type->tp, compare, comp, METH_VARARGS, - "compare with another object"); - FILLENTRY(type->tp, getattr, getattr, METH_VARARGS, "Get an attribute"); - FILLENTRY(type->tp, setattr, setattr, METH_VARARGS, "Set an attribute"); - FILLENTRY(type->tp, getattro, getattr, METH_VARARGS, "Get an attribute"); - FILLENTRY(type->tp, setattro, setattr, METH_VARARGS, "Set an attribute"); - - if ((sm=type->tp_as_sequence)) - { - FILLENTRY(sm->sq, length, len, METH_VARARGS, "Get the object length"); - FILLENTRY(sm->sq, repeat, mul, METH_VARARGS, - "Get a new object that is the object repeated."); - FILLENTRY(sm->sq, item, getitem, METH_VARARGS, "Get an item"); - FILLENTRY(sm->sq, slice, getslice, METH_VARARGS, "Get a slice"); - FILLENTRY(sm->sq, ass_item, setitem, METH_VARARGS, "Assign an item"); - FILLENTRY(sm->sq, ass_slice, setslice, METH_VARARGS, "Assign a slice"); - } - - if ((mm=type->tp_as_mapping)) - { - FILLENTRY(mm->mp, length, len, METH_VARARGS, "Get the object length"); - FILLENTRY(mm->mp, subscript, getitem, METH_VARARGS, "Get an item"); - FILLENTRY(mm->mp, ass_subscript, setitem, METH_VARARGS, - "Assign an item"); - } - - if ((nm=type->tp_as_number) != NULL) - { - FILLENTRY(nm->nb, add, add, METH_VARARGS, "Add to another"); - FILLENTRY(nm->nb, subtract, sub, METH_VARARGS, "Subtract another"); - FILLENTRY(nm->nb, multiply, mul, METH_VARARGS, "Multiple by another"); - FILLENTRY(nm->nb, divide, div, METH_VARARGS, "Divide by another"); - FILLENTRY(nm->nb, remainder, mod, METH_VARARGS, "Compute a remainder"); - FILLENTRY(nm->nb, power, pow, METH_VARARGS, "Raise to a power"); - FILLENTRY(nm->nb, divmod, divmod, METH_VARARGS, - "Compute the whole result and remainder of dividing\n" - "by another"); - FILLENTRY(nm->nb, negative, neg, METH_VARARGS, - "Get the negative value."); - FILLENTRY(nm->nb, positive, pos, METH_VARARGS, "Compute positive value"); - FILLENTRY(nm->nb, absolute, abs, METH_VARARGS, "Compute absolute value"); - FILLENTRY(nm->nb, nonzero, nonzero, METH_VARARGS, - "Determine whether nonzero"); - FILLENTRY(nm->nb, invert, inv, METH_VARARGS, "Compute inverse"); - FILLENTRY(nm->nb, lshift, lshift, METH_VARARGS, "Shist left"); - FILLENTRY(nm->nb, rshift, rshift, METH_VARARGS, "Shist right"); - FILLENTRY(nm->nb, and, and, METH_VARARGS, "bitwize logical and"); - FILLENTRY(nm->nb, or, or, METH_VARARGS, "bitwize logical or"); - FILLENTRY(nm->nb, xor, xor, METH_VARARGS, "bitwize logical excusive or"); - FILLENTRY(nm->nb, coerce, coerce, METH_VARARGS, - "Coerce woth another to a common type"); - FILLENTRY(nm->nb, int, int, METH_VARARGS, "Convert to an integer"); - FILLENTRY(nm->nb, long, long, METH_VARARGS, - "Convert to an infinite-precision integer"); - FILLENTRY(nm->nb, float, float, METH_VARARGS, - "Convert to floating point number"); - FILLENTRY(nm->nb, oct, oct, METH_VARARGS, "Convert to an octal string"); - FILLENTRY(nm->nb, hex, hex, METH_VARARGS, - "Convert to a hexadecimal string"); - } - - if ((sm=type->tp_as_sequence)) - { - FILLENTRY(sm->sq, concat, add, METH_VARARGS, - "Concatinate the object with another"); - } - - return dict; -err: - Py_DECREF(dict); - return NULL; -} - -#undef UNARY_OP -#undef BINOP -#undef UNOP -#undef FILLENTRY - -PyObject * -EC_reduce(PyObject *self, PyObject *args) -{ - PyObject *state=0; - - if ((args=PyObject_GetAttr(self,py__getinitargs__))) - { - UNLESS_ASSIGN(args,PyEval_CallObject(args,NULL)) return NULL; - UNLESS_ASSIGN(args,PySequence_Tuple(args)) return NULL; - } - else - { - PyErr_Clear(); - if (ExtensionClassOf(self)->class_flags & EXTENSIONCLASS_BASICNEW_FLAG) - { - args=Py_None; - Py_INCREF(args); - } - else args=PyTuple_New(0); - } - - if ((state=PyObject_GetAttr(self,py__getstate__))) - { - UNLESS_ASSIGN(state,PyEval_CallObject(state,NULL)) goto err; - ASSIGN(args,Py_BuildValue("OOO", self->ob_type, args, state)); - Py_DECREF(state); - } - else - { - PyErr_Clear(); - - if ((state=PyObject_GetAttr(self, py__dict__))) - { - ASSIGN(args,Py_BuildValue("OOO", self->ob_type, args, state)); - Py_DECREF(state); - } - else - { - PyErr_Clear(); - ASSIGN(args, Py_BuildValue("OO", self->ob_type, args)); - } - } - - return args; - -err: - Py_DECREF(args); - return NULL; -} - -static PyObject * -inheritedAttribute(PyExtensionClass *self, PyObject *args) -{ - PyObject *name; - - UNLESS(PyArg_ParseTuple(args,"O!",&PyString_Type, &name)) return NULL; - - return CCL_getattr(AsExtensionClass(self),name,1); -} - -static PyObject * -basicnew(PyExtensionClass *self, PyObject *args) -{ - PyObject *inst=0; - typedef struct { PyObject_VAR_HEAD } PyVarObject__; - - if (! self->tp_dealloc) - { - PyErr_SetString(PyExc_TypeError, - "Attempt to create instance of an abstract type"); - return NULL; - } - - UNLESS(self->class_flags & EXTENSIONCLASS_BASICNEW_FLAG) - return PyObject_CallObject(OBJECT(self), NULL); - - if (self->tp_itemsize) - { - /* We have a variable-sized object, we need to get it's size */ - PyObject *var_size; - int size; - - UNLESS(var_size=CCL_getattr(self, py__var_size__, 0)) return NULL; - UNLESS_ASSIGN(var_size,PyObject_CallObject(var_size,NULL)) return NULL; - size=PyInt_AsLong(var_size); - if (PyErr_Occurred()) return NULL; - UNLESS(inst=PyObject_NEW_VAR(PyObject,(PyTypeObject *)self, size)) - return NULL; - memset(inst,0,self->tp_basicsize+self->tp_itemsize*size); - ((PyVarObject__*)inst)->ob_size=size; - } - else - { - UNLESS(inst=PyObject_NEW(PyObject,(PyTypeObject *)self)) return NULL; - memset(inst,0,self->tp_basicsize); - } - - inst->ob_refcnt=1; - inst->ob_type=(PyTypeObject *)self; - Py_INCREF(self); - - if (ClassHasInstDict(self)) - UNLESS(INSTANCE_DICT(inst)=PyDict_New()) goto err; - - if (self->bases && subclass_watcher && - ! PyObject_CallMethod(subclass_watcher,"created","O",inst)) - PyErr_Clear(); - - return inst; - -err: - Py_DECREF(inst); - return NULL; -} - -struct PyMethodDef ECI_methods[] = { - {"__reduce__",(PyCFunction)EC_reduce, METH_VARARGS, - "__reduce__() -- Reduce an instance into it's class and creation data" - }, - {"inheritedAttribute",(PyCFunction)inheritedAttribute, - METH_VARARGS | METH_CLASS_METHOD, - "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" - }, - {"__basicnew__",(PyCFunction)basicnew, - METH_VARARGS | METH_CLASS_METHOD, - "__basicnew__() -- return a new uninitialized instance" - }, - {NULL, NULL} /* sentinel */ -}; - -static PyObject * -initializeBaseExtensionClass(PyExtensionClass *self) -{ - static PyMethodChain top = { ECI_methods, NULL }; - PyMethodChain *chain; - PyObject *dict; - int abstract; - - /* Is this an abstract, or at least a dataless, class? */ - abstract=self->tp_basicsize == sizeof(PyPureMixinObject); - - self->ob_type=(PyTypeObject*)&ECType; - Py_INCREF(self->ob_type); - - UNLESS(dict=self->class_dictionary=getBaseDictionary(self)) return NULL; - - if (self->tp_name) - { - PyObject *name; - - UNLESS(name=PyString_FromString(self->tp_name)) goto err; - if (0 > PyMapping_SetItemString(dict,"__doc__",name)) goto err; - Py_DECREF(name); - } - else if (0 > PyMapping_SetItemString(dict,"__doc__",Py_None)) goto err; - - if (&self->methods) chain=&(self->methods); - else chain=⊤ - - while (1) - { - PyMethodDef *ml = chain->methods; - - for (; ml && ml->ml_name != NULL; ml++) - { - if (ml->ml_meth) - { - if (! PyMapping_HasKeyString(dict,ml->ml_name)) - { - PyObject *m; - - /* Note that we create a circular reference here. - I suppose that this isn't so bad, since this is - probably a static thing anyway. Still, it is a - bit troubling. Oh well. - */ - if (ml->ml_flags & METH_CLASS_METHOD) - { - UNLESS(m=newCMethod( - AsExtensionClass(self->ob_type), NULL, - ml->ml_name, ml->ml_meth, - ml->ml_flags, ml->ml_doc)) - return NULL; - } - else - { - UNLESS(m=newCMethod(self, NULL, ml->ml_name, ml->ml_meth, - ml->ml_flags, ml->ml_doc)) - return NULL; - - if (abstract) - UNLESS_ASSIGN(m, newPMethod(self, m)) - return NULL; - } - - if (PyMapping_SetItemString(dict,ml->ml_name,m) < 0) - return NULL; - } - } - else if (ml->ml_doc && *(ml->ml_doc)) - { - /* No actual meth, this is probably to hook a doc string - onto a special method. */ - PyObject *m; - - if ((m=PyMapping_GetItemString(dict,ml->ml_name))) - { - if (m->ob_type==&CMethodType) - ((CMethod *)(m))->doc=ml->ml_doc; - } - else - PyErr_Clear(); - } - } - - if (chain == &top) break; - - UNLESS(chain=chain->link) chain=⊤ - } - return (PyObject*)self; - -err: - Py_DECREF(dict); - return NULL; -} - -static void -CCL_dealloc(PyExtensionClass *self) -{ -#ifdef TRACE_DEALLOC - fprintf(stderr,"Deallocating %s\n", self->tp_name); -#endif - Py_XDECREF(self->class_dictionary); - /* if this ExtensionClass was subclassed in python, free this info */ - if ((self->class_flags & EXTENSIONCLASS_PYSUBCLASS_FLAG) != 0) - { - /* If we are a subclass, then we strduped our name */ - free(self->tp_name); - - /* And we allocated our own protocol structures */ - if (self->tp_as_number) free(self->tp_as_number); - if (self->tp_as_sequence) free(self->tp_as_sequence); - if (self->tp_as_mapping) free(self->tp_as_mapping); - } - Py_XDECREF(self->bases); - if (((PyExtensionClass*)self->ob_type) != self) Py_XDECREF(self->ob_type); - PyMem_DEL(self); -} - -static PyObject * -ExtensionClass_FindInstanceAttribute(PyObject *inst, PyObject *oname, - char *name) -{ - /* Look up an attribute for an instance from: - - The instance dictionary, - The class dictionary, or - The base objects. - */ - PyObject *r=0; - PyExtensionClass *self; - - if (! name) return NULL; - - self=(PyExtensionClass*)(inst->ob_type); - - if (*name=='_' && name[1]=='_') - { - char *n=name+2; - if (*n == 'c' && strcmp(n,"class__")==0) - { - Py_INCREF(self); - return (PyObject*)self; - } - if (ClassHasInstDict(self) && *n=='d' && strcmp(n,"dict__")==0) - { - r = INSTANCE_DICT(inst); - Py_INCREF(r); - return r; - } - } - - if (ClassHasInstDict(self)) - { - r= INSTANCE_DICT(inst); - if ((r = PyObject_GetItem(r,oname)) && NeedsToBeBound(r)) - { - ASSIGN(r, CallMethodO(r, py__of__, Build("(O)", inst), NULL)); - UNLESS(r) return NULL; - } - } - UNLESS(r) - { - if (*name=='_' && name[1]=='_' && name[2]=='b' && - strcmp(name+2,"bases__")==0) - { - PyErr_SetObject(PyExc_AttributeError, oname); - return NULL; - } - - PyErr_Clear(); - - UNLESS(r=CCL_getattr(self,oname,0)) return NULL; - - /* We got something from our class, maybe its an unbound method. */ - if (UnboundCMethod_Check(r)) - ASSIGN(r,(PyObject*)bindCMethod((CMethod*)r,inst)); - else if (UnboundPMethod_Check(r)) - ASSIGN(r,bindPMethod((PMethod*)r,inst)); - } - - return r; -} - -static PyObject * -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, int look_super) -{ - PyObject *r=0; - - if (! look_super) r=PyObject_GetItem(self->class_dictionary,oname); - UNLESS(r) - { - if (self->bases) - { - int n, i; - PyObject *c; - - n=PyTuple_Size(self->bases); - for (i=0; i < n; i++) - { - PyErr_Clear(); - c=PyTuple_GET_ITEM(self->bases, i); - if (ExtensionClass_Check(c)) - r=CCL_getattr(AsExtensionClass(c),oname,0); - else - r=PyObject_GetAttr(c,oname); - if (r) break; - } - } - UNLESS(r) - { - PyObject *t, *v, *tb; - - PyErr_Fetch(&t,&v,&tb); - if (t==PyExc_KeyError && PyObject_Compare(v,oname) == 0) - { - Py_DECREF(t); - t=PyExc_AttributeError; - Py_INCREF(t); - } - PyErr_Restore(t,v,tb); - return NULL; - } - } - - if (PyFunction_Check(r) || NeedsToBeBound(r)) - ASSIGN(r,newPMethod(self,r)); - else if (PyMethod_Check(r) && ! PyMethod_Self(r)) - ASSIGN(r,newPMethod(self, PyMethod_Function(r))); - - return r; -} - -static PyObject * -CCL_reduce(PyExtensionClass *self, PyObject *args) -{ - return PyString_FromString(self->tp_name); -} - -PyObject * -CCL_getattro(PyExtensionClass *self, PyObject *name) -{ - char *n, *nm=0; - PyObject *r; - - if (PyString_Check(name) && (n=nm=PyString_AS_STRING((PyStringObject*)name))) - { - if (*n=='_' && *++n=='_') - { - switch (*++n) - { - case 's': - if (strcmp(n,"safe_for_unpickling__")==0) - return PyInt_FromLong(1); - break; - case 'n': - if (strcmp(n,"name__")==0) - return PyString_FromString(self->tp_name); - break; - case 'b': - if (strcmp(n,"bases__")==0) - { - if (self->bases) - { - Py_INCREF(self->bases); - return self->bases; - } - else - return PyTuple_New(0); - } - break; - case 'r': - if (strcmp(n,"reduce__")==0) - return newCMethod(self,(PyObject*)self, - "__reduce__",(PyCFunction)CCL_reduce,0, - "__reduce__() -- Reduce the class to a class name"); - break; - case 'd': - if (strcmp(n,"dict__")==0) - { - Py_INCREF(self->class_dictionary); - return self->class_dictionary; - } - break; - case 'c': - if (strcmp(n,"class__")==0) - { - Py_INCREF(self->ob_type); - return OBJECT(self->ob_type); - } - break; - } - } - } - - if ((r=CCL_getattr(self,name,0))) - { - if (UnboundCMethod_Check(r) && (AsCMethod(r)->flags & METH_CLASS_METHOD)) - ASSIGN(r,(PyObject*)bindCMethod((CMethod*)r,OBJECT(self))); - } - - return r; -} - -static int -CCL_setattro(PyExtensionClass *self, PyObject *name, PyObject *v) -{ - if (! v) return PyObject_DelItem(self->class_dictionary, name); - - if (v && UnboundCMethod_Check(v) && - ! (self->class_flags & EXTENSIONCLASS_METHODHOOK_FLAG) - ) - { - char *n; - PyNumberMethods *nm; - PySequenceMethods *s, *ms; - PyMappingMethods *m, *mm; - - UNLESS(n=PyString_AsString(name)) return -1; - if (*n++=='_' && *n++=='_') - { -#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==(PyCFunction)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==(PyCFunction)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==(PyCFunction)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(PyExtensionClass *self, PyObject *arg, PyObject *kw) -{ - PyObject *inst=0, *init=0, *args=0; - typedef struct { PyObject_VAR_HEAD } PyVarObject__; - - if (! self->tp_dealloc) - { - PyErr_SetString(PyExc_TypeError, - "Attempt to create instance of an abstract type"); - return NULL; - } - - if (self->tp_itemsize) - { - /* We have a variable-sized object, we need to get it's size */ - PyObject *var_size; - int size; - - if ((var_size=CCL_getattr(self,py__var_size__, 0))) - { - UNLESS_ASSIGN(var_size,PyObject_CallObject(var_size,arg)) - return NULL; - size=PyInt_AsLong(var_size); - if (PyErr_Occurred()) return NULL; - } - else - { - UNLESS(-1 != (size=PyTuple_Size(arg))) return NULL; - if (size > 0) - { - var_size=PyTuple_GET_ITEM(arg, 0); - if (PyInt_Check(var_size)) - size=PyInt_AsLong(var_size); - else - size=-1; - } - else - size=-1; - if (size < 0) - { - PyErr_SetString(PyExc_TypeError, - "object size expected as first argument"); - return NULL; - } - } - UNLESS(inst=PyObject_NEW_VAR(PyObject,(PyTypeObject *)self, size)) - return NULL; - memset(inst,0,self->tp_basicsize+self->tp_itemsize*size); - ((PyVarObject__*)inst)->ob_size=size; - } - else - { - UNLESS(inst=PyObject_NEW(PyObject,(PyTypeObject *)self)) return NULL; - memset(inst,0,self->tp_basicsize); - } - - inst->ob_refcnt=1; - inst->ob_type=(PyTypeObject *)self; - Py_INCREF(self); - - if (ClassHasInstDict(self)) - UNLESS(INSTANCE_DICT(inst)=PyDict_New()) goto err; - - if ((init=CCL_getattr(self,py__init__,0))) - { - UNLESS(args=Py_BuildValue("(O)",inst)) goto err; - if (arg) UNLESS_ASSIGN(args,PySequence_Concat(args,arg)) goto err; - UNLESS_ASSIGN(args,PyEval_CallObjectWithKeywords(init,args,kw)) goto err; - Py_DECREF(args); - Py_DECREF(init); - } - else PyErr_Clear(); - - if (self->bases && subclass_watcher && - ! PyObject_CallMethod(subclass_watcher,"created","O",inst)) - PyErr_Clear(); - - return inst; -err: - Py_DECREF(inst); - Py_XDECREF(init); - Py_XDECREF(args); - return NULL; -} - -static PyObject * -CCL_repr(PyExtensionClass *self) -{ - char p[128], *pp; - PyObject *m; - - if ((m=PyObject_GetAttr(OBJECT(self), py__module__))) - { - if (! PyObject_IsTrue(m)) - { - Py_DECREF(m); - m=0; - } - } - else PyErr_Clear(); - - sprintf(p,"%p",self); - if (*p=='0' && p[1]=='x') pp=p+2; - else pp=p; - - - if (m) ASSIGN(m, JimString_Build("<extension class %s.%s at %s>","Oss", - m, self->tp_name, pp)); - else m= JimString_Build("<extension class %s at %s>","ss", - self->tp_name, pp); - - return m; -} - -static PyTypeObject ECTypeType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "ExtensionClass Class", /*tp_name*/ - sizeof(PyExtensionClass), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)CCL_dealloc, /*tp_dealloc*/ - (printfunc)0, /*tp_print*/ - (getattrfunc)0, /*tp_getattr*/ - (setattrfunc)0, /*tp_setattr*/ - (cmpfunc)0, /*tp_compare*/ - (reprfunc)CCL_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - (hashfunc)0, /*tp_hash*/ - (ternaryfunc)CCL_call, /*tp_call*/ - (reprfunc)0, /*tp_str*/ - (getattrofunc)CCL_getattro, /*tp_getattr with object key*/ - (setattrofunc)CCL_setattro, /*tp_setattr with object key*/ - /* Space for future expansion */ - 0L,0L, - "Class of C classes" /* Documentation string */ -}; - -/* End of code for ExtensionClass objects */ -/* -------------------------------------------------------- */ - -/* subclassing code: */ - -static PyObject * -subclass_getspecial(PyObject *inst, PyObject *oname) -{ - PyObject *r=0; - PyExtensionClass *self; - - self=(PyExtensionClass*)(inst->ob_type); - if (HasInstDict(inst)) - { - r= INSTANCE_DICT(inst); - r = PyObject_GetItem(r,oname); - UNLESS(r) - { - PyErr_Clear(); - r=CCL_getattr(self,oname,0); - } - } - else r=CCL_getattr(self,oname,0); - - return r; -} - -static PyObject * -subclass_getattro(PyObject *self, PyObject *name) -{ - PyObject *r; - - if (! name) return NULL; - UNLESS(r=EC_findiattro(self,name)) - { - PyErr_Clear(); - r=EC_findiattro(self,py__getattr__); - if (r) ASSIGN(r,PyObject_CallFunction(r,"O",name)); - if (r && NeedsToBeBound(r)) - ASSIGN(r, CallMethodO(r, py__of__, Build("(O)", self), NULL)); - } - return r; -} - -static int -subclass_simple_setattro(PyObject *self, PyObject *name, PyObject *v) -{ - if (! HasInstDict(self)) - { - PyErr_SetObject(PyExc_AttributeError, name); - return -1; - } - if (v) - return PyDict_SetItem(INSTANCE_DICT(self),name,v); - else - return PyDict_DelItem(INSTANCE_DICT(self),name); -} - -static int -subclass_simple_setattr(PyObject *self, char *name, PyObject *v) -{ - if (! HasInstDict(self)) - { - PyErr_SetString(PyExc_AttributeError, name); - return -1; - } - if (v) - return PyDict_SetItemString(INSTANCE_DICT(self),name,v); - else - return PyDict_DelItemString(INSTANCE_DICT(self),name); -} - -static int -subclass_setattr(PyObject *self, PyObject *oname, char *name, PyObject *v) -{ - PyObject *m=0, *et, *ev, *etb; - - if (! name) return -1; - - if (!v && (m=subclass_getspecial(self,py__delattr__))) - { - if (UnboundEMethod_Check(m)) - { - UNLESS_ASSIGN(m,PyObject_CallFunction(m,"OO",self,oname)) return -1; - } - else UNLESS_ASSIGN(m,PyObject_CallFunction(m,"O",oname)) return -1; - Py_DECREF(m); - return 0; - } - - UNLESS(m=subclass_getspecial(self,py__setattr__)) - goto default_setattr; - if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)setattr_by_name - && SubclassInstance_Check(self,AsCMethod(m)->type)) - { - UNLESS(-1 != AsCMethod(m)->type->tp_setattr(self,name,v)) - goto dictionary_setattr; - return 0; - } - else - if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)setattro_by_name - && SubclassInstance_Check(self,AsCMethod(m)->type)) - { - UNLESS(-1 != AsCMethod(m)->type->tp_setattro(self,oname,v)) - goto dictionary_setattr; - return 0; - } - if (! v) goto default_setattr; - 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; - -dictionary_setattr: - - Py_XDECREF(m); - - PyErr_Fetch(&et, &ev, &etb); - if (et==PyExc_AttributeError) - { - char *s; - - if (ev && PyString_Check(ev) && (s=PyString_AsString(ev)) && - strcmp(s,name)==0) - { - Py_XDECREF(et); - Py_XDECREF(ev); - Py_XDECREF(etb); - et=0; - } - } - if (et) - { - PyErr_Restore(et,ev,etb); - return -1; - } - -default_setattr: - - PyErr_Clear(); - - return subclass_simple_setattro(self, oname, v); -} - -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=subclass_getspecial(self,py__cmp__)) - { - PyErr_Clear(); - return self-v; - } - - if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)compare_by_name - && SubclassInstance_Check(self,AsCMethod(m)->type) - && ! HasMethodHook(self)) - r=AsCMethod(m)->type->tp_compare(self,v); - else - { - 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); - return r; -} - -static long -subclass_hash(PyObject *self) -{ - PyObject *m; - long r; - - UNLESS(m=subclass_getspecial(self,py__hash__)) return -1; - if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)hash_by_name - && SubclassInstance_Check(self,AsCMethod(m)->type) - && ! HasMethodHook(self)) - r=AsCMethod(m)->type->tp_hash(self); - else - { - 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); - return r; -} - -static PyObject * -default_subclass_repr(PyObject *self) -{ - char p[128], *pp; - - PyErr_Clear(); - sprintf(p,"%p",self); - if (*p=='0' && p[1]=='x') pp=p+2; - else pp=p; - return JimString_Build("<%s instance at %s>","ss", - self->ob_type->tp_name, pp); -} - -static PyObject * -subclass_repr(PyObject *self) -{ - PyObject *m; - - UNLESS(m=subclass_getspecial(self,py__repr__)) - return default_subclass_repr(self); - - if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)repr_by_name - && SubclassInstance_Check(self,AsCMethod(m)->type) - && ! HasMethodHook(self)) - ASSIGN(m,AsCMethod(m)->type->tp_repr(self)); - else if (UnboundEMethod_Check(m)) - ASSIGN(m,PyObject_CallFunction(m,"O",self)); - else - ASSIGN(m,PyObject_CallFunction(m,"")); - return m; -} - -static PyObject * -subclass_call(PyObject *self, PyObject *args, PyObject *kw) -{ - PyObject *m; - - 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) - && ! HasMethodHook(self)) - ASSIGN(m,AsCMethod(m)->type->tp_call(self,args,kw)); - else - { - if (UnboundEMethod_Check(m)) - { - PyObject *a; - a=Py_BuildValue("(O)",self); - if (a) ASSIGN(a,PySequence_Concat(a,args)); - if (a) ASSIGN(m,PyEval_CallObjectWithKeywords(m,a,kw)); - else ASSIGN(m,NULL); - Py_XDECREF(a); - } - else - ASSIGN(m,PyEval_CallObjectWithKeywords(m,args,kw)); - } - return m; -} - -static PyObject * -subclass_str(PyObject *self) -{ - PyObject *m; - - UNLESS(m=subclass_getspecial(self,py__str__)) - { - PyErr_Clear(); - return subclass_repr(self); - } - if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)str_by_name - && SubclassInstance_Check(self,AsCMethod(m)->type) - && ! HasMethodHook(self)) - ASSIGN(m,AsCMethod(m)->type->tp_str(self)); - else if (UnboundEMethod_Check(m)) - ASSIGN(m,PyObject_CallFunction(m,"O",self)); - else - ASSIGN(m,PyObject_CallFunction(m,"")); - return m; -} - -#define BINSUB(M,N,A) \ -static PyObject * \ -subclass_ ## M(PyObject *self, PyObject *v) \ -{ \ - PyObject *m; \ - UNLESS(m=subclass_getspecial(self,py__ ## N ## __)) return NULL; \ - if (UnboundCMethod_Check(m) \ - && AsCMethod(m)->meth==(PyCFunction)M ## _by_name \ - && SubclassInstance_Check(self,AsCMethod(m)->type) \ - && ! HasMethodHook(self)) \ - ASSIGN(m,AsCMethod(m)->type->tp_as_number->nb_ ## M(self,v)); \ - else if (UnboundEMethod_Check(m)) \ - ASSIGN(m,PyObject_CallFunction(m,"OO",self,v)); \ - else \ - ASSIGN(m,PyObject_CallFunction(m,"O",v)); \ - return m; \ -} - -static PyObject * -subclass_add(PyObject *self, PyObject *v) -{ - PyObject *m; - - UNLESS(m=subclass_getspecial(self,py__add__)) return NULL; - - if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)concat_by_name - && SubclassInstance_Check(self,AsCMethod(m)->type) - && ! HasMethodHook(self)) - ASSIGN(m,AsCMethod(m)->type->tp_as_sequence->sq_concat(self,v)); - else if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)add_by_name - && SubclassInstance_Check(self,AsCMethod(m)->type) - && ! HasMethodHook(self)) - ASSIGN(m,AsCMethod(m)->type->tp_as_number->nb_add(self,v)); - else if (UnboundEMethod_Check(m)) - ASSIGN(m,PyObject_CallFunction(m,"OO",self,v)); - else - ASSIGN(m,PyObject_CallFunction(m,"O",v)); - - return m; -} - -BINSUB(subtract,sub,Subtract) - -static PyObject * -subclass_multiply(PyObject *self, PyObject *v) -{ - PyObject *m; - - UNLESS(m=subclass_getspecial(self,py__mul__)) return NULL; - if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)repeat_by_name - && SubclassInstance_Check(self,AsCMethod(m)->type) - && ! HasMethodHook(self)) - { - int i; - - i=PyInt_AsLong(v); - if (i==-1 && PyErr_Occurred()) return NULL; - ASSIGN(m,AsCMethod(m)->type->tp_as_sequence->sq_repeat(self,i)); - } - else if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)multiply_by_name - && SubclassInstance_Check(self,AsCMethod(m)->type) - && ! HasMethodHook(self)) - ASSIGN(m,AsCMethod(m)->type->tp_as_number->nb_multiply(self,v)); - else if (UnboundEMethod_Check(m)) - ASSIGN(m,PyObject_CallFunction(m,"OO",self,v)); - else - ASSIGN(m,PyObject_CallFunction(m,"O",v)); - return m; -} - -BINSUB(divide,div,Divide) -BINSUB(remainder,mod,Remainder) - -static PyObject * -subclass_power(PyObject *self, PyObject *v, PyObject *w) -{ - PyObject *m; - UNLESS(m=subclass_getspecial(self,py__pow__)) return NULL; - if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)power_by_name - && SubclassInstance_Check(self,AsCMethod(m)->type) - && ! HasMethodHook(self)) - ASSIGN(m,AsCMethod(m)->type->tp_as_number->nb_power(self,v,w)); - else if (UnboundEMethod_Check(m)) - ASSIGN(m,PyObject_CallFunction(m,"OOO",self,v,w)); - else - ASSIGN(m,PyObject_CallFunction(m,"OO",v,w)); - return m; -} - -BINSUB(divmod,divmod,Divmod) -BINSUB(lshift,lshift,Lshift) -BINSUB(rshift,rshift,Rshift) -BINSUB(and,and,And) -BINSUB(or,or,Or) -BINSUB(xor,xor,Xor) - - -static int -subclass_coerce(PyObject **self, PyObject **v) -{ - PyObject *m; - int r; - - UNLESS(m=subclass_getspecial(*self,py__coerce__)) - { - PyErr_Clear(); - Py_INCREF(*self); - Py_INCREF(*v); - return 0; - } - if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)coerce_by_name - && SubclassInstance_Check(*self,AsCMethod(m)->type) - && ! HasMethodHook(*self)) - r=AsCMethod(m)->type->tp_as_number->nb_coerce(self,v); - else - { - if (UnboundEMethod_Check(m)) - { - UNLESS_ASSIGN(m,PyObject_CallFunction(m,"OO",*self,*v)) return -1; - } - UNLESS_ASSIGN(m,PyObject_CallFunction(m,"O",*v)) return -1; - if (m==Py_None) r=-1; - else - { - PyArg_ParseTuple(m,"OO",self,v); - Py_INCREF(*self); - Py_INCREF(*v); - r=0; - } - } - Py_DECREF(m); - return r; -} - -#define UNSUB(M,N) \ -static PyObject * \ -subclass_ ## M(PyObject *self) \ -{ \ - PyObject *m; \ - UNLESS(m=subclass_getspecial(self,py__ ## N ## __)) return NULL; \ - if (UnboundCMethod_Check(m) \ - && AsCMethod(m)->meth==(PyCFunction)M ## _by_name \ - && SubclassInstance_Check(self,AsCMethod(m)->type) \ - && ! HasMethodHook(self)) \ - ASSIGN(m,AsCMethod(m)->type->tp_as_number->nb_ ## M(self)); \ - else if (UnboundEMethod_Check(m)) \ - ASSIGN(m,PyObject_CallFunction(m,"O",self)); \ - else \ - ASSIGN(m,PyObject_CallFunction(m,"")); \ - return m; \ -} - -UNSUB(negative, neg) -UNSUB(positive, pos) -UNSUB(absolute, abs) - -static int -subclass_nonzero(PyObject *self) -{ - PyObject *m; - long r; - - UNLESS(m=subclass_getspecial(self,py__nonzero__)) - { /* We are being asked is we are true - Check out len, and if that fails, say we are true. - */ - PyErr_Clear(); - UNLESS(m=subclass_getspecial(self,py__len__)) - { - PyErr_Clear(); - return 1; - } - } - if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)nonzero_by_name - && SubclassInstance_Check(self,AsCMethod(m)->type) - && ! HasMethodHook(self)) - r=AsCMethod(m)->type->tp_as_number->nb_nonzero(self); - else - { - 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); - return r; -} - -UNSUB(invert, inv) -UNSUB(int, int) -UNSUB(long, long) -UNSUB(float, float) -UNSUB(oct, oct) -UNSUB(hex, hex) - -#undef UNSUB -#undef BINSUB - - -static PyNumberMethods subclass_as_number = { - (binaryfunc)subclass_add, /*nb_add*/ - (binaryfunc)subclass_subtract, /*nb_subtract*/ - (binaryfunc)subclass_multiply, /*nb_multiply*/ - (binaryfunc)subclass_divide, /*nb_divide*/ - (binaryfunc)subclass_remainder, /*nb_remainder*/ - (binaryfunc)subclass_divmod, /*nb_divmod*/ - (ternaryfunc)subclass_power, /*nb_power*/ - (unaryfunc)subclass_negative, /*nb_negative*/ - (unaryfunc)subclass_positive, /*nb_positive*/ - (unaryfunc)subclass_absolute, /*nb_absolute*/ - (inquiry)subclass_nonzero, /*nb_nonzero*/ - (unaryfunc)subclass_invert, /*nb_invert*/ - (binaryfunc)subclass_lshift, /*nb_lshift*/ - (binaryfunc)subclass_rshift, /*nb_rshift*/ - (binaryfunc)subclass_and, /*nb_and*/ - (binaryfunc)subclass_xor, /*nb_xor*/ - (binaryfunc)subclass_or, /*nb_or*/ - (coercion)subclass_coerce, /*nb_coerce*/ - (unaryfunc)subclass_int, /*nb_int*/ - (unaryfunc)subclass_long, /*nb_long*/ - (unaryfunc)subclass_float, /*nb_float*/ - (unaryfunc)subclass_oct, /*nb_oct*/ - (unaryfunc)subclass_hex, /*nb_hex*/ -}; - -static long -subclass_length(PyObject *self) -{ - PyObject *m; - long r; - PyExtensionClass *t; - - UNLESS(m=subclass_getspecial(self,py__len__)) - { - /* Hm. Maybe we are being checked to see if we are true. - - Check to see if we have a __getitem__. If we don't, then - answer that we are true. - */ - PyErr_Clear(); - if ((m=subclass_getspecial(self,py__getitem__))) - { - /* Hm, we have getitem, must be error */ - Py_DECREF(m); - PyErr_SetObject(PyExc_AttributeError, py__len__); - return -1; - } - PyErr_Clear(); - return subclass_nonzero(self); - } - if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)length_by_name - && SubclassInstance_Check(self,AsCMethod(m)->type) - && ! HasMethodHook(self)) - { - t=(PyExtensionClass*)AsCMethod(m)->type; - Py_DECREF(m); - if (t->tp_as_sequence) - return t->tp_as_sequence->sq_length(self); - else - return t->tp_as_mapping->mp_length(self); - } - 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); - return r; -} - -static PyObject * -subclass_item(PyObject *self, int index) -{ - PyObject *m; - PyExtensionClass *t; - - 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) - && ! HasMethodHook(self)) - { - t=(PyExtensionClass*)AsCMethod(m)->type; - if (t->tp_as_sequence && t->tp_as_sequence->sq_item) - { - Py_DECREF(m); - return t->tp_as_sequence->sq_item(self,index); - } - } - if (UnboundEMethod_Check(m)) - ASSIGN(m,PyObject_CallFunction(m,"Oi",self,index)); - else - ASSIGN(m,PyObject_CallFunction(m,"i",index)); - return m; -} - -static PyObject * -subclass_slice(PyObject *self, int i1, int i2) -{ - PyObject *m; - - UNLESS(m=subclass_getspecial(self,py__getslice__)) return NULL; - if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)slice_by_name - && SubclassInstance_Check(self,AsCMethod(m)->type) - && ! HasMethodHook(self)) - ASSIGN(m,AsCMethod(m)->type->tp_as_sequence->sq_slice(self,i1,i2)); - else if (UnboundEMethod_Check(m)) - ASSIGN(m,PyObject_CallFunction(m,"Oii",self,i1,i2)); - else - ASSIGN(m,PyObject_CallFunction(m,"ii",i1,i2)); - return m; -} - -static long -subclass_ass_item(PyObject *self, int index, PyObject *v) -{ - PyObject *m; - PyExtensionClass *t; - - if (! v && (m=subclass_getspecial(self,py__delitem__))) - { - if (UnboundEMethod_Check(m)) - { - UNLESS_ASSIGN(m,PyObject_CallFunction(m,"Oi",self,index)) return -1; - } - else UNLESS_ASSIGN(m,PyObject_CallFunction(m,"i",index)) return -1; - Py_DECREF(m); - return 0; - } - - 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) - && ! HasMethodHook(self)) - { - t=(PyExtensionClass*)AsCMethod(m)->type; - if (t->tp_as_sequence && t->tp_as_sequence->sq_ass_item) - { - Py_DECREF(m); - return t->tp_as_sequence->sq_ass_item(self,index,v); - } - } - if (! v) - { - PyErr_SetObject(PyExc_AttributeError, py__delitem__); - return -1; - } - if (UnboundEMethod_Check(m)) - { - UNLESS_ASSIGN(m,PyObject_CallFunction(m,"OiO",self,index,v)) return -1; - } - else UNLESS_ASSIGN(m,PyObject_CallFunction(m,"iO",index,v)) return -1; - Py_DECREF(m); - return 0; -} - -static int -subclass_ass_slice(PyObject *self, int i1, int i2, PyObject *v) -{ - PyObject *m; - long r; - - if (! v && (m=subclass_getspecial(self,py__delslice__))) - { - if (UnboundEMethod_Check(m)) - { - UNLESS_ASSIGN(m,PyObject_CallFunction(m,"Oii",self,i1,i2)) return -1; - } - else UNLESS_ASSIGN(m,PyObject_CallFunction(m,"ii",i1,i2)) return -1; - Py_DECREF(m); - return 0; - } - - 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) - && ! HasMethodHook(self)) - { - r=AsCMethod(m)->type->tp_as_sequence->sq_ass_slice(self,i1,i2,v); - Py_DECREF(m); - return r; - } - - if (! v) - { - PyErr_SetObject(PyExc_AttributeError, py__delslice__); - return -1; - } - - if (UnboundEMethod_Check(m)) - { - UNLESS_ASSIGN(m,PyObject_CallFunction(m,"OiiO",self,i1,i2,v)) - return -1; - } - else UNLESS_ASSIGN(m,PyObject_CallFunction(m,"iiO",i1,i2,v)) return -1; - Py_DECREF(m); - return 0; -} - -static PyObject * -subclass_repeat(PyObject *self, int v) -{ - PyObject *m; - - UNLESS(m=subclass_getspecial(self,py__mul__)) return NULL; - if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)repeat_by_name - && SubclassInstance_Check(self,AsCMethod(m)->type) - && ! HasMethodHook(self)) - ASSIGN(m,AsCMethod(m)->type->tp_as_sequence->sq_repeat(self,v)); - else if (UnboundEMethod_Check(m)) - ASSIGN(m,PyObject_CallFunction(m,"Oi",self,v)); - else - ASSIGN(m,PyObject_CallFunction(m,"i",v)); - return m; -} - -PySequenceMethods subclass_as_sequence = { - (inquiry)subclass_length, /*sq_length*/ - (binaryfunc)subclass_add, /*sq_concat*/ - (intargfunc)subclass_repeat, /*sq_repeat*/ - (intargfunc)subclass_item, /*sq_item*/ - (intintargfunc)subclass_slice, /*sq_slice*/ - (intobjargproc)subclass_ass_item, /*sq_ass_item*/ - (intintobjargproc)subclass_ass_slice, /*sq_ass_slice*/ -}; - -static PyObject * -subclass_subscript(PyObject *self, PyObject *key) -{ - PyObject *m; - PyExtensionClass *t; - - 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) - && ! HasMethodHook(self)) - { - t=(PyExtensionClass*)AsCMethod(m)->type; - if (t->tp_as_mapping && t->tp_as_mapping->mp_subscript) - { - Py_DECREF(m); - return t->tp_as_mapping->mp_subscript(self,key); - } - else if (t->tp_as_sequence && t->tp_as_sequence->sq_item) - { - int i, l; - - Py_DECREF(m); - - UNLESS(PyInt_Check(key)) - { - PyErr_SetString(PyExc_TypeError, "sequence subscript not int"); - return NULL; - } - i=PyInt_AsLong(key); - if (i < 0) - { - if ((l=PyObject_Length(self)) < 0) return NULL; - i+=l; - } - return t->tp_as_sequence->sq_item(self,i); - } - } - if (UnboundEMethod_Check(m)) - ASSIGN(m,PyObject_CallFunction(m,"OO",self,key)); - else - ASSIGN(m,PyObject_CallFunction(m,"O",key)); - return m; -} - -static long -subclass_ass_subscript(PyObject *self, PyObject *index, PyObject *v) -{ - PyObject *m; - PyExtensionClass *t; - - if (! v && (m=subclass_getspecial(self,py__delitem__))) - { - if (UnboundEMethod_Check(m)) - { - UNLESS_ASSIGN(m,PyObject_CallFunction(m,"OO",self,index)) return -1; - } - else UNLESS_ASSIGN(m,PyObject_CallFunction(m,"O",index)) return -1; - Py_DECREF(m); - return 0; - } - - 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) - && ! HasMethodHook(self)) - { - t=(PyExtensionClass*)AsCMethod(m)->type; - if (t->tp_as_mapping && t->tp_as_mapping->mp_ass_subscript) - { - Py_DECREF(m); - return t->tp_as_mapping->mp_ass_subscript(self,index,v); - } - else if (t->tp_as_sequence && t->tp_as_sequence->sq_ass_item) - { - int i, l; - - Py_DECREF(m); - - UNLESS(PyInt_Check(index)) - { - PyErr_SetString(PyExc_TypeError, "sequence subscript not int"); - return -1; - } - i=PyInt_AsLong(index); - if (i < 0) - { - if ((l=PyObject_Length(self)) < 0) return -1; - i+=l; - } - return t->tp_as_sequence->sq_ass_item(self,i,v); - } - } - if (! v) - { - PyErr_SetObject(PyExc_AttributeError, py__delitem__); - return -1; - } - if (UnboundEMethod_Check(m)) - { - UNLESS_ASSIGN(m,PyObject_CallFunction(m,"OOO",self,index,v)) return -1; - } - else UNLESS_ASSIGN(m,PyObject_CallFunction(m,"OO",index,v)) return -1; - Py_DECREF(m); - return 0; -} - -PyMappingMethods subclass_as_mapping = { - (inquiry)subclass_length, /*mp_length*/ - (binaryfunc)subclass_subscript, /*mp_subscript*/ - (objobjargproc)subclass_ass_subscript, /*mp_ass_subscript*/ -}; - -static int -dealloc_base(PyObject *inst, PyExtensionClass* self) -{ - int i,l; - PyObject *t; - - l=PyTuple_Size(self->bases); - for (i=0; i < l; i++) - { - t=PyTuple_GET_ITEM(self->bases, i); - if (ExtensionClass_Check(t)) - { - if (AsExtensionClass(t)->bases) - { - if (dealloc_base(inst,AsExtensionClass(t))) return 1; - } - else - { - if (((PyExtensionClass*)t)->tp_dealloc) - { - ((PyExtensionClass*)t)->tp_dealloc(inst); - return 1; - } - } - } - } - return 0; -} - -static void -subclass_dealloc(PyObject *self) -{ - PyObject *m, *t, *v, *tb; - int base_dealloced; - -#ifdef TRACE_DEALLOC - fprintf(stderr,"Deallocating a %s\n", self->ob_type->tp_name); -#endif - - PyErr_Fetch(&t,&v,&tb); - Py_INCREF(self); /* Give us a new lease on life */ - - if (subclass_watcher && - ! PyObject_CallMethod(subclass_watcher,"destroying","O",self)) - PyErr_Clear(); - - - if ((m=subclass_getspecial(self,py__del__))) - { - if (UnboundEMethod_Check(m)) - ASSIGN(m,PyObject_CallFunction(m,"O",self)); - else - ASSIGN(m,PyObject_CallFunction(m,"")); - Py_XDECREF(m); - } - - PyErr_Clear(); - - if (--self->ob_refcnt > 0) - { - PyErr_Restore(t,v,tb); - return; /* we added a reference; don't delete now */ - } - - if (HasInstDict(self)) Py_XDECREF(INSTANCE_DICT(self)); - - /* See if there was a dealloc handler in a (C) base class. - If there was, then it deallocates the object and we - get a true value back. - - Note that if there *is* a base class dealloc, then - *it* should decref the class. - */ - base_dealloced=dealloc_base(self,(PyExtensionClass*)self->ob_type); - - /* We only deallocate ourselves if a base class didn't */ - UNLESS(base_dealloced) - { - Py_DECREF(self->ob_type); - PyMem_DEL(self); - } - - PyErr_Restore(t,v,tb); -} - -static void -datafull_baseclassesf(PyExtensionClass *type, PyObject **c1, PyObject **c2) -{ - /* Find the number of classes that have data and return them. - There should be no more than one. - */ - int l, i; - PyObject *base; - - l=PyTuple_Size(type->bases); - for (i=0; i < l && ! (*c1 && *c2); i++) - { - base=PyTuple_GET_ITEM(type->bases, i); - if (ExtensionClass_Check(base)) - { - if (AsExtensionClass(base)->bases) - datafull_baseclassesf(AsExtensionClass(base),c1,c2); - else - { - if (AsExtensionClass(base)->tp_basicsize > - sizeof(PyPureMixinObject) || - AsExtensionClass(base)->tp_itemsize > 0) - { - if (! *c1) - *c1=base; - else if (*c1 != base) - *c2=base; - } - } - } - } -} - -static int -datafull_baseclasses(PyExtensionClass *type) -{ - PyObject *c1=0, *c2=0; - datafull_baseclassesf(type, &c1, &c2); - if (c2) return 2; - if (c1) return 1; - return 0; -} - -static PyObject * -datafull_baseclass(PyExtensionClass *type) -{ - /* Find the baseclass that has data and. There should be only one. */ - int l, i; - PyObject *base, *dbase; - - l=PyTuple_Size(type->bases); - for (i=0; i < l; i++) - { - base=PyTuple_GET_ITEM(type->bases, i); - if (ExtensionClass_Check(base)) - { - if (AsExtensionClass(base)->bases) - { - if ((dbase=datafull_baseclass(AsExtensionClass(base)))) - return dbase; - } - else - { - if (AsExtensionClass(base)->tp_basicsize > - sizeof(PyPureMixinObject) || - AsExtensionClass(base)->tp_itemsize > 0) - return base; - } - } - } - return NULL; -} - -static PyObject * -extension_baseclass(PyExtensionClass *type) -{ - /* Find the first immediate base class that is an extension class */ - int l, i; - PyObject *base; - - l=PyTuple_Size(type->bases); - for (i=0; i < l; i++) - { - base=PyTuple_GET_ITEM(type->bases, i); - if (ExtensionClass_Check(base)) return base; - } - return JimErr_Format(PyExc_TypeError, - "No extension class found in subclass", NULL); -} - -static int -subclass_hasattr(PyExtensionClass *type, PyObject *name) -{ - PyObject *o; - - if ((o=CCL_getattro(type,name))) - { - Py_DECREF(o); - return 1; - } - PyErr_Clear(); - return 0; -} - -static void -subclass_init_getattr(PyExtensionClass *self, PyObject *methods) -{ - PyObject *m; - - if ((m=CCL_getattr(self,py__getattr__,0))) - { - if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)getattr_by_name - && Subclass_Check(self,AsCMethod(m)->type)) - { - self->tp_getattr=AsCMethod(m)->type->tp_getattr; - } - else if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)getattro_by_name - && Subclass_Check(self,AsCMethod(m)->type)) - { - self->tp_getattro=AsCMethod(m)->type->tp_getattro; - } - else - { - PyObject_SetItem(methods,py__getattr__,m); - self->tp_getattro=subclass_getattro; - } - Py_DECREF(m); - } - else - { - PyErr_Clear(); - self->tp_getattro=EC_findiattro; - } -} - -static void -subclass_init_setattr(PyExtensionClass *self, PyObject *methods) -{ - PyObject *m; - - if ((m=CCL_getattr(self,py__setattr__,0))) - { - if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)setattr_by_name - && Subclass_Check(self,AsCMethod(m)->type)) - { - self->tp_setattr=AsCMethod(m)->type->tp_setattr; - } - else if (UnboundCMethod_Check(m) - && AsCMethod(m)->meth==(PyCFunction)setattro_by_name - && Subclass_Check(self,AsCMethod(m)->type)) - { - self->tp_setattro=AsCMethod(m)->type->tp_setattro; - } - else - { - PyObject_SetItem(methods,py__setattr__,m); - self->tp_setattro=subclass_setattro; - } - Py_DECREF(m); - } - else - { - PyErr_Clear(); - self->tp_setattro=subclass_simple_setattro; - } -} - -static PyObject * -CopyMethods(PyExtensionClass *type, PyObject *base_methods) -{ - PyObject *methods, *key, *v; - int pos; - - UNLESS(type->class_dictionary && PyDict_Check(base_methods) && - ExtensionInstance_Check(type->class_dictionary)) - { - Py_INCREF(base_methods); - return base_methods; - } - - UNLESS(methods= - PyObject_CallObject((PyObject*)type->class_dictionary->ob_type, NULL)) - return NULL; - - for (pos=0; PyDict_Next(base_methods, &pos, &key, &v); ) - UNLESS(0 <= PyObject_SetItem(methods,key,v)) goto err; - - return methods; - -err: - Py_DECREF(methods); - return NULL; -} - -/* 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__(PyExtensionClass *self, PyObject *args) -{ - PyObject *bases, *methods, *class_init; - PyExtensionClass *type; - char *name, *p; - int l; - - UNLESS(PyArg_ParseTuple(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); - name=p; - - UNLESS(PyTuple_Check(bases) && PyTuple_Size(bases)) - { - PyErr_SetString - (PyExc_TypeError, - "second argument must be a tuple of 1 or more base classes"); - } - - self->bases=bases; - Py_INCREF(bases); - - if (datafull_baseclasses(self) > 1) - { - PyErr_SetString(PyExc_TypeError, "too many datafull base classes"); - return NULL; - } - 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; - -#define copy_member(M) self->M=type->M - copy_member(ob_size); - copy_member(class_flags); - /* mark subclass as a python one, so subclass structures are freed on - * deallocation */ - self->class_flags |= EXTENSIONCLASS_PYSUBCLASS_FLAG; - - copy_member(tp_itemsize); - copy_member(tp_print); - self->tp_dealloc=subclass_dealloc; - - subclass_init_getattr(self,methods); - subclass_init_setattr(self,methods); - -#define subclass_set(OP,N) \ - self->tp_ ##OP = subclass_ ##OP - - subclass_set(compare,cmp); - subclass_set(repr,repr); - - 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 (type->bases || ! ClassHasInstDict(self)) - copy_member(tp_basicsize); - else - { - self->tp_basicsize=type->tp_basicsize/sizeof(PyObject*)*sizeof(PyObject*); - if (self->tp_basicsize < type->tp_basicsize) - self->tp_basicsize += sizeof(PyObject*); /* To align on PyObject */ - self->tp_basicsize += sizeof(PyObject*); /* For instance dictionary */ - } - - - self->tp_as_number=(PyNumberMethods*)malloc(sizeof(PyNumberMethods)); - UNLESS(self->tp_as_number) return PyErr_NoMemory(); - *(self->tp_as_number)=subclass_as_number; - - self->tp_as_sequence= - (PySequenceMethods*)malloc(sizeof(PySequenceMethods)); - UNLESS(self->tp_as_sequence) return PyErr_NoMemory(); - *(self->tp_as_sequence)=subclass_as_sequence; - - self->tp_as_mapping=(PyMappingMethods*)malloc(sizeof(PyMappingMethods)); - UNLESS(self->tp_as_mapping) return PyErr_NoMemory(); - *(self->tp_as_mapping)=subclass_as_mapping; - - subclass_set(hash,hash); - subclass_set(call,call); - subclass_set(str,str); - self->tp_doc=0; - - /* Implement __module__=__name__ */ - if (PyDict_GetItem(methods, py__module__) == NULL) - { - PyObject *globals = PyEval_GetGlobals(); - if (globals != NULL) - { - PyObject *modname = PyDict_GetItem(globals, py__name__); - if (modname != NULL) { - if (PyDict_SetItem(methods, py__module__, modname) < 0) - return NULL; - } - } - } - - /* 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; -} - -struct PyMethodDef ExtensionClass_methods[] = { - {"__init__",(PyCFunction)subclass__init__,1,""}, - {NULL, NULL} /* sentinel */ -}; - -static PyExtensionClass ECType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "ExtensionClass", /*tp_name*/ - sizeof(PyExtensionClass), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)CCL_dealloc, /*tp_dealloc*/ - (printfunc)0, /*tp_print*/ - (getattrfunc)0, /*tp_getattr*/ - (setattrfunc)0, /*tp_setattr*/ - (cmpfunc)0, /*tp_compare*/ - (reprfunc)CCL_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - (hashfunc)0, /*tp_hash*/ - (ternaryfunc)CCL_call, /*tp_call*/ - (reprfunc)0, /*tp_str*/ - (getattrofunc)CCL_getattro, /*tp_getattr with object key*/ - (setattrofunc)CCL_setattro, /*tp_setattr with object key*/ - /* Space for future expansion */ - 0L,0L, - "C classes", /* Documentation string */ - METHOD_CHAIN(ExtensionClass_methods) -}; - -/* List of methods defined in the module */ - -static PyObject * -set_subclass_watcher(PyObject *ignored, PyObject *args) -{ - PyObject *old, *sw=0; - - UNLESS(PyArg_ParseTuple(args,"|O",&sw)) return NULL; - old=subclass_watcher; - subclass_watcher=sw; - if (sw) Py_INCREF(sw); - if (old) return old; - Py_INCREF(Py_None); - return Py_None; -} - -static struct PyMethodDef CC_methods[] = { - {"subclass_watcher", (PyCFunction)set_subclass_watcher, 1, - "subclass_watcher(ob) -- " - "Register an object to watch subclass instance events" - }, - {NULL, NULL} /* sentinel */ -}; - -static int -export_type(PyObject *dict, char *name, PyExtensionClass *typ) -{ - initializeBaseExtensionClass(typ); - - if (PyErr_Occurred()) return -1; - - if (PyDict_GetItem(typ->class_dictionary, py__module__) == NULL) - { - PyObject *modname = PyDict_GetItem(dict, py__name__); - if (modname != NULL) { - if (PyDict_SetItem(typ->class_dictionary, py__module__, modname) < 0) - return -1; - } - } - PyErr_Clear(); - - return PyMapping_SetItemString(dict,name,(PyObject*)typ); -} - -/* bases is a tuple of base classes. This function absorbs the reference */ -static int -export_subclassed_type(PyObject *dict, char *name, PyExtensionClass *typ, - PyObject *bases) -{ - initializeBaseExtensionClass(typ); - - if (PyErr_Occurred()) return -1; - - /* set this up as a subclassed ExtensionClass */ - UNLESS (bases && PyTuple_Check(bases) && PyTuple_Size(bases)) { - PyErr_SetString(PyExc_TypeError, - "second argument must be a tuple of 1 or more base classes"); - return -1; - } - typ->bases = bases; - - if (PyDict_GetItem(typ->class_dictionary, py__module__) == NULL) - { - PyObject *modname = PyDict_GetItem(dict, py__name__); - if (modname != NULL) { - if (PyDict_SetItem(typ->class_dictionary, py__module__, modname) < 0) - return -1; - } - } - PyErr_Clear(); - - return PyMapping_SetItemString(dict,name,(PyObject*)typ); -} - -static struct ExtensionClassCAPIstruct -TrueExtensionClassCAPI = { - export_type, - EC_findiattrs, - EC_findiattro, - subclass_simple_setattr, - subclass_simple_setattro, - (PyObject*)&ECType, - (PyObject*)&PMethodType, - PMethod_New, - CMethod_issubclass, - export_subclassed_type, -}; - -void -initExtensionClass() -{ - PyObject *m, *d; - char *rev="$Revision$"; - PURE_MIXIN_CLASS(Base, "Minimalbase class for Extension Classes", NULL); - - PMethodType.ob_type=&PyType_Type; - CMethodType.ob_type=&PyType_Type; - ECTypeType.ob_type=&PyType_Type; - ECType.ob_type=&ECTypeType; - - UNLESS(concat_fmt=PyString_FromString("%s%s")); - - m = Py_InitModule4("ExtensionClass", CC_methods, - ExtensionClass_module_documentation, - (PyObject*)NULL,PYTHON_API_VERSION); - - d = PyModule_GetDict(m); - PyDict_SetItemString(d,"__version__", - PyString_FromStringAndSize(rev+11,strlen(rev+11)-2)); - - init_py_names(); - - if (0) PyCObject_Import14("this will go away", "in 1.5 :-)"); - - initializeBaseExtensionClass(&ECType); - PyDict_SetItemString(d, "ExtensionClass", (PyObject*)&ECType); - - initializeBaseExtensionClass(&BaseType); - PyDict_SetItemString(d, "Base", (PyObject*)&BaseType); - - PyDict_SetItemString(d, "PythonMethodType", (PyObject*)&PMethodType); - PyDict_SetItemString(d, "ExtensionMethodType", (PyObject*)&CMethodType); - - /* Export C attribute lookup API */ - PyExtensionClassCAPI=&TrueExtensionClassCAPI; - PyDict_SetItemString(d, "CAPI", - PyCObject_FromVoidPtr(PyExtensionClassCAPI,NULL)); - - CHECK_FOR_ERRORS("can't initialize module ExtensionClass"); -} diff --git a/ExtensionClass.h b/ExtensionClass.h deleted file mode 100644 index 7a6af6ca..00000000 --- a/ExtensionClass.h +++ /dev/null @@ -1,471 +0,0 @@ -/* - - $Id$ - - Extension Class Definitions - - Copyright (c) 1996-1998, Digital Creations, Fredericksburg, VA, USA. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - o Redistributions of source code must retain the above copyright - notice, this list of conditions, and the disclaimer that follows. - - o Redistributions in binary form must reproduce the above copyright - notice, this list of conditions, and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - o Neither the name of Digital Creations nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - - THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS - IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL - CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - DAMAGE. - - Implementing base extension classes - - A base extension class is implemented in much the same way that an - extension type is implemented, except: - - - The include file, 'ExtensionClass.h', must be included. - - - The type structure is declared to be of type - 'PyExtensionClass', rather than of type 'PyTypeObject'. - - - The type structure has an additional member that must be defined - after the documentation string. This extra member is a method chain - ('PyMethodChain') containing a linked list of method definition - ('PyMethodDef') lists. Method chains can be used to implement - method inheritance in C. Most extensions don't use method chains, - but simply define method lists, which are null-terminated arrays - of method definitions. A macro, 'METHOD_CHAIN' is defined in - 'ExtensionClass.h' that converts a method list to a method chain. - (See the example below.) - - - Module functions that create new instances must be replaced by an - '__init__' method that initializes, but does not create storage for - instances. - - - The extension class must be initialized and exported to the module - with:: - - PyExtensionClass_Export(d,"name",type); - - where 'name' is the module name and 'type' is the extension class - type object. - - Attribute lookup - - Attribute lookup is performed by calling the base extension class - 'getattr' operation for the base extension class that includes C - data, or for the first base extension class, if none of the base - extension classes include C data. 'ExtensionClass.h' defines a - macro 'Py_FindAttrString' that can be used to find an object's - attributes that are stored in the object's instance dictionary or - in the object's class or base classes:: - - v = Py_FindAttrString(self,name); - - In addition, a macro is provided that replaces 'Py_FindMethod' - calls with logic to perform the same sort of lookup that is - provided by 'Py_FindAttrString'. - - Linking - - The extension class mechanism was designed to be useful with - dynamically linked extension modules. Modules that implement - extension classes do not have to be linked against an extension - class library. The macro 'PyExtensionClass_Export' imports the - 'ExtensionClass' module and uses objects imported from this module - to initialize an extension class with necessary behavior. - - If you have questions regarding this software, - contact: - - - If you have questions regarding this software, - contact: - - Digital Creations L.C. - info@digicool.com - - (540) 371-6909 - -*/ - -#ifndef EXTENSIONCLASS_H -#define EXTENSIONCLASS_H - -#include "Python.h" -#include "import.h" - -/* Declarations for objects of type ExtensionClass */ - -typedef struct { - PyObject_VAR_HEAD - char *tp_name; /* For printing */ - int tp_basicsize, tp_itemsize; /* For allocation */ - - /* Methods to implement standard operations */ - - destructor tp_dealloc; - printfunc tp_print; - getattrfunc tp_getattr; - setattrfunc tp_setattr; - cmpfunc tp_compare; - reprfunc tp_repr; - - /* Method suites for standard classes */ - - PyNumberMethods *tp_as_number; - PySequenceMethods *tp_as_sequence; - PyMappingMethods *tp_as_mapping; - - /* More standard operations (at end for binary compatibility) */ - - hashfunc tp_hash; - ternaryfunc tp_call; - reprfunc tp_str; - getattrofunc tp_getattro; - setattrofunc tp_setattro; - /* Space for future expansion */ - long tp_xxx3; - long tp_xxx4; - - char *tp_doc; /* Documentation string */ - -#ifdef COUNT_ALLOCS - /* these must be last */ - int tp_alloc; - int tp_free; - int tp_maxalloc; - struct _typeobject *tp_next; -#endif - - /* Here's the juicy stuff: */ - - /* Put your method chain here. If you just have a method - list, you can use the METHON_CHAIN macro to make a chain. - */ - PyMethodChain methods; - - /* You may set certain flags here. */ - long class_flags; - - /* 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 -#define EXTENSIONCLASS_BASICNEW_FLAG 1 << 6 -#define EXTENSIONCLASS_PYSUBCLASS_FLAG 1 << 7 - - /* 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. - If you do provide your own class dictionary, it *must* be - a mapping object. If the object given is also an extension - instance, then sub-class instance dictionaries will be created - by calling the class dictionary's class with zero argumemts. - Otherwise, subclass dictionaries will be of the default type. - */ - PyObject *class_dictionary; - - /* You should not set the remaining members. */ - PyObject *bases; - PyObject *reserved; -} PyExtensionClass; - -/* Following are macros that are needed or useful for defining extension - classes: - */ - -/* This macro redefines Py_FindMethod to do attribute for an attribute - name given by a C string lookup using extension class meta-data. - This is used by older getattr implementations. - - This macro is used in base class implementations of tp_getattr to - lookup methods or attributes that are not managed by the base type - directly. The macro is generally used to search for attributes - after other attribute searches have failed. - - Note that in Python 1.4, a getattr operation may be provided that - uses an object argument. Classes that support this new operation - should use Py_FindAttr. - */ -#define Py_FindMethod(M,SELF,NAME) \ - (PyExtensionClassCAPI->getattrs((SELF),(NAME))) - -/* Do method or attribute lookup for an attribute name given by a C - string using extension class meta-data. - - This macro is used in base class implementations of tp_getattro to - lookup methods or attributes that are not managed by the base type - directly. The macro is generally used to search for attributes - after other attribute searches have failed. - - Note that in Python 1.4, a getattr operation may be provided that - uses an object argument. Classes that support this new operation - should use Py_FindAttr. - */ -#define Py_FindAttrString(SELF,NAME) \ - (PyExtensionClassCAPI->getattrs((SELF),(NAME))) - -/* Do method or attribute lookup using extension class meta-data. - - This macro is used in base class implementations of tp_getattr to - lookup methods or attributes that are not managed by the base type - directly. The macro is generally used to search for attributes - after other attribute searches have failed. */ -#define Py_FindAttr(SELF,NAME) (PyExtensionClassCAPI->getattro((SELF),(NAME))) - -/* Do method or attribute assignment for an attribute name given by a - C string using extension class meta-data. - - This macro is used in base class implementations of tp_setattr to - set attributes that are not managed by the base type directly. The - macro is generally used to assign attributes after other attribute - attempts to assign attributes have failed. - - Note that in Python 1.4, a setattr operation may be provided that - uses an object argument. Classes that support this new operation - should use PyEC_SetAttr. - */ -#define PyEC_SetAttrString(SELF,NAME,V) \ - (PyExtensionClassCAPI->setattrs((SELF),(NAME),(V))) - -/* Do attribute assignment for an attribute. - - This macro is used in base class implementations of tp_setattro to - set attributes that are not managed by the base type directly. The - macro is generally used to assign attributes after other attribute - attempts to assign attributes have failed. - */ -#define PyEC_SetAttr(SELF,NAME,V) \ - (PyExtensionClassCAPI->setattro((SELF),(NAME),(V))) - -/* Import the ExtensionClass CAPI */ -#define ExtensionClassImported \ - (PyExtensionClassCAPI=PyCObject_Import("ExtensionClass","CAPI")) - -/* Make sure the C interface has been imported and import it if necessary. - This can be used in an if. - */ -#define MakeSureExtensionClassImported \ - (PyExtensionClassCAPI || \ - (PyExtensionClassCAPI=PyCObject_Import("ExtensionClass","CAPI"))) - - -/* Export an Extension Base class in a given module dictionary with a - given name and ExtensionClass structure. - */ -#define PyExtensionClass_Export(D,N,T) \ - if(PyExtensionClassCAPI || \ - (PyExtensionClassCAPI= (struct ExtensionClassCAPIstruct*) \ - PyCObject_Import("ExtensionClass","CAPI"))) \ - { PyExtensionClassCAPI->Export(D,N,&T); } - -/* Export an Extension Subclass class in a given module dictionary with a - given name, ExtensionClass structure and set of base classes. It is - up to the programmer to make sure that the instance structures of the - base classes are compatible with that of the new class. - */ -#define PyExtensionClass_ExportSubclass(D,N,T,B) \ - if(PyExtensionClassCAPI || \ - (PyExtensionClassCAPI= (struct ExtensionClassCAPIstruct*) \ - PyCObject_Import("ExtensionClass","CAPI"))) \ - { PyExtensionClassCAPI->ExportSubclass(D,N,&T,B); } - -/* Export an Extension Subclass class in a given module dictionary with a - given name, ExtensionClass structure and single base class. It is up to - the programmer to make sure that the instance structures of the base - classes are compatible with that of the new class. - */ -#define PyExtensionClass_ExportSubclassSingle(D,N,T,B) \ - PyExtensionClass_ExportSubclass(D, N, T, Py_BuildValue("(O)",(PyObject*)&B)) - -/* Convert a method list to a method chain. */ -#define METHOD_CHAIN(DEF) { DEF, NULL } - -/* The following macro checks whether a type is an extension class: */ -#define PyExtensionClass_Check(TYPE) \ - ((PyObject*)(TYPE)->ob_type==PyExtensionClassCAPI->ExtensionClassType) - -/* The following macro checks whether an instance is an extension instance: */ -#define PyExtensionInstance_Check(INST) \ - ((PyObject*)(INST)->ob_type->ob_type== \ - PyExtensionClassCAPI->ExtensionClassType) - -/* The following macro checks for errors and prints out an error - message that is more informative than the one given by Python when - an extension module initialization fails. - */ -#define CHECK_FOR_ERRORS(MESS) \ -if(PyErr_Occurred()) { \ - PyObject *__sys_exc_type, *__sys_exc_value, *__sys_exc_traceback; \ - PyErr_Fetch( &__sys_exc_type, &__sys_exc_value, \ - &__sys_exc_traceback); \ - fprintf(stderr, # MESS ":\n\t"); \ - PyObject_Print(__sys_exc_type, stderr,0); \ - fprintf(stderr,", "); \ - PyObject_Print(__sys_exc_value, stderr,0); \ - fprintf(stderr,"\n"); \ - fflush(stderr); \ - Py_FatalError(# MESS); \ -} - -/* The following macro can be used to define an extension base class - that only provides method and that is used as a pure mix-in class. */ -#define PURE_MIXIN_CLASS(NAME,DOC,METHODS) \ -static PyExtensionClass NAME ## Type = { PyObject_HEAD_INIT(NULL) \ - 0, # NAME, sizeof(PyPureMixinObject), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, DOC, {METHODS, NULL}, \ - EXTENSIONCLASS_BASICNEW_FLAG} - -/* The following macros provide limited access to extension-class - method facilities. */ - -/* Test for an ExtensionClass method: */ -#define PyECMethod_Check(O) \ - ((PyObject*)(O)->ob_type==PyExtensionClassCAPI->MethodType) - -/* Create a method object that wraps a callable object and an - instance. Note that if the callable object is an extension class - method, then the new method will wrap the callable object that is - wrapped by the extension class method. Also note that if the - callable object is an extension class method with a reference - count of 1, then the callable object will be rebound to the - instance and returned with an incremented reference count. - */ -#define PyECMethod_New(CALLABLE,INST) \ - (PyExtensionClassCAPI->Method_New(CALLABLE,INST)) - -/* Return the instance that is bound by an extension class method. */ -#define PyECMethod_Self(M) (((PyECMethodObject*)M)->self) - -/* Check whether an object has an __of__ method for returning itself - in the context of it's container. */ -#define has__of__(O) \ - ((O)->ob_type->ob_type == \ - (PyTypeObject*)PyExtensionClassCAPI->ExtensionClassType && \ - (((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)) - -/* Test whether an ExtensionClass, S, is a subclass of ExtensionClass C. */ -#define ExtensionClassSubclass_Check(S,C) ( \ - ((PyObject*)(S)->ob_type==PyExtensionClassCAPI->ExtensionClassType) && \ - ((PyObject*)(C)->ob_type==PyExtensionClassCAPI->ExtensionClassType) && \ - (PyExtensionClassCAPI->issubclass((PyExtensionClass *)(S), \ - (PyExtensionClass *)(C)))) - -/* Test whether an ExtensionClass instance , I, is a subclass of - ExtensionClass C. */ -#define ExtensionClassSubclassInstance_Check(I,C) ( \ - ((PyObject*)(I)->ob_type->ob_type== \ - PyExtensionClassCAPI->ExtensionClassType) && \ - ((PyObject*)(C)->ob_type==PyExtensionClassCAPI->ExtensionClassType) && \ - (PyExtensionClassCAPI->issubclass((PyExtensionClass *)((I)->ob_type), \ - (PyExtensionClass *)(C)))) - -/* This let's you define built-in class methods. */ -#define METH_CLASS_METHOD (2 << 17) - -/***************************************************************************** - - WARNING: EVERYTHING BELOW HERE IS PRIVATE TO THE EXTENSION CLASS INTERFACE - IMPLEMENTATION AND IS SUBJECT TO CHANGE !!! - - *****************************************************************************/ - -static struct ExtensionClassCAPIstruct { - int (*Export)(PyObject *dict, char *name, PyExtensionClass *ob_type); - PyObject *(*getattrs)(PyObject *, char *); - PyObject *(*getattro)(PyObject *, PyObject *); - int (*setattrs)(PyObject *, char *, PyObject *); - int (*setattro)(PyObject *, PyObject *, PyObject *); - PyObject *ExtensionClassType; - PyObject *MethodType; - PyObject *(*Method_New)(PyObject *callable, PyObject *inst); - int (*issubclass)(PyExtensionClass *sub, PyExtensionClass *type); - int (*ExportSubclass)(PyObject *dict, char *name, - PyExtensionClass *ob_type, PyObject *bases); -} *PyExtensionClassCAPI = NULL; - -typedef struct { PyObject_HEAD } PyPureMixinObject; - -typedef struct { - PyObject_HEAD - PyTypeObject *type; - PyObject *self; - PyObject *meth; -} PyECMethodObject; - -/* The following is to avoid whining from 1.5 :-) */ -#define PyCObject_Import PyCObject_Import14 - -static void * -PyCObject_Import14(char *module_name, char *name) -{ - PyObject *m, *c; - void *r=NULL; - - if((m=PyImport_ImportModule(module_name))) - { - if((c=PyObject_GetAttrString(m,name))) - { - r=PyCObject_AsVoidPtr(c); - Py_DECREF(c); - } - Py_DECREF(m); - } - - return r; -} - -#endif - - diff --git a/ExtensionClass.stx b/ExtensionClass.stx deleted file mode 100644 index cab7e46b..00000000 --- a/ExtensionClass.stx +++ /dev/null @@ -1,714 +0,0 @@ -Extension Classes, Python Extension Types Become Classes - - Jim Fulton, Digital Creations, Inc. - jim@digicool.com - - "Copyright (C) 1996-1998, Digital Creations":COPYRIGHT.html. - - Abstract - - A lightweight mechanism has been developed for making Python - extension types more class-like. Classes can be developed in an - extension language, such as C or C++, and these classes can be - treated like other python classes: - - - They can be sub-classed in python, - - - They provide access to method documentation strings, and - - - They can be used to directly create new instances. - - An example class shows how extension classes are implemented and how - they differ from extension types. - - Extension classes provide additional extensions to class and - instance semantics, including: - - - A protocol for accessing subobjects "in the context of" their - containers. This is used to implement custom method types - and "environmental acquisition":Acquisition.html. - - - A protocol for overriding method call semantics. This is used - to implement "synchonized" classes and could be used to - implement argument type checking. - - - A protocol for class initialization that supports execution of a - special '__class_init__' method after a class has been - initialized. - - Extension classes illustrate how the Python class mechanism can be - extended and may provide a basis for improved or specialized class - models. - - Releases - - To find out what's changed in this release, - see the "release notes":release.html. - - Problem - - Currently, Python provides two ways of defining new kinds of objects: - - - Python classes - - - Extension types - - Each approach has it's strengths. Extension types provide much greater - control to the programmer and, generally, better performance. Because - extension types are written in C, the programmer has greater access to - external resources. (Note that Python's use of the term type has - little to do with the notion of type as a formal specification.) - - Classes provide a higher level of abstraction and are generally much - easier to develop. Classes provide full inheritance support, while - support for inheritance when developing extension types is very - limited. Classes provide run-time meta-data, such as method documentation - strings, that are useful for documentation and discovery. Classes - act as factories for creating instances, while separate functions - must be provided to create instances of types. - - It would be useful to combine the features of the two approaches. It - would be useful to be able to have better support for inheritance for - types, or to be able to subclass from types in Python. It would be - useful to be able to have class-like meta-data support for types and - the ability to construct instances directly from types. - - Our software is developed in Python. When necessary, we convert - debugged Python routines and classes to C for improved - performance. In most cases, a small number of methods in a class - is responsible for most of the computation. It should be possible - to convert only these methods to C, while leaving the other method - in Python. A natural way to approach this is to create a base - class in C that contains only the performance-critical aspects of - a class' implementation and mix this base class into a Python - class. - - We have need, in a number of projects, for semantics that are - slightly different than the usual class and instance semantics, - yet we don't want to do most of our development in C. For - example, we have developed a persistence mechanism [1] that - redefines '__getattr__' and '__setattr__' to take storage-related - actions when object state is accessed or modified. We want to be - able to take certain actions on *every* attribute reference, but - for python class instances, '__getattr__' is only called when - attribute lookup fails by normal means. - - As another example, we would like to have greater control over how - methods are bound. Currently, when accessing a class - instance attribute, the attribute value is bound together with the - instance in a method object *if and only if* the attribute value is a - python function. For some applications, we might also want to be - able to bind extension functions, or other types of callable - objects, such as HTML document templates [2]. Furthermore, - we might want to have greater control over how objects are bound. - For example, we might want to bind instances and callable objects - with special method objects that assure that no more than one thread - accesses the object or method at one time. - - We can provide these special semantics in extension types, but we - wish to provide them for classes developed in Python. - - Background - - At the first Python Workshop, Don Beaudry presented work [3] done - at V.I. Corp to integrate Python with C++ frameworks. This system - provided a number of important features, including: - - - Definition of extension types that provide class-like meta-data - and that can be called to create instances. - - - Ability to subclass in python from C types. - - - Ability to define classes in python who's data are stored as - C structures rather than in dictionaries to better interface to - C and C++ libraries, and for better performance. - - - Less dynamic data structures. In particular, the data structure - for a class is declared during class definition. - - - Support for enumeration types. - - This work was not released, initially. - - Shortly after the workshop, changes were made to Python to support - the sub-classing features described in [3]. These changes were not - documented until the fourth Python Workshop [4]. - - At the third Python workshop, I presented some work I had done on - generating module documentation for extension types. Based on the - discussion at this workshop, I developed a meta-type proposal [5]. - This meta-type proposal was for an object that simply stored - meta-information for a type, for the purpose of generating module - documentation. - - In the summer of 1996, Don Beaudry released the system described in - [3] under the name MESS [6]. MESS addresses a number of needs but - has a few drawbacks: - - - Only single inheritance is supported. - - - The mechanisms for defining MESS extension types is very different - from and more complicated than the standard Python type creation - mechanism. - - - Defining MESS types requires the use of an extensive C - applications programming interface. This presents problems for - configuring dynamically-loaded extension modules unless the MESS - library is linked into the Python interpreter. - - - Because the system tries to do a number of different things, it is - fairly large, about 15,000 lines. - - - There is very little documentation, especially for the C - programming interface. - - - The system is a work in progress, with a number of outstanding - bugs. - - As MESS matures, we expect most of these problems to be addressed. - - Extension Classes - - To meet short term needs for a C-based persistence mechanism [1], an - extension class module was developed using the mechanism described - in [4] and building on ideas from MESS [6]. The extension class module - recasts extension types as "extension classes" by seeking to - eliminate, or at least reduce semantic differences between types and - classes. The module was designed to meet the following goal: - - - Provide class-like behavior for extension types, including - interfaces for meta information and for constructing instances. - - - Support sub-classing in Python from extension classes, with support - for multiple inheritance. - - - Provide a small hardened implementation that can be used for - current products. - - - Provide a mechanism that requires minimal modification to existing - extension types. - - - Provide a basis for research on alternative semantics for classes - and inheritance. - - **Note:** I use *non-standard* terminology here. By standard - *python* terminology, only standard python classes can be called - classes. ExtensionClass "classes" are technically just "types" - that happen to swim, walk and quack like python classes. - - Base extension classes and extension subclasses - - Base extension classes are implemented in C. Extension subclasses - are implemented in Python and inherit, directly or indirectly from - one or more base extension classes. An extension subclass may - inherit from base extension classes, extension subclasses, and - ordinary python classes. The usual inheritance order rules - apply. Currently, extension subclasses must conform to the - following two rules: - - - The first super class listed in the class statement defining an - extension subclass must be either a base extension class or an - extension subclass. This restriction will be removed in - Python-1.5. - - - At most one base extension direct or indirect super class may - define C data members. If an extension subclass inherits from - multiple base extension classes, then all but one must be mix-in - classes that provide extension methods but no data. - - Meta Information - - Like standard python classes, extension classes have the following - attributes containing meta-data: - - '__doc__' -- a documentation string for the class, - - '__name__' -- the class name, - - '__bases__' -- a sequence of base classes, - - '__dict__' -- a class dictionary, and - - '__module__' -- the name of the module in which the class was - defined. - - The class dictionary provides access to unbound methods and their - documentation strings, including extension methods and special - methods, such as methods that implement sequence and numeric - protocols. Unbound methods can be called with instance first - arguments. - - Subclass instance data - - Extension subclass instances have instance dictionaries, just - like Python class instances do. When fetching attribute values, - extension class instances will first try to obtain data from the - base extension class data structure, then from the instance - dictionary, then from the class dictionary, and finally from base - classes. When setting attributes, extension classes first attempt - to use extension base class attribute setting operations, and if - these fail, then data are placed in the instance dictionary. - - Implementing base extension classes - - A base extension class is implemented in much the same way that an - extension type is implemented, except: - - - The include file, 'ExtensionClass.h', must be included. - - - The type structure is declared to be of type 'PyExtensionClass', rather - than of type 'PyTypeObject'. - - - The type structure has an additional member that must be defined - after the documentation string. This extra member is a method chain - ('PyMethodChain') containing a linked list of method definition - ('PyMethodDef') lists. Method chains can be used to implement - method inheritance in C. Most extensions don't use method chains, - but simply define method lists, which are null-terminated arrays - of method definitions. A macro, 'METHOD_CHAIN' is defined in - 'ExtensionClass.h' that converts a method list to a method chain. - (See the example below.) - - - Module functions that create new instances must be replaced by - '__init__' methods that initialize, but does not create storage for - instances. - - - The extension class must be initialized and exported to the module - with:: - - PyExtensionClass_Export(d,"name",type); - - where 'name' is the module name and 'type' is the extension class - type object. - - Attribute lookup - - Attribute lookup is performed by calling the base extension class - 'getattr' operation for the base extension class that includes C - data, or for the first base extension class, if none of the base - extension classes include C data. 'ExtensionClass.h' defines a - macro 'Py_FindAttrString' that can be used to find an object's - attributes that are stored in the object's instance dictionary or - in the object's class or base classes:: - - v = Py_FindAttrString(self,name); - - where 'name' is a C string containing the attribute name. - - In addition, a macro is provided that replaces 'Py_FindMethod' - calls with logic to perform the same sort of lookup that is - provided by 'Py_FindAttrString'. - - If an attribute name is contained in a Python string object, - rather than a C string object, then the macro 'Py_FindAttr' should - be used to look up an attribute value. - - Linking - - The extension class mechanism was designed to be useful with - dynamically linked extension modules. Modules that implement - extension classes do not have to be linked against an extension - class library. The macro 'PyExtensionClass_Export' imports the - 'ExtensionClass' module and uses objects imported from this module - to initialize an extension class with necessary behavior. - - Example: MultiMapping objects - - An "example":MultiMapping.html, is provided that illustrates the - changes needed to convert an existing type to an ExtensionClass. - - Implementing base extension class constructors - - Some care should be taken when implementing or overriding base - class constructors. When a Python class overrides a base class - constructor and fails to call the base class constructor, a - program using the class may fail, but it will not crash the - interpreter. On the other hand, an extension subclass that - overrides a constructor in an extension base class must call the - extension base class constructor or risk crashing the interpreter. - This is because the base class constructor may set C pointers that, - if not set properly, will cause the interpreter to crash when - accessed. This is the case with the 'MultiMapping' extension base - class shown in the example above. - - If no base class constructor is provided, extension class instance - memory will be initialized to 0. It is a good idea to design - extension base classes so that instance methods check for - uninitialized memory and perform initialialization if necessary. - This was not done above to simplify the example. - - Overriding methods inherited from Python base classes - - A problem occurs when trying to overide methods inherited from - Python base classes. Consider the following example:: - - from ExtensionClass import Base - - class Spam: - - def __init__(self, name): - self.name=name - - class ECSpam(Base, Spam): - - def __init__(self, name, favorite_color): - Spam.__init__(self,name) - self.favorite_color=favorite_color - - This implementation will fail when an 'ECSpam' object is - instantiated. The problem is that 'ECSpam.__init__' calls - 'Spam.__init__', and 'Spam.__init__' can only be called with a - Python instance (an object of type '"instance"') as the first - argument. The first argument passed to 'Spam.__init__' will be an - 'ECSpam' instance (an object of type 'ECSPam'). - - To overcome this problem, extension classes provide a class method - 'inheritedAttribute' that can be used to obtain an inherited - attribute that is suitable for calling with an extension class - instance. Using the 'inheritedAttribute' method, the above - example can be rewritten as:: - - from ExtensionClass import Base - - class Spam: - - def __init__(self, name): - self.name=name - - class ECSpam(Base, Spam): - - def __init__(self, name, favorite_color): - ECSpam.inheritedAttribute('__init__')(self,name) - self.favorite_color=favorite_color - - This isn't as pretty but does provide the desired result. - - New class and instance semantics - - Context Wrapping - - It is sometimes useful to be able to wrap up an object together - with a containing object. I call this "context wrapping" - because an object is accessed in the context of the object it is - accessed through. - - We have found many applications for this, including: - - - User-defined method objects, - - - "Acquisition":Acquisition.html, and - - - Computed attributes - - User-defined method objects - - Python classes wrap Python function attributes into methods. When a - class has a function attribute that is accessed as an instance - attribute, a method object is created and returned that contains - references to the original function and instance. When the method - is called, the original function is called with the instance as the - first argument followed by any arguments passed to the method. - - Extension classes provide a similar mechanism for attributes that - are Python functions or inherited extension functions. In - addition, if an extension class attribute is an instance of an - extension class that defines an '__of__' method, then when the - attribute is accessed through an instance, it's '__of__' method - will be called to create a bound method. - - Consider the following example:: - - import ExtensionClass - - class CustomMethod(ExtensionClass.Base): - - def __call__(self,ob): - print 'a %s was called' % ob.__class__.__name__ - - class wrapper: - - def __init__(self,m,o): self.meth, self.ob=m,o - - def __call__(self): self.meth(self.ob) - - def __of__(self,o): return self.wrapper(self,o) - - class bar(ExtensionClass.Base): - hi=CustomMethod() - - x=bar() - hi=x.hi() - - Note that 'ExtensionClass.Base' is a base extension class that - provides very basic ExtensionClass behavior. - - When run, this program outputs: 'a bar was called'. - - Computed Attributes - - It is not uncommon to wish to expose information via the - attribute interface without affecting implementation data - structures. One can use a custom '__getattr__' method to - implement computed attributes, however, this can be a bit - cumbersome and can interfere with other uses of '__getattr__', - such as for persistence. - - The '__of__' protocol provides a convenient way to implement - computed attributes. First, we define a ComputedAttribute - class. a ComputedAttribute is constructed with a function to - be used to compute an attribute, and calls the function when - it's '__of__' method is called: - - import ExtensionClass - - class ComputedAttribute(ExtensionClass.Base): - - def __init__(self, func): self.func=func - - def __of__(self, parent): return self.func(parent) - - Then we can use this class to create computed attributes. In the - example below, we create a computed attribute, 'radius': - - from math import sqrt - - class Point(ExtensionClass.Base): - - def __init__(self, x, y): self.x, self.y = x, y - - radius=ComputedAttribute(lambda self: sqrt(self.x**2+self.y**2)) - - which we can use just like an ordinary attribute: - - p=Point(2,2) - print p.radius - - Overriding method calls - - Normally, when a method is called, the function wrapped by the - method is called directly by the method. In some cases, it is - useful for user-defined logic to participate in the actual - function call. Extension classes introduce a new protocol that - provides extension classes greater control over how their - methods are called. If an extension class defines a special - method, '__call_method__', then this method will be called to - call the functions (or other callable object) wrapped by the - method. The method. '__call_method__' should provide the same - interface as provided by the Python builtin 'apply' function. - - For example, consider the expression: 'x.meth(arg1, arg2)'. The - expression is evaluated by first computing a method object that - wraps 'x' and the attribute of 'x' stored under the name 'meth'. - Assuming that 'x' has a '__call_method__' method defined, then - the '__call_method__' method of 'x' will be called with two - arguments, the attribute of 'x' stored under the name 'meth', - and a tuple containing 'x', 'arg1', and 'arg2'. - - To see how this feature may be used, see the Python module, - 'Syn.py', which is included in the ExtensionClass distribution. - This module provides a mix-in class that provides Java-like - "synchonized" classes that limit access to their methods to one - thread at a time. - - An interesting application of this mechanism would be to - implement interface checking on method calls. - - Method attributes - - Methods of ExtensionClass instances can have user-defined - attributes, which are stored in their associated instances. - - For example:: - - class C(ExtensionClass.Base): - - def f(self): - "Get a secret" - .... - - c=C() - - c.f.__roles__=['Trusted People'] - - print c.f.__roles__ # outputs ['Trusted People'] - print c.f__roles__ # outputs ['Trusted People'] - - print C.f.__roles__ # fails, unbound method - - A bound method attribute is set by setting an attribute in it's - instance with a name consisting of the concatination of the - method's '__name__' attribute and the attribute name. - Attributes cannot be set on unbound methods. - - Class initialization - - Normal Python class initialization is similar to but subtley - different from instance initialization. An instance '__init__' - function is called on an instance immediately *after* it is - created. An instance '__init__' function can use instance - information, like it's class and can pass the instance to other - functions. On the other hand, the code in class statements is - executed immediately *before* the class is created. This means - that the code in a class statement cannot use class attributes, - like '__bases__', or pass the class to functions. - - Extension classes provide a mechanism for specifying code to be - run *after* a class has been created. If a class or one of it's - base classes defines a '__class_init__' method, then this method - will be called just after a class has been created. The one - argument passed to the method will be the class, *not* an - instance of the class. - - Useful macros defined in ExtensionClass.h - - A number of useful macros are defined in ExtensionClass.h. - These are documented in 'ExtensionClass.h'. - - Pickleability - - Classes created with ExtensionClass, including extension base - classes are automatically pickleable. The usual gymnastics - necessary to pickle 'non-standard' types are not necessray for - types that have been modified to be extension base classes. - - Status - - The current release of the extension class module is "1.1", - http://www.digicool.com/releases/ExtensionClass/ExtensionClass-1.1.tar.gz. - The core implementation has less than four thousand lines of code, - including comments. This release requires Python 1.4 or higher. - - To find out what's changed in this release, see the - "release notes":release.html. - - "Installation instructions":Installation.html, are provided. - - Issues - - There are a number of issues that came up in the course of this work - and that deserve mention. - - - In Python 1.4, the class extension mechanism described in [4] required - that the first superclass in a list of super-classes must be of the - extended class type. This may not be convenient if mix-in - behavior is desired. If a list of base classes starts with a - standard python class, but includes an extension class, then an - error was raised. It would be more useful if, when a list of base - classes contains one or more objects that are not python classes, - the first such object was used to control the extended class - definition. To get around this, the 'ExtensionClass' module exports - a base extension class, 'Base', that can be used as the first base - class in a list of base classes to assure that an extension - subclass is created. - - Python 1.5 allows the class extension even if the first non-class - object in the list of base classes is not the first object in - the list. This issue appears to go away in Python 1.5, however, - the restriction that the first non-class object in a list of - base classes must be the first in the list may reappear in later - versions of Python. - - - Currently, only one base extension class can define any data in - C. The data layout of subclasses-instances is the same as for the - base class that defines data in C, except that the data structure - is extended to hold an instance dictionary. The data structure - begins with a standard python header, and extension methods expect - the C instance data to occur immediately after the object header. If - two or more base classes defined C data, the methods for the - different base classes would expect their data to be in the same - location. A solution might be to allocate base class instances and - store pointers to these instances in the subclass data structure. - The method binding mechanism would have to be a more complicated - to make sure that methods were bound to the correct base data - structure. Alternatively, the signature of C methods could be - expanded to allow pointers to expected class data to be passed - in addition to object pointers. - - - There is currently no support for sub-classing in C, beyond that - provided by method chains. - - - Rules for mixed-type arithmetic are different for python class - instances than they are for extension type instances. Python - classes can define right and left versions of numeric binary - operators, or they can define a coercion operator for converting - binary operator operands to a common type. For extension types, - only the latter, coercion-based, approach is supported. The - coercion-based approach does not work well for many data types for - which coercion rules depend on the operator. Because extension - classes are based on extension types, they are currently limited - to the coercion-based approach. It should be possible to - extend the extension class implementation to allow both types of - mixed-type arithmetic control. - - - I considered making extension classes immutable, meaning that - class attributes could not be set after class creation. I also - considered making extension subclasses cache inherited - attributes. Both of these are related and attractive for some - applications, however, I decided that it would be better to retain - standard class instance semantics and provide these features as - options at a later time. - - - The extension class module defines new method types to bind C and - python methods to extension class instances. It would be useful - for these method objects to provide access to function call - information, such as the number and names of arguments and the - number of defaults, by parsing extension function documentation - strings. - - Applications - - Aside from test and demonstration applications, the extension class - mechanism has been used to provide an extension-based implementation - of the persistence mechanism described in [1]. We have developed - this further to provide features such as automatic deactivation of - objects not used after some period of time and to provide more - efficient persistent-object cache management. - - Acquisition has been heavily used in our recent products. - Synchonized classes have also been used in recent products. - - Summary - - The extension-class mechanism described here provides a way to add - class services to extension types. It allows: - - - Sub-classing extension classes in Python, - - - Construction of extension class instances by calling extension - classes, - - - Extension classes to provide meta-data, such as unbound methods - and their documentation string. - - In addition, the extension class module provides a relatively - concise example of the use of mechanisms that were added to Python - to support MESS [6], and that were described at the fourth Python - Workshop [4]. It is hoped that this will spur research in improved - and specialized models for class implementation in Python. - - References - -.. [1] Fulton, J., "Providing Persistence for World-Wide-Web Applications", - http://www.digicool.com/papers/Persistence.html, - Proceedings of the 5th Python Workshop. - -.. [2] Page, R. and Cropper, S., "Document Template", - http://www.digicool.com/papers/DocumentTemplate.html, - Proceedings of the 5th Python Workshop. - -.. [3] Beaudry, D., "Deriving Built-In Classes in Python", - http://www.python.org/workshops/1994-11/BuiltInClasses/BuiltInClasses_1.html, - Proceedings of the First International Python Workshop. - -.. [4] Van Rossum, G., "Don Beaudry Hack - MESS", - http://www.python.org/workshops/1996-06/notes/thursday.html, - presented in the Developer's Future Enhancements session of the - 4th Python Workshop. - -.. [5] Fulton, J., "Meta-Type Object", - http://www.digicool.com/jim/MetaType.c, - This is a small proposal, the text of which is contained in a - sample implementation source file, - -.. [6] Beaudry, D., and Ascher, D., "The Meta-Extension Set", - http://starship.skyport.net/~da/mess/. diff --git a/Makefile.am b/Makefile.am index 7112f40b..039246c8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,13 +5,7 @@ SUBDIRS = codegen gtk INCLUDES = $(PYTHON_INCLUDES) $(GLIB_CFLAGS) $(PANGO_CFLAGS) -pyexec_LTLIBRARIES = ExtensionClass.la gobjectmodule.la pangomodule.la - -ExtensionClass_la_LDFLAGS = -module -avoid-version \ - -export-symbols-regex initExtensionClass -ExtensionClass_la_SOURCES = \ - ExtensionClass.h \ - ExtensionClass.c +pyexec_LTLIBRARIES = gobjectmodule.la pangomodule.la gobjectmodule_la_LDFLAGS = -module -avoid-version \ -export-symbols-regex initgobject @@ -36,7 +30,7 @@ $(srcdir)/pango.c: $(srcdir)/pango.defs $(srcdir)/pango.override && cp gen-pango.c pango.c \ && rm -f gen-pango.c -pkginclude_HEADERS = pygobject.h ExtensionClass.h +pkginclude_HEADERS = pygobject.h noinst_PYTHON = ltihooks.py @@ -53,7 +47,6 @@ EXTRA_DIST = \ pygtk.spec \ pygtk-2.0.pc.in \ MAPPING \ - ExtensionClass.stx \ pango.defs \ pango.override \ examples/gobject/signal.py \ diff --git a/codegen/codegen.py b/codegen/codegen.py index bbb7e99b..4a5c28b3 100644 --- a/codegen/codegen.py +++ b/codegen/codegen.py @@ -29,49 +29,43 @@ methtmpl = 'static PyObject *\n' + \ '}\n\n' methcalltmpl = '%(cname)s(%(cast)s(self->obj)%(arglist)s)' -consttmpl = 'static PyObject *\n' + \ +consttmpl = 'static int\n' + \ '_wrap_%(cname)s(PyGObject *self, PyObject *args, PyObject *kwargs)\n' + \ '{\n' + \ '%(varlist)s' + \ ' if (!PyArg_ParseTupleAndKeywords(args, kwargs, "%(typecodes)s:%(class)s.__init__"%(parselist)s))\n' + \ - ' return NULL;\n' + \ + ' return -1;\n' + \ '%(extracode)s\n' + \ ' self->obj = (GObject *)%(cname)s(%(arglist)s);\n' + \ ' if (!self->obj) {\n' + \ ' PyErr_SetString(PyExc_RuntimeError, "could not create %(class)s object");\n' + \ - ' return NULL;\n' + \ + ' return -1;\n' + \ ' }\n' + \ '%(gtkobjectsink)s' + \ ' pygobject_register_wrapper((PyObject *)self);\n' + \ - ' Py_INCREF(Py_None);\n' + \ - ' return Py_None;\n' + \ + ' return 0;\n' + \ '}\n\n' methdeftmpl = ' { "%(name)s", (PyCFunction)%(cname)s, %(flags)s },\n' -getattrtmpl = 'static PyObject *\n' + \ - '%(getattr)s(PyGObject *self, char *attr)\n' + \ - '{\n' + \ - '%(attrchecks)s' + \ - ' PyErr_SetString(PyExc_AttributeError, attr);\n' + \ - ' return NULL;\n' + \ - '}\n\n' -attrchecktmpl = ' if (!strcmp(attr, "%(attr)s")) {\n' + \ - '%(varlist)s' + \ - '%(code)s\n' + \ - ' }\n' +gettertmpl = 'static PyObject *\n' + \ + '%(funcname)s(PyGObject *self, void *closure)\n' + \ + '{\n' + \ + '%(varlist)s' + \ + '%(code)s\n' + \ + '}\n\n' -noconstructor = 'static PyObject *\n' + \ - 'pygobject_no_constructor(PyObject *self, PyObject *args)\n' +\ +noconstructor = 'static int\n' + \ + 'pygobject_no_constructor(PyObject *self, PyObject *args, PyObject *kwargs)\n' +\ '{\n' + \ ' gchar buf[512];\n' + \ '\n' + \ ' g_snprintf(buf, sizeof(buf), "%s is an abstract widget", self->ob_type->tp_name);\n' + \ ' PyErr_SetString(PyExc_NotImplementedError, buf);\n' + \ - ' return NULL;\n' + \ + ' return -1;\n' + \ '}\n\n' -typetmpl = 'PyExtensionClass Py%(class)s_Type = {\n' + \ +typetmpl = 'PyTypeObject Py%(class)s_Type = {\n' + \ ' PyObject_HEAD_INIT(NULL)\n' + \ ' 0, /* ob_size */\n' + \ ' "%(classname)s", /* tp_name */\n' + \ @@ -80,7 +74,7 @@ typetmpl = 'PyExtensionClass Py%(class)s_Type = {\n' + \ ' /* methods */\n' + \ ' (destructor)0, /* tp_dealloc */\n' + \ ' (printfunc)0, /* tp_print */\n' + \ - ' (getattrfunc)%(getattr)s, /* tp_getattr */\n' + \ + ' (getattrfunc)0, /* tp_getattr */\n' + \ ' (setattrfunc)0, /* tp_setattr */\n' + \ ' (cmpfunc)0, /* tp_compare */\n' + \ ' (reprfunc)0, /* tp_repr */\n' + \ @@ -92,18 +86,31 @@ typetmpl = 'PyExtensionClass Py%(class)s_Type = {\n' + \ ' (reprfunc)0, /* tp_str */\n' + \ ' (getattrofunc)0, /* tp_getattro */\n' + \ ' (setattrofunc)0, /* tp_setattro */\n' + \ - ' /* Space for future expansion */\n' + \ - ' 0L, 0L,\n' + \ + ' 0, /* tp_as_buffer */\n' + \ + ' Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */\n' + \ ' NULL, /* Documentation string */\n' + \ - ' %(methods)s,\n' + \ - ' EXTENSIONCLASS_INSTDICT_FLAG,\n' + \ + ' (traverseproc)0, /* tp_traverse */\n' + \ + ' (inquiry)0, /* tp_clear */\n' + \ + ' (richcmpfunc)0, /* tp_richcompare */\n' + \ + ' offsetof(PyGObject, weakreflist), /* tp_weaklistoffset */\n' +\ + ' (getiterfunc)0, /* tp_iter */\n' + \ + ' (iternextfunc)0, /* tp_iternext */\n' + \ + ' %(methods)s, /* tp_methods */\n' + \ + ' 0, /* tp_members */\n' + \ + ' %(getsets)s, /* tp_getset */\n' + \ + ' NULL, /* tp_base */\n' + \ + ' NULL, /* tp_dict */\n' + \ + ' (descrgetfunc)0, /* tp_descr_get */\n' + \ + ' (descrsetfunc)0, /* tp_descr_set */\n' + \ + ' offsetof(PyGObject, inst_dict), /* tp_dictoffset */\n' + \ + ' (initproc)%(initfunc)s, /* tp_init */\n' + \ '};\n\n' -interfacetypetmpl = 'PyExtensionClass Py%(class)s_Type = {\n' + \ +interfacetypetmpl = 'PyTypeObject Py%(class)s_Type = {\n' + \ ' PyObject_HEAD_INIT(NULL)\n' + \ ' 0, /* ob_size */\n' + \ ' "%(classname)s", /* tp_name */\n' + \ - ' sizeof(PyPureMixinObject), /* tp_basicsize */\n' + \ + ' sizeof(PyObject), /* tp_basicsize */\n' + \ ' 0, /* tp_itemsize */\n' + \ ' /* methods */\n' + \ ' (destructor)0, /* tp_dealloc */\n' + \ @@ -120,11 +127,24 @@ interfacetypetmpl = 'PyExtensionClass Py%(class)s_Type = {\n' + \ ' (reprfunc)0, /* tp_str */\n' + \ ' (getattrofunc)0, /* tp_getattro */\n' + \ ' (setattrofunc)0, /* tp_setattro */\n' + \ - ' /* Space for future expansion */\n' + \ - ' 0L, 0L,\n' + \ + ' 0, /* tp_as_buffer */\n' + \ + ' Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */\n' + \ ' NULL, /* Documentation string */\n' + \ - ' %(methods)s,\n' + \ - ' 0,\n' + \ + ' (traverseproc)0, /* tp_traverse */\n' + \ + ' (inquiry)0, /* tp_clear */\n' + \ + ' (richcmpfunc)0, /* tp_richcompare */\n' + \ + ' 0, /* tp_weaklistoffset */\n' +\ + ' (getiterfunc)0, /* tp_iter */\n' + \ + ' (iternextfunc)0, /* tp_iternext */\n' + \ + ' %(methods)s, /* tp_methods */\n' + \ + ' 0, /* tp_members */\n' + \ + ' 0, /* tp_getset */\n' + \ + ' NULL, /* tp_base */\n' + \ + ' NULL, /* tp_dict */\n' + \ + ' (descrgetfunc)0, /* tp_descr_get */\n' + \ + ' (descrsetfunc)0, /* tp_descr_set */\n' + \ + ' 0, /* tp_dictoffset */\n' + \ + ' (initproc)0, /* tp_init */\n' + \ '};\n\n' boxedmethtmpl = 'static PyObject *\n' + \ @@ -138,23 +158,22 @@ boxedmethtmpl = 'static PyObject *\n' + \ '}\n\n' boxedmethcalltmpl = '%(cname)s(pyg_boxed_get(self, %(typename)s)%(arglist)s)' -boxedconsttmpl = 'static PyObject *\n' + \ +boxedconsttmpl = 'static int\n' + \ '_wrap_%(cname)s(PyGBoxed *self, PyObject *args, PyObject *kwargs)\n' + \ '{\n' + \ '%(varlist)s' + \ ' if (!PyArg_ParseTupleAndKeywords(args, kwargs, "%(typecodes)s:%(typename)s.__init__"%(parselist)s))\n' + \ - ' return NULL;\n' + \ + ' return -1;\n' + \ '%(extracode)s\n' + \ ' self->gtype = %(typecode)s;\n' + \ ' self->free_on_dealloc = FALSE;\n' + \ ' self->boxed = %(cname)s(%(arglist)s);\n' + \ ' if (!self->boxed) {\n' + \ ' PyErr_SetString(PyExc_RuntimeError, "could not create %(typename)s object");\n' + \ - ' return NULL;\n' + \ + ' return -1;\n' + \ ' }\n' + \ ' self->free_on_dealloc = TRUE;\n' + \ - ' Py_INCREF(Py_None);\n' + \ - ' return Py_None;\n' + \ + ' return 0;\n' + \ '}\n\n' boxedgetattrtmpl = 'static PyObject *\n' + \ @@ -164,8 +183,12 @@ boxedgetattrtmpl = 'static PyObject *\n' + \ ' PyErr_SetString(PyExc_AttributeError, attr);\n' + \ ' return NULL;\n' + \ '}\n\n' +attrchecktmpl = ' if (!strcmp(attr, "%(attr)s")) {\n' + \ + '%(varlist)s' + \ + '%(code)s\n' + \ + ' }\n' -boxedtmpl = 'PyExtensionClass Py%(typename)s_Type = {\n' + \ +boxedtmpl = 'PyTypeObject Py%(typename)s_Type = {\n' + \ ' PyObject_HEAD_INIT(NULL)\n' + \ ' 0, /* ob_size */\n' + \ ' "%(typename)s", /* tp_name */\n' + \ @@ -186,11 +209,24 @@ boxedtmpl = 'PyExtensionClass Py%(typename)s_Type = {\n' + \ ' (reprfunc)0, /* tp_str */\n' + \ ' (getattrofunc)0, /* tp_getattro */\n' + \ ' (setattrofunc)0, /* tp_setattro */\n' + \ - ' /* Space for future expansion */\n' + \ - ' 0L, 0L,\n' + \ + ' 0, /* tp_as_buffer */\n' + \ + ' Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */\n' +\ ' NULL, /* Documentation string */\n' + \ - ' %(methods)s,\n' + \ - ' 0,\n' + \ + ' (traverseproc)0, /* tp_traverse */\n' + \ + ' (inquiry)0, /* tp_clear */\n' + \ + ' (richcmpfunc)0, /* tp_richcompare */\n' + \ + ' 0, /* tp_weaklistoffset */\n' +\ + ' (getiterfunc)0, /* tp_iter */\n' + \ + ' (iternextfunc)0, /* tp_iternext */\n' + \ + ' %(methods)s, /* tp_methods */\n' + \ + ' 0, /* tp_members */\n' + \ + ' 0, /* tp_getset */\n' + \ + ' NULL, /* tp_base */\n' + \ + ' NULL, /* tp_dict */\n' + \ + ' (descrgetfunc)0, /* tp_descr_get */\n' + \ + ' (descrsetfunc)0, /* tp_descr_set */\n' + \ + ' 0, /* tp_dictoffset */\n' + \ + ' (initproc)%(initfunc)s, /* tp_init */\n' + \ '};\n\n' def fixname(name): @@ -317,70 +353,67 @@ def write_constructor(objname, castmacro, funcobj, fp=sys.stdout): extracode, arglist) dict['typecodes'] = parsestr dict['parselist'] = string.join(parselist, ', ') - dict['extracode'] = string.join(extracode, '') + dict['extracode'] = string.replace(string.join(extracode, ''), + 'return NULL;', 'return -1;') dict['arglist'] = string.join(arglist, ', ') fp.write(consttmpl % dict) -def write_getattr(parser, objobj, castmacro, overrides, fp=sys.stdout): - funcname = '_wrap_' + string.lower(castmacro) + '_getattr' +def write_getsets(parser, objobj, castmacro, overrides, fp=sys.stdout): + getsets_name = string.lower(castmacro) + '_getsets' + funcprefix = '_wrap_' + string.lower(castmacro) + '__get_' - if overrides.is_overriden(funcname[6:]): - fp.write(overrides.override(funcname[6:])) - fp.write('\n\n') - return funcname - # no overrides for the whole function. If no fields, don't write a func if not objobj.fields: return '0' - attrchecks = '' + getsets = [] for ftype, fname in objobj.fields: + funcname = funcprefix + fname attrname = objobj.c_name + '.' + fname if overrides.attr_is_overriden(attrname): code = overrides.attr_override(attrname) - code = ' ' + string.replace(code, '\n', '\n ') - attrchecks = attrchecks + attrchecktmpl % { 'attr': fixname(fname), - 'varlist': '', - 'code': code } + fp.write(code) + getsets.append(' { "%s", (getter)%s, (setter)0 },\n' % + (fixname(fname), funcname)) continue try: varlist = argtypes.VarList() handler = argtypes.matcher.get(ftype) code = handler.write_return(ftype, varlist) % \ {'func': castmacro + '(self->obj)->' + fname} - if code: - # indent code ... - code = ' ' + string.replace(code, '\n', '\n ') - attrchecks = attrchecks + attrchecktmpl % { 'attr': fixname(fname), - 'varlist': varlist, - 'code': code } + fp.write(gettertmpl % { 'funcname': funcname, + 'attr': fname, + 'varlist': varlist, + 'code': code }) + getsets.append(' { "%s", (getter)%s, (setter)0 },\n' % + (fixname(fname), funcname)) except: sys.stderr.write("couldn't write check for " + objobj.c_name + '.' + fname + '\n') #traceback.print_exc() - fp.write(getattrtmpl % {'getattr': funcname, - 'attrchecks': attrchecks }) - return funcname + if not getsets: + return '0' + fp.write('static PyGetSetDef %s[] = {\n' % getsets_name) + for getset in getsets: + fp.write(getset) + fp.write(' { NULL, (getter)0, (setter)0 },\n') + fp.write('};\n\n') + + return getsets_name def write_class(parser, objobj, overrides, fp=sys.stdout): fp.write('\n/* ----------- ' + objobj.c_name + ' ----------- */\n\n') constructor = parser.find_constructor(objobj, overrides) methods = [] castmacro = string.replace(objobj.typecode, '_TYPE_', '_', 1) + initfunc = '0' if constructor: try: - methtype = 'METH_VARARGS' if overrides.is_overriden(constructor.c_name): fp.write(overrides.override(constructor.c_name)) fp.write('\n\n') - if overrides.wants_kwargs(constructor.c_name): - methtype = methtype + '|METH_KEYWORDS' else: write_constructor(objobj.c_name, castmacro, constructor, fp) - methtype = methtype + '|METH_KEYWORDS' - methods.append(methdeftmpl % - { 'name': '__init__', - 'cname': '_wrap_' + constructor.c_name, - 'flags': methtype}) + initfunc = '_wrap_' + constructor.c_name except: sys.stderr.write('Could not write constructor for ' + objobj.c_name + '\n') @@ -389,19 +422,13 @@ def write_class(parser, objobj, overrides, fp=sys.stdout): if not hasattr(overrides, 'no_constructor_written'): fp.write(noconstructor) overrides.no_constructor_written = 1 - methods.append(methdeftmpl % - { 'name': '__init__', - 'cname': 'pygobject_no_constructor', - 'flags': 'METH_VARARGS'}) + initfunc = 'pygobject_no_constructor' else: # this is a hack ... if not hasattr(overrides, 'no_constructor_written'): fp.write(noconstructor) overrides.no_constructor_written = 1 - methods.append(methdeftmpl % - { 'name': '__init__', - 'cname': 'pygobject_no_constructor', - 'flags': 'METH_VARARGS'}) + initfunc = 'pygobject_no_constructor' for meth in parser.find_methods(objobj): if overrides.is_ignored(meth.c_name): continue @@ -430,9 +457,13 @@ def write_class(parser, objobj, overrides, fp=sys.stdout): fp.write('};\n\n') # write the type template - dict = { 'class': objobj.c_name, 'classname': objobj.name } - dict['getattr'] = write_getattr(parser, objobj, castmacro, overrides, fp) - dict['methods'] = 'METHOD_CHAIN(_Py' + dict['class'] + '_methods)' + dict = { + 'class': objobj.c_name, + 'classname': objobj.name, + 'initfunc': initfunc + } + dict['getsets'] = write_getsets(parser, objobj, castmacro, overrides, fp) + dict['methods'] = '_Py' + dict['class'] + '_methods' fp.write(typetmpl % dict) def write_interface(parser, interface, overrides, fp=sys.stdout): @@ -469,7 +500,7 @@ def write_interface(parser, interface, overrides, fp=sys.stdout): # write the type template dict = { 'class': interface.c_name, 'classname': interface.name, 'getattr': '0' } - dict['methods'] = 'METHOD_CHAIN(_Py' + dict['class'] + '_methods)' + dict['methods'] = '_Py' + dict['class'] + '_methods' fp.write(interfacetypetmpl % dict) ## boxed types ... @@ -546,7 +577,8 @@ def write_boxed_constructor(objname, typecode, funcobj, fp=sys.stdout): extracode, arglist) dict['typecodes'] = parsestr dict['parselist'] = string.join(parselist, ', ') - dict['extracode'] = string.join(extracode, '') + dict['extracode'] = string.replace(string.join(extracode, ''), + 'return NULL;', 'return -1;') dict['arglist'] = string.join(arglist, ', ') fp.write(boxedconsttmpl % dict) @@ -597,22 +629,16 @@ def write_boxed(parser, boxedobj, overrides, fp=sys.stdout): fp.write('\n/* ----------- ' + boxedobj.c_name + ' ----------- */\n\n') constructor = parser.find_constructor(boxedobj, overrides) methods = [] + initfunc = '0' if constructor: try: - methtype = 'METH_VARARGS' if overrides.is_overriden(constructor.c_name): fp.write(overrides.override(constructor.c_name)) fp.write('\n\n') - if overrides.wants_kwargs(constructor.c_name): - methtype = methtype + '|METH_KEYWORDS' else: write_boxed_constructor(boxedobj.c_name, boxedobj.typecode, constructor, fp) - methtype = methtype + '|METH_KEYWORDS' - methods.append(methdeftmpl % - { 'name': '__init__', - 'cname': '_wrap_' + constructor.c_name, - 'flags': methtype}) + initfunc = '_wrap_' + constructor.c_name except: sys.stderr.write('Could not write constructor for ' + boxedobj.c_name + '\n') @@ -645,9 +671,9 @@ def write_boxed(parser, boxedobj, overrides, fp=sys.stdout): fp.write('};\n\n') # write the type template - dict = { 'typename': boxedobj.c_name } + dict = { 'typename': boxedobj.c_name, 'initfunc': initfunc } dict['getattr'] = write_boxed_getattr(parser, boxedobj, overrides, fp) - dict['methods'] = 'METHOD_CHAIN(_Py' + dict['typename'] + '_methods)' + dict['methods'] = '_Py' + dict['typename'] + '_methods' fp.write(boxedtmpl % dict) @@ -695,16 +721,16 @@ def write_enums(parser, prefix, fp=sys.stdout): def write_source(parser, overrides, prefix, fp=sys.stdout): fp.write('/* -*- Mode: C; c-basic-offset: 4 -*- */\n\n') - fp.write('#include <Python.h>\n#include <ExtensionClass.h>\n\n') + fp.write('#include <Python.h>\n\n\n') fp.write(overrides.get_headers()) fp.write('\n\n') fp.write('/* ---------- forward type declarations ---------- */\n') for obj in parser.boxes: - fp.write('PyExtensionClass Py' + obj.c_name + '_Type;\n') + fp.write('PyTypeObject Py' + obj.c_name + '_Type;\n') for obj in parser.objects: - fp.write('PyExtensionClass Py' + obj.c_name + '_Type;\n') + fp.write('PyTypeObject Py' + obj.c_name + '_Type;\n') for interface in parser.interfaces: - fp.write('PyExtensionClass Py' + interface.c_name + '_Type;\n') + fp.write('PyTypeObject Py' + interface.c_name + '_Type;\n') fp.write('\n') for boxed in parser.boxes: write_boxed(parser, boxed, overrides, fp) @@ -722,7 +748,6 @@ def write_source(parser, overrides, prefix, fp=sys.stdout): fp.write('/* intialise stuff extension classes */\n') fp.write('void\n' + prefix + '_register_classes(PyObject *d)\n{\n') - fp.write(' ExtensionClassImported;\n') fp.write(overrides.get_init() + '\n') for boxed in parser.boxes: diff --git a/configure.in b/configure.in index eee9d7bf..8783ea3a 100644 --- a/configure.in +++ b/configure.in @@ -11,7 +11,23 @@ ACLOCAL="$ACLOCAL $ACLOCAL_FLAGS" AC_DISABLE_STATIC AC_PROG_LIBTOOL -AM_PATH_PYTHON(2.0) +dnl AM_PATH_PYTHON(2.2) +AM_PATH_PYTHON +AC_MSG_CHECKING(for python >= 2.2) +prog=" +import sys, string +minver = (2,2,0) +if sys.version_info < minver: + sys.exit(1) +sys.exit(0)" +if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC +then + AC_MSG_RESULT(okay) +else + AC_MSG_ERROR(too old) +fi + + AM_CHECK_PYTHON_HEADERS(,[AC_MSG_ERROR(could not find Python headers)]) AC_ARG_ENABLE(thread, diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c index 8bf83d0c..14fe42ee 100644 --- a/gobject/gobjectmodule.c +++ b/gobject/gobjectmodule.c @@ -7,13 +7,21 @@ static GHashTable *class_hash; static GQuark pygobject_wrapper_key = 0; static GQuark pygobject_ownedref_key = 0; -staticforward PyExtensionClass PyGObject_Type; -static void pygobject_dealloc(PyGObject *self); -static PyObject *pygobject_getattro(PyGObject *self, PyObject *attro); -static int pygobject_setattr(PyGObject *self, char *attr, PyObject *val); -static int pygobject_compare(PyGObject *self, PyGObject *v); -static long pygobject_hash(PyGObject *self); -static PyObject *pygobject_repr(PyGObject *self); +staticforward PyTypeObject PyGObject_Type; +static void pygobject_dealloc(PyGObject *self); +static int pygobject_traverse(PyGObject *self, visitproc visit, void *arg); + +static void +object_free(PyObject *op) +{ + PyObject_FREE(op); +} + +static void +object_gc_free(PyObject *op) +{ + PyObject_GC_Del(op); +} /* -------------- __gtype__ objects ---------------------------- */ @@ -103,7 +111,7 @@ pygobject_destroy_notify(gpointer user_data) static void pygobject_register_class(PyObject *dict, const gchar *type_name, - GType type, PyExtensionClass *ec, + GType gtype, PyTypeObject *type, PyObject *bases) { PyObject *o; @@ -112,28 +120,35 @@ pygobject_register_class(PyObject *dict, const gchar *type_name, if (!class_hash) class_hash = g_hash_table_new(g_str_hash, g_str_equal); - class_name = ec->tp_name; - /* set standard pyobject class functions if they aren't already set */ - if (!ec->tp_dealloc) ec->tp_dealloc = (destructor)pygobject_dealloc; - if (!ec->tp_getattro) ec->tp_getattro = (getattrofunc)pygobject_getattro; - if (!ec->tp_setattr) ec->tp_setattr = (setattrfunc)pygobject_setattr; - if (!ec->tp_compare) ec->tp_compare = (cmpfunc)pygobject_compare; - if (!ec->tp_repr) ec->tp_repr = (reprfunc)pygobject_repr; - if (!ec->tp_hash) ec->tp_hash = (hashfunc)pygobject_hash; + class_name = type->tp_name; + type->ob_type = &PyType_Type; if (bases) { - PyExtensionClass_ExportSubclass(dict, (char *)class_name, - *ec, bases); - } else { - PyExtensionClass_Export(dict, (char *)class_name, *ec); + type->tp_bases = bases; + type->tp_base = (PyTypeObject *)PyTuple_GetItem(bases, 0); } - if (type) { - o = pyg_type_wrapper_new(type); - PyDict_SetItemString(ec->class_dictionary, "__gtype__", o); + type->tp_dealloc = (destructor)pygobject_dealloc; + type->tp_traverse = (traverseproc)pygobject_traverse; + type->tp_flags |= Py_TPFLAGS_HAVE_GC; + type->tp_weaklistoffset = offsetof(PyGObject, weakreflist); + type->tp_dictoffset = offsetof(PyGObject, inst_dict); + + if (PyType_Ready(type) < 0) { + g_warning ("couldn't make the type `%s' ready", type->tp_name); + return; + } + + if (gtype) { + o = pyg_type_wrapper_new(gtype); + PyDict_SetItemString(type->tp_dict, "__gtype__", o); + PyDict_SetItemString(type->tp_defined, "__gtype__", o); Py_DECREF(o); } - g_hash_table_insert(class_hash, g_strdup(type_name), ec); + + g_hash_table_insert(class_hash, g_strdup(type_name), type); + + PyDict_SetItemString(dict, (char *)class_name, (PyObject *)type); } void @@ -145,17 +160,17 @@ pygobject_register_wrapper(PyObject *self) g_object_set_qdata(obj, pygobject_wrapper_key, self); } -static PyExtensionClass * -pygobject_lookup_class(GType type) +static PyTypeObject * +pygobject_lookup_class(GType gtype) { - PyExtensionClass *ec; + PyTypeObject *type; /* find the python type for this object. If not found, use parent. */ - while ((ec = g_hash_table_lookup(class_hash, g_type_name(type))) == NULL - && type != 0) - type = g_type_parent(type); - g_assert(ec != NULL); - return ec; + while ((type = g_hash_table_lookup(class_hash, g_type_name(gtype))) == NULL + && gtype != 0) + gtype = g_type_parent(gtype); + g_assert(type != NULL); + return type; } static PyObject * @@ -181,8 +196,8 @@ pygobject_new(GObject *obj) return (PyObject *)self; } - tp = (PyTypeObject *)pygobject_lookup_class(G_TYPE_FROM_INSTANCE(obj)); - self = PyObject_NEW(PyGObject, tp); + tp = pygobject_lookup_class(G_TYPE_FROM_INSTANCE(obj)); + self = PyObject_GC_New(PyGObject, tp); if (self == NULL) return NULL; @@ -190,7 +205,6 @@ pygobject_new(GObject *obj) g_object_ref(obj); /* save wrapper pointer so we can access it later */ g_object_set_qdata(obj, pygobject_wrapper_key, self); - self->inst_dict = PyDict_New(); return (PyObject *)self; } @@ -221,7 +235,8 @@ pyg_boxed_dealloc(PyGBoxed *self) { if (self->free_on_dealloc && self->boxed) g_boxed_free(self->gtype, self->boxed); - PyMem_DEL(self); + + self->ob_type->tp_free((PyObject *)self); } static int @@ -248,46 +263,13 @@ pyg_boxed_repr(PyGBoxed *self) return PyString_FromString(buf); } -static PyObject * -pyg_boxed_getattro(PyGBoxed *self, PyObject *attro) -{ - char *attr; - PyObject *ret; - - attr = PyString_AsString(attro); - - ret = Py_FindAttrString((PyObject *)self, attr); - if (ret) - return ret; - PyErr_Clear(); - - if (self->ob_type->tp_getattr) - return (* self->ob_type->tp_getattr)((PyObject *)self, attr); - - PyErr_SetString(PyExc_AttributeError, attr); - return NULL; -} - -static PyObject * -pyg_boxed__class_init__(PyObject *self, PyObject *args) -{ - PyExtensionClass *subclass; - - if (!PyArg_ParseTuple(args, "O:GBoxed.__class_init__", &subclass)) - return NULL; - - g_message("subclassing GBoxed types is bad m'kay"); - PyErr_SetString(PyExc_TypeError, "attempt to subclass a boxed type"); - return NULL; -} - -static PyObject * -pyg_boxed_init(PyGBoxed *self, PyObject *args) +static int +pyg_boxed_init(PyGBoxed *self, PyObject *args, PyObject *kwargs) { gchar buf[512]; if (!PyArg_ParseTuple(args, ":GBoxed.__init__")) - return NULL; + return -1; self->boxed = NULL; self->gtype = 0; @@ -295,16 +277,10 @@ pyg_boxed_init(PyGBoxed *self, PyObject *args) g_snprintf(buf, sizeof(buf), "%s can not be constructed", self->ob_type->tp_name); PyErr_SetString(PyExc_NotImplementedError, buf); - return NULL; + return -1; } -static PyMethodDef pyg_boxed_methods[] = { - {"__class_init__",pyg_boxed__class_init__, METH_VARARGS|METH_CLASS_METHOD}, - {"__init__", (PyCFunction)pyg_boxed_init, METH_VARARGS}, - {NULL,NULL,0} -}; - -static PyExtensionClass PyGBoxed_Type = { +static PyTypeObject PyGBoxed_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "GBoxed", /* tp_name */ @@ -323,43 +299,64 @@ static PyExtensionClass PyGBoxed_Type = { (hashfunc)pyg_boxed_hash, /* tp_hash */ (ternaryfunc)0, /* tp_call */ (reprfunc)0, /* tp_str */ - (getattrofunc)pyg_boxed_getattro, /* tp_getattro */ + (getattrofunc)0, /* tp_getattro */ (setattrofunc)0, /* tp_setattro */ - /* Space for future expansion */ - 0L, 0L, + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ NULL, /* Documentation string */ - METHOD_CHAIN(pyg_boxed_methods), - 0, + (traverseproc)0, /* tp_traverse */ + (inquiry)0, /* tp_clear */ + (richcmpfunc)0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)0, /* tp_iter */ + (iternextfunc)0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + (PyTypeObject *)0, /* tp_base */ + (PyObject *)0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)pyg_boxed_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ + object_free, /* tp_free */ + (PyObject *)0, /* tp_bases */ }; static GHashTable *boxed_types = NULL; static void pyg_register_boxed(PyObject *dict, const gchar *class_name, - GType boxed_type, PyExtensionClass *ec) + GType boxed_type, PyTypeObject *type) { PyObject *o; g_return_if_fail(dict != NULL); g_return_if_fail(class_name != NULL); g_return_if_fail(boxed_type != 0); - g_return_if_fail(ec != NULL); if (!boxed_types) boxed_types = g_hash_table_new(g_direct_hash, g_direct_equal); - if (!ec->tp_dealloc) ec->tp_dealloc = (destructor)pyg_boxed_dealloc; - if (!ec->tp_compare) ec->tp_compare = (cmpfunc)pyg_boxed_compare; - if (!ec->tp_hash) ec->tp_hash = (hashfunc)pyg_boxed_hash; - if (!ec->tp_repr) ec->tp_repr = (reprfunc)pyg_boxed_repr; - if (!ec->tp_getattro) ec->tp_getattro = (getattrofunc)pyg_boxed_getattro; + if (!type->tp_dealloc) type->tp_dealloc = (destructor)pyg_boxed_dealloc; - PyExtensionClass_ExportSubclassSingle(dict, (char *)class_name, *ec, - PyGBoxed_Type); - PyDict_SetItemString(ec->class_dictionary, "__gtype__", + type->ob_type = &PyType_Type; + type->tp_base = &PyGBoxed_Type; + + if (PyType_Ready(type) < 0) { + g_warning("could not get type `%s' ready", type->tp_name); + return; + } + + PyDict_SetItemString(type->tp_dict, "__gtype__", o=pyg_type_wrapper_new(boxed_type)); + PyDict_SetItemString(type->tp_defined, "__gtype__", o); Py_DECREF(o); - g_hash_table_insert(boxed_types, GUINT_TO_POINTER(boxed_type), ec); + g_hash_table_insert(boxed_types, GUINT_TO_POINTER(boxed_type), type); + + PyDict_SetItemString(dict, (char *)class_name, (PyObject *)type); } static PyObject * @@ -641,8 +638,8 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj) break; case G_TYPE_OBJECT: { - PyExtensionClass *ec =pygobject_lookup_class(G_VALUE_TYPE(value)); - if (!ExtensionClassSubclassInstance_Check(obj, ec)) { + PyTypeObject *type =pygobject_lookup_class(G_VALUE_TYPE(value)); + if (!PyObject_TypeCheck(obj, type)) { return -1; } g_value_set_object(value, pygobject_get(obj)); @@ -670,7 +667,7 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj) if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT)) { g_value_set_boxed(value, obj); - } else if (ExtensionClassSubclassInstance_Check(obj, &PyGBoxed_Type) && + } else if (PyObject_TypeCheck(obj, &PyGBoxed_Type) && G_VALUE_HOLDS(value, ((PyGBoxed *)obj)->gtype)) { g_value_set_boxed(value, pyg_boxed_get(obj, gpointer)); } else if ((bm = pyg_boxed_lookup(G_VALUE_TYPE(value))) != NULL) { @@ -955,89 +952,36 @@ pyg_signal_class_closure_get(void) } /* -------------- PyGObject behaviour ----------------- */ + static void pygobject_dealloc(PyGObject *self) { GObject *obj = self->obj; - if (obj && !(((PyExtensionClass *)self->ob_type)->class_flags & - EXTENSIONCLASS_PYSUBCLASS_FLAG)) { - /* save reference to python wrapper if there are still - * references to the GObject in such a way that it will be - * freed when the GObject is destroyed, so is the python - * wrapper, but if a python wrapper can be */ - if (obj->ref_count > 1) { - Py_INCREF(self); /* grab a reference on the wrapper */ - self->hasref = TRUE; - g_object_set_qdata_full(obj, pygobject_ownedref_key, - self, pygobject_destroy_notify); - g_object_unref(obj); - return; - } - if (!self->hasref) /* don't unref the GObject if it owns us */ - g_object_unref(obj); - } - /* subclass_dealloc (ExtensionClass.c) does this for us for python - * subclasses */ - if (self->inst_dict && - !(((PyExtensionClass *)self->ob_type)->class_flags & - EXTENSIONCLASS_PYSUBCLASS_FLAG)) { - Py_DECREF(self->inst_dict); - } - PyMem_DEL(self); -} - -/* standard getattr method */ -static PyObject * -check_bases(PyGObject *self, PyExtensionClass *class, char *attr) -{ - PyObject *ret; - - if (class->tp_getattr) { - ret = (* class->tp_getattr)((PyObject *)self, attr); - if (ret) - return ret; - else - PyErr_Clear(); + /* save reference to python wrapper if there are still + * references to the GObject in such a way that it will be + * freed when the GObject is destroyed, so is the python + * wrapper, but if a python wrapper can be */ + if (obj && obj->ref_count > 1) { + Py_INCREF(self); /* grab a reference on the wrapper */ + self->hasref = TRUE; + g_object_set_qdata_full(obj, pygobject_ownedref_key, + self, pygobject_destroy_notify); + g_object_unref(obj); + return; } - if (PyExtensionClass_Check(class) && class->bases) { - guint i, len = PyTuple_Size(class->bases); + if (obj && !self->hasref) /* don't unref the GObject if it owns us */ + g_object_unref(obj); - for (i = 0; i < len; i++) { - PyExtensionClass *base = (PyExtensionClass *)PyTuple_GetItem( - class->bases, i); - - ret = check_bases(self, base, attr); - if (ret) - return ret; - } - } - return NULL; -} -static PyObject * -pygobject_getattro(PyGObject *self, PyObject *attro) -{ - char *attr; - PyObject *ret; + PyObject_ClearWeakRefs((PyObject *)self); - attr = PyString_AsString(attro); + PyObject_GC_UnTrack((PyObject *)self); - ret = Py_FindAttrString((PyObject *)self, attr); - if (ret) - return ret; - PyErr_Clear(); - ret = check_bases(self, (PyExtensionClass *)self->ob_type, attr); - if (ret) - return ret; - PyErr_SetString(PyExc_AttributeError, attr); - return NULL; -} + if (self->inst_dict) + Py_DECREF(self->inst_dict); + self->inst_dict = NULL; -static int -pygobject_setattr(PyGObject *self, char *attr, PyObject *value) -{ - PyDict_SetItemString(INSTANCE_DICT(self), attr, value); - return 0; + self->ob_type->tp_free((PyObject *)self); } static int @@ -1064,90 +1008,43 @@ pygobject_repr(PyGObject *self) return PyString_FromString(buf); } -/* ---------------- PyGObject methods ----------------- */ -static destructor real_subclass_dealloc = NULL; -static void -pygobject_subclass_dealloc(PyGObject *self) +static int +pygobject_traverse(PyGObject *self, visitproc visit, void *arg) { - GObject *obj = self->obj; - - if (obj) { - /* save reference to python wrapper if there are still - * references to the GObject in such a way that it will be - * freed when the GObject is destroyed, so is the python - * wrapper, but if a python wrapper can be */ - if (obj->ref_count > 1) { - Py_INCREF(self); /* grab a reference on the wrapper */ - self->hasref = TRUE; - g_object_set_qdata_full(obj, pygobject_ownedref_key, - self, pygobject_destroy_notify); - g_object_unref(obj); - return; - } - if (!self->hasref) /* don't unref the GObject if it owns us */ - g_object_unref(obj); - } - if (real_subclass_dealloc) - (* real_subclass_dealloc)((PyObject *)self); + if (self->inst_dict) + return visit(self->inst_dict, arg); + return 0; } -/* more hackery to stop segfaults caused by multi deallocs on a subclass - * (which happens quite regularly in pygobject) */ -static PyObject * -pygobject__class_init__(PyObject *something, PyObject *args) -{ - PyExtensionClass *subclass; - GTypeInfo type_info = { - 0, /* class_size */ - (GBaseInitFunc) 0, - (GBaseFinalizeFunc) 0, - (GClassInitFunc) 0, - (GClassFinalizeFunc) 0, - NULL, /* class_data */ - - 0, /* instance_size */ - 0, /* n_preallocs */ - (GInstanceInitFunc) 0 - }; - - if (!PyArg_ParseTuple(args, "O:GObject.__class_init__", &subclass)) - return NULL; - g_message("__class_init__ called for %s", subclass->tp_name); - - /* make sure ExtensionClass doesn't screw up our dealloc hack */ - if ((subclass->class_flags & EXTENSIONCLASS_PYSUBCLASS_FLAG) && - subclass->tp_dealloc != (destructor)pygobject_subclass_dealloc) { - real_subclass_dealloc = subclass->tp_dealloc; - subclass->tp_dealloc = (destructor)pygobject_subclass_dealloc; - } - - /* put code in here to create a new GType for this subclass, using - * __module__.__name__ as the name for the type. Then we can add - * the code needed for adding signals to the subclass. The actual - * implementation will have to wait for a g_type_query function */ - - Py_INCREF(Py_None); - return Py_None; -} +/* ---------------- PyGObject methods ----------------- */ -static PyObject * -pygobject__init__(PyGObject *self, PyObject *args) +static int +pygobject_init(PyGObject *self, PyObject *args, PyObject *kwargs) { GType object_type; if (!PyArg_ParseTuple(args, ":GObject.__init__", &object_type)) - return NULL; + return -1; object_type = pyg_type_from_object((PyObject *)self); if (!object_type) - return NULL; + return -1; self->obj = g_object_new(object_type, NULL); if (!self->obj) { PyErr_SetString(PyExc_RuntimeError, "could not create object"); - return NULL; + return -1; } pygobject_register_wrapper((PyObject *)self); + + return 0; +} + +static PyObject * +pygobject__gobject_init__(PyGObject *self, PyObject *args, PyObject *kwargs) +{ + if (pygobject_init(self, args, kwargs) < 0) + return NULL; Py_INCREF(Py_None); return Py_None; } @@ -1552,9 +1449,8 @@ pygobject_stop_emission(PyGObject *self, PyObject *args) } static PyMethodDef pygobject_methods[] = { - { "__class_init__", (PyCFunction)pygobject__class_init__, METH_VARARGS|METH_CLASS_METHOD }, - { "__init__", (PyCFunction)pygobject__init__, METH_VARARGS }, - { "__gobject_init__", (PyCFunction)pygobject__init__, METH_VARARGS }, + { "__gobject_init__", (PyCFunction)pygobject__gobject_init__, + METH_VARARGS|METH_KEYWORDS }, { "get_property", (PyCFunction)pygobject_get_property, METH_VARARGS }, { "set_property", (PyCFunction)pygobject_set_property, METH_VARARGS }, { "freeze_notify", (PyCFunction)pygobject_freeze_notify, METH_VARARGS }, @@ -1576,7 +1472,24 @@ static PyMethodDef pygobject_methods[] = { { NULL, NULL, 0 } }; -static PyExtensionClass PyGObject_Type = { +static PyObject * +pygobject_get_dict(PyGObject *self, void *closure) +{ + if (self->inst_dict == NULL) { + self->inst_dict = PyDict_New(); + if (self->inst_dict == NULL) + return NULL; + } + Py_INCREF(self->inst_dict); + return self->inst_dict; +} + +static PyGetSetDef pygobject_getsets[] = { + { "__dict__", (getter)pygobject_get_dict, (setter)0 }, + { NULL, 0, 0 } +}; + +static PyTypeObject PyGObject_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "GObject", /* tp_name */ @@ -1586,7 +1499,7 @@ static PyExtensionClass PyGObject_Type = { (destructor)pygobject_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)0, /* tp_getattr */ - (setattrfunc)pygobject_setattr, /* tp_setattr */ + (setattrfunc)0, /* tp_setattr */ (cmpfunc)pygobject_compare, /* tp_compare */ (reprfunc)pygobject_repr, /* tp_repr */ 0, /* tp_as_number */ @@ -1597,53 +1510,51 @@ static PyExtensionClass PyGObject_Type = { (reprfunc)0, /* tp_str */ (getattrofunc)0, /* tp_getattro */ (setattrofunc)0, /* tp_setattro */ - /* Space for future expansion */ - 0L, 0L, + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC, /* tp_flags */ NULL, /* Documentation string */ - METHOD_CHAIN(pygobject_methods), - EXTENSIONCLASS_INSTDICT_FLAG, + (traverseproc)pygobject_traverse, /* tp_traverse */ + (inquiry)0, /* tp_clear */ + (richcmpfunc)0, /* tp_richcompare */ + offsetof(PyGObject, weakreflist), /* tp_weaklistoffset */ + (getiterfunc)0, /* tp_iter */ + (iternextfunc)0, /* tp_iternext */ + pygobject_methods, /* tp_methods */ + 0, /* tp_members */ + pygobject_getsets, /* tp_getset */ + (PyTypeObject *)0, /* tp_base */ + (PyObject *)0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + offsetof(PyGObject, inst_dict), /* tp_dictoffset */ + (initproc)pygobject_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ + object_gc_free, /* tp_free */ + (PyObject *)0, /* tp_bases */ }; /* ---------------- GInterface functions -------------------- */ -static PyObject * -pyg_interface__class_init__(PyObject *self, PyObject *args) -{ - PyExtensionClass *subclass; - - if (!PyArg_ParseTuple(args, "O:GInterface.__class_init__", &subclass)) - return NULL; - - g_message("subclassing GInterface types is bad m'kay"); - PyErr_SetString(PyExc_TypeError, "attempt to subclass an interface"); - return NULL; -} - -static PyObject * -pyg_interface_init(PyObject *self, PyObject *args) +static int +pyg_interface_init(PyObject *self, PyObject *args, PyObject *kwargs) { gchar buf[512]; if (!PyArg_ParseTuple(args, ":GInterface.__init__")) - return NULL; + return -1; g_snprintf(buf, sizeof(buf), "%s can not be constructed", self->ob_type->tp_name); PyErr_SetString(PyExc_NotImplementedError, buf); - return NULL; + return -1; } -static PyMethodDef pyg_interface_methods[] = { - {"__class_init__", pyg_interface__class_init__, - METH_VARARGS|METH_CLASS_METHOD}, - {"__init__", pyg_interface_init, METH_VARARGS}, - {NULL,NULL,0} -}; - -static PyExtensionClass PyGInterface_Type = { +static PyTypeObject PyGInterface_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "GInterface", /* tp_name */ - sizeof(PyPureMixinObject), /* tp_basicsize */ + sizeof(PyObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)0, /* tp_dealloc */ @@ -1660,27 +1571,52 @@ static PyExtensionClass PyGInterface_Type = { (reprfunc)0, /* tp_str */ (getattrofunc)0, /* tp_getattro */ (setattrofunc)0, /* tp_setattro */ - /* Space for future expansion */ - 0L, 0L, + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ NULL, /* Documentation string */ - METHOD_CHAIN(pyg_interface_methods), - 0, + (traverseproc)0, /* tp_traverse */ + (inquiry)0, /* tp_clear */ + (richcmpfunc)0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)0, /* tp_iter */ + (iternextfunc)0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + (PyTypeObject *)0, /* tp_base */ + (PyObject *)0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)pyg_interface_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ + object_free, /* tp_free */ + (PyObject *)0, /* tp_bases */ }; static void pyg_register_interface(PyObject *dict, const gchar *class_name, - GType type, PyExtensionClass *ec) + GType gtype, PyTypeObject *type) { PyObject *o; - PyExtensionClass_ExportSubclassSingle(dict, (char *)class_name, - *ec, PyGInterface_Type); + type->ob_type = &PyType_Type; + type->tp_base = &PyGInterface_Type; + + if (PyType_Ready(type) < 0) { + g_warning("could not ready `%s'", type->tp_name); + return; + } - if (type) { - o = pyg_type_wrapper_new(type); - PyDict_SetItemString(ec->class_dictionary, "__gtype__", o); + if (gtype) { + o = pyg_type_wrapper_new(gtype); + PyDict_SetItemString(type->tp_dict, "__gtype__", o); + PyDict_SetItemString(type->tp_defined, "__gtype__", o); Py_DECREF(o); } + + PyDict_SetItemString(dict, (char *)class_name, (PyObject *)type); } @@ -1806,7 +1742,8 @@ pyg_type_interfaces (PyObject *self, PyObject *args) static PyObject * pyg_type_register(PyObject *self, PyObject *args) { - PyObject *class, *gtype, *module; + PyObject *gtype, *module; + PyTypeObject *class; GType parent_type, instance_type; gchar *type_name = NULL; gint i; @@ -1828,28 +1765,28 @@ pyg_type_register(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "O:gobject.type_register", &class)) return NULL; - if (!ExtensionClassSubclass_Check(class, &PyGObject_Type)) { + if (!PyType_IsSubtype(class, &PyGObject_Type)) { PyErr_SetString(PyExc_TypeError,"argument must be a GObject subclass"); return NULL; } /* find the GType of the parent */ - parent_type = pyg_type_from_object(class); + parent_type = pyg_type_from_object((PyObject *)class); if (!parent_type) { return NULL; } /* make name for new widget */ - module = PyObject_GetAttrString(class, "__module__"); + module = PyObject_GetAttrString((PyObject *)class, "__module__"); if (module && PyString_Check(module)) { type_name = g_strconcat(PyString_AsString(module), ".", - ((PyExtensionClass *)class)->tp_name, NULL); + class->tp_name, NULL); } else { if (module) Py_DECREF(module); else PyErr_Clear(); - type_name = g_strdup(((PyExtensionClass *)class)->tp_name); + type_name = g_strdup(class->tp_name); } /* convert '.' in type name to '+', which isn't banned (grumble) */ for (i = 0; type_name[i] != '\0'; i++) @@ -1872,7 +1809,8 @@ pyg_type_register(PyObject *self, PyObject *args) /* set new value of __gtype__ on class */ gtype = pyg_type_wrapper_new(instance_type); - PyObject_SetAttrString(class, "__gtype__", gtype); + PyDict_SetItemString(class->tp_dict, "__gtype__", gtype); + PyDict_SetItemString(class->tp_defined, "__gtype__", gtype); Py_DECREF(gtype); Py_INCREF(Py_None); @@ -2159,14 +2097,22 @@ initgobject(void) pygobject_register_class(d, "GObject", G_TYPE_OBJECT, &PyGObject_Type, NULL); - PyExtensionClass_Export(d, "GInterface", PyGInterface_Type); - PyDict_SetItemString(PyGInterface_Type.class_dictionary, "__gtype__", + PyGInterface_Type.ob_type = &PyType_Type; + if (PyType_Ready(&PyGInterface_Type)) + return; + PyDict_SetItemString(d, "GInterface", (PyObject *)&PyGInterface_Type); + PyDict_SetItemString(PyGInterface_Type.tp_dict, "__gtype__", o=pyg_type_wrapper_new(G_TYPE_INTERFACE)); + PyDict_SetItemString(PyGInterface_Type.tp_defined, "__gtype__", o); Py_DECREF(o); - PyExtensionClass_Export(d, "GBoxed", PyGBoxed_Type); - PyDict_SetItemString(PyGBoxed_Type.class_dictionary, "__gtype__", + PyGBoxed_Type.ob_type = &PyType_Type; + if (PyType_Ready(&PyGBoxed_Type)) + return; + PyDict_SetItemString(d, "GBoxed", (PyObject *)&PyGBoxed_Type); + PyDict_SetItemString(PyGBoxed_Type.tp_dict, "__gtype__", o=pyg_type_wrapper_new(G_TYPE_BOXED)); + PyDict_SetItemString(PyGBoxed_Type.tp_defined, "__gtype__", o); Py_DECREF(o); boxed_marshalers = g_hash_table_new(g_direct_hash, g_direct_equal); diff --git a/gobject/pygobject.h b/gobject/pygobject.h index 2b031a13..4be17b9a 100644 --- a/gobject/pygobject.h +++ b/gobject/pygobject.h @@ -3,7 +3,6 @@ #define _PYGOBJECT_H_ #include <Python.h> -#include <ExtensionClass.h> #include <glib.h> #include <glib-object.h> @@ -13,10 +12,11 @@ typedef struct { GObject *obj; gboolean hasref; /* the GObject owns this reference */ PyObject *inst_dict; /* the instance dictionary -- must be last */ + PyObject *weakreflist; /* list of weak references */ } PyGObject; #define pygobject_get(v) (((PyGObject *)(v))->obj) -#define pygobject_check(v,base) (ExtensionClassSubclassInstance_Check(v,base)) +#define pygobject_check(v,base) (PyObject_TypeCheck(v,base)) typedef struct { PyObject_HEAD @@ -26,13 +26,13 @@ typedef struct { } PyGBoxed; #define pyg_boxed_get(v,t) ((t *)((PyGBoxed *)(v))->boxed) -#define pyg_boxed_check(v,typecode) (ExtensionClassSubclassInstance_Check(v, &PyGBoxed_Type) && ((PyGBoxed *)(v))->gtype == typecode) +#define pyg_boxed_check(v,typecode) (PyObject_TypeCheck(v, &PyGBoxed_Type) && ((PyGBoxed *)(v))->gtype == typecode) struct _PyGObject_Functions { void (* register_class)(PyObject *dict, const gchar *class_name, - GType type, PyExtensionClass *ec, PyObject *bases); + GType gtype, PyTypeObject *type, PyObject *bases); void (* register_wrapper)(PyObject *self); - PyExtensionClass *(* lookup_class)(GType type); + PyTypeObject *(* lookup_class)(GType type); PyObject *(* newgobj)(GObject *obj); GClosure *(* closure_new)(PyObject *callback, PyObject *extra_args, PyObject *swap_data); @@ -49,11 +49,11 @@ struct _PyGObject_Functions { PyObject *(* value_as_pyobject)(const GValue *value); void (* register_interface)(PyObject *dict, const gchar *class_name, - GType type, PyExtensionClass *ec); + GType gtype, PyTypeObject *type); - PyExtensionClass *boxed_type; + PyTypeObject *boxed_type; void (* register_boxed)(PyObject *dict, const gchar *class_name, - GType boxed_type, PyExtensionClass *ec); + GType boxed_type, PyTypeObject *type); PyObject *(* boxed_new)(GType boxed_type, gpointer boxed, gboolean copy_boxed, gboolean own_ref); @@ -105,7 +105,6 @@ struct _PyGObject_Functions *_PyGObject_API; Py_FatalError("could not import gobject"); \ return; \ } \ - ExtensionClassImported; \ } #endif /* !_INSIDE_PYGOBJECT_ */ diff --git a/gobjectmodule.c b/gobjectmodule.c index 8bf83d0c..14fe42ee 100644 --- a/gobjectmodule.c +++ b/gobjectmodule.c @@ -7,13 +7,21 @@ static GHashTable *class_hash; static GQuark pygobject_wrapper_key = 0; static GQuark pygobject_ownedref_key = 0; -staticforward PyExtensionClass PyGObject_Type; -static void pygobject_dealloc(PyGObject *self); -static PyObject *pygobject_getattro(PyGObject *self, PyObject *attro); -static int pygobject_setattr(PyGObject *self, char *attr, PyObject *val); -static int pygobject_compare(PyGObject *self, PyGObject *v); -static long pygobject_hash(PyGObject *self); -static PyObject *pygobject_repr(PyGObject *self); +staticforward PyTypeObject PyGObject_Type; +static void pygobject_dealloc(PyGObject *self); +static int pygobject_traverse(PyGObject *self, visitproc visit, void *arg); + +static void +object_free(PyObject *op) +{ + PyObject_FREE(op); +} + +static void +object_gc_free(PyObject *op) +{ + PyObject_GC_Del(op); +} /* -------------- __gtype__ objects ---------------------------- */ @@ -103,7 +111,7 @@ pygobject_destroy_notify(gpointer user_data) static void pygobject_register_class(PyObject *dict, const gchar *type_name, - GType type, PyExtensionClass *ec, + GType gtype, PyTypeObject *type, PyObject *bases) { PyObject *o; @@ -112,28 +120,35 @@ pygobject_register_class(PyObject *dict, const gchar *type_name, if (!class_hash) class_hash = g_hash_table_new(g_str_hash, g_str_equal); - class_name = ec->tp_name; - /* set standard pyobject class functions if they aren't already set */ - if (!ec->tp_dealloc) ec->tp_dealloc = (destructor)pygobject_dealloc; - if (!ec->tp_getattro) ec->tp_getattro = (getattrofunc)pygobject_getattro; - if (!ec->tp_setattr) ec->tp_setattr = (setattrfunc)pygobject_setattr; - if (!ec->tp_compare) ec->tp_compare = (cmpfunc)pygobject_compare; - if (!ec->tp_repr) ec->tp_repr = (reprfunc)pygobject_repr; - if (!ec->tp_hash) ec->tp_hash = (hashfunc)pygobject_hash; + class_name = type->tp_name; + type->ob_type = &PyType_Type; if (bases) { - PyExtensionClass_ExportSubclass(dict, (char *)class_name, - *ec, bases); - } else { - PyExtensionClass_Export(dict, (char *)class_name, *ec); + type->tp_bases = bases; + type->tp_base = (PyTypeObject *)PyTuple_GetItem(bases, 0); } - if (type) { - o = pyg_type_wrapper_new(type); - PyDict_SetItemString(ec->class_dictionary, "__gtype__", o); + type->tp_dealloc = (destructor)pygobject_dealloc; + type->tp_traverse = (traverseproc)pygobject_traverse; + type->tp_flags |= Py_TPFLAGS_HAVE_GC; + type->tp_weaklistoffset = offsetof(PyGObject, weakreflist); + type->tp_dictoffset = offsetof(PyGObject, inst_dict); + + if (PyType_Ready(type) < 0) { + g_warning ("couldn't make the type `%s' ready", type->tp_name); + return; + } + + if (gtype) { + o = pyg_type_wrapper_new(gtype); + PyDict_SetItemString(type->tp_dict, "__gtype__", o); + PyDict_SetItemString(type->tp_defined, "__gtype__", o); Py_DECREF(o); } - g_hash_table_insert(class_hash, g_strdup(type_name), ec); + + g_hash_table_insert(class_hash, g_strdup(type_name), type); + + PyDict_SetItemString(dict, (char *)class_name, (PyObject *)type); } void @@ -145,17 +160,17 @@ pygobject_register_wrapper(PyObject *self) g_object_set_qdata(obj, pygobject_wrapper_key, self); } -static PyExtensionClass * -pygobject_lookup_class(GType type) +static PyTypeObject * +pygobject_lookup_class(GType gtype) { - PyExtensionClass *ec; + PyTypeObject *type; /* find the python type for this object. If not found, use parent. */ - while ((ec = g_hash_table_lookup(class_hash, g_type_name(type))) == NULL - && type != 0) - type = g_type_parent(type); - g_assert(ec != NULL); - return ec; + while ((type = g_hash_table_lookup(class_hash, g_type_name(gtype))) == NULL + && gtype != 0) + gtype = g_type_parent(gtype); + g_assert(type != NULL); + return type; } static PyObject * @@ -181,8 +196,8 @@ pygobject_new(GObject *obj) return (PyObject *)self; } - tp = (PyTypeObject *)pygobject_lookup_class(G_TYPE_FROM_INSTANCE(obj)); - self = PyObject_NEW(PyGObject, tp); + tp = pygobject_lookup_class(G_TYPE_FROM_INSTANCE(obj)); + self = PyObject_GC_New(PyGObject, tp); if (self == NULL) return NULL; @@ -190,7 +205,6 @@ pygobject_new(GObject *obj) g_object_ref(obj); /* save wrapper pointer so we can access it later */ g_object_set_qdata(obj, pygobject_wrapper_key, self); - self->inst_dict = PyDict_New(); return (PyObject *)self; } @@ -221,7 +235,8 @@ pyg_boxed_dealloc(PyGBoxed *self) { if (self->free_on_dealloc && self->boxed) g_boxed_free(self->gtype, self->boxed); - PyMem_DEL(self); + + self->ob_type->tp_free((PyObject *)self); } static int @@ -248,46 +263,13 @@ pyg_boxed_repr(PyGBoxed *self) return PyString_FromString(buf); } -static PyObject * -pyg_boxed_getattro(PyGBoxed *self, PyObject *attro) -{ - char *attr; - PyObject *ret; - - attr = PyString_AsString(attro); - - ret = Py_FindAttrString((PyObject *)self, attr); - if (ret) - return ret; - PyErr_Clear(); - - if (self->ob_type->tp_getattr) - return (* self->ob_type->tp_getattr)((PyObject *)self, attr); - - PyErr_SetString(PyExc_AttributeError, attr); - return NULL; -} - -static PyObject * -pyg_boxed__class_init__(PyObject *self, PyObject *args) -{ - PyExtensionClass *subclass; - - if (!PyArg_ParseTuple(args, "O:GBoxed.__class_init__", &subclass)) - return NULL; - - g_message("subclassing GBoxed types is bad m'kay"); - PyErr_SetString(PyExc_TypeError, "attempt to subclass a boxed type"); - return NULL; -} - -static PyObject * -pyg_boxed_init(PyGBoxed *self, PyObject *args) +static int +pyg_boxed_init(PyGBoxed *self, PyObject *args, PyObject *kwargs) { gchar buf[512]; if (!PyArg_ParseTuple(args, ":GBoxed.__init__")) - return NULL; + return -1; self->boxed = NULL; self->gtype = 0; @@ -295,16 +277,10 @@ pyg_boxed_init(PyGBoxed *self, PyObject *args) g_snprintf(buf, sizeof(buf), "%s can not be constructed", self->ob_type->tp_name); PyErr_SetString(PyExc_NotImplementedError, buf); - return NULL; + return -1; } -static PyMethodDef pyg_boxed_methods[] = { - {"__class_init__",pyg_boxed__class_init__, METH_VARARGS|METH_CLASS_METHOD}, - {"__init__", (PyCFunction)pyg_boxed_init, METH_VARARGS}, - {NULL,NULL,0} -}; - -static PyExtensionClass PyGBoxed_Type = { +static PyTypeObject PyGBoxed_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "GBoxed", /* tp_name */ @@ -323,43 +299,64 @@ static PyExtensionClass PyGBoxed_Type = { (hashfunc)pyg_boxed_hash, /* tp_hash */ (ternaryfunc)0, /* tp_call */ (reprfunc)0, /* tp_str */ - (getattrofunc)pyg_boxed_getattro, /* tp_getattro */ + (getattrofunc)0, /* tp_getattro */ (setattrofunc)0, /* tp_setattro */ - /* Space for future expansion */ - 0L, 0L, + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ NULL, /* Documentation string */ - METHOD_CHAIN(pyg_boxed_methods), - 0, + (traverseproc)0, /* tp_traverse */ + (inquiry)0, /* tp_clear */ + (richcmpfunc)0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)0, /* tp_iter */ + (iternextfunc)0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + (PyTypeObject *)0, /* tp_base */ + (PyObject *)0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)pyg_boxed_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ + object_free, /* tp_free */ + (PyObject *)0, /* tp_bases */ }; static GHashTable *boxed_types = NULL; static void pyg_register_boxed(PyObject *dict, const gchar *class_name, - GType boxed_type, PyExtensionClass *ec) + GType boxed_type, PyTypeObject *type) { PyObject *o; g_return_if_fail(dict != NULL); g_return_if_fail(class_name != NULL); g_return_if_fail(boxed_type != 0); - g_return_if_fail(ec != NULL); if (!boxed_types) boxed_types = g_hash_table_new(g_direct_hash, g_direct_equal); - if (!ec->tp_dealloc) ec->tp_dealloc = (destructor)pyg_boxed_dealloc; - if (!ec->tp_compare) ec->tp_compare = (cmpfunc)pyg_boxed_compare; - if (!ec->tp_hash) ec->tp_hash = (hashfunc)pyg_boxed_hash; - if (!ec->tp_repr) ec->tp_repr = (reprfunc)pyg_boxed_repr; - if (!ec->tp_getattro) ec->tp_getattro = (getattrofunc)pyg_boxed_getattro; + if (!type->tp_dealloc) type->tp_dealloc = (destructor)pyg_boxed_dealloc; - PyExtensionClass_ExportSubclassSingle(dict, (char *)class_name, *ec, - PyGBoxed_Type); - PyDict_SetItemString(ec->class_dictionary, "__gtype__", + type->ob_type = &PyType_Type; + type->tp_base = &PyGBoxed_Type; + + if (PyType_Ready(type) < 0) { + g_warning("could not get type `%s' ready", type->tp_name); + return; + } + + PyDict_SetItemString(type->tp_dict, "__gtype__", o=pyg_type_wrapper_new(boxed_type)); + PyDict_SetItemString(type->tp_defined, "__gtype__", o); Py_DECREF(o); - g_hash_table_insert(boxed_types, GUINT_TO_POINTER(boxed_type), ec); + g_hash_table_insert(boxed_types, GUINT_TO_POINTER(boxed_type), type); + + PyDict_SetItemString(dict, (char *)class_name, (PyObject *)type); } static PyObject * @@ -641,8 +638,8 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj) break; case G_TYPE_OBJECT: { - PyExtensionClass *ec =pygobject_lookup_class(G_VALUE_TYPE(value)); - if (!ExtensionClassSubclassInstance_Check(obj, ec)) { + PyTypeObject *type =pygobject_lookup_class(G_VALUE_TYPE(value)); + if (!PyObject_TypeCheck(obj, type)) { return -1; } g_value_set_object(value, pygobject_get(obj)); @@ -670,7 +667,7 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj) if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT)) { g_value_set_boxed(value, obj); - } else if (ExtensionClassSubclassInstance_Check(obj, &PyGBoxed_Type) && + } else if (PyObject_TypeCheck(obj, &PyGBoxed_Type) && G_VALUE_HOLDS(value, ((PyGBoxed *)obj)->gtype)) { g_value_set_boxed(value, pyg_boxed_get(obj, gpointer)); } else if ((bm = pyg_boxed_lookup(G_VALUE_TYPE(value))) != NULL) { @@ -955,89 +952,36 @@ pyg_signal_class_closure_get(void) } /* -------------- PyGObject behaviour ----------------- */ + static void pygobject_dealloc(PyGObject *self) { GObject *obj = self->obj; - if (obj && !(((PyExtensionClass *)self->ob_type)->class_flags & - EXTENSIONCLASS_PYSUBCLASS_FLAG)) { - /* save reference to python wrapper if there are still - * references to the GObject in such a way that it will be - * freed when the GObject is destroyed, so is the python - * wrapper, but if a python wrapper can be */ - if (obj->ref_count > 1) { - Py_INCREF(self); /* grab a reference on the wrapper */ - self->hasref = TRUE; - g_object_set_qdata_full(obj, pygobject_ownedref_key, - self, pygobject_destroy_notify); - g_object_unref(obj); - return; - } - if (!self->hasref) /* don't unref the GObject if it owns us */ - g_object_unref(obj); - } - /* subclass_dealloc (ExtensionClass.c) does this for us for python - * subclasses */ - if (self->inst_dict && - !(((PyExtensionClass *)self->ob_type)->class_flags & - EXTENSIONCLASS_PYSUBCLASS_FLAG)) { - Py_DECREF(self->inst_dict); - } - PyMem_DEL(self); -} - -/* standard getattr method */ -static PyObject * -check_bases(PyGObject *self, PyExtensionClass *class, char *attr) -{ - PyObject *ret; - - if (class->tp_getattr) { - ret = (* class->tp_getattr)((PyObject *)self, attr); - if (ret) - return ret; - else - PyErr_Clear(); + /* save reference to python wrapper if there are still + * references to the GObject in such a way that it will be + * freed when the GObject is destroyed, so is the python + * wrapper, but if a python wrapper can be */ + if (obj && obj->ref_count > 1) { + Py_INCREF(self); /* grab a reference on the wrapper */ + self->hasref = TRUE; + g_object_set_qdata_full(obj, pygobject_ownedref_key, + self, pygobject_destroy_notify); + g_object_unref(obj); + return; } - if (PyExtensionClass_Check(class) && class->bases) { - guint i, len = PyTuple_Size(class->bases); + if (obj && !self->hasref) /* don't unref the GObject if it owns us */ + g_object_unref(obj); - for (i = 0; i < len; i++) { - PyExtensionClass *base = (PyExtensionClass *)PyTuple_GetItem( - class->bases, i); - - ret = check_bases(self, base, attr); - if (ret) - return ret; - } - } - return NULL; -} -static PyObject * -pygobject_getattro(PyGObject *self, PyObject *attro) -{ - char *attr; - PyObject *ret; + PyObject_ClearWeakRefs((PyObject *)self); - attr = PyString_AsString(attro); + PyObject_GC_UnTrack((PyObject *)self); - ret = Py_FindAttrString((PyObject *)self, attr); - if (ret) - return ret; - PyErr_Clear(); - ret = check_bases(self, (PyExtensionClass *)self->ob_type, attr); - if (ret) - return ret; - PyErr_SetString(PyExc_AttributeError, attr); - return NULL; -} + if (self->inst_dict) + Py_DECREF(self->inst_dict); + self->inst_dict = NULL; -static int -pygobject_setattr(PyGObject *self, char *attr, PyObject *value) -{ - PyDict_SetItemString(INSTANCE_DICT(self), attr, value); - return 0; + self->ob_type->tp_free((PyObject *)self); } static int @@ -1064,90 +1008,43 @@ pygobject_repr(PyGObject *self) return PyString_FromString(buf); } -/* ---------------- PyGObject methods ----------------- */ -static destructor real_subclass_dealloc = NULL; -static void -pygobject_subclass_dealloc(PyGObject *self) +static int +pygobject_traverse(PyGObject *self, visitproc visit, void *arg) { - GObject *obj = self->obj; - - if (obj) { - /* save reference to python wrapper if there are still - * references to the GObject in such a way that it will be - * freed when the GObject is destroyed, so is the python - * wrapper, but if a python wrapper can be */ - if (obj->ref_count > 1) { - Py_INCREF(self); /* grab a reference on the wrapper */ - self->hasref = TRUE; - g_object_set_qdata_full(obj, pygobject_ownedref_key, - self, pygobject_destroy_notify); - g_object_unref(obj); - return; - } - if (!self->hasref) /* don't unref the GObject if it owns us */ - g_object_unref(obj); - } - if (real_subclass_dealloc) - (* real_subclass_dealloc)((PyObject *)self); + if (self->inst_dict) + return visit(self->inst_dict, arg); + return 0; } -/* more hackery to stop segfaults caused by multi deallocs on a subclass - * (which happens quite regularly in pygobject) */ -static PyObject * -pygobject__class_init__(PyObject *something, PyObject *args) -{ - PyExtensionClass *subclass; - GTypeInfo type_info = { - 0, /* class_size */ - (GBaseInitFunc) 0, - (GBaseFinalizeFunc) 0, - (GClassInitFunc) 0, - (GClassFinalizeFunc) 0, - NULL, /* class_data */ - - 0, /* instance_size */ - 0, /* n_preallocs */ - (GInstanceInitFunc) 0 - }; - - if (!PyArg_ParseTuple(args, "O:GObject.__class_init__", &subclass)) - return NULL; - g_message("__class_init__ called for %s", subclass->tp_name); - - /* make sure ExtensionClass doesn't screw up our dealloc hack */ - if ((subclass->class_flags & EXTENSIONCLASS_PYSUBCLASS_FLAG) && - subclass->tp_dealloc != (destructor)pygobject_subclass_dealloc) { - real_subclass_dealloc = subclass->tp_dealloc; - subclass->tp_dealloc = (destructor)pygobject_subclass_dealloc; - } - - /* put code in here to create a new GType for this subclass, using - * __module__.__name__ as the name for the type. Then we can add - * the code needed for adding signals to the subclass. The actual - * implementation will have to wait for a g_type_query function */ - - Py_INCREF(Py_None); - return Py_None; -} +/* ---------------- PyGObject methods ----------------- */ -static PyObject * -pygobject__init__(PyGObject *self, PyObject *args) +static int +pygobject_init(PyGObject *self, PyObject *args, PyObject *kwargs) { GType object_type; if (!PyArg_ParseTuple(args, ":GObject.__init__", &object_type)) - return NULL; + return -1; object_type = pyg_type_from_object((PyObject *)self); if (!object_type) - return NULL; + return -1; self->obj = g_object_new(object_type, NULL); if (!self->obj) { PyErr_SetString(PyExc_RuntimeError, "could not create object"); - return NULL; + return -1; } pygobject_register_wrapper((PyObject *)self); + + return 0; +} + +static PyObject * +pygobject__gobject_init__(PyGObject *self, PyObject *args, PyObject *kwargs) +{ + if (pygobject_init(self, args, kwargs) < 0) + return NULL; Py_INCREF(Py_None); return Py_None; } @@ -1552,9 +1449,8 @@ pygobject_stop_emission(PyGObject *self, PyObject *args) } static PyMethodDef pygobject_methods[] = { - { "__class_init__", (PyCFunction)pygobject__class_init__, METH_VARARGS|METH_CLASS_METHOD }, - { "__init__", (PyCFunction)pygobject__init__, METH_VARARGS }, - { "__gobject_init__", (PyCFunction)pygobject__init__, METH_VARARGS }, + { "__gobject_init__", (PyCFunction)pygobject__gobject_init__, + METH_VARARGS|METH_KEYWORDS }, { "get_property", (PyCFunction)pygobject_get_property, METH_VARARGS }, { "set_property", (PyCFunction)pygobject_set_property, METH_VARARGS }, { "freeze_notify", (PyCFunction)pygobject_freeze_notify, METH_VARARGS }, @@ -1576,7 +1472,24 @@ static PyMethodDef pygobject_methods[] = { { NULL, NULL, 0 } }; -static PyExtensionClass PyGObject_Type = { +static PyObject * +pygobject_get_dict(PyGObject *self, void *closure) +{ + if (self->inst_dict == NULL) { + self->inst_dict = PyDict_New(); + if (self->inst_dict == NULL) + return NULL; + } + Py_INCREF(self->inst_dict); + return self->inst_dict; +} + +static PyGetSetDef pygobject_getsets[] = { + { "__dict__", (getter)pygobject_get_dict, (setter)0 }, + { NULL, 0, 0 } +}; + +static PyTypeObject PyGObject_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "GObject", /* tp_name */ @@ -1586,7 +1499,7 @@ static PyExtensionClass PyGObject_Type = { (destructor)pygobject_dealloc, /* tp_dealloc */ (printfunc)0, /* tp_print */ (getattrfunc)0, /* tp_getattr */ - (setattrfunc)pygobject_setattr, /* tp_setattr */ + (setattrfunc)0, /* tp_setattr */ (cmpfunc)pygobject_compare, /* tp_compare */ (reprfunc)pygobject_repr, /* tp_repr */ 0, /* tp_as_number */ @@ -1597,53 +1510,51 @@ static PyExtensionClass PyGObject_Type = { (reprfunc)0, /* tp_str */ (getattrofunc)0, /* tp_getattro */ (setattrofunc)0, /* tp_setattro */ - /* Space for future expansion */ - 0L, 0L, + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC, /* tp_flags */ NULL, /* Documentation string */ - METHOD_CHAIN(pygobject_methods), - EXTENSIONCLASS_INSTDICT_FLAG, + (traverseproc)pygobject_traverse, /* tp_traverse */ + (inquiry)0, /* tp_clear */ + (richcmpfunc)0, /* tp_richcompare */ + offsetof(PyGObject, weakreflist), /* tp_weaklistoffset */ + (getiterfunc)0, /* tp_iter */ + (iternextfunc)0, /* tp_iternext */ + pygobject_methods, /* tp_methods */ + 0, /* tp_members */ + pygobject_getsets, /* tp_getset */ + (PyTypeObject *)0, /* tp_base */ + (PyObject *)0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + offsetof(PyGObject, inst_dict), /* tp_dictoffset */ + (initproc)pygobject_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ + object_gc_free, /* tp_free */ + (PyObject *)0, /* tp_bases */ }; /* ---------------- GInterface functions -------------------- */ -static PyObject * -pyg_interface__class_init__(PyObject *self, PyObject *args) -{ - PyExtensionClass *subclass; - - if (!PyArg_ParseTuple(args, "O:GInterface.__class_init__", &subclass)) - return NULL; - - g_message("subclassing GInterface types is bad m'kay"); - PyErr_SetString(PyExc_TypeError, "attempt to subclass an interface"); - return NULL; -} - -static PyObject * -pyg_interface_init(PyObject *self, PyObject *args) +static int +pyg_interface_init(PyObject *self, PyObject *args, PyObject *kwargs) { gchar buf[512]; if (!PyArg_ParseTuple(args, ":GInterface.__init__")) - return NULL; + return -1; g_snprintf(buf, sizeof(buf), "%s can not be constructed", self->ob_type->tp_name); PyErr_SetString(PyExc_NotImplementedError, buf); - return NULL; + return -1; } -static PyMethodDef pyg_interface_methods[] = { - {"__class_init__", pyg_interface__class_init__, - METH_VARARGS|METH_CLASS_METHOD}, - {"__init__", pyg_interface_init, METH_VARARGS}, - {NULL,NULL,0} -}; - -static PyExtensionClass PyGInterface_Type = { +static PyTypeObject PyGInterface_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "GInterface", /* tp_name */ - sizeof(PyPureMixinObject), /* tp_basicsize */ + sizeof(PyObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)0, /* tp_dealloc */ @@ -1660,27 +1571,52 @@ static PyExtensionClass PyGInterface_Type = { (reprfunc)0, /* tp_str */ (getattrofunc)0, /* tp_getattro */ (setattrofunc)0, /* tp_setattro */ - /* Space for future expansion */ - 0L, 0L, + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ NULL, /* Documentation string */ - METHOD_CHAIN(pyg_interface_methods), - 0, + (traverseproc)0, /* tp_traverse */ + (inquiry)0, /* tp_clear */ + (richcmpfunc)0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)0, /* tp_iter */ + (iternextfunc)0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + (PyTypeObject *)0, /* tp_base */ + (PyObject *)0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)pyg_interface_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ + object_free, /* tp_free */ + (PyObject *)0, /* tp_bases */ }; static void pyg_register_interface(PyObject *dict, const gchar *class_name, - GType type, PyExtensionClass *ec) + GType gtype, PyTypeObject *type) { PyObject *o; - PyExtensionClass_ExportSubclassSingle(dict, (char *)class_name, - *ec, PyGInterface_Type); + type->ob_type = &PyType_Type; + type->tp_base = &PyGInterface_Type; + + if (PyType_Ready(type) < 0) { + g_warning("could not ready `%s'", type->tp_name); + return; + } - if (type) { - o = pyg_type_wrapper_new(type); - PyDict_SetItemString(ec->class_dictionary, "__gtype__", o); + if (gtype) { + o = pyg_type_wrapper_new(gtype); + PyDict_SetItemString(type->tp_dict, "__gtype__", o); + PyDict_SetItemString(type->tp_defined, "__gtype__", o); Py_DECREF(o); } + + PyDict_SetItemString(dict, (char *)class_name, (PyObject *)type); } @@ -1806,7 +1742,8 @@ pyg_type_interfaces (PyObject *self, PyObject *args) static PyObject * pyg_type_register(PyObject *self, PyObject *args) { - PyObject *class, *gtype, *module; + PyObject *gtype, *module; + PyTypeObject *class; GType parent_type, instance_type; gchar *type_name = NULL; gint i; @@ -1828,28 +1765,28 @@ pyg_type_register(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "O:gobject.type_register", &class)) return NULL; - if (!ExtensionClassSubclass_Check(class, &PyGObject_Type)) { + if (!PyType_IsSubtype(class, &PyGObject_Type)) { PyErr_SetString(PyExc_TypeError,"argument must be a GObject subclass"); return NULL; } /* find the GType of the parent */ - parent_type = pyg_type_from_object(class); + parent_type = pyg_type_from_object((PyObject *)class); if (!parent_type) { return NULL; } /* make name for new widget */ - module = PyObject_GetAttrString(class, "__module__"); + module = PyObject_GetAttrString((PyObject *)class, "__module__"); if (module && PyString_Check(module)) { type_name = g_strconcat(PyString_AsString(module), ".", - ((PyExtensionClass *)class)->tp_name, NULL); + class->tp_name, NULL); } else { if (module) Py_DECREF(module); else PyErr_Clear(); - type_name = g_strdup(((PyExtensionClass *)class)->tp_name); + type_name = g_strdup(class->tp_name); } /* convert '.' in type name to '+', which isn't banned (grumble) */ for (i = 0; type_name[i] != '\0'; i++) @@ -1872,7 +1809,8 @@ pyg_type_register(PyObject *self, PyObject *args) /* set new value of __gtype__ on class */ gtype = pyg_type_wrapper_new(instance_type); - PyObject_SetAttrString(class, "__gtype__", gtype); + PyDict_SetItemString(class->tp_dict, "__gtype__", gtype); + PyDict_SetItemString(class->tp_defined, "__gtype__", gtype); Py_DECREF(gtype); Py_INCREF(Py_None); @@ -2159,14 +2097,22 @@ initgobject(void) pygobject_register_class(d, "GObject", G_TYPE_OBJECT, &PyGObject_Type, NULL); - PyExtensionClass_Export(d, "GInterface", PyGInterface_Type); - PyDict_SetItemString(PyGInterface_Type.class_dictionary, "__gtype__", + PyGInterface_Type.ob_type = &PyType_Type; + if (PyType_Ready(&PyGInterface_Type)) + return; + PyDict_SetItemString(d, "GInterface", (PyObject *)&PyGInterface_Type); + PyDict_SetItemString(PyGInterface_Type.tp_dict, "__gtype__", o=pyg_type_wrapper_new(G_TYPE_INTERFACE)); + PyDict_SetItemString(PyGInterface_Type.tp_defined, "__gtype__", o); Py_DECREF(o); - PyExtensionClass_Export(d, "GBoxed", PyGBoxed_Type); - PyDict_SetItemString(PyGBoxed_Type.class_dictionary, "__gtype__", + PyGBoxed_Type.ob_type = &PyType_Type; + if (PyType_Ready(&PyGBoxed_Type)) + return; + PyDict_SetItemString(d, "GBoxed", (PyObject *)&PyGBoxed_Type); + PyDict_SetItemString(PyGBoxed_Type.tp_dict, "__gtype__", o=pyg_type_wrapper_new(G_TYPE_BOXED)); + PyDict_SetItemString(PyGBoxed_Type.tp_defined, "__gtype__", o); Py_DECREF(o); boxed_marshalers = g_hash_table_new(g_direct_hash, g_direct_equal); diff --git a/gtk/__init__.py b/gtk/__init__.py index f8e2bc7d..dcb6b8f8 100644 --- a/gtk/__init__.py +++ b/gtk/__init__.py @@ -11,10 +11,6 @@ except ImportError: FALSE = 0 TRUE = 1 -# hack so that ltihooks is used when importing ExtensionClass ... -import ExtensionClass -del ExtensionClass - import gobject del gobject diff --git a/gtk/gdk.override b/gtk/gdk.override index 8d0d9955..45d67625 100644 --- a/gtk/gdk.override +++ b/gtk/gdk.override @@ -11,17 +11,17 @@ headers #undef gdk_window_get_type #define gdk_window_get_type gdk_window_object_get_type -static PyExtensionClass *_PyGObject_Type; +static PyTypeObject *_PyGObject_Type; #define PyGObject_Type (*_PyGObject_Type) -static PyExtensionClass *_PyPangoContext_Type; +static PyTypeObject *_PyPangoContext_Type; #define PyPangoContext_Type (*_PyPangoContext_Type) -static PyExtensionClass *_PyPangoFont_Type; +static PyTypeObject *_PyPangoFont_Type; #define PyPangoFont_Type (*_PyPangoFont_Type) -static PyExtensionClass *_PyPangoLayout_Type; +static PyTypeObject *_PyPangoLayout_Type; #define PyPangoLayout_Type (*_PyPangoLayout_Type) -extern PyExtensionClass PyGtkWidget_Type; +extern PyTypeObject PyGtkWidget_Type; %% init @@ -32,8 +32,8 @@ init if (pygobject != NULL) { PyObject *module_dict = PyModule_GetDict(pygobject); - _PyGObject_Type = (PyExtensionClass *)PyDict_GetItemString(module_dict, - "GObject"); + _PyGObject_Type = (PyTypeObject *)PyDict_GetItemString(module_dict, + "GObject"); } else { Py_FatalError("could not import gobject"); return; @@ -43,14 +43,11 @@ init PyObject *module_dict = PyModule_GetDict(pypango); _PyPangoContext_Type = - (PyExtensionClass *)PyDict_GetItemString(module_dict, - "Context"); + (PyTypeObject *)PyDict_GetItemString(module_dict, "Context"); _PyPangoFont_Type = - (PyExtensionClass *)PyDict_GetItemString(module_dict, - "Font"); + (PyTypeObject *)PyDict_GetItemString(module_dict, "Font"); _PyPangoLayout_Type = - (PyExtensionClass *)PyDict_GetItemString(module_dict, - "Layout"); + (PyTypeObject *)PyDict_GetItemString(module_dict, "Layout"); } else { Py_FatalError("could not import pango"); return; @@ -515,7 +512,7 @@ _wrap_gdk_pixmap_colormap_create_from_xpm_d(PyObject *self, PyObject *args, ignore gdk_cursor_new_from_pixmap %% override gdk_cursor_new kwargs -static PyObject * +static int _wrap_gdk_cursor_new(PyGBoxed *self, PyObject *args, PyObject *kwargs) { static char *kwlist1[] = { "cursor_type", NULL }; @@ -531,12 +528,12 @@ _wrap_gdk_cursor_new(PyGBoxed *self, PyObject *args, PyObject *kwargs) if (pyg_enum_get_value(GDK_TYPE_CURSOR_TYPE, py_cursor_type, (gint *)&cursor_type)) - return NULL; + return -1; self->boxed = gdk_cursor_new(cursor_type); if (!self->boxed) { PyErr_SetString(PyExc_RuntimeError, "could not create GdkCursor object"); - return NULL; + return -1; } self->free_on_dealloc = TRUE; } else { @@ -548,22 +545,22 @@ _wrap_gdk_cursor_new(PyGBoxed *self, PyObject *args, PyObject *kwargs) if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOOOii:GdkCursor.__init__", kwlist2, &source, &mask, &fg, &bg, &x, &y)) - return NULL; + return -1; if (!pygobject_check(source, &PyGdkPixmap_Type)) { PyErr_SetString(PyExc_TypeError, "source should be a GdkPixmap"); - return NULL; + return -1; } if (!pygobject_check(mask, &PyGdkPixmap_Type)) { PyErr_SetString(PyExc_TypeError, "mask should be a GdkPixmap"); - return NULL; + return -1; } if (!pyg_boxed_check(fg, GDK_TYPE_COLOR)) { PyErr_SetString(PyExc_TypeError, "fg should be a GdkColor"); - return NULL; + return -1; } if (!pyg_boxed_check(bg, GDK_TYPE_COLOR)) { PyErr_SetString(PyExc_TypeError, "bg should be a GdkColor"); - return NULL; + return -1; } self->boxed = gdk_cursor_new_from_pixmap(GDK_PIXMAP(source->obj), GDK_PIXMAP(mask->obj), @@ -573,12 +570,11 @@ _wrap_gdk_cursor_new(PyGBoxed *self, PyObject *args, PyObject *kwargs) if (!self->boxed) { PyErr_SetString(PyExc_RuntimeError, "could not create GdkCursor object"); - return NULL; + return -1; } self->free_on_dealloc = TRUE; } - Py_INCREF(Py_None); - return Py_None; + return 0; } %% override gdk_event_getattr @@ -821,29 +817,37 @@ _wrap_gdk_event_getattr(PyObject *self, char *attr) } %% override-attr GdkDevice.axes -GdkDevice *device = GDK_DEVICE(self->obj); -PyObject *ret; -gint i; +static PyObject * +_wrap_gdk_device__get_axes(PyGObject *self, void *closure) +{ + GdkDevice *device = GDK_DEVICE(self->obj); + PyObject *ret; + gint i; -ret = PyTuple_New(device->num_axes); -for (i = 0; i < device->num_axes; i++) - PyTuple_SetItem(ret, i, Py_BuildValue("(idd)", - device->axes[i].use, - device->axes[i].min, - device->axes[i].max)); -return ret; + ret = PyTuple_New(device->num_axes); + for (i = 0; i < device->num_axes; i++) + PyTuple_SetItem(ret, i, Py_BuildValue("(idd)", + device->axes[i].use, + device->axes[i].min, + device->axes[i].max)); + return ret; +} %% override-attr GdkDevice.keys -GdkDevice *device = GDK_DEVICE(self->obj); -PyObject *ret; -gint i; +static PyObject * +_wrap_gdk_device__get_keys(PyGObject *self, void *closure) +{ + GdkDevice *device = GDK_DEVICE(self->obj); + PyObject *ret; + gint i; -ret = PyTuple_New(device->num_keys); -for (i = 0; i < device->num_keys; i++) - PyTuple_SetItem(ret, i, Py_BuildValue("(ii)", - device->keys[i].keyval, - device->keys[i].modifiers)); -return ret; + ret = PyTuple_New(device->num_keys); + for (i = 0; i < device->num_keys; i++) + PyTuple_SetItem(ret, i, Py_BuildValue("(ii)", + device->keys[i].keyval, + device->keys[i].modifiers)); + return ret; +} %% override gdk_device_get_state kwargs static PyObject * @@ -981,19 +985,23 @@ _wrap_gdk_drag_find_window(PyGObject *self, PyObject *args, PyObject *kwargs) } %% override-attr GdkDragContext.targets -PyObject *atom, *ret = PyList_New(0); -GList *tmp; -if (ret == NULL) - return NULL; -for (tmp = GDK_DRAG_CONTEXT(self->obj)->targets; tmp; tmp = tmp->next) { - if ((atom = PyGdkAtom_New(GPOINTER_TO_INT(tmp->data))) == NULL) { - Py_DECREF(ret); +static PyObject * +_wrap_gdk_drag_context__get_targets(PyGObject *self, void *closure) +{ + PyObject *atom, *ret = PyList_New(0); + GList *tmp; + if (ret == NULL) return NULL; + for (tmp = GDK_DRAG_CONTEXT(self->obj)->targets; tmp; tmp = tmp->next) { + if ((atom = PyGdkAtom_New(GPOINTER_TO_INT(tmp->data))) == NULL) { + Py_DECREF(ret); + return NULL; + } + PyList_Append(ret, atom); + Py_DECREF(atom); } - PyList_Append(ret, atom); - Py_DECREF(atom); + return ret; } -return ret; %% override gdk_gc_new_with_values kwargs static PyObject * diff --git a/gtk/gtk-types.c b/gtk/gtk-types.c index ac28b5f5..d82635f3 100644 --- a/gtk/gtk-types.c +++ b/gtk/gtk-types.c @@ -3,9 +3,6 @@ #include "pygtk-private.h" #include <structmember.h> -/* these aren't ExtensionClass's */ -#undef Py_FindMethod - #if 0 PyObject * PyGtkStyle_New(GtkStyle *obj) @@ -1451,7 +1448,6 @@ _pygtk_register_boxed_types(PyObject *moddict) PyDict_SetItemString(moddict, #x "Type", (PyObject *)&Py##x##_Type); \ pyg_register_boxed_custom(tp, Py##x##_from_value, Py##x##_to_value) - ExtensionClassImported; #if 0 register_tp(GtkStyle); PyGtkStyleHelper_Type.ob_type = &PyType_Type; diff --git a/gtk/gtk.override b/gtk/gtk.override index 3e01b432..2c8a295c 100644 --- a/gtk/gtk.override +++ b/gtk/gtk.override @@ -8,25 +8,25 @@ headers #include "pygtk-private.h" #include "pygtktreemodel.h" -static PyExtensionClass *_PyGObject_Type; +static PyTypeObject *_PyGObject_Type; #define PyGObject_Type (*_PyGObject_Type) -static PyExtensionClass *_PyPangoContext_Type; +static PyTypeObject *_PyPangoContext_Type; #define PyPangoContext_Type (*_PyPangoContext_Type) -static PyExtensionClass *_PyPangoFont_Type; +static PyTypeObject *_PyPangoFont_Type; #define PyPangoFont_Type (*_PyPangoFont_Type) -static PyExtensionClass *_PyPangoLayout_Type; +static PyTypeObject *_PyPangoLayout_Type; #define PyPangoLayout_Type (*_PyPangoLayout_Type) /* from the gdk portion ... */ -extern PyExtensionClass PyGdkColormap_Type; -extern PyExtensionClass PyGdkGC_Type; -extern PyExtensionClass PyGdkWindow_Type; -extern PyExtensionClass PyGdkPixmap_Type; -extern PyExtensionClass PyGdkImage_Type; -extern PyExtensionClass PyGdkPixbuf_Type; -extern PyExtensionClass PyGdkPixbufAnimation_Type; -extern PyExtensionClass PyGdkDragContext_Type; +extern PyTypeObject PyGdkColormap_Type; +extern PyTypeObject PyGdkGC_Type; +extern PyTypeObject PyGdkWindow_Type; +extern PyTypeObject PyGdkPixmap_Type; +extern PyTypeObject PyGdkImage_Type; +extern PyTypeObject PyGdkPixbuf_Type; +extern PyTypeObject PyGdkPixbufAnimation_Type; +extern PyTypeObject PyGdkDragContext_Type; %% @@ -38,8 +38,8 @@ init if (pygobject != NULL) { PyObject *module_dict = PyModule_GetDict(pygobject); - _PyGObject_Type = (PyExtensionClass *)PyDict_GetItemString(module_dict, - "GObject"); + _PyGObject_Type = (PyTypeObject *)PyDict_GetItemString(module_dict, + "GObject"); } else { Py_FatalError("could not import gobject"); return; @@ -49,14 +49,11 @@ init PyObject *module_dict = PyModule_GetDict(pypango); _PyPangoContext_Type = - (PyExtensionClass *)PyDict_GetItemString(module_dict, - "Context"); + (PyTypeObject *)PyDict_GetItemString(module_dict, "Context"); _PyPangoFont_Type = - (PyExtensionClass *)PyDict_GetItemString(module_dict, - "Font"); + (PyTypeObject *)PyDict_GetItemString(module_dict, "Font"); _PyPangoLayout_Type = - (PyExtensionClass *)PyDict_GetItemString(module_dict, - "Layout"); + (PyTypeObject *)PyDict_GetItemString(module_dict, "Layout"); } else { Py_FatalError("could not import pango"); return; @@ -67,13 +64,17 @@ init ignore gtk_selection_data_copy gtk_selection_data_free %% override-attr GtkSelectionData.data -if (pyg_boxed_get(self, GtkSelectionData)->length >= 0) { - return PyString_FromStringAndSize( +static PyObject * +_wrap_gtk_selection_data__get_data(PyGObject *self, void *closure) +{ + if (pyg_boxed_get(self, GtkSelectionData)->length >= 0) { + return PyString_FromStringAndSize( pyg_boxed_get(self, GtkSelectionData)->data, pyg_boxed_get(self, GtkSelectionData)->length); -} else { - Py_INCREF(Py_None); - return Py_None; + } else { + Py_INCREF(Py_None); + return Py_None; + } } %% override gtk_selection_data_set kwargs @@ -337,7 +338,7 @@ _wrap_gtk_box_query_child_packing(PyGObject *self, PyObject *args, ignore gtk_clist_new %% override gtk_clist_new_with_titles kwargs -static PyObject * +static int _wrap_gtk_clist_new_with_titles(PyGObject *self, PyObject *args, PyObject *kwargs) { @@ -347,17 +348,17 @@ _wrap_gtk_clist_new_with_titles(PyGObject *self, PyObject *args, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:GtkCList.__init__", kwlist, &count, &py_list)) - return NULL; + return -1; if (py_list) { gchar **list; if (!PySequence_Check(py_list)) { PyErr_SetString(PyExc_TypeError,"2nd argument not a sequence"); - return NULL; + return -1; } if (PySequence_Length(py_list) < count) { PyErr_SetString(PyExc_TypeError, "sequence not long enough"); - return NULL; + return -1; } list = g_new(gchar *, count); for (i = 0; i < count; i++) { @@ -367,7 +368,7 @@ _wrap_gtk_clist_new_with_titles(PyGObject *self, PyObject *args, if (!PyString_Check(item)) { PyErr_SetString(PyExc_TypeError, "sequence item not a string"); g_free(list); - return NULL; + return -1; } list[i] = PyString_AsString(item); } @@ -377,13 +378,12 @@ _wrap_gtk_clist_new_with_titles(PyGObject *self, PyObject *args, self->obj = (GObject *)gtk_clist_new(count); if (!self->obj) { PyErr_SetString(PyExc_RuntimeError,"could not create GtkCList object"); - return NULL; + return -1; } gtk_object_ref(GTK_OBJECT(self->obj)); gtk_object_sink(GTK_OBJECT(self->obj)); pygobject_register_wrapper((PyObject *)self); - Py_INCREF(Py_None); - return Py_None; + return 0; } %% override gtk_clist_get_text kwargs @@ -637,28 +637,32 @@ _wrap_gtk_clist_get_selection_info(PyGObject *self, PyObject *args, } %% override-attr GtkCList.selection -guint row; -GList *selection; -PyObject *py_int, *ret = PyList_New(0); +static PyObject * +_wrap_gtk_clist__get_selection(PyGObject *self, void *closure) +{ + guint row; + GList *selection; + PyObject *py_int, *ret = PyList_New(0); -if (ret == NULL) - return NULL; + if (ret == NULL) + return NULL; -for (selection = GTK_CLIST(self->obj)->selection; selection != NULL; - selection = selection->next) { - row = GPOINTER_TO_UINT(selection->data); + for (selection = GTK_CLIST(self->obj)->selection; selection != NULL; + selection = selection->next) { + row = GPOINTER_TO_UINT(selection->data); - py_int = PyInt_FromLong(row); + py_int = PyInt_FromLong(row); - if (!py_int) { - Py_DECREF(ret); - return NULL; - } + if (!py_int) { + Py_DECREF(ret); + return NULL; + } - PyList_Append(ret, py_int); - Py_DECREF(py_int); + PyList_Append(ret, py_int); + Py_DECREF(py_int); + } + return ret; } -return ret; %% override gtk_combo_set_popdown_strings kwargs static PyObject * @@ -1179,7 +1183,7 @@ ignore gtk_tree_view_column_new_with_attributes %% override gtk_tree_view_column_new kwargs -static PyObject * +static int _wrap_gtk_tree_view_column_new(PyGObject *self, PyObject*args, PyObject*kwargs) { PyObject *py_cell = NULL, *key, *item; @@ -1190,14 +1194,14 @@ _wrap_gtk_tree_view_column_new(PyGObject *self, PyObject*args, PyObject*kwargs) if (!PyArg_ParseTuple(args, "|zO:GtkTreeViewColumn.__init__", &title, &py_cell)) - return NULL; + return -1; if (py_cell != NULL) { if (pygobject_check(py_cell, &PyGtkCellRenderer_Type)) cell = GTK_CELL_RENDERER(pygobject_get(py_cell)); else if (py_cell != Py_None) { PyErr_SetString(PyExc_TypeError, "cell must be a GtkCellRenderer or None"); - return NULL; + return -1; } } tvc = gtk_tree_view_column_new(); @@ -1215,7 +1219,7 @@ _wrap_gtk_tree_view_column_new(PyGObject *self, PyObject*args, PyObject*kwargs) "%s must be an integer column number", attr); PyErr_SetString(PyExc_TypeError, err); g_object_unref(G_OBJECT(tvc)); - return NULL; + return -1; } gtk_tree_view_column_add_attribute(tvc, cell, attr, PyInt_AsLong(item)); @@ -1225,8 +1229,7 @@ _wrap_gtk_tree_view_column_new(PyGObject *self, PyObject*args, PyObject*kwargs) gtk_object_ref(GTK_OBJECT(self->obj)); gtk_object_sink(GTK_OBJECT(self->obj)); pygobject_register_wrapper((PyObject *)self); - Py_INCREF(Py_None); - return Py_None; + return 0; } %% override gtk_tree_view_get_path_at_pos kwargs @@ -1887,7 +1890,7 @@ _wrap_gtk_pixmap_get(PyGObject *self, PyObject *args) ignore gtk_button_new_with_label gtk_button_new_from_stock gtk_button_new_with_mnemonic %% override gtk_button_new kwargs -static PyObject * +static int _wrap_gtk_button_new(PyGObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "label", "stock", NULL }; @@ -1895,7 +1898,7 @@ _wrap_gtk_button_new(PyGObject *self, PyObject *args, PyObject *kwargs) if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zz:GtkButton.__init__", kwlist, &text, &stock)) - return NULL; + return -1; if (stock) self->obj = (GObject *)gtk_button_new_from_stock(stock); else if (text) @@ -1904,19 +1907,18 @@ _wrap_gtk_button_new(PyGObject *self, PyObject *args, PyObject *kwargs) self->obj = (GObject *)gtk_button_new(); if (!self->obj) { PyErr_SetString(PyExc_RuntimeError, "could not create GtkButton object"); - return NULL; + return -1; } gtk_object_ref(GTK_OBJECT(self->obj)); gtk_object_sink(GTK_OBJECT(self->obj)); pygobject_register_wrapper((PyObject *)self); - Py_INCREF(Py_None); - return Py_None; + return 0; } %% ignore gtk_toggle_button_new_with_label gtk_toggle_button_new_with_mnemonic %% override gtk_toggle_button_new kwargs -static PyObject * +static int _wrap_gtk_toggle_button_new(PyGObject *self, PyObject*args, PyObject*kwargs) { static char *kwlist[] = { "label", NULL }; @@ -1925,26 +1927,25 @@ _wrap_gtk_toggle_button_new(PyGObject *self, PyObject*args, PyObject*kwargs) if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|z:GtkToggleButton.__init__", kwlist, &text)) - return NULL; + return -1; if (text) self->obj = (GObject *)gtk_toggle_button_new_with_mnemonic(text); else self->obj = (GObject *)gtk_toggle_button_new(); if (!self->obj) { PyErr_SetString(PyExc_RuntimeError, "could not create GtkToggleButton object"); - return NULL; + return -1; } gtk_object_ref(GTK_OBJECT(self->obj)); gtk_object_sink(GTK_OBJECT(self->obj)); pygobject_register_wrapper((PyObject *)self); - Py_INCREF(Py_None); - return Py_None; + return 0; } %% ignore gtk_check_button_new_with_label gtk_check_button_new_with_mnemonic %% override gtk_check_button_new kwargs -static PyObject * +static int _wrap_gtk_check_button_new(PyGObject *self, PyObject *args, PyObject*kwargs) { static char *kwlist[] = { "label", NULL }; @@ -1952,26 +1953,25 @@ _wrap_gtk_check_button_new(PyGObject *self, PyObject *args, PyObject*kwargs) if (!PyArg_ParseTupleAndKeywords(args, kwargs,"|z:GtkCheckButton.__init__", kwlist, &text)) - return NULL; + return -1; if (text) self->obj = (GObject *)gtk_check_button_new_with_mnemonic(text); else self->obj = (GObject *)gtk_check_button_new(); if (!self->obj) { PyErr_SetString(PyExc_RuntimeError, "could not create GtkCheckButton object"); - return NULL; + return -1; } gtk_object_ref(GTK_OBJECT(self->obj)); gtk_object_sink(GTK_OBJECT(self->obj)); pygobject_register_wrapper((PyObject *)self); - Py_INCREF(Py_None); - return Py_None; + return 0; } %% ignore-glob gtk_radio_button_new_* %% override gtk_radio_button_new kwargs -static PyObject * +static int _wrap_gtk_radio_button_new(PyGObject *self, PyObject *args, PyObject*kwargs) { static char *kwlist[] = { "group", "label", NULL }; @@ -1981,7 +1981,7 @@ _wrap_gtk_radio_button_new(PyGObject *self, PyObject *args, PyObject*kwargs) if (!PyArg_ParseTupleAndKeywords(args,kwargs,"|Oz:GtkRadioButton.__init__", kwlist, &py_group, &label)) - return NULL; + return -1; if (py_group == Py_None) group = NULL; else if (pygobject_check(py_group, &PyGtkRadioButton_Type)) @@ -1989,7 +1989,7 @@ _wrap_gtk_radio_button_new(PyGObject *self, PyObject *args, PyObject*kwargs) else { PyErr_SetString(PyExc_TypeError, "first argument must be a GtkRadioButton or None"); - return NULL; + return -1; } /* various configs for create radio buttons ... */ if (label == NULL) { @@ -2006,19 +2006,18 @@ _wrap_gtk_radio_button_new(PyGObject *self, PyObject *args, PyObject*kwargs) } if (!self->obj) { PyErr_SetString(PyExc_RuntimeError, "could not create GtkRadioButton object"); - return NULL; + return -1; } gtk_object_ref(GTK_OBJECT(self->obj)); gtk_object_sink(GTK_OBJECT(self->obj)); pygobject_register_wrapper((PyObject *)self); - Py_INCREF(Py_None); - return Py_None; + return 0; } %% ignore gtk_list_item_new_with_label %% override gtk_list_item_new kwargs -static PyObject * +static int _wrap_gtk_list_item_new(PyGObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "label", NULL }; @@ -2026,26 +2025,25 @@ _wrap_gtk_list_item_new(PyGObject *self, PyObject *args, PyObject *kwargs) if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|z:GtkListItem.__init__", kwlist, &text)) - return NULL; + return -1; if (text) self->obj = (GObject *)gtk_list_item_new_with_label(text); else self->obj = (GObject *)gtk_list_item_new(); if (!self->obj) { PyErr_SetString(PyExc_RuntimeError, "could not create GtkListItem object"); - return NULL; + return -1; } gtk_object_ref(GTK_OBJECT(self->obj)); gtk_object_sink(GTK_OBJECT(self->obj)); pygobject_register_wrapper((PyObject *)self); - Py_INCREF(Py_None); - return Py_None; + return 0; } %% ignore gtk_menu_item_new_with_label gtk_menu_item_new_with_mnemonic %% override gtk_menu_item_new kwargs -static PyObject * +static int _wrap_gtk_menu_item_new(PyGObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "label", NULL }; @@ -2053,26 +2051,25 @@ _wrap_gtk_menu_item_new(PyGObject *self, PyObject *args, PyObject *kwargs) if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|z:GtkMenuItem.__init__", kwlist, &text)) - return NULL; + return -1; if (text) self->obj = (GObject *)gtk_menu_item_new_with_mnemonic(text); else self->obj = (GObject *)gtk_menu_item_new(); if (!self->obj) { PyErr_SetString(PyExc_RuntimeError, "could not create GtkMenuItem object"); - return NULL; + return -1; } gtk_object_ref(GTK_OBJECT(self->obj)); gtk_object_sink(GTK_OBJECT(self->obj)); pygobject_register_wrapper((PyObject *)self); - Py_INCREF(Py_None); - return Py_None; + return 0; } %% ignore gtk_check_menu_item_new_with_label gtk_check_menu_item_new_with_mnemonic %% override gtk_check_menu_item_new kwargs -static PyObject * +static int _wrap_gtk_check_menu_item_new(PyGObject *self, PyObject *args, PyObject *kwargs) { @@ -2082,26 +2079,25 @@ _wrap_gtk_check_menu_item_new(PyGObject *self, PyObject *args, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|z:GtkCheckMenuItem.__init__", kwlist, &text)) - return NULL; + return -1; if (text) self->obj = (GObject *)gtk_check_menu_item_new_with_mnemonic(text); else self->obj = (GObject *)gtk_check_menu_item_new(); if (!self->obj) { PyErr_SetString(PyExc_RuntimeError, "could not create GtkCheckMenuItem object"); - return NULL; + return -1; } gtk_object_ref(GTK_OBJECT(self->obj)); gtk_object_sink(GTK_OBJECT(self->obj)); pygobject_register_wrapper((PyObject *)self); - Py_INCREF(Py_None); - return Py_None; + return 0; } %% ignore gtk_radio_menu_item_new_with_label gtk_radio_menu_item_new_with_mnemonic %% override gtk_radio_menu_item_new kwargs -static PyObject * +static int _wrap_gtk_radio_menu_item_new(PyGObject *self, PyObject *args, PyObject *kwargs) { @@ -2113,7 +2109,7 @@ _wrap_gtk_radio_menu_item_new(PyGObject *self, PyObject *args, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oz:GtkRadioMenuItem.__init__", kwlist, &py_group, &text)) - return NULL; + return -1; if (py_group == Py_None) group = NULL; else if (pygobject_check(py_group, &PyGtkRadioMenuItem_Type)) @@ -2121,7 +2117,7 @@ _wrap_gtk_radio_menu_item_new(PyGObject *self, PyObject *args, else { PyErr_SetString(PyExc_TypeError, "first argument must be a GtkRadioMenuItem or None"); - return NULL; + return -1; } /* various configs for create radio buttons ... */ if (text == NULL) { @@ -2139,13 +2135,12 @@ _wrap_gtk_radio_menu_item_new(PyGObject *self, PyObject *args, } if (!self->obj) { PyErr_SetString(PyExc_RuntimeError, "could not create GtkRadioMenuItem object"); - return NULL; + return -1; } gtk_object_ref(GTK_OBJECT(self->obj)); gtk_object_sink(GTK_OBJECT(self->obj)); pygobject_register_wrapper((PyObject *)self); - Py_INCREF(Py_None); - return Py_None; + return 0; } %% ignore gtk_ctree_construct @@ -2160,26 +2155,30 @@ ignore gtk_ctree_construct ignore gtk_ctree_new %% override-attr GtkCTree.selection -GList *selection; -GtkCTreeNode *node; -PyObject *ret, *py_node; -if ((ret = PyList_New(0)) == NULL) - return NULL; +static PyObject * +_wrap_gtk_ctree__get_selection(PyGObject *self, void *closure) +{ + GList *selection; + GtkCTreeNode *node; + PyObject *ret, *py_node; + if ((ret = PyList_New(0)) == NULL) + return NULL; -for (selection = GTK_CLIST(self->obj)->selection; selection != NULL; - selection = selection->next) { - node = selection->data; - if ((py_node = pyg_boxed_new(GTK_TYPE_CTREE_NODE, node, TRUE, TRUE)) == NULL) { - Py_DECREF(ret); - return NULL; + for (selection = GTK_CLIST(self->obj)->selection; selection != NULL; + selection = selection->next) { + node = selection->data; + if ((py_node = pyg_boxed_new(GTK_TYPE_CTREE_NODE, node, TRUE, TRUE)) == NULL) { + Py_DECREF(ret); + return NULL; + } + PyList_Append(ret, py_node); + Py_DECREF(py_node); } - PyList_Append(ret, py_node); - Py_DECREF(py_node); + return ret; } -return ret; %% override gtk_ctree_new_with_titles kwargs -static PyObject* +static int _wrap_gtk_ctree_new_with_titles(PyGObject *self, PyObject *args, PyObject *kwargs) { @@ -2190,18 +2189,18 @@ _wrap_gtk_ctree_new_with_titles(PyGObject *self, PyObject *args, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iiO:GtkCTree.__init__", kwlist, &columns, &tree_column, &py_titles)) - return NULL; + return -1; if (py_titles) { gchar **titles; gint i; if (!PySequence_Check(py_titles)) { PyErr_SetString(PyExc_TypeError, "titles must be a sequence"); - return NULL; + return -1; } if (PySequence_Length(py_titles) < columns) { PyErr_SetString(PyExc_TypeError, "titles too short"); - return NULL; + return -1; } titles = g_new(gchar *, columns); for (i = 0; i < columns; i++) { @@ -2211,7 +2210,7 @@ _wrap_gtk_ctree_new_with_titles(PyGObject *self, PyObject *args, if (!PyString_Check(item)) { PyErr_SetString(PyExc_TypeError, "sequence item not a string"); g_free(titles); - return NULL; + return -1; } titles[i] = PyString_AsString(item); } @@ -2222,13 +2221,12 @@ _wrap_gtk_ctree_new_with_titles(PyGObject *self, PyObject *args, self->obj = (GObject *)gtk_ctree_new(columns, tree_column); if (!self->obj) { PyErr_SetString(PyExc_RuntimeError,"could not create GtkCTree object"); - return NULL; + return -1; } gtk_object_ref(GTK_OBJECT(self->obj)); gtk_object_sink(GTK_OBJECT(self->obj)); pygobject_register_wrapper((PyObject *)self); - Py_INCREF(Py_None); - return Py_None; + return 0; } %% override gtk_ctree_base_nodes @@ -3686,7 +3684,7 @@ _wrap_gtk_text_buffer_get_iter_at_mark(PyGObject *self, PyObject *args, PyObject ignore gtk_dialog_new %% override gtk_dialog_new_with_buttons kwargs -static PyObject * +static int _wrap_gtk_dialog_new_with_buttons(PyGObject *self, PyObject *args, PyObject *kwargs) { gchar *title = NULL; @@ -3701,12 +3699,12 @@ _wrap_gtk_dialog_new_with_buttons(PyGObject *self, PyObject *args, PyObject *kwa "|sOdO!:GtkDialog.__init__", kwlist, &title, &py_window, &flags, &PyTuple_Type, &py_buttons)) - return NULL; + return -1; if (py_window != NULL && py_window != (PyGObject *) Py_None && !pygobject_check(py_window, &PyGtkWindow_Type)) { PyErr_SetString(PyExc_TypeError, "window must be a GtkWindow or None"); - return NULL; + return -1; } if (py_buttons != Py_None) @@ -3716,7 +3714,7 @@ _wrap_gtk_dialog_new_with_buttons(PyGObject *self, PyObject *args, PyObject *kwa if (len % 2) { PyErr_SetString(PyExc_RuntimeError, "buttons tuple must contain text/response id pairs"); - return NULL; + return -1; } self->obj = (GObject *) @@ -3726,7 +3724,7 @@ _wrap_gtk_dialog_new_with_buttons(PyGObject *self, PyObject *args, PyObject *kwa if (!self->obj) { PyErr_SetString(PyExc_RuntimeError, "could not create GtkDialog object"); - return NULL; + return -1; } for (i = 0; i < len; i += 2) { @@ -3736,13 +3734,13 @@ _wrap_gtk_dialog_new_with_buttons(PyGObject *self, PyObject *args, PyObject *kwa gtk_object_destroy(GTK_OBJECT(self->obj)); self->obj = NULL; PyErr_SetString(PyExc_RuntimeError, "first member of each text/response id pair must be a string"); - return NULL; + return -1; } if (!PyInt_Check(id)) { gtk_object_destroy(GTK_OBJECT(self->obj)); self->obj = NULL; PyErr_SetString(PyExc_RuntimeError, "second member of each text/response id pair must be a number"); - return NULL; + return -1; } gtk_dialog_add_button(GTK_DIALOG(self->obj), PyString_AsString(text), PyInt_AsLong(id)); @@ -3751,12 +3749,11 @@ _wrap_gtk_dialog_new_with_buttons(PyGObject *self, PyObject *args, PyObject *kwa gtk_object_ref(GTK_OBJECT(self->obj)); gtk_object_sink(GTK_OBJECT(self->obj)); pygobject_register_wrapper((PyObject *)self); - Py_INCREF(Py_None); - return Py_None; + return 0; } %% override gtk_message_dialog_new kwargs -static PyObject * +static int _wrap_gtk_message_dialog_new(PyGObject *self, PyObject *args, PyObject *kwargs) { GtkButtonsType buttons = GTK_BUTTONS_NONE; @@ -3769,32 +3766,31 @@ _wrap_gtk_message_dialog_new(PyGObject *self, PyObject *args, PyObject *kwargs) char *message_format = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOOz:GtkMessageDialog.__init__", kwlist, &py_parent, &py_flags, &py_type, &py_buttons, &message_format)) - return NULL; + return -1; if ((PyObject *)py_parent == Py_None) parent = NULL; else if (py_parent && pygobject_check(py_parent, &PyGtkWindow_Type)) parent = GTK_WINDOW(py_parent->obj); else if (py_parent) { PyErr_SetString(PyExc_TypeError, "parent should be a GtkWindow or None"); - return NULL; + return -1; } if (pyg_enum_get_value(GTK_TYPE_DIALOG_FLAGS, py_flags, (gint *)&flags)) - return NULL; + return -1; if (pyg_enum_get_value(GTK_TYPE_MESSAGE_TYPE, py_type, (gint *)&type)) - return NULL; + return -1; if (pyg_enum_get_value(GTK_TYPE_BUTTONS_TYPE, py_buttons, (gint *)&buttons)) - return NULL; + return -1; self->obj = (GObject *)gtk_message_dialog_new(parent, flags, type, buttons, "%s", message_format); if (!self->obj) { PyErr_SetString(PyExc_RuntimeError, "could not create GtkMessageDialog object"); - return NULL; + return -1; } gtk_object_ref(GTK_OBJECT(self->obj)); gtk_object_sink(GTK_OBJECT(self->obj)); pygobject_register_wrapper((PyObject *)self); - Py_INCREF(Py_None); - return Py_None; + return 0; } %% ignore gtk_progress_bar_new diff --git a/gtk/libglade.override b/gtk/libglade.override index 14bd1752..39442025 100644 --- a/gtk/libglade.override +++ b/gtk/libglade.override @@ -4,9 +4,9 @@ headers #include <pygobject.h> #include <glade/glade.h> -static PyExtensionClass *_PyGObject_Type; +static PyTypeObject *_PyGObject_Type; #define PyGObject_Type (*_PyGObject_Type) -static PyExtensionClass *_PyGtkWidget_Type; +static PyTypeObject *_PyGtkWidget_Type; #define PyGtkWidget_Type (*_PyGtkWidget_Type) %% init @@ -16,7 +16,7 @@ init if ((module = PyImport_ImportModule("gobject")) != NULL) { PyObject *module_dict = PyModule_GetDict(module); - _PyGObject_Type = (PyExtensionClass *) + _PyGObject_Type = (PyTypeObject *) PyDict_GetItemString(module_dict, "GObject"); } else { Py_FatalError("could not import gobject"); @@ -25,7 +25,7 @@ init if ((module = PyImport_ImportModule("gtk._gtk")) != NULL) { PyObject *module_dict = PyModule_GetDict(module); - _PyGtkWidget_Type = (PyExtensionClass *) + _PyGtkWidget_Type = (PyTypeObject *) PyDict_GetItemString(module_dict, "Widget"); } else { Py_FatalError("could not import gtk._gtk"); diff --git a/gtk/libglademodule.c b/gtk/libglademodule.c index 3943c6f1..47679a28 100644 --- a/gtk/libglademodule.c +++ b/gtk/libglademodule.c @@ -8,7 +8,6 @@ void pylibglade_register_classes(PyObject *d); extern PyMethodDef pylibglade_functions[]; -extern PyExtensionClass PyGladeXML_Type; DL_EXPORT(void) initglade(void) diff --git a/gtk/pygtk.h b/gtk/pygtk.h index f46949f0..a0daa650 100644 --- a/gtk/pygtk.h +++ b/gtk/pygtk.h @@ -5,7 +5,6 @@ #define NO_IMPORT_PYGOBJECT #include <pygobject.h> #include <Python.h> -#include <ExtensionClass.h> #include <gtk/gtk.h> struct _PyGtk_FunctionStruct { @@ -78,7 +77,6 @@ struct _PyGtk_FunctionStruct *_PyGtk_API; Py_FatalError("could not import _gtk"); \ return; \ } \ - ExtensionClassImported; \ } #endif diff --git a/gtk/pygtktreemodel.c b/gtk/pygtktreemodel.c index 91dfdc74..92b7dd0f 100644 --- a/gtk/pygtktreemodel.c +++ b/gtk/pygtktreemodel.c @@ -188,7 +188,7 @@ pygtk_tree_model_get_column_type(GtkTreeModel *tree_model, gint index) py_ret = PyObject_CallMethod(self, METHOD_PREFIX "get_column_type", "(i)", index); if (py_ret) { - GType ret = PyInt_AsLong(py_ret); + GType ret = pyg_type_from_object(py_ret); Py_DECREF(py_ret); return ret; diff --git a/pango.override b/pango.override index 5ed77ee4..c3c0636d 100644 --- a/pango.override +++ b/pango.override @@ -5,7 +5,7 @@ headers #include <pygobject.h> #include <pango/pango.h> -static PyExtensionClass *_PyGObject_Type; +static PyTypeObject *_PyGObject_Type; #define PyGObject_Type (*_PyGObject_Type) %% @@ -16,8 +16,8 @@ init if (pygobject != NULL) { PyObject *module_dict = PyModule_GetDict(pygobject); - _PyGObject_Type = (PyExtensionClass *)PyDict_GetItemString(module_dict, - "GObject"); + _PyGObject_Type = (PyTypeObject *)PyDict_GetItemString(module_dict, + "GObject"); } else { Py_FatalError("could not import gobject"); return; @@ -49,7 +49,7 @@ ignore ignore pango_font_description_from_string %% override pango_font_description_new kwargs -static PyObject * +static int _wrap_pango_font_description_new(PyGBoxed *self, PyObject *args, PyObject *kwargs) { @@ -59,7 +59,7 @@ _wrap_pango_font_description_new(PyGBoxed *self, PyObject *args, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|z:PangoFontDescription.__init__", kwlist, &str)) - return NULL; + return -1; self->gtype = PANGO_TYPE_FONT_DESCRIPTION; self->free_on_dealloc = FALSE; @@ -70,9 +70,8 @@ _wrap_pango_font_description_new(PyGBoxed *self, PyObject *args, if (!self->boxed) { PyErr_SetString(PyExc_RuntimeError, "could not create PangoFontDescription object"); - return NULL; + return -1; } self->free_on_dealloc = TRUE; - Py_INCREF(Py_None); - return Py_None; + return 0; } diff --git a/pygobject.h b/pygobject.h index 2b031a13..4be17b9a 100644 --- a/pygobject.h +++ b/pygobject.h @@ -3,7 +3,6 @@ #define _PYGOBJECT_H_ #include <Python.h> -#include <ExtensionClass.h> #include <glib.h> #include <glib-object.h> @@ -13,10 +12,11 @@ typedef struct { GObject *obj; gboolean hasref; /* the GObject owns this reference */ PyObject *inst_dict; /* the instance dictionary -- must be last */ + PyObject *weakreflist; /* list of weak references */ } PyGObject; #define pygobject_get(v) (((PyGObject *)(v))->obj) -#define pygobject_check(v,base) (ExtensionClassSubclassInstance_Check(v,base)) +#define pygobject_check(v,base) (PyObject_TypeCheck(v,base)) typedef struct { PyObject_HEAD @@ -26,13 +26,13 @@ typedef struct { } PyGBoxed; #define pyg_boxed_get(v,t) ((t *)((PyGBoxed *)(v))->boxed) -#define pyg_boxed_check(v,typecode) (ExtensionClassSubclassInstance_Check(v, &PyGBoxed_Type) && ((PyGBoxed *)(v))->gtype == typecode) +#define pyg_boxed_check(v,typecode) (PyObject_TypeCheck(v, &PyGBoxed_Type) && ((PyGBoxed *)(v))->gtype == typecode) struct _PyGObject_Functions { void (* register_class)(PyObject *dict, const gchar *class_name, - GType type, PyExtensionClass *ec, PyObject *bases); + GType gtype, PyTypeObject *type, PyObject *bases); void (* register_wrapper)(PyObject *self); - PyExtensionClass *(* lookup_class)(GType type); + PyTypeObject *(* lookup_class)(GType type); PyObject *(* newgobj)(GObject *obj); GClosure *(* closure_new)(PyObject *callback, PyObject *extra_args, PyObject *swap_data); @@ -49,11 +49,11 @@ struct _PyGObject_Functions { PyObject *(* value_as_pyobject)(const GValue *value); void (* register_interface)(PyObject *dict, const gchar *class_name, - GType type, PyExtensionClass *ec); + GType gtype, PyTypeObject *type); - PyExtensionClass *boxed_type; + PyTypeObject *boxed_type; void (* register_boxed)(PyObject *dict, const gchar *class_name, - GType boxed_type, PyExtensionClass *ec); + GType boxed_type, PyTypeObject *type); PyObject *(* boxed_new)(GType boxed_type, gpointer boxed, gboolean copy_boxed, gboolean own_ref); @@ -105,7 +105,6 @@ struct _PyGObject_Functions *_PyGObject_API; Py_FatalError("could not import gobject"); \ return; \ } \ - ExtensionClassImported; \ } #endif /* !_INSIDE_PYGOBJECT_ */ |