From 8cc4416b2e9481c25ed36dca14abb88205343943 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 6 Feb 2024 15:39:02 +0100 Subject: [PATCH] gh-110850 Partially revert "gh-106316: Remove pytime.h header file (#106317)" This reverts commit 46d77610fc77088bceac720a13d9f2df3a50f29e, and returns to the status quo (3.12). Tests are left in _testinternalcapi; this sounds appropriate for underscored functions. --- .github/CODEOWNERS | 1 + Doc/whatsnew/3.13.rst | 3 - Include/Python.h | 1 + Include/cpython/pytime.h | 293 ++++++++++++++++++ Include/internal/pycore_time.h | 287 ----------------- Lib/test/test_time.py | 2 +- Makefile.pre.in | 1 + ...-02-06-15-42-33.gh-issue-110850.TELYgQ.rst | 3 + Modules/_testsinglephase.c | 1 - Modules/socketmodule.h | 2 - PCbuild/_testcapi.vcxproj | 1 + PCbuild/_testcapi.vcxproj.filters | 3 + PCbuild/pythoncore.vcxproj | 1 + PCbuild/pythoncore.vcxproj.filters | 3 + Python/pytime.c | 2 +- 15 files changed, 309 insertions(+), 295 deletions(-) create mode 100644 Include/cpython/pytime.h create mode 100644 Misc/NEWS.d/next/C API/2024-02-06-15-42-33.gh-issue-110850.TELYgQ.rst diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 7933d319550576..5dde3b6f0edbbb 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -127,6 +127,7 @@ Lib/test/test_time.py @pganssle @abalkin Modules/timemodule.c @pganssle @abalkin Python/pytime.c @pganssle @abalkin Include/internal/pycore_time.h @pganssle @abalkin +Include/pytime.h @pganssle @abalkin # Email and related **/*mail* @python/email-team diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 1b803278ae0d5b..80a6aafd2db69a 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -1739,9 +1739,6 @@ Removed (:pep:`590`). (Contributed by Victor Stinner in :gh:`106023`.) -* Remove ``cpython/pytime.h`` header file: it only contained private functions. - (Contributed by Victor Stinner in :gh:`106316`.) - * Remove ``_PyInterpreterState_Get()`` alias to :c:func:`PyInterpreterState_Get()` which was kept for backward compatibility with Python 3.8. The `pythoncapi-compat project diff --git a/Include/Python.h b/Include/Python.h index 196751c3201e62..01fc45137a17bb 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -97,6 +97,7 @@ #include "weakrefobject.h" #include "structseq.h" #include "cpython/picklebufobject.h" +#include "cpython/pytime.h" #include "codecs.h" #include "pyerrors.h" #include "pythread.h" diff --git a/Include/cpython/pytime.h b/Include/cpython/pytime.h new file mode 100644 index 00000000000000..d0fa55ce17e5a0 --- /dev/null +++ b/Include/cpython/pytime.h @@ -0,0 +1,293 @@ +// The _PyTime_t API is not supported for public use, and may be changed or +// removed at any time. +// See Include/internal/pycore_time.h for details of the current +// implementation. + +#ifndef Py_LIMITED_API +#ifndef Py_PYTIME_H +#define Py_PYTIME_H + +/************************************************************************** +Symbols and macros to supply platform-independent interfaces to time related +functions and constants +**************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __clang__ +struct timeval; +#endif + +/* _PyTime_t: Python timestamp with subsecond precision. It can be used to + store a duration, and so indirectly a date (related to another date, like + UNIX epoch). */ +typedef int64_t _PyTime_t; +// _PyTime_MIN nanoseconds is around -292.3 years +#define _PyTime_MIN INT64_MIN +// _PyTime_MAX nanoseconds is around +292.3 years +#define _PyTime_MAX INT64_MAX +#define _SIZEOF_PYTIME_T 8 + +typedef enum { + /* Round towards minus infinity (-inf). + For example, used to read a clock. */ + _PyTime_ROUND_FLOOR=0, + /* Round towards infinity (+inf). + For example, used for timeout to wait "at least" N seconds. */ + _PyTime_ROUND_CEILING=1, + /* Round to nearest with ties going to nearest even integer. + For example, used to round from a Python float. */ + _PyTime_ROUND_HALF_EVEN=2, + /* Round away from zero + For example, used for timeout. _PyTime_ROUND_CEILING rounds + -1e-9 to 0 milliseconds which causes bpo-31786 issue. + _PyTime_ROUND_UP rounds -1e-9 to -1 millisecond which keeps + the timeout sign as expected. select.poll(timeout) must block + for negative values." */ + _PyTime_ROUND_UP=3, + /* _PyTime_ROUND_TIMEOUT (an alias for _PyTime_ROUND_UP) should be + used for timeouts. */ + _PyTime_ROUND_TIMEOUT = _PyTime_ROUND_UP +} _PyTime_round_t; + + +/* Convert a time_t to a PyLong. */ +PyAPI_FUNC(PyObject *) _PyLong_FromTime_t( + time_t sec); + +/* Convert a PyLong to a time_t. */ +PyAPI_FUNC(time_t) _PyLong_AsTime_t( + PyObject *obj); + +/* Convert a number of seconds, int or float, to time_t. */ +PyAPI_FUNC(int) _PyTime_ObjectToTime_t( + PyObject *obj, + time_t *sec, + _PyTime_round_t); + +/* Convert a number of seconds, int or float, to a timeval structure. + usec is in the range [0; 999999] and rounded towards zero. + For example, -1.2 is converted to (-2, 800000). */ +PyAPI_FUNC(int) _PyTime_ObjectToTimeval( + PyObject *obj, + time_t *sec, + long *usec, + _PyTime_round_t); + +/* Convert a number of seconds, int or float, to a timespec structure. + nsec is in the range [0; 999999999] and rounded towards zero. + For example, -1.2 is converted to (-2, 800000000). */ +PyAPI_FUNC(int) _PyTime_ObjectToTimespec( + PyObject *obj, + time_t *sec, + long *nsec, + _PyTime_round_t); + + +/* Create a timestamp from a number of seconds. */ +PyAPI_FUNC(_PyTime_t) _PyTime_FromSeconds(int seconds); + +/* Macro to create a timestamp from a number of seconds, no integer overflow. + Only use the macro for small values, prefer _PyTime_FromSeconds(). */ +#define _PYTIME_FROMSECONDS(seconds) \ + ((_PyTime_t)(seconds) * (1000 * 1000 * 1000)) + +/* Create a timestamp from a number of nanoseconds. */ +PyAPI_FUNC(_PyTime_t) _PyTime_FromNanoseconds(_PyTime_t ns); + +/* Create a timestamp from a number of microseconds. + * Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow. */ +PyAPI_FUNC(_PyTime_t) _PyTime_FromMicrosecondsClamp(_PyTime_t us); + +/* Create a timestamp from nanoseconds (Python int). */ +PyAPI_FUNC(int) _PyTime_FromNanosecondsObject(_PyTime_t *t, + PyObject *obj); + +/* Convert a number of seconds (Python float or int) to a timestamp. + Raise an exception and return -1 on error, return 0 on success. */ +PyAPI_FUNC(int) _PyTime_FromSecondsObject(_PyTime_t *t, + PyObject *obj, + _PyTime_round_t round); + +/* Convert a number of milliseconds (Python float or int, 10^-3) to a timestamp. + Raise an exception and return -1 on error, return 0 on success. */ +PyAPI_FUNC(int) _PyTime_FromMillisecondsObject(_PyTime_t *t, + PyObject *obj, + _PyTime_round_t round); + +/* Convert a timestamp to a number of seconds as a C double. */ +PyAPI_FUNC(double) _PyTime_AsSecondsDouble(_PyTime_t t); + +/* Convert timestamp to a number of milliseconds (10^-3 seconds). */ +PyAPI_FUNC(_PyTime_t) _PyTime_AsMilliseconds(_PyTime_t t, + _PyTime_round_t round); + +/* Convert timestamp to a number of microseconds (10^-6 seconds). */ +PyAPI_FUNC(_PyTime_t) _PyTime_AsMicroseconds(_PyTime_t t, + _PyTime_round_t round); + +/* Convert timestamp to a number of nanoseconds (10^-9 seconds). */ +PyAPI_FUNC(_PyTime_t) _PyTime_AsNanoseconds(_PyTime_t t); + +#ifdef MS_WINDOWS +// Convert timestamp to a number of 100 nanoseconds (10^-7 seconds). +PyAPI_FUNC(_PyTime_t) _PyTime_As100Nanoseconds(_PyTime_t t, + _PyTime_round_t round); +#endif + +/* Convert timestamp to a number of nanoseconds (10^-9 seconds) as a Python int + object. */ +PyAPI_FUNC(PyObject *) _PyTime_AsNanosecondsObject(_PyTime_t t); + +#ifndef MS_WINDOWS +/* Create a timestamp from a timeval structure. + Raise an exception and return -1 on overflow, return 0 on success. */ +PyAPI_FUNC(int) _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv); +#endif + +/* Convert a timestamp to a timeval structure (microsecond resolution). + tv_usec is always positive. + Raise an exception and return -1 if the conversion overflowed, + return 0 on success. */ +PyAPI_FUNC(int) _PyTime_AsTimeval(_PyTime_t t, + struct timeval *tv, + _PyTime_round_t round); + +/* Similar to _PyTime_AsTimeval() but don't raise an exception on overflow. + On overflow, clamp tv_sec to _PyTime_t min/max. */ +PyAPI_FUNC(void) _PyTime_AsTimeval_clamp(_PyTime_t t, + struct timeval *tv, + _PyTime_round_t round); + +/* Convert a timestamp to a number of seconds (secs) and microseconds (us). + us is always positive. This function is similar to _PyTime_AsTimeval() + except that secs is always a time_t type, whereas the timeval structure + uses a C long for tv_sec on Windows. + Raise an exception and return -1 if the conversion overflowed, + return 0 on success. */ +PyAPI_FUNC(int) _PyTime_AsTimevalTime_t( + _PyTime_t t, + time_t *secs, + int *us, + _PyTime_round_t round); + +#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE) +/* Create a timestamp from a timespec structure. + Raise an exception and return -1 on overflow, return 0 on success. */ +PyAPI_FUNC(int) _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts); + +/* Convert a timestamp to a timespec structure (nanosecond resolution). + tv_nsec is always positive. + Raise an exception and return -1 on error, return 0 on success. */ +PyAPI_FUNC(int) _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts); + +/* Similar to _PyTime_AsTimespec() but don't raise an exception on overflow. + On overflow, clamp tv_sec to _PyTime_t min/max. */ +PyAPI_FUNC(void) _PyTime_AsTimespec_clamp(_PyTime_t t, struct timespec *ts); +#endif + + +// Compute t1 + t2. Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow. +PyAPI_FUNC(_PyTime_t) _PyTime_Add(_PyTime_t t1, _PyTime_t t2); + +/* Compute ticks * mul / div. + Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow. + The caller must ensure that ((div - 1) * mul) cannot overflow. */ +PyAPI_FUNC(_PyTime_t) _PyTime_MulDiv(_PyTime_t ticks, + _PyTime_t mul, + _PyTime_t div); + +/* Structure used by time.get_clock_info() */ +typedef struct { + const char *implementation; + int monotonic; + int adjustable; + double resolution; +} _Py_clock_info_t; + +/* Get the current time from the system clock. + + If the internal clock fails, silently ignore the error and return 0. + On integer overflow, silently ignore the overflow and clamp the clock to + [_PyTime_MIN; _PyTime_MAX]. + + Use _PyTime_GetSystemClockWithInfo() to check for failure. */ +PyAPI_FUNC(_PyTime_t) _PyTime_GetSystemClock(void); + +/* Get the current time from the system clock. + * On success, set *t and *info (if not NULL), and return 0. + * On error, raise an exception and return -1. + */ +PyAPI_FUNC(int) _PyTime_GetSystemClockWithInfo( + _PyTime_t *t, + _Py_clock_info_t *info); + +/* Get the time of a monotonic clock, i.e. a clock that cannot go backwards. + The clock is not affected by system clock updates. The reference point of + the returned value is undefined, so that only the difference between the + results of consecutive calls is valid. + + If the internal clock fails, silently ignore the error and return 0. + On integer overflow, silently ignore the overflow and clamp the clock to + [_PyTime_MIN; _PyTime_MAX]. + + Use _PyTime_GetMonotonicClockWithInfo() to check for failure. */ +PyAPI_FUNC(_PyTime_t) _PyTime_GetMonotonicClock(void); + +/* Get the time of a monotonic clock, i.e. a clock that cannot go backwards. + The clock is not affected by system clock updates. The reference point of + the returned value is undefined, so that only the difference between the + results of consecutive calls is valid. + + Fill info (if set) with information of the function used to get the time. + + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) _PyTime_GetMonotonicClockWithInfo( + _PyTime_t *t, + _Py_clock_info_t *info); + + +/* Converts a timestamp to the Gregorian time, using the local time zone. + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) _PyTime_localtime(time_t t, struct tm *tm); + +/* Converts a timestamp to the Gregorian time, assuming UTC. + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) _PyTime_gmtime(time_t t, struct tm *tm); + +/* Get the performance counter: clock with the highest available resolution to + measure a short duration. + + If the internal clock fails, silently ignore the error and return 0. + On integer overflow, silently ignore the overflow and clamp the clock to + [_PyTime_MIN; _PyTime_MAX]. + + Use _PyTime_GetPerfCounterWithInfo() to check for failure. */ +PyAPI_FUNC(_PyTime_t) _PyTime_GetPerfCounter(void); + +/* Get the performance counter: clock with the highest available resolution to + measure a short duration. + + Fill info (if set) with information of the function used to get the time. + + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) _PyTime_GetPerfCounterWithInfo( + _PyTime_t *t, + _Py_clock_info_t *info); + + +// Create a deadline. +// Pseudo code: _PyTime_GetMonotonicClock() + timeout. +PyAPI_FUNC(_PyTime_t) _PyDeadline_Init(_PyTime_t timeout); + +// Get remaining time from a deadline. +// Pseudo code: deadline - _PyTime_GetMonotonicClock(). +PyAPI_FUNC(_PyTime_t) _PyDeadline_Get(_PyTime_t deadline); + +#ifdef __cplusplus +} +#endif + +#endif /* Py_PYTIME_H */ +#endif /* Py_LIMITED_API */ diff --git a/Include/internal/pycore_time.h b/Include/internal/pycore_time.h index dabbd7b41556cd..04640300b86b4e 100644 --- a/Include/internal/pycore_time.h +++ b/Include/internal/pycore_time.h @@ -56,298 +56,11 @@ extern "C" { struct timeval; #endif -// _PyTime_t: Python timestamp with subsecond precision. It can be used to -// store a duration, and so indirectly a date (related to another date, like -// UNIX epoch). -typedef int64_t _PyTime_t; -// _PyTime_MIN nanoseconds is around -292.3 years -#define _PyTime_MIN INT64_MIN -// _PyTime_MAX nanoseconds is around +292.3 years -#define _PyTime_MAX INT64_MAX -#define _SIZEOF_PYTIME_T 8 - -typedef enum { - // Round towards minus infinity (-inf). - // For example, used to read a clock. - _PyTime_ROUND_FLOOR=0, - - // Round towards infinity (+inf). - // For example, used for timeout to wait "at least" N seconds. - _PyTime_ROUND_CEILING=1, - - // Round to nearest with ties going to nearest even integer. - // For example, used to round from a Python float. - _PyTime_ROUND_HALF_EVEN=2, - - // Round away from zero - // For example, used for timeout. _PyTime_ROUND_CEILING rounds - // -1e-9 to 0 milliseconds which causes bpo-31786 issue. - // _PyTime_ROUND_UP rounds -1e-9 to -1 millisecond which keeps - // the timeout sign as expected. select.poll(timeout) must block - // for negative values. - _PyTime_ROUND_UP=3, - - // _PyTime_ROUND_TIMEOUT (an alias for _PyTime_ROUND_UP) should be - // used for timeouts. - _PyTime_ROUND_TIMEOUT = _PyTime_ROUND_UP -} _PyTime_round_t; - - -// Convert a time_t to a PyLong. -// Export for '_testinternalcapi' shared extension -PyAPI_FUNC(PyObject*) _PyLong_FromTime_t(time_t sec); - -// Convert a PyLong to a time_t. -// Export for '_datetime' shared extension -PyAPI_FUNC(time_t) _PyLong_AsTime_t(PyObject *obj); - -// Convert a number of seconds, int or float, to time_t. -// Export for '_datetime' shared extension. -PyAPI_FUNC(int) _PyTime_ObjectToTime_t( - PyObject *obj, - time_t *sec, - _PyTime_round_t); - -// Convert a number of seconds, int or float, to a timeval structure. -// usec is in the range [0; 999999] and rounded towards zero. -// For example, -1.2 is converted to (-2, 800000). -// Export for '_datetime' shared extension. -PyAPI_FUNC(int) _PyTime_ObjectToTimeval( - PyObject *obj, - time_t *sec, - long *usec, - _PyTime_round_t); - -// Convert a number of seconds, int or float, to a timespec structure. -// nsec is in the range [0; 999999999] and rounded towards zero. -// For example, -1.2 is converted to (-2, 800000000). -// Export for '_testinternalcapi' shared extension. -PyAPI_FUNC(int) _PyTime_ObjectToTimespec( - PyObject *obj, - time_t *sec, - long *nsec, - _PyTime_round_t); - - -// Create a timestamp from a number of seconds. -// Export for '_socket' shared extension. -PyAPI_FUNC(_PyTime_t) _PyTime_FromSeconds(int seconds); // Create a timestamp from a number of seconds in double. // Export for '_socket' shared extension. PyAPI_FUNC(_PyTime_t) _PyTime_FromSecondsDouble(double seconds, _PyTime_round_t round); -// Macro to create a timestamp from a number of seconds, no integer overflow. -// Only use the macro for small values, prefer _PyTime_FromSeconds(). -#define _PYTIME_FROMSECONDS(seconds) \ - ((_PyTime_t)(seconds) * (1000 * 1000 * 1000)) - -// Create a timestamp from a number of nanoseconds. -// Export for '_testinternalcapi' shared extension. -PyAPI_FUNC(_PyTime_t) _PyTime_FromNanoseconds(_PyTime_t ns); - -// Create a timestamp from a number of microseconds. -// Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow. -extern _PyTime_t _PyTime_FromMicrosecondsClamp(_PyTime_t us); - -// Create a timestamp from nanoseconds (Python int). -// Export for '_lsprof' shared extension. -PyAPI_FUNC(int) _PyTime_FromNanosecondsObject(_PyTime_t *t, - PyObject *obj); - -// Convert a number of seconds (Python float or int) to a timestamp. -// Raise an exception and return -1 on error, return 0 on success. -// Export for '_socket' shared extension. -PyAPI_FUNC(int) _PyTime_FromSecondsObject(_PyTime_t *t, - PyObject *obj, - _PyTime_round_t round); - -// Convert a number of milliseconds (Python float or int, 10^-3) to a timestamp. -// Raise an exception and return -1 on error, return 0 on success. -// Export for 'select' shared extension. -PyAPI_FUNC(int) _PyTime_FromMillisecondsObject(_PyTime_t *t, - PyObject *obj, - _PyTime_round_t round); - -// Convert a timestamp to a number of seconds as a C double. -// Export for '_socket' shared extension. -PyAPI_FUNC(double) _PyTime_AsSecondsDouble(_PyTime_t t); - -// Convert timestamp to a number of milliseconds (10^-3 seconds). -// Export for '_ssl' shared extension. -PyAPI_FUNC(_PyTime_t) _PyTime_AsMilliseconds(_PyTime_t t, - _PyTime_round_t round); - -// Convert timestamp to a number of microseconds (10^-6 seconds). -// Export for '_queue' shared extension. -PyAPI_FUNC(_PyTime_t) _PyTime_AsMicroseconds(_PyTime_t t, - _PyTime_round_t round); - -// Convert timestamp to a number of nanoseconds (10^-9 seconds). -extern _PyTime_t _PyTime_AsNanoseconds(_PyTime_t t); - -#ifdef MS_WINDOWS -// Convert timestamp to a number of 100 nanoseconds (10^-7 seconds). -extern _PyTime_t _PyTime_As100Nanoseconds(_PyTime_t t, - _PyTime_round_t round); -#endif - -// Convert timestamp to a number of nanoseconds (10^-9 seconds) as a Python int -// object. -// Export for '_testinternalcapi' shared extension. -PyAPI_FUNC(PyObject*) _PyTime_AsNanosecondsObject(_PyTime_t t); - -#ifndef MS_WINDOWS -// Create a timestamp from a timeval structure. -// Raise an exception and return -1 on overflow, return 0 on success. -extern int _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv); -#endif - -// Convert a timestamp to a timeval structure (microsecond resolution). -// tv_usec is always positive. -// Raise an exception and return -1 if the conversion overflowed, -// return 0 on success. -// Export for 'select' shared extension. -PyAPI_FUNC(int) _PyTime_AsTimeval(_PyTime_t t, - struct timeval *tv, - _PyTime_round_t round); - -// Similar to _PyTime_AsTimeval() but don't raise an exception on overflow. -// On overflow, clamp tv_sec to _PyTime_t min/max. -// Export for 'select' shared extension. -PyAPI_FUNC(void) _PyTime_AsTimeval_clamp(_PyTime_t t, - struct timeval *tv, - _PyTime_round_t round); - -// Convert a timestamp to a number of seconds (secs) and microseconds (us). -// us is always positive. This function is similar to _PyTime_AsTimeval() -// except that secs is always a time_t type, whereas the timeval structure -// uses a C long for tv_sec on Windows. -// Raise an exception and return -1 if the conversion overflowed, -// return 0 on success. -// Export for '_datetime' shared extension. -PyAPI_FUNC(int) _PyTime_AsTimevalTime_t( - _PyTime_t t, - time_t *secs, - int *us, - _PyTime_round_t round); - -#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE) -// Create a timestamp from a timespec structure. -// Raise an exception and return -1 on overflow, return 0 on success. -extern int _PyTime_FromTimespec(_PyTime_t *tp, const struct timespec *ts); - -// Convert a timestamp to a timespec structure (nanosecond resolution). -// tv_nsec is always positive. -// Raise an exception and return -1 on error, return 0 on success. -// Export for '_testinternalcapi' shared extension. -PyAPI_FUNC(int) _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts); - -// Similar to _PyTime_AsTimespec() but don't raise an exception on overflow. -// On overflow, clamp tv_sec to _PyTime_t min/max. -// Export for '_testinternalcapi' shared extension. -PyAPI_FUNC(void) _PyTime_AsTimespec_clamp(_PyTime_t t, struct timespec *ts); -#endif - - -// Compute t1 + t2. Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow. -extern _PyTime_t _PyTime_Add(_PyTime_t t1, _PyTime_t t2); - -// Structure used by time.get_clock_info() -typedef struct { - const char *implementation; - int monotonic; - int adjustable; - double resolution; -} _Py_clock_info_t; - -// Get the current time from the system clock. -// -// If the internal clock fails, silently ignore the error and return 0. -// On integer overflow, silently ignore the overflow and clamp the clock to -// [_PyTime_MIN; _PyTime_MAX]. -// -// Use _PyTime_GetSystemClockWithInfo() to check for failure. -// Export for '_random' shared extension. -PyAPI_FUNC(_PyTime_t) _PyTime_GetSystemClock(void); - -// Get the current time from the system clock. -// On success, set *t and *info (if not NULL), and return 0. -// On error, raise an exception and return -1. -extern int _PyTime_GetSystemClockWithInfo( - _PyTime_t *t, - _Py_clock_info_t *info); - -// Get the time of a monotonic clock, i.e. a clock that cannot go backwards. -// The clock is not affected by system clock updates. The reference point of -// the returned value is undefined, so that only the difference between the -// results of consecutive calls is valid. -// -// If the internal clock fails, silently ignore the error and return 0. -// On integer overflow, silently ignore the overflow and clamp the clock to -// [_PyTime_MIN; _PyTime_MAX]. -// -// Use _PyTime_GetMonotonicClockWithInfo() to check for failure. -// Export for '_random' shared extension. -PyAPI_FUNC(_PyTime_t) _PyTime_GetMonotonicClock(void); - -// Get the time of a monotonic clock, i.e. a clock that cannot go backwards. -// The clock is not affected by system clock updates. The reference point of -// the returned value is undefined, so that only the difference between the -// results of consecutive calls is valid. -// -// Fill info (if set) with information of the function used to get the time. -// -// Return 0 on success, raise an exception and return -1 on error. -// Export for '_testsinglephase' shared extension. -PyAPI_FUNC(int) _PyTime_GetMonotonicClockWithInfo( - _PyTime_t *t, - _Py_clock_info_t *info); - - -// Converts a timestamp to the Gregorian time, using the local time zone. -// Return 0 on success, raise an exception and return -1 on error. -// Export for '_datetime' shared extension. -PyAPI_FUNC(int) _PyTime_localtime(time_t t, struct tm *tm); - -// Converts a timestamp to the Gregorian time, assuming UTC. -// Return 0 on success, raise an exception and return -1 on error. -// Export for '_datetime' shared extension. -PyAPI_FUNC(int) _PyTime_gmtime(time_t t, struct tm *tm); - -// Get the performance counter: clock with the highest available resolution to -// measure a short duration. -// -// If the internal clock fails, silently ignore the error and return 0. -// On integer overflow, silently ignore the overflow and clamp the clock to -// [_PyTime_MIN; _PyTime_MAX]. -// -// Use _PyTime_GetPerfCounterWithInfo() to check for failure. -// Export for '_lsprof' shared extension. -PyAPI_FUNC(_PyTime_t) _PyTime_GetPerfCounter(void); - -// Get the performance counter: clock with the highest available resolution to -// measure a short duration. -// -// Fill info (if set) with information of the function used to get the time. -// -// Return 0 on success, raise an exception and return -1 on error. -extern int _PyTime_GetPerfCounterWithInfo( - _PyTime_t *t, - _Py_clock_info_t *info); - - -// Create a deadline. -// Pseudo code: _PyTime_GetMonotonicClock() + timeout. -// Export for '_ssl' shared extension. -PyAPI_FUNC(_PyTime_t) _PyDeadline_Init(_PyTime_t timeout); - -// Get remaining time from a deadline. -// Pseudo code: deadline - _PyTime_GetMonotonicClock(). -// Export for '_ssl' shared extension. -PyAPI_FUNC(_PyTime_t) _PyDeadline_Get(_PyTime_t deadline); - - // --- _PyTimeFraction ------------------------------------------------------- typedef struct { diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index 3b5640abdb6b89..1656eef5a69a9e 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -765,7 +765,7 @@ def test_short_times(self): self.assertIs(lt.tm_zone, None) -@unittest.skipIf(_testcapi is None, 'need the _testinternalcapi module') +@unittest.skipIf(_testcapi is None, 'need the _testcapi module') @unittest.skipIf(_testinternalcapi is None, 'need the _testinternalcapi module') class CPyTimeTestCase: """ diff --git a/Makefile.pre.in b/Makefile.pre.in index 4dabe328ce0362..1eef99256d0c22 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1064,6 +1064,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/cpython/pystats.h \ $(srcdir)/Include/cpython/pythonrun.h \ $(srcdir)/Include/cpython/pythread.h \ + $(srcdir)/Include/cpython/pytime.h \ $(srcdir)/Include/cpython/setobject.h \ $(srcdir)/Include/cpython/sysmodule.h \ $(srcdir)/Include/cpython/traceback.h \ diff --git a/Misc/NEWS.d/next/C API/2024-02-06-15-42-33.gh-issue-110850.TELYgQ.rst b/Misc/NEWS.d/next/C API/2024-02-06-15-42-33.gh-issue-110850.TELYgQ.rst new file mode 100644 index 00000000000000..32e811045d8632 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2024-02-06-15-42-33.gh-issue-110850.TELYgQ.rst @@ -0,0 +1,3 @@ +``_PyTime`` C API is exposed in public headers again. Note that there are no +guarantees about stability of API with a leading underscore in the name: +this API may be removed again at any time. diff --git a/Modules/_testsinglephase.c b/Modules/_testsinglephase.c index c42a15a0eff494..30a065688db595 100644 --- a/Modules/_testsinglephase.c +++ b/Modules/_testsinglephase.c @@ -8,7 +8,6 @@ //#include #include "Python.h" #include "pycore_namespace.h" // _PyNamespace_New() -#include "pycore_time.h" // _PyTime_t typedef struct { diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h index 47146a28e02c8f..14e566bed64af9 100644 --- a/Modules/socketmodule.h +++ b/Modules/socketmodule.h @@ -1,7 +1,5 @@ /* Socket module header file */ -#include "pycore_time.h" // _PyTime_t - /* Includes needed for the sockaddr_* symbols below */ #ifndef MS_WINDOWS #ifdef __VMS diff --git a/PCbuild/_testcapi.vcxproj b/PCbuild/_testcapi.vcxproj index 6911aacab29b97..26b71bccdccac5 100644 --- a/PCbuild/_testcapi.vcxproj +++ b/PCbuild/_testcapi.vcxproj @@ -103,6 +103,7 @@ + diff --git a/PCbuild/_testcapi.vcxproj.filters b/PCbuild/_testcapi.vcxproj.filters index 6059959bb9a040..b9a1683a1396e7 100644 --- a/PCbuild/_testcapi.vcxproj.filters +++ b/PCbuild/_testcapi.vcxproj.filters @@ -39,6 +39,9 @@ Source Files + + Source Files + Source Files diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 4cc0ca4b9af8de..69255eaa31efd3 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -181,6 +181,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index ceaa21217267cf..34968c2bbc2044 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -474,6 +474,9 @@ Include\cpython + + Include\cpython + Include\cpython diff --git a/Python/pytime.c b/Python/pytime.c index 77cb95f8feb179..e804978c6f8057 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -536,7 +536,7 @@ pytime_fromtimespec(_PyTime_t *tp, const struct timespec *ts, int raise_exc) } int -_PyTime_FromTimespec(_PyTime_t *tp, const struct timespec *ts) +_PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts) { return pytime_fromtimespec(tp, ts, 1); }