Author: Matti Picus <[email protected]>
Branch: pycheck-macros
Changeset: r92291:a24b838be800
Date: 2017-09-01 14:49 +0300
http://bitbucket.org/pypy/pypy/changeset/a24b838be800/
Log: test, fix for SUBCLASS flags on types
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
@@ -128,6 +128,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))
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", "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/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, 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,
@@ -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)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit