Author: Armin Rigo <[email protected]>
Branch:
Changeset: r92359:a1608b11c5da
Date: 2017-09-08 17:22 +0200
http://bitbucket.org/pypy/pypy/changeset/a1608b11c5da/
Log: merge heads
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/_csv/interp_csv.py b/pypy/module/_csv/interp_csv.py
--- a/pypy/module/_csv/interp_csv.py
+++ b/pypy/module/_csv/interp_csv.py
@@ -29,10 +29,15 @@
return default
return space.is_true(w_src)
-def _get_int(space, w_src, default):
+def _get_int(space, w_src, default, attrname):
if w_src is None:
return default
- return space.int_w(w_src)
+ try:
+ return space.int_w(w_src)
+ except OperationError as e:
+ if e.match(space, space.w_TypeError):
+ raise oefmt(space.w_TypeError, '"%s" must be a string', attrname)
+ raise
def _get_str(space, w_src, default, attrname):
if w_src is None:
@@ -100,7 +105,7 @@
dialect.escapechar = _get_char(space, w_escapechar, '\0', 'escapechar')
dialect.lineterminator = _get_str(space, w_lineterminator, '\r\n',
'lineterminator')
dialect.quotechar = _get_char(space, w_quotechar, '"', 'quotechar')
- tmp_quoting = _get_int(space, w_quoting, QUOTE_MINIMAL)
+ tmp_quoting = _get_int(space, w_quoting, QUOTE_MINIMAL, 'quoting')
dialect.skipinitialspace = _get_bool(space, w_skipinitialspace, False)
dialect.strict = _get_bool(space, w_strict, False)
diff --git a/pypy/module/_csv/test/test_dialect.py
b/pypy/module/_csv/test/test_dialect.py
--- a/pypy/module/_csv/test/test_dialect.py
+++ b/pypy/module/_csv/test/test_dialect.py
@@ -65,7 +65,8 @@
name = attempt[0]
for value in attempt[1:]:
kwargs = {name: value}
- raises(TypeError, _csv.register_dialect, 'foo1', **kwargs)
+ exc_info = raises(TypeError, _csv.register_dialect, 'foo1',
**kwargs)
+ assert name in exc_info.value.args[0]
exc_info = raises(TypeError, _csv.register_dialect, 'foo1',
lineterminator=4)
assert exc_info.value.args[0] == '"lineterminator" must be a string'
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit