diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst index 7810d05b0ebc2e..8ee351918006e4 100644 --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -79,12 +79,9 @@ Dictionary Objects .. c:function:: int PyDict_SetItemString(PyObject *p, const char *key, PyObject *val) - .. index:: single: PyUnicode_FromString() - - Insert *val* into the dictionary *p* using *key* as a key. *key* should - be a :c:expr:`const char*` UTF-8 encoded bytes string. The key object is created using - ``PyUnicode_FromString(key)``. Return ``0`` on success or ``-1`` on - failure. This function *does not* steal a reference to *val*. + This is the same as :c:func:`PyDict_SetItem`, but *key* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. .. c:function:: int PyDict_DelItem(PyObject *p, PyObject *key) @@ -97,10 +94,9 @@ Dictionary Objects .. c:function:: int PyDict_DelItemString(PyObject *p, const char *key) - Remove the entry in dictionary *p* which has a key specified by the UTF-8 - encoded bytes string *key*. - If *key* is not in the dictionary, :exc:`KeyError` is raised. - Return ``0`` on success or ``-1`` on failure. + This is the same as :c:func:`PyDict_DelItem`, but *key* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. .. c:function:: int PyDict_GetItemRef(PyObject *p, PyObject *key, PyObject **result) diff --git a/Doc/c-api/mapping.rst b/Doc/c-api/mapping.rst index 82011d9d36a524..5b909ef8f5e2ce 100644 --- a/Doc/c-api/mapping.rst +++ b/Doc/c-api/mapping.rst @@ -28,9 +28,9 @@ See also :c:func:`PyObject_GetItem`, :c:func:`PyObject_SetItem` and .. c:function:: PyObject* PyMapping_GetItemString(PyObject *o, const char *key) - Return element of *o* corresponding to the string *key* or ``NULL`` on failure. - This is the equivalent of the Python expression ``o[key]``. - See also :c:func:`PyObject_GetItem`. + This is the same as :c:func:`PyObject_GetItem`, but *key* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. .. c:function:: int PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result) @@ -50,38 +50,30 @@ See also :c:func:`PyObject_GetItem`, :c:func:`PyObject_SetItem` and .. c:function:: int PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result) - Variant of :c:func:`PyMapping_GetItemString` which doesn't raise - :exc:`KeyError` if the key is not found. - - If the key is found, return ``1`` and set *\*result* to a new - :term:`strong reference` to the corresponding value. - If the key is not found, return ``0`` and set *\*result* to ``NULL``; - the :exc:`KeyError` is silenced. - If an error other than :exc:`KeyError` is raised, return ``-1`` and - set *\*result* to ``NULL``. + This is the same as :c:func:`PyMapping_GetOptionalItem`, but *key* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. .. versionadded:: 3.13 .. c:function:: int PyMapping_SetItemString(PyObject *o, const char *key, PyObject *v) - Map the string *key* to the value *v* in object *o*. Returns ``-1`` on - failure. This is the equivalent of the Python statement ``o[key] = v``. - See also :c:func:`PyObject_SetItem`. This function *does not* steal a - reference to *v*. + This is the same as :c:func:`PyObject_SetItem`, but *key* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. .. c:function:: int PyMapping_DelItem(PyObject *o, PyObject *key) - Remove the mapping for the object *key* from the object *o*. Return ``-1`` - on failure. This is equivalent to the Python statement ``del o[key]``. This is an alias of :c:func:`PyObject_DelItem`. .. c:function:: int PyMapping_DelItemString(PyObject *o, const char *key) - Remove the mapping for the string *key* from the object *o*. Return ``-1`` - on failure. This is equivalent to the Python statement ``del o[key]``. + This is the same as :c:func:`PyObject_DelItem`, but *key* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. .. c:function:: int PyMapping_HasKey(PyObject *o, PyObject *key) @@ -90,20 +82,27 @@ See also :c:func:`PyObject_GetItem`, :c:func:`PyObject_SetItem` and This is equivalent to the Python expression ``key in o``. This function always succeeds. - Note that exceptions which occur while calling the :meth:`~object.__getitem__` - method will get suppressed. - To get error reporting use :c:func:`PyObject_GetItem()` instead. + .. note:: + + Exceptions which occur when this calls :meth:`~object.__getitem__` + method are silently ignored. + For proper error handling, use :c:func:`PyMapping_GetOptionalItem` or + :c:func:`PyObject_GetItem()` instead. .. c:function:: int PyMapping_HasKeyString(PyObject *o, const char *key) - Return ``1`` if the mapping object has the key *key* and ``0`` otherwise. - This is equivalent to the Python expression ``key in o``. - This function always succeeds. + This is the same as :c:func:`PyMapping_HasKey`, but *key* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. + + .. note:: - Note that exceptions which occur while calling the :meth:`~object.__getitem__` - method and creating a temporary string object will get suppressed. - To get error reporting use :c:func:`PyMapping_GetItemString()` instead. + Exceptions that occur when this calls :meth:`~object.__getitem__` + method or while creating the temporary :class:`str` + object are silently ignored. + For proper error handling, use :c:func:`PyMapping_GetOptionalItemString` or + :c:func:`PyMapping_GetItemString` instead. .. c:function:: PyObject* PyMapping_Keys(PyObject *o) diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst index 6d9fc7f50604da..2572c087738fe3 100644 --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -43,15 +43,15 @@ Object Protocol .. c:function:: int PyObject_HasAttrString(PyObject *o, const char *attr_name) - Returns ``1`` if *o* has the attribute *attr_name*, and ``0`` otherwise. This - is equivalent to the Python expression ``hasattr(o, attr_name)``. This function - always succeeds. + This is the same as :c:func:`PyObject_HasAttr`, but *attr_name* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. .. note:: Exceptions that occur when this calls :meth:`~object.__getattr__` and - :meth:`~object.__getattribute__` methods or while creating the temporary :class:`str` - object are silently ignored. + :meth:`~object.__getattribute__` methods or while creating the temporary + :class:`str` object are silently ignored. For proper error handling, use :c:func:`PyObject_GetOptionalAttrString` or :c:func:`PyObject_GetAttrString` instead. @@ -68,9 +68,9 @@ Object Protocol .. c:function:: PyObject* PyObject_GetAttrString(PyObject *o, const char *attr_name) - Retrieve an attribute named *attr_name* from object *o*. Returns the attribute - value on success, or ``NULL`` on failure. This is the equivalent of the Python - expression ``o.attr_name``. + This is the same as :c:func:`PyObject_GetAttr`, but *attr_name* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. If the missing attribute should not be treated as a failure, you can use :c:func:`PyObject_GetOptionalAttrString` instead. @@ -93,15 +93,9 @@ Object Protocol .. c:function:: int PyObject_GetOptionalAttrString(PyObject *obj, const char *attr_name, PyObject **result); - Variant of :c:func:`PyObject_GetAttrString` which doesn't raise - :exc:`AttributeError` if the attribute is not found. - - If the attribute is found, return ``1`` and set *\*result* to a new - :term:`strong reference` to the attribute. - If the attribute is not found, return ``0`` and set *\*result* to ``NULL``; - the :exc:`AttributeError` is silenced. - If an error other than :exc:`AttributeError` is raised, return ``-1`` and - set *\*result* to ``NULL``. + This is the same as :c:func:`PyObject_GetOptionalAttr`, but *attr_name* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. .. versionadded:: 3.13 @@ -129,10 +123,9 @@ Object Protocol .. c:function:: int PyObject_SetAttrString(PyObject *o, const char *attr_name, PyObject *v) - Set the value of the attribute named *attr_name*, for object *o*, to the value - *v*. Raise an exception and return ``-1`` on failure; - return ``0`` on success. This is the equivalent of the Python statement - ``o.attr_name = v``. + This is the same as :c:func:`PyObject_SetAttr`, but *attr_name* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. If *v* is ``NULL``, the attribute is deleted, but this feature is deprecated in favour of using :c:func:`PyObject_DelAttrString`. @@ -158,8 +151,9 @@ Object Protocol .. c:function:: int PyObject_DelAttrString(PyObject *o, const char *attr_name) - Delete attribute named *attr_name*, for object *o*. Returns ``-1`` on failure. - This is the equivalent of the Python statement ``del o.attr_name``. + This is the same as :c:func:`PyObject_DelAttr`, but *attr_name* is + specified as a :c:expr:`const char*` UTF-8 encoded bytes string, + rather than a :c:expr:`PyObject*`. .. c:function:: PyObject* PyObject_GenericGetDict(PyObject *o, void *context) diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 400c369a9bb736..04cc75562937e0 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -37,6 +37,10 @@ on efficient attribute extraction for output formatting and manipulation. Package `dateutil `_ Third-party library with expanded time zone and parsing support. + Package `DateType `_ + Third-party library that introduces distinct static types to e.g. allow static type checkers + to differentiate between naive and aware datetimes. + .. _datetime-naive-aware: Aware and Naive Objects diff --git a/Doc/library/doctest.rst b/Doc/library/doctest.rst index 92da6133f9bf09..54a8e79a0ef941 100644 --- a/Doc/library/doctest.rst +++ b/Doc/library/doctest.rst @@ -1409,6 +1409,27 @@ DocTestParser objects identifying this string, and is only used for error messages. +TestResults objects +^^^^^^^^^^^^^^^^^^^ + + +.. class:: TestResults(failed, attempted) + + .. attribute:: failed + + Number of failed tests. + + .. attribute:: attempted + + Number of attempted tests. + + .. attribute:: skipped + + Number of skipped tests. + + .. versionadded:: 3.13 + + .. _doctest-doctestrunner: DocTestRunner objects @@ -1427,7 +1448,7 @@ DocTestRunner objects passing a subclass of :class:`OutputChecker` to the constructor. The test runner's display output can be controlled in two ways. First, an output - function can be passed to :meth:`TestRunner.run`; this function will be called + function can be passed to :meth:`run`; this function will be called with strings that should be displayed. It defaults to ``sys.stdout.write``. If capturing the output is not sufficient, then the display output can be also customized by subclassing DocTestRunner, and overriding the methods @@ -1448,6 +1469,10 @@ DocTestRunner objects runner compares expected output to actual output, and how it displays failures. For more information, see section :ref:`doctest-options`. + The test runner accumulates statistics. The aggregated number of attempted, + failed and skipped examples is also available via the :attr:`tries`, + :attr:`failures` and :attr:`skips` attributes. The :meth:`run` and + :meth:`summarize` methods return a :class:`TestResults` instance. :class:`DocTestParser` defines the following methods: @@ -1500,7 +1525,8 @@ DocTestRunner objects .. method:: run(test, compileflags=None, out=None, clear_globs=True) Run the examples in *test* (a :class:`DocTest` object), and display the - results using the writer function *out*. + results using the writer function *out*. Return a :class:`TestResults` + instance. The examples are run in the namespace ``test.globs``. If *clear_globs* is true (the default), then this namespace will be cleared after the test runs, @@ -1519,12 +1545,29 @@ DocTestRunner objects .. method:: summarize(verbose=None) Print a summary of all the test cases that have been run by this DocTestRunner, - and return a :term:`named tuple` ``TestResults(failed, attempted)``. + and return a :class:`TestResults` instance. The optional *verbose* argument controls how detailed the summary is. If the verbosity is not specified, then the :class:`DocTestRunner`'s verbosity is used. + :class:`DocTestParser` has the following attributes: + + .. attribute:: tries + + Number of attempted examples. + + .. attribute:: failures + + Number of failed examples. + + .. attribute:: skips + + Number of skipped examples. + + .. versionadded:: 3.13 + + .. _doctest-outputchecker: OutputChecker objects diff --git a/Doc/library/unittest.mock-examples.rst b/Doc/library/unittest.mock-examples.rst index 895b9f9f07671b..744fc9de63cd16 100644 --- a/Doc/library/unittest.mock-examples.rst +++ b/Doc/library/unittest.mock-examples.rst @@ -579,14 +579,14 @@ Partial mocking In some tests I wanted to mock out a call to :meth:`datetime.date.today` to return a known date, but I didn't want to prevent the code under test from creating new date objects. Unfortunately :class:`datetime.date` is written in C, and -so I couldn't just monkey-patch out the static :meth:`date.today` method. +so I couldn't just monkey-patch out the static :meth:`datetime.date.today` method. I found a simple way of doing this that involved effectively wrapping the date class with a mock, but passing through calls to the constructor to the real class (and returning real instances). The :func:`patch decorator ` is used here to -mock out the ``date`` class in the module under test. The :attr:`side_effect` +mock out the ``date`` class in the module under test. The :attr:`~Mock.side_effect` attribute on the mock date class is then set to a lambda function that returns a real date. When the mock date class is called a real date will be constructed and returned by ``side_effect``. :: @@ -766,8 +766,8 @@ mock has a nice API for making assertions about how your mock objects are used. >>> mock.foo_bar.assert_called_with('baz', spam='eggs') If your mock is only being called once you can use the -:meth:`assert_called_once_with` method that also asserts that the -:attr:`call_count` is one. +:meth:`~Mock.assert_called_once_with` method that also asserts that the +:attr:`~Mock.call_count` is one. >>> mock.foo_bar.assert_called_once_with('baz', spam='eggs') >>> mock.foo_bar() @@ -835,7 +835,7 @@ One possibility would be for mock to copy the arguments you pass in. This could then cause problems if you do assertions that rely on object identity for equality. -Here's one solution that uses the :attr:`side_effect` +Here's one solution that uses the :attr:`~Mock.side_effect` functionality. If you provide a ``side_effect`` function for a mock then ``side_effect`` will be called with the same args as the mock. This gives us an opportunity to copy the arguments and store them for later assertions. In this @@ -971,7 +971,8 @@ We can do this with :class:`MagicMock`, which will behave like a dictionary, and using :data:`~Mock.side_effect` to delegate dictionary access to a real underlying dictionary that is under our control. -When the :meth:`__getitem__` and :meth:`__setitem__` methods of our ``MagicMock`` are called +When the :meth:`~object.__getitem__` and :meth:`~object.__setitem__` methods +of our ``MagicMock`` are called (normal dictionary access) then ``side_effect`` is called with the key (and in the case of ``__setitem__`` the value too). We can also control what is returned. diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index 94b9a432372195..adf01770656754 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -22,7 +22,7 @@ random UUID. Depending on support from the underlying platform, :func:`uuid1` may or may not return a "safe" UUID. A safe UUID is one which is generated using synchronization methods that ensure no two processes can obtain the same -UUID. All instances of :class:`UUID` have an :attr:`is_safe` attribute +UUID. All instances of :class:`UUID` have an :attr:`~UUID.is_safe` attribute which relays any information about the UUID's safety, using this enumeration: .. class:: SafeUUID @@ -95,25 +95,34 @@ which relays any information about the UUID's safety, using this enumeration: A tuple of the six integer fields of the UUID, which are also available as six individual attributes and two derived attributes: - +------------------------------+-------------------------------+ - | Field | Meaning | - +==============================+===============================+ - | :attr:`time_low` | the first 32 bits of the UUID | - +------------------------------+-------------------------------+ - | :attr:`time_mid` | the next 16 bits of the UUID | - +------------------------------+-------------------------------+ - | :attr:`time_hi_version` | the next 16 bits of the UUID | - +------------------------------+-------------------------------+ - | :attr:`clock_seq_hi_variant` | the next 8 bits of the UUID | - +------------------------------+-------------------------------+ - | :attr:`clock_seq_low` | the next 8 bits of the UUID | - +------------------------------+-------------------------------+ - | :attr:`node` | the last 48 bits of the UUID | - +------------------------------+-------------------------------+ - | :attr:`time` | the 60-bit timestamp | - +------------------------------+-------------------------------+ - | :attr:`clock_seq` | the 14-bit sequence number | - +------------------------------+-------------------------------+ +.. list-table:: + + * - Field + - Meaning + + * - .. attribute:: UUID.time_low + - The first 32 bits of the UUID. + + * - .. attribute:: UUID.time_mid + - The next 16 bits of the UUID. + + * - .. attribute:: UUID.time_hi_version + - The next 16 bits of the UUID. + + * - .. attribute:: UUID.clock_seq_hi_variant + - The next 8 bits of the UUID. + + * - .. attribute:: UUID.clock_seq_low + - The next 8 bits of the UUID. + + * - .. attribute:: UUID.node + - The last 48 bits of the UUID. + + * - .. attribute:: UUID.time + - The 60-bit timestamp. + + * - .. attribute:: UUID.clock_seq + - The 14-bit sequence number. .. attribute:: UUID.hex @@ -233,7 +242,7 @@ The :mod:`uuid` module defines the following namespace identifiers for use with text output format. The :mod:`uuid` module defines the following constants for the possible values -of the :attr:`variant` attribute: +of the :attr:`~UUID.variant` attribute: .. data:: RESERVED_NCS diff --git a/Doc/tools/.nitignore b/Doc/tools/.nitignore index 1d89c9c683a070..a6268048e143db 100644 --- a/Doc/tools/.nitignore +++ b/Doc/tools/.nitignore @@ -131,12 +131,10 @@ Doc/library/tkinter.ttk.rst Doc/library/traceback.rst Doc/library/tty.rst Doc/library/turtle.rst -Doc/library/unittest.mock-examples.rst Doc/library/unittest.mock.rst Doc/library/unittest.rst Doc/library/urllib.parse.rst Doc/library/urllib.request.rst -Doc/library/uuid.rst Doc/library/weakref.rst Doc/library/wsgiref.rst Doc/library/xml.dom.minidom.rst diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index d35d20ebb25293..1c91a1dadb899f 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -122,6 +122,14 @@ dbm from the database. (Contributed by Dong-hee Na in :gh:`107122`.) +doctest +------- + +* The :meth:`doctest.DocTestRunner.run` method now counts the number of skipped + tests. Add :attr:`doctest.DocTestRunner.skips` and + :attr:`doctest.TestResults.skipped` attributes. + (Contributed by Victor Stinner in :gh:`108794`.) + io -- @@ -915,6 +923,25 @@ New Features Porting to Python 3.13 ---------------------- +* ``Python.h`` no longer includes the ```` standard header. It was + included for the ``finite()`` function which is now provided by the + ```` header. It should now be included explicitly if needed. Remove + also the ``HAVE_IEEEFP_H`` macro. + (Contributed by Victor Stinner in :gh:`108765`.) + +* ``Python.h`` no longer includes the ```` standard header file. If + needed, it should now be included explicitly. For example, it provides the + functions: ``close()``, ``getpagesize()``, ``getpid()`` and ``sysconf()``. + (Contributed by Victor Stinner in :gh:`108765`.) + +* ``Python.h`` no longer includes these standard header files: ````, + ```` and ````. If needed, they should now be + included explicitly. For example, ```` provides the ``clock()`` and + ``gmtime()`` functions, ```` provides the ``select()`` + function, and ```` provides the ``futimes()``, ``gettimeofday()`` + and ``setitimer()`` functions. + (Contributed by Victor Stinner in :gh:`108765`.) + Deprecated ---------- diff --git a/Include/Python.h b/Include/Python.h index 07f6c202a7f126..4cc72bb23ce7a3 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -5,42 +5,50 @@ #ifndef Py_PYTHON_H #define Py_PYTHON_H -// Since this is a "meta-include" file, no #ifdef __cplusplus / extern "C" { +// Since this is a "meta-include" file, "#ifdef __cplusplus / extern "C" {" +// is not needed. + // Include Python header files #include "patchlevel.h" #include "pyconfig.h" #include "pymacconfig.h" -#if defined(__sgi) && !defined(_SGI_MP_SOURCE) -# define _SGI_MP_SOURCE + +// Include standard header files +#include // assert() +#include // tolower() +#include // uintptr_t +#include // INT_MAX +#include // HUGE_VAL +#include // va_list +#include // wchar_t +#ifdef HAVE_STDDEF_H +# include // size_t +#endif +#ifdef HAVE_SYS_TYPES_H +# include // ssize_t #endif -// stdlib.h, stdio.h, errno.h and string.h headers are not used by Python -// headers, but kept for backward compatibility. They are excluded from the -// limited C API of Python 3.11. +// errno.h, stdio.h, stdlib.h and string.h headers are no longer used by +// Python, but kept for backward compatibility (avoid compiler warnings). +// They are no longer included by limited C API version 3.11 and newer. #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 -# include -# include // FILE* # include // errno +# include // FILE* +# include // getenv() # include // memcpy() #endif -#ifndef MS_WINDOWS -# include -#endif -#ifdef HAVE_STDDEF_H -# include // size_t -#endif -#include // assert() -#include // wchar_t +// Include Python header files #include "pyport.h" #include "pymacro.h" #include "pymath.h" #include "pymem.h" #include "pytypedefs.h" #include "pybuffer.h" +#include "pystats.h" #include "object.h" #include "objimpl.h" #include "typeslots.h" diff --git a/Include/bytesobject.h b/Include/bytesobject.h index ee448cd02bdab3..c5a24195be6bc3 100644 --- a/Include/bytesobject.h +++ b/Include/bytesobject.h @@ -1,5 +1,4 @@ - -/* Bytes object interface */ +// Bytes object interface #ifndef Py_BYTESOBJECT_H #define Py_BYTESOBJECT_H @@ -7,8 +6,6 @@ extern "C" { #endif -#include // va_list - /* Type PyBytesObject represents a byte string. An extra zero byte is reserved at the end to ensure it is zero-terminated, but a size is diff --git a/Include/internal/pycore_condvar.h b/Include/internal/pycore_condvar.h index db8682a4c077aa..489e67d4ec4f9f 100644 --- a/Include/internal/pycore_condvar.h +++ b/Include/internal/pycore_condvar.h @@ -5,6 +5,10 @@ # error "this header requires Py_BUILD_CORE define" #endif +#ifndef MS_WINDOWS +# include // _POSIX_THREADS +#endif + #ifndef _POSIX_THREADS /* This means pthreads are not implemented in libc headers, hence the macro not present in unistd.h. But they still can be implemented as an external diff --git a/Include/modsupport.h b/Include/modsupport.h index 7c15ab50c320e2..6efe9dfaa9089e 100644 --- a/Include/modsupport.h +++ b/Include/modsupport.h @@ -1,3 +1,4 @@ +// Module support interface #ifndef Py_MODSUPPORT_H #define Py_MODSUPPORT_H @@ -5,10 +6,6 @@ extern "C" { #endif -/* Module support interface */ - -#include // va_list - PyAPI_FUNC(int) PyArg_Parse(PyObject *, const char *, ...); PyAPI_FUNC(int) PyArg_ParseTuple(PyObject *, const char *, ...); PyAPI_FUNC(int) PyArg_ParseTupleAndKeywords(PyObject *, PyObject *, diff --git a/Include/object.h b/Include/object.h index de2a1ce0f3c4dd..b94b2907e4f163 100644 --- a/Include/object.h +++ b/Include/object.h @@ -51,8 +51,6 @@ A standard interface exists for objects that contain an array of items whose size is determined when the object is allocated. */ -#include "pystats.h" - /* Py_DEBUG implies Py_REF_DEBUG. */ #if defined(Py_DEBUG) && !defined(Py_REF_DEBUG) # define Py_REF_DEBUG diff --git a/Include/objimpl.h b/Include/objimpl.h index ef871c5ea93ebe..967e2776767756 100644 --- a/Include/objimpl.h +++ b/Include/objimpl.h @@ -1,12 +1,8 @@ -/* The PyObject_ memory family: high-level object memory interfaces. - See pymem.h for the low-level PyMem_ family. -*/ +// The PyObject_ memory family: high-level object memory interfaces. +// See pymem.h for the low-level PyMem_ family. #ifndef Py_OBJIMPL_H #define Py_OBJIMPL_H - -#include "pymem.h" - #ifdef __cplusplus extern "C" { #endif @@ -231,4 +227,4 @@ PyAPI_FUNC(int) PyObject_GC_IsFinalized(PyObject *); #ifdef __cplusplus } #endif -#endif /* !Py_OBJIMPL_H */ +#endif // !Py_OBJIMPL_H diff --git a/Include/pyerrors.h b/Include/pyerrors.h index d089fa71779330..5d0028c116e2d8 100644 --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -1,13 +1,11 @@ +// Error handling definitions + #ifndef Py_ERRORS_H #define Py_ERRORS_H #ifdef __cplusplus extern "C" { #endif -#include // va_list - -/* Error handling definitions */ - PyAPI_FUNC(void) PyErr_SetNone(PyObject *); PyAPI_FUNC(void) PyErr_SetObject(PyObject *, PyObject *); PyAPI_FUNC(void) PyErr_SetString( diff --git a/Include/pymem.h b/Include/pymem.h index e882645757bfd3..68e33f90b7b913 100644 --- a/Include/pymem.h +++ b/Include/pymem.h @@ -1,12 +1,8 @@ -/* The PyMem_ family: low-level memory allocation interfaces. - See objimpl.h for the PyObject_ memory family. -*/ +// The PyMem_ family: low-level memory allocation interfaces. +// See objimpl.h for the PyObject_ memory family. #ifndef Py_PYMEM_H #define Py_PYMEM_H - -#include "pyport.h" - #ifdef __cplusplus extern "C" { #endif @@ -100,5 +96,4 @@ PyAPI_FUNC(void) PyMem_Free(void *ptr); #ifdef __cplusplus } #endif - -#endif /* !Py_PYMEM_H */ +#endif // !Py_PYMEM_H diff --git a/Include/pyport.h b/Include/pyport.h index 115b54fd969287..c4168d10f58151 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -1,13 +1,8 @@ #ifndef Py_PYPORT_H #define Py_PYPORT_H -#include "pyconfig.h" /* include for defines */ - -#include - -#include #ifndef UCHAR_MAX -# error "limits.h must define UCHAR_MAX" +# error " header must define UCHAR_MAX" #endif #if UCHAR_MAX != 255 # error "Python's source code assumes C's unsigned char is an 8-bit type" @@ -189,31 +184,6 @@ typedef Py_ssize_t Py_ssize_clean_t; # define Py_MEMCPY memcpy #endif -#ifdef HAVE_IEEEFP_H -#include /* needed for 'finite' declaration on some platforms */ -#endif - -#include /* Moved here from the math section, before extern "C" */ - -/******************************************** - * WRAPPER FOR and/or * - ********************************************/ - -#ifdef HAVE_SYS_TIME_H -#include -#endif -#include - -/****************************** - * WRAPPER FOR * - ******************************/ - -/* NB caller must include */ - -#ifdef HAVE_SYS_SELECT_H -#include -#endif /* !HAVE_SYS_SELECT_H */ - /******************************* * stat() and fstat() fiddling * *******************************/ @@ -422,32 +392,6 @@ extern "C" { # define Py_NO_INLINE #endif -/************************************************************************** -Prototypes that are missing from the standard include files on some systems -(and possibly only some versions of such systems.) - -Please be conservative with adding new ones, document them and enclose them -in platform-specific #ifdefs. -**************************************************************************/ - -#ifdef SOLARIS -/* Unchecked */ -extern int gethostname(char *, int); -#endif - -#ifdef HAVE__GETPTY -#include /* we need to import mode_t */ -extern char * _getpty(int *, int, mode_t, int); -#endif - -/* On QNX 6, struct termio must be declared by including sys/termio.h - if TCGETA, TCSETA, TCSETAW, or TCSETAF are used. sys/termio.h must - be included before termios.h or it will generate an error. */ -#if defined(HAVE_SYS_TERMIO_H) && !defined(__hpux) -#include -#endif - - /* On 4.4BSD-descendants, ctype functions serves the whole range of * wchar_t character set rather than single byte code points only. * This characteristic can break some operations of string object @@ -771,4 +715,8 @@ extern char * _getpty(int *, int, mode_t, int); # define ALIGNOF_MAX_ALIGN_T _Alignof(long double) #endif +#if defined(__sgi) && !defined(_SGI_MP_SOURCE) +# define _SGI_MP_SOURCE +#endif + #endif /* Py_PYPORT_H */ diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index 5839c747a29275..f00277787122aa 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -1,8 +1,6 @@ #ifndef Py_UNICODEOBJECT_H #define Py_UNICODEOBJECT_H -#include // va_list - /* Unicode implementation based on original code by Fredrik Lundh, @@ -55,8 +53,6 @@ Copyright (c) Corporation for National Research Initiatives. * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * -------------------------------------------------------------------- */ -#include - /* === Internal API ======================================================= */ /* --- Internal Unicode Format -------------------------------------------- */ @@ -93,10 +89,6 @@ Copyright (c) Corporation for National Research Initiatives. # endif #endif -#ifdef HAVE_WCHAR_H -# include -#endif - /* Py_UCS4 and Py_UCS2 are typedefs for the respective unicode representations. */ typedef uint32_t Py_UCS4; diff --git a/Lib/_pydatetime.py b/Lib/_pydatetime.py index f4fc2c58e5e293..549fcda19dccf2 100644 --- a/Lib/_pydatetime.py +++ b/Lib/_pydatetime.py @@ -1812,7 +1812,7 @@ def utcfromtimestamp(cls, t): warnings.warn("datetime.utcfromtimestamp() is deprecated and scheduled " "for removal in a future version. Use timezone-aware " "objects to represent datetimes in UTC: " - "datetime.fromtimestamp(t, datetime.UTC).", + "datetime.datetime.fromtimestamp(t, datetime.UTC).", DeprecationWarning, stacklevel=2) return cls._fromtimestamp(t, True, None) @@ -1830,7 +1830,7 @@ def utcnow(cls): warnings.warn("datetime.utcnow() is deprecated and scheduled for " "removal in a future version. Instead, Use timezone-aware " "objects to represent datetimes in UTC: " - "datetime.now(datetime.UTC).", + "datetime.datetime.now(datetime.UTC).", DeprecationWarning, stacklevel=2) t = _time.time() diff --git a/Lib/doctest.py b/Lib/doctest.py index a63df46a112e64..46b4dd6769b063 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -105,7 +105,23 @@ def _test(): from io import StringIO, IncrementalNewlineDecoder from collections import namedtuple -TestResults = namedtuple('TestResults', 'failed attempted') + +class TestResults(namedtuple('TestResults', 'failed attempted')): + def __new__(cls, failed, attempted, *, skipped=0): + results = super().__new__(cls, failed, attempted) + results.skipped = skipped + return results + + def __repr__(self): + if self.skipped: + return (f'TestResults(failed={self.failed}, ' + f'attempted={self.attempted}, ' + f'skipped={self.skipped})') + else: + # Leave the repr() unchanged for backward compatibility + # if skipped is zero + return super().__repr__() + # There are 4 basic classes: # - Example: a pair, plus an intra-docstring line number. @@ -1150,8 +1166,7 @@ class DocTestRunner: """ A class used to run DocTest test cases, and accumulate statistics. The `run` method is used to process a single DocTest case. It - returns a tuple `(f, t)`, where `t` is the number of test cases - tried, and `f` is the number of test cases that failed. + returns a TestResults instance. >>> tests = DocTestFinder().find(_TestClass) >>> runner = DocTestRunner(verbose=False) @@ -1164,8 +1179,8 @@ class DocTestRunner: _TestClass.square -> TestResults(failed=0, attempted=1) The `summarize` method prints a summary of all the test cases that - have been run by the runner, and returns an aggregated `(f, t)` - tuple: + have been run by the runner, and returns an aggregated TestResults + instance: >>> runner.summarize(verbose=1) 4 items passed all tests: @@ -1178,13 +1193,15 @@ class DocTestRunner: Test passed. TestResults(failed=0, attempted=7) - The aggregated number of tried examples and failed examples is - also available via the `tries` and `failures` attributes: + The aggregated number of tried examples and failed examples is also + available via the `tries`, `failures` and `skips` attributes: >>> runner.tries 7 >>> runner.failures 0 + >>> runner.skips + 0 The comparison between expected outputs and actual outputs is done by an `OutputChecker`. This comparison may be customized with a @@ -1233,7 +1250,8 @@ def __init__(self, checker=None, verbose=None, optionflags=0): # Keep track of the examples we've run. self.tries = 0 self.failures = 0 - self._name2ft = {} + self.skips = 0 + self._stats = {} # Create a fake output target for capturing doctest output. self._fakeout = _SpoofOut() @@ -1302,13 +1320,11 @@ def __run(self, test, compileflags, out): Run the examples in `test`. Write the outcome of each example with one of the `DocTestRunner.report_*` methods, using the writer function `out`. `compileflags` is the set of compiler - flags that should be used to execute examples. Return a tuple - `(f, t)`, where `t` is the number of examples tried, and `f` - is the number of examples that failed. The examples are run - in the namespace `test.globs`. + flags that should be used to execute examples. Return a TestResults + instance. The examples are run in the namespace `test.globs`. """ - # Keep track of the number of failures and tries. - failures = tries = 0 + # Keep track of the number of failed, attempted, skipped examples. + failures = attempted = skips = 0 # Save the option flags (since option directives can be used # to modify them). @@ -1320,6 +1336,7 @@ def __run(self, test, compileflags, out): # Process each example. for examplenum, example in enumerate(test.examples): + attempted += 1 # If REPORT_ONLY_FIRST_FAILURE is set, then suppress # reporting after the first failure. @@ -1337,10 +1354,10 @@ def __run(self, test, compileflags, out): # If 'SKIP' is set, then skip this example. if self.optionflags & SKIP: + skips += 1 continue # Record that we started this example. - tries += 1 if not quiet: self.report_start(out, test, example) @@ -1418,19 +1435,22 @@ def __run(self, test, compileflags, out): # Restore the option flags (in case they were modified) self.optionflags = original_optionflags - # Record and return the number of failures and tries. - self.__record_outcome(test, failures, tries) - return TestResults(failures, tries) + # Record and return the number of failures and attempted. + self.__record_outcome(test, failures, attempted, skips) + return TestResults(failures, attempted, skipped=skips) - def __record_outcome(self, test, f, t): + def __record_outcome(self, test, failures, tries, skips): """ - Record the fact that the given DocTest (`test`) generated `f` - failures out of `t` tried examples. + Record the fact that the given DocTest (`test`) generated `failures` + failures out of `tries` tried examples. """ - f2, t2 = self._name2ft.get(test.name, (0,0)) - self._name2ft[test.name] = (f+f2, t+t2) - self.failures += f - self.tries += t + failures2, tries2, skips2 = self._stats.get(test.name, (0, 0, 0)) + self._stats[test.name] = (failures + failures2, + tries + tries2, + skips + skips2) + self.failures += failures + self.tries += tries + self.skips += skips __LINECACHE_FILENAME_RE = re.compile(r'.+)' @@ -1519,9 +1539,7 @@ def out(s): def summarize(self, verbose=None): """ Print a summary of all the test cases that have been run by - this DocTestRunner, and return a tuple `(f, t)`, where `f` is - the total number of failed examples, and `t` is the total - number of tried examples. + this DocTestRunner, and return a TestResults instance. The optional `verbose` argument controls how detailed the summary is. If the verbosity is not specified, then the @@ -1532,59 +1550,61 @@ def summarize(self, verbose=None): notests = [] passed = [] failed = [] - totalt = totalf = 0 - for x in self._name2ft.items(): - name, (f, t) = x - assert f <= t - totalt += t - totalf += f - if t == 0: + total_tries = total_failures = total_skips = 0 + for item in self._stats.items(): + name, (failures, tries, skips) = item + assert failures <= tries + total_tries += tries + total_failures += failures + total_skips += skips + if tries == 0: notests.append(name) - elif f == 0: - passed.append( (name, t) ) + elif failures == 0: + passed.append((name, tries)) else: - failed.append(x) + failed.append(item) if verbose: if notests: - print(len(notests), "items had no tests:") + print(f"{len(notests)} items had no tests:") notests.sort() - for thing in notests: - print(" ", thing) + for name in notests: + print(f" {name}") if passed: - print(len(passed), "items passed all tests:") + print(f"{len(passed)} items passed all tests:") passed.sort() - for thing, count in passed: - print(" %3d tests in %s" % (count, thing)) + for name, count in passed: + print(f" {count:3d} tests in {name}") if failed: print(self.DIVIDER) - print(len(failed), "items had failures:") + print(f"{len(failed)} items had failures:") failed.sort() - for thing, (f, t) in failed: - print(" %3d of %3d in %s" % (f, t, thing)) + for name, (failures, tries, skips) in failed: + print(f" {failures:3d} of {tries:3d} in {name}") if verbose: - print(totalt, "tests in", len(self._name2ft), "items.") - print(totalt - totalf, "passed and", totalf, "failed.") - if totalf: - print("***Test Failed***", totalf, "failures.") + print(f"{total_tries} tests in {len(self._stats)} items.") + print(f"{total_tries - total_failures} passed and {total_failures} failed.") + if total_failures: + msg = f"***Test Failed*** {total_failures} failures" + if total_skips: + msg = f"{msg} and {total_skips} skipped tests" + print(f"{msg}.") elif verbose: print("Test passed.") - return TestResults(totalf, totalt) + return TestResults(total_failures, total_tries, skipped=total_skips) #///////////////////////////////////////////////////////////////// # Backward compatibility cruft to maintain doctest.master. #///////////////////////////////////////////////////////////////// def merge(self, other): - d = self._name2ft - for name, (f, t) in other._name2ft.items(): + d = self._stats + for name, (failures, tries, skips) in other._stats.items(): if name in d: - # Don't print here by default, since doing - # so breaks some of the buildbots - #print("*** DocTestRunner.merge: '" + name + "' in both" \ - # " testers; summing outcomes.") - f2, t2 = d[name] - f = f + f2 - t = t + t2 - d[name] = f, t + failures2, tries2, skips2 = d[name] + failures = failures + failures2 + tries = tries + tries2 + skips = skips + skips2 + d[name] = (failures, tries, skips) + class OutputChecker: """ @@ -1984,7 +2004,8 @@ class doctest.Tester, then merges the results into (or creates) else: master.merge(runner) - return TestResults(runner.failures, runner.tries) + return TestResults(runner.failures, runner.tries, skipped=runner.skips) + def testfile(filename, module_relative=True, name=None, package=None, globs=None, verbose=None, report=True, optionflags=0, @@ -2107,7 +2128,8 @@ class doctest.Tester, then merges the results into (or creates) else: master.merge(runner) - return TestResults(runner.failures, runner.tries) + return TestResults(runner.failures, runner.tries, skipped=runner.skips) + def run_docstring_examples(f, globs, verbose=False, name="NoName", compileflags=None, optionflags=0): diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 758f70f5ba7077..f4ec315da6b4fa 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -1009,8 +1009,7 @@ def iterdir(self): The children are yielded in arbitrary order, and the special entries '.' and '..' are not included. """ - for name in os.listdir(self): - yield self._make_child_relpath(name) + return (self._make_child_relpath(name) for name in os.listdir(self)) def _scandir(self): # bpo-24132: a future version of pathlib will support subclassing of diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 7a851d3df78781..bcbb4c2929d69e 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -329,6 +329,7 @@ def test_set_executable(self): p.join() self.assertEqual(p.exitcode, 0) + @support.requires_resource('cpu') def test_args_argument(self): # bpo-45735: Using list or tuple as *args* in constructor could # achieve the same effect. @@ -4504,6 +4505,7 @@ def test_finalize(self): result = [obj for obj in iter(conn.recv, 'STOP')] self.assertEqual(result, ['a', 'b', 'd10', 'd03', 'd02', 'd01', 'e']) + @support.requires_resource('cpu') def test_thread_safety(self): # bpo-24484: _run_finalizers() should be thread-safe def cb(): diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index 6e87370c2065ba..a687fe0629080a 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -2576,6 +2576,7 @@ def check_frame_opcodes(self, pickled): self.assertLess(pos - frameless_start, self.FRAME_SIZE_MIN) @support.skip_if_pgo_task + @support.requires_resource('cpu') def test_framing_many_objects(self): obj = list(range(10**5)) for proto in range(4, pickle.HIGHEST_PROTOCOL + 1): diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 68de4d6f3f1923..fa96e259b8c978 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -2031,6 +2031,7 @@ def test_nameconstant(self): 'ast.NameConstant is deprecated and will be removed in Python 3.14; use ast.Constant instead', ]) + @support.requires_resource('cpu') def test_stdlib_validates(self): stdlib = os.path.dirname(ast.__file__) tests = [fn for fn in os.listdir(stdlib) if fn.endswith(".py")] diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py index a2d7d0293ce1ae..eb831b1a06fcb8 100644 --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -5,6 +5,7 @@ import array import re from test.support import bigmemtest, _1G, _4G +from test.support.hypothesis_helper import hypothesis # Note: "*_hex" functions are aliases for "(un)hexlify" @@ -27,6 +28,14 @@ class BinASCIITest(unittest.TestCase): def setUp(self): self.data = self.type2test(self.rawdata) + def assertConversion(self, original, converted, restored, **kwargs): + self.assertIsInstance(original, bytes) + self.assertIsInstance(converted, bytes) + self.assertIsInstance(restored, bytes) + if converted: + self.assertLess(max(converted), 128) + self.assertEqual(original, restored, msg=f'{self.type2test=} {kwargs=}') + def test_exceptions(self): # Check module exceptions self.assertTrue(issubclass(binascii.Error, Exception)) @@ -52,9 +61,7 @@ def test_returned_value(self): self.fail("{}/{} conversion raises {!r}".format(fb, fa, err)) self.assertEqual(res, raw, "{}/{} conversion: " "{!r} != {!r}".format(fb, fa, res, raw)) - self.assertIsInstance(res, bytes) - self.assertIsInstance(a, bytes) - self.assertLess(max(a), 128) + self.assertConversion(raw, a, res) self.assertIsInstance(binascii.crc_hqx(raw, 0), int) self.assertIsInstance(binascii.crc32(raw), int) @@ -222,6 +229,15 @@ def test_uu(self): with self.assertRaises(TypeError): binascii.b2a_uu(b"", True) + @hypothesis.given( + binary=hypothesis.strategies.binary(), + backtick=hypothesis.strategies.booleans(), + ) + def test_hex_roundtrip(self, binary, backtick): + converted = binascii.b2a_uu(self.type2test(binary), backtick=backtick) + restored = binascii.a2b_uu(self.type2test(converted)) + self.assertConversion(binary, converted, restored, backtick=backtick) + def test_crc_hqx(self): crc = binascii.crc_hqx(self.type2test(b"Test the CRC-32 of"), 0) crc = binascii.crc_hqx(self.type2test(b" this string."), crc) @@ -259,6 +275,12 @@ def test_hex(self): self.assertEqual(binascii.hexlify(self.type2test(s)), t) self.assertEqual(binascii.unhexlify(self.type2test(t)), u) + @hypothesis.given(binary=hypothesis.strategies.binary()) + def test_hex_roundtrip(self, binary): + converted = binascii.hexlify(self.type2test(binary)) + restored = binascii.unhexlify(self.type2test(converted)) + self.assertConversion(binary, converted, restored) + def test_hex_separator(self): """Test that hexlify and b2a_hex are binary versions of bytes.hex.""" # Logic of separators is tested in test_bytes.py. This checks that @@ -373,6 +395,21 @@ def test_qp(self): self.assertEqual(b2a_qp(type2test(b'a.\n')), b'a.\n') self.assertEqual(b2a_qp(type2test(b'.a')[:-1]), b'=2E') + @hypothesis.given( + binary=hypothesis.strategies.binary(), + quotetabs=hypothesis.strategies.booleans(), + istext=hypothesis.strategies.booleans(), + header=hypothesis.strategies.booleans(), + ) + def test_b2a_qp_a2b_qp_round_trip(self, binary, quotetabs, istext, header): + converted = binascii.b2a_qp( + self.type2test(binary), + quotetabs=quotetabs, istext=istext, header=header, + ) + restored = binascii.a2b_qp(self.type2test(converted), header=header) + self.assertConversion(binary, converted, restored, + quotetabs=quotetabs, istext=istext, header=header) + def test_empty_string(self): # A test for SF bug #1022953. Make sure SystemError is not raised. empty = self.type2test(b'') @@ -428,6 +465,15 @@ def test_b2a_base64_newline(self): self.assertEqual(binascii.b2a_base64(b, newline=False), b'aGVsbG8=') + @hypothesis.given( + binary=hypothesis.strategies.binary(), + newline=hypothesis.strategies.booleans(), + ) + def test_base64_roundtrip(self, binary, newline): + converted = binascii.b2a_base64(self.type2test(binary), newline=newline) + restored = binascii.a2b_base64(self.type2test(converted)) + self.assertConversion(binary, converted, restored, newline=newline) + class ArrayBinASCIITest(BinASCIITest): def type2test(self, s): diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py index b679d2e8a01f92..72a06d6af450e3 100644 --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -1029,6 +1029,7 @@ def match(req, flag): ndim=ndim, shape=shape, strides=strides, lst=lst, sliced=sliced) + @support.requires_resource('cpu') def test_ndarray_getbuf(self): requests = ( # distinct flags @@ -2760,6 +2761,7 @@ def iter_roundtrip(ex, m, items, fmt): m = memoryview(ex) iter_roundtrip(ex, m, items, fmt) + @support.requires_resource('cpu') def test_memoryview_cast_1D_ND(self): # Cast between C-contiguous buffers. At least one buffer must # be 1D, at least one format must be 'c', 'b' or 'B'. diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index dbc706ae7b41f5..33cb248ff6e82b 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -952,6 +952,7 @@ def test_filter_pickle(self): f2 = filter(filter_char, "abcdeabcde") self.check_iter_pickle(f1, list(f2), proto) + @support.requires_resource('cpu') def test_filter_dealloc(self): # Tests recursive deallocation of nested filter objects using the # thrashcan mechanism. See gh-102356 for more details. diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index a470d6187aa673..de513daf825d81 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -784,6 +784,7 @@ def test_path_like_objects(self): # An implicit test for PyUnicode_FSDecoder(). compile("42", FakePath("test_compile_pathlike"), "single") + @support.requires_resource('cpu') def test_stack_overflow(self): # bpo-31113: Stack overflow when compile a long sequence of # complex statements. diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py index 05154c8f1c6057..df7c5122b3b1f5 100644 --- a/Lib/test/test_compileall.py +++ b/Lib/test/test_compileall.py @@ -551,6 +551,7 @@ def test_no_args_compiles_path(self): self.assertNotCompiled(self.barfn) @without_source_date_epoch # timestamp invalidation test + @support.requires_resource('cpu') def test_no_args_respects_force_flag(self): bazfn = script_helper.make_script(self.directory, 'baz', '') with self.temporary_pycache_prefix() as env: @@ -568,6 +569,7 @@ def test_no_args_respects_force_flag(self): mtime2 = os.stat(pycpath).st_mtime self.assertNotEqual(mtime, mtime2) + @support.requires_resource('cpu') def test_no_args_respects_quiet_flag(self): script_helper.make_script(self.directory, 'baz', '') with self.temporary_pycache_prefix() as env: diff --git a/Lib/test/test_concurrent_futures/test_thread_pool.py b/Lib/test/test_concurrent_futures/test_thread_pool.py index daef7b5a836825..812f989d8f3ad2 100644 --- a/Lib/test/test_concurrent_futures/test_thread_pool.py +++ b/Lib/test/test_concurrent_futures/test_thread_pool.py @@ -6,6 +6,7 @@ import threading import unittest from concurrent import futures +from test import support from .executor import ExecutorTest, mul from .util import BaseTestCase, ThreadPoolMixin, setup_module @@ -49,6 +50,7 @@ def test_idle_thread_reuse(self): executor.shutdown(wait=True) @unittest.skipUnless(hasattr(os, 'register_at_fork'), 'need os.register_at_fork') + @support.requires_resource('cpu') def test_hang_global_shutdown_lock(self): # bpo-45021: _global_shutdown_lock should be reinitialized in the child # process, otherwise it will never exit diff --git a/Lib/test/test_context.py b/Lib/test/test_context.py index b72d5addc6bd7d..255be306156c0b 100644 --- a/Lib/test/test_context.py +++ b/Lib/test/test_context.py @@ -6,6 +6,7 @@ import time import unittest import weakref +from test import support from test.support import threading_helper try: @@ -570,6 +571,7 @@ def test_hamt_collision_3(self): self.assertEqual({k.name for k in h.keys()}, {'C', 'D', 'E'}) + @support.requires_resource('cpu') def test_hamt_stress(self): COLLECTION_SIZE = 7000 TEST_ITERS_EVERY = 647 diff --git a/Lib/test/test_cppext/__init__.py b/Lib/test/test_cppext/__init__.py index 8adff91c38efcf..74bf420900367e 100644 --- a/Lib/test/test_cppext/__init__.py +++ b/Lib/test/test_cppext/__init__.py @@ -16,9 +16,11 @@ @support.requires_subprocess() class TestCPPExt(unittest.TestCase): + @support.requires_resource('cpu') def test_build_cpp11(self): self.check_build(False, '_testcpp11ext') + @support.requires_resource('cpu') def test_build_cpp03(self): self.check_build(True, '_testcpp03ext') diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index fc8d0a305d8da0..f6bd9094e8fece 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -4457,6 +4457,7 @@ class Oops(object): o.whatever = Provoker(o) del o + @support.requires_resource('cpu') def test_wrapper_segfault(self): # SF 927248: deeply nested wrappers could cause stack overflow f = lambda:None diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py index c364e81a6b1495..9cc460c8b913f6 100644 --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -748,6 +748,38 @@ def non_Python_modules(): r""" """ +class TestDocTest(unittest.TestCase): + + def test_run(self): + test = ''' + >>> 1 + 1 + 11 + >>> 2 + 3 # doctest: +SKIP + "23" + >>> 5 + 7 + 57 + ''' + + def myfunc(): + pass + myfunc.__doc__ = test + + # test DocTestFinder.run() + test = doctest.DocTestFinder().find(myfunc)[0] + with support.captured_stdout(): + with support.captured_stderr(): + results = doctest.DocTestRunner(verbose=False).run(test) + + # test TestResults + self.assertIsInstance(results, doctest.TestResults) + self.assertEqual(results.failed, 2) + self.assertEqual(results.attempted, 3) + self.assertEqual(results.skipped, 1) + self.assertEqual(tuple(results), (2, 3)) + x, y = results + self.assertEqual((x, y), (2, 3)) + + class TestDocTestFinder(unittest.TestCase): def test_issue35753(self): diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index cdb6ef1275e520..2a237095b9080c 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -38,6 +38,7 @@ from email import quoprimime from email import utils +from test import support from test.support import threading_helper from test.support.os_helper import unlink from test.test_email import openfile, TestEmailBase @@ -3358,6 +3359,7 @@ def test_getaddresses_header_obj(self): self.assertEqual(addrs[0][1], 'aperson@dom.ain') @threading_helper.requires_working_threading() + @support.requires_resource('cpu') def test_make_msgid_collisions(self): # Test make_msgid uniqueness, even with multiple threads class MsgidsThread(Thread): diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index c766f4d43311eb..106baf959a6898 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -1350,6 +1350,7 @@ def g(): @cpython_only + @support.requires_resource('cpu') def test_trashcan_recursion(self): # See bpo-33930 diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py index 85009089f21d2f..c05a2d387c429c 100644 --- a/Lib/test/test_gdb.py +++ b/Lib/test/test_gdb.py @@ -317,6 +317,7 @@ def assertGdbRepr(self, val, exp_repr=None): ('%r did not equal expected %r; full output was:\n%s' % (gdb_repr, exp_repr, gdb_output))) + @support.requires_resource('cpu') def test_int(self): 'Verify the pretty-printing of various int values' self.assertGdbRepr(42) @@ -343,6 +344,7 @@ def test_lists(self): self.assertGdbRepr([]) self.assertGdbRepr(list(range(5))) + @support.requires_resource('cpu') def test_bytes(self): 'Verify the pretty-printing of bytes' self.assertGdbRepr(b'') @@ -357,6 +359,7 @@ def test_bytes(self): self.assertGdbRepr(bytes([b for b in range(255)])) + @support.requires_resource('cpu') def test_strings(self): 'Verify the pretty-printing of unicode strings' # We cannot simply call locale.getpreferredencoding() here, @@ -407,6 +410,7 @@ def test_tuples(self): self.assertGdbRepr((1,), '(1,)') self.assertGdbRepr(('foo', 'bar', 'baz')) + @support.requires_resource('cpu') def test_sets(self): 'Verify the pretty-printing of sets' if (gdb_major_version, gdb_minor_version) < (7, 3): @@ -425,6 +429,7 @@ def test_sets(self): id(s)''') self.assertEqual(gdb_repr, "{'b'}") + @support.requires_resource('cpu') def test_frozensets(self): 'Verify the pretty-printing of frozensets' if (gdb_major_version, gdb_minor_version) < (7, 3): @@ -828,6 +833,7 @@ def test_bt_full(self): @unittest.skipIf(python_is_optimized(), "Python was compiled with optimizations") + @support.requires_resource('cpu') def test_threads(self): 'Verify that "py-bt" indicates threads that are waiting for the GIL' cmd = ''' @@ -889,6 +895,7 @@ def test_gc(self): @unittest.skipIf(python_is_optimized(), "Python was compiled with optimizations") + @support.requires_resource('cpu') # Some older versions of gdb will fail with # "Cannot find new threads: generic error" # unless we add LD_PRELOAD=PATH-TO-libpthread.so.1 as a workaround diff --git a/Lib/test/test_interpreters.py b/Lib/test/test_interpreters.py index 5981d96de8de06..90932c0f66f38f 100644 --- a/Lib/test/test_interpreters.py +++ b/Lib/test/test_interpreters.py @@ -469,12 +469,14 @@ class StressTests(TestBase): # In these tests we generally want a lot of interpreters, # but not so many that any test takes too long. + @support.requires_resource('cpu') def test_create_many_sequential(self): alive = [] for _ in range(100): interp = interpreters.create() alive.append(interp) + @support.requires_resource('cpu') def test_create_many_threaded(self): alive = [] def task(): diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py index 4d6ea780e15373..512745e45350d1 100644 --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -2401,6 +2401,7 @@ def gen2(x): self.assertEqual(hist, [0,1]) @support.skip_if_pgo_task + @support.requires_resource('cpu') def test_long_chain_of_empty_iterables(self): # Make sure itertools.chain doesn't run into recursion limits when # dealing with long chains of empty iterables. Even with a high diff --git a/Lib/test/test_largefile.py b/Lib/test/test_largefile.py index 3c11c59baef6e5..3b0930fe69e30e 100644 --- a/Lib/test/test_largefile.py +++ b/Lib/test/test_largefile.py @@ -8,7 +8,7 @@ import socket import shutil import threading -from test.support import requires, bigmemtest +from test.support import requires, bigmemtest, requires_resource from test.support import SHORT_TIMEOUT from test.support import socket_helper from test.support.os_helper import TESTFN, unlink @@ -173,6 +173,7 @@ class TestCopyfile(LargeFileTest, unittest.TestCase): # Exact required disk space would be (size * 2), but let's give it a # bit more tolerance. @skip_no_disk_space(TESTFN, size * 2.5) + @requires_resource('cpu') def test_it(self): # Internally shutil.copyfile() can use "fast copy" methods like # os.sendfile(). @@ -222,6 +223,7 @@ def run(sock): # Exact required disk space would be (size * 2), but let's give it a # bit more tolerance. @skip_no_disk_space(TESTFN, size * 2.5) + @requires_resource('cpu') def test_it(self): port = socket_helper.find_unused_port() with socket.create_server(("", port)) as sock: diff --git a/Lib/test/test_multibytecodec.py b/Lib/test/test_multibytecodec.py index cf8bb5e3a0520d..6451df14696933 100644 --- a/Lib/test/test_multibytecodec.py +++ b/Lib/test/test_multibytecodec.py @@ -363,6 +363,7 @@ def test_iso2022_jp_g0(self): e = '\u3406'.encode(encoding) self.assertFalse(any(x > 0x80 for x in e)) + @support.requires_resource('cpu') def test_bug1572832(self): for x in range(0x10000, 0x110000): # Any ISO 2022 codec will cause the segfault diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 74deec84336f72..09df3fe471fc3e 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -1766,7 +1766,7 @@ def test_iterdir_nodir(self): # __iter__ on something that is not a directory. p = self.cls(BASE, 'fileA') with self.assertRaises(OSError) as cm: - next(p.iterdir()) + p.iterdir() # ENOENT or EINVAL under Windows, ENOTDIR otherwise # (see issue #12802). self.assertIn(cm.exception.errno, (errno.ENOTDIR, diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index fba41f0b119796..b825b27060e86b 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -4,6 +4,7 @@ import textwrap import unittest +from test import support from test.support.bytecode_helper import BytecodeTestCase, CfgOptimizationTestCase @@ -522,6 +523,7 @@ def genexpr(): return (y for x in a for y in [f(x)]) self.assertEqual(count_instr_recursively(genexpr, 'FOR_ITER'), 1) + @support.requires_resource('cpu') def test_format_combinations(self): flags = '-+ #0' testcases = [ diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index 806b932a164df8..0c1400c8105037 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -548,7 +548,11 @@ def run_command(self, args, input=None, exitcode=0, **kw): return proc def run_python(self, args, **kw): - args = [sys.executable, '-X', 'faulthandler', '-I', *args] + extraargs = [] + if 'uops' in sys._xoptions: + # Pass -X uops along + extraargs.extend(['-X', 'uops']) + args = [sys.executable, *extraargs, '-X', 'faulthandler', '-I', *args] proc = self.run_command(args, **kw) return proc.stdout @@ -893,12 +897,12 @@ def check_leak(self, code, what): filename = 'reflog.txt' self.addCleanup(os_helper.unlink, filename) - output = self.run_tests('--huntrleaks', '3:3:', test, + output = self.run_tests('--huntrleaks', '6:3:', test, exitcode=EXITCODE_BAD_TEST, stderr=subprocess.STDOUT) self.check_executed_tests(output, [test], failed=test) - line = 'beginning 6 repetitions\n123456\n......\n' + line = 'beginning 9 repetitions\n123456789\n.........\n' self.check_line(output, re.escape(line)) line2 = '%s leaked [1, 1, 1] %s, sum=3\n' % (test, what) diff --git a/Lib/test/test_runpy.py b/Lib/test/test_runpy.py index 6aaa288c14e1d7..628c8cae38a751 100644 --- a/Lib/test/test_runpy.py +++ b/Lib/test/test_runpy.py @@ -12,7 +12,7 @@ import textwrap import unittest import warnings -from test.support import no_tracing, verbose, requires_subprocess +from test.support import no_tracing, verbose, requires_subprocess, requires_resource from test.support.import_helper import forget, make_legacy_pyc, unload from test.support.os_helper import create_empty_file, temp_dir from test.support.script_helper import make_script, make_zip_script @@ -733,6 +733,7 @@ def test_zipfile_error(self): self._check_import_error(zip_name, msg) @no_tracing + @requires_resource('cpu') def test_main_recursion_error(self): with temp_dir() as script_dir, temp_dir() as dummy_dir: mod_name = '__main__' diff --git a/Lib/test/test_selectors.py b/Lib/test/test_selectors.py index 4545cbadb796fd..33417ca6a11af0 100644 --- a/Lib/test/test_selectors.py +++ b/Lib/test/test_selectors.py @@ -455,6 +455,7 @@ class ScalableSelectorMixIn: # see issue #18963 for why it's skipped on older OS X versions @support.requires_mac_ver(10, 5) @unittest.skipUnless(resource, "Test needs resource module") + @support.requires_resource('cpu') def test_above_fd_setsize(self): # A scalable implementation should have no problem with more than # FD_SETSIZE file descriptors. Since we don't know the value, we just diff --git a/Lib/test/test_source_encoding.py b/Lib/test/test_source_encoding.py index b05173ad00d442..72c2b47779e005 100644 --- a/Lib/test/test_source_encoding.py +++ b/Lib/test/test_source_encoding.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- import unittest -from test.support import script_helper, captured_stdout, requires_subprocess +from test.support import script_helper, captured_stdout, requires_subprocess, requires_resource from test.support.os_helper import TESTFN, unlink, rmtree from test.support.import_helper import unload import importlib @@ -250,6 +250,7 @@ def test_crcrcrlf2(self): class UTF8ValidatorTest(unittest.TestCase): @unittest.skipIf(not sys.platform.startswith("linux"), "Too slow to run on non-Linux platforms") + @requires_resource('cpu') def test_invalid_utf8(self): # This is a port of test_utf8_decode_invalid_sequences in # test_unicode.py to exercise the separate utf8 validator in diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index aa2cf2b1edc584..23a3973305303d 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -2145,6 +2145,7 @@ def test_integer_sqrt_of_frac_rto(self): self.assertTrue(m * (r - 1)**2 < n < m * (r + 1)**2) @requires_IEEE_754 + @support.requires_resource('cpu') def test_float_sqrt_of_frac(self): def is_root_correctly_rounded(x: Fraction, root: float) -> bool: @@ -2849,6 +2850,7 @@ def test_cdf(self): self.assertTrue(math.isnan(X.cdf(float('NaN')))) @support.skip_if_pgo_task + @support.requires_resource('cpu') def test_inv_cdf(self): NormalDist = self.module.NormalDist diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 817eab0c8a7e19..0b9e9e16f55d7e 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1292,6 +1292,7 @@ def test_bufsize_equal_one_binary_mode(self): with self.assertWarnsRegex(RuntimeWarning, 'line buffering'): self._test_bufsize_equal_one(line, b'', universal_newlines=False) + @support.requires_resource('cpu') def test_leaking_fds_on_error(self): # see bug #5179: Popen leaks file descriptors to PIPEs if # the child fails to execute; this will eventually exhaust diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index cd1679dd23281c..86d26b7e8df4d0 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -497,6 +497,7 @@ def check_options(self, args, func, expected=None): self.assertEqual(proc.stdout.rstrip(), repr(expected)) self.assertEqual(proc.returncode, 0) + @support.requires_resource('cpu') def test_args_from_interpreter_flags(self): # Test test.support.args_from_interpreter_flags() for opts in ( diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index 4462b5c712d662..7d38addaee413e 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -2834,6 +2834,7 @@ def test_jump_extended_args_unpack_ex_tricky(output): ) = output.append(4) or "Spam" output.append(5) + @support.requires_resource('cpu') def test_jump_extended_args_for_iter(self): # In addition to failing when extended arg handling is broken, this can # also hang for a *very* long time: diff --git a/Lib/test/test_tools/test_freeze.py b/Lib/test/test_tools/test_freeze.py index 3e9a48b5bc6a89..922e74b441457a 100644 --- a/Lib/test/test_tools/test_freeze.py +++ b/Lib/test/test_tools/test_freeze.py @@ -17,10 +17,8 @@ @support.skip_if_buildbot('not all buildbots have enough space') class TestFreeze(unittest.TestCase): + @support.requires_resource('cpu') # Building Python is slow def test_freeze_simple_script(self): - # Building Python is slow - support.requires('cpu') - script = textwrap.dedent(""" import sys print('running...') diff --git a/Lib/test/test_trace.py b/Lib/test/test_trace.py index 73339ebdb7c4e9..d1ef005a4314ed 100644 --- a/Lib/test/test_trace.py +++ b/Lib/test/test_trace.py @@ -1,7 +1,7 @@ import os from pickle import dump import sys -from test.support import captured_stdout +from test.support import captured_stdout, requires_resource from test.support.os_helper import (TESTFN, rmtree, unlink) from test.support.script_helper import assert_python_ok, assert_python_failure import textwrap @@ -367,6 +367,7 @@ def _coverage(self, tracer, r = tracer.results() r.write_results(show_missing=True, summary=True, coverdir=TESTFN) + @requires_resource('cpu') def test_coverage(self): tracer = trace.Trace(trace=0, count=1) with captured_stdout() as stdout: diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 7c6fdbf762921f..316ade2171e94f 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -3539,6 +3539,7 @@ def CHECK(a, b, expected): CHECK("AttributeError", "AttributeErrorTests", 10) CHECK("ABA", "AAB", 4) + @support.requires_resource('cpu') def test_levenshtein_distance_short_circuit(self): if not LEVENSHTEIN_DATA_FILE.is_file(): self.fail( diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 6447ed6078e178..69f5ff913c57bb 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -8189,8 +8189,7 @@ class AnnotatedTests(BaseTestCase): def test_new(self): with self.assertRaisesRegex( - TypeError, - 'Type Annotated cannot be instantiated', + TypeError, 'Cannot instantiate typing.Annotated', ): Annotated() diff --git a/Lib/test/test_unicodedata.py b/Lib/test/test_unicodedata.py index 3dc0790ca15b41..515c3840cb3647 100644 --- a/Lib/test/test_unicodedata.py +++ b/Lib/test/test_unicodedata.py @@ -313,6 +313,7 @@ def test_ucd_510(self): self.assertTrue("\u1d79".upper()=='\ua77d') self.assertTrue(".".upper()=='.') + @requires_resource('cpu') def test_bug_5828(self): self.assertEqual("\u1d79".lower(), "\u1d79") # Only U+0000 should have U+0000 as its upper/lower/titlecase variant @@ -353,6 +354,7 @@ def unistr(data): return "".join([chr(x) for x in data]) @requires_resource('network') + @requires_resource('cpu') def test_normalization(self): TESTDATAFILE = "NormalizationTest.txt" TESTDATAURL = f"http://www.pythontest.net/unicode/{unicodedata.unidata_version}/{TESTDATAFILE}" diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index 5205604c2c7185..aa6a8fbf8cfd17 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -20,7 +20,8 @@ from test.support import (captured_stdout, captured_stderr, skip_if_broken_multiprocessing_synchronize, verbose, requires_subprocess, is_emscripten, is_wasi, - requires_venv_with_pip, TEST_HOME_DIR) + requires_venv_with_pip, TEST_HOME_DIR, + requires_resource) from test.support.os_helper import (can_symlink, EnvironmentVarGuard, rmtree) import unittest import venv @@ -775,6 +776,7 @@ def nicer_error(self): ) @requires_venv_with_pip() + @requires_resource('cpu') def test_with_pip(self): self.do_test_with_pip(False) self.do_test_with_pip(True) diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py index 1bc1d05f7daba9..4cdd66d3769e0c 100644 --- a/Lib/test/test_weakref.py +++ b/Lib/test/test_weakref.py @@ -1933,6 +1933,7 @@ def test_threaded_weak_key_dict_copy(self): self.check_threaded_weak_dict_copy(weakref.WeakKeyDictionary, False) @threading_helper.requires_working_threading() + @support.requires_resource('cpu') def test_threaded_weak_key_dict_deepcopy(self): # Issue #35615: Weakref keys or values getting GC'ed during dict # copying should not result in a crash. @@ -1945,6 +1946,7 @@ def test_threaded_weak_value_dict_copy(self): self.check_threaded_weak_dict_copy(weakref.WeakValueDictionary, False) @threading_helper.requires_working_threading() + @support.requires_resource('cpu') def test_threaded_weak_value_dict_deepcopy(self): # Issue #35615: Weakref keys or values getting GC'ed during dict # copying should not result in a crash. diff --git a/Lib/typing.py b/Lib/typing.py index 387b4c5ad5284b..8655b756a9fd13 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -2001,7 +2001,8 @@ def __mro_entries__(self, bases): return (self.__origin__,) -class Annotated: +@_SpecialForm +def Annotated(self, params): """Add context-specific metadata to a type. Example: Annotated[int, runtime_check.Unsigned] indicates to the @@ -2048,30 +2049,17 @@ class Annotated: where T1, T2 etc. are TypeVars, which would be invalid, because only one type should be passed to Annotated. """ - - __slots__ = () - - def __new__(cls, *args, **kwargs): - raise TypeError("Type Annotated cannot be instantiated.") - - @_tp_cache - def __class_getitem__(cls, params): - if not isinstance(params, tuple) or len(params) < 2: - raise TypeError("Annotated[...] should be used " - "with at least two arguments (a type and an " - "annotation).") - if _is_unpacked_typevartuple(params[0]): - raise TypeError("Annotated[...] should not be used with an " - "unpacked TypeVarTuple") - msg = "Annotated[t, ...]: t must be a type." - origin = _type_check(params[0], msg, allow_special_forms=True) - metadata = tuple(params[1:]) - return _AnnotatedAlias(origin, metadata) - - def __init_subclass__(cls, *args, **kwargs): - raise TypeError( - "Cannot subclass {}.Annotated".format(cls.__module__) - ) + if not isinstance(params, tuple) or len(params) < 2: + raise TypeError("Annotated[...] should be used " + "with at least two arguments (a type and an " + "annotation).") + if _is_unpacked_typevartuple(params[0]): + raise TypeError("Annotated[...] should not be used with an " + "unpacked TypeVarTuple") + msg = "Annotated[t, ...]: t must be a type." + origin = _type_check(params[0], msg, allow_special_forms=True) + metadata = tuple(params[1:]) + return _AnnotatedAlias(origin, metadata) def runtime_checkable(cls): diff --git a/Makefile.pre.in b/Makefile.pre.in index 0870cb3d899d45..7b67738f4341a2 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -2799,7 +2799,8 @@ MODULE__SHA2_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_SHA2_HEADERS) $(LIBHACL_ MODULE__SHA3_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_HEADERS) Modules/_hacl/Hacl_Hash_SHA3.h Modules/_hacl/Hacl_Hash_SHA3.c MODULE__SOCKET_DEPS=$(srcdir)/Modules/socketmodule.h $(srcdir)/Modules/addrinfo.h $(srcdir)/Modules/getaddrinfo.c $(srcdir)/Modules/getnameinfo.c MODULE__SSL_DEPS=$(srcdir)/Modules/_ssl.h $(srcdir)/Modules/_ssl/cert.c $(srcdir)/Modules/_ssl/debughelpers.c $(srcdir)/Modules/_ssl/misc.c $(srcdir)/Modules/_ssl_data.h $(srcdir)/Modules/_ssl_data_111.h $(srcdir)/Modules/_ssl_data_300.h $(srcdir)/Modules/socketmodule.h -MODULE__TESTCAPI_DEPS=$(srcdir)/Modules/_testcapi/testcapi_long.h $(srcdir)/Modules/_testcapi/parts.h +MODULE__TESTCAPI_DEPS=$(srcdir)/Modules/_testcapi/testcapi_long.h $(srcdir)/Modules/_testcapi/parts.h $(srcdir)/Modules/_testcapi/util.h +MODULE__TESTINTERNALCAPI_DEPS=$(srcdir)/Modules/_testinternalcapi/parts.h MODULE__SQLITE3_DEPS=$(srcdir)/Modules/_sqlite/connection.h $(srcdir)/Modules/_sqlite/cursor.h $(srcdir)/Modules/_sqlite/microprotocols.h $(srcdir)/Modules/_sqlite/module.h $(srcdir)/Modules/_sqlite/prepare_protocol.h $(srcdir)/Modules/_sqlite/row.h $(srcdir)/Modules/_sqlite/util.h CODECS_COMMON_HEADERS=$(srcdir)/Modules/cjkcodecs/multibytecodec.h $(srcdir)/Modules/cjkcodecs/cjkcodecs.h diff --git a/Misc/NEWS.d/next/C API/2023-09-01-18-42-31.gh-issue-108765.IyYNDu.rst b/Misc/NEWS.d/next/C API/2023-09-01-18-42-31.gh-issue-108765.IyYNDu.rst new file mode 100644 index 00000000000000..7b33481f225b5a --- /dev/null +++ b/Misc/NEWS.d/next/C API/2023-09-01-18-42-31.gh-issue-108765.IyYNDu.rst @@ -0,0 +1,6 @@ +``Python.h`` no longer includes these standard header files: ````, +```` and ````. If needed, they should now be included +explicitly. For example, ```` provides the ``clock()`` and ``gmtime()`` +functions, ```` provides the ``select()`` function, and +```` provides the ``futimes()``, ``gettimeofday()`` and +``setitimer()`` functions. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-09-01-20-41-49.gh-issue-108765.5dXc1r.rst b/Misc/NEWS.d/next/C API/2023-09-01-20-41-49.gh-issue-108765.5dXc1r.rst new file mode 100644 index 00000000000000..cc512df7e1bc08 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2023-09-01-20-41-49.gh-issue-108765.5dXc1r.rst @@ -0,0 +1,4 @@ +``Python.h`` no longer includes the ```` standard header. It was +included for the ``finite()`` function which is now provided by the +```` header. It should now be included explicitly if needed. Remove +also the ``HAVE_IEEEFP_H`` macro. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2023-09-01-21-10-29.gh-issue-108765.eeXtYF.rst b/Misc/NEWS.d/next/C API/2023-09-01-21-10-29.gh-issue-108765.eeXtYF.rst new file mode 100644 index 00000000000000..ff8f79998fa968 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2023-09-01-21-10-29.gh-issue-108765.eeXtYF.rst @@ -0,0 +1,4 @@ +``Python.h`` no longer includes the ```` standard header file. If +needed, it should now be included explicitly. For example, it provides the +functions: ``close()``, ``getpagesize()``, ``getpid()`` and ``sysconf()``. +Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-06-08-15-56-45.gh-issue-105509.YIG57j.rst b/Misc/NEWS.d/next/Library/2023-06-08-15-56-45.gh-issue-105509.YIG57j.rst new file mode 100644 index 00000000000000..26d8a66c2c4e03 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-06-08-15-56-45.gh-issue-105509.YIG57j.rst @@ -0,0 +1,3 @@ +:data:`typing.Annotated` is now implemented as an instance of +``typing._SpecialForm`` rather than a class. This should have no user-facing +impact for users of the :mod:`typing` module public API. diff --git a/Misc/NEWS.d/next/Library/2023-07-26-22-52-48.gh-issue-78722.6SKBLt.rst b/Misc/NEWS.d/next/Library/2023-07-26-22-52-48.gh-issue-78722.6SKBLt.rst new file mode 100644 index 00000000000000..aea26ee2f99467 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-07-26-22-52-48.gh-issue-78722.6SKBLt.rst @@ -0,0 +1,2 @@ +Fix issue where :meth:`pathlib.Path.iterdir` did not raise :exc:`OSError` +until iterated. diff --git a/Misc/NEWS.d/next/Library/2023-09-02-16-07-23.gh-issue-108791.fBcAqh.rst b/Misc/NEWS.d/next/Library/2023-09-02-16-07-23.gh-issue-108791.fBcAqh.rst new file mode 100644 index 00000000000000..84a2cd589e10d5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-09-02-16-07-23.gh-issue-108791.fBcAqh.rst @@ -0,0 +1 @@ +Improved error handling in :mod:`pdb` command line interface, making it produce more concise error messages. diff --git a/Misc/NEWS.d/next/Tests/2023-09-02-05-13-38.gh-issue-108794.tGHXBt.rst b/Misc/NEWS.d/next/Tests/2023-09-02-05-13-38.gh-issue-108794.tGHXBt.rst new file mode 100644 index 00000000000000..00027c7c07da2e --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2023-09-02-05-13-38.gh-issue-108794.tGHXBt.rst @@ -0,0 +1,3 @@ +The :meth:`doctest.DocTestRunner.run` method now counts the number of skipped +tests. Add :attr:`doctest.DocTestRunner.skips` and +:attr:`doctest.TestResults.skipped` attributes. Patch by Victor Stinner. diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 2bb39d2936894a..56c1badf6b44a0 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -158,7 +158,7 @@ @MODULE_XXSUBTYPE_TRUE@xxsubtype xxsubtype.c @MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c @MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c -@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c +@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/pytime.c @MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/pyos.c _testcapi/immortal.c _testcapi/heaptype_relative.c _testcapi/gc.c @MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c @MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c diff --git a/Modules/_ctypes/malloc_closure.c b/Modules/_ctypes/malloc_closure.c index 3a859322772ba7..bb4f8f21bd3f77 100644 --- a/Modules/_ctypes/malloc_closure.c +++ b/Modules/_ctypes/malloc_closure.c @@ -1,16 +1,17 @@ #ifndef Py_BUILD_CORE_BUILTIN # define Py_BUILD_CORE_MODULE 1 #endif + #include #include #ifdef MS_WIN32 -#include +# include #else -#include -#include -# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) -# define MAP_ANONYMOUS MAP_ANON -# endif +# include +# include // sysconf() +# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +# define MAP_ANONYMOUS MAP_ANON +# endif #endif #include "ctypes.h" diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c index d22b8d18e33e42..f8f2afda28d06d 100644 --- a/Modules/_multiprocessing/semaphore.c +++ b/Modules/_multiprocessing/semaphore.c @@ -9,6 +9,10 @@ #include "multiprocessing.h" +#ifdef HAVE_SYS_TIME_H +# include // gettimeofday() +#endif + #ifdef HAVE_MP_SEMAPHORE enum { RECURSIVE_MUTEX, SEMAPHORE }; diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c index ac2b0d4f55468c..ef76d26282e1b3 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -8,28 +8,28 @@ #include "pycore_pystate.h" #include "pycore_signal.h" // _Py_RestoreSignals() #if defined(HAVE_PIPE2) && !defined(_GNU_SOURCE) -# define _GNU_SOURCE +# define _GNU_SOURCE #endif -#include -#include +#include // close() +#include // fcntl() #ifdef HAVE_SYS_TYPES_H -#include +# include #endif #if defined(HAVE_SYS_STAT_H) -#include +# include // stat() #endif #ifdef HAVE_SYS_SYSCALL_H -#include +# include #endif #if defined(HAVE_SYS_RESOURCE_H) -#include +# include #endif #ifdef HAVE_DIRENT_H -#include +# include // opendir() +#endif +#if defined(HAVE_SETGROUPS) +# include // setgroups() #endif -#ifdef HAVE_GRP_H -#include -#endif /* HAVE_GRP_H */ #include "posixmodule.h" diff --git a/Modules/_testcapi/abstract.c b/Modules/_testcapi/abstract.c index 10d7ff8d4a7bc8..91a1ee3aaafc02 100644 --- a/Modules/_testcapi/abstract.c +++ b/Modules/_testcapi/abstract.c @@ -1,24 +1,7 @@ #include // ptrdiff_t #include "parts.h" - -#define NULLABLE(x) do { if (x == Py_None) x = NULL; } while (0); - -#define RETURN_INT(value) do { \ - int _ret = (value); \ - if (_ret == -1) { \ - return NULL; \ - } \ - return PyLong_FromLong(_ret); \ - } while (0) - -#define RETURN_SIZE(value) do { \ - Py_ssize_t _ret = (value); \ - if (_ret == -1) { \ - return NULL; \ - } \ - return PyLong_FromSsize_t(_ret); \ - } while (0) +#include "util.h" static PyObject * diff --git a/Modules/_testcapi/dict.c b/Modules/_testcapi/dict.c index 6c3f9cd22faa5a..6720f0437401ef 100644 --- a/Modules/_testcapi/dict.c +++ b/Modules/_testcapi/dict.c @@ -1,24 +1,7 @@ #include // ptrdiff_t #include "parts.h" - -#define NULLABLE(x) do { if (x == Py_None) x = NULL; } while (0); - -#define RETURN_INT(value) do { \ - int _ret = (value); \ - if (_ret == -1) { \ - return NULL; \ - } \ - return PyLong_FromLong(_ret); \ - } while (0) - -#define RETURN_SIZE(value) do { \ - Py_ssize_t _ret = (value); \ - if (_ret == -1) { \ - return NULL; \ - } \ - return PyLong_FromSsize_t(_ret); \ - } while (0) +#include "util.h" static PyObject * diff --git a/Modules/_testcapi/exceptions.c b/Modules/_testcapi/exceptions.c index d7edf8c7ce6744..025b42db247e81 100644 --- a/Modules/_testcapi/exceptions.c +++ b/Modules/_testcapi/exceptions.c @@ -1,7 +1,7 @@ #include "parts.h" +#include "util.h" #include "clinic/exceptions.c.h" -#define NULLABLE(x) do { if (x == Py_None) x = NULL; } while (0); /*[clinic input] module _testcapi diff --git a/Modules/_testcapi/pytime.c b/Modules/_testcapi/pytime.c deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/Modules/_testcapi/unicode.c b/Modules/_testcapi/unicode.c index b4c6c4b5e3ce1a..f2cf9a744007d9 100644 --- a/Modules/_testcapi/unicode.c +++ b/Modules/_testcapi/unicode.c @@ -1,6 +1,7 @@ #include // ptrdiff_t #include "parts.h" +#include "util.h" static struct PyModuleDef *_testcapimodule = NULL; // set at initialization @@ -101,7 +102,6 @@ test_widechar(PyObject *self, PyObject *Py_UNUSED(ignored)) Py_RETURN_NONE; } -#define NULLABLE(x) do { if (x == Py_None) x = NULL; } while (0); static PyObject * unicode_copy(PyObject *unicode) @@ -347,13 +347,8 @@ unicode_substring(PyObject *self, PyObject *args) static PyObject * unicode_getlength(PyObject *self, PyObject *arg) { - Py_ssize_t result; - NULLABLE(arg); - result = PyUnicode_GetLength(arg); - if (result == -1) - return NULL; - return PyLong_FromSsize_t(result); + RETURN_SIZE(PyUnicode_GetLength(arg)); } /* Test PyUnicode_ReadChar() */ @@ -482,16 +477,12 @@ static PyObject * unicode_aswidechar_null(PyObject *self, PyObject *args) { PyObject *unicode; - Py_ssize_t buflen, size; + Py_ssize_t buflen; if (!PyArg_ParseTuple(args, "On", &unicode, &buflen)) return NULL; NULLABLE(unicode); - size = PyUnicode_AsWideChar(unicode, NULL, buflen); - if (size == -1) { - return NULL; - } - return PyLong_FromSsize_t(size); + RETURN_SIZE(PyUnicode_AsWideChar(unicode, NULL, buflen)); } /* Test PyUnicode_AsWideCharString() */ @@ -1293,17 +1284,13 @@ unicode_count(PyObject *self, PyObject *args) PyObject *substr; Py_ssize_t start; Py_ssize_t end; - Py_ssize_t result; if (!PyArg_ParseTuple(args, "OOnn", &str, &substr, &start, &end)) return NULL; NULLABLE(str); NULLABLE(substr); - result = PyUnicode_Count(str, substr, start, end); - if (result == -1) - return NULL; - return PyLong_FromSsize_t(result); + RETURN_SIZE(PyUnicode_Count(str, substr, start, end)); } /* Test PyUnicode_Find() */ @@ -1323,8 +1310,11 @@ unicode_find(PyObject *self, PyObject *args) NULLABLE(str); NULLABLE(substr); result = PyUnicode_Find(str, substr, start, end, direction); - if (result == -2) + if (result == -2) { + assert(PyErr_Occurred()); return NULL; + } + assert(!PyErr_Occurred()); return PyLong_FromSsize_t(result); } @@ -1337,17 +1327,13 @@ unicode_tailmatch(PyObject *self, PyObject *args) Py_ssize_t start; Py_ssize_t end; int direction; - Py_ssize_t result; if (!PyArg_ParseTuple(args, "OOnni", &str, &substr, &start, &end, &direction)) return NULL; NULLABLE(str); NULLABLE(substr); - result = PyUnicode_Tailmatch(str, substr, start, end, direction); - if (result == -1) - return NULL; - return PyLong_FromSsize_t(result); + RETURN_SIZE(PyUnicode_Tailmatch(str, substr, start, end, direction)); } /* Test PyUnicode_FindChar() */ @@ -1366,10 +1352,12 @@ unicode_findchar(PyObject *self, PyObject *args) } NULLABLE(str); result = PyUnicode_FindChar(str, (Py_UCS4)ch, start, end, direction); - if (result == -2) + if (result == -2) { + assert(PyErr_Occurred()); return NULL; - else - return PyLong_FromSsize_t(result); + } + assert(!PyErr_Occurred()); + return PyLong_FromSsize_t(result); } /* Test PyUnicode_Replace() */ @@ -1407,6 +1395,7 @@ unicode_compare(PyObject *self, PyObject *args) if (result == -1 && PyErr_Occurred()) { return NULL; } + assert(!PyErr_Occurred()); return PyLong_FromLong(result); } @@ -1467,32 +1456,21 @@ unicode_contains(PyObject *self, PyObject *args) { PyObject *container; PyObject *element; - int result; if (!PyArg_ParseTuple(args, "OO", &container, &element)) return NULL; NULLABLE(container); NULLABLE(element); - result = PyUnicode_Contains(container, element); - if (result == -1 && PyErr_Occurred()) { - return NULL; - } - return PyLong_FromLong(result); + RETURN_INT(PyUnicode_Contains(container, element)); } /* Test PyUnicode_IsIdentifier() */ static PyObject * unicode_isidentifier(PyObject *self, PyObject *arg) { - int result; - NULLABLE(arg); - result = PyUnicode_IsIdentifier(arg); - if (result == -1 && PyErr_Occurred()) { - return NULL; - } - return PyLong_FromLong(result); + RETURN_INT(PyUnicode_IsIdentifier(arg)); } /* Test PyUnicode_CopyCharacters() */ diff --git a/Modules/_testcapi/util.h b/Modules/_testcapi/util.h new file mode 100644 index 00000000000000..05ccb12a4444f8 --- /dev/null +++ b/Modules/_testcapi/util.h @@ -0,0 +1,25 @@ +#define NULLABLE(x) do { \ + if (x == Py_None) { \ + x = NULL; \ + } \ + } while (0); + +#define RETURN_INT(value) do { \ + int _ret = (value); \ + if (_ret == -1) { \ + assert(PyErr_Occurred()); \ + return NULL; \ + } \ + assert(!PyErr_Occurred()); \ + return PyLong_FromLong(_ret); \ + } while (0) + +#define RETURN_SIZE(value) do { \ + Py_ssize_t _ret = (value); \ + if (_ret == -1) { \ + assert(PyErr_Occurred()); \ + return NULL; \ + } \ + assert(!PyErr_Occurred()); \ + return PyLong_FromSsize_t(_ret); \ + } while (0) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index f8b36ff9ce835a..ab33702cdfd872 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -24,9 +24,6 @@ #include // FLT_MAX #include #include // offsetof() -#ifndef MS_WINDOWS -# include -#endif #ifdef HAVE_SYS_WAIT_H # include // W_STOPCODE @@ -43,16 +40,8 @@ // Several parts of this module are broken out into files in _testcapi/. // Include definitions from there. #include "_testcapi/parts.h" +#include "_testcapi/util.h" -#define NULLABLE(x) do { if (x == Py_None) x = NULL; } while (0); - -#define RETURN_INT(value) do { \ - int _ret = (value); \ - if (_ret == -1) { \ - return NULL; \ - } \ - return PyLong_FromLong(_ret); \ - } while (0) // Forward declarations static struct PyModuleDef _testcapimodule; @@ -1333,19 +1322,13 @@ static PyObject * test_PyBuffer_SizeFromFormat(PyObject *self, PyObject *args) { const char *format; - Py_ssize_t result; if (!PyArg_ParseTuple(args, "s:test_PyBuffer_SizeFromFormat", &format)) { return NULL; } - result = PyBuffer_SizeFromFormat(format); - if (result == -1) { - return NULL; - } - - return PyLong_FromSsize_t(result); + RETURN_SIZE(PyBuffer_SizeFromFormat(format)); } /* Test that the fatal error from not having a current thread doesn't diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index e375ca8556d217..96d568294a9710 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -33,9 +33,8 @@ #include "clinic/_testinternalcapi.c.h" -#ifdef MS_WINDOWS -# include // struct timeval -#endif +// Include test definitions from _testinternalcapi/ +#include "_testinternalcapi/parts.h" #define MODULE_NAME "_testinternalcapi" @@ -1123,250 +1122,6 @@ pending_identify(PyObject *self, PyObject *args) return res; } - -static PyObject * -test_pytime_fromseconds(PyObject *self, PyObject *args) -{ - int seconds; - if (!PyArg_ParseTuple(args, "i", &seconds)) { - return NULL; - } - _PyTime_t ts = _PyTime_FromSeconds(seconds); - return _PyTime_AsNanosecondsObject(ts); -} - -static int -check_time_rounding(int round) -{ - if (round != _PyTime_ROUND_FLOOR - && round != _PyTime_ROUND_CEILING - && round != _PyTime_ROUND_HALF_EVEN - && round != _PyTime_ROUND_UP) - { - PyErr_SetString(PyExc_ValueError, "invalid rounding"); - return -1; - } - return 0; -} - -static PyObject * -test_pytime_fromsecondsobject(PyObject *self, PyObject *args) -{ - PyObject *obj; - int round; - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { - return NULL; - } - if (check_time_rounding(round) < 0) { - return NULL; - } - _PyTime_t ts; - if (_PyTime_FromSecondsObject(&ts, obj, round) == -1) { - return NULL; - } - return _PyTime_AsNanosecondsObject(ts); -} - -static PyObject * -test_pytime_assecondsdouble(PyObject *self, PyObject *args) -{ - PyObject *obj; - if (!PyArg_ParseTuple(args, "O", &obj)) { - return NULL; - } - _PyTime_t ts; - if (_PyTime_FromNanosecondsObject(&ts, obj) < 0) { - return NULL; - } - double d = _PyTime_AsSecondsDouble(ts); - return PyFloat_FromDouble(d); -} - -static PyObject * -test_PyTime_AsTimeval(PyObject *self, PyObject *args) -{ - PyObject *obj; - int round; - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { - return NULL; - } - if (check_time_rounding(round) < 0) { - return NULL; - } - _PyTime_t t; - if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { - return NULL; - } - struct timeval tv; - if (_PyTime_AsTimeval(t, &tv, round) < 0) { - return NULL; - } - - PyObject *seconds = PyLong_FromLongLong(tv.tv_sec); - if (seconds == NULL) { - return NULL; - } - return Py_BuildValue("Nl", seconds, (long)tv.tv_usec); -} - -static PyObject * -test_PyTime_AsTimeval_clamp(PyObject *self, PyObject *args) -{ - PyObject *obj; - int round; - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { - return NULL; - } - if (check_time_rounding(round) < 0) { - return NULL; - } - _PyTime_t t; - if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { - return NULL; - } - struct timeval tv; - _PyTime_AsTimeval_clamp(t, &tv, round); - - PyObject *seconds = PyLong_FromLongLong(tv.tv_sec); - if (seconds == NULL) { - return NULL; - } - return Py_BuildValue("Nl", seconds, (long)tv.tv_usec); -} - -#ifdef HAVE_CLOCK_GETTIME -static PyObject * -test_PyTime_AsTimespec(PyObject *self, PyObject *args) -{ - PyObject *obj; - if (!PyArg_ParseTuple(args, "O", &obj)) { - return NULL; - } - _PyTime_t t; - if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { - return NULL; - } - struct timespec ts; - if (_PyTime_AsTimespec(t, &ts) == -1) { - return NULL; - } - return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec); -} - -static PyObject * -test_PyTime_AsTimespec_clamp(PyObject *self, PyObject *args) -{ - PyObject *obj; - if (!PyArg_ParseTuple(args, "O", &obj)) { - return NULL; - } - _PyTime_t t; - if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { - return NULL; - } - struct timespec ts; - _PyTime_AsTimespec_clamp(t, &ts); - return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec); -} -#endif - -static PyObject * -test_PyTime_AsMilliseconds(PyObject *self, PyObject *args) -{ - PyObject *obj; - int round; - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { - return NULL; - } - _PyTime_t t; - if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { - return NULL; - } - if (check_time_rounding(round) < 0) { - return NULL; - } - _PyTime_t ms = _PyTime_AsMilliseconds(t, round); - _PyTime_t ns = _PyTime_FromNanoseconds(ms); - return _PyTime_AsNanosecondsObject(ns); -} - -static PyObject * -test_PyTime_AsMicroseconds(PyObject *self, PyObject *args) -{ - PyObject *obj; - int round; - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { - return NULL; - } - _PyTime_t t; - if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { - return NULL; - } - if (check_time_rounding(round) < 0) { - return NULL; - } - _PyTime_t us = _PyTime_AsMicroseconds(t, round); - _PyTime_t ns = _PyTime_FromNanoseconds(us); - return _PyTime_AsNanosecondsObject(ns); -} - -static PyObject * -test_pytime_object_to_time_t(PyObject *self, PyObject *args) -{ - PyObject *obj; - time_t sec; - int round; - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { - return NULL; - } - if (check_time_rounding(round) < 0) { - return NULL; - } - if (_PyTime_ObjectToTime_t(obj, &sec, round) == -1) { - return NULL; - } - return _PyLong_FromTime_t(sec); -} - -static PyObject * -test_pytime_object_to_timeval(PyObject *self, PyObject *args) -{ - PyObject *obj; - time_t sec; - long usec; - int round; - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { - return NULL; - } - if (check_time_rounding(round) < 0) { - return NULL; - } - if (_PyTime_ObjectToTimeval(obj, &sec, &usec, round) == -1) { - return NULL; - } - return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), usec); -} - -static PyObject * -test_pytime_object_to_timespec(PyObject *self, PyObject *args) -{ - PyObject *obj; - time_t sec; - long nsec; - int round; - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { - return NULL; - } - if (check_time_rounding(round) < 0) { - return NULL; - } - if (_PyTime_ObjectToTimespec(obj, &sec, &nsec, round) == -1) { - return NULL; - } - return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), nsec); -} - - static PyObject * tracemalloc_get_traceback(PyObject *self, PyObject *args) { @@ -1731,20 +1486,6 @@ static PyMethodDef module_functions[] = { {"pending_threadfunc", _PyCFunction_CAST(pending_threadfunc), METH_VARARGS | METH_KEYWORDS}, {"pending_identify", pending_identify, METH_VARARGS, NULL}, - {"_PyTime_AsMicroseconds", test_PyTime_AsMicroseconds, METH_VARARGS}, - {"_PyTime_AsMilliseconds", test_PyTime_AsMilliseconds, METH_VARARGS}, - {"_PyTime_AsSecondsDouble", test_pytime_assecondsdouble, METH_VARARGS}, -#ifdef HAVE_CLOCK_GETTIME - {"_PyTime_AsTimespec", test_PyTime_AsTimespec, METH_VARARGS}, - {"_PyTime_AsTimespec_clamp", test_PyTime_AsTimespec_clamp, METH_VARARGS}, -#endif - {"_PyTime_AsTimeval", test_PyTime_AsTimeval, METH_VARARGS}, - {"_PyTime_AsTimeval_clamp", test_PyTime_AsTimeval_clamp, METH_VARARGS}, - {"_PyTime_FromSeconds", test_pytime_fromseconds, METH_VARARGS}, - {"_PyTime_FromSecondsObject", test_pytime_fromsecondsobject, METH_VARARGS}, - {"_PyTime_ObjectToTime_t", test_pytime_object_to_time_t, METH_VARARGS}, - {"_PyTime_ObjectToTimespec", test_pytime_object_to_timespec, METH_VARARGS}, - {"_PyTime_ObjectToTimeval", test_pytime_object_to_timeval, METH_VARARGS}, {"_PyTraceMalloc_GetTraceback", tracemalloc_get_traceback, METH_VARARGS}, {"test_tstate_capi", test_tstate_capi, METH_NOARGS, NULL}, {"_PyUnicode_TransformDecimalAndSpaceToASCII", unicode_transformdecimalandspacetoascii, METH_O}, @@ -1771,6 +1512,10 @@ static PyMethodDef module_functions[] = { static int module_exec(PyObject *module) { + if (_PyTestInternalCapi_Init_PyTime(module) < 0) { + return 1; + } + if (PyModule_Add(module, "SIZEOF_PYGC_HEAD", PyLong_FromSsize_t(sizeof(PyGC_Head))) < 0) { return 1; diff --git a/Modules/_testinternalcapi/README.txt b/Modules/_testinternalcapi/README.txt new file mode 100644 index 00000000000000..eb071135e4c592 --- /dev/null +++ b/Modules/_testinternalcapi/README.txt @@ -0,0 +1,5 @@ +Tests in this directory are compiled into the _testinternalcapi extension. +The main file for the extension is Modules/_testinternalcapimodule.c, which +calls `_PyTestInternalCapi_Init_*` from these functions. + +See Modules/_testcapi/README.txt for guideline when writing C test code. \ No newline at end of file diff --git a/Modules/_testinternalcapi/parts.h b/Modules/_testinternalcapi/parts.h new file mode 100644 index 00000000000000..43e7714b235156 --- /dev/null +++ b/Modules/_testinternalcapi/parts.h @@ -0,0 +1,15 @@ +#ifndef Py_TESTINTERNALCAPI_PARTS_H +#define Py_TESTINTERNALCAPI_PARTS_H + +// Always enable assertions +#undef NDEBUG + +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + +#include "Python.h" + +int _PyTestInternalCapi_Init_PyTime(PyObject *module); + +#endif // Py_TESTINTERNALCAPI_PARTS_H diff --git a/Modules/_testinternalcapi/pytime.c b/Modules/_testinternalcapi/pytime.c new file mode 100644 index 00000000000000..2b5f9eb0ef2851 --- /dev/null +++ b/Modules/_testinternalcapi/pytime.c @@ -0,0 +1,279 @@ +/* Test pycore_time.h */ + +#include "parts.h" + +#include "pycore_time.h" + +#ifdef MS_WINDOWS +# include // struct timeval +#endif + + +static PyObject * +test_pytime_fromseconds(PyObject *self, PyObject *args) +{ + int seconds; + if (!PyArg_ParseTuple(args, "i", &seconds)) { + return NULL; + } + _PyTime_t ts = _PyTime_FromSeconds(seconds); + return _PyTime_AsNanosecondsObject(ts); +} + +static int +check_time_rounding(int round) +{ + if (round != _PyTime_ROUND_FLOOR + && round != _PyTime_ROUND_CEILING + && round != _PyTime_ROUND_HALF_EVEN + && round != _PyTime_ROUND_UP) + { + PyErr_SetString(PyExc_ValueError, "invalid rounding"); + return -1; + } + return 0; +} + +static PyObject * +test_pytime_fromsecondsobject(PyObject *self, PyObject *args) +{ + PyObject *obj; + int round; + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { + return NULL; + } + if (check_time_rounding(round) < 0) { + return NULL; + } + _PyTime_t ts; + if (_PyTime_FromSecondsObject(&ts, obj, round) == -1) { + return NULL; + } + return _PyTime_AsNanosecondsObject(ts); +} + +static PyObject * +test_pytime_assecondsdouble(PyObject *self, PyObject *args) +{ + PyObject *obj; + if (!PyArg_ParseTuple(args, "O", &obj)) { + return NULL; + } + _PyTime_t ts; + if (_PyTime_FromNanosecondsObject(&ts, obj) < 0) { + return NULL; + } + double d = _PyTime_AsSecondsDouble(ts); + return PyFloat_FromDouble(d); +} + +static PyObject * +test_PyTime_AsTimeval(PyObject *self, PyObject *args) +{ + PyObject *obj; + int round; + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { + return NULL; + } + if (check_time_rounding(round) < 0) { + return NULL; + } + _PyTime_t t; + if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { + return NULL; + } + struct timeval tv; + if (_PyTime_AsTimeval(t, &tv, round) < 0) { + return NULL; + } + + PyObject *seconds = PyLong_FromLongLong(tv.tv_sec); + if (seconds == NULL) { + return NULL; + } + return Py_BuildValue("Nl", seconds, (long)tv.tv_usec); +} + +static PyObject * +test_PyTime_AsTimeval_clamp(PyObject *self, PyObject *args) +{ + PyObject *obj; + int round; + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { + return NULL; + } + if (check_time_rounding(round) < 0) { + return NULL; + } + _PyTime_t t; + if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { + return NULL; + } + struct timeval tv; + _PyTime_AsTimeval_clamp(t, &tv, round); + + PyObject *seconds = PyLong_FromLongLong(tv.tv_sec); + if (seconds == NULL) { + return NULL; + } + return Py_BuildValue("Nl", seconds, (long)tv.tv_usec); +} + +#ifdef HAVE_CLOCK_GETTIME +static PyObject * +test_PyTime_AsTimespec(PyObject *self, PyObject *args) +{ + PyObject *obj; + if (!PyArg_ParseTuple(args, "O", &obj)) { + return NULL; + } + _PyTime_t t; + if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { + return NULL; + } + struct timespec ts; + if (_PyTime_AsTimespec(t, &ts) == -1) { + return NULL; + } + return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec); +} + +static PyObject * +test_PyTime_AsTimespec_clamp(PyObject *self, PyObject *args) +{ + PyObject *obj; + if (!PyArg_ParseTuple(args, "O", &obj)) { + return NULL; + } + _PyTime_t t; + if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { + return NULL; + } + struct timespec ts; + _PyTime_AsTimespec_clamp(t, &ts); + return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec); +} +#endif + +static PyObject * +test_PyTime_AsMilliseconds(PyObject *self, PyObject *args) +{ + PyObject *obj; + int round; + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { + return NULL; + } + _PyTime_t t; + if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { + return NULL; + } + if (check_time_rounding(round) < 0) { + return NULL; + } + _PyTime_t ms = _PyTime_AsMilliseconds(t, round); + _PyTime_t ns = _PyTime_FromNanoseconds(ms); + return _PyTime_AsNanosecondsObject(ns); +} + +static PyObject * +test_PyTime_AsMicroseconds(PyObject *self, PyObject *args) +{ + PyObject *obj; + int round; + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { + return NULL; + } + _PyTime_t t; + if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { + return NULL; + } + if (check_time_rounding(round) < 0) { + return NULL; + } + _PyTime_t us = _PyTime_AsMicroseconds(t, round); + _PyTime_t ns = _PyTime_FromNanoseconds(us); + return _PyTime_AsNanosecondsObject(ns); +} + +static PyObject * +test_pytime_object_to_time_t(PyObject *self, PyObject *args) +{ + PyObject *obj; + time_t sec; + int round; + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { + return NULL; + } + if (check_time_rounding(round) < 0) { + return NULL; + } + if (_PyTime_ObjectToTime_t(obj, &sec, round) == -1) { + return NULL; + } + return _PyLong_FromTime_t(sec); +} + +static PyObject * +test_pytime_object_to_timeval(PyObject *self, PyObject *args) +{ + PyObject *obj; + time_t sec; + long usec; + int round; + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { + return NULL; + } + if (check_time_rounding(round) < 0) { + return NULL; + } + if (_PyTime_ObjectToTimeval(obj, &sec, &usec, round) == -1) { + return NULL; + } + return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), usec); +} + +static PyObject * +test_pytime_object_to_timespec(PyObject *self, PyObject *args) +{ + PyObject *obj; + time_t sec; + long nsec; + int round; + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { + return NULL; + } + if (check_time_rounding(round) < 0) { + return NULL; + } + if (_PyTime_ObjectToTimespec(obj, &sec, &nsec, round) == -1) { + return NULL; + } + return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), nsec); +} + +static PyMethodDef TestMethods[] = { + {"_PyTime_AsMicroseconds", test_PyTime_AsMicroseconds, METH_VARARGS}, + {"_PyTime_AsMilliseconds", test_PyTime_AsMilliseconds, METH_VARARGS}, + {"_PyTime_AsSecondsDouble", test_pytime_assecondsdouble, METH_VARARGS}, +#ifdef HAVE_CLOCK_GETTIME + {"_PyTime_AsTimespec", test_PyTime_AsTimespec, METH_VARARGS}, + {"_PyTime_AsTimespec_clamp", test_PyTime_AsTimespec_clamp, METH_VARARGS}, +#endif + {"_PyTime_AsTimeval", test_PyTime_AsTimeval, METH_VARARGS}, + {"_PyTime_AsTimeval_clamp", test_PyTime_AsTimeval_clamp, METH_VARARGS}, + {"_PyTime_FromSeconds", test_pytime_fromseconds, METH_VARARGS}, + {"_PyTime_FromSecondsObject", test_pytime_fromsecondsobject, METH_VARARGS}, + {"_PyTime_ObjectToTime_t", test_pytime_object_to_time_t, METH_VARARGS}, + {"_PyTime_ObjectToTimespec", test_pytime_object_to_timespec, METH_VARARGS}, + {"_PyTime_ObjectToTimeval", test_pytime_object_to_timeval, METH_VARARGS}, + {NULL, NULL} /* sentinel */ +}; + +int +_PyTestInternalCapi_Init_PyTime(PyObject *m) +{ + if (PyModule_AddFunctions(m, TestMethods) < 0) { + return -1; + } + return 0; +} diff --git a/Modules/grpmodule.c b/Modules/grpmodule.c index f5709296334a8f..20e83de84e8340 100644 --- a/Modules/grpmodule.c +++ b/Modules/grpmodule.c @@ -4,7 +4,8 @@ #include "Python.h" #include "posixmodule.h" -#include +#include // getgrgid_r() +#include // sysconf() #include "clinic/grpmodule.c.h" /*[clinic input] diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index c8cd7e59dbab50..d11200a4042551 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -28,6 +28,9 @@ #include "pycore_fileutils.h" // _Py_stat_struct #include // offsetof() +#ifndef MS_WINDOWS +# include // close() +#endif // to support MS_WINDOWS_SYSTEM OpenFileMappingA / CreateFileMappingA // need to be replaced with OpenFileMappingW / CreateFileMappingW diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 0436571abc9054..b4c502bef50ba9 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -57,6 +57,17 @@ #include // ctermid() #include // system() +#ifdef HAVE_SYS_TIME_H +# include // futimes() +#endif + + +// SGI apparently needs this forward declaration +#ifdef HAVE__GETPTY +# include // mode_t + extern char * _getpty(int *, int, mode_t, int); +#endif + /* * A number of APIs are available on macOS from a certain macOS version. @@ -279,7 +290,7 @@ corresponding Unix manual entries for more information on calls."); #endif #ifdef HAVE_COPY_FILE_RANGE -# include +# include // copy_file_range() #endif #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY) diff --git a/Modules/pwdmodule.c b/Modules/pwdmodule.c index cc2e2a43893971..b7034369c4731e 100644 --- a/Modules/pwdmodule.c +++ b/Modules/pwdmodule.c @@ -4,7 +4,8 @@ #include "Python.h" #include "posixmodule.h" -#include +#include // getpwuid() +#include // sysconf() #include "clinic/pwdmodule.c.h" /*[clinic input] diff --git a/Modules/readline.c b/Modules/readline.c index 2531b236b6ef17..aeae654162f13f 100644 --- a/Modules/readline.c +++ b/Modules/readline.c @@ -12,14 +12,13 @@ #include "Python.h" #include "pycore_pylifecycle.h" // _Py_SetLocaleFromEnv() -#include -#include -#include +#include // errno +#include // SIGWINCH #include // free() -#ifdef HAVE_SYS_TIME_H -#include +#include // strdup() +#ifdef HAVE_SYS_SELECT_H +# include // select() #endif -#include #if defined(HAVE_SETLOCALE) /* GNU readline() mistakenly sets the LC_CTYPE locale. @@ -27,7 +26,7 @@ * We must save and restore the locale around the rl_initialize() call. */ #define SAVE_LOCALE -#include +# include // setlocale() #endif #ifdef SAVE_LOCALE @@ -1333,7 +1332,8 @@ readline_until_enter_or_signal(const char *prompt, int *signal) int has_input = 0, err = 0; while (!has_input) - { struct timeval timeout = {0, 100000}; /* 0.1 seconds */ + { + struct timeval timeout = {0, 100000}; // 100 ms (0.1 seconds) /* [Bug #1552726] Only limit the pause if an input hook has been defined. */ diff --git a/Modules/resource.c b/Modules/resource.c index 4614f5e98cc888..9e302a3a1ed962 100644 --- a/Modules/resource.c +++ b/Modules/resource.c @@ -1,13 +1,8 @@ - #include "Python.h" -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif -#include +#include // errno #include -#include -#include +#include // getrusage() +#include // getpagesize() /* On some systems, these aren't in any header file. On others they are, with inconsistent prototypes. diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index 4987cf0f2065c2..c56e682b21e2a1 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -17,6 +17,9 @@ #include "pycore_time.h" // _PyTime_t #include // offsetof() +#ifndef MS_WINDOWS +# include // close() +#endif #ifdef HAVE_SYS_DEVPOLL_H #include diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 3adb2e8dfe58d8..8d6556727b3a5a 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -16,10 +16,10 @@ #include "pycore_signal.h" // _Py_RestoreSignals() #ifndef MS_WINDOWS -# include "posixmodule.h" +# include "posixmodule.h" // _PyLong_FromUid() #endif #ifdef MS_WINDOWS -# include "socketmodule.h" /* needed for SOCKET_T */ +# include "socketmodule.h" // SOCKET_T #endif #ifdef MS_WINDOWS @@ -29,16 +29,16 @@ #endif #ifdef HAVE_SIGNAL_H -# include +# include // sigaction() #endif #ifdef HAVE_SYS_SYSCALL_H -# include +# include // __NR_pidfd_send_signal #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_SYS_TIME_H -# include +# include // setitimer() #endif #if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index e3681853dad095..74b1c1c661604f 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -111,9 +111,13 @@ Local naming conventions: #include "pycore_fileutils.h" // _Py_set_inheritable() #include "pycore_moduleobject.h" // _PyModule_GetState +// gethostname() prototype missing from Solaris standard header files +#ifdef __sun +extern int gethostname(char *, int); +#endif #ifdef _Py_MEMORY_SANITIZER -# include +# include #endif /* Socket object documentation */ @@ -265,7 +269,7 @@ shutdown(how) -- shut down traffic in one or both directions\n\ #ifdef HAVE_NETDB_H # include #endif -# include +#include // close() /* Headers needed for inet_ntoa() and inet_addr() */ # include diff --git a/Modules/termios.c b/Modules/termios.c index 21d3541c177bc3..a0613837ef9795 100644 --- a/Modules/termios.c +++ b/Modules/termios.c @@ -6,10 +6,17 @@ #include "Python.h" -/* Apparently, on SGI, termios.h won't define CTRL if _XOPEN_SOURCE - is defined, so we define it here. */ +// On QNX 6, struct termio must be declared by including sys/termio.h +// if TCGETA, TCSETA, TCSETAW, or TCSETAF are used. sys/termio.h must +// be included before termios.h or it will generate an error. +#if defined(HAVE_SYS_TERMIO_H) && !defined(__hpux) +# include +#endif + +// Apparently, on SGI, termios.h won't define CTRL if _XOPEN_SOURCE +// is defined, so we define it here. #if defined(__sgi) -#define CTRL(c) ((c)&037) +# define CTRL(c) ((c)&037) #endif #if defined(__sun) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 68948b6be1a61a..4e55da71b117ca 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -7,7 +7,7 @@ #include "pycore_runtime.h" // _Py_ID() #include - +#include // clock() #ifdef HAVE_SYS_TIMES_H # include #endif diff --git a/Modules/xxsubtype.c b/Modules/xxsubtype.c index 63b22268c597b6..560f43e5b3a643 100644 --- a/Modules/xxsubtype.c +++ b/Modules/xxsubtype.c @@ -1,5 +1,7 @@ #include "Python.h" + #include // offsetof() +#include // clock() PyDoc_STRVAR(xxsubtype__doc__, diff --git a/PCbuild/_testinternalcapi.vcxproj b/PCbuild/_testinternalcapi.vcxproj index 6c5b12cd40e983..59491c644b6655 100644 --- a/PCbuild/_testinternalcapi.vcxproj +++ b/PCbuild/_testinternalcapi.vcxproj @@ -94,6 +94,7 @@ + diff --git a/PCbuild/_testinternalcapi.vcxproj.filters b/PCbuild/_testinternalcapi.vcxproj.filters index 7734da0b7b426b..21a66a2aa79f76 100644 --- a/PCbuild/_testinternalcapi.vcxproj.filters +++ b/PCbuild/_testinternalcapi.vcxproj.filters @@ -12,6 +12,9 @@ Source Files + + Source Files + diff --git a/Programs/_freeze_module.c b/Programs/_freeze_module.c index e55f1d56745c4d..f6c46fa629efba 100644 --- a/Programs/_freeze_module.c +++ b/Programs/_freeze_module.c @@ -19,7 +19,7 @@ #include #include #ifndef MS_WINDOWS -#include +# include #endif uint32_t _Py_next_func_version = 1; diff --git a/Python/dup2.c b/Python/dup2.c index a1df0492099163..936211f27ec737 100644 --- a/Python/dup2.c +++ b/Python/dup2.c @@ -11,9 +11,9 @@ * Return fd2 if all went well; return BADEXIT otherwise. */ -#include -#include -#include +#include // errno +#include // fcntl() +#include // close() #define BADEXIT -1 diff --git a/Python/perf_trampoline.c b/Python/perf_trampoline.c index b8885a303977d0..10675bf9f8292a 100644 --- a/Python/perf_trampoline.c +++ b/Python/perf_trampoline.c @@ -140,9 +140,9 @@ any DWARF information available for them). #include #include #include -#include +#include // mmap() #include -#include +#include // sysconf() #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) #define PY_HAVE_INVALIDATE_ICACHE diff --git a/Python/pytime.c b/Python/pytime.c index 49cd5f4e8ea617..d1e29e57d362f6 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -1,5 +1,10 @@ #include "Python.h" #include "pycore_time.h" // _PyTime_t + +#include // gmtime_r() +#ifdef HAVE_SYS_TIME_H +# include // gettimeofday() +#endif #ifdef MS_WINDOWS # include // struct timeval #endif diff --git a/configure b/configure index 7fe4aead29a732..d73b4b271ac719 100755 --- a/configure +++ b/configure @@ -10325,12 +10325,6 @@ if test "x$ac_cv_header_grp_h" = xyes then : printf "%s\n" "#define HAVE_GRP_H 1" >>confdefs.h -fi -ac_fn_c_check_header_compile "$LINENO" "ieeefp.h" "ac_cv_header_ieeefp_h" "$ac_includes_default" -if test "x$ac_cv_header_ieeefp_h" = xyes -then : - printf "%s\n" "#define HAVE_IEEEFP_H 1" >>confdefs.h - fi ac_fn_c_check_header_compile "$LINENO" "io.h" "ac_cv_header_io_h" "$ac_includes_default" if test "x$ac_cv_header_io_h" = xyes @@ -26553,6 +26547,7 @@ SRCDIRS="\ Modules/_sqlite \ Modules/_sre \ Modules/_testcapi \ + Modules/_testinternalcapi \ Modules/_xxtestfuzz \ Modules/cjkcodecs \ Modules/expat \ diff --git a/configure.ac b/configure.ac index 5673b374353b47..612c072af329d4 100644 --- a/configure.ac +++ b/configure.ac @@ -2667,7 +2667,7 @@ AC_DEFINE([STDC_HEADERS], [1], # checks for header files AC_CHECK_HEADERS([ \ alloca.h asm/types.h bluetooth.h conio.h direct.h dlfcn.h endian.h errno.h fcntl.h grp.h \ - ieeefp.h io.h langinfo.h libintl.h libutil.h linux/auxvec.h sys/auxv.h linux/fs.h linux/limits.h linux/memfd.h \ + io.h langinfo.h libintl.h libutil.h linux/auxvec.h sys/auxv.h linux/fs.h linux/limits.h linux/memfd.h \ linux/random.h linux/soundcard.h \ linux/tipc.h linux/wait.h netdb.h net/ethernet.h netinet/in.h netpacket/packet.h poll.h process.h pthread.h pty.h \ sched.h setjmp.h shadow.h signal.h spawn.h stropts.h sys/audioio.h sys/bsdtty.h sys/devpoll.h \ @@ -6470,6 +6470,7 @@ SRCDIRS="\ Modules/_sqlite \ Modules/_sre \ Modules/_testcapi \ + Modules/_testinternalcapi \ Modules/_xxtestfuzz \ Modules/cjkcodecs \ Modules/expat \ diff --git a/pyconfig.h.in b/pyconfig.h.in index 418ccade8e8bb1..86c72cc6b4e62a 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -607,9 +607,6 @@ /* Define this if you have le64toh() */ #undef HAVE_HTOLE64 -/* Define to 1 if you have the header file. */ -#undef HAVE_IEEEFP_H - /* Define to 1 if you have the `if_nameindex' function. */ #undef HAVE_IF_NAMEINDEX