summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml15
-rw-r--r--Cython/Compiler/Code.py32
-rw-r--r--Cython/Compiler/ModuleNode.py39
-rw-r--r--Cython/Compiler/Naming.py2
-rw-r--r--Cython/Compiler/Nodes.py327
-rw-r--r--Cython/Compiler/TypeSlots.py102
-rw-r--r--Cython/Utility/AsyncGen.c130
-rw-r--r--Cython/Utility/CommonStructures.c30
-rw-r--r--Cython/Utility/Coroutine.c166
-rw-r--r--Cython/Utility/CythonFunction.c198
-rw-r--r--Cython/Utility/ExtensionTypes.c196
-rw-r--r--Cython/Utility/ImportExport.c14
-rw-r--r--Cython/Utility/ModuleSetupCode.c88
-rw-r--r--Cython/Utility/ObjectHandling.c1
-rw-r--r--appveyor.yml18
-rw-r--r--tests/compile/types_and_names.pyx13
-rw-r--r--tests/limited_api_bugs.txt3
-rw-r--r--tests/run/cdef_multiple_inheritance_errors.srctree10
18 files changed, 1026 insertions, 358 deletions
diff --git a/.travis.yml b/.travis.yml
index bb3aa5a94..81a6120c5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -34,6 +34,7 @@ env:
- CCACHE_MAXSIZE=250M
- PATH="/usr/lib/ccache:$HOME/miniconda/bin:$PATH"
- BACKEND=c,cpp
+ - EXTRA_CFLAGS=
matrix:
- BACKEND=c
- BACKEND=cpp
@@ -60,6 +61,18 @@ matrix:
# env: COVERAGE=1
- python: 3.7
env: TEST_CODE_STYLE=1
+ - python: 3.9-dev
+ env: EXTRA_CFLAGS="-DCYTHON_USE_TYPE_SPECS=1" BACKEND=c
+ - python: 3.8
+ env: EXTRA_CFLAGS="-DCYTHON_USE_TYPE_SPECS=1" BACKEND=c
+ - python: 3.7
+ env: EXTRA_CFLAGS="-DCYTHON_USE_TYPE_SPECS=1" BACKEND=c
+ - python: 3.6
+ env: EXTRA_CFLAGS="-DCYTHON_USE_TYPE_SPECS=1" BACKEND=c
+ - python: 3.5
+ env: EXTRA_CFLAGS="-DCYTHON_USE_TYPE_SPECS=1" BACKEND=c
+ - python: 3.4
+ env: EXTRA_CFLAGS="-DCYTHON_USE_TYPE_SPECS=1" BACKEND=c
- python: 3.8
env: LIMITED_API=--limited-api EXCLUDE=--no-file
- python: 3.7
@@ -158,5 +171,5 @@ script:
# Need to clear the ccache? Try something like this:
# - if [ -n "${BACKEND##*cpp*}" -a -z "${TRAVIS_PYTHON_VERSION##*3.4}" ]; then ccache -C || true; fi
- if [ "$COVERAGE" != "1" ]; then CFLAGS="-O2 -ggdb -Wall -Wextra $(python -c 'import sys; print("-fno-strict-aliasing" if sys.version_info[0] == 2 else "")')" python setup.py build_ext -i $(python -c 'import sys; print("-j5" if sys.version_info >= (3,5) else "")'); fi
- - CFLAGS="-O0 -ggdb -Wall -Wextra" python runtests.py -vv $STYLE_ARGS -x Debugger --backends=$BACKEND $LIMITED_API $EXCLUDE $(if [ "$COVERAGE" == "1" ]; then echo " --coverage"; fi) $(if [ -z "$TEST_CODE_STYLE" ]; then echo " -j7 "; fi)
+ - CFLAGS="-O0 -ggdb -Wall -Wextra $EXTRA_CFLAGS" python runtests.py -vv $STYLE_ARGS -x Debugger --backends=$BACKEND $LIMITED_API $EXCLUDE $(if [ "$COVERAGE" == "1" ]; then echo " --coverage"; fi) $(if [ -z "$TEST_CODE_STYLE" ]; then echo " -j7 "; fi)
- ccache -s || true
diff --git a/Cython/Compiler/Code.py b/Cython/Compiler/Code.py
index c7ee4d82d..9968a6336 100644
--- a/Cython/Compiler/Code.py
+++ b/Cython/Compiler/Code.py
@@ -1476,7 +1476,7 @@ class GlobalState(object):
for c in self.py_constants]
consts.sort()
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:
self.parts['module_state'].putln("%s;" % c.type.declaration_code(cname))
self.parts['module_state_defines'].putln(
@@ -1551,16 +1551,16 @@ class GlobalState(object):
w = self.parts['pystring_table']
w.putln("")
w.putln("static __Pyx_StringTabEntry %s[] = {" % Naming.stringtab_cname)
- w.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
- w_limited_writer = w.insertion_point()
+ w.putln("#if CYTHON_USE_MODULE_STATE")
+ w_in_module_state = w.insertion_point()
w.putln("#else")
- w_not_limited_writer = w.insertion_point()
+ w_not_in_module_state = w.insertion_point()
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()
decls_writer.putln("#endif")
- init_globals.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
- init_globals_limited_api = init_globals.insertion_point()
+ init_globals.putln("#if CYTHON_USE_MODULE_STATE")
+ init_globals_in_module_state = init_globals.insertion_point()
init_globals.putln("#endif")
for idx, py_string_args in enumerate(py_strings):
c_cname, _, py_string = py_string_args
@@ -1583,16 +1583,16 @@ class GlobalState(object):
not_limited_api_decls_writer.putln(
"static PyObject *%s;" % py_string.cname)
if py_string.py3str_cstring:
- w_not_limited_writer.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("#if PY_MAJOR_VERSION >= 3")
+ w_not_in_module_state.putln("{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
py_string.cname,
py_string.py3str_cstring.cname,
py_string.py3str_cstring.cname,
'0', 1, 0,
py_string.intern
))
- w_not_limited_writer.putln("#else")
- w_not_limited_writer.putln("{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
+ w_not_in_module_state.putln("#else")
+ w_not_in_module_state.putln("{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
py_string.cname,
c_cname,
c_cname,
@@ -1602,8 +1602,8 @@ class GlobalState(object):
py_string.intern
))
if py_string.py3str_cstring:
- w_not_limited_writer.putln("#endif")
- w_limited_writer.putln("{0, %s, sizeof(%s), %s, %d, %d, %d}," % (
+ w_not_in_module_state.putln("#endif")
+ 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,
encoding if not py_string.py3str_cstring else '0',
@@ -1611,7 +1611,7 @@ class GlobalState(object):
py_string.is_str,
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,
idx,
py_string.cname,
@@ -1619,7 +1619,7 @@ class GlobalState(object):
w.putln("{0, 0, 0, 0, 0, 0, 0}")
w.putln("};")
- init_globals.putln("#if !CYTHON_COMPILING_IN_LIMITED_API")
+ init_globals.putln("#if !CYTHON_USE_MODULE_STATE")
init_globals.putln(
"if (__Pyx_InitStrings(%s) < 0) %s;" % (
Naming.stringtab_cname,
@@ -1631,7 +1631,7 @@ class GlobalState(object):
for c in self.num_const_index.values()]
consts.sort()
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']
for py_type, _, _, value, value_code, c in consts:
cname = c.cname
diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py
index 77a92368c..41c959796 100644
--- a/Cython/Compiler/ModuleNode.py
+++ b/Cython/Compiler/ModuleNode.py
@@ -804,7 +804,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.put(Nodes.branch_prediction_macros)
code.putln('static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; }')
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;' % env.module_dict_cname)
code.putln('static PyObject *%s;' % Naming.builtins_cname)
@@ -1239,7 +1239,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
module_state_defines = globalstate['module_state_defines']
module_state_clear = globalstate['module_state_clear']
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:
if definition or entry.defined_in_pxd:
code.putln("static PyTypeObject *%s = 0;" % (
@@ -1376,7 +1376,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self.generate_property_accessors(scope, code)
self.generate_method_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)
code.putln("#else")
self.generate_typeobj_definition(full_module_name, entry, code)
@@ -1566,11 +1566,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
slot_func_cname = scope.mangle_internal("tp_dealloc")
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(
"static void %s(PyObject *o) {" % slot_func_cname)
@@ -1700,8 +1695,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln(
"}")
- if cdealloc_func_entry is None:
- code.putln("#endif")
def generate_usr_dealloc_call(self, scope, code):
entry = scope.lookup_here("__dealloc__")
@@ -2376,6 +2369,16 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_typeobj_spec(self, entry, code):
ext_type = entry.type
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)
for slot in TypeSlots.slot_table:
slot.generate_spec(scope, code)
@@ -2567,8 +2570,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.exit_cfunc_scope() # done with labels
def generate_module_state_start(self, env, code):
- # TODO: Reactor LIMITED_API struct decl closer to the static decl
- code.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
+ # TODO: Refactor to move module state struct decl closer to the static decl
+ code.putln("#if CYTHON_USE_MODULE_STATE")
code.putln('typedef struct {')
code.putln('PyObject *%s;' % env.module_dict_cname)
code.putln('PyObject *%s;' % Naming.builtins_cname)
@@ -2622,7 +2625,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
module_state_traverse.putln("#endif")
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' % (
env.module_dict_cname,
Naming.modulestateglobal_cname,
@@ -2666,7 +2669,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln('#endif')
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("%s *clear_module_state = %s(m);" % (
Naming.modulestate_cname,
@@ -2694,7 +2697,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln('#endif')
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("%s *traverse_module_state = %s(m);" % (
Naming.modulestate_cname,
@@ -2838,7 +2841,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
for ext_type in ('CyFunction', 'FusedFunction', 'Coroutine', 'Generator', 'AsyncGen', 'StopAsyncIteration'):
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("/*--- Library function declarations ---*/")
@@ -3247,7 +3250,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln(" %s, /* m_doc */" % doc)
code.putln("#if CYTHON_PEP489_MULTI_PHASE_INIT")
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("#else")
code.putln(" -1, /* m_size */")
@@ -3258,7 +3261,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("#else")
code.putln(" NULL, /* m_reload */")
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_clear, /* m_clear */" % Naming.module_cname)
code.putln(" %s /* m_free */" % cleanup_func)
diff --git a/Cython/Compiler/Naming.py b/Cython/Compiler/Naming.py
index b36239433..005bd0530 100644
--- a/Cython/Compiler/Naming.py
+++ b/Cython/Compiler/Naming.py
@@ -131,7 +131,7 @@ fused_func_prefix = pyrex_prefix + 'fuse_'
quick_temp_cname = pyrex_prefix + "temp" # temp variable for quick'n'dirty temping
tp_dict_version_temp = pyrex_prefix + "tp_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"
cyfunction_type_cname = pyrex_prefix + "CyFunctionType"
fusedfunction_type_cname = pyrex_prefix + "FusedFunctionType"
diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py
index 5f935360f..5fd378c96 100644
--- a/Cython/Compiler/Nodes.py
+++ b/Cython/Compiler/Nodes.py
@@ -2562,38 +2562,45 @@ class CFuncDefNode(FuncDefNode):
self.create_local_scope(env)
def declare_cpdef_wrapper(self, env):
- if self.overridable:
- if self.is_static_method:
- # TODO(robertwb): Finish this up, perhaps via more function refactoring.
- error(self.pos, "static cpdef methods not yet supported")
- name = self.entry.name
- py_func_body = self.call_self_node(is_module_scope=env.is_module_scope)
- if self.is_static_method:
- from .ExprNodes import NameNode
- decorators = [DecoratorNode(self.pos, decorator=NameNode(self.pos, name=EncodedString('staticmethod')))]
- decorators[0].decorator.analyse_types(env)
+ if not self.overridable:
+ return
+ if self.is_static_method:
+ # TODO(robertwb): Finish this up, perhaps via more function refactoring.
+ error(self.pos, "static cpdef methods not yet supported")
+
+ name = self.entry.name
+ py_func_body = self.call_self_node(is_module_scope=env.is_module_scope)
+ if self.is_static_method:
+ from .ExprNodes import NameNode
+ decorators = [DecoratorNode(self.pos, decorator=NameNode(self.pos, name=EncodedString('staticmethod')))]
+ decorators[0].decorator.analyse_types(env)
+ else:
+ decorators = []
+ self.py_func = DefNode(pos=self.pos,
+ name=self.entry.name,
+ args=self.args,
+ star_arg=None,
+ starstar_arg=None,
+ doc=self.doc,
+ body=py_func_body,
+ decorators=decorators,
+ is_wrapper=1)
+ self.py_func.is_module_scope = env.is_module_scope
+ self.py_func.analyse_declarations(env)
+ self.py_func.entry.is_overridable = True
+ self.py_func_stat = StatListNode(self.pos, stats=[self.py_func])
+ self.py_func.type = PyrexTypes.py_object_type
+ self.entry.as_variable = self.py_func.entry
+ self.entry.used = self.entry.as_variable.used = True
+ # Reset scope entry the above cfunction
+ env.entries[name] = self.entry
+ if (not self.entry.is_final_cmethod and
+ (not env.is_module_scope or Options.lookup_module_cpdef)):
+ if self.override:
+ # This is a hack: we shouldn't create the wrapper twice, but we do for fused functions.
+ assert self.entry.is_fused_specialized # should not happen for non-fused cpdef functions
+ self.override.py_func = self.py_func
else:
- decorators = []
- self.py_func = DefNode(pos=self.pos,
- name=self.entry.name,
- args=self.args,
- star_arg=None,
- starstar_arg=None,
- doc=self.doc,
- body=py_func_body,
- decorators=decorators,
- is_wrapper=1)
- self.py_func.is_module_scope = env.is_module_scope
- self.py_func.analyse_declarations(env)
- self.py_func.entry.is_overridable = True
- self.py_func_stat = StatListNode(self.pos, stats=[self.py_func])
- self.py_func.type = PyrexTypes.py_object_type
- self.entry.as_variable = self.py_func.entry
- self.entry.used = self.entry.as_variable.used = True
- # Reset scope entry the above cfunction
- env.entries[name] = self.entry
- if (not self.entry.is_final_cmethod and
- (not env.is_module_scope or Options.lookup_module_cpdef)):
self.override = OverrideCheckNode(self.pos, py_func=self.py_func)
self.body = StatListNode(self.pos, stats=[self.override, self.body])
@@ -3866,7 +3873,7 @@ class DefNodeWrapper(FuncDefNode):
non_posonly_args = [arg for arg in all_args if not arg.pos_only]
non_pos_args_id = ','.join(
['&%s' % code.intern_identifier(arg.entry.name) for arg in non_posonly_args] + ['0'])
- code.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
+ code.putln("#if CYTHON_USE_MODULE_STATE")
code.putln("PyObject **%s[] = {%s};" % (
Naming.pykwdlist_cname,
non_pos_args_id))
@@ -4663,7 +4670,10 @@ class OverrideCheckNode(StatNode):
return self
def generate_execution_code(self, code):
- interned_attr_cname = code.intern_identifier(self.py_func.entry.name)
+ # For fused functions, look up the dispatch function, not the specialisation.
+ method_entry = self.py_func.fused_py_func.entry if self.py_func.fused_py_func else self.py_func.entry
+ interned_attr_cname = code.intern_identifier(method_entry.name)
+
# Check to see if we are an extension type
if self.py_func.is_module_scope:
self_arg = "((PyObject *)%s)" % Naming.module_cname
@@ -4704,10 +4714,14 @@ class OverrideCheckNode(StatNode):
func_node_temp, self_arg, interned_attr_cname, err))
code.put_gotref(func_node_temp, py_object_type)
- is_builtin_function_or_method = "PyCFunction_Check(%s)" % func_node_temp
is_overridden = "(PyCFunction_GET_FUNCTION(%s) != (PyCFunction)(void*)%s)" % (
- func_node_temp, self.py_func.entry.func_cname)
- code.putln("if (!%s || %s) {" % (is_builtin_function_or_method, is_overridden))
+ func_node_temp, method_entry.func_cname)
+ code.putln("#ifdef __Pyx_CyFunction_USED")
+ code.putln("if (!__Pyx_IsCyOrPyCFunction(%s)" % func_node_temp)
+ code.putln("#else")
+ code.putln("if (!PyCFunction_Check(%s)" % func_node_temp)
+ code.putln("#endif")
+ code.putln(" || %s) {" % is_overridden)
self.body.generate_execution_code(code)
code.putln("}")
@@ -5219,12 +5233,18 @@ class CClassDefNode(ClassDefNode):
# default values of method arguments.
code.mark_pos(self.pos)
if not self.entry.type.early_init:
+ bases = None
if self.type_init_args:
+ # Extract bases tuple and validate 'best base' by actually calling 'type()'.
+ bases = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
+
self.type_init_args.generate_evaluation_code(code)
- bases = "PyTuple_GET_ITEM(%s, 1)" % self.type_init_args.result()
+ code.putln("%s = PyTuple_GET_ITEM(%s, 1);" % (bases, self.type_init_args.result()))
+ code.put_incref(bases, PyrexTypes.py_object_type)
+
first_base = "((PyTypeObject*)PyTuple_GET_ITEM(%s, 0))" % bases
# Let Python do the base types compatibility checking.
- trial_type = code.funcstate.allocate_temp(PyrexTypes.py_object_type, True)
+ trial_type = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
code.putln("%s = PyType_Type.tp_new(&PyType_Type, %s, NULL);" % (
trial_type, self.type_init_args.result()))
code.putln(code.error_goto_if_null(trial_type, self.pos))
@@ -5240,73 +5260,156 @@ class CClassDefNode(ClassDefNode):
code.putln("__Pyx_DECREF_TypeName(type_name);")
code.putln(code.error_goto(self.pos))
code.putln("}")
- code.funcstate.release_temp(trial_type)
- code.put_incref(bases, PyrexTypes.py_object_type)
- code.put_giveref(bases, py_object_type)
- code.putln("%s.tp_bases = %s;" % (self.entry.type.typeobj_cname, bases))
+
code.put_decref_clear(trial_type, PyrexTypes.py_object_type)
+ code.funcstate.release_temp(trial_type)
+
self.type_init_args.generate_disposal_code(code)
self.type_init_args.free_temps(code)
- self.generate_type_ready_code(self.entry, code)
+ self.generate_type_ready_code(self.entry, code, bases_tuple_cname=bases, check_heap_type_bases=True)
+ if bases is not None:
+ code.put_decref_clear(bases, PyrexTypes.py_object_type)
+ code.funcstate.release_temp(bases)
+
if self.body:
self.body.generate_execution_code(code)
# Also called from ModuleNode for early init types.
@staticmethod
- def generate_type_ready_code(entry, code):
+ def generate_type_ready_code(entry, code, bases_tuple_cname=None, check_heap_type_bases=False):
# Generate a call to PyType_Ready for an extension
# type defined in this module.
type = entry.type
- typeobj_cname = type.typeobj_cname
+ typeptr_cname = type.typeptr_cname
scope = type.scope
if not scope: # could be None if there was an error
return
- if entry.visibility != 'extern':
- code.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
- base_type = scope.parent_type.base_type
- if base_type:
+ if entry.visibility == 'extern':
+ # Generate code to initialise the typeptr of an external extension
+ # type defined in this module to point to its type object.
+ if type.typeobj_cname:
+ # FIXME: this should not normally be set :-?
+ assert not type.typeobj_cname
+ code.putln("%s = &%s;" % (
+ type.typeptr_cname,
+ type.typeobj_cname,
+ ))
+ return
+ # TODO: remove 'else:' and dedent
+ else:
+ assert typeptr_cname
+ assert type.typeobj_cname
+ typespec_cname = "%s_spec" % type.typeobj_cname
+ code.putln("#if CYTHON_USE_TYPE_SPECS")
+ tuple_temp = None
+ if not bases_tuple_cname and scope.parent_type.base_type:
tuple_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
- code.putln(
- "%s = PyTuple_Pack(1, (PyObject *)%s); %s" % (
+ code.putln("%s = PyTuple_Pack(1, (PyObject *)%s); %s" % (
tuple_temp,
- base_type.typeptr_cname,
- code.error_goto_if_null(tuple_temp, entry.pos)))
+ scope.parent_type.base_type.typeptr_cname,
+ code.error_goto_if_null(tuple_temp, entry.pos),
+ ))
code.put_gotref(tuple_temp, py_object_type)
- code.putln(
- "%s = PyType_FromSpecWithBases(&%s_spec, %s); %s" % (
- typeobj_cname,
- typeobj_cname,
- tuple_temp,
- code.error_goto_if_null(typeobj_cname, entry.pos)))
- code.put_xdecref_clear(tuple_temp, type=py_object_type)
- code.funcstate.release_temp(tuple_temp)
+
+ if bases_tuple_cname or tuple_temp:
+ if check_heap_type_bases:
+ code.globalstate.use_utility_code(
+ UtilityCode.load_cached('ValidateBasesTuple', 'ExtensionTypes.c'))
+ code.put_error_if_neg(entry.pos, "__Pyx_validate_bases_tuple(%s.name, %s, %s)" % (
+ typespec_cname,
+ TypeSlots.get_slot_by_name("tp_dictoffset").slot_code(scope),
+ bases_tuple_cname or tuple_temp,
+ ))
+
+ code.putln("%s = (PyTypeObject *) __Pyx_PyType_FromModuleAndSpec(%s, &%s, %s);" % (
+ typeptr_cname,
+ Naming.module_cname,
+ typespec_cname,
+ bases_tuple_cname or tuple_temp,
+ ))
+ if tuple_temp:
+ code.put_xdecref_clear(tuple_temp, type=py_object_type)
+ code.funcstate.release_temp(tuple_temp)
+ code.putln(code.error_goto_if_null(typeptr_cname, entry.pos))
else:
code.putln(
- "%s = PyType_FromSpec(&%s_spec); %s" % (
- typeobj_cname,
- typeobj_cname,
- code.error_goto_if_null(typeobj_cname, entry.pos)))
+ "%s = (PyTypeObject *) __Pyx_PyType_FromModuleAndSpec(%s, &%s, NULL); %s" % (
+ typeptr_cname,
+ Naming.module_cname,
+ typespec_cname,
+ code.error_goto_if_null(typeptr_cname, entry.pos),
+ ))
+
+ # The buffer interface is not currently supported by PyType_FromSpec().
+ 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")
+ code.putln("%s->%s = %s;" % (
+ typeptr_cname,
+ buffer_slot.slot_name,
+ buffer_slot.slot_code(scope),
+ ))
+ # Still need to inherit buffer methods since PyType_Ready() didn't do it for us.
+ for buffer_method_name in ("__getbuffer__", "__releasebuffer__"):
+ buffer_slot = TypeSlots.get_slot_by_method_name(buffer_method_name)
+ if buffer_slot.slot_code(scope) == "0" and not TypeSlots.get_base_slot_function(scope, buffer_slot):
+ code.putln("if (!%s->tp_as_buffer->%s &&"
+ " %s->tp_base->tp_as_buffer &&"
+ " %s->tp_base->tp_as_buffer->%s) {" % (
+ typeptr_cname, buffer_slot.slot_name,
+ typeptr_cname,
+ typeptr_cname, buffer_slot.slot_name,
+ ))
+ code.putln("%s->tp_as_buffer->%s = %s->tp_base->tp_as_buffer->%s;" % (
+ typeptr_cname, buffer_slot.slot_name,
+ typeptr_cname, buffer_slot.slot_name,
+ ))
+ code.putln("}")
+ code.putln("#else")
+ code.putln("#warning The buffer protocol is not supported in the Limited C-API.")
+ code.putln("#endif")
+
+ code.globalstate.use_utility_code(
+ UtilityCode.load_cached("FixUpExtensionType", "ExtensionTypes.c"))
+ code.put_error_if_neg(entry.pos, "__Pyx_fix_up_extension_type_from_spec(&%s, %s)" % (
+ typespec_cname, typeptr_cname))
+
code.putln("#else")
+ if bases_tuple_cname:
+ code.put_incref(bases_tuple_cname, py_object_type)
+ code.put_giveref(bases_tuple_cname, py_object_type)
+ code.putln("%s.tp_bases = %s;" % (type.typeobj_cname, bases_tuple_cname))
+ code.putln("%s = &%s;" % (
+ typeptr_cname,
+ type.typeobj_cname,
+ ))
+ code.putln("#endif") # if CYTHON_USE_TYPE_SPECS
+
+ code.putln("#if !CYTHON_COMPILING_IN_LIMITED_API")
+ # FIXME: these still need to get initialised even with the limited-API
for slot in TypeSlots.slot_table:
slot.generate_dynamic_init_code(scope, code)
+ code.putln("#endif")
+
+ code.putln("#if !CYTHON_USE_TYPE_SPECS")
code.globalstate.use_utility_code(
UtilityCode.load_cached('PyType_Ready', 'ExtensionTypes.c'))
- code.putln(
- "if (__Pyx_PyType_Ready(&%s) < 0) %s" % (
- typeobj_cname,
- code.error_goto(entry.pos)))
+ code.put_error_if_neg(entry.pos, "__Pyx_PyType_Ready(%s)" % typeptr_cname)
+ code.putln("#endif")
+
# Don't inherit tp_print from builtin types in Python 2, restoring the
# behavior of using tp_repr or tp_str instead.
# ("tp_print" was renamed to "tp_vectorcall_offset" in Py3.8b1)
code.putln("#if PY_MAJOR_VERSION < 3")
- code.putln("%s.tp_print = 0;" % typeobj_cname)
+ code.putln("%s->tp_print = 0;" % typeptr_cname)
code.putln("#endif")
# Use specialised attribute lookup for types with generic lookup but no instance dict.
getattr_slot_func = TypeSlots.get_slot_code_by_name(scope, 'tp_getattro')
dictoffset_slot_func = TypeSlots.get_slot_code_by_name(scope, 'tp_dictoffset')
if getattr_slot_func == '0' and dictoffset_slot_func == '0':
+ code.putln("#if !CYTHON_COMPILING_IN_LIMITED_API") # FIXME
if type.is_final_type:
py_cfunc = "__Pyx_PyObject_GenericGetAttrNoDict" # grepable
utility_func = "PyObject_GenericGetAttrNoDict"
@@ -5316,12 +5419,12 @@ class CClassDefNode(ClassDefNode):
code.globalstate.use_utility_code(UtilityCode.load_cached(utility_func, "ObjectHandling.c"))
code.putln("if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) &&"
- " likely(!%s.tp_dictoffset && %s.tp_getattro == PyObject_GenericGetAttr)) {" % (
- typeobj_cname, typeobj_cname))
- code.putln("%s.tp_getattro = %s;" % (
- typeobj_cname, py_cfunc))
+ " likely(!%s->tp_dictoffset && %s->tp_getattro == PyObject_GenericGetAttr)) {" % (
+ typeptr_cname, typeptr_cname))
+ code.putln("%s->tp_getattro = %s;" % (
+ typeptr_cname, py_cfunc))
code.putln("}")
- code.putln("#endif")
+ code.putln("#endif") # if !CYTHON_COMPILING_IN_LIMITED_API
# Fix special method docstrings. This is a bit of a hack, but
# unless we let PyType_Ready create the slot wrappers we have
@@ -5337,8 +5440,8 @@ class CClassDefNode(ClassDefNode):
code.putln('#if CYTHON_COMPILING_IN_CPYTHON')
code.putln("{")
code.putln(
- 'PyObject *wrapper = PyObject_GetAttrString((PyObject *)&%s, "%s"); %s' % (
- typeobj_cname,
+ 'PyObject *wrapper = PyObject_GetAttrString((PyObject *)%s, "%s"); %s' % (
+ typeptr_cname,
func.name,
code.error_goto_if_null('wrapper', entry.pos)))
code.putln(
@@ -5356,50 +5459,33 @@ class CClassDefNode(ClassDefNode):
code.putln('#endif')
if preprocessor_guard:
code.putln('#endif')
+
if type.vtable_cname:
code.globalstate.use_utility_code(
UtilityCode.load_cached('SetVTable', 'ImportExport.c'))
- code.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
- code.putln(
- "if (__Pyx_SetVtable(%s, %s) < 0) %s" % (
- typeobj_cname,
- type.vtabptr_cname,
- code.error_goto(entry.pos)))
- code.putln("#else")
- code.putln(
- "if (__Pyx_SetVtable(%s.tp_dict, %s) < 0) %s" % (
- typeobj_cname,
- type.vtabptr_cname,
- code.error_goto(entry.pos)))
- code.putln("#endif")
- code.globalstate.use_utility_code(
- UtilityCode.load_cached('MergeVTables', 'ImportExport.c'))
- code.putln("if (__Pyx_MergeVtables(&%s) < 0) %s" % (
- typeobj_cname,
- code.error_goto(entry.pos)))
+ code.put_error_if_neg(entry.pos, "__Pyx_SetVtable(%s, %s)" % (
+ typeptr_cname,
+ type.vtabptr_cname,
+ ))
+ if bases_tuple_cname:
+ code.globalstate.use_utility_code(
+ UtilityCode.load_cached('MergeVTables', 'ImportExport.c'))
+ code.put_error_if_neg(entry.pos, "__Pyx_MergeVtables(%s)" % typeptr_cname)
+
if not type.scope.is_internal and not type.scope.directives.get('internal'):
# scope.is_internal is set for types defined by
# Cython (such as closures), the 'internal'
# directive is set by users
- code.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
- code.putln(
- 'if (PyObject_SetAttr(%s, %s, %s) < 0) %s' % (
- Naming.module_cname,
- code.intern_identifier(scope.class_name),
- typeobj_cname,
- code.error_goto(entry.pos)))
- code.putln("#else")
- code.putln(
- 'if (PyObject_SetAttr(%s, %s, (PyObject *)&%s) < 0) %s' % (
- Naming.module_cname,
- code.intern_identifier(scope.class_name),
- typeobj_cname,
- code.error_goto(entry.pos)))
- code.putln("#endif")
+ code.put_error_if_neg(entry.pos, "PyObject_SetAttr(%s, %s, (PyObject *) %s)" % (
+ Naming.module_cname,
+ code.intern_identifier(scope.class_name),
+ typeptr_cname,
+ ))
+
weakref_entry = scope.lookup_here("__weakref__") if not scope.is_closure_class_scope else None
if weakref_entry:
if weakref_entry.type is py_object_type:
- tp_weaklistoffset = "%s.tp_weaklistoffset" % typeobj_cname
+ tp_weaklistoffset = "%s->tp_weaklistoffset" % typeptr_cname
if type.typedef_flag:
objstruct = type.objstruct_cname
else:
@@ -5411,29 +5497,16 @@ class CClassDefNode(ClassDefNode):
weakref_entry.cname))
else:
error(weakref_entry.pos, "__weakref__ slot must be of type 'object'")
+
if scope.lookup_here("__reduce_cython__") if not scope.is_closure_class_scope else None:
# Unfortunately, we cannot reliably detect whether a
# superclass defined __reduce__ at compile time, so we must
# do so at runtime.
code.globalstate.use_utility_code(
UtilityCode.load_cached('SetupReduce', 'ExtensionTypes.c'))
- code.putln("#if !CYTHON_COMPILING_IN_LIMITED_API")
- code.putln('if (__Pyx_setup_reduce((PyObject*)&%s) < 0) %s' % (
- typeobj_cname,
- code.error_goto(entry.pos)))
+ code.putln("#if !CYTHON_COMPILING_IN_LIMITED_API") # FIXME
+ code.put_error_if_neg(entry.pos, "__Pyx_setup_reduce((PyObject *) %s)" % typeptr_cname)
code.putln("#endif")
- # Generate code to initialise the typeptr of an extension
- # type defined in this module to point to its type object.
- if type.typeobj_cname:
- code.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
- code.putln(
- "%s = (PyTypeObject *)%s;" % (
- type.typeptr_cname, type.typeobj_cname))
- code.putln("#else")
- code.putln(
- "%s = &%s;" % (
- type.typeptr_cname, type.typeobj_cname))
- code.putln("#endif")
def annotate(self, code):
if self.type_init_args:
diff --git a/Cython/Compiler/TypeSlots.py b/Cython/Compiler/TypeSlots.py
index 1db912991..c260ada1d 100644
--- a/Cython/Compiler/TypeSlots.py
+++ b/Cython/Compiler/TypeSlots.py
@@ -276,7 +276,7 @@ class SlotDescriptor(object):
# PyPy currently has a broken PyType_Ready() that fails to
# inherit some slots. To work around this, we explicitly
# set inherited slots here, but only in PyPy since CPython
- # handles this better than we do.
+ # handles this better than we do (except for buffer slots in type specs).
inherited_value = value
current_scope = scope
while (inherited_value == "0"
@@ -286,7 +286,9 @@ class SlotDescriptor(object):
current_scope = current_scope.parent_type.base_type.scope
inherited_value = self.slot_code(current_scope)
if inherited_value != "0":
- code.putln("#if CYTHON_COMPILING_IN_PYPY")
+ # we always need inherited buffer slots for the type spec
+ is_buffer_slot = int(self.slot_name in ("bf_getbuffer", "bf_releasebuffer"))
+ code.putln("#if CYTHON_COMPILING_IN_PYPY || %d" % is_buffer_slot)
code.putln("%s, /*%s*/" % (inherited_value, self.slot_name))
code.putln("#else")
end_pypy_guard = True
@@ -315,11 +317,14 @@ class SlotDescriptor(object):
def generate_set_slot_code(self, value, scope, code):
if value == "0":
return
- code.putln("%s.%s = %s;" % (
- scope.parent_type.typeobj_cname,
- self.slot_name,
- value,
- ))
+
+ if scope.parent_type.typeptr_cname:
+ target = "%s->%s" % (scope.parent_type.typeptr_cname, self.slot_name)
+ else:
+ assert scope.parent_type.typeobj_cname
+ target = "%s.%s" % (scope.parent_type.typeobj_cname, self.slot_name)
+
+ code.putln("%s = %s;" % (target, value))
class FixedSlot(SlotDescriptor):
@@ -458,9 +463,11 @@ class ConstructorSlot(InternalMethodSlot):
return InternalMethodSlot.slot_code(self, scope)
def spec_value(self, scope):
- if self.slot_name == "tp_dealloc" and not scope.lookup_here("__dealloc__"):
+ slot_function = self.slot_code(scope)
+ if self.slot_name == "tp_dealloc" and slot_function != scope.mangle_internal("tp_dealloc"):
+ # Not used => inherit from base type.
return "0"
- return self.slot_code(scope)
+ return slot_function
def generate_dynamic_init_code(self, scope, code):
if self.slot_code(scope) != '0':
@@ -468,10 +475,10 @@ class ConstructorSlot(InternalMethodSlot):
# If we don't have our own slot function and don't know the
# parent function statically, copy it dynamically.
base_type = scope.parent_type.base_type
- if base_type.is_extension_type and base_type.typeobj_cname:
- src = '%s.%s' % (base_type.typeobj_cname, self.slot_name)
- elif base_type.typeptr_cname:
+ if base_type.typeptr_cname:
src = '%s->%s' % (base_type.typeptr_cname, self.slot_name)
+ elif base_type.is_extension_type and base_type.typeobj_cname:
+ src = '%s.%s' % (base_type.typeobj_cname, self.slot_name)
else:
return
@@ -498,8 +505,6 @@ class SyntheticSlot(InternalMethodSlot):
return self.default_value
def spec_value(self, scope):
- if self.slot_name == "tp_getattro" and not scope.defines_any_special(self.user_methods):
- return "PyObject_GenericGetAttr"
return self.slot_code(scope)
@@ -623,8 +628,43 @@ class MemberTableSlot(SlotDescriptor):
# Slot descriptor for the table of Python-accessible attributes.
def slot_code(self, scope):
+ # Only used in specs.
return "0"
+ def get_member_specs(self, scope):
+ return [
+ get_slot_by_name("tp_dictoffset").members_slot_value(scope),
+ #get_slot_by_name("tp_weaklistoffset").spec_value(scope),
+ ]
+
+ def is_empty(self, scope):
+ for member_entry in self.get_member_specs(scope):
+ if member_entry:
+ return False
+ return True
+
+ def substructure_cname(self, scope):
+ return "%s%s_%s" % (Naming.pyrex_prefix, self.slot_name, scope.class_name)
+
+ def generate_substructure_spec(self, scope, code):
+ if self.is_empty(scope):
+ return
+ from .Code import UtilityCode
+ code.globalstate.use_utility_code(UtilityCode.load_cached("IncludeStructmemberH", "ModuleSetupCode.c"))
+
+ ext_type = scope.parent_type
+ code.putln("static struct PyMemberDef %s[] = {" % self.substructure_cname(scope))
+ for member_entry in self.get_member_specs(scope):
+ if member_entry:
+ code.putln(member_entry)
+ code.putln("{NULL, 0, 0, 0, NULL}")
+ code.putln("};")
+
+ def spec_value(self, scope):
+ if self.is_empty(scope):
+ return "0"
+ return self.substructure_cname(scope)
+
class GetSetSlot(SlotDescriptor):
# Slot descriptor for the table of attribute get & set methods.
@@ -645,8 +685,8 @@ class BaseClassSlot(SlotDescriptor):
def generate_dynamic_init_code(self, scope, code):
base_type = scope.parent_type.base_type
if base_type:
- code.putln("%s.%s = %s;" % (
- scope.parent_type.typeobj_cname,
+ code.putln("%s->%s = %s;" % (
+ scope.parent_type.typeptr_cname,
self.slot_name,
base_type.typeptr_cname))
@@ -671,6 +711,13 @@ class DictOffsetSlot(SlotDescriptor):
else:
return "0"
+ def members_slot_value(self, scope):
+ dict_offset = self.slot_code(scope)
+ if dict_offset == "0":
+ return None
+ return '{"__dictoffset__", T_PYSSIZET, %s, READONLY, NULL},' % dict_offset
+
+
# The following dictionary maps __xxx__ method names to slot descriptors.
@@ -712,7 +759,7 @@ def get_base_slot_function(scope, slot):
# This is useful for enabling the compiler to optimize calls
# that recursively climb the class hierarchy.
base_type = scope.parent_type.base_type
- if scope.parent_scope is base_type.scope.parent_scope:
+ if base_type and scope.parent_scope is base_type.scope.parent_scope:
parent_slot = slot.slot_code(base_type.scope)
if parent_slot != '0':
entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
@@ -741,6 +788,11 @@ def get_slot_by_name(slot_name):
assert False, "Slot not found: %s" % slot_name
+def get_slot_by_method_name(method_name):
+ # For now, only search the type struct, no referenced sub-structs.
+ return method_name_to_slot[method_name]
+
+
def get_slot_code_by_name(scope, slot_name):
slot = get_slot_by_name(slot_name)
return slot.slot_code(scope)
@@ -845,38 +897,38 @@ property_accessor_signatures = {
#
#------------------------------------------------------------------------------------------
-PyNumberMethods_Py3_GUARD = "PY_MAJOR_VERSION < 3 || (CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x03050000)"
+PyNumberMethods_Py2only_GUARD = "PY_MAJOR_VERSION < 3 || (CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x03050000)"
PyNumberMethods = (
BinopSlot(binaryfunc, "nb_add", "__add__"),
BinopSlot(binaryfunc, "nb_subtract", "__sub__"),
BinopSlot(binaryfunc, "nb_multiply", "__mul__"),
- BinopSlot(binaryfunc, "nb_divide", "__div__", ifdef = PyNumberMethods_Py3_GUARD),
+ BinopSlot(binaryfunc, "nb_divide", "__div__", ifdef = PyNumberMethods_Py2only_GUARD),
BinopSlot(binaryfunc, "nb_remainder", "__mod__"),
BinopSlot(binaryfunc, "nb_divmod", "__divmod__"),
BinopSlot(ternaryfunc, "nb_power", "__pow__"),
MethodSlot(unaryfunc, "nb_negative", "__neg__"),
MethodSlot(unaryfunc, "nb_positive", "__pos__"),
MethodSlot(unaryfunc, "nb_absolute", "__abs__"),
- MethodSlot(inquiry, "nb_nonzero", "__nonzero__", py3 = ("nb_bool", "__bool__")),
+ MethodSlot(inquiry, "nb_bool", "__bool__", py2 = ("nb_nonzero", "__nonzero__")),
MethodSlot(unaryfunc, "nb_invert", "__invert__"),
BinopSlot(binaryfunc, "nb_lshift", "__lshift__"),
BinopSlot(binaryfunc, "nb_rshift", "__rshift__"),
BinopSlot(binaryfunc, "nb_and", "__and__"),
BinopSlot(binaryfunc, "nb_xor", "__xor__"),
BinopSlot(binaryfunc, "nb_or", "__or__"),
- EmptySlot("nb_coerce", ifdef = PyNumberMethods_Py3_GUARD),
+ EmptySlot("nb_coerce", ifdef = PyNumberMethods_Py2only_GUARD),
MethodSlot(unaryfunc, "nb_int", "__int__", fallback="__long__"),
MethodSlot(unaryfunc, "nb_long", "__long__", fallback="__int__", py3 = "<RESERVED>"),
MethodSlot(unaryfunc, "nb_float", "__float__"),
- MethodSlot(unaryfunc, "nb_oct", "__oct__", ifdef = PyNumberMethods_Py3_GUARD),
- MethodSlot(unaryfunc, "nb_hex", "__hex__", ifdef = PyNumberMethods_Py3_GUARD),
+ MethodSlot(unaryfunc, "nb_oct", "__oct__", ifdef = PyNumberMethods_Py2only_GUARD),
+ MethodSlot(unaryfunc, "nb_hex", "__hex__", ifdef = PyNumberMethods_Py2only_GUARD),
# Added in release 2.0
MethodSlot(ibinaryfunc, "nb_inplace_add", "__iadd__"),
MethodSlot(ibinaryfunc, "nb_inplace_subtract", "__isub__"),
MethodSlot(ibinaryfunc, "nb_inplace_multiply", "__imul__"),
- MethodSlot(ibinaryfunc, "nb_inplace_divide", "__idiv__", ifdef = PyNumberMethods_Py3_GUARD),
+ MethodSlot(ibinaryfunc, "nb_inplace_divide", "__idiv__", ifdef = PyNumberMethods_Py2only_GUARD),
MethodSlot(ibinaryfunc, "nb_inplace_remainder", "__imod__"),
MethodSlot(ibinaryfunc, "nb_inplace_power", "__ipow__"), # actually ternaryfunc!!!
MethodSlot(ibinaryfunc, "nb_inplace_lshift", "__ilshift__"),
@@ -992,7 +1044,7 @@ slot_table = (
SyntheticSlot("tp_descr_get", ["__get__"], "0"),
SyntheticSlot("tp_descr_set", ["__set__", "__delete__"], "0"),
- DictOffsetSlot("tp_dictoffset"),
+ DictOffsetSlot("tp_dictoffset", ifdef="!CYTHON_USE_TYPE_SPECS"), # otherwise set via "__dictoffset__" member
MethodSlot(initproc, "tp_init", "__init__"),
EmptySlot("tp_alloc"), #FixedSlot("tp_alloc", "PyType_GenericAlloc"),
diff --git a/Cython/Utility/AsyncGen.c b/Cython/Utility/AsyncGen.c
index ab2dbdb90..8aee0e78a 100644
--- a/Cython/Utility/AsyncGen.c
+++ b/Cython/Utility/AsyncGen.c
@@ -47,7 +47,7 @@ static __pyx_CoroutineObject *__Pyx_AsyncGen_New(
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);
//////////////////// AsyncGenerator.cleanup ////////////////////
@@ -322,6 +322,10 @@ static PyMemberDef __Pyx_async_gen_memberlist[] = {
//ADDED: "ag_await"
{(char*) "ag_await", T_OBJECT, offsetof(__pyx_CoroutineObject, yieldfrom), READONLY,
(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 */
};
@@ -350,6 +354,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
static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_as_async = {
0, /* am_await */
@@ -435,6 +464,7 @@ static PyTypeObject __pyx_AsyncGenType_type = {
0, /*tp_pypy_flags*/
#endif
};
+#endif /* CYTHON_USE_TYPE_SPECS */
static int
@@ -446,14 +476,14 @@ __Pyx_PyAsyncGen_ClearFreeLists(void)
__pyx__PyAsyncGenWrappedValue *o;
o = __Pyx_ag_value_freelist[--__Pyx_ag_value_freelist_free];
assert(__pyx__PyAsyncGenWrappedValue_CheckExact(o));
- PyObject_GC_Del(o);
+ __Pyx_PyHeapTypeObject_GC_Del(o);
}
while (__Pyx_ag_asend_freelist_free) {
__pyx_PyAsyncGenASend *o;
o = __Pyx_ag_asend_freelist[--__Pyx_ag_asend_freelist_free];
assert(__Pyx_IS_TYPE(o, __pyx__PyAsyncGenASendType));
- PyObject_GC_Del(o);
+ __Pyx_PyHeapTypeObject_GC_Del(o);
}
return ret;
@@ -507,7 +537,7 @@ __Pyx_async_gen_asend_dealloc(__pyx_PyAsyncGenASend *o)
assert(__pyx_PyAsyncGenASend_CheckExact(o));
__Pyx_ag_asend_freelist[__Pyx_ag_asend_freelist_free++] = o;
} else {
- PyObject_GC_Del(o);
+ __Pyx_PyHeapTypeObject_GC_Del(o);
}
}
@@ -603,6 +633,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
static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_asend_as_async = {
PyObject_SelfIter, /* am_await */
@@ -611,7 +661,6 @@ static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_asend_as_async = {
};
#endif
-
static PyTypeObject __pyx__PyAsyncGenASendType_type = {
PyVarObject_HEAD_INIT(0, 0)
"async_generator_asend", /* tp_name */
@@ -683,6 +732,7 @@ static PyTypeObject __pyx__PyAsyncGenASendType_type = {
0, /*tp_pypy_flags*/
#endif
};
+#endif /* CYTHON_USE_TYPE_SPECS */
static PyObject *
@@ -725,7 +775,7 @@ __Pyx_async_gen_wrapped_val_dealloc(__pyx__PyAsyncGenWrappedValue *o)
assert(__pyx__PyAsyncGenWrappedValue_CheckExact(o));
__Pyx_ag_value_freelist[__Pyx_ag_value_freelist_free++] = o;
} else {
- PyObject_GC_Del(o);
+ __Pyx_PyHeapTypeObject_GC_Del(o);
}
}
@@ -739,6 +789,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 = {
PyVarObject_HEAD_INIT(0, 0)
"async_generator_wrapped_value", /* tp_name */
@@ -801,6 +867,7 @@ static PyTypeObject __pyx__PyAsyncGenWrappedValueType_type = {
0, /*tp_pypy_flags*/
#endif
};
+#endif /* CYTHON_USE_TYPE_SPECS */
static PyObject *
@@ -838,7 +905,7 @@ __Pyx_async_gen_athrow_dealloc(__pyx_PyAsyncGenAThrow *o)
PyObject_GC_UnTrack((PyObject *)o);
Py_CLEAR(o->agt_gen);
Py_CLEAR(o->agt_args);
- PyObject_GC_Del(o);
+ __Pyx_PyHeapTypeObject_GC_Del(o);
}
@@ -1038,6 +1105,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
static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_athrow_as_async = {
PyObject_SelfIter, /* am_await */
@@ -1046,7 +1134,6 @@ static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_athrow_as_async = {
};
#endif
-
static PyTypeObject __pyx__PyAsyncGenAThrowType_type = {
PyVarObject_HEAD_INIT(0, 0)
"async_generator_athrow", /* tp_name */
@@ -1117,6 +1204,7 @@ static PyTypeObject __pyx__PyAsyncGenAThrowType_type = {
0, /*tp_pypy_flags*/
#endif
};
+#endif /* CYTHON_USE_TYPE_SPECS */
static PyObject *
@@ -1139,26 +1227,42 @@ __Pyx_async_gen_athrow_new(__pyx_PyAsyncGenObject *gen, PyObject *args)
/* ---------- 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
__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);
+#endif
if (unlikely(!__pyx_AsyncGenType))
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);
+#endif
if (unlikely(!__pyx__PyAsyncGenAThrowType))
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);
+#endif
if (unlikely(!__pyx__PyAsyncGenWrappedValueType))
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);
+#endif
if (unlikely(!__pyx__PyAsyncGenASendType))
return -1;
diff --git a/Cython/Utility/CommonStructures.c b/Cython/Utility/CommonStructures.c
index 4b572defb..80055a330 100644
--- a/Cython/Utility/CommonStructures.c
+++ b/Cython/Utility/CommonStructures.c
@@ -1,11 +1,13 @@
/////////////// FetchCommonType.proto ///////////////
+#if !CYTHON_USE_TYPE_SPECS
static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type);
-#if CYTHON_COMPILING_IN_LIMITED_API
-static PyTypeObject* __Pyx_FetchCommonTypeFromSpec(PyType_Spec *spec, PyObject *bases);
+#else
+static PyTypeObject* __Pyx_FetchCommonTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases);
#endif
/////////////// FetchCommonType ///////////////
+//@requires:ExtensionTypes.c::FixUpExtensionType
static PyObject *__Pyx_FetchSharedCythonABIModule(void) {
PyObject *abi_module = PyImport_AddModule((char*) __PYX_ABI_MODULE_NAME);
@@ -32,6 +34,7 @@ static int __Pyx_VerifyCachedType(PyObject *cached_type,
return 0;
}
+#if !CYTHON_USE_TYPE_SPECS
static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type) {
PyObject* abi_module;
PyTypeObject *cached_type = NULL;
@@ -68,22 +71,28 @@ bad:
cached_type = NULL;
goto done;
}
+#else
-#if CYTHON_COMPILING_IN_LIMITED_API
-static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyType_Spec *spec, PyObject *bases) {
- PyObject *abi_module, *py_basicsize, *cached_type = NULL;
- Py_ssize_t basicsize;
+static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) {
+ PyObject *abi_module, *cached_type = NULL;
abi_module = __Pyx_FetchSharedCythonABIModule();
if (!abi_module) return NULL;
+
cached_type = PyObject_GetAttrString(abi_module, spec->name);
if (cached_type) {
+ Py_ssize_t basicsize;
+#if CYTHON_COMPILING_IN_LIMITED_API
+ PyObject *py_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);
Py_DECREF(py_basicsize);
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(
cached_type,
spec->name,
@@ -96,8 +105,11 @@ static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyType_Spec *spec, PyObject *
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad;
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(__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;
done:
diff --git a/Cython/Utility/Coroutine.c b/Cython/Utility/Coroutine.c
index a2540d5d4..6cd1b78b4 100644
--- a/Cython/Utility/Coroutine.c
+++ b/Cython/Utility/Coroutine.c
@@ -452,7 +452,7 @@ static PyTypeObject *__pyx_CoroutineAwaitType = 0;
#define __Pyx_Coroutine_New(body, code, closure, name, qualname, module_name) \
__Pyx__Coroutine_New(__pyx_CoroutineType, body, code, closure, name, qualname, module_name)
-static int __pyx_Coroutine_init(void); /*proto*/
+static int __pyx_Coroutine_init(PyObject *module); /*proto*/
static PyObject *__Pyx__Coroutine_await(PyObject *coroutine); /*proto*/
typedef struct {
@@ -474,7 +474,7 @@ static PyTypeObject *__pyx_GeneratorType = 0;
__Pyx__Coroutine_New(__pyx_GeneratorType, body, code, closure, name, qualname, module_name)
static PyObject *__Pyx_Generator_Next(PyObject *self);
-static int __pyx_Generator_init(void); /*proto*/
+static int __pyx_Generator_init(PyObject *module); /*proto*/
//////////////////// AsyncGen ////////////////////
@@ -495,8 +495,8 @@ static int __pyx_Generator_init(void); /*proto*/
//@requires: ObjectHandling.c::PyObjectGetAttrStr
//@requires: ObjectHandling.c::PyObjectGetAttrStrNoError
//@requires: CommonStructures.c::FetchCommonType
+//@requires: ModuleSetupCode.c::IncludeStructmemberH
-#include <structmember.h>
#include <frameobject.h>
#define __Pyx_Coroutine_Undelegate(gen) Py_CLEAR((gen)->yieldfrom)
@@ -1184,7 +1184,7 @@ static void __Pyx_Coroutine_dealloc(PyObject *self) {
}
#endif
__Pyx_Coroutine_clear(self);
- PyObject_GC_Del(gen);
+ __Pyx_PyHeapTypeObject_GC_Del(gen);
}
static void __Pyx_Coroutine_del(PyObject *self) {
@@ -1443,7 +1443,7 @@ static __pyx_CoroutineObject *__Pyx__Coroutine_NewInit(
static void __Pyx_CoroutineAwait_dealloc(PyObject *self) {
PyObject_GC_UnTrack(self);
Py_CLEAR(((__pyx_CoroutineAwaitObject*)self)->coroutine);
- PyObject_GC_Del(self);
+ __Pyx_PyHeapTypeObject_GC_Del(self);
}
static int __Pyx_CoroutineAwait_traverse(__pyx_CoroutineAwaitObject *self, visitproc visit, void *arg) {
@@ -1494,6 +1494,29 @@ static PyMethodDef __pyx_CoroutineAwait_methods[] = {
{0, 0, 0, 0}
};
+#if CYTHON_USE_TYPE_SPECS
+static PyType_Slot __pyx_CoroutineAwaitType_slots[] = {
+ {Py_tp_dealloc, (void *)__Pyx_CoroutineAwait_dealloc},
+ {Py_tp_traverse, (void *)__Pyx_CoroutineAwait_traverse},
+ {Py_tp_clear, (void *)__Pyx_CoroutineAwait_clear},
+#if !CYTHON_COMPILING_IN_PYPY
+ {Py_tp_new, (void *)__Pyx_CoroutineAwait_no_new},
+#endif
+ {Py_tp_methods, (void *)__pyx_CoroutineAwait_methods},
+ {Py_tp_iter, (void *)__Pyx_CoroutineAwait_self},
+ {Py_tp_iternext, (void *)__Pyx_CoroutineAwait_Next},
+ {0, 0},
+};
+
+static PyType_Spec __pyx_CoroutineAwaitType_spec = {
+ __PYX_TYPE_MODULE_PREFIX "coroutine_wrapper",
+ sizeof(__pyx_CoroutineAwaitObject),
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+ __pyx_CoroutineAwaitType_slots
+};
+#else /* CYTHON_USE_TYPE_SPECS */
+
static PyTypeObject __pyx_CoroutineAwaitType_type = {
PyVarObject_HEAD_INIT(0, 0)
__PYX_TYPE_MODULE_PREFIX "coroutine_wrapper", /*tp_name*/
@@ -1559,6 +1582,7 @@ static PyTypeObject __pyx_CoroutineAwaitType_type = {
0, /*tp_pypy_flags*/
#endif
};
+#endif /* CYTHON_USE_TYPE_SPECS */
#if PY_VERSION_HEX < 0x030500B1 || defined(__Pyx_IterableCoroutine_USED) || CYTHON_USE_ASYNC_SLOTS
static CYTHON_INLINE PyObject *__Pyx__Coroutine_await(PyObject *coroutine) {
@@ -1620,7 +1644,10 @@ static PyMemberDef __pyx_Coroutine_memberlist[] = {
{(char*) "cr_await", T_OBJECT, offsetof(__pyx_CoroutineObject, yieldfrom), READONLY,
(char*) PyDoc_STR("object being awaited, or None")},
{(char*) "cr_code", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_code), READONLY, NULL},
- {(char *) "__module__", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_modulename), PY_WRITE_RESTRICTED, 0},
+ {(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}
};
@@ -1634,6 +1661,30 @@ static PyGetSetDef __pyx_Coroutine_getsets[] = {
{0, 0, 0, 0, 0}
};
+#if CYTHON_USE_TYPE_SPECS
+static PyType_Slot __pyx_CoroutineType_slots[] = {
+ {Py_tp_dealloc, (void *)__Pyx_Coroutine_dealloc},
+ {Py_am_await, (void *)&__Pyx_Coroutine_await},
+ {Py_tp_traverse, (void *)__Pyx_Coroutine_traverse},
+ {Py_tp_methods, (void *)__pyx_Coroutine_methods},
+ {Py_tp_members, (void *)__pyx_Coroutine_memberlist},
+ {Py_tp_getset, (void *)__pyx_Coroutine_getsets},
+ {Py_tp_getattro, (void *) __Pyx_PyObject_GenericGetAttrNoDict},
+#if CYTHON_USE_TP_FINALIZE
+ {Py_tp_finalize, (void *)__Pyx_Coroutine_del},
+#endif
+ {0, 0},
+};
+
+static PyType_Spec __pyx_CoroutineType_spec = {
+ __PYX_TYPE_MODULE_PREFIX "coroutine",
+ sizeof(__pyx_CoroutineObject),
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
+ __pyx_CoroutineType_slots
+};
+#else /* CYTHON_USE_TYPE_SPECS */
+
#if CYTHON_USE_ASYNC_SLOTS
static __Pyx_PyAsyncMethodsStruct __pyx_Coroutine_as_async = {
__Pyx_Coroutine_await, /*am_await*/
@@ -1719,20 +1770,30 @@ static PyTypeObject __pyx_CoroutineType_type = {
0, /*tp_pypy_flags*/
#endif
};
+#endif /* CYTHON_USE_TYPE_SPECS */
-static int __pyx_Coroutine_init(void) {
+static int __pyx_Coroutine_init(PyObject *module) {
// on Windows, C-API functions can't be used in slots statically
+#if CYTHON_USE_TYPE_SPECS
+ __pyx_CoroutineType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_CoroutineType_spec, NULL);
+#else
+ (void) module;
__pyx_CoroutineType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict;
__pyx_CoroutineType = __Pyx_FetchCommonType(&__pyx_CoroutineType_type);
+#endif
if (unlikely(!__pyx_CoroutineType))
return -1;
#ifdef __Pyx_IterableCoroutine_USED
- if (unlikely(__pyx_IterableCoroutine_init() == -1))
+ if (unlikely(__pyx_IterableCoroutine_init(module) == -1))
return -1;
#endif
+#if CYTHON_USE_TYPE_SPECS
+ __pyx_CoroutineAwaitType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_CoroutineAwaitType_spec, NULL);
+#else
__pyx_CoroutineAwaitType = __Pyx_FetchCommonType(&__pyx_CoroutineAwaitType_type);
+#endif
if (unlikely(!__pyx_CoroutineAwaitType))
return -1;
return 0;
@@ -1751,13 +1812,39 @@ static PyTypeObject *__pyx_IterableCoroutineType = 0;
#define __Pyx_IterableCoroutine_New(body, code, closure, name, qualname, module_name) \
__Pyx__Coroutine_New(__pyx_IterableCoroutineType, body, code, closure, name, qualname, module_name)
-static int __pyx_IterableCoroutine_init(void);/*proto*/
+static int __pyx_IterableCoroutine_init(PyObject *module);/*proto*/
//////////////////// IterableCoroutine ////////////////////
//@requires: Coroutine
//@requires: CommonStructures.c::FetchCommonType
+#if CYTHON_USE_TYPE_SPECS
+static PyType_Slot __pyx_IterableCoroutineType_slots[] = {
+ {Py_tp_dealloc, (void *)__Pyx_Coroutine_dealloc},
+ {Py_am_await, (void *)&__Pyx_Coroutine_await},
+ {Py_tp_traverse, (void *)__Pyx_Coroutine_traverse},
+ {Py_tp_iter, (void *)__Pyx_Coroutine_await},
+ {Py_tp_iternext, (void *)__Pyx_Generator_Next},
+ {Py_tp_methods, (void *)__pyx_Coroutine_methods},
+ {Py_tp_members, (void *)__pyx_Coroutine_memberlist},
+ {Py_tp_getset, (void *)__pyx_Coroutine_getsets},
+ {Py_tp_getattro, (void *) __Pyx_PyObject_GenericGetAttrNoDict},
+#if CYTHON_USE_TP_FINALIZE
+ {Py_tp_finalize, (void *)__Pyx_Coroutine_del},
+#endif
+ {0, 0},
+};
+
+static PyType_Spec __pyx_IterableCoroutineType_spec = {
+ __PYX_TYPE_MODULE_PREFIX "iterable_coroutine",
+ sizeof(__pyx_CoroutineObject),
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
+ __pyx_IterableCoroutineType_slots
+};
+#else /* CYTHON_USE_TYPE_SPECS */
+
static PyTypeObject __pyx_IterableCoroutineType_type = {
PyVarObject_HEAD_INIT(0, 0)
__PYX_TYPE_MODULE_PREFIX "iterable_coroutine", /*tp_name*/
@@ -1833,11 +1920,17 @@ static PyTypeObject __pyx_IterableCoroutineType_type = {
0, /*tp_pypy_flags*/
#endif
};
+#endif /* CYTHON_USE_TYPE_SPECS */
-static int __pyx_IterableCoroutine_init(void) {
+static int __pyx_IterableCoroutine_init(PyObject *module) {
+#if CYTHON_USE_TYPE_SPECS
+ __pyx_IterableCoroutineType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_IterableCoroutineType_spec, NULL);
+#else
+ (void) module;
__pyx_IterableCoroutineType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict;
__pyx_IterableCoroutineType = __Pyx_FetchCommonType(&__pyx_IterableCoroutineType_type);
+#endif
if (unlikely(!__pyx_IterableCoroutineType))
return -1;
return 0;
@@ -1864,6 +1957,10 @@ static PyMemberDef __pyx_Generator_memberlist[] = {
{(char*) "gi_yieldfrom", T_OBJECT, offsetof(__pyx_CoroutineObject, yieldfrom), READONLY,
(char*) PyDoc_STR("object being iterated by 'yield from', or None")},
{(char*) "gi_code", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_code), READONLY, NULL},
+ {(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}
};
@@ -1873,10 +1970,35 @@ static PyGetSetDef __pyx_Generator_getsets[] = {
{(char *) "__qualname__", (getter)__Pyx_Coroutine_get_qualname, (setter)__Pyx_Coroutine_set_qualname,
(char*) PyDoc_STR("qualified name of the generator"), 0},
{(char *) "gi_frame", (getter)__Pyx_Coroutine_get_frame, NULL,
- (char*) PyDoc_STR("Frame of the coroutine"), 0},
+ (char*) PyDoc_STR("Frame of the generator"), 0},
{0, 0, 0, 0, 0}
};
+#if CYTHON_USE_TYPE_SPECS
+static PyType_Slot __pyx_GeneratorType_slots[] = {
+ {Py_tp_dealloc, (void *)__Pyx_Coroutine_dealloc},
+ {Py_tp_traverse, (void *)__Pyx_Coroutine_traverse},
+ {Py_tp_iter, (void *)PyObject_SelfIter},
+ {Py_tp_iternext, (void *)__Pyx_Generator_Next},
+ {Py_tp_methods, (void *)__pyx_Generator_methods},
+ {Py_tp_members, (void *)__pyx_Generator_memberlist},
+ {Py_tp_getset, (void *)__pyx_Generator_getsets},
+ {Py_tp_getattro, (void *) __Pyx_PyObject_GenericGetAttrNoDict},
+#if CYTHON_USE_TP_FINALIZE
+ {Py_tp_finalize, (void *)__Pyx_Coroutine_del},
+#endif
+ {0, 0},
+};
+
+static PyType_Spec __pyx_GeneratorType_spec = {
+ __PYX_TYPE_MODULE_PREFIX "generator",
+ sizeof(__pyx_CoroutineObject),
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
+ __pyx_GeneratorType_slots
+};
+#else /* CYTHON_USE_TYPE_SPECS */
+
static PyTypeObject __pyx_GeneratorType_type = {
PyVarObject_HEAD_INIT(0, 0)
__PYX_TYPE_MODULE_PREFIX "generator", /*tp_name*/
@@ -1886,7 +2008,7 @@ static PyTypeObject __pyx_GeneratorType_type = {
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
- 0, /*tp_compare / tp_as_async*/
+ 0, /*tp_as_async*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
@@ -1944,13 +2066,18 @@ static PyTypeObject __pyx_GeneratorType_type = {
0, /*tp_pypy_flags*/
#endif
};
+#endif /* CYTHON_USE_TYPE_SPECS */
-static int __pyx_Generator_init(void) {
+static int __pyx_Generator_init(PyObject *module) {
+#if CYTHON_USE_TYPE_SPECS
+ __pyx_GeneratorType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_GeneratorType_spec, NULL);
+#else
+ (void) module;
// on Windows, C-API functions can't be used in slots statically
__pyx_GeneratorType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict;
__pyx_GeneratorType_type.tp_iter = PyObject_SelfIter;
-
__pyx_GeneratorType = __Pyx_FetchCommonType(&__pyx_GeneratorType_type);
+#endif
if (unlikely(!__pyx_GeneratorType)) {
return -1;
}
@@ -2283,11 +2410,15 @@ old_types.add(_cython_generator_type)
#define __Pyx_StopAsyncIteration_USED
static PyObject *__Pyx_PyExc_StopAsyncIteration;
-static int __pyx_StopAsyncIteration_init(void); /*proto*/
+static int __pyx_StopAsyncIteration_init(PyObject *module); /*proto*/
//////////////////// StopAsyncIteration ////////////////////
#if PY_VERSION_HEX < 0x030500B1
+#if CYTHON_USE_TYPE_SPECS
+#error Using async coroutines with type specs requires Python 3.5 or later.
+#else
+
static PyTypeObject __Pyx__PyExc_StopAsyncIteration_type = {
PyVarObject_HEAD_INIT(0, 0)
"StopAsyncIteration", /*tp_name*/
@@ -2344,9 +2475,11 @@ static PyTypeObject __Pyx__PyExc_StopAsyncIteration_type = {
#endif
};
#endif
+#endif
-static int __pyx_StopAsyncIteration_init(void) {
+static int __pyx_StopAsyncIteration_init(PyObject *module) {
#if PY_VERSION_HEX >= 0x030500B1
+ (void) module;
__Pyx_PyExc_StopAsyncIteration = PyExc_StopAsyncIteration;
#else
PyObject *builtins = PyEval_GetBuiltins();
@@ -2364,6 +2497,7 @@ static int __pyx_StopAsyncIteration_init(void) {
__Pyx__PyExc_StopAsyncIteration_type.tp_dictoffset = ((PyTypeObject*)PyExc_BaseException)->tp_dictoffset;
__Pyx__PyExc_StopAsyncIteration_type.tp_base = (PyTypeObject*)PyExc_Exception;
+ (void) module;
__Pyx_PyExc_StopAsyncIteration = (PyObject*) __Pyx_FetchCommonType(&__Pyx__PyExc_StopAsyncIteration_type);
if (unlikely(!__Pyx_PyExc_StopAsyncIteration))
return -1;
diff --git a/Cython/Utility/CythonFunction.c b/Cython/Utility/CythonFunction.c
index 69e325e12..b3021b944 100644
--- a/Cython/Utility/CythonFunction.c
+++ b/Cython/Utility/CythonFunction.c
@@ -10,8 +10,16 @@
#define __Pyx_CyFunction_GetClosure(f) \
(((__pyx_CyFunctionObject *) (f))->func_closure)
-#define __Pyx_CyFunction_GetClassObj(f) \
- (((__pyx_CyFunctionObject *) (f))->func_classobj)
+
+#if PY_VERSION_HEX < 0x030900B1
+ #define __Pyx_CyFunction_GetClassObj(f) \
+ (((__pyx_CyFunctionObject *) (f))->func_classobj)
+#else
+ #define __Pyx_CyFunction_GetClassObj(f) \
+ ((PyObject*) ((PyCMethodObject *) (f))->mm_class)
+#endif
+#define __Pyx_CyFunction_SetClassObj(f, classobj) \
+ __Pyx__CyFunction_SetClassObj((__pyx_CyFunctionObject *) (f), (classobj))
#define __Pyx_CyFunction_Defaults(type, f) \
((type *)(((__pyx_CyFunctionObject *) (f))->defaults))
@@ -20,7 +28,12 @@
typedef struct {
+#if PY_VERSION_HEX < 0x030900B1
PyCFunctionObject func;
+#else
+ // PEP-573: PyCFunctionObject + mm_class
+ PyCMethodObject func;
+#endif
#if CYTHON_BACKPORT_VECTORCALL
__pyx_vectorcallfunc func_vectorcall;
#endif
@@ -34,9 +47,10 @@ typedef struct {
PyObject *func_globals;
PyObject *func_code;
PyObject *func_closure;
+#if PY_VERSION_HEX < 0x030900B1
// No-args super() class cell
PyObject *func_classobj;
-
+#endif
// Dynamic default args and annotations
void *defaults;
int defaults_pyobjects;
@@ -53,7 +67,7 @@ typedef struct {
PyObject *func_is_coroutine;
} __pyx_CyFunctionObject;
-#if !CYTHON_COMPILING_IN_LIMITED_API
+#if !CYTHON_USE_MODULE_STATE
static PyTypeObject *__pyx_CyFunctionType = 0;
#endif
@@ -67,6 +81,7 @@ static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject* op, PyMethodDef *
PyObject *module, PyObject *globals,
PyObject* code);
+static CYTHON_INLINE void __Pyx__CyFunction_SetClassObj(__pyx_CyFunctionObject* f, PyObject* classobj);
static CYTHON_INLINE void *__Pyx_CyFunction_InitDefaults(PyObject *m,
size_t size,
int pyobjects);
@@ -78,16 +93,17 @@ static CYTHON_INLINE void __Pyx_CyFunction_SetAnnotationsDict(PyObject *m,
PyObject *dict);
-static int __pyx_CyFunction_init(void);
+static int __pyx_CyFunction_init(PyObject *module);
#if CYTHON_METH_FASTCALL
static PyObject * __Pyx_CyFunction_Vectorcall_NOARGS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
static PyObject * __Pyx_CyFunction_Vectorcall_O(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
+static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS_METHOD(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
#if CYTHON_BACKPORT_VECTORCALL
#define __Pyx_CyFunction_func_vectorcall(f) (((__pyx_CyFunctionObject*)f)->func_vectorcall)
#else
-#define __Pyx_CyFunction_func_vectorcall(f) (((__pyx_CyFunctionObject*)f)->func.vectorcall)
+#define __Pyx_CyFunction_func_vectorcall(f) (((PyCFunctionObject*)f)->vectorcall)
#endif
#endif
@@ -96,19 +112,31 @@ static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS(PyObject *func,
//@requires: CommonStructures.c::FetchCommonType
//@requires: ObjectHandling.c::PyMethodNew
//@requires: ObjectHandling.c::PyVectorcallFastCallDict
+//@requires: ModuleSetupCode.c::IncludeStructmemberH
//@requires: ObjectHandling.c::PyObjectGetAttrStr
-#include <structmember.h>
+static CYTHON_INLINE void __Pyx__CyFunction_SetClassObj(__pyx_CyFunctionObject* f, PyObject* classobj) {
+ __Pyx_Py_XDECREF_SET(
+#if PY_VERSION_HEX < 0x030900B1
+ __Pyx_CyFunction_GetClassObj(f),
+#else
+ // assigning to "mm_class", which is a "PyTypeObject*"
+ ((PyCMethodObject *) (f))->mm_class,
+ (PyTypeObject*)
+#endif
+ ((classobj) ? __Pyx_NewRef(classobj) : NULL)
+ );
+}
static PyObject *
__Pyx_CyFunction_get_doc(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *closure)
{
if (unlikely(op->func_doc == NULL)) {
- if (op->func.m_ml->ml_doc) {
+ if (((PyCFunctionObject*)op)->m_ml->ml_doc) {
#if PY_MAJOR_VERSION >= 3
- op->func_doc = PyUnicode_FromString(op->func.m_ml->ml_doc);
+ op->func_doc = PyUnicode_FromString(((PyCFunctionObject*)op)->m_ml->ml_doc);
#else
- op->func_doc = PyString_FromString(op->func.m_ml->ml_doc);
+ op->func_doc = PyString_FromString(((PyCFunctionObject*)op)->m_ml->ml_doc);
#endif
if (unlikely(op->func_doc == NULL))
return NULL;
@@ -138,9 +166,9 @@ __Pyx_CyFunction_get_name(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *contex
{
if (unlikely(op->func_name == NULL)) {
#if PY_MAJOR_VERSION >= 3
- op->func_name = PyUnicode_InternFromString(op->func.m_ml->ml_name);
+ op->func_name = PyUnicode_InternFromString(((PyCFunctionObject*)op)->m_ml->ml_name);
#else
- op->func_name = PyString_InternFromString(op->func.m_ml->ml_name);
+ op->func_name = PyString_InternFromString(((PyCFunctionObject*)op)->m_ml->ml_name);
#endif
if (unlikely(op->func_name == NULL))
return NULL;
@@ -437,9 +465,16 @@ static PyGetSetDef __pyx_CyFunction_getsets[] = {
};
static PyMemberDef __pyx_CyFunction_members[] = {
- {(char *) "__module__", T_OBJECT, offsetof(PyCFunctionObject, m_module), PY_WRITE_RESTRICTED, 0},
-#if CYTHON_COMPILING_IN_LIMITED_API
+ {(char *) "__module__", T_OBJECT, offsetof(PyCFunctionObject, m_module), 0, 0},
+#if CYTHON_USE_TYPE_SPECS
{(char *) "__dictoffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_dict), READONLY, 0},
+#if CYTHON_METH_FASTCALL
+#if CYTHON_BACKPORT_VECTORCALL
+ {(char *) "__vectorcalloffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_vectorcall), READONLY, 0},
+#else
+ {(char *) "__vectorcalloffset__", T_PYSSIZET, offsetof(PyCFunctionObject, vectorcall), READONLY, 0},
+#endif
+#endif
#if PY_VERSION_HEX < 0x030500A0
{(char *) "__weaklistoffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_weakreflist), READONLY, 0},
#else
@@ -456,7 +491,7 @@ __Pyx_CyFunction_reduce(__pyx_CyFunctionObject *m, CYTHON_UNUSED PyObject *args)
Py_INCREF(m->func_qualname);
return m->func_qualname;
#else
- return PyString_FromString(m->func.m_ml->ml_name);
+ return PyString_FromString(((PyCFunctionObject*)m)->m_ml->ml_name);
#endif
}
@@ -469,27 +504,32 @@ static PyMethodDef __pyx_CyFunction_methods[] = {
#if PY_VERSION_HEX < 0x030500A0
#define __Pyx_CyFunction_weakreflist(cyfunc) ((cyfunc)->func_weakreflist)
#else
-#define __Pyx_CyFunction_weakreflist(cyfunc) ((cyfunc)->func.m_weakreflist)
+#define __Pyx_CyFunction_weakreflist(cyfunc) (((PyCFunctionObject*)cyfunc)->m_weakreflist)
#endif
static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject *op, PyMethodDef *ml, int flags, PyObject* qualname,
PyObject *closure, PyObject *module, PyObject* globals, PyObject* code) {
+ PyCFunctionObject *cf = (PyCFunctionObject*) op;
if (unlikely(op == NULL))
return NULL;
op->flags = flags;
__Pyx_CyFunction_weakreflist(op) = NULL;
- op->func.m_ml = ml;
- op->func.m_self = (PyObject *) op;
+ cf->m_ml = ml;
+ cf->m_self = (PyObject *) op;
Py_XINCREF(closure);
op->func_closure = closure;
Py_XINCREF(module);
- op->func.m_module = module;
+ cf->m_module = module;
op->func_dict = NULL;
op->func_name = NULL;
Py_INCREF(qualname);
op->func_qualname = qualname;
op->func_doc = NULL;
+#if PY_VERSION_HEX < 0x030900B1
op->func_classobj = NULL;
+#else
+ ((PyCMethodObject*)op)->mm_class = NULL;
+#endif
op->func_globals = globals;
Py_INCREF(op->func_globals);
Py_XINCREF(code);
@@ -504,7 +544,7 @@ static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject *op, PyMethodDef *
op->func_annotations = NULL;
op->func_is_coroutine = NULL;
#if CYTHON_METH_FASTCALL
- switch (ml->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O | METH_KEYWORDS)) {
+ switch (ml->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O | METH_KEYWORDS | METH_METHOD)) {
case METH_NOARGS:
__Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_NOARGS;
break;
@@ -512,6 +552,9 @@ static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject *op, PyMethodDef *
__Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_O;
break;
// case METH_FASTCALL is not used
+ case METH_METHOD | METH_FASTCALL | METH_KEYWORDS:
+ __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS_METHOD;
+ break;
case METH_FASTCALL | METH_KEYWORDS:
__Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS;
break;
@@ -532,14 +575,22 @@ static int
__Pyx_CyFunction_clear(__pyx_CyFunctionObject *m)
{
Py_CLEAR(m->func_closure);
- Py_CLEAR(m->func.m_module);
+ Py_CLEAR(((PyCFunctionObject*)m)->m_module);
Py_CLEAR(m->func_dict);
Py_CLEAR(m->func_name);
Py_CLEAR(m->func_qualname);
Py_CLEAR(m->func_doc);
Py_CLEAR(m->func_globals);
Py_CLEAR(m->func_code);
- Py_CLEAR(m->func_classobj);
+#if PY_VERSION_HEX < 0x030900B1
+ Py_CLEAR(__Pyx_CyFunction_GetClassObj(m));
+#else
+ {
+ PyObject *cls = (PyObject*) ((PyCMethodObject *) (m))->mm_class;
+ ((PyCMethodObject *) (m))->mm_class = NULL;
+ Py_XDECREF(cls);
+ }
+#endif
Py_CLEAR(m->defaults_tuple);
Py_CLEAR(m->defaults_kwdict);
Py_CLEAR(m->func_annotations);
@@ -564,7 +615,7 @@ static void __Pyx__CyFunction_dealloc(__pyx_CyFunctionObject *m)
if (__Pyx_CyFunction_weakreflist(m) != NULL)
PyObject_ClearWeakRefs((PyObject *) m);
__Pyx_CyFunction_clear(m);
- PyObject_GC_Del(m);
+ __Pyx_PyHeapTypeObject_GC_Del(m);
}
static void __Pyx_CyFunction_dealloc(__pyx_CyFunctionObject *m)
@@ -576,14 +627,14 @@ static void __Pyx_CyFunction_dealloc(__pyx_CyFunctionObject *m)
static int __Pyx_CyFunction_traverse(__pyx_CyFunctionObject *m, visitproc visit, void *arg)
{
Py_VISIT(m->func_closure);
- Py_VISIT(m->func.m_module);
+ Py_VISIT(((PyCFunctionObject*)m)->m_module);
Py_VISIT(m->func_dict);
Py_VISIT(m->func_name);
Py_VISIT(m->func_qualname);
Py_VISIT(m->func_doc);
Py_VISIT(m->func_globals);
Py_VISIT(m->func_code);
- Py_VISIT(m->func_classobj);
+ Py_VISIT(__Pyx_CyFunction_GetClassObj(m));
Py_VISIT(m->defaults_tuple);
Py_VISIT(m->defaults_kwdict);
Py_VISIT(m->func_is_coroutine);
@@ -727,14 +778,14 @@ static CYTHON_INLINE int __Pyx_CyFunction_Vectorcall_CheckArgs(__pyx_CyFunctionO
if ((cyfunc->flags & __Pyx_CYFUNCTION_CCLASS) && !(cyfunc->flags & __Pyx_CYFUNCTION_STATICMETHOD)) {
if (unlikely(nargs < 1)) {
PyErr_Format(PyExc_TypeError, "%.200s() needs an argument",
- cyfunc->func.m_ml->ml_name);
+ ((PyCFunctionObject*)cyfunc)->m_ml->ml_name);
return -1;
}
ret = 1;
}
if (unlikely(kwnames) && unlikely(PyTuple_GET_SIZE(kwnames))) {
PyErr_Format(PyExc_TypeError,
- "%.200s() takes no keyword arguments", cyfunc->func.m_ml->ml_name);
+ "%.200s() takes no keyword arguments", ((PyCFunctionObject*)cyfunc)->m_ml->ml_name);
return -1;
}
return ret;
@@ -743,7 +794,7 @@ static CYTHON_INLINE int __Pyx_CyFunction_Vectorcall_CheckArgs(__pyx_CyFunctionO
static PyObject * __Pyx_CyFunction_Vectorcall_NOARGS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
{
__pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func;
- PyMethodDef* def = cyfunc->func.m_ml;
+ PyMethodDef* def = ((PyCFunctionObject*)cyfunc)->m_ml;
#if CYTHON_BACKPORT_VECTORCALL
Py_ssize_t nargs = (Py_ssize_t)nargsf;
#else
@@ -757,7 +808,7 @@ static PyObject * __Pyx_CyFunction_Vectorcall_NOARGS(PyObject *func, PyObject *c
nargs -= 1;
break;
case 0:
- self = cyfunc->func.m_self;
+ self = ((PyCFunctionObject*)cyfunc)->m_self;
break;
default:
return NULL;
@@ -775,7 +826,7 @@ static PyObject * __Pyx_CyFunction_Vectorcall_NOARGS(PyObject *func, PyObject *c
static PyObject * __Pyx_CyFunction_Vectorcall_O(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
{
__pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func;
- PyMethodDef* def = cyfunc->func.m_ml;
+ PyMethodDef* def = ((PyCFunctionObject*)cyfunc)->m_ml;
#if CYTHON_BACKPORT_VECTORCALL
Py_ssize_t nargs = (Py_ssize_t)nargsf;
#else
@@ -789,7 +840,7 @@ static PyObject * __Pyx_CyFunction_Vectorcall_O(PyObject *func, PyObject *const
nargs -= 1;
break;
case 0:
- self = cyfunc->func.m_self;
+ self = ((PyCFunctionObject*)cyfunc)->m_self;
break;
default:
return NULL;
@@ -807,7 +858,7 @@ static PyObject * __Pyx_CyFunction_Vectorcall_O(PyObject *func, PyObject *const
static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
{
__pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func;
- PyMethodDef* def = cyfunc->func.m_ml;
+ PyMethodDef* def = ((PyCFunctionObject*)cyfunc)->m_ml;
#if CYTHON_BACKPORT_VECTORCALL
Py_ssize_t nargs = (Py_ssize_t)nargsf;
#else
@@ -821,7 +872,7 @@ static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS(PyObject *func,
nargs -= 1;
break;
case 0:
- self = cyfunc->func.m_self;
+ self = ((PyCFunctionObject*)cyfunc)->m_self;
break;
default:
return NULL;
@@ -829,9 +880,36 @@ static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS(PyObject *func,
return ((_PyCFunctionFastWithKeywords)(void(*)(void))def->ml_meth)(self, args, nargs, kwnames);
}
+
+static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS_METHOD(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
+{
+ __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func;
+ PyMethodDef* def = ((PyCFunctionObject*)cyfunc)->m_ml;
+ PyTypeObject *cls = (PyTypeObject *) __Pyx_CyFunction_GetClassObj(cyfunc);
+#if CYTHON_BACKPORT_VECTORCALL
+ Py_ssize_t nargs = (Py_ssize_t)nargsf;
+#else
+ Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
#endif
+ PyObject *self;
+ switch (__Pyx_CyFunction_Vectorcall_CheckArgs(cyfunc, nargs, NULL)) {
+ case 1:
+ self = args[0];
+ args += 1;
+ nargs -= 1;
+ break;
+ case 0:
+ self = ((PyCFunctionObject*)cyfunc)->m_self;
+ break;
+ default:
+ return NULL;
+ }
-#if CYTHON_COMPILING_IN_LIMITED_API
+ return ((__Pyx_PyCMethod)(void(*)(void))def->ml_meth)(self, cls, args, nargs, kwnames);
+}
+#endif
+
+#if CYTHON_USE_TYPE_SPECS
static PyType_Slot __pyx_CyFunctionType_slots[] = {
{Py_tp_dealloc, (void *)__Pyx_CyFunction_dealloc},
{Py_tp_repr, (void *)__Pyx_CyFunction_repr},
@@ -849,11 +927,17 @@ static PyType_Spec __pyx_CyFunctionType_spec = {
__PYX_TYPE_MODULE_PREFIX "cython_function_or_method",
sizeof(__pyx_CyFunctionObject),
0,
- // TODO: Support _Py_TPFLAGS_HAVE_VECTORCALL and _Py_TPFLAGS_HAVE_VECTORCALL
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+#ifdef Py_TPFLAGS_METHOD_DESCRIPTOR
+ Py_TPFLAGS_METHOD_DESCRIPTOR |
+#endif
+#ifdef _Py_TPFLAGS_HAVE_VECTORCALL
+ _Py_TPFLAGS_HAVE_VECTORCALL |
+#endif
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /*tp_flags*/
__pyx_CyFunctionType_slots
};
-#else
+#else /* CYTHON_USE_TYPE_SPECS */
+
static PyTypeObject __pyx_CyFunctionType_type = {
PyVarObject_HEAD_INIT(0, 0)
__PYX_TYPE_MODULE_PREFIX "cython_function_or_method", /*tp_name*/
@@ -865,7 +949,7 @@ static PyTypeObject __pyx_CyFunctionType_type = {
#elif CYTHON_BACKPORT_VECTORCALL
(printfunc)offsetof(__pyx_CyFunctionObject, func_vectorcall), /*tp_vectorcall_offset backported into tp_print*/
#else
- offsetof(__pyx_CyFunctionObject, func.vectorcall), /*tp_vectorcall_offset*/
+ offsetof(PyCFunctionObject, vectorcall), /*tp_vectorcall_offset*/
#endif
0, /*tp_getattr*/
0, /*tp_setattr*/
@@ -890,7 +974,7 @@ static PyTypeObject __pyx_CyFunctionType_type = {
#ifdef _Py_TPFLAGS_HAVE_VECTORCALL
_Py_TPFLAGS_HAVE_VECTORCALL |
#endif
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /*tp_flags*/
0, /*tp_doc*/
(traverseproc) __Pyx_CyFunction_traverse, /*tp_traverse*/
(inquiry) __Pyx_CyFunction_clear, /*tp_clear*/
@@ -935,13 +1019,14 @@ static PyTypeObject __pyx_CyFunctionType_type = {
0, /*tp_pypy_flags*/
#endif
};
-#endif /* CYTHON_COMPILING_IN_LIMITED_API */
+#endif /* CYTHON_USE_TYPE_SPECS */
-static int __pyx_CyFunction_init(void) {
-#if CYTHON_COMPILING_IN_LIMITED_API
- __pyx_CyFunctionType = __Pyx_FetchCommonTypeFromSpec(&__pyx_CyFunctionType_spec, NULL);
+static int __pyx_CyFunction_init(PyObject *module) {
+#if CYTHON_USE_TYPE_SPECS
+ __pyx_CyFunctionType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_CyFunctionType_spec, NULL);
#else
+ (void) module;
__pyx_CyFunctionType = __Pyx_FetchCommonType(&__pyx_CyFunctionType_type);
#endif
if (unlikely(__pyx_CyFunctionType == NULL)) {
@@ -1023,8 +1108,7 @@ static int __Pyx_CyFunction_InitClassCell(PyObject *cyfunctions, PyObject *class
if (unlikely(!m))
return -1;
#endif
- Py_INCREF(classobj);
- m->func_classobj = classobj;
+ __Pyx_CyFunction_SetClassObj(m, classobj);
#if !(CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS)
Py_DECREF((PyObject*)m);
#endif
@@ -1047,10 +1131,10 @@ static PyObject *__pyx_FusedFunction_New(PyMethodDef *ml, int flags,
PyObject *code);
static int __pyx_FusedFunction_clear(__pyx_FusedFunctionObject *self);
-#if !CYTHON_COMPILING_IN_LIMITED_API
+#if !CYTHON_USE_MODULE_STATE
static PyTypeObject *__pyx_FusedFunctionType = NULL;
#endif
-static int __pyx_FusedFunction_init(void);
+static int __pyx_FusedFunction_init(PyObject *module);
#define __Pyx_FusedFunction_USED
@@ -1153,8 +1237,7 @@ __pyx_FusedFunction_descr_get(PyObject *self, PyObject *obj, PyObject *type)
Py_XINCREF(pydefaults[i]);
}
- Py_XINCREF(func->func.func_classobj);
- meth->func.func_classobj = func->func.func_classobj;
+ __Pyx_CyFunction_SetClassObj(meth, __Pyx_CyFunction_GetClassObj(func));
Py_XINCREF(func->__signatures__);
meth->__signatures__ = func->__signatures__;
@@ -1238,8 +1321,7 @@ __pyx_err:;
__pyx_FusedFunctionObject *unbound = (__pyx_FusedFunctionObject *) unbound_result_func;
// TODO: move this to InitClassCell
- Py_XINCREF(self->func.func_classobj);
- __Pyx_Py_XDECREF_SET(unbound->func.func_classobj, self->func.func_classobj);
+ __Pyx_CyFunction_SetClassObj(unbound, __Pyx_CyFunction_GetClassObj(self));
result_func = __pyx_FusedFunction_descr_get(unbound_result_func,
self->self, self->self);
@@ -1334,8 +1416,7 @@ __pyx_FusedFunction_call(PyObject *func, PyObject *args, PyObject *kw)
if (unlikely(!new_func))
goto bad;
- Py_XINCREF(binding_func->func.func_classobj);
- __Pyx_Py_XDECREF_SET(new_func->func.func_classobj, binding_func->func.func_classobj);
+ __Pyx_CyFunction_SetClassObj(new_func, __Pyx_CyFunction_GetClassObj(binding_func));
func = (PyObject *) new_func;
}
@@ -1377,7 +1458,7 @@ static PyGetSetDef __pyx_FusedFunction_getsets[] = {
{0, 0, 0, 0, 0}
};
-#if CYTHON_COMPILING_IN_LIMITED_API
+#if CYTHON_USE_TYPE_SPECS
static PyType_Slot __pyx_FusedFunctionType_slots[] = {
{Py_tp_dealloc, (void *)__pyx_FusedFunction_dealloc},
{Py_tp_call, (void *)__pyx_FusedFunction_call},
@@ -1398,7 +1479,7 @@ static PyType_Spec __pyx_FusedFunctionType_spec = {
__pyx_FusedFunctionType_slots
};
-#else /* !CYTHON_COMPILING_IN_LIMITED_API */
+#else /* !CYTHON_USE_TYPE_SPECS */
static PyMappingMethods __pyx_FusedFunction_mapping_methods = {
0,
@@ -1474,15 +1555,16 @@ static PyTypeObject __pyx_FusedFunctionType_type = {
};
#endif
-static int __pyx_FusedFunction_init(void) {
-#if CYTHON_COMPILING_IN_LIMITED_API
+static int __pyx_FusedFunction_init(PyObject *module) {
+#if CYTHON_USE_TYPE_SPECS
PyObject *bases = PyTuple_Pack(1, __pyx_CyFunctionType);
if (unlikely(!bases)) {
return -1;
}
- __pyx_FusedFunctionType = __Pyx_FetchCommonTypeFromSpec(&__pyx_FusedFunctionType_spec, bases);
+ __pyx_FusedFunctionType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_FusedFunctionType_spec, bases);
Py_DECREF(bases);
#else
+ (void) module;
// Set base from __Pyx_FetchCommonTypeFromSpec, in case it's different from the local static value.
__pyx_FusedFunctionType_type.tp_base = __pyx_CyFunctionType;
__pyx_FusedFunctionType = __Pyx_FetchCommonType(&__pyx_FusedFunctionType_type);
diff --git a/Cython/Utility/ExtensionTypes.c b/Cython/Utility/ExtensionTypes.c
index 26bc2d9d9..e19df8578 100644
--- a/Cython/Utility/ExtensionTypes.c
+++ b/Cython/Utility/ExtensionTypes.c
@@ -1,13 +1,104 @@
-/////////////// PyType_Ready.proto ///////////////
+/////////////// FixUpExtensionType.proto ///////////////
-static int __Pyx_PyType_Ready(PyTypeObject *t);
+#if CYTHON_USE_TYPE_SPECS
+static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject *type); /*proto*/
+#endif
-/////////////// PyType_Ready ///////////////
-//@requires: ObjectHandling.c::PyObjectCallNoArg
+/////////////// FixUpExtensionType ///////////////
+//@requires:ModuleSetupCode.c::IncludeStructmemberH
+//@requires:StringTools.c::IncludeStringH
-// Wrapper around PyType_Ready() with some runtime checks and fixes
-// to deal with multiple inheritance.
-static int __Pyx_PyType_Ready(PyTypeObject *t) {
+#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
+ 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
+
+
+/////////////// ValidateBasesTuple.proto ///////////////
+
+static int __Pyx_validate_bases_tuple(const char *type_name, Py_ssize_t dictoffset, PyObject *bases); /*proto*/
+
+/////////////// ValidateBasesTuple ///////////////
+
+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
// really are heap types. Otherwise, it would not be safe to
// subclass them.
@@ -18,49 +109,63 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) {
// tp_dictoffset (i.e. there is no __dict__ attribute in the object
// structure), we need to check that none of the base classes sets
// it either.
- int r;
- PyObject *bases = t->tp_bases;
- if (bases)
+ Py_ssize_t i, n = PyTuple_GET_SIZE(bases);
+ for (i = 1; i < n; i++) /* Skip first base */
{
- Py_ssize_t i, n = PyTuple_GET_SIZE(bases);
- for (i = 1; i < n; i++) /* Skip first base */
- {
- PyObject *b0 = PyTuple_GET_ITEM(bases, i);
- PyTypeObject *b;
+ PyObject *b0 = PyTuple_GET_ITEM(bases, i);
+ PyTypeObject *b;
#if PY_MAJOR_VERSION < 3
- /* Disallow old-style classes */
- if (PyClass_Check(b0))
- {
- PyErr_Format(PyExc_TypeError, "base class '%.200s' is an old-style class",
- PyString_AS_STRING(((PyClassObject*)b0)->cl_name));
- return -1;
- }
+ /* Disallow old-style classes */
+ if (PyClass_Check(b0))
+ {
+ PyErr_Format(PyExc_TypeError, "base class '%.200s' is an old-style class",
+ PyString_AS_STRING(((PyClassObject*)b0)->cl_name));
+ return -1;
+ }
#endif
- b = (PyTypeObject*)b0;
- if (!__Pyx_PyType_HasFeature(b, Py_TPFLAGS_HEAPTYPE))
- {
- __Pyx_TypeName b_name = __Pyx_PyType_GetName(b);
- PyErr_Format(PyExc_TypeError,
- "base class '" __Pyx_FMT_TYPENAME "' is not a heap type", b_name);
- __Pyx_DECREF_TypeName(b_name);
- return -1;
- }
- if (t->tp_dictoffset == 0 && b->tp_dictoffset)
- {
- __Pyx_TypeName t_name = __Pyx_PyType_GetName(t);
- __Pyx_TypeName b_name = __Pyx_PyType_GetName(b);
- PyErr_Format(PyExc_TypeError,
- "extension type '" __Pyx_FMT_TYPENAME "' has no __dict__ slot, "
- "but base type '" __Pyx_FMT_TYPENAME "' has: "
- "either add 'cdef dict __dict__' to the extension type "
- "or add '__slots__ = [...]' to the base type",
- t_name, b_name);
- __Pyx_DECREF_TypeName(t_name);
- __Pyx_DECREF_TypeName(b_name);
- return -1;
- }
+ b = (PyTypeObject*) b0;
+ if (!__Pyx_PyType_HasFeature(b, Py_TPFLAGS_HEAPTYPE))
+ {
+ __Pyx_TypeName b_name = __Pyx_PyType_GetName(b);
+ PyErr_Format(PyExc_TypeError,
+ "base class '" __Pyx_FMT_TYPENAME "' is not a heap type", b_name);
+ __Pyx_DECREF_TypeName(b_name);
+ return -1;
+ }
+ if (dictoffset == 0 && b->tp_dictoffset)
+ {
+ __Pyx_TypeName b_name = __Pyx_PyType_GetName(b);
+ PyErr_Format(PyExc_TypeError,
+ "extension type '%.200s' has no __dict__ slot, "
+ "but base type '" __Pyx_FMT_TYPENAME "' has: "
+ "either add 'cdef dict __dict__' to the extension type "
+ "or add '__slots__ = [...]' to the base type",
+ type_name, b_name);
+ __Pyx_DECREF_TypeName(b_name);
+ return -1;
}
}
+ return 0;
+}
+
+
+/////////////// PyType_Ready.proto ///////////////
+
+#if !CYTHON_USE_TYPE_SPECS
+static int __Pyx_PyType_Ready(PyTypeObject *t);
+#endif
+
+/////////////// PyType_Ready ///////////////
+//@requires: ObjectHandling.c::PyObjectCallNoArg
+//@requires: ValidateBasesTuple
+
+// Wrapper around PyType_Ready() with some runtime checks and fixes
+// to deal with multiple inheritance.
+#if !CYTHON_USE_TYPE_SPECS
+static int __Pyx_PyType_Ready(PyTypeObject *t) {
+ 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
{
@@ -136,6 +241,7 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) {
return r;
}
+#endif
/////////////// PyTrashcan.proto ///////////////
diff --git a/Cython/Utility/ImportExport.c b/Cython/Utility/ImportExport.c
index 655781ee1..523de2010 100644
--- a/Cython/Utility/ImportExport.c
+++ b/Cython/Utility/ImportExport.c
@@ -693,22 +693,18 @@ bad:
/////////////// SetVTable.proto ///////////////
-static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
+static int __Pyx_SetVtable(PyTypeObject* typeptr , void* vtable); /*proto*/
/////////////// SetVTable ///////////////
-#if CYTHON_COMPILING_IN_LIMITED_API
-static int __Pyx_SetVtable(PyObject *type, void *vtable) {
-#else
-static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
-#endif
+static int __Pyx_SetVtable(PyTypeObject *type, void *vtable) {
PyObject *ob = PyCapsule_New(vtable, 0, 0);
- if (!ob)
+ if (unlikely(!ob))
goto bad;
#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
- if (PyDict_SetItem(dict, PYIDENT("__pyx_vtable__"), ob) < 0)
+ if (unlikely(PyDict_SetItem(type->tp_dict, PYIDENT("__pyx_vtable__"), ob) < 0))
#endif
goto bad;
Py_DECREF(ob);
diff --git a/Cython/Utility/ModuleSetupCode.c b/Cython/Utility/ModuleSetupCode.c
index 3929bc64b..4ddc9da05 100644
--- a/Cython/Utility/ModuleSetupCode.c
+++ b/Cython/Utility/ModuleSetupCode.c
@@ -61,6 +61,8 @@
#undef CYTHON_USE_TYPE_SLOTS
#define CYTHON_USE_TYPE_SLOTS 0
+ #undef CYTHON_USE_TYPE_SPECS
+ #define CYTHON_USE_TYPE_SPECS 0
#undef CYTHON_USE_PYTYPE_LOOKUP
#define CYTHON_USE_PYTYPE_LOOKUP 0
#if PY_VERSION_HEX < 0x03050000
@@ -96,6 +98,8 @@
#endif
#undef CYTHON_PEP489_MULTI_PHASE_INIT
#define CYTHON_PEP489_MULTI_PHASE_INIT 0
+ #undef CYTHON_USE_MODULE_STATE
+ #define CYTHON_USE_MODULE_STATE 0
#undef CYTHON_USE_TP_FINALIZE
#define CYTHON_USE_TP_FINALIZE 0
#undef CYTHON_USE_DICT_VERSIONS
@@ -112,6 +116,8 @@
#ifndef CYTHON_USE_TYPE_SLOTS
#define CYTHON_USE_TYPE_SLOTS 1
#endif
+ #undef CYTHON_USE_TYPE_SPECS
+ #define CYTHON_USE_TYPE_SPECS 0
#undef CYTHON_USE_PYTYPE_LOOKUP
#define CYTHON_USE_PYTYPE_LOOKUP 0
#undef CYTHON_USE_ASYNC_SLOTS
@@ -146,6 +152,8 @@
#define CYTHON_PEP487_INIT_SUBCLASS 0
#undef CYTHON_PEP489_MULTI_PHASE_INIT
#define CYTHON_PEP489_MULTI_PHASE_INIT 0
+ #undef CYTHON_USE_MODULE_STATE
+ #define CYTHON_USE_MODULE_STATE 0
#undef CYTHON_USE_TP_FINALIZE
#define CYTHON_USE_TP_FINALIZE 0
#undef CYTHON_USE_DICT_VERSIONS
@@ -154,6 +162,7 @@
#define CYTHON_USE_EXC_INFO_STACK 0
#elif defined(CYTHON_LIMITED_API)
+ // EXPERIMENTAL !!
#define CYTHON_COMPILING_IN_PYPY 0
#define CYTHON_COMPILING_IN_PYSTON 0
#define CYTHON_COMPILING_IN_CPYTHON 0
@@ -161,6 +170,8 @@
#undef CYTHON_USE_TYPE_SLOTS
#define CYTHON_USE_TYPE_SLOTS 0
+ #undef CYTHON_USE_TYPE_SPECS
+ #define CYTHON_USE_TYPE_SPECS 1
#undef CYTHON_USE_PYTYPE_LOOKUP
#define CYTHON_USE_PYTYPE_LOOKUP 0
#undef CYTHON_USE_ASYNC_SLOTS
@@ -194,6 +205,8 @@
#endif
#undef CYTHON_PEP489_MULTI_PHASE_INIT
#define CYTHON_PEP489_MULTI_PHASE_INIT 0
+ #undef CYTHON_USE_MODULE_STATE
+ #define CYTHON_USE_MODULE_STATE 1
#ifndef CYTHON_USE_TP_FINALIZE
#define CYTHON_USE_TP_FINALIZE 1
#endif
@@ -211,6 +224,9 @@
#ifndef CYTHON_USE_TYPE_SLOTS
#define CYTHON_USE_TYPE_SLOTS 1
#endif
+ #ifndef CYTHON_USE_TYPE_SPECS
+ #define CYTHON_USE_TYPE_SPECS 0
+ #endif
#ifndef CYTHON_USE_PYTYPE_LOOKUP
#define CYTHON_USE_PYTYPE_LOOKUP 1
#endif
@@ -262,17 +278,33 @@
#ifndef CYTHON_PEP487_INIT_SUBCLASS
#define CYTHON_PEP487_INIT_SUBCLASS 1
#endif
- #ifndef CYTHON_PEP489_MULTI_PHASE_INIT
- #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000)
+ #if 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
- #ifndef CYTHON_USE_TP_FINALIZE
- #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1)
+ #ifndef CYTHON_USE_MODULE_STATE
+ // EXPERIMENTAL !!
+ #define CYTHON_USE_MODULE_STATE 0
#endif
- #ifndef CYTHON_USE_DICT_VERSIONS
- #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1)
+ #if PY_VERSION_HEX < 0x030400a1
+ #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
- #ifndef CYTHON_USE_EXC_INFO_STACK
- #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3)
+ #if 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
@@ -565,6 +597,18 @@ class __Pyx_FakeReference {
#define __Pyx_PyVectorcall_NARGS(n) ((Py_ssize_t)(n))
#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)
#define PyObject_Malloc(s) PyMem_Malloc(s)
#define PyObject_Free(p) PyMem_Free(p)
@@ -604,7 +648,7 @@ class __Pyx_FakeReference {
#endif
#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;
@@ -704,20 +748,30 @@ static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStrWithError(PyObject *dict,
#endif
/* 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
+ #define __Pyx_PyType_GetFlags(tp) (((PyTypeObject *)tp)->tp_flags)
#define __Pyx_PyType_HasFeature(type, feature) ((__Pyx_PyType_GetFlags(type) & (feature)) != 0)
#define __Pyx_PyObject_GetIterNextFunc(obj) (Py_TYPE(obj)->tp_iternext)
#else
+ #define __Pyx_PyType_GetFlags(tp) (PyType_GetFlags((PyTypeObject *)tp))
#define __Pyx_PyType_HasFeature(type, feature) PyType_HasFeature(type, feature)
#define __Pyx_PyObject_GetIterNextFunc(obj) PyIter_Next
#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
#define CYTHON_PEP393_ENABLED 1
#define __Pyx_PyUnicode_READY(op) (0)
@@ -902,6 +956,12 @@ static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStrWithError(PyObject *dict,
} __Pyx_PyAsyncMethodsStruct;
#endif
+
+/////////////// IncludeStructmemberH.proto ///////////////
+
+#include <structmember.h>
+
+
/////////////// SmallCodeConfig.proto ///////////////
#ifndef CYTHON_SMALL_CODE
diff --git a/Cython/Utility/ObjectHandling.c b/Cython/Utility/ObjectHandling.c
index 903c03833..bd6e438da 100644
--- a/Cython/Utility/ObjectHandling.c
+++ b/Cython/Utility/ObjectHandling.c
@@ -1575,6 +1575,7 @@ static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name)
#endif
{
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_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1
// Identifier names are always interned and have a pre-calculated hash value.
diff --git a/appveyor.yml b/appveyor.yml
index a6ad04ea7..8148e517c 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -9,6 +9,7 @@ environment:
WITH_ENV: "cmd /E:ON /V:ON /C .\\appveyor\\run_with_env.cmd"
BACKEND: c
PARALLEL: "-j4"
+ EXTRA_CFLAGS: ""
matrix:
- PYTHON: "C:\\Python27"
@@ -38,6 +39,11 @@ environment:
- PYTHON: "C:\\Python38-x64"
PYTHON_VERSION: "3.8"
PYTHON_ARCH: "64"
+ EXTRA_CFLAGS: "-DCYTHON_USE_TYPE_SPECS=1"
+
+ - PYTHON: "C:\\Python38-x64"
+ PYTHON_VERSION: "3.8"
+ PYTHON_ARCH: "64"
BACKEND: c,cpp
- PYTHON: "C:\\Python37"
@@ -49,6 +55,16 @@ environment:
PYTHON_VERSION: "3.7"
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_VERSION: "3.6"
PYTHON_ARCH: "32"
@@ -108,7 +124,7 @@ test: off
test_script:
- "%PYTHON%\\Scripts\\pip.exe install -r test-requirements.txt"
- "%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"
artifacts:
diff --git a/tests/compile/types_and_names.pyx b/tests/compile/types_and_names.pyx
index 8ded94e4d..2637d4ba6 100644
--- a/tests/compile/types_and_names.pyx
+++ b/tests/compile/types_and_names.pyx
@@ -23,3 +23,16 @@ cdef A a
foo(2, 3, [], [], P, 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
diff --git a/tests/limited_api_bugs.txt b/tests/limited_api_bugs.txt
index 60baf6eb4..b98ff76c0 100644
--- a/tests/limited_api_bugs.txt
+++ b/tests/limited_api_bugs.txt
@@ -6,3 +6,6 @@ dict_animal
not_none
queue3
test_queue
+memoryview
+memview
+buffer
diff --git a/tests/run/cdef_multiple_inheritance_errors.srctree b/tests/run/cdef_multiple_inheritance_errors.srctree
index dd4aaa200..4f49184f4 100644
--- a/tests/run/cdef_multiple_inheritance_errors.srctree
+++ b/tests/run/cdef_multiple_inheritance_errors.srctree
@@ -65,31 +65,31 @@ import sys
try:
import notheaptype
- assert False
+ assert False, "notheaptype"
except TypeError as msg:
assert str(msg) == "base class 'object' is not a heap type"
try:
import wrongbase
- assert False
+ assert False, "wrongbase"
except TypeError as msg:
assert str(msg) == "best base 'str' must be equal to first base 'wrongbase.Base'"
try:
import badmro
- assert False
+ assert False, "badmro"
except TypeError as msg:
assert str(msg).startswith("Cannot create a consistent method resolution")
try:
import nodict
- assert False
+ assert False, "nodict"
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"
try:
# This should work on Python 3 but fail on Python 2
import oldstyle
- assert sys.version_info[0] >= 3
+ assert sys.version_info[0] >= 3, "oldstyle"
except TypeError as msg:
assert str(msg) == "base class 'OldStyle' is an old-style class"