diff options
Diffstat (limited to 'Cython/Includes/cpython')
29 files changed, 802 insertions, 71 deletions
diff --git a/Cython/Includes/cpython/__init__.pxd b/Cython/Includes/cpython/__init__.pxd index c81f4e665..7ad2684aa 100644 --- a/Cython/Includes/cpython/__init__.pxd +++ b/Cython/Includes/cpython/__init__.pxd @@ -179,6 +179,9 @@ from cpython.bytes cimport * # Python >= 3.0 from cpython.pycapsule cimport * +# Python >= 3.7 +from cpython.contextvars cimport * + ################################################################# # END OF DEPRECATED SECTION ################################################################# diff --git a/Cython/Includes/cpython/array.pxd b/Cython/Includes/cpython/array.pxd index 19230a0a8..8431f7b66 100644 --- a/Cython/Includes/cpython/array.pxd +++ b/Cython/Includes/cpython/array.pxd @@ -46,8 +46,19 @@ : 2012-05-02 andreasvc : (see revision control) """ -from libc.string cimport strcat, strncat, \ - memset, memchr, memcmp, memcpy, memmove + +cdef extern from *: + """ + #if CYTHON_COMPILING_IN_PYPY + #ifdef _MSC_VER + #pragma message ("This module uses CPython specific internals of 'array.array', which are not available in PyPy.") + #else + #warning This module uses CPython specific internals of 'array.array', which are not available in PyPy. + #endif + #endif + """ + +from libc.string cimport memset, memcpy from cpython.object cimport Py_SIZE from cpython.ref cimport PyTypeObject, Py_TYPE diff --git a/Cython/Includes/cpython/bool.pxd b/Cython/Includes/cpython/bool.pxd index c775088ce..335921452 100644 --- a/Cython/Includes/cpython/bool.pxd +++ b/Cython/Includes/cpython/bool.pxd @@ -35,4 +35,3 @@ cdef extern from "Python.h": object PyBool_FromLong(long v) # Return value: New reference. # Return a new reference to Py_True or Py_False depending on the truth value of v. - diff --git a/Cython/Includes/cpython/bytes.pxd b/Cython/Includes/cpython/bytes.pxd index ea72c6aae..8998770d8 100644 --- a/Cython/Includes/cpython/bytes.pxd +++ b/Cython/Includes/cpython/bytes.pxd @@ -68,6 +68,10 @@ cdef extern from "Python.h": # Return value: New reference. # Identical to PyBytes_FromFormat() except that it takes exactly two arguments. + bytes PyBytes_FromObject(object o) + # Return value: New reference. + # Return the bytes representation of object o that implements the buffer protocol. + Py_ssize_t PyBytes_Size(object string) except -1 # Return the length of the string in string object string. @@ -194,5 +198,3 @@ cdef extern from "Python.h": # string encode() method. The codec to be used is looked up using # the Python codec registry. Return NULL if an exception was # raised by the codec. - - diff --git a/Cython/Includes/cpython/complex.pxd b/Cython/Includes/cpython/complex.pxd index f5ba33957..3fa145008 100644 --- a/Cython/Includes/cpython/complex.pxd +++ b/Cython/Includes/cpython/complex.pxd @@ -14,9 +14,14 @@ cdef extern from "Python.h": ctypedef class __builtin__.complex [object PyComplexObject]: cdef Py_complex cval - # not making these available to keep them read-only: - #cdef double imag "cval.imag" - #cdef double real "cval.real" + + @property + cdef inline double real(self): + return self.cval.real + + @property + cdef inline double imag(self): + return self.cval.imag # PyTypeObject PyComplex_Type # This instance of PyTypeObject represents the Python complex diff --git a/Cython/Includes/cpython/contextvars.pxd b/Cython/Includes/cpython/contextvars.pxd new file mode 100644 index 000000000..aa8002664 --- /dev/null +++ b/Cython/Includes/cpython/contextvars.pxd @@ -0,0 +1,140 @@ +from cpython.object cimport PyObject +from cpython.ref cimport Py_XDECREF + +cdef extern from "Python.h": + # Defining PyContextVar_Get() below to always return the default value for Py<3.7 and PyPy<7.3.6 + # to make the inline functions sort-of work. + """ + #if (PY_VERSION_HEX < 0x030700b1 || (CYTHON_COMPILING_IN_PYPY && PYPY_VERSION_NUM < 0x07030600)) && !defined(PyContextVar_Get) + #define PyContextVar_Get(var, d, v) \ + ((d) ? \ + ((void)(var), Py_INCREF(d), (v)[0] = (d), 0) : \ + ((v)[0] = NULL, 0) \ + ) + #endif + """ + + ############################################################################ + # Context Variables Objects + ############################################################################ + + # PyContext + # The C structure used to represent a `contextvars.Context` object. + + # PyContextVar + # The C structure used to represent a `contextvars.ContextVar` object. + + # PyContextToken + # The C structure used to represent a `contextvars.Token` object. + + # PyTypeObject PyContext_Type + # Type object representing the `contextvars.Context` type. + + # PyTypeObject PyContextVar_Type + # Type object representing the `contextvars.ContextVar` type. + + # PyTypeObject PyContextToken_Type + # Type object representing the `contextvars.Token` type. + + bint PyContext_CheckExact(object obj) + # Return `true` if `obj` is of type `PyContext_Type`. + # `obj` must not be NULL. This function always succeeds. + + bint PyContextVar_CheckExact(object obj) + # Return `true` if `obj` is of type `PyContextVar_Type`. + # `obj` must not be NULL. This function always succeeds. + + bint PyContextToken_CheckExact(object obj) + # Return `true` if `obj` is of type `PyContextToken_Type`. + # `obj` must not be NULL. This function always succeeds. + + object PyContext_New() + # Return value: New reference. + # Create a new empty context object. + # Returns NULL if an error has occurred. + + object PyContext_Copy(object ctx) + # Return value: New reference. + # Create a shallow copy of the passed `ctx` context object. + # Returns NULL if an error has occurred. + + object PyContext_CopyCurrent() + # Return value: New reference. + # Create a shallow copy of the current thread context. + # Returns NULL if an error has occurred. + + int PyContext_Enter(object ctx) except -1 + # Set `ctx` as the current context for the current thread. + # Returns 0 on success, and -1 on error. + + int PyContext_Exit(object ctx) except -1 + # Deactivate the `ctx` context and restore the previous context + # as the current context for the current thread. + # Returns 0 on success, and -1 on error. + + object PyContextVar_New(const char* name, PyObject* default_value) + # Return value: New reference. + # Create a new ContextVar object. The `name` parameter is used + # for introspection and debug purposes. The `default_value` parameter + # may optionally specify the default value for the context variable. + # If an error has occurred, this function returns NULL. + + object PyContextVar_New_with_default "PyContextVar_New" (const char* name, object default_value) + # A different declaration of PyContextVar_New that requires a default value + # to be passed on call. + + int PyContextVar_Get(object var, PyObject* default_value, PyObject** value) except -1 + # Get the value of a context variable. + # Returns -1 if an error has occurred during lookup, and 0 if no error + # occurred, whether or not a value was found. + # + # If the context variable was found, `value` will be a pointer to it. + # If the context variable was not found, `value` will point to: + # + # • `default_value`, if not NULL; + # • the default value of `var`, if not NULL; + # • NULL + int PyContextVar_Get_with_default "PyContextVar_Get" (object var, object default_value, PyObject** value) except -1 + # A different declaration of PyContextVar_Get that requires a default value + # to be passed on call. + + object PyContextVar_Set(object var, object value) + # Return value: New reference. + # Set the value of `var` to `value` in the current context. + # Returns a token object for this value change, or NULL if an error has occurred. + + int PyContextVar_Reset(object var, object token) except -1 + # Reset the state of the `var` context variable to that it was in + # before `PyContextVar_Set()` that returned `token` was called. + # This function returns 0 on success and -1 on error. + + +cdef inline object get_value(var, default_value=None): + """Return a new reference to the value of the context variable, + or the default value of the context variable, + or None if no such value or default was found. + """ + cdef PyObject *value = NULL + PyContextVar_Get(var, NULL, &value) + if value is NULL: + # context variable does not have a default + pyvalue = default_value + else: + # value or default value of context variable + pyvalue = <object>value + Py_XDECREF(value) # PyContextVar_Get() returned an owned reference as 'PyObject*' + return pyvalue + + +cdef inline object get_value_no_default(var, default_value=None): + """Return a new reference to the value of the context variable, + or the provided default value if no such value was found. + + Ignores the default value of the context variable, if any. + """ + cdef PyObject *value = NULL + PyContextVar_Get(var, <PyObject*>default_value, &value) + # value of context variable or 'default_value' + pyvalue = <object>value + Py_XDECREF(value) # PyContextVar_Get() returned an owned reference as 'PyObject*' + return pyvalue diff --git a/Cython/Includes/cpython/datetime.pxd b/Cython/Includes/cpython/datetime.pxd index cd0f90719..7d6ee29f3 100644 --- a/Cython/Includes/cpython/datetime.pxd +++ b/Cython/Includes/cpython/datetime.pxd @@ -1,22 +1,161 @@ from cpython.object cimport PyObject +from cpython.version cimport PY_VERSION_HEX cdef extern from "Python.h": ctypedef struct PyTypeObject: pass cdef extern from "datetime.h": + """ + /* Backport for Python 2.x */ + #if PY_MAJOR_VERSION < 3 + #ifndef PyDateTime_DELTA_GET_DAYS + #define PyDateTime_DELTA_GET_DAYS(o) (((PyDateTime_Delta*)o)->days) + #endif + #ifndef PyDateTime_DELTA_GET_SECONDS + #define PyDateTime_DELTA_GET_SECONDS(o) (((PyDateTime_Delta*)o)->seconds) + #endif + #ifndef PyDateTime_DELTA_GET_MICROSECONDS + #define PyDateTime_DELTA_GET_MICROSECONDS(o) (((PyDateTime_Delta*)o)->microseconds) + #endif + #endif + + /* Backport for Python < 3.6 */ + #if PY_VERSION_HEX < 0x030600a4 + #ifndef PyDateTime_TIME_GET_FOLD + #define PyDateTime_TIME_GET_FOLD(o) ((void)(o), 0) + #endif + #ifndef PyDateTime_DATE_GET_FOLD + #define PyDateTime_DATE_GET_FOLD(o) ((void)(o), 0) + #endif + #endif + + /* Backport for Python < 3.6 */ + #if PY_VERSION_HEX < 0x030600a4 + #define __Pyx_DateTime_DateTimeWithFold(year, month, day, hour, minute, second, microsecond, tz, fold) \ + ((void)(fold), PyDateTimeAPI->DateTime_FromDateAndTime(year, month, day, hour, minute, second, \ + microsecond, tz, PyDateTimeAPI->DateTimeType)) + #define __Pyx_DateTime_TimeWithFold(hour, minute, second, microsecond, tz, fold) \ + ((void)(fold), PyDateTimeAPI->Time_FromTime(hour, minute, second, microsecond, tz, PyDateTimeAPI->TimeType)) + #else /* For Python 3.6+ so that we can pass tz */ + #define __Pyx_DateTime_DateTimeWithFold(year, month, day, hour, minute, second, microsecond, tz, fold) \ + PyDateTimeAPI->DateTime_FromDateAndTimeAndFold(year, month, day, hour, minute, second, \ + microsecond, tz, fold, PyDateTimeAPI->DateTimeType) + #define __Pyx_DateTime_TimeWithFold(hour, minute, second, microsecond, tz, fold) \ + PyDateTimeAPI->Time_FromTimeAndFold(hour, minute, second, microsecond, tz, fold, PyDateTimeAPI->TimeType) + #endif + + /* Backport for Python < 3.7 */ + #if PY_VERSION_HEX < 0x030700b1 + #define __Pyx_TimeZone_UTC NULL + #define __Pyx_TimeZone_FromOffsetAndName(offset, name) ((void)(offset), (void)(name), (PyObject*)NULL) + #else + #define __Pyx_TimeZone_UTC PyDateTime_TimeZone_UTC + #define __Pyx_TimeZone_FromOffsetAndName(offset, name) PyTimeZone_FromOffsetAndName(offset, name) + #endif + + /* Backport for Python < 3.10 */ + #if PY_VERSION_HEX < 0x030a00a1 + #ifndef PyDateTime_TIME_GET_TZINFO + #define PyDateTime_TIME_GET_TZINFO(o) \ + ((((PyDateTime_Time*)o)->hastzinfo) ? ((PyDateTime_Time*)o)->tzinfo : Py_None) + #endif + #ifndef PyDateTime_DATE_GET_TZINFO + #define PyDateTime_DATE_GET_TZINFO(o) \ + ((((PyDateTime_DateTime*)o)->hastzinfo) ? ((PyDateTime_DateTime*)o)->tzinfo : Py_None) + #endif + #endif + """ ctypedef extern class datetime.date[object PyDateTime_Date]: - pass + @property + cdef inline int year(self): + return PyDateTime_GET_YEAR(self) + + @property + cdef inline int month(self): + return PyDateTime_GET_MONTH(self) + + @property + cdef inline int day(self): + return PyDateTime_GET_DAY(self) ctypedef extern class datetime.time[object PyDateTime_Time]: - pass + @property + cdef inline int hour(self): + return PyDateTime_TIME_GET_HOUR(self) + + @property + cdef inline int minute(self): + return PyDateTime_TIME_GET_MINUTE(self) + + @property + cdef inline int second(self): + return PyDateTime_TIME_GET_SECOND(self) + + @property + cdef inline int microsecond(self): + return PyDateTime_TIME_GET_MICROSECOND(self) + + @property + cdef inline object tzinfo(self): + return <object>PyDateTime_TIME_GET_TZINFO(self) + + @property + cdef inline int fold(self): + # For Python < 3.6 this returns 0 no matter what + return PyDateTime_TIME_GET_FOLD(self) ctypedef extern class datetime.datetime[object PyDateTime_DateTime]: - pass + @property + cdef inline int year(self): + return PyDateTime_GET_YEAR(self) + + @property + cdef inline int month(self): + return PyDateTime_GET_MONTH(self) + + @property + cdef inline int day(self): + return PyDateTime_GET_DAY(self) + + @property + cdef inline int hour(self): + return PyDateTime_DATE_GET_HOUR(self) + + @property + cdef inline int minute(self): + return PyDateTime_DATE_GET_MINUTE(self) + + @property + cdef inline int second(self): + return PyDateTime_DATE_GET_SECOND(self) + + @property + cdef inline int microsecond(self): + return PyDateTime_DATE_GET_MICROSECOND(self) + + @property + cdef inline object tzinfo(self): + return <object>PyDateTime_DATE_GET_TZINFO(self) + + @property + cdef inline int fold(self): + # For Python < 3.6 this returns 0 no matter what + return PyDateTime_DATE_GET_FOLD(self) ctypedef extern class datetime.timedelta[object PyDateTime_Delta]: - pass + @property + cdef inline int day(self): + return PyDateTime_DELTA_GET_DAYS(self) + + @property + cdef inline int second(self): + return PyDateTime_DELTA_GET_SECONDS(self) + + @property + cdef inline int microsecond(self): + return PyDateTime_DELTA_GET_MICROSECONDS(self) ctypedef extern class datetime.tzinfo[object PyDateTime_TZInfo]: pass @@ -25,10 +164,12 @@ cdef extern from "datetime.h": pass ctypedef struct PyDateTime_Time: + unsigned char fold char hastzinfo PyObject *tzinfo ctypedef struct PyDateTime_DateTime: + unsigned char fold char hastzinfo PyObject *tzinfo @@ -47,14 +188,27 @@ cdef extern from "datetime.h": PyTypeObject *TZInfoType # constructors - object (*Date_FromDate)(int, int, int, PyTypeObject*) - object (*DateTime_FromDateAndTime)(int, int, int, int, int, int, int, object, PyTypeObject*) - object (*Time_FromTime)(int, int, int, int, object, PyTypeObject*) - object (*Delta_FromDelta)(int, int, int, int, PyTypeObject*) + date (*Date_FromDate)(int, int, int, PyTypeObject*) + datetime (*DateTime_FromDateAndTime)(int, int, int, int, int, int, int, object, PyTypeObject*) + time (*Time_FromTime)(int, int, int, int, object, PyTypeObject*) + timedelta (*Delta_FromDelta)(int, int, int, int, PyTypeObject*) # constructors for the DB API - object (*DateTime_FromTimestamp)(object, object, object) - object (*Date_FromTimestamp)(object, object) + datetime (*DateTime_FromTimestamp)(PyObject*, object, PyObject*) + date (*Date_FromTimestamp)(PyObject*, object) + + # We cannot use the following because they do not compile in older Python versions. + # Instead, we use datetime.h's macros here that we can backport in C. + + # Python 3.7+ constructors + object (*TimeZone_FromTimeZone)(object offset, PyObject *name) + + # Python 3.7+ singletons + PyObject *TimeZone_UTC + + # Python 3.6+ PEP 495 constructors + datetime (*DateTime_FromDateAndTimeAndFold)(int, int, int, int, int, int, int, object, int, PyTypeObject*) + time (*Time_FromTimeAndFold)(int, int, int ,int, object, int, PyTypeObject*) # Check type of the object. bint PyDate_Check(object op) @@ -82,21 +236,45 @@ cdef extern from "datetime.h": int PyDateTime_DATE_GET_MINUTE(object o) int PyDateTime_DATE_GET_SECOND(object o) int PyDateTime_DATE_GET_MICROSECOND(object o) + int PyDateTime_DATE_GET_FOLD(object o) + PyObject* PyDateTime_DATE_GET_TZINFO(object o) # returns a borrowed reference # Getters for time (C macros). int PyDateTime_TIME_GET_HOUR(object o) int PyDateTime_TIME_GET_MINUTE(object o) int PyDateTime_TIME_GET_SECOND(object o) int PyDateTime_TIME_GET_MICROSECOND(object o) + int PyDateTime_TIME_GET_FOLD(object o) + PyObject* PyDateTime_TIME_GET_TZINFO(object o) # returns a borrowed reference # Getters for timedelta (C macros). int PyDateTime_DELTA_GET_DAYS(object o) int PyDateTime_DELTA_GET_SECONDS(object o) int PyDateTime_DELTA_GET_MICROSECONDS(object o) + # Constructors + object PyTimeZone_FromOffset(object offset) + object PyTimeZone_FromOffsetAndName(object offset, object name) + + # The above macros is Python 3.7+ so we use these instead + object __Pyx_TimeZone_FromOffsetAndName(object offset, PyObject* name) + + # Constructors for the DB API + datetime PyDateTime_FromTimeStamp(object args) + date PyDate_FromTimeStamp(object args) + + # PEP 495 constructors but patched above to allow passing tz + datetime __Pyx_DateTime_DateTimeWithFold(int, int, int, int, int, int, int, object, int) + datetime __Pyx_DateTime_TimeWithFold(int, int, int ,int, object, int) + # PyDateTime CAPI object. PyDateTime_CAPI *PyDateTimeAPI + PyObject* PyDateTime_TimeZone_UTC + + # PyDateTime_TimeZone_UTC is Python 3.7+ so instead we use the following macro + PyObject* __Pyx_TimeZone_UTC + void PyDateTime_IMPORT() # Datetime C API initialization function. @@ -106,42 +284,57 @@ cdef inline void import_datetime(): # Create date object using DateTime CAPI factory function. # Note, there are no range checks for any of the arguments. -cdef inline object date_new(int year, int month, int day): +cdef inline date date_new(int year, int month, int day): return PyDateTimeAPI.Date_FromDate(year, month, day, PyDateTimeAPI.DateType) # Create time object using DateTime CAPI factory function # Note, there are no range checks for any of the arguments. -cdef inline object time_new(int hour, int minute, int second, int microsecond, object tz): - return PyDateTimeAPI.Time_FromTime(hour, minute, second, microsecond, tz, PyDateTimeAPI.TimeType) +cdef inline time time_new(int hour, int minute, int second, int microsecond, object tz, int fold=0): + return __Pyx_DateTime_TimeWithFold(hour, minute, second, microsecond, tz, fold) # Create datetime object using DateTime CAPI factory function. # Note, there are no range checks for any of the arguments. -cdef inline object datetime_new(int year, int month, int day, int hour, int minute, int second, int microsecond, object tz): - return PyDateTimeAPI.DateTime_FromDateAndTime(year, month, day, hour, minute, second, microsecond, tz, PyDateTimeAPI.DateTimeType) +cdef inline datetime datetime_new(int year, int month, int day, int hour, int minute, int second, int microsecond, object tz, int fold=0): + return __Pyx_DateTime_DateTimeWithFold(year, month, day, hour, minute, second, microsecond, tz, fold) # Create timedelta object using DateTime CAPI factory function. # Note, there are no range checks for any of the arguments. -cdef inline object timedelta_new(int days, int seconds, int useconds): +cdef inline timedelta timedelta_new(int days, int seconds, int useconds): return PyDateTimeAPI.Delta_FromDelta(days, seconds, useconds, 1, PyDateTimeAPI.DeltaType) +# Create timedelta object using DateTime CAPI factory function. +cdef inline object timezone_new(object offset, object name=None): + if PY_VERSION_HEX < 0x030700b1: + raise RuntimeError('Time zones are not available from the C-API.') + return __Pyx_TimeZone_FromOffsetAndName(offset, <PyObject*>name if name is not None else NULL) + +# Create datetime object using DB API constructor. +cdef inline datetime datetime_from_timestamp(timestamp, tz=None): + return PyDateTimeAPI.DateTime_FromTimestamp( + <PyObject*>PyDateTimeAPI.DateTimeType, (timestamp, tz) if tz is not None else (timestamp,), NULL) + +# Create date object using DB API constructor. +cdef inline date date_from_timestamp(timestamp): + return PyDateTimeAPI.Date_FromTimestamp(<PyObject*>PyDateTimeAPI.DateType, (timestamp,)) + # More recognizable getters for date/time/datetime/timedelta. # There are no setters because datetime.h hasn't them. # This is because of immutable nature of these objects by design. # If you would change time/date/datetime/timedelta object you need to recreate. +# Get UTC singleton +cdef inline object get_utc(): + if PY_VERSION_HEX < 0x030700b1: + raise RuntimeError('Time zones are not available from the C-API.') + return <object>__Pyx_TimeZone_UTC + # Get tzinfo of time cdef inline object time_tzinfo(object o): - if (<PyDateTime_Time*>o).hastzinfo: - return <object>(<PyDateTime_Time*>o).tzinfo - else: - return None + return <object>PyDateTime_TIME_GET_TZINFO(o) # Get tzinfo of datetime cdef inline object datetime_tzinfo(object o): - if (<PyDateTime_DateTime*>o).hastzinfo: - return <object>(<PyDateTime_DateTime*>o).tzinfo - else: - return None + return <object>PyDateTime_DATE_GET_TZINFO(o) # Get year of date cdef inline int date_year(object o): @@ -183,6 +376,11 @@ cdef inline int time_second(object o): cdef inline int time_microsecond(object o): return PyDateTime_TIME_GET_MICROSECOND(o) +# Get fold of time +cdef inline int time_fold(object o): + # For Python < 3.6 this returns 0 no matter what + return PyDateTime_TIME_GET_FOLD(o) + # Get hour of datetime cdef inline int datetime_hour(object o): return PyDateTime_DATE_GET_HOUR(o) @@ -199,6 +397,11 @@ cdef inline int datetime_second(object o): cdef inline int datetime_microsecond(object o): return PyDateTime_DATE_GET_MICROSECOND(o) +# Get fold of datetime +cdef inline int datetime_fold(object o): + # For Python < 3.6 this returns 0 no matter what + return PyDateTime_DATE_GET_FOLD(o) + # Get days of timedelta cdef inline int timedelta_days(object o): return (<PyDateTime_Delta*>o).days @@ -210,3 +413,14 @@ cdef inline int timedelta_seconds(object o): # Get microseconds of timedelta cdef inline int timedelta_microseconds(object o): return (<PyDateTime_Delta*>o).microseconds + +cdef inline double total_seconds(timedelta obj): + # Mirrors the "timedelta.total_seconds()" method. + # Note that this implementation is not guaranteed to give *exactly* the same + # result as the original method, due to potential differences in floating point rounding. + cdef: + double days, seconds, micros + days = <double>PyDateTime_DELTA_GET_DAYS(obj) + seconds = <double>PyDateTime_DELTA_GET_SECONDS(obj) + micros = <double>PyDateTime_DELTA_GET_MICROSECONDS(obj) + return days * 24 * 3600 + seconds + micros / 1_000_000 diff --git a/Cython/Includes/cpython/descr.pxd b/Cython/Includes/cpython/descr.pxd new file mode 100644 index 000000000..5075f0bbd --- /dev/null +++ b/Cython/Includes/cpython/descr.pxd @@ -0,0 +1,26 @@ +from .object cimport PyObject, PyTypeObject + +cdef extern from "Python.h": + ctypedef object (*wrapperfunc)(self, args, void* wrapped) + ctypedef object (*wrapperfunc_kwds)(self, args, void* wrapped, kwds) + + struct wrapperbase: + char* name + int offset + void* function + wrapperfunc wrapper + char* doc + int flags + PyObject* name_strobj + + int PyWrapperFlag_KEYWORDS + + ctypedef class __builtin__.wrapper_descriptor [object PyWrapperDescrObject]: + cdef type d_type + cdef d_name + cdef wrapperbase* d_base + cdef void* d_wrapped + + object PyDescr_NewWrapper(PyTypeObject* cls, wrapperbase* wrapper, void* wrapped) + + int PyDescr_IsData(descr) diff --git a/Cython/Includes/cpython/dict.pxd b/Cython/Includes/cpython/dict.pxd index 16dd5e145..979dd392a 100644 --- a/Cython/Includes/cpython/dict.pxd +++ b/Cython/Includes/cpython/dict.pxd @@ -1,6 +1,13 @@ from .object cimport PyObject +from .pyport cimport uint64_t cdef extern from "Python.h": + # On Python 2, PyDict_GetItemWithError is called _PyDict_GetItemWithError + """ + #if PY_MAJOR_VERSION <= 2 + #define PyDict_GetItemWithError _PyDict_GetItemWithError + #endif + """ ############################################################################ # 7.4.1 Dictionary Objects @@ -72,11 +79,25 @@ cdef extern from "Python.h": # NULL if the key key is not present, but without setting an # exception. + PyObject* PyDict_GetItemWithError(object p, object key) except? NULL + # Return value: Borrowed reference. + # Variant of PyDict_GetItem() that does not suppress exceptions. Return + # NULL with an exception set if an exception occurred. Return NULL + # without an exception set if the key wasn’t present. + PyObject* PyDict_GetItemString(object p, const char *key) # Return value: Borrowed reference. # This is the same as PyDict_GetItem(), but key is specified as a # char*, rather than a PyObject*. + PyObject* PyDict_SetDefault(object p, object key, object default) except NULL + # Return value: Borrowed reference. + # This is the same as the Python-level dict.setdefault(). If present, it + # returns the value corresponding to key from the dictionary p. If the key + # is not in the dict, it is inserted with value defaultobj and defaultobj + # is returned. This function evaluates the hash function of key only once, + # instead of evaluating it independently for the lookup and the insertion. + list PyDict_Items(object p) # Return value: New reference. # Return a PyListObject containing all the items from the diff --git a/Cython/Includes/cpython/exc.pxd b/Cython/Includes/cpython/exc.pxd index bc57c0e57..756342ad3 100644 --- a/Cython/Includes/cpython/exc.pxd +++ b/Cython/Includes/cpython/exc.pxd @@ -88,6 +88,11 @@ cdef extern from "Python.h": # needs to handle exceptions or by code that needs to save and # restore the error indicator temporarily. + PyObject* PyErr_GetHandledException() + void PyErr_SetHandledException(PyObject* exc) + PyObject* PyErr_GetRaisedException() + void PyErr_SetRaisedException(PyObject* exc) + void PyErr_Restore(PyObject* type, PyObject* value, PyObject* traceback) # Set the error indicator from the three objects. If the error # indicator is already set, it is cleared first. If the objects @@ -236,6 +241,8 @@ cdef extern from "Python.h": # KeyboardInterrupt will be raised. It may be called without # holding the interpreter lock. + int PyErr_SetInterruptEx(int signum) + object PyErr_NewException(char *name, object base, object dict) # Return value: New reference. # This utility function creates and returns a new exception @@ -254,4 +261,3 @@ cdef extern from "Python.h": # identifies the context in which the unraisable exception # occurred. The repr of obj will be printed in the warning # message. - diff --git a/Cython/Includes/cpython/fileobject.pxd b/Cython/Includes/cpython/fileobject.pxd new file mode 100644 index 000000000..e52cd33f5 --- /dev/null +++ b/Cython/Includes/cpython/fileobject.pxd @@ -0,0 +1,57 @@ +""" +From https://docs.python.org/3.9/c-api/file.html + +These APIs are a minimal emulation of the Python 2 C API for built-in file objects, +which used to rely on the buffered I/O (FILE*) support from the C standard library. +In Python 3, files and streams use the new io module, which defines several layers +over the low-level unbuffered I/O of the operating system. The functions described +below are convenience C wrappers over these new APIs, and meant mostly for internal +error reporting in the interpreter; + +third-party code is advised to access the io APIs instead. +""" + +cdef extern from "Python.h": + + ########################################################################### + # File Objects + ########################################################################### + + object PyFile_FromFd(int fd, const char *name, const char *mode, int buffering, + const char *encoding, const char *errors, const char *newline, int closefd) + # Return value: New reference. + # Create a Python file object from the file descriptor of an already + # opened file fd. The arguments name, encoding, errors and newline can be + # NULL to use the defaults; buffering can be -1 to use the default. name + # is ignored and kept for backward compatibility. Return NULL on failure. + # For a more comprehensive description of the arguments, please refer to + # the io.open() function documentation. + + # Warning: Since Python streams have their own buffering layer, mixing + # them with OS-level file descriptors can produce various issues (such as + # unexpected ordering of data). + + # Changed in version 3.2: Ignore name attribute. + + object PyFile_GetLine(object p, int n) + # Return value: New reference. + # Equivalent to p.readline([n]), this function reads one line from the + # object p. p may be a file object or any object with a readline() + # method. If n is 0, exactly one line is read, regardless of the length of + # the line. If n is greater than 0, no more than n bytes will be read from + # the file; a partial line can be returned. In both cases, an empty string + # is returned if the end of the file is reached immediately. If n is less + # than 0, however, one line is read regardless of length, but EOFError is + # raised if the end of the file is reached immediately. + + int PyFile_WriteObject(object obj, object p, int flags) except? -1 + # Write object obj to file object p. The only supported flag for flags + # is Py_PRINT_RAW; if given, the str() of the object is written instead of + # the repr(). Return 0 on success or -1 on failure; the appropriate + # exception will be set. + + int PyFile_WriteString(const char *s, object p) except? -1 + # Write string s to file object p. Return 0 on success or -1 on failure; + # the appropriate exception will be set. + + enum: Py_PRINT_RAW diff --git a/Cython/Includes/cpython/float.pxd b/Cython/Includes/cpython/float.pxd index 65328f31e..7c567a80f 100644 --- a/Cython/Includes/cpython/float.pxd +++ b/Cython/Includes/cpython/float.pxd @@ -1,4 +1,11 @@ cdef extern from "Python.h": + """ + #if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyFloat_FromString(obj) PyFloat_FromString(obj) + #else + #define __Pyx_PyFloat_FromString(obj) PyFloat_FromString(obj, NULL) + #endif + """ ############################################################################ # 7.2.3 @@ -21,7 +28,7 @@ cdef extern from "Python.h": # Return true if its argument is a PyFloatObject, but not a # subtype of PyFloatObject. - object PyFloat_FromString(object str, char **pend) + object PyFloat_FromString "__Pyx_PyFloat_FromString" (object str) # Return value: New reference. # Create a PyFloatObject object based on the string value in str, # or NULL on failure. The pend argument is ignored. It remains diff --git a/Cython/Includes/cpython/list.pxd b/Cython/Includes/cpython/list.pxd index c6a29535c..1d0503c2c 100644 --- a/Cython/Includes/cpython/list.pxd +++ b/Cython/Includes/cpython/list.pxd @@ -42,17 +42,19 @@ cdef extern from "Python.h": int PyList_SetItem(object list, Py_ssize_t index, object item) except -1 # Set the item at index index in list to item. Return 0 on success - # or -1 on failure. Note: This function ``steals'' a reference to - # item and discards a reference to an item already in the list at - # the affected position. + # or -1 on failure. + # + # WARNING: This function _steals_ a reference to item and discards a + # reference to an item already in the list at the affected position. void PyList_SET_ITEM(object list, Py_ssize_t i, object o) # Macro form of PyList_SetItem() without error checking. This is # normally only used to fill in new lists where there is no - # previous content. Note: This function ``steals'' a reference to - # item, and, unlike PyList_SetItem(), does not discard a reference - # to any item that it being replaced; any reference in list at - # position i will be *leaked*. + # previous content. + # + # WARNING: This function _steals_ a reference to item, and, unlike + # PyList_SetItem(), does not discard a reference to any item that + # it being replaced; any reference in list at position i will be *leaked*. int PyList_Insert(object list, Py_ssize_t index, object item) except -1 # Insert the item item into list list in front of index @@ -88,5 +90,3 @@ cdef extern from "Python.h": # Return value: New reference. # Return a new tuple object containing the contents of list; # equivalent to "tuple(list)". - - diff --git a/Cython/Includes/cpython/long.pxd b/Cython/Includes/cpython/long.pxd index eb8140d41..f65cd0073 100644 --- a/Cython/Includes/cpython/long.pxd +++ b/Cython/Includes/cpython/long.pxd @@ -89,7 +89,7 @@ cdef extern from "Python.h": # Return a C long representation of the contents of pylong. If # pylong is greater than LONG_MAX, an OverflowError is raised. - # long PyLong_AsLongAndOverflow(object pylong, int *overflow) except? -1 + long PyLong_AsLongAndOverflow(object pylong, int *overflow) except? -1 # Return a C long representation of the contents of pylong. If pylong is # greater than LONG_MAX or less than LONG_MIN, set *overflow to 1 or -1, # respectively, and return -1; otherwise, set *overflow to 0. If any other @@ -97,7 +97,7 @@ cdef extern from "Python.h": # be returned and *overflow will be 0. # New in version 2.7. - # PY_LONG_LONG PyLong_AsLongLongAndOverflow(object pylong, int *overflow) except? -1 + PY_LONG_LONG PyLong_AsLongLongAndOverflow(object pylong, int *overflow) except? -1 # Return a C long long representation of the contents of pylong. If pylong # is greater than PY_LLONG_MAX or less than PY_LLONG_MIN, set *overflow to # 1 or -1, respectively, and return -1; otherwise, set *overflow to 0. If diff --git a/Cython/Includes/cpython/mapping.pxd b/Cython/Includes/cpython/mapping.pxd index 3d235b65e..5e54af531 100644 --- a/Cython/Includes/cpython/mapping.pxd +++ b/Cython/Includes/cpython/mapping.pxd @@ -61,4 +61,3 @@ cdef extern from "Python.h": # Map the object key to the value v in object o. Returns -1 on # failure. This is the equivalent of the Python statement "o[key] # = v". - diff --git a/Cython/Includes/cpython/marshal.pxd b/Cython/Includes/cpython/marshal.pxd new file mode 100644 index 000000000..1d8a54c86 --- /dev/null +++ b/Cython/Includes/cpython/marshal.pxd @@ -0,0 +1,66 @@ +from libc.stdio cimport FILE + +cdef extern from "Python.h": + + ########################################################################### + # Data marshalling support + ########################################################################### + + const int Py_MARSHAL_VERSION + + void PyMarshal_WriteLongToFile(long value, FILE *file, int version) + # Marshal a long integer, value, to file. This will only write the + # least-significant 32 bits of value, regardless of the size of the native + # long type. version indicates the file format. + + void PyMarshal_WriteObjectToFile(object value, FILE *file, int version) + # Marshal a Python object, value, to file. version indicates the file + # format. + + bytes PyMarshal_WriteObjectToString(object value, int version) + # Return value: New reference. + # Return a bytes object containing the marshalled representation of value. + # version indicates the file format. + + long PyMarshal_ReadLongFromFile(FILE *file) except? -1 + # Return a C long from the data stream in a FILE* opened for reading. Only + # a 32-bit value can be read in using this function, regardless of the + # native size of long. + + # On error, sets the appropriate exception (EOFError) and returns -1. + + int PyMarshal_ReadShortFromFile(FILE *file) except? -1 + # Return a C short from the data stream in a FILE* opened for reading. Only + # a 16-bit value can be read in using this function, regardless of the + # native size of short. + + # On error, sets the appropriate exception (EOFError) and returns -1. + + object PyMarshal_ReadObjectFromFile(FILE *file) + # Return value: New reference. + # Return a Python object from the data stream in a FILE* opened for + # reading. + + # On error, sets the appropriate exception (EOFError, ValueError or + # TypeError) and returns NULL. + + object PyMarshal_ReadLastObjectFromFile(FILE *file) + # Return value: New reference. + # Return a Python object from the data stream in a FILE* opened for + # reading. Unlike PyMarshal_ReadObjectFromFile(), this function assumes + # that no further objects will be read from the file, allowing it to + # aggressively load file data into memory so that the de-serialization can + # operate from data in memory, rather than reading a byte at a time from the + # file. Only use these variant if you are certain that you won’t be reading + # anything else from the file. + + # On error, sets the appropriate exception (EOFError, ValueError or + # TypeError) and returns NULL. + + object PyMarshal_ReadObjectFromString(const char *data, Py_ssize_t len) + # Return value: New reference. + # Return a Python object from the data stream in a byte buffer containing + # len bytes pointed to by data. + + # On error, sets the appropriate exception (EOFError, ValueError or + # TypeError) and returns NULL. diff --git a/Cython/Includes/cpython/mem.pxd b/Cython/Includes/cpython/mem.pxd index af820f2ee..236d111f6 100644 --- a/Cython/Includes/cpython/mem.pxd +++ b/Cython/Includes/cpython/mem.pxd @@ -35,6 +35,15 @@ cdef extern from "Python.h": # PyMem_Malloc(1) had been called instead. The memory will not # have been initialized in any way. + void* PyMem_RawCalloc(size_t nelem, size_t elsize) nogil + void* PyMem_Calloc(size_t nelem, size_t elsize) + # Allocates nelem elements each whose size in bytes is elsize and + # returns a pointer of type void* to the allocated memory, or NULL if + # the request fails. The memory is initialized to zeros. Requesting + # zero elements or elements of size zero bytes returns a distinct + # non-NULL pointer if possible, as if PyMem_Calloc(1, 1) had been + # called instead. + void* PyMem_RawRealloc(void *p, size_t n) nogil void* PyMem_Realloc(void *p, size_t n) # Resizes the memory block pointed to by p to n bytes. The @@ -43,13 +52,13 @@ cdef extern from "Python.h": # else if n is equal to zero, the memory block is resized but is # not freed, and the returned pointer is non-NULL. Unless p is # NULL, it must have been returned by a previous call to - # PyMem_Malloc() or PyMem_Realloc(). + # PyMem_Malloc(), PyMem_Realloc(), or PyMem_Calloc(). void PyMem_RawFree(void *p) nogil void PyMem_Free(void *p) # Frees the memory block pointed to by p, which must have been - # returned by a previous call to PyMem_Malloc() or - # PyMem_Realloc(). Otherwise, or if PyMem_Free(p) has been called + # returned by a previous call to PyMem_Malloc(), PyMem_Realloc(), or + # PyMem_Calloc(). Otherwise, or if PyMem_Free(p) has been called # before, undefined behavior occurs. If p is NULL, no operation is # performed. diff --git a/Cython/Includes/cpython/module.pxd b/Cython/Includes/cpython/module.pxd index 8eb323b01..ea4c3817e 100644 --- a/Cython/Includes/cpython/module.pxd +++ b/Cython/Includes/cpython/module.pxd @@ -145,6 +145,12 @@ cdef extern from "Python.h": bint PyModule_CheckExact(object p) # Return true if p is a module object, but not a subtype of PyModule_Type. + object PyModule_NewObject(object name) + # Return a new module object with the __name__ attribute set to name. + # The module’s __name__, __doc__, __package__, and __loader__ + # attributes are filled in (all but __name__ are set to None); the caller + # is responsible for providing a __file__ attribute. + object PyModule_New(const char *name) # Return value: New reference. # Return a new module object with the __name__ attribute set to @@ -160,21 +166,35 @@ cdef extern from "Python.h": # use other PyModule_*() and PyObject_*() functions rather than # directly manipulate a module's __dict__. + object PyModule_GetNameObject(object module) + # Return module’s __name__ value. If the module does not provide one, or if + # it is not a string, SystemError is raised and NULL is returned. + char* PyModule_GetName(object module) except NULL - # Return module's __name__ value. If the module does not provide - # one, or if it is not a string, SystemError is raised and NULL is - # returned. + # Similar to PyModule_GetNameObject() but return the name encoded + # to 'utf-8'. + + void* PyModule_GetState(object module) + # Return the “state” of the module, that is, a pointer to the block of + # memory allocated at module creation time, or NULL. + # See PyModuleDef.m_size. + + object PyModule_GetFilenameObject(object module) + # Return the name of the file from which module was loaded using module’s + # __file__ attribute. If this is not defined, or if it is not a unicode + # string, raise SystemError and return NULL; otherwise return a reference + # to a Unicode object. char* PyModule_GetFilename(object module) except NULL - # Return the name of the file from which module was loaded using - # module's __file__ attribute. If this is not defined, or if it is - # not a string, raise SystemError and return NULL. + # Similar to PyModule_GetFilenameObject() but return the filename encoded + # to ‘utf-8’. int PyModule_AddObject(object module, const char *name, object value) except -1 # Add an object to module as name. This is a convenience function - # which can be used from the module's initialization - # function. This steals a reference to value. Return -1 on error, - # 0 on success. + # which can be used from the module's initialization function. + # Return -1 on error, 0 on success. + # + # WARNING: This _steals_ a reference to value. int PyModule_AddIntConstant(object module, const char *name, long value) except -1 # Add an integer constant to module as name. This convenience diff --git a/Cython/Includes/cpython/object.pxd b/Cython/Includes/cpython/object.pxd index 5a8116639..41874159c 100644 --- a/Cython/Includes/cpython/object.pxd +++ b/Cython/Includes/cpython/object.pxd @@ -5,7 +5,7 @@ cdef extern from "Python.h": ctypedef struct PyObject # forward declaration - ctypedef object (*newfunc)(cpython.type.type, object, object) # (type, args, kwargs) + ctypedef object (*newfunc)(cpython.type.type, PyObject*, PyObject*) # (type, args|NULL, kwargs|NULL) ctypedef object (*unaryfunc)(object) ctypedef object (*binaryfunc)(object, object) @@ -35,6 +35,14 @@ cdef extern from "Python.h": ctypedef object (*descrgetfunc)(object, object, object) ctypedef int (*descrsetfunc)(object, object, object) except -1 + ctypedef object (*PyCFunction)(object, object) + + ctypedef struct PyMethodDef: + const char* ml_name + PyCFunction ml_meth + int ml_flags + const char* ml_doc + ctypedef struct PyTypeObject: const char* tp_name const char* tp_doc @@ -45,6 +53,8 @@ cdef extern from "Python.h": newfunc tp_new destructor tp_dealloc + destructor tp_del + destructor tp_finalize traverseproc tp_traverse inquiry tp_clear freefunc tp_free @@ -57,12 +67,16 @@ cdef extern from "Python.h": cmpfunc tp_compare richcmpfunc tp_richcompare + PyMethodDef* tp_methods + PyTypeObject* tp_base PyObject* tp_dict descrgetfunc tp_descr_get descrsetfunc tp_descr_set + unsigned int tp_version_tag + ctypedef struct PyObject: Py_ssize_t ob_refcnt PyTypeObject *ob_type @@ -128,6 +142,17 @@ cdef extern from "Python.h": # failure. This is the equivalent of the Python statement "del # o.attr_name". + object PyObject_GenericGetDict(object o, void *context) + # Return value: New reference. + # A generic implementation for the getter of a __dict__ descriptor. It + # creates the dictionary if necessary. + # New in version 3.3. + + int PyObject_GenericSetDict(object o, object value, void *context) except -1 + # A generic implementation for the setter of a __dict__ descriptor. This + # implementation does not allow the dictionary to be deleted. + # New in version 3.3. + int Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, Py_GE object PyObject_RichCompare(object o1, object o2, int opid) @@ -177,6 +202,14 @@ cdef extern from "Python.h": # equivalent of the Python expression "str(o)". Called by the # str() built-in function and by the print statement. + object PyObject_Bytes(object o) + # Return value: New reference. + # Compute a bytes representation of object o. Return NULL on + # failure and a bytes object on success. This is equivalent to + # the Python expression bytes(o), when o is not an integer. + # Unlike bytes(o), a TypeError is raised when o is an integer + # instead of a zero-initialized bytes object. + object PyObject_Unicode(object o) # Return value: New reference. # Compute a Unicode string representation of object o. Returns the @@ -320,6 +353,13 @@ cdef extern from "Python.h": # returned. On error, -1 is returned. This is the equivalent to # the Python expression "len(o)". + Py_ssize_t PyObject_LengthHint(object o, Py_ssize_t default) except -1 + # Return an estimated length for the object o. First try to return its + # actual length, then an estimate using __length_hint__(), and finally + # return the default value. On error, return -1. This is the equivalent to + # the Python expression "operator.length_hint(o, default)". + # New in version 3.4. + object PyObject_GetItem(object o, object key) # Return value: New reference. # Return element of o corresponding to the object key or NULL on @@ -397,3 +437,4 @@ cdef extern from "Python.h": long Py_TPFLAGS_DEFAULT_EXTERNAL long Py_TPFLAGS_DEFAULT_CORE long Py_TPFLAGS_DEFAULT + long Py_TPFLAGS_HAVE_FINALIZE diff --git a/Cython/Includes/cpython/pycapsule.pxd b/Cython/Includes/cpython/pycapsule.pxd index 08062da85..1c21b370b 100644 --- a/Cython/Includes/cpython/pycapsule.pxd +++ b/Cython/Includes/cpython/pycapsule.pxd @@ -1,5 +1,5 @@ -# available since Python 3.1! +# available since Python 2.7! cdef extern from "Python.h": @@ -141,4 +141,3 @@ cdef extern from "Python.h": # set an exception and return NULL. However, if PyCapsule_Import() # failed to import the module, and no_block was true, no exception # is set. - diff --git a/Cython/Includes/cpython/pyport.pxd b/Cython/Includes/cpython/pyport.pxd new file mode 100644 index 000000000..fec59c9c8 --- /dev/null +++ b/Cython/Includes/cpython/pyport.pxd @@ -0,0 +1,8 @@ +cdef extern from "Python.h": + ctypedef int int32_t + ctypedef int int64_t + ctypedef unsigned int uint32_t + ctypedef unsigned int uint64_t + + const Py_ssize_t PY_SSIZE_T_MIN + const Py_ssize_t PY_SSIZE_T_MAX diff --git a/Cython/Includes/cpython/pystate.pxd b/Cython/Includes/cpython/pystate.pxd index 1af630793..ee8856b20 100644 --- a/Cython/Includes/cpython/pystate.pxd +++ b/Cython/Includes/cpython/pystate.pxd @@ -84,6 +84,9 @@ cdef extern from "Python.h": # PyGILState_Release on the same thread. void PyGILState_Release(PyGILState_STATE) + # Return 1 if the current thread holds the GIL and 0 otherwise. + int PyGILState_Check() + # Routines for advanced debuggers, requested by David Beazley. # Don't use unless you know what you are doing! PyInterpreterState * PyInterpreterState_Head() diff --git a/Cython/Includes/cpython/ref.pxd b/Cython/Includes/cpython/ref.pxd index 4bc9a7d7c..44f870006 100644 --- a/Cython/Includes/cpython/ref.pxd +++ b/Cython/Includes/cpython/ref.pxd @@ -48,4 +48,3 @@ cdef extern from "Python.h": # It is a good idea to use this macro whenever decrementing the # value of a variable that might be traversed during garbage # collection. - diff --git a/Cython/Includes/cpython/sequence.pxd b/Cython/Includes/cpython/sequence.pxd index eb279968d..e50e4c495 100644 --- a/Cython/Includes/cpython/sequence.pxd +++ b/Cython/Includes/cpython/sequence.pxd @@ -132,5 +132,3 @@ cdef extern from "Python.h": # gotten by calling PySequence_Size() on o, but # PySequence_Fast_GET_SIZE() is faster because it can assume o is # a list or tuple. - - diff --git a/Cython/Includes/cpython/string.pxd b/Cython/Includes/cpython/string.pxd index 8af78f3dd..3ba25515f 100644 --- a/Cython/Includes/cpython/string.pxd +++ b/Cython/Includes/cpython/string.pxd @@ -194,5 +194,3 @@ cdef extern from "Python.h": # string encode() method. The codec to be used is looked up using # the Python codec registry. Return NULL if an exception was # raised by the codec. - - diff --git a/Cython/Includes/cpython/time.pxd b/Cython/Includes/cpython/time.pxd new file mode 100644 index 000000000..7f20095a1 --- /dev/null +++ b/Cython/Includes/cpython/time.pxd @@ -0,0 +1,51 @@ +""" +Cython implementation of (parts of) the standard library time module. +""" + +from libc.stdint cimport int64_t +from cpython.exc cimport PyErr_SetFromErrno + +cdef extern from "Python.h": + ctypedef int64_t _PyTime_t + _PyTime_t _PyTime_GetSystemClock() nogil + double _PyTime_AsSecondsDouble(_PyTime_t t) nogil + +from libc.time cimport ( + tm, + time_t, + localtime as libc_localtime, +) + + +cdef inline double time() nogil: + cdef: + _PyTime_t tic + + tic = _PyTime_GetSystemClock() + return _PyTime_AsSecondsDouble(tic) + + +cdef inline int _raise_from_errno() except -1 with gil: + PyErr_SetFromErrno(RuntimeError) + return <int> -1 # Let the C compiler know that this function always raises. + + +cdef inline tm localtime() except * nogil: + """ + Analogue to the stdlib time.localtime. The returned struct + has some entries that the stdlib version does not: tm_gmtoff, tm_zone + """ + cdef: + time_t tic = <time_t>time() + tm* result + + result = libc_localtime(&tic) + if result is NULL: + _raise_from_errno() + # Fix 0-based date values (and the 1900-based year). + # See tmtotuple() in https://github.com/python/cpython/blob/master/Modules/timemodule.c + result.tm_year += 1900 + result.tm_mon += 1 + result.tm_wday = (result.tm_wday + 6) % 7 + result.tm_yday += 1 + return result[0] diff --git a/Cython/Includes/cpython/tuple.pxd b/Cython/Includes/cpython/tuple.pxd index 09c46e0b4..907033fe4 100644 --- a/Cython/Includes/cpython/tuple.pxd +++ b/Cython/Includes/cpython/tuple.pxd @@ -47,13 +47,15 @@ cdef extern from "Python.h": int PyTuple_SetItem(object p, Py_ssize_t pos, object o) except -1 # Insert a reference to object o at position pos of the tuple - # pointed to by p. Return 0 on success. Note: This function - # ``steals'' a reference to o. + # pointed to by p. Return 0 on success. + # + # WARNING: This function _steals_ a reference to o. void PyTuple_SET_ITEM(object p, Py_ssize_t pos, object o) # Like PyTuple_SetItem(), but does no error checking, and should - # only be used to fill in brand new tuples. Note: This function - # ``steals'' a reference to o. + # only be used to fill in brand new tuples. + # + # WARNING: This function _steals_ a reference to o. int _PyTuple_Resize(PyObject **p, Py_ssize_t newsize) except -1 # Can be used to resize a tuple. newsize will be the new length of @@ -68,4 +70,3 @@ cdef extern from "Python.h": # the object referenced by *p is replaced, the original *p is # destroyed. On failure, returns -1 and sets *p to NULL, and # raises MemoryError or SystemError. - diff --git a/Cython/Includes/cpython/type.pxd b/Cython/Includes/cpython/type.pxd index a1d094e37..928a748cd 100644 --- a/Cython/Includes/cpython/type.pxd +++ b/Cython/Includes/cpython/type.pxd @@ -23,6 +23,11 @@ cdef extern from "Python.h": # of the standard type object. Return false in all other # cases. + void PyType_Modified(type type) + # Invalidate the internal lookup cache for the type and all of its + # subtypes. This function must be called after any manual modification + # of the attributes or base classes of the type. + bint PyType_HasFeature(object o, int feature) # Return true if the type object o sets the feature feature. Type # features are denoted by single bit flags. diff --git a/Cython/Includes/cpython/unicode.pxd b/Cython/Includes/cpython/unicode.pxd index 2072c8cb2..6452d892e 100644 --- a/Cython/Includes/cpython/unicode.pxd +++ b/Cython/Includes/cpython/unicode.pxd @@ -1,4 +1,8 @@ + cdef extern from *: + ctypedef unsigned char Py_UCS1 # uint8_t + ctypedef unsigned short Py_UCS2 # uint16_t + # Return true if the object o is a Unicode object or an instance # of a Unicode subtype. Changed in version 2.2: Allowed subtypes # to be accepted. @@ -23,6 +27,21 @@ cdef extern from *: # New in version 3.3. Py_ssize_t PyUnicode_GET_LENGTH(object o) + Py_UCS1 *PyUnicode_1BYTE_DATA(object o) + Py_UCS2 *PyUnicode_2BYTE_DATA(object o) + Py_UCS4 *PyUnicode_4BYTE_DATA(object o) + + int PyUnicode_WCHAR_KIND # Deprecated since Python 3.10, removed in 3.12. + int PyUnicode_1BYTE_KIND + int PyUnicode_2BYTE_KIND + int PyUnicode_4BYTE_KIND + void PyUnicode_WRITE(int kind, void *data, Py_ssize_t index, Py_UCS4 value) + Py_UCS4 PyUnicode_READ(int kind, void *data, Py_ssize_t index) + Py_UCS4 PyUnicode_READ_CHAR(object o, Py_ssize_t index) + + unsigned int PyUnicode_KIND(object o) + void *PyUnicode_DATA(object o) + # Return the size of the object's internal buffer in bytes. o has # to be a PyUnicodeObject (not checked). Py_ssize_t PyUnicode_GET_DATA_SIZE(object o) @@ -35,6 +54,8 @@ cdef extern from *: # be a PyUnicodeObject (not checked). char* PyUnicode_AS_DATA(object o) + bint PyUnicode_IsIdentifier(object o) + # Return 1 or 0 depending on whether ch is a whitespace character. bint Py_UNICODE_ISSPACE(Py_UCS4 ch) @@ -65,6 +86,8 @@ cdef extern from *: # Return 1 or 0 depending on whether ch is an alphanumeric character. bint Py_UNICODE_ISALNUM(Py_UCS4 ch) + bint Py_UNICODE_ISPRINTABLE(Py_UCS4 ch) + # Return the character ch converted to lower case. # Used to return a Py_UNICODE value before Py3.3. Py_UCS4 Py_UNICODE_TOLOWER(Py_UCS4 ch) @@ -103,6 +126,26 @@ cdef extern from *: # when u is NULL. unicode PyUnicode_FromUnicode(Py_UNICODE *u, Py_ssize_t size) + # Similar to PyUnicode_FromUnicode(), but u points to UTF-8 encoded + # bytes + unicode PyUnicode_FromStringAndSize(const char *u, Py_ssize_t size) + + # Similar to PyUnicode_FromUnicode(), but u points to null-terminated + # UTF-8 encoded bytes. The size is determined with strlen(). + unicode PyUnicode_FromString(const char *u) + + unicode PyUnicode_New(Py_ssize_t size, Py_UCS4 maxchar) + unicode PyUnicode_FromKindAndData(int kind, const void *buffer, Py_ssize_t size) + unicode PyUnicode_FromFormat(const char *format, ...) + Py_ssize_t PyUnicode_GetLength(object unicode) except -1 + Py_ssize_t PyUnicode_CopyCharacters(object to, Py_ssize_t to_start, object from_, Py_ssize_t from_start, Py_ssize_t how_many) except -1 + Py_ssize_t PyUnicode_Fill(object unicode, Py_ssize_t start, Py_ssize_t length, Py_UCS4 fill_char) except -1 + int PyUnicode_WriteChar(object unicode, Py_ssize_t index, Py_UCS4 character) except -1 + Py_UCS4 PyUnicode_ReadChar(object unicode, Py_ssize_t index) except -1 + unicode PyUnicode_Substring(object str, Py_ssize_t start, Py_ssize_t end) + Py_UCS4 *PyUnicode_AsUCS4(object u, Py_UCS4 *buffer, Py_ssize_t buflen, int copy_null) except NULL + Py_UCS4 *PyUnicode_AsUCS4Copy(object u) except NULL + # Create a Unicode Object from the given Unicode code point ordinal. # # The ordinal must be in range(0x10000) on narrow Python builds |