summaryrefslogtreecommitdiff
path: root/Cython/Utility
diff options
context:
space:
mode:
Diffstat (limited to 'Cython/Utility')
-rw-r--r--Cython/Utility/AsyncGen.c301
-rw-r--r--Cython/Utility/Buffer.c19
-rw-r--r--Cython/Utility/Builtins.c213
-rw-r--r--Cython/Utility/CConvert.pyx8
-rw-r--r--Cython/Utility/Capsule.c20
-rw-r--r--Cython/Utility/CommonStructures.c170
-rw-r--r--Cython/Utility/Complex.c94
-rw-r--r--Cython/Utility/Coroutine.c451
-rw-r--r--Cython/Utility/CpdefEnums.pyx124
-rw-r--r--Cython/Utility/CppConvert.pyx82
-rw-r--r--Cython/Utility/CppSupport.cpp75
-rw-r--r--Cython/Utility/CythonFunction.c759
-rw-r--r--Cython/Utility/Dataclasses.c178
-rw-r--r--Cython/Utility/Dataclasses.py112
-rw-r--r--Cython/Utility/Embed.c88
-rw-r--r--Cython/Utility/Exceptions.c187
-rw-r--r--Cython/Utility/ExtensionTypes.c444
-rw-r--r--Cython/Utility/FunctionArguments.c165
-rw-r--r--Cython/Utility/ImportExport.c370
-rw-r--r--Cython/Utility/MemoryView.pyx452
-rw-r--r--Cython/Utility/MemoryView_C.c120
-rw-r--r--Cython/Utility/ModuleSetupCode.c814
-rw-r--r--Cython/Utility/NumpyImportArray.c46
-rw-r--r--Cython/Utility/ObjectHandling.c1464
-rw-r--r--Cython/Utility/Optimize.c647
-rw-r--r--Cython/Utility/Overflow.c207
-rw-r--r--Cython/Utility/Profile.c6
-rw-r--r--Cython/Utility/StringTools.c129
-rw-r--r--Cython/Utility/TestCythonScope.pyx30
-rw-r--r--Cython/Utility/TypeConversion.c383
-rw-r--r--Cython/Utility/UFuncs.pyx51
-rw-r--r--Cython/Utility/UFuncs_C.c42
32 files changed, 6249 insertions, 2002 deletions
diff --git a/Cython/Utility/AsyncGen.c b/Cython/Utility/AsyncGen.c
index dd4bf3728..a3d068e97 100644
--- a/Cython/Utility/AsyncGen.c
+++ b/Cython/Utility/AsyncGen.c
@@ -11,6 +11,7 @@ typedef struct {
PyObject *ag_finalizer;
int ag_hooks_inited;
int ag_closed;
+ int ag_running_async;
} __pyx_PyAsyncGenObject;
static PyTypeObject *__pyx__PyAsyncGenWrappedValueType = 0;
@@ -18,11 +19,11 @@ static PyTypeObject *__pyx__PyAsyncGenASendType = 0;
static PyTypeObject *__pyx__PyAsyncGenAThrowType = 0;
static PyTypeObject *__pyx_AsyncGenType = 0;
-#define __Pyx_AsyncGen_CheckExact(obj) (Py_TYPE(obj) == __pyx_AsyncGenType)
+#define __Pyx_AsyncGen_CheckExact(obj) __Pyx_IS_TYPE(obj, __pyx_AsyncGenType)
#define __pyx_PyAsyncGenASend_CheckExact(o) \
- (Py_TYPE(o) == __pyx__PyAsyncGenASendType)
+ __Pyx_IS_TYPE(o, __pyx__PyAsyncGenASendType)
#define __pyx_PyAsyncGenAThrow_CheckExact(o) \
- (Py_TYPE(o) == __pyx__PyAsyncGenAThrowType)
+ __Pyx_IS_TYPE(o, __pyx__PyAsyncGenAThrowType)
static PyObject *__Pyx_async_gen_anext(PyObject *o);
static CYTHON_INLINE PyObject *__Pyx_async_gen_asend_iternext(PyObject *o);
@@ -42,10 +43,11 @@ static __pyx_CoroutineObject *__Pyx_AsyncGen_New(
gen->ag_finalizer = NULL;
gen->ag_closed = 0;
gen->ag_hooks_inited = 0;
+ gen->ag_running_async = 0;
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 ////////////////////
@@ -127,6 +129,8 @@ static PyObject *__Pyx_async_gen_athrow_new(__pyx_PyAsyncGenObject *, PyObject *
static const char *__Pyx_NON_INIT_CORO_MSG = "can't send non-None value to a just-started coroutine";
static const char *__Pyx_ASYNC_GEN_IGNORED_EXIT_MSG = "async generator ignored GeneratorExit";
+static const char *__Pyx_ASYNC_GEN_CANNOT_REUSE_SEND_MSG = "cannot reuse already awaited __anext__()/asend()";
+static const char *__Pyx_ASYNC_GEN_CANNOT_REUSE_CLOSE_MSG = "cannot reuse already awaited aclose()/athrow()";
typedef enum {
__PYX_AWAITABLE_STATE_INIT, /* new awaitable, has not yet been iterated */
@@ -178,7 +182,7 @@ static __pyx_PyAsyncGenASend *__Pyx_ag_asend_freelist[_PyAsyncGen_MAXFREELIST];
static int __Pyx_ag_asend_freelist_free = 0;
#define __pyx__PyAsyncGenWrappedValue_CheckExact(o) \
- (Py_TYPE(o) == __pyx__PyAsyncGenWrappedValueType)
+ __Pyx_IS_TYPE(o, __pyx__PyAsyncGenWrappedValueType)
static int
@@ -253,14 +257,15 @@ static PyObject *
__Pyx_async_gen_anext(PyObject *g)
{
__pyx_PyAsyncGenObject *o = (__pyx_PyAsyncGenObject*) g;
- if (__Pyx_async_gen_init_hooks(o)) {
+ if (unlikely(__Pyx_async_gen_init_hooks(o))) {
return NULL;
}
return __Pyx_async_gen_asend_new(o, NULL);
}
static PyObject *
-__Pyx_async_gen_anext_method(PyObject *g, CYTHON_UNUSED PyObject *arg) {
+__Pyx_async_gen_anext_method(PyObject *g, PyObject *arg) {
+ CYTHON_UNUSED_VAR(arg);
return __Pyx_async_gen_anext(g);
}
@@ -268,7 +273,7 @@ __Pyx_async_gen_anext_method(PyObject *g, CYTHON_UNUSED PyObject *arg) {
static PyObject *
__Pyx_async_gen_asend(__pyx_PyAsyncGenObject *o, PyObject *arg)
{
- if (__Pyx_async_gen_init_hooks(o)) {
+ if (unlikely(__Pyx_async_gen_init_hooks(o))) {
return NULL;
}
return __Pyx_async_gen_asend_new(o, arg);
@@ -276,9 +281,10 @@ __Pyx_async_gen_asend(__pyx_PyAsyncGenObject *o, PyObject *arg)
static PyObject *
-__Pyx_async_gen_aclose(__pyx_PyAsyncGenObject *o, CYTHON_UNUSED PyObject *arg)
+__Pyx_async_gen_aclose(__pyx_PyAsyncGenObject *o, PyObject *arg)
{
- if (__Pyx_async_gen_init_hooks(o)) {
+ CYTHON_UNUSED_VAR(arg);
+ if (unlikely(__Pyx_async_gen_init_hooks(o))) {
return NULL;
}
return __Pyx_async_gen_athrow_new(o, NULL);
@@ -288,7 +294,7 @@ __Pyx_async_gen_aclose(__pyx_PyAsyncGenObject *o, CYTHON_UNUSED PyObject *arg)
static PyObject *
__Pyx_async_gen_athrow(__pyx_PyAsyncGenObject *o, PyObject *args)
{
- if (__Pyx_async_gen_init_hooks(o)) {
+ if (unlikely(__Pyx_async_gen_init_hooks(o))) {
return NULL;
}
return __Pyx_async_gen_athrow_new(o, args);
@@ -296,7 +302,8 @@ __Pyx_async_gen_athrow(__pyx_PyAsyncGenObject *o, PyObject *args)
static PyObject *
-__Pyx_async_gen_self_method(PyObject *g, CYTHON_UNUSED PyObject *arg) {
+__Pyx_async_gen_self_method(PyObject *g, PyObject *arg) {
+ CYTHON_UNUSED_VAR(arg);
return __Pyx_NewRef(g);
}
@@ -313,11 +320,15 @@ static PyGetSetDef __Pyx_async_gen_getsetlist[] = {
static PyMemberDef __Pyx_async_gen_memberlist[] = {
//REMOVED: {(char*) "ag_frame", T_OBJECT, offsetof(__pyx_PyAsyncGenObject, ag_frame), READONLY},
- {(char*) "ag_running", T_BOOL, offsetof(__pyx_CoroutineObject, is_running), READONLY, NULL},
+ {(char*) "ag_running", T_BOOL, offsetof(__pyx_PyAsyncGenObject, ag_running_async), READONLY, NULL},
//REMOVED: {(char*) "ag_code", T_OBJECT, offsetof(__pyx_PyAsyncGenObject, ag_code), READONLY},
//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 */
};
@@ -346,6 +357,31 @@ static PyMethodDef __Pyx_async_gen_methods[] = {
};
+#if CYTHON_USE_TYPE_SPECS
+static PyType_Slot __pyx_AsyncGenType_slots[] = {
+ {Py_tp_dealloc, (void *)__Pyx_Coroutine_dealloc},
+ {Py_am_aiter, (void *)PyObject_SelfIter},
+ {Py_am_anext, (void *)__Pyx_async_gen_anext},
+ {Py_tp_repr, (void *)__Pyx_async_gen_repr},
+ {Py_tp_traverse, (void *)__Pyx_async_gen_traverse},
+ {Py_tp_methods, (void *)__Pyx_async_gen_methods},
+ {Py_tp_members, (void *)__Pyx_async_gen_memberlist},
+ {Py_tp_getset, (void *)__Pyx_async_gen_getsetlist},
+#if CYTHON_USE_TP_FINALIZE
+ {Py_tp_finalize, (void *)__Pyx_Coroutine_del},
+#endif
+ {0, 0},
+};
+
+static PyType_Spec __pyx_AsyncGenType_spec = {
+ __PYX_TYPE_MODULE_PREFIX "async_generator",
+ sizeof(__pyx_PyAsyncGenObject),
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
+ __pyx_AsyncGenType_slots
+};
+#else /* CYTHON_USE_TYPE_SPECS */
+
#if CYTHON_USE_ASYNC_SLOTS
static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_as_async = {
0, /* am_await */
@@ -363,7 +399,7 @@ static PyTypeObject __pyx_AsyncGenType_type = {
sizeof(__pyx_PyAsyncGenObject), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)__Pyx_Coroutine_dealloc, /* tp_dealloc */
- 0, /* tp_print */
+ 0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
#if CYTHON_USE_ASYNC_SLOTS
@@ -427,7 +463,7 @@ static PyTypeObject __pyx_AsyncGenType_type = {
#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
0, /*tp_vectorcall*/
#endif
-#if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
+#if __PYX_NEED_TP_PRINT_SLOT
0, /*tp_print*/
#endif
#if PY_VERSION_HEX >= 0x030C0000
@@ -437,6 +473,7 @@ static PyTypeObject __pyx_AsyncGenType_type = {
0, /*tp_pypy_flags*/
#endif
};
+#endif /* CYTHON_USE_TYPE_SPECS */
static int
@@ -448,14 +485,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(Py_TYPE(o) == __pyx__PyAsyncGenASendType);
- PyObject_GC_Del(o);
+ assert(__Pyx_IS_TYPE(o, __pyx__PyAsyncGenASendType));
+ __Pyx_PyHeapTypeObject_GC_Del(o);
}
return ret;
@@ -480,6 +517,7 @@ __Pyx_async_gen_unwrap_value(__pyx_PyAsyncGenObject *gen, PyObject *result)
gen->ag_closed = 1;
}
+ gen->ag_running_async = 0;
return NULL;
}
@@ -487,6 +525,7 @@ __Pyx_async_gen_unwrap_value(__pyx_PyAsyncGenObject *gen, PyObject *result)
/* async yield */
__Pyx_ReturnWithStopIteration(((__pyx__PyAsyncGenWrappedValue*)result)->agw_val);
Py_DECREF(result);
+ gen->ag_running_async = 0;
return NULL;
}
@@ -503,11 +542,11 @@ __Pyx_async_gen_asend_dealloc(__pyx_PyAsyncGenASend *o)
PyObject_GC_UnTrack((PyObject *)o);
Py_CLEAR(o->ags_gen);
Py_CLEAR(o->ags_sendval);
- if (__Pyx_ag_asend_freelist_free < _PyAsyncGen_MAXFREELIST) {
+ if (likely(__Pyx_ag_asend_freelist_free < _PyAsyncGen_MAXFREELIST)) {
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);
}
}
@@ -527,17 +566,25 @@ __Pyx_async_gen_asend_send(PyObject *g, PyObject *arg)
PyObject *result;
if (unlikely(o->ags_state == __PYX_AWAITABLE_STATE_CLOSED)) {
- PyErr_SetNone(PyExc_StopIteration);
+ PyErr_SetString(PyExc_RuntimeError, __Pyx_ASYNC_GEN_CANNOT_REUSE_SEND_MSG);
return NULL;
}
if (o->ags_state == __PYX_AWAITABLE_STATE_INIT) {
+ if (unlikely(o->ags_gen->ag_running_async)) {
+ PyErr_SetString(
+ PyExc_RuntimeError,
+ "anext(): asynchronous generator is already running");
+ return NULL;
+ }
+
if (arg == NULL || arg == Py_None) {
arg = o->ags_sendval ? o->ags_sendval : Py_None;
}
o->ags_state = __PYX_AWAITABLE_STATE_ITER;
}
+ o->ags_gen->ag_running_async = 1;
result = __Pyx_Coroutine_Send((PyObject*)o->ags_gen, arg);
result = __Pyx_async_gen_unwrap_value(o->ags_gen, result);
@@ -562,7 +609,7 @@ __Pyx_async_gen_asend_throw(__pyx_PyAsyncGenASend *o, PyObject *args)
PyObject *result;
if (unlikely(o->ags_state == __PYX_AWAITABLE_STATE_CLOSED)) {
- PyErr_SetNone(PyExc_StopIteration);
+ PyErr_SetString(PyExc_RuntimeError, __Pyx_ASYNC_GEN_CANNOT_REUSE_SEND_MSG);
return NULL;
}
@@ -578,9 +625,10 @@ __Pyx_async_gen_asend_throw(__pyx_PyAsyncGenASend *o, PyObject *args)
static PyObject *
-__Pyx_async_gen_asend_close(PyObject *g, CYTHON_UNUSED PyObject *args)
+__Pyx_async_gen_asend_close(PyObject *g, PyObject *args)
{
__pyx_PyAsyncGenASend *o = (__pyx_PyAsyncGenASend*) g;
+ CYTHON_UNUSED_VAR(args);
o->ags_state = __PYX_AWAITABLE_STATE_CLOSED;
Py_RETURN_NONE;
}
@@ -595,6 +643,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 */
@@ -606,7 +674,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 */
@@ -614,7 +681,7 @@ static PyTypeObject __pyx__PyAsyncGenASendType_type = {
0, /* tp_itemsize */
/* methods */
(destructor)__Pyx_async_gen_asend_dealloc, /* tp_dealloc */
- 0, /* tp_print */
+ 0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
#if CYTHON_USE_ASYNC_SLOTS
@@ -671,7 +738,7 @@ static PyTypeObject __pyx__PyAsyncGenASendType_type = {
#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
0, /*tp_vectorcall*/
#endif
-#if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
+#if __PYX_NEED_TP_PRINT_SLOT
0, /*tp_print*/
#endif
#if PY_VERSION_HEX >= 0x030C0000
@@ -681,19 +748,20 @@ static PyTypeObject __pyx__PyAsyncGenASendType_type = {
0, /*tp_pypy_flags*/
#endif
};
+#endif /* CYTHON_USE_TYPE_SPECS */
static PyObject *
__Pyx_async_gen_asend_new(__pyx_PyAsyncGenObject *gen, PyObject *sendval)
{
__pyx_PyAsyncGenASend *o;
- if (__Pyx_ag_asend_freelist_free) {
+ if (likely(__Pyx_ag_asend_freelist_free)) {
__Pyx_ag_asend_freelist_free--;
o = __Pyx_ag_asend_freelist[__Pyx_ag_asend_freelist_free];
_Py_NewReference((PyObject *)o);
} else {
o = PyObject_GC_New(__pyx_PyAsyncGenASend, __pyx__PyAsyncGenASendType);
- if (o == NULL) {
+ if (unlikely(o == NULL)) {
return NULL;
}
}
@@ -719,11 +787,11 @@ __Pyx_async_gen_wrapped_val_dealloc(__pyx__PyAsyncGenWrappedValue *o)
{
PyObject_GC_UnTrack((PyObject *)o);
Py_CLEAR(o->agw_val);
- if (__Pyx_ag_value_freelist_free < _PyAsyncGen_MAXFREELIST) {
+ if (likely(__Pyx_ag_value_freelist_free < _PyAsyncGen_MAXFREELIST)) {
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);
}
}
@@ -737,6 +805,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 */
@@ -744,7 +828,7 @@ static PyTypeObject __pyx__PyAsyncGenWrappedValueType_type = {
0, /* tp_itemsize */
/* methods */
(destructor)__Pyx_async_gen_wrapped_val_dealloc, /* tp_dealloc */
- 0, /* tp_print */
+ 0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
@@ -792,7 +876,7 @@ static PyTypeObject __pyx__PyAsyncGenWrappedValueType_type = {
#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
0, /*tp_vectorcall*/
#endif
-#if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
+#if __PYX_NEED_TP_PRINT_SLOT
0, /*tp_print*/
#endif
#if PY_VERSION_HEX >= 0x030C0000
@@ -802,6 +886,7 @@ static PyTypeObject __pyx__PyAsyncGenWrappedValueType_type = {
0, /*tp_pypy_flags*/
#endif
};
+#endif /* CYTHON_USE_TYPE_SPECS */
static PyObject *
@@ -811,7 +896,7 @@ __Pyx__PyAsyncGenValueWrapperNew(PyObject *val)
__pyx__PyAsyncGenWrappedValue *o;
assert(val);
- if (__Pyx_ag_value_freelist_free) {
+ if (likely(__Pyx_ag_value_freelist_free)) {
__Pyx_ag_value_freelist_free--;
o = __Pyx_ag_value_freelist[__Pyx_ag_value_freelist_free];
assert(__pyx__PyAsyncGenWrappedValue_CheckExact(o));
@@ -839,7 +924,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);
}
@@ -856,34 +941,56 @@ static PyObject *
__Pyx_async_gen_athrow_send(__pyx_PyAsyncGenAThrow *o, PyObject *arg)
{
__pyx_CoroutineObject *gen = (__pyx_CoroutineObject*)o->agt_gen;
- PyObject *retval;
+ PyObject *retval, *exc_type;
- if (o->agt_state == __PYX_AWAITABLE_STATE_CLOSED) {
+ if (unlikely(o->agt_state == __PYX_AWAITABLE_STATE_CLOSED)) {
+ PyErr_SetString(PyExc_RuntimeError, __Pyx_ASYNC_GEN_CANNOT_REUSE_CLOSE_MSG);
+ return NULL;
+ }
+
+ if (unlikely(gen->resume_label == -1)) {
+ // already run past the end
+ o->agt_state = __PYX_AWAITABLE_STATE_CLOSED;
PyErr_SetNone(PyExc_StopIteration);
return NULL;
}
if (o->agt_state == __PYX_AWAITABLE_STATE_INIT) {
- if (o->agt_gen->ag_closed) {
- PyErr_SetNone(PyExc_StopIteration);
+ if (unlikely(o->agt_gen->ag_running_async)) {
+ o->agt_state = __PYX_AWAITABLE_STATE_CLOSED;
+ if (o->agt_args == NULL) {
+ PyErr_SetString(
+ PyExc_RuntimeError,
+ "aclose(): asynchronous generator is already running");
+ } else {
+ PyErr_SetString(
+ PyExc_RuntimeError,
+ "athrow(): asynchronous generator is already running");
+ }
+ return NULL;
+ }
+
+ if (unlikely(o->agt_gen->ag_closed)) {
+ o->agt_state = __PYX_AWAITABLE_STATE_CLOSED;
+ PyErr_SetNone(__Pyx_PyExc_StopAsyncIteration);
return NULL;
}
- if (arg != Py_None) {
+ if (unlikely(arg != Py_None)) {
PyErr_SetString(PyExc_RuntimeError, __Pyx_NON_INIT_CORO_MSG);
return NULL;
}
o->agt_state = __PYX_AWAITABLE_STATE_ITER;
+ o->agt_gen->ag_running_async = 1;
if (o->agt_args == NULL) {
/* aclose() mode */
o->agt_gen->ag_closed = 1;
retval = __Pyx__Coroutine_Throw((PyObject*)gen,
- /* Do not close generator when
- PyExc_GeneratorExit is passed */
- PyExc_GeneratorExit, NULL, NULL, NULL, 0);
+ /* Do not close generator when PyExc_GeneratorExit is passed */
+ PyExc_GeneratorExit, NULL, NULL, NULL, 0);
if (retval && __pyx__PyAsyncGenWrappedValue_CheckExact(retval)) {
Py_DECREF(retval);
@@ -894,14 +1001,13 @@ __Pyx_async_gen_athrow_send(__pyx_PyAsyncGenAThrow *o, PyObject *arg)
PyObject *tb = NULL;
PyObject *val = NULL;
- if (!PyArg_UnpackTuple(o->agt_args, "athrow", 1, 3,
- &typ, &val, &tb)) {
+ if (unlikely(!PyArg_UnpackTuple(o->agt_args, "athrow", 1, 3, &typ, &val, &tb))) {
return NULL;
}
retval = __Pyx__Coroutine_Throw((PyObject*)gen,
- /* Do not close generator when PyExc_GeneratorExit is passed */
- typ, val, tb, o->agt_args, 0);
+ /* Do not close generator when PyExc_GeneratorExit is passed */
+ typ, val, tb, o->agt_args, 0);
retval = __Pyx_async_gen_unwrap_value(o->agt_gen, retval);
}
if (retval == NULL) {
@@ -918,7 +1024,7 @@ __Pyx_async_gen_athrow_send(__pyx_PyAsyncGenAThrow *o, PyObject *arg)
} else {
/* aclose() mode */
if (retval) {
- if (__pyx__PyAsyncGenWrappedValue_CheckExact(retval)) {
+ if (unlikely(__pyx__PyAsyncGenWrappedValue_CheckExact(retval))) {
Py_DECREF(retval);
goto yield_close;
}
@@ -932,26 +1038,26 @@ __Pyx_async_gen_athrow_send(__pyx_PyAsyncGenAThrow *o, PyObject *arg)
}
yield_close:
+ o->agt_gen->ag_running_async = 0;
+ o->agt_state = __PYX_AWAITABLE_STATE_CLOSED;
PyErr_SetString(
PyExc_RuntimeError, __Pyx_ASYNC_GEN_IGNORED_EXIT_MSG);
return NULL;
check_error:
- if (PyErr_ExceptionMatches(__Pyx_PyExc_StopAsyncIteration)) {
- o->agt_state = __PYX_AWAITABLE_STATE_CLOSED;
+ o->agt_gen->ag_running_async = 0;
+ o->agt_state = __PYX_AWAITABLE_STATE_CLOSED;
+ exc_type = PyErr_Occurred();
+ if (__Pyx_PyErr_GivenExceptionMatches2(exc_type, __Pyx_PyExc_StopAsyncIteration, PyExc_GeneratorExit)) {
if (o->agt_args == NULL) {
// when aclose() is called we don't want to propagate
- // StopAsyncIteration; just raise StopIteration, signalling
- // that 'aclose()' is done.
+ // StopAsyncIteration or GeneratorExit; just raise
+ // StopIteration, signalling that this 'aclose()' await
+ // is done.
PyErr_Clear();
PyErr_SetNone(PyExc_StopIteration);
}
}
- else if (PyErr_ExceptionMatches(PyExc_GeneratorExit)) {
- o->agt_state = __PYX_AWAITABLE_STATE_CLOSED;
- PyErr_Clear(); /* ignore these errors */
- PyErr_SetNone(PyExc_StopIteration);
- }
return NULL;
}
@@ -961,13 +1067,8 @@ __Pyx_async_gen_athrow_throw(__pyx_PyAsyncGenAThrow *o, PyObject *args)
{
PyObject *retval;
- if (o->agt_state == __PYX_AWAITABLE_STATE_INIT) {
- PyErr_SetString(PyExc_RuntimeError, __Pyx_NON_INIT_CORO_MSG);
- return NULL;
- }
-
- if (o->agt_state == __PYX_AWAITABLE_STATE_CLOSED) {
- PyErr_SetNone(PyExc_StopIteration);
+ if (unlikely(o->agt_state == __PYX_AWAITABLE_STATE_CLOSED)) {
+ PyErr_SetString(PyExc_RuntimeError, __Pyx_ASYNC_GEN_CANNOT_REUSE_CLOSE_MSG);
return NULL;
}
@@ -975,12 +1076,24 @@ __Pyx_async_gen_athrow_throw(__pyx_PyAsyncGenAThrow *o, PyObject *args)
if (o->agt_args) {
return __Pyx_async_gen_unwrap_value(o->agt_gen, retval);
} else {
- /* aclose() mode */
- if (retval && __pyx__PyAsyncGenWrappedValue_CheckExact(retval)) {
+ // aclose() mode
+ PyObject *exc_type;
+ if (unlikely(retval && __pyx__PyAsyncGenWrappedValue_CheckExact(retval))) {
+ o->agt_gen->ag_running_async = 0;
+ o->agt_state = __PYX_AWAITABLE_STATE_CLOSED;
Py_DECREF(retval);
PyErr_SetString(PyExc_RuntimeError, __Pyx_ASYNC_GEN_IGNORED_EXIT_MSG);
return NULL;
}
+ exc_type = PyErr_Occurred();
+ if (__Pyx_PyErr_GivenExceptionMatches2(exc_type, __Pyx_PyExc_StopAsyncIteration, PyExc_GeneratorExit)) {
+ // when aclose() is called we don't want to propagate
+ // StopAsyncIteration or GeneratorExit; just raise
+ // StopIteration, signalling that this 'aclose()' await
+ // is done.
+ PyErr_Clear();
+ PyErr_SetNone(PyExc_StopIteration);
+ }
return retval;
}
}
@@ -994,9 +1107,10 @@ __Pyx_async_gen_athrow_iternext(__pyx_PyAsyncGenAThrow *o)
static PyObject *
-__Pyx_async_gen_athrow_close(PyObject *g, CYTHON_UNUSED PyObject *args)
+__Pyx_async_gen_athrow_close(PyObject *g, PyObject *args)
{
__pyx_PyAsyncGenAThrow *o = (__pyx_PyAsyncGenAThrow*) g;
+ CYTHON_UNUSED_VAR(args);
o->agt_state = __PYX_AWAITABLE_STATE_CLOSED;
Py_RETURN_NONE;
}
@@ -1011,6 +1125,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 */
@@ -1022,14 +1157,13 @@ 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 */
sizeof(__pyx_PyAsyncGenAThrow), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)__Pyx_async_gen_athrow_dealloc, /* tp_dealloc */
- 0, /* tp_print */
+ 0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
#if CYTHON_USE_ASYNC_SLOTS
@@ -1086,7 +1220,7 @@ static PyTypeObject __pyx__PyAsyncGenAThrowType_type = {
#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
0, /*tp_vectorcall*/
#endif
-#if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
+#if __PYX_NEED_TP_PRINT_SLOT
0, /*tp_print*/
#endif
#if PY_VERSION_HEX >= 0x030C0000
@@ -1096,6 +1230,7 @@ static PyTypeObject __pyx__PyAsyncGenAThrowType_type = {
0, /*tp_pypy_flags*/
#endif
};
+#endif /* CYTHON_USE_TYPE_SPECS */
static PyObject *
@@ -1103,7 +1238,7 @@ __Pyx_async_gen_athrow_new(__pyx_PyAsyncGenObject *gen, PyObject *args)
{
__pyx_PyAsyncGenAThrow *o;
o = PyObject_GC_New(__pyx_PyAsyncGenAThrow, __pyx__PyAsyncGenAThrowType);
- if (o == NULL) {
+ if (unlikely(o == NULL)) {
return NULL;
}
o->agt_gen = gen;
@@ -1118,26 +1253,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
+ CYTHON_MAYBE_UNUSED_VAR(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/Buffer.c b/Cython/Utility/Buffer.c
index 3c7105fa3..8958b9e50 100644
--- a/Cython/Utility/Buffer.c
+++ b/Cython/Utility/Buffer.c
@@ -54,8 +54,6 @@ static void __Pyx_RaiseBufferFallbackError(void) {
/////////////// BufferFormatStructs.proto ///////////////
//@proto_block: utility_code_proto_before_types
-#define IS_UNSIGNED(type) (((type) -1) > 0)
-
/* Run-time type information about structs used with buffers */
struct __Pyx_StructField_;
@@ -111,6 +109,7 @@ typedef struct {
#if PY_MAJOR_VERSION < 3
static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) {
+ __Pyx_TypeName obj_type_name;
if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags);
{{for type_ptr, getbuffer, releasebuffer in types}}
@@ -119,7 +118,11 @@ static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) {
{{endif}}
{{endfor}}
- PyErr_Format(PyExc_TypeError, "'%.200s' does not have the buffer interface", Py_TYPE(obj)->tp_name);
+ obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj));
+ PyErr_Format(PyExc_TypeError,
+ "'" __Pyx_FMT_TYPENAME "' does not have the buffer interface",
+ obj_type_name);
+ __Pyx_DECREF_TypeName(obj_type_name);
return -1;
}
@@ -224,8 +227,8 @@ fail:;
// the format string; the access mode/flags is checked by the
// exporter. See:
//
-// http://docs.python.org/3/library/struct.html
-// http://legacy.python.org/dev/peps/pep-3118/#additions-to-the-struct-string-syntax
+// https://docs.python.org/3/library/struct.html
+// https://www.python.org/dev/peps/pep-3118/#additions-to-the-struct-string-syntax
//
// The alignment code is copied from _struct.c in Python.
@@ -372,7 +375,8 @@ typedef struct { char c; void *x; } __Pyx_st_void_p;
typedef struct { char c; PY_LONG_LONG x; } __Pyx_st_longlong;
#endif
-static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, CYTHON_UNUSED int is_complex) {
+static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, int is_complex) {
+ CYTHON_UNUSED_VAR(is_complex);
switch (ch) {
case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short);
@@ -406,7 +410,8 @@ typedef struct { void *x; char c; } __Pyx_pad_void_p;
typedef struct { PY_LONG_LONG x; char c; } __Pyx_pad_longlong;
#endif
-static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, CYTHON_UNUSED int is_complex) {
+static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, int is_complex) {
+ CYTHON_UNUSED_VAR(is_complex);
switch (ch) {
case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
case 'h': case 'H': return sizeof(__Pyx_pad_short) - sizeof(short);
diff --git a/Cython/Utility/Builtins.c b/Cython/Utility/Builtins.c
index 32aeff8f2..b77f95105 100644
--- a/Cython/Utility/Builtins.c
+++ b/Cython/Utility/Builtins.c
@@ -20,47 +20,7 @@ static PyObject* __Pyx_Globals(void); /*proto*/
// access requires a rewrite as a dedicated class.
static PyObject* __Pyx_Globals(void) {
- Py_ssize_t i;
- PyObject *names;
- PyObject *globals = $moddict_cname;
- Py_INCREF(globals);
- names = PyObject_Dir($module_cname);
- if (!names)
- goto bad;
- for (i = PyList_GET_SIZE(names)-1; i >= 0; i--) {
-#if CYTHON_COMPILING_IN_PYPY
- PyObject* name = PySequence_ITEM(names, i);
- if (!name)
- goto bad;
-#else
- PyObject* name = PyList_GET_ITEM(names, i);
-#endif
- if (!PyDict_Contains(globals, name)) {
- PyObject* value = __Pyx_GetAttr($module_cname, name);
- if (!value) {
-#if CYTHON_COMPILING_IN_PYPY
- Py_DECREF(name);
-#endif
- goto bad;
- }
- if (PyDict_SetItem(globals, name, value) < 0) {
-#if CYTHON_COMPILING_IN_PYPY
- Py_DECREF(name);
-#endif
- Py_DECREF(value);
- goto bad;
- }
- }
-#if CYTHON_COMPILING_IN_PYPY
- Py_DECREF(name);
-#endif
- }
- Py_DECREF(names);
- return globals;
-bad:
- Py_XDECREF(names);
- Py_XDECREF(globals);
- return NULL;
+ return __Pyx_NewRef($moddict_cname);
}
//////////////////// PyExecGlobals.proto ////////////////////
@@ -68,17 +28,11 @@ bad:
static PyObject* __Pyx_PyExecGlobals(PyObject*);
//////////////////// PyExecGlobals ////////////////////
-//@requires: Globals
+//@substitute: naming
//@requires: PyExec
static PyObject* __Pyx_PyExecGlobals(PyObject* code) {
- PyObject* result;
- PyObject* globals = __Pyx_Globals();
- if (unlikely(!globals))
- return NULL;
- result = __Pyx_PyExec2(code, globals);
- Py_DECREF(globals);
- return result;
+ return __Pyx_PyExec2(code, $moddict_cname);
}
//////////////////// PyExec.proto ////////////////////
@@ -100,9 +54,13 @@ static PyObject* __Pyx_PyExec3(PyObject* o, PyObject* globals, PyObject* locals)
if (!globals || globals == Py_None) {
globals = $moddict_cname;
- } else if (!PyDict_Check(globals)) {
- PyErr_Format(PyExc_TypeError, "exec() arg 2 must be a dict, not %.200s",
- Py_TYPE(globals)->tp_name);
+ } else if (unlikely(!PyDict_Check(globals))) {
+ __Pyx_TypeName globals_type_name =
+ __Pyx_PyType_GetName(Py_TYPE(globals));
+ PyErr_Format(PyExc_TypeError,
+ "exec() arg 2 must be a dict, not " __Pyx_FMT_TYPENAME,
+ globals_type_name);
+ __Pyx_DECREF_TypeName(globals_type_name);
goto bad;
}
if (!locals || locals == Py_None) {
@@ -110,12 +68,12 @@ static PyObject* __Pyx_PyExec3(PyObject* o, PyObject* globals, PyObject* locals)
}
if (__Pyx_PyDict_GetItemStr(globals, PYIDENT("__builtins__")) == NULL) {
- if (PyDict_SetItem(globals, PYIDENT("__builtins__"), PyEval_GetBuiltins()) < 0)
+ if (unlikely(PyDict_SetItem(globals, PYIDENT("__builtins__"), PyEval_GetBuiltins()) < 0))
goto bad;
}
if (PyCode_Check(o)) {
- if (__Pyx_PyCode_HasFreeVars((PyCodeObject *)o)) {
+ if (unlikely(__Pyx_PyCode_HasFreeVars((PyCodeObject *)o))) {
PyErr_SetString(PyExc_TypeError,
"code object passed to exec() may not contain free variables");
goto bad;
@@ -134,16 +92,18 @@ static PyObject* __Pyx_PyExec3(PyObject* o, PyObject* globals, PyObject* locals)
if (PyUnicode_Check(o)) {
cf.cf_flags = PyCF_SOURCE_IS_UTF8;
s = PyUnicode_AsUTF8String(o);
- if (!s) goto bad;
+ if (unlikely(!s)) goto bad;
o = s;
#if PY_MAJOR_VERSION >= 3
- } else if (!PyBytes_Check(o)) {
+ } else if (unlikely(!PyBytes_Check(o))) {
#else
- } else if (!PyString_Check(o)) {
+ } else if (unlikely(!PyString_Check(o))) {
#endif
+ __Pyx_TypeName o_type_name = __Pyx_PyType_GetName(Py_TYPE(o));
PyErr_Format(PyExc_TypeError,
- "exec: arg 1 must be string, bytes or code object, got %.200s",
- Py_TYPE(o)->tp_name);
+ "exec: arg 1 must be string, bytes or code object, got " __Pyx_FMT_TYPENAME,
+ o_type_name);
+ __Pyx_DECREF_TypeName(o_type_name);
goto bad;
}
#if PY_MAJOR_VERSION >= 3
@@ -170,7 +130,7 @@ bad:
static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); /*proto*/
//////////////////// GetAttr3 ////////////////////
-//@requires: ObjectHandling.c::GetAttr
+//@requires: ObjectHandling.c::PyObjectGetAttrStr
//@requires: Exceptions.c::PyThreadStateGet
//@requires: Exceptions.c::PyErrFetchRestore
//@requires: Exceptions.c::PyErrExceptionMatches
@@ -186,7 +146,17 @@ static PyObject *__Pyx_GetAttr3Default(PyObject *d) {
}
static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) {
- PyObject *r = __Pyx_GetAttr(o, n);
+ PyObject *r;
+#if CYTHON_USE_TYPE_SLOTS
+ if (likely(PyString_Check(n))) {
+ r = __Pyx_PyObject_GetAttrStrNoError(o, n);
+ if (unlikely(!r) && likely(!PyErr_Occurred())) {
+ r = __Pyx_NewRef(d);
+ }
+ return r;
+ }
+#endif
+ r = PyObject_GetAttr(o, n);
return (likely(r)) ? r : __Pyx_GetAttr3Default(d);
}
@@ -205,7 +175,7 @@ static CYTHON_INLINE int __Pyx_HasAttr(PyObject *o, PyObject *n) {
return -1;
}
r = __Pyx_GetAttr(o, n);
- if (unlikely(!r)) {
+ if (!r) {
PyErr_Clear();
return 0;
} else {
@@ -219,11 +189,12 @@ static CYTHON_INLINE int __Pyx_HasAttr(PyObject *o, PyObject *n) {
static PyObject* __Pyx_Intern(PyObject* s); /* proto */
//////////////////// Intern ////////////////////
+//@requires: ObjectHandling.c::RaiseUnexpectedTypeError
static PyObject* __Pyx_Intern(PyObject* s) {
- if (!(likely(PyString_CheckExact(s)))) {
- PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "str", Py_TYPE(s)->tp_name);
- return 0;
+ if (unlikely(!PyString_CheckExact(s))) {
+ __Pyx_RaiseUnexpectedTypeError("str", s);
+ return NULL;
}
Py_INCREF(s);
#if PY_MAJOR_VERSION >= 3
@@ -263,7 +234,7 @@ static PyObject *__Pyx_PyLong_AbsNeg(PyObject *num);/*proto*/
#define __Pyx_PyNumber_Absolute(x) \
((likely(PyLong_CheckExact(x))) ? \
- (likely(Py_SIZE(x) >= 0) ? (Py_INCREF(x), (x)) : __Pyx_PyLong_AbsNeg(x)) : \
+ (likely(__Pyx_PyLong_IsNonNeg(x)) ? (Py_INCREF(x), (x)) : __Pyx_PyLong_AbsNeg(x)) : \
PyNumber_Absolute(x))
#else
@@ -274,16 +245,27 @@ static PyObject *__Pyx_PyLong_AbsNeg(PyObject *num);/*proto*/
#if CYTHON_USE_PYLONG_INTERNALS
static PyObject *__Pyx_PyLong_AbsNeg(PyObject *n) {
+#if PY_VERSION_HEX >= 0x030C00A7
+ if (likely(__Pyx_PyLong_IsCompact(n))) {
+ return PyLong_FromSize_t(__Pyx_PyLong_CompactValueUnsigned(n));
+ }
+#else
if (likely(Py_SIZE(n) == -1)) {
// digits are unsigned
- return PyLong_FromLong(((PyLongObject*)n)->ob_digit[0]);
+ return PyLong_FromUnsignedLong(__Pyx_PyLong_Digits(n)[0]);
}
+#endif
#if CYTHON_COMPILING_IN_CPYTHON
{
PyObject *copy = _PyLong_Copy((PyLongObject*)n);
if (likely(copy)) {
+ #if PY_VERSION_HEX >= 0x030C00A7
+ // clear the sign bits to set the sign from SIGN_NEGATIVE (2) to positive (0)
+ ((PyLongObject*)copy)->long_value.lv_tag = ((PyLongObject*)copy)->long_value.lv_tag & ~3;
+ #else
// negate the size to swap the sign
__Pyx_SET_SIZE(copy, -Py_SIZE(copy));
+ #endif
}
return copy;
}
@@ -299,6 +281,42 @@ static PyObject *__Pyx_PyLong_AbsNeg(PyObject *n) {
#define __Pyx_PyNumber_Power2(a, b) PyNumber_Power(a, b, Py_None)
+//////////////////// int_pyucs4.proto ////////////////////
+
+static CYTHON_INLINE int __Pyx_int_from_UCS4(Py_UCS4 uchar);
+
+//////////////////// int_pyucs4 ////////////////////
+
+static int __Pyx_int_from_UCS4(Py_UCS4 uchar) {
+ int digit = Py_UNICODE_TODIGIT(uchar);
+ if (unlikely(digit < 0)) {
+ PyErr_Format(PyExc_ValueError,
+ "invalid literal for int() with base 10: '%c'",
+ (int) uchar);
+ return -1;
+ }
+ return digit;
+}
+
+
+//////////////////// float_pyucs4.proto ////////////////////
+
+static CYTHON_INLINE double __Pyx_double_from_UCS4(Py_UCS4 uchar);
+
+//////////////////// float_pyucs4 ////////////////////
+
+static double __Pyx_double_from_UCS4(Py_UCS4 uchar) {
+ double digit = Py_UNICODE_TONUMERIC(uchar);
+ if (unlikely(digit < 0.0)) {
+ PyErr_Format(PyExc_ValueError,
+ "could not convert string to float: '%c'",
+ (int) uchar);
+ return -1.0;
+ }
+ return digit;
+}
+
+
//////////////////// object_ord.proto ////////////////////
//@requires: TypeConversion.c::UnicodeAsUCS4
@@ -332,8 +350,11 @@ static long __Pyx__PyObject_Ord(PyObject* c) {
#endif
} else {
// FIXME: support character buffers - but CPython doesn't support them either
+ __Pyx_TypeName c_type_name = __Pyx_PyType_GetName(Py_TYPE(c));
PyErr_Format(PyExc_TypeError,
- "ord() expected string of length 1, but %.200s found", Py_TYPE(c)->tp_name);
+ "ord() expected string of length 1, but " __Pyx_FMT_TYPENAME " found",
+ c_type_name);
+ __Pyx_DECREF_TypeName(c_type_name);
return (long)(Py_UCS4)-1;
}
PyErr_Format(PyExc_TypeError,
@@ -422,9 +443,6 @@ static CYTHON_INLINE PyObject* __Pyx_PyDict_IterItems(PyObject* d) {
//////////////////// py_dict_viewkeys.proto ////////////////////
-#if PY_VERSION_HEX < 0x02070000
-#error This module uses dict views, which require Python 2.7 or later
-#endif
static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewKeys(PyObject* d); /*proto*/
//////////////////// py_dict_viewkeys ////////////////////
@@ -438,9 +456,6 @@ static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewKeys(PyObject* d) {
//////////////////// py_dict_viewvalues.proto ////////////////////
-#if PY_VERSION_HEX < 0x02070000
-#error This module uses dict views, which require Python 2.7 or later
-#endif
static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewValues(PyObject* d); /*proto*/
//////////////////// py_dict_viewvalues ////////////////////
@@ -454,9 +469,6 @@ static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewValues(PyObject* d) {
//////////////////// py_dict_viewitems.proto ////////////////////
-#if PY_VERSION_HEX < 0x02070000
-#error This module uses dict views, which require Python 2.7 or later
-#endif
static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewItems(PyObject* d); /*proto*/
//////////////////// py_dict_viewitems ////////////////////
@@ -540,3 +552,50 @@ static CYTHON_INLINE int __Pyx_PySet_Update(PyObject* set, PyObject* it) {
Py_DECREF(retval);
return 0;
}
+
+///////////////// memoryview_get_from_buffer.proto ////////////////////
+
+// buffer is in limited api from Py3.11
+#if !CYTHON_COMPILING_IN_LIMITED_API || CYTHON_LIMITED_API >= 0x030b0000
+#define __Pyx_PyMemoryView_Get_{{name}}(o) PyMemoryView_GET_BUFFER(o)->{{name}}
+#else
+{{py:
+out_types = dict(
+ ndim='int', readonly='int',
+ len='Py_ssize_t', itemsize='Py_ssize_t')
+}} // can't get format like this unfortunately. It's unicode via getattr
+{{py: out_type = out_types[name]}}
+static {{out_type}} __Pyx_PyMemoryView_Get_{{name}}(PyObject *obj); /* proto */
+#endif
+
+////////////// memoryview_get_from_buffer /////////////////////////
+
+#if !CYTHON_COMPILING_IN_LIMITED_API || CYTHON_LIMITED_API >= 0x030b0000
+#else
+{{py:
+out_types = dict(
+ ndim='int', readonly='int',
+ len='Py_ssize_t', itemsize='Py_ssize_t')
+}}
+{{py: out_type = out_types[name]}}
+static {{out_type}} __Pyx_PyMemoryView_Get_{{name}}(PyObject *obj) {
+ {{out_type}} result;
+ PyObject *attr = PyObject_GetAttr(obj, PYIDENT("{{name}}"));
+ if (!attr) {
+ goto bad;
+ }
+{{if out_type == 'int'}}
+ // I'm not worrying about overflow here because
+ // ultimately it comes from a C struct that's an int
+ result = PyLong_AsLong(attr);
+{{elif out_type == 'Py_ssize_t'}}
+ result = PyLong_AsSsize_t(attr);
+{{endif}}
+ Py_DECREF(attr);
+ return result;
+
+ bad:
+ Py_XDECREF(attr);
+ return -1;
+}
+#endif
diff --git a/Cython/Utility/CConvert.pyx b/Cython/Utility/CConvert.pyx
index 5969f6a58..4ae66162e 100644
--- a/Cython/Utility/CConvert.pyx
+++ b/Cython/Utility/CConvert.pyx
@@ -6,19 +6,20 @@ cdef extern from *:
PyTypeObject *Py_TYPE(obj)
bint PyMapping_Check(obj)
object PyErr_Format(exc, const char *format, ...)
+ int __Pyx_RaiseUnexpectedTypeError(const char *expected, object obj) except 0
@cname("{{funcname}}")
cdef {{struct_type}} {{funcname}}(obj) except *:
cdef {{struct_type}} result
if not PyMapping_Check(obj):
- PyErr_Format(TypeError, b"Expected %.16s, got %.200s", b"a mapping", Py_TYPE(obj).tp_name)
+ __Pyx_RaiseUnexpectedTypeError(b"a mapping", obj)
{{for member in var_entries:}}
try:
value = obj['{{member.name}}']
except KeyError:
raise ValueError("No value specified for struct attribute '{{member.name}}'")
- result.{{member.cname}} = value
+ result.{{member.name}} = value
{{endfor}}
return result
@@ -31,13 +32,14 @@ cdef extern from *:
PyTypeObject *Py_TYPE(obj)
bint PyMapping_Check(obj)
object PyErr_Format(exc, const char *format, ...)
+ int __Pyx_RaiseUnexpectedTypeError(const char *expected, object obj) except 0
@cname("{{funcname}}")
cdef {{struct_type}} {{funcname}}(obj) except *:
cdef {{struct_type}} result
cdef Py_ssize_t length
if not PyMapping_Check(obj):
- PyErr_Format(TypeError, b"Expected %.16s, got %.200s", b"a mapping", Py_TYPE(obj).tp_name)
+ __Pyx_RaiseUnexpectedTypeError(b"a mapping", obj)
last_found = None
length = len(obj)
diff --git a/Cython/Utility/Capsule.c b/Cython/Utility/Capsule.c
deleted file mode 100644
index cc4fe0d88..000000000
--- a/Cython/Utility/Capsule.c
+++ /dev/null
@@ -1,20 +0,0 @@
-//////////////// Capsule.proto ////////////////
-
-/* Todo: wrap the rest of the functionality in similar functions */
-static CYTHON_INLINE PyObject *__pyx_capsule_create(void *p, const char *sig);
-
-//////////////// Capsule ////////////////
-
-static CYTHON_INLINE PyObject *
-__pyx_capsule_create(void *p, CYTHON_UNUSED const char *sig)
-{
- PyObject *cobj;
-
-#if PY_VERSION_HEX >= 0x02070000
- cobj = PyCapsule_New(p, sig, NULL);
-#else
- cobj = PyCObject_FromVoidPtr(p, NULL);
-#endif
-
- return cobj;
-}
diff --git a/Cython/Utility/CommonStructures.c b/Cython/Utility/CommonStructures.c
index c7945feb4..f39f3d70d 100644
--- a/Cython/Utility/CommonStructures.c
+++ b/Cython/Utility/CommonStructures.c
@@ -1,43 +1,80 @@
+/////////////// FetchSharedCythonModule.proto ///////
+
+static PyObject *__Pyx_FetchSharedCythonABIModule(void);
+
+/////////////// FetchSharedCythonModule ////////////
+
+static PyObject *__Pyx_FetchSharedCythonABIModule(void) {
+ PyObject *abi_module = PyImport_AddModule((char*) __PYX_ABI_MODULE_NAME);
+ if (unlikely(!abi_module)) return NULL;
+ Py_INCREF(abi_module);
+ return abi_module;
+}
+
/////////////// FetchCommonType.proto ///////////////
+#if !CYTHON_USE_TYPE_SPECS
static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type);
+#else
+static PyTypeObject* __Pyx_FetchCommonTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases);
+#endif
/////////////// FetchCommonType ///////////////
+//@requires:ExtensionTypes.c::FixUpExtensionType
+//@requires: FetchSharedCythonModule
+//@requires:StringTools.c::IncludeStringH
+
+static int __Pyx_VerifyCachedType(PyObject *cached_type,
+ const char *name,
+ Py_ssize_t basicsize,
+ Py_ssize_t expected_basicsize) {
+ if (!PyType_Check(cached_type)) {
+ PyErr_Format(PyExc_TypeError,
+ "Shared Cython type %.200s is not a type object", name);
+ return -1;
+ }
+ if (basicsize != expected_basicsize) {
+ PyErr_Format(PyExc_TypeError,
+ "Shared Cython type %.200s has the wrong size, try recompiling",
+ name);
+ return -1;
+ }
+ return 0;
+}
+#if !CYTHON_USE_TYPE_SPECS
static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type) {
- PyObject* fake_module;
- PyTypeObject* cached_type = NULL;
-
- fake_module = PyImport_AddModule((char*) "_cython_" CYTHON_ABI);
- if (!fake_module) return NULL;
- Py_INCREF(fake_module);
-
- cached_type = (PyTypeObject*) PyObject_GetAttrString(fake_module, type->tp_name);
+ PyObject* abi_module;
+ const char* object_name;
+ PyTypeObject *cached_type = NULL;
+
+ abi_module = __Pyx_FetchSharedCythonABIModule();
+ if (!abi_module) return NULL;
+ // get the final part of the object name (after the last dot)
+ object_name = strrchr(type->tp_name, '.');
+ object_name = object_name ? object_name+1 : type->tp_name;
+ cached_type = (PyTypeObject*) PyObject_GetAttrString(abi_module, object_name);
if (cached_type) {
- if (!PyType_Check((PyObject*)cached_type)) {
- PyErr_Format(PyExc_TypeError,
- "Shared Cython type %.200s is not a type object",
- type->tp_name);
+ if (__Pyx_VerifyCachedType(
+ (PyObject *)cached_type,
+ object_name,
+ cached_type->tp_basicsize,
+ type->tp_basicsize) < 0) {
goto bad;
}
- if (cached_type->tp_basicsize != type->tp_basicsize) {
- PyErr_Format(PyExc_TypeError,
- "Shared Cython type %.200s has the wrong size, try recompiling",
- type->tp_name);
- goto bad;
- }
- } else {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad;
- PyErr_Clear();
- if (PyType_Ready(type) < 0) goto bad;
- if (PyObject_SetAttrString(fake_module, type->tp_name, (PyObject*) type) < 0)
- goto bad;
- Py_INCREF(type);
- cached_type = type;
+ goto done;
}
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad;
+ PyErr_Clear();
+ if (PyType_Ready(type) < 0) goto bad;
+ if (PyObject_SetAttrString(abi_module, object_name, (PyObject *)type) < 0)
+ goto bad;
+ Py_INCREF(type);
+ cached_type = type;
+
done:
- Py_DECREF(fake_module);
+ Py_DECREF(abi_module);
// NOTE: always returns owned reference, or NULL on error
return cached_type;
@@ -46,41 +83,60 @@ bad:
cached_type = NULL;
goto done;
}
+#else
+static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) {
+ PyObject *abi_module, *cached_type = NULL;
+ // get the final part of the object name (after the last dot)
+ const char* object_name = strrchr(spec->name, '.');
+ object_name = object_name ? object_name+1 : spec->name;
-/////////////// FetchCommonPointer.proto ///////////////
-
-static void* __Pyx_FetchCommonPointer(void* pointer, const char* name);
-
-/////////////// FetchCommonPointer ///////////////
-
-
-static void* __Pyx_FetchCommonPointer(void* pointer, const char* name) {
-#if PY_VERSION_HEX >= 0x02070000
- PyObject* fake_module = NULL;
- PyObject* capsule = NULL;
- void* value = NULL;
-
- fake_module = PyImport_AddModule((char*) "_cython_" CYTHON_ABI);
- if (!fake_module) return NULL;
- Py_INCREF(fake_module);
+ abi_module = __Pyx_FetchSharedCythonABIModule();
+ if (!abi_module) return NULL;
- capsule = PyObject_GetAttrString(fake_module, name);
- if (!capsule) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad;
- PyErr_Clear();
- capsule = PyCapsule_New(pointer, name, NULL);
- if (!capsule) goto bad;
- if (PyObject_SetAttrString(fake_module, name, capsule) < 0)
+ cached_type = PyObject_GetAttrString(abi_module, object_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 (unlikely(!py_basicsize)) goto bad;
+ basicsize = PyLong_AsSsize_t(py_basicsize);
+ Py_DECREF(py_basicsize);
+ py_basicsize = 0;
+ 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,
+ object_name,
+ basicsize,
+ spec->basicsize) < 0) {
goto bad;
+ }
+ goto done;
}
- value = PyCapsule_GetPointer(capsule, name);
+
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad;
+ PyErr_Clear();
+ // We pass the ABI module reference to avoid keeping the user module alive by foreign type usages.
+ CYTHON_UNUSED_VAR(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, object_name, cached_type) < 0) goto bad;
+
+done:
+ Py_DECREF(abi_module);
+ // NOTE: always returns owned reference, or NULL on error
+ assert(cached_type == NULL || PyType_Check(cached_type));
+ return (PyTypeObject *) cached_type;
bad:
- Py_XDECREF(capsule);
- Py_DECREF(fake_module);
- return value;
-#else
- return pointer;
-#endif
+ Py_XDECREF(cached_type);
+ cached_type = NULL;
+ goto done;
}
+#endif
+
diff --git a/Cython/Utility/Complex.c b/Cython/Utility/Complex.c
index 15d5f544d..fd2cd081a 100644
--- a/Cython/Utility/Complex.c
+++ b/Cython/Utility/Complex.c
@@ -4,7 +4,8 @@
#if !defined(CYTHON_CCOMPLEX)
#if defined(__cplusplus)
#define CYTHON_CCOMPLEX 1
- #elif defined(_Complex_I)
+ #elif defined(_Complex_I) || (__STDC_VERSION__ >= 201112L && !defined(__STDC_NO_COMPLEX__))
+ // <complex.h> should exist since C99, but only C11 defines a test to detect it
#define CYTHON_CCOMPLEX 1
#else
#define CYTHON_CCOMPLEX 0
@@ -24,7 +25,6 @@
#define _Complex_I 1.0fj
#endif
-
/////////////// RealImag.proto ///////////////
#if CYTHON_CCOMPLEX
@@ -49,11 +49,42 @@
#define __Pyx_SET_CIMAG(z,y) __Pyx_CIMAG(z) = (y)
#endif
+/////////////// RealImag_Cy.proto ///////////////
+
+// alternative version of RealImag.proto for the case where
+// we definitely want to force it to use the Cython utility
+// code version of complex.
+// Because integer complex types simply aren't covered by
+// the C or C++ standards
+// (although practically will probably work in C++).
+
+#define __Pyx_CREAL_Cy(z) ((z).real)
+#define __Pyx_CIMAG_Cy(z) ((z).imag)
+#define __Pyx_SET_CREAL_Cy(z,x) __Pyx_CREAL_Cy(z) = (x)
+#define __Pyx_SET_CIMAG_Cy(z,y) __Pyx_CIMAG_cy(z) = (y)
+
+/////////////// RealImag_CyTypedef.proto //////////
+//@requires: RealImag
+//@requires: RealImag_Cy
+
+#if __cplusplus
+// C++ is fine with complexes based on typedefs because the template sees through them
+#define __Pyx_CREAL_CyTypedef(z) __Pyx_CREAL(z)
+#define __Pyx_CIMAG_CyTypedef(z) __Pyx_CIMAG(z)
+#define __Pyx_SET_CREAL_CyTypedef(z,x) __Pyx_SET_CREAL(z)
+#define __Pyx_SET_CIMAG_CyTypedef(z,x) __Pyx_SET_CIMAG(z)
+#else
+// C isn't
+#define __Pyx_CREAL_CyTypedef(z) __Pyx_CREAL_Cy(z)
+#define __Pyx_CIMAG_CyTypedef(z) __Pyx_CIMAG_Cy(z)
+#define __Pyx_SET_CREAL_CyTypedef(z,x) __Pyx_SET_CREAL_Cy(z)
+#define __Pyx_SET_CIMAG_CyTypedef(z,x) __Pyx_SET_CIMAG_Cy(z)
+#endif
/////////////// Declarations.proto ///////////////
//@proto_block: complex_type_declarations
-#if CYTHON_CCOMPLEX
+#if CYTHON_CCOMPLEX && ({{is_float}}) && (!{{is_extern_float_typedef}} || __cplusplus)
#ifdef __cplusplus
typedef ::std::complex< {{real_type}} > {{type_name}};
#else
@@ -67,7 +98,7 @@ static CYTHON_INLINE {{type}} {{type_name}}_from_parts({{real_type}}, {{real_typ
/////////////// Declarations ///////////////
-#if CYTHON_CCOMPLEX
+#if CYTHON_CCOMPLEX && ({{is_float}}) && (!{{is_extern_float_typedef}} || __cplusplus)
#ifdef __cplusplus
static CYTHON_INLINE {{type}} {{type_name}}_from_parts({{real_type}} x, {{real_type}} y) {
return ::std::complex< {{real_type}} >(x, y);
@@ -89,10 +120,10 @@ static CYTHON_INLINE {{type}} {{type_name}}_from_parts({{real_type}}, {{real_typ
/////////////// ToPy.proto ///////////////
-#define __pyx_PyComplex_FromComplex(z) \
- PyComplex_FromDoubles((double)__Pyx_CREAL(z), \
- (double)__Pyx_CIMAG(z))
-
+{{py: func_suffix = "_CyTypedef" if is_extern_float_typedef else ("" if is_float else "_Cy")}}
+#define __pyx_PyComplex_FromComplex{{func_suffix}}(z) \
+ PyComplex_FromDoubles((double)__Pyx_CREAL{{func_suffix}}(z), \
+ (double)__Pyx_CIMAG{{func_suffix}}(z))
/////////////// FromPy.proto ///////////////
@@ -116,7 +147,7 @@ static {{type}} __Pyx_PyComplex_As_{{type_name}}(PyObject* o) {
/////////////// Arithmetic.proto ///////////////
-#if CYTHON_CCOMPLEX
+#if CYTHON_CCOMPLEX && ({{is_float}}) && (!{{is_extern_float_typedef}} || __cplusplus)
#define __Pyx_c_eq{{func_suffix}}(a, b) ((a)==(b))
#define __Pyx_c_sum{{func_suffix}}(a, b) ((a)+(b))
#define __Pyx_c_diff{{func_suffix}}(a, b) ((a)-(b))
@@ -155,7 +186,7 @@ static {{type}} __Pyx_PyComplex_As_{{type_name}}(PyObject* o) {
/////////////// Arithmetic ///////////////
-#if CYTHON_CCOMPLEX
+#if CYTHON_CCOMPLEX && ({{is_float}}) && (!{{is_extern_float_typedef}} || __cplusplus)
#else
static CYTHON_INLINE int __Pyx_c_eq{{func_suffix}}({{type}} a, {{type}} b) {
return (a.real == b.real) && (a.imag == b.imag);
@@ -289,3 +320,46 @@ static {{type}} __Pyx_PyComplex_As_{{type_name}}(PyObject* o) {
}
#endif
#endif
+
+/////////////// SoftComplexToDouble.proto //////////////////
+
+static double __Pyx_SoftComplexToDouble(__pyx_t_double_complex value, int have_gil); /* proto */
+
+/////////////// SoftComplexToDouble //////////////////
+//@requires: RealImag
+
+static double __Pyx_SoftComplexToDouble(__pyx_t_double_complex value, int have_gil) {
+ // This isn't an absolutely perfect match for the Python behaviour:
+ // In Python the type would be determined right after the number is
+ // created (usually '**'), while here it's determined when coerced
+ // to a PyObject, which may be a few operations later.
+ if (unlikely(__Pyx_CIMAG(value))) {
+ PyGILState_STATE gilstate;
+ if (!have_gil)
+ gilstate = PyGILState_Ensure();
+ PyErr_SetString(PyExc_TypeError,
+ "Cannot convert 'complex' with non-zero imaginary component to 'double' "
+ "(this most likely comes from the '**' operator; "
+ "use 'cython.cpow(True)' to return 'nan' instead of a "
+ "complex number).");
+ if (!have_gil)
+ PyGILState_Release(gilstate);
+ return -1.;
+ }
+ return __Pyx_CREAL(value);
+}
+
+///////// SoftComplexToPy.proto ///////////////////////
+
+static PyObject *__pyx_Py_FromSoftComplex(__pyx_t_double_complex value); /* proto */
+
+//////// SoftComplexToPy ////////////////
+//@requires: RealImag
+
+static PyObject *__pyx_Py_FromSoftComplex(__pyx_t_double_complex value) {
+ if (__Pyx_CIMAG(value)) {
+ return PyComplex_FromDoubles(__Pyx_CREAL(value), __Pyx_CIMAG(value));
+ } else {
+ return PyFloat_FromDouble(__Pyx_CREAL(value));
+ }
+}
diff --git a/Cython/Utility/Coroutine.c b/Cython/Utility/Coroutine.c
index aaa8a8e26..8d3c64a4f 100644
--- a/Cython/Utility/Coroutine.c
+++ b/Cython/Utility/Coroutine.c
@@ -5,12 +5,15 @@ static CYTHON_INLINE PyObject* __Pyx_Generator_Yield_From(__pyx_CoroutineObject
//////////////////// GeneratorYieldFrom ////////////////////
//@requires: Generator
-static void __PyxPyIter_CheckErrorAndDecref(PyObject *source) {
+#if CYTHON_USE_TYPE_SLOTS
+static void __Pyx_PyIter_CheckErrorAndDecref(PyObject *source) {
+ __Pyx_TypeName source_type_name = __Pyx_PyType_GetName(Py_TYPE(source));
PyErr_Format(PyExc_TypeError,
- "iter() returned non-iterator of type '%.100s'",
- Py_TYPE(source)->tp_name);
+ "iter() returned non-iterator of type '" __Pyx_FMT_TYPENAME "'", source_type_name);
+ __Pyx_DECREF_TypeName(source_type_name);
Py_DECREF(source);
}
+#endif
static CYTHON_INLINE PyObject* __Pyx_Generator_Yield_From(__pyx_CoroutineObject *gen, PyObject *source) {
PyObject *source_gen, *retval;
@@ -29,7 +32,7 @@ static CYTHON_INLINE PyObject* __Pyx_Generator_Yield_From(__pyx_CoroutineObject
if (unlikely(!source_gen))
return NULL;
if (unlikely(!PyIter_Check(source_gen))) {
- __PyxPyIter_CheckErrorAndDecref(source_gen);
+ __Pyx_PyIter_CheckErrorAndDecref(source_gen);
return NULL;
}
} else
@@ -41,11 +44,7 @@ static CYTHON_INLINE PyObject* __Pyx_Generator_Yield_From(__pyx_CoroutineObject
return NULL;
}
// source_gen is now the iterator, make the first next() call
-#if CYTHON_USE_TYPE_SLOTS
- retval = Py_TYPE(source_gen)->tp_iternext(source_gen);
-#else
- retval = PyIter_Next(source_gen);
-#endif
+ retval = __Pyx_PyObject_GetIterNextFunc(source_gen)(source_gen);
}
if (likely(retval)) {
gen->yieldfrom = source_gen;
@@ -74,11 +73,7 @@ static PyObject* __Pyx__Coroutine_Yield_From_Generic(__pyx_CoroutineObject *gen,
if (__Pyx_Coroutine_Check(source_gen)) {
retval = __Pyx_Generator_Next(source_gen);
} else {
-#if CYTHON_USE_TYPE_SLOTS
- retval = Py_TYPE(source_gen)->tp_iternext(source_gen);
-#else
- retval = PyIter_Next(source_gen);
-#endif
+ retval = __Pyx_PyObject_GetIterNextFunc(source_gen)(source_gen);
}
if (retval) {
gen->yieldfrom = source_gen;
@@ -136,13 +131,13 @@ static CYTHON_INLINE PyObject *__Pyx_Coroutine_GetAwaitableIter(PyObject *o) {
static void __Pyx_Coroutine_AwaitableIterError(PyObject *source) {
#if PY_VERSION_HEX >= 0x030600B3 || defined(_PyErr_FormatFromCause)
- _PyErr_FormatFromCause(
- PyExc_TypeError,
- "'async for' received an invalid object "
- "from __anext__: %.100s",
- Py_TYPE(source)->tp_name);
+ __Pyx_TypeName source_type_name = __Pyx_PyType_GetName(Py_TYPE(source));
+ _PyErr_FormatFromCause(PyExc_TypeError,
+ "'async for' received an invalid object from __anext__: " __Pyx_FMT_TYPENAME, source_type_name);
+ __Pyx_DECREF_TypeName(source_type_name);
#elif PY_MAJOR_VERSION >= 3
PyObject *exc, *val, *val2, *tb;
+ __Pyx_TypeName source_type_name = __Pyx_PyType_GetName(Py_TYPE(source));
assert(PyErr_Occurred());
PyErr_Fetch(&exc, &val, &tb);
PyErr_NormalizeException(&exc, &val, &tb);
@@ -152,11 +147,9 @@ static void __Pyx_Coroutine_AwaitableIterError(PyObject *source) {
}
Py_DECREF(exc);
assert(!PyErr_Occurred());
- PyErr_Format(
- PyExc_TypeError,
- "'async for' received an invalid object "
- "from __anext__: %.100s",
- Py_TYPE(source)->tp_name);
+ PyErr_Format(PyExc_TypeError,
+ "'async for' received an invalid object from __anext__: " __Pyx_FMT_TYPENAME, source_type_name);
+ __Pyx_DECREF_TypeName(source_type_name);
PyErr_Fetch(&exc, &val2, &tb);
PyErr_NormalizeException(&exc, &val2, &tb);
@@ -211,9 +204,10 @@ static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *obj) {
goto bad;
}
if (unlikely(!PyIter_Check(res))) {
+ __Pyx_TypeName res_type_name = __Pyx_PyType_GetName(Py_TYPE(res));
PyErr_Format(PyExc_TypeError,
- "__await__() returned non-iterator of type '%.100s'",
- Py_TYPE(res)->tp_name);
+ "__await__() returned non-iterator of type '" __Pyx_FMT_TYPENAME "'", res_type_name);
+ __Pyx_DECREF_TypeName(res_type_name);
Py_CLEAR(res);
} else {
int is_coroutine = 0;
@@ -233,9 +227,12 @@ static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *obj) {
}
return res;
slot_error:
- PyErr_Format(PyExc_TypeError,
- "object %.100s can't be used in 'await' expression",
- Py_TYPE(obj)->tp_name);
+ {
+ __Pyx_TypeName obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj));
+ PyErr_Format(PyExc_TypeError,
+ "object " __Pyx_FMT_TYPENAME " can't be used in 'await' expression", obj_type_name);
+ __Pyx_DECREF_TypeName(obj_type_name);
+ }
bad:
return NULL;
}
@@ -251,6 +248,7 @@ static CYTHON_INLINE PyObject *__Pyx_Coroutine_AsyncIterNext(PyObject *o); /*pro
//@requires: ObjectHandling.c::PyObjectCallMethod0
static PyObject *__Pyx_Coroutine_GetAsyncIter_Generic(PyObject *obj) {
+ __Pyx_TypeName obj_type_name;
#if PY_VERSION_HEX < 0x030500B1
{
PyObject *iter = __Pyx_PyObject_CallMethod0(obj, PYIDENT("__aiter__"));
@@ -262,11 +260,13 @@ static PyObject *__Pyx_Coroutine_GetAsyncIter_Generic(PyObject *obj) {
}
#else
// avoid C warning about 'unused function'
- if ((0)) (void) __Pyx_PyObject_CallMethod0(obj, PYIDENT("__aiter__"));
+ (void)&__Pyx_PyObject_CallMethod0;
#endif
- PyErr_Format(PyExc_TypeError, "'async for' requires an object with __aiter__ method, got %.100s",
- Py_TYPE(obj)->tp_name);
+ obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj));
+ PyErr_Format(PyExc_TypeError,
+ "'async for' requires an object with __aiter__ method, got " __Pyx_FMT_TYPENAME, obj_type_name);
+ __Pyx_DECREF_TypeName(obj_type_name);
return NULL;
}
@@ -299,8 +299,12 @@ static PyObject *__Pyx__Coroutine_AsyncIterNext(PyObject *obj) {
// FIXME: for the sake of a nicely conforming exception message, assume any AttributeError meant '__anext__'
if (PyErr_ExceptionMatches(PyExc_AttributeError))
#endif
- PyErr_Format(PyExc_TypeError, "'async for' requires an object with __anext__ method, got %.100s",
- Py_TYPE(obj)->tp_name);
+ {
+ __Pyx_TypeName obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj));
+ PyErr_Format(PyExc_TypeError,
+ "'async for' requires an object with __anext__ method, got " __Pyx_FMT_TYPENAME, obj_type_name);
+ __Pyx_DECREF_TypeName(obj_type_name);
+ }
return NULL;
}
@@ -330,12 +334,13 @@ static void __Pyx_Generator_Replace_StopIteration(int in_async_gen); /*proto*/
//////////////////// pep479 ////////////////////
//@requires: Exceptions.c::GetException
-static void __Pyx_Generator_Replace_StopIteration(CYTHON_UNUSED int in_async_gen) {
+static void __Pyx_Generator_Replace_StopIteration(int in_async_gen) {
PyObject *exc, *val, *tb, *cur_exc;
__Pyx_PyThreadState_declare
#ifdef __Pyx_StopAsyncIteration_USED
int is_async_stopiteration = 0;
#endif
+ CYTHON_MAYBE_UNUSED_VAR(in_async_gen);
cur_exc = PyErr_Occurred();
if (likely(!__Pyx_PyErr_GivenExceptionMatches(cur_exc, PyExc_StopIteration))) {
@@ -366,7 +371,8 @@ static void __Pyx_Generator_Replace_StopIteration(CYTHON_UNUSED int in_async_gen
//////////////////// CoroutineBase.proto ////////////////////
//@substitute: naming
-typedef PyObject *(*__pyx_coroutine_body_t)(PyObject *, PyThreadState *, PyObject *);
+struct __pyx_CoroutineObject;
+typedef PyObject *(*__pyx_coroutine_body_t)(struct __pyx_CoroutineObject *, PyThreadState *, PyObject *);
#if CYTHON_USE_EXC_INFO_STACK
// See https://bugs.python.org/issue25612
@@ -380,7 +386,7 @@ typedef struct {
} __Pyx_ExcInfoStruct;
#endif
-typedef struct {
+typedef struct __pyx_CoroutineObject {
PyObject_HEAD
__pyx_coroutine_body_t body;
PyObject *closure;
@@ -441,17 +447,15 @@ static CYTHON_INLINE void __Pyx_Coroutine_ResetFrameBackpointer(__Pyx_ExcInfoStr
//////////////////// Coroutine.proto ////////////////////
#define __Pyx_Coroutine_USED
-static PyTypeObject *__pyx_CoroutineType = 0;
-static PyTypeObject *__pyx_CoroutineAwaitType = 0;
-#define __Pyx_Coroutine_CheckExact(obj) (Py_TYPE(obj) == __pyx_CoroutineType)
+#define __Pyx_Coroutine_CheckExact(obj) __Pyx_IS_TYPE(obj, __pyx_CoroutineType)
// __Pyx_Coroutine_Check(obj): see override for IterableCoroutine below
#define __Pyx_Coroutine_Check(obj) __Pyx_Coroutine_CheckExact(obj)
-#define __Pyx_CoroutineAwait_CheckExact(obj) (Py_TYPE(obj) == __pyx_CoroutineAwaitType)
+#define __Pyx_CoroutineAwait_CheckExact(obj) __Pyx_IS_TYPE(obj, __pyx_CoroutineAwaitType)
#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 {
@@ -466,14 +470,13 @@ static PyObject *__Pyx_CoroutineAwait_Throw(__pyx_CoroutineAwaitObject *self, Py
//////////////////// Generator.proto ////////////////////
#define __Pyx_Generator_USED
-static PyTypeObject *__pyx_GeneratorType = 0;
-#define __Pyx_Generator_CheckExact(obj) (Py_TYPE(obj) == __pyx_GeneratorType)
+#define __Pyx_Generator_CheckExact(obj) __Pyx_IS_TYPE(obj, __pyx_GeneratorType)
#define __Pyx_Generator_New(body, code, closure, name, qualname, module_name) \
__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 ////////////////////
@@ -489,10 +492,13 @@ static int __pyx_Generator_init(void); /*proto*/
//@requires: Exceptions.c::RaiseException
//@requires: Exceptions.c::SaveResetException
//@requires: ObjectHandling.c::PyObjectCallMethod1
+//@requires: ObjectHandling.c::PyObjectCallNoArg
+//@requires: ObjectHandling.c::PyObjectFastCall
//@requires: ObjectHandling.c::PyObjectGetAttrStr
+//@requires: ObjectHandling.c::PyObjectGetAttrStrNoError
//@requires: CommonStructures.c::FetchCommonType
+//@requires: ModuleSetupCode.c::IncludeStructmemberH
-#include <structmember.h>
#include <frameobject.h>
#if PY_VERSION_HEX >= 0x030b00a6
#ifndef Py_BUILD_CORE
@@ -509,9 +515,10 @@ static int __pyx_Generator_init(void); /*proto*/
// Returns 0 if no exception or StopIteration is set.
// If any other exception is set, returns -1 and leaves
// pvalue unchanged.
-static int __Pyx_PyGen__FetchStopIterationValue(CYTHON_UNUSED PyThreadState *$local_tstate_cname, PyObject **pvalue) {
+static int __Pyx_PyGen__FetchStopIterationValue(PyThreadState *$local_tstate_cname, PyObject **pvalue) {
PyObject *et, *ev, *tb;
PyObject *value = NULL;
+ CYTHON_UNUSED_VAR($local_tstate_cname);
__Pyx_ErrFetch(&et, &ev, &tb);
@@ -530,7 +537,7 @@ static int __Pyx_PyGen__FetchStopIterationValue(CYTHON_UNUSED PyThreadState *$lo
value = Py_None;
}
#if PY_VERSION_HEX >= 0x030300A0
- else if (Py_TYPE(ev) == (PyTypeObject*)PyExc_StopIteration) {
+ else if (likely(__Pyx_IS_TYPE(ev, (PyTypeObject*)PyExc_StopIteration))) {
value = ((PyStopIterationObject *)ev)->value;
Py_INCREF(value);
Py_DECREF(ev);
@@ -601,6 +608,9 @@ static int __Pyx_PyGen__FetchStopIterationValue(CYTHON_UNUSED PyThreadState *$lo
static CYTHON_INLINE
void __Pyx_Coroutine_ExceptionClear(__Pyx_ExcInfoStruct *exc_state) {
+#if PY_VERSION_HEX >= 0x030B00a4
+ Py_CLEAR(exc_state->exc_value);
+#else
PyObject *t, *v, *tb;
t = exc_state->exc_type;
v = exc_state->exc_value;
@@ -613,11 +623,13 @@ void __Pyx_Coroutine_ExceptionClear(__Pyx_ExcInfoStruct *exc_state) {
Py_XDECREF(t);
Py_XDECREF(v);
Py_XDECREF(tb);
+#endif
}
#define __Pyx_Coroutine_AlreadyRunningError(gen) (__Pyx__Coroutine_AlreadyRunningError(gen), (PyObject*)NULL)
-static void __Pyx__Coroutine_AlreadyRunningError(CYTHON_UNUSED __pyx_CoroutineObject *gen) {
+static void __Pyx__Coroutine_AlreadyRunningError(__pyx_CoroutineObject *gen) {
const char *msg;
+ CYTHON_MAYBE_UNUSED_VAR(gen);
if ((0)) {
#ifdef __Pyx_Coroutine_USED
} else if (__Pyx_Coroutine_Check((PyObject*)gen)) {
@@ -634,8 +646,9 @@ static void __Pyx__Coroutine_AlreadyRunningError(CYTHON_UNUSED __pyx_CoroutineOb
}
#define __Pyx_Coroutine_NotStartedError(gen) (__Pyx__Coroutine_NotStartedError(gen), (PyObject*)NULL)
-static void __Pyx__Coroutine_NotStartedError(CYTHON_UNUSED PyObject *gen) {
+static void __Pyx__Coroutine_NotStartedError(PyObject *gen) {
const char *msg;
+ CYTHON_MAYBE_UNUSED_VAR(gen);
if ((0)) {
#ifdef __Pyx_Coroutine_USED
} else if (__Pyx_Coroutine_Check(gen)) {
@@ -652,7 +665,9 @@ static void __Pyx__Coroutine_NotStartedError(CYTHON_UNUSED PyObject *gen) {
}
#define __Pyx_Coroutine_AlreadyTerminatedError(gen, value, closing) (__Pyx__Coroutine_AlreadyTerminatedError(gen, value, closing), (PyObject*)NULL)
-static void __Pyx__Coroutine_AlreadyTerminatedError(CYTHON_UNUSED PyObject *gen, PyObject *value, CYTHON_UNUSED int closing) {
+static void __Pyx__Coroutine_AlreadyTerminatedError(PyObject *gen, PyObject *value, int closing) {
+ CYTHON_MAYBE_UNUSED_VAR(gen);
+ CYTHON_MAYBE_UNUSED_VAR(closing);
#ifdef __Pyx_Coroutine_USED
if (!closing && __Pyx_Coroutine_Check(gen)) {
// `self` is an exhausted coroutine: raise an error,
@@ -714,14 +729,21 @@ PyObject *__Pyx_Coroutine_SendEx(__pyx_CoroutineObject *self, PyObject *value, i
// - do not touch external frames and tracebacks
exc_state = &self->gi_exc_state;
- if (exc_state->exc_type) {
- #if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_PYSTON
+ if (exc_state->exc_value) {
+ #if CYTHON_COMPILING_IN_PYPY
// FIXME: what to do in PyPy?
#else
// Generators always return to their most recent caller, not
// necessarily their creator.
- if (exc_state->exc_traceback) {
- PyTracebackObject *tb = (PyTracebackObject *) exc_state->exc_traceback;
+ PyObject *exc_tb;
+ #if PY_VERSION_HEX >= 0x030B00a4
+ // owned reference!
+ exc_tb = PyException_GetTraceback(exc_state->exc_value);
+ #else
+ exc_tb = exc_state->exc_traceback;
+ #endif
+ if (exc_tb) {
+ PyTracebackObject *tb = (PyTracebackObject *) exc_tb;
PyFrameObject *f = tb->tb_frame;
assert(f->f_back == NULL);
@@ -733,6 +755,9 @@ PyObject *__Pyx_Coroutine_SendEx(__pyx_CoroutineObject *self, PyObject *value, i
Py_XINCREF(tstate->frame);
f->f_back = tstate->frame;
#endif
+ #if PY_VERSION_HEX >= 0x030B00a4
+ Py_DECREF(exc_tb);
+ #endif
}
#endif
}
@@ -755,7 +780,7 @@ PyObject *__Pyx_Coroutine_SendEx(__pyx_CoroutineObject *self, PyObject *value, i
#endif
self->is_running = 1;
- retval = self->body((PyObject *) self, tstate, value);
+ retval = self->body(self, tstate, value);
self->is_running = 0;
#if CYTHON_USE_EXC_INFO_STACK
@@ -774,21 +799,34 @@ static CYTHON_INLINE void __Pyx_Coroutine_ResetFrameBackpointer(__Pyx_ExcInfoStr
// Don't keep the reference to f_back any longer than necessary. It
// may keep a chain of frames alive or it could create a reference
// cycle.
- PyObject *exc_tb = exc_state->exc_traceback;
-
- if (likely(exc_tb)) {
-#if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_PYSTON
+#if CYTHON_COMPILING_IN_PYPY
// FIXME: what to do in PyPy?
+ CYTHON_UNUSED_VAR(exc_state);
#else
+ PyObject *exc_tb;
+
+ #if PY_VERSION_HEX >= 0x030B00a4
+ if (!exc_state->exc_value) return;
+ // owned reference!
+ exc_tb = PyException_GetTraceback(exc_state->exc_value);
+ #else
+ exc_tb = exc_state->exc_traceback;
+ #endif
+
+ if (likely(exc_tb)) {
PyTracebackObject *tb = (PyTracebackObject *) exc_tb;
PyFrameObject *f = tb->tb_frame;
Py_CLEAR(f->f_back);
-#endif
+ #if PY_VERSION_HEX >= 0x030B00a4
+ Py_DECREF(exc_tb);
+ #endif
}
+#endif
}
static CYTHON_INLINE
-PyObject *__Pyx_Coroutine_MethodReturn(CYTHON_UNUSED PyObject* gen, PyObject *retval) {
+PyObject *__Pyx_Coroutine_MethodReturn(PyObject* gen, PyObject *retval) {
+ CYTHON_MAYBE_UNUSED_VAR(gen);
if (unlikely(!retval)) {
__Pyx_PyThreadState_declare
__Pyx_PyThreadState_assign
@@ -883,7 +921,7 @@ static PyObject *__Pyx_Coroutine_Send(PyObject *self, PyObject *value) {
#endif
{
if (value == Py_None)
- ret = Py_TYPE(yf)->tp_iternext(yf);
+ ret = __Pyx_PyObject_GetIterNextFunc(yf)(yf);
else
ret = __Pyx_PyObject_CallMethod1(yf, PYIDENT("send"), value);
}
@@ -937,16 +975,15 @@ static int __Pyx_Coroutine_CloseIter(__pyx_CoroutineObject *gen, PyObject *yf) {
{
PyObject *meth;
gen->is_running = 1;
- meth = __Pyx_PyObject_GetAttrStr(yf, PYIDENT("close"));
+ meth = __Pyx_PyObject_GetAttrStrNoError(yf, PYIDENT("close"));
if (unlikely(!meth)) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
+ if (unlikely(PyErr_Occurred())) {
PyErr_WriteUnraisable(yf);
}
- PyErr_Clear();
} else {
- retval = PyObject_CallFunction(meth, NULL);
+ retval = __Pyx_PyObject_CallNoArg(meth);
Py_DECREF(meth);
- if (!retval)
+ if (unlikely(!retval))
err = -1;
}
gen->is_running = 0;
@@ -982,7 +1019,7 @@ static PyObject *__Pyx_Generator_Next(PyObject *self) {
ret = __Pyx_Coroutine_Send(yf, Py_None);
} else
#endif
- ret = Py_TYPE(yf)->tp_iternext(yf);
+ ret = __Pyx_PyObject_GetIterNextFunc(yf)(yf);
gen->is_running = 0;
//Py_DECREF(yf);
if (likely(ret)) {
@@ -993,7 +1030,8 @@ static PyObject *__Pyx_Generator_Next(PyObject *self) {
return __Pyx_Coroutine_SendEx(gen, Py_None, 0);
}
-static PyObject *__Pyx_Coroutine_Close_Method(PyObject *self, CYTHON_UNUSED PyObject *arg) {
+static PyObject *__Pyx_Coroutine_Close_Method(PyObject *self, PyObject *arg) {
+ CYTHON_UNUSED_VAR(arg);
return __Pyx_Coroutine_Close(self);
}
@@ -1084,23 +1122,23 @@ static PyObject *__Pyx__Coroutine_Throw(PyObject *self, PyObject *typ, PyObject
ret = __Pyx__Coroutine_Throw(((__pyx_CoroutineAwaitObject*)yf)->coroutine, typ, val, tb, args, close_on_genexit);
#endif
} else {
- PyObject *meth = __Pyx_PyObject_GetAttrStr(yf, PYIDENT("throw"));
+ PyObject *meth = __Pyx_PyObject_GetAttrStrNoError(yf, PYIDENT("throw"));
if (unlikely(!meth)) {
Py_DECREF(yf);
- if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
+ if (unlikely(PyErr_Occurred())) {
gen->is_running = 0;
return NULL;
}
- PyErr_Clear();
__Pyx_Coroutine_Undelegate(gen);
gen->is_running = 0;
goto throw_here;
}
if (likely(args)) {
- ret = PyObject_CallObject(meth, args);
+ ret = __Pyx_PyObject_Call(meth, args, NULL);
} else {
// "tb" or even "val" might be NULL, but that also correctly terminates the argument list
- ret = PyObject_CallFunctionObjArgs(meth, typ, val, tb, NULL);
+ PyObject *cargs[4] = {NULL, typ, val, tb};
+ ret = __Pyx_PyObject_FastCall(meth, cargs+1, 3 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET);
}
Py_DECREF(meth);
}
@@ -1121,16 +1159,20 @@ static PyObject *__Pyx_Coroutine_Throw(PyObject *self, PyObject *args) {
PyObject *val = NULL;
PyObject *tb = NULL;
- if (!PyArg_UnpackTuple(args, (char *)"throw", 1, 3, &typ, &val, &tb))
+ if (unlikely(!PyArg_UnpackTuple(args, (char *)"throw", 1, 3, &typ, &val, &tb)))
return NULL;
return __Pyx__Coroutine_Throw(self, typ, val, tb, args, 1);
}
static CYTHON_INLINE int __Pyx_Coroutine_traverse_excstate(__Pyx_ExcInfoStruct *exc_state, visitproc visit, void *arg) {
+#if PY_VERSION_HEX >= 0x030B00a4
+ Py_VISIT(exc_state->exc_value);
+#else
Py_VISIT(exc_state->exc_type);
Py_VISIT(exc_state->exc_value);
Py_VISIT(exc_state->exc_traceback);
+#endif
return 0;
}
@@ -1172,10 +1214,10 @@ static void __Pyx_Coroutine_dealloc(PyObject *self) {
// Generator is paused or unstarted, so we need to close
PyObject_GC_Track(self);
#if PY_VERSION_HEX >= 0x030400a1 && CYTHON_USE_TP_FINALIZE
- if (PyObject_CallFinalizerFromDealloc(self))
+ if (unlikely(PyObject_CallFinalizerFromDealloc(self)))
#else
Py_TYPE(gen)->tp_del(self);
- if (Py_REFCNT(self) > 0)
+ if (unlikely(Py_REFCNT(self) > 0))
#endif
{
// resurrected. :(
@@ -1193,7 +1235,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) {
@@ -1291,7 +1333,7 @@ static void __Pyx_Coroutine_del(PyObject *self) {
// Undo the temporary resurrection; can't use DECREF here, it would
// cause a recursive call.
assert(Py_REFCNT(self) > 0);
- if (--self->ob_refcnt == 0) {
+ if (likely(--self->ob_refcnt == 0)) {
// this is the normal path out
return;
}
@@ -1324,9 +1366,10 @@ static void __Pyx_Coroutine_del(PyObject *self) {
}
static PyObject *
-__Pyx_Coroutine_get_name(__pyx_CoroutineObject *self, CYTHON_UNUSED void *context)
+__Pyx_Coroutine_get_name(__pyx_CoroutineObject *self, void *context)
{
PyObject *name = self->gi_name;
+ CYTHON_UNUSED_VAR(context);
// avoid NULL pointer dereference during garbage collection
if (unlikely(!name)) name = Py_None;
Py_INCREF(name);
@@ -1334,10 +1377,9 @@ __Pyx_Coroutine_get_name(__pyx_CoroutineObject *self, CYTHON_UNUSED void *contex
}
static int
-__Pyx_Coroutine_set_name(__pyx_CoroutineObject *self, PyObject *value, CYTHON_UNUSED void *context)
+__Pyx_Coroutine_set_name(__pyx_CoroutineObject *self, PyObject *value, void *context)
{
- PyObject *tmp;
-
+ CYTHON_UNUSED_VAR(context);
#if PY_MAJOR_VERSION >= 3
if (unlikely(value == NULL || !PyUnicode_Check(value)))
#else
@@ -1348,17 +1390,16 @@ __Pyx_Coroutine_set_name(__pyx_CoroutineObject *self, PyObject *value, CYTHON_UN
"__name__ must be set to a string object");
return -1;
}
- tmp = self->gi_name;
Py_INCREF(value);
- self->gi_name = value;
- Py_XDECREF(tmp);
+ __Pyx_Py_XDECREF_SET(self->gi_name, value);
return 0;
}
static PyObject *
-__Pyx_Coroutine_get_qualname(__pyx_CoroutineObject *self, CYTHON_UNUSED void *context)
+__Pyx_Coroutine_get_qualname(__pyx_CoroutineObject *self, void *context)
{
PyObject *name = self->gi_qualname;
+ CYTHON_UNUSED_VAR(context);
// avoid NULL pointer dereference during garbage collection
if (unlikely(!name)) name = Py_None;
Py_INCREF(name);
@@ -1366,10 +1407,9 @@ __Pyx_Coroutine_get_qualname(__pyx_CoroutineObject *self, CYTHON_UNUSED void *co
}
static int
-__Pyx_Coroutine_set_qualname(__pyx_CoroutineObject *self, PyObject *value, CYTHON_UNUSED void *context)
+__Pyx_Coroutine_set_qualname(__pyx_CoroutineObject *self, PyObject *value, void *context)
{
- PyObject *tmp;
-
+ CYTHON_UNUSED_VAR(context);
#if PY_MAJOR_VERSION >= 3
if (unlikely(value == NULL || !PyUnicode_Check(value)))
#else
@@ -1380,18 +1420,16 @@ __Pyx_Coroutine_set_qualname(__pyx_CoroutineObject *self, PyObject *value, CYTHO
"__qualname__ must be set to a string object");
return -1;
}
- tmp = self->gi_qualname;
Py_INCREF(value);
- self->gi_qualname = value;
- Py_XDECREF(tmp);
+ __Pyx_Py_XDECREF_SET(self->gi_qualname, value);
return 0;
}
-
static PyObject *
-__Pyx_Coroutine_get_frame(__pyx_CoroutineObject *self, CYTHON_UNUSED void *context)
+__Pyx_Coroutine_get_frame(__pyx_CoroutineObject *self, void *context)
{
PyObject *frame = self->gi_frame;
+ CYTHON_UNUSED_VAR(context);
if (!frame) {
if (unlikely(!self->gi_code)) {
// Avoid doing something stupid, e.g. during garbage collection.
@@ -1431,9 +1469,13 @@ static __pyx_CoroutineObject *__Pyx__Coroutine_NewInit(
gen->resume_label = 0;
gen->classobj = NULL;
gen->yieldfrom = NULL;
+ #if PY_VERSION_HEX >= 0x030B00a4
+ gen->gi_exc_state.exc_value = NULL;
+ #else
gen->gi_exc_state.exc_type = NULL;
gen->gi_exc_state.exc_value = NULL;
gen->gi_exc_state.exc_traceback = NULL;
+ #endif
#if CYTHON_USE_EXC_INFO_STACK
gen->gi_exc_state.previous_item = NULL;
#endif
@@ -1461,7 +1503,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) {
@@ -1486,7 +1528,8 @@ static PyObject *__Pyx_CoroutineAwait_Throw(__pyx_CoroutineAwaitObject *self, Py
return __Pyx_Coroutine_Throw(self->coroutine, args);
}
-static PyObject *__Pyx_CoroutineAwait_Close(__pyx_CoroutineAwaitObject *self, CYTHON_UNUSED PyObject *arg) {
+static PyObject *__Pyx_CoroutineAwait_Close(__pyx_CoroutineAwaitObject *self, PyObject *arg) {
+ CYTHON_UNUSED_VAR(arg);
return __Pyx_Coroutine_Close(self->coroutine);
}
@@ -1496,12 +1539,31 @@ static PyObject *__Pyx_CoroutineAwait_self(PyObject *self) {
}
#if !CYTHON_COMPILING_IN_PYPY
-static PyObject *__Pyx_CoroutineAwait_no_new(CYTHON_UNUSED PyTypeObject *type, CYTHON_UNUSED PyObject *args, CYTHON_UNUSED PyObject *kwargs) {
+static PyObject *__Pyx_CoroutineAwait_no_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) {
+ CYTHON_UNUSED_VAR(type);
+ CYTHON_UNUSED_VAR(args);
+ CYTHON_UNUSED_VAR(kwargs);
PyErr_SetString(PyExc_TypeError, "cannot instantiate type, use 'await coroutine' instead");
return NULL;
}
#endif
+// In earlier versions of Python an object with no __dict__ and not __slots__ is assumed
+// to be pickleable by default. Coroutine-wrappers have significant state so shouldn't be.
+// Therefore provide a default implementation.
+// Something similar applies to heaptypes (i.e. with type_specs) with protocols 0 and 1
+// even in more recent versions.
+// We are applying this to all Python versions (hence the commented out version guard)
+// to make the behaviour explicit.
+// #if PY_VERSION_HEX < 0x03060000 || CYTHON_USE_TYPE_SPECS
+static PyObject *__Pyx_CoroutineAwait_reduce_ex(__pyx_CoroutineAwaitObject *self, PyObject *arg) {
+ CYTHON_UNUSED_VAR(arg);
+ PyErr_Format(PyExc_TypeError, "cannot pickle '%.200s' object",
+ Py_TYPE(self)->tp_name);
+ return NULL;
+}
+// #endif
+
static PyMethodDef __pyx_CoroutineAwait_methods[] = {
{"send", (PyCFunction) __Pyx_CoroutineAwait_Send, METH_O,
(char*) PyDoc_STR("send(arg) -> send 'arg' into coroutine,\nreturn next yielded value or raise StopIteration.")},
@@ -1509,12 +1571,40 @@ static PyMethodDef __pyx_CoroutineAwait_methods[] = {
(char*) PyDoc_STR("throw(typ[,val[,tb]]) -> raise exception in coroutine,\nreturn next yielded value or raise StopIteration.")},
{"close", (PyCFunction) __Pyx_CoroutineAwait_Close, METH_NOARGS,
(char*) PyDoc_STR("close() -> raise GeneratorExit inside coroutine.")},
+// only needed with type-specs or version<3.6, but included in all versions for clarity
+// #if PY_VERSION_HEX < 0x03060000 || CYTHON_USE_TYPE_SPECS
+ {"__reduce_ex__", (PyCFunction) __Pyx_CoroutineAwait_reduce_ex, METH_O, 0},
+ {"__reduce__", (PyCFunction) __Pyx_CoroutineAwait_reduce_ex, METH_NOARGS, 0},
+// #endif
{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)
- "coroutine_wrapper", /*tp_name*/
+ __PYX_TYPE_MODULE_PREFIX "coroutine_wrapper", /*tp_name*/
sizeof(__pyx_CoroutineAwaitObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor) __Pyx_CoroutineAwait_dealloc,/*tp_dealloc*/
@@ -1570,7 +1660,7 @@ static PyTypeObject __pyx_CoroutineAwaitType_type = {
#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
0, /*tp_vectorcall*/
#endif
-#if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
+#if __PYX_NEED_TP_PRINT_SLOT
0, /*tp_print*/
#endif
#if PY_VERSION_HEX >= 0x030C0000
@@ -1580,6 +1670,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) {
@@ -1593,7 +1684,8 @@ static CYTHON_INLINE PyObject *__Pyx__Coroutine_await(PyObject *coroutine) {
#endif
#if PY_VERSION_HEX < 0x030500B1
-static PyObject *__Pyx_Coroutine_await_method(PyObject *coroutine, CYTHON_UNUSED PyObject *arg) {
+static PyObject *__Pyx_Coroutine_await_method(PyObject *coroutine, PyObject *arg) {
+ CYTHON_UNUSED_VAR(arg);
return __Pyx__Coroutine_await(coroutine);
}
#endif
@@ -1641,7 +1733,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}
};
@@ -1655,6 +1750,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*/
@@ -1668,7 +1787,7 @@ static __Pyx_PyAsyncMethodsStruct __pyx_Coroutine_as_async = {
static PyTypeObject __pyx_CoroutineType_type = {
PyVarObject_HEAD_INIT(0, 0)
- "coroutine", /*tp_name*/
+ __PYX_TYPE_MODULE_PREFIX "coroutine", /*tp_name*/
sizeof(__pyx_CoroutineObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor) __Pyx_Coroutine_dealloc,/*tp_dealloc*/
@@ -1736,7 +1855,7 @@ static PyTypeObject __pyx_CoroutineType_type = {
#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
0, /*tp_vectorcall*/
#endif
-#if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
+#if __PYX_NEED_TP_PRINT_SLOT
0, /*tp_print*/
#endif
#if PY_VERSION_HEX >= 0x030C0000
@@ -1746,20 +1865,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) {
+ CYTHON_MAYBE_UNUSED_VAR(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
__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;
@@ -1770,24 +1899,48 @@ static int __pyx_Coroutine_init(void) {
#define __Pyx_IterableCoroutine_USED
-static PyTypeObject *__pyx_IterableCoroutineType = 0;
-
#undef __Pyx_Coroutine_Check
-#define __Pyx_Coroutine_Check(obj) (__Pyx_Coroutine_CheckExact(obj) || (Py_TYPE(obj) == __pyx_IterableCoroutineType))
+#define __Pyx_Coroutine_Check(obj) (__Pyx_Coroutine_CheckExact(obj) || __Pyx_IS_TYPE(obj, __pyx_IterableCoroutineType))
#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)
- "iterable_coroutine", /*tp_name*/
+ __PYX_TYPE_MODULE_PREFIX "iterable_coroutine", /*tp_name*/
sizeof(__pyx_CoroutineObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor) __Pyx_Coroutine_dealloc,/*tp_dealloc*/
@@ -1847,13 +2000,13 @@ static PyTypeObject __pyx_IterableCoroutineType_type = {
__Pyx_Coroutine_del, /*tp_del*/
#endif
0, /*tp_version_tag*/
-#if PY_VERSION_HEX >= 0x030400a1
+#if PY_VERSION_HEX >= 0x030400a1 && !CYTHON_COMPILING_IN_PYPY
__Pyx_Coroutine_del, /*tp_finalize*/
#endif
#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
0, /*tp_vectorcall*/
#endif
-#if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
+#if __PYX_NEED_TP_PRINT_SLOT
0, /*tp_print*/
#endif
#if PY_VERSION_HEX >= 0x030C0000
@@ -1863,11 +2016,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
+ CYTHON_UNUSED_VAR(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;
@@ -1894,6 +2053,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}
};
@@ -1907,16 +2070,41 @@ static PyGetSetDef __pyx_Generator_getsets[] = {
{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)
- "generator", /*tp_name*/
+ __PYX_TYPE_MODULE_PREFIX "generator", /*tp_name*/
sizeof(__pyx_CoroutineObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor) __Pyx_Coroutine_dealloc,/*tp_dealloc*/
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*/
@@ -1967,7 +2155,7 @@ static PyTypeObject __pyx_GeneratorType_type = {
#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
0, /*tp_vectorcall*/
#endif
-#if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
+#if __PYX_NEED_TP_PRINT_SLOT
0, /*tp_print*/
#endif
#if PY_VERSION_HEX >= 0x030C0000
@@ -1977,13 +2165,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
+ CYTHON_UNUSED_VAR(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;
}
@@ -2010,7 +2203,7 @@ static void __Pyx__ReturnWithStopIteration(PyObject* value); /*proto*/
static void __Pyx__ReturnWithStopIteration(PyObject* value) {
PyObject *exc, *args;
-#if CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_PYSTON
+#if CYTHON_COMPILING_IN_CPYTHON
__Pyx_PyThreadState_declare
if ((PY_VERSION_HEX >= 0x03030000 && PY_VERSION_HEX < 0x030500B1)
|| unlikely(PyTuple_Check(value) || PyExceptionInstance_Check(value))) {
@@ -2029,7 +2222,7 @@ static void __Pyx__ReturnWithStopIteration(PyObject* value) {
#if CYTHON_FAST_THREAD_STATE
__Pyx_PyThreadState_assign
#if CYTHON_USE_EXC_INFO_STACK
- if (!$local_tstate_cname->exc_info->exc_type)
+ if (!$local_tstate_cname->exc_info->exc_value)
#else
if (!$local_tstate_cname->exc_type)
#endif
@@ -2139,7 +2332,7 @@ static int __Pyx_patch_abc(void) {
if (CYTHON_REGISTER_ABCS && !abc_patched) {
PyObject *module;
module = PyImport_ImportModule((PY_MAJOR_VERSION >= 3) ? "collections.abc" : "collections");
- if (!module) {
+ if (unlikely(!module)) {
PyErr_WriteUnraisable(NULL);
if (unlikely(PyErr_WarnEx(PyExc_RuntimeWarning,
((PY_MAJOR_VERSION >= 3) ?
@@ -2316,11 +2509,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*/
@@ -2377,8 +2574,10 @@ static PyTypeObject __Pyx__PyExc_StopAsyncIteration_type = {
#endif
};
#endif
+#endif
-static int __pyx_StopAsyncIteration_init(void) {
+static int __pyx_StopAsyncIteration_init(PyObject *module) {
+ CYTHON_UNUSED_VAR(module);
#if PY_VERSION_HEX >= 0x030500B1
__Pyx_PyExc_StopAsyncIteration = PyExc_StopAsyncIteration;
#else
@@ -2400,7 +2599,7 @@ static int __pyx_StopAsyncIteration_init(void) {
__Pyx_PyExc_StopAsyncIteration = (PyObject*) __Pyx_FetchCommonType(&__Pyx__PyExc_StopAsyncIteration_type);
if (unlikely(!__Pyx_PyExc_StopAsyncIteration))
return -1;
- if (builtins && unlikely(PyMapping_SetItemString(builtins, (char*) "StopAsyncIteration", __Pyx_PyExc_StopAsyncIteration) < 0))
+ if (likely(builtins) && unlikely(PyMapping_SetItemString(builtins, (char*) "StopAsyncIteration", __Pyx_PyExc_StopAsyncIteration) < 0))
return -1;
#endif
return 0;
diff --git a/Cython/Utility/CpdefEnums.pyx b/Cython/Utility/CpdefEnums.pyx
index 148d776c2..39377b30c 100644
--- a/Cython/Utility/CpdefEnums.pyx
+++ b/Cython/Utility/CpdefEnums.pyx
@@ -6,10 +6,11 @@ cdef extern from *:
int PY_VERSION_HEX
cdef object __Pyx_OrderedDict
-if PY_VERSION_HEX >= 0x02070000:
- from collections import OrderedDict as __Pyx_OrderedDict
-else:
+
+if PY_VERSION_HEX >= 0x03060000:
__Pyx_OrderedDict = dict
+else:
+ from collections import OrderedDict as __Pyx_OrderedDict
@cython.internal
cdef class __Pyx_EnumMeta(type):
@@ -23,8 +24,7 @@ cdef class __Pyx_EnumMeta(type):
# @cython.internal
cdef object __Pyx_EnumBase
-class __Pyx_EnumBase(int):
- __metaclass__ = __Pyx_EnumMeta
+class __Pyx_EnumBase(int, metaclass=__Pyx_EnumMeta):
def __new__(cls, value, name=None):
for v in cls:
if v == value:
@@ -44,23 +44,121 @@ class __Pyx_EnumBase(int):
if PY_VERSION_HEX >= 0x03040000:
from enum import IntEnum as __Pyx_EnumBase
+cdef object __Pyx_FlagBase
+class __Pyx_FlagBase(int, metaclass=__Pyx_EnumMeta):
+ def __new__(cls, value, name=None):
+ for v in cls:
+ if v == value:
+ return v
+ res = int.__new__(cls, value)
+ if name is None:
+ # some bitwise combination, no validation here
+ res.name = ""
+ else:
+ res.name = name
+ setattr(cls, name, res)
+ cls.__members__[name] = res
+ return res
+ def __repr__(self):
+ return "<%s.%s: %d>" % (self.__class__.__name__, self.name, self)
+ def __str__(self):
+ return "%s.%s" % (self.__class__.__name__, self.name)
+
+if PY_VERSION_HEX >= 0x03060000:
+ from enum import IntFlag as __Pyx_FlagBase
+
#################### EnumType ####################
#@requires: EnumBase
+cdef extern from *:
+ object {{enum_to_pyint_func}}({{name}} value)
+
cdef dict __Pyx_globals = globals()
-if PY_VERSION_HEX >= 0x03040000:
- # create new IntEnum()
- {{name}} = __Pyx_EnumBase('{{name}}', __Pyx_OrderedDict([
+if PY_VERSION_HEX >= 0x03060000:
+ # create new IntFlag() - the assumption is that C enums are sufficiently commonly
+ # used as flags that this is the most appropriate base class
+ {{name}} = __Pyx_FlagBase('{{name}}', [
{{for item in items}}
- ('{{item}}', {{item}}),
+ ('{{item}}', {{enum_to_pyint_func}}({{item}})),
{{endfor}}
- ]))
+ # Try to look up the module name dynamically if possible
+ ], module=__Pyx_globals.get("__module__", '{{static_modname}}'))
+
+ if PY_VERSION_HEX >= 0x030B0000:
+ # Python 3.11 starts making the behaviour of flags stricter
+ # (only including powers of 2 when iterating). Since we're using
+ # "flag" because C enums *might* be used as flags, not because
+ # we want strict flag behaviour, manually undo some of this.
+ {{name}}._member_names_ = list({{name}}.__members__)
+
+ {{if enum_doc is not None}}
+ {{name}}.__doc__ = {{ repr(enum_doc) }}
+ {{endif}}
+
{{for item in items}}
__Pyx_globals['{{item}}'] = {{name}}.{{item}}
{{endfor}}
else:
- class {{name}}(__Pyx_EnumBase):
- pass
+ class {{name}}(__Pyx_FlagBase):
+ {{ repr(enum_doc) if enum_doc is not None else 'pass' }}
+ {{for item in items}}
+ __Pyx_globals['{{item}}'] = {{name}}({{enum_to_pyint_func}}({{item}}), '{{item}}')
+ {{endfor}}
+
+#################### CppScopedEnumType ####################
+#@requires: EnumBase
+cdef dict __Pyx_globals = globals()
+
+if PY_VERSION_HEX >= 0x03040000:
+ __Pyx_globals["{{name}}"] = __Pyx_EnumBase('{{name}}', [
+ {{for item in items}}
+ ('{{item}}', <{{underlying_type}}>({{name}}.{{item}})),
+ {{endfor}}
+ ], module=__Pyx_globals.get("__module__", '{{static_modname}}'))
+else:
+ __Pyx_globals["{{name}}"] = type('{{name}}', (__Pyx_EnumBase,), {})
{{for item in items}}
- __Pyx_globals['{{item}}'] = {{name}}({{item}}, '{{item}}')
+ __Pyx_globals["{{name}}"](<{{underlying_type}}>({{name}}.{{item}}), '{{item}}')
{{endfor}}
+
+{{if enum_doc is not None}}
+__Pyx_globals["{{name}}"].__doc__ = {{ repr(enum_doc) }}
+{{endif}}
+
+
+#################### EnumTypeToPy ####################
+
+@cname("{{funcname}}")
+cdef {{funcname}}({{name}} c_val):
+ cdef object __pyx_enum
+ # There's a complication here: the Python enum wrapping is only generated
+ # for enums defined in the same module that they're used in. Therefore, if
+ # the enum was cimported from a different module, we try to import it.
+ # If that fails we return an int equivalent as the next best option.
+{{if module_name}}
+ try:
+ from {{module_name}} import {{name}} as __pyx_enum
+ except ImportError:
+ import warnings
+ warnings.warn(
+ f"enum class {{name}} not importable from {{module_name}}. "
+ "You are probably using a cpdef enum declared in a .pxd file that "
+ "does not have a .py or .pyx file.")
+ return <{{underlying_type}}>c_val
+{{else}}
+ __pyx_enum = {{name}}
+{{endif}}
+ # TODO - Cython only manages to optimize C enums to a switch currently
+ if 0:
+ pass
+{{for item in items}}
+ elif c_val == {{name}}.{{item}}:
+ return __pyx_enum.{{item}}
+{{endfor}}
+ else:
+ underlying_c_val = <{{underlying_type}}>c_val
+{{if is_flag}}
+ return __pyx_enum(underlying_c_val)
+{{else}}
+ raise ValueError(f"{underlying_c_val} is not a valid {{name}}")
+{{endif}}
diff --git a/Cython/Utility/CppConvert.pyx b/Cython/Utility/CppConvert.pyx
index 03360e510..1c6239b2b 100644
--- a/Cython/Utility/CppConvert.pyx
+++ b/Cython/Utility/CppConvert.pyx
@@ -5,8 +5,8 @@
cdef extern from *:
cdef cppclass string "{{type}}":
- string()
- string(char* c_str, size_t size)
+ string() except +
+ string(char* c_str, size_t size) except +
cdef const char* __Pyx_PyObject_AsStringAndSize(object, Py_ssize_t*) except NULL
@cname("{{cname}}")
@@ -39,7 +39,7 @@ cdef inline object {{cname.replace("PyObject", py_type, 1)}}(const string& s):
cdef extern from *:
cdef cppclass vector "std::vector" [T]:
- void push_back(T&)
+ void push_back(T&) except +
@cname("{{cname}}")
cdef vector[X] {{cname}}(object o) except *:
@@ -52,20 +52,39 @@ cdef vector[X] {{cname}}(object o) except *:
#################### vector.to_py ####################
cdef extern from *:
- cdef cppclass vector "const std::vector" [T]:
+ cdef cppclass vector "std::vector" [T]:
size_t size()
T& operator[](size_t)
+cdef extern from "Python.h":
+ void Py_INCREF(object)
+ list PyList_New(Py_ssize_t size)
+ void PyList_SET_ITEM(object list, Py_ssize_t i, object o)
+ cdef Py_ssize_t PY_SSIZE_T_MAX
+
@cname("{{cname}}")
-cdef object {{cname}}(vector[X]& v):
- return [v[i] for i in range(v.size())]
+cdef object {{cname}}(const vector[X]& v):
+ if v.size() > <size_t> PY_SSIZE_T_MAX:
+ raise MemoryError()
+ v_size_signed = <Py_ssize_t> v.size()
+
+ o = PyList_New(v_size_signed)
+
+ cdef Py_ssize_t i
+ cdef object item
+ for i in range(v_size_signed):
+ item = v[i]
+ Py_INCREF(item)
+ PyList_SET_ITEM(o, i, item)
+
+ return o
#################### list.from_py ####################
cdef extern from *:
cdef cppclass cpp_list "std::list" [T]:
- void push_back(T&)
+ void push_back(T&) except +
@cname("{{cname}}")
cdef cpp_list[X] {{cname}}(object o) except *:
@@ -87,14 +106,32 @@ cdef extern from *:
bint operator!=(const_iterator)
const_iterator begin()
const_iterator end()
+ size_t size()
+
+cdef extern from "Python.h":
+ void Py_INCREF(object)
+ list PyList_New(Py_ssize_t size)
+ void PyList_SET_ITEM(object list, Py_ssize_t i, object o)
+ cdef Py_ssize_t PY_SSIZE_T_MAX
@cname("{{cname}}")
cdef object {{cname}}(const cpp_list[X]& v):
- o = []
+ if v.size() > <size_t> PY_SSIZE_T_MAX:
+ raise MemoryError()
+
+ o = PyList_New(<Py_ssize_t> v.size())
+
+ cdef object item
+ cdef Py_ssize_t i = 0
cdef cpp_list[X].const_iterator iter = v.begin()
+
while iter != v.end():
- o.append(cython.operator.dereference(iter))
+ item = cython.operator.dereference(iter)
+ Py_INCREF(item)
+ PyList_SET_ITEM(o, i, item)
cython.operator.preincrement(iter)
+ i += 1
+
return o
@@ -102,7 +139,7 @@ cdef object {{cname}}(const cpp_list[X]& v):
cdef extern from *:
cdef cppclass set "std::{{maybe_unordered}}set" [T]:
- void insert(T&)
+ void insert(T&) except +
@cname("{{cname}}")
cdef set[X] {{cname}}(object o) except *:
@@ -127,19 +164,14 @@ cdef extern from *:
@cname("{{cname}}")
cdef object {{cname}}(const cpp_set[X]& s):
- o = set()
- cdef cpp_set[X].const_iterator iter = s.begin()
- while iter != s.end():
- o.add(cython.operator.dereference(iter))
- cython.operator.preincrement(iter)
- return o
+ return {v for v in s}
#################### pair.from_py ####################
cdef extern from *:
cdef cppclass pair "std::pair" [T, U]:
- pair()
- pair(T&, U&)
+ pair() except +
+ pair(T&, U&) except +
@cname("{{cname}}")
cdef pair[X,Y] {{cname}}(object o) except *:
@@ -163,19 +195,23 @@ cdef object {{cname}}(const pair[X,Y]& p):
cdef extern from *:
cdef cppclass pair "std::pair" [T, U]:
- pair(T&, U&)
+ pair(T&, U&) except +
cdef cppclass map "std::{{maybe_unordered}}map" [T, U]:
- void insert(pair[T, U]&)
+ void insert(pair[T, U]&) except +
cdef cppclass vector "std::vector" [T]:
pass
+ int PY_MAJOR_VERSION
@cname("{{cname}}")
cdef map[X,Y] {{cname}}(object o) except *:
- cdef dict d = o
cdef map[X,Y] m
- for key, value in d.iteritems():
- m.insert(pair[X,Y](<X>key, <Y>value))
+ if PY_MAJOR_VERSION < 3:
+ for key, value in o.iteritems():
+ m.insert(pair[X,Y](<X>key, <Y>value))
+ else:
+ for key, value in o.items():
+ m.insert(pair[X,Y](<X>key, <Y>value))
return m
diff --git a/Cython/Utility/CppSupport.cpp b/Cython/Utility/CppSupport.cpp
index b8fcff064..ba0002c94 100644
--- a/Cython/Utility/CppSupport.cpp
+++ b/Cython/Utility/CppSupport.cpp
@@ -56,3 +56,78 @@ auto __Pyx_pythran_to_python(T &&value) -> decltype(to_python(
using returnable_type = typename pythonic::returnable<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::type;
return to_python(returnable_type{std::forward<T>(value)});
}
+
+#define __Pyx_PythranShapeAccessor(x) (pythonic::builtins::getattr(pythonic::types::attr::SHAPE{}, x))
+
+////////////// MoveIfSupported.proto //////////////////
+
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
+ // move should be defined for these versions of MSVC, but __cplusplus isn't set usefully
+ #include <utility>
+ #define __PYX_STD_MOVE_IF_SUPPORTED(x) std::move(x)
+#else
+ #define __PYX_STD_MOVE_IF_SUPPORTED(x) x
+#endif
+
+////////////// EnumClassDecl.proto //////////////////
+
+#if defined (_MSC_VER)
+ #if _MSC_VER >= 1910
+ #define __PYX_ENUM_CLASS_DECL enum
+ #else
+ #define __PYX_ENUM_CLASS_DECL
+ #endif
+#else
+ #define __PYX_ENUM_CLASS_DECL enum
+#endif
+
+////////////// OptionalLocals.proto ////////////////
+//@proto_block: utility_code_proto_before_types
+
+#include <utility>
+#if defined(CYTHON_USE_BOOST_OPTIONAL)
+ // fallback mode - std::optional is preferred but this gives
+ // people with a less up-to-date compiler a chance
+ #include <boost/optional.hpp>
+ #define __Pyx_Optional_BaseType boost::optional
+#else
+ #include <optional>
+ // since std::optional is a C++17 features, a templated using declaration should be safe
+ // (although it could be replaced with a define)
+ template <typename T>
+ using __Pyx_Optional_BaseType = std::optional<T>;
+#endif
+
+// This class reuses as much of the implementation of std::optional as possible.
+// The only place it differs significantly is the assignment operators, which use
+// "emplace" (thus requiring move/copy constructors, but not move/copy
+// assignment operators). This is preferred because it lets us work with assignable
+// types (for example those with const members)
+template <typename T>
+class __Pyx_Optional_Type : private __Pyx_Optional_BaseType<T> {
+public:
+ using __Pyx_Optional_BaseType<T>::__Pyx_Optional_BaseType;
+ using __Pyx_Optional_BaseType<T>::has_value;
+ using __Pyx_Optional_BaseType<T>::operator*;
+ using __Pyx_Optional_BaseType<T>::operator->;
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
+ __Pyx_Optional_Type& operator=(const __Pyx_Optional_Type& rhs) {
+ this->emplace(*rhs);
+ return *this;
+ }
+ __Pyx_Optional_Type& operator=(__Pyx_Optional_Type&& rhs) {
+ this->emplace(std::move(*rhs));
+ return *this;
+ }
+ template <typename U=T>
+ __Pyx_Optional_Type& operator=(U&& rhs) {
+ this->emplace(std::forward<U>(rhs));
+ return *this;
+ }
+#else
+ // Note - the "cpp_locals" feature is designed to require C++14.
+ // This pre-c++11 fallback is largely untested, and definitely won't work
+ // in all the cases that the more modern version does
+ using __Pyx_Optional_BaseType<T>::operator=; // the chances are emplace can't work...
+#endif
+};
diff --git a/Cython/Utility/CythonFunction.c b/Cython/Utility/CythonFunction.c
index 93f577f64..c2f85581a 100644
--- a/Cython/Utility/CythonFunction.c
+++ b/Cython/Utility/CythonFunction.c
@@ -1,16 +1,25 @@
//////////////////// CythonFunctionShared.proto ////////////////////
-#define __Pyx_CyFunction_USED 1
+#define __Pyx_CyFunction_USED
#define __Pyx_CYFUNCTION_STATICMETHOD 0x01
#define __Pyx_CYFUNCTION_CLASSMETHOD 0x02
#define __Pyx_CYFUNCTION_CCLASS 0x04
+#define __Pyx_CYFUNCTION_COROUTINE 0x08
#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))
@@ -19,7 +28,15 @@
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
#if PY_VERSION_HEX < 0x030500A0
PyObject *func_weakreflist;
#endif
@@ -30,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;
@@ -44,18 +62,22 @@ typedef struct {
PyObject *defaults_kwdict; /* Const kwonly defaults dict */
PyObject *(*defaults_getter)(PyObject *);
PyObject *func_annotations; /* function annotations dict */
-} __pyx_CyFunctionObject;
-static PyTypeObject *__pyx_CyFunctionType = 0;
+ // Coroutine marker
+ PyObject *func_is_coroutine;
+} __pyx_CyFunctionObject;
-#define __Pyx_CyFunction_Check(obj) (__Pyx_TypeCheck(obj, __pyx_CyFunctionType))
+#define __Pyx_CyFunction_Check(obj) __Pyx_TypeCheck(obj, __pyx_CyFunctionType)
+#define __Pyx_IsCyOrPyCFunction(obj) __Pyx_TypeCheck2(obj, __pyx_CyFunctionType, &PyCFunction_Type)
+#define __Pyx_CyFunction_CheckExact(obj) __Pyx_IS_TYPE(obj, __pyx_CyFunctionType)
static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject* op, PyMethodDef *ml,
int flags, PyObject* qualname,
- PyObject *self,
+ PyObject *closure,
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);
@@ -67,25 +89,51 @@ 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) (((PyCFunctionObject*)f)->vectorcall)
+#endif
+#endif
//////////////////// CythonFunctionShared ////////////////////
//@substitute: naming
//@requires: CommonStructures.c::FetchCommonType
-////@requires: ObjectHandling.c::PyObjectGetAttrStr
-
-#include <structmember.h>
+//@requires: ObjectHandling.c::PyMethodNew
+//@requires: ObjectHandling.c::PyVectorcallFastCallDict
+//@requires: ModuleSetupCode.c::IncludeStructmemberH
+//@requires: ObjectHandling.c::PyObjectGetAttrStr
+
+static CYTHON_INLINE void __Pyx__CyFunction_SetClassObj(__pyx_CyFunctionObject* f, PyObject* classobj) {
+#if PY_VERSION_HEX < 0x030900B1
+ __Pyx_Py_XDECREF_SET(
+ __Pyx_CyFunction_GetClassObj(f),
+ ((classobj) ? __Pyx_NewRef(classobj) : NULL));
+#else
+ __Pyx_Py_XDECREF_SET(
+ // assigning to "mm_class", which is a "PyTypeObject*"
+ ((PyCMethodObject *) (f))->mm_class,
+ (PyTypeObject*)((classobj) ? __Pyx_NewRef(classobj) : NULL));
+#endif
+}
static PyObject *
-__Pyx_CyFunction_get_doc(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *closure)
+__Pyx_CyFunction_get_doc(__pyx_CyFunctionObject *op, void *closure)
{
+ CYTHON_UNUSED_VAR(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;
@@ -99,27 +147,27 @@ __Pyx_CyFunction_get_doc(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *closure
}
static int
-__Pyx_CyFunction_set_doc(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UNUSED void *context)
+__Pyx_CyFunction_set_doc(__pyx_CyFunctionObject *op, PyObject *value, void *context)
{
- PyObject *tmp = op->func_doc;
+ CYTHON_UNUSED_VAR(context);
if (value == NULL) {
// Mark as deleted
value = Py_None;
}
Py_INCREF(value);
- op->func_doc = value;
- Py_XDECREF(tmp);
+ __Pyx_Py_XDECREF_SET(op->func_doc, value);
return 0;
}
static PyObject *
-__Pyx_CyFunction_get_name(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context)
+__Pyx_CyFunction_get_name(__pyx_CyFunctionObject *op, void *context)
{
+ CYTHON_UNUSED_VAR(context);
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;
@@ -129,10 +177,9 @@ __Pyx_CyFunction_get_name(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *contex
}
static int
-__Pyx_CyFunction_set_name(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UNUSED void *context)
+__Pyx_CyFunction_set_name(__pyx_CyFunctionObject *op, PyObject *value, void *context)
{
- PyObject *tmp;
-
+ CYTHON_UNUSED_VAR(context);
#if PY_MAJOR_VERSION >= 3
if (unlikely(value == NULL || !PyUnicode_Check(value)))
#else
@@ -143,25 +190,23 @@ __Pyx_CyFunction_set_name(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UN
"__name__ must be set to a string object");
return -1;
}
- tmp = op->func_name;
Py_INCREF(value);
- op->func_name = value;
- Py_XDECREF(tmp);
+ __Pyx_Py_XDECREF_SET(op->func_name, value);
return 0;
}
static PyObject *
-__Pyx_CyFunction_get_qualname(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context)
+__Pyx_CyFunction_get_qualname(__pyx_CyFunctionObject *op, void *context)
{
+ CYTHON_UNUSED_VAR(context);
Py_INCREF(op->func_qualname);
return op->func_qualname;
}
static int
-__Pyx_CyFunction_set_qualname(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UNUSED void *context)
+__Pyx_CyFunction_set_qualname(__pyx_CyFunctionObject *op, PyObject *value, void *context)
{
- PyObject *tmp;
-
+ CYTHON_UNUSED_VAR(context);
#if PY_MAJOR_VERSION >= 3
if (unlikely(value == NULL || !PyUnicode_Check(value)))
#else
@@ -172,28 +217,15 @@ __Pyx_CyFunction_set_qualname(__pyx_CyFunctionObject *op, PyObject *value, CYTHO
"__qualname__ must be set to a string object");
return -1;
}
- tmp = op->func_qualname;
Py_INCREF(value);
- op->func_qualname = value;
- Py_XDECREF(tmp);
+ __Pyx_Py_XDECREF_SET(op->func_qualname, value);
return 0;
}
static PyObject *
-__Pyx_CyFunction_get_self(__pyx_CyFunctionObject *m, CYTHON_UNUSED void *closure)
-{
- PyObject *self;
-
- self = m->func_closure;
- if (self == NULL)
- self = Py_None;
- Py_INCREF(self);
- return self;
-}
-
-static PyObject *
-__Pyx_CyFunction_get_dict(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context)
+__Pyx_CyFunction_get_dict(__pyx_CyFunctionObject *op, void *context)
{
+ CYTHON_UNUSED_VAR(context);
if (unlikely(op->func_dict == NULL)) {
op->func_dict = PyDict_New();
if (unlikely(op->func_dict == NULL))
@@ -204,10 +236,9 @@ __Pyx_CyFunction_get_dict(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *contex
}
static int
-__Pyx_CyFunction_set_dict(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UNUSED void *context)
+__Pyx_CyFunction_set_dict(__pyx_CyFunctionObject *op, PyObject *value, void *context)
{
- PyObject *tmp;
-
+ CYTHON_UNUSED_VAR(context);
if (unlikely(value == NULL)) {
PyErr_SetString(PyExc_TypeError,
"function's dictionary may not be deleted");
@@ -218,31 +249,33 @@ __Pyx_CyFunction_set_dict(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UN
"setting function's dictionary to a non-dict");
return -1;
}
- tmp = op->func_dict;
Py_INCREF(value);
- op->func_dict = value;
- Py_XDECREF(tmp);
+ __Pyx_Py_XDECREF_SET(op->func_dict, value);
return 0;
}
static PyObject *
-__Pyx_CyFunction_get_globals(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context)
+__Pyx_CyFunction_get_globals(__pyx_CyFunctionObject *op, void *context)
{
+ CYTHON_UNUSED_VAR(context);
Py_INCREF(op->func_globals);
return op->func_globals;
}
static PyObject *
-__Pyx_CyFunction_get_closure(CYTHON_UNUSED __pyx_CyFunctionObject *op, CYTHON_UNUSED void *context)
+__Pyx_CyFunction_get_closure(__pyx_CyFunctionObject *op, void *context)
{
+ CYTHON_UNUSED_VAR(op);
+ CYTHON_UNUSED_VAR(context);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
-__Pyx_CyFunction_get_code(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context)
+__Pyx_CyFunction_get_code(__pyx_CyFunctionObject *op, void *context)
{
PyObject* result = (op->func_code) ? op->func_code : Py_None;
+ CYTHON_UNUSED_VAR(context);
Py_INCREF(result);
return result;
}
@@ -273,29 +306,30 @@ __Pyx_CyFunction_init_defaults(__pyx_CyFunctionObject *op) {
}
static int
-__Pyx_CyFunction_set_defaults(__pyx_CyFunctionObject *op, PyObject* value, CYTHON_UNUSED void *context) {
- PyObject* tmp;
+__Pyx_CyFunction_set_defaults(__pyx_CyFunctionObject *op, PyObject* value, void *context) {
+ CYTHON_UNUSED_VAR(context);
if (!value) {
// del => explicit None to prevent rebuilding
value = Py_None;
- } else if (value != Py_None && !PyTuple_Check(value)) {
+ } else if (unlikely(value != Py_None && !PyTuple_Check(value))) {
PyErr_SetString(PyExc_TypeError,
"__defaults__ must be set to a tuple object");
return -1;
}
+ PyErr_WarnEx(PyExc_RuntimeWarning, "changes to cyfunction.__defaults__ will not "
+ "currently affect the values used in function calls", 1);
Py_INCREF(value);
- tmp = op->defaults_tuple;
- op->defaults_tuple = value;
- Py_XDECREF(tmp);
+ __Pyx_Py_XDECREF_SET(op->defaults_tuple, value);
return 0;
}
static PyObject *
-__Pyx_CyFunction_get_defaults(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) {
+__Pyx_CyFunction_get_defaults(__pyx_CyFunctionObject *op, void *context) {
PyObject* result = op->defaults_tuple;
+ CYTHON_UNUSED_VAR(context);
if (unlikely(!result)) {
if (op->defaults_getter) {
- if (__Pyx_CyFunction_init_defaults(op) < 0) return NULL;
+ if (unlikely(__Pyx_CyFunction_init_defaults(op) < 0)) return NULL;
result = op->defaults_tuple;
} else {
result = Py_None;
@@ -306,29 +340,30 @@ __Pyx_CyFunction_get_defaults(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *co
}
static int
-__Pyx_CyFunction_set_kwdefaults(__pyx_CyFunctionObject *op, PyObject* value, CYTHON_UNUSED void *context) {
- PyObject* tmp;
+__Pyx_CyFunction_set_kwdefaults(__pyx_CyFunctionObject *op, PyObject* value, void *context) {
+ CYTHON_UNUSED_VAR(context);
if (!value) {
// del => explicit None to prevent rebuilding
value = Py_None;
- } else if (value != Py_None && !PyDict_Check(value)) {
+ } else if (unlikely(value != Py_None && !PyDict_Check(value))) {
PyErr_SetString(PyExc_TypeError,
"__kwdefaults__ must be set to a dict object");
return -1;
}
+ PyErr_WarnEx(PyExc_RuntimeWarning, "changes to cyfunction.__kwdefaults__ will not "
+ "currently affect the values used in function calls", 1);
Py_INCREF(value);
- tmp = op->defaults_kwdict;
- op->defaults_kwdict = value;
- Py_XDECREF(tmp);
+ __Pyx_Py_XDECREF_SET(op->defaults_kwdict, value);
return 0;
}
static PyObject *
-__Pyx_CyFunction_get_kwdefaults(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) {
+__Pyx_CyFunction_get_kwdefaults(__pyx_CyFunctionObject *op, void *context) {
PyObject* result = op->defaults_kwdict;
+ CYTHON_UNUSED_VAR(context);
if (unlikely(!result)) {
if (op->defaults_getter) {
- if (__Pyx_CyFunction_init_defaults(op) < 0) return NULL;
+ if (unlikely(__Pyx_CyFunction_init_defaults(op) < 0)) return NULL;
result = op->defaults_kwdict;
} else {
result = Py_None;
@@ -339,25 +374,24 @@ __Pyx_CyFunction_get_kwdefaults(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *
}
static int
-__Pyx_CyFunction_set_annotations(__pyx_CyFunctionObject *op, PyObject* value, CYTHON_UNUSED void *context) {
- PyObject* tmp;
+__Pyx_CyFunction_set_annotations(__pyx_CyFunctionObject *op, PyObject* value, void *context) {
+ CYTHON_UNUSED_VAR(context);
if (!value || value == Py_None) {
value = NULL;
- } else if (!PyDict_Check(value)) {
+ } else if (unlikely(!PyDict_Check(value))) {
PyErr_SetString(PyExc_TypeError,
"__annotations__ must be set to a dict object");
return -1;
}
Py_XINCREF(value);
- tmp = op->func_annotations;
- op->func_annotations = value;
- Py_XDECREF(tmp);
+ __Pyx_Py_XDECREF_SET(op->func_annotations, value);
return 0;
}
static PyObject *
-__Pyx_CyFunction_get_annotations(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) {
+__Pyx_CyFunction_get_annotations(__pyx_CyFunctionObject *op, void *context) {
PyObject* result = op->func_annotations;
+ CYTHON_UNUSED_VAR(context);
if (unlikely(!result)) {
result = PyDict_New();
if (unlikely(!result)) return NULL;
@@ -367,10 +401,44 @@ __Pyx_CyFunction_get_annotations(__pyx_CyFunctionObject *op, CYTHON_UNUSED void
return result;
}
+static PyObject *
+__Pyx_CyFunction_get_is_coroutine(__pyx_CyFunctionObject *op, void *context) {
+ int is_coroutine;
+ CYTHON_UNUSED_VAR(context);
+ if (op->func_is_coroutine) {
+ return __Pyx_NewRef(op->func_is_coroutine);
+ }
+
+ is_coroutine = op->flags & __Pyx_CYFUNCTION_COROUTINE;
+#if PY_VERSION_HEX >= 0x03050000
+ if (is_coroutine) {
+ PyObject *module, *fromlist, *marker = PYIDENT("_is_coroutine");
+ fromlist = PyList_New(1);
+ if (unlikely(!fromlist)) return NULL;
+ Py_INCREF(marker);
+ PyList_SET_ITEM(fromlist, 0, marker);
+ module = PyImport_ImportModuleLevelObject(PYIDENT("asyncio.coroutines"), NULL, NULL, fromlist, 0);
+ Py_DECREF(fromlist);
+ if (unlikely(!module)) goto ignore;
+ op->func_is_coroutine = __Pyx_PyObject_GetAttrStr(module, marker);
+ Py_DECREF(module);
+ if (likely(op->func_is_coroutine)) {
+ return __Pyx_NewRef(op->func_is_coroutine);
+ }
+ignore:
+ PyErr_Clear();
+ }
+#endif
+
+ op->func_is_coroutine = __Pyx_PyBool_FromLong(is_coroutine);
+ return __Pyx_NewRef(op->func_is_coroutine);
+}
+
//#if PY_VERSION_HEX >= 0x030400C1
//static PyObject *
-//__Pyx_CyFunction_get_signature(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) {
+//__Pyx_CyFunction_get_signature(__pyx_CyFunctionObject *op, void *context) {
// PyObject *inspect_module, *signature_class, *signature;
+// CYTHON_UNUSED_VAR(context);
// // from inspect import Signature
// inspect_module = PyImport_ImportModuleLevelObject(PYIDENT("inspect"), NULL, NULL, NULL, 0);
// if (unlikely(!inspect_module))
@@ -398,7 +466,6 @@ static PyGetSetDef __pyx_CyFunction_getsets[] = {
{(char *) "func_name", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0},
{(char *) "__name__", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0},
{(char *) "__qualname__", (getter)__Pyx_CyFunction_get_qualname, (setter)__Pyx_CyFunction_set_qualname, 0, 0},
- {(char *) "__self__", (getter)__Pyx_CyFunction_get_self, 0, 0, 0},
{(char *) "func_dict", (getter)__Pyx_CyFunction_get_dict, (setter)__Pyx_CyFunction_set_dict, 0, 0},
{(char *) "__dict__", (getter)__Pyx_CyFunction_get_dict, (setter)__Pyx_CyFunction_set_dict, 0, 0},
{(char *) "func_globals", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0},
@@ -411,6 +478,7 @@ static PyGetSetDef __pyx_CyFunction_getsets[] = {
{(char *) "__defaults__", (getter)__Pyx_CyFunction_get_defaults, (setter)__Pyx_CyFunction_set_defaults, 0, 0},
{(char *) "__kwdefaults__", (getter)__Pyx_CyFunction_get_kwdefaults, (setter)__Pyx_CyFunction_set_kwdefaults, 0, 0},
{(char *) "__annotations__", (getter)__Pyx_CyFunction_get_annotations, (setter)__Pyx_CyFunction_set_annotations, 0, 0},
+ {(char *) "_is_coroutine", (getter)__Pyx_CyFunction_get_is_coroutine, 0, 0, 0},
//#if PY_VERSION_HEX >= 0x030400C1
// {(char *) "__signature__", (getter)__Pyx_CyFunction_get_signature, 0, 0, 0},
//#endif
@@ -418,18 +486,34 @@ static PyGetSetDef __pyx_CyFunction_getsets[] = {
};
static PyMemberDef __pyx_CyFunction_members[] = {
- {(char *) "__module__", T_OBJECT, offsetof(PyCFunctionObject, m_module), PY_WRITE_RESTRICTED, 0},
+ {(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
+ {(char *) "__weaklistoffset__", T_PYSSIZET, offsetof(PyCFunctionObject, m_weakreflist), READONLY, 0},
+#endif
+#endif
{0, 0, 0, 0, 0}
};
static PyObject *
-__Pyx_CyFunction_reduce(__pyx_CyFunctionObject *m, CYTHON_UNUSED PyObject *args)
+__Pyx_CyFunction_reduce(__pyx_CyFunctionObject *m, PyObject *args)
{
+ CYTHON_UNUSED_VAR(args);
#if PY_MAJOR_VERSION >= 3
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
}
@@ -442,27 +526,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);
@@ -475,6 +564,32 @@ static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject *op, PyMethodDef *
op->defaults_kwdict = NULL;
op->defaults_getter = NULL;
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 | METH_METHOD)) {
+ case METH_NOARGS:
+ __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_NOARGS;
+ break;
+ case METH_O:
+ __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;
+ // case METH_VARARGS is not used
+ case METH_VARARGS | METH_KEYWORDS:
+ __Pyx_CyFunction_func_vectorcall(op) = NULL;
+ break;
+ default:
+ PyErr_SetString(PyExc_SystemError, "Bad call flags for CyFunction");
+ Py_DECREF(op);
+ return NULL;
+ }
+#endif
return (PyObject *) op;
}
@@ -482,17 +597,26 @@ 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);
+ Py_CLEAR(m->func_is_coroutine);
if (m->defaults) {
PyObject **pydefaults = __Pyx_CyFunction_Defaults(PyObject *, m);
@@ -513,7 +637,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)
@@ -525,16 +649,17 @@ 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);
if (m->defaults) {
PyObject **pydefaults = __Pyx_CyFunction_Defaults(PyObject *, m);
@@ -547,28 +672,6 @@ static int __Pyx_CyFunction_traverse(__pyx_CyFunctionObject *m, visitproc visit,
return 0;
}
-static PyObject *__Pyx_CyFunction_descr_get(PyObject *func, PyObject *obj, PyObject *type)
-{
-#if PY_MAJOR_VERSION < 3
- __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func;
-
- if (m->flags & __Pyx_CYFUNCTION_STATICMETHOD) {
- Py_INCREF(func);
- return func;
- }
-
- if (m->flags & __Pyx_CYFUNCTION_CLASSMETHOD) {
- if (type == NULL)
- type = (PyObject *)(Py_TYPE(obj));
- return __Pyx_PyMethod_New(func, type, (PyObject *)(Py_TYPE(type)));
- }
-
- if (obj == Py_None)
- obj = NULL;
-#endif
- return __Pyx_PyMethod_New(func, obj, type);
-}
-
static PyObject*
__Pyx_CyFunction_repr(__pyx_CyFunctionObject *op)
{
@@ -628,10 +731,7 @@ static PyObject * __Pyx_CyFunction_CallMethod(PyObject *func, PyObject *self, Py
}
break;
default:
- PyErr_SetString(PyExc_SystemError, "Bad call flags in "
- "__Pyx_CyFunction_Call. METH_OLDARGS is no "
- "longer supported!");
-
+ PyErr_SetString(PyExc_SystemError, "Bad call flags for CyFunction");
return NULL;
}
PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
@@ -646,6 +746,22 @@ static CYTHON_INLINE PyObject *__Pyx_CyFunction_Call(PyObject *func, PyObject *a
static PyObject *__Pyx_CyFunction_CallAsMethod(PyObject *func, PyObject *args, PyObject *kw) {
PyObject *result;
__pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *) func;
+
+#if CYTHON_METH_FASTCALL
+ // Prefer vectorcall if available. This is not the typical case, as
+ // CPython would normally use vectorcall directly instead of tp_call.
+ __pyx_vectorcallfunc vc = __Pyx_CyFunction_func_vectorcall(cyfunc);
+ if (vc) {
+#if CYTHON_ASSUME_SAFE_MACROS
+ return __Pyx_PyVectorcall_FastCallDict(func, vc, &PyTuple_GET_ITEM(args, 0), (size_t)PyTuple_GET_SIZE(args), kw);
+#else
+ // avoid unused function warning
+ (void) &__Pyx_PyVectorcall_FastCallDict;
+ return PyVectorcall_Call(func, args, kw);
+#endif
+ }
+#endif
+
if ((cyfunc->flags & __Pyx_CYFUNCTION_CCLASS) && !(cyfunc->flags & __Pyx_CYFUNCTION_STATICMETHOD)) {
Py_ssize_t argc;
PyObject *new_args;
@@ -682,19 +798,198 @@ static PyObject *__Pyx_CyFunction_CallAsMethod(PyObject *func, PyObject *args, P
return result;
}
+#if CYTHON_METH_FASTCALL
+// Check that kwnames is empty (if you want to allow keyword arguments,
+// simply pass kwnames=NULL) and figure out what to do with "self".
+// Return value:
+// 1: self = args[0]
+// 0: self = cyfunc->func.m_self
+// -1: error
+static CYTHON_INLINE int __Pyx_CyFunction_Vectorcall_CheckArgs(__pyx_CyFunctionObject *cyfunc, Py_ssize_t nargs, PyObject *kwnames)
+{
+ int ret = 0;
+ if ((cyfunc->flags & __Pyx_CYFUNCTION_CCLASS) && !(cyfunc->flags & __Pyx_CYFUNCTION_STATICMETHOD)) {
+ if (unlikely(nargs < 1)) {
+ PyErr_Format(PyExc_TypeError, "%.200s() needs an argument",
+ ((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", ((PyCFunctionObject*)cyfunc)->m_ml->ml_name);
+ return -1;
+ }
+ return ret;
+}
+
+static PyObject * __Pyx_CyFunction_Vectorcall_NOARGS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
+{
+ __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func;
+ PyMethodDef* def = ((PyCFunctionObject*)cyfunc)->m_ml;
+#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, kwnames)) {
+ case 1:
+ self = args[0];
+ args += 1;
+ nargs -= 1;
+ break;
+ case 0:
+ self = ((PyCFunctionObject*)cyfunc)->m_self;
+ break;
+ default:
+ return NULL;
+ }
+
+ if (unlikely(nargs != 0)) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s() takes no arguments (%" CYTHON_FORMAT_SSIZE_T "d given)",
+ def->ml_name, nargs);
+ return NULL;
+ }
+ return def->ml_meth(self, NULL);
+}
+
+static PyObject * __Pyx_CyFunction_Vectorcall_O(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
+{
+ __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func;
+ PyMethodDef* def = ((PyCFunctionObject*)cyfunc)->m_ml;
+#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, kwnames)) {
+ case 1:
+ self = args[0];
+ args += 1;
+ nargs -= 1;
+ break;
+ case 0:
+ self = ((PyCFunctionObject*)cyfunc)->m_self;
+ break;
+ default:
+ return NULL;
+ }
+
+ if (unlikely(nargs != 1)) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s() takes exactly one argument (%" CYTHON_FORMAT_SSIZE_T "d given)",
+ def->ml_name, nargs);
+ return NULL;
+ }
+ return def->ml_meth(self, args[0]);
+}
+
+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 = ((PyCFunctionObject*)cyfunc)->m_ml;
+#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;
+ }
+
+ 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;
+ }
+
+ return ((__Pyx_PyCMethod)(void(*)(void))def->ml_meth)(self, cls, args, (size_t)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},
+ {Py_tp_call, (void *)__Pyx_CyFunction_CallAsMethod},
+ {Py_tp_traverse, (void *)__Pyx_CyFunction_traverse},
+ {Py_tp_clear, (void *)__Pyx_CyFunction_clear},
+ {Py_tp_methods, (void *)__pyx_CyFunction_methods},
+ {Py_tp_members, (void *)__pyx_CyFunction_members},
+ {Py_tp_getset, (void *)__pyx_CyFunction_getsets},
+ {Py_tp_descr_get, (void *)__Pyx_PyMethod_New},
+ {0, 0},
+};
+
+static PyType_Spec __pyx_CyFunctionType_spec = {
+ __PYX_TYPE_MODULE_PREFIX "cython_function_or_method",
+ sizeof(__pyx_CyFunctionObject),
+ 0,
+#ifdef Py_TPFLAGS_METHOD_DESCRIPTOR
+ Py_TPFLAGS_METHOD_DESCRIPTOR |
+#endif
+#if (defined(_Py_TPFLAGS_HAVE_VECTORCALL) && CYTHON_METH_FASTCALL)
+ _Py_TPFLAGS_HAVE_VECTORCALL |
+#endif
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ __pyx_CyFunctionType_slots
+};
+#else /* CYTHON_USE_TYPE_SPECS */
+
static PyTypeObject __pyx_CyFunctionType_type = {
PyVarObject_HEAD_INIT(0, 0)
- "cython_function_or_method", /*tp_name*/
+ __PYX_TYPE_MODULE_PREFIX "cython_function_or_method", /*tp_name*/
sizeof(__pyx_CyFunctionObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor) __Pyx_CyFunction_dealloc, /*tp_dealloc*/
+#if !CYTHON_METH_FASTCALL
0, /*tp_print*/
+#elif CYTHON_BACKPORT_VECTORCALL
+ (printfunc)offsetof(__pyx_CyFunctionObject, func_vectorcall), /*tp_vectorcall_offset backported into tp_print*/
+#else
+ offsetof(PyCFunctionObject, vectorcall), /*tp_vectorcall_offset*/
+#endif
0, /*tp_getattr*/
0, /*tp_setattr*/
#if PY_MAJOR_VERSION < 3
0, /*tp_compare*/
#else
- 0, /*reserved*/
+ 0, /*tp_as_async*/
#endif
(reprfunc) __Pyx_CyFunction_repr, /*tp_repr*/
0, /*tp_as_number*/
@@ -706,7 +1001,13 @@ static PyTypeObject __pyx_CyFunctionType_type = {
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
- 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*/
0, /*tp_doc*/
(traverseproc) __Pyx_CyFunction_traverse, /*tp_traverse*/
(inquiry) __Pyx_CyFunction_clear, /*tp_clear*/
@@ -723,7 +1024,7 @@ static PyTypeObject __pyx_CyFunctionType_type = {
__pyx_CyFunction_getsets, /*tp_getset*/
0, /*tp_base*/
0, /*tp_dict*/
- __Pyx_CyFunction_descr_get, /*tp_descr_get*/
+ __Pyx_PyMethod_New, /*tp_descr_get*/
0, /*tp_descr_set*/
offsetof(__pyx_CyFunctionObject, func_dict),/*tp_dictoffset*/
0, /*tp_init*/
@@ -744,7 +1045,7 @@ static PyTypeObject __pyx_CyFunctionType_type = {
#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
0, /*tp_vectorcall*/
#endif
-#if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
+#if __PYX_NEED_TP_PRINT_SLOT
0, /*tp_print*/
#endif
#if PY_VERSION_HEX >= 0x030C0000
@@ -754,10 +1055,16 @@ static PyTypeObject __pyx_CyFunctionType_type = {
0, /*tp_pypy_flags*/
#endif
};
+#endif /* CYTHON_USE_TYPE_SPECS */
-static int __pyx_CyFunction_init(void) {
+static int __pyx_CyFunction_init(PyObject *module) {
+#if CYTHON_USE_TYPE_SPECS
+ __pyx_CyFunctionType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_CyFunctionType_spec, NULL);
+#else
+ CYTHON_UNUSED_VAR(module);
__pyx_CyFunctionType = __Pyx_FetchCommonType(&__pyx_CyFunctionType_type);
+#endif
if (unlikely(__pyx_CyFunctionType == NULL)) {
return -1;
}
@@ -837,8 +1144,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
@@ -852,7 +1158,6 @@ static int __Pyx_CyFunction_InitClassCell(PyObject *cyfunctions, PyObject *class
typedef struct {
__pyx_CyFunctionObject func;
PyObject *__signatures__;
- PyObject *type;
PyObject *self;
} __pyx_FusedFunctionObject;
@@ -862,8 +1167,7 @@ static PyObject *__pyx_FusedFunction_New(PyMethodDef *ml, int flags,
PyObject *code);
static int __pyx_FusedFunction_clear(__pyx_FusedFunctionObject *self);
-static PyTypeObject *__pyx_FusedFunctionType = NULL;
-static int __pyx_FusedFunction_init(void);
+static int __pyx_FusedFunction_init(PyObject *module);
#define __Pyx_FusedFunction_USED
@@ -884,7 +1188,6 @@ __pyx_FusedFunction_New(PyMethodDef *ml, int flags,
if (likely(op)) {
__pyx_FusedFunctionObject *fusedfunc = (__pyx_FusedFunctionObject *) op;
fusedfunc->__signatures__ = NULL;
- fusedfunc->type = NULL;
fusedfunc->self = NULL;
PyObject_GC_Track(op);
}
@@ -896,7 +1199,6 @@ __pyx_FusedFunction_dealloc(__pyx_FusedFunctionObject *self)
{
PyObject_GC_UnTrack(self);
Py_CLEAR(self->self);
- Py_CLEAR(self->type);
Py_CLEAR(self->__signatures__);
__Pyx__CyFunction_dealloc((__pyx_CyFunctionObject *) self);
}
@@ -907,7 +1209,6 @@ __pyx_FusedFunction_traverse(__pyx_FusedFunctionObject *self,
void *arg)
{
Py_VISIT(self->self);
- Py_VISIT(self->type);
Py_VISIT(self->__signatures__);
return __Pyx_CyFunction_traverse((__pyx_CyFunctionObject *) self, visit, arg);
}
@@ -916,7 +1217,6 @@ static int
__pyx_FusedFunction_clear(__pyx_FusedFunctionObject *self)
{
Py_CLEAR(self->self);
- Py_CLEAR(self->type);
Py_CLEAR(self->__signatures__);
return __Pyx_CyFunction_clear((__pyx_CyFunctionObject *) self);
}
@@ -938,6 +1238,15 @@ __pyx_FusedFunction_descr_get(PyObject *self, PyObject *obj, PyObject *type)
if (obj == Py_None)
obj = NULL;
+ if (func->func.flags & __Pyx_CYFUNCTION_CLASSMETHOD)
+ obj = type;
+
+ if (obj == NULL) {
+ // We aren't actually binding to anything, save the effort of rebinding
+ Py_INCREF(self);
+ return self;
+ }
+
meth = (__pyx_FusedFunctionObject *) __pyx_FusedFunction_New(
((PyCFunctionObject *) func)->m_ml,
((__pyx_CyFunctionObject *) func)->flags,
@@ -946,7 +1255,7 @@ __pyx_FusedFunction_descr_get(PyObject *self, PyObject *obj, PyObject *type)
((PyCFunctionObject *) func)->m_module,
((__pyx_CyFunctionObject *) func)->func_globals,
((__pyx_CyFunctionObject *) func)->func_code);
- if (!meth)
+ if (unlikely(!meth))
return NULL;
// defaults needs copying fully rather than just copying the pointer
@@ -956,9 +1265,10 @@ __pyx_FusedFunction_descr_get(PyObject *self, PyObject *obj, PyObject *type)
PyObject **pydefaults;
int i;
- if (!__Pyx_CyFunction_InitDefaults((PyObject*)meth,
- func->func.defaults_size,
- func->func.defaults_pyobjects)) {
+ if (unlikely(!__Pyx_CyFunction_InitDefaults(
+ (PyObject*)meth,
+ func->func.defaults_size,
+ func->func.defaults_pyobjects))) {
Py_XDECREF((PyObject*)meth);
return NULL;
}
@@ -969,21 +1279,14 @@ __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__;
- Py_XINCREF(type);
- meth->type = type;
-
Py_XINCREF(func->func.defaults_tuple);
meth->func.defaults_tuple = func->func.defaults_tuple;
- if (func->func.flags & __Pyx_CYFUNCTION_CLASSMETHOD)
- obj = type;
-
Py_XINCREF(obj);
meth->self = obj;
@@ -991,12 +1294,18 @@ __pyx_FusedFunction_descr_get(PyObject *self, PyObject *obj, PyObject *type)
}
static PyObject *
-_obj_to_str(PyObject *obj)
+_obj_to_string(PyObject *obj)
{
- if (PyType_Check(obj))
+ if (PyUnicode_CheckExact(obj))
+ return __Pyx_NewRef(obj);
+#if PY_MAJOR_VERSION == 2
+ else if (PyString_Check(obj))
+ return PyUnicode_FromEncodedObject(obj, NULL, "strict");
+#endif
+ else if (PyType_Check(obj))
return PyObject_GetAttr(obj, PYIDENT("__name__"));
else
- return PyObject_Str(obj);
+ return PyObject_Unicode(obj);
}
static PyObject *
@@ -1006,65 +1315,55 @@ __pyx_FusedFunction_getitem(__pyx_FusedFunctionObject *self, PyObject *idx)
PyObject *unbound_result_func;
PyObject *result_func = NULL;
- if (self->__signatures__ == NULL) {
+ if (unlikely(self->__signatures__ == NULL)) {
PyErr_SetString(PyExc_TypeError, "Function is not fused");
return NULL;
}
if (PyTuple_Check(idx)) {
- PyObject *list = PyList_New(0);
Py_ssize_t n = PyTuple_GET_SIZE(idx);
- PyObject *sep = NULL;
+ PyObject *list = PyList_New(n);
int i;
if (unlikely(!list))
return NULL;
for (i = 0; i < n; i++) {
- int ret;
PyObject *string;
#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
PyObject *item = PyTuple_GET_ITEM(idx, i);
#else
PyObject *item = PySequence_ITEM(idx, i); if (unlikely(!item)) goto __pyx_err;
#endif
- string = _obj_to_str(item);
+ string = _obj_to_string(item);
#if !(CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS)
Py_DECREF(item);
#endif
if (unlikely(!string)) goto __pyx_err;
- ret = PyList_Append(list, string);
- Py_DECREF(string);
- if (unlikely(ret < 0)) goto __pyx_err;
+ PyList_SET_ITEM(list, i, string);
}
- sep = PyUnicode_FromString("|");
- if (likely(sep))
- signature = PyUnicode_Join(sep, list);
-__pyx_err:
-;
+ signature = PyUnicode_Join(PYUNICODE("|"), list);
+__pyx_err:;
Py_DECREF(list);
- Py_XDECREF(sep);
} else {
- signature = _obj_to_str(idx);
+ signature = _obj_to_string(idx);
}
- if (!signature)
+ if (unlikely(!signature))
return NULL;
unbound_result_func = PyObject_GetItem(self->__signatures__, signature);
- if (unbound_result_func) {
- if (self->self || self->type) {
+ if (likely(unbound_result_func)) {
+ if (self->self) {
__pyx_FusedFunctionObject *unbound = (__pyx_FusedFunctionObject *) unbound_result_func;
// TODO: move this to InitClassCell
- Py_CLEAR(unbound->func.func_classobj);
- Py_XINCREF(self->func.func_classobj);
- 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->type);
+ self->self, self->self);
} else {
result_func = unbound_result_func;
Py_INCREF(result_func);
@@ -1084,7 +1383,7 @@ __pyx_FusedFunction_callfunction(PyObject *func, PyObject *args, PyObject *kw)
int static_specialized = (cyfunc->flags & __Pyx_CYFUNCTION_STATICMETHOD &&
!((__pyx_FusedFunctionObject *) func)->__signatures__);
- if (cyfunc->flags & __Pyx_CYFUNCTION_CCLASS && !static_specialized) {
+ if ((cyfunc->flags & __Pyx_CYFUNCTION_CCLASS) && !static_specialized) {
return __Pyx_CyFunction_CallAsMethod(func, args, kw);
} else {
return __Pyx_CyFunction_Call(func, args, kw);
@@ -1105,23 +1404,21 @@ __pyx_FusedFunction_call(PyObject *func, PyObject *args, PyObject *kw)
PyObject *new_args = NULL;
__pyx_FusedFunctionObject *new_func = NULL;
PyObject *result = NULL;
- PyObject *self = NULL;
int is_staticmethod = binding_func->func.flags & __Pyx_CYFUNCTION_STATICMETHOD;
- int is_classmethod = binding_func->func.flags & __Pyx_CYFUNCTION_CLASSMETHOD;
if (binding_func->self) {
// Bound method call, put 'self' in the args tuple
+ PyObject *self;
Py_ssize_t i;
new_args = PyTuple_New(argc + 1);
- if (!new_args)
+ if (unlikely(!new_args))
return NULL;
self = binding_func->self;
-#if !(CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS)
- Py_INCREF(self);
-#endif
+
Py_INCREF(self);
PyTuple_SET_ITEM(new_args, 0, self);
+ self = NULL;
for (i = 0; i < argc; i++) {
#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
@@ -1134,35 +1431,7 @@ __pyx_FusedFunction_call(PyObject *func, PyObject *args, PyObject *kw)
}
args = new_args;
- } else if (binding_func->type) {
- // Unbound method call
- if (argc < 1) {
- PyErr_SetString(PyExc_TypeError, "Need at least one argument, 0 given.");
- return NULL;
- }
-#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
- self = PyTuple_GET_ITEM(args, 0);
-#else
- self = PySequence_ITEM(args, 0); if (unlikely(!self)) return NULL;
-#endif
- }
-
- if (self && !is_classmethod && !is_staticmethod) {
- int is_instance = PyObject_IsInstance(self, binding_func->type);
- if (unlikely(!is_instance)) {
- PyErr_Format(PyExc_TypeError,
- "First argument should be of type %.200s, got %.200s.",
- ((PyTypeObject *) binding_func->type)->tp_name,
- Py_TYPE(self)->tp_name);
- goto bad;
- } else if (unlikely(is_instance == -1)) {
- goto bad;
- }
}
-#if !(CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS)
- Py_XDECREF(self);
- self = NULL;
-#endif
if (binding_func->__signatures__) {
PyObject *tup;
@@ -1186,18 +1455,13 @@ __pyx_FusedFunction_call(PyObject *func, PyObject *args, PyObject *kw)
if (unlikely(!new_func))
goto bad;
- Py_XINCREF(binding_func->func.func_classobj);
- Py_CLEAR(new_func->func.func_classobj);
- new_func->func.func_classobj = binding_func->func.func_classobj;
+ __Pyx_CyFunction_SetClassObj(new_func, __Pyx_CyFunction_GetClassObj(binding_func));
func = (PyObject *) new_func;
}
result = __pyx_FusedFunction_callfunction(func, args, kw);
bad:
-#if !(CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS)
- Py_XDECREF(self);
-#endif
Py_XDECREF(new_args);
Py_XDECREF((PyObject *) new_func);
return result;
@@ -1209,9 +1473,41 @@ static PyMemberDef __pyx_FusedFunction_members[] = {
offsetof(__pyx_FusedFunctionObject, __signatures__),
READONLY,
0},
+ {(char *) "__self__", T_OBJECT_EX, offsetof(__pyx_FusedFunctionObject, self), READONLY, 0},
{0, 0, 0, 0, 0},
};
+static PyGetSetDef __pyx_FusedFunction_getsets[] = {
+ // __doc__ is None for the fused function type, but we need it to be
+ // a descriptor for the instance's __doc__, so rebuild the descriptor in our subclass
+ // (all other descriptors are inherited)
+ {(char *) "__doc__", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0},
+ {0, 0, 0, 0, 0}
+};
+
+#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},
+ {Py_tp_traverse, (void *)__pyx_FusedFunction_traverse},
+ {Py_tp_clear, (void *)__pyx_FusedFunction_clear},
+ {Py_tp_members, (void *)__pyx_FusedFunction_members},
+ {Py_tp_getset, (void *)__pyx_FusedFunction_getsets},
+ {Py_tp_descr_get, (void *)__pyx_FusedFunction_descr_get},
+ {Py_mp_subscript, (void *)__pyx_FusedFunction_getitem},
+ {0, 0},
+};
+
+static PyType_Spec __pyx_FusedFunctionType_spec = {
+ __PYX_TYPE_MODULE_PREFIX "fused_cython_function",
+ sizeof(__pyx_FusedFunctionObject),
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ __pyx_FusedFunctionType_slots
+};
+
+#else /* !CYTHON_USE_TYPE_SPECS */
+
static PyMappingMethods __pyx_FusedFunction_mapping_methods = {
0,
(binaryfunc) __pyx_FusedFunction_getitem,
@@ -1220,7 +1516,7 @@ static PyMappingMethods __pyx_FusedFunction_mapping_methods = {
static PyTypeObject __pyx_FusedFunctionType_type = {
PyVarObject_HEAD_INIT(0, 0)
- "fused_cython_function", /*tp_name*/
+ __PYX_TYPE_MODULE_PREFIX "fused_cython_function", /*tp_name*/
sizeof(__pyx_FusedFunctionObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor) __pyx_FusedFunction_dealloc, /*tp_dealloc*/
@@ -1230,7 +1526,7 @@ static PyTypeObject __pyx_FusedFunctionType_type = {
#if PY_MAJOR_VERSION < 3
0, /*tp_compare*/
#else
- 0, /*reserved*/
+ 0, /*tp_as_async*/
#endif
0, /*tp_repr*/
0, /*tp_as_number*/
@@ -1252,9 +1548,7 @@ static PyTypeObject __pyx_FusedFunctionType_type = {
0, /*tp_iternext*/
0, /*tp_methods*/
__pyx_FusedFunction_members, /*tp_members*/
- // __doc__ is None for the fused function type, but we need it to be
- // a descriptor for the instance's __doc__, so rebuild descriptors in our subclass
- __pyx_CyFunction_getsets, /*tp_getset*/
+ __pyx_FusedFunction_getsets, /*tp_getset*/
// NOTE: tp_base may be changed later during module initialisation when importing CyFunction across modules.
&__pyx_CyFunctionType_type, /*tp_base*/
0, /*tp_dict*/
@@ -1279,7 +1573,7 @@ static PyTypeObject __pyx_FusedFunctionType_type = {
#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
0, /*tp_vectorcall*/
#endif
-#if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
+#if __PYX_NEED_TP_PRINT_SLOT
0, /*tp_print*/
#endif
#if PY_VERSION_HEX >= 0x030C0000
@@ -1289,12 +1583,23 @@ static PyTypeObject __pyx_FusedFunctionType_type = {
0, /*tp_pypy_flags*/
#endif
};
+#endif
-static int __pyx_FusedFunction_init(void) {
+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(module, &__pyx_FusedFunctionType_spec, bases);
+ Py_DECREF(bases);
+#else
+ CYTHON_UNUSED_VAR(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);
- if (__pyx_FusedFunctionType == NULL) {
+#endif
+ if (unlikely(__pyx_FusedFunctionType == NULL)) {
return -1;
}
return 0;
@@ -1303,7 +1608,7 @@ static int __pyx_FusedFunction_init(void) {
//////////////////// ClassMethod.proto ////////////////////
#include "descrobject.h"
-static CYTHON_UNUSED PyObject* __Pyx_Method_ClassMethod(PyObject *method); /*proto*/
+CYTHON_UNUSED static PyObject* __Pyx_Method_ClassMethod(PyObject *method); /*proto*/
//////////////////// ClassMethod ////////////////////
@@ -1314,16 +1619,16 @@ static PyObject* __Pyx_Method_ClassMethod(PyObject *method) {
return PyClassMethod_New(method);
}
#else
-#if CYTHON_COMPILING_IN_PYSTON || CYTHON_COMPILING_IN_PYPY
- // special C-API function only in Pyston and PyPy >= 5.9
+#if CYTHON_COMPILING_IN_PYPY
+ // special C-API function only in PyPy >= 5.9
if (PyMethodDescr_Check(method))
#else
#if PY_MAJOR_VERSION == 2
// PyMethodDescr_Type is not exposed in the CPython C-API in Py2.
static PyTypeObject *methoddescr_type = NULL;
- if (methoddescr_type == NULL) {
+ if (unlikely(methoddescr_type == NULL)) {
PyObject *meth = PyObject_GetAttrString((PyObject*)&PyList_Type, "append");
- if (!meth) return NULL;
+ if (unlikely(!meth)) return NULL;
methoddescr_type = Py_TYPE(meth);
Py_DECREF(meth);
}
diff --git a/Cython/Utility/Dataclasses.c b/Cython/Utility/Dataclasses.c
new file mode 100644
index 000000000..fc6a88d94
--- /dev/null
+++ b/Cython/Utility/Dataclasses.c
@@ -0,0 +1,178 @@
+///////////////////// ModuleLoader.proto //////////////////////////
+
+static PyObject* __Pyx_LoadInternalModule(const char* name, const char* fallback_code); /* proto */
+
+//////////////////// ModuleLoader ///////////////////////
+//@requires: CommonStructures.c::FetchSharedCythonModule
+
+static PyObject* __Pyx_LoadInternalModule(const char* name, const char* fallback_code) {
+ // We want to be able to use the contents of the standard library dataclasses module where available.
+ // If those objects aren't available (due to Python version) then a simple fallback is substituted
+ // instead, which largely just fails with a not-implemented error.
+ //
+ // The fallbacks are placed in the "shared abi module" as a convenient internal place to
+ // store them
+
+ PyObject *shared_abi_module = 0, *module = 0;
+
+ shared_abi_module = __Pyx_FetchSharedCythonABIModule();
+ if (!shared_abi_module) return NULL;
+
+ if (PyObject_HasAttrString(shared_abi_module, name)) {
+ PyObject* result = PyObject_GetAttrString(shared_abi_module, name);
+ Py_DECREF(shared_abi_module);
+ return result;
+ }
+
+ // the best and simplest case is simply to defer to the standard library (if available)
+ module = PyImport_ImportModule(name);
+ if (!module) {
+ PyObject *localDict, *runValue, *builtins, *modulename;
+ if (!PyErr_ExceptionMatches(PyExc_ImportError)) goto bad;
+ PyErr_Clear(); // this is reasonably likely (especially on older versions of Python)
+#if PY_MAJOR_VERSION < 3
+ modulename = PyBytes_FromFormat("_cython_" CYTHON_ABI ".%s", name);
+#else
+ modulename = PyUnicode_FromFormat("_cython_" CYTHON_ABI ".%s", name);
+#endif
+ if (!modulename) goto bad;
+#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_CPYTHON
+ module = PyImport_AddModuleObject(modulename); // borrowed
+#else
+ module = PyImport_AddModule(PyBytes_AsString(modulename)); // borrowed
+#endif
+ Py_DECREF(modulename);
+ if (!module) goto bad;
+ Py_INCREF(module);
+ if (PyObject_SetAttrString(shared_abi_module, name, module) < 0) goto bad;
+ localDict = PyModule_GetDict(module); // borrowed
+ if (!localDict) goto bad;
+ builtins = PyEval_GetBuiltins(); // borrowed
+ if (!builtins) goto bad;
+ if (PyDict_SetItemString(localDict, "__builtins__", builtins) <0) goto bad;
+
+ runValue = PyRun_String(fallback_code, Py_file_input, localDict, localDict);
+ if (!runValue) goto bad;
+ Py_DECREF(runValue);
+ }
+ goto shared_cleanup;
+
+ bad:
+ Py_CLEAR(module);
+ shared_cleanup:
+ Py_XDECREF(shared_abi_module);
+ return module;
+}
+
+///////////////////// SpecificModuleLoader.proto //////////////////////
+//@substitute: tempita
+
+static PyObject* __Pyx_Load_{{cname}}_Module(void); /* proto */
+
+
+//////////////////// SpecificModuleLoader ///////////////////////
+//@requires: ModuleLoader
+
+static PyObject* __Pyx_Load_{{cname}}_Module(void) {
+ return __Pyx_LoadInternalModule("{{cname}}", {{py_code}});
+}
+
+//////////////////// DataclassesCallHelper.proto ////////////////////////
+
+static PyObject* __Pyx_DataclassesCallHelper(PyObject *callable, PyObject *kwds); /* proto */
+
+//////////////////// DataclassesCallHelper ////////////////////////
+//@substitute: naming
+
+// The signature of a few of the dataclasses module functions has
+// been expanded over the years. Cython always passes the full set
+// of arguments from the most recent version we know of, so needs
+// to remove any arguments that don't exist on earlier versions.
+
+#if PY_MAJOR_VERSION >= 3
+static int __Pyx_DataclassesCallHelper_FilterToDict(PyObject *callable, PyObject *kwds, PyObject *new_kwds, PyObject *args_list, int is_kwonly) {
+ Py_ssize_t size, i;
+ size = PySequence_Size(args_list);
+ if (size == -1) return -1;
+
+ for (i=0; i<size; ++i) {
+ PyObject *key, *value;
+ int setitem_result;
+ key = PySequence_GetItem(args_list, i);
+ if (!key) return -1;
+
+ if (PyUnicode_Check(key) && (
+ PyUnicode_CompareWithASCIIString(key, "self") == 0 ||
+ // namedtuple constructor in fallback code
+ PyUnicode_CompareWithASCIIString(key, "_cls") == 0)) {
+ Py_DECREF(key);
+ continue;
+ }
+
+ value = PyDict_GetItem(kwds, key);
+ if (!value) {
+ if (is_kwonly) {
+ Py_DECREF(key);
+ continue;
+ } else {
+ // The most likely reason for this is that Cython
+ // hasn't kept up to date with the Python dataclasses module.
+ // To be nice to our users, try not to fail, but ask them
+ // to report a bug so we can keep up to date.
+ value = Py_None;
+ if (PyErr_WarnFormat(
+ PyExc_RuntimeWarning, 1,
+ "Argument %S not passed to %R. This is likely a bug in Cython so please report it.",
+ key, callable) == -1) {
+ Py_DECREF(key);
+ return -1;
+ }
+ }
+ }
+ Py_INCREF(value);
+ setitem_result = PyDict_SetItem(new_kwds, key, value);
+ Py_DECREF(key);
+ Py_DECREF(value);
+ if (setitem_result == -1) return -1;
+ }
+ return 0;
+}
+#endif
+
+static PyObject* __Pyx_DataclassesCallHelper(PyObject *callable, PyObject *kwds) {
+#if PY_MAJOR_VERSION < 3
+ // We're falling back to our full replacement anyway
+ return PyObject_Call(callable, $empty_tuple, kwds);
+#else
+ PyObject *new_kwds=NULL, *result=NULL;
+ PyObject *inspect;
+ PyObject *args_list=NULL, *kwonly_args_list=NULL, *getfullargspec_result=NULL;
+
+ // Going via inspect to work out what arguments to pass is unlikely to be the
+ // fastest thing ever. However, it is compatible, and only happens once
+ // at module-import time.
+ inspect = PyImport_ImportModule("inspect");
+ if (!inspect) goto bad;
+ getfullargspec_result = PyObject_CallMethodObjArgs(inspect, PYUNICODE("getfullargspec"), callable, NULL);
+ Py_DECREF(inspect);
+ if (!getfullargspec_result) goto bad;
+ args_list = PyObject_GetAttrString(getfullargspec_result, "args");
+ if (!args_list) goto bad;
+ kwonly_args_list = PyObject_GetAttrString(getfullargspec_result, "kwonlyargs");
+ if (!kwonly_args_list) goto bad;
+
+ new_kwds = PyDict_New();
+ if (!new_kwds) goto bad;
+
+ // copy over only those arguments that are in the specification
+ if (__Pyx_DataclassesCallHelper_FilterToDict(callable, kwds, new_kwds, args_list, 0) == -1) goto bad;
+ if (__Pyx_DataclassesCallHelper_FilterToDict(callable, kwds, new_kwds, kwonly_args_list, 1) == -1) goto bad;
+ result = PyObject_Call(callable, $empty_tuple, new_kwds);
+bad:
+ Py_XDECREF(getfullargspec_result);
+ Py_XDECREF(args_list);
+ Py_XDECREF(kwonly_args_list);
+ Py_XDECREF(new_kwds);
+ return result;
+#endif
+}
diff --git a/Cython/Utility/Dataclasses.py b/Cython/Utility/Dataclasses.py
new file mode 100644
index 000000000..2aa2d25a3
--- /dev/null
+++ b/Cython/Utility/Dataclasses.py
@@ -0,0 +1,112 @@
+################### Dataclasses_fallback ###############################
+
+# This is the fallback dataclass code if the stdlib module isn't available.
+# It defines enough of the support types to be used with cdef classes
+# and to fail if used on regular types.
+
+# (Intended to be included as py code - not compiled)
+
+from collections import namedtuple
+try:
+ from types import MappingProxyType
+except ImportError:
+ # mutable fallback if unavailable
+ MappingProxyType = lambda x: x
+
+class _MISSING_TYPE(object):
+ pass
+MISSING = _MISSING_TYPE()
+
+_DataclassParams = namedtuple('_DataclassParams',
+ ["init", "repr", "eq", "order", "unsafe_hash", "frozen",
+ "match_args", "kw_only", "slots", "weakref_slot"])
+class Field(object):
+ __slots__ = ('name',
+ 'type',
+ 'default',
+ 'default_factory',
+ 'repr',
+ 'hash',
+ 'init',
+ 'compare',
+ 'metadata',
+ 'kw_only',
+ '_field_type', # Private: not to be used by user code.
+ )
+
+ def __init__(self, default, default_factory, init, repr, hash, compare,
+ metadata, kw_only):
+ self.name = None
+ self.type = None
+ self.default = default
+ self.default_factory = default_factory
+ self.init = init
+ self.repr = repr
+ self.hash = hash
+ self.compare = compare
+ # Be aware that if MappingProxyType is unavailable (i.e. py2?) then we
+ # don't enforce non-mutability that the real module does
+ self.metadata = (MappingProxyType({})
+ if metadata is None else
+ MappingProxyType(metadata))
+ self.kw_only = kw_only
+ self._field_type = None
+
+ def __repr__(self):
+ return ('Field('
+ 'name={0!r},'
+ 'type={1!r},'
+ 'default={2!r},'
+ 'default_factory={3!r},'
+ 'init={4!r},'
+ 'repr={5!r},'
+ 'hash={6!r},'
+ 'compare={7!r},'
+ 'metadata={8!r},'
+ 'kwonly={9!r},'
+ ')'.format(self.name, self.type, self.default,
+ self.default_factory, self.init,
+ self.repr, self.hash, self.compare,
+ self.metadata, self.kw_only))
+
+# A sentinel object for default values to signal that a default
+# factory will be used. This is given a nice repr() which will appear
+# in the function signature of dataclasses' constructors.
+class _HAS_DEFAULT_FACTORY_CLASS:
+ def __repr__(self):
+ return '<factory>'
+_HAS_DEFAULT_FACTORY = _HAS_DEFAULT_FACTORY_CLASS()
+
+def dataclass(*args, **kwds):
+ raise NotImplementedError("Standard library 'dataclasses' module"
+ "is unavailable, likely due to the version of Python you're using.")
+
+# Markers for the various kinds of fields and pseudo-fields.
+class _FIELD_BASE:
+ def __init__(self, name):
+ self.name = name
+ def __repr__(self):
+ return self.name
+_FIELD = _FIELD_BASE('_FIELD')
+_FIELD_CLASSVAR = _FIELD_BASE('_FIELD_CLASSVAR')
+_FIELD_INITVAR = _FIELD_BASE('_FIELD_INITVAR')
+
+def field(*ignore, **kwds):
+ default = kwds.pop("default", MISSING)
+ default_factory = kwds.pop("default_factory", MISSING)
+ init = kwds.pop("init", True)
+ repr = kwds.pop("repr", True)
+ hash = kwds.pop("hash", None)
+ compare = kwds.pop("compare", True)
+ metadata = kwds.pop("metadata", None)
+ kw_only = kwds.pop("kw_only", None)
+
+ if kwds:
+ raise ValueError("field received unexpected keyword arguments: %s"
+ % list(kwds.keys()))
+ if default is not MISSING and default_factory is not MISSING:
+ raise ValueError('cannot specify both default and default_factory')
+ if ignore:
+ raise ValueError("'field' does not take any positional arguments")
+ return Field(default, default_factory, init,
+ repr, hash, compare, metadata, kw_only)
diff --git a/Cython/Utility/Embed.c b/Cython/Utility/Embed.c
index 8f7e8f46e..3c827794e 100644
--- a/Cython/Utility/Embed.c
+++ b/Cython/Utility/Embed.c
@@ -5,12 +5,13 @@
#endif
#if PY_MAJOR_VERSION < 3
-int %(main_method)s(int argc, char** argv) {
-#elif defined(WIN32) || defined(MS_WINDOWS)
-int %(wmain_method)s(int argc, wchar_t **argv) {
+int %(main_method)s(int argc, char** argv)
+#elif defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS)
+int %(wmain_method)s(int argc, wchar_t **argv)
#else
-static int __Pyx_main(int argc, wchar_t **argv) {
+static int __Pyx_main(int argc, wchar_t **argv)
#endif
+{
/* 754 requires that FP exceptions run in "no stop" mode by default,
* and until C vendors implement C99's ways to control FP exceptions,
* Python requires non-stop mode. Alas, some platforms enable FP
@@ -22,34 +23,60 @@ static int __Pyx_main(int argc, wchar_t **argv) {
m = fpgetmask();
fpsetmask(m & ~FP_X_OFL);
#endif
+#if PY_VERSION_HEX < 0x03080000
if (argc && argv)
Py_SetProgramName(argv[0]);
+#endif
+
+ #if PY_MAJOR_VERSION < 3
+ if (PyImport_AppendInittab("%(module_name)s", init%(module_name)s) < 0) return 1;
+ #else
+ if (PyImport_AppendInittab("%(module_name)s", PyInit_%(module_name)s) < 0) return 1;
+ #endif
+
+#if PY_VERSION_HEX < 0x03080000
Py_Initialize();
if (argc && argv)
PySys_SetArgv(argc, argv);
+#else
+ {
+ PyStatus status;
+
+ PyConfig config;
+ PyConfig_InitPythonConfig(&config);
+ // Disable parsing command line arguments
+ config.parse_argv = 0;
+
+ if (argc && argv) {
+ status = PyConfig_SetString(&config, &config.program_name, argv[0]);
+ if (PyStatus_Exception(status)) {
+ PyConfig_Clear(&config);
+ return 1;
+ }
+
+ status = PyConfig_SetArgv(&config, argc, argv);
+ if (PyStatus_Exception(status)) {
+ PyConfig_Clear(&config);
+ return 1;
+ }
+ }
+
+ status = Py_InitializeFromConfig(&config);
+ if (PyStatus_Exception(status)) {
+ PyConfig_Clear(&config);
+ return 1;
+ }
+
+ PyConfig_Clear(&config);
+ }
+#endif
+
{ /* init module '%(module_name)s' as '__main__' */
PyObject* m = NULL;
%(module_is_main)s = 1;
- #if PY_MAJOR_VERSION < 3
- init%(module_name)s();
- #elif CYTHON_PEP489_MULTI_PHASE_INIT
- m = PyInit_%(module_name)s();
- if (!PyModule_Check(m)) {
- PyModuleDef *mdef = (PyModuleDef *) m;
- PyObject *modname = PyUnicode_FromString("__main__");
- m = NULL;
- if (modname) {
- // FIXME: not currently calling PyModule_FromDefAndSpec() here because we do not have a module spec!
- // FIXME: not currently setting __file__, __path__, __spec__, ...
- m = PyModule_NewObject(modname);
- Py_DECREF(modname);
- if (m) PyModule_ExecDef(m, mdef);
- }
- }
- #else
- m = PyInit_%(module_name)s();
- #endif
- if (PyErr_Occurred()) {
+ m = PyImport_ImportModule("%(module_name)s");
+
+ if (!m && PyErr_Occurred()) {
PyErr_Print(); /* This exits with the right code if SystemExit. */
#if PY_MAJOR_VERSION < 3
if (Py_FlushLine()) PyErr_Clear();
@@ -68,9 +95,11 @@ static int __Pyx_main(int argc, wchar_t **argv) {
}
-#if PY_MAJOR_VERSION >= 3 && !defined(WIN32) && !defined(MS_WINDOWS)
+#if PY_MAJOR_VERSION >= 3 && !defined(_WIN32) && !defined(WIN32) && !defined(MS_WINDOWS)
#include <locale.h>
+#if PY_VERSION_HEX < 0x03050000
+
static wchar_t*
__Pyx_char2wchar(char* arg)
{
@@ -175,6 +204,8 @@ oom:
return NULL;
}
+#endif
+
int
%(main_method)s(int argc, char **argv)
{
@@ -197,7 +228,12 @@ int
res = 0;
setlocale(LC_ALL, "");
for (i = 0; i < argc; i++) {
- argv_copy2[i] = argv_copy[i] = __Pyx_char2wchar(argv[i]);
+ argv_copy2[i] = argv_copy[i] =
+#if PY_VERSION_HEX < 0x03050000
+ __Pyx_char2wchar(argv[i]);
+#else
+ Py_DecodeLocale(argv[i], NULL);
+#endif
if (!argv_copy[i]) res = 1; /* failure, but continue to simplify cleanup */
}
setlocale(LC_ALL, oldloc);
diff --git a/Cython/Utility/Exceptions.c b/Cython/Utility/Exceptions.c
index 87d3a5cdd..abf95afda 100644
--- a/Cython/Utility/Exceptions.c
+++ b/Cython/Utility/Exceptions.c
@@ -6,6 +6,49 @@
// __Pyx_GetException()
+/////////////// AssertionsEnabled.init ///////////////
+__Pyx_init_assertions_enabled();
+
+/////////////// AssertionsEnabled.proto ///////////////
+
+#define __Pyx_init_assertions_enabled()
+
+#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag)
+ #define __pyx_assertions_enabled() (1)
+#elif PY_VERSION_HEX < 0x03080000 || CYTHON_COMPILING_IN_PYPY || defined(Py_LIMITED_API)
+ #define __pyx_assertions_enabled() (!Py_OptimizeFlag)
+#elif CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030900A6
+ // Py3.8+ has PyConfig from PEP 587, but only Py3.9 added read access to it.
+ // Py_OptimizeFlag is deprecated in Py3.12+
+ static int __pyx_assertions_enabled_flag;
+ #define __pyx_assertions_enabled() (__pyx_assertions_enabled_flag)
+
+ #undef __Pyx_init_assertions_enabled
+ static void __Pyx_init_assertions_enabled(void) {
+ __pyx_assertions_enabled_flag = ! _PyInterpreterState_GetConfig(__Pyx_PyThreadState_Current->interp)->optimization_level;
+ }
+#else
+ #define __pyx_assertions_enabled() (!Py_OptimizeFlag)
+#endif
+
+
+/////////////// ErrOccurredWithGIL.proto ///////////////
+static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void); /* proto */
+
+/////////////// ErrOccurredWithGIL ///////////////
+static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void) {
+ int err;
+ #ifdef WITH_THREAD
+ PyGILState_STATE _save = PyGILState_Ensure();
+ #endif
+ err = !!PyErr_Occurred();
+ #ifdef WITH_THREAD
+ PyGILState_Release(_save);
+ #endif
+ return err;
+}
+
+
/////////////// PyThreadStateGet.proto ///////////////
//@substitute: naming
@@ -127,9 +170,9 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
// has changed quite a lot between the two versions.
#if PY_MAJOR_VERSION < 3
-static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
- CYTHON_UNUSED PyObject *cause) {
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
__Pyx_PyThreadState_declare
+ CYTHON_UNUSED_VAR(cause);
/* 'cause' is only used in Py3 */
Py_XINCREF(type);
if (!value || value == Py_None)
@@ -310,19 +353,19 @@ bad:
/////////////// GetTopmostException.proto ///////////////
-#if CYTHON_USE_EXC_INFO_STACK
+#if CYTHON_USE_EXC_INFO_STACK && CYTHON_FAST_THREAD_STATE
static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate);
#endif
/////////////// GetTopmostException ///////////////
-#if CYTHON_USE_EXC_INFO_STACK
+#if CYTHON_USE_EXC_INFO_STACK && CYTHON_FAST_THREAD_STATE
// Copied from errors.c in CPython.
static _PyErr_StackItem *
__Pyx_PyErr_GetTopmostException(PyThreadState *tstate)
{
_PyErr_StackItem *exc_info = tstate->exc_info;
- while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) &&
+ while ((exc_info->exc_value == NULL || exc_info->exc_value == Py_None) &&
exc_info->previous_item != NULL)
{
exc_info = exc_info->previous_item;
@@ -388,12 +431,21 @@ static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb)
#if CYTHON_USE_EXC_INFO_STACK
{
_PyErr_StackItem *exc_info = tstate->exc_info;
+ #if PY_VERSION_HEX >= 0x030B00a4
+ tmp_value = exc_info->exc_value;
+ exc_info->exc_value = local_value;
+ tmp_type = NULL;
+ tmp_tb = NULL;
+ Py_XDECREF(local_type);
+ Py_XDECREF(local_tb);
+ #else
tmp_type = exc_info->exc_type;
tmp_value = exc_info->exc_value;
tmp_tb = exc_info->exc_traceback;
exc_info->exc_type = local_type;
exc_info->exc_value = local_value;
exc_info->exc_traceback = local_tb;
+ #endif
}
#else
tmp_type = tstate->exc_type;
@@ -433,35 +485,44 @@ static CYTHON_INLINE void __Pyx_ReraiseException(void) {
PyObject *type = NULL, *value = NULL, *tb = NULL;
#if CYTHON_FAST_THREAD_STATE
PyThreadState *tstate = PyThreadState_GET();
- #if CYTHON_USE_EXC_INFO_STACK
+ #if CYTHON_USE_EXC_INFO_STACK
_PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate);
- type = exc_info->exc_type;
value = exc_info->exc_value;
- tb = exc_info->exc_traceback;
+ #if PY_VERSION_HEX >= 0x030B00a4
+ if (unlikely(value == Py_None)) {
+ value = NULL;
+ } else if (value) {
+ Py_INCREF(value);
+ type = (PyObject*) Py_TYPE(value);
+ Py_INCREF(type);
+ tb = PyException_GetTraceback(value);
+ }
#else
+ type = exc_info->exc_type;
+ tb = exc_info->exc_traceback;
+ Py_XINCREF(type);
+ Py_XINCREF(value);
+ Py_XINCREF(tb);
+ #endif
+ #else
type = tstate->exc_type;
value = tstate->exc_value;
tb = tstate->exc_traceback;
- #endif
+ Py_XINCREF(type);
+ Py_XINCREF(value);
+ Py_XINCREF(tb);
+ #endif
#else
PyErr_GetExcInfo(&type, &value, &tb);
#endif
- if (!type || type == Py_None) {
-#if !CYTHON_FAST_THREAD_STATE
+ if (unlikely(!type || type == Py_None)) {
Py_XDECREF(type);
Py_XDECREF(value);
Py_XDECREF(tb);
-#endif
// message copied from Py3
PyErr_SetString(PyExc_RuntimeError,
"No active exception to reraise");
} else {
-#if CYTHON_FAST_THREAD_STATE
- Py_INCREF(type);
- Py_XINCREF(value);
- Py_XINCREF(tb);
-
-#endif
PyErr_Restore(type, value, tb);
}
}
@@ -487,24 +548,49 @@ static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject
#if CYTHON_FAST_THREAD_STATE
static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) {
- #if CYTHON_USE_EXC_INFO_STACK
+ #if CYTHON_USE_EXC_INFO_STACK && PY_VERSION_HEX >= 0x030B00a4
+ _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate);
+ PyObject *exc_value = exc_info->exc_value;
+ if (exc_value == NULL || exc_value == Py_None) {
+ *value = NULL;
+ *type = NULL;
+ *tb = NULL;
+ } else {
+ *value = exc_value;
+ Py_INCREF(*value);
+ *type = (PyObject*) Py_TYPE(exc_value);
+ Py_INCREF(*type);
+ *tb = PyException_GetTraceback(exc_value);
+ }
+ #elif CYTHON_USE_EXC_INFO_STACK
_PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate);
*type = exc_info->exc_type;
*value = exc_info->exc_value;
*tb = exc_info->exc_traceback;
- #else
+ Py_XINCREF(*type);
+ Py_XINCREF(*value);
+ Py_XINCREF(*tb);
+ #else
*type = tstate->exc_type;
*value = tstate->exc_value;
*tb = tstate->exc_traceback;
- #endif
Py_XINCREF(*type);
Py_XINCREF(*value);
Py_XINCREF(*tb);
+ #endif
}
static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) {
+ #if CYTHON_USE_EXC_INFO_STACK && PY_VERSION_HEX >= 0x030B00a4
+ _PyErr_StackItem *exc_info = tstate->exc_info;
+ PyObject *tmp_value = exc_info->exc_value;
+ exc_info->exc_value = value;
+ Py_XDECREF(tmp_value);
+ // TODO: avoid passing these at all
+ Py_XDECREF(type);
+ Py_XDECREF(tb);
+ #else
PyObject *tmp_type, *tmp_value, *tmp_tb;
-
#if CYTHON_USE_EXC_INFO_STACK
_PyErr_StackItem *exc_info = tstate->exc_info;
tmp_type = exc_info->exc_type;
@@ -524,6 +610,7 @@ static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject
Py_XDECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);
+ #endif
}
#endif
@@ -543,8 +630,22 @@ static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value,
#if CYTHON_FAST_THREAD_STATE
static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) {
PyObject *tmp_type, *tmp_value, *tmp_tb;
-
- #if CYTHON_USE_EXC_INFO_STACK
+ #if CYTHON_USE_EXC_INFO_STACK && PY_VERSION_HEX >= 0x030B00a4
+ _PyErr_StackItem *exc_info = tstate->exc_info;
+ tmp_value = exc_info->exc_value;
+ exc_info->exc_value = *value;
+ if (tmp_value == NULL || tmp_value == Py_None) {
+ Py_XDECREF(tmp_value);
+ tmp_value = NULL;
+ tmp_type = NULL;
+ tmp_tb = NULL;
+ } else {
+ // TODO: avoid swapping these at all
+ tmp_type = (PyObject*) Py_TYPE(tmp_value);
+ Py_INCREF(tmp_type);
+ tmp_tb = PyException_GetTraceback(tmp_value);
+ }
+ #elif CYTHON_USE_EXC_INFO_STACK
_PyErr_StackItem *exc_info = tstate->exc_info;
tmp_type = exc_info->exc_type;
tmp_value = exc_info->exc_value;
@@ -553,7 +654,7 @@ static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject *
exc_info->exc_type = *type;
exc_info->exc_value = *value;
exc_info->exc_traceback = *tb;
- #else
+ #else
tmp_type = tstate->exc_type;
tmp_value = tstate->exc_value;
tmp_tb = tstate->exc_traceback;
@@ -561,7 +662,7 @@ static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject *
tstate->exc_type = *type;
tstate->exc_value = *value;
tstate->exc_traceback = *tb;
- #endif
+ #endif
*type = tmp_type;
*value = tmp_value;
@@ -590,9 +691,9 @@ static void __Pyx_WriteUnraisable(const char *name, int clineno,
//@requires: PyErrFetchRestore
//@requires: PyThreadStateGet
-static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno,
- CYTHON_UNUSED int lineno, CYTHON_UNUSED const char *filename,
- int full_traceback, CYTHON_UNUSED int nogil) {
+static void __Pyx_WriteUnraisable(const char *name, int clineno,
+ int lineno, const char *filename,
+ int full_traceback, int nogil) {
PyObject *old_exc, *old_val, *old_tb;
PyObject *ctx;
__Pyx_PyThreadState_declare
@@ -600,9 +701,14 @@ static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno,
PyGILState_STATE state;
if (nogil)
state = PyGILState_Ensure();
- /* initalize to suppress warning */
+ /* arbitrary, to suppress warning */
else state = (PyGILState_STATE)0;
#endif
+ CYTHON_UNUSED_VAR(clineno);
+ CYTHON_UNUSED_VAR(lineno);
+ CYTHON_UNUSED_VAR(filename);
+ CYTHON_MAYBE_UNUSED_VAR(nogil);
+
__Pyx_PyThreadState_assign
__Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
if (full_traceback) {
@@ -639,19 +745,21 @@ static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line);/*proto*/
#endif
/////////////// CLineInTraceback ///////////////
-//@requires: ObjectHandling.c::PyObjectGetAttrStr
+//@requires: ObjectHandling.c::PyObjectGetAttrStrNoError
//@requires: ObjectHandling.c::PyDictVersioning
//@requires: PyErrFetchRestore
//@substitute: naming
#ifndef CYTHON_CLINE_IN_TRACEBACK
-static int __Pyx_CLineForTraceback(CYTHON_UNUSED PyThreadState *tstate, int c_line) {
+static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) {
PyObject *use_cline;
PyObject *ptype, *pvalue, *ptraceback;
#if CYTHON_COMPILING_IN_CPYTHON
PyObject **cython_runtime_dict;
#endif
+ CYTHON_MAYBE_UNUSED_VAR(tstate);
+
if (unlikely(!${cython_runtime_cname})) {
// Very early error where the runtime module is not set up yet.
return c_line;
@@ -668,7 +776,7 @@ static int __Pyx_CLineForTraceback(CYTHON_UNUSED PyThreadState *tstate, int c_li
} else
#endif
{
- PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(${cython_runtime_cname}, PYIDENT("cline_in_traceback"));
+ PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStrNoError(${cython_runtime_cname}, PYIDENT("cline_in_traceback"));
if (use_cline_obj) {
use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True;
Py_DECREF(use_cline_obj);
@@ -710,6 +818,17 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line,
#include "internal/pycore_frame.h"
#endif
+#if CYTHON_COMPILING_IN_LIMITED_API
+static void __Pyx_AddTraceback(const char *funcname, int c_line,
+ int py_line, const char *filename) {
+ if (c_line) {
+ // Avoid "unused" warning as long as we don't use this.
+ (void) $cfilenm_cname;
+ (void) __Pyx_CLineForTraceback(__Pyx_PyThreadState_Current, c_line);
+ }
+ _PyTraceback_Add(funcname, filename, py_line);
+}
+#else
static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
const char *funcname, int c_line,
int py_line, const char *filename) {
@@ -742,6 +861,7 @@ static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
#if PY_MAJOR_VERSION < 3
py_code = __Pyx_PyCode_New(
0, /*int argcount,*/
+ 0, /*int posonlyargcount,*/
0, /*int kwonlyargcount,*/
0, /*int nlocals,*/
0, /*int stacksize,*/
@@ -812,3 +932,4 @@ bad:
Py_XDECREF(py_code);
Py_XDECREF(py_frame);
}
+#endif
diff --git a/Cython/Utility/ExtensionTypes.c b/Cython/Utility/ExtensionTypes.c
index dc187ab49..8b73824dd 100644
--- a/Cython/Utility/ExtensionTypes.c
+++ b/Cython/Utility/ExtensionTypes.c
@@ -1,12 +1,107 @@
-/////////////// 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 ///////////////
+/////////////// 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
+ CYTHON_UNUSED_VAR(spec);
+ CYTHON_UNUSED_VAR(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 ///////////////
+
+#if CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_LIMITED_API || CYTHON_USE_TYPE_SPECS
+static int __Pyx_validate_bases_tuple(const char *type_name, Py_ssize_t dictoffset, PyObject *bases); /*proto*/
+#endif
+
+/////////////// ValidateBasesTuple ///////////////
+
+#if CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_LIMITED_API || CYTHON_USE_TYPE_SPECS
+static int __Pyx_validate_bases_tuple(const char *type_name, Py_ssize_t dictoffset, PyObject *bases) {
// Loop over all bases (except the first) and check that those
// really are heap types. Otherwise, it would not be safe to
// subclass them.
@@ -17,52 +112,97 @@ 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 (!PyType_HasFeature(b, Py_TPFLAGS_HEAPTYPE))
- {
- PyErr_Format(PyExc_TypeError, "base class '%.200s' is not a heap type",
- b->tp_name);
- return -1;
- }
- if (t->tp_dictoffset == 0 && b->tp_dictoffset)
- {
- PyErr_Format(PyExc_TypeError,
- "extension type '%.200s' has no __dict__ slot, but base type '%.200s' has: "
- "either add 'cdef dict __dict__' to the extension type "
- "or add '__slots__ = [...]' to the base type",
- t->tp_name, b->tp_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;
+}
+#endif
+
+
+/////////////// PyType_Ready.proto ///////////////
+
+// unused when using type specs
+CYTHON_UNUSED static int __Pyx_PyType_Ready(PyTypeObject *t);/*proto*/
+
+/////////////// PyType_Ready ///////////////
+//@requires: ObjectHandling.c::PyObjectCallMethod0
+//@requires: ValidateBasesTuple
+
+// Wrapper around PyType_Ready() with some runtime checks and fixes
+// to deal with multiple inheritance.
+static int __Pyx_PyType_Ready(PyTypeObject *t) {
+
+// FIXME: is this really suitable for CYTHON_COMPILING_IN_LIMITED_API?
+#if CYTHON_USE_TYPE_SPECS || !(CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_LIMITED_API) || defined(PYSTON_MAJOR_VERSION)
+ // avoid C warning about unused helper function
+ (void)__Pyx_PyObject_CallMethod0;
+#if CYTHON_USE_TYPE_SPECS
+ (void)__Pyx_validate_bases_tuple;
+#endif
+
+ return PyType_Ready(t);
+
+#else
+ int r;
+ PyObject *bases = __Pyx_PyType_GetSlot(t, tp_bases, PyObject*);
+ if (bases && unlikely(__Pyx_validate_bases_tuple(t->tp_name, t->tp_dictoffset, bases) == -1))
+ return -1;
#if PY_VERSION_HEX >= 0x03050000 && !defined(PYSTON_MAJOR_VERSION)
{
// Make sure GC does not pick up our non-heap type as heap type with this hack!
// For details, see https://github.com/cython/cython/issues/3603
- PyObject *ret, *py_status;
int gc_was_enabled;
- PyObject *gc = PyImport_Import(PYUNICODE("gc"));
+ #if PY_VERSION_HEX >= 0x030A00b1
+ // finally added in Py3.10 :)
+ gc_was_enabled = PyGC_Disable();
+ (void)__Pyx_PyObject_CallMethod0;
+
+ #else
+ // Call gc.disable() as a backwards compatible fallback, but only if needed.
+ PyObject *ret, *py_status;
+ PyObject *gc = NULL;
+ #if PY_VERSION_HEX >= 0x030700a1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM+0 >= 0x07030400)
+ // https://foss.heptapod.net/pypy/pypy/-/issues/3385
+ gc = PyImport_GetModule(PYUNICODE("gc"));
+ #endif
+ if (unlikely(!gc)) gc = PyImport_Import(PYUNICODE("gc"));
if (unlikely(!gc)) return -1;
- py_status = PyObject_CallMethodObjArgs(gc, PYUNICODE("isenabled"), NULL);
+ py_status = __Pyx_PyObject_CallMethod0(gc, PYUNICODE("isenabled"));
if (unlikely(!py_status)) {
Py_DECREF(gc);
return -1;
@@ -70,7 +210,7 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) {
gc_was_enabled = __Pyx_PyObject_IsTrue(py_status);
Py_DECREF(py_status);
if (gc_was_enabled > 0) {
- ret = PyObject_CallMethodObjArgs(gc, PYUNICODE("disable"), NULL);
+ ret = __Pyx_PyObject_CallMethod0(gc, PYUNICODE("disable"));
if (unlikely(!ret)) {
Py_DECREF(gc);
return -1;
@@ -80,6 +220,7 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) {
Py_DECREF(gc);
return -1;
}
+ #endif
// As of https://bugs.python.org/issue22079
// PyType_Ready enforces that all bases of a non-heap type are
@@ -89,6 +230,18 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) {
// Other than this check, the Py_TPFLAGS_HEAPTYPE flag is unused
// in PyType_Ready().
t->tp_flags |= Py_TPFLAGS_HEAPTYPE;
+#if PY_VERSION_HEX >= 0x030A0000
+ // As of https://github.com/python/cpython/pull/25520
+ // PyType_Ready marks types as immutable if they are static types
+ // and requires the Py_TPFLAGS_IMMUTABLETYPE flag to mark types as
+ // immutable
+ // Manually set the Py_TPFLAGS_IMMUTABLETYPE flag, since the type
+ // is immutable
+ t->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE;
+#endif
+#else
+ // avoid C warning about unused helper function
+ (void)__Pyx_PyObject_CallMethod0;
#endif
r = PyType_Ready(t);
@@ -96,29 +249,84 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) {
#if PY_VERSION_HEX >= 0x03050000 && !defined(PYSTON_MAJOR_VERSION)
t->tp_flags &= ~Py_TPFLAGS_HEAPTYPE;
+ #if PY_VERSION_HEX >= 0x030A00b1
+ if (gc_was_enabled)
+ PyGC_Enable();
+ #else
if (gc_was_enabled) {
- PyObject *t, *v, *tb;
- PyErr_Fetch(&t, &v, &tb);
- ret = PyObject_CallMethodObjArgs(gc, PYUNICODE("enable"), NULL);
+ PyObject *tp, *v, *tb;
+ PyErr_Fetch(&tp, &v, &tb);
+ ret = __Pyx_PyObject_CallMethod0(gc, PYUNICODE("enable"));
if (likely(ret || r == -1)) {
Py_XDECREF(ret);
// do not overwrite exceptions raised by PyType_Ready() above
- PyErr_Restore(t, v, tb);
+ PyErr_Restore(tp, v, tb);
} else {
// PyType_Ready() succeeded, but gc.enable() failed.
- Py_XDECREF(t);
+ Py_XDECREF(tp);
Py_XDECREF(v);
Py_XDECREF(tb);
r = -1;
}
}
Py_DECREF(gc);
+ #endif
}
#endif
return r;
+#endif
}
+
+/////////////// PyTrashcan.proto ///////////////
+
+// These macros are taken from https://github.com/python/cpython/pull/11841
+// Unlike the Py_TRASHCAN_SAFE_BEGIN/Py_TRASHCAN_SAFE_END macros, they
+// allow dealing correctly with subclasses.
+
+// This requires CPython version >= 2.7.4
+// (or >= 3.2.4 but we don't support such old Python 3 versions anyway)
+#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03080000
+// https://github.com/python/cpython/pull/11841 merged so Cython reimplementation
+// is no longer necessary
+#define __Pyx_TRASHCAN_BEGIN Py_TRASHCAN_BEGIN
+#define __Pyx_TRASHCAN_END Py_TRASHCAN_END
+#elif CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x02070400
+#define __Pyx_TRASHCAN_BEGIN_CONDITION(op, cond) \
+ do { \
+ PyThreadState *_tstate = NULL; \
+ // If "cond" is false, then _tstate remains NULL and the deallocator
+ // is run normally without involving the trashcan
+ if (cond) { \
+ _tstate = PyThreadState_GET(); \
+ if (_tstate->trash_delete_nesting >= PyTrash_UNWIND_LEVEL) { \
+ // Store the object (to be deallocated later) and jump past
+ // Py_TRASHCAN_END, skipping the body of the deallocator
+ _PyTrash_thread_deposit_object((PyObject*)(op)); \
+ break; \
+ } \
+ ++_tstate->trash_delete_nesting; \
+ }
+ // The body of the deallocator is here.
+#define __Pyx_TRASHCAN_END \
+ if (_tstate) { \
+ --_tstate->trash_delete_nesting; \
+ if (_tstate->trash_delete_later && _tstate->trash_delete_nesting <= 0) \
+ _PyTrash_thread_destroy_chain(); \
+ } \
+ } while (0);
+
+#define __Pyx_TRASHCAN_BEGIN(op, dealloc) __Pyx_TRASHCAN_BEGIN_CONDITION(op, \
+ __Pyx_PyObject_GetSlot(op, tp_dealloc, destructor) == (destructor)(dealloc))
+
+#else
+// The trashcan is a no-op on other Python implementations
+// or old CPython versions
+#define __Pyx_TRASHCAN_BEGIN(op, dealloc)
+#define __Pyx_TRASHCAN_END
+#endif
+
/////////////// CallNextTpDealloc.proto ///////////////
static void __Pyx_call_next_tp_dealloc(PyObject* obj, destructor current_tp_dealloc);
@@ -127,13 +335,14 @@ static void __Pyx_call_next_tp_dealloc(PyObject* obj, destructor current_tp_deal
static void __Pyx_call_next_tp_dealloc(PyObject* obj, destructor current_tp_dealloc) {
PyTypeObject* type = Py_TYPE(obj);
+ destructor tp_dealloc = NULL;
/* try to find the first parent type that has a different tp_dealloc() function */
- while (type && type->tp_dealloc != current_tp_dealloc)
- type = type->tp_base;
- while (type && type->tp_dealloc == current_tp_dealloc)
- type = type->tp_base;
+ while (type && __Pyx_PyType_GetSlot(type, tp_dealloc, destructor) != current_tp_dealloc)
+ type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*);
+ while (type && (tp_dealloc = __Pyx_PyType_GetSlot(type, tp_dealloc, destructor)) == current_tp_dealloc)
+ type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*);
if (type)
- type->tp_dealloc(obj);
+ tp_dealloc(obj);
}
/////////////// CallNextTpTraverse.proto ///////////////
@@ -144,48 +353,53 @@ static int __Pyx_call_next_tp_traverse(PyObject* obj, visitproc v, void *a, trav
static int __Pyx_call_next_tp_traverse(PyObject* obj, visitproc v, void *a, traverseproc current_tp_traverse) {
PyTypeObject* type = Py_TYPE(obj);
+ traverseproc tp_traverse = NULL;
/* try to find the first parent type that has a different tp_traverse() function */
- while (type && type->tp_traverse != current_tp_traverse)
- type = type->tp_base;
- while (type && type->tp_traverse == current_tp_traverse)
- type = type->tp_base;
- if (type && type->tp_traverse)
- return type->tp_traverse(obj, v, a);
+ while (type && __Pyx_PyType_GetSlot(type, tp_traverse, traverseproc) != current_tp_traverse)
+ type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*);
+ while (type && (tp_traverse = __Pyx_PyType_GetSlot(type, tp_traverse, traverseproc)) == current_tp_traverse)
+ type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*);
+ if (type && tp_traverse)
+ return tp_traverse(obj, v, a);
// FIXME: really ignore?
return 0;
}
/////////////// CallNextTpClear.proto ///////////////
-static void __Pyx_call_next_tp_clear(PyObject* obj, inquiry current_tp_dealloc);
+static void __Pyx_call_next_tp_clear(PyObject* obj, inquiry current_tp_clear);
/////////////// CallNextTpClear ///////////////
static void __Pyx_call_next_tp_clear(PyObject* obj, inquiry current_tp_clear) {
PyTypeObject* type = Py_TYPE(obj);
+ inquiry tp_clear = NULL;
/* try to find the first parent type that has a different tp_clear() function */
- while (type && type->tp_clear != current_tp_clear)
- type = type->tp_base;
- while (type && type->tp_clear == current_tp_clear)
- type = type->tp_base;
- if (type && type->tp_clear)
- type->tp_clear(obj);
+ while (type && __Pyx_PyType_GetSlot(type, tp_clear, inquiry) != current_tp_clear)
+ type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*);
+ while (type && (tp_clear = __Pyx_PyType_GetSlot(type, tp_clear, inquiry)) == current_tp_clear)
+ type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*);
+ if (type && tp_clear)
+ tp_clear(obj);
}
/////////////// SetupReduce.proto ///////////////
+#if !CYTHON_COMPILING_IN_LIMITED_API
static int __Pyx_setup_reduce(PyObject* type_obj);
+#endif
/////////////// SetupReduce ///////////////
//@requires: ObjectHandling.c::PyObjectGetAttrStrNoError
//@requires: ObjectHandling.c::PyObjectGetAttrStr
//@substitute: naming
+#if !CYTHON_COMPILING_IN_LIMITED_API
static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) {
int ret;
PyObject *name_attr;
- name_attr = __Pyx_PyObject_GetAttrStr(meth, PYIDENT("__name__"));
+ name_attr = __Pyx_PyObject_GetAttrStrNoError(meth, PYIDENT("__name__"));
if (likely(name_attr)) {
ret = PyObject_RichCompareBool(name_attr, name, Py_EQ);
} else {
@@ -263,7 +477,7 @@ static int __Pyx_setup_reduce(PyObject* type_obj) {
goto __PYX_BAD;
}
- setstate = __Pyx_PyObject_GetAttrStr(type_obj, PYIDENT("__setstate__"));
+ setstate = __Pyx_PyObject_GetAttrStrNoError(type_obj, PYIDENT("__setstate__"));
if (!setstate) PyErr_Clear();
if (!setstate || __Pyx_setup_reduce_is_named(setstate, PYIDENT("__setstate_cython__"))) {
setstate_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, PYIDENT("__setstate_cython__"));
@@ -282,8 +496,13 @@ static int __Pyx_setup_reduce(PyObject* type_obj) {
goto __PYX_GOOD;
__PYX_BAD:
- if (!PyErr_Occurred())
- PyErr_Format(PyExc_RuntimeError, "Unable to initialize pickling for %s", ((PyTypeObject*)type_obj)->tp_name);
+ if (!PyErr_Occurred()) {
+ __Pyx_TypeName type_obj_name =
+ __Pyx_PyType_GetName((PyTypeObject*)type_obj);
+ PyErr_Format(PyExc_RuntimeError,
+ "Unable to initialize pickling for " __Pyx_FMT_TYPENAME, type_obj_name);
+ __Pyx_DECREF_TypeName(type_obj_name);
+ }
ret = -1;
__PYX_GOOD:
#if !CYTHON_USE_PYTYPE_LOOKUP
@@ -299,3 +518,92 @@ __PYX_GOOD:
Py_XDECREF(setstate_cython);
return ret;
}
+#endif
+
+
+/////////////// BinopSlot ///////////////
+
+static CYTHON_INLINE PyObject *{{func_name}}_maybe_call_slot(PyTypeObject* type, PyObject *left, PyObject *right {{extra_arg_decl}}) {
+ {{slot_type}} slot;
+#if CYTHON_USE_TYPE_SLOTS || PY_MAJOR_VERSION < 3 || CYTHON_COMPILING_IN_PYPY
+ slot = type->tp_as_number ? type->tp_as_number->{{slot_name}} : NULL;
+#else
+ slot = ({{slot_type}}) PyType_GetSlot(type, Py_{{slot_name}});
+#endif
+ return slot ? slot(left, right {{extra_arg}}) : __Pyx_NewRef(Py_NotImplemented);
+}
+
+static PyObject *{{func_name}}(PyObject *left, PyObject *right {{extra_arg_decl}}) {
+ int maybe_self_is_left, maybe_self_is_right = 0;
+ maybe_self_is_left = Py_TYPE(left) == Py_TYPE(right)
+#if CYTHON_USE_TYPE_SLOTS
+ || (Py_TYPE(left)->tp_as_number && Py_TYPE(left)->tp_as_number->{{slot_name}} == &{{func_name}})
+#endif
+ || __Pyx_TypeCheck(left, {{type_cname}});
+ // Optimize for the common case where the left operation is defined (and successful).
+ if (!({{overloads_left}})) {
+ maybe_self_is_right = Py_TYPE(left) == Py_TYPE(right)
+#if CYTHON_USE_TYPE_SLOTS
+ || (Py_TYPE(right)->tp_as_number && Py_TYPE(right)->tp_as_number->{{slot_name}} == &{{func_name}})
+#endif
+ || __Pyx_TypeCheck(right, {{type_cname}});
+ }
+ if (maybe_self_is_left) {
+ PyObject *res;
+ if (maybe_self_is_right && {{overloads_right}} && !({{overloads_left}})) {
+ res = {{call_right}};
+ if (res != Py_NotImplemented) return res;
+ Py_DECREF(res);
+ // Don't bother calling it again.
+ maybe_self_is_right = 0;
+ }
+ res = {{call_left}};
+ if (res != Py_NotImplemented) return res;
+ Py_DECREF(res);
+ }
+ if (({{overloads_left}})) {
+ maybe_self_is_right = Py_TYPE(left) == Py_TYPE(right)
+#if CYTHON_USE_TYPE_SLOTS
+ || (Py_TYPE(right)->tp_as_number && Py_TYPE(right)->tp_as_number->{{slot_name}} == &{{func_name}})
+#endif
+ || PyType_IsSubtype(Py_TYPE(right), {{type_cname}});
+ }
+ if (maybe_self_is_right) {
+ return {{call_right}};
+ }
+ return __Pyx_NewRef(Py_NotImplemented);
+}
+
+/////////////// ValidateExternBase.proto ///////////////
+
+static int __Pyx_validate_extern_base(PyTypeObject *base); /* proto */
+
+/////////////// ValidateExternBase ///////////////
+//@requires: ObjectHandling.c::FormatTypeName
+
+static int __Pyx_validate_extern_base(PyTypeObject *base) {
+ Py_ssize_t itemsize;
+#if CYTHON_COMPILING_IN_LIMITED_API
+ PyObject *py_itemsize;
+#endif
+#if !CYTHON_COMPILING_IN_LIMITED_API
+ itemsize = ((PyTypeObject *)base)->tp_itemsize;
+#else
+ py_itemsize = PyObject_GetAttrString((PyObject*)base, "__itemsize__");
+ if (!py_itemsize)
+ return -1;
+ itemsize = PyLong_AsSsize_t(py_itemsize);
+ Py_DECREF(py_itemsize);
+ py_itemsize = 0;
+ if (itemsize == (Py_ssize_t)-1 && PyErr_Occurred())
+ return -1;
+#endif
+ if (itemsize) {
+ __Pyx_TypeName b_name = __Pyx_PyType_GetName(base);
+ PyErr_Format(PyExc_TypeError,
+ "inheritance from PyVarObject types like '" __Pyx_FMT_TYPENAME "' not currently supported", b_name);
+ __Pyx_DECREF_TypeName(b_name);
+ return -1;
+ }
+ return 0;
+}
diff --git a/Cython/Utility/FunctionArguments.c b/Cython/Utility/FunctionArguments.c
index 8333d9366..8bdaee562 100644
--- a/Cython/Utility/FunctionArguments.c
+++ b/Cython/Utility/FunctionArguments.c
@@ -2,7 +2,7 @@
#define __Pyx_ArgTypeTest(obj, type, none_allowed, name, exact) \
- ((likely((Py_TYPE(obj) == type) | (none_allowed && (obj == Py_None)))) ? 1 : \
+ ((likely(__Pyx_IS_TYPE(obj, type) | (none_allowed && (obj == Py_None)))) ? 1 : \
__Pyx__ArgTypeTest(obj, type, name, exact))
static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact); /*proto*/
@@ -11,6 +11,8 @@ static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *nam
static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact)
{
+ __Pyx_TypeName type_name;
+ __Pyx_TypeName obj_type_name;
if (unlikely(!type)) {
PyErr_SetString(PyExc_SystemError, "Missing type object");
return 0;
@@ -23,9 +25,13 @@ static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *nam
else {
if (likely(__Pyx_TypeCheck(obj, type))) return 1;
}
+ type_name = __Pyx_PyType_GetName(type);
+ obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj));
PyErr_Format(PyExc_TypeError,
- "Argument '%.200s' has incorrect type (expected %.200s, got %.200s)",
- name, type->tp_name, Py_TYPE(obj)->tp_name);
+ "Argument '%.200s' has incorrect type (expected " __Pyx_FMT_TYPENAME
+ ", got " __Pyx_FMT_TYPENAME ")", name, type_name, obj_type_name);
+ __Pyx_DECREF_TypeName(type_name);
+ __Pyx_DECREF_TypeName(obj_type_name);
return 0;
}
@@ -111,22 +117,28 @@ static void __Pyx_RaiseMappingExpectedError(PyObject* arg); /*proto*/
//////////////////// RaiseMappingExpected ////////////////////
static void __Pyx_RaiseMappingExpectedError(PyObject* arg) {
- PyErr_Format(PyExc_TypeError, "'%.200s' object is not a mapping", Py_TYPE(arg)->tp_name);
+ __Pyx_TypeName arg_type_name = __Pyx_PyType_GetName(Py_TYPE(arg));
+ PyErr_Format(PyExc_TypeError,
+ "'" __Pyx_FMT_TYPENAME "' object is not a mapping", arg_type_name);
+ __Pyx_DECREF_TypeName(arg_type_name);
}
//////////////////// KeywordStringCheck.proto ////////////////////
-static int __Pyx_CheckKeywordStrings(PyObject *kwdict, const char* function_name, int kw_allowed); /*proto*/
+static int __Pyx_CheckKeywordStrings(PyObject *kw, const char* function_name, int kw_allowed); /*proto*/
//////////////////// KeywordStringCheck ////////////////////
-// __Pyx_CheckKeywordStrings raises an error if non-string keywords
-// were passed to a function, or if any keywords were passed to a
-// function that does not accept them.
+// __Pyx_CheckKeywordStrings raises an error if non-string keywords
+// were passed to a function, or if any keywords were passed to a
+// function that does not accept them.
+//
+// The "kw" argument is either a dict (for METH_VARARGS) or a tuple
+// (for METH_FASTCALL).
static int __Pyx_CheckKeywordStrings(
- PyObject *kwdict,
+ PyObject *kw,
const char* function_name,
int kw_allowed)
{
@@ -134,18 +146,37 @@ static int __Pyx_CheckKeywordStrings(
Py_ssize_t pos = 0;
#if CYTHON_COMPILING_IN_PYPY
/* PyPy appears to check keywords at call time, not at unpacking time => not much to do here */
- if (!kw_allowed && PyDict_Next(kwdict, &pos, &key, 0))
+ if (!kw_allowed && PyDict_Next(kw, &pos, &key, 0))
goto invalid_keyword;
return 1;
#else
- while (PyDict_Next(kwdict, &pos, &key, 0)) {
+ if (CYTHON_METH_FASTCALL && likely(PyTuple_Check(kw))) {
+ if (unlikely(PyTuple_GET_SIZE(kw) == 0))
+ return 1;
+ if (!kw_allowed) {
+ key = PyTuple_GET_ITEM(kw, 0);
+ goto invalid_keyword;
+ }
+#if PY_VERSION_HEX < 0x03090000
+ // On CPython >= 3.9, the FASTCALL protocol guarantees that keyword
+ // names are strings (see https://bugs.python.org/issue37540)
+ for (pos = 0; pos < PyTuple_GET_SIZE(kw); pos++) {
+ key = PyTuple_GET_ITEM(kw, pos);
+ if (unlikely(!PyUnicode_Check(key)))
+ goto invalid_keyword_type;
+ }
+#endif
+ return 1;
+ }
+
+ while (PyDict_Next(kw, &pos, &key, 0)) {
#if PY_MAJOR_VERSION < 3
if (unlikely(!PyString_Check(key)))
#endif
if (unlikely(!PyUnicode_Check(key)))
goto invalid_keyword_type;
}
- if ((!kw_allowed) && unlikely(key))
+ if (!kw_allowed && unlikely(key))
goto invalid_keyword;
return 1;
invalid_keyword_type:
@@ -154,11 +185,12 @@ invalid_keyword_type:
return 0;
#endif
invalid_keyword:
- PyErr_Format(PyExc_TypeError,
#if PY_MAJOR_VERSION < 3
+ PyErr_Format(PyExc_TypeError,
"%.200s() got an unexpected keyword argument '%.200s'",
function_name, PyString_AsString(key));
#else
+ PyErr_Format(PyExc_TypeError,
"%s() got an unexpected keyword argument '%U'",
function_name, key);
#endif
@@ -168,17 +200,22 @@ invalid_keyword:
//////////////////// ParseKeywords.proto ////////////////////
-static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
- PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
+static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject *const *kwvalues,
+ PyObject **argnames[],
+ PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,
const char* function_name); /*proto*/
//////////////////// ParseKeywords ////////////////////
//@requires: RaiseDoubleKeywords
// __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
-// arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
+// arguments from kwds into the dict kwds2. If kwds2 is NULL, unknown
// keywords will raise an invalid keyword error.
//
+// When not using METH_FASTCALL, kwds is a dict and kwvalues is NULL.
+// Otherwise, kwds is a tuple with keyword names and kwvalues is a C
+// array with the corresponding values.
+//
// Three kinds of errors are checked: 1) non-string keywords, 2)
// unexpected keywords and 3) overlap with positional arguments.
//
@@ -190,6 +227,7 @@ static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
static int __Pyx_ParseOptionalKeywords(
PyObject *kwds,
+ PyObject *const *kwvalues,
PyObject **argnames[],
PyObject *kwds2,
PyObject *values[],
@@ -200,8 +238,20 @@ static int __Pyx_ParseOptionalKeywords(
Py_ssize_t pos = 0;
PyObject*** name;
PyObject*** first_kw_arg = argnames + num_pos_args;
+ int kwds_is_tuple = CYTHON_METH_FASTCALL && likely(PyTuple_Check(kwds));
+
+ while (1) {
+ if (kwds_is_tuple) {
+ if (pos >= PyTuple_GET_SIZE(kwds)) break;
+ key = PyTuple_GET_ITEM(kwds, pos);
+ value = kwvalues[pos];
+ pos++;
+ }
+ else
+ {
+ if (!PyDict_Next(kwds, &pos, &key, &value)) break;
+ }
- while (PyDict_Next(kwds, &pos, &key, &value)) {
name = first_kw_arg;
while (*name && (**name != key)) name++;
if (*name) {
@@ -237,12 +287,13 @@ static int __Pyx_ParseOptionalKeywords(
#endif
if (likely(PyUnicode_Check(key))) {
while (*name) {
- int cmp = (**name == key) ? 0 :
+ int cmp = (
#if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3
(__Pyx_PyUnicode_GET_LENGTH(**name) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 :
#endif
// In Py2, we may need to convert the argument name from str to unicode for comparison.
- PyUnicode_Compare(**name, key);
+ PyUnicode_Compare(**name, key)
+ );
if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad;
if (cmp == 0) {
values[name-argnames] = value;
@@ -284,11 +335,12 @@ invalid_keyword_type:
"%.200s() keywords must be strings", function_name);
goto bad;
invalid_keyword:
- PyErr_Format(PyExc_TypeError,
#if PY_MAJOR_VERSION < 3
+ PyErr_Format(PyExc_TypeError,
"%.200s() got an unexpected keyword argument '%.200s'",
function_name, PyString_AsString(key));
#else
+ PyErr_Format(PyExc_TypeError,
"%s() got an unexpected keyword argument '%U'",
function_name, key);
#endif
@@ -314,7 +366,7 @@ static int __Pyx_MergeKeywords(PyObject *kwdict, PyObject *source_mapping) {
if (unlikely(!iter)) {
// slow fallback: try converting to dict, then iterate
PyObject *args;
- if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad;
+ if (unlikely(!PyErr_ExceptionMatches(PyExc_AttributeError))) goto bad;
PyErr_Clear();
args = PyTuple_Pack(1, source_mapping);
if (likely(args)) {
@@ -350,3 +402,74 @@ bad:
Py_XDECREF(iter);
return -1;
}
+
+
+/////////////// fastcall.proto ///////////////
+
+// We define various functions and macros with two variants:
+//..._FASTCALL and ..._VARARGS
+
+// The first is used when METH_FASTCALL is enabled and the second is used
+// otherwise. If the Python implementation does not support METH_FASTCALL
+// (because it's an old version of CPython or it's not CPython at all),
+// then the ..._FASTCALL macros simply alias ..._VARARGS
+
+#define __Pyx_Arg_VARARGS(args, i) PyTuple_GET_ITEM(args, i)
+#define __Pyx_NumKwargs_VARARGS(kwds) PyDict_Size(kwds)
+#define __Pyx_KwValues_VARARGS(args, nargs) NULL
+#define __Pyx_GetKwValue_VARARGS(kw, kwvalues, s) __Pyx_PyDict_GetItemStrWithError(kw, s)
+#define __Pyx_KwargsAsDict_VARARGS(kw, kwvalues) PyDict_Copy(kw)
+#if CYTHON_METH_FASTCALL
+ #define __Pyx_Arg_FASTCALL(args, i) args[i]
+ #define __Pyx_NumKwargs_FASTCALL(kwds) PyTuple_GET_SIZE(kwds)
+ #define __Pyx_KwValues_FASTCALL(args, nargs) ((args) + (nargs))
+ static CYTHON_INLINE PyObject * __Pyx_GetKwValue_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues, PyObject *s);
+ #define __Pyx_KwargsAsDict_FASTCALL(kw, kwvalues) _PyStack_AsDict(kwvalues, kw)
+#else
+ #define __Pyx_Arg_FASTCALL __Pyx_Arg_VARARGS
+ #define __Pyx_NumKwargs_FASTCALL __Pyx_NumKwargs_VARARGS
+ #define __Pyx_KwValues_FASTCALL __Pyx_KwValues_VARARGS
+ #define __Pyx_GetKwValue_FASTCALL __Pyx_GetKwValue_VARARGS
+ #define __Pyx_KwargsAsDict_FASTCALL __Pyx_KwargsAsDict_VARARGS
+#endif
+
+#if CYTHON_COMPILING_IN_CPYTHON
+#define __Pyx_ArgsSlice_VARARGS(args, start, stop) __Pyx_PyTuple_FromArray(&__Pyx_Arg_VARARGS(args, start), stop - start)
+#define __Pyx_ArgsSlice_FASTCALL(args, start, stop) __Pyx_PyTuple_FromArray(&__Pyx_Arg_FASTCALL(args, start), stop - start)
+#else
+/* Not CPython, so certainly no METH_FASTCALL support */
+#define __Pyx_ArgsSlice_VARARGS(args, start, stop) PyTuple_GetSlice(args, start, stop)
+#define __Pyx_ArgsSlice_FASTCALL(args, start, stop) PyTuple_GetSlice(args, start, stop)
+#endif
+
+
+/////////////// fastcall ///////////////
+//@requires: ObjectHandling.c::TupleAndListFromArray
+//@requires: StringTools.c::UnicodeEquals
+
+#if CYTHON_METH_FASTCALL
+// kwnames: tuple with names of keyword arguments
+// kwvalues: C array with values of keyword arguments
+// s: str with the keyword name to look for
+static CYTHON_INLINE PyObject * __Pyx_GetKwValue_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues, PyObject *s)
+{
+ // Search the kwnames array for s and return the corresponding value.
+ // We do two loops: a first one to compare pointers (which will find a
+ // match if the name in kwnames is interned, given that s is interned
+ // by Cython). A second loop compares the actual strings.
+ Py_ssize_t i, n = PyTuple_GET_SIZE(kwnames);
+ for (i = 0; i < n; i++)
+ {
+ if (s == PyTuple_GET_ITEM(kwnames, i)) return kwvalues[i];
+ }
+ for (i = 0; i < n; i++)
+ {
+ int eq = __Pyx_PyUnicode_Equals(s, PyTuple_GET_ITEM(kwnames, i), Py_EQ);
+ if (unlikely(eq != 0)) {
+ if (unlikely(eq < 0)) return NULL; // error
+ return kwvalues[i];
+ }
+ }
+ return NULL; // not found (no exception set)
+}
+#endif
diff --git a/Cython/Utility/ImportExport.c b/Cython/Utility/ImportExport.c
index d6f06ecd7..007f7b43a 100644
--- a/Cython/Utility/ImportExport.c
+++ b/Cython/Utility/ImportExport.c
@@ -1,12 +1,190 @@
-/////////////// PyIdentifierFromString.proto ///////////////
+/////////////// ImportDottedModule.proto ///////////////
-#if !defined(__Pyx_PyIdentifier_FromString)
+static PyObject *__Pyx_ImportDottedModule(PyObject *name, PyObject *parts_tuple); /*proto*/
+#if PY_MAJOR_VERSION >= 3
+static PyObject *__Pyx_ImportDottedModule_WalkParts(PyObject *module, PyObject *name, PyObject *parts_tuple); /*proto*/
+#endif
+
+/////////////// ImportDottedModule ///////////////
+//@requires: Import
+
+#if PY_MAJOR_VERSION >= 3
+static PyObject *__Pyx__ImportDottedModule_Error(PyObject *name, PyObject *parts_tuple, Py_ssize_t count) {
+ PyObject *partial_name = NULL, *slice = NULL, *sep = NULL;
+ if (unlikely(PyErr_Occurred())) {
+ PyErr_Clear();
+ }
+ if (likely(PyTuple_GET_SIZE(parts_tuple) == count)) {
+ partial_name = name;
+ } else {
+ slice = PySequence_GetSlice(parts_tuple, 0, count);
+ if (unlikely(!slice))
+ goto bad;
+ sep = PyUnicode_FromStringAndSize(".", 1);
+ if (unlikely(!sep))
+ goto bad;
+ partial_name = PyUnicode_Join(sep, slice);
+ }
+
+ PyErr_Format(
+#if PY_MAJOR_VERSION < 3
+ PyExc_ImportError,
+ "No module named '%s'", PyString_AS_STRING(partial_name));
+#else
+#if PY_VERSION_HEX >= 0x030600B1
+ PyExc_ModuleNotFoundError,
+#else
+ PyExc_ImportError,
+#endif
+ "No module named '%U'", partial_name);
+#endif
+
+bad:
+ Py_XDECREF(sep);
+ Py_XDECREF(slice);
+ Py_XDECREF(partial_name);
+ return NULL;
+}
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+static PyObject *__Pyx__ImportDottedModule_Lookup(PyObject *name) {
+ PyObject *imported_module;
+#if PY_VERSION_HEX < 0x030700A1 || (CYTHON_COMPILING_IN_PYPY && PYPY_VERSION_NUM < 0x07030400)
+ PyObject *modules = PyImport_GetModuleDict();
+ if (unlikely(!modules))
+ return NULL;
+ imported_module = __Pyx_PyDict_GetItemStr(modules, name);
+ Py_XINCREF(imported_module);
+#else
+ imported_module = PyImport_GetModule(name);
+#endif
+ return imported_module;
+}
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+static PyObject *__Pyx_ImportDottedModule_WalkParts(PyObject *module, PyObject *name, PyObject *parts_tuple) {
+ Py_ssize_t i, nparts;
+ nparts = PyTuple_GET_SIZE(parts_tuple);
+ for (i=1; i < nparts && module; i++) {
+ PyObject *part, *submodule;
+#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+ part = PyTuple_GET_ITEM(parts_tuple, i);
+#else
+ part = PySequence_ITEM(parts_tuple, i);
+#endif
+ submodule = __Pyx_PyObject_GetAttrStrNoError(module, part);
+ // We stop if the attribute isn't found, i.e. if submodule is NULL here.
+#if !(CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS)
+ Py_DECREF(part);
+#endif
+ Py_DECREF(module);
+ module = submodule;
+ }
+ if (unlikely(!module)) {
+ return __Pyx__ImportDottedModule_Error(name, parts_tuple, i);
+ }
+ return module;
+}
+#endif
+
+static PyObject *__Pyx__ImportDottedModule(PyObject *name, PyObject *parts_tuple) {
#if PY_MAJOR_VERSION < 3
- #define __Pyx_PyIdentifier_FromString(s) PyString_FromString(s)
+ PyObject *module, *from_list, *star = PYIDENT("*");
+ CYTHON_UNUSED_VAR(parts_tuple);
+ from_list = PyList_New(1);
+ if (unlikely(!from_list))
+ return NULL;
+ Py_INCREF(star);
+ PyList_SET_ITEM(from_list, 0, star);
+ module = __Pyx_Import(name, from_list, 0);
+ Py_DECREF(from_list);
+ return module;
#else
- #define __Pyx_PyIdentifier_FromString(s) PyUnicode_FromString(s)
+ PyObject *imported_module;
+ PyObject *module = __Pyx_Import(name, NULL, 0);
+ if (!parts_tuple || unlikely(!module))
+ return module;
+
+ // Look up module in sys.modules, which is safer than the attribute lookups below.
+ imported_module = __Pyx__ImportDottedModule_Lookup(name);
+ if (likely(imported_module)) {
+ Py_DECREF(module);
+ return imported_module;
+ }
+ PyErr_Clear();
+ return __Pyx_ImportDottedModule_WalkParts(module, name, parts_tuple);
#endif
+}
+
+static PyObject *__Pyx_ImportDottedModule(PyObject *name, PyObject *parts_tuple) {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030400B1
+ PyObject *module = __Pyx__ImportDottedModule_Lookup(name);
+ if (likely(module)) {
+ // CPython guards against thread-concurrent initialisation in importlib.
+ // In this case, we let PyImport_ImportModuleLevelObject() handle the locking.
+ PyObject *spec = __Pyx_PyObject_GetAttrStrNoError(module, PYIDENT("__spec__"));
+ if (likely(spec)) {
+ PyObject *unsafe = __Pyx_PyObject_GetAttrStrNoError(spec, PYIDENT("_initializing"));
+ if (likely(!unsafe || !__Pyx_PyObject_IsTrue(unsafe))) {
+ Py_DECREF(spec);
+ spec = NULL;
+ }
+ Py_XDECREF(unsafe);
+ }
+ if (likely(!spec)) {
+ // Not in initialisation phase => use modules as is.
+ PyErr_Clear();
+ return module;
+ }
+ Py_DECREF(spec);
+ Py_DECREF(module);
+ } else if (PyErr_Occurred()) {
+ PyErr_Clear();
+ }
+#endif
+
+ return __Pyx__ImportDottedModule(name, parts_tuple);
+}
+
+
+/////////////// ImportDottedModuleRelFirst.proto ///////////////
+
+static PyObject *__Pyx_ImportDottedModuleRelFirst(PyObject *name, PyObject *parts_tuple); /*proto*/
+
+/////////////// ImportDottedModuleRelFirst ///////////////
+//@requires: ImportDottedModule
+//@requires: Import
+
+static PyObject *__Pyx_ImportDottedModuleRelFirst(PyObject *name, PyObject *parts_tuple) {
+ PyObject *module;
+ PyObject *from_list = NULL;
+#if PY_MAJOR_VERSION < 3
+ PyObject *star = PYIDENT("*");
+ from_list = PyList_New(1);
+ if (unlikely(!from_list))
+ return NULL;
+ Py_INCREF(star);
+ PyList_SET_ITEM(from_list, 0, star);
#endif
+ module = __Pyx_Import(name, from_list, -1);
+ Py_XDECREF(from_list);
+ if (module) {
+ #if PY_MAJOR_VERSION >= 3
+ if (parts_tuple) {
+ module = __Pyx_ImportDottedModule_WalkParts(module, name, parts_tuple);
+ }
+ #endif
+ return module;
+ }
+ if (unlikely(!PyErr_ExceptionMatches(PyExc_ImportError)))
+ return NULL;
+ PyErr_Clear();
+ // try absolute import
+ return __Pyx_ImportDottedModule(name, parts_tuple);
+}
+
/////////////// Import.proto ///////////////
@@ -17,30 +195,23 @@ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); /
//@substitute: naming
static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) {
- PyObject *empty_list = 0;
PyObject *module = 0;
- PyObject *global_dict = 0;
PyObject *empty_dict = 0;
- PyObject *list;
+ PyObject *empty_list = 0;
#if PY_MAJOR_VERSION < 3
PyObject *py_import;
py_import = __Pyx_PyObject_GetAttrStr($builtins_cname, PYIDENT("__import__"));
- if (!py_import)
+ if (unlikely(!py_import))
goto bad;
- #endif
- if (from_list)
- list = from_list;
- else {
+ if (!from_list) {
empty_list = PyList_New(0);
- if (!empty_list)
+ if (unlikely(!empty_list))
goto bad;
- list = empty_list;
+ from_list = empty_list;
}
- global_dict = PyModule_GetDict($module_cname);
- if (!global_dict)
- goto bad;
+ #endif
empty_dict = PyDict_New();
- if (!empty_dict)
+ if (unlikely(!empty_dict))
goto bad;
{
#if PY_MAJOR_VERSION >= 3
@@ -48,10 +219,15 @@ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) {
// Avoid C compiler warning if strchr() evaluates to false at compile time.
if ((1) && (strchr(__Pyx_MODULE_NAME, '.'))) {
/* try package relative import first */
+ #if CYTHON_COMPILING_IN_LIMITED_API
module = PyImport_ImportModuleLevelObject(
- name, global_dict, empty_dict, list, 1);
- if (!module) {
- if (!PyErr_ExceptionMatches(PyExc_ImportError))
+ name, empty_dict, empty_dict, from_list, 1);
+ #else
+ module = PyImport_ImportModuleLevelObject(
+ name, $moddict_cname, empty_dict, from_list, 1);
+ #endif
+ if (unlikely(!module)) {
+ if (unlikely(!PyErr_ExceptionMatches(PyExc_ImportError)))
goto bad;
PyErr_Clear();
}
@@ -62,23 +238,28 @@ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) {
if (!module) {
#if PY_MAJOR_VERSION < 3
PyObject *py_level = PyInt_FromLong(level);
- if (!py_level)
+ if (unlikely(!py_level))
goto bad;
module = PyObject_CallFunctionObjArgs(py_import,
- name, global_dict, empty_dict, list, py_level, (PyObject *)NULL);
+ name, $moddict_cname, empty_dict, from_list, py_level, (PyObject *)NULL);
Py_DECREF(py_level);
#else
+ #if CYTHON_COMPILING_IN_LIMITED_API
+ module = PyImport_ImportModuleLevelObject(
+ name, empty_dict, empty_dict, from_list, level);
+ #else
module = PyImport_ImportModuleLevelObject(
- name, global_dict, empty_dict, list, level);
+ name, $moddict_cname, empty_dict, from_list, level);
+ #endif
#endif
}
}
bad:
+ Py_XDECREF(empty_dict);
+ Py_XDECREF(empty_list);
#if PY_MAJOR_VERSION < 3
Py_XDECREF(py_import);
#endif
- Py_XDECREF(empty_list);
- Py_XDECREF(empty_dict);
return module;
}
@@ -93,6 +274,39 @@ static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name); /*proto*/
static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name) {
PyObject* value = __Pyx_PyObject_GetAttrStr(module, name);
if (unlikely(!value) && PyErr_ExceptionMatches(PyExc_AttributeError)) {
+ // 'name' may refer to a (sub-)module which has not finished initialization
+ // yet, and may not be assigned as an attribute to its parent, so try
+ // finding it by full name.
+ const char* module_name_str = 0;
+ PyObject* module_name = 0;
+ PyObject* module_dot = 0;
+ PyObject* full_name = 0;
+ PyErr_Clear();
+ module_name_str = PyModule_GetName(module);
+ if (unlikely(!module_name_str)) { goto modbad; }
+ module_name = PyUnicode_FromString(module_name_str);
+ if (unlikely(!module_name)) { goto modbad; }
+ module_dot = PyUnicode_Concat(module_name, PYUNICODE("."));
+ if (unlikely(!module_dot)) { goto modbad; }
+ full_name = PyUnicode_Concat(module_dot, name);
+ if (unlikely(!full_name)) { goto modbad; }
+ #if PY_VERSION_HEX < 0x030700A1 || (CYTHON_COMPILING_IN_PYPY && PYPY_VERSION_NUM < 0x07030400)
+ {
+ PyObject *modules = PyImport_GetModuleDict();
+ if (unlikely(!modules))
+ goto modbad;
+ value = PyObject_GetItem(modules, full_name);
+ }
+ #else
+ value = PyImport_GetModule(full_name);
+ #endif
+
+ modbad:
+ Py_XDECREF(full_name);
+ Py_XDECREF(module_dot);
+ Py_XDECREF(module_name);
+ }
+ if (unlikely(!value)) {
PyErr_Format(PyExc_ImportError,
#if PY_MAJOR_VERSION < 3
"cannot import name %.230s", PyString_AS_STRING(name));
@@ -334,7 +548,7 @@ static PyTypeObject *__Pyx_ImportType_$cyversion(PyObject *module, const char *m
char warning[200];
Py_ssize_t basicsize;
Py_ssize_t itemsize;
-#ifdef Py_LIMITED_API
+#if CYTHON_COMPILING_IN_LIMITED_API
PyObject *py_basicsize;
PyObject *py_itemsize;
#endif
@@ -348,7 +562,7 @@ static PyTypeObject *__Pyx_ImportType_$cyversion(PyObject *module, const char *m
module_name, class_name);
goto bad;
}
-#ifndef Py_LIMITED_API
+#if !CYTHON_COMPILING_IN_LIMITED_API
basicsize = ((PyTypeObject *)result)->tp_basicsize;
itemsize = ((PyTypeObject *)result)->tp_itemsize;
#else
@@ -385,14 +599,17 @@ static PyTypeObject *__Pyx_ImportType_$cyversion(PyObject *module, const char *m
PyErr_Format(PyExc_ValueError,
"%.200s.%.200s size changed, may indicate binary incompatibility. "
"Expected %zd from C header, got %zd from PyObject",
- module_name, class_name, size, basicsize);
+ module_name, class_name, size, basicsize+itemsize);
goto bad;
}
- if (check_size == __Pyx_ImportType_CheckSize_Error_$cyversion && (size_t)basicsize != size) {
+ // varobjects almost have structs between basicsize and basicsize + itemsize
+ // but the struct isn't always one of the two limiting values
+ if (check_size == __Pyx_ImportType_CheckSize_Error_$cyversion &&
+ ((size_t)basicsize > size || (size_t)(basicsize + itemsize) < size)) {
PyErr_Format(PyExc_ValueError,
"%.200s.%.200s size changed, may indicate binary incompatibility. "
- "Expected %zd from C header, got %zd from PyObject",
- module_name, class_name, size, basicsize);
+ "Expected %zd from C header, got %zd-%zd from PyObject",
+ module_name, class_name, size, basicsize, basicsize+itemsize);
goto bad;
}
else if (check_size == __Pyx_ImportType_CheckSize_Warn_$cyversion && (size_t)basicsize > size) {
@@ -438,7 +655,6 @@ static int __Pyx_ImportFunction_$cyversion(PyObject *module, const char *funcnam
PyModule_GetName(module), funcname);
goto bad;
}
-#if PY_VERSION_HEX >= 0x02070000
if (!PyCapsule_IsValid(cobj, sig)) {
PyErr_Format(PyExc_TypeError,
"C function %.200s.%.200s has wrong signature (expected %.500s, got %.500s)",
@@ -446,21 +662,6 @@ static int __Pyx_ImportFunction_$cyversion(PyObject *module, const char *funcnam
goto bad;
}
tmp.p = PyCapsule_GetPointer(cobj, sig);
-#else
- {const char *desc, *s1, *s2;
- desc = (const char *)PyCObject_GetDesc(cobj);
- if (!desc)
- goto bad;
- s1 = desc; s2 = sig;
- while (*s1 != '\0' && *s1 == *s2) { s1++; s2++; }
- if (*s1 != *s2) {
- PyErr_Format(PyExc_TypeError,
- "C function %.200s.%.200s has wrong signature (expected %.500s, got %.500s)",
- PyModule_GetName(module), funcname, sig, desc);
- goto bad;
- }
- tmp.p = PyCObject_AsVoidPtr(cobj);}
-#endif
*f = tmp.fp;
if (!(*f))
goto bad;
@@ -498,11 +699,7 @@ static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *s
goto bad;
}
tmp.fp = f;
-#if PY_VERSION_HEX >= 0x02070000
cobj = PyCapsule_New(tmp.p, sig, 0);
-#else
- cobj = PyCObject_FromVoidPtrAndDesc(tmp.p, (void *)sig, 0);
-#endif
if (!cobj)
goto bad;
if (PyDict_SetItemString(d, name, cobj) < 0)
@@ -540,7 +737,6 @@ static int __Pyx_ImportVoidPtr_$cyversion(PyObject *module, const char *name, vo
PyModule_GetName(module), name);
goto bad;
}
-#if PY_VERSION_HEX >= 0x02070000
if (!PyCapsule_IsValid(cobj, sig)) {
PyErr_Format(PyExc_TypeError,
"C variable %.200s.%.200s has wrong signature (expected %.500s, got %.500s)",
@@ -548,21 +744,6 @@ static int __Pyx_ImportVoidPtr_$cyversion(PyObject *module, const char *name, vo
goto bad;
}
*p = PyCapsule_GetPointer(cobj, sig);
-#else
- {const char *desc, *s1, *s2;
- desc = (const char *)PyCObject_GetDesc(cobj);
- if (!desc)
- goto bad;
- s1 = desc; s2 = sig;
- while (*s1 != '\0' && *s1 == *s2) { s1++; s2++; }
- if (*s1 != *s2) {
- PyErr_Format(PyExc_TypeError,
- "C variable %.200s.%.200s has wrong signature (expected %.500s, got %.500s)",
- PyModule_GetName(module), name, sig, desc);
- goto bad;
- }
- *p = PyCObject_AsVoidPtr(cobj);}
-#endif
if (!(*p))
goto bad;
Py_DECREF(d);
@@ -594,11 +775,7 @@ static int __Pyx_ExportVoidPtr(PyObject *name, void *p, const char *sig) {
if (__Pyx_PyObject_SetAttrStr($module_cname, PYIDENT("$api_name"), d) < 0)
goto bad;
}
-#if PY_VERSION_HEX >= 0x02070000
cobj = PyCapsule_New(p, sig, 0);
-#else
- cobj = PyCObject_FromVoidPtrAndDesc(p, (void *)sig, 0);
-#endif
if (!cobj)
goto bad;
if (PyDict_SetItem(d, name, cobj) < 0)
@@ -615,19 +792,19 @@ bad:
/////////////// SetVTable.proto ///////////////
-static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
+static int __Pyx_SetVtable(PyTypeObject* typeptr , void* vtable); /*proto*/
/////////////// SetVTable ///////////////
-static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
-#if PY_VERSION_HEX >= 0x02070000
+static int __Pyx_SetVtable(PyTypeObject *type, void *vtable) {
PyObject *ob = PyCapsule_New(vtable, 0, 0);
+ if (unlikely(!ob))
+ goto bad;
+#if CYTHON_COMPILING_IN_LIMITED_API
+ if (unlikely(PyObject_SetAttr((PyObject *) type, PYIDENT("__pyx_vtable__"), ob) < 0))
#else
- PyObject *ob = PyCObject_FromVoidPtr(vtable, 0);
+ if (unlikely(PyDict_SetItem(type->tp_dict, PYIDENT("__pyx_vtable__"), ob) < 0))
#endif
- if (!ob)
- goto bad;
- if (PyDict_SetItem(dict, PYIDENT("__pyx_vtable__"), ob) < 0)
goto bad;
Py_DECREF(ob);
return 0;
@@ -639,20 +816,20 @@ bad:
/////////////// GetVTable.proto ///////////////
-static void* __Pyx_GetVtable(PyObject *dict); /*proto*/
+static void* __Pyx_GetVtable(PyTypeObject *type); /*proto*/
/////////////// GetVTable ///////////////
-static void* __Pyx_GetVtable(PyObject *dict) {
+static void* __Pyx_GetVtable(PyTypeObject *type) {
void* ptr;
- PyObject *ob = PyObject_GetItem(dict, PYIDENT("__pyx_vtable__"));
+#if CYTHON_COMPILING_IN_LIMITED_API
+ PyObject *ob = PyObject_GetAttr((PyObject *)type, PYIDENT("__pyx_vtable__"));
+#else
+ PyObject *ob = PyObject_GetItem(type->tp_dict, PYIDENT("__pyx_vtable__"));
+#endif
if (!ob)
goto bad;
-#if PY_VERSION_HEX >= 0x02070000
ptr = PyCapsule_GetPointer(ob, 0);
-#else
- ptr = PyCObject_AsVoidPtr(ob);
-#endif
if (!ptr && !PyErr_Occurred())
PyErr_SetString(PyExc_RuntimeError, "invalid vtable found for imported type");
Py_DECREF(ob);
@@ -666,13 +843,19 @@ bad:
/////////////// MergeVTables.proto ///////////////
//@requires: GetVTable
+// TODO: find a way to make this work with the Limited API!
+#if !CYTHON_COMPILING_IN_LIMITED_API
static int __Pyx_MergeVtables(PyTypeObject *type); /*proto*/
+#endif
/////////////// MergeVTables ///////////////
+#if !CYTHON_COMPILING_IN_LIMITED_API
static int __Pyx_MergeVtables(PyTypeObject *type) {
int i;
void** base_vtables;
+ __Pyx_TypeName tp_base_name;
+ __Pyx_TypeName base_name;
void* unknown = (void*)-1;
PyObject* bases = type->tp_bases;
int base_depth = 0;
@@ -692,13 +875,13 @@ static int __Pyx_MergeVtables(PyTypeObject *type) {
// instance struct is so extended. (It would be good to also do this
// check when a multiple-base class is created in pure Python as well.)
for (i = 1; i < PyTuple_GET_SIZE(bases); i++) {
- void* base_vtable = __Pyx_GetVtable(((PyTypeObject*)PyTuple_GET_ITEM(bases, i))->tp_dict);
+ void* base_vtable = __Pyx_GetVtable(((PyTypeObject*)PyTuple_GET_ITEM(bases, i)));
if (base_vtable != NULL) {
int j;
PyTypeObject* base = type->tp_base;
for (j = 0; j < base_depth; j++) {
if (base_vtables[j] == unknown) {
- base_vtables[j] = __Pyx_GetVtable(base->tp_dict);
+ base_vtables[j] = __Pyx_GetVtable(base);
base_vtables[j + 1] = unknown;
}
if (base_vtables[j] == base_vtable) {
@@ -715,13 +898,16 @@ static int __Pyx_MergeVtables(PyTypeObject *type) {
free(base_vtables);
return 0;
bad:
- PyErr_Format(
- PyExc_TypeError,
- "multiple bases have vtable conflict: '%s' and '%s'",
- type->tp_base->tp_name, ((PyTypeObject*)PyTuple_GET_ITEM(bases, i))->tp_name);
+ tp_base_name = __Pyx_PyType_GetName(type->tp_base);
+ base_name = __Pyx_PyType_GetName((PyTypeObject*)PyTuple_GET_ITEM(bases, i));
+ PyErr_Format(PyExc_TypeError,
+ "multiple bases have vtable conflict: '" __Pyx_FMT_TYPENAME "' and '" __Pyx_FMT_TYPENAME "'", tp_base_name, base_name);
+ __Pyx_DECREF_TypeName(tp_base_name);
+ __Pyx_DECREF_TypeName(base_name);
free(base_vtables);
return -1;
}
+#endif
/////////////// ImportNumPyArray.proto ///////////////
diff --git a/Cython/Utility/MemoryView.pyx b/Cython/Utility/MemoryView.pyx
index 277c0bd87..40572d60e 100644
--- a/Cython/Utility/MemoryView.pyx
+++ b/Cython/Utility/MemoryView.pyx
@@ -1,5 +1,8 @@
#################### View.MemoryView ####################
+# cython: language_level=3str
+# cython: binding=False
+
# This utility provides cython.array and cython.view.memoryview
from __future__ import absolute_import
@@ -8,22 +11,22 @@ cimport cython
# from cpython cimport ...
cdef extern from "Python.h":
+ ctypedef struct PyObject
int PyIndex_Check(object)
- object PyLong_FromVoidPtr(void *)
+ PyObject *PyExc_IndexError
+ PyObject *PyExc_ValueError
cdef extern from "pythread.h":
ctypedef void *PyThread_type_lock
PyThread_type_lock PyThread_allocate_lock()
void PyThread_free_lock(PyThread_type_lock)
- int PyThread_acquire_lock(PyThread_type_lock, int mode) nogil
- void PyThread_release_lock(PyThread_type_lock) nogil
cdef extern from "<string.h>":
void *memset(void *b, int c, size_t len)
cdef extern from *:
- bint __PYX_CYTHON_ATOMICS_ENABLED() noexcept
+ bint __PYX_CYTHON_ATOMICS_ENABLED()
int __Pyx_GetBuffer(object, Py_buffer *, int) except -1
void __Pyx_ReleaseBuffer(Py_buffer *)
@@ -50,7 +53,7 @@ cdef extern from *:
Py_ssize_t suboffsets[{{max_dims}}]
void __PYX_INC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil)
- void __PYX_XDEC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil)
+ void __PYX_XCLEAR_MEMVIEW({{memviewslice_name}} *memslice, int have_gil)
ctypedef struct __pyx_buffer "Py_buffer":
PyObject *obj
@@ -72,17 +75,13 @@ cdef extern from *:
ctypedef struct __Pyx_TypeInfo:
pass
- cdef object capsule "__pyx_capsule_create" (void *p, char *sig)
- cdef int __pyx_array_getbuffer(PyObject *obj, Py_buffer view, int flags)
- cdef int __pyx_memoryview_getbuffer(PyObject *obj, Py_buffer view, int flags)
-
cdef extern from *:
ctypedef int __pyx_atomic_int
{{memviewslice_name}} slice_copy_contig "__pyx_memoryview_copy_new_contig"(
__Pyx_memviewslice *from_mvs,
char *mode, int ndim,
size_t sizeof_dtype, int contig_flag,
- bint dtype_is_object) nogil except *
+ bint dtype_is_object) except * nogil
bint slice_is_contig "__pyx_memviewslice_is_contig" (
{{memviewslice_name}} mvs, char order, int ndim) nogil
bint slices_overlap "__pyx_slices_overlap" ({{memviewslice_name}} *slice1,
@@ -95,13 +94,22 @@ cdef extern from "<stdlib.h>":
void free(void *) nogil
void *memcpy(void *dest, void *src, size_t n) nogil
-
-
+# the sequence abstract base class
+cdef object __pyx_collections_abc_Sequence "__pyx_collections_abc_Sequence"
+try:
+ if __import__("sys").version_info >= (3, 3):
+ __pyx_collections_abc_Sequence = __import__("collections.abc").abc.Sequence
+ else:
+ __pyx_collections_abc_Sequence = __import__("collections").Sequence
+except:
+ # it isn't a big problem if this fails
+ __pyx_collections_abc_Sequence = None
#
### cython.array class
#
+@cython.collection_type("sequence")
@cname("__pyx_array")
cdef class array:
@@ -115,7 +123,7 @@ cdef class array:
Py_ssize_t itemsize
unicode mode # FIXME: this should have been a simple 'char'
bytes _format
- void (*callback_free_data)(void *data)
+ void (*callback_free_data)(void *data) noexcept
# cdef object _memview
cdef bint free_data
cdef bint dtype_is_object
@@ -124,17 +132,16 @@ cdef class array:
mode="c", bint allocate_buffer=True):
cdef int idx
- cdef Py_ssize_t i, dim
- cdef PyObject **p
+ cdef Py_ssize_t dim
self.ndim = <int> len(shape)
self.itemsize = itemsize
if not self.ndim:
- raise ValueError("Empty shape tuple for cython.array")
+ raise ValueError, "Empty shape tuple for cython.array"
if itemsize <= 0:
- raise ValueError("itemsize <= 0 for cython.array")
+ raise ValueError, "itemsize <= 0 for cython.array"
if not isinstance(format, bytes):
format = format.encode('ASCII')
@@ -146,76 +153,66 @@ cdef class array:
self._strides = self._shape + self.ndim
if not self._shape:
- raise MemoryError("unable to allocate shape and strides.")
+ raise MemoryError, "unable to allocate shape and strides."
# cdef Py_ssize_t dim, stride
for idx, dim in enumerate(shape):
if dim <= 0:
- raise ValueError("Invalid shape in axis %d: %d." % (idx, dim))
+ raise ValueError, f"Invalid shape in axis {idx}: {dim}."
self._shape[idx] = dim
cdef char order
- if mode == 'fortran':
- order = b'F'
- self.mode = u'fortran'
- elif mode == 'c':
+ if mode == 'c':
order = b'C'
self.mode = u'c'
+ elif mode == 'fortran':
+ order = b'F'
+ self.mode = u'fortran'
else:
- raise ValueError("Invalid mode, expected 'c' or 'fortran', got %s" % mode)
+ raise ValueError, f"Invalid mode, expected 'c' or 'fortran', got {mode}"
- self.len = fill_contig_strides_array(self._shape, self._strides,
- itemsize, self.ndim, order)
+ self.len = fill_contig_strides_array(self._shape, self._strides, itemsize, self.ndim, order)
self.free_data = allocate_buffer
self.dtype_is_object = format == b'O'
- if allocate_buffer:
- # use malloc() for backwards compatibility
- # in case external code wants to change the data pointer
- self.data = <char *>malloc(self.len)
- if not self.data:
- raise MemoryError("unable to allocate array data.")
- if self.dtype_is_object:
- p = <PyObject **> self.data
- for i in range(self.len / itemsize):
- p[i] = Py_None
- Py_INCREF(Py_None)
+ if allocate_buffer:
+ _allocate_buffer(self)
@cname('getbuffer')
def __getbuffer__(self, Py_buffer *info, int flags):
cdef int bufmode = -1
- if self.mode == u"c":
- bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS
- elif self.mode == u"fortran":
- bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS
- if not (flags & bufmode):
- raise ValueError("Can only create a buffer that is contiguous in memory.")
+ if flags & (PyBUF_C_CONTIGUOUS | PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS):
+ if self.mode == u"c":
+ bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS
+ elif self.mode == u"fortran":
+ bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS
+ if not (flags & bufmode):
+ raise ValueError, "Can only create a buffer that is contiguous in memory."
info.buf = self.data
info.len = self.len
- info.ndim = self.ndim
- info.shape = self._shape
- info.strides = self._strides
- info.suboffsets = NULL
- info.itemsize = self.itemsize
- info.readonly = 0
- if flags & PyBUF_FORMAT:
- info.format = self.format
+ if flags & PyBUF_STRIDES:
+ info.ndim = self.ndim
+ info.shape = self._shape
+ info.strides = self._strides
else:
- info.format = NULL
+ info.ndim = 1
+ info.shape = &self.len if flags & PyBUF_ND else NULL
+ info.strides = NULL
+ info.suboffsets = NULL
+ info.itemsize = self.itemsize
+ info.readonly = 0
+ info.format = self.format if flags & PyBUF_FORMAT else NULL
info.obj = self
- __pyx_getbuffer = capsule(<void *> &__pyx_array_getbuffer, "getbuffer(obj, view, flags)")
-
def __dealloc__(array self):
if self.callback_free_data != NULL:
self.callback_free_data(self.data)
- elif self.free_data:
+ elif self.free_data and self.data is not NULL:
if self.dtype_is_object:
- refcount_objects_in_slice(self.data, self._shape,
- self._strides, self.ndim, False)
+ refcount_objects_in_slice(self.data, self._shape, self._strides, self.ndim, inc=False)
free(self.data)
PyObject_Free(self._shape)
@@ -240,17 +237,42 @@ cdef class array:
def __setitem__(self, item, value):
self.memview[item] = value
+ # Sequence methods
+ try:
+ count = __pyx_collections_abc_Sequence.count
+ index = __pyx_collections_abc_Sequence.index
+ except:
+ pass
+
+@cname("__pyx_array_allocate_buffer")
+cdef int _allocate_buffer(array self) except -1:
+ # use malloc() for backwards compatibility
+ # in case external code wants to change the data pointer
+ cdef Py_ssize_t i
+ cdef PyObject **p
+
+ self.free_data = True
+ self.data = <char *>malloc(self.len)
+ if not self.data:
+ raise MemoryError, "unable to allocate array data."
+
+ if self.dtype_is_object:
+ p = <PyObject **> self.data
+ for i in range(self.len // self.itemsize):
+ p[i] = Py_None
+ Py_INCREF(Py_None)
+ return 0
+
@cname("__pyx_array_new")
-cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format,
- char *mode, char *buf):
+cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format, char *c_mode, char *buf):
cdef array result
+ cdef str mode = "fortran" if c_mode[0] == b'f' else "c" # this often comes from a constant C string.
- if buf == NULL:
- result = array(shape, itemsize, format, mode.decode('ASCII'))
+ if buf is NULL:
+ result = array.__new__(array, shape, itemsize, format, mode)
else:
- result = array(shape, itemsize, format, mode.decode('ASCII'),
- allocate_buffer=False)
+ result = array.__new__(array, shape, itemsize, format, mode, allocate_buffer=False)
result.data = buf
return result
@@ -296,7 +318,7 @@ cdef indirect_contiguous = Enum("<contiguous and indirect>")
@cname('__pyx_align_pointer')
-cdef void *align_pointer(void *memory, size_t alignment) nogil:
+cdef void *align_pointer(void *memory, size_t alignment) noexcept nogil:
"Align pointer memory on a given boundary"
cdef Py_intptr_t aligned_p = <Py_intptr_t> memory
cdef size_t offset
@@ -313,22 +335,16 @@ cdef void *align_pointer(void *memory, size_t alignment) nogil:
# pre-allocate thread locks for reuse
## note that this could be implemented in a more beautiful way in "normal" Cython,
## but this code gets merged into the user module and not everything works there.
-DEF THREAD_LOCKS_PREALLOCATED = 8
cdef int __pyx_memoryview_thread_locks_used = 0
-cdef PyThread_type_lock[THREAD_LOCKS_PREALLOCATED] __pyx_memoryview_thread_locks = [
- PyThread_allocate_lock(),
- PyThread_allocate_lock(),
- PyThread_allocate_lock(),
- PyThread_allocate_lock(),
- PyThread_allocate_lock(),
- PyThread_allocate_lock(),
- PyThread_allocate_lock(),
+cdef PyThread_type_lock[{{THREAD_LOCKS_PREALLOCATED}}] __pyx_memoryview_thread_locks = [
+{{for _ in range(THREAD_LOCKS_PREALLOCATED)}}
PyThread_allocate_lock(),
+{{endfor}}
]
@cname('__pyx_memoryview')
-cdef class memoryview(object):
+cdef class memoryview:
cdef object obj
cdef object _size
@@ -354,7 +370,7 @@ cdef class memoryview(object):
if not __PYX_CYTHON_ATOMICS_ENABLED():
global __pyx_memoryview_thread_locks_used
- if __pyx_memoryview_thread_locks_used < THREAD_LOCKS_PREALLOCATED:
+ if __pyx_memoryview_thread_locks_used < {{THREAD_LOCKS_PREALLOCATED}}:
self.lock = __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used]
__pyx_memoryview_thread_locks_used += 1
if self.lock is NULL:
@@ -417,7 +433,7 @@ cdef class memoryview(object):
def __setitem__(memoryview self, object index, object value):
if self.view.readonly:
- raise TypeError("Cannot assign to read-only memoryview")
+ raise TypeError, "Cannot assign to read-only memoryview"
have_slices, index = _unellipsify(index, self.view.ndim)
@@ -443,10 +459,10 @@ cdef class memoryview(object):
cdef setitem_slice_assignment(self, dst, src):
cdef {{memviewslice_name}} dst_slice
cdef {{memviewslice_name}} src_slice
+ cdef {{memviewslice_name}} msrc = get_slice_from_memview(src, &src_slice)[0]
+ cdef {{memviewslice_name}} mdst = get_slice_from_memview(dst, &dst_slice)[0]
- memoryview_copy_contents(get_slice_from_memview(src, &src_slice)[0],
- get_slice_from_memview(dst, &dst_slice)[0],
- src.ndim, dst.ndim, self.dtype_is_object)
+ memoryview_copy_contents(msrc, mdst, src.ndim, dst.ndim, self.dtype_is_object)
cdef setitem_slice_assign_scalar(self, memoryview dst, value):
cdef int array[128]
@@ -494,7 +510,7 @@ cdef class memoryview(object):
try:
result = struct.unpack(self.view.format, bytesitem)
except struct.error:
- raise ValueError("Unable to convert item to object")
+ raise ValueError, "Unable to convert item to object"
else:
if len(self.view.format) == 1:
return result[0]
@@ -519,7 +535,7 @@ cdef class memoryview(object):
@cname('getbuffer')
def __getbuffer__(self, Py_buffer *info, int flags):
if flags & PyBUF_WRITABLE and self.view.readonly:
- raise ValueError("Cannot create writable memory view from read-only memoryview")
+ raise ValueError, "Cannot create writable memory view from read-only memoryview"
if flags & PyBUF_ND:
info.shape = self.view.shape
@@ -548,8 +564,6 @@ cdef class memoryview(object):
info.readonly = self.view.readonly
info.obj = self
- __pyx_getbuffer = capsule(<void *> &__pyx_memoryview_getbuffer, "getbuffer(obj, view, flags)")
-
# Some properties that have the same semantics as in NumPy
@property
def T(self):
@@ -559,6 +573,9 @@ cdef class memoryview(object):
@property
def base(self):
+ return self._get_base()
+
+ cdef _get_base(self):
return self.obj
@property
@@ -569,7 +586,7 @@ cdef class memoryview(object):
def strides(self):
if self.view.strides == NULL:
# Note: we always ask for strides, so if this is not set it's a bug
- raise ValueError("Buffer view does not expose strides")
+ raise ValueError, "Buffer view does not expose strides"
return tuple([stride for stride in self.view.strides[:self.view.ndim]])
@@ -662,7 +679,7 @@ cdef memoryview_cwrapper(object o, int flags, bint dtype_is_object, __Pyx_TypeIn
return result
@cname('__pyx_memoryview_check')
-cdef inline bint memoryview_check(object o):
+cdef inline bint memoryview_check(object o) noexcept:
return isinstance(o, memoryview)
cdef tuple _unellipsify(object index, int ndim):
@@ -670,39 +687,35 @@ cdef tuple _unellipsify(object index, int ndim):
Replace all ellipses with full slices and fill incomplete indices with
full slices.
"""
- if not isinstance(index, tuple):
- tup = (index,)
- else:
- tup = index
+ cdef Py_ssize_t idx
+ tup = <tuple>index if isinstance(index, tuple) else (index,)
- result = []
+ result = [slice(None)] * ndim
have_slices = False
seen_ellipsis = False
- for idx, item in enumerate(tup):
+ idx = 0
+ for item in tup:
if item is Ellipsis:
if not seen_ellipsis:
- result.extend([slice(None)] * (ndim - len(tup) + 1))
+ idx += ndim - len(tup)
seen_ellipsis = True
- else:
- result.append(slice(None))
have_slices = True
else:
- if not isinstance(item, slice) and not PyIndex_Check(item):
- raise TypeError("Cannot index with type '%s'" % type(item))
-
- have_slices = have_slices or isinstance(item, slice)
- result.append(item)
-
- nslices = ndim - len(result)
- if nslices:
- result.extend([slice(None)] * nslices)
-
+ if isinstance(item, slice):
+ have_slices = True
+ elif not PyIndex_Check(item):
+ raise TypeError, f"Cannot index with type '{type(item)}'"
+ result[idx] = item
+ idx += 1
+
+ nslices = ndim - idx
return have_slices or nslices, tuple(result)
-cdef assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim):
+cdef int assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim) except -1:
for suboffset in suboffsets[:ndim]:
if suboffset >= 0:
- raise ValueError("Indirect dimensions not supported")
+ raise ValueError, "Indirect dimensions not supported"
+ return 0 # return type just used as an error flag
#
### Slicing a memoryview
@@ -742,15 +755,16 @@ cdef memoryview memview_slice(memoryview memview, object indices):
# may not be as expected"
cdef {{memviewslice_name}} *p_dst = &dst
cdef int *p_suboffset_dim = &suboffset_dim
- cdef Py_ssize_t start, stop, step
+ cdef Py_ssize_t start, stop, step, cindex
cdef bint have_start, have_stop, have_step
for dim, index in enumerate(indices):
if PyIndex_Check(index):
+ cindex = index
slice_memviewslice(
p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim],
dim, new_ndim, p_suboffset_dim,
- index, 0, 0, # start, stop, step
+ cindex, 0, 0, # start, stop, step
0, 0, 0, # have_{start,stop,step}
False)
elif index is None:
@@ -789,22 +803,6 @@ cdef memoryview memview_slice(memoryview memview, object indices):
### Slicing in a single dimension of a memoryviewslice
#
-cdef extern from "<stdlib.h>":
- void abort() nogil
- void printf(char *s, ...) nogil
-
-cdef extern from "<stdio.h>":
- ctypedef struct FILE
- FILE *stderr
- int fputs(char *s, FILE *stream)
-
-cdef extern from "pystate.h":
- void PyThreadState_Get() nogil
-
- # These are not actually nogil, but we check for the GIL before calling them
- void PyErr_SetString(PyObject *type, char *msg) nogil
- PyObject *PyErr_Format(PyObject *exc, char *msg, ...) nogil
-
@cname('__pyx_memoryview_slice_memviewslice')
cdef int slice_memviewslice(
{{memviewslice_name}} *dst,
@@ -812,7 +810,7 @@ cdef int slice_memviewslice(
int dim, int new_ndim, int *suboffset_dim,
Py_ssize_t start, Py_ssize_t stop, Py_ssize_t step,
int have_start, int have_stop, int have_step,
- bint is_slice) nogil except -1:
+ bint is_slice) except -1 nogil:
"""
Create a new slice dst given slice src.
@@ -831,13 +829,16 @@ cdef int slice_memviewslice(
if start < 0:
start += shape
if not 0 <= start < shape:
- _err_dim(IndexError, "Index out of bounds (axis %d)", dim)
+ _err_dim(PyExc_IndexError, "Index out of bounds (axis %d)", dim)
else:
# index is a slice
- negative_step = have_step != 0 and step < 0
-
- if have_step and step == 0:
- _err_dim(ValueError, "Step may not be zero (axis %d)", dim)
+ if have_step:
+ negative_step = step < 0
+ if step == 0:
+ _err_dim(PyExc_ValueError, "Step may not be zero (axis %d)", dim)
+ else:
+ negative_step = False
+ step = 1
# check our bounds and set defaults
if have_start:
@@ -869,9 +870,6 @@ cdef int slice_memviewslice(
else:
stop = shape
- if not have_step:
- step = 1
-
# len = ceil( (stop - start) / step )
with cython.cdivision(True):
new_shape = (stop - start) // step
@@ -887,7 +885,7 @@ cdef int slice_memviewslice(
dst.shape[new_ndim] = new_shape
dst.suboffsets[new_ndim] = suboffset
- # Add the slicing or idexing offsets to the right suboffset or base data *
+ # Add the slicing or indexing offsets to the right suboffset or base data *
if suboffset_dim[0] < 0:
dst.data += start * stride
else:
@@ -898,7 +896,7 @@ cdef int slice_memviewslice(
if new_ndim == 0:
dst.data = (<char **> dst.data)[0] + suboffset
else:
- _err_dim(IndexError, "All dimensions preceding dimension %d "
+ _err_dim(PyExc_IndexError, "All dimensions preceding dimension %d "
"must be indexed and not sliced", dim)
else:
suboffset_dim[0] = new_ndim
@@ -916,7 +914,7 @@ cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index,
cdef char *resultp
if view.ndim == 0:
- shape = view.len / itemsize
+ shape = view.len // itemsize
stride = itemsize
else:
shape = view.shape[dim]
@@ -927,10 +925,10 @@ cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index,
if index < 0:
index += view.shape[dim]
if index < 0:
- raise IndexError("Out of bounds on buffer access (axis %d)" % dim)
+ raise IndexError, f"Out of bounds on buffer access (axis {dim})"
if index >= shape:
- raise IndexError("Out of bounds on buffer access (axis %d)" % dim)
+ raise IndexError, f"Out of bounds on buffer access (axis {dim})"
resultp = bufp + index * stride
if suboffset >= 0:
@@ -942,7 +940,7 @@ cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index,
### Transposing a memoryviewslice
#
@cname('__pyx_memslice_transpose')
-cdef int transpose_memslice({{memviewslice_name}} *memslice) nogil except 0:
+cdef int transpose_memslice({{memviewslice_name}} *memslice) except -1 nogil:
cdef int ndim = memslice.memview.view.ndim
cdef Py_ssize_t *shape = memslice.shape
@@ -950,19 +948,20 @@ cdef int transpose_memslice({{memviewslice_name}} *memslice) nogil except 0:
# reverse strides and shape
cdef int i, j
- for i in range(ndim / 2):
+ for i in range(ndim // 2):
j = ndim - 1 - i
strides[i], strides[j] = strides[j], strides[i]
shape[i], shape[j] = shape[j], shape[i]
if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0:
- _err(ValueError, "Cannot transpose memoryview with indirect dimensions")
+ _err(PyExc_ValueError, "Cannot transpose memoryview with indirect dimensions")
- return 1
+ return 0
#
### Creating new memoryview objects from slices and memoryviews
#
+@cython.collection_type("sequence")
@cname('__pyx_memoryviewslice')
cdef class _memoryviewslice(memoryview):
"Internal class for passing memoryview slices to Python"
@@ -976,7 +975,7 @@ cdef class _memoryviewslice(memoryview):
cdef int (*to_dtype_func)(char *, object) except 0
def __dealloc__(self):
- __PYX_XDEC_MEMVIEW(&self.from_slice, 1)
+ __PYX_XCLEAR_MEMVIEW(&self.from_slice, 1)
cdef convert_item_to_object(self, char *itemp):
if self.to_object_func != NULL:
@@ -990,12 +989,25 @@ cdef class _memoryviewslice(memoryview):
else:
memoryview.assign_item_from_object(self, itemp, value)
- @property
- def base(self):
+ cdef _get_base(self):
return self.from_object
- __pyx_getbuffer = capsule(<void *> &__pyx_memoryview_getbuffer, "getbuffer(obj, view, flags)")
+ # Sequence methods
+ try:
+ count = __pyx_collections_abc_Sequence.count
+ index = __pyx_collections_abc_Sequence.index
+ except:
+ pass
+try:
+ if __pyx_collections_abc_Sequence:
+ # The main value of registering _memoryviewslice as a
+ # Sequence is that it can be used in structural pattern
+ # matching in Python 3.10+
+ __pyx_collections_abc_Sequence.register(_memoryviewslice)
+ __pyx_collections_abc_Sequence.register(array)
+except:
+ pass # ignore failure, it's a minor issue
@cname('__pyx_memoryview_fromslice')
cdef memoryview_fromslice({{memviewslice_name}} memviewslice,
@@ -1012,12 +1024,12 @@ cdef memoryview_fromslice({{memviewslice_name}} memviewslice,
# assert 0 < ndim <= memviewslice.memview.view.ndim, (
# ndim, memviewslice.memview.view.ndim)
- result = _memoryviewslice(None, 0, dtype_is_object)
+ result = _memoryviewslice.__new__(_memoryviewslice, None, 0, dtype_is_object)
result.from_slice = memviewslice
__PYX_INC_MEMVIEW(&memviewslice, 1)
- result.from_object = (<memoryview> memviewslice.memview).base
+ result.from_object = (<memoryview> memviewslice.memview)._get_base()
result.typeinfo = memviewslice.memview.typeinfo
result.view = memviewslice.memview.view
@@ -1062,7 +1074,7 @@ cdef {{memviewslice_name}} *get_slice_from_memview(memoryview memview,
return mslice
@cname('__pyx_memoryview_slice_copy')
-cdef void slice_copy(memoryview memview, {{memviewslice_name}} *dst):
+cdef void slice_copy(memoryview memview, {{memviewslice_name}} *dst) noexcept:
cdef int dim
cdef (Py_ssize_t*) shape, strides, suboffsets
@@ -1108,14 +1120,11 @@ cdef memoryview_copy_from_slice(memoryview memview, {{memviewslice_name}} *memvi
#
### Copy the contents of a memoryview slices
#
-cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) nogil:
- if arg < 0:
- return -arg
- else:
- return arg
+cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) noexcept nogil:
+ return -arg if arg < 0 else arg
@cname('__pyx_get_best_slice_order')
-cdef char get_best_order({{memviewslice_name}} *mslice, int ndim) nogil:
+cdef char get_best_order({{memviewslice_name}} *mslice, int ndim) noexcept nogil:
"""
Figure out the best memory access order for a given slice.
"""
@@ -1142,7 +1151,7 @@ cdef char get_best_order({{memviewslice_name}} *mslice, int ndim) nogil:
cdef void _copy_strided_to_strided(char *src_data, Py_ssize_t *src_strides,
char *dst_data, Py_ssize_t *dst_strides,
Py_ssize_t *src_shape, Py_ssize_t *dst_shape,
- int ndim, size_t itemsize) nogil:
+ int ndim, size_t itemsize) noexcept nogil:
# Note: src_extent is 1 if we're broadcasting
# dst_extent always >= src_extent as we don't do reductions
cdef Py_ssize_t i
@@ -1152,14 +1161,14 @@ cdef void _copy_strided_to_strided(char *src_data, Py_ssize_t *src_strides,
cdef Py_ssize_t dst_stride = dst_strides[0]
if ndim == 1:
- if (src_stride > 0 and dst_stride > 0 and
- <size_t> src_stride == itemsize == <size_t> dst_stride):
- memcpy(dst_data, src_data, itemsize * dst_extent)
- else:
- for i in range(dst_extent):
- memcpy(dst_data, src_data, itemsize)
- src_data += src_stride
- dst_data += dst_stride
+ if (src_stride > 0 and dst_stride > 0 and
+ <size_t> src_stride == itemsize == <size_t> dst_stride):
+ memcpy(dst_data, src_data, itemsize * dst_extent)
+ else:
+ for i in range(dst_extent):
+ memcpy(dst_data, src_data, itemsize)
+ src_data += src_stride
+ dst_data += dst_stride
else:
for i in range(dst_extent):
_copy_strided_to_strided(src_data, src_strides + 1,
@@ -1171,12 +1180,12 @@ cdef void _copy_strided_to_strided(char *src_data, Py_ssize_t *src_strides,
cdef void copy_strided_to_strided({{memviewslice_name}} *src,
{{memviewslice_name}} *dst,
- int ndim, size_t itemsize) nogil:
+ int ndim, size_t itemsize) noexcept nogil:
_copy_strided_to_strided(src.data, src.strides, dst.data, dst.strides,
src.shape, dst.shape, ndim, itemsize)
@cname('__pyx_memoryview_slice_get_size')
-cdef Py_ssize_t slice_get_size({{memviewslice_name}} *src, int ndim) nogil:
+cdef Py_ssize_t slice_get_size({{memviewslice_name}} *src, int ndim) noexcept nogil:
"Return the size of the memory occupied by the slice in number of bytes"
cdef Py_ssize_t shape, size = src.memview.view.itemsize
@@ -1188,7 +1197,7 @@ cdef Py_ssize_t slice_get_size({{memviewslice_name}} *src, int ndim) nogil:
@cname('__pyx_fill_contig_strides_array')
cdef Py_ssize_t fill_contig_strides_array(
Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t stride,
- int ndim, char order) nogil:
+ int ndim, char order) noexcept nogil:
"""
Fill the strides array for a slice with C or F contiguous strides.
This is like PyBuffer_FillContiguousStrides, but compatible with py < 2.6
@@ -1210,7 +1219,7 @@ cdef Py_ssize_t fill_contig_strides_array(
cdef void *copy_data_to_temp({{memviewslice_name}} *src,
{{memviewslice_name}} *tmpslice,
char order,
- int ndim) nogil except NULL:
+ int ndim) except NULL nogil:
"""
Copy a direct slice to temporary contiguous memory. The caller should free
the result when done.
@@ -1223,7 +1232,7 @@ cdef void *copy_data_to_temp({{memviewslice_name}} *src,
result = malloc(size)
if not result:
- _err(MemoryError, NULL)
+ _err_no_memory()
# tmpslice[0] = src
tmpslice.data = <char *> result
@@ -1232,8 +1241,7 @@ cdef void *copy_data_to_temp({{memviewslice_name}} *src,
tmpslice.shape[i] = src.shape[i]
tmpslice.suboffsets[i] = -1
- fill_contig_strides_array(&tmpslice.shape[0], &tmpslice.strides[0], itemsize,
- ndim, order)
+ fill_contig_strides_array(&tmpslice.shape[0], &tmpslice.strides[0], itemsize, ndim, order)
# We need to broadcast strides again
for i in range(ndim):
@@ -1252,25 +1260,26 @@ cdef void *copy_data_to_temp({{memviewslice_name}} *src,
@cname('__pyx_memoryview_err_extents')
cdef int _err_extents(int i, Py_ssize_t extent1,
Py_ssize_t extent2) except -1 with gil:
- raise ValueError("got differing extents in dimension %d (got %d and %d)" %
- (i, extent1, extent2))
+ raise ValueError, f"got differing extents in dimension {i} (got {extent1} and {extent2})"
@cname('__pyx_memoryview_err_dim')
-cdef int _err_dim(object error, char *msg, int dim) except -1 with gil:
- raise error(msg.decode('ascii') % dim)
+cdef int _err_dim(PyObject *error, str msg, int dim) except -1 with gil:
+ raise <object>error, msg % dim
@cname('__pyx_memoryview_err')
-cdef int _err(object error, char *msg) except -1 with gil:
- if msg != NULL:
- raise error(msg.decode('ascii'))
- else:
- raise error
+cdef int _err(PyObject *error, str msg) except -1 with gil:
+ raise <object>error, msg
+
+@cname('__pyx_memoryview_err_no_memory')
+cdef int _err_no_memory() except -1 with gil:
+ raise MemoryError
+
@cname('__pyx_memoryview_copy_contents')
cdef int memoryview_copy_contents({{memviewslice_name}} src,
{{memviewslice_name}} dst,
int src_ndim, int dst_ndim,
- bint dtype_is_object) nogil except -1:
+ bint dtype_is_object) except -1 nogil:
"""
Copy memory from slice src to slice dst.
Check for overlapping memory and verify the shapes.
@@ -1299,7 +1308,7 @@ cdef int memoryview_copy_contents({{memviewslice_name}} src,
_err_extents(i, dst.shape[i], src.shape[i])
if src.suboffsets[i] >= 0:
- _err_dim(ValueError, "Dimension %d is not direct", i)
+ _err_dim(PyExc_ValueError, "Dimension %d is not direct", i)
if slices_overlap(&src, &dst, ndim, itemsize):
# slices overlap, copy to temp, copy temp to dst
@@ -1319,9 +1328,9 @@ cdef int memoryview_copy_contents({{memviewslice_name}} src,
if direct_copy:
# Contiguous slices with same order
- refcount_copying(&dst, dtype_is_object, ndim, False)
+ refcount_copying(&dst, dtype_is_object, ndim, inc=False)
memcpy(dst.data, src.data, slice_get_size(&src, ndim))
- refcount_copying(&dst, dtype_is_object, ndim, True)
+ refcount_copying(&dst, dtype_is_object, ndim, inc=True)
free(tmpdata)
return 0
@@ -1331,9 +1340,9 @@ cdef int memoryview_copy_contents({{memviewslice_name}} src,
transpose_memslice(&src)
transpose_memslice(&dst)
- refcount_copying(&dst, dtype_is_object, ndim, False)
+ refcount_copying(&dst, dtype_is_object, ndim, inc=False)
copy_strided_to_strided(&src, &dst, ndim, itemsize)
- refcount_copying(&dst, dtype_is_object, ndim, True)
+ refcount_copying(&dst, dtype_is_object, ndim, inc=True)
free(tmpdata)
return 0
@@ -1341,7 +1350,7 @@ cdef int memoryview_copy_contents({{memviewslice_name}} src,
@cname('__pyx_memoryview_broadcast_leading')
cdef void broadcast_leading({{memviewslice_name}} *mslice,
int ndim,
- int ndim_other) nogil:
+ int ndim_other) noexcept nogil:
cdef int i
cdef int offset = ndim_other - ndim
@@ -1361,24 +1370,22 @@ cdef void broadcast_leading({{memviewslice_name}} *mslice,
#
@cname('__pyx_memoryview_refcount_copying')
-cdef void refcount_copying({{memviewslice_name}} *dst, bint dtype_is_object,
- int ndim, bint inc) nogil:
- # incref or decref the objects in the destination slice if the dtype is
- # object
+cdef void refcount_copying({{memviewslice_name}} *dst, bint dtype_is_object, int ndim, bint inc) noexcept nogil:
+ # incref or decref the objects in the destination slice if the dtype is object
if dtype_is_object:
- refcount_objects_in_slice_with_gil(dst.data, dst.shape,
- dst.strides, ndim, inc)
+ refcount_objects_in_slice_with_gil(dst.data, dst.shape, dst.strides, ndim, inc)
@cname('__pyx_memoryview_refcount_objects_in_slice_with_gil')
cdef void refcount_objects_in_slice_with_gil(char *data, Py_ssize_t *shape,
Py_ssize_t *strides, int ndim,
- bint inc) with gil:
+ bint inc) noexcept with gil:
refcount_objects_in_slice(data, shape, strides, ndim, inc)
@cname('__pyx_memoryview_refcount_objects_in_slice')
cdef void refcount_objects_in_slice(char *data, Py_ssize_t *shape,
- Py_ssize_t *strides, int ndim, bint inc):
+ Py_ssize_t *strides, int ndim, bint inc) noexcept:
cdef Py_ssize_t i
+ cdef Py_ssize_t stride = strides[0]
for i in range(shape[0]):
if ndim == 1:
@@ -1387,10 +1394,9 @@ cdef void refcount_objects_in_slice(char *data, Py_ssize_t *shape,
else:
Py_DECREF((<PyObject **> data)[0])
else:
- refcount_objects_in_slice(data, shape + 1, strides + 1,
- ndim - 1, inc)
+ refcount_objects_in_slice(data, shape + 1, strides + 1, ndim - 1, inc)
- data += strides[0]
+ data += stride
#
### Scalar to slice assignment
@@ -1398,17 +1404,16 @@ cdef void refcount_objects_in_slice(char *data, Py_ssize_t *shape,
@cname('__pyx_memoryview_slice_assign_scalar')
cdef void slice_assign_scalar({{memviewslice_name}} *dst, int ndim,
size_t itemsize, void *item,
- bint dtype_is_object) nogil:
- refcount_copying(dst, dtype_is_object, ndim, False)
- _slice_assign_scalar(dst.data, dst.shape, dst.strides, ndim,
- itemsize, item)
- refcount_copying(dst, dtype_is_object, ndim, True)
+ bint dtype_is_object) noexcept nogil:
+ refcount_copying(dst, dtype_is_object, ndim, inc=False)
+ _slice_assign_scalar(dst.data, dst.shape, dst.strides, ndim, itemsize, item)
+ refcount_copying(dst, dtype_is_object, ndim, inc=True)
@cname('__pyx_memoryview__slice_assign_scalar')
cdef void _slice_assign_scalar(char *data, Py_ssize_t *shape,
Py_ssize_t *strides, int ndim,
- size_t itemsize, void *item) nogil:
+ size_t itemsize, void *item) noexcept nogil:
cdef Py_ssize_t i
cdef Py_ssize_t stride = strides[0]
cdef Py_ssize_t extent = shape[0]
@@ -1419,8 +1424,7 @@ cdef void _slice_assign_scalar(char *data, Py_ssize_t *shape,
data += stride
else:
for i in range(extent):
- _slice_assign_scalar(data, shape + 1, strides + 1,
- ndim - 1, itemsize, item)
+ _slice_assign_scalar(data, shape + 1, strides + 1, ndim - 1, itemsize, item)
data += stride
@@ -1433,27 +1437,27 @@ cdef extern from *:
__PYX_BUF_FLAGS_INTEGER_COMPLEX
ctypedef struct __Pyx_TypeInfo:
- char* name
- __Pyx_StructField* fields
- size_t size
- size_t arraysize[8]
- int ndim
- char typegroup
- char is_unsigned
- int flags
+ char* name
+ __Pyx_StructField* fields
+ size_t size
+ size_t arraysize[8]
+ int ndim
+ char typegroup
+ char is_unsigned
+ int flags
ctypedef struct __Pyx_StructField:
- __Pyx_TypeInfo* type
- char* name
- size_t offset
+ __Pyx_TypeInfo* type
+ char* name
+ size_t offset
ctypedef struct __Pyx_BufFmt_StackElem:
- __Pyx_StructField* field
- size_t parent_offset
+ __Pyx_StructField* field
+ size_t parent_offset
#ctypedef struct __Pyx_BufFmt_Context:
# __Pyx_StructField root
- __Pyx_BufFmt_StackElem* head
+ __Pyx_BufFmt_StackElem* head
struct __pyx_typeinfo_string:
char string[3]
@@ -1466,6 +1470,7 @@ cdef bytes format_from_typeinfo(__Pyx_TypeInfo *type):
cdef __Pyx_StructField *field
cdef __pyx_typeinfo_string fmt
cdef bytes part, result
+ cdef Py_ssize_t i
if type.typegroup == 'S':
assert type.fields != NULL
@@ -1487,10 +1492,9 @@ cdef bytes format_from_typeinfo(__Pyx_TypeInfo *type):
result = alignment.join(parts) + b'}'
else:
fmt = __Pyx_TypeInfoToFormat(type)
+ result = fmt.string
if type.arraysize[0]:
- extents = [unicode(type.arraysize[i]) for i in range(type.ndim)]
- result = (u"(%s)" % u','.join(extents)).encode('ascii') + fmt.string
- else:
- result = fmt.string
+ extents = [f"{type.arraysize[i]}" for i in range(type.ndim)]
+ result = f"({u','.join(extents)})".encode('ascii') + result
return result
diff --git a/Cython/Utility/MemoryView_C.c b/Cython/Utility/MemoryView_C.c
index 1b78b2a4e..774ec1767 100644
--- a/Cython/Utility/MemoryView_C.c
+++ b/Cython/Utility/MemoryView_C.c
@@ -29,8 +29,57 @@ typedef struct {
#define __PYX_CYTHON_ATOMICS_ENABLED() CYTHON_ATOMICS
#define __pyx_atomic_int_type int
+#define __pyx_nonatomic_int_type int
+
+// For standard C/C++ atomics, get the headers first so we have ATOMIC_INT_LOCK_FREE
+// defined when we decide to use them.
+#if CYTHON_ATOMICS && (defined(__STDC_VERSION__) && \
+ (__STDC_VERSION__ >= 201112L) && \
+ !defined(__STDC_NO_ATOMICS__))
+ #include <stdatomic.h>
+#elif CYTHON_ATOMICS && (defined(__cplusplus) && ( \
+ (__cplusplus >= 201103L) || \
+ (defined(_MSC_VER) && _MSC_VER >= 1700)))
+ #include <atomic>
+#endif
-#if CYTHON_ATOMICS && (__GNUC__ >= 5 || (__GNUC__ == 4 && \
+#if CYTHON_ATOMICS && (defined(__STDC_VERSION__) && \
+ (__STDC_VERSION__ >= 201112L) && \
+ !defined(__STDC_NO_ATOMICS__) && \
+ ATOMIC_INT_LOCK_FREE == 2)
+ // C11 atomics are available.
+ // Require ATOMIC_INT_LOCK_FREE because I'm nervous about the __pyx_atomic_int[2]
+ // alignment trick in MemoryView.pyx if it uses mutexes.
+ #undef __pyx_atomic_int_type
+ #define __pyx_atomic_int_type atomic_int
+ // TODO - it might be possible to use a less strict memory ordering here
+ #define __pyx_atomic_incr_aligned(value) atomic_fetch_add(value, 1)
+ #define __pyx_atomic_decr_aligned(value) atomic_fetch_sub(value, 1)
+ #if defined(__PYX_DEBUG_ATOMICS) && defined(_MSC_VER)
+ #pragma message ("Using standard C atomics")
+ #elif defined(__PYX_DEBUG_ATOMICS)
+ #warning "Using standard C atomics"
+ #endif
+#elif CYTHON_ATOMICS && (defined(__cplusplus) && ( \
+ (__cplusplus >= 201103L) || \
+ /*_MSC_VER 1700 is Visual Studio 2012 */ \
+ (defined(_MSC_VER) && _MSC_VER >= 1700)) && \
+ ATOMIC_INT_LOCK_FREE == 2)
+ // C++11 atomics are available.
+ // Require ATOMIC_INT_LOCK_FREE because I'm nervous about the __pyx_atomic_int[2]
+ // alignment trick in MemoryView.pyx if it uses mutexes.
+ #undef __pyx_atomic_int_type
+ #define __pyx_atomic_int_type std::atomic_int
+ // TODO - it might be possible to use a less strict memory ordering here
+ #define __pyx_atomic_incr_aligned(value) std::atomic_fetch_add(value, 1)
+ #define __pyx_atomic_decr_aligned(value) std::atomic_fetch_sub(value, 1)
+
+ #if defined(__PYX_DEBUG_ATOMICS) && defined(_MSC_VER)
+ #pragma message ("Using standard C++ atomics")
+ #elif defined(__PYX_DEBUG_ATOMICS)
+ #warning "Using standard C++ atomics"
+ #endif
+#elif CYTHON_ATOMICS && (__GNUC__ >= 5 || (__GNUC__ == 4 && \
(__GNUC_MINOR__ > 1 || \
(__GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ >= 2))))
/* gcc >= 4.1.2 */
@@ -40,11 +89,12 @@ typedef struct {
#ifdef __PYX_DEBUG_ATOMICS
#warning "Using GNU atomics"
#endif
-#elif CYTHON_ATOMICS && defined(_MSC_VER) && CYTHON_COMPILING_IN_NOGIL
+#elif CYTHON_ATOMICS && defined(_MSC_VER)
/* msvc */
#include <intrin.h>
#undef __pyx_atomic_int_type
#define __pyx_atomic_int_type long
+ #define __pyx_nonatomic_int_type long
#pragma intrinsic (_InterlockedExchangeAdd)
#define __pyx_atomic_incr_aligned(value) _InterlockedExchangeAdd(value, 1)
#define __pyx_atomic_decr_aligned(value) _InterlockedExchangeAdd(value, -1)
@@ -109,9 +159,9 @@ static CYTHON_INLINE int __pyx_sub_acquisition_count_locked(
#define __pyx_get_slice_count_pointer(memview) (memview->acquisition_count_aligned_p)
#define __pyx_get_slice_count(memview) (*__pyx_get_slice_count_pointer(memview))
#define __PYX_INC_MEMVIEW(slice, have_gil) __Pyx_INC_MEMVIEW(slice, have_gil, __LINE__)
-#define __PYX_XDEC_MEMVIEW(slice, have_gil) __Pyx_XDEC_MEMVIEW(slice, have_gil, __LINE__)
+#define __PYX_XCLEAR_MEMVIEW(slice, have_gil) __Pyx_XCLEAR_MEMVIEW(slice, have_gil, __LINE__)
static CYTHON_INLINE void __Pyx_INC_MEMVIEW({{memviewslice_name}} *, int, int);
-static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *, int, int);
+static CYTHON_INLINE void __Pyx_XCLEAR_MEMVIEW({{memviewslice_name}} *, int, int);
/////////////// MemviewSliceIndex.proto ///////////////
@@ -226,8 +276,9 @@ fail:
}
static int
-__pyx_check_suboffsets(Py_buffer *buf, int dim, CYTHON_UNUSED int ndim, int spec)
+__pyx_check_suboffsets(Py_buffer *buf, int dim, int ndim, int spec)
{
+ CYTHON_UNUSED_VAR(ndim);
// Todo: without PyBUF_INDIRECT we may not have suboffset information, i.e., the
// ptr may not be set to NULL but may be uninitialized?
if (spec & __Pyx_MEMVIEW_DIRECT) {
@@ -483,47 +534,49 @@ __pyx_sub_acquisition_count_locked(__pyx_atomic_int *acquisition_count,
static CYTHON_INLINE void
__Pyx_INC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil, int lineno)
{
- int first_time;
+ __pyx_nonatomic_int_type old_acquisition_count;
struct {{memview_struct_name}} *memview = memslice->memview;
- if (unlikely(!memview || (PyObject *) memview == Py_None))
- return; /* allow uninitialized memoryview assignment */
-
- if (unlikely(__pyx_get_slice_count(memview) < 0))
- __pyx_fatalerror("Acquisition count is %d (line %d)",
- __pyx_get_slice_count(memview), lineno);
-
- first_time = __pyx_add_acquisition_count(memview) == 0;
+ if (unlikely(!memview || (PyObject *) memview == Py_None)) {
+ // Allow uninitialized memoryview assignment and do not ref-count None.
+ return;
+ }
- if (unlikely(first_time)) {
- if (have_gil) {
- Py_INCREF((PyObject *) memview);
+ old_acquisition_count = __pyx_add_acquisition_count(memview);
+ if (unlikely(old_acquisition_count <= 0)) {
+ if (likely(old_acquisition_count == 0)) {
+ // First acquisition => keep the memoryview object alive.
+ if (have_gil) {
+ Py_INCREF((PyObject *) memview);
+ } else {
+ PyGILState_STATE _gilstate = PyGILState_Ensure();
+ Py_INCREF((PyObject *) memview);
+ PyGILState_Release(_gilstate);
+ }
} else {
- PyGILState_STATE _gilstate = PyGILState_Ensure();
- Py_INCREF((PyObject *) memview);
- PyGILState_Release(_gilstate);
+ __pyx_fatalerror("Acquisition count is %d (line %d)",
+ __pyx_get_slice_count(memview), lineno);
}
}
}
-static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *memslice,
+static CYTHON_INLINE void __Pyx_XCLEAR_MEMVIEW({{memviewslice_name}} *memslice,
int have_gil, int lineno) {
- int last_time;
+ __pyx_nonatomic_int_type old_acquisition_count;
struct {{memview_struct_name}} *memview = memslice->memview;
if (unlikely(!memview || (PyObject *) memview == Py_None)) {
- // we do not ref-count None
+ // Do not ref-count None.
memslice->memview = NULL;
return;
}
- if (unlikely(__pyx_get_slice_count(memview) <= 0))
- __pyx_fatalerror("Acquisition count is %d (line %d)",
- __pyx_get_slice_count(memview), lineno);
-
- last_time = __pyx_sub_acquisition_count(memview) == 1;
+ old_acquisition_count = __pyx_sub_acquisition_count(memview);
memslice->data = NULL;
-
- if (unlikely(last_time)) {
+ if (likely(old_acquisition_count > 1)) {
+ // Still other slices out there => we do not own the reference.
+ memslice->memview = NULL;
+ } else if (likely(old_acquisition_count == 1)) {
+ // Last slice => discard owned Python reference to memoryview object.
if (have_gil) {
Py_CLEAR(memslice->memview);
} else {
@@ -532,7 +585,8 @@ static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *memslice,
PyGILState_Release(_gilstate);
}
} else {
- memslice->memview = NULL;
+ __pyx_fatalerror("Acquisition count is %d (line %d)",
+ __pyx_get_slice_count(memview), lineno);
}
}
@@ -770,7 +824,7 @@ static CYTHON_INLINE PyObject *{{get_function}}(const char *itemp) {
{{if from_py_function}}
static CYTHON_INLINE int {{set_function}}(const char *itemp, PyObject *obj) {
{{dtype}} value = {{from_py_function}}(obj);
- if ({{error_condition}})
+ if (unlikely({{error_condition}}))
return 0;
*({{dtype}} *) itemp = value;
return 1;
@@ -921,7 +975,7 @@ __pyx_fill_slice_{{dtype_name}}({{type_decl}} *p, Py_ssize_t extent, Py_ssize_t
////////// FillStrided1DScalar //////////
/* Fill a slice with a scalar value. The dimension is direct and strided or contiguous */
-/* This can be used as a callback for the memoryview object to efficienty assign a scalar */
+/* This can be used as a callback for the memoryview object to efficiently assign a scalar */
/* Currently unused */
static void
__pyx_fill_slice_{{dtype_name}}({{type_decl}} *p, Py_ssize_t extent, Py_ssize_t stride,
diff --git a/Cython/Utility/ModuleSetupCode.c b/Cython/Utility/ModuleSetupCode.c
index 13bc7a8b3..cc398f6ff 100644
--- a/Cython/Utility/ModuleSetupCode.c
+++ b/Cython/Utility/ModuleSetupCode.c
@@ -1,3 +1,16 @@
+/////////////// InitLimitedAPI ///////////////
+
+#if defined(CYTHON_LIMITED_API) && 0 /* disabled: enabling Py_LIMITED_API needs more work */
+ #ifndef Py_LIMITED_API
+ #if CYTHON_LIMITED_API+0 > 0x03030000
+ #define Py_LIMITED_API CYTHON_LIMITED_API
+ #else
+ #define Py_LIMITED_API 0x03030000
+ #endif
+ #endif
+#endif
+
+
/////////////// CModulePreamble ///////////////
#include <stddef.h> /* For offsetof */
@@ -5,7 +18,7 @@
#define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
#endif
-#if !defined(WIN32) && !defined(MS_WINDOWS)
+#if !defined(_WIN32) && !defined(WIN32) && !defined(MS_WINDOWS)
#ifndef __stdcall
#define __stdcall
#endif
@@ -29,9 +42,7 @@
#ifndef HAVE_LONG_LONG
// CPython has required PY_LONG_LONG support for years, even if HAVE_LONG_LONG is not defined for us
- #if PY_VERSION_HEX >= 0x02070000
- #define HAVE_LONG_LONG
- #endif
+ #define HAVE_LONG_LONG
#endif
#ifndef PY_LONG_LONG
@@ -42,14 +53,78 @@
#define Py_HUGE_VAL HUGE_VAL
#endif
-#ifdef PYPY_VERSION
+#if defined(GRAALVM_PYTHON)
+ /* For very preliminary testing purposes. Most variables are set the same as PyPy.
+ The existence of this section does not imply that anything works or is even tested */
+ // GRAALVM_PYTHON test comes before PyPy test because GraalPython unhelpfully defines PYPY_VERSION
+ #define CYTHON_COMPILING_IN_PYPY 0
+ #define CYTHON_COMPILING_IN_CPYTHON 0
+ #define CYTHON_COMPILING_IN_LIMITED_API 0
+ #define CYTHON_COMPILING_IN_GRAAL 1
+ #define CYTHON_COMPILING_IN_NOGIL 0
+
+ #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
+ #undef CYTHON_USE_ASYNC_SLOTS
+ #define CYTHON_USE_ASYNC_SLOTS 0
+ #elif !defined(CYTHON_USE_ASYNC_SLOTS)
+ #define CYTHON_USE_ASYNC_SLOTS 1
+ #endif
+ #undef CYTHON_USE_PYLIST_INTERNALS
+ #define CYTHON_USE_PYLIST_INTERNALS 0
+ #undef CYTHON_USE_UNICODE_INTERNALS
+ #define CYTHON_USE_UNICODE_INTERNALS 0
+ #undef CYTHON_USE_UNICODE_WRITER
+ #define CYTHON_USE_UNICODE_WRITER 0
+ #undef CYTHON_USE_PYLONG_INTERNALS
+ #define CYTHON_USE_PYLONG_INTERNALS 0
+ #undef CYTHON_AVOID_BORROWED_REFS
+ #define CYTHON_AVOID_BORROWED_REFS 1
+ #undef CYTHON_ASSUME_SAFE_MACROS
+ #define CYTHON_ASSUME_SAFE_MACROS 0
+ #undef CYTHON_UNPACK_METHODS
+ #define CYTHON_UNPACK_METHODS 0
+ #undef CYTHON_FAST_THREAD_STATE
+ #define CYTHON_FAST_THREAD_STATE 0
+ #undef CYTHON_FAST_GIL
+ #define CYTHON_FAST_GIL 0
+ #undef CYTHON_METH_FASTCALL
+ #define CYTHON_METH_FASTCALL 0
+ #undef CYTHON_FAST_PYCALL
+ #define CYTHON_FAST_PYCALL 0
+ #ifndef CYTHON_PEP487_INIT_SUBCLASS
+ #define CYTHON_PEP487_INIT_SUBCLASS (PY_MAJOR_VERSION >= 3)
+ #endif
+ #undef CYTHON_PEP489_MULTI_PHASE_INIT
+ #define CYTHON_PEP489_MULTI_PHASE_INIT 1
+ #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
+ #define CYTHON_USE_DICT_VERSIONS 0
+ #undef CYTHON_USE_EXC_INFO_STACK
+ #define CYTHON_USE_EXC_INFO_STACK 0
+ #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC
+ #define CYTHON_UPDATE_DESCRIPTOR_DOC 0
+ #endif
+
+#elif defined(PYPY_VERSION)
#define CYTHON_COMPILING_IN_PYPY 1
- #define CYTHON_COMPILING_IN_PYSTON 0
#define CYTHON_COMPILING_IN_CPYTHON 0
+ #define CYTHON_COMPILING_IN_LIMITED_API 0
+ #define CYTHON_COMPILING_IN_GRAAL 0
#define CYTHON_COMPILING_IN_NOGIL 0
#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
@@ -74,14 +149,23 @@
#define CYTHON_UNPACK_METHODS 0
#undef CYTHON_FAST_THREAD_STATE
#define CYTHON_FAST_THREAD_STATE 0
+ #undef CYTHON_FAST_GIL
+ #define CYTHON_FAST_GIL 0
+ #undef CYTHON_METH_FASTCALL
+ #define CYTHON_METH_FASTCALL 0
#undef CYTHON_FAST_PYCALL
#define CYTHON_FAST_PYCALL 0
+ #ifndef CYTHON_PEP487_INIT_SUBCLASS
+ #define CYTHON_PEP487_INIT_SUBCLASS (PY_MAJOR_VERSION >= 3)
+ #endif
#if PY_VERSION_HEX < 0x03090000
#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
+ #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
@@ -92,45 +176,60 @@
#define CYTHON_UPDATE_DESCRIPTOR_DOC 0
#endif
-#elif defined(PYSTON_VERSION)
+#elif defined(CYTHON_LIMITED_API)
+ // EXPERIMENTAL !!
#define CYTHON_COMPILING_IN_PYPY 0
- #define CYTHON_COMPILING_IN_PYSTON 1
#define CYTHON_COMPILING_IN_CPYTHON 0
+ #define CYTHON_COMPILING_IN_LIMITED_API 1
+ #define CYTHON_COMPILING_IN_GRAAL 0
#define CYTHON_COMPILING_IN_NOGIL 0
- #ifndef CYTHON_USE_TYPE_SLOTS
- #define CYTHON_USE_TYPE_SLOTS 1
- #endif
+ // CYTHON_CLINE_IN_TRACEBACK is currently disabled for the Limited API
+ #undef CYTHON_CLINE_IN_TRACEBACK
+ #define CYTHON_CLINE_IN_TRACEBACK 0
+
+ #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
#define CYTHON_USE_ASYNC_SLOTS 0
#undef CYTHON_USE_PYLIST_INTERNALS
#define CYTHON_USE_PYLIST_INTERNALS 0
- #ifndef CYTHON_USE_UNICODE_INTERNALS
- #define CYTHON_USE_UNICODE_INTERNALS 1
+ #undef CYTHON_USE_UNICODE_INTERNALS
+ #define CYTHON_USE_UNICODE_INTERNALS 0
+ #ifndef CYTHON_USE_UNICODE_WRITER
+ #define CYTHON_USE_UNICODE_WRITER 0
#endif
- #undef CYTHON_USE_UNICODE_WRITER
- #define CYTHON_USE_UNICODE_WRITER 0
#undef CYTHON_USE_PYLONG_INTERNALS
#define CYTHON_USE_PYLONG_INTERNALS 0
#ifndef CYTHON_AVOID_BORROWED_REFS
#define CYTHON_AVOID_BORROWED_REFS 0
#endif
- #ifndef CYTHON_ASSUME_SAFE_MACROS
- #define CYTHON_ASSUME_SAFE_MACROS 1
- #endif
- #ifndef CYTHON_UNPACK_METHODS
- #define CYTHON_UNPACK_METHODS 1
- #endif
+ #undef CYTHON_ASSUME_SAFE_MACROS
+ #define CYTHON_ASSUME_SAFE_MACROS 0
+ #undef CYTHON_UNPACK_METHODS
+ #define CYTHON_UNPACK_METHODS 0
#undef CYTHON_FAST_THREAD_STATE
#define CYTHON_FAST_THREAD_STATE 0
+ #undef CYTHON_FAST_GIL
+ #define CYTHON_FAST_GIL 0
+ #undef CYTHON_METH_FASTCALL
+ #define CYTHON_METH_FASTCALL 0
#undef CYTHON_FAST_PYCALL
#define CYTHON_FAST_PYCALL 0
+ #ifndef CYTHON_PEP487_INIT_SUBCLASS
+ #define CYTHON_PEP487_INIT_SUBCLASS 1
+ #endif
#undef CYTHON_PEP489_MULTI_PHASE_INIT
#define CYTHON_PEP489_MULTI_PHASE_INIT 0
- #undef CYTHON_USE_TP_FINALIZE
- #define CYTHON_USE_TP_FINALIZE 0
+ #undef CYTHON_USE_MODULE_STATE
+ #define CYTHON_USE_MODULE_STATE 1
+ #ifndef CYTHON_USE_TP_FINALIZE
+ #define CYTHON_USE_TP_FINALIZE 1
+ #endif
#undef CYTHON_USE_DICT_VERSIONS
#define CYTHON_USE_DICT_VERSIONS 0
#undef CYTHON_USE_EXC_INFO_STACK
@@ -141,8 +240,9 @@
#elif defined(PY_NOGIL)
#define CYTHON_COMPILING_IN_PYPY 0
- #define CYTHON_COMPILING_IN_PYSTON 0
#define CYTHON_COMPILING_IN_CPYTHON 0
+ #define CYTHON_COMPILING_IN_LIMITED_API 0
+ #define CYTHON_COMPILING_IN_GRAAL 0
#define CYTHON_COMPILING_IN_NOGIL 1
#ifndef CYTHON_USE_TYPE_SLOTS
@@ -188,18 +288,18 @@
#else
#define CYTHON_COMPILING_IN_PYPY 0
- #define CYTHON_COMPILING_IN_PYSTON 0
#define CYTHON_COMPILING_IN_CPYTHON 1
+ #define CYTHON_COMPILING_IN_LIMITED_API 0
+ #define CYTHON_COMPILING_IN_GRAAL 0
#define CYTHON_COMPILING_IN_NOGIL 0
#ifndef CYTHON_USE_TYPE_SLOTS
#define CYTHON_USE_TYPE_SLOTS 1
#endif
- #if PY_VERSION_HEX < 0x02070000
- // looks like calling _PyType_Lookup() isn't safe in Py<=2.6/3.1
- #undef CYTHON_USE_PYTYPE_LOOKUP
- #define CYTHON_USE_PYTYPE_LOOKUP 0
- #elif !defined(CYTHON_USE_PYTYPE_LOOKUP)
+ #ifndef CYTHON_USE_TYPE_SPECS
+ #define CYTHON_USE_TYPE_SPECS 0
+ #endif
+ #ifndef CYTHON_USE_PYTYPE_LOOKUP
#define CYTHON_USE_PYTYPE_LOOKUP 1
#endif
#if PY_MAJOR_VERSION < 3
@@ -208,12 +308,8 @@
#elif !defined(CYTHON_USE_ASYNC_SLOTS)
#define CYTHON_USE_ASYNC_SLOTS 1
#endif
- #if PY_VERSION_HEX < 0x02070000
- #undef CYTHON_USE_PYLONG_INTERNALS
- #define CYTHON_USE_PYLONG_INTERNALS 0
- #elif !defined(CYTHON_USE_PYLONG_INTERNALS)
- // PyLong internals changed in Py3.12.
- #define CYTHON_USE_PYLONG_INTERNALS (PY_VERSION_HEX < 0x030C00A5)
+ #ifndef CYTHON_USE_PYLONG_INTERNALS
+ #define CYTHON_USE_PYLONG_INTERNALS 1
#endif
#ifndef CYTHON_USE_PYLIST_INTERNALS
#define CYTHON_USE_PYLIST_INTERNALS 1
@@ -238,33 +334,54 @@
#ifndef CYTHON_UNPACK_METHODS
#define CYTHON_UNPACK_METHODS 1
#endif
- #if PY_VERSION_HEX >= 0x030B00A4
- #undef CYTHON_FAST_THREAD_STATE
- #define CYTHON_FAST_THREAD_STATE 0
- #elif !defined(CYTHON_FAST_THREAD_STATE)
- #define CYTHON_FAST_THREAD_STATE 1
+ #ifndef CYTHON_FAST_THREAD_STATE
+ // CPython 3.12a6 made PyThreadState an opaque struct.
+ #define CYTHON_FAST_THREAD_STATE (PY_VERSION_HEX < 0x030C00A6)
+ #endif
+ #ifndef CYTHON_FAST_GIL
+ // Py3<3.5.2 does not support _PyThreadState_UncheckedGet().
+ // FIXME: FastGIL can probably be supported also in CPython 3.12 but needs to be adapted.
+ #define CYTHON_FAST_GIL (PY_MAJOR_VERSION < 3 || PY_VERSION_HEX >= 0x03060000 && PY_VERSION_HEX < 0x030C00A6)
+ #endif
+ #ifndef CYTHON_METH_FASTCALL
+ // CPython 3.6 introduced METH_FASTCALL but with slightly different
+ // semantics. It became stable starting from CPython 3.7.
+ #define CYTHON_METH_FASTCALL (PY_VERSION_HEX >= 0x030700A1)
#endif
#ifndef CYTHON_FAST_PYCALL
- // Python 3.11 deleted localplus argument from frame object, which is used in our
- // fast_pycall code
- // On Python 3.10 it causes issues when used while profiling/debugging
- #define CYTHON_FAST_PYCALL (PY_VERSION_HEX < 0x030A0000)
+ #define CYTHON_FAST_PYCALL 1
#endif
- #ifndef CYTHON_PEP489_MULTI_PHASE_INIT
- #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000)
+ #ifndef CYTHON_PEP487_INIT_SUBCLASS
+ #define CYTHON_PEP487_INIT_SUBCLASS 1
#endif
- #ifndef CYTHON_USE_TP_FINALIZE
- #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1)
+ #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_DICT_VERSIONS
- // The dict version field is now deprecated in Py3.12.
- #define CYTHON_USE_DICT_VERSIONS ((PY_VERSION_HEX >= 0x030600B1) && (PY_VERSION_HEX < 0x030C00A5))
+ #ifndef CYTHON_USE_MODULE_STATE
+ // EXPERIMENTAL !!
+ #define CYTHON_USE_MODULE_STATE 0
#endif
- #if PY_VERSION_HEX >= 0x030B00A4
+ #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)
+ // Python 3.12a5 deprecated "ma_version_tag"
+ #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX < 0x030C00A5)
+ #endif
+ #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 (PY_VERSION_HEX >= 0x030700A3)
+ #define CYTHON_USE_EXC_INFO_STACK 1
#endif
#ifndef CYTHON_UPDATE_DESCRIPTOR_DOC
#define CYTHON_UPDATE_DESCRIPTOR_DOC 1
@@ -275,6 +392,13 @@
#define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1)
#endif
+#if !defined(CYTHON_VECTORCALL)
+#define CYTHON_VECTORCALL (CYTHON_FAST_PYCCALL && PY_VERSION_HEX >= 0x030800B1)
+#endif
+
+/* Whether to use METH_FASTCALL with a fake backported implementation of vectorcall */
+#define CYTHON_BACKPORT_VECTORCALL (CYTHON_METH_FASTCALL && PY_VERSION_HEX < 0x030800B1)
+
#if CYTHON_USE_PYLONG_INTERNALS
#if PY_MAJOR_VERSION < 3
#include "longintrepr.h"
@@ -312,6 +436,17 @@
// unused attribute
#ifndef CYTHON_UNUSED
+ #if defined(__cplusplus)
+ /* for clang __has_cpp_attribute(maybe_unused) is true even before C++17
+ * but leads to warnings with -pedantic, since it is a C++17 feature */
+ #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
+ #if __has_cpp_attribute(maybe_unused)
+ #define CYTHON_UNUSED [[maybe_unused]]
+ #endif
+ #endif
+ #endif
+#endif
+#ifndef CYTHON_UNUSED
# if defined(__GNUC__)
# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
# define CYTHON_UNUSED __attribute__ ((__unused__))
@@ -325,14 +460,18 @@
# endif
#endif
-#ifndef CYTHON_MAYBE_UNUSED_VAR
+#ifndef CYTHON_UNUSED_VAR
# if defined(__cplusplus)
- template<class T> void CYTHON_MAYBE_UNUSED_VAR( const T& ) { }
+ template<class T> void CYTHON_UNUSED_VAR( const T& ) { }
# else
-# define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x)
+# define CYTHON_UNUSED_VAR(x) (void)(x)
# endif
#endif
+#ifndef CYTHON_MAYBE_UNUSED_VAR
+ #define CYTHON_MAYBE_UNUSED_VAR(x) CYTHON_UNUSED_VAR(x)
+#endif
+
#ifndef CYTHON_NCP_UNUSED
# if CYTHON_COMPILING_IN_CPYTHON
# define CYTHON_NCP_UNUSED
@@ -346,26 +485,50 @@
#ifdef _MSC_VER
#ifndef _MSC_STDINT_H_
#if _MSC_VER < 1300
- typedef unsigned char uint8_t;
- typedef unsigned int uint32_t;
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
#else
- typedef unsigned __int8 uint8_t;
- typedef unsigned __int32 uint32_t;
+ typedef unsigned __int8 uint8_t;
+ typedef unsigned __int16 uint16_t;
+ typedef unsigned __int32 uint32_t;
+ #endif
+ #endif
+ #if _MSC_VER < 1300
+ #ifdef _WIN64
+ typedef unsigned long long __pyx_uintptr_t;
+ #else
+ typedef unsigned int __pyx_uintptr_t;
+ #endif
+ #else
+ #ifdef _WIN64
+ typedef unsigned __int64 __pyx_uintptr_t;
+ #else
+ typedef unsigned __int32 __pyx_uintptr_t;
#endif
#endif
#else
- #include <stdint.h>
+ #include <stdint.h>
+ typedef uintptr_t __pyx_uintptr_t;
#endif
#ifndef CYTHON_FALLTHROUGH
- #if defined(__cplusplus) && __cplusplus >= 201103L
- #if __has_cpp_attribute(fallthrough)
- #define CYTHON_FALLTHROUGH [[fallthrough]]
- #elif __has_cpp_attribute(clang::fallthrough)
- #define CYTHON_FALLTHROUGH [[clang::fallthrough]]
- #elif __has_cpp_attribute(gnu::fallthrough)
- #define CYTHON_FALLTHROUGH [[gnu::fallthrough]]
+ #if defined(__cplusplus)
+ /* for clang __has_cpp_attribute(fallthrough) is true even before C++17
+ * but leads to warnings with -pedantic, since it is a C++17 feature */
+ #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
+ #if __has_cpp_attribute(fallthrough)
+ #define CYTHON_FALLTHROUGH [[fallthrough]]
+ #endif
+ #endif
+
+ #ifndef CYTHON_FALLTHROUGH
+ #if __has_cpp_attribute(clang::fallthrough)
+ #define CYTHON_FALLTHROUGH [[clang::fallthrough]]
+ #elif __has_cpp_attribute(gnu::fallthrough)
+ #define CYTHON_FALLTHROUGH [[gnu::fallthrough]]
+ #endif
#endif
#endif
@@ -377,7 +540,7 @@
#endif
#endif
- #if defined(__clang__ ) && defined(__apple_build_version__)
+ #if defined(__clang__) && defined(__apple_build_version__)
#if __apple_build_version__ < 7000000 /* Xcode < 7.0 */
#undef CYTHON_FALLTHROUGH
#define CYTHON_FALLTHROUGH
@@ -385,6 +548,27 @@
#endif
#endif
+#ifdef __cplusplus
+ template <typename T>
+ struct __PYX_IS_UNSIGNED_IMPL {static const bool value = T(0) < T(-1);};
+ #define __PYX_IS_UNSIGNED(type) (__PYX_IS_UNSIGNED_IMPL<type>::value)
+#else
+ #define __PYX_IS_UNSIGNED(type) (((type)-1) > 0)
+#endif
+
+#if CYTHON_COMPILING_IN_PYPY == 1
+ #define __PYX_NEED_TP_PRINT_SLOT (PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x030A0000)
+#else
+ #define __PYX_NEED_TP_PRINT_SLOT (PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000)
+#endif
+// reinterpret
+
+// TODO: refactor existing code to use those macros
+#define __PYX_REINTERPRET_FUNCION(func_pointer, other_pointer) ((func_pointer)(void(*)(void))(other_pointer))
+// #define __PYX_REINTERPRET_POINTER(pointer_type, pointer) ((pointer_type)(void *)(pointer))
+// #define __PYX_RUNTIME_REINTERPRET(type, var) (*(type *)(&var))
+
+
/////////////// CInitCode ///////////////
// inline attribute
@@ -418,7 +602,7 @@
#endif
#endif
-// Work around clang bug http://stackoverflow.com/questions/21847816/c-invoke-nested-template-class-destructor
+// Work around clang bug https://stackoverflow.com/questions/21847816/c-invoke-nested-template-class-destructor
template<typename T>
void __Pyx_call_destructor(T& x) {
x.~T();
@@ -436,8 +620,10 @@ class __Pyx_FakeReference {
T *operator&() { return ptr; }
operator T&() { return *ptr; }
// TODO(robertwb): Delegate all operators (or auto-generate unwrapping code where needed).
- template<typename U> bool operator ==(U other) { return *ptr == other; }
- template<typename U> bool operator !=(U other) { return *ptr != other; }
+ template<typename U> bool operator ==(const U& other) const { return *ptr == other; }
+ template<typename U> bool operator !=(const U& other) const { return *ptr != other; }
+ template<typename U> bool operator==(const __Pyx_FakeReference<U>& other) const { return *ptr == *other.ptr; }
+ template<typename U> bool operator!=(const __Pyx_FakeReference<U>& other) const { return *ptr != *other.ptr; }
private:
T *ptr;
};
@@ -445,33 +631,29 @@ class __Pyx_FakeReference {
/////////////// PythonCompatibility ///////////////
-#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag)
- #define Py_OptimizeFlag 0
-#endif
-
#define __PYX_BUILD_PY_SSIZE_T "n"
#define CYTHON_FORMAT_SSIZE_T "z"
#if PY_MAJOR_VERSION < 3
#define __Pyx_BUILTIN_MODULE_NAME "__builtin__"
- #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
- PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
#define __Pyx_DefaultClassType PyClass_Type
+ #define __Pyx_PyCode_New(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
+ PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
#else
#define __Pyx_BUILTIN_MODULE_NAME "builtins"
#define __Pyx_DefaultClassType PyType_Type
#if PY_VERSION_HEX >= 0x030B00A1
- static CYTHON_INLINE PyCodeObject* __Pyx_PyCode_New(int a, int k, int l, int s, int f,
+ static CYTHON_INLINE PyCodeObject* __Pyx_PyCode_New(int a, int p, int k, int l, int s, int f,
PyObject *code, PyObject *c, PyObject* n, PyObject *v,
PyObject *fv, PyObject *cell, PyObject* fn,
PyObject *name, int fline, PyObject *lnos) {
// TODO - currently written to be simple and work in limited API etc.
// A more optimized version would be good
PyObject *kwds=NULL, *argcount=NULL, *posonlyargcount=NULL, *kwonlyargcount=NULL;
- PyObject *nlocals=NULL, *stacksize=NULL, *flags=NULL, *replace=NULL, *call_result=NULL, *empty=NULL;
+ PyObject *nlocals=NULL, *stacksize=NULL, *flags=NULL, *replace=NULL, *empty=NULL;
const char *fn_cstr=NULL;
const char *name_cstr=NULL;
- PyCodeObject* co=NULL;
+ PyCodeObject *co=NULL, *result=NULL;
PyObject *type, *value, *traceback;
// we must be able to call this while an exception is happening - thus clear then restore the state
@@ -480,7 +662,7 @@ class __Pyx_FakeReference {
if (!(kwds=PyDict_New())) goto end;
if (!(argcount=PyLong_FromLong(a))) goto end;
if (PyDict_SetItemString(kwds, "co_argcount", argcount) != 0) goto end;
- if (!(posonlyargcount=PyLong_FromLong(0))) goto end;
+ if (!(posonlyargcount=PyLong_FromLong(p))) goto end;
if (PyDict_SetItemString(kwds, "co_posonlyargcount", posonlyargcount) != 0) goto end;
if (!(kwonlyargcount=PyLong_FromLong(k))) goto end;
if (PyDict_SetItemString(kwds, "co_kwonlyargcount", kwonlyargcount) != 0) goto end;
@@ -502,20 +684,14 @@ class __Pyx_FakeReference {
if (!(name_cstr=PyUnicode_AsUTF8AndSize(name, NULL))) goto end;
if (!(co = PyCode_NewEmpty(fn_cstr, name_cstr, fline))) goto end;
- if (!(replace = PyObject_GetAttrString((PyObject*)co, "replace"))) goto cleanup_code_too;
- if (!(empty = PyTuple_New(0))) goto cleanup_code_too; // unfortunately __pyx_empty_tuple isn't available here
- if (!(call_result = PyObject_Call(replace, empty, kwds))) goto cleanup_code_too;
+ if (!(replace = PyObject_GetAttrString((PyObject*)co, "replace"))) goto end;
+ // unfortunately, __pyx_empty_tuple isn't available here
+ if (!(empty = PyTuple_New(0))) goto end;
- Py_XDECREF((PyObject*)co);
- co = (PyCodeObject*)call_result;
- call_result = NULL;
+ result = (PyCodeObject*) PyObject_Call(replace, empty, kwds);
- if (0) {
- cleanup_code_too:
- Py_XDECREF((PyObject*)co);
- co = NULL;
- }
- end:
+ end:
+ Py_XDECREF((PyObject*) co);
Py_XDECREF(kwds);
Py_XDECREF(argcount);
Py_XDECREF(posonlyargcount);
@@ -523,18 +699,55 @@ class __Pyx_FakeReference {
Py_XDECREF(nlocals);
Py_XDECREF(stacksize);
Py_XDECREF(replace);
- Py_XDECREF(call_result);
Py_XDECREF(empty);
if (type) {
PyErr_Restore(type, value, traceback);
}
- return co;
+ return result;
}
+#elif PY_VERSION_HEX >= 0x030800B2 && !CYTHON_COMPILING_IN_PYPY
+
+ #define __Pyx_PyCode_New(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
+ PyCode_NewWithPosOnlyArgs(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
#else
- #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
+ #define __Pyx_PyCode_New(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
#endif
- #define __Pyx_DefaultClassType PyType_Type
+#endif
+
+#if PY_VERSION_HEX >= 0x030900A4 || defined(Py_IS_TYPE)
+ #define __Pyx_IS_TYPE(ob, type) Py_IS_TYPE(ob, type)
+#else
+ #define __Pyx_IS_TYPE(ob, type) (((const PyObject*)ob)->ob_type == (type))
+#endif
+
+#if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_Is)
+ #define __Pyx_Py_Is(x, y) Py_Is(x, y)
+#else
+ #define __Pyx_Py_Is(x, y) ((x) == (y))
+#endif
+#if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_IsNone)
+ #define __Pyx_Py_IsNone(ob) Py_IsNone(ob)
+#else
+ #define __Pyx_Py_IsNone(ob) __Pyx_Py_Is((ob), Py_None)
+#endif
+#if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_IsTrue)
+ #define __Pyx_Py_IsTrue(ob) Py_IsTrue(ob)
+#else
+ #define __Pyx_Py_IsTrue(ob) __Pyx_Py_Is((ob), Py_True)
+#endif
+#if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_IsFalse)
+ #define __Pyx_Py_IsFalse(ob) Py_IsFalse(ob)
+#else
+ #define __Pyx_Py_IsFalse(ob) __Pyx_Py_Is((ob), Py_False)
+#endif
+#define __Pyx_NoneAsNull(obj) (__Pyx_Py_IsNone(obj) ? NULL : (obj))
+
+#ifndef CO_COROUTINE
+ #define CO_COROUTINE 0x80
+#endif
+#ifndef CO_ASYNC_GENERATOR
+ #define CO_ASYNC_GENERATOR 0x200
#endif
#ifndef Py_TPFLAGS_CHECKTYPES
@@ -549,6 +762,12 @@ class __Pyx_FakeReference {
#ifndef Py_TPFLAGS_HAVE_FINALIZE
#define Py_TPFLAGS_HAVE_FINALIZE 0
#endif
+#ifndef Py_TPFLAGS_SEQUENCE
+ #define Py_TPFLAGS_SEQUENCE 0
+#endif
+#ifndef Py_TPFLAGS_MAPPING
+ #define Py_TPFLAGS_MAPPING 0
+#endif
#ifndef METH_STACKLESS
// already defined for Stackless Python (all versions) and C-Python >= 3.7
@@ -572,11 +791,41 @@ class __Pyx_FakeReference {
#define __Pyx_PyCFunctionFast _PyCFunctionFast
#define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords
#endif
-#if CYTHON_FAST_PYCCALL
-#define __Pyx_PyFastCFunction_Check(func) \
- ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS)))))
+
+#if CYTHON_METH_FASTCALL
+ #define __Pyx_METH_FASTCALL METH_FASTCALL
+ #define __Pyx_PyCFunction_FastCall __Pyx_PyCFunctionFast
+ #define __Pyx_PyCFunction_FastCallWithKeywords __Pyx_PyCFunctionFastWithKeywords
+#else
+ #define __Pyx_METH_FASTCALL METH_VARARGS
+ #define __Pyx_PyCFunction_FastCall PyCFunction
+ #define __Pyx_PyCFunction_FastCallWithKeywords PyCFunctionWithKeywords
+#endif
+
+#if CYTHON_VECTORCALL
+ #define __pyx_vectorcallfunc vectorcallfunc
+ #define __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET PY_VECTORCALL_ARGUMENTS_OFFSET
+ #define __Pyx_PyVectorcall_NARGS(n) PyVectorcall_NARGS((size_t)(n))
+#elif CYTHON_BACKPORT_VECTORCALL
+ typedef PyObject *(*__pyx_vectorcallfunc)(PyObject *callable, PyObject *const *args,
+ size_t nargsf, PyObject *kwnames);
+ #define __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET ((size_t)1 << (8 * sizeof(size_t) - 1))
+ #define __Pyx_PyVectorcall_NARGS(n) ((Py_ssize_t)(((size_t)(n)) & ~__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET))
+#else
+ #define __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET 0
+ #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_PyFastCFunction_Check(func) 0
+ #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)
@@ -585,22 +834,17 @@ class __Pyx_FakeReference {
#define PyObject_Realloc(p) PyMem_Realloc(p)
#endif
-#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1
- #define PyMem_RawMalloc(n) PyMem_Malloc(n)
- #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n)
- #define PyMem_RawFree(p) PyMem_Free(p)
-#endif
-
-#if CYTHON_COMPILING_IN_PYSTON
- // special C-API functions only in Pyston
- #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co)
- #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno)
+#if CYTHON_COMPILING_IN_LIMITED_API
+ #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0)
+ #define __Pyx_PyFrame_SetLineNumber(frame, lineno)
#else
#define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0)
#define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno)
#endif
-#if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000
+#if CYTHON_COMPILING_IN_LIMITED_API
+ #define __Pyx_PyThreadState_Current PyThreadState_Get()
+#elif !CYTHON_FAST_THREAD_STATE
#define __Pyx_PyThreadState_Current PyThreadState_GET()
#elif PY_VERSION_HEX >= 0x03060000
//#elif PY_VERSION_HEX >= 0x03050200
@@ -612,6 +856,25 @@ class __Pyx_FakeReference {
#define __Pyx_PyThreadState_Current _PyThreadState_Current
#endif
+#if CYTHON_COMPILING_IN_LIMITED_API
+static CYTHON_INLINE void *__Pyx_PyModule_GetState(PyObject *op)
+{
+ void *result;
+
+ result = PyModule_GetState(op);
+ if (!result)
+ Py_FatalError("Couldn't find the module state");
+ return result;
+}
+#endif
+
+#define __Pyx_PyObject_GetSlot(obj, name, func_ctype) __Pyx_PyType_GetSlot(Py_TYPE(obj), name, func_ctype)
+#if CYTHON_COMPILING_IN_LIMITED_API
+ #define __Pyx_PyType_GetSlot(type, name, func_ctype) ((func_ctype) PyType_GetSlot((type), Py_##name))
+#else
+ #define __Pyx_PyType_GetSlot(type, name, func_ctype) ((type)->name)
+#endif
+
// TSS (Thread Specific Storage) API
#if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT)
#include "pythread.h"
@@ -642,10 +905,40 @@ static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) {
static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
return PyThread_get_key_value(*key);
}
-// PyThread_delete_key_value(key) is equalivalent to PyThread_set_key_value(key, NULL)
+// PyThread_delete_key_value(key) is equivalent to PyThread_set_key_value(key, NULL)
// PyThread_ReInitTLS() is a no-op
#endif /* TSS (Thread Specific Storage) API */
+
+#if PY_MAJOR_VERSION < 3
+ #if CYTHON_COMPILING_IN_PYPY
+ #if PYPY_VERSION_NUM < 0x07030600
+ #if defined(__cplusplus) && __cplusplus >= 201402L
+ [[deprecated("`with nogil:` inside a nogil function will not release the GIL in PyPy2 < 7.3.6")]]
+ #elif defined(__GNUC__) || defined(__clang__)
+ __attribute__ ((__deprecated__("`with nogil:` inside a nogil function will not release the GIL in PyPy2 < 7.3.6")))
+ #elif defined(_MSC_VER)
+ __declspec(deprecated("`with nogil:` inside a nogil function will not release the GIL in PyPy2 < 7.3.6"))
+ #endif
+ static CYTHON_INLINE int PyGILState_Check(void) {
+ // PyGILState_Check is used to decide whether to release the GIL when we don't
+ // know that we have it. For PyPy2 it isn't possible to check.
+ // Therefore assume that we don't have the GIL (which causes us not to release it,
+ // but is "safe")
+ return 0;
+ }
+ #else // PYPY_VERSION_NUM < 0x07030600
+ // PyPy2 >= 7.3.6 has PyGILState_Check
+ #endif // PYPY_VERSION_NUM < 0x07030600
+ #else
+ // https://stackoverflow.com/a/25666624
+ static CYTHON_INLINE int PyGILState_Check(void) {
+ PyThreadState * tstate = _PyThreadState_Current;
+ return tstate && (tstate == PyGILState_GetThisThreadState());
+ }
+ #endif
+#endif
+
#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized)
#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n))
#else
@@ -660,14 +953,85 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
#define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y)
#endif
-#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS
-#define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash)
+#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX > 0x030600B4 && CYTHON_USE_UNICODE_INTERNALS
+// _PyDict_GetItem_KnownHash() exists since CPython 3.5, but it was
+// dropping exceptions. Since 3.6, exceptions are kept.
+#define __Pyx_PyDict_GetItemStrWithError(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash)
+static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStr(PyObject *dict, PyObject *name) {
+ PyObject *res = __Pyx_PyDict_GetItemStrWithError(dict, name);
+ if (res == NULL) PyErr_Clear();
+ return res;
+}
+#elif PY_MAJOR_VERSION >= 3 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07020000)
+#define __Pyx_PyDict_GetItemStrWithError PyDict_GetItemWithError
+#define __Pyx_PyDict_GetItemStr PyDict_GetItem
+#else
+static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStrWithError(PyObject *dict, PyObject *name) {
+ // This is tricky - we should return a borrowed reference but not swallow non-KeyError exceptions. 8-|
+ // But: this function is only used in Py2 and older PyPys,
+ // and currently only for argument parsing and other non-correctness-critical lookups
+ // and we know that 'name' is an interned 'str' with pre-calculated hash value (only comparisons can fail),
+ // thus, performance matters more than correctness here, especially in the "not found" case.
+#if CYTHON_COMPILING_IN_PYPY
+ // So we ignore any exceptions in old PyPys ...
+ return PyDict_GetItem(dict, name);
#else
-#define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name)
+ // and hack together a stripped-down and modified PyDict_GetItem() in CPython 2.
+ PyDictEntry *ep;
+ PyDictObject *mp = (PyDictObject*) dict;
+ long hash = ((PyStringObject *) name)->ob_shash;
+ assert(hash != -1); /* hash values of interned strings are always initialised */
+ ep = (mp->ma_lookup)(mp, name, hash);
+ if (ep == NULL) {
+ // error occurred
+ return NULL;
+ }
+ // found or not found
+ return ep->me_value;
+#endif
+}
+#define __Pyx_PyDict_GetItemStr PyDict_GetItem
#endif
-/* new Py3.3 unicode type (PEP 393) */
-#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND)
+/* Type slots */
+
+#if CYTHON_USE_TYPE_SLOTS
+ #define __Pyx_PyType_GetFlags(tp) (((PyTypeObject *)tp)->tp_flags)
+ #define __Pyx_PyType_HasFeature(type, feature) ((__Pyx_PyType_GetFlags(type) & (feature)) != 0)
+ #define __Pyx_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)
+ #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GetLength(u)
+ #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_ReadChar(u, i)
+ #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((void)u, 1114111U)
+ #define __Pyx_PyUnicode_KIND(u) ((void)u, (0))
+ // __Pyx_PyUnicode_DATA() and __Pyx_PyUnicode_READ() must go together, e.g. for iteration.
+ #define __Pyx_PyUnicode_DATA(u) ((void*)u)
+ #define __Pyx_PyUnicode_READ(k, d, i) ((void)k, PyUnicode_ReadChar((PyObject*)(d), i))
+ //#define __Pyx_PyUnicode_WRITE(k, d, i, ch) /* not available */
+ #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GetLength(u))
+#elif PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND)
+ /* new Py3.3 unicode type (PEP 393) */
#define CYTHON_PEP393_ENABLED 1
#if PY_VERSION_HEX >= 0x030C0000
@@ -681,7 +1045,7 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
#define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u)
#define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i)
#define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u)
- #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u)
+ #define __Pyx_PyUnicode_KIND(u) ((int)PyUnicode_KIND(u))
#define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u)
#define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i)
#define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch)
@@ -704,10 +1068,10 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
#define __Pyx_PyUnicode_READY(op) (0)
#define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u)
#define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i]))
- #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111)
- #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE))
+ #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535U : 1114111U)
+ #define __Pyx_PyUnicode_KIND(u) ((int)sizeof(Py_UNICODE))
#define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u))
- /* (void)(k) => avoid unused variable warning due to macro: */
+ // (void)(k) => avoid unused variable warning due to macro:
#define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i]))
#define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch)
#define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u))
@@ -722,16 +1086,20 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b))
#endif
-#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains)
- #define PyUnicode_Contains(u, s) PySequence_Contains(u, s)
-#endif
-
-#if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check)
- #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type)
-#endif
-
-#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format)
- #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt)
+#if CYTHON_COMPILING_IN_PYPY
+ #if !defined(PyUnicode_DecodeUnicodeEscape)
+ #define PyUnicode_DecodeUnicodeEscape(s, size, errors) PyUnicode_Decode(s, size, "unicode_escape", errors)
+ #endif
+ #if !defined(PyUnicode_Contains) || (PY_MAJOR_VERSION == 2 && PYPY_VERSION_NUM < 0x07030500)
+ #undef PyUnicode_Contains
+ #define PyUnicode_Contains(u, s) PySequence_Contains(u, s)
+ #endif
+ #if !defined(PyByteArray_Check)
+ #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type)
+ #endif
+ #if !defined(PyObject_Format)
+ #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt)
+ #endif
#endif
// ("..." % x) must call PyNumber_Remainder() if x is a string subclass that implements "__rmod__()".
@@ -768,10 +1136,16 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
#define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj))
#endif
-#ifndef PySet_CheckExact
- #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type)
+#if CYTHON_COMPILING_IN_CPYTHON
+ #define __Pyx_PySequence_ListKeepNew(obj) \
+ (likely(PyList_CheckExact(obj) && Py_REFCNT(obj) == 1) ? __Pyx_NewRef(obj) : PySequence_List(obj))
+#else
+ #define __Pyx_PySequence_ListKeepNew(obj) PySequence_List(obj)
#endif
+#ifndef PySet_CheckExact
+ #define PySet_CheckExact(obj) __Pyx_IS_TYPE(obj, &PySet_Type)
+#endif
#if PY_VERSION_HEX >= 0x030900A4
#define __Pyx_SET_REFCNT(obj, refcnt) Py_SET_REFCNT(obj, refcnt)
@@ -793,6 +1167,8 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
#define PyInt_Type PyLong_Type
#define PyInt_Check(op) PyLong_Check(op)
#define PyInt_CheckExact(op) PyLong_CheckExact(op)
+ #define __Pyx_Py3Int_Check(op) PyLong_Check(op)
+ #define __Pyx_Py3Int_CheckExact(op) PyLong_CheckExact(op)
#define PyInt_FromString PyLong_FromString
#define PyInt_FromUnicode PyLong_FromUnicode
#define PyInt_FromLong PyLong_FromLong
@@ -804,6 +1180,9 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
#define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask
#define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask
#define PyNumber_Int PyNumber_Long
+#else
+ #define __Pyx_Py3Int_Check(op) (PyLong_Check(op) || PyInt_Check(op))
+ #define __Pyx_Py3Int_CheckExact(op) (PyLong_CheckExact(op) || PyInt_CheckExact(op))
#endif
#if PY_MAJOR_VERSION >= 3
@@ -825,12 +1204,6 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
#define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsSsize_t
#endif
-#if PY_MAJOR_VERSION >= 3
- #define __Pyx_PyMethod_New(func, self, klass) ((self) ? ((void)(klass), PyMethod_New(func, self)) : __Pyx_NewRef(func))
-#else
- #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass)
-#endif
-
// backport of PyAsyncMethods from Py3.5 to older Py3.x versions
// (mis-)using the "tp_reserved" type slot which is re-activated as "tp_as_async" in Py3.5
#if CYTHON_USE_ASYNC_SLOTS
@@ -852,6 +1225,11 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
#endif
+/////////////// IncludeStructmemberH.proto ///////////////
+
+#include <structmember.h>
+
+
/////////////// SmallCodeConfig.proto ///////////////
#ifndef CYTHON_SMALL_CODE
@@ -892,14 +1270,18 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
#if CYTHON_COMPILING_IN_CPYTHON
#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type)
+#define __Pyx_TypeCheck2(obj, type1, type2) __Pyx_IsAnySubtype2(Py_TYPE(obj), (PyTypeObject *)type1, (PyTypeObject *)type2)
static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b);/*proto*/
+static CYTHON_INLINE int __Pyx_IsAnySubtype2(PyTypeObject *cls, PyTypeObject *a, PyTypeObject *b);/*proto*/
static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type);/*proto*/
static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2);/*proto*/
#else
#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type)
+#define __Pyx_TypeCheck2(obj, type1, type2) (PyObject_TypeCheck(obj, (PyTypeObject *)type1) || PyObject_TypeCheck(obj, (PyTypeObject *)type2))
#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type)
#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2))
#endif
+#define __Pyx_PyErr_ExceptionMatches2(err1, err2) __Pyx_PyErr_GivenExceptionMatches2(__Pyx_PyErr_Occurred(), err1, err2)
#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception)
@@ -910,7 +1292,7 @@ static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObj
#if CYTHON_COMPILING_IN_CPYTHON
static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) {
while (a) {
- a = a->tp_base;
+ a = __Pyx_PyType_GetSlot(a, tp_base, PyTypeObject*);
if (a == b)
return 1;
}
@@ -934,6 +1316,24 @@ static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) {
return __Pyx_InBases(a, b);
}
+static CYTHON_INLINE int __Pyx_IsAnySubtype2(PyTypeObject *cls, PyTypeObject *a, PyTypeObject *b) {
+ PyObject *mro;
+ if (cls == a || cls == b) return 1;
+ mro = cls->tp_mro;
+ if (likely(mro)) {
+ Py_ssize_t i, n;
+ n = PyTuple_GET_SIZE(mro);
+ for (i = 0; i < n; i++) {
+ PyObject *base = PyTuple_GET_ITEM(mro, i);
+ if (base == (PyObject *)a || base == (PyObject *)b)
+ return 1;
+ }
+ return 0;
+ }
+ // should only get here for incompletely initialised types, i.e. never under normal usage patterns
+ return __Pyx_InBases(cls, a) || __Pyx_InBases(cls, b);
+}
+
#if PY_MAJOR_VERSION == 2
static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) {
@@ -964,11 +1364,11 @@ static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc
}
#else
static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) {
- int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0;
- if (!res) {
- res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2);
+ if (exc_type1) {
+ return __Pyx_IsAnySubtype2((PyTypeObject*)err, (PyTypeObject*)exc_type1, (PyTypeObject*)exc_type2);
+ } else {
+ return __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2);
}
- return res;
}
#endif
@@ -1105,12 +1505,21 @@ static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) {
return 0;
}
-static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) {
+#if CYTHON_COMPILING_IN_LIMITED_API
+static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *module, const char* from_name, const char* to_name, int allow_none)
+#else
+static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none)
+#endif
+{
PyObject *value = PyObject_GetAttrString(spec, from_name);
int result = 0;
if (likely(value)) {
if (allow_none || value != Py_None) {
+#if CYTHON_COMPILING_IN_LIMITED_API
+ result = PyModule_AddObject(module, to_name, value);
+#else
result = PyDict_SetItemString(moddict, to_name, value);
+#endif
}
Py_DECREF(value);
} else if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
@@ -1121,8 +1530,9 @@ static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject
return result;
}
-static CYTHON_SMALL_CODE PyObject* ${pymodule_create_func_cname}(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) {
+static CYTHON_SMALL_CODE PyObject* ${pymodule_create_func_cname}(PyObject *spec, PyModuleDef *def) {
PyObject *module = NULL, *moddict, *modname;
+ CYTHON_UNUSED_VAR(def);
// For now, we only have exactly one module instance.
if (__Pyx_check_single_interpreter())
@@ -1137,9 +1547,13 @@ static CYTHON_SMALL_CODE PyObject* ${pymodule_create_func_cname}(PyObject *spec,
Py_DECREF(modname);
if (unlikely(!module)) goto bad;
+#if CYTHON_COMPILING_IN_LIMITED_API
+ moddict = module;
+#else
moddict = PyModule_GetDict(module);
if (unlikely(!moddict)) goto bad;
// moddict is a borrowed reference
+#endif
if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad;
if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad;
@@ -1156,6 +1570,7 @@ bad:
/////////////// CodeObjectCache.proto ///////////////
+#if !CYTHON_COMPILING_IN_LIMITED_API
typedef struct {
PyCodeObject* code_object;
int code_line;
@@ -1172,11 +1587,13 @@ static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL};
static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line);
static PyCodeObject *__pyx_find_code_object(int code_line);
static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object);
+#endif
/////////////// CodeObjectCache ///////////////
// Note that errors are simply ignored in the code below.
// This is just a cache, if a lookup or insertion fails - so what?
+#if !CYTHON_COMPILING_IN_LIMITED_API
static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) {
int start = 0, mid = 0, end = count - 1;
if (end >= 0 && code_line > entries[end].code_line) {
@@ -1257,9 +1674,11 @@ static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) {
__pyx_code_cache.count++;
Py_INCREF(code_object);
}
+#endif
/////////////// CodeObjectCache.cleanup ///////////////
+ #if !CYTHON_COMPILING_IN_LIMITED_API
if (__pyx_code_cache.entries) {
__Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries;
int i, count = __pyx_code_cache.count;
@@ -1271,6 +1690,7 @@ static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) {
}
PyMem_Free(entries);
}
+ #endif
/////////////// CheckBinaryVersion.proto ///////////////
@@ -1311,7 +1731,7 @@ static int __Pyx_check_binary_version(void) {
rtversion[i] = rt_from_call[i];
}
PyOS_snprintf(message, sizeof(message),
- "compiletime version %s of module '%.100s' "
+ "compile time version %s of module '%.100s' "
"does not match runtime version %s",
ctversion, __Pyx_MODULE_NAME, rtversion);
return PyErr_WarnEx(NULL, message, 1);
@@ -1343,11 +1763,11 @@ static CYTHON_INLINE int __Pyx_Is_Little_Endian(void)
#if CYTHON_REFNANNY
typedef struct {
- void (*INCREF)(void*, PyObject*, int);
- void (*DECREF)(void*, PyObject*, int);
- void (*GOTREF)(void*, PyObject*, int);
- void (*GIVEREF)(void*, PyObject*, int);
- void* (*SetupContext)(const char*, int, const char*);
+ void (*INCREF)(void*, PyObject*, Py_ssize_t);
+ void (*DECREF)(void*, PyObject*, Py_ssize_t);
+ void (*GOTREF)(void*, PyObject*, Py_ssize_t);
+ void (*GIVEREF)(void*, PyObject*, Py_ssize_t);
+ void* (*SetupContext)(const char*, Py_ssize_t, const char*);
void (*FinishContext)(void**);
} __Pyx_RefNannyAPIStruct;
static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL;
@@ -1357,28 +1777,40 @@ static CYTHON_INLINE int __Pyx_Is_Little_Endian(void)
#define __Pyx_RefNannySetupContext(name, acquire_gil) \
if (acquire_gil) { \
PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); \
- __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
+ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), (__LINE__), (__FILE__)); \
PyGILState_Release(__pyx_gilstate_save); \
} else { \
- __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
+ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), (__LINE__), (__FILE__)); \
+ }
+ #define __Pyx_RefNannyFinishContextNogil() { \
+ PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); \
+ __Pyx_RefNannyFinishContext(); \
+ PyGILState_Release(__pyx_gilstate_save); \
}
#else
#define __Pyx_RefNannySetupContext(name, acquire_gil) \
- __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
+ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), (__LINE__), (__FILE__))
+ #define __Pyx_RefNannyFinishContextNogil() __Pyx_RefNannyFinishContext()
#endif
+ #define __Pyx_RefNannyFinishContextNogil() { \
+ PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); \
+ __Pyx_RefNannyFinishContext(); \
+ PyGILState_Release(__pyx_gilstate_save); \
+ }
#define __Pyx_RefNannyFinishContext() \
__Pyx_RefNanny->FinishContext(&__pyx_refnanny)
- #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
- #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
- #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
- #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
- #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0)
- #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0)
- #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0)
- #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0)
+ #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), (__LINE__))
+ #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), (__LINE__))
+ #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), (__LINE__))
+ #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), (__LINE__))
+ #define __Pyx_XINCREF(r) do { if((r) == NULL); else {__Pyx_INCREF(r); }} while(0)
+ #define __Pyx_XDECREF(r) do { if((r) == NULL); else {__Pyx_DECREF(r); }} while(0)
+ #define __Pyx_XGOTREF(r) do { if((r) == NULL); else {__Pyx_GOTREF(r); }} while(0)
+ #define __Pyx_XGIVEREF(r) do { if((r) == NULL); else {__Pyx_GIVEREF(r);}} while(0)
#else
#define __Pyx_RefNannyDeclarations
#define __Pyx_RefNannySetupContext(name, acquire_gil)
+ #define __Pyx_RefNannyFinishContextNogil()
#define __Pyx_RefNannyFinishContext()
#define __Pyx_INCREF(r) Py_INCREF(r)
#define __Pyx_DECREF(r) Py_DECREF(r)
@@ -1390,6 +1822,10 @@ static CYTHON_INLINE int __Pyx_Is_Little_Endian(void)
#define __Pyx_XGIVEREF(r)
#endif /* CYTHON_REFNANNY */
+#define __Pyx_Py_XDECREF_SET(r, v) do { \
+ PyObject *tmp = (PyObject *) r; \
+ r = v; Py_XDECREF(tmp); \
+ } while (0)
#define __Pyx_XDECREF_SET(r, v) do { \
PyObject *tmp = (PyObject *) r; \
r = v; __Pyx_XDECREF(tmp); \
@@ -1449,7 +1885,8 @@ static int __Pyx_RegisterCleanup(void); /*proto*/
//@substitute: naming
#if PY_MAJOR_VERSION < 3 || CYTHON_COMPILING_IN_PYPY
-static PyObject* ${cleanup_cname}_atexit(PyObject *module, CYTHON_UNUSED PyObject *unused) {
+static PyObject* ${cleanup_cname}_atexit(PyObject *module, PyObject *unused) {
+ CYTHON_UNUSED_VAR(unused);
${cleanup_cname}(module);
Py_INCREF(Py_None); return Py_None;
}
@@ -1537,6 +1974,8 @@ __Pyx_FastGilFuncInit();
/////////////// FastGil.proto ///////////////
//@proto_block: utility_code_proto_before_types
+#if CYTHON_FAST_GIL
+
struct __Pyx_FastGilVtab {
PyGILState_STATE (*Fast_PyGILState_Ensure)(void);
void (*Fast_PyGILState_Release)(PyGILState_STATE oldstate);
@@ -1571,8 +2010,15 @@ static void __Pyx_FastGilFuncInit(void);
#endif
#endif
+#else
+#define __Pyx_PyGILState_Ensure PyGILState_Ensure
+#define __Pyx_PyGILState_Release PyGILState_Release
+#define __Pyx_FastGIL_Remember()
+#define __Pyx_FastGIL_Forget()
+#define __Pyx_FastGilFuncInit()
+#endif
+
/////////////// FastGil ///////////////
-//@requires: CommonStructures.c::FetchCommonPointer
// The implementations of PyGILState_Ensure/Release calls PyThread_get_key_value
// several times which is turns out to be quite slow (slower in fact than
// acquiring the GIL itself). Simply storing it in a thread local for the
@@ -1580,15 +2026,13 @@ static void __Pyx_FastGilFuncInit(void);
// To make optimal use of this thread local, we attempt to share it between
// modules.
-#define __Pyx_FastGIL_ABI_module "_cython_" CYTHON_ABI
+#if CYTHON_FAST_GIL
+
+#define __Pyx_FastGIL_ABI_module __PYX_ABI_MODULE_NAME
#define __Pyx_FastGIL_PyCapsuleName "FastGilFuncs"
#define __Pyx_FastGIL_PyCapsule \
__Pyx_FastGIL_ABI_module "." __Pyx_FastGIL_PyCapsuleName
-#if PY_VERSION_HEX < 0x02070000
- #undef CYTHON_THREAD_LOCAL
-#endif
-
#ifdef CYTHON_THREAD_LOCAL
#include "pythread.h"
@@ -1676,17 +2120,12 @@ static void __Pyx_FastGilFuncInit0(void) {
#else
static void __Pyx_FastGilFuncInit0(void) {
- CYTHON_UNUSED void* force_use = (void*)&__Pyx_FetchCommonPointer;
}
#endif
static void __Pyx_FastGilFuncInit(void) {
-#if PY_VERSION_HEX >= 0x02070000
struct __Pyx_FastGilVtab* shared = (struct __Pyx_FastGilVtab*)PyCapsule_Import(__Pyx_FastGIL_PyCapsule, 1);
-#else
- struct __Pyx_FastGilVtab* shared = NULL;
-#endif
if (shared) {
__Pyx_FastGilFuncs = *shared;
} else {
@@ -1694,3 +2133,22 @@ static void __Pyx_FastGilFuncInit(void) {
__Pyx_FastGilFuncInit0();
}
}
+
+#endif
+
+///////////////////// UtilityCodePragmas /////////////////////////
+
+#ifdef _MSC_VER
+#pragma warning( push )
+/* Warning 4127: conditional expression is constant
+ * Cython uses constant conditional expressions to allow in inline functions to be optimized at
+ * compile-time, so this warning is not useful
+ */
+#pragma warning( disable : 4127 )
+#endif
+
+///////////////////// UtilityCodePragmasEnd //////////////////////
+
+#ifdef _MSC_VER
+#pragma warning( pop ) /* undo whatever Cython has done to warnings */
+#endif
diff --git a/Cython/Utility/NumpyImportArray.c b/Cython/Utility/NumpyImportArray.c
new file mode 100644
index 000000000..4f72d0b46
--- /dev/null
+++ b/Cython/Utility/NumpyImportArray.c
@@ -0,0 +1,46 @@
+///////////////////////// NumpyImportArray.init ////////////////////
+
+// comment below is deliberately kept in the generated C file to
+// help users debug where this came from:
+/*
+ * Cython has automatically inserted a call to _import_array since
+ * you didn't include one when you cimported numpy. To disable this
+ * add the line
+ * <void>numpy._import_array
+ */
+#ifdef NPY_FEATURE_VERSION /* This is a public define that makes us reasonably confident it's "real" Numpy */
+// NO_IMPORT_ARRAY is Numpy's mechanism for indicating that import_array is handled elsewhere
+#if !NO_IMPORT_ARRAY /* https://docs.scipy.org/doc/numpy-1.17.0/reference/c-api.array.html#c.NO_IMPORT_ARRAY */
+if (unlikely(_import_array() == -1)) {
+ PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import "
+ "(auto-generated because you didn't call 'numpy.import_array()' after cimporting numpy; "
+ "use '<void>numpy._import_array' to disable if you are certain you don't need it).");
+}
+#endif
+#endif
+
+///////////////////////// NumpyImportUFunc.init ////////////////////
+
+// Unlike import_array, this is generated by the @cython.ufunc decorator
+// so we're confident the right headers are present and don't need to override them
+
+{
+ // NO_IMPORT_UFUNC is Numpy's mechanism for indicating that import_umath is handled elsewhere
+#if !NO_IMPORT_UFUNC /* https://numpy.org/devdocs/reference/c-api/ufunc.html#c.NO_IMPORT_UFUNC */
+ if (unlikely(_import_umath() == -1)) {
+ PyErr_SetString(PyExc_ImportError, "numpy.core.umath failed to import "
+ "(auto-generated by @cython.ufunc).");
+ }
+#else
+ if ((0)) {}
+#endif
+ // NO_IMPORT_ARRAY is Numpy's mechanism for indicating that import_array is handled elsewhere
+#if !NO_IMPORT_ARRAY /* https://docs.scipy.org/doc/numpy-1.17.0/reference/c-api.array.html#c.NO_IMPORT_ARRAY */
+ else if (unlikely(_import_array() == -1)) {
+ PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import "
+ "(auto-generated by @cython.ufunc).");
+ }
+#endif
+}
+
+
diff --git a/Cython/Utility/ObjectHandling.c b/Cython/Utility/ObjectHandling.c
index 02574e46e..e97569895 100644
--- a/Cython/Utility/ObjectHandling.c
+++ b/Cython/Utility/ObjectHandling.c
@@ -132,7 +132,7 @@ static int __Pyx_unpack_tuple2_generic(PyObject* tuple, PyObject** pvalue1, PyOb
if (unlikely(!iter)) goto bad;
if (decref_tuple) { Py_DECREF(tuple); tuple = NULL; }
- iternext = Py_TYPE(iter)->tp_iternext;
+ iternext = __Pyx_PyObject_GetIterNextFunc(iter);
value1 = iternext(iter); if (unlikely(!value1)) { index = 0; goto unpacking_failed; }
value2 = iternext(iter); if (unlikely(!value2)) { index = 1; goto unpacking_failed; }
if (!has_known_size && unlikely(__Pyx_IternextUnpackEndCheck(iternext(iter), 2))) goto bad;
@@ -184,8 +184,10 @@ static PyObject *__Pyx_PyIter_Next2Default(PyObject* defval) {
}
static void __Pyx_PyIter_Next_ErrorNoIterator(PyObject *iterator) {
+ __Pyx_TypeName iterator_type_name = __Pyx_PyType_GetName(Py_TYPE(iterator));
PyErr_Format(PyExc_TypeError,
- "%.200s object is not an iterator", Py_TYPE(iterator)->tp_name);
+ __Pyx_FMT_TYPENAME " object is not an iterator", iterator_type_name);
+ __Pyx_DECREF_TypeName(iterator_type_name);
}
// originally copied from Py3's builtin_next()
@@ -198,10 +200,8 @@ static CYTHON_INLINE PyObject *__Pyx_PyIter_Next2(PyObject* iterator, PyObject*
next = iternext(iterator);
if (likely(next))
return next;
- #if PY_VERSION_HEX >= 0x02070000
if (unlikely(iternext == &_PyObject_NextNotImplemented))
return NULL;
- #endif
#else
// Since the slot was set, assume that PyIter_Next() will likely succeed, and properly fail otherwise.
// Note: PyIter_Next() crashes in CPython if "tp_iternext" is NULL.
@@ -274,24 +274,21 @@ static CYTHON_INLINE int __Pyx_IterFinish(void) {
/////////////// ObjectGetItem.proto ///////////////
#if CYTHON_USE_TYPE_SLOTS
-static CYTHON_INLINE PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key);/*proto*/
+static CYTHON_INLINE PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject *key);/*proto*/
#else
#define __Pyx_PyObject_GetItem(obj, key) PyObject_GetItem(obj, key)
#endif
/////////////// ObjectGetItem ///////////////
// //@requires: GetItemInt - added in IndexNode as it uses templating.
+//@requires: PyObjectGetAttrStrNoError
+//@requires: PyObjectCallOneArg
#if CYTHON_USE_TYPE_SLOTS
-static PyObject *__Pyx_PyObject_GetIndex(PyObject *obj, PyObject* index) {
+static PyObject *__Pyx_PyObject_GetIndex(PyObject *obj, PyObject *index) {
+ // Get element from sequence object `obj` at index `index`.
PyObject *runerr = NULL;
Py_ssize_t key_value;
- PySequenceMethods *m = Py_TYPE(obj)->tp_as_sequence;
- if (unlikely(!(m && m->sq_item))) {
- PyErr_Format(PyExc_TypeError, "'%.200s' object is not subscriptable", Py_TYPE(obj)->tp_name);
- return NULL;
- }
-
key_value = __Pyx_PyIndex_AsSsize_t(index);
if (likely(key_value != -1 || !(runerr = PyErr_Occurred()))) {
return __Pyx_GetItemInt_Fast(obj, key_value, 0, 1, 1);
@@ -299,18 +296,46 @@ static PyObject *__Pyx_PyObject_GetIndex(PyObject *obj, PyObject* index) {
// Error handling code -- only manage OverflowError differently.
if (PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError)) {
+ __Pyx_TypeName index_type_name = __Pyx_PyType_GetName(Py_TYPE(index));
PyErr_Clear();
- PyErr_Format(PyExc_IndexError, "cannot fit '%.200s' into an index-sized integer", Py_TYPE(index)->tp_name);
+ PyErr_Format(PyExc_IndexError,
+ "cannot fit '" __Pyx_FMT_TYPENAME "' into an index-sized integer", index_type_name);
+ __Pyx_DECREF_TypeName(index_type_name);
+ }
+ return NULL;
+}
+
+static PyObject *__Pyx_PyObject_GetItem_Slow(PyObject *obj, PyObject *key) {
+ __Pyx_TypeName obj_type_name;
+ // Handles less common slow-path checks for GetItem
+ if (likely(PyType_Check(obj))) {
+ PyObject *meth = __Pyx_PyObject_GetAttrStrNoError(obj, PYIDENT("__class_getitem__"));
+ if (meth) {
+ PyObject *result = __Pyx_PyObject_CallOneArg(meth, key);
+ Py_DECREF(meth);
+ return result;
+ }
}
+
+ obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj));
+ PyErr_Format(PyExc_TypeError,
+ "'" __Pyx_FMT_TYPENAME "' object is not subscriptable", obj_type_name);
+ __Pyx_DECREF_TypeName(obj_type_name);
return NULL;
}
-static PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key) {
- PyMappingMethods *m = Py_TYPE(obj)->tp_as_mapping;
- if (likely(m && m->mp_subscript)) {
- return m->mp_subscript(obj, key);
+static PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject *key) {
+ PyTypeObject *tp = Py_TYPE(obj);
+ PyMappingMethods *mm = tp->tp_as_mapping;
+ PySequenceMethods *sm = tp->tp_as_sequence;
+
+ if (likely(mm && mm->mp_subscript)) {
+ return mm->mp_subscript(obj, key);
+ }
+ if (likely(sm && sm->sq_item)) {
+ return __Pyx_PyObject_GetIndex(obj, key);
}
- return __Pyx_PyObject_GetIndex(obj, key);
+ return __Pyx_PyObject_GetItem_Slow(obj, key);
}
#endif
@@ -357,6 +382,7 @@ static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) {
#endif
/////////////// GetItemInt.proto ///////////////
+//@substitute: tempita
#define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck) \
(__Pyx_fits_Py_ssize_t(i, type, is_signed) ? \
@@ -379,10 +405,11 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i,
int is_list, int wraparound, int boundscheck);
/////////////// GetItemInt ///////////////
+//@substitute: tempita
static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
PyObject *r;
- if (!j) return NULL;
+ if (unlikely(!j)) return NULL;
r = PyObject_GetItem(o, j);
Py_DECREF(j);
return r;
@@ -430,10 +457,18 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i,
}
} else {
// inlined PySequence_GetItem() + special cased length overflow
- PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence;
- if (likely(m && m->sq_item)) {
- if (wraparound && unlikely(i < 0) && likely(m->sq_length)) {
- Py_ssize_t l = m->sq_length(o);
+ PyMappingMethods *mm = Py_TYPE(o)->tp_as_mapping;
+ PySequenceMethods *sm = Py_TYPE(o)->tp_as_sequence;
+ if (mm && mm->mp_subscript) {
+ PyObject *r, *key = PyInt_FromSsize_t(i);
+ if (unlikely(!key)) return NULL;
+ r = mm->mp_subscript(o, key);
+ Py_DECREF(key);
+ return r;
+ }
+ if (likely(sm && sm->sq_item)) {
+ if (wraparound && unlikely(i < 0) && likely(sm->sq_length)) {
+ Py_ssize_t l = sm->sq_length(o);
if (likely(l >= 0)) {
i += l;
} else {
@@ -443,7 +478,7 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i,
PyErr_Clear();
}
}
- return m->sq_item(o, i);
+ return sm->sq_item(o, i);
}
}
#else
@@ -470,7 +505,7 @@ static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObje
static int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
int r;
- if (!j) return -1;
+ if (unlikely(!j)) return -1;
r = PyObject_SetItem(o, j, v);
Py_DECREF(j);
return r;
@@ -490,10 +525,19 @@ static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObje
}
} else {
// inlined PySequence_SetItem() + special cased length overflow
- PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence;
- if (likely(m && m->sq_ass_item)) {
- if (wraparound && unlikely(i < 0) && likely(m->sq_length)) {
- Py_ssize_t l = m->sq_length(o);
+ PyMappingMethods *mm = Py_TYPE(o)->tp_as_mapping;
+ PySequenceMethods *sm = Py_TYPE(o)->tp_as_sequence;
+ if (mm && mm->mp_ass_subscript) {
+ int r;
+ PyObject *key = PyInt_FromSsize_t(i);
+ if (unlikely(!key)) return -1;
+ r = mm->mp_ass_subscript(o, key, v);
+ Py_DECREF(key);
+ return r;
+ }
+ if (likely(sm && sm->sq_ass_item)) {
+ if (wraparound && unlikely(i < 0) && likely(sm->sq_length)) {
+ Py_ssize_t l = sm->sq_length(o);
if (likely(l >= 0)) {
i += l;
} else {
@@ -503,7 +547,7 @@ static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObje
PyErr_Clear();
}
}
- return m->sq_ass_item(o, i, v);
+ return sm->sq_ass_item(o, i, v);
}
}
#else
@@ -536,24 +580,29 @@ static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i,
static int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
int r;
- if (!j) return -1;
+ if (unlikely(!j)) return -1;
r = PyObject_DelItem(o, j);
Py_DECREF(j);
return r;
}
static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i,
- CYTHON_UNUSED int is_list, CYTHON_NCP_UNUSED int wraparound) {
+ int is_list, CYTHON_NCP_UNUSED int wraparound) {
#if !CYTHON_USE_TYPE_SLOTS
if (is_list || PySequence_Check(o)) {
return PySequence_DelItem(o, i);
}
#else
// inlined PySequence_DelItem() + special cased length overflow
- PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence;
- if (likely(m && m->sq_ass_item)) {
- if (wraparound && unlikely(i < 0) && likely(m->sq_length)) {
- Py_ssize_t l = m->sq_length(o);
+ PyMappingMethods *mm = Py_TYPE(o)->tp_as_mapping;
+ PySequenceMethods *sm = Py_TYPE(o)->tp_as_sequence;
+ if ((!is_list) && mm && mm->mp_ass_subscript) {
+ PyObject *key = PyInt_FromSsize_t(i);
+ return likely(key) ? mm->mp_ass_subscript(o, key, (PyObject *)NULL) : -1;
+ }
+ if (likely(sm && sm->sq_ass_item)) {
+ if (wraparound && unlikely(i < 0) && likely(sm->sq_length)) {
+ Py_ssize_t l = sm->sq_length(o);
if (likely(l >= 0)) {
i += l;
} else {
@@ -563,7 +612,7 @@ static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i,
PyErr_Clear();
}
}
- return m->sq_ass_item(o, i, (PyObject *)NULL);
+ return sm->sq_ass_item(o, i, (PyObject *)NULL);
}
#endif
return __Pyx_DelItem_Generic(o, PyInt_FromSsize_t(i));
@@ -598,7 +647,8 @@ static CYTHON_INLINE int __Pyx_PyObject_SetSlice(PyObject* obj, PyObject* value,
{{endif}}
Py_ssize_t cstart, Py_ssize_t cstop,
PyObject** _py_start, PyObject** _py_stop, PyObject** _py_slice,
- int has_cstart, int has_cstop, CYTHON_UNUSED int wraparound) {
+ int has_cstart, int has_cstop, int wraparound) {
+ __Pyx_TypeName obj_type_name;
#if CYTHON_USE_TYPE_SLOTS
PyMappingMethods* mp;
#if PY_MAJOR_VERSION < 3
@@ -642,6 +692,8 @@ static CYTHON_INLINE int __Pyx_PyObject_SetSlice(PyObject* obj, PyObject* value,
return ms->sq_ass_slice(obj, cstart, cstop, value);
{{endif}}
}
+#else
+ CYTHON_UNUSED_VAR(wraparound);
#endif
mp = Py_TYPE(obj)->tp_as_mapping;
@@ -650,6 +702,8 @@ static CYTHON_INLINE int __Pyx_PyObject_SetSlice(PyObject* obj, PyObject* value,
{{else}}
if (likely(mp && mp->mp_ass_subscript))
{{endif}}
+#else
+ CYTHON_UNUSED_VAR(wraparound);
#endif
{
{{if access == 'Get'}}PyObject*{{else}}int{{endif}} result;
@@ -701,19 +755,70 @@ static CYTHON_INLINE int __Pyx_PyObject_SetSlice(PyObject* obj, PyObject* value,
}
return result;
}
+ obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj));
PyErr_Format(PyExc_TypeError,
{{if access == 'Get'}}
- "'%.200s' object is unsliceable", Py_TYPE(obj)->tp_name);
+ "'" __Pyx_FMT_TYPENAME "' object is unsliceable", obj_type_name);
{{else}}
- "'%.200s' object does not support slice %.10s",
- Py_TYPE(obj)->tp_name, value ? "assignment" : "deletion");
+ "'" __Pyx_FMT_TYPENAME "' object does not support slice %.10s",
+ obj_type_name, value ? "assignment" : "deletion");
{{endif}}
+ __Pyx_DECREF_TypeName(obj_type_name);
bad:
return {{if access == 'Get'}}NULL{{else}}-1{{endif}};
}
+/////////////// TupleAndListFromArray.proto ///////////////
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyList_FromArray(PyObject *const *src, Py_ssize_t n);
+static CYTHON_INLINE PyObject* __Pyx_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n);
+#endif
+
+/////////////// TupleAndListFromArray ///////////////
+//@substitute: naming
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE void __Pyx_copy_object_array(PyObject *const *CYTHON_RESTRICT src, PyObject** CYTHON_RESTRICT dest, Py_ssize_t length) {
+ PyObject *v;
+ Py_ssize_t i;
+ for (i = 0; i < length; i++) {
+ v = dest[i] = src[i];
+ Py_INCREF(v);
+ }
+}
+
+static CYTHON_INLINE PyObject *
+__Pyx_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
+{
+ PyObject *res;
+ if (n <= 0) {
+ Py_INCREF($empty_tuple);
+ return $empty_tuple;
+ }
+ res = PyTuple_New(n);
+ if (unlikely(res == NULL)) return NULL;
+ __Pyx_copy_object_array(src, ((PyTupleObject*)res)->ob_item, n);
+ return res;
+}
+
+static CYTHON_INLINE PyObject *
+__Pyx_PyList_FromArray(PyObject *const *src, Py_ssize_t n)
+{
+ PyObject *res;
+ if (n <= 0) {
+ return PyList_New(0);
+ }
+ res = PyList_New(n);
+ if (unlikely(res == NULL)) return NULL;
+ __Pyx_copy_object_array(src, ((PyListObject*)res)->ob_item, n);
+ return res;
+}
+#endif
+
+
/////////////// SliceTupleAndList.proto ///////////////
#if CYTHON_COMPILING_IN_CPYTHON
@@ -725,6 +830,8 @@ static CYTHON_INLINE PyObject* __Pyx_PyTuple_GetSlice(PyObject* src, Py_ssize_t
#endif
/////////////// SliceTupleAndList ///////////////
+//@requires: TupleAndListFromArray
+//@substitute: tempita
#if CYTHON_COMPILING_IN_CPYTHON
static CYTHON_INLINE void __Pyx_crop_slice(Py_ssize_t* _start, Py_ssize_t* _stop, Py_ssize_t* _length) {
@@ -745,32 +852,18 @@ static CYTHON_INLINE void __Pyx_crop_slice(Py_ssize_t* _start, Py_ssize_t* _stop
*_stop = stop;
}
-static CYTHON_INLINE void __Pyx_copy_object_array(PyObject** CYTHON_RESTRICT src, PyObject** CYTHON_RESTRICT dest, Py_ssize_t length) {
- PyObject *v;
- Py_ssize_t i;
- for (i = 0; i < length; i++) {
- v = dest[i] = src[i];
- Py_INCREF(v);
- }
-}
-
{{for type in ['List', 'Tuple']}}
static CYTHON_INLINE PyObject* __Pyx_Py{{type}}_GetSlice(
PyObject* src, Py_ssize_t start, Py_ssize_t stop) {
- PyObject* dest;
Py_ssize_t length = Py{{type}}_GET_SIZE(src);
__Pyx_crop_slice(&start, &stop, &length);
- if (unlikely(length <= 0))
- return Py{{type}}_New(0);
-
- dest = Py{{type}}_New(length);
- if (unlikely(!dest))
- return NULL;
- __Pyx_copy_object_array(
- ((Py{{type}}Object*)src)->ob_item + start,
- ((Py{{type}}Object*)dest)->ob_item,
- length);
- return dest;
+{{if type=='List'}}
+ if (length <= 0) {
+ // Avoid undefined behaviour when accessing `ob_item` of an empty list.
+ return PyList_New(0);
+ }
+{{endif}}
+ return __Pyx_Py{{type}}_FromArray(((Py{{type}}Object*)src)->ob_item + start, length);
}
{{endfor}}
#endif
@@ -912,10 +1005,14 @@ static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *na
PyObject *result;
PyObject *metaclass;
- if (PyDict_SetItem(dict, PYIDENT("__module__"), modname) < 0)
+ if (unlikely(PyDict_SetItem(dict, PYIDENT("__module__"), modname) < 0))
return NULL;
- if (PyDict_SetItem(dict, PYIDENT("__qualname__"), qualname) < 0)
+#if PY_VERSION_HEX >= 0x03030000
+ if (unlikely(PyDict_SetItem(dict, PYIDENT("__qualname__"), qualname) < 0))
return NULL;
+#else
+ CYTHON_MAYBE_UNUSED_VAR(qualname);
+#endif
/* Python2 __metaclass__ */
metaclass = __Pyx_PyDict_GetItemStr(dict, PYIDENT("__metaclass__"));
@@ -936,6 +1033,94 @@ static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *na
return result;
}
+/////////////// Py3UpdateBases.proto ///////////////
+
+static PyObject* __Pyx_PEP560_update_bases(PyObject *bases); /* proto */
+
+/////////////// Py3UpdateBases /////////////////////
+//@requires: PyObjectCallOneArg
+//@requires: PyObjectGetAttrStrNoError
+
+/* Shamelessly adapted from cpython/bltinmodule.c update_bases */
+static PyObject*
+__Pyx_PEP560_update_bases(PyObject *bases)
+{
+ Py_ssize_t i, j, size_bases;
+ PyObject *base, *meth, *new_base, *result, *new_bases = NULL;
+ /*assert(PyTuple_Check(bases));*/
+
+ size_bases = PyTuple_GET_SIZE(bases);
+ for (i = 0; i < size_bases; i++) {
+ // original code in CPython: base = args[i];
+ base = PyTuple_GET_ITEM(bases, i);
+ if (PyType_Check(base)) {
+ if (new_bases) {
+ // If we already have made a replacement, then we append every normal base,
+ // otherwise just skip it.
+ if (PyList_Append(new_bases, base) < 0) {
+ goto error;
+ }
+ }
+ continue;
+ }
+ // original code in CPython:
+ // if (_PyObject_LookupAttrId(base, &PyId___mro_entries__, &meth) < 0) {
+ meth = __Pyx_PyObject_GetAttrStrNoError(base, PYIDENT("__mro_entries__"));
+ if (!meth && PyErr_Occurred()) {
+ goto error;
+ }
+ if (!meth) {
+ if (new_bases) {
+ if (PyList_Append(new_bases, base) < 0) {
+ goto error;
+ }
+ }
+ continue;
+ }
+ new_base = __Pyx_PyObject_CallOneArg(meth, bases);
+ Py_DECREF(meth);
+ if (!new_base) {
+ goto error;
+ }
+ if (!PyTuple_Check(new_base)) {
+ PyErr_SetString(PyExc_TypeError,
+ "__mro_entries__ must return a tuple");
+ Py_DECREF(new_base);
+ goto error;
+ }
+ if (!new_bases) {
+ // If this is a first successful replacement, create new_bases list and
+ // copy previously encountered bases.
+ if (!(new_bases = PyList_New(i))) {
+ goto error;
+ }
+ for (j = 0; j < i; j++) {
+ // original code in CPython: base = args[j];
+ base = PyTuple_GET_ITEM(bases, j);
+ PyList_SET_ITEM(new_bases, j, base);
+ Py_INCREF(base);
+ }
+ }
+ j = PyList_GET_SIZE(new_bases);
+ if (PyList_SetSlice(new_bases, j, j, new_base) < 0) {
+ goto error;
+ }
+ Py_DECREF(new_base);
+ }
+ if (!new_bases) {
+ // unlike the CPython implementation, always return a new reference
+ Py_INCREF(bases);
+ return bases;
+ }
+ result = PyList_AsTuple(new_bases);
+ Py_DECREF(new_bases);
+ return result;
+
+error:
+ Py_XDECREF(new_bases);
+ return NULL;
+}
+
/////////////// Py3ClassCreate.proto ///////////////
static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name, PyObject *qualname,
@@ -944,27 +1129,27 @@ static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObj
PyObject *mkw, int calculate_metaclass, int allow_py2_metaclass); /*proto*/
/////////////// Py3ClassCreate ///////////////
-//@requires: PyObjectGetAttrStr
+//@substitute: naming
+//@requires: PyObjectGetAttrStrNoError
//@requires: CalculateMetaclass
+//@requires: PyObjectFastCall
+//@requires: PyObjectCall2Args
+//@requires: PyObjectLookupSpecial
+// only in fallback code:
+//@requires: GetBuiltinName
static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name,
PyObject *qualname, PyObject *mkw, PyObject *modname, PyObject *doc) {
PyObject *ns;
if (metaclass) {
- PyObject *prep = __Pyx_PyObject_GetAttrStr(metaclass, PYIDENT("__prepare__"));
+ PyObject *prep = __Pyx_PyObject_GetAttrStrNoError(metaclass, PYIDENT("__prepare__"));
if (prep) {
- PyObject *pargs = PyTuple_Pack(2, name, bases);
- if (unlikely(!pargs)) {
- Py_DECREF(prep);
- return NULL;
- }
- ns = PyObject_Call(prep, pargs, mkw);
+ PyObject *pargs[3] = {NULL, name, bases};
+ ns = __Pyx_PyObject_FastCallDict(prep, pargs+1, 2 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET, mkw);
Py_DECREF(prep);
- Py_DECREF(pargs);
} else {
- if (unlikely(!PyErr_ExceptionMatches(PyExc_AttributeError)))
+ if (unlikely(PyErr_Occurred()))
return NULL;
- PyErr_Clear();
ns = PyDict_New();
}
} else {
@@ -976,7 +1161,11 @@ static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases,
/* Required here to emulate assignment order */
if (unlikely(PyObject_SetItem(ns, PYIDENT("__module__"), modname) < 0)) goto bad;
+#if PY_VERSION_HEX >= 0x03030000
if (unlikely(PyObject_SetItem(ns, PYIDENT("__qualname__"), qualname) < 0)) goto bad;
+#else
+ CYTHON_MAYBE_UNUSED_VAR(qualname);
+#endif
if (unlikely(doc && PyObject_SetItem(ns, PYIDENT("__doc__"), doc) < 0)) goto bad;
return ns;
bad:
@@ -984,11 +1173,164 @@ bad:
return NULL;
}
+#if PY_VERSION_HEX < 0x030600A4 && CYTHON_PEP487_INIT_SUBCLASS
+// https://www.python.org/dev/peps/pep-0487/
+static int __Pyx_SetNamesPEP487(PyObject *type_obj) {
+ PyTypeObject *type = (PyTypeObject*) type_obj;
+ PyObject *names_to_set, *key, *value, *set_name, *tmp;
+ Py_ssize_t i = 0;
+
+#if CYTHON_USE_TYPE_SLOTS
+ names_to_set = PyDict_Copy(type->tp_dict);
+#else
+ {
+ PyObject *d = PyObject_GetAttr(type_obj, PYIDENT("__dict__"));
+ names_to_set = NULL;
+ if (likely(d)) {
+ // d may not be a dict, e.g. PyDictProxy in PyPy2.
+ PyObject *names_to_set = PyDict_New();
+ int ret = likely(names_to_set) ? PyDict_Update(names_to_set, d) : -1;
+ Py_DECREF(d);
+ if (unlikely(ret < 0))
+ Py_CLEAR(names_to_set);
+ }
+ }
+#endif
+ if (unlikely(names_to_set == NULL))
+ goto bad;
+
+ while (PyDict_Next(names_to_set, &i, &key, &value)) {
+ set_name = __Pyx_PyObject_LookupSpecialNoError(value, PYIDENT("__set_name__"));
+ if (unlikely(set_name != NULL)) {
+ tmp = __Pyx_PyObject_Call2Args(set_name, type_obj, key);
+ Py_DECREF(set_name);
+ if (unlikely(tmp == NULL)) {
+ __Pyx_TypeName value_type_name =
+ __Pyx_PyType_GetName(Py_TYPE(value));
+ __Pyx_TypeName type_name = __Pyx_PyType_GetName(type);
+ PyErr_Format(PyExc_RuntimeError,
+#if PY_MAJOR_VERSION >= 3
+ "Error calling __set_name__ on '" __Pyx_FMT_TYPENAME "' instance %R " "in '" __Pyx_FMT_TYPENAME "'",
+ value_type_name, key, type_name);
+#else
+ "Error calling __set_name__ on '" __Pyx_FMT_TYPENAME "' instance %.100s in '" __Pyx_FMT_TYPENAME "'",
+ value_type_name,
+ PyString_Check(key) ? PyString_AS_STRING(key) : "?",
+ type_name);
+#endif
+ goto bad;
+ } else {
+ Py_DECREF(tmp);
+ }
+ }
+ else if (unlikely(PyErr_Occurred())) {
+ goto bad;
+ }
+ }
+
+ Py_DECREF(names_to_set);
+ return 0;
+bad:
+ Py_XDECREF(names_to_set);
+ return -1;
+}
+
+static PyObject *__Pyx_InitSubclassPEP487(PyObject *type_obj, PyObject *mkw) {
+#if CYTHON_USE_TYPE_SLOTS && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+// Stripped-down version of "super(type_obj, type_obj).__init_subclass__(**mkw)" in CPython 3.8.
+ PyTypeObject *type = (PyTypeObject*) type_obj;
+ PyObject *mro = type->tp_mro;
+ Py_ssize_t i, nbases;
+ if (unlikely(!mro)) goto done;
+
+ // avoid "unused" warning
+ (void) &__Pyx_GetBuiltinName;
+
+ Py_INCREF(mro);
+ nbases = PyTuple_GET_SIZE(mro);
+
+ // Skip over the type itself and 'object'.
+ assert(PyTuple_GET_ITEM(mro, 0) == type_obj);
+ for (i = 1; i < nbases-1; i++) {
+ PyObject *base, *dict, *meth;
+ base = PyTuple_GET_ITEM(mro, i);
+ dict = ((PyTypeObject *)base)->tp_dict;
+ meth = __Pyx_PyDict_GetItemStrWithError(dict, PYIDENT("__init_subclass__"));
+ if (unlikely(meth)) {
+ descrgetfunc f = Py_TYPE(meth)->tp_descr_get;
+ PyObject *res;
+ Py_INCREF(meth);
+ if (likely(f)) {
+ res = f(meth, NULL, type_obj);
+ Py_DECREF(meth);
+ if (unlikely(!res)) goto bad;
+ meth = res;
+ }
+ res = __Pyx_PyObject_FastCallDict(meth, NULL, 0, mkw);
+ Py_DECREF(meth);
+ if (unlikely(!res)) goto bad;
+ Py_DECREF(res);
+ goto done;
+ } else if (unlikely(PyErr_Occurred())) {
+ goto bad;
+ }
+ }
+
+done:
+ Py_XDECREF(mro);
+ return type_obj;
+
+bad:
+ Py_XDECREF(mro);
+ Py_DECREF(type_obj);
+ return NULL;
+
+// CYTHON_USE_TYPE_SLOTS && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+#else
+// Generic fallback: "super(type_obj, type_obj).__init_subclass__(**mkw)", as used in CPython 3.8.
+ PyObject *super_type, *super, *func, *res;
+
+#if CYTHON_COMPILING_IN_PYPY && !defined(PySuper_Type)
+ super_type = __Pyx_GetBuiltinName(PYIDENT("super"));
+#else
+ super_type = (PyObject*) &PySuper_Type;
+ // avoid "unused" warning
+ (void) &__Pyx_GetBuiltinName;
+#endif
+ super = likely(super_type) ? __Pyx_PyObject_Call2Args(super_type, type_obj, type_obj) : NULL;
+#if CYTHON_COMPILING_IN_PYPY && !defined(PySuper_Type)
+ Py_XDECREF(super_type);
+#endif
+ if (unlikely(!super)) {
+ Py_CLEAR(type_obj);
+ goto done;
+ }
+ func = __Pyx_PyObject_GetAttrStrNoError(super, PYIDENT("__init_subclass__"));
+ Py_DECREF(super);
+ if (likely(!func)) {
+ if (unlikely(PyErr_Occurred()))
+ Py_CLEAR(type_obj);
+ goto done;
+ }
+ res = __Pyx_PyObject_FastCallDict(func, NULL, 0, mkw);
+ Py_DECREF(func);
+ if (unlikely(!res))
+ Py_CLEAR(type_obj);
+ Py_XDECREF(res);
+done:
+ return type_obj;
+#endif
+}
+
+// PY_VERSION_HEX < 0x030600A4 && CYTHON_PEP487_INIT_SUBCLASS
+#endif
+
static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObject *bases,
PyObject *dict, PyObject *mkw,
int calculate_metaclass, int allow_py2_metaclass) {
- PyObject *result, *margs;
+ PyObject *result;
PyObject *owned_metaclass = NULL;
+ PyObject *margs[4] = {NULL, name, bases, dict};
if (allow_py2_metaclass) {
/* honour Python2 __metaclass__ for backward compatibility */
owned_metaclass = PyObject_GetItem(dict, PYIDENT("__metaclass__"));
@@ -1007,14 +1349,28 @@ static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObj
return NULL;
owned_metaclass = metaclass;
}
- margs = PyTuple_Pack(3, name, bases, dict);
- if (unlikely(!margs)) {
- result = NULL;
- } else {
- result = PyObject_Call(metaclass, margs, mkw);
- Py_DECREF(margs);
- }
+ result = __Pyx_PyObject_FastCallDict(metaclass, margs+1, 3 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET,
+#if PY_VERSION_HEX < 0x030600A4
+ // Before PEP-487, type(a,b,c) did not accept any keyword arguments, so guard at least against that case.
+ (metaclass == (PyObject*)&PyType_Type) ? NULL : mkw
+#else
+ mkw
+#endif
+ );
Py_XDECREF(owned_metaclass);
+
+#if PY_VERSION_HEX < 0x030600A4 && CYTHON_PEP487_INIT_SUBCLASS
+ if (likely(result) && likely(PyType_Check(result))) {
+ if (unlikely(__Pyx_SetNamesPEP487(result) < 0)) {
+ Py_CLEAR(result);
+ } else {
+ result = __Pyx_InitSubclassPEP487(result, mkw);
+ }
+ }
+#else
+ // avoid "unused" warning
+ (void) &__Pyx_GetBuiltinName;
+#endif
return result;
}
@@ -1025,14 +1381,21 @@ static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*pr
/////////////// ExtTypeTest ///////////////
static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
+ __Pyx_TypeName obj_type_name;
+ __Pyx_TypeName type_name;
if (unlikely(!type)) {
PyErr_SetString(PyExc_SystemError, "Missing type object");
return 0;
}
if (likely(__Pyx_TypeCheck(obj, type)))
return 1;
- PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s",
- Py_TYPE(obj)->tp_name, type->tp_name);
+ obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj));
+ type_name = __Pyx_PyType_GetName(type);
+ PyErr_Format(PyExc_TypeError,
+ "Cannot convert " __Pyx_FMT_TYPENAME " to " __Pyx_FMT_TYPENAME,
+ obj_type_name, type_name);
+ __Pyx_DECREF_TypeName(obj_type_name);
+ __Pyx_DECREF_TypeName(type_name);
return 0;
}
@@ -1100,12 +1463,12 @@ static CYTHON_INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) {
static PyObject *__Pyx_GetBuiltinName(PyObject *name); /*proto*/
/////////////// GetBuiltinName ///////////////
-//@requires: PyObjectGetAttrStr
+//@requires: PyObjectGetAttrStrNoError
//@substitute: naming
static PyObject *__Pyx_GetBuiltinName(PyObject *name) {
- PyObject* result = __Pyx_PyObject_GetAttrStr($builtins_cname, name);
- if (unlikely(!result)) {
+ PyObject* result = __Pyx_PyObject_GetAttrStrNoError($builtins_cname, name);
+ if (unlikely(!result) && !PyErr_Occurred()) {
PyErr_Format(PyExc_NameError,
#if PY_MAJOR_VERSION >= 3
"name '%U' is not defined", name);
@@ -1122,29 +1485,27 @@ static PyObject *__Pyx_GetBuiltinName(PyObject *name) {
static PyObject *__Pyx__GetNameInClass(PyObject *nmspace, PyObject *name); /*proto*/
/////////////// GetNameInClass ///////////////
-//@requires: PyObjectGetAttrStr
//@requires: GetModuleGlobalName
-//@requires: Exceptions.c::PyThreadStateGet
-//@requires: Exceptions.c::PyErrFetchRestore
-//@requires: Exceptions.c::PyErrExceptionMatches
-
-static PyObject *__Pyx_GetGlobalNameAfterAttributeLookup(PyObject *name) {
- PyObject *result;
- __Pyx_PyThreadState_declare
- __Pyx_PyThreadState_assign
- if (unlikely(!__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError)))
- return NULL;
- __Pyx_PyErr_Clear();
- __Pyx_GetModuleGlobalNameUncached(result, name);
- return result;
-}
static PyObject *__Pyx__GetNameInClass(PyObject *nmspace, PyObject *name) {
PyObject *result;
- result = __Pyx_PyObject_GetAttrStr(nmspace, name);
- if (!result) {
- result = __Pyx_GetGlobalNameAfterAttributeLookup(name);
+ PyObject *dict;
+ assert(PyType_Check(nmspace));
+#if CYTHON_USE_TYPE_SLOTS
+ dict = ((PyTypeObject*)nmspace)->tp_dict;
+ Py_XINCREF(dict);
+#else
+ dict = PyObject_GetAttr(nmspace, PYIDENT("__dict__"));
+#endif
+ if (likely(dict)) {
+ result = PyObject_GetItem(dict, name);
+ Py_DECREF(dict);
+ if (result) {
+ return result;
+ }
}
+ PyErr_Clear();
+ __Pyx_GetModuleGlobalNameUncached(result, name);
return result;
}
@@ -1162,6 +1523,30 @@ static PyObject *__Pyx__GetNameInClass(PyObject *nmspace, PyObject *name) {
#define __Pyx_SetNameInClass(ns, name, value) PyObject_SetItem(ns, name, value)
#endif
+/////////////// SetNewInClass.proto ///////////////
+
+static int __Pyx_SetNewInClass(PyObject *ns, PyObject *name, PyObject *value);
+
+/////////////// SetNewInClass ///////////////
+//@requires: SetNameInClass
+
+// Special-case setting __new__: if it's a Cython function, wrap it in a
+// staticmethod. This is similar to what Python does for a Python function
+// called __new__.
+static int __Pyx_SetNewInClass(PyObject *ns, PyObject *name, PyObject *value) {
+#ifdef __Pyx_CyFunction_USED
+ int ret;
+ if (__Pyx_CyFunction_Check(value)) {
+ PyObject *staticnew = PyStaticMethod_New(value);
+ if (unlikely(!staticnew)) return -1;
+ ret = __Pyx_SetNameInClass(ns, name, staticnew);
+ Py_DECREF(staticnew);
+ return ret;
+ }
+#endif
+ return __Pyx_SetNameInClass(ns, name, value);
+}
+
/////////////// GetModuleGlobalName.proto ///////////////
//@requires: PyDictVersioning
@@ -1199,6 +1584,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.
@@ -1209,6 +1595,14 @@ static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name)
} else if (unlikely(PyErr_Occurred())) {
return NULL;
}
+#elif CYTHON_COMPILING_IN_LIMITED_API
+ if (unlikely(!$module_cname)) {
+ return NULL;
+ }
+ result = PyObject_GetAttr($module_cname, name);
+ if (likely(result)) {
+ return result;
+ }
#else
result = PyDict_GetItem($moddict_cname, name);
__PYX_UPDATE_DICT_CACHE($moddict_cname, result, *dict_cached_value, *dict_version)
@@ -1246,16 +1640,31 @@ static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *o, PyObject *n) {
return PyObject_GetAttr(o, n);
}
+
/////////////// PyObjectLookupSpecial.proto ///////////////
+
+#if CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
+#define __Pyx_PyObject_LookupSpecialNoError(obj, attr_name) __Pyx__PyObject_LookupSpecial(obj, attr_name, 0)
+#define __Pyx_PyObject_LookupSpecial(obj, attr_name) __Pyx__PyObject_LookupSpecial(obj, attr_name, 1)
+
+static CYTHON_INLINE PyObject* __Pyx__PyObject_LookupSpecial(PyObject* obj, PyObject* attr_name, int with_error); /*proto*/
+
+#else
+#define __Pyx_PyObject_LookupSpecialNoError(o,n) __Pyx_PyObject_GetAttrStrNoError(o,n)
+#define __Pyx_PyObject_LookupSpecial(o,n) __Pyx_PyObject_GetAttrStr(o,n)
+#endif
+
+/////////////// PyObjectLookupSpecial ///////////////
//@requires: PyObjectGetAttrStr
+//@requires: PyObjectGetAttrStrNoError
#if CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
-static CYTHON_INLINE PyObject* __Pyx_PyObject_LookupSpecial(PyObject* obj, PyObject* attr_name) {
+static CYTHON_INLINE PyObject* __Pyx__PyObject_LookupSpecial(PyObject* obj, PyObject* attr_name, int with_error) {
PyObject *res;
PyTypeObject *tp = Py_TYPE(obj);
#if PY_MAJOR_VERSION < 3
if (unlikely(PyInstance_Check(obj)))
- return __Pyx_PyObject_GetAttrStr(obj, attr_name);
+ return with_error ? __Pyx_PyObject_GetAttrStr(obj, attr_name) : __Pyx_PyObject_GetAttrStrNoError(obj, attr_name);
#endif
// adapted from CPython's special_lookup() in ceval.c
res = _PyType_Lookup(tp, attr_name);
@@ -1266,13 +1675,11 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_LookupSpecial(PyObject* obj, PyObj
} else {
res = f(res, obj, (PyObject *)tp);
}
- } else {
+ } else if (with_error) {
PyErr_SetObject(PyExc_AttributeError, attr_name);
}
return res;
}
-#else
-#define __Pyx_PyObject_LookupSpecial(o,n) __Pyx_PyObject_GetAttrStr(o,n)
#endif
@@ -1291,19 +1698,21 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj
#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000
static PyObject *__Pyx_RaiseGenericGetAttributeError(PyTypeObject *tp, PyObject *attr_name) {
+ __Pyx_TypeName type_name = __Pyx_PyType_GetName(tp);
PyErr_Format(PyExc_AttributeError,
#if PY_MAJOR_VERSION >= 3
- "'%.50s' object has no attribute '%U'",
- tp->tp_name, attr_name);
+ "'" __Pyx_FMT_TYPENAME "' object has no attribute '%U'",
+ type_name, attr_name);
#else
- "'%.50s' object has no attribute '%.400s'",
- tp->tp_name, PyString_AS_STRING(attr_name));
+ "'" __Pyx_FMT_TYPENAME "' object has no attribute '%.400s'",
+ type_name, PyString_AS_STRING(attr_name));
#endif
+ __Pyx_DECREF_TypeName(type_name);
return NULL;
}
static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name) {
- // Copied and adapted from _PyObject_GenericGetAttrWithDict() in CPython 2.6/3.7.
+ // Copied and adapted from _PyObject_GenericGetAttrWithDict() in CPython 3.6/3.7.
// To be used in the "tp_getattro" slot of extension types that have no instance dict and cannot be subclassed.
PyObject *descr;
PyTypeObject *tp = Py_TYPE(obj);
@@ -1455,6 +1864,7 @@ static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **me
static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) {
PyObject *attr;
#if CYTHON_UNPACK_METHODS && CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_PYTYPE_LOOKUP
+ __Pyx_TypeName type_name;
// Copied from _PyObject_GetMethod() in CPython 3.7
PyTypeObject *tp = Py_TYPE(obj);
PyObject *descr;
@@ -1475,12 +1885,14 @@ static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **me
descr = _PyType_Lookup(tp, name);
if (likely(descr != NULL)) {
Py_INCREF(descr);
+#if defined(Py_TPFLAGS_METHOD_DESCRIPTOR) && Py_TPFLAGS_METHOD_DESCRIPTOR
+ if (__Pyx_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR))
+#elif PY_MAJOR_VERSION >= 3
// Repeating the condition below accommodates for MSVC's inability to test macros inside of macro expansions.
-#if PY_MAJOR_VERSION >= 3
#ifdef __Pyx_CyFunction_USED
- if (likely(PyFunction_Check(descr) || (Py_TYPE(descr) == &PyMethodDescr_Type) || __Pyx_CyFunction_Check(descr)))
+ if (likely(PyFunction_Check(descr) || __Pyx_IS_TYPE(descr, &PyMethodDescr_Type) || __Pyx_CyFunction_Check(descr)))
#else
- if (likely(PyFunction_Check(descr) || (Py_TYPE(descr) == &PyMethodDescr_Type)))
+ if (likely(PyFunction_Check(descr) || __Pyx_IS_TYPE(descr, &PyMethodDescr_Type)))
#endif
#else
// "PyMethodDescr_Type" is not part of the C-API in Py2.
@@ -1526,19 +1938,21 @@ static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **me
goto try_unpack;
}
- if (descr != NULL) {
+ if (likely(descr != NULL)) {
*method = descr;
return 0;
}
+ type_name = __Pyx_PyType_GetName(tp);
PyErr_Format(PyExc_AttributeError,
#if PY_MAJOR_VERSION >= 3
- "'%.50s' object has no attribute '%U'",
- tp->tp_name, name);
+ "'" __Pyx_FMT_TYPENAME "' object has no attribute '%U'",
+ type_name, name);
#else
- "'%.50s' object has no attribute '%.400s'",
- tp->tp_name, PyString_AS_STRING(name));
+ "'" __Pyx_FMT_TYPENAME "' object has no attribute '%.400s'",
+ type_name, PyString_AS_STRING(name));
#endif
+ __Pyx_DECREF_TypeName(type_name);
return 0;
// Generic fallback implementation using normal attribute lookup.
@@ -1578,23 +1992,77 @@ typedef struct {
/////////////// UnpackUnboundCMethod ///////////////
//@requires: PyObjectGetAttrStr
+static PyObject *__Pyx_SelflessCall(PyObject *method, PyObject *args, PyObject *kwargs) {
+ // NOTE: possible optimization - use vectorcall
+ PyObject *selfless_args = PyTuple_GetSlice(args, 1, PyTuple_Size(args));
+ if (unlikely(!selfless_args)) return NULL;
+
+ PyObject *result = PyObject_Call(method, selfless_args, kwargs);
+ Py_DECREF(selfless_args);
+ return result;
+}
+
+static PyMethodDef __Pyx_UnboundCMethod_Def = {
+ /* .ml_name = */ "CythonUnboundCMethod",
+ /* .ml_meth = */ __PYX_REINTERPRET_FUNCION(PyCFunction, __Pyx_SelflessCall),
+ /* .ml_flags = */ METH_VARARGS | METH_KEYWORDS,
+ /* .ml_doc = */ NULL
+};
+
static int __Pyx_TryUnpackUnboundCMethod(__Pyx_CachedCFunction* target) {
PyObject *method;
method = __Pyx_PyObject_GetAttrStr(target->type, *target->method_name);
if (unlikely(!method))
return -1;
target->method = method;
+// FIXME: use functionality from CythonFunction.c/ClassMethod
#if CYTHON_COMPILING_IN_CPYTHON
#if PY_MAJOR_VERSION >= 3
- // method dscriptor type isn't exported in Py2.x, cannot easily check the type there
if (likely(__Pyx_TypeCheck(method, &PyMethodDescr_Type)))
+ #else
+ // method descriptor type isn't exported in Py2.x, cannot easily check the type there.
+ // Therefore, reverse the check to the most likely alternative
+ // (which is returned for class methods)
+ if (likely(!PyCFunction_Check(method)))
#endif
{
PyMethodDescrObject *descr = (PyMethodDescrObject*) method;
target->func = descr->d_method->ml_meth;
target->flag = descr->d_method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_STACKLESS);
- }
+ } else
+#endif
+ // bound classmethods need special treatment
+#if defined(CYTHON_COMPILING_IN_PYPY)
+ // In PyPy functions are regular methods, so just do
+ // the self check
+#elif PY_VERSION_HEX >= 0x03090000
+ if (PyCFunction_CheckExact(method))
+#else
+ if (PyCFunction_Check(method))
#endif
+ {
+ PyObject *self;
+ int self_found;
+#if CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_PYPY
+ self = PyObject_GetAttrString(method, "__self__");
+ if (!self) {
+ PyErr_Clear();
+ }
+#else
+ self = PyCFunction_GET_SELF(method);
+#endif
+ self_found = (self && self != Py_None);
+#if CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_PYPY
+ Py_XDECREF(self);
+#endif
+ if (self_found) {
+ PyObject *unbound_method = PyCFunction_New(&__Pyx_UnboundCMethod_Def, method);
+ if (unlikely(!unbound_method)) return -1;
+ // New PyCFunction will own method reference, thus decref __Pyx_PyObject_GetAttrStr
+ Py_DECREF(method);
+ target->method = unbound_method;
+ }
+ }
return 0;
}
@@ -1666,13 +2134,13 @@ static CYTHON_INLINE PyObject* __Pyx_CallUnboundCMethod1(__Pyx_CachedCFunction*
// Not using #ifdefs for PY_VERSION_HEX to avoid C compiler warnings about unused functions.
if (flag == METH_O) {
return (*(cfunc->func))(self, arg);
- } else if (PY_VERSION_HEX >= 0x030600B1 && flag == METH_FASTCALL) {
+ } else if ((PY_VERSION_HEX >= 0x030600B1) && flag == METH_FASTCALL) {
#if PY_VERSION_HEX >= 0x030700A0
return (*(__Pyx_PyCFunctionFast)(void*)(PyCFunction)cfunc->func)(self, &arg, 1);
#else
return (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)cfunc->func)(self, &arg, 1, NULL);
#endif
- } else if (PY_VERSION_HEX >= 0x030700A0 && flag == (METH_FASTCALL | METH_KEYWORDS)) {
+ } else if ((PY_VERSION_HEX >= 0x030700A0) && flag == (METH_FASTCALL | METH_KEYWORDS)) {
return (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)cfunc->func)(self, &arg, 1, NULL);
}
}
@@ -1784,6 +2252,107 @@ bad:
}
+/////////////// PyObjectFastCall.proto ///////////////
+
+#define __Pyx_PyObject_FastCall(func, args, nargs) __Pyx_PyObject_FastCallDict(func, args, (size_t)(nargs), NULL)
+static CYTHON_INLINE PyObject* __Pyx_PyObject_FastCallDict(PyObject *func, PyObject **args, size_t nargs, PyObject *kwargs); /*proto*/
+
+/////////////// PyObjectFastCall ///////////////
+//@requires: PyObjectCall
+//@requires: PyFunctionFastCall
+//@requires: PyObjectCallMethO
+//@substitute: naming
+
+static PyObject* __Pyx_PyObject_FastCall_fallback(PyObject *func, PyObject **args, size_t nargs, PyObject *kwargs) {
+ PyObject *argstuple;
+ PyObject *result;
+ size_t i;
+
+ argstuple = PyTuple_New((Py_ssize_t)nargs);
+ if (unlikely(!argstuple)) return NULL;
+ for (i = 0; i < nargs; i++) {
+ Py_INCREF(args[i]);
+ PyTuple_SET_ITEM(argstuple, (Py_ssize_t)i, args[i]);
+ }
+ result = __Pyx_PyObject_Call(func, argstuple, kwargs);
+ Py_DECREF(argstuple);
+ return result;
+}
+
+static CYTHON_INLINE PyObject* __Pyx_PyObject_FastCallDict(PyObject *func, PyObject **args, size_t _nargs, PyObject *kwargs) {
+ // Special fast paths for 0 and 1 arguments
+ // NOTE: in many cases, this is called with a constant value for nargs
+ // which is known at compile-time. So the branches below will typically
+ // be optimized away.
+ Py_ssize_t nargs = __Pyx_PyVectorcall_NARGS(_nargs);
+#if CYTHON_COMPILING_IN_CPYTHON
+ if (nargs == 0 && kwargs == NULL) {
+#if defined(__Pyx_CyFunction_USED) && defined(NDEBUG)
+ // TODO PyCFunction_GET_FLAGS has a type-check assert that breaks with a CyFunction
+ // in debug mode. There is likely to be a better way of avoiding tripping this
+ // check that doesn't involve disabling the optimized path.
+ if (__Pyx_IsCyOrPyCFunction(func))
+#else
+ if (PyCFunction_Check(func))
+#endif
+ {
+ if (likely(PyCFunction_GET_FLAGS(func) & METH_NOARGS)) {
+ return __Pyx_PyObject_CallMethO(func, NULL);
+ }
+ }
+ }
+ else if (nargs == 1 && kwargs == NULL) {
+ if (PyCFunction_Check(func))
+ {
+ if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) {
+ return __Pyx_PyObject_CallMethO(func, args[0]);
+ }
+ }
+ }
+#endif
+
+ #if PY_VERSION_HEX < 0x030800B1
+ #if CYTHON_FAST_PYCCALL
+ if (PyCFunction_Check(func)) {
+ if (kwargs) {
+ return _PyCFunction_FastCallDict(func, args, nargs, kwargs);
+ } else {
+ return _PyCFunction_FastCallKeywords(func, args, nargs, NULL);
+ }
+ }
+ #if PY_VERSION_HEX >= 0x030700A1
+ if (!kwargs && __Pyx_IS_TYPE(func, &PyMethodDescr_Type)) {
+ return _PyMethodDescr_FastCallKeywords(func, args, nargs, NULL);
+ }
+ #endif
+ #endif
+ #if CYTHON_FAST_PYCALL
+ if (PyFunction_Check(func)) {
+ return __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs);
+ }
+ #endif
+ #endif
+
+ #if CYTHON_VECTORCALL
+ vectorcallfunc f = _PyVectorcall_Function(func);
+ if (f) {
+ return f(func, args, (size_t)nargs, kwargs);
+ }
+ #elif defined(__Pyx_CyFunction_USED) && CYTHON_BACKPORT_VECTORCALL
+ // exclude fused functions for now
+ if (__Pyx_CyFunction_CheckExact(func)) {
+ __pyx_vectorcallfunc f = __Pyx_CyFunction_func_vectorcall(func);
+ if (f) return f(func, args, (size_t)nargs, kwargs);
+ }
+ #endif
+
+ if (nargs == 0) {
+ return __Pyx_PyObject_Call(func, $empty_tuple, kwargs);
+ }
+ return __Pyx_PyObject_FastCall_fallback(func, args, (size_t)nargs, kwargs);
+}
+
+
/////////////// PyObjectCallMethod0.proto ///////////////
static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name); /*proto*/
@@ -1838,59 +2407,6 @@ static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name
}
-/////////////// PyObjectCallMethod2.proto ///////////////
-
-static PyObject* __Pyx_PyObject_CallMethod2(PyObject* obj, PyObject* method_name, PyObject* arg1, PyObject* arg2); /*proto*/
-
-/////////////// PyObjectCallMethod2 ///////////////
-//@requires: PyObjectCall
-//@requires: PyFunctionFastCall
-//@requires: PyCFunctionFastCall
-//@requires: PyObjectCall2Args
-
-static PyObject* __Pyx_PyObject_Call3Args(PyObject* function, PyObject* arg1, PyObject* arg2, PyObject* arg3) {
- #if CYTHON_FAST_PYCALL
- if (PyFunction_Check(function)) {
- PyObject *args[3] = {arg1, arg2, arg3};
- return __Pyx_PyFunction_FastCall(function, args, 3);
- }
- #endif
- #if CYTHON_FAST_PYCCALL
- if (__Pyx_PyFastCFunction_Check(function)) {
- PyObject *args[3] = {arg1, arg2, arg3};
- return __Pyx_PyFunction_FastCall(function, args, 3);
- }
- #endif
-
- args = PyTuple_New(3);
- if (unlikely(!args)) goto done;
- Py_INCREF(arg1);
- PyTuple_SET_ITEM(args, 0, arg1);
- Py_INCREF(arg2);
- PyTuple_SET_ITEM(args, 1, arg2);
- Py_INCREF(arg3);
- PyTuple_SET_ITEM(args, 2, arg3);
-
- result = __Pyx_PyObject_Call(function, args, NULL);
- Py_DECREF(args);
- return result;
-}
-
-static PyObject* __Pyx_PyObject_CallMethod2(PyObject* obj, PyObject* method_name, PyObject* arg1, PyObject* arg2) {
- PyObject *args, *method = NULL, *result = NULL;
- int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method);
- if (likely(is_method)) {
- result = __Pyx_PyObject_Call3Args(method, obj, arg1, arg2);
- Py_DECREF(method);
- return result;
- }
- if (unlikely(!method)) return NULL;
- result = __Pyx_PyObject_Call2Args(method, arg1, arg2);
- Py_DECREF(method);
- return result;
-}
-
-
/////////////// tp_new.proto ///////////////
#define __Pyx_tp_new(type_obj, args) __Pyx_tp_new_kwargs(type_obj, args, NULL)
@@ -1962,14 +2478,12 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject
/////////////// PyFunctionFastCall.proto ///////////////
#if CYTHON_FAST_PYCALL
+
+#if !CYTHON_VECTORCALL
#define __Pyx_PyFunction_FastCall(func, args, nargs) \
__Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL)
-// let's assume that the non-public C-API function might still change during the 3.6 beta phase
-#if 1 || PY_VERSION_HEX < 0x030600B1
static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs);
-#else
-#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs)
#endif
// Backport from Python 3
@@ -1981,7 +2495,7 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args,
// ((char *)(foo) \
// + Py_BUILD_ASSERT_EXPR(offsetof(struct foo, string) == 0))
//
-// Written by Rusty Russell, public domain, http://ccodearchive.net/
+// Written by Rusty Russell, public domain, https://ccodearchive.net/
#define __Pyx_BUILD_ASSERT_EXPR(cond) \
(sizeof(char [1 - 2*!(cond)]) - 1)
@@ -1990,10 +2504,8 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args,
#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
#endif
-#if CYTHON_FAST_PYCALL
- // Initialised by module init code.
- static size_t __pyx_pyframe_localsplus_offset = 0;
-
+#if !CYTHON_VECTORCALL
+#if PY_VERSION_HEX >= 0x03080000
#include "frameobject.h"
#if PY_VERSION_HEX >= 0x030b00a6
#ifndef Py_BUILD_CORE
@@ -2001,10 +2513,16 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args,
#endif
#include "internal/pycore_frame.h"
#endif
+ #define __Pxy_PyFrame_Initialize_Offsets()
+ #define __Pyx_PyFrame_GetLocalsplus(frame) ((frame)->f_localsplus)
+#else
+ // Initialised by module init code.
+ static size_t __pyx_pyframe_localsplus_offset = 0;
+ #include "frameobject.h"
// This is the long runtime version of
// #define __Pyx_PyFrame_GetLocalsplus(frame) ((frame)->f_localsplus)
- // offsetof(PyFrameObject, f_localsplus) differs between regular C-Python and Stackless Python.
+ // offsetof(PyFrameObject, f_localsplus) differs between regular C-Python and Stackless Python < 3.8.
// Therefore the offset is computed at run time from PyFrame_type.tp_basicsize. That is feasible,
// because f_localsplus is the last field of PyFrameObject (checked by Py_BUILD_ASSERT_EXPR below).
#define __Pxy_PyFrame_Initialize_Offsets() \
@@ -2012,15 +2530,16 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args,
(void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus)))
#define __Pyx_PyFrame_GetLocalsplus(frame) \
(assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset))
-#endif // CYTHON_FAST_PYCALL
#endif
+#endif /* !CYTHON_VECTORCALL */
+
+#endif /* CYTHON_FAST_PYCALL */
/////////////// PyFunctionFastCall ///////////////
// copied from CPython 3.6 ceval.c
-#if CYTHON_FAST_PYCALL
-
+#if CYTHON_FAST_PYCALL && !CYTHON_VECTORCALL
static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na,
PyObject *globals) {
PyFrameObject *f;
@@ -2056,7 +2575,6 @@ static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args
}
-#if 1 || PY_VERSION_HEX < 0x030600B1
static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) {
PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
PyObject *globals = PyFunction_GET_GLOBALS(func);
@@ -2077,7 +2595,7 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args,
assert(kwargs == NULL || PyDict_Check(kwargs));
nk = kwargs ? PyDict_Size(kwargs) : 0;
- if (Py_EnterRecursiveCall((char*)" while calling a Python object")) {
+ if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) {
return NULL;
}
@@ -2166,83 +2684,19 @@ done:
Py_LeaveRecursiveCall();
return result;
}
-#endif /* CPython < 3.6 */
-#endif /* CYTHON_FAST_PYCALL */
-
-
-/////////////// PyCFunctionFastCall.proto ///////////////
-
-#if CYTHON_FAST_PYCCALL
-static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs);
-#else
-#define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL)
-#endif
-
-/////////////// PyCFunctionFastCall ///////////////
-
-#if CYTHON_FAST_PYCCALL
-static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) {
- PyCFunctionObject *func = (PyCFunctionObject*)func_obj;
- PyCFunction meth = PyCFunction_GET_FUNCTION(func);
- PyObject *self = PyCFunction_GET_SELF(func);
- int flags = PyCFunction_GET_FLAGS(func);
-
- assert(PyCFunction_Check(func));
- assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS)));
- assert(nargs >= 0);
- assert(nargs == 0 || args != NULL);
-
- /* _PyCFunction_FastCallDict() must not be called with an exception set,
- because it may clear it (directly or indirectly) and so the
- caller loses its exception */
- assert(!PyErr_Occurred());
-
- if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) {
- return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL);
- } else {
- return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs);
- }
-}
-#endif /* CYTHON_FAST_PYCCALL */
+#endif /* CYTHON_FAST_PYCALL && !CYTHON_VECTORCALL */
/////////////// PyObjectCall2Args.proto ///////////////
-static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2); /*proto*/
+static CYTHON_INLINE PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2); /*proto*/
/////////////// PyObjectCall2Args ///////////////
-//@requires: PyObjectCall
-//@requires: PyFunctionFastCall
-//@requires: PyCFunctionFastCall
-
-static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2) {
- PyObject *args, *result = NULL;
- #if CYTHON_FAST_PYCALL
- if (PyFunction_Check(function)) {
- PyObject *args[2] = {arg1, arg2};
- return __Pyx_PyFunction_FastCall(function, args, 2);
- }
- #endif
- #if CYTHON_FAST_PYCCALL
- if (__Pyx_PyFastCFunction_Check(function)) {
- PyObject *args[2] = {arg1, arg2};
- return __Pyx_PyCFunction_FastCall(function, args, 2);
- }
- #endif
+//@requires: PyObjectFastCall
- args = PyTuple_New(2);
- if (unlikely(!args)) goto done;
- Py_INCREF(arg1);
- PyTuple_SET_ITEM(args, 0, arg1);
- Py_INCREF(arg2);
- PyTuple_SET_ITEM(args, 1, arg2);
-
- Py_INCREF(function);
- result = __Pyx_PyObject_Call(function, args, NULL);
- Py_DECREF(args);
- Py_DECREF(function);
-done:
- return result;
+static CYTHON_INLINE PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2) {
+ PyObject *args[3] = {NULL, arg1, arg2};
+ return __Pyx_PyObject_FastCall(function, args+1, 2 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET);
}
@@ -2251,91 +2705,97 @@ done:
static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); /*proto*/
/////////////// PyObjectCallOneArg ///////////////
-//@requires: PyObjectCallMethO
-//@requires: PyObjectCall
-//@requires: PyFunctionFastCall
-//@requires: PyCFunctionFastCall
-
-#if CYTHON_COMPILING_IN_CPYTHON
-static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) {
- PyObject *result;
- PyObject *args = PyTuple_New(1);
- if (unlikely(!args)) return NULL;
- Py_INCREF(arg);
- PyTuple_SET_ITEM(args, 0, arg);
- result = __Pyx_PyObject_Call(func, args, NULL);
- Py_DECREF(args);
- return result;
-}
+//@requires: PyObjectFastCall
static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) {
-#if CYTHON_FAST_PYCALL
- if (PyFunction_Check(func)) {
- return __Pyx_PyFunction_FastCall(func, &arg, 1);
- }
-#endif
- if (likely(PyCFunction_Check(func))) {
- if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) {
- // fast and simple case that we are optimising for
- return __Pyx_PyObject_CallMethO(func, arg);
-#if CYTHON_FAST_PYCCALL
- } else if (__Pyx_PyFastCFunction_Check(func)) {
- return __Pyx_PyCFunction_FastCall(func, &arg, 1);
-#endif
- }
- }
- return __Pyx__PyObject_CallOneArg(func, arg);
-}
-#else
-static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) {
- PyObject *result;
- PyObject *args = PyTuple_Pack(1, arg);
- if (unlikely(!args)) return NULL;
- result = __Pyx_PyObject_Call(func, args, NULL);
- Py_DECREF(args);
- return result;
+ PyObject *args[2] = {NULL, arg};
+ return __Pyx_PyObject_FastCall(func, args+1, 1 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET);
}
-#endif
/////////////// PyObjectCallNoArg.proto ///////////////
-//@requires: PyObjectCall
-//@substitute: naming
-#if CYTHON_COMPILING_IN_CPYTHON
static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func); /*proto*/
-#else
-#define __Pyx_PyObject_CallNoArg(func) __Pyx_PyObject_Call(func, $empty_tuple, NULL)
-#endif
/////////////// PyObjectCallNoArg ///////////////
-//@requires: PyObjectCallMethO
-//@requires: PyObjectCall
-//@requires: PyFunctionFastCall
-//@substitute: naming
+//@requires: PyObjectFastCall
-#if CYTHON_COMPILING_IN_CPYTHON
static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) {
-#if CYTHON_FAST_PYCALL
- if (PyFunction_Check(func)) {
- return __Pyx_PyFunction_FastCall(func, NULL, 0);
- }
-#endif
-#if defined(__Pyx_CyFunction_USED) && defined(NDEBUG)
- // TODO PyCFunction_GET_FLAGS has a type-check assert that breaks with a CyFunction
- // in debug mode. There is likely to be a better way of avoiding tripping this
- // check that doesn't involve disabling the optimized path.
- if (likely(PyCFunction_Check(func) || __Pyx_CyFunction_Check(func)))
-#else
- if (likely(PyCFunction_Check(func)))
+ PyObject *arg = NULL;
+ return __Pyx_PyObject_FastCall(func, (&arg)+1, 0 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET);
+}
+
+
+/////////////// PyVectorcallFastCallDict.proto ///////////////
+
+#if CYTHON_METH_FASTCALL
+static CYTHON_INLINE PyObject *__Pyx_PyVectorcall_FastCallDict(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw);
#endif
- {
- if (likely(PyCFunction_GET_FLAGS(func) & METH_NOARGS)) {
- // fast and simple case that we are optimising for
- return __Pyx_PyObject_CallMethO(func, NULL);
- }
+
+/////////////// PyVectorcallFastCallDict ///////////////
+
+#if CYTHON_METH_FASTCALL
+// Slow path when kw is non-empty
+static PyObject *__Pyx_PyVectorcall_FastCallDict_kw(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw)
+{
+ // Code based on _PyObject_FastCallDict() and _PyStack_UnpackDict() from CPython
+ PyObject *res = NULL;
+ PyObject *kwnames;
+ PyObject **newargs;
+ PyObject **kwvalues;
+ Py_ssize_t i, pos;
+ size_t j;
+ PyObject *key, *value;
+ unsigned long keys_are_strings;
+ Py_ssize_t nkw = PyDict_GET_SIZE(kw);
+
+ // Copy positional arguments
+ newargs = (PyObject **)PyMem_Malloc((nargs + (size_t)nkw) * sizeof(args[0]));
+ if (unlikely(newargs == NULL)) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ for (j = 0; j < nargs; j++) newargs[j] = args[j];
+
+ // Copy keyword arguments
+ kwnames = PyTuple_New(nkw);
+ if (unlikely(kwnames == NULL)) {
+ PyMem_Free(newargs);
+ return NULL;
+ }
+ kwvalues = newargs + nargs;
+ pos = i = 0;
+ keys_are_strings = Py_TPFLAGS_UNICODE_SUBCLASS;
+ while (PyDict_Next(kw, &pos, &key, &value)) {
+ keys_are_strings &= Py_TYPE(key)->tp_flags;
+ Py_INCREF(key);
+ Py_INCREF(value);
+ PyTuple_SET_ITEM(kwnames, i, key);
+ kwvalues[i] = value;
+ i++;
+ }
+ if (unlikely(!keys_are_strings)) {
+ PyErr_SetString(PyExc_TypeError, "keywords must be strings");
+ goto cleanup;
+ }
+
+ // The actual call
+ res = vc(func, newargs, nargs, kwnames);
+
+cleanup:
+ Py_DECREF(kwnames);
+ for (i = 0; i < nkw; i++)
+ Py_DECREF(kwvalues[i]);
+ PyMem_Free(newargs);
+ return res;
+}
+
+static CYTHON_INLINE PyObject *__Pyx_PyVectorcall_FastCallDict(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw)
+{
+ if (likely(kw == NULL) || PyDict_GET_SIZE(kw) == 0) {
+ return vc(func, args, nargs, NULL);
}
- return __Pyx_PyObject_Call(func, $empty_tuple, NULL);
+ return __Pyx_PyVectorcall_FastCallDict_kw(func, vc, args, nargs, kw);
}
#endif
@@ -2352,10 +2812,9 @@ static PyObject* __Pyx_PyNumber_InPlaceMatrixMultiply(PyObject* x, PyObject* y);
#endif
/////////////// MatrixMultiply ///////////////
-//@requires: PyObjectGetAttrStr
+//@requires: PyObjectGetAttrStrNoError
//@requires: PyObjectCallOneArg
-//@requires: PyFunctionFastCall
-//@requires: PyCFunctionFastCall
+//@requires: PyObjectCall2Args
#if PY_VERSION_HEX < 0x03050000
static PyObject* __Pyx_PyObject_CallMatrixMethod(PyObject* method, PyObject* arg) {
@@ -2365,34 +2824,9 @@ static PyObject* __Pyx_PyObject_CallMatrixMethod(PyObject* method, PyObject* arg
if (likely(PyMethod_Check(method))) {
PyObject *self = PyMethod_GET_SELF(method);
if (likely(self)) {
- PyObject *args;
PyObject *function = PyMethod_GET_FUNCTION(method);
- #if CYTHON_FAST_PYCALL
- if (PyFunction_Check(function)) {
- PyObject *args[2] = {self, arg};
- result = __Pyx_PyFunction_FastCall(function, args, 2);
- goto done;
- }
- #endif
- #if CYTHON_FAST_PYCCALL
- if (__Pyx_PyFastCFunction_Check(function)) {
- PyObject *args[2] = {self, arg};
- result = __Pyx_PyCFunction_FastCall(function, args, 2);
- goto done;
- }
- #endif
- args = PyTuple_New(2);
- if (unlikely(!args)) goto done;
- Py_INCREF(self);
- PyTuple_SET_ITEM(args, 0, self);
- Py_INCREF(arg);
- PyTuple_SET_ITEM(args, 1, arg);
- Py_INCREF(function);
- Py_DECREF(method); method = NULL;
- result = __Pyx_PyObject_Call(function, args, NULL);
- Py_DECREF(args);
- Py_DECREF(function);
- return result;
+ result = __Pyx_PyObject_Call2Args(function, self, arg);
+ goto done;
}
}
#endif
@@ -2402,21 +2836,21 @@ done:
return result;
}
-#define __Pyx_TryMatrixMethod(x, y, py_method_name) { \
- PyObject *func = __Pyx_PyObject_GetAttrStr(x, py_method_name); \
+#define __Pyx_TryMatrixMethod(x, y, py_method_name) { \
+ PyObject *func = __Pyx_PyObject_GetAttrStrNoError(x, py_method_name); \
if (func) { \
PyObject *result = __Pyx_PyObject_CallMatrixMethod(func, y); \
if (result != Py_NotImplemented) \
return result; \
Py_DECREF(result); \
- } else { \
- if (!PyErr_ExceptionMatches(PyExc_AttributeError)) \
- return NULL; \
- PyErr_Clear(); \
+ } else if (unlikely(PyErr_Occurred())) { \
+ return NULL; \
} \
}
static PyObject* __Pyx__PyNumber_MatrixMultiply(PyObject* x, PyObject* y, const char* op_name) {
+ __Pyx_TypeName x_type_name;
+ __Pyx_TypeName y_type_name;
int right_is_subtype = PyObject_IsSubclass((PyObject*)Py_TYPE(y), (PyObject*)Py_TYPE(x));
if (unlikely(right_is_subtype == -1))
return NULL;
@@ -2429,11 +2863,13 @@ static PyObject* __Pyx__PyNumber_MatrixMultiply(PyObject* x, PyObject* y, const
if (!right_is_subtype) {
__Pyx_TryMatrixMethod(y, x, PYIDENT("__rmatmul__"))
}
+ x_type_name = __Pyx_PyType_GetName(Py_TYPE(x));
+ y_type_name = __Pyx_PyType_GetName(Py_TYPE(y));
PyErr_Format(PyExc_TypeError,
- "unsupported operand type(s) for %.2s: '%.100s' and '%.100s'",
- op_name,
- Py_TYPE(x)->tp_name,
- Py_TYPE(y)->tp_name);
+ "unsupported operand type(s) for %.2s: '" __Pyx_FMT_TYPENAME "' and '"
+ __Pyx_FMT_TYPENAME "'", op_name, x_type_name, y_type_name);
+ __Pyx_DECREF_TypeName(x_type_name);
+ __Pyx_DECREF_TypeName(y_type_name);
return NULL;
}
@@ -2504,3 +2940,277 @@ static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UIN
return obj_dict_version == __Pyx_get_object_dict_version(obj);
}
#endif
+
+
+/////////////// PyMethodNew.proto ///////////////
+
+#if PY_MAJOR_VERSION >= 3
+// This should be an actual function (not a macro), such that we can put it
+// directly in a tp_descr_get slot.
+static PyObject *__Pyx_PyMethod_New(PyObject *func, PyObject *self, PyObject *typ) {
+ CYTHON_UNUSED_VAR(typ);
+ if (!self)
+ return __Pyx_NewRef(func);
+ return PyMethod_New(func, self);
+}
+#else
+ #define __Pyx_PyMethod_New PyMethod_New
+#endif
+
+///////////// PyMethodNew2Arg.proto /////////////
+
+// Another wrapping of PyMethod_New that matches the Python3 signature
+#if PY_MAJOR_VERSION >= 3
+#define __Pyx_PyMethod_New2Arg PyMethod_New
+#else
+#define __Pyx_PyMethod_New2Arg(func, self) PyMethod_New(func, self, (PyObject*)Py_TYPE(self))
+#endif
+
+/////////////// UnicodeConcatInPlace.proto ////////////////
+
+# if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+// __Pyx_PyUnicode_ConcatInPlace may modify the first argument 'left'
+// However, unlike `PyUnicode_Append` it will never NULL it.
+// It behaves like a regular function - returns a new reference and NULL on error
+ #if CYTHON_REFNANNY
+ #define __Pyx_PyUnicode_ConcatInPlace(left, right) __Pyx_PyUnicode_ConcatInPlaceImpl(&left, right, __pyx_refnanny)
+ #else
+ #define __Pyx_PyUnicode_ConcatInPlace(left, right) __Pyx_PyUnicode_ConcatInPlaceImpl(&left, right)
+ #endif
+ // __Pyx_PyUnicode_ConcatInPlace is slightly odd because it has the potential to modify the input
+ // argument (but only in cases where no user should notice). Therefore, it needs to keep Cython's
+ // refnanny informed.
+ static CYTHON_INLINE PyObject *__Pyx_PyUnicode_ConcatInPlaceImpl(PyObject **p_left, PyObject *right
+ #if CYTHON_REFNANNY
+ , void* __pyx_refnanny
+ #endif
+ ); /* proto */
+#else
+#define __Pyx_PyUnicode_ConcatInPlace __Pyx_PyUnicode_Concat
+#endif
+#define __Pyx_PyUnicode_ConcatInPlaceSafe(left, right) ((unlikely((left) == Py_None) || unlikely((right) == Py_None)) ? \
+ PyNumber_InPlaceAdd(left, right) : __Pyx_PyUnicode_ConcatInPlace(left, right))
+
+/////////////// UnicodeConcatInPlace ////////////////
+//@substitute: naming
+
+# if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+// copied directly from unicode_object.c "unicode_modifiable
+// removing _PyUnicode_HASH since it's a macro we don't have
+// - this is OK because trying PyUnicode_Resize on a non-modifyable
+// object will still work, it just won't happen in place
+static int
+__Pyx_unicode_modifiable(PyObject *unicode)
+{
+ if (Py_REFCNT(unicode) != 1)
+ return 0;
+ if (!PyUnicode_CheckExact(unicode))
+ return 0;
+ if (PyUnicode_CHECK_INTERNED(unicode))
+ return 0;
+ return 1;
+}
+
+static CYTHON_INLINE PyObject *__Pyx_PyUnicode_ConcatInPlaceImpl(PyObject **p_left, PyObject *right
+ #if CYTHON_REFNANNY
+ , void* __pyx_refnanny
+ #endif
+ ) {
+ // heavily based on PyUnicode_Append
+ PyObject *left = *p_left;
+ Py_ssize_t left_len, right_len, new_len;
+
+ if (unlikely(__Pyx_PyUnicode_READY(left) == -1))
+ return NULL;
+ if (unlikely(__Pyx_PyUnicode_READY(right) == -1))
+ return NULL;
+
+ // Shortcuts
+ left_len = PyUnicode_GET_LENGTH(left);
+ if (left_len == 0) {
+ Py_INCREF(right);
+ return right;
+ }
+ right_len = PyUnicode_GET_LENGTH(right);
+ if (right_len == 0) {
+ Py_INCREF(left);
+ return left;
+ }
+ if (unlikely(left_len > PY_SSIZE_T_MAX - right_len)) {
+ PyErr_SetString(PyExc_OverflowError,
+ "strings are too large to concat");
+ return NULL;
+ }
+ new_len = left_len + right_len;
+
+ if (__Pyx_unicode_modifiable(left)
+ && PyUnicode_CheckExact(right)
+ && PyUnicode_KIND(right) <= PyUnicode_KIND(left)
+ // Don't resize for ascii += latin1. Convert ascii to latin1 requires
+ // to change the structure size, but characters are stored just after
+ // the structure, and so it requires to move all characters which is
+ // not so different than duplicating the string.
+ && !(PyUnicode_IS_ASCII(left) && !PyUnicode_IS_ASCII(right))) {
+
+ __Pyx_GIVEREF(*p_left);
+ if (unlikely(PyUnicode_Resize(p_left, new_len) != 0)) {
+ // on failure PyUnicode_Resize does not deallocate the the input
+ // so left will remain unchanged - simply undo the giveref
+ __Pyx_GOTREF(*p_left);
+ return NULL;
+ }
+ __Pyx_INCREF(*p_left);
+
+ // copy 'right' into the newly allocated area of 'left'
+ _PyUnicode_FastCopyCharacters(*p_left, left_len, right, 0, right_len);
+ return *p_left;
+ } else {
+ return __Pyx_PyUnicode_Concat(left, right);
+ }
+ }
+#endif
+
+////////////// StrConcatInPlace.proto ///////////////////////
+//@requires: UnicodeConcatInPlace
+
+#if PY_MAJOR_VERSION >= 3
+ // allow access to the more efficient versions where we know str_type is unicode
+ #define __Pyx_PyStr_Concat __Pyx_PyUnicode_Concat
+ #define __Pyx_PyStr_ConcatInPlace __Pyx_PyUnicode_ConcatInPlace
+#else
+ #define __Pyx_PyStr_Concat PyNumber_Add
+ #define __Pyx_PyStr_ConcatInPlace PyNumber_InPlaceAdd
+#endif
+#define __Pyx_PyStr_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ? \
+ PyNumber_Add(a, b) : __Pyx_PyStr_Concat(a, b))
+#define __Pyx_PyStr_ConcatInPlaceSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ? \
+ PyNumber_InPlaceAdd(a, b) : __Pyx_PyStr_ConcatInPlace(a, b))
+
+
+/////////////// PySequenceMultiply.proto ///////////////
+
+#define __Pyx_PySequence_Multiply_Left(mul, seq) __Pyx_PySequence_Multiply(seq, mul)
+static CYTHON_INLINE PyObject* __Pyx_PySequence_Multiply(PyObject *seq, Py_ssize_t mul);
+
+/////////////// PySequenceMultiply ///////////////
+
+static PyObject* __Pyx_PySequence_Multiply_Generic(PyObject *seq, Py_ssize_t mul) {
+ PyObject *result, *pymul = PyInt_FromSsize_t(mul);
+ if (unlikely(!pymul))
+ return NULL;
+ result = PyNumber_Multiply(seq, pymul);
+ Py_DECREF(pymul);
+ return result;
+}
+
+static CYTHON_INLINE PyObject* __Pyx_PySequence_Multiply(PyObject *seq, Py_ssize_t mul) {
+#if CYTHON_USE_TYPE_SLOTS
+ PyTypeObject *type = Py_TYPE(seq);
+ if (likely(type->tp_as_sequence && type->tp_as_sequence->sq_repeat)) {
+ return type->tp_as_sequence->sq_repeat(seq, mul);
+ } else
+#endif
+ {
+ return __Pyx_PySequence_Multiply_Generic(seq, mul);
+ }
+}
+
+
+/////////////// FormatTypeName.proto ///////////////
+
+#if CYTHON_COMPILING_IN_LIMITED_API
+typedef PyObject *__Pyx_TypeName;
+#define __Pyx_FMT_TYPENAME "%U"
+static __Pyx_TypeName __Pyx_PyType_GetName(PyTypeObject* tp); /*proto*/
+#define __Pyx_DECREF_TypeName(obj) Py_XDECREF(obj)
+#else
+typedef const char *__Pyx_TypeName;
+#define __Pyx_FMT_TYPENAME "%.200s"
+#define __Pyx_PyType_GetName(tp) ((tp)->tp_name)
+#define __Pyx_DECREF_TypeName(obj)
+#endif
+
+/////////////// FormatTypeName ///////////////
+
+#if CYTHON_COMPILING_IN_LIMITED_API
+static __Pyx_TypeName
+__Pyx_PyType_GetName(PyTypeObject* tp)
+{
+ PyObject *name = __Pyx_PyObject_GetAttrStr((PyObject *)tp,
+ PYIDENT("__name__"));
+ if (unlikely(name == NULL) || unlikely(!PyUnicode_Check(name))) {
+ PyErr_Clear();
+ Py_XSETREF(name, __Pyx_NewRef(PYIDENT("?")));
+ }
+ return name;
+}
+#endif
+
+
+/////////////// RaiseUnexpectedTypeError.proto ///////////////
+
+static int __Pyx_RaiseUnexpectedTypeError(const char *expected, PyObject *obj); /*proto*/
+
+/////////////// RaiseUnexpectedTypeError ///////////////
+
+static int
+__Pyx_RaiseUnexpectedTypeError(const char *expected, PyObject *obj)
+{
+ __Pyx_TypeName obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj));
+ PyErr_Format(PyExc_TypeError, "Expected %s, got " __Pyx_FMT_TYPENAME,
+ expected, obj_type_name);
+ __Pyx_DECREF_TypeName(obj_type_name);
+ return 0;
+}
+
+
+/////////////// RaiseUnboundLocalError.proto ///////////////
+static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname);/*proto*/
+
+/////////////// RaiseUnboundLocalError ///////////////
+static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname) {
+ PyErr_Format(PyExc_UnboundLocalError, "local variable '%s' referenced before assignment", varname);
+}
+
+
+/////////////// RaiseClosureNameError.proto ///////////////
+static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname);/*proto*/
+
+/////////////// RaiseClosureNameError ///////////////
+static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname) {
+ PyErr_Format(PyExc_NameError, "free variable '%s' referenced before assignment in enclosing scope", varname);
+}
+
+
+/////////////// RaiseUnboundMemoryviewSliceNogil.proto ///////////////
+static void __Pyx_RaiseUnboundMemoryviewSliceNogil(const char *varname);/*proto*/
+
+/////////////// RaiseUnboundMemoryviewSliceNogil ///////////////
+//@requires: RaiseUnboundLocalError
+
+// Don't inline the function, it should really never be called in production
+static void __Pyx_RaiseUnboundMemoryviewSliceNogil(const char *varname) {
+ #ifdef WITH_THREAD
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+ #endif
+ __Pyx_RaiseUnboundLocalError(varname);
+ #ifdef WITH_THREAD
+ PyGILState_Release(gilstate);
+ #endif
+}
+
+//////////////// RaiseCppGlobalNameError.proto ///////////////////////
+static CYTHON_INLINE void __Pyx_RaiseCppGlobalNameError(const char *varname); /*proto*/
+
+/////////////// RaiseCppGlobalNameError //////////////////////////////
+static CYTHON_INLINE void __Pyx_RaiseCppGlobalNameError(const char *varname) {
+ PyErr_Format(PyExc_NameError, "C++ global '%s' is not initialized", varname);
+}
+
+//////////////// RaiseCppAttributeError.proto ///////////////////////
+static CYTHON_INLINE void __Pyx_RaiseCppAttributeError(const char *varname); /*proto*/
+
+/////////////// RaiseCppAttributeError //////////////////////////////
+static CYTHON_INLINE void __Pyx_RaiseCppAttributeError(const char *varname) {
+ PyErr_Format(PyExc_AttributeError, "C++ attribute '%s' is not initialized", varname);
+}
diff --git a/Cython/Utility/Optimize.c b/Cython/Utility/Optimize.c
index 35f3a67c9..a16fb6ac9 100644
--- a/Cython/Utility/Optimize.c
+++ b/Cython/Utility/Optimize.c
@@ -94,7 +94,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L); /*proto*/
//@requires: ObjectHandling.c::PyObjectCallMethod0
static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L) {
- if (Py_TYPE(L) == &PySet_Type) {
+ if (__Pyx_IS_TYPE(L, &PySet_Type)) {
return PySet_Pop(L);
}
return __Pyx_PyObject_CallMethod0(L, PYIDENT("pop"));
@@ -190,7 +190,7 @@ static PyObject* __Pyx_PyDict_GetItemDefault(PyObject* d, PyObject* key, PyObjec
static PyObject* __Pyx_PyDict_GetItemDefault(PyObject* d, PyObject* key, PyObject* default_value) {
PyObject* value;
-#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY
+#if PY_MAJOR_VERSION >= 3 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07020000)
value = PyDict_GetItemWithError(d, key);
if (unlikely(!value)) {
if (unlikely(PyErr_Occurred()))
@@ -227,8 +227,9 @@ static CYTHON_INLINE PyObject *__Pyx_PyDict_SetDefault(PyObject *d, PyObject *ke
/////////////// dict_setdefault ///////////////
static CYTHON_INLINE PyObject *__Pyx_PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *default_value,
- CYTHON_UNUSED int is_safe_type) {
+ int is_safe_type) {
PyObject* value;
+ CYTHON_MAYBE_UNUSED_VAR(is_safe_type);
#if PY_VERSION_HEX >= 0x030400A0
// we keep the method call at the end to avoid "unused" C compiler warnings
if ((1)) {
@@ -238,7 +239,7 @@ static CYTHON_INLINE PyObject *__Pyx_PyDict_SetDefault(PyObject *d, PyObject *ke
#else
if (is_safe_type == 1 || (is_safe_type == -1 &&
/* the following builtins presumably have repeatably safe and fast hash functions */
-#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY
+#if PY_MAJOR_VERSION >= 3 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07020000)
(PyUnicode_CheckExact(key) || PyString_CheckExact(key) || PyLong_CheckExact(key)))) {
value = PyDict_GetItemWithError(d, key);
if (unlikely(!value)) {
@@ -444,7 +445,7 @@ static CYTHON_INLINE PyObject* __Pyx_set_iterator(PyObject* iterable, int is_set
return iterable;
}
#else
- (void)is_set;
+ CYTHON_UNUSED_VAR(is_set);
*p_source_is_set = 0;
#endif
*p_orig_length = 0;
@@ -460,8 +461,8 @@ static CYTHON_INLINE int __Pyx_set_iter_next(
if (unlikely(!*value)) {
return __Pyx_IterFinish();
}
- (void)orig_length;
- (void)ppos;
+ CYTHON_UNUSED_VAR(orig_length);
+ CYTHON_UNUSED_VAR(ppos);
return 1;
}
#if CYTHON_COMPILING_IN_CPYTHON
@@ -567,7 +568,12 @@ static CYTHON_INLINE int __Pyx_init_unicode_iteration(
static CYTHON_INLINE int __Pyx_init_unicode_iteration(
PyObject* ustring, Py_ssize_t *length, void** data, int *kind) {
-#if CYTHON_PEP393_ENABLED
+#if CYTHON_COMPILING_IN_LIMITED_API
+ // In the limited API we just point data to the unicode object
+ *kind = 0;
+ *length = PyUnicode_GetLength(ustring);
+ *data = (void*)ustring;
+#elif CYTHON_PEP393_ENABLED
if (unlikely(__Pyx_PyUnicode_READY(ustring) < 0)) return -1;
*kind = PyUnicode_KIND(ustring);
*length = PyUnicode_GET_LENGTH(ustring);
@@ -591,51 +597,366 @@ static double __Pyx__PyObject_AsDouble(PyObject* obj); /* proto */
PyFloat_AsDouble(obj) : __Pyx__PyObject_AsDouble(obj))
#else
#define __Pyx_PyObject_AsDouble(obj) \
-((likely(PyFloat_CheckExact(obj))) ? \
- PyFloat_AS_DOUBLE(obj) : __Pyx__PyObject_AsDouble(obj))
+((likely(PyFloat_CheckExact(obj))) ? PyFloat_AS_DOUBLE(obj) : \
+ likely(PyLong_CheckExact(obj)) ? \
+ PyLong_AsDouble(obj) : __Pyx__PyObject_AsDouble(obj))
#endif
/////////////// pyobject_as_double ///////////////
+//@requires: pybytes_as_double
+//@requires: pyunicode_as_double
+//@requires: ObjectHandling.c::PyObjectCallOneArg
static double __Pyx__PyObject_AsDouble(PyObject* obj) {
- PyObject* float_value;
+ if (PyUnicode_CheckExact(obj)) {
+ return __Pyx_PyUnicode_AsDouble(obj);
+ } else if (PyBytes_CheckExact(obj)) {
+ return __Pyx_PyBytes_AsDouble(obj);
+ } else if (PyByteArray_CheckExact(obj)) {
+ return __Pyx_PyByteArray_AsDouble(obj);
+ } else {
+ PyObject* float_value;
#if !CYTHON_USE_TYPE_SLOTS
- float_value = PyNumber_Float(obj); if ((0)) goto bad;
+ float_value = PyNumber_Float(obj); if ((0)) goto bad;
+ // avoid "unused" warnings
+ (void)__Pyx_PyObject_CallOneArg;
#else
- PyNumberMethods *nb = Py_TYPE(obj)->tp_as_number;
- if (likely(nb) && likely(nb->nb_float)) {
- float_value = nb->nb_float(obj);
- if (likely(float_value) && unlikely(!PyFloat_Check(float_value))) {
- PyErr_Format(PyExc_TypeError,
- "__float__ returned non-float (type %.200s)",
- Py_TYPE(float_value)->tp_name);
- Py_DECREF(float_value);
- goto bad;
+ PyNumberMethods *nb = Py_TYPE(obj)->tp_as_number;
+ if (likely(nb) && likely(nb->nb_float)) {
+ float_value = nb->nb_float(obj);
+ if (likely(float_value) && unlikely(!PyFloat_Check(float_value))) {
+ __Pyx_TypeName float_value_type_name = __Pyx_PyType_GetName(Py_TYPE(float_value));
+ PyErr_Format(PyExc_TypeError,
+ "__float__ returned non-float (type " __Pyx_FMT_TYPENAME ")",
+ float_value_type_name);
+ __Pyx_DECREF_TypeName(float_value_type_name);
+ Py_DECREF(float_value);
+ goto bad;
+ }
+ } else {
+ float_value = __Pyx_PyObject_CallOneArg((PyObject*)&PyFloat_Type, obj);
}
- } else if (PyUnicode_CheckExact(obj) || PyBytes_CheckExact(obj)) {
-#if PY_MAJOR_VERSION >= 3
- float_value = PyFloat_FromString(obj);
-#else
- float_value = PyFloat_FromString(obj, 0);
#endif
+ if (likely(float_value)) {
+ double value = PyFloat_AS_DOUBLE(float_value);
+ Py_DECREF(float_value);
+ return value;
+ }
+ }
+bad:
+ return (double)-1;
+}
+
+
+/////////////// pystring_as_double.proto ///////////////
+//@requires: pyunicode_as_double
+//@requires: pybytes_as_double
+
+static CYTHON_INLINE double __Pyx_PyString_AsDouble(PyObject *obj) {
+ #if PY_MAJOR_VERSION >= 3
+ (void)__Pyx_PyBytes_AsDouble;
+ return __Pyx_PyUnicode_AsDouble(obj);
+ #else
+ (void)__Pyx_PyUnicode_AsDouble;
+ return __Pyx_PyBytes_AsDouble(obj);
+ #endif
+}
+
+
+/////////////// pyunicode_as_double.proto ///////////////
+
+static CYTHON_INLINE double __Pyx_PyUnicode_AsDouble(PyObject *obj);/*proto*/
+
+/////////////// pyunicode_as_double.proto ///////////////
+//@requires: pybytes_as_double
+
+#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY
+static const char* __Pyx__PyUnicode_AsDouble_Copy(const void* data, const int kind, char* buffer, Py_ssize_t start, Py_ssize_t end) {
+ int last_was_punctuation;
+ Py_ssize_t i;
+ // number must not start with punctuation
+ last_was_punctuation = 1;
+ for (i=start; i <= end; i++) {
+ Py_UCS4 chr = PyUnicode_READ(kind, data, i);
+ int is_punctuation = (chr == '_') | (chr == '.');
+ *buffer = (char)chr;
+ // reject sequences of '_' and '.'
+ buffer += (chr != '_');
+ if (unlikely(chr > 127)) goto parse_failure;
+ if (unlikely(last_was_punctuation & is_punctuation)) goto parse_failure;
+ last_was_punctuation = is_punctuation;
+ }
+ if (unlikely(last_was_punctuation)) goto parse_failure;
+ *buffer = '\0';
+ return buffer;
+
+parse_failure:
+ return NULL;
+}
+
+static double __Pyx__PyUnicode_AsDouble_inf_nan(const void* data, int kind, Py_ssize_t start, Py_ssize_t length) {
+ int matches = 1;
+ Py_UCS4 chr;
+ Py_UCS4 sign = PyUnicode_READ(kind, data, start);
+ int is_signed = (sign == '-') | (sign == '+');
+ start += is_signed;
+ length -= is_signed;
+
+ switch (PyUnicode_READ(kind, data, start)) {
+ #ifdef Py_NAN
+ case 'n':
+ case 'N':
+ if (unlikely(length != 3)) goto parse_failure;
+ chr = PyUnicode_READ(kind, data, start+1);
+ matches &= (chr == 'a') | (chr == 'A');
+ chr = PyUnicode_READ(kind, data, start+2);
+ matches &= (chr == 'n') | (chr == 'N');
+ if (unlikely(!matches)) goto parse_failure;
+ return (sign == '-') ? -Py_NAN : Py_NAN;
+ #endif
+ case 'i':
+ case 'I':
+ if (unlikely(length < 3)) goto parse_failure;
+ chr = PyUnicode_READ(kind, data, start+1);
+ matches &= (chr == 'n') | (chr == 'N');
+ chr = PyUnicode_READ(kind, data, start+2);
+ matches &= (chr == 'f') | (chr == 'F');
+ if (likely(length == 3 && matches))
+ return (sign == '-') ? -Py_HUGE_VAL : Py_HUGE_VAL;
+ if (unlikely(length != 8)) goto parse_failure;
+ chr = PyUnicode_READ(kind, data, start+3);
+ matches &= (chr == 'i') | (chr == 'I');
+ chr = PyUnicode_READ(kind, data, start+4);
+ matches &= (chr == 'n') | (chr == 'N');
+ chr = PyUnicode_READ(kind, data, start+5);
+ matches &= (chr == 'i') | (chr == 'I');
+ chr = PyUnicode_READ(kind, data, start+6);
+ matches &= (chr == 't') | (chr == 'T');
+ chr = PyUnicode_READ(kind, data, start+7);
+ matches &= (chr == 'y') | (chr == 'Y');
+ if (unlikely(!matches)) goto parse_failure;
+ return (sign == '-') ? -Py_HUGE_VAL : Py_HUGE_VAL;
+ case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
+ break;
+ default:
+ goto parse_failure;
+ }
+ return 0.0;
+parse_failure:
+ return -1.0;
+}
+
+static double __Pyx_PyUnicode_AsDouble_WithSpaces(PyObject *obj) {
+ double value;
+ const char *last;
+ char *end;
+ Py_ssize_t start, length = PyUnicode_GET_LENGTH(obj);
+ const int kind = PyUnicode_KIND(obj);
+ const void* data = PyUnicode_DATA(obj);
+
+ // strip spaces at start and end
+ start = 0;
+ while (Py_UNICODE_ISSPACE(PyUnicode_READ(kind, data, start)))
+ start++;
+ while (start < length - 1 && Py_UNICODE_ISSPACE(PyUnicode_READ(kind, data, length - 1)))
+ length--;
+ length -= start;
+ if (unlikely(length <= 0)) goto fallback;
+
+ // parse NaN / inf
+ value = __Pyx__PyUnicode_AsDouble_inf_nan(data, kind, start, length);
+ if (unlikely(value == -1.0)) goto fallback;
+ if (value != 0.0) return value;
+
+ if (length < 40) {
+ char number[40];
+ last = __Pyx__PyUnicode_AsDouble_Copy(data, kind, number, start, start + length);
+ if (unlikely(!last)) goto fallback;
+ value = PyOS_string_to_double(number, &end, NULL);
} else {
- PyObject* args = PyTuple_New(1);
- if (unlikely(!args)) goto bad;
- PyTuple_SET_ITEM(args, 0, obj);
- float_value = PyObject_Call((PyObject*)&PyFloat_Type, args, 0);
- PyTuple_SET_ITEM(args, 0, 0);
- Py_DECREF(args);
+ char *number = (char*) PyMem_Malloc((length + 1) * sizeof(char));
+ if (unlikely(!number)) goto fallback;
+ last = __Pyx__PyUnicode_AsDouble_Copy(data, kind, number, start, start + length);
+ if (unlikely(!last)) {
+ PyMem_Free(number);
+ goto fallback;
+ }
+ value = PyOS_string_to_double(number, &end, NULL);
+ PyMem_Free(number);
+ }
+ if (likely(end == last) || (value == (double)-1 && PyErr_Occurred())) {
+ return value;
+ }
+fallback:
+ return __Pyx_SlowPyString_AsDouble(obj);
+}
+#endif
+
+static CYTHON_INLINE double __Pyx_PyUnicode_AsDouble(PyObject *obj) {
+ // Currently not optimised for Py2.7.
+#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY
+ if (unlikely(__Pyx_PyUnicode_READY(obj) == -1))
+ return (double)-1;
+ if (likely(PyUnicode_IS_ASCII(obj))) {
+ const char *s;
+ Py_ssize_t length;
+ s = PyUnicode_AsUTF8AndSize(obj, &length);
+ return __Pyx__PyBytes_AsDouble(obj, s, length);
}
+ return __Pyx_PyUnicode_AsDouble_WithSpaces(obj);
+#else
+ return __Pyx_SlowPyString_AsDouble(obj);
+#endif
+}
+
+
+/////////////// pybytes_as_double.proto ///////////////
+
+static double __Pyx_SlowPyString_AsDouble(PyObject *obj);/*proto*/
+static double __Pyx__PyBytes_AsDouble(PyObject *obj, const char* start, Py_ssize_t length);/*proto*/
+
+static CYTHON_INLINE double __Pyx_PyBytes_AsDouble(PyObject *obj) {
+ return __Pyx__PyBytes_AsDouble(obj, PyBytes_AS_STRING(obj), PyBytes_GET_SIZE(obj));
+}
+static CYTHON_INLINE double __Pyx_PyByteArray_AsDouble(PyObject *obj) {
+ return __Pyx__PyBytes_AsDouble(obj, PyByteArray_AS_STRING(obj), PyByteArray_GET_SIZE(obj));
+}
+
+
+/////////////// pybytes_as_double ///////////////
+
+static double __Pyx_SlowPyString_AsDouble(PyObject *obj) {
+ PyObject *float_value;
+#if PY_MAJOR_VERSION >= 3
+ float_value = PyFloat_FromString(obj);
+#else
+ float_value = PyFloat_FromString(obj, 0);
#endif
if (likely(float_value)) {
double value = PyFloat_AS_DOUBLE(float_value);
Py_DECREF(float_value);
return value;
}
-bad:
return (double)-1;
}
+static const char* __Pyx__PyBytes_AsDouble_Copy(const char* start, char* buffer, Py_ssize_t length) {
+ // number must not start with punctuation
+ int last_was_punctuation = 1;
+ Py_ssize_t i;
+ for (i=0; i < length; i++) {
+ char chr = start[i];
+ int is_punctuation = (chr == '_') | (chr == '.') | (chr == 'e') | (chr == 'E');
+ *buffer = chr;
+ buffer += (chr != '_');
+ // reject sequences of '_' and '.'
+ if (unlikely(last_was_punctuation & is_punctuation)) goto parse_failure;
+ last_was_punctuation = is_punctuation;
+ }
+ if (unlikely(last_was_punctuation)) goto parse_failure;
+ *buffer = '\0';
+ return buffer;
+
+parse_failure:
+ return NULL;
+}
+
+static double __Pyx__PyBytes_AsDouble_inf_nan(const char* start, Py_ssize_t length) {
+ int matches = 1;
+ char sign = start[0];
+ int is_signed = (sign == '+') | (sign == '-');
+ start += is_signed;
+ length -= is_signed;
+
+ switch (start[0]) {
+ #ifdef Py_NAN
+ case 'n':
+ case 'N':
+ if (unlikely(length != 3)) goto parse_failure;
+ matches &= (start[1] == 'a' || start[1] == 'A');
+ matches &= (start[2] == 'n' || start[2] == 'N');
+ if (unlikely(!matches)) goto parse_failure;
+ return (sign == '-') ? -Py_NAN : Py_NAN;
+ #endif
+ case 'i':
+ case 'I':
+ if (unlikely(length < 3)) goto parse_failure;
+ matches &= (start[1] == 'n' || start[1] == 'N');
+ matches &= (start[2] == 'f' || start[2] == 'F');
+ if (likely(length == 3 && matches))
+ return (sign == '-') ? -Py_HUGE_VAL : Py_HUGE_VAL;
+ if (unlikely(length != 8)) goto parse_failure;
+ matches &= (start[3] == 'i' || start[3] == 'I');
+ matches &= (start[4] == 'n' || start[4] == 'N');
+ matches &= (start[5] == 'i' || start[5] == 'I');
+ matches &= (start[6] == 't' || start[6] == 'T');
+ matches &= (start[7] == 'y' || start[7] == 'Y');
+ if (unlikely(!matches)) goto parse_failure;
+ return (sign == '-') ? -Py_HUGE_VAL : Py_HUGE_VAL;
+ case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
+ break;
+ default:
+ goto parse_failure;
+ }
+ return 0.0;
+parse_failure:
+ return -1.0;
+}
+
+static CYTHON_INLINE int __Pyx__PyBytes_AsDouble_IsSpace(char ch) {
+ // see Py_ISSPACE() in CPython
+ // https://github.com/python/cpython/blob/master/Python/pyctype.c
+ return (ch == 0x20) | !((ch < 0x9) | (ch > 0xd));
+}
+
+CYTHON_UNUSED static double __Pyx__PyBytes_AsDouble(PyObject *obj, const char* start, Py_ssize_t length) {
+ double value;
+ Py_ssize_t i, digits;
+ const char *last = start + length;
+ char *end;
+
+ // strip spaces at start and end
+ while (__Pyx__PyBytes_AsDouble_IsSpace(*start))
+ start++;
+ while (start < last - 1 && __Pyx__PyBytes_AsDouble_IsSpace(last[-1]))
+ last--;
+ length = last - start;
+ if (unlikely(length <= 0)) goto fallback;
+
+ // parse NaN / inf
+ value = __Pyx__PyBytes_AsDouble_inf_nan(start, length);
+ if (unlikely(value == -1.0)) goto fallback;
+ if (value != 0.0) return value;
+
+ // look for underscores
+ digits = 0;
+ for (i=0; i < length; digits += start[i++] != '_');
+
+ if (likely(digits == length)) {
+ value = PyOS_string_to_double(start, &end, NULL);
+ } else if (digits < 40) {
+ char number[40];
+ last = __Pyx__PyBytes_AsDouble_Copy(start, number, length);
+ if (unlikely(!last)) goto fallback;
+ value = PyOS_string_to_double(number, &end, NULL);
+ } else {
+ char *number = (char*) PyMem_Malloc((digits + 1) * sizeof(char));
+ if (unlikely(!number)) goto fallback;
+ last = __Pyx__PyBytes_AsDouble_Copy(start, number, length);
+ if (unlikely(!last)) {
+ PyMem_Free(number);
+ goto fallback;
+ }
+ value = PyOS_string_to_double(number, &end, NULL);
+ PyMem_Free(number);
+ }
+ if (likely(end == last) || (value == (double)-1 && PyErr_Occurred())) {
+ return value;
+ }
+fallback:
+ return __Pyx_SlowPyString_AsDouble(obj);
+}
+
/////////////// PyNumberPow2.proto ///////////////
@@ -648,7 +969,7 @@ static PyObject* __Pyx__PyNumber_PowerOf2(PyObject *two, PyObject *exp, PyObject
static PyObject* __Pyx__PyNumber_PowerOf2(PyObject *two, PyObject *exp, PyObject *none, int inplace) {
// in CPython, 1<<N is substantially faster than 2**N
-// see http://bugs.python.org/issue21420
+// see https://bugs.python.org/issue21420
#if !CYTHON_COMPILING_IN_PYPY
Py_ssize_t shiftby;
#if PY_MAJOR_VERSION < 3
@@ -658,14 +979,12 @@ static PyObject* __Pyx__PyNumber_PowerOf2(PyObject *two, PyObject *exp, PyObject
#endif
if (likely(PyLong_CheckExact(exp))) {
#if CYTHON_USE_PYLONG_INTERNALS
- const Py_ssize_t size = Py_SIZE(exp);
- // tuned to optimise branch prediction
- if (likely(size == 1)) {
- shiftby = ((PyLongObject*)exp)->ob_digit[0];
- } else if (size == 0) {
+ if (__Pyx_PyLong_IsZero(exp)) {
return PyInt_FromLong(1L);
- } else if (unlikely(size < 0)) {
+ } else if (__Pyx_PyLong_IsNeg(exp)) {
goto fallback;
+ } else if (__Pyx_PyLong_IsCompact(exp)) {
+ shiftby = __Pyx_PyLong_CompactValueUnsigned(exp);
} else {
shiftby = PyLong_AsSsize_t(exp);
}
@@ -722,7 +1041,9 @@ return_compare = (
)
}}
-static CYTHON_INLINE {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(PyObject *op1, PyObject *op2, CYTHON_UNUSED long intval, CYTHON_UNUSED long inplace) {
+static CYTHON_INLINE {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(PyObject *op1, PyObject *op2, long intval, long inplace) {
+ CYTHON_MAYBE_UNUSED_VAR(intval);
+ CYTHON_UNUSED_VAR(inplace);
if (op1 == op2) {
{{return_true if op == 'Eq' else return_false}};
}
@@ -739,21 +1060,18 @@ static CYTHON_INLINE {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject els
if (likely(PyLong_CheckExact({{pyval}}))) {
int unequal;
unsigned long uintval;
- Py_ssize_t size = Py_SIZE({{pyval}});
- const digit* digits = ((PyLongObject*){{pyval}})->ob_digit;
+ Py_ssize_t size = __Pyx_PyLong_DigitCount({{pyval}});
+ const digit* digits = __Pyx_PyLong_Digits({{pyval}});
if (intval == 0) {
- // == 0 => Py_SIZE(pyval) == 0
- {{return_compare('size', '0', c_op)}}
+ {{return_compare('__Pyx_PyLong_IsZero(%s)' % pyval, '1', c_op)}}
} else if (intval < 0) {
- // < 0 => Py_SIZE(pyval) < 0
- if (size >= 0)
+ if (__Pyx_PyLong_IsNonNeg({{pyval}}))
{{return_false if op == 'Eq' else return_true}};
// both are negative => can use absolute values now.
intval = -intval;
- size = -size;
} else {
// > 0 => Py_SIZE(pyval) > 0
- if (size <= 0)
+ if (__Pyx_PyLong_IsNeg({{pyval}}))
{{return_false if op == 'Eq' else return_true}};
}
// After checking that the sign is the same (and excluding 0), now compare the absolute values.
@@ -776,7 +1094,11 @@ static CYTHON_INLINE {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject els
if (PyFloat_CheckExact({{pyval}})) {
const long {{'a' if order == 'CObj' else 'b'}} = intval;
+#if CYTHON_COMPILING_IN_LIMITED_API
+ double {{ival}} = __pyx_PyFloat_AsDouble({{pyval}});
+#else
double {{ival}} = PyFloat_AS_DOUBLE({{pyval}});
+#endif
{{return_compare('(double)a', '(double)b', c_op)}}
}
@@ -807,29 +1129,27 @@ static {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op
{{py: return_false = 'Py_RETURN_FALSE' if ret_type.is_pyobject else 'return 0'}}
{{py: slot_name = {'TrueDivide': 'true_divide', 'FloorDivide': 'floor_divide'}.get(op, op.lower()) }}
{{py: cfunc_name = '__Pyx_PyInt_%s%s%s' % ('' if ret_type.is_pyobject else 'Bool', op, order)}}
-{{py: zerodiv_check = lambda operand, _cfunc_name=cfunc_name: '%s_ZeroDivisionError(%s)' % (_cfunc_name, operand)}}
{{py:
c_op = {
- 'Add': '+', 'Subtract': '-', 'Remainder': '%', 'TrueDivide': '/', 'FloorDivide': '/',
+ 'Add': '+', 'Subtract': '-', 'Multiply': '*', 'Remainder': '%', 'TrueDivide': '/', 'FloorDivide': '/',
'Or': '|', 'Xor': '^', 'And': '&', 'Rshift': '>>', 'Lshift': '<<',
'Eq': '==', 'Ne': '!=',
}[op]
}}
+{{py:
+def zerodiv_check(operand, optype='integer', _is_mod=op == 'Remainder', _needs_check=(order == 'CObj' and c_op in '%/')):
+ return (((
+ 'if (unlikely(zerodivision_check && ((%s) == 0))) {'
+ ' PyErr_SetString(PyExc_ZeroDivisionError, "%s division%s by zero");'
+ ' return NULL;'
+ '}') % (operand, optype, ' or modulo' if _is_mod else '')
+ ) if _needs_check else '')
+}}
-{{if op in ('TrueDivide', 'FloorDivide', 'Remainder')}}
-#if PY_MAJOR_VERSION < 3 || CYTHON_USE_PYLONG_INTERNALS
-#define {{zerodiv_check('operand')}} \
- if (unlikely(zerodivision_check && ((operand) == 0))) { \
- PyErr_SetString(PyExc_ZeroDivisionError, "integer division{{if op == 'Remainder'}} or modulo{{endif}} by zero"); \
- return NULL; \
- }
-#endif
-{{endif}}
-
-static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, CYTHON_UNUSED long intval, int inplace, int zerodivision_check) {
- // Prevent "unused" warnings.
- (void)inplace;
- (void)zerodivision_check;
+static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check) {
+ CYTHON_MAYBE_UNUSED_VAR(intval);
+ CYTHON_MAYBE_UNUSED_VAR(inplace);
+ CYTHON_UNUSED_VAR(zerodivision_check);
{{if op in ('Eq', 'Ne')}}
if (op1 == op2) {
@@ -844,6 +1164,7 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, CYTHON_UNUSED
long x;
{{endif}}
long {{ival}} = PyInt_AS_LONG({{pyval}});
+ {{zerodiv_check('b')}}
{{if op in ('Eq', 'Ne')}}
if (a {{c_op}} b) {
@@ -859,21 +1180,18 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, CYTHON_UNUSED
return PyInt_FromLong(x);
return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
{{elif c_op == '%'}}
- {{zerodiv_check('b')}}
// see ExprNodes.py :: mod_int_utility_code
x = a % b;
x += ((x != 0) & ((x ^ b) < 0)) * b;
return PyInt_FromLong(x);
{{elif op == 'TrueDivide'}}
- {{zerodiv_check('b')}}
if (8 * sizeof(long) <= 53 || likely(labs({{ival}}) <= ((PY_LONG_LONG)1 << 53))) {
return PyFloat_FromDouble((double)a / (double)b);
}
// let Python do the rounding
return PyInt_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
{{elif op == 'FloorDivide'}}
- // INT_MIN / -1 is the only case that overflows, b == 0 is an error case
- {{zerodiv_check('b')}}
+ // INT_MIN / -1 is the only case that overflows
if (unlikely(b == -1 && ((unsigned long)a) == 0-(unsigned long)a))
return PyInt_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
else {
@@ -889,6 +1207,19 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, CYTHON_UNUSED
if (likely(b < (long) (sizeof(long)*8) && a == (a << b) >> b) || !a) {
return PyInt_FromLong(a {{c_op}} b);
}
+ {{elif c_op == '*'}}
+#ifdef HAVE_LONG_LONG
+ if (sizeof(PY_LONG_LONG) > sizeof(long)) {
+ PY_LONG_LONG result = (PY_LONG_LONG)a {{c_op}} (PY_LONG_LONG)b;
+ return (result >= LONG_MIN && result <= LONG_MAX) ?
+ PyInt_FromLong((long)result) : PyLong_FromLongLong(result);
+ }
+#endif
+#if CYTHON_USE_TYPE_SLOTS
+ return PyInt_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
+#else
+ return PyNumber_{{op}}(op1, op2);
+#endif
{{else}}
// other operations are safe, no overflow
return PyInt_FromLong(a {{c_op}} b);
@@ -906,26 +1237,54 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, CYTHON_UNUSED
PY_LONG_LONG ll{{ival}}, llx;
#endif
{{endif}}
- const digit* digits = ((PyLongObject*){{pyval}})->ob_digit;
- const Py_ssize_t size = Py_SIZE({{pyval}});
+ {{if c_op == '&'}}
+ // special case for &-ing arbitrarily large numbers with known single digit operands
+ if ((intval & PyLong_MASK) == intval) {
+ long result = intval & (long) __Pyx_PyLong_CompactValue({{pyval}});
+ return PyLong_FromLong(result);
+ }
+ {{endif}}
+ // special cases for 0: + - * % / // | ^ & >> <<
+ if (unlikely(__Pyx_PyLong_IsZero({{pyval}}))) {
+ {{if order == 'CObj' and c_op in '%/'}}
+ // division by zero!
+ {{zerodiv_check('0')}}
+ {{elif order == 'CObj' and c_op in '+-|^>><<'}}
+ // x == x+0 == x-0 == x|0 == x^0 == x>>0 == x<<0
+ return __Pyx_NewRef(op1);
+ {{elif order == 'CObj' and c_op in '*&'}}
+ // 0 == x*0 == x&0
+ return __Pyx_NewRef(op2);
+ {{elif order == 'ObjC' and c_op in '+|^'}}
+ // x == 0+x == 0|x == 0^x
+ return __Pyx_NewRef(op2);
+ {{elif order == 'ObjC' and c_op == '-'}}
+ // -x == 0-x
+ return PyLong_FromLong(-intval);
+ {{elif order == 'ObjC' and (c_op in '*%&>><<' or op == 'FloorDivide')}}
+ // 0 == 0*x == 0%x == 0&x == 0>>x == 0<<x == 0//x
+ return __Pyx_NewRef(op1);
+ {{endif}}
+ }
// handle most common case first to avoid indirect branch and optimise branch prediction
- if (likely(__Pyx_sst_abs(size) <= 1)) {
- {{ival}} = likely(size) ? digits[0] : 0;
- if (size == -1) {{ival}} = -{{ival}};
+ if (likely(__Pyx_PyLong_IsCompact({{pyval}}))) {
+ {{ival}} = __Pyx_PyLong_CompactValue({{pyval}});
} else {
+ const digit* digits = __Pyx_PyLong_Digits({{pyval}});
+ const Py_ssize_t size = __Pyx_PyLong_SignedDigitCount({{pyval}});
switch (size) {
{{for _size in range(2, 5)}}
{{for _case in (-_size, _size)}}
case {{_case}}:
- if (8 * sizeof(long) - 1 > {{_size}} * PyLong_SHIFT{{if op == 'TrueDivide'}} && {{_size-1}} * PyLong_SHIFT < 53{{endif}}) {
+ if (8 * sizeof(long) - 1 > {{_size}} * PyLong_SHIFT{{if c_op == '*'}}+30{{endif}}{{if op == 'TrueDivide'}} && {{_size-1}} * PyLong_SHIFT < 53{{endif}}) {
{{ival}} = {{'-' if _case < 0 else ''}}(long) {{pylong_join(_size, 'digits')}};
break;
{{if op not in ('Eq', 'Ne', 'TrueDivide')}}
-#ifdef HAVE_LONG_LONG
- } else if (8 * sizeof(PY_LONG_LONG) - 1 > {{_size}} * PyLong_SHIFT) {
+ #ifdef HAVE_LONG_LONG
+ } else if (8 * sizeof(PY_LONG_LONG) - 1 > {{_size}} * PyLong_SHIFT{{if c_op == '*'}}+30{{endif}}) {
ll{{ival}} = {{'-' if _case < 0 else ''}}(PY_LONG_LONG) {{pylong_join(_size, 'digits', 'unsigned PY_LONG_LONG')}};
goto long_long;
-#endif
+ #endif
{{endif}}
}
// if size doesn't fit into a long or PY_LONG_LONG anymore, fall through to default
@@ -954,20 +1313,26 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, CYTHON_UNUSED
{{return_false}};
}
{{else}}
- {{if c_op == '%'}}
- {{zerodiv_check('b')}}
+ {{if c_op == '*'}}
+ CYTHON_UNUSED_VAR(a);
+ CYTHON_UNUSED_VAR(b);
+ #ifdef HAVE_LONG_LONG
+ ll{{ival}} = {{ival}};
+ goto long_long;
+ #else
+ return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
+ #endif
+ {{elif c_op == '%'}}
// see ExprNodes.py :: mod_int_utility_code
x = a % b;
x += ((x != 0) & ((x ^ b) < 0)) * b;
{{elif op == 'TrueDivide'}}
- {{zerodiv_check('b')}}
if ((8 * sizeof(long) <= 53 || likely(labs({{ival}}) <= ((PY_LONG_LONG)1 << 53)))
- || __Pyx_sst_abs(size) <= 52 / PyLong_SHIFT) {
+ || __Pyx_PyLong_DigitCount({{pyval}}) <= 52 / PyLong_SHIFT) {
return PyFloat_FromDouble((double)a / (double)b);
}
return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
{{elif op == 'FloorDivide'}}
- {{zerodiv_check('b')}}
{
long q, r;
// see ExprNodes.py :: div_int_utility_code
@@ -1020,10 +1385,14 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, CYTHON_UNUSED
}
#endif
- {{if c_op in '+-' or op in ('TrueDivide', 'Eq', 'Ne')}}
+ {{if c_op in '+-*' or op in ('TrueDivide', 'Eq', 'Ne')}}
if (PyFloat_CheckExact({{pyval}})) {
const long {{'a' if order == 'CObj' else 'b'}} = intval;
+#if CYTHON_COMPILING_IN_LIMITED_API
+ double {{ival}} = __pyx_PyFloat_AsDouble({{pyval}});
+#else
double {{ival}} = PyFloat_AS_DOUBLE({{pyval}});
+#endif
{{if op in ('Eq', 'Ne')}}
if ((double)a {{c_op}} (double)b) {
{{return_true}};
@@ -1032,12 +1401,7 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, CYTHON_UNUSED
}
{{else}}
double result;
- {{if op == 'TrueDivide'}}
- if (unlikely(zerodivision_check && b == 0)) {
- PyErr_SetString(PyExc_ZeroDivisionError, "float division by zero");
- return NULL;
- }
- {{endif}}
+ {{zerodiv_check('b', 'float')}}
// copied from floatobject.c in Py3.5:
PyFPE_START_PROTECT("{{op.lower() if not op.endswith('Divide') else 'divide'}}", return NULL)
result = ((double)a) {{c_op}} (double)b;
@@ -1078,27 +1442,27 @@ static {{c_ret_type}} __Pyx_PyFloat_{{'' if ret_type.is_pyobject else 'Bool'}}{{
{{py: return_false = 'Py_RETURN_FALSE' if ret_type.is_pyobject else 'return 0'}}
{{py: pyval, fval = ('op2', 'b') if order == 'CObj' else ('op1', 'a') }}
{{py: cfunc_name = '__Pyx_PyFloat_%s%s%s' % ('' if ret_type.is_pyobject else 'Bool', op, order) }}
-{{py: zerodiv_check = lambda operand, _cfunc_name=cfunc_name: '%s_ZeroDivisionError(%s)' % (_cfunc_name, operand)}}
{{py:
c_op = {
'Add': '+', 'Subtract': '-', 'TrueDivide': '/', 'Divide': '/', 'Remainder': '%',
'Eq': '==', 'Ne': '!=',
}[op]
}}
-
-{{if order == 'CObj' and c_op in '%/'}}
-#define {{zerodiv_check('operand')}} if (unlikely(zerodivision_check && ((operand) == 0))) { \
- PyErr_SetString(PyExc_ZeroDivisionError, "float division{{if op == 'Remainder'}} or modulo{{endif}} by zero"); \
- return NULL; \
-}
-{{endif}}
+{{py:
+def zerodiv_check(operand, _is_mod=op == 'Remainder', _needs_check=(order == 'CObj' and c_op in '%/')):
+ return (((
+ 'if (unlikely(zerodivision_check && ((%s) == 0.0))) {'
+ ' PyErr_SetString(PyExc_ZeroDivisionError, "float division%s by zero");'
+ ' return NULL;'
+ '}') % (operand, ' or modulo' if _is_mod else '')
+ ) if _needs_check else '')
+}}
static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, double floatval, int inplace, int zerodivision_check) {
const double {{'a' if order == 'CObj' else 'b'}} = floatval;
double {{fval}}{{if op not in ('Eq', 'Ne')}}, result{{endif}};
- // Prevent "unused" warnings.
- (void)inplace;
- (void)zerodivision_check;
+ CYTHON_UNUSED_VAR(inplace);
+ CYTHON_UNUSED_VAR(zerodivision_check);
{{if op in ('Eq', 'Ne')}}
if (op1 == op2) {
@@ -1107,57 +1471,69 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, double floatv
{{endif}}
if (likely(PyFloat_CheckExact({{pyval}}))) {
+#if CYTHON_COMPILING_IN_LIMITED_API
+ {{fval}} = __pyx_PyFloat_AsDouble({{pyval}});
+#else
{{fval}} = PyFloat_AS_DOUBLE({{pyval}});
- {{if order == 'CObj' and c_op in '%/'}}{{zerodiv_check(fval)}}{{endif}}
+#endif
+ {{zerodiv_check(fval)}}
} else
#if PY_MAJOR_VERSION < 3
if (likely(PyInt_CheckExact({{pyval}}))) {
{{fval}} = (double) PyInt_AS_LONG({{pyval}});
- {{if order == 'CObj' and c_op in '%/'}}{{zerodiv_check(fval)}}{{endif}}
+ {{zerodiv_check(fval)}}
} else
#endif
if (likely(PyLong_CheckExact({{pyval}}))) {
#if CYTHON_USE_PYLONG_INTERNALS
- const digit* digits = ((PyLongObject*){{pyval}})->ob_digit;
- const Py_ssize_t size = Py_SIZE({{pyval}});
- switch (size) {
- case 0: {{if order == 'CObj' and c_op in '%/'}}{{zerodiv_check('0')}}{{else}}{{fval}} = 0.0;{{endif}} break;
- case -1: {{fval}} = -(double) digits[0]; break;
- case 1: {{fval}} = (double) digits[0]; break;
- {{for _size in (2, 3, 4)}}
- case -{{_size}}:
- case {{_size}}:
- if (8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT && ((8 * sizeof(unsigned long) < 53) || ({{_size-1}} * PyLong_SHIFT < 53))) {
- {{fval}} = (double) {{pylong_join(_size, 'digits')}};
- // let CPython do its own float rounding from 2**53 on (max. consecutive integer in double float)
- if ((8 * sizeof(unsigned long) < 53) || ({{_size}} * PyLong_SHIFT < 53) || ({{fval}} < (double) ((PY_LONG_LONG)1 << 53))) {
- if (size == {{-_size}})
- {{fval}} = -{{fval}};
- break;
+ if (__Pyx_PyLong_IsZero({{pyval}})) {
+ {{fval}} = 0.0;
+ {{zerodiv_check(fval)}}
+ } else if (__Pyx_PyLong_IsCompact({{pyval}})) {
+ {{fval}} = (double) __Pyx_PyLong_CompactValue({{pyval}});
+ } else {
+ const digit* digits = __Pyx_PyLong_Digits({{pyval}});
+ const Py_ssize_t size = __Pyx_PyLong_SignedDigitCount({{pyval}});
+ switch (size) {
+ {{for _size in (2, 3, 4)}}
+ case -{{_size}}:
+ case {{_size}}:
+ if (8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT && ((8 * sizeof(unsigned long) < 53) || ({{_size-1}} * PyLong_SHIFT < 53))) {
+ {{fval}} = (double) {{pylong_join(_size, 'digits')}};
+ // let CPython do its own float rounding from 2**53 on (max. consecutive integer in double float)
+ if ((8 * sizeof(unsigned long) < 53) || ({{_size}} * PyLong_SHIFT < 53) || ({{fval}} < (double) ((PY_LONG_LONG)1 << 53))) {
+ if (size == {{-_size}})
+ {{fval}} = -{{fval}};
+ break;
+ }
}
- }
- // Fall through if size doesn't fit safely into a double anymore.
- // It may not be obvious that this is a safe fall-through given the "fval < 2**53"
- // check above. However, the number of digits that CPython uses for a given PyLong
- // value is minimal, and together with the "(size-1) * SHIFT < 53" check above,
- // this should make it safe.
- CYTHON_FALLTHROUGH;
- {{endfor}}
- default:
- #else
- {
+ // Fall through if size doesn't fit safely into a double anymore.
+ // It may not be obvious that this is a safe fall-through given the "fval < 2**53"
+ // check above. However, the number of digits that CPython uses for a given PyLong
+ // value is minimal, and together with the "(size-1) * SHIFT < 53" check above,
+ // this should make it safe.
+ CYTHON_FALLTHROUGH;
+ {{endfor}}
+ default:
#endif
{{if op in ('Eq', 'Ne')}}
- return {{'' if ret_type.is_pyobject else '__Pyx_PyObject_IsTrueAndDecref'}}(
- PyFloat_Type.tp_richcompare({{'op1, op2' if order == 'CObj' else 'op2, op1'}}, Py_{{op.upper()}}));
+ return {{'' if ret_type.is_pyobject else '__Pyx_PyObject_IsTrueAndDecref'}}(
+ PyFloat_Type.tp_richcompare({{'op1, op2' if order == 'CObj' else 'op2, op1'}}, Py_{{op.upper()}}));
{{else}}
- {{fval}} = PyLong_AsDouble({{pyval}});
- if (unlikely({{fval}} == -1.0 && PyErr_Occurred())) return NULL;
- {{if order == 'CObj' and c_op in '%/'}}{{zerodiv_check(fval)}}{{endif}}
+ {{fval}} = PyLong_AsDouble({{pyval}});
+ if (unlikely({{fval}} == -1.0 && PyErr_Occurred())) return NULL;
+ {{if zerodiv_check(fval)}}
+ #if !CYTHON_USE_PYLONG_INTERNALS
+ {{zerodiv_check(fval)}}
+ #endif
+ {{endif}}
{{endif}}
+ #if CYTHON_USE_PYLONG_INTERNALS
+ }
}
+ #endif
} else {
{{if op in ('Eq', 'Ne')}}
return {{'' if ret_type.is_pyobject else '__Pyx_PyObject_IsTrueAndDecref'}}(
@@ -1177,7 +1553,6 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, double floatv
}
{{else}}
// copied from floatobject.c in Py3.5:
- {{if order == 'CObj' and c_op in '%/'}}{{zerodiv_check('b')}}{{endif}}
PyFPE_START_PROTECT("{{op.lower() if not op.endswith('Divide') else 'divide'}}", return NULL)
{{if c_op == '%'}}
result = fmod(a, b);
diff --git a/Cython/Utility/Overflow.c b/Cython/Utility/Overflow.c
index 0259c58f0..78e517717 100644
--- a/Cython/Utility/Overflow.c
+++ b/Cython/Utility/Overflow.c
@@ -20,7 +20,7 @@ TODO: Conditionally support 128-bit with intmax_t?
/////////////// Common.proto ///////////////
static int __Pyx_check_twos_complement(void) {
- if ((-1 != ~0)) {
+ if ((-1) != (~0)) {
PyErr_SetString(PyExc_RuntimeError, "Two's complement required for overflow checks.");
return 1;
} else if ((sizeof(short) == sizeof(int))) {
@@ -31,7 +31,6 @@ static int __Pyx_check_twos_complement(void) {
}
}
-#define __PYX_IS_UNSIGNED(type) ((((type) -1) > 0))
#define __PYX_SIGN_BIT(type) ((((unsigned type) 1) << (sizeof(type) * 8 - 1)))
#define __PYX_HALF_MAX(type) ((((type) 1) << (sizeof(type) * 8 - 2)))
#define __PYX_MIN(type) ((__PYX_IS_UNSIGNED(type) ? (type) 0 : 0 - __PYX_HALF_MAX(type) - __PYX_HALF_MAX(type)))
@@ -46,6 +45,24 @@ static int __Pyx_check_twos_complement(void) {
#define __Pyx_div_no_overflow(a, b, overflow) ((a) / (b))
#define __Pyx_div_const_no_overflow(a, b, overflow) ((a) / (b))
+#if defined(__has_builtin)
+# if __has_builtin(__builtin_add_overflow) && !defined(__ibmxl__)
+# define __PYX_HAVE_BUILTIN_OVERFLOW
+# endif
+#elif defined(__GNUC__) && (__GNUC__ >= 5) && (!defined(__INTEL_COMPILER) || (__INTEL_COMPILER >= 1800))
+# define __PYX_HAVE_BUILTIN_OVERFLOW
+#endif
+
+#if defined(__GNUC__)
+# define __Pyx_is_constant(x) (__builtin_constant_p(x))
+#elif defined(__has_builtin)
+# if __has_builtin(__builtin_constant_p)
+# define __Pyx_is_constant(x) (__builtin_constant_p(x))
+# endif
+#else
+# define __Pyx_is_constant(x) (0)
+#endif
+
/////////////// Common.init ///////////////
//@substitute: naming
@@ -56,6 +73,8 @@ if (unlikely(__Pyx_check_twos_complement())) {
/////////////// BaseCaseUnsigned.proto ///////////////
+{{if UINT == "long long"}}#ifdef HAVE_LONG_LONG{{endif}}
+
static CYTHON_INLINE {{UINT}} __Pyx_add_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow);
static CYTHON_INLINE {{UINT}} __Pyx_sub_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow);
static CYTHON_INLINE {{UINT}} __Pyx_mul_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow);
@@ -64,11 +83,41 @@ static CYTHON_INLINE {{UINT}} __Pyx_div_{{NAME}}_checking_overflow({{UINT}} a, {
// Use these when b is known at compile time.
#define __Pyx_add_const_{{NAME}}_checking_overflow __Pyx_add_{{NAME}}_checking_overflow
#define __Pyx_sub_const_{{NAME}}_checking_overflow __Pyx_sub_{{NAME}}_checking_overflow
+#if defined(__PYX_HAVE_BUILTIN_OVERFLOW)
+#define __Pyx_mul_const_{{NAME}}_checking_overflow __Pyx_mul_{{NAME}}_checking_overflow
+#else
static CYTHON_INLINE {{UINT}} __Pyx_mul_const_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} constant, int *overflow);
+#endif
#define __Pyx_div_const_{{NAME}}_checking_overflow __Pyx_div_{{NAME}}_checking_overflow
+{{if UINT == "long long"}}#endif{{endif}}
+
/////////////// BaseCaseUnsigned ///////////////
+{{if UINT == "long long"}}#ifdef HAVE_LONG_LONG{{endif}}
+
+#if defined(__PYX_HAVE_BUILTIN_OVERFLOW)
+
+static CYTHON_INLINE {{UINT}} __Pyx_add_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) {
+ {{UINT}} result;
+ *overflow |= __builtin_add_overflow(a, b, &result);
+ return result;
+}
+
+static CYTHON_INLINE {{UINT}} __Pyx_sub_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) {
+ {{UINT}} result;
+ *overflow |= __builtin_sub_overflow(a, b, &result);
+ return result;
+}
+
+static CYTHON_INLINE {{UINT}} __Pyx_mul_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) {
+ {{UINT}} result;
+ *overflow |= __builtin_mul_overflow(a, b, &result);
+ return result;
+}
+
+#else
+
static CYTHON_INLINE {{UINT}} __Pyx_add_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) {
{{UINT}} r = a + b;
*overflow |= r < a;
@@ -82,7 +131,12 @@ static CYTHON_INLINE {{UINT}} __Pyx_sub_{{NAME}}_checking_overflow({{UINT}} a, {
}
static CYTHON_INLINE {{UINT}} __Pyx_mul_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) {
- if ((sizeof({{UINT}}) < sizeof(unsigned long))) {
+ // if we have a constant, use the constant version
+ if (__Pyx_is_constant(b)) {
+ return __Pyx_mul_const_{{NAME}}_checking_overflow(a, b, overflow);
+ } else if (__Pyx_is_constant(a)) {
+ return __Pyx_mul_const_{{NAME}}_checking_overflow(b, a, overflow);
+ } else if ((sizeof({{UINT}}) < sizeof(unsigned long))) {
unsigned long big_r = ((unsigned long) a) * ((unsigned long) b);
{{UINT}} r = ({{UINT}}) big_r;
*overflow |= big_r != r;
@@ -95,21 +149,27 @@ static CYTHON_INLINE {{UINT}} __Pyx_mul_{{NAME}}_checking_overflow({{UINT}} a, {
return r;
#endif
} else {
- {{UINT}} prod = a * b;
- double dprod = ((double) a) * ((double) b);
- // Overflow results in an error of at least 2^sizeof(UINT),
- // whereas rounding represents an error on the order of 2^(sizeof(UINT)-53).
- *overflow |= fabs(dprod - prod) > (__PYX_MAX({{UINT}}) / 2);
- return prod;
+ return __Pyx_mul_const_{{NAME}}_checking_overflow(a, b, overflow);
}
}
static CYTHON_INLINE {{UINT}} __Pyx_mul_const_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) {
- if (b > 1) {
- *overflow |= a > __PYX_MAX({{UINT}}) / b;
+ // note that deliberately the overflow check is written such that it divides by b; this
+ // function is used when b is a constant thus the compiler should be able to eliminate the
+ // (very slow on most CPUs!) division operation
+ {{UINT}} prod;
+ if (__Pyx_is_constant(a) && !__Pyx_is_constant(b)) {
+ // if a is a compile-time constant and b isn't, swap them
+ {{UINT}} temp = b;
+ b = a;
+ a = temp;
}
- return a * b;
+ prod = a * b;
+ if (b != 0)
+ *overflow |= a > (__PYX_MAX({{UINT}}) / b);
+ return prod;
}
+#endif // __PYX_HAVE_BUILTIN_OVERFLOW
static CYTHON_INLINE {{UINT}} __Pyx_div_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) {
@@ -120,9 +180,13 @@ static CYTHON_INLINE {{UINT}} __Pyx_div_{{NAME}}_checking_overflow({{UINT}} a, {
return a / b;
}
+{{if UINT == "long long"}}#endif{{endif}}
+
/////////////// BaseCaseSigned.proto ///////////////
+{{if INT == "long long"}}#ifdef HAVE_LONG_LONG{{endif}}
+
static CYTHON_INLINE {{INT}} __Pyx_add_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow);
static CYTHON_INLINE {{INT}} __Pyx_sub_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow);
static CYTHON_INLINE {{INT}} __Pyx_mul_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow);
@@ -130,13 +194,43 @@ static CYTHON_INLINE {{INT}} __Pyx_div_{{NAME}}_checking_overflow({{INT}} a, {{I
// Use when b is known at compile time.
-static CYTHON_INLINE {{INT}} __Pyx_add_const_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow);
-static CYTHON_INLINE {{INT}} __Pyx_sub_const_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow);
+#define __Pyx_add_const_{{NAME}}_checking_overflow __Pyx_add_{{NAME}}_checking_overflow
+#define __Pyx_sub_const_{{NAME}}_checking_overflow __Pyx_sub_{{NAME}}_checking_overflow
+#if defined(__PYX_HAVE_BUILTIN_OVERFLOW)
+#define __Pyx_mul_const_{{NAME}}_checking_overflow __Pyx_mul_{{NAME}}_checking_overflow
+#else
static CYTHON_INLINE {{INT}} __Pyx_mul_const_{{NAME}}_checking_overflow({{INT}} a, {{INT}} constant, int *overflow);
+#endif
#define __Pyx_div_const_{{NAME}}_checking_overflow __Pyx_div_{{NAME}}_checking_overflow
+{{if INT == "long long"}}#endif{{endif}}
+
/////////////// BaseCaseSigned ///////////////
+{{if INT == "long long"}}#ifdef HAVE_LONG_LONG{{endif}}
+
+#if defined(__PYX_HAVE_BUILTIN_OVERFLOW)
+
+static CYTHON_INLINE {{INT}} __Pyx_add_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) {
+ {{INT}} result;
+ *overflow |= __builtin_add_overflow(a, b, &result);
+ return result;
+}
+
+static CYTHON_INLINE {{INT}} __Pyx_sub_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) {
+ {{INT}} result;
+ *overflow |= __builtin_sub_overflow(a, b, &result);
+ return result;
+}
+
+static CYTHON_INLINE {{INT}} __Pyx_mul_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) {
+ {{INT}} result;
+ *overflow |= __builtin_mul_overflow(a, b, &result);
+ return result;
+}
+
+#else
+
static CYTHON_INLINE {{INT}} __Pyx_add_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) {
if ((sizeof({{INT}}) < sizeof(long))) {
long big_r = ((long) a) + ((long) b);
@@ -151,40 +245,33 @@ static CYTHON_INLINE {{INT}} __Pyx_add_{{NAME}}_checking_overflow({{INT}} a, {{I
return r;
#endif
} else {
- // Signed overflow undefined, but unsigned overflow is well defined.
- {{INT}} r = ({{INT}}) ((unsigned {{INT}}) a + (unsigned {{INT}}) b);
+ // Signed overflow undefined, but unsigned overflow is well defined. Casting is
+ // implementation-defined, but we assume two's complement (see __Pyx_check_twos_complement
+ // above), and arithmetic in two's-complement is the same as unsigned arithmetic.
+ unsigned {{INT}} r = (unsigned {{INT}}) a + (unsigned {{INT}}) b;
// Overflow happened if the operands have the same sign, but the result
// has opposite sign.
- // sign(a) == sign(b) != sign(r)
- {{INT}} sign_a = __PYX_SIGN_BIT({{INT}}) & a;
- {{INT}} sign_b = __PYX_SIGN_BIT({{INT}}) & b;
- {{INT}} sign_r = __PYX_SIGN_BIT({{INT}}) & r;
- *overflow |= (sign_a == sign_b) & (sign_a != sign_r);
- return r;
- }
-}
-
-static CYTHON_INLINE {{INT}} __Pyx_add_const_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) {
- if (b > 0) {
- *overflow |= a > __PYX_MAX({{INT}}) - b;
- } else if (b < 0) {
- *overflow |= a < __PYX_MIN({{INT}}) - b;
+ *overflow |= (((unsigned {{INT}})a ^ r) & ((unsigned {{INT}})b ^ r)) >> (8 * sizeof({{INT}}) - 1);
+ return ({{INT}}) r;
}
- return a + b;
}
static CYTHON_INLINE {{INT}} __Pyx_sub_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) {
- *overflow |= b == __PYX_MIN({{INT}});
- return __Pyx_add_{{NAME}}_checking_overflow(a, -b, overflow);
-}
-
-static CYTHON_INLINE {{INT}} __Pyx_sub_const_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) {
- *overflow |= b == __PYX_MIN({{INT}});
- return __Pyx_add_const_{{NAME}}_checking_overflow(a, -b, overflow);
+ // Compilers don't handle widening as well in the subtraction case, so don't bother
+ unsigned {{INT}} r = (unsigned {{INT}}) a - (unsigned {{INT}}) b;
+ // Overflow happened if the operands differing signs, and the result
+ // has opposite sign to a.
+ *overflow |= (((unsigned {{INT}})a ^ (unsigned {{INT}})b) & ((unsigned {{INT}})a ^ r)) >> (8 * sizeof({{INT}}) - 1);
+ return ({{INT}}) r;
}
static CYTHON_INLINE {{INT}} __Pyx_mul_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) {
- if ((sizeof({{INT}}) < sizeof(long))) {
+ // if we have a constant, use the constant version
+ if (__Pyx_is_constant(b)) {
+ return __Pyx_mul_const_{{NAME}}_checking_overflow(a, b, overflow);
+ } else if (__Pyx_is_constant(a)) {
+ return __Pyx_mul_const_{{NAME}}_checking_overflow(b, a, overflow);
+ } else if ((sizeof({{INT}}) < sizeof(long))) {
long big_r = ((long) a) * ((long) b);
{{INT}} r = ({{INT}}) big_r;
*overflow |= big_r != r;
@@ -197,16 +284,20 @@ static CYTHON_INLINE {{INT}} __Pyx_mul_{{NAME}}_checking_overflow({{INT}} a, {{I
return ({{INT}}) r;
#endif
} else {
- {{INT}} prod = a * b;
- double dprod = ((double) a) * ((double) b);
- // Overflow results in an error of at least 2^sizeof(INT),
- // whereas rounding represents an error on the order of 2^(sizeof(INT)-53).
- *overflow |= fabs(dprod - prod) > (__PYX_MAX({{INT}}) / 2);
- return prod;
+ return __Pyx_mul_const_{{NAME}}_checking_overflow(a, b, overflow);
}
}
static CYTHON_INLINE {{INT}} __Pyx_mul_const_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) {
+ // note that deliberately all these comparisons are written such that they divide by b; this
+ // function is used when b is a constant thus the compiler should be able to eliminate the
+ // (very slow on most CPUs!) division operations
+ if (__Pyx_is_constant(a) && !__Pyx_is_constant(b)) {
+ // if a is a compile-time constant and b isn't, swap them
+ {{INT}} temp = b;
+ b = a;
+ a = temp;
+ }
if (b > 1) {
*overflow |= a > __PYX_MAX({{INT}}) / b;
*overflow |= a < __PYX_MIN({{INT}}) / b;
@@ -216,18 +307,21 @@ static CYTHON_INLINE {{INT}} __Pyx_mul_const_{{NAME}}_checking_overflow({{INT}}
*overflow |= a > __PYX_MIN({{INT}}) / b;
*overflow |= a < __PYX_MAX({{INT}}) / b;
}
- return a * b;
+ return ({{INT}}) (((unsigned {{INT}})a) * ((unsigned {{INT}}) b));
}
+#endif // defined(__PYX_HAVE_BUILTIN_OVERFLOW)
static CYTHON_INLINE {{INT}} __Pyx_div_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) {
if (b == 0) {
*overflow |= 1;
return 0;
}
- *overflow |= (a == __PYX_MIN({{INT}})) & (b == -1);
- return a / b;
+ *overflow |= a == __PYX_MIN({{INT}}) && b == -1;
+ return ({{INT}}) ((unsigned {{INT}}) a / (unsigned {{INT}}) b);
}
+{{if INT == "long long"}}#endif{{endif}}
+
/////////////// SizeCheck.init ///////////////
//@substitute: naming
@@ -293,19 +387,24 @@ static CYTHON_INLINE {{TYPE}} __Pyx_{{BINOP}}_{{NAME}}_checking_overflow({{TYPE}
/////////////// LeftShift.proto ///////////////
static CYTHON_INLINE {{TYPE}} __Pyx_lshift_{{NAME}}_checking_overflow({{TYPE}} a, {{TYPE}} b, int *overflow) {
- *overflow |=
+ int overflow_check =
#if {{SIGNED}}
- (b < 0) |
+ (a < 0) || (b < 0) ||
#endif
- (b > ({{TYPE}}) (8 * sizeof({{TYPE}}))) | (a > (__PYX_MAX({{TYPE}}) >> b));
- return a << b;
+ // the following must be a _logical_ OR as the RHS is undefined if the LHS is true
+ (b >= ({{TYPE}}) (8 * sizeof({{TYPE}}))) || (a > (__PYX_MAX({{TYPE}}) >> b));
+ if (overflow_check) {
+ *overflow |= 1;
+ return 0;
+ } else {
+ return a << b;
+ }
}
#define __Pyx_lshift_const_{{NAME}}_checking_overflow __Pyx_lshift_{{NAME}}_checking_overflow
/////////////// UnaryNegOverflows.proto ///////////////
-//FIXME: shouldn't the macro name be prefixed by "__Pyx_" ? Too late now, I guess...
// from intobject.c
-#define UNARY_NEG_WOULD_OVERFLOW(x) \
+#define __Pyx_UNARY_NEG_WOULD_OVERFLOW(x) \
(((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
diff --git a/Cython/Utility/Profile.c b/Cython/Utility/Profile.c
index a0ab1fa98..20b599e79 100644
--- a/Cython/Utility/Profile.c
+++ b/Cython/Utility/Profile.c
@@ -6,7 +6,7 @@
// but maybe some other profilers don't.
#ifndef CYTHON_PROFILE
-#if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_PYSTON
+#if CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_PYPY
#define CYTHON_PROFILE 0
#else
#define CYTHON_PROFILE 1
@@ -239,12 +239,12 @@
if (CYTHON_TRACE_NOGIL) { \
int ret = 0; \
PyThreadState *tstate; \
- PyGILState_STATE state = PyGILState_Ensure(); \
+ PyGILState_STATE state = __Pyx_PyGILState_Ensure(); \
tstate = __Pyx_PyThreadState_Current; \
if (__Pyx_IsTracing(tstate, 0, 0) && tstate->c_tracefunc && $frame_cname->f_trace) { \
ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \
} \
- PyGILState_Release(state); \
+ __Pyx_PyGILState_Release(state); \
if (unlikely(ret)) goto_error; \
} \
} else { \
diff --git a/Cython/Utility/StringTools.c b/Cython/Utility/StringTools.c
index 98b5e260e..553585987 100644
--- a/Cython/Utility/StringTools.c
+++ b/Cython/Utility/StringTools.c
@@ -7,15 +7,73 @@
#include <string>
+
+//////////////////// ssize_strlen.proto ////////////////////
+
+static CYTHON_INLINE Py_ssize_t __Pyx_ssize_strlen(const char *s);/*proto*/
+
+//////////////////// ssize_strlen ////////////////////
+//@requires: IncludeStringH
+
+static CYTHON_INLINE Py_ssize_t __Pyx_ssize_strlen(const char *s) {
+ size_t len = strlen(s);
+ if (unlikely(len > PY_SSIZE_T_MAX)) {
+ PyErr_SetString(PyExc_OverflowError, "byte string is too long");
+ return -1;
+ }
+ return (Py_ssize_t) len;
+}
+
+
+//////////////////// ssize_pyunicode_strlen.proto ////////////////////
+
+static CYTHON_INLINE Py_ssize_t __Pyx_Py_UNICODE_ssize_strlen(const Py_UNICODE *u);/*proto*/
+
+//////////////////// ssize_pyunicode_strlen ////////////////////
+
+static CYTHON_INLINE Py_ssize_t __Pyx_Py_UNICODE_ssize_strlen(const Py_UNICODE *u) {
+ size_t len = __Pyx_Py_UNICODE_strlen(u);
+ if (unlikely(len > PY_SSIZE_T_MAX)) {
+ PyErr_SetString(PyExc_OverflowError, "Py_UNICODE string is too long");
+ return -1;
+ }
+ return (Py_ssize_t) len;
+}
+
+
//////////////////// InitStrings.proto ////////////////////
static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
//////////////////// InitStrings ////////////////////
+#if PY_MAJOR_VERSION >= 3
+static int __Pyx_InitString(__Pyx_StringTabEntry t, PyObject **str) {
+ if (t.is_unicode | t.is_str) {
+ if (t.intern) {
+ *str = PyUnicode_InternFromString(t.s);
+ } else if (t.encoding) {
+ *str = PyUnicode_Decode(t.s, t.n - 1, t.encoding, NULL);
+ } else {
+ *str = PyUnicode_FromStringAndSize(t.s, t.n - 1);
+ }
+ } else {
+ *str = PyBytes_FromStringAndSize(t.s, t.n - 1);
+ }
+ if (!*str)
+ return -1;
+ // initialise cached hash value
+ if (PyObject_Hash(*str) == -1)
+ return -1;
+ return 0;
+}
+#endif
+
static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
while (t->p) {
- #if PY_MAJOR_VERSION < 3
+ #if PY_MAJOR_VERSION >= 3 /* Python 3+ has unicode identifiers */
+ __Pyx_InitString(*t, t->p);
+ #else
if (t->is_unicode) {
*t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
} else if (t->intern) {
@@ -23,24 +81,12 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
} else {
*t->p = PyString_FromStringAndSize(t->s, t->n - 1);
}
- #else /* Python 3+ has unicode identifiers */
- if (t->is_unicode | t->is_str) {
- if (t->intern) {
- *t->p = PyUnicode_InternFromString(t->s);
- } else if (t->encoding) {
- *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL);
- } else {
- *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
- }
- } else {
- *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
- }
- #endif
if (!*t->p)
return -1;
// initialise cached hash value
if (PyObject_Hash(*t->p) == -1)
return -1;
+ #endif
++t;
}
return 0;
@@ -183,7 +229,7 @@ static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int
//@requires: BytesEquals
static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals) {
-#if CYTHON_COMPILING_IN_PYPY
+#if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API
return PyObject_RichCompareBool(s1, s2, equals);
#else
#if PY_MAJOR_VERSION < 3
@@ -294,7 +340,7 @@ static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int eq
//@requires: IncludeStringH
static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals) {
-#if CYTHON_COMPILING_IN_PYPY
+#if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API
return PyObject_RichCompareBool(s1, s2, equals);
#else
if (s1 == s2) {
@@ -591,6 +637,8 @@ static CYTHON_INLINE PyObject* __Pyx_PyUnicode_Substring(
stop = length;
if (stop <= start)
return __Pyx_NewRef($empty_unicode);
+ if (start == 0 && stop == length)
+ return __Pyx_NewRef(text);
#if CYTHON_PEP393_ENABLED
return PyUnicode_FromKindAndData(PyUnicode_KIND(text),
PyUnicode_1BYTE_DATA(text) + start*PyUnicode_KIND(text), stop-start);
@@ -835,25 +883,29 @@ static PyObject* __Pyx_PyUnicode_Join(PyObject* value_tuple, Py_ssize_t value_co
//@substitute: naming
static PyObject* __Pyx_PyUnicode_Join(PyObject* value_tuple, Py_ssize_t value_count, Py_ssize_t result_ulength,
- CYTHON_UNUSED Py_UCS4 max_char) {
+ Py_UCS4 max_char) {
#if CYTHON_USE_UNICODE_INTERNALS && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
PyObject *result_uval;
- int result_ukind;
+ int result_ukind, kind_shift;
Py_ssize_t i, char_pos;
void *result_udata;
+ CYTHON_MAYBE_UNUSED_VAR(max_char);
#if CYTHON_PEP393_ENABLED
// Py 3.3+ (post PEP-393)
result_uval = PyUnicode_New(result_ulength, max_char);
if (unlikely(!result_uval)) return NULL;
result_ukind = (max_char <= 255) ? PyUnicode_1BYTE_KIND : (max_char <= 65535) ? PyUnicode_2BYTE_KIND : PyUnicode_4BYTE_KIND;
+ kind_shift = (result_ukind == PyUnicode_4BYTE_KIND) ? 2 : result_ukind - 1;
result_udata = PyUnicode_DATA(result_uval);
#else
// Py 2.x/3.2 (pre PEP-393)
result_uval = PyUnicode_FromUnicode(NULL, result_ulength);
if (unlikely(!result_uval)) return NULL;
result_ukind = sizeof(Py_UNICODE);
+ kind_shift = (result_ukind == 4) ? 2 : result_ukind - 1;
result_udata = PyUnicode_AS_UNICODE(result_uval);
#endif
+ assert(kind_shift == 2 || kind_shift == 1 || kind_shift == 0);
char_pos = 0;
for (i=0; i < value_count; i++) {
@@ -866,12 +918,12 @@ static PyObject* __Pyx_PyUnicode_Join(PyObject* value_tuple, Py_ssize_t value_co
ulength = __Pyx_PyUnicode_GET_LENGTH(uval);
if (unlikely(!ulength))
continue;
- if (unlikely(char_pos + ulength < 0))
+ if (unlikely((PY_SSIZE_T_MAX >> kind_shift) - ulength < char_pos))
goto overflow;
ukind = __Pyx_PyUnicode_KIND(uval);
udata = __Pyx_PyUnicode_DATA(uval);
if (!CYTHON_PEP393_ENABLED || ukind == result_ukind) {
- memcpy((char *)result_udata + char_pos * result_ukind, udata, (size_t) (ulength * result_ukind));
+ memcpy((char *)result_udata + (char_pos << kind_shift), udata, (size_t) (ulength << kind_shift));
} else {
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030300F0 || defined(_PyUnicode_FastCopyCharacters)
_PyUnicode_FastCopyCharacters(result_uval, char_pos, uval, 0, ulength);
@@ -893,8 +945,9 @@ bad:
return NULL;
#else
// non-CPython fallback
- result_ulength++;
- value_count++;
+ CYTHON_UNUSED_VAR(max_char);
+ CYTHON_UNUSED_VAR(result_ulength);
+ CYTHON_UNUSED_VAR(value_count);
return PyUnicode_Join($empty_unicode, value_tuple);
#endif
}
@@ -1008,11 +1061,11 @@ static CYTHON_INLINE int __Pyx_PyByteArray_AppendObject(PyObject* bytearray, PyO
} else
#endif
#if CYTHON_USE_PYLONG_INTERNALS
- if (likely(PyLong_CheckExact(value)) && likely(Py_SIZE(value) == 1 || Py_SIZE(value) == 0)) {
- if (Py_SIZE(value) == 0) {
+ if (likely(PyLong_CheckExact(value)) && likely(__Pyx_PyLong_IsCompact(value))) {
+ if (__Pyx_PyLong_IsZero(value)) {
ival = 0;
} else {
- ival = ((PyLongObject*)value)->ob_digit[0];
+ ival = __Pyx_PyLong_CompactValue(value);
if (unlikely(ival > 255)) goto bad_range;
}
} else
@@ -1130,11 +1183,12 @@ static PyObject* __Pyx_PyObject_Format(PyObject* obj, PyObject* format_spec) {
likely(PyString_CheckExact(s)) ? PyUnicode_FromEncodedObject(s, NULL, "strict") : \
PyObject_Format(s, f))
#elif CYTHON_USE_TYPE_SLOTS
- // Py3 nicely returns unicode strings from str() which makes this quite efficient for builtin types
+ // Py3 nicely returns unicode strings from str() and repr(), which makes this quite efficient for builtin types.
+ // In Py3.8+, tp_str() delegates to tp_repr(), so we call tp_repr() directly here.
#define __Pyx_PyObject_FormatSimple(s, f) ( \
likely(PyUnicode_CheckExact(s)) ? (Py_INCREF(s), s) : \
- likely(PyLong_CheckExact(s)) ? PyLong_Type.tp_str(s) : \
- likely(PyFloat_CheckExact(s)) ? PyFloat_Type.tp_str(s) : \
+ likely(PyLong_CheckExact(s)) ? PyLong_Type.tp_repr(s) : \
+ likely(PyFloat_CheckExact(s)) ? PyFloat_Type.tp_repr(s) : \
PyObject_Format(s, f))
#else
#define __Pyx_PyObject_FormatSimple(s, f) ( \
@@ -1193,3 +1247,22 @@ static CYTHON_INLINE PyObject* __Pyx_PyUnicode_Unicode(PyObject *obj) {
#define __Pyx_PyObject_Unicode(obj) \
(likely(PyUnicode_CheckExact(obj)) ? __Pyx_NewRef(obj) : PyObject_Unicode(obj))
#endif
+
+
+//////////////////// PyStr_Str.proto ////////////////////
+
+static CYTHON_INLINE PyObject* __Pyx_PyStr_Str(PyObject *obj);/*proto*/
+
+//////////////////// PyStr_Str ////////////////////
+
+static CYTHON_INLINE PyObject* __Pyx_PyStr_Str(PyObject *obj) {
+ if (unlikely(obj == Py_None))
+ obj = PYIDENT("None");
+ return __Pyx_NewRef(obj);
+}
+
+
+//////////////////// PyObject_Str.proto ////////////////////
+
+#define __Pyx_PyObject_Str(obj) \
+ (likely(PyString_CheckExact(obj)) ? __Pyx_NewRef(obj) : PyObject_Str(obj))
diff --git a/Cython/Utility/TestCythonScope.pyx b/Cython/Utility/TestCythonScope.pyx
index f585be298..7da7665c3 100644
--- a/Cython/Utility/TestCythonScope.pyx
+++ b/Cython/Utility/TestCythonScope.pyx
@@ -1,6 +1,11 @@
########## TestClass ##########
# These utilities are for testing purposes
+# The "cythonscope" test calls METH_O functions with their (self, arg) signature.
+# cython: always_allow_keywords=False
+
+from __future__ import print_function
+
cdef extern from *:
cdef object __pyx_test_dep(object)
@@ -12,32 +17,32 @@ cdef class TestClass(object):
self.value = value
def __str__(self):
- return 'TestClass(%d)' % self.value
+ return f'TestClass({self.value})'
cdef cdef_method(self, int value):
- print 'Hello from cdef_method', value
+ print('Hello from cdef_method', value)
cpdef cpdef_method(self, int value):
- print 'Hello from cpdef_method', value
+ print('Hello from cpdef_method', value)
def def_method(self, int value):
- print 'Hello from def_method', value
+ print('Hello from def_method', value)
@cname('cdef_cname')
cdef cdef_cname_method(self, int value):
- print "Hello from cdef_cname_method", value
+ print("Hello from cdef_cname_method", value)
@cname('cpdef_cname')
cpdef cpdef_cname_method(self, int value):
- print "Hello from cpdef_cname_method", value
+ print("Hello from cpdef_cname_method", value)
@cname('def_cname')
def def_cname_method(self, int value):
- print "Hello from def_cname_method", value
+ print("Hello from def_cname_method", value)
@cname('__pyx_test_call_other_cy_util')
cdef test_call(obj):
- print 'test_call'
+ print('test_call')
__pyx_test_dep(obj)
@cname('__pyx_TestClass_New')
@@ -46,19 +51,20 @@ cdef _testclass_new(int value):
########### TestDep ##########
+from __future__ import print_function
+
@cname('__pyx_test_dep')
cdef test_dep(obj):
- print 'test_dep', obj
+ print('test_dep', obj)
########## TestScope ##########
@cname('__pyx_testscope')
cdef object _testscope(int value):
- return "hello from cython scope, value=%d" % value
+ return f"hello from cython scope, value={value}"
########## View.TestScope ##########
@cname('__pyx_view_testscope')
cdef object _testscope(int value):
- return "hello from cython.view scope, value=%d" % value
-
+ return f"hello from cython.view scope, value={value}"
diff --git a/Cython/Utility/TypeConversion.c b/Cython/Utility/TypeConversion.c
index 404814907..3e730e0fb 100644
--- a/Cython/Utility/TypeConversion.c
+++ b/Cython/Utility/TypeConversion.c
@@ -68,9 +68,9 @@ static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*);
#define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s))
#define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s))
#define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s))
-#define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s))
-#define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s))
-#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s))
+#define __Pyx_PyObject_AsWritableString(s) ((char*)(__pyx_uintptr_t) __Pyx_PyObject_AsString(s))
+#define __Pyx_PyObject_AsWritableSString(s) ((signed char*)(__pyx_uintptr_t) __Pyx_PyObject_AsString(s))
+#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*)(__pyx_uintptr_t) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s)
@@ -80,12 +80,23 @@ static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*);
#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s)
// There used to be a Py_UNICODE_strlen() in CPython 3.x, but it is deprecated since Py3.3.
-static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) {
+#if CYTHON_COMPILING_IN_LIMITED_API
+static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const wchar_t *u)
+{
+ const wchar_t *u_end = u;
+ while (*u_end++) ;
+ return (size_t)(u_end - u - 1);
+}
+#else
+static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u)
+{
const Py_UNICODE *u_end = u;
while (*u_end++) ;
return (size_t)(u_end - u - 1);
}
+#endif
+#define __Pyx_PyUnicode_FromOrdinal(o) PyUnicode_FromOrdinal((int)o)
#define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u))
#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode
#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode
@@ -116,7 +127,49 @@ static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*);
#else
#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x))
#endif
-#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x))
+// __Pyx_PyNumber_Float is now in its own section since it has dependencies (needed to make
+// string conversion work the same in all circumstances).
+
+#if CYTHON_USE_PYLONG_INTERNALS
+ #if PY_VERSION_HEX >= 0x030C00A7
+ #define __Pyx_PyLong_Sign(x) (((PyLongObject*)x)->long_value.lv_tag & 3)
+ #define __Pyx_PyLong_IsNeg(x) ((__Pyx_PyLong_Sign(x) & 2) != 0)
+ #define __Pyx_PyLong_IsNonNeg(x) (!__Pyx_PyLong_IsNeg(x))
+ #define __Pyx_PyLong_IsZero(x) (__Pyx_PyLong_Sign(x) & 1)
+ #define __Pyx_PyLong_IsPos(x) (__Pyx_PyLong_Sign(x) == 0)
+ #define __Pyx_PyLong_IsCompact(x) (((PyLongObject*)x)->long_value.lv_tag < (2 << 3)) // (2 << NON_SIZE_BITS)
+ #define __Pyx_PyLong_CompactValue(x) ((1 - (Py_ssize_t) __Pyx_PyLong_Sign(x)) * (Py_ssize_t) __Pyx_PyLong_Digits(x)[0])
+ #define __Pyx_PyLong_CompactValueUnsigned(x) (__Pyx_PyLong_Digits(x)[0])
+ #define __Pyx_PyLong_DigitCount(x) (((PyLongObject*)x)->long_value.lv_tag >> 3) // (>> NON_SIZE_BITS)
+ #define __Pyx_PyLong_SignedDigitCount(x) \
+ ((1 - (Py_ssize_t) (((PyLongObject*)x)->long_value.lv_tag & 3)) * (Py_ssize_t) (((PyLongObject*)x)->long_value.lv_tag >> 3)) // (>> NON_SIZE_BITS)
+
+ // CPython 3.12 requires C99
+ typedef Py_ssize_t __Pyx_compact_pylong;
+ typedef size_t __Pyx_compact_upylong;
+
+ #else // Py < 3.12
+ #define __Pyx_PyLong_IsNeg(x) (Py_SIZE(x) < 0)
+ #define __Pyx_PyLong_IsNonNeg(x) (Py_SIZE(x) >= 0)
+ #define __Pyx_PyLong_IsZero(x) (Py_SIZE(x) == 0)
+ #define __Pyx_PyLong_IsPos(x) (Py_SIZE(x) > 0)
+ #define __Pyx_PyLong_IsCompact(x) (Py_SIZE(x) == 0 || Py_SIZE(x) == 1 || Py_SIZE(x) == -1)
+ #define __Pyx_PyLong_CompactValue(x) \
+ ((Py_SIZE(x) == 0) ? (sdigit) 0 : ((Py_SIZE(x) < 0) ? -(sdigit)__Pyx_PyLong_Digits(x)[0] : (sdigit)__Pyx_PyLong_Digits(x)[0]))
+ #define __Pyx_PyLong_CompactValueUnsigned(x) ((Py_SIZE(x) == 0) ? 0 : __Pyx_PyLong_Digits(x)[0])
+ #define __Pyx_PyLong_DigitCount(x) __Pyx_sst_abs(Py_SIZE(x))
+ #define __Pyx_PyLong_SignedDigitCount(x) Py_SIZE(x)
+
+ typedef sdigit __Pyx_compact_pylong;
+ typedef digit __Pyx_compact_upylong;
+ #endif
+
+ #if PY_VERSION_HEX >= 0x030C00A5
+ #define __Pyx_PyLong_Digits(x) (((PyLongObject*)x)->long_value.ob_digit)
+ #else
+ #define __Pyx_PyLong_Digits(x) (((PyLongObject*)x)->ob_digit)
+ #endif
+#endif
#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
static int __Pyx_sys_getdefaultencoding_not_ascii;
@@ -271,7 +324,7 @@ static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_
} else
#endif /* __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT */
-#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE))
+#if (!CYTHON_COMPILING_IN_PYPY && !CYTHON_COMPILING_IN_LIMITED_API) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE))
if (PyByteArray_Check(o)) {
*length = PyByteArray_GET_SIZE(o);
return PyByteArray_AS_STRING(o);
@@ -304,23 +357,27 @@ static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) {
}
static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) {
+ __Pyx_TypeName result_type_name = __Pyx_PyType_GetName(Py_TYPE(result));
#if PY_MAJOR_VERSION >= 3
if (PyLong_Check(result)) {
// CPython issue #17576: warn if 'result' not of exact type int.
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
- "__int__ returned non-int (type %.200s). "
- "The ability to return an instance of a strict subclass of int "
- "is deprecated, and may be removed in a future version of Python.",
- Py_TYPE(result)->tp_name)) {
+ "__int__ returned non-int (type " __Pyx_FMT_TYPENAME "). "
+ "The ability to return an instance of a strict subclass of int is deprecated, "
+ "and may be removed in a future version of Python.",
+ result_type_name)) {
+ __Pyx_DECREF_TypeName(result_type_name);
Py_DECREF(result);
return NULL;
}
+ __Pyx_DECREF_TypeName(result_type_name);
return result;
}
#endif
PyErr_Format(PyExc_TypeError,
- "__%.4s__ returned non-%.4s (type %.200s)",
- type_name, type_name, Py_TYPE(result)->tp_name);
+ "__%.4s__ returned non-%.4s (type " __Pyx_FMT_TYPENAME ")",
+ type_name, type_name, result_type_name);
+ __Pyx_DECREF_TypeName(result_type_name);
Py_DECREF(result);
return NULL;
}
@@ -390,14 +447,12 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
#endif
if (likely(PyLong_CheckExact(b))) {
#if CYTHON_USE_PYLONG_INTERNALS
- const digit* digits = ((PyLongObject*)b)->ob_digit;
- const Py_ssize_t size = Py_SIZE(b);
// handle most common case first to avoid indirect branch and optimise branch prediction
- if (likely(__Pyx_sst_abs(size) <= 1)) {
- ival = likely(size) ? digits[0] : 0;
- if (size == -1) ival = -ival;
- return ival;
+ if (likely(__Pyx_PyLong_IsCompact(b))) {
+ return __Pyx_PyLong_CompactValue(b);
} else {
+ const digit* digits = __Pyx_PyLong_Digits(b);
+ const Py_ssize_t size = __Pyx_PyLong_SignedDigitCount(b);
switch (size) {
{{for _size in (2, 3, 4)}}
{{for _case in (_size, -_size)}}
@@ -449,12 +504,50 @@ static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) {
return PyInt_FromSize_t(ival);
}
+/////////////// pynumber_float.proto ///////////////
+
+static CYTHON_INLINE PyObject* __Pyx__PyNumber_Float(PyObject* obj); /* proto */
+#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : __Pyx__PyNumber_Float(x))
+
+/////////////// pynumber_float ///////////////
+//@requires: Optimize.c::pybytes_as_double
+//@requires: Optimize.c::pyunicode_as_double
+
+static CYTHON_INLINE PyObject* __Pyx__PyNumber_Float(PyObject* obj) {
+ // 'obj is PyFloat' is handled in the calling macro
+ double val;
+ if (PyLong_CheckExact(obj)) {
+#if CYTHON_USE_PYLONG_INTERNALS
+ if (likely(__Pyx_PyLong_IsCompact(obj))) {
+ val = (double) __Pyx_PyLong_CompactValue(obj);
+ goto no_error;
+ }
+#endif
+ val = PyLong_AsDouble(obj);
+ } else if (PyUnicode_CheckExact(obj)) {
+ val = __Pyx_PyUnicode_AsDouble(obj);
+ } else if (PyBytes_CheckExact(obj)) {
+ val = __Pyx_PyBytes_AsDouble(obj);
+ } else if (PyByteArray_CheckExact(obj)) {
+ val = __Pyx_PyByteArray_AsDouble(obj);
+ } else {
+ return PyNumber_Float(obj);
+ }
+
+ if (unlikely(val == -1 && PyErr_Occurred())) {
+ return NULL;
+ }
+#if CYTHON_USE_PYLONG_INTERNALS
+no_error:
+#endif
+ return PyFloat_FromDouble(val);
+}
/////////////// GCCDiagnostics.proto ///////////////
// GCC diagnostic pragmas were introduced in GCC 4.6
// Used to silence conversion warnings that are ok but cannot be avoided.
-#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+#if !defined(__INTEL_COMPILER) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
#define __Pyx_HAS_GCC_DIAGNOSTIC
#endif
@@ -484,24 +577,41 @@ bad:
/////////////// FromPyCTupleUtility.proto ///////////////
-static {{struct_type_decl}} {{funcname}}(PyObject *);
+static CYTHON_INLINE {{struct_type_decl}} {{funcname}}(PyObject *);
/////////////// FromPyCTupleUtility ///////////////
-static {{struct_type_decl}} {{funcname}}(PyObject * o) {
- {{struct_type_decl}} result;
-
- if (!PyTuple_Check(o) || PyTuple_GET_SIZE(o) != {{size}}) {
- PyErr_Format(PyExc_TypeError, "Expected %.16s of size %d, got %.200s", "a tuple", {{size}}, Py_TYPE(o)->tp_name);
- goto bad;
- }
#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+static {{struct_type_decl}} __Pyx_tuple_{{funcname}}(PyObject * o) {
+ {{struct_type_decl}} result;
+
{{for ix, component in enumerate(components):}}
{{py:attr = "result.f%s" % ix}}
{{attr}} = {{component.from_py_function}}(PyTuple_GET_ITEM(o, {{ix}}));
if ({{component.error_condition(attr)}}) goto bad;
{{endfor}}
-#else
+
+ return result;
+bad:
+ return result;
+}
+#endif
+
+static {{struct_type_decl}} __Pyx_seq_{{funcname}}(PyObject * o) {
+ {{struct_type_decl}} result;
+
+ if (unlikely(!PySequence_Check(o))) {
+ __Pyx_TypeName o_type_name = __Pyx_PyType_GetName(Py_TYPE(o));
+ PyErr_Format(PyExc_TypeError,
+ "Expected a sequence of size %zd, got " __Pyx_FMT_TYPENAME, (Py_ssize_t) {{size}}, o_type_name);
+ __Pyx_DECREF_TypeName(o_type_name);
+ goto bad;
+ } else if (unlikely(PySequence_Length(o) != {{size}})) {
+ PyErr_Format(PyExc_TypeError,
+ "Expected a sequence of size %zd, got size %zd", (Py_ssize_t) {{size}}, PySequence_Length(o));
+ goto bad;
+ }
+
{
PyObject *item;
{{for ix, component in enumerate(components):}}
@@ -512,13 +622,22 @@ static {{struct_type_decl}} {{funcname}}(PyObject * o) {
if ({{component.error_condition(attr)}}) goto bad;
{{endfor}}
}
-#endif
return result;
bad:
return result;
}
+static CYTHON_INLINE {{struct_type_decl}} {{funcname}}(PyObject * o) {
+ #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+ if (likely(PyTuple_Check(o) && PyTuple_GET_SIZE(o) == {{size}})) {
+ return __Pyx_tuple_{{funcname}}(o);
+ }
+ #endif
+
+ return __Pyx_seq_{{funcname}}(o);
+}
+
/////////////// UnicodeAsUCS4.proto ///////////////
@@ -784,10 +903,10 @@ static CYTHON_INLINE PyObject* {{TO_PY_FUNCTION}}({{TYPE}} value, Py_ssize_t wid
}
} while (unlikely(remaining != 0));
- if (last_one_off) {
- assert(*dpos == '0');
- dpos++;
- }
+ // Correct dpos by 1 if we read an excess digit.
+ assert(!last_one_off || *dpos == '0');
+ dpos += last_one_off;
+
length = end - dpos;
ulength = length;
prepend_sign = 0;
@@ -886,7 +1005,7 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
const int is_unsigned = neg_one > const_zero;
#if PY_MAJOR_VERSION < 3
if (likely(PyInt_Check(x))) {
- if (sizeof({{TYPE}}) < sizeof(long)) {
+ if ((sizeof({{TYPE}}) < sizeof(long))) {
__PYX_VERIFY_RETURN_INT({{TYPE}}, long, PyInt_AS_LONG(x))
} else {
long val = PyInt_AS_LONG(x);
@@ -900,21 +1019,28 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
if (likely(PyLong_Check(x))) {
if (is_unsigned) {
#if CYTHON_USE_PYLONG_INTERNALS
- const digit* digits = ((PyLongObject*)x)->ob_digit;
- switch (Py_SIZE(x)) {
- case 0: return ({{TYPE}}) 0;
- case 1: __PYX_VERIFY_RETURN_INT({{TYPE}}, digit, digits[0])
- {{for _size in (2, 3, 4)}}
- case {{_size}}:
- if (8 * sizeof({{TYPE}}) > {{_size-1}} * PyLong_SHIFT) {
- if (8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT) {
- __PYX_VERIFY_RETURN_INT({{TYPE}}, unsigned long, {{pylong_join(_size, 'digits')}})
- } else if (8 * sizeof({{TYPE}}) >= {{_size}} * PyLong_SHIFT) {
- return ({{TYPE}}) {{pylong_join(_size, 'digits', TYPE)}};
+ if (unlikely(__Pyx_PyLong_IsNeg(x))) {
+ goto raise_neg_overflow;
+ //} else if (__Pyx_PyLong_IsZero(x)) {
+ // return ({{TYPE}}) 0;
+ } else if (__Pyx_PyLong_IsCompact(x)) {
+ __PYX_VERIFY_RETURN_INT({{TYPE}}, __Pyx_compact_upylong, __Pyx_PyLong_CompactValueUnsigned(x))
+ } else {
+ const digit* digits = __Pyx_PyLong_Digits(x);
+ assert(__Pyx_PyLong_DigitCount(x) > 1);
+ switch (__Pyx_PyLong_DigitCount(x)) {
+ {{for _size in (2, 3, 4)}}
+ case {{_size}}:
+ if ((8 * sizeof({{TYPE}}) > {{_size-1}} * PyLong_SHIFT)) {
+ if ((8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT)) {
+ __PYX_VERIFY_RETURN_INT({{TYPE}}, unsigned long, {{pylong_join(_size, 'digits')}})
+ } else if ((8 * sizeof({{TYPE}}) >= {{_size}} * PyLong_SHIFT)) {
+ return ({{TYPE}}) {{pylong_join(_size, 'digits', TYPE)}};
+ }
}
- }
- break;
- {{endfor}}
+ break;
+ {{endfor}}
+ }
}
#endif
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A7
@@ -931,71 +1057,170 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
goto raise_neg_overflow;
}
#endif
- if (sizeof({{TYPE}}) <= sizeof(unsigned long)) {
+ if ((sizeof({{TYPE}}) <= sizeof(unsigned long))) {
__PYX_VERIFY_RETURN_INT_EXC({{TYPE}}, unsigned long, PyLong_AsUnsignedLong(x))
#ifdef HAVE_LONG_LONG
- } else if (sizeof({{TYPE}}) <= sizeof(unsigned PY_LONG_LONG)) {
+ } else if ((sizeof({{TYPE}}) <= sizeof(unsigned PY_LONG_LONG))) {
__PYX_VERIFY_RETURN_INT_EXC({{TYPE}}, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x))
#endif
}
} else {
// signed
#if CYTHON_USE_PYLONG_INTERNALS
- const digit* digits = ((PyLongObject*)x)->ob_digit;
- switch (Py_SIZE(x)) {
- case 0: return ({{TYPE}}) 0;
- case -1: __PYX_VERIFY_RETURN_INT({{TYPE}}, sdigit, (sdigit) (-(sdigit)digits[0]))
- case 1: __PYX_VERIFY_RETURN_INT({{TYPE}}, digit, +digits[0])
- {{for _size in (2, 3, 4)}}
- {{for _case in (-_size, _size)}}
- case {{_case}}:
- if (8 * sizeof({{TYPE}}){{' - 1' if _case < 0 else ''}} > {{_size-1}} * PyLong_SHIFT) {
- if (8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT) {
- __PYX_VERIFY_RETURN_INT({{TYPE}}, {{'long' if _case < 0 else 'unsigned long'}}, {{'-(long) ' if _case < 0 else ''}}{{pylong_join(_size, 'digits')}})
- } else if (8 * sizeof({{TYPE}}) - 1 > {{_size}} * PyLong_SHIFT) {
- return ({{TYPE}}) ({{'((%s)-1)*' % TYPE if _case < 0 else ''}}{{pylong_join(_size, 'digits', TYPE)}});
+ if (__Pyx_PyLong_IsCompact(x)) {
+ __PYX_VERIFY_RETURN_INT({{TYPE}}, __Pyx_compact_pylong, __Pyx_PyLong_CompactValue(x))
+ } else {
+ const digit* digits = __Pyx_PyLong_Digits(x);
+ assert(__Pyx_PyLong_DigitCount(x) > 1);
+ switch (__Pyx_PyLong_SignedDigitCount(x)) {
+ {{for _size in (2, 3, 4)}}
+ {{for _case in (-_size, _size)}}
+ case {{_case}}:
+ if ((8 * sizeof({{TYPE}}){{' - 1' if _case < 0 else ''}} > {{_size-1}} * PyLong_SHIFT)) {
+ if ((8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT)) {
+ __PYX_VERIFY_RETURN_INT({{TYPE}}, {{'long' if _case < 0 else 'unsigned long'}}, {{'-(long) ' if _case < 0 else ''}}{{pylong_join(_size, 'digits')}})
+ } else if ((8 * sizeof({{TYPE}}) - 1 > {{_size}} * PyLong_SHIFT)) {
+ return ({{TYPE}}) ({{'((%s)-1)*' % TYPE if _case < 0 else ''}}{{pylong_join(_size, 'digits', TYPE)}});
+ }
}
- }
- break;
- {{endfor}}
- {{endfor}}
+ break;
+ {{endfor}}
+ {{endfor}}
+ }
}
#endif
- if (sizeof({{TYPE}}) <= sizeof(long)) {
+ if ((sizeof({{TYPE}}) <= sizeof(long))) {
__PYX_VERIFY_RETURN_INT_EXC({{TYPE}}, long, PyLong_AsLong(x))
#ifdef HAVE_LONG_LONG
- } else if (sizeof({{TYPE}}) <= sizeof(PY_LONG_LONG)) {
+ } else if ((sizeof({{TYPE}}) <= sizeof(PY_LONG_LONG))) {
__PYX_VERIFY_RETURN_INT_EXC({{TYPE}}, PY_LONG_LONG, PyLong_AsLongLong(x))
#endif
}
}
+
+ {{if IS_ENUM}}
+ PyErr_SetString(PyExc_RuntimeError,
+ "_PyLong_AsByteArray() not available, cannot convert large enums");
+ return ({{TYPE}}) -1;
+ {{else}}
+ // large integer type and no access to PyLong internals => allow for a more expensive conversion
{
-#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray)
- PyErr_SetString(PyExc_RuntimeError,
- "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers");
-#else
{{TYPE}} val;
PyObject *v = __Pyx_PyNumber_IntOrLong(x);
- #if PY_MAJOR_VERSION < 3
+#if PY_MAJOR_VERSION < 3
if (likely(v) && !PyLong_Check(v)) {
PyObject *tmp = v;
v = PyNumber_Long(tmp);
Py_DECREF(tmp);
}
- #endif
+#endif
if (likely(v)) {
+ int ret = -1;
+#if !(CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API) || defined(_PyLong_AsByteArray)
int one = 1; int is_little = (int)*(unsigned char *)&one;
unsigned char *bytes = (unsigned char *)&val;
- int ret = _PyLong_AsByteArray((PyLongObject *)v,
- bytes, sizeof(val),
- is_little, !is_unsigned);
+ ret = _PyLong_AsByteArray((PyLongObject *)v,
+ bytes, sizeof(val),
+ is_little, !is_unsigned);
+#else
+// Inefficient copy of bit chunks through the C-API. Probably still better than a "cannot do this" exception.
+ PyObject *stepval = NULL, *mask = NULL, *shift = NULL;
+ int bits, remaining_bits, is_negative = 0;
+ long idigit;
+ int chunk_size = (sizeof(long) < 8) ? 30 : 62;
+
+ // use exact PyLong to prevent user defined &&/<</etc. implementations
+ if (unlikely(!PyLong_CheckExact(v))) {
+ PyObject *tmp = v;
+ v = PyNumber_Long(v);
+ assert(PyLong_CheckExact(v));
+ Py_DECREF(tmp);
+ if (unlikely(!v)) return ({{TYPE}}) -1;
+ }
+
+#if CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030B0000
+ if (Py_SIZE(x) == 0)
+ return ({{TYPE}}) 0;
+ is_negative = Py_SIZE(x) < 0;
+#else
+ {
+ // misuse Py_False as a quick way to compare to a '0' int object
+ int result = PyObject_RichCompareBool(x, Py_False, Py_LT);
+ if (unlikely(result < 0))
+ return ({{TYPE}}) -1;
+ is_negative = result == 1;
+ }
+#endif
+
+ if (is_unsigned && unlikely(is_negative)) {
+ goto raise_neg_overflow;
+ } else if (is_negative) {
+ // bit-invert to make sure we can safely convert it
+ stepval = PyNumber_Invert(v);
+ if (unlikely(!stepval))
+ return ({{TYPE}}) -1;
+ } else {
+ stepval = __Pyx_NewRef(v);
+ }
+
+ // unpack full chunks of bits
+ val = ({{TYPE}}) 0;
+ mask = PyLong_FromLong((1L << chunk_size) - 1); if (unlikely(!mask)) goto done;
+ shift = PyLong_FromLong(chunk_size); if (unlikely(!shift)) goto done;
+ for (bits = 0; bits < (int) sizeof({{TYPE}}) * 8 - chunk_size; bits += chunk_size) {
+ PyObject *tmp, *digit;
+
+ digit = PyNumber_And(stepval, mask);
+ if (unlikely(!digit)) goto done;
+ idigit = PyLong_AsLong(digit);
+ Py_DECREF(digit);
+ if (unlikely(idigit < 0)) goto done;
+
+ tmp = PyNumber_Rshift(stepval, shift);
+ if (unlikely(!tmp)) goto done;
+ Py_DECREF(stepval); stepval = tmp;
+
+ val |= (({{TYPE}}) idigit) << bits;
+
+ #if CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030B0000
+ if (Py_SIZE(stepval) == 0)
+ goto unpacking_done;
+ #endif
+ }
+
+ // detect overflow when adding the last bits
+ idigit = PyLong_AsLong(stepval);
+ if (unlikely(idigit < 0)) goto done;
+ remaining_bits = ((int) sizeof({{TYPE}}) * 8) - bits - (is_unsigned ? 0 : 1);
+ if (unlikely(idigit >= (1L << remaining_bits)))
+ goto raise_overflow;
+ val |= (({{TYPE}}) idigit) << bits;
+
+ #if CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030B0000
+ unpacking_done:
+ #endif
+ // handle sign and overflow into sign bit
+ if (!is_unsigned) {
+ // gcc warns about unsigned (val < 0) => test sign bit instead
+ if (unlikely(val & ((({{TYPE}}) 1) << (sizeof({{TYPE}}) * 8 - 1))))
+ goto raise_overflow;
+ // undo the PyNumber_Invert() above
+ if (is_negative)
+ val = ~val;
+ }
+ ret = 0;
+ done:
+ Py_XDECREF(shift);
+ Py_XDECREF(mask);
+ Py_XDECREF(stepval);
+#endif
Py_DECREF(v);
if (likely(!ret))
return val;
}
-#endif
return ({{TYPE}}) -1;
}
+ {{endif}}
} else {
{{TYPE}} val;
PyObject *tmp = __Pyx_PyNumber_IntOrLong(x);
diff --git a/Cython/Utility/UFuncs.pyx b/Cython/Utility/UFuncs.pyx
new file mode 100644
index 000000000..c2043e8cc
--- /dev/null
+++ b/Cython/Utility/UFuncs.pyx
@@ -0,0 +1,51 @@
+##################### UFuncDefinition ######################
+
+cdef extern from *:
+ ctypedef int npy_intp
+ struct PyObject
+ PyObject* __Pyx_NewRef(object)
+ {{inline_func_declaration}}
+
+# variable names have to come from tempita to avoid duplication
+@cname("{{func_cname}}")
+cdef void {{func_cname}}(char **args, const npy_intp *dimensions, const npy_intp* steps, void* data) except * {{"nogil" if will_be_called_without_gil else ""}}:
+ cdef npy_intp i
+ cdef npy_intp n = dimensions[0]
+ {{for idx, tp in enumerate(in_types)}}
+ cdef char* in_{{idx}} = args[{{idx}}]
+ cdef {{tp.empty_declaration_code(pyrex=True)}} cast_in_{{idx}}
+ {{endfor}}
+ {{for idx, tp in enumerate(out_types)}}
+ cdef char* out_{{idx}} = args[{{idx+len(in_types)}}]
+ cdef {{tp.empty_declaration_code(pyrex=True)}} cast_out_{{idx}}
+ {{endfor}}
+ {{for idx in range(len(out_types)+len(in_types))}}
+ cdef npy_intp step_{{idx}} = steps[{{idx}}]
+ {{endfor}}
+
+ {{"with gil" if (not nogil and will_be_called_without_gil) else "if True"}}:
+ for i in range(n):
+ {{for idx, tp in enumerate(in_types)}}
+ {{if tp.is_pyobject}}
+ cast_in_{{idx}} = (<{{tp.empty_declaration_code(pyrex=True)}}>(<void**>in_{{idx}})[0])
+ {{else}}
+ cast_in_{{idx}} = (<{{tp.empty_declaration_code(pyrex=True)}}*>in_{{idx}})[0]
+ {{endif}}
+ {{endfor}}
+
+ {{", ".join("cast_out_{}".format(idx) for idx in range(len(out_types)))}} = \
+ {{inline_func_call}}({{", ".join("cast_in_{}".format(idx) for idx in range(len(in_types)))}})
+
+ {{for idx, tp in enumerate(out_types)}}
+ {{if tp.is_pyobject}}
+ (<void**>out_{{idx}})[0] = <void*>__Pyx_NewRef(cast_out_{{idx}})
+ {{else}}
+ (<{{tp.empty_declaration_code(pyrex=True)}}*>out_{{idx}})[0] = cast_out_{{idx}}
+ {{endif}}
+ {{endfor}}
+ {{for idx in range(len(in_types))}}
+ in_{{idx}} += step_{{idx}}
+ {{endfor}}
+ {{for idx in range(len(out_types))}}
+ out_{{idx}} += step_{{idx+len(in_types)}}
+ {{endfor}}
diff --git a/Cython/Utility/UFuncs_C.c b/Cython/Utility/UFuncs_C.c
new file mode 100644
index 000000000..e7ce8812e
--- /dev/null
+++ b/Cython/Utility/UFuncs_C.c
@@ -0,0 +1,42 @@
+///////////////////////// UFuncsInit.proto /////////////////////////
+//@proto_block: utility_code_proto_before_types
+
+#include <numpy/arrayobject.h>
+#include <numpy/ufuncobject.h>
+
+// account for change in type of arguments to PyUFuncGenericFunction in Numpy 1.19.x
+// Unfortunately we can only test against Numpy version 1.20.x since it wasn't marked
+// as an API break. Therefore, I'm "solving" the issue by casting function pointer types
+// on lower Numpy versions.
+#if NPY_API_VERSION >= 0x0000000e // Numpy 1.20.x
+#define __PYX_PYUFUNCGENERICFUNCTION_CAST(x) x
+#else
+#define __PYX_PYUFUNCGENERICFUNCTION_CAST(x) (PyUFuncGenericFunction)x
+#endif
+
+/////////////////////// UFuncConsts.proto ////////////////////
+
+// getter functions because we can't forward-declare arrays
+static PyUFuncGenericFunction* {{ufunc_funcs_name}}(void); /* proto */
+static char* {{ufunc_types_name}}(void); /* proto */
+static void* {{ufunc_data_name}}[] = {NULL}; // always null
+
+/////////////////////// UFuncConsts /////////////////////////
+
+static PyUFuncGenericFunction* {{ufunc_funcs_name}}(void) {
+ static PyUFuncGenericFunction arr[] = {
+ {{for loop, cname in looper(func_cnames)}}
+ __PYX_PYUFUNCGENERICFUNCTION_CAST(&{{cname}}){{if not loop.last}},{{endif}}
+ {{endfor}}
+ };
+ return arr;
+}
+
+static char* {{ufunc_types_name}}(void) {
+ static char arr[] = {
+ {{for loop, tp in looper(type_constants)}}
+ {{tp}}{{if not loop.last}},{{endif}}
+ {{endfor}}
+ };
+ return arr;
+}