Author: Matti Picus <matti.pi...@gmail.com> Branch: Changeset: r92354:2782c2c4ec0b Date: 2017-09-08 17:25 +0300 http://bitbucket.org/pypy/pypy/changeset/2782c2c4ec0b/
Log: merge pycheck-macros, which avoids cpyext for many Py*_Check function calls diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -77,3 +77,7 @@ .. branch: pypy_swappedbytes Added ``_swappedbytes_`` support for ``ctypes.Structure`` + +.. branch: pycheck-macros + +Convert many Py*_Check cpyext functions into macros, like CPython. diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -129,6 +129,11 @@ Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE Py_TPFLAGS_CHECKTYPES Py_MAX_NDIMS PyBUF_FORMAT PyBUF_ND PyBUF_STRIDES PyBUF_WRITABLE """.split() + +for name in ('INT', 'LONG', 'LIST', 'TUPLE', 'UNICODE', 'DICT', 'BASE_EXC', + 'TYPE', 'STRING'): # 'STRING' -> 'BYTES' in py3 + constant_names.append('Py_TPFLAGS_%s_SUBCLASS' % name) + for name in constant_names: setattr(CConfig_constants, name, rffi_platform.ConstantInteger(name)) globals().update(rffi_platform.configure(CConfig_constants)) @@ -749,6 +754,45 @@ return check, check_exact +def build_type_checkers_flags(type_name, cls=None, flagsubstr=None): + """ + Builds two api functions: Py_XxxCheck() and Py_XxxCheckExact() + Does not export the functions, assumes they are macros in the *. files + check will try a fast path via pto flags + """ + if cls is None: + attrname = "w_" + type_name.lower() + def get_w_type(space): + return getattr(space, attrname) + else: + def get_w_type(space): + return getattr(space, cls) + if flagsubstr is None: + tp_flag_str = 'Py_TPFLAGS_%s_SUBCLASS' % type_name.upper() + else: + tp_flag_str = 'Py_TPFLAGS_%s_SUBCLASS' % flagsubstr + check_name = "Py" + type_name + "_Check" + tp_flag = globals()[tp_flag_str] + + @specialize.argtype(1) + def check(space, pto): + from pypy.module.cpyext.pyobject import is_pyobj, as_pyobj + "Implements the Py_Xxx_Check function" + if is_pyobj(pto): + return (pto.c_ob_type.c_tp_flags & tp_flag) == tp_flag + w_obj_type = space.type(pto) + w_type = get_w_type(space) + return (space.is_w(w_obj_type, w_type) or + space.issubtype_w(w_obj_type, w_type)) + + def check_exact(space, w_obj): + "Implements the Py_Xxx_CheckExact function" + w_obj_type = space.type(w_obj) + w_type = get_w_type(space) + return space.is_w(w_obj_type, w_type) + + return check, check_exact + pypy_debug_catch_fatal_exception = rffi.llexternal('pypy_debug_catch_fatal_exception', [], lltype.Void) diff --git a/pypy/module/cpyext/bytesobject.py b/pypy/module/cpyext/bytesobject.py --- a/pypy/module/cpyext/bytesobject.py +++ b/pypy/module/cpyext/bytesobject.py @@ -1,7 +1,7 @@ from pypy.interpreter.error import oefmt from rpython.rtyper.lltypesystem import rffi, lltype from pypy.module.cpyext.api import ( - cpython_api, cpython_struct, bootstrap_function, build_type_checkers, + cpython_api, cpython_struct, bootstrap_function, build_type_checkers_flags, PyVarObjectFields, Py_ssize_t, CONST_STRING, CANNOT_FAIL, slot_function) from pypy.module.cpyext.pyerrors import PyErr_BadArgument from pypy.module.cpyext.pyobject import ( @@ -58,7 +58,7 @@ dealloc=bytes_dealloc, realize=bytes_realize) -PyString_Check, PyString_CheckExact = build_type_checkers("String", "w_bytes") +PyString_Check, PyString_CheckExact = build_type_checkers_flags("String", "w_bytes") def new_empty_str(space, length): """ diff --git a/pypy/module/cpyext/dictobject.py b/pypy/module/cpyext/dictobject.py --- a/pypy/module/cpyext/dictobject.py +++ b/pypy/module/cpyext/dictobject.py @@ -4,7 +4,7 @@ from pypy.objspace.std.classdict import ClassDictStrategy from pypy.interpreter.typedef import GetSetProperty from pypy.module.cpyext.api import ( - cpython_api, CANNOT_FAIL, build_type_checkers, Py_ssize_t, + cpython_api, CANNOT_FAIL, build_type_checkers_flags, Py_ssize_t, Py_ssize_tP, CONST_STRING, PyObjectFields, cpython_struct, bootstrap_function, slot_function) from pypy.module.cpyext.pyobject import (PyObject, PyObjectP, as_pyobj, @@ -66,7 +66,7 @@ def PyDict_New(space): return space.newdict() -PyDict_Check, PyDict_CheckExact = build_type_checkers("Dict") +PyDict_Check, PyDict_CheckExact = build_type_checkers_flags("Dict") @cpython_api([PyObject, PyObject], PyObject, error=CANNOT_FAIL, result_borrowed=True) diff --git a/pypy/module/cpyext/include/dictobject.h b/pypy/module/cpyext/include/dictobject.h --- a/pypy/module/cpyext/include/dictobject.h +++ b/pypy/module/cpyext/include/dictobject.h @@ -12,6 +12,10 @@ PyObject *_tmpkeys; /* a private place to put keys during PyDict_Next */ } PyDictObject; +#define PyDict_Check(op) \ + PyType_FastSubclass((op)->ob_type, Py_TPFLAGS_DICT_SUBCLASS) +#define PyDict_CheckExact(op) ((op)->ob_type == &PyDict_Type) + #ifdef __cplusplus } #endif diff --git a/pypy/module/cpyext/include/intobject.h b/pypy/module/cpyext/include/intobject.h --- a/pypy/module/cpyext/include/intobject.h +++ b/pypy/module/cpyext/include/intobject.h @@ -12,6 +12,10 @@ long ob_ival; } PyIntObject; +#define PyInt_Check(op) \ + PyType_FastSubclass((op)->ob_type, Py_TPFLAGS_INT_SUBCLASS) +#define PyInt_CheckExact(op) ((op)->ob_type == &PyInt_Type) + #ifdef __cplusplus } #endif diff --git a/pypy/module/cpyext/include/listobject.h b/pypy/module/cpyext/include/listobject.h --- a/pypy/module/cpyext/include/listobject.h +++ b/pypy/module/cpyext/include/listobject.h @@ -1,1 +1,4 @@ /* empty */ +#define PyList_Check(op) \ + PyType_FastSubclass((op)->ob_type, Py_TPFLAGS_LIST_SUBCLASS) +#define PyList_CheckExact(op) ((op)->ob_type == &PyList_Type) diff --git a/pypy/module/cpyext/include/longobject.h b/pypy/module/cpyext/include/longobject.h --- a/pypy/module/cpyext/include/longobject.h +++ b/pypy/module/cpyext/include/longobject.h @@ -14,6 +14,9 @@ #define PyOS_strtoul strtoul #define PyOS_strtol strtoul +#define PyLong_Check(op) \ + PyType_FastSubclass((op)->ob_type, Py_TPFLAGS_LONG_SUBCLASS) +#define PyLong_CheckExact(op) ((op)->ob_type == &PyLong_Type) #ifdef __cplusplus } diff --git a/pypy/module/cpyext/include/object.h b/pypy/module/cpyext/include/object.h --- a/pypy/module/cpyext/include/object.h +++ b/pypy/module/cpyext/include/object.h @@ -236,6 +236,11 @@ #define Py_TPFLAGS_DEFAULT Py_TPFLAGS_DEFAULT_EXTERNAL #define PyType_HasFeature(t,f) (((t)->tp_flags & (f)) != 0) +#define PyType_FastSubclass(t,f) PyType_HasFeature(t,f) + +#define PyType_Check(op) \ + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TYPE_SUBCLASS) +#define PyType_CheckExact(op) (Py_TYPE(op) == &PyType_Type) /* objimpl.h ----------------------------------------------*/ #define PyObject_New(type, typeobj) \ diff --git a/pypy/module/cpyext/include/pyerrors.h b/pypy/module/cpyext/include/pyerrors.h --- a/pypy/module/cpyext/include/pyerrors.h +++ b/pypy/module/cpyext/include/pyerrors.h @@ -9,7 +9,7 @@ #define PyExceptionClass_Check(x) \ (PyClass_Check((x)) || (PyType_Check((x)) && \ - PyObject_IsSubclass((x), PyExc_BaseException))) + PyType_FastSubclass((PyTypeObject*)(x), Py_TPFLAGS_BASE_EXC_SUBCLASS))) PyAPI_FUNC(PyObject *) PyErr_NewException(const char *name, PyObject *base, PyObject *dict); PyAPI_FUNC(PyObject *) PyErr_NewExceptionWithDoc(const char *name, const char *doc, PyObject *base, PyObject *dict); diff --git a/pypy/module/cpyext/include/stringobject.h b/pypy/module/cpyext/include/stringobject.h --- a/pypy/module/cpyext/include/stringobject.h +++ b/pypy/module/cpyext/include/stringobject.h @@ -61,6 +61,10 @@ PyAPI_FUNC(PyObject *) PyString_FromFormatV(const char *format, va_list vargs); PyAPI_FUNC(PyObject *) PyString_FromFormat(const char *format, ...); +#define PyString_Check(op) \ + PyType_FastSubclass((op)->ob_type, Py_TPFLAGS_STRING_SUBCLASS) +#define PyString_CheckExact(op) ((op)->ob_type == &PyString_Type) + #ifdef __cplusplus } #endif diff --git a/pypy/module/cpyext/include/tupleobject.h b/pypy/module/cpyext/include/tupleobject.h --- a/pypy/module/cpyext/include/tupleobject.h +++ b/pypy/module/cpyext/include/tupleobject.h @@ -26,6 +26,9 @@ /* Macro, *only* to be used to fill in brand new tuples */ #define PyTuple_SET_ITEM(op, i, v) (((PyTupleObject *)(op))->ob_item[i] = v) +#define PyTuple_Check(op) \ + PyType_FastSubclass((op)->ob_type, Py_TPFLAGS_TUPLE_SUBCLASS) +#define PyTuple_CheckExact(op) ((op)->ob_type == &PyTuple_Type) #ifdef __cplusplus } diff --git a/pypy/module/cpyext/include/unicodeobject.h b/pypy/module/cpyext/include/unicodeobject.h --- a/pypy/module/cpyext/include/unicodeobject.h +++ b/pypy/module/cpyext/include/unicodeobject.h @@ -7,6 +7,10 @@ #include "cpyext_unicodeobject.h" +#define PyUnicode_Check(op) \ + PyType_FastSubclass((op)->ob_type, Py_TPFLAGS_UNICODE_SUBCLASS) +#define PyUnicode_CheckExact(op) ((op)->ob_type == &PyUnicode_Type) + #ifdef __cplusplus } #endif diff --git a/pypy/module/cpyext/intobject.py b/pypy/module/cpyext/intobject.py --- a/pypy/module/cpyext/intobject.py +++ b/pypy/module/cpyext/intobject.py @@ -2,7 +2,7 @@ from rpython.rtyper.lltypesystem import rffi, lltype from pypy.interpreter.error import oefmt from pypy.module.cpyext.api import ( - cpython_api, cpython_struct, build_type_checkers, bootstrap_function, + cpython_api, cpython_struct, build_type_checkers_flags, bootstrap_function, PyObject, PyObjectFields, CONST_STRING, CANNOT_FAIL, Py_ssize_t) from pypy.module.cpyext.pyobject import ( make_typedescr, track_reference, from_ref) @@ -40,7 +40,7 @@ track_reference(space, obj, w_obj) return w_obj -PyInt_Check, PyInt_CheckExact = build_type_checkers("Int") +PyInt_Check, PyInt_CheckExact = build_type_checkers_flags("Int") @cpython_api([], lltype.Signed, error=CANNOT_FAIL) def PyInt_GetMax(space): diff --git a/pypy/module/cpyext/listobject.py b/pypy/module/cpyext/listobject.py --- a/pypy/module/cpyext/listobject.py +++ b/pypy/module/cpyext/listobject.py @@ -2,14 +2,14 @@ from rpython.rlib.objectmodel import always_inline from rpython.rtyper.lltypesystem import rffi, lltype from pypy.module.cpyext.api import (cpython_api, CANNOT_FAIL, Py_ssize_t, - build_type_checkers) + build_type_checkers_flags) from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall from pypy.module.cpyext.pyobject import decref, incref, PyObject, make_ref from pypy.objspace.std.listobject import W_ListObject from pypy.interpreter.error import oefmt -PyList_Check, PyList_CheckExact = build_type_checkers("List") +PyList_Check, PyList_CheckExact = build_type_checkers_flags("List") @cpython_api([Py_ssize_t], PyObject) def PyList_New(space, len): diff --git a/pypy/module/cpyext/longobject.py b/pypy/module/cpyext/longobject.py --- a/pypy/module/cpyext/longobject.py +++ b/pypy/module/cpyext/longobject.py @@ -1,14 +1,13 @@ from rpython.rtyper.lltypesystem import lltype, rffi from pypy.module.cpyext.api import ( - cpython_api, PyObject, build_type_checkers, Py_ssize_t, + cpython_api, PyObject, build_type_checkers_flags, Py_ssize_t, CONST_STRING, ADDR, CANNOT_FAIL) from pypy.objspace.std.longobject import W_LongObject from pypy.interpreter.error import OperationError from pypy.module.cpyext.intobject import PyInt_AsUnsignedLongMask from rpython.rlib.rbigint import rbigint - -PyLong_Check, PyLong_CheckExact = build_type_checkers("Long") +PyLong_Check, PyLong_CheckExact = build_type_checkers_flags("Long") @cpython_api([lltype.Signed], PyObject) def PyLong_FromLong(space, val): diff --git a/pypy/module/cpyext/methodobject.py b/pypy/module/cpyext/methodobject.py --- a/pypy/module/cpyext/methodobject.py +++ b/pypy/module/cpyext/methodobject.py @@ -10,7 +10,7 @@ from pypy.module.cpyext.api import ( CONST_STRING, METH_CLASS, METH_COEXIST, METH_KEYWORDS, METH_NOARGS, METH_O, METH_STATIC, METH_VARARGS, PyObject, bootstrap_function, - build_type_checkers, cpython_api, generic_cpy_call, CANNOT_FAIL, + cpython_api, generic_cpy_call, CANNOT_FAIL, PyTypeObjectPtr, slot_function, cts) from pypy.module.cpyext.pyobject import ( Py_DecRef, from_ref, make_ref, as_pyobj, make_typedescr) diff --git a/pypy/module/cpyext/pytraceback.py b/pypy/module/cpyext/pytraceback.py --- a/pypy/module/cpyext/pytraceback.py +++ b/pypy/module/cpyext/pytraceback.py @@ -1,7 +1,7 @@ from rpython.rtyper.lltypesystem import rffi, lltype from pypy.module.cpyext.api import ( PyObjectFields, generic_cpy_call, CONST_STRING, CANNOT_FAIL, Py_ssize_t, - cpython_api, bootstrap_function, cpython_struct, build_type_checkers, + cpython_api, bootstrap_function, cpython_struct, slot_function) from pypy.module.cpyext.pyobject import ( PyObject, make_ref, from_ref, Py_DecRef, make_typedescr) diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -1072,7 +1072,7 @@ def test_call_tp_dealloc(self): module = self.import_extension('foo', [ - ("fetchFooType", "METH_VARARGS", + ("fetchFooType", "METH_NOARGS", """ PyObject *o; o = PyObject_New(PyObject, &Foo_Type); @@ -1090,7 +1090,7 @@ Py_DECREF(e); return o; """), - ("getCounter", "METH_VARARGS", + ("getCounter", "METH_NOARGS", """ return PyInt_FromLong(foo_counter); """)], prologue=""" @@ -1377,3 +1377,53 @@ # this is equivalent to from collections import Hashable assert not isinstance(obj, Hashable) + + +class AppTestFlags(AppTestCpythonExtensionBase): + def test_has_subclass_flag(self): + module = self.import_extension('foo', [ + ("test_flags", "METH_VARARGS", + ''' + long in_flag, my_flag; + PyObject * obj; + if (!PyArg_ParseTuple(args, "Ol", &obj, &in_flag)) + return NULL; + if (!PyType_Check(obj)) + { + PyErr_SetString(PyExc_ValueError, "input must be type"); + return NULL; + } + my_flag = ((PyTypeObject*)obj)->tp_flags; + if ((my_flag & in_flag) != in_flag) + return PyLong_FromLong(-1); + if (!PyType_CheckExact(obj)) { + if ((my_flag & Py_TPFLAGS_TYPE_SUBCLASS) == Py_TPFLAGS_TYPE_SUBCLASS) + return PyLong_FromLong(-2); + } + return PyLong_FromLong(0); + '''),]) + # copied from object.h + Py_TPFLAGS_INT_SUBCLASS = (1L<<23) # goes away on py3 + Py_TPFLAGS_LONG_SUBCLASS = (1L<<24) + Py_TPFLAGS_LIST_SUBCLASS = (1L<<25) + Py_TPFLAGS_TUPLE_SUBCLASS = (1L<<26) + Py_TPFLAGS_STRING_SUBCLASS = (1L<<27) # rename to BYTES on py3 + Py_TPFLAGS_UNICODE_SUBCLASS = (1L<<28) + Py_TPFLAGS_DICT_SUBCLASS = (1L<<29) + Py_TPFLAGS_BASE_EXC_SUBCLASS = (1L<<30) + Py_TPFLAGS_TYPE_SUBCLASS = (1L<<31) + for t,f in ((long, Py_TPFLAGS_LONG_SUBCLASS), + (int, Py_TPFLAGS_INT_SUBCLASS), + (list, Py_TPFLAGS_LIST_SUBCLASS), + (tuple, Py_TPFLAGS_TUPLE_SUBCLASS), + (str, Py_TPFLAGS_STRING_SUBCLASS), + (unicode, Py_TPFLAGS_UNICODE_SUBCLASS), + (Exception, Py_TPFLAGS_BASE_EXC_SUBCLASS), + (type, Py_TPFLAGS_TYPE_SUBCLASS), + ): + assert module.test_flags(t, f) == 0 + class MyList(list): + pass + assert module.test_flags(MyList, Py_TPFLAGS_LIST_SUBCLASS) == 0 + + diff --git a/pypy/module/cpyext/tupleobject.py b/pypy/module/cpyext/tupleobject.py --- a/pypy/module/cpyext/tupleobject.py +++ b/pypy/module/cpyext/tupleobject.py @@ -2,7 +2,7 @@ from rpython.rtyper.lltypesystem import rffi, lltype from rpython.rlib.debug import fatalerror_notb from pypy.module.cpyext.api import ( - cpython_api, Py_ssize_t, build_type_checkers, + cpython_api, Py_ssize_t, build_type_checkers_flags, PyVarObjectFields, cpython_struct, bootstrap_function, slot_function) from pypy.module.cpyext.pyobject import ( PyObject, PyObjectP, make_ref, from_ref, decref, incref, @@ -42,7 +42,7 @@ dealloc=tuple_dealloc, realize=tuple_realize) -PyTuple_Check, PyTuple_CheckExact = build_type_checkers("Tuple") +PyTuple_Check, PyTuple_CheckExact = build_type_checkers_flags("Tuple") def tuple_check_ref(space, ref): w_type = from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py --- a/pypy/module/cpyext/typeobject.py +++ b/pypy/module/cpyext/typeobject.py @@ -12,12 +12,17 @@ from pypy.module.cpyext import structmemberdefs from pypy.module.cpyext.api import ( cpython_api, cpython_struct, bootstrap_function, Py_ssize_t, Py_ssize_tP, - slot_function, generic_cpy_call, Py_TPFLAGS_READY, Py_TPFLAGS_READYING, - Py_TPFLAGS_HEAPTYPE, METH_VARARGS, METH_KEYWORDS, CANNOT_FAIL, - Py_TPFLAGS_HAVE_GETCHARBUFFER, build_type_checkers, - PyObjectFields, PyTypeObject, PyTypeObjectPtr, - Py_TPFLAGS_HAVE_NEWBUFFER, Py_TPFLAGS_CHECKTYPES, - Py_TPFLAGS_HAVE_INPLACEOPS, cts, parse_dir) + slot_function, generic_cpy_call, METH_VARARGS, METH_KEYWORDS, CANNOT_FAIL, + build_type_checkers_flags, cts, parse_dir, PyObjectFields, PyTypeObject, + PyTypeObjectPtr, Py_TPFLAGS_CHECKTYPES, + Py_TPFLAGS_HEAPTYPE, Py_TPFLAGS_READY, Py_TPFLAGS_READYING, + Py_TPFLAGS_HAVE_GETCHARBUFFER, Py_TPFLAGS_HAVE_INPLACEOPS, + Py_TPFLAGS_HAVE_NEWBUFFER, Py_TPFLAGS_LONG_SUBCLASS, Py_TPFLAGS_LIST_SUBCLASS, + Py_TPFLAGS_TUPLE_SUBCLASS, Py_TPFLAGS_UNICODE_SUBCLASS, + Py_TPFLAGS_DICT_SUBCLASS, Py_TPFLAGS_BASE_EXC_SUBCLASS, + Py_TPFLAGS_TYPE_SUBCLASS, + Py_TPFLAGS_INT_SUBCLASS, Py_TPFLAGS_STRING_SUBCLASS, # change on py3 + ) from pypy.module.cpyext.cparser import parse_source from pypy.module.cpyext.methodobject import (W_PyCClassMethodObject, W_PyCWrapperObject, PyCFunction_NewEx, PyCFunction, PyMethodDef, @@ -39,7 +44,7 @@ #WARN_ABOUT_MISSING_SLOT_FUNCTIONS = False -PyType_Check, PyType_CheckExact = build_type_checkers("Type", "w_type") +PyType_Check, PyType_CheckExact = build_type_checkers_flags("Type") PyHeapTypeObject = cts.gettype('PyHeapTypeObject *') @@ -428,7 +433,7 @@ dict_w["__new__"] = PyCFunction_NewEx(space, get_new_method_def(space), from_ref(space, pyo), None) -def inherit_special(space, pto, base_pto): +def inherit_special(space, pto, w_obj, base_pto): # XXX missing: copy basicsize and flags in a magical way # (minimally, if tp_basicsize is zero or too low, we copy it from the base) if pto.c_tp_basicsize < base_pto.c_tp_basicsize: @@ -438,6 +443,26 @@ pto.c_tp_flags |= base_pto.c_tp_flags & Py_TPFLAGS_CHECKTYPES pto.c_tp_flags |= base_pto.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS + #/* Setup fast subclass flags */ + if space.issubtype_w(w_obj, space.w_Exception): + pto.c_tp_flags |= Py_TPFLAGS_BASE_EXC_SUBCLASS + elif space.issubtype_w(w_obj, space.w_type): + pto.c_tp_flags |= Py_TPFLAGS_TYPE_SUBCLASS + elif space.issubtype_w(w_obj, space.w_int): # remove on py3 + pto.c_tp_flags |= Py_TPFLAGS_INT_SUBCLASS + elif space.issubtype_w(w_obj, space.w_long): + pto.c_tp_flags |= Py_TPFLAGS_LONG_SUBCLASS + elif space.issubtype_w(w_obj, space.w_bytes): + pto.c_tp_flags |= Py_TPFLAGS_STRING_SUBCLASS # STRING->BYTES on py3 + elif space.issubtype_w(w_obj, space.w_unicode): + pto.c_tp_flags |= Py_TPFLAGS_UNICODE_SUBCLASS + elif space.issubtype_w(w_obj, space.w_tuple): + pto.c_tp_flags |= Py_TPFLAGS_TUPLE_SUBCLASS + elif space.issubtype_w(w_obj, space.w_list): + pto.c_tp_flags |= Py_TPFLAGS_LIST_SUBCLASS + elif space.issubtype_w(w_obj, space.w_dict): + pto.c_tp_flags |= Py_TPFLAGS_DICT_SUBCLASS + def check_descr(space, w_self, w_type): if not space.isinstance_w(w_self, w_type): raise DescrMismatch() @@ -939,7 +964,7 @@ pto.c_tp_mro = make_ref(space, space.newtuple(w_obj.mro_w)) base = pto.c_tp_base if base: - inherit_special(space, pto, base) + inherit_special(space, pto, w_obj, base) for w_base in space.fixedview(from_ref(space, pto.c_tp_bases)): if isinstance(w_base, W_TypeObject): inherit_slots(space, pto, w_base) diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py --- a/pypy/module/cpyext/unicodeobject.py +++ b/pypy/module/cpyext/unicodeobject.py @@ -2,7 +2,7 @@ from rpython.rtyper.lltypesystem import rffi, lltype from pypy.module.unicodedata import unicodedb from pypy.module.cpyext.api import ( - CANNOT_FAIL, Py_ssize_t, build_type_checkers, cpython_api, + CANNOT_FAIL, Py_ssize_t, build_type_checkers_flags, cpython_api, bootstrap_function, CONST_STRING, CONST_WSTRING, slot_function, cts, parse_dir) from pypy.module.cpyext.pyerrors import PyErr_BadArgument @@ -36,7 +36,7 @@ default_encoding = lltype.malloc(rffi.CCHARP.TO, DEFAULT_ENCODING_SIZE, flavor='raw', zero=True) -PyUnicode_Check, PyUnicode_CheckExact = build_type_checkers("Unicode", "w_unicode") +PyUnicode_Check, PyUnicode_CheckExact = build_type_checkers_flags("Unicode") def new_empty_unicode(space, length): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit