Commit 70be8d1b authored by scoder's avatar scoder Committed by GitHub

Split the current "CYTHON_COMPILING_IN_LIMITED_API" macro guard (GH-3611)

* Split the current "CYTHON_COMPILING_IN_LIMITED_API" macro guard into separate feature guards:
1) using a global module state struct ("CYTHON_USE_MODULE_STATE")
2) using PyType_FromSpec() for extension types ("CYTHON_USE_TYPE_SPECS")
3) actual limited-API special casing ("CYTHON_COMPILING_IN_LIMITED_API")

* Start using PyType_FromModuleAndSpec() for creating extension types since that adds the module reference with PEP-573.

* Do not pass the module reference into *shared* extension types since we do not want to keep the module alive just because other modules still refer to the type.

* Mark the Limited-API and module state struct features as experimental.

* Add CI setups for using PyType_FromSpec() for creating extension types.

* Avoid overly complicated code in __Pyx_FetchCommonTypeFromSpec() when we are not compiling against the Limited-API.

* Correctly set up the bases tuple for PyType_FromSpecWithBases() and stop relying on the PyTypeObject struct being available in several places by using the type pointer instead (and setting it early enough).

* Set the "tp_dealloc" slot from the type spec, also for the limited API case.

* Generally re-enable the "heaptype bases hack" when creating extension types.

* Implement "tp_dictoffset" slot when using type specs in Py3.9+.

* Fix and simplify the vtable setup in the limited API config.

* Make CyFunction inheritable to "correctly" allow FusedFunction subclassing it.

* Enable buffer interface support when using type specs by assigning the "tp_as_buffer" slot explicitly after creating the type.

* Set "vectorcalloffset" when using type specs.

* Make "__bool__" slot prefer Py3+ name instead of Py2 name to make the correct name ("Py_nb_bool") appear in the type spec.

* Validate and fix up all extension types when constructing them from type specs (not only the internal ones).

* Only call PyType_Modified() once after changing a type, not once per change.

* Turn the "no buffer protocol in the limited API" error into a warning since the user code might still work without it.

* Enable the same flags for CyFunction in the static type and type spec case since it's shared across modules and thus, we might otherwise end up with differently configured types in the same runtime.

* The names of Cython's internal types (functions, generator, coroutine, etc.) are now prefixed with the shared module name, instead of making them look like homeless builtins.
See https://bugs.python.org/issue20204
See https://github.com/python/cpython/commit/490055a1673b524da2ebe2312f072aba2a826036

* Work around a CPython bug that makes it overwrite exttype member definitions for the "__module__" attribute.
See https://bugs.python.org/issue40703

* Inherit buffer slots manually since type slots don't support them and thus PyType_Ready() does not see them.

* Add METH_METHOD call support (currently unused).

* Fix the vectorcall offset used in CyFunction type struct in Py3.9, if it inherits from PyCMethodObject instead of PyCFunctionObject.

* Work around the duplicate creation of the "OverrideCheckNode" for fused cpdef functions.
See https://github.com/cython/cython/issues/3628

* Decref the type when deallocating instances of heap types in Py3.8+.
See https://bugs.python.org/issue35810

* Look up the fused dispatch function in the override check, not the specialisation (which shouldn't be overridden all by itself).
Closes https://github.com/cython/cython/issues/3628

* Avoid running the override check for CyFunction, just because it's not a PyCFunction itself.
parent 3aed7ef5
...@@ -68,6 +68,33 @@ jobs: ...@@ -68,6 +68,33 @@ jobs:
backend: "c,cpp" backend: "c,cpp"
env: { LIMITED_API: "--limited-api", EXCLUDE: "--no-file" } env: { LIMITED_API: "--limited-api", EXCLUDE: "--no-file" }
extra_hash: "-limited_api" extra_hash: "-limited_api"
# Type specs
- os: ubuntu-18.04
python-version: 3.9
backend: c
env: { EXTRA_CFLAGS: "-DCYTHON_USE_TYPE_SPECS=1" }
extra_hash: "-typespecs"
- os: ubuntu-18.04
python-version: 3.8
backend: c
env: { EXTRA_CFLAGS: "-DCYTHON_USE_TYPE_SPECS=1" }
extra_hash: "-typespecs"
- os: ubuntu-18.04
python-version: 3.7
backend: c
env: { EXTRA_CFLAGS: "-DCYTHON_USE_TYPE_SPECS=1" }
extra_hash: "-typespecs"
- os: ubuntu-18.04
python-version: 3.6
backend: c
env: { EXTRA_CFLAGS: "-DCYTHON_USE_TYPE_SPECS=1" }
extra_hash: "-typespecs"
- os: ubuntu-18.04
python-version: 3.5
backend: c
env: { EXTRA_CFLAGS: "-DCYTHON_USE_TYPE_SPECS=1" }
extra_hash: "-typespecs"
allowed_failure: true
# Stackless # Stackless
- os: ubuntu-18.04 - os: ubuntu-18.04
python-version: 2.7 python-version: 2.7
......
...@@ -1476,7 +1476,7 @@ class GlobalState(object): ...@@ -1476,7 +1476,7 @@ class GlobalState(object):
for c in self.py_constants] for c in self.py_constants]
consts.sort() consts.sort()
decls_writer = self.parts['decls'] decls_writer = self.parts['decls']
decls_writer.putln("#if !CYTHON_COMPILING_IN_LIMITED_API") decls_writer.putln("#if !CYTHON_USE_MODULE_STATE")
for _, cname, c in consts: for _, cname, c in consts:
self.parts['module_state'].putln("%s;" % c.type.declaration_code(cname)) self.parts['module_state'].putln("%s;" % c.type.declaration_code(cname))
self.parts['module_state_defines'].putln( self.parts['module_state_defines'].putln(
...@@ -1551,16 +1551,16 @@ class GlobalState(object): ...@@ -1551,16 +1551,16 @@ class GlobalState(object):
w = self.parts['pystring_table'] w = self.parts['pystring_table']
w.putln("") w.putln("")
w.putln("static __Pyx_StringTabEntry %s[] = {" % Naming.stringtab_cname) w.putln("static __Pyx_StringTabEntry %s[] = {" % Naming.stringtab_cname)
w.putln("#if CYTHON_COMPILING_IN_LIMITED_API") w.putln("#if CYTHON_USE_MODULE_STATE")
w_limited_writer = w.insertion_point() w_in_module_state = w.insertion_point()
w.putln("#else") w.putln("#else")
w_not_limited_writer = w.insertion_point() w_not_in_module_state = w.insertion_point()
w.putln("#endif") w.putln("#endif")
decls_writer.putln("#if !CYTHON_COMPILING_IN_LIMITED_API") decls_writer.putln("#if !CYTHON_USE_MODULE_STATE")
not_limited_api_decls_writer = decls_writer.insertion_point() not_limited_api_decls_writer = decls_writer.insertion_point()
decls_writer.putln("#endif") decls_writer.putln("#endif")
init_globals.putln("#if CYTHON_COMPILING_IN_LIMITED_API") init_globals.putln("#if CYTHON_USE_MODULE_STATE")
init_globals_limited_api = init_globals.insertion_point() init_globals_in_module_state = init_globals.insertion_point()
init_globals.putln("#endif") init_globals.putln("#endif")
for idx, py_string_args in enumerate(py_strings): for idx, py_string_args in enumerate(py_strings):
c_cname, _, py_string = py_string_args c_cname, _, py_string = py_string_args
...@@ -1583,16 +1583,16 @@ class GlobalState(object): ...@@ -1583,16 +1583,16 @@ class GlobalState(object):
not_limited_api_decls_writer.putln( not_limited_api_decls_writer.putln(
"static PyObject *%s;" % py_string.cname) "static PyObject *%s;" % py_string.cname)
if py_string.py3str_cstring: if py_string.py3str_cstring:
w_not_limited_writer.putln("#if PY_MAJOR_VERSION >= 3") w_not_in_module_state.putln("#if PY_MAJOR_VERSION >= 3")
w_not_limited_writer.putln("{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % ( w_not_in_module_state.putln("{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
py_string.cname, py_string.cname,
py_string.py3str_cstring.cname, py_string.py3str_cstring.cname,
py_string.py3str_cstring.cname, py_string.py3str_cstring.cname,
'0', 1, 0, '0', 1, 0,
py_string.intern py_string.intern
)) ))
w_not_limited_writer.putln("#else") w_not_in_module_state.putln("#else")
w_not_limited_writer.putln("{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % ( w_not_in_module_state.putln("{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
py_string.cname, py_string.cname,
c_cname, c_cname,
c_cname, c_cname,
...@@ -1602,8 +1602,8 @@ class GlobalState(object): ...@@ -1602,8 +1602,8 @@ class GlobalState(object):
py_string.intern py_string.intern
)) ))
if py_string.py3str_cstring: if py_string.py3str_cstring:
w_not_limited_writer.putln("#endif") w_not_in_module_state.putln("#endif")
w_limited_writer.putln("{0, %s, sizeof(%s), %s, %d, %d, %d}," % ( w_in_module_state.putln("{0, %s, sizeof(%s), %s, %d, %d, %d}," % (
c_cname if not py_string.py3str_cstring else py_string.py3str_cstring.cname, c_cname if not py_string.py3str_cstring else py_string.py3str_cstring.cname,
c_cname if not py_string.py3str_cstring else py_string.py3str_cstring.cname, c_cname if not py_string.py3str_cstring else py_string.py3str_cstring.cname,
encoding if not py_string.py3str_cstring else '0', encoding if not py_string.py3str_cstring else '0',
...@@ -1611,7 +1611,7 @@ class GlobalState(object): ...@@ -1611,7 +1611,7 @@ class GlobalState(object):
py_string.is_str, py_string.is_str,
py_string.intern py_string.intern
)) ))
init_globals_limited_api.putln("if (__Pyx_InitString(%s[%d], &%s) < 0) %s;" % ( init_globals_in_module_state.putln("if (__Pyx_InitString(%s[%d], &%s) < 0) %s;" % (
Naming.stringtab_cname, Naming.stringtab_cname,
idx, idx,
py_string.cname, py_string.cname,
...@@ -1619,7 +1619,7 @@ class GlobalState(object): ...@@ -1619,7 +1619,7 @@ class GlobalState(object):
w.putln("{0, 0, 0, 0, 0, 0, 0}") w.putln("{0, 0, 0, 0, 0, 0, 0}")
w.putln("};") w.putln("};")
init_globals.putln("#if !CYTHON_COMPILING_IN_LIMITED_API") init_globals.putln("#if !CYTHON_USE_MODULE_STATE")
init_globals.putln( init_globals.putln(
"if (__Pyx_InitStrings(%s) < 0) %s;" % ( "if (__Pyx_InitStrings(%s) < 0) %s;" % (
Naming.stringtab_cname, Naming.stringtab_cname,
...@@ -1631,7 +1631,7 @@ class GlobalState(object): ...@@ -1631,7 +1631,7 @@ class GlobalState(object):
for c in self.num_const_index.values()] for c in self.num_const_index.values()]
consts.sort() consts.sort()
decls_writer = self.parts['decls'] decls_writer = self.parts['decls']
decls_writer.putln("#if !CYTHON_COMPILING_IN_LIMITED_API") decls_writer.putln("#if !CYTHON_USE_MODULE_STATE")
init_globals = self.parts['init_globals'] init_globals = self.parts['init_globals']
for py_type, _, _, value, value_code, c in consts: for py_type, _, _, value, value_code, c in consts:
cname = c.cname cname = c.cname
......
...@@ -819,7 +819,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -819,7 +819,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.put(Nodes.branch_prediction_macros) code.put(Nodes.branch_prediction_macros)
code.putln('static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; }') code.putln('static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; }')
code.putln('') code.putln('')
code.putln('#if !CYTHON_COMPILING_IN_LIMITED_API') code.putln('#if !CYTHON_USE_MODULE_STATE')
code.putln('static PyObject *%s = NULL;' % env.module_cname) code.putln('static PyObject *%s = NULL;' % env.module_cname)
code.putln('static PyObject *%s;' % env.module_dict_cname) code.putln('static PyObject *%s;' % env.module_dict_cname)
code.putln('static PyObject *%s;' % Naming.builtins_cname) code.putln('static PyObject *%s;' % Naming.builtins_cname)
...@@ -1254,7 +1254,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1254,7 +1254,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
module_state_defines = globalstate['module_state_defines'] module_state_defines = globalstate['module_state_defines']
module_state_clear = globalstate['module_state_clear'] module_state_clear = globalstate['module_state_clear']
module_state_traverse = globalstate['module_state_traverse'] module_state_traverse = globalstate['module_state_traverse']
code.putln("#if !CYTHON_COMPILING_IN_LIMITED_API") code.putln("#if !CYTHON_USE_MODULE_STATE")
for entry in env.c_class_entries: for entry in env.c_class_entries:
if definition or entry.defined_in_pxd: if definition or entry.defined_in_pxd:
code.putln("static PyTypeObject *%s = 0;" % ( code.putln("static PyTypeObject *%s = 0;" % (
...@@ -1391,7 +1391,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1391,7 +1391,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self.generate_property_accessors(scope, code) self.generate_property_accessors(scope, code)
self.generate_method_table(scope, code) self.generate_method_table(scope, code)
self.generate_getset_table(scope, code) self.generate_getset_table(scope, code)
code.putln("#if CYTHON_COMPILING_IN_LIMITED_API") code.putln("#if CYTHON_USE_TYPE_SPECS")
self.generate_typeobj_spec(entry, code) self.generate_typeobj_spec(entry, code)
code.putln("#else") code.putln("#else")
self.generate_typeobj_definition(full_module_name, entry, code) self.generate_typeobj_definition(full_module_name, entry, code)
...@@ -1581,11 +1581,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1581,11 +1581,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
slot_func_cname = scope.mangle_internal("tp_dealloc") slot_func_cname = scope.mangle_internal("tp_dealloc")
code.putln("") code.putln("")
cdealloc_func_entry = scope.lookup_here("__dealloc__")
if cdealloc_func_entry and not cdealloc_func_entry.is_special:
cdealloc_func_entry = None
if cdealloc_func_entry is None:
code.putln("#if !CYTHON_COMPILING_IN_LIMITED_API")
code.putln( code.putln(
"static void %s(PyObject *o) {" % slot_func_cname) "static void %s(PyObject *o) {" % slot_func_cname)
...@@ -1715,8 +1710,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1715,8 +1710,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln( code.putln(
"}") "}")
if cdealloc_func_entry is None:
code.putln("#endif")
def generate_usr_dealloc_call(self, scope, code): def generate_usr_dealloc_call(self, scope, code):
entry = scope.lookup_here("__dealloc__") entry = scope.lookup_here("__dealloc__")
...@@ -2391,6 +2384,16 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -2391,6 +2384,16 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_typeobj_spec(self, entry, code): def generate_typeobj_spec(self, entry, code):
ext_type = entry.type ext_type = entry.type
scope = ext_type.scope scope = ext_type.scope
members_slot = TypeSlots.get_slot_by_name("tp_members")
members_slot.generate_substructure_spec(scope, code)
buffer_slot = TypeSlots.get_slot_by_name("tp_as_buffer")
if not buffer_slot.is_empty(scope):
code.putln("#if !CYTHON_COMPILING_IN_LIMITED_API")
buffer_slot.generate_substructure(scope, code)
code.putln("#endif")
code.putln("static PyType_Slot %s_slots[] = {" % ext_type.typeobj_cname) code.putln("static PyType_Slot %s_slots[] = {" % ext_type.typeobj_cname)
for slot in TypeSlots.slot_table: for slot in TypeSlots.slot_table:
slot.generate_spec(scope, code) slot.generate_spec(scope, code)
...@@ -2582,8 +2585,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -2582,8 +2585,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.exit_cfunc_scope() # done with labels code.exit_cfunc_scope() # done with labels
def generate_module_state_start(self, env, code): def generate_module_state_start(self, env, code):
# TODO: Reactor LIMITED_API struct decl closer to the static decl # TODO: Refactor to move module state struct decl closer to the static decl
code.putln("#if CYTHON_COMPILING_IN_LIMITED_API") code.putln("#if CYTHON_USE_MODULE_STATE")
code.putln('typedef struct {') code.putln('typedef struct {')
code.putln('PyObject *%s;' % env.module_dict_cname) code.putln('PyObject *%s;' % env.module_dict_cname)
code.putln('PyObject *%s;' % Naming.builtins_cname) code.putln('PyObject *%s;' % Naming.builtins_cname)
...@@ -2637,7 +2640,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -2637,7 +2640,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
module_state_traverse.putln("#endif") module_state_traverse.putln("#endif")
def generate_module_state_defines(self, env, code): def generate_module_state_defines(self, env, code):
code.putln("#if CYTHON_COMPILING_IN_LIMITED_API") code.putln("#if CYTHON_USE_MODULE_STATE")
code.putln('#define %s %s->%s' % ( code.putln('#define %s %s->%s' % (
env.module_dict_cname, env.module_dict_cname,
Naming.modulestateglobal_cname, Naming.modulestateglobal_cname,
...@@ -2681,7 +2684,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -2681,7 +2684,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln('#endif') code.putln('#endif')
def generate_module_state_clear(self, env, code): def generate_module_state_clear(self, env, code):
code.putln("#if CYTHON_COMPILING_IN_LIMITED_API") code.putln("#if CYTHON_USE_MODULE_STATE")
code.putln("static int %s_clear(PyObject *m) {" % Naming.module_cname) code.putln("static int %s_clear(PyObject *m) {" % Naming.module_cname)
code.putln("%s *clear_module_state = %s(m);" % ( code.putln("%s *clear_module_state = %s(m);" % (
Naming.modulestate_cname, Naming.modulestate_cname,
...@@ -2709,7 +2712,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -2709,7 +2712,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln('#endif') code.putln('#endif')
def generate_module_state_traverse(self, env, code): def generate_module_state_traverse(self, env, code):
code.putln("#if CYTHON_COMPILING_IN_LIMITED_API") code.putln("#if CYTHON_USE_MODULE_STATE")
code.putln("static int %s_traverse(PyObject *m, visitproc visit, void *arg) {" % Naming.module_cname) code.putln("static int %s_traverse(PyObject *m, visitproc visit, void *arg) {" % Naming.module_cname)
code.putln("%s *traverse_module_state = %s(m);" % ( code.putln("%s *traverse_module_state = %s(m);" % (
Naming.modulestate_cname, Naming.modulestate_cname,
...@@ -2861,7 +2864,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -2861,7 +2864,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
for ext_type in ('CyFunction', 'FusedFunction', 'Coroutine', 'Generator', 'AsyncGen', 'StopAsyncIteration'): for ext_type in ('CyFunction', 'FusedFunction', 'Coroutine', 'Generator', 'AsyncGen', 'StopAsyncIteration'):
code.putln("#ifdef __Pyx_%s_USED" % ext_type) code.putln("#ifdef __Pyx_%s_USED" % ext_type)
code.put_error_if_neg(self.pos, "__pyx_%s_init()" % ext_type) code.put_error_if_neg(self.pos, "__pyx_%s_init(%s)" % (ext_type, env.module_cname))
code.putln("#endif") code.putln("#endif")
code.putln("/*--- Library function declarations ---*/") code.putln("/*--- Library function declarations ---*/")
...@@ -3278,7 +3281,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -3278,7 +3281,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln(" %s, /* m_doc */" % doc) code.putln(" %s, /* m_doc */" % doc)
code.putln("#if CYTHON_PEP489_MULTI_PHASE_INIT") code.putln("#if CYTHON_PEP489_MULTI_PHASE_INIT")
code.putln(" 0, /* m_size */") code.putln(" 0, /* m_size */")
code.putln("#elif CYTHON_COMPILING_IN_LIMITED_API") code.putln("#elif CYTHON_USE_MODULE_STATE") # FIXME: should allow combination with PEP-489
code.putln(" sizeof(%s), /* m_size */" % Naming.modulestate_cname) code.putln(" sizeof(%s), /* m_size */" % Naming.modulestate_cname)
code.putln("#else") code.putln("#else")
code.putln(" -1, /* m_size */") code.putln(" -1, /* m_size */")
...@@ -3289,7 +3292,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -3289,7 +3292,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("#else") code.putln("#else")
code.putln(" NULL, /* m_reload */") code.putln(" NULL, /* m_reload */")
code.putln("#endif") code.putln("#endif")
code.putln("#if CYTHON_COMPILING_IN_LIMITED_API") code.putln("#if CYTHON_USE_MODULE_STATE")
code.putln(" %s_traverse, /* m_traverse */" % Naming.module_cname) code.putln(" %s_traverse, /* m_traverse */" % Naming.module_cname)
code.putln(" %s_clear, /* m_clear */" % Naming.module_cname) code.putln(" %s_clear, /* m_clear */" % Naming.module_cname)
code.putln(" %s /* m_free */" % cleanup_func) code.putln(" %s /* m_free */" % cleanup_func)
......
...@@ -131,7 +131,7 @@ fused_func_prefix = pyrex_prefix + 'fuse_' ...@@ -131,7 +131,7 @@ fused_func_prefix = pyrex_prefix + 'fuse_'
quick_temp_cname = pyrex_prefix + "temp" # temp variable for quick'n'dirty temping quick_temp_cname = pyrex_prefix + "temp" # temp variable for quick'n'dirty temping
tp_dict_version_temp = pyrex_prefix + "tp_dict_version" tp_dict_version_temp = pyrex_prefix + "tp_dict_version"
obj_dict_version_temp = pyrex_prefix + "obj_dict_version" obj_dict_version_temp = pyrex_prefix + "obj_dict_version"
type_dict_guard_temp = pyrex_prefix + "type_dict_guard" type_dict_guard_temp = pyrex_prefix + "typedict_guard"
cython_runtime_cname = pyrex_prefix + "cython_runtime" cython_runtime_cname = pyrex_prefix + "cython_runtime"
cyfunction_type_cname = pyrex_prefix + "CyFunctionType" cyfunction_type_cname = pyrex_prefix + "CyFunctionType"
fusedfunction_type_cname = pyrex_prefix + "FusedFunctionType" fusedfunction_type_cname = pyrex_prefix + "FusedFunctionType"
......
This diff is collapsed.
This diff is collapsed.
...@@ -47,7 +47,7 @@ static __pyx_CoroutineObject *__Pyx_AsyncGen_New( ...@@ -47,7 +47,7 @@ static __pyx_CoroutineObject *__Pyx_AsyncGen_New(
return __Pyx__Coroutine_NewInit((__pyx_CoroutineObject*)gen, body, code, closure, name, qualname, module_name); return __Pyx__Coroutine_NewInit((__pyx_CoroutineObject*)gen, body, code, closure, name, qualname, module_name);
} }
static int __pyx_AsyncGen_init(void); static int __pyx_AsyncGen_init(PyObject *module);
static void __Pyx_PyAsyncGen_Fini(void); static void __Pyx_PyAsyncGen_Fini(void);
//////////////////// AsyncGenerator.cleanup //////////////////// //////////////////// AsyncGenerator.cleanup ////////////////////
...@@ -325,6 +325,10 @@ static PyMemberDef __Pyx_async_gen_memberlist[] = { ...@@ -325,6 +325,10 @@ static PyMemberDef __Pyx_async_gen_memberlist[] = {
//ADDED: "ag_await" //ADDED: "ag_await"
{(char*) "ag_await", T_OBJECT, offsetof(__pyx_CoroutineObject, yieldfrom), READONLY, {(char*) "ag_await", T_OBJECT, offsetof(__pyx_CoroutineObject, yieldfrom), READONLY,
(char*) PyDoc_STR("object being awaited on, or None")}, (char*) PyDoc_STR("object being awaited on, or None")},
{(char *) "__module__", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_modulename), 0, 0},
#if CYTHON_USE_TYPE_SPECS
{(char *) "__weaklistoffset__", T_PYSSIZET, offsetof(__pyx_CoroutineObject, gi_weakreflist), READONLY, 0},
#endif
{0, 0, 0, 0, 0} /* Sentinel */ {0, 0, 0, 0, 0} /* Sentinel */
}; };
...@@ -353,6 +357,31 @@ static PyMethodDef __Pyx_async_gen_methods[] = { ...@@ -353,6 +357,31 @@ static PyMethodDef __Pyx_async_gen_methods[] = {
}; };
#if CYTHON_USE_TYPE_SPECS
static PyType_Slot __pyx_AsyncGenType_slots[] = {
{Py_tp_dealloc, (void *)__Pyx_Coroutine_dealloc},
{Py_am_aiter, (void *)PyObject_SelfIter},
{Py_am_anext, (void *)__Pyx_async_gen_anext},
{Py_tp_repr, (void *)__Pyx_async_gen_repr},
{Py_tp_traverse, (void *)__Pyx_async_gen_traverse},
{Py_tp_methods, (void *)__Pyx_async_gen_methods},
{Py_tp_members, (void *)__Pyx_async_gen_memberlist},
{Py_tp_getset, (void *)__Pyx_async_gen_getsetlist},
#if CYTHON_USE_TP_FINALIZE
{Py_tp_finalize, (void *)__Pyx_Coroutine_del},
#endif
{0, 0},
};
static PyType_Spec __pyx_AsyncGenType_spec = {
__PYX_TYPE_MODULE_PREFIX "async_generator",
sizeof(__pyx_PyAsyncGenObject),
0,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
__pyx_AsyncGenType_slots
};
#else /* CYTHON_USE_TYPE_SPECS */
#if CYTHON_USE_ASYNC_SLOTS #if CYTHON_USE_ASYNC_SLOTS
static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_as_async = { static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_as_async = {
0, /* am_await */ 0, /* am_await */
...@@ -438,6 +467,7 @@ static PyTypeObject __pyx_AsyncGenType_type = { ...@@ -438,6 +467,7 @@ static PyTypeObject __pyx_AsyncGenType_type = {
0, /*tp_pypy_flags*/ 0, /*tp_pypy_flags*/
#endif #endif
}; };
#endif /* CYTHON_USE_TYPE_SPECS */
static int static int
...@@ -449,14 +479,14 @@ __Pyx_PyAsyncGen_ClearFreeLists(void) ...@@ -449,14 +479,14 @@ __Pyx_PyAsyncGen_ClearFreeLists(void)
__pyx__PyAsyncGenWrappedValue *o; __pyx__PyAsyncGenWrappedValue *o;
o = __Pyx_ag_value_freelist[--__Pyx_ag_value_freelist_free]; o = __Pyx_ag_value_freelist[--__Pyx_ag_value_freelist_free];
assert(__pyx__PyAsyncGenWrappedValue_CheckExact(o)); assert(__pyx__PyAsyncGenWrappedValue_CheckExact(o));
PyObject_GC_Del(o); __Pyx_PyHeapTypeObject_GC_Del(o);
} }
while (__Pyx_ag_asend_freelist_free) { while (__Pyx_ag_asend_freelist_free) {
__pyx_PyAsyncGenASend *o; __pyx_PyAsyncGenASend *o;
o = __Pyx_ag_asend_freelist[--__Pyx_ag_asend_freelist_free]; o = __Pyx_ag_asend_freelist[--__Pyx_ag_asend_freelist_free];
assert(__Pyx_IS_TYPE(o, __pyx__PyAsyncGenASendType)); assert(__Pyx_IS_TYPE(o, __pyx__PyAsyncGenASendType));
PyObject_GC_Del(o); __Pyx_PyHeapTypeObject_GC_Del(o);
} }
return ret; return ret;
...@@ -510,7 +540,7 @@ __Pyx_async_gen_asend_dealloc(__pyx_PyAsyncGenASend *o) ...@@ -510,7 +540,7 @@ __Pyx_async_gen_asend_dealloc(__pyx_PyAsyncGenASend *o)
assert(__pyx_PyAsyncGenASend_CheckExact(o)); assert(__pyx_PyAsyncGenASend_CheckExact(o));
__Pyx_ag_asend_freelist[__Pyx_ag_asend_freelist_free++] = o; __Pyx_ag_asend_freelist[__Pyx_ag_asend_freelist_free++] = o;
} else { } else {
PyObject_GC_Del(o); __Pyx_PyHeapTypeObject_GC_Del(o);
} }
} }
...@@ -607,6 +637,26 @@ static PyMethodDef __Pyx_async_gen_asend_methods[] = { ...@@ -607,6 +637,26 @@ static PyMethodDef __Pyx_async_gen_asend_methods[] = {
}; };
#if CYTHON_USE_TYPE_SPECS
static PyType_Slot __pyx__PyAsyncGenASendType_slots[] = {
{Py_tp_dealloc, (void *)__Pyx_async_gen_asend_dealloc},
{Py_am_await, (void *)PyObject_SelfIter},
{Py_tp_traverse, (void *)__Pyx_async_gen_asend_traverse},
{Py_tp_methods, (void *)__Pyx_async_gen_asend_methods},
{Py_tp_iter, (void *)PyObject_SelfIter},
{Py_tp_iternext, (void *)__Pyx_async_gen_asend_iternext},
{0, 0},
};
static PyType_Spec __pyx__PyAsyncGenASendType_spec = {
__PYX_TYPE_MODULE_PREFIX "async_generator_asend",
sizeof(__pyx_PyAsyncGenASend),
0,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
__pyx__PyAsyncGenASendType_slots
};
#else /* CYTHON_USE_TYPE_SPECS */
#if CYTHON_USE_ASYNC_SLOTS #if CYTHON_USE_ASYNC_SLOTS
static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_asend_as_async = { static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_asend_as_async = {
PyObject_SelfIter, /* am_await */ PyObject_SelfIter, /* am_await */
...@@ -615,7 +665,6 @@ static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_asend_as_async = { ...@@ -615,7 +665,6 @@ static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_asend_as_async = {
}; };
#endif #endif
static PyTypeObject __pyx__PyAsyncGenASendType_type = { static PyTypeObject __pyx__PyAsyncGenASendType_type = {
PyVarObject_HEAD_INIT(0, 0) PyVarObject_HEAD_INIT(0, 0)
"async_generator_asend", /* tp_name */ "async_generator_asend", /* tp_name */
...@@ -687,6 +736,7 @@ static PyTypeObject __pyx__PyAsyncGenASendType_type = { ...@@ -687,6 +736,7 @@ static PyTypeObject __pyx__PyAsyncGenASendType_type = {
0, /*tp_pypy_flags*/ 0, /*tp_pypy_flags*/
#endif #endif
}; };
#endif /* CYTHON_USE_TYPE_SPECS */
static PyObject * static PyObject *
...@@ -729,7 +779,7 @@ __Pyx_async_gen_wrapped_val_dealloc(__pyx__PyAsyncGenWrappedValue *o) ...@@ -729,7 +779,7 @@ __Pyx_async_gen_wrapped_val_dealloc(__pyx__PyAsyncGenWrappedValue *o)
assert(__pyx__PyAsyncGenWrappedValue_CheckExact(o)); assert(__pyx__PyAsyncGenWrappedValue_CheckExact(o));
__Pyx_ag_value_freelist[__Pyx_ag_value_freelist_free++] = o; __Pyx_ag_value_freelist[__Pyx_ag_value_freelist_free++] = o;
} else { } else {
PyObject_GC_Del(o); __Pyx_PyHeapTypeObject_GC_Del(o);
} }
} }
...@@ -743,6 +793,22 @@ __Pyx_async_gen_wrapped_val_traverse(__pyx__PyAsyncGenWrappedValue *o, ...@@ -743,6 +793,22 @@ __Pyx_async_gen_wrapped_val_traverse(__pyx__PyAsyncGenWrappedValue *o,
} }
#if CYTHON_USE_TYPE_SPECS
static PyType_Slot __pyx__PyAsyncGenWrappedValueType_slots[] = {
{Py_tp_dealloc, (void *)__Pyx_async_gen_wrapped_val_dealloc},
{Py_tp_traverse, (void *)__Pyx_async_gen_wrapped_val_traverse},
{0, 0},
};
static PyType_Spec __pyx__PyAsyncGenWrappedValueType_spec = {
__PYX_TYPE_MODULE_PREFIX "async_generator_wrapped_value",
sizeof(__pyx__PyAsyncGenWrappedValue),
0,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
__pyx__PyAsyncGenWrappedValueType_slots
};
#else /* CYTHON_USE_TYPE_SPECS */
static PyTypeObject __pyx__PyAsyncGenWrappedValueType_type = { static PyTypeObject __pyx__PyAsyncGenWrappedValueType_type = {
PyVarObject_HEAD_INIT(0, 0) PyVarObject_HEAD_INIT(0, 0)
"async_generator_wrapped_value", /* tp_name */ "async_generator_wrapped_value", /* tp_name */
...@@ -805,6 +871,7 @@ static PyTypeObject __pyx__PyAsyncGenWrappedValueType_type = { ...@@ -805,6 +871,7 @@ static PyTypeObject __pyx__PyAsyncGenWrappedValueType_type = {
0, /*tp_pypy_flags*/ 0, /*tp_pypy_flags*/
#endif #endif
}; };
#endif /* CYTHON_USE_TYPE_SPECS */
static PyObject * static PyObject *
...@@ -842,7 +909,7 @@ __Pyx_async_gen_athrow_dealloc(__pyx_PyAsyncGenAThrow *o) ...@@ -842,7 +909,7 @@ __Pyx_async_gen_athrow_dealloc(__pyx_PyAsyncGenAThrow *o)
PyObject_GC_UnTrack((PyObject *)o); PyObject_GC_UnTrack((PyObject *)o);
Py_CLEAR(o->agt_gen); Py_CLEAR(o->agt_gen);
Py_CLEAR(o->agt_args); Py_CLEAR(o->agt_args);
PyObject_GC_Del(o); __Pyx_PyHeapTypeObject_GC_Del(o);
} }
...@@ -1043,6 +1110,27 @@ static PyMethodDef __Pyx_async_gen_athrow_methods[] = { ...@@ -1043,6 +1110,27 @@ static PyMethodDef __Pyx_async_gen_athrow_methods[] = {
}; };
#if CYTHON_USE_TYPE_SPECS
static PyType_Slot __pyx__PyAsyncGenAThrowType_slots[] = {
{Py_tp_dealloc, (void *)__Pyx_async_gen_athrow_dealloc},
{Py_am_await, (void *)PyObject_SelfIter},
{Py_tp_traverse, (void *)__Pyx_async_gen_athrow_traverse},
{Py_tp_iter, (void *)PyObject_SelfIter},
{Py_tp_iternext, (void *)__Pyx_async_gen_athrow_iternext},
{Py_tp_methods, (void *)__Pyx_async_gen_athrow_methods},
{Py_tp_getattro, (void *)__Pyx_PyObject_GenericGetAttrNoDict},
{0, 0},
};
static PyType_Spec __pyx__PyAsyncGenAThrowType_spec = {
__PYX_TYPE_MODULE_PREFIX "async_generator_athrow",
sizeof(__pyx_PyAsyncGenAThrow),
0,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
__pyx__PyAsyncGenAThrowType_slots
};
#else /* CYTHON_USE_TYPE_SPECS */
#if CYTHON_USE_ASYNC_SLOTS #if CYTHON_USE_ASYNC_SLOTS
static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_athrow_as_async = { static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_athrow_as_async = {
PyObject_SelfIter, /* am_await */ PyObject_SelfIter, /* am_await */
...@@ -1051,7 +1139,6 @@ static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_athrow_as_async = { ...@@ -1051,7 +1139,6 @@ static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_athrow_as_async = {
}; };
#endif #endif
static PyTypeObject __pyx__PyAsyncGenAThrowType_type = { static PyTypeObject __pyx__PyAsyncGenAThrowType_type = {
PyVarObject_HEAD_INIT(0, 0) PyVarObject_HEAD_INIT(0, 0)
"async_generator_athrow", /* tp_name */ "async_generator_athrow", /* tp_name */
...@@ -1122,6 +1209,7 @@ static PyTypeObject __pyx__PyAsyncGenAThrowType_type = { ...@@ -1122,6 +1209,7 @@ static PyTypeObject __pyx__PyAsyncGenAThrowType_type = {
0, /*tp_pypy_flags*/ 0, /*tp_pypy_flags*/
#endif #endif
}; };
#endif /* CYTHON_USE_TYPE_SPECS */
static PyObject * static PyObject *
...@@ -1144,26 +1232,42 @@ __Pyx_async_gen_athrow_new(__pyx_PyAsyncGenObject *gen, PyObject *args) ...@@ -1144,26 +1232,42 @@ __Pyx_async_gen_athrow_new(__pyx_PyAsyncGenObject *gen, PyObject *args)
/* ---------- global type sharing ------------ */ /* ---------- global type sharing ------------ */
static int __pyx_AsyncGen_init(void) { static int __pyx_AsyncGen_init(PyObject *module) {
#if CYTHON_USE_TYPE_SPECS
__pyx_AsyncGenType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_AsyncGenType_spec, NULL);
#else
(void) module;
// on Windows, C-API functions can't be used in slots statically // on Windows, C-API functions can't be used in slots statically
__pyx_AsyncGenType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict; __pyx_AsyncGenType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict;
__pyx__PyAsyncGenWrappedValueType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict;
__pyx__PyAsyncGenAThrowType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict;
__pyx__PyAsyncGenASendType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict;
__pyx_AsyncGenType = __Pyx_FetchCommonType(&__pyx_AsyncGenType_type); __pyx_AsyncGenType = __Pyx_FetchCommonType(&__pyx_AsyncGenType_type);
#endif
if (unlikely(!__pyx_AsyncGenType)) if (unlikely(!__pyx_AsyncGenType))
return -1; return -1;
#if CYTHON_USE_TYPE_SPECS
__pyx__PyAsyncGenAThrowType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx__PyAsyncGenAThrowType_spec, NULL);
#else
__pyx__PyAsyncGenAThrowType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict;
__pyx__PyAsyncGenAThrowType = __Pyx_FetchCommonType(&__pyx__PyAsyncGenAThrowType_type); __pyx__PyAsyncGenAThrowType = __Pyx_FetchCommonType(&__pyx__PyAsyncGenAThrowType_type);
#endif
if (unlikely(!__pyx__PyAsyncGenAThrowType)) if (unlikely(!__pyx__PyAsyncGenAThrowType))
return -1; return -1;
#if CYTHON_USE_TYPE_SPECS
__pyx__PyAsyncGenWrappedValueType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx__PyAsyncGenWrappedValueType_spec, NULL);
#else
__pyx__PyAsyncGenWrappedValueType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict;
__pyx__PyAsyncGenWrappedValueType = __Pyx_FetchCommonType(&__pyx__PyAsyncGenWrappedValueType_type); __pyx__PyAsyncGenWrappedValueType = __Pyx_FetchCommonType(&__pyx__PyAsyncGenWrappedValueType_type);
#endif
if (unlikely(!__pyx__PyAsyncGenWrappedValueType)) if (unlikely(!__pyx__PyAsyncGenWrappedValueType))
return -1; return -1;
#if CYTHON_USE_TYPE_SPECS
__pyx__PyAsyncGenASendType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx__PyAsyncGenASendType_spec, NULL);
#else
__pyx__PyAsyncGenASendType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict;
__pyx__PyAsyncGenASendType = __Pyx_FetchCommonType(&__pyx__PyAsyncGenASendType_type); __pyx__PyAsyncGenASendType = __Pyx_FetchCommonType(&__pyx__PyAsyncGenASendType_type);
#endif
if (unlikely(!__pyx__PyAsyncGenASendType)) if (unlikely(!__pyx__PyAsyncGenASendType))
return -1; return -1;
......
/////////////// FetchCommonType.proto /////////////// /////////////// FetchCommonType.proto ///////////////
#if !CYTHON_USE_TYPE_SPECS
static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type); static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type);
#if CYTHON_COMPILING_IN_LIMITED_API #else
static PyTypeObject* __Pyx_FetchCommonTypeFromSpec(PyType_Spec *spec, PyObject *bases); static PyTypeObject* __Pyx_FetchCommonTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases);
#endif #endif
/////////////// FetchCommonType /////////////// /////////////// FetchCommonType ///////////////
//@requires:ExtensionTypes.c::FixUpExtensionType
static PyObject *__Pyx_FetchSharedCythonABIModule(void) { static PyObject *__Pyx_FetchSharedCythonABIModule(void) {
PyObject *abi_module = PyImport_AddModule((char*) __PYX_ABI_MODULE_NAME); PyObject *abi_module = PyImport_AddModule((char*) __PYX_ABI_MODULE_NAME);
...@@ -32,6 +34,7 @@ static int __Pyx_VerifyCachedType(PyObject *cached_type, ...@@ -32,6 +34,7 @@ static int __Pyx_VerifyCachedType(PyObject *cached_type,
return 0; return 0;
} }
#if !CYTHON_USE_TYPE_SPECS
static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type) { static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type) {
PyObject* abi_module; PyObject* abi_module;
PyTypeObject *cached_type = NULL; PyTypeObject *cached_type = NULL;
...@@ -68,22 +71,28 @@ bad: ...@@ -68,22 +71,28 @@ bad:
cached_type = NULL; cached_type = NULL;
goto done; goto done;
} }
#else
#if CYTHON_COMPILING_IN_LIMITED_API static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) {
static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyType_Spec *spec, PyObject *bases) { PyObject *abi_module, *cached_type = NULL;
PyObject *abi_module, *py_basicsize, *cached_type = NULL;
Py_ssize_t basicsize;
abi_module = __Pyx_FetchSharedCythonABIModule(); abi_module = __Pyx_FetchSharedCythonABIModule();
if (!abi_module) return NULL; if (!abi_module) return NULL;
cached_type = PyObject_GetAttrString(abi_module, spec->name); cached_type = PyObject_GetAttrString(abi_module, spec->name);
if (cached_type) { if (cached_type) {
Py_ssize_t basicsize;
#if CYTHON_COMPILING_IN_LIMITED_API
PyObject *py_basicsize;
py_basicsize = PyObject_GetAttrString(cached_type, "__basicsize__"); py_basicsize = PyObject_GetAttrString(cached_type, "__basicsize__");
if (!py_basicsize) goto bad; if (unlikely(!py_basicsize)) goto bad;
basicsize = PyLong_AsSsize_t(py_basicsize); basicsize = PyLong_AsSsize_t(py_basicsize);
Py_DECREF(py_basicsize); Py_DECREF(py_basicsize);
py_basicsize = 0; py_basicsize = 0;
if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) goto bad; if (unlikely(basicsize == (Py_ssize_t)-1) && PyErr_Occurred()) goto bad;
#else
basicsize = likely(PyType_Check(cached_type)) ? ((PyTypeObject*) cached_type)->tp_basicsize : -1;
#endif
if (__Pyx_VerifyCachedType( if (__Pyx_VerifyCachedType(
cached_type, cached_type,
spec->name, spec->name,
...@@ -96,8 +105,11 @@ static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyType_Spec *spec, PyObject * ...@@ -96,8 +105,11 @@ static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyType_Spec *spec, PyObject *
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad; if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad;
PyErr_Clear(); PyErr_Clear();
cached_type = PyType_FromSpecWithBases(spec, bases); // We pass the ABI module reference to avoid keeping the user module alive by foreign type usages.
(void) module;
cached_type = __Pyx_PyType_FromModuleAndSpec(abi_module, spec, bases);
if (unlikely(!cached_type)) goto bad; if (unlikely(!cached_type)) goto bad;
if (unlikely(__Pyx_fix_up_extension_type_from_spec(spec, (PyTypeObject *) cached_type) < 0)) goto bad;
if (PyObject_SetAttrString(abi_module, spec->name, cached_type) < 0) goto bad; if (PyObject_SetAttrString(abi_module, spec->name, cached_type) < 0) goto bad;
done: done:
......
This diff is collapsed.
This diff is collapsed.
/////////////// PyType_Ready.proto /////////////// /////////////// FixUpExtensionType.proto ///////////////
// FIXME: is this really suitable for CYTHON_COMPILING_IN_LIMITED_API? #if CYTHON_USE_TYPE_SPECS
#if CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_LIMITED_API static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject *type); /*proto*/
static int __Pyx_PyType_Ready(PyTypeObject *t);/*proto*/ #endif
/////////////// FixUpExtensionType ///////////////
//@requires:ModuleSetupCode.c::IncludeStructmemberH
//@requires:StringTools.c::IncludeStringH
#if CYTHON_USE_TYPE_SPECS
static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject *type) {
#if PY_VERSION_HEX > 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API
(void) spec;
(void) type;
#else
// Set tp_weakreflist, tp_dictoffset, tp_vectorcalloffset
// Copied and adapted from https://bugs.python.org/issue38140
const PyType_Slot *slot = spec->slots;
while (slot && slot->slot && slot->slot != Py_tp_members)
slot++;
if (slot && slot->slot == Py_tp_members) {
int changed = 0;
#if !(PY_VERSION_HEX <= 0x030900b1 && CYTHON_COMPILING_IN_CPYTHON)
const
#endif
PyMemberDef *memb = (PyMemberDef*) slot->pfunc;
while (memb && memb->name) {
if (memb->name[0] == '_' && memb->name[1] == '_') {
#if PY_VERSION_HEX < 0x030900b1
if (strcmp(memb->name, "__weaklistoffset__") == 0) {
// The PyMemberDef must be a Py_ssize_t and readonly.
assert(memb->type == T_PYSSIZET);
assert(memb->flags == READONLY);
type->tp_weaklistoffset = memb->offset;
// FIXME: is it even worth calling PyType_Modified() here?
changed = 1;
}
else if (strcmp(memb->name, "__dictoffset__") == 0) {
// The PyMemberDef must be a Py_ssize_t and readonly.
assert(memb->type == T_PYSSIZET);
assert(memb->flags == READONLY);
type->tp_dictoffset = memb->offset;
// FIXME: is it even worth calling PyType_Modified() here?
changed = 1;
}
#if CYTHON_METH_FASTCALL
else if (strcmp(memb->name, "__vectorcalloffset__") == 0) {
// The PyMemberDef must be a Py_ssize_t and readonly.
assert(memb->type == T_PYSSIZET);
assert(memb->flags == READONLY);
#if PY_VERSION_HEX >= 0x030800b4
type->tp_vectorcall_offset = memb->offset;
#else #else
#define __Pyx_PyType_Ready(t) PyType_Ready(t) type->tp_print = (printfunc) memb->offset;
#endif
// FIXME: is it even worth calling PyType_Modified() here?
changed = 1;
}
#endif
#else
if ((0));
#endif
#if PY_VERSION_HEX <= 0x030900b1 && CYTHON_COMPILING_IN_CPYTHON
else if (strcmp(memb->name, "__module__") == 0) {
// PyType_FromSpec() in CPython <= 3.9b1 overwrites this field with a constant string.
// See https://bugs.python.org/issue40703
PyObject *descr;
// The PyMemberDef must be an object and normally readable, possibly writable.
assert(memb->type == T_OBJECT);
assert(memb->flags == 0 || memb->flags == READONLY);
descr = PyDescr_NewMember(type, memb);
if (unlikely(!descr))
return -1;
if (unlikely(PyDict_SetItem(type->tp_dict, PyDescr_NAME(descr), descr) < 0)) {
Py_DECREF(descr);
return -1;
}
Py_DECREF(descr);
changed = 1;
}
#endif
}
memb++;
}
if (changed)
PyType_Modified(type);
}
#endif
return 0;
}
#endif #endif
/////////////// PyType_Ready ///////////////
//@requires: ObjectHandling.c::PyObjectCallMethod0
#if CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_LIMITED_API /////////////// ValidateBasesTuple.proto ///////////////
// Wrapper around PyType_Ready() with some runtime checks and fixes
// to deal with multiple inheritance. #if CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_LIMITED_API || CYTHON_USE_TYPE_SPECS
static int __Pyx_PyType_Ready(PyTypeObject *t) { static int __Pyx_validate_bases_tuple(const char *type_name, Py_ssize_t dictoffset, PyObject *bases); /*proto*/
#endif
/////////////// ValidateBasesTuple ///////////////
#if CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_LIMITED_API || CYTHON_USE_TYPE_SPECS
static int __Pyx_validate_bases_tuple(const char *type_name, Py_ssize_t dictoffset, PyObject *bases) {
// Loop over all bases (except the first) and check that those // Loop over all bases (except the first) and check that those
// really are heap types. Otherwise, it would not be safe to // really are heap types. Otherwise, it would not be safe to
// subclass them. // subclass them.
...@@ -24,49 +112,73 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) { ...@@ -24,49 +112,73 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) {
// tp_dictoffset (i.e. there is no __dict__ attribute in the object // tp_dictoffset (i.e. there is no __dict__ attribute in the object
// structure), we need to check that none of the base classes sets // structure), we need to check that none of the base classes sets
// it either. // it either.
int r; Py_ssize_t i, n = PyTuple_GET_SIZE(bases);
PyObject *bases = t->tp_bases; for (i = 1; i < n; i++) /* Skip first base */
if (bases)
{ {
Py_ssize_t i, n = PyTuple_GET_SIZE(bases); PyObject *b0 = PyTuple_GET_ITEM(bases, i);
for (i = 1; i < n; i++) /* Skip first base */ PyTypeObject *b;
{
PyObject *b0 = PyTuple_GET_ITEM(bases, i);
PyTypeObject *b;
#if PY_MAJOR_VERSION < 3 #if PY_MAJOR_VERSION < 3
/* Disallow old-style classes */ /* Disallow old-style classes */
if (PyClass_Check(b0)) if (PyClass_Check(b0))
{ {
PyErr_Format(PyExc_TypeError, "base class '%.200s' is an old-style class", PyErr_Format(PyExc_TypeError, "base class '%.200s' is an old-style class",
PyString_AS_STRING(((PyClassObject*)b0)->cl_name)); PyString_AS_STRING(((PyClassObject*)b0)->cl_name));
return -1; return -1;
} }
#endif #endif
b = (PyTypeObject*)b0; b = (PyTypeObject*) b0;
if (!__Pyx_PyType_HasFeature(b, Py_TPFLAGS_HEAPTYPE)) if (!__Pyx_PyType_HasFeature(b, Py_TPFLAGS_HEAPTYPE))
{ {
__Pyx_TypeName b_name = __Pyx_PyType_GetName(b); __Pyx_TypeName b_name = __Pyx_PyType_GetName(b);
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"base class '" __Pyx_FMT_TYPENAME "' is not a heap type", b_name); "base class '" __Pyx_FMT_TYPENAME "' is not a heap type", b_name);
__Pyx_DECREF_TypeName(b_name); __Pyx_DECREF_TypeName(b_name);
return -1; return -1;
} }
if (t->tp_dictoffset == 0 && b->tp_dictoffset) if (dictoffset == 0 && b->tp_dictoffset)
{ {
__Pyx_TypeName t_name = __Pyx_PyType_GetName(t); __Pyx_TypeName b_name = __Pyx_PyType_GetName(b);
__Pyx_TypeName b_name = __Pyx_PyType_GetName(b); PyErr_Format(PyExc_TypeError,
PyErr_Format(PyExc_TypeError, "extension type '%.200s' has no __dict__ slot, "
"extension type '" __Pyx_FMT_TYPENAME "' has no __dict__ slot, " "but base type '" __Pyx_FMT_TYPENAME "' has: "
"but base type '" __Pyx_FMT_TYPENAME "' has: " "either add 'cdef dict __dict__' to the extension type "
"either add 'cdef dict __dict__' to the extension type " "or add '__slots__ = [...]' to the base type",
"or add '__slots__ = [...]' to the base type", type_name, b_name);
t_name, b_name); __Pyx_DECREF_TypeName(b_name);
__Pyx_DECREF_TypeName(t_name); return -1;
__Pyx_DECREF_TypeName(b_name);
return -1;
}
} }
} }
return 0;
}
#endif
/////////////// PyType_Ready.proto ///////////////
static int __Pyx_PyType_Ready(PyTypeObject *t);/*proto*/
/////////////// PyType_Ready ///////////////
//@requires: ObjectHandling.c::PyObjectCallMethod0
//@requires: ValidateBasesTuple
// Wrapper around PyType_Ready() with some runtime checks and fixes
// to deal with multiple inheritance.
static int __Pyx_PyType_Ready(PyTypeObject *t) {
// FIXME: is this really suitable for CYTHON_COMPILING_IN_LIMITED_API?
#if CYTHON_USE_TYPE_SPECS || !(CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_LIMITED_API)
// avoid C warning about unused helper function
(void)__Pyx_PyObject_CallMethod0;
#if CYTHON_USE_TYPE_SPECS
(void)__Pyx_validate_bases_tuple;
#endif
return PyType_Ready(t);
#else
int r;
if (t->tp_bases && unlikely(__Pyx_validate_bases_tuple(t->tp_name, t->tp_dictoffset, t->tp_bases) == -1))
return -1;
#if PY_VERSION_HEX >= 0x03050000 #if PY_VERSION_HEX >= 0x03050000
{ {
...@@ -152,8 +264,9 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) { ...@@ -152,8 +264,9 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) {
#endif #endif
return r; return r;
}
#endif #endif
}
/////////////// PyTrashcan.proto /////////////// /////////////// PyTrashcan.proto ///////////////
......
...@@ -694,22 +694,18 @@ bad: ...@@ -694,22 +694,18 @@ bad:
/////////////// SetVTable.proto /////////////// /////////////// SetVTable.proto ///////////////
static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/ static int __Pyx_SetVtable(PyTypeObject* typeptr , void* vtable); /*proto*/
/////////////// SetVTable /////////////// /////////////// SetVTable ///////////////
#if CYTHON_COMPILING_IN_LIMITED_API static int __Pyx_SetVtable(PyTypeObject *type, void *vtable) {
static int __Pyx_SetVtable(PyObject *type, void *vtable) {
#else
static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
#endif
PyObject *ob = PyCapsule_New(vtable, 0, 0); PyObject *ob = PyCapsule_New(vtable, 0, 0);
if (!ob) if (unlikely(!ob))
goto bad; goto bad;
#if CYTHON_COMPILING_IN_LIMITED_API #if CYTHON_COMPILING_IN_LIMITED_API
if (PyObject_SetAttr(type, PYIDENT("__pyx_vtable__"), ob) < 0) if (unlikely(PyObject_SetAttr((PyObject *) type, PYIDENT("__pyx_vtable__"), ob) < 0))
#else #else
if (PyDict_SetItem(dict, PYIDENT("__pyx_vtable__"), ob) < 0) if (unlikely(PyDict_SetItem(type->tp_dict, PYIDENT("__pyx_vtable__"), ob) < 0))
#endif #endif
goto bad; goto bad;
Py_DECREF(ob); Py_DECREF(ob);
......
...@@ -61,6 +61,8 @@ ...@@ -61,6 +61,8 @@
#undef CYTHON_USE_TYPE_SLOTS #undef CYTHON_USE_TYPE_SLOTS
#define CYTHON_USE_TYPE_SLOTS 0 #define CYTHON_USE_TYPE_SLOTS 0
#undef CYTHON_USE_TYPE_SPECS
#define CYTHON_USE_TYPE_SPECS 0
#undef CYTHON_USE_PYTYPE_LOOKUP #undef CYTHON_USE_PYTYPE_LOOKUP
#define CYTHON_USE_PYTYPE_LOOKUP 0 #define CYTHON_USE_PYTYPE_LOOKUP 0
#if PY_VERSION_HEX < 0x03050000 #if PY_VERSION_HEX < 0x03050000
...@@ -96,6 +98,8 @@ ...@@ -96,6 +98,8 @@
#endif #endif
#undef CYTHON_PEP489_MULTI_PHASE_INIT #undef CYTHON_PEP489_MULTI_PHASE_INIT
#define CYTHON_PEP489_MULTI_PHASE_INIT 0 #define CYTHON_PEP489_MULTI_PHASE_INIT 0
#undef CYTHON_USE_MODULE_STATE
#define CYTHON_USE_MODULE_STATE 0
#undef CYTHON_USE_TP_FINALIZE #undef CYTHON_USE_TP_FINALIZE
#define CYTHON_USE_TP_FINALIZE 0 #define CYTHON_USE_TP_FINALIZE 0
#undef CYTHON_USE_DICT_VERSIONS #undef CYTHON_USE_DICT_VERSIONS
...@@ -112,6 +116,8 @@ ...@@ -112,6 +116,8 @@
#ifndef CYTHON_USE_TYPE_SLOTS #ifndef CYTHON_USE_TYPE_SLOTS
#define CYTHON_USE_TYPE_SLOTS 1 #define CYTHON_USE_TYPE_SLOTS 1
#endif #endif
#undef CYTHON_USE_TYPE_SPECS
#define CYTHON_USE_TYPE_SPECS 0
#undef CYTHON_USE_PYTYPE_LOOKUP #undef CYTHON_USE_PYTYPE_LOOKUP
#define CYTHON_USE_PYTYPE_LOOKUP 0 #define CYTHON_USE_PYTYPE_LOOKUP 0
#undef CYTHON_USE_ASYNC_SLOTS #undef CYTHON_USE_ASYNC_SLOTS
...@@ -146,6 +152,8 @@ ...@@ -146,6 +152,8 @@
#define CYTHON_PEP487_INIT_SUBCLASS 0 #define CYTHON_PEP487_INIT_SUBCLASS 0
#undef CYTHON_PEP489_MULTI_PHASE_INIT #undef CYTHON_PEP489_MULTI_PHASE_INIT
#define CYTHON_PEP489_MULTI_PHASE_INIT 0 #define CYTHON_PEP489_MULTI_PHASE_INIT 0
#undef CYTHON_USE_MODULE_STATE
#define CYTHON_USE_MODULE_STATE 0
#undef CYTHON_USE_TP_FINALIZE #undef CYTHON_USE_TP_FINALIZE
#define CYTHON_USE_TP_FINALIZE 0 #define CYTHON_USE_TP_FINALIZE 0
#undef CYTHON_USE_DICT_VERSIONS #undef CYTHON_USE_DICT_VERSIONS
...@@ -154,6 +162,7 @@ ...@@ -154,6 +162,7 @@
#define CYTHON_USE_EXC_INFO_STACK 0 #define CYTHON_USE_EXC_INFO_STACK 0
#elif defined(CYTHON_LIMITED_API) #elif defined(CYTHON_LIMITED_API)
// EXPERIMENTAL !!
#define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_PYPY 0
#define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_PYSTON 0
#define CYTHON_COMPILING_IN_CPYTHON 0 #define CYTHON_COMPILING_IN_CPYTHON 0
...@@ -161,6 +170,8 @@ ...@@ -161,6 +170,8 @@
#undef CYTHON_USE_TYPE_SLOTS #undef CYTHON_USE_TYPE_SLOTS
#define CYTHON_USE_TYPE_SLOTS 0 #define CYTHON_USE_TYPE_SLOTS 0
#undef CYTHON_USE_TYPE_SPECS
#define CYTHON_USE_TYPE_SPECS 1
#undef CYTHON_USE_PYTYPE_LOOKUP #undef CYTHON_USE_PYTYPE_LOOKUP
#define CYTHON_USE_PYTYPE_LOOKUP 0 #define CYTHON_USE_PYTYPE_LOOKUP 0
#undef CYTHON_USE_ASYNC_SLOTS #undef CYTHON_USE_ASYNC_SLOTS
...@@ -194,6 +205,8 @@ ...@@ -194,6 +205,8 @@
#endif #endif
#undef CYTHON_PEP489_MULTI_PHASE_INIT #undef CYTHON_PEP489_MULTI_PHASE_INIT
#define CYTHON_PEP489_MULTI_PHASE_INIT 0 #define CYTHON_PEP489_MULTI_PHASE_INIT 0
#undef CYTHON_USE_MODULE_STATE
#define CYTHON_USE_MODULE_STATE 1
#ifndef CYTHON_USE_TP_FINALIZE #ifndef CYTHON_USE_TP_FINALIZE
#define CYTHON_USE_TP_FINALIZE 1 #define CYTHON_USE_TP_FINALIZE 1
#endif #endif
...@@ -211,6 +224,9 @@ ...@@ -211,6 +224,9 @@
#ifndef CYTHON_USE_TYPE_SLOTS #ifndef CYTHON_USE_TYPE_SLOTS
#define CYTHON_USE_TYPE_SLOTS 1 #define CYTHON_USE_TYPE_SLOTS 1
#endif #endif
#ifndef CYTHON_USE_TYPE_SPECS
#define CYTHON_USE_TYPE_SPECS 0
#endif
#ifndef CYTHON_USE_PYTYPE_LOOKUP #ifndef CYTHON_USE_PYTYPE_LOOKUP
#define CYTHON_USE_PYTYPE_LOOKUP 1 #define CYTHON_USE_PYTYPE_LOOKUP 1
#endif #endif
...@@ -262,17 +278,33 @@ ...@@ -262,17 +278,33 @@
#ifndef CYTHON_PEP487_INIT_SUBCLASS #ifndef CYTHON_PEP487_INIT_SUBCLASS
#define CYTHON_PEP487_INIT_SUBCLASS 1 #define CYTHON_PEP487_INIT_SUBCLASS 1
#endif #endif
#ifndef CYTHON_PEP489_MULTI_PHASE_INIT #if PY_VERSION_HEX < 0x03050000
#define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) #undef CYTHON_PEP489_MULTI_PHASE_INIT
#define CYTHON_PEP489_MULTI_PHASE_INIT 0
#elif !defined(CYTHON_PEP489_MULTI_PHASE_INIT)
#define CYTHON_PEP489_MULTI_PHASE_INIT 1
#endif #endif
#ifndef CYTHON_USE_TP_FINALIZE #ifndef CYTHON_USE_MODULE_STATE
#define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) // EXPERIMENTAL !!
#define CYTHON_USE_MODULE_STATE 0
#endif #endif
#ifndef CYTHON_USE_DICT_VERSIONS #if PY_VERSION_HEX < 0x030400a1
#define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) #undef CYTHON_USE_TP_FINALIZE
#define CYTHON_USE_TP_FINALIZE 0
#elif !defined(CYTHON_USE_TP_FINALIZE)
#define CYTHON_USE_TP_FINALIZE 1
#endif
#if PY_VERSION_HEX < 0x030600B1
#undef CYTHON_USE_DICT_VERSIONS
#define CYTHON_USE_DICT_VERSIONS 0
#elif !defined(CYTHON_USE_DICT_VERSIONS)
#define CYTHON_USE_DICT_VERSIONS 1
#endif #endif
#ifndef CYTHON_USE_EXC_INFO_STACK #if PY_VERSION_HEX < 0x030700A3
#define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) #undef CYTHON_USE_EXC_INFO_STACK
#define CYTHON_USE_EXC_INFO_STACK 0
#elif !defined(CYTHON_USE_EXC_INFO_STACK)
#define CYTHON_USE_EXC_INFO_STACK 1
#endif #endif
#endif #endif
...@@ -569,6 +601,18 @@ class __Pyx_FakeReference { ...@@ -569,6 +601,18 @@ class __Pyx_FakeReference {
#define __Pyx_PyVectorcall_NARGS(n) ((Py_ssize_t)(n)) #define __Pyx_PyVectorcall_NARGS(n) ((Py_ssize_t)(n))
#endif #endif
// PEP-573: PyCFunction holds reference to defining class (PyCMethodObject)
#if PY_VERSION_HEX < 0x030900B1
#define __Pyx_PyType_FromModuleAndSpec(m, s, b) ((void)m, PyType_FromSpecWithBases(s, b))
typedef PyObject *(*__Pyx_PyCMethod)(PyObject *, PyTypeObject *, PyObject *const *, size_t, PyObject *);
#else
#define __Pyx_PyType_FromModuleAndSpec(m, s, b) PyType_FromModuleAndSpec(m, s, b)
#define __Pyx_PyCMethod PyCMethod
#endif
#ifndef METH_METHOD
#define METH_METHOD 0x200
#endif
#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) #if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc)
#define PyObject_Malloc(s) PyMem_Malloc(s) #define PyObject_Malloc(s) PyMem_Malloc(s)
#define PyObject_Free(p) PyMem_Free(p) #define PyObject_Free(p) PyMem_Free(p)
...@@ -608,7 +652,7 @@ class __Pyx_FakeReference { ...@@ -608,7 +652,7 @@ class __Pyx_FakeReference {
#endif #endif
#if CYTHON_COMPILING_IN_LIMITED_API #if CYTHON_COMPILING_IN_LIMITED_API
static inline void *__Pyx_PyModule_GetState(PyObject *op) static CYTHON_INLINE void *__Pyx_PyModule_GetState(PyObject *op)
{ {
void *result; void *result;
...@@ -708,20 +752,30 @@ static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStrWithError(PyObject *dict, ...@@ -708,20 +752,30 @@ static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStrWithError(PyObject *dict,
#endif #endif
/* Type slots */ /* Type slots */
#if CYTHON_COMPILING_IN_LIMITED_API
#define __Pyx_PyType_GetFlags(tp) (PyType_GetFlags((PyTypeObject *)tp))
#else
#define __Pyx_PyType_GetFlags(tp) (((PyTypeObject *)tp)->tp_flags)
#endif
#if CYTHON_USE_TYPE_SLOTS #if CYTHON_USE_TYPE_SLOTS
#define __Pyx_PyType_GetFlags(tp) (((PyTypeObject *)tp)->tp_flags)
#define __Pyx_PyType_HasFeature(type, feature) ((__Pyx_PyType_GetFlags(type) & (feature)) != 0) #define __Pyx_PyType_HasFeature(type, feature) ((__Pyx_PyType_GetFlags(type) & (feature)) != 0)
#define __Pyx_PyObject_GetIterNextFunc(obj) (Py_TYPE(obj)->tp_iternext) #define __Pyx_PyObject_GetIterNextFunc(obj) (Py_TYPE(obj)->tp_iternext)
#else #else
#define __Pyx_PyType_GetFlags(tp) (PyType_GetFlags((PyTypeObject *)tp))
#define __Pyx_PyType_HasFeature(type, feature) PyType_HasFeature(type, feature) #define __Pyx_PyType_HasFeature(type, feature) PyType_HasFeature(type, feature)
#define __Pyx_PyObject_GetIterNextFunc(obj) PyIter_Next #define __Pyx_PyObject_GetIterNextFunc(obj) PyIter_Next
#endif #endif
#if CYTHON_USE_TYPE_SPECS && PY_VERSION_HEX >= 0x03080000
// In Py3.8+, instances of heap types need to decref their type on deallocation.
// https://bugs.python.org/issue35810
#define __Pyx_PyHeapTypeObject_GC_Del(obj) { \
PyTypeObject *type = Py_TYPE(obj); \
assert(__Pyx_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)); \
PyObject_GC_Del(obj); \
Py_DECREF(type); \
}
#else
#define __Pyx_PyHeapTypeObject_GC_Del(obj) PyObject_GC_Del(obj)
#endif
#if CYTHON_COMPILING_IN_LIMITED_API #if CYTHON_COMPILING_IN_LIMITED_API
#define CYTHON_PEP393_ENABLED 1 #define CYTHON_PEP393_ENABLED 1
#define __Pyx_PyUnicode_READY(op) (0) #define __Pyx_PyUnicode_READY(op) (0)
...@@ -923,6 +977,12 @@ static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStrWithError(PyObject *dict, ...@@ -923,6 +977,12 @@ static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStrWithError(PyObject *dict,
} __Pyx_PyAsyncMethodsStruct; } __Pyx_PyAsyncMethodsStruct;
#endif #endif
/////////////// IncludeStructmemberH.proto ///////////////
#include <structmember.h>
/////////////// SmallCodeConfig.proto /////////////// /////////////// SmallCodeConfig.proto ///////////////
#ifndef CYTHON_SMALL_CODE #ifndef CYTHON_SMALL_CODE
......
...@@ -1579,6 +1579,7 @@ static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) ...@@ -1579,6 +1579,7 @@ static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name)
#endif #endif
{ {
PyObject *result; PyObject *result;
// FIXME: clean up the macro guard order here: limited API first, then borrowed refs, then cpython
#if !CYTHON_AVOID_BORROWED_REFS #if !CYTHON_AVOID_BORROWED_REFS
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1
// Identifier names are always interned and have a pre-calculated hash value. // Identifier names are always interned and have a pre-calculated hash value.
......
...@@ -107,7 +107,7 @@ elif [ -n "${PYTHON_VERSION##pypy*}" ]; then ...@@ -107,7 +107,7 @@ elif [ -n "${PYTHON_VERSION##pypy*}" ]; then
if $PYTHON_DBG -V >&2; then CFLAGS="-O0 -ggdb" $PYTHON_DBG runtests.py -vv --no-code-style Debugger --backends=$BACKEND; fi; if $PYTHON_DBG -V >&2; then CFLAGS="-O0 -ggdb" $PYTHON_DBG runtests.py -vv --no-code-style Debugger --backends=$BACKEND; fi;
fi fi
export CFLAGS="-O0 -ggdb -Wall -Wextra" export CFLAGS="-O0 -ggdb -Wall -Wextra $EXTRA_CFLAGS"
python runtests.py \ python runtests.py \
-vv $STYLE_ARGS \ -vv $STYLE_ARGS \
-x Debugger \ -x Debugger \
......
...@@ -9,6 +9,7 @@ environment: ...@@ -9,6 +9,7 @@ environment:
WITH_ENV: "cmd /E:ON /V:ON /C .\\appveyor\\run_with_env.cmd" WITH_ENV: "cmd /E:ON /V:ON /C .\\appveyor\\run_with_env.cmd"
BACKEND: c BACKEND: c
PARALLEL: "-j4" PARALLEL: "-j4"
EXTRA_CFLAGS: ""
matrix: matrix:
- PYTHON: "C:\\Python27" - PYTHON: "C:\\Python27"
...@@ -35,6 +36,11 @@ environment: ...@@ -35,6 +36,11 @@ environment:
PYTHON_VERSION: "3.8" PYTHON_VERSION: "3.8"
PYTHON_ARCH: "32" PYTHON_ARCH: "32"
- PYTHON: "C:\\Python38-x64"
PYTHON_VERSION: "3.8"
PYTHON_ARCH: "64"
EXTRA_CFLAGS: "-DCYTHON_USE_TYPE_SPECS=1"
- PYTHON: "C:\\Python38-x64" - PYTHON: "C:\\Python38-x64"
PYTHON_VERSION: "3.8" PYTHON_VERSION: "3.8"
PYTHON_ARCH: "64" PYTHON_ARCH: "64"
...@@ -49,6 +55,16 @@ environment: ...@@ -49,6 +55,16 @@ environment:
PYTHON_VERSION: "3.7" PYTHON_VERSION: "3.7"
PYTHON_ARCH: "64" PYTHON_ARCH: "64"
- PYTHON: "C:\\Python37-x64"
PYTHON_VERSION: "3.7"
PYTHON_ARCH: "64"
EXTRA_CFLAGS: "-DCYTHON_USE_TYPE_SPECS=1"
- PYTHON: "C:\\Python37-x64"
PYTHON_VERSION: "3.7"
PYTHON_ARCH: "64"
BACKEND: cpp
- PYTHON: "C:\\Python36" - PYTHON: "C:\\Python36"
PYTHON_VERSION: "3.6" PYTHON_VERSION: "3.6"
PYTHON_ARCH: "32" PYTHON_ARCH: "32"
...@@ -108,7 +124,7 @@ test: off ...@@ -108,7 +124,7 @@ test: off
test_script: test_script:
- "%PYTHON%\\Scripts\\pip.exe install -r test-requirements.txt" - "%PYTHON%\\Scripts\\pip.exe install -r test-requirements.txt"
- "%PYTHON%\\Scripts\\pip.exe install win_unicode_console" - "%PYTHON%\\Scripts\\pip.exe install win_unicode_console"
- "set CFLAGS=/Od /W3" - "set CFLAGS=/Od /W3 %EXTRA_CFLAGS%"
- "%WITH_ENV% %PYTHON%\\python.exe runtests.py -vv --backend=%BACKEND% --no-code-style -j5" - "%WITH_ENV% %PYTHON%\\python.exe runtests.py -vv --backend=%BACKEND% --no-code-style -j5"
artifacts: artifacts:
......
...@@ -23,3 +23,16 @@ cdef A a ...@@ -23,3 +23,16 @@ cdef A a
foo(2, 3, [], [], P, P, &P) foo(2, 3, [], [], P, P, &P)
a.point("something", 3, "anything", [], "an object", P, &P) a.point("something", 3, "anything", [], "an object", P, &P)
# Test that internally generated names do not conflict.
cdef class A_spec:
pass
cdef class A_members:
pass
cdef class A_methods:
pass
cdef class A_slots:
pass
...@@ -6,3 +6,6 @@ dict_animal ...@@ -6,3 +6,6 @@ dict_animal
not_none not_none
queue3 queue3
test_queue test_queue
memoryview
memview
buffer
...@@ -65,31 +65,31 @@ import sys ...@@ -65,31 +65,31 @@ import sys
try: try:
import notheaptype import notheaptype
assert False assert False, "notheaptype"
except TypeError as msg: except TypeError as msg:
assert str(msg) == "base class 'object' is not a heap type" assert str(msg) == "base class 'object' is not a heap type"
try: try:
import wrongbase import wrongbase
assert False assert False, "wrongbase"
except TypeError as msg: except TypeError as msg:
assert str(msg) == "best base 'str' must be equal to first base 'wrongbase.Base'" assert str(msg) == "best base 'str' must be equal to first base 'wrongbase.Base'"
try: try:
import badmro import badmro
assert False assert False, "badmro"
except TypeError as msg: except TypeError as msg:
assert str(msg).startswith("Cannot create a consistent method resolution") assert str(msg).startswith("Cannot create a consistent method resolution")
try: try:
import nodict import nodict
assert False assert False, "nodict"
except TypeError as msg: except TypeError as msg:
assert str(msg) == "extension type 'nodict.X' has no __dict__ slot, but base type 'Py' has: either add 'cdef dict __dict__' to the extension type or add '__slots__ = [...]' to the base type" assert str(msg) == "extension type 'nodict.X' has no __dict__ slot, but base type 'Py' has: either add 'cdef dict __dict__' to the extension type or add '__slots__ = [...]' to the base type"
try: try:
# This should work on Python 3 but fail on Python 2 # This should work on Python 3 but fail on Python 2
import oldstyle import oldstyle
assert sys.version_info[0] >= 3 assert sys.version_info[0] >= 3, "oldstyle"
except TypeError as msg: except TypeError as msg:
assert str(msg) == "base class 'OldStyle' is an old-style class" assert str(msg) == "base class 'OldStyle' is an old-style class"
# tag: pstats # tag: pstats
# cython: profile = True # cython: profile = True
__doc__ = u""" u"""
>>> import os, tempfile, cProfile as profile, pstats >>> import os, tempfile, cProfile as profile, pstats
>>> statsfile = tempfile.mkstemp()[1] >>> statsfile = tempfile.mkstemp()[1]
>>> profile.runctx("test_profile(100)", locals(), globals(), statsfile) >>> profile.runctx("test_profile(100)", locals(), globals(), statsfile)
...@@ -47,7 +47,7 @@ __doc__ = u""" ...@@ -47,7 +47,7 @@ __doc__ = u"""
200 200
>>> short_stats['m_cdef'] >>> short_stats['m_cdef']
100 100
>>> short_stats['m_cpdef'] >>> short_stats['m_cpdef'] - (200 if CPDEF_METHODS_COUNT_TWICE else 0) # FIXME!
300 300
>>> try: >>> try:
...@@ -117,6 +117,15 @@ __doc__ = u""" ...@@ -117,6 +117,15 @@ __doc__ = u"""
cimport cython cimport cython
# FIXME: With type specs, cpdef methods are currently counted twice.
# https://github.com/cython/cython/issues/2137
cdef extern from *:
int CYTHON_USE_TYPE_SPECS
CPDEF_METHODS_COUNT_TWICE = CYTHON_USE_TYPE_SPECS
def callees(pstats, target_caller): def callees(pstats, target_caller):
pstats.calc_callees() pstats.calc_callees()
for (_, _, caller), callees in pstats.all_callees.items(): for (_, _, caller), callees in pstats.all_callees.items():
...@@ -125,6 +134,7 @@ def callees(pstats, target_caller): ...@@ -125,6 +134,7 @@ def callees(pstats, target_caller):
if 'pyx' in file: if 'pyx' in file:
yield callee yield callee
def test_profile(long N): def test_profile(long N):
cdef long i, n = 0 cdef long i, n = 0
cdef A a = A() cdef A a = A()
......
...@@ -56,30 +56,6 @@ __doc__ = u""" ...@@ -56,30 +56,6 @@ __doc__ = u"""
>>> g11 = object.__getattribute__(GetAttribute(), '__getattribute__') >>> g11 = object.__getattribute__(GetAttribute(), '__getattribute__')
>>> g11('attr') >>> g11('attr')
GetAttribute getattribute 'attr' GetAttribute getattribute 'attr'
>>> # If you define either setattr or delattr, you get wrapper objects
>>> # for both methods. (This behavior is unchanged by #561.)
>>> sa_setattr = SetAttr().__setattr__
>>> sa_setattr('foo', 'bar')
SetAttr setattr 'foo' 'bar'
>>> sa_delattr = SetAttr().__delattr__
>>> sa_delattr('foo')
Traceback (most recent call last):
...
AttributeError: 'special_methods_T561.SetAttr' object has no attribute 'foo'
>>> da_setattr = DelAttr().__setattr__
>>> da_setattr('foo', 'bar')
Traceback (most recent call last):
...
AttributeError: 'special_methods_T561.DelAttr' object has no attribute 'foo'
>>> da_delattr = DelAttr().__delattr__
>>> da_delattr('foo')
DelAttr delattr 'foo'
>>> sda_setattr = SetDelAttr().__setattr__
>>> sda_setattr('foo', 'bar')
SetDelAttr setattr 'foo' 'bar'
>>> sda_delattr = SetDelAttr().__delattr__
>>> sda_delattr('foo')
SetDelAttr delattr 'foo'
>>> # If you define either set or delete, you get wrapper objects >>> # If you define either set or delete, you get wrapper objects
>>> # for both methods. (This behavior is unchanged by #561.) >>> # for both methods. (This behavior is unchanged by #561.)
>>> s_set = Set().__set__ >>> s_set = Set().__set__
...@@ -119,6 +95,39 @@ if sys.version_info >= (2,5): ...@@ -119,6 +95,39 @@ if sys.version_info >= (2,5):
VS __index__ 0 VS __index__ 0
""" """
cdef extern from *:
# type specs require a bug fix in Py3.8+ for some of these tests.
const int CYTHON_USE_TYPE_SPECS
if not CYTHON_USE_TYPE_SPECS or sys.version_info >= (3,8):
__doc__ += u"""
>>> # If you define either setattr or delattr, you get wrapper objects
>>> # for both methods. (This behavior is unchanged by #561.)
>>> sa_setattr = SetAttr().__setattr__
>>> sa_setattr('foo', 'bar')
SetAttr setattr 'foo' 'bar'
>>> sa_delattr = SetAttr().__delattr__
>>> sa_delattr('foo')
Traceback (most recent call last):
...
AttributeError: 'special_methods_T561.SetAttr' object has no attribute 'foo'
>>> da_setattr = DelAttr().__setattr__
>>> da_setattr('foo', 'bar')
Traceback (most recent call last):
...
AttributeError: 'special_methods_T561.DelAttr' object has no attribute 'foo'
>>> da_delattr = DelAttr().__delattr__
>>> da_delattr('foo')
DelAttr delattr 'foo'
>>> sda_setattr = SetDelAttr().__setattr__
>>> sda_setattr('foo', 'bar')
SetDelAttr setattr 'foo' 'bar'
>>> sda_delattr = SetDelAttr().__delattr__
>>> sda_delattr('foo')
SetDelAttr delattr 'foo'
"""
cdef class VerySpecial: cdef class VerySpecial:
""" """
>>> vs0 = VerySpecial(0) >>> vs0 = VerySpecial(0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment