Index: src/zope/proxy/_zope_proxy_proxy.c =================================================================== --- src/zope/proxy/_zope_proxy_proxy.c (revision 103608) +++ src/zope/proxy/_zope_proxy_proxy.c (working copy) @@ -34,6 +34,12 @@ #define Proxy_Check(wrapper) (PyObject_TypeCheck((wrapper), &ProxyType)) +#if PY_MAJOR_VERSION < 3 +#define _ZP_HAVE_CLASS(T) PyType_HasFeature(T, Py_TPFLAGS_HAVE_CLASS) +#else +#define _ZP_HAVE_CLASS(T) 1 +#endif + static PyObject * empty_tuple = NULL; @@ -173,12 +179,17 @@ base = PyTuple_GET_ITEM(mro, i); if (((PyTypeObject *)base) != &ProxyType) { +#if PY_MAJOR_VERSION < 3 if (PyClass_Check(base)) dict = ((PyClassObject *)base)->cl_dict; else { assert(PyType_Check(base)); dict = ((PyTypeObject *)base)->tp_dict; } +#else + assert(PyType_Check(base)); + dict = ((PyTypeObject *)base)->tp_dict; +#endif assert(dict && PyDict_Check(dict)); res = PyDict_GetItem(dict, name); if (res != NULL) @@ -195,9 +206,11 @@ PyObject *wrapped; PyObject *descriptor; PyObject *res = NULL; + PyObject *name_utf8 = NULL; char *name_as_string; int maybe_special_name; +#if PY_MAJOR_VERSION < 3 #ifdef Py_USING_UNICODE /* The Unicode to string conversion is done here because the existing tp_getattro slots expect a string object as name @@ -217,11 +230,29 @@ Py_INCREF(name); name_as_string = PyString_AS_STRING(name); +#else /* Python 3.x */ + if (!PyUnicode_Check(name)) { + PyErr_SetString(PyExc_TypeError, "attribute name must be string"); + return NULL; + } + name_utf8 = PyUnicode_AsUTF8String(name); + if (!name_utf8) + return NULL; + Py_INCREF(name); + name_as_string = PyBytes_AsString(name_utf8); +#endif + wrapped = Proxy_GET_OBJECT(self); if (wrapped == NULL) { + #if PY_MAJOR_VERSION < 3 PyErr_Format(PyExc_RuntimeError, "object is NULL; requested to get attribute '%s'", name_as_string); + #else + PyErr_Format(PyExc_RuntimeError, + "object is NULL; requested to get attribute '%U'", + name); + #endif goto finally; } @@ -232,7 +263,7 @@ descriptor = WrapperType_Lookup(self->ob_type, name); if (descriptor != NULL) { - if (PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS) + if (_ZP_HAVE_CLASS(descriptor->ob_type) && descriptor->ob_type->tp_descr_get != NULL) { if (descriptor->ob_type->tp_descr_set == NULL) @@ -260,6 +291,7 @@ res = PyObject_GetAttr(wrapped, name); finally: + Py_XDECREF(name_utf8); Py_DECREF(name); return res; } @@ -271,6 +303,7 @@ PyObject *descriptor; int res = -1; +#if PY_MAJOR_VERSION < 3 #ifdef Py_USING_UNICODE /* The Unicode to string conversion is done here because the existing tp_setattro slots expect a string object as name @@ -288,10 +321,17 @@ } else Py_INCREF(name); +#else + if (!PyUnicode_Check(name)){ + PyErr_SetString(PyExc_TypeError, "attribute name must be string"); + return -1; + } + Py_INCREF(name); +#endif descriptor = WrapperType_Lookup(self->ob_type, name); if (descriptor != NULL - && PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS) + && _ZP_HAVE_CLASS(descriptor->ob_type) && descriptor->ob_type->tp_descr_set != NULL) { res = descriptor->ob_type->tp_descr_set(descriptor, self, value); @@ -300,9 +340,15 @@ wrapped = Proxy_GET_OBJECT(self); if (wrapped == NULL) { + #if PY_MAJOR_VERSION < 3 PyErr_Format(PyExc_RuntimeError, "object is NULL; requested to set attribute '%s'", PyString_AS_STRING(name)); + #else + PyErr_Format(PyExc_RuntimeError, + "object is NULL; requested to set attribute '%U'", + name); + #endif goto finally; } res = PyObject_SetAttr(wrapped, name, value); @@ -330,11 +376,15 @@ } +#if PY_MAJOR_VERSION < 3 static int wrap_compare(PyObject *wrapper, PyObject *v) { return PyObject_Compare(Proxy_GET_OBJECT(wrapper), v); } +#else +#define wrap_compare 0 +#endif static long wrap_hash(PyObject *self) @@ -372,6 +422,7 @@ return nb->nb_int(self); } +#if PY_MAJOR_VERSION < 3 static PyObject * call_long(PyObject *self) { @@ -383,6 +434,7 @@ } return nb->nb_long(self); } +#endif static PyObject * call_float(PyObject *self) @@ -396,6 +448,7 @@ return nb->nb_float(self); } +#if PY_MAJOR_VERSION < 3 static PyObject * call_oct(PyObject *self) { @@ -419,6 +472,7 @@ } return nb->nb_hex(self); } +#endif static PyObject * call_ipow(PyObject *self, PyObject *other) @@ -508,7 +562,9 @@ BINOP(add, PyNumber_Add) BINOP(sub, PyNumber_Subtract) BINOP(mul, PyNumber_Multiply) +#if PY_MAJOR_VERSION < 3 BINOP(div, PyNumber_Divide) +#endif BINOP(mod, PyNumber_Remainder) BINOP(divmod, PyNumber_Divmod) @@ -543,6 +599,7 @@ BINOP(xor, PyNumber_Xor) BINOP(or, PyNumber_Or) +#if PY_MAJOR_VERSION < 3 static int wrap_coerce(PyObject **p_self, PyObject **p_other) { @@ -581,6 +638,7 @@ *p_other = right; return 0; } +#endif UNOP(neg, PyNumber_Negative) UNOP(pos, PyNumber_Positive) @@ -588,15 +646,21 @@ UNOP(invert, PyNumber_Invert) UNOP(int, call_int) +#if PY_MAJOR_VERSION < 3 UNOP(long, call_long) -UNOP(float, call_float) UNOP(oct, call_oct) UNOP(hex, call_hex) +#else +#define wrap_long 0 +#endif +UNOP(float, call_float) INPLACE(add, PyNumber_InPlaceAdd) INPLACE(sub, PyNumber_InPlaceSubtract) INPLACE(mul, PyNumber_InPlaceMultiply) +#if PY_MAJOR_VERSION < 3 INPLACE(div, PyNumber_InPlaceDivide) +#endif INPLACE(mod, PyNumber_InPlaceRemainder) INPLACE(pow, call_ipow) INPLACE(lshift, PyNumber_InPlaceLshift) @@ -715,7 +779,9 @@ wrap_add, /* nb_add */ wrap_sub, /* nb_subtract */ wrap_mul, /* nb_multiply */ +#if PY_MAJOR_VERSION < 3 wrap_div, /* nb_divide */ +#endif wrap_mod, /* nb_remainder */ wrap_divmod, /* nb_divmod */ wrap_pow, /* nb_power */ @@ -729,19 +795,25 @@ wrap_and, /* nb_and */ wrap_xor, /* nb_xor */ wrap_or, /* nb_or */ +#if PY_MAJOR_VERSION < 3 wrap_coerce, /* nb_coerce */ +#endif wrap_int, /* nb_int */ wrap_long, /* nb_long */ wrap_float, /* nb_float */ +#if PY_MAJOR_VERSION < 3 wrap_oct, /* nb_oct */ wrap_hex, /* nb_hex */ +#endif /* Added in release 2.0 */ /* These require the Py_TPFLAGS_HAVE_INPLACEOPS flag */ wrap_iadd, /* nb_inplace_add */ wrap_isub, /* nb_inplace_subtract */ wrap_imul, /* nb_inplace_multiply */ +#if PY_MAJOR_VERSION < 3 wrap_idiv, /* nb_inplace_divide */ +#endif wrap_imod, /* nb_inplace_remainder */ (ternaryfunc)wrap_ipow, /* nb_inplace_power */ wrap_ilshift, /* nb_inplace_lshift */ @@ -756,6 +828,12 @@ wrap_truediv, /* nb_true_divide */ wrap_ifloordiv, /* nb_inplace_floor_divide */ wrap_itruediv, /* nb_inplace_true_divide */ + +#if PY_VERSION_HEX >= 0x02050000 + /* mvl: TODO? */ + 0, /* nb_index */ +#endif + }; static PySequenceMethods @@ -768,6 +846,9 @@ 0, /* sq_ass_item */ wrap_ass_slice, /* sq_ass_slice */ wrap_contains, /* sq_contains */ + /* mvl: TODO? */ + 0, /* sq_inplace_concat */ + 0, /* sq_inplace_repeat */ }; static PyMappingMethods @@ -792,11 +873,17 @@ * sides the way weakrefs do, since we don't know what semantics will * be associated with the wrapper itself. */ - -statichere PyTypeObject +#ifndef Py_TPFLAGS_CHECKTYPES +#define Py_TPFLAGS_CHECKTYPES 0 +#endif +static PyTypeObject ProxyType = { +#if PY_MAJOR_VERSION < 3 PyObject_HEAD_INIT(NULL) /* PyObject_HEAD_INIT(&PyType_Type) */ 0, +#else + PyVarObject_HEAD_INIT(NULL, 0) +#endif "zope.proxy.ProxyBase", sizeof(ProxyObject), 0, @@ -836,6 +923,13 @@ 0, /* tp_alloc */ wrap_new, /* tp_new */ 0, /*_PyObject_GC_Del,*/ /* tp_free */ + /* mvl: TODO? they are all present in 2.3 */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ + 0, /* tp_del */ }; static PyObject * @@ -1114,31 +1208,67 @@ {NULL} }; -void -init_zope_proxy_proxy(void) +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef _zpp_module = { + PyModuleDef_HEAD_INIT, + "_zope_proxy_proxy", + module___doc__, + -1, + module_functions, + NULL, + NULL, + NULL, + NULL +}; +#endif + +PyObject* +init(void) { +#if PY_MAJOR_VERSION < 3 PyObject *m = Py_InitModule3("_zope_proxy_proxy", module_functions, module___doc__); - +#else + PyObject *m = PyModule_Create(&_zpp_module); +#endif if (m == NULL) - return; + return NULL; if (empty_tuple == NULL) empty_tuple = PyTuple_New(0); ProxyType.tp_free = _PyObject_GC_Del; - if (PyType_Ready(&ProxyType) < 0) - return; + if (PyType_Ready(&ProxyType) < 0) { + Py_DECREF(m); + return NULL; + } Py_INCREF(&ProxyType); PyModule_AddObject(m, "ProxyBase", (PyObject *)&ProxyType); if (api_object == NULL) { api_object = PyCObject_FromVoidPtr(&wrapper_capi, NULL); - if (api_object == NULL) - return; + if (api_object == NULL) { + Py_DECREF(m); + return NULL; + } } Py_INCREF(api_object); PyModule_AddObject(m, "_CAPI", api_object); + return m; } + +#if PY_MAJOR_VERSION < 3 +void +init_zope_proxy_proxy(void) +{ + init(); +} +#else +PyMODINIT_FUNC +PyInit__zope_proxy_proxy(void) +{ + return init(); +} +#endif Index: setup.py =================================================================== --- setup.py (revision 103608) +++ setup.py (working copy) @@ -17,6 +17,7 @@ """ import os from setuptools import setup, Extension +import setuptools; setuptools.run_2to3=True def read(*rnames): return open(os.path.join(os.path.dirname(__file__), *rnames)).read()