-976f5483c6df8570f34076ef25af7e7512dd9347
+fc777dd6f2661e9b34f50cbd39ac9b184eded484
Cython Changelog
================
+0.29.22 (2021-02-20)
+====================
+
+Features added
+--------------
+
+* Some declarations were added to the provided pxd includes.
+ Patches by Zackery Spytz and John Kirkham.
+ (Github issues #3811, #3882, #3899, #3901)
+
+Bugs fixed
+----------
+
+* A crash when calling certain functions in Py3.9 and later was resolved.
+ (Github issue #3917)
+
+* ``const`` memory views of structs failed to compile.
+ (Github issue #2251)
+
+* ``const`` template declarations could not be nested.
+ Patch by Ashwin Srinath. (Github issue #1355)
+
+* The declarations in the ``cpython.pycapsule`` module were missing their
+ ``const`` modifiers and generated incorrect C code.
+ Patch by Warren Weckesser. (Github issue #3964)
+
+* Casts to memory views failed for fused dtypes.
+ Patch by David Woods. (Github issue #3881)
+
+* ``repr()`` was assumed to return ``str`` instead of ``unicode`` with ``language_level=3``.
+ (Github issue #3736)
+
+* Calling ``cpdef`` functions from cimported modules crashed the compiler.
+ Patch by David Woods. (Github issue #4000)
+
+* Cython no longer validates the ABI size of the NumPy classes it compiled against.
+ See the discussion in https://github.com/numpy/numpy/pull/432
+
+* A C compiler warning about enum value casting was resolved in GCC.
+ (Github issue #2749)
+
+* Coverage reporting in the annotated HTML file failed in Py3.9.
+ Patch by Nick Pope. (Github issue #3865)
+
+* The embedding code now reports Python errors as exit status.
+
+* Long type declarations could lead to (harmless) random changes in the
+ C file when used in auto-generated Python wrappers or pickled classes.
+
+Other changes
+-------------
+
+* Variables defined as ``cpdef`` now generate a warning since this
+ is currently useless and thus does not do what users would expect.
+ Patch by David Woods. (Github issue #3959)
+
+
0.29.21 (2020-07-09)
====================
if dtype.is_simple_buffer_dtype():
structinfo_name = "NULL"
elif dtype.is_struct:
- fields = dtype.scope.var_entries
- # Must pre-call all used types in order not to recurse utility code
- # writing.
+ struct_scope = dtype.scope
+ if dtype.is_const:
+ struct_scope = struct_scope.const_base_type_scope
+ # Must pre-call all used types in order not to recurse during utility code writing.
+ fields = struct_scope.var_entries
assert len(fields) > 0
types = [get_type_information_cname(code, f.type, maxdepth - 1)
for f in fields]
#('raw_input', "", "", ""),
#('reduce', "", "", ""),
BuiltinFunction('reload', "O", "O", "PyImport_ReloadModule"),
- BuiltinFunction('repr', "O", "O", "PyObject_Repr", builtin_return_type='str'),
+ BuiltinFunction('repr', "O", "O", "PyObject_Repr"), # , builtin_return_type='str'), # add in Cython 3.1
#('round', "", "", ""),
BuiltinFunction('setattr', "OOO", "r", "PyObject_SetAttr"),
#('sum', "", "", ""),
# not an attribute itself, but might have been assigned from one (e.g. bound method)
for assignment in self.function.cf_state:
value = assignment.rhs
- if value and value.is_attribute and value.obj.type.is_pyobject:
+ if value and value.is_attribute and value.obj.type and value.obj.type.is_pyobject:
if attribute_is_likely_method(value):
likely_method = 'likely'
break
# FIXME: this is way too redundant with analyse_types()
node = self.analyse_as_cimported_attribute_node(env, target=False)
if node is not None:
- return node.entry.type
+ if node.entry.type and node.entry.type.is_cfunction:
+ # special-case - function converted to pointer
+ return PyrexTypes.CPtrType(node.entry.type)
+ else:
+ return node.entry.type
node = self.analyse_as_type_attribute(env)
if node is not None:
return node.entry.type
except ImportError:
import xml.etree.ElementTree as ET
coverage_xml = ET.parse(coverage_xml_filename).getroot()
- for el in coverage_xml.getiterator():
+ if hasattr(coverage_xml, 'iter'):
+ iterator = coverage_xml.iter() # Python 2.7 & 3.2+
+ else:
+ iterator = coverage_xml.getiterator()
+ for el in iterator:
el.tail = None # save some memory
else:
coverage_xml = None
type = PyrexTypes.TemplatePlaceholderType(self.name)
else:
error(self.pos, "'%s' is not a type identifier" % self.name)
+ if type and type.is_fused and env.fused_to_specific:
+ type = type.specialize(env.fused_to_specific)
if self.complex:
if not type.is_numeric or type.is_complex:
error(self.pos, "can only complexify c numeric types")
self.entry.type.create_to_py_utility_code(env)
self.entry.create_wrapper = True
else:
+ if self.overridable:
+ warning(self.pos, "cpdef variables will not be supported in Cython 3; "
+ "currently they are no different from cdef variables", 2)
if self.directive_locals:
error(self.pos, "Decorators can only be followed by functions")
self.entry = dest_scope.declare_var(
s.put_back(*saved)
elif s.sy == '[':
s.next()
- is_type = s.sy == ']'
+ is_type = s.sy == ']' or not looking_at_expr(s) # could be a nested template type
s.put_back(*saved)
dotted_path.reverse()
from __future__ import absolute_import
-import collections
import copy
+import hashlib
import re
try:
def cap_length(s, max_prefix=63, max_len=1024):
if len(s) <= max_prefix:
return s
- else:
- return '%x__%s__etc' % (abs(hash(s)) % (1<<20), s[:max_len-17])
+ hash_prefix = hashlib.sha256(s.encode('ascii')).hexdigest()[:6]
+ return '%s__%s__etc' % (hash_prefix, s[:max_len-17])
""" fast creation of a new array, given a template array.
type will be same as template.
if zero is true, new array will be initialized with zeroes."""
- op = newarrayobject(Py_TYPE(template), length, template.ob_descr)
+ cdef array op = newarrayobject(Py_TYPE(template), length, template.ob_descr)
if zero and op is not None:
memset(op.data.as_chars, 0, length * op.ob_descr.itemsize)
return op
cdef inline array copy(array self):
""" make a copy of an array. """
- op = newarrayobject(Py_TYPE(self), Py_SIZE(self), self.ob_descr)
+ cdef array op = newarrayobject(Py_TYPE(self), Py_SIZE(self), self.ob_descr)
memcpy(op.data.as_chars, self.data.as_chars, Py_SIZE(op) * op.ob_descr.itemsize)
return op
cdef extern from "Python.h":
cdef enum:
+ PyBUF_MAX_NDIM
+
+ cdef enum:
PyBUF_SIMPLE,
PyBUF_WRITABLE,
PyBUF_WRITEABLE, # backwards compatibility
--- /dev/null
+from .object cimport PyObject
+
+cdef extern from "Python.h":
+
+ ############################################################################
+ # Cell Objects
+ ############################################################################
+
+ bint PyCell_Check(object ob)
+ # Return true if ob is a cell object; ob must not be NULL.
+
+ object PyCell_New(PyObject* ob)
+ # Return value: New reference.
+ # Create and return a new cell object containing the value ob. The
+ # parameter may be NULL.
+
+ object PyCell_Get(object cell)
+ # Return value: New reference.
+ # Return the contents of the cell object cell.
+
+ object PyCell_GET(object cell)
+ # Return value: Borrowed reference.
+ # Return the contents of the cell object cell, but without checking that
+ # cell is non-NULL and is a cell object.
+
+ int PyCell_Set(object cell, PyObject* value) except? -1
+ # Set the contents of the cell object cell to value. This releases the
+ # reference to any current content of the cell. value may be NULL. cell
+ # must be non-NULL; if it is not a cell object, -1 will be returned. On
+ # success, 0 will be returned.
+
+ void PyCell_SET(object cell, PyObject* value)
+ # Sets the value of the cell object cell to value. No reference counts are
+ # adjusted, and no checks are made for safety; cell must be non-NULL and
+ # must be a cell object.
--- /dev/null
+cdef extern from "Python.h":
+
+ ###########################################################################
+ # Codec registry and support functions
+ ###########################################################################
+
+ int PyCodec_Register(object search_function)
+ # Register a new codec search function.
+
+ # As side effect, this tries to load the encodings package, if not yet
+ # done, to make sure that it is always first in the list of search
+ # functions.
+
+ int PyCodec_KnownEncoding(const char *encoding)
+ # Return 1 or 0 depending on whether there is a registered codec for the
+ # given encoding. This function always succeeds.
+
+ object PyCodec_Encode(object o, const char *encoding, const char *errors)
+ # Return value: New reference.
+ # Generic codec based encoding API.
+
+ # o is passed through the encoder function found for the given encoding
+ # using the error handling method defined by errors. errors may be NULL
+ # to use the default method defined for the codec. Raises a LookupError
+ # if no encoder can be found.
+
+ object PyCodec_Decode(object o, const char *encoding, const char *errors)
+ # Return value: New reference.
+ # Generic codec based decoding API.
+
+ # o is passed through the decoder function found for the given encoding
+ # using the error handling method defined by errors. errors may be NULL
+ # to use the default method defined for the codec. Raises a LookupError
+ # if no encoder can be found.
+
+
+ # Codec lookup API
+
+ # In the following functions, the encoding string is looked up converted
+ # to all lower-case characters, which makes encodings looked up through
+ # this mechanism effectively case-insensitive. If no codec is found, a
+ # KeyError is set and NULL returned.
+
+ object PyCodec_Encoder(const char *encoding)
+ # Return value: New reference.
+ # Get an encoder function for the given encoding.
+
+ object PyCodec_Decoder(const char *encoding)
+ # Return value: New reference.
+ # Get a decoder function for the given encoding.
+
+ object PyCodec_IncrementalEncoder(const char *encoding, const char *errors)
+ # Return value: New reference.
+ # Get an IncrementalEncoder object for the given encoding.
+
+ object PyCodec_IncrementalDecoder(const char *encoding, const char *errors)
+ # Return value: New reference.
+ # Get an IncrementalDecoder object for the given encoding.
+
+ object PyCodec_StreamReader(const char *encoding, object stream, const char *errors)
+ # Return value: New reference.
+ # Get a StreamReader factory function for the given encoding.
+
+ object PyCodec_StreamWriter(const char *encoding, object stream, const char *errors)
+ # Return value: New reference.
+ # Get a StreamWriter factory function for the given encoding.
+
+
+ # Registry API for Unicode encoding error handlers
+
+ int PyCodec_RegisterError(const char *name, object error) except? -1
+ # Register the error handling callback function error under the given
+ # name. This callback function will be called by a codec when it
+ # encounters unencodable characters/undecodable bytes and name is
+ # specified as the error parameter in the call to the encode/decode
+ # function.
+
+ # The callback gets a single argument, an instance of
+ # UnicodeEncodeError, UnicodeDecodeError or UnicodeTranslateError that
+ # holds information about the problematic sequence of characters or bytes
+ # and their offset in the original string (see Unicode Exception Objects
+ # for functions to extract this information). The callback must either
+ # raise the given exception, or return a two-item tuple containing the
+ # replacement for the problematic sequence, and an integer giving the
+ # offset in the original string at which encoding/decoding should be
+ # resumed.
+
+ # Return 0 on success, -1 on error.
+
+ object PyCodec_LookupError(const char *name)
+ # Return value: New reference.
+ # Lookup the error handling callback function registered under name. As a
+ # special case NULL can be passed, in which case the error handling
+ # callback for "strict" will be returned.
+
+ object PyCodec_StrictErrors(object exc)
+ # Return value: Always NULL.
+ # Raise exc as an exception.
+
+ object PyCodec_IgnoreErrors(object exc)
+ # Return value: New reference.
+ # Ignore the unicode error, skipping the faulty input.
+
+ object PyCodec_ReplaceErrors(object exc)
+ # Return value: New reference.
+ # Replace the unicode encode error with "?" or "U+FFFD".
+
+ object PyCodec_XMLCharRefReplaceErrors(object exc)
+ # Return value: New reference.
+ # Replace the unicode encode error with XML character references.
+
+ object PyCodec_BackslashReplaceErrors(object exc)
+ # Return value: New reference.
+ # Replace the unicode encode error with backslash escapes ("\x", "\u"
+ # and "\U").
+
+ object PyCodec_NameReplaceErrors(object exc)
+ # Return value: New reference.
+ # Replace the unicode encode error with "\N{...}" escapes.
+
+ # New in version 3.5.
--- /dev/null
+# From https://docs.python.org/3/c-api/conversion.html
+
+from .object cimport PyObject
+
+cdef extern from "Python.h":
+ ctypedef struct va_list
+
+ int PyOS_snprintf(char *str, size_t size, const char *format, ...)
+ # Output not more than size bytes to str according to the format
+ # string format and the extra arguments. See the Unix man page snprintf(2).
+
+ int PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
+ # Output not more than size bytes to str according to the format
+ # string format and the variable argument list va. Unix man page vsnprintf(2).
+
+ double PyOS_string_to_double(const char *s, char **endptr, PyObject *overflow_exception) except? -1.0
+ # Convert a string s to a double, raising a Python exception on failure. The set of
+ # accepted strings corresponds to the set of strings accepted by Python’s float()
+ # constructor, except that s must not have leading or trailing whitespace.
+ # The conversion is independent of the current locale.
+
+ enum:
+ Py_DTSF_SIGN
+ Py_DTSF_ADD_DOT_0
+ Py_DTSF_ALT
+
+ char* PyOS_double_to_string(double val, char format_code, int precision, int flags, int *ptype) except NULL
+ # Convert a double val to a string using supplied format_code, precision, and flags.
+
+ int PyOS_stricmp(const char *s1, const char *s2)
+ # Case insensitive comparison of strings. The function works almost identically
+ # to strcmp() except that it ignores the case.
+
+ int PyOS_strnicmp(const char *s1, const char *s2, Py_ssize_t size)
+ # Case insensitive comparison of strings. The function works almost identically
+ # to strncmp() except that it ignores the case.
# available since Python 3.1!
-# note all char* in the below functions are actually const char*
cdef extern from "Python.h":
# Return true if its argument is a PyCapsule.
- object PyCapsule_New(void *pointer, char *name,
+ object PyCapsule_New(void *pointer, const char *name,
PyCapsule_Destructor destructor)
# Return value: New reference.
#
# PyCapsule_Import().
- void* PyCapsule_GetPointer(object capsule, char *name) except? NULL
+ void* PyCapsule_GetPointer(object capsule, const char *name) except? NULL
# Retrieve the pointer stored in the capsule. On failure, set an
# exception and return NULL.
#
# or PyErr_Occurred() to disambiguate.
- char* PyCapsule_GetName(object capsule) except? NULL
+ const char* PyCapsule_GetName(object capsule) except? NULL
# Return the current name stored in the capsule. On failure, set
# an exception and return NULL.
#
# PyErr_Occurred() to disambiguate.
- bint PyCapsule_IsValid(object capsule, char *name)
+ bint PyCapsule_IsValid(object capsule, const char *name)
# Determines whether or not capsule is a valid capsule. A valid
# capsule is non-NULL, passes PyCapsule_CheckExact(), has a
# non-NULL pointer stored in it, and its internal name matches the
# failure.
- int PyCapsule_SetName(object capsule, char *name) except -1
+ int PyCapsule_SetName(object capsule, const char *name) except -1
# Set the name inside capsule to name. If non-NULL, the name must
# outlive the capsule. If the previous name stored in the capsule
# was not NULL, no attempt is made to free it.
# success. Return nonzero and set an exception on failure.
- void* PyCapsule_Import(char *name, int no_block) except? NULL
+ void* PyCapsule_Import(const char *name, int no_block) except? NULL
# Import a pointer to a C object from a capsule attribute in a
# module. The name parameter should specify the full name to the
# attribute, as in module.attribute. The name stored in the
# this field via the inline helper method PyDataType_SHAPE.
cdef PyArray_ArrayDescr* subarray
- ctypedef extern class numpy.flatiter [object PyArrayIterObject]:
+ ctypedef class numpy.flatiter [object PyArrayIterObject, check_size ignore]:
# Use through macros
pass
- ctypedef extern class numpy.broadcast [object PyArrayMultiIterObject]:
+ ctypedef class numpy.broadcast [object PyArrayMultiIterObject, check_size ignore]:
# Use through macros
pass
ctypedef void (*PyUFuncGenericFunction) (char **, npy_intp *, npy_intp *, void *)
- ctypedef extern class numpy.ufunc [object PyUFuncObject]:
+ ctypedef class numpy.ufunc [object PyUFuncObject, check_size ignore]:
cdef:
int nin, nout, nargs
int identity
enum: SEEK_END
enum: O_CREAT
+ enum: O_DIRECT
enum: O_EXCL
enum: O_NOCTTY
enum: O_TRUNC
# cython.* namespace for pure mode.
from __future__ import absolute_import
-__version__ = "0.29.21"
+__version__ = "0.29.22"
try:
from __builtin__ import basestring
return retval;
}
+#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03030000 && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3)
+static CYTHON_INLINE
+PyObject *__Pyx_PyGen_Send(PyGenObject *gen, PyObject *arg) {
+#if PY_VERSION_HEX <= 0x030A00A1
+ return _PyGen_Send(gen, arg);
+#else
+ PyObject *result;
+ // PyIter_Send() asserts non-NULL arg
+ if (PyIter_Send((PyObject*)gen, arg ? arg : Py_None, &result) == PYGEN_RETURN) {
+ if (PyAsyncGen_CheckExact(gen)) {
+ assert(result == Py_None);
+ PyErr_SetNone(PyExc_StopAsyncIteration);
+ }
+ else if (result == Py_None) {
+ PyErr_SetNone(PyExc_StopIteration);
+ }
+ else {
+ _PyGen_SetStopIterationValue(result);
+ }
+ Py_CLEAR(result);
+ }
+ return result;
+#endif
+}
+#endif
+
static CYTHON_INLINE
PyObject *__Pyx_Coroutine_FinishDelegation(__pyx_CoroutineObject *gen) {
PyObject *ret;
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03030000 && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3)
// _PyGen_Send() is not exported before Py3.6
if (PyGen_CheckExact(yf)) {
- ret = _PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value);
+ ret = __Pyx_PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value);
} else
#endif
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03050000 && defined(PyCoro_CheckExact) && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3)
// _PyGen_Send() is not exported before Py3.6
if (PyCoro_CheckExact(yf)) {
- ret = _PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value);
+ ret = __Pyx_PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value);
} else
#endif
{
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03030000 && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3)
// _PyGen_Send() is not exported before Py3.6
if (PyGen_CheckExact(yf)) {
- ret = _PyGen_Send((PyGenObject*)yf, NULL);
+ ret = __Pyx_PyGen_Send((PyGenObject*)yf, NULL);
} else
#endif
#ifdef __Pyx_Coroutine_USED
#if !CYTHON_USE_TP_FINALIZE
// Temporarily resurrect the object.
assert(self->ob_refcnt == 0);
- self->ob_refcnt = 1;
+ __Pyx_SET_REFCNT(self, 1);
#endif
__Pyx_PyThreadState_assign
{
Py_ssize_t refcnt = self->ob_refcnt;
_Py_NewReference(self);
- self->ob_refcnt = refcnt;
+ __Pyx_SET_REFCNT(self, refcnt);
}
#if CYTHON_COMPILING_IN_CPYTHON
assert(PyType_IS_GC(self->ob_type) &&
}
Py_XDECREF(m);
}
+#if PY_VERSION_HEX < 0x03060000
Py_Finalize();
+#else
+ if (Py_FinalizeEx() < 0)
+ return 2;
+#endif
return 0;
}
if (res == 0)
res = __Pyx_main(argc, argv_copy);
for (i = 0; i < argc; i++) {
+#if PY_VERSION_HEX < 0x03050000
free(argv_copy2[i]);
+#else
+ PyMem_RawFree(argv_copy2[i]);
+#endif
}
free(argv_copy);
free(argv_copy2);
cdef bytes part, result
if type.typegroup == 'S':
- assert type.fields != NULL and type.fields.type != NULL
+ assert type.fields != NULL
+ assert type.fields.type != NULL
if type.flags & __PYX_BUF_FLAGS_PACKED_STRUCT:
alignment = b'^'
// fast and simple case that we are optimising for
return __Pyx_PyObject_CallMethO(func, arg);
#if CYTHON_FAST_PYCCALL
- } else if (PyCFunction_GET_FLAGS(func) & METH_FASTCALL) {
+ } else if (__Pyx_PyFastCFunction_Check(func)) {
return __Pyx_PyCFunction_FastCall(func, &arg, 1);
#endif
}
}
+/////////////// 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))
+#define __Pyx_HAS_GCC_DIAGNOSTIC
+#endif
+
+
/////////////// ToPyCTupleUtility.proto ///////////////
static PyObject* {{funcname}}({{struct_type_decl}});
static CYTHON_INLINE PyObject* {{TO_PY_FUNCTION}}({{TYPE}} value);
/////////////// CIntToPy ///////////////
+//@requires: GCCDiagnostics
static CYTHON_INLINE PyObject* {{TO_PY_FUNCTION}}({{TYPE}} value) {
- const {{TYPE}} neg_one = ({{TYPE}}) (({{TYPE}}) 0 - ({{TYPE}}) 1), const_zero = ({{TYPE}}) 0;
+#ifdef __Pyx_HAS_GCC_DIAGNOSTIC
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wconversion"
+#endif
+ const {{TYPE}} neg_one = ({{TYPE}}) -1, const_zero = ({{TYPE}}) 0;
+#ifdef __Pyx_HAS_GCC_DIAGNOSTIC
+#pragma GCC diagnostic pop
+#endif
const int is_unsigned = neg_one > const_zero;
if (is_unsigned) {
if (sizeof({{TYPE}}) < sizeof(long)) {
/////////////// CIntToPyUnicode ///////////////
//@requires: StringTools.c::BuildPyUnicode
//@requires: CIntToDigits
+//@requires: GCCDiagnostics
#ifdef _MSC_VER
#ifndef _MSC_STDINT_H_
// NOTE: inlining because most arguments are constant, which collapses lots of code below
-// GCC diagnostic pragmas were introduced in GCC 4.6
-#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
-#define GCC_DIAGNOSTIC
-#endif
static CYTHON_INLINE PyObject* {{TO_PY_FUNCTION}}({{TYPE}} value, Py_ssize_t width, char padding_char, char format_char) {
// simple and conservative C string allocation on the stack: each byte gives at most 3 digits, plus sign
char digits[sizeof({{TYPE}})*3+2];
Py_ssize_t length, ulength;
int prepend_sign, last_one_off;
{{TYPE}} remaining;
-#ifdef GCC_DIAGNOSTIC
+#ifdef __Pyx_HAS_GCC_DIAGNOSTIC
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
const {{TYPE}} neg_one = ({{TYPE}}) -1, const_zero = ({{TYPE}}) 0;
-#ifdef GCC_DIAGNOSTIC
+#ifdef __Pyx_HAS_GCC_DIAGNOSTIC
#pragma GCC diagnostic pop
#endif
const int is_unsigned = neg_one > const_zero;
/////////////// CIntFromPy ///////////////
//@requires: CIntFromPyVerify
+//@requires: GCCDiagnostics
{{py: from Cython.Utility import pylong_join }}
static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
- const {{TYPE}} neg_one = ({{TYPE}}) (({{TYPE}}) 0 - ({{TYPE}}) 1), const_zero = ({{TYPE}}) 0;
+#ifdef __Pyx_HAS_GCC_DIAGNOSTIC
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wconversion"
+#endif
+ const {{TYPE}} neg_one = ({{TYPE}}) -1, const_zero = ({{TYPE}}) 0;
+#ifdef __Pyx_HAS_GCC_DIAGNOSTIC
+#pragma GCC diagnostic pop
+#endif
const int is_unsigned = neg_one > const_zero;
#if PY_MAJOR_VERSION < 3
if (likely(PyInt_Check(x))) {
op->ob_descr = descr;
op->allocated = size;
op->weakreflist = NULL;
- op->ob_size = size;
+ __Pyx_SET_SIZE(op, size);
if (size <= 0) {
op->data.ob_item = NULL;
}
return -1;
}
self->data.ob_item = (char*) items;
- self->ob_size = n;
+ __Pyx_SET_SIZE(self, n);
self->allocated = n;
return 0;
}
void *items = (void*) self->data.ob_item;
Py_ssize_t newsize;
if (n < self->allocated && n*4 > self->allocated) {
- self->ob_size = n;
+ __Pyx_SET_SIZE(self, n);
return 0;
}
newsize = n + (n / 2) + 1;
return -1;
}
self->data.ob_item = (char*) items;
- self->ob_size = n;
+ __Pyx_SET_SIZE(self, n);
self->allocated = newsize;
return 0;
}
import io
import codecs
import shutil
+import tempfile
from contextlib import contextmanager
modification_time = os.path.getmtime
@contextmanager
def captured_fd(stream=2, encoding=None):
- pipe_in = t = None
orig_stream = os.dup(stream) # keep copy of original stream
try:
- pipe_in, pipe_out = os.pipe()
- os.dup2(pipe_out, stream) # replace stream by copy of pipe
- try:
- os.close(pipe_out) # close original pipe-out stream
- data = []
-
- def copy():
- try:
- while True:
- d = os.read(pipe_in, 1000)
- if d:
- data.append(d)
- else:
- break
- finally:
- os.close(pipe_in)
-
- def get_output():
- output = b''.join(data)
- if encoding:
- output = output.decode(encoding)
- return output
-
- from threading import Thread
- t = Thread(target=copy)
- t.daemon = True # just in case
- t.start()
- yield get_output
- finally:
- os.dup2(orig_stream, stream) # restore original stream
- if t is not None:
- t.join()
+ with tempfile.TemporaryFile(mode="a+b") as temp_file:
+ def read_output(_output=[b'']):
+ if not temp_file.closed:
+ temp_file.seek(0)
+ _output[0] = temp_file.read()
+ return _output[0]
+
+ os.dup2(temp_file.fileno(), stream) # replace stream by copy of pipe
+ try:
+ def get_output():
+ result = read_output()
+ return result.decode(encoding) if encoding else result
+
+ yield get_output
+ finally:
+ os.dup2(orig_stream, stream) # restore original stream
+ read_output() # keep the output in case it's used after closing the context manager
finally:
os.close(orig_stream)
Metadata-Version: 1.2
Name: Cython
-Version: 0.29.21
+Version: 0.29.22
Summary: The Cython compiler for writing C extensions for the Python language.
Home-page: http://cython.org/
Author: Robert Bradshaw, Stefan Behnel, Dag Seljebotn, Greg Ewing, et al.
Error return values
-------------------
-If you don't do anything special, a function declared with :keyword:`cdef` that
-does not return a Python object has no way of reporting Python exceptions to
-its caller. If an exception is detected in such a function, a warning message
-is printed and the exception is ignored.
-
-If you want a C function that does not return a Python object to be able to
-propagate exceptions to its caller, you need to declare an exception value for
-it. Here is an example::
+In Python (more specifically, in the CPython runtime), exceptions that occur
+inside of a function are signaled to the caller and propagated up the call stack
+through defined error return values. For functions that return a Python object
+(and thus, a pointer to such an object), the error return value is simply the
+``NULL`` pointer, so any function returning a Python object has a well-defined
+error return value.
+
+While this is always the case for :keyword:`def` functions, functions
+defined as :keyword:`cdef` or :keyword:`cpdef` can return arbitrary C types,
+which do not have such a well-defined error return value. Thus, if an
+exception is detected in such a function, a warning message is printed,
+the exception is ignored, and the function returns immediately without
+propagating the exception to its caller.
+
+If you want such a C function to be able to propagate exceptions, you need
+to declare an exception return value for it as a contract with the caller.
+Here is an example::
cdef int spam() except -1:
...
-With this declaration, whenever an exception occurs inside spam, it will
-immediately return with the value ``-1``. Furthermore, whenever a call to spam
-returns ``-1``, an exception will be assumed to have occurred and will be
-propagated.
+With this declaration, whenever an exception occurs inside ``spam``, it will
+immediately return with the value ``-1``. From the caller's side, whenever
+a call to spam returns ``-1``, the caller will assume that an exception has
+occurred and can now process or propagate it.
-When you declare an exception value for a function, you should never
-explicitly or implicitly return that value. In particular, if the exceptional return value
-is a ``False`` value, then you should ensure the function will never terminate via an implicit
-or empty return.
+When you declare an exception value for a function, you should never explicitly
+or implicitly return that value. This includes empty :keyword:`return`
+statements, without a return value, for which Cython inserts the default return
+value (e.g. ``0`` for C number types). In general, exception return values
+are best chosen from invalid or very unlikely return values of the function,
+such as a negative value for functions that return only non-negative results,
+or a very large value like ``INT_MAX`` for a function that "usually" only
+returns small results.
If all possible return values are legal and you
can't reserve one entirely for signalling errors, you can use an alternative
cdef int spam() except? -1:
...
-The "?" indicates that the value ``-1`` only indicates a possible error. In this
-case, Cython generates a call to :c:func:`PyErr_Occurred` if the exception value is
-returned, to make sure it really is an error.
+The "?" indicates that the value ``-1`` only signals a possible error. In this
+case, Cython generates a call to :c:func:`PyErr_Occurred` if the exception value
+is returned, to make sure it really received an exception and not just a normal
+result.
There is also a third form of exception value declaration::
...
This form causes Cython to generate a call to :c:func:`PyErr_Occurred` after
-every call to spam, regardless of what value it returns. If you have a
-function returning void that needs to propagate errors, you will have to use
-this form, since there isn't any return value to test.
-Otherwise there is little use for this form.
+*every* call to spam, regardless of what value it returns. If you have a
+function returning ``void`` that needs to propagate errors, you will have to
+use this form, since there isn't any error return value to test.
+Otherwise, an explicit error return value allows the C compiler to generate
+more efficient code and is thus generally preferable.
An external C++ function that may raise an exception can be declared with::
Some things to note:
-* Exception values can only declared for functions returning an integer, enum,
- float or pointer type, and the value must be a constant expression.
- Void functions can only use the ``except *`` form.
+* Exception values can only be declared for functions returning a C integer,
+ enum, float or pointer type, and the value must be a constant expression.
+ Functions that return ``void``, or a struct/union by value, can only use
+ the ``except *`` form.
* The exception value specification is part of the signature of the function.
If you're passing a pointer to a function as a parameter or assigning it
to a variable, the declared type of the parameter or variable must have
- the same exception value specification (or lack thereof). Here is an
- example of a pointer-to-function declaration with an exception
- value::
+ the same exception value specification (or lack thereof). Here is an
+ example of a pointer-to-function declaration with an exception value::
int (*grail)(int, char*) except -1
* You don't need to (and shouldn't) declare exception values for functions
which return Python objects. Remember that a function with no declared
- return type implicitly returns a Python object. (Exceptions on such functions
- are implicitly propagated by returning NULL.)
+ return type implicitly returns a Python object. (Exceptions on such
+ functions are implicitly propagated by returning ``NULL``.)
.. _checking_return_values_of_non_cython_functions:
expressions as for the ``DEF`` statement, although they can evaluate to any
Python value, and the truth of the result is determined in the usual Python
way.
-
continue
suite.addTest(
self.handle_directory(path, filename))
- if sys.platform not in ['win32'] and self.add_embedded_test:
+ if (sys.platform not in ['win32'] and self.add_embedded_test
+ # the embedding test is currently broken in Py3.8+, except on Linux.
+ and (sys.version_info < (3, 8) or sys.platform != 'darwin')):
# Non-Windows makefile.
if [1 for selector in self.selectors if selector("embedded")] \
and not [1 for selector in self.exclude_selectors if selector("embedded")]:
import sys
from Cython.Build.Dependencies import cythonize
+import platform
+import os
from distutils.core import setup
+# os x on Travis specifically seems to crash with nthreads>0
+osx_on_travis = (platform.system() == "Darwin" and os.getenv("TRAVIS"))
+
# Test concurrent safety if multiprocessing is available.
# (In particular, TravisCI does not support spawning processes from tests.)
nthreads = 0
-if not hasattr(sys, 'pypy_version_info'):
+if not (hasattr(sys, 'pypy_version_info') or osx_on_travis):
try:
import multiprocessing
multiprocessing.Pool(2).close()
--- /dev/null
+# tag: cpp
+# mode: compile
+
+from libcpp.vector cimport vector
+
+cdef extern from *:
+ cdef cppclass Foo[T]:
+ pass
+
+ cdef cppclass Bar:
+ pass
+
+cdef vector[vector[int]] a
+cdef vector[vector[const int]] b
+cdef vector[vector[vector[int]]] c
+cdef vector[vector[vector[const int]]] d
+cdef Foo[Foo[Bar]] e
+cdef Foo[Foo[const Bar]] f
--- /dev/null
+# tag: warnings
+
+cpdef str a = "123"
+cpdef b = 2
+
+cdef class C:
+ cpdef float c
+
+def func():
+ """
+ >>> c = func()
+ >>> isinstance(c, C) or c
+ True
+ """
+ cpdef d = C()
+ return d
+
+
+_WARNINGS = """
+3:6: cpdef variables will not be supported in Cython 3; currently they are no different from cdef variables
+4:6: cpdef variables will not be supported in Cython 3; currently they are no different from cdef variables
+7:10: cpdef variables will not be supported in Cython 3; currently they are no different from cdef variables
+15:10: cpdef variables will not be supported in Cython 3; currently they are no different from cdef variables
+"""
"""
See also buffmt.pyx
- >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)])) # , writable=False))
+ >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)]))
1 2 3 4 5
- >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ccqii")) # , writable=False))
+ >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ccqii"))
+ 1 2 3 4 5
+ """
+ print buf[0].a, buf[0].b, buf[0].c, buf[0].d, buf[0].e
+
+@testcase
+def const_struct(const MyStruct[:] buf):
+ """
+ See also buffmt.pyx
+
+ >>> const_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], writable=False))
+ 1 2 3 4 5
+ >>> const_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ccqii", writable=False))
1 2 3 4 5
"""
print buf[0].a, buf[0].b, buf[0].c, buf[0].d, buf[0].e
"""
See also buffmt.pyx
- >>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)])) # , writable=False))
+ >>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)]))
+ 1 2 3 4 5
+ >>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="T{ii}T{2i}i"))
+ 1 2 3 4 5
+ """
+ print buf[0].x.a, buf[0].x.b, buf[0].y.a, buf[0].y.b, buf[0].z
+
+@testcase
+def const_nested_struct(const NestedStruct[:] buf):
+ """
+ See also buffmt.pyx
+
+ >>> const_nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], writable=False))
1 2 3 4 5
- >>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="T{ii}T{2i}i")) # , writable=False))
+ >>> const_nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="T{ii}T{2i}i", writable=False))
1 2 3 4 5
"""
print buf[0].x.a, buf[0].x.b, buf[0].y.a, buf[0].y.b, buf[0].z
"""
See also buffmt.pyx
- >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)])) # , writable=False))
+ >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)]))
+ 1 2
+ >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c^i}"))
+ 1 2
+ >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c=i}"))
+ 1 2
+
+ """
+ print buf[0].a, buf[0].b
+
+@testcase
+def const_packed_struct(const PackedStruct[:] buf):
+ """
+ See also buffmt.pyx
+
+ >>> const_packed_struct(PackedStructMockBuffer(None, [(1, 2)], writable=False))
1 2
- >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c^i}")) # , writable=False))
+ >>> const_packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c^i}", writable=False))
1 2
- >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c=i}")) # , writable=False))
+ >>> const_packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c=i}", writable=False))
1 2
"""
"""
See also buffmt.pyx
- >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)])) # , writable=False))
+ >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)]))
+ 1 2 3 4 5
+ >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ci^ci@i"))
+ 1 2 3 4 5
+ >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="^c@i^ci@i"))
+ 1 2 3 4 5
+ """
+ print buf[0].a, buf[0].b, buf[0].sub.a, buf[0].sub.b, buf[0].c
+
+
+@testcase
+def const_nested_packed_struct(const NestedPackedStruct[:] buf):
+ """
+ See also buffmt.pyx
+
+ >>> const_nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], writable=False))
1 2 3 4 5
- >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ci^ci@i")) # , writable=False))
+ >>> const_nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ci^ci@i", writable=False))
1 2 3 4 5
- >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="^c@i^ci@i")) # , writable=False))
+ >>> const_nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="^c@i^ci@i", writable=False))
1 2 3 4 5
"""
print buf[0].a, buf[0].b, buf[0].sub.a, buf[0].sub.b, buf[0].c
A,
foo,
)
-print A, foo(10)
+print(A, foo(10))
cimport other
-print other.A, other.foo(10)
+
+cdef call_fooptr(int (*fptr)(int)):
+ return fptr(10)
+
+def call_other_foo():
+ x = other.foo # GH4000 - failed because other was untyped
+ return call_fooptr(x) # check that x is correctly resolved as a function pointer
+
+print(other.A, other.foo(10), call_other_foo())
from pkg cimport sub
cdef sub.my_int a = 100
-from pkg.subpkg cimport submod
\ No newline at end of file
+from pkg.subpkg cimport submod
int
"""
return float(x)
+
+
+'''
+def repr_returns_str(x) -> str:
+ """
+ >>> repr_returns_str(123)
+ '123'
+ """
+ return repr(x)
+'''
cimport cpython.buffer
cimport cpython.bytearray
cimport cpython.bytes
+cimport cpython.cellobject
cimport cpython.ceval
cimport cpython.cobject
+cimport cpython.codecs
cimport cpython.complex
+cimport cpython.conversion
cimport cpython.datetime
cimport cpython.dict
cimport cpython.exc
cdef cython.floating[:] otherarray = array[0:100:1]
print cython.typeof(array), cython.typeof(otherarray), \
array[5], otherarray[6]
+ cdef cython.floating value;
+ cdef cython.floating[:] test_cast = <cython.floating[:1:1]>&value
def test_fused_memslice_dtype_repeated(cython.floating[:] array1, cython.floating[:] array2):
"""