diff --git a/.gitattributes b/.gitattributes index fb11ddb6dfae18e6462c18eca79b53e024b4ef06..79f7b712aa459e76f8b007a25a511d2dc4156c90 100644 --- a/.gitattributes +++ b/.gitattributes @@ -28,8 +28,8 @@ Lib/test/cjkencodings/* noeol Lib/test/coding20731.py noeol Lib/test/decimaltestdata/*.decTest noeol Lib/test/test_email/data/*.txt noeol -Lib/test/test_importlib/data01/* noeol -Lib/test/test_importlib/namespacedata01/* noeol +Lib/test/test_importlib/resources/data01/* noeol +Lib/test/test_importlib/resources/namespacedata01/* noeol Lib/test/xmltestdata/* noeol # CRLF files diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 013e1cbd7241d5d9e69e80bf0ff993ee646af344..df79aa6503e0cf43e438f77270731eeeb84c96bd 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -61,7 +61,7 @@ Python/pythonrun.c @iritkatriel # bytecode. **/*import*.c @brettcannon @encukou @ericsnowcurrently @ncoghlan @warsaw **/*import*.py @brettcannon @encukou @ericsnowcurrently @ncoghlan @warsaw -**/importlib/resources/* @jaraco @warsaw @brettcannon +**/*importlib/resources/* @jaraco @warsaw @brettcannon **/importlib/metadata/* @jaraco @warsaw # Dates and times diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index 7bdca2112b287b9929357d5713f47eca51529642..1d93e0735e50f33a73e96df998745f51b7140157 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -15,12 +15,12 @@ your problem has already been reported --> -**Bug report** +# Bug report A clear and concise description of what the bug is. Include a minimal, reproducible example (https://stackoverflow.com/help/minimal-reproducible-example), if possible. -**Your environment** +# Your environment <!-- Include as many relevant details as possible about the environment you experienced the bug in --> diff --git a/.github/ISSUE_TEMPLATE/crash.md b/.github/ISSUE_TEMPLATE/crash.md index 28d7bfec193814fc35c75ed3e5d387146fc9fb71..dad3423db03410f65eca1c7ca4e2929c3a4a73e5 100644 --- a/.github/ISSUE_TEMPLATE/crash.md +++ b/.github/ISSUE_TEMPLATE/crash.md @@ -13,15 +13,15 @@ For CPython, a "crash" is when Python itself fails, leading to a traceback in the C stack. --> -**Crash report** +# Crash report Tell us what happened, ideally including a minimal, reproducible example (https://stackoverflow.com/help/minimal-reproducible-example). -**Error messages** +# Error messages Enter any relevant error message caused by the crash, including a core dump if there is one. -**Your environment** +# Your environment <!-- Include as many relevant details as possible about the environment you experienced the bug in --> diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md index 669c92adb475318628e051da4cc9105a689924d4..174fd39171d47dd24806f13c1e76a38b3f1c9f90 100644 --- a/.github/ISSUE_TEMPLATE/documentation.md +++ b/.github/ISSUE_TEMPLATE/documentation.md @@ -4,6 +4,6 @@ labels: "docs" --- -**Documentation** +# Documentation (A clear and concise description of the issue.) diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md index 635ea43545f4971e8f50d609da1698300b0619ca..ed051e945f81207acaf501c5d8d620746fb819b8 100644 --- a/.github/ISSUE_TEMPLATE/feature.md +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -4,16 +4,16 @@ labels: "type-feature" --- -**Feature or enhancement** +# Feature or enhancement (A clear and concise description of your proposal.) -**Pitch** +# Pitch (Explain why this feature or enhancement should be implemented and how it would be used. Add examples, if applicable.) -**Previous discussion** +# Previous discussion <!-- New features to Python should first be discussed elsewhere before creating issues on GitHub, diff --git a/Doc/c-api/datetime.rst b/Doc/c-api/datetime.rst index 4c4e4bcfa63335ae217b8a6a908f0af6667b571e..72fc07afbf1f4db9fccf24b4de748365e90bd615 100644 --- a/Doc/c-api/datetime.rst +++ b/Doc/c-api/datetime.rst @@ -132,6 +132,7 @@ Macros to create objects: resulting number of microseconds and seconds lie in the ranges documented for :class:`datetime.timedelta` objects. + .. c:function:: PyObject* PyTimeZone_FromOffset(PyDateTime_DeltaType* offset) Return a :class:`datetime.timezone` object with an unnamed fixed offset @@ -139,6 +140,7 @@ Macros to create objects: .. versionadded:: 3.7 + .. c:function:: PyObject* PyTimeZone_FromOffsetAndName(PyDateTime_DeltaType* offset, PyUnicode* name) Return a :class:`datetime.timezone` object with a fixed offset represented @@ -190,12 +192,21 @@ must not be ``NULL``, and the type is not checked: Return the microsecond, as an int from 0 through 999999. + +.. c:function:: int PyDateTime_DATE_GET_FOLD(PyDateTime_DateTime *o) + + Return the fold, as an int from 0 through 1. + + .. versionadded:: 3.6 + + .. c:function:: PyObject* PyDateTime_DATE_GET_TZINFO(PyDateTime_DateTime *o) Return the tzinfo (which may be ``None``). .. versionadded:: 3.10 + Macros to extract fields from time objects. The argument must be an instance of :c:data:`PyDateTime_Time`, including subclasses. The argument must not be ``NULL``, and the type is not checked: @@ -219,6 +230,14 @@ and the type is not checked: Return the microsecond, as an int from 0 through 999999. + +.. c:function:: int PyDateTime_TIME_GET_FOLD(PyDateTime_Time *o) + + Return the fold, as an int from 0 through 1. + + .. versionadded:: 3.6 + + .. c:function:: PyObject* PyDateTime_TIME_GET_TZINFO(PyDateTime_Time *o) Return the tzinfo (which may be ``None``). diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst index 620344e71373b2a92694d696b49bfa7b1200af4d..56a7c069de908ecb8a4817d66b563371babeea1a 100644 --- a/Doc/c-api/long.rst +++ b/Doc/c-api/long.rst @@ -84,14 +84,15 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: PyObject* PyLong_FromString(const char *str, char **pend, int base) Return a new :c:type:`PyLongObject` based on the string value in *str*, which - is interpreted according to the radix in *base*. If *pend* is non-``NULL``, - *\*pend* will point to the first character in *str* which follows the - representation of the number. If *base* is ``0``, *str* is interpreted using - the :ref:`integers` definition; in this case, leading zeros in a - non-zero decimal number raises a :exc:`ValueError`. If *base* is not ``0``, - it must be between ``2`` and ``36``, inclusive. Leading spaces and single - underscores after a base specifier and between digits are ignored. If there - are no digits, :exc:`ValueError` will be raised. + is interpreted according to the radix in *base*, or ``NULL`` on failure. If + *pend* is non-``NULL``, *\*pend* will point to the end of *str* on success or + to the first character that could not be processed on error. If *base* is ``0``, + *str* is interpreted using the :ref:`integers` definition; in this case, leading + zeros in a non-zero decimal number raises a :exc:`ValueError`. If *base* is not + ``0``, it must be between ``2`` and ``36``, inclusive. Leading and trailing + whitespace and single underscores after a base specifier and between digits are + ignored. If there are no digits or *str* is not NULL-terminated following the + digits and trailing whitespace, :exc:`ValueError` will be raised. .. c:function:: PyObject* PyLong_FromUnicodeObject(PyObject *u, int base) diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index a331e9c188509261bfc28dd692ce4f6708ddbe09..7514801f2d4d59dd10158a59a526481df2b68d47 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1942,6 +1942,13 @@ and :c:type:`PyType_Type` effectively act as defaults.) Weak reference list head, for weak references to this type object. Not inherited. Internal use only. + .. versionchanged:: 3.12 + + Internals detail: For the static builtin types this is always ``NULL``, + even if weakrefs are added. Instead, the weakrefs for each are stored + on ``PyInterpreterState``. Use the public C-API or the internal + ``_PyObject_GET_WEAKREFS_LISTPTR()`` macro to avoid the distinction. + **Inheritance:** This field is not inherited. diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst index 5d420bfa93cb276129ebe8647d25d99d961a14ce..339ee35c7aa4747b1620c00d9a7112d7f9aa610c 100644 --- a/Doc/c-api/unicode.rst +++ b/Doc/c-api/unicode.rst @@ -819,7 +819,7 @@ wchar_t Support most C functions. If *size* is ``NULL`` and the :c:type:`wchar_t*` string contains null characters a :exc:`ValueError` is raised. - Returns a buffer allocated by :c:func:`PyMem_Alloc` (use + Returns a buffer allocated by :c:func:`PyMem_New` (use :c:func:`PyMem_Free` to free it) on success. On error, returns ``NULL`` and *\*size* is undefined. Raises a :exc:`MemoryError` if memory allocation is failed. diff --git a/Doc/contents.rst b/Doc/contents.rst index 8690de77bf3d82b94927322b5241561c3f73d5da..464f93bdf85f95b7c271c905e5f947256be03f02 100644 --- a/Doc/contents.rst +++ b/Doc/contents.rst @@ -27,5 +27,4 @@ .. toctree:: :hidden: - distutils/index.rst install/index.rst diff --git a/Doc/distributing/index.rst b/Doc/distributing/index.rst index 136cf4e77b15430505eb3a0c396d6e4ac17f18c1..2ae2726d4e4b92ae967192a60d3e79e42845588a 100644 --- a/Doc/distributing/index.rst +++ b/Doc/distributing/index.rst @@ -41,21 +41,21 @@ Key terms file format standards. They maintain a variety of tools, documentation and issue trackers on both `GitHub <https://github.com/pypa>`__ and `Bitbucket <https://bitbucket.org/pypa/>`__. -* :mod:`distutils` is the original build and distribution system first added - to the Python standard library in 1998. While direct use of :mod:`distutils` +* ``distutils`` is the original build and distribution system first added + to the Python standard library in 1998. While direct use of ``distutils`` is being phased out, it still laid the foundation for the current packaging and distribution infrastructure, and it not only remains part of the standard library, but its name lives on in other ways (such as the name of the mailing list used to coordinate Python packaging standards development). -* `setuptools`_ is a (largely) drop-in replacement for :mod:`distutils` first +* `setuptools`_ is a (largely) drop-in replacement for ``distutils`` first published in 2004. Its most notable addition over the unmodified - :mod:`distutils` tools was the ability to declare dependencies on other + ``distutils`` tools was the ability to declare dependencies on other packages. It is currently recommended as a more regularly updated - alternative to :mod:`distutils` that offers consistent support for more + alternative to ``distutils`` that offers consistent support for more recent packaging standards across a wide range of Python versions. * `wheel`_ (in this context) is a project that adds the ``bdist_wheel`` - command to :mod:`distutils`/`setuptools`_. This produces a cross platform + command to ``distutils``/`setuptools`_. This produces a cross platform binary packaging format (called "wheels" or "wheel files" and defined in :pep:`427`) that allows Python libraries, even those including binary extensions, to be installed on a system without needing to be built diff --git a/Doc/distutils/_setuptools_disclaimer.rst b/Doc/distutils/_setuptools_disclaimer.rst deleted file mode 100644 index cc75858326d44d988c90df0e6c11b48bc57579a8..0000000000000000000000000000000000000000 --- a/Doc/distutils/_setuptools_disclaimer.rst +++ /dev/null @@ -1,5 +0,0 @@ -.. note:: - - This document is being retained solely until the ``setuptools`` documentation - at https://setuptools.readthedocs.io/en/latest/setuptools.html - independently covers all of the relevant information currently included here. diff --git a/Doc/distutils/apiref.rst b/Doc/distutils/apiref.rst deleted file mode 100644 index 87c928555554a64cd1bbf029c22ad6bc04a0c470..0000000000000000000000000000000000000000 --- a/Doc/distutils/apiref.rst +++ /dev/null @@ -1,2041 +0,0 @@ -.. _api-reference: - -************* -API Reference -************* - -.. seealso:: - - `New and changed setup.py arguments in setuptools`_ - The ``setuptools`` project adds new capabilities to the ``setup`` function - and other APIs, makes the API consistent across different Python versions, - and is hence recommended over using ``distutils`` directly. - -.. _New and changed setup.py arguments in setuptools: https://web.archive.org/web/20210614192516/https://setuptools.pypa.io/en/stable/userguide/keywords.html - -.. include:: ./_setuptools_disclaimer.rst - -:mod:`distutils.core` --- Core Distutils functionality -====================================================== - -.. module:: distutils.core - :synopsis: The core Distutils functionality - - -The :mod:`distutils.core` module is the only module that needs to be installed -to use the Distutils. It provides the :func:`setup` (which is called from the -setup script). Indirectly provides the :class:`distutils.dist.Distribution` and -:class:`distutils.cmd.Command` class. - - -.. function:: setup(arguments) - - The basic do-everything function that does most everything you could ever ask - for from a Distutils method. - - The setup function takes a large number of arguments. These are laid out in the - following table. - - .. tabularcolumns:: |l|L|L| - - +--------------------+--------------------------------+-------------------------------------------------------------+ - | argument name | value | type | - +====================+================================+=============================================================+ - | *name* | The name of the package | a string | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *version* | The version number of the | a string | - | | package; see | | - | | :mod:`distutils.version` | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *description* | A single line describing the | a string | - | | package | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *long_description* | Longer description of the | a string | - | | package | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *author* | The name of the package author | a string | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *author_email* | The email address of the | a string | - | | package author | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *maintainer* | The name of the current | a string | - | | maintainer, if different from | | - | | the author. Note that if | | - | | the maintainer is provided, | | - | | distutils will use it as the | | - | | author in :file:`PKG-INFO` | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *maintainer_email* | The email address of the | a string | - | | current maintainer, if | | - | | different from the author | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *url* | A URL for the package | a string | - | | (homepage) | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *download_url* | A URL to download the package | a string | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *packages* | A list of Python packages that | a list of strings | - | | distutils will manipulate | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *py_modules* | A list of Python modules that | a list of strings | - | | distutils will manipulate | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *scripts* | A list of standalone script | a list of strings | - | | files to be built and | | - | | installed | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *ext_modules* | A list of Python extensions to | a list of instances of | - | | be built | :class:`distutils.core.Extension` | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *classifiers* | A list of categories for the | a list of strings; valid classifiers are listed on `PyPI | - | | package | <https://pypi.org/classifiers>`_. | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *distclass* | the :class:`Distribution` | a subclass of | - | | class to use | :class:`distutils.core.Distribution` | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *script_name* | The name of the setup.py | a string | - | | script - defaults to | | - | | ``sys.argv[0]`` | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *script_args* | Arguments to supply to the | a list of strings | - | | setup script | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *options* | default options for the setup | a dictionary | - | | script | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *license* | The license for the package | a string | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *keywords* | Descriptive meta-data, see | a list of strings or a comma-separated string | - | | :pep:`314` | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *platforms* | | a list of strings or a comma-separated string | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *cmdclass* | A mapping of command names to | a dictionary | - | | :class:`Command` subclasses | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *data_files* | A list of data files to | a list | - | | install | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *package_dir* | A mapping of package to | a dictionary | - | | directory names | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - - - -.. function:: run_setup(script_name[, script_args=None, stop_after='run']) - - Run a setup script in a somewhat controlled environment, and return the - :class:`distutils.dist.Distribution` instance that drives things. This is - useful if you need to find out the distribution meta-data (passed as keyword - args from *script* to :func:`setup`), or the contents of the config files or - command-line. - - *script_name* is a file that will be read and run with :func:`exec`. ``sys.argv[0]`` - will be replaced with *script* for the duration of the call. *script_args* is a - list of strings; if supplied, ``sys.argv[1:]`` will be replaced by *script_args* - for the duration of the call. - - *stop_after* tells :func:`setup` when to stop processing; possible values: - - .. tabularcolumns:: |l|L| - - +---------------+---------------------------------------------+ - | value | description | - +===============+=============================================+ - | *init* | Stop after the :class:`Distribution` | - | | instance has been created and populated | - | | with the keyword arguments to :func:`setup` | - +---------------+---------------------------------------------+ - | *config* | Stop after config files have been parsed | - | | (and their data stored in the | - | | :class:`Distribution` instance) | - +---------------+---------------------------------------------+ - | *commandline* | Stop after the command-line | - | | (``sys.argv[1:]`` or *script_args*) have | - | | been parsed (and the data stored in the | - | | :class:`Distribution` instance.) | - +---------------+---------------------------------------------+ - | *run* | Stop after all commands have been run (the | - | | same as if :func:`setup` had been called | - | | in the usual way). This is the default | - | | value. | - +---------------+---------------------------------------------+ - -In addition, the :mod:`distutils.core` module exposed a number of classes that -live elsewhere. - -* :class:`~distutils.extension.Extension` from :mod:`distutils.extension` - -* :class:`~distutils.cmd.Command` from :mod:`distutils.cmd` - -* :class:`~distutils.dist.Distribution` from :mod:`distutils.dist` - -A short description of each of these follows, but see the relevant module for -the full reference. - - -.. class:: Extension - - The Extension class describes a single C or C++ extension module in a setup - script. It accepts the following keyword arguments in its constructor: - - .. tabularcolumns:: |l|L|l| - - +------------------------+--------------------------------+---------------------------+ - | argument name | value | type | - +========================+================================+===========================+ - | *name* | the full name of the | a string | - | | extension, including any | | - | | packages --- ie. *not* a | | - | | filename or pathname, but | | - | | Python dotted name | | - +------------------------+--------------------------------+---------------------------+ - | *sources* | list of source filenames, | a list of strings | - | | relative to the distribution | | - | | root (where the setup script | | - | | lives), in Unix form | | - | | (slash-separated) for | | - | | portability. | | - | | Source files may be C, C++, | | - | | SWIG (.i), platform-specific | | - | | resource files, or whatever | | - | | else is recognized by the | | - | | :command:`build_ext` command | | - | | as source for a Python | | - | | extension. | | - +------------------------+--------------------------------+---------------------------+ - | *include_dirs* | list of directories to search | a list of strings | - | | for C/C++ header files (in | | - | | Unix form for portability) | | - +------------------------+--------------------------------+---------------------------+ - | *define_macros* | list of macros to define; each | a list of tuples | - | | macro is defined using a | | - | | 2-tuple ``(name, value)``, | | - | | where *value* is | | - | | either the string to define it | | - | | to or ``None`` to define it | | - | | without a particular value | | - | | (equivalent of ``#define FOO`` | | - | | in source or :option:`!-DFOO` | | - | | on Unix C compiler command | | - | | line) | | - +------------------------+--------------------------------+---------------------------+ - | *undef_macros* | list of macros to undefine | a list of strings | - | | explicitly | | - +------------------------+--------------------------------+---------------------------+ - | *library_dirs* | list of directories to search | a list of strings | - | | for C/C++ libraries at link | | - | | time | | - +------------------------+--------------------------------+---------------------------+ - | *libraries* | list of library names (not | a list of strings | - | | filenames or paths) to link | | - | | against | | - +------------------------+--------------------------------+---------------------------+ - | *runtime_library_dirs* | list of directories to search | a list of strings | - | | for C/C++ libraries at run | | - | | time (for shared extensions, | | - | | this is when the extension is | | - | | loaded) | | - +------------------------+--------------------------------+---------------------------+ - | *extra_objects* | list of extra files to link | a list of strings | - | | with (eg. object files not | | - | | implied by 'sources', static | | - | | library that must be | | - | | explicitly specified, binary | | - | | resource files, etc.) | | - +------------------------+--------------------------------+---------------------------+ - | *extra_compile_args* | any extra platform- and | a list of strings | - | | compiler-specific information | | - | | to use when compiling the | | - | | source files in 'sources'. For | | - | | platforms and compilers where | | - | | a command line makes sense, | | - | | this is typically a list of | | - | | command-line arguments, but | | - | | for other platforms it could | | - | | be anything. | | - +------------------------+--------------------------------+---------------------------+ - | *extra_link_args* | any extra platform- and | a list of strings | - | | compiler-specific information | | - | | to use when linking object | | - | | files together to create the | | - | | extension (or to create a new | | - | | static Python interpreter). | | - | | Similar interpretation as for | | - | | 'extra_compile_args'. | | - +------------------------+--------------------------------+---------------------------+ - | *export_symbols* | list of symbols to be exported | a list of strings | - | | from a shared extension. Not | | - | | used on all platforms, and not | | - | | generally necessary for Python | | - | | extensions, which typically | | - | | export exactly one symbol: | | - | | ``init`` + extension_name. | | - +------------------------+--------------------------------+---------------------------+ - | *depends* | list of files that the | a list of strings | - | | extension depends on | | - +------------------------+--------------------------------+---------------------------+ - | *language* | extension language (i.e. | a string | - | | ``'c'``, ``'c++'``, | | - | | ``'objc'``). Will be detected | | - | | from the source extensions if | | - | | not provided. | | - +------------------------+--------------------------------+---------------------------+ - | *optional* | specifies that a build failure | a boolean | - | | in the extension should not | | - | | abort the build process, but | | - | | simply skip the extension. | | - +------------------------+--------------------------------+---------------------------+ - - .. versionchanged:: 3.8 - - On Unix, C extensions are no longer linked to libpython except on - Android and Cygwin. - - -.. class:: Distribution - - A :class:`Distribution` describes how to build, install and package up a Python - software package. - - See the :func:`setup` function for a list of keyword arguments accepted by the - Distribution constructor. :func:`setup` creates a Distribution instance. - - .. versionchanged:: 3.7 - :class:`~distutils.core.Distribution` now warns if ``classifiers``, - ``keywords`` and ``platforms`` fields are not specified as a list or - a string. - -.. class:: Command - - A :class:`Command` class (or rather, an instance of one of its subclasses) - implement a single distutils command. - - -:mod:`distutils.ccompiler` --- CCompiler base class -=================================================== - -.. module:: distutils.ccompiler - :synopsis: Abstract CCompiler class - - -This module provides the abstract base class for the :class:`CCompiler` -classes. A :class:`CCompiler` instance can be used for all the compile and -link steps needed to build a single project. Methods are provided to set -options for the compiler --- macro definitions, include directories, link path, -libraries and the like. - -This module provides the following functions. - - -.. function:: gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries) - - Generate linker options for searching library directories and linking with - specific libraries. *libraries* and *library_dirs* are, respectively, lists of - library names (not filenames!) and search directories. Returns a list of - command-line options suitable for use with some compiler (depending on the two - format strings passed in). - - -.. function:: gen_preprocess_options(macros, include_dirs) - - Generate C pre-processor options (:option:`!-D`, :option:`!-U`, :option:`!-I`) as - used by at least two types of compilers: the typical Unix compiler and Visual - C++. *macros* is the usual thing, a list of 1- or 2-tuples, where ``(name,)`` - means undefine (:option:`!-U`) macro *name*, and ``(name, value)`` means define - (:option:`!-D`) macro *name* to *value*. *include_dirs* is just a list of - directory names to be added to the header file search path (:option:`!-I`). - Returns a list of command-line options suitable for either Unix compilers or - Visual C++. - - -.. function:: get_default_compiler(osname, platform) - - Determine the default compiler to use for the given platform. - - *osname* should be one of the standard Python OS names (i.e. the ones returned - by ``os.name``) and *platform* the common value returned by ``sys.platform`` for - the platform in question. - - The default values are ``os.name`` and ``sys.platform`` in case the parameters - are not given. - - -.. function:: new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0) - - Factory function to generate an instance of some CCompiler subclass for the - supplied platform/compiler combination. *plat* defaults to ``os.name`` (eg. - ``'posix'``, ``'nt'``), and *compiler* defaults to the default compiler for - that platform. Currently only ``'posix'`` and ``'nt'`` are supported, and the - default compilers are "traditional Unix interface" (:class:`UnixCCompiler` - class) and Visual C++ (:class:`MSVCCompiler` class). Note that it's perfectly - possible to ask for a Unix compiler object under Windows, and a Microsoft - compiler object under Unix---if you supply a value for *compiler*, *plat* is - ignored. - - .. % Is the posix/nt only thing still true? macOS seems to work, and - .. % returns a UnixCCompiler instance. How to document this... hmm. - - -.. function:: show_compilers() - - Print list of available compilers (used by the :option:`!--help-compiler` options - to :command:`build`, :command:`build_ext`, :command:`build_clib`). - - -.. class:: CCompiler([verbose=0, dry_run=0, force=0]) - - The abstract base class :class:`CCompiler` defines the interface that must be - implemented by real compiler classes. The class also has some utility methods - used by several compiler classes. - - The basic idea behind a compiler abstraction class is that each instance can be - used for all the compile/link steps in building a single project. Thus, - attributes common to all of those compile and link steps --- include - directories, macros to define, libraries to link against, etc. --- are - attributes of the compiler instance. To allow for variability in how individual - files are treated, most of those attributes may be varied on a per-compilation - or per-link basis. - - The constructor for each subclass creates an instance of the Compiler object. - Flags are *verbose* (show verbose output), *dry_run* (don't actually execute the - steps) and *force* (rebuild everything, regardless of dependencies). All of - these flags default to ``0`` (off). Note that you probably don't want to - instantiate :class:`CCompiler` or one of its subclasses directly - use the - :func:`distutils.CCompiler.new_compiler` factory function instead. - - The following methods allow you to manually alter compiler options for the - instance of the Compiler class. - - - .. method:: CCompiler.add_include_dir(dir) - - Add *dir* to the list of directories that will be searched for header files. - The compiler is instructed to search directories in the order in which they are - supplied by successive calls to :meth:`add_include_dir`. - - - .. method:: CCompiler.set_include_dirs(dirs) - - Set the list of directories that will be searched to *dirs* (a list of strings). - Overrides any preceding calls to :meth:`add_include_dir`; subsequent calls to - :meth:`add_include_dir` add to the list passed to :meth:`set_include_dirs`. - This does not affect any list of standard include directories that the compiler - may search by default. - - - .. method:: CCompiler.add_library(libname) - - Add *libname* to the list of libraries that will be included in all links driven - by this compiler object. Note that *libname* should \*not\* be the name of a - file containing a library, but the name of the library itself: the actual - filename will be inferred by the linker, the compiler, or the compiler class - (depending on the platform). - - The linker will be instructed to link against libraries in the order they were - supplied to :meth:`add_library` and/or :meth:`set_libraries`. It is perfectly - valid to duplicate library names; the linker will be instructed to link against - libraries as many times as they are mentioned. - - - .. method:: CCompiler.set_libraries(libnames) - - Set the list of libraries to be included in all links driven by this compiler - object to *libnames* (a list of strings). This does not affect any standard - system libraries that the linker may include by default. - - - .. method:: CCompiler.add_library_dir(dir) - - Add *dir* to the list of directories that will be searched for libraries - specified to :meth:`add_library` and :meth:`set_libraries`. The linker will be - instructed to search for libraries in the order they are supplied to - :meth:`add_library_dir` and/or :meth:`set_library_dirs`. - - - .. method:: CCompiler.set_library_dirs(dirs) - - Set the list of library search directories to *dirs* (a list of strings). This - does not affect any standard library search path that the linker may search by - default. - - - .. method:: CCompiler.add_runtime_library_dir(dir) - - Add *dir* to the list of directories that will be searched for shared libraries - at runtime. - - - .. method:: CCompiler.set_runtime_library_dirs(dirs) - - Set the list of directories to search for shared libraries at runtime to *dirs* - (a list of strings). This does not affect any standard search path that the - runtime linker may search by default. - - - .. method:: CCompiler.define_macro(name[, value=None]) - - Define a preprocessor macro for all compilations driven by this compiler object. - The optional parameter *value* should be a string; if it is not supplied, then - the macro will be defined without an explicit value and the exact outcome - depends on the compiler used. - - .. XXX true? does ANSI say anything about this? - - - .. method:: CCompiler.undefine_macro(name) - - Undefine a preprocessor macro for all compilations driven by this compiler - object. If the same macro is defined by :meth:`define_macro` and - undefined by :meth:`undefine_macro` the last call takes precedence - (including multiple redefinitions or undefinitions). If the macro is - redefined/undefined on a per-compilation basis (ie. in the call to - :meth:`compile`), then that takes precedence. - - - .. method:: CCompiler.add_link_object(object) - - Add *object* to the list of object files (or analogues, such as explicitly named - library files or the output of "resource compilers") to be included in every - link driven by this compiler object. - - - .. method:: CCompiler.set_link_objects(objects) - - Set the list of object files (or analogues) to be included in every link to - *objects*. This does not affect any standard object files that the linker may - include by default (such as system libraries). - - The following methods implement methods for autodetection of compiler options, - providing some functionality similar to GNU :program:`autoconf`. - - - .. method:: CCompiler.detect_language(sources) - - Detect the language of a given file, or list of files. Uses the instance - attributes :attr:`language_map` (a dictionary), and :attr:`language_order` (a - list) to do the job. - - - .. method:: CCompiler.find_library_file(dirs, lib[, debug=0]) - - Search the specified list of directories for a static or shared library file - *lib* and return the full path to that file. If *debug* is true, look for a - debugging version (if that makes sense on the current platform). Return - ``None`` if *lib* wasn't found in any of the specified directories. - - - .. method:: CCompiler.has_function(funcname [, includes=None, include_dirs=None, libraries=None, library_dirs=None]) - - Return a boolean indicating whether *funcname* is supported on the current - platform. The optional arguments can be used to augment the compilation - environment by providing additional include files and paths and libraries and - paths. - - - .. method:: CCompiler.library_dir_option(dir) - - Return the compiler option to add *dir* to the list of directories searched for - libraries. - - - .. method:: CCompiler.library_option(lib) - - Return the compiler option to add *lib* to the list of libraries linked into the - shared library or executable. - - - .. method:: CCompiler.runtime_library_dir_option(dir) - - Return the compiler option to add *dir* to the list of directories searched for - runtime libraries. - - - .. method:: CCompiler.set_executables(**args) - - Define the executables (and options for them) that will be run to perform the - various stages of compilation. The exact set of executables that may be - specified here depends on the compiler class (via the 'executables' class - attribute), but most will have: - - +--------------+------------------------------------------+ - | attribute | description | - +==============+==========================================+ - | *compiler* | the C/C++ compiler | - +--------------+------------------------------------------+ - | *linker_so* | linker used to create shared objects and | - | | libraries | - +--------------+------------------------------------------+ - | *linker_exe* | linker used to create binary executables | - +--------------+------------------------------------------+ - | *archiver* | static library creator | - +--------------+------------------------------------------+ - - On platforms with a command-line (Unix, DOS/Windows), each of these is a string - that will be split into executable name and (optional) list of arguments. - (Splitting the string is done similarly to how Unix shells operate: words are - delimited by spaces, but quotes and backslashes can override this. See - :func:`distutils.util.split_quoted`.) - - The following methods invoke stages in the build process. - - - .. method:: CCompiler.compile(sources[, output_dir=None, macros=None, include_dirs=None, debug=0, extra_preargs=None, extra_postargs=None, depends=None]) - - Compile one or more source files. Generates object files (e.g. transforms a - :file:`.c` file to a :file:`.o` file.) - - *sources* must be a list of filenames, most likely C/C++ files, but in reality - anything that can be handled by a particular compiler and compiler class (eg. - :class:`MSVCCompiler` can handle resource files in *sources*). Return a list of - object filenames, one per source filename in *sources*. Depending on the - implementation, not all source files will necessarily be compiled, but all - corresponding object filenames will be returned. - - If *output_dir* is given, object files will be put under it, while retaining - their original path component. That is, :file:`foo/bar.c` normally compiles to - :file:`foo/bar.o` (for a Unix implementation); if *output_dir* is *build*, then - it would compile to :file:`build/foo/bar.o`. - - *macros*, if given, must be a list of macro definitions. A macro definition is - either a ``(name, value)`` 2-tuple or a ``(name,)`` 1-tuple. The former defines - a macro; if the value is ``None``, the macro is defined without an explicit - value. The 1-tuple case undefines a macro. Later - definitions/redefinitions/undefinitions take precedence. - - *include_dirs*, if given, must be a list of strings, the directories to add to - the default include file search path for this compilation only. - - *debug* is a boolean; if true, the compiler will be instructed to output debug - symbols in (or alongside) the object file(s). - - *extra_preargs* and *extra_postargs* are implementation-dependent. On platforms - that have the notion of a command-line (e.g. Unix, DOS/Windows), they are most - likely lists of strings: extra command-line arguments to prepend/append to the - compiler command line. On other platforms, consult the implementation class - documentation. In any event, they are intended as an escape hatch for those - occasions when the abstract compiler framework doesn't cut the mustard. - - *depends*, if given, is a list of filenames that all targets depend on. If a - source file is older than any file in depends, then the source file will be - recompiled. This supports dependency tracking, but only at a coarse - granularity. - - Raises :exc:`CompileError` on failure. - - - .. method:: CCompiler.create_static_lib(objects, output_libname[, output_dir=None, debug=0, target_lang=None]) - - Link a bunch of stuff together to create a static library file. The "bunch of - stuff" consists of the list of object files supplied as *objects*, the extra - object files supplied to :meth:`add_link_object` and/or - :meth:`set_link_objects`, the libraries supplied to :meth:`add_library` and/or - :meth:`set_libraries`, and the libraries supplied as *libraries* (if any). - - *output_libname* should be a library name, not a filename; the filename will be - inferred from the library name. *output_dir* is the directory where the library - file will be put. - - .. XXX defaults to what? - - *debug* is a boolean; if true, debugging information will be included in the - library (note that on most platforms, it is the compile step where this matters: - the *debug* flag is included here just for consistency). - - *target_lang* is the target language for which the given objects are being - compiled. This allows specific linkage time treatment of certain languages. - - Raises :exc:`LibError` on failure. - - - .. method:: CCompiler.link(target_desc, objects, output_filename[, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None]) - - Link a bunch of stuff together to create an executable or shared library file. - - The "bunch of stuff" consists of the list of object files supplied as *objects*. - *output_filename* should be a filename. If *output_dir* is supplied, - *output_filename* is relative to it (i.e. *output_filename* can provide - directory components if needed). - - *libraries* is a list of libraries to link against. These are library names, - not filenames, since they're translated into filenames in a platform-specific - way (eg. *foo* becomes :file:`libfoo.a` on Unix and :file:`foo.lib` on - DOS/Windows). However, they can include a directory component, which means the - linker will look in that specific directory rather than searching all the normal - locations. - - *library_dirs*, if supplied, should be a list of directories to search for - libraries that were specified as bare library names (ie. no directory - component). These are on top of the system default and those supplied to - :meth:`add_library_dir` and/or :meth:`set_library_dirs`. *runtime_library_dirs* - is a list of directories that will be embedded into the shared library and used - to search for other shared libraries that \*it\* depends on at run-time. (This - may only be relevant on Unix.) - - *export_symbols* is a list of symbols that the shared library will export. - (This appears to be relevant only on Windows.) - - *debug* is as for :meth:`compile` and :meth:`create_static_lib`, with the - slight distinction that it actually matters on most platforms (as opposed to - :meth:`create_static_lib`, which includes a *debug* flag mostly for form's - sake). - - *extra_preargs* and *extra_postargs* are as for :meth:`compile` (except of - course that they supply command-line arguments for the particular linker being - used). - - *target_lang* is the target language for which the given objects are being - compiled. This allows specific linkage time treatment of certain languages. - - Raises :exc:`LinkError` on failure. - - - .. method:: CCompiler.link_executable(objects, output_progname[, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, debug=0, extra_preargs=None, extra_postargs=None, target_lang=None]) - - Link an executable. *output_progname* is the name of the file executable, while - *objects* are a list of object filenames to link in. Other arguments are as for - the :meth:`link` method. - - - .. method:: CCompiler.link_shared_lib(objects, output_libname[, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None]) - - Link a shared library. *output_libname* is the name of the output library, - while *objects* is a list of object filenames to link in. Other arguments are - as for the :meth:`link` method. - - - .. method:: CCompiler.link_shared_object(objects, output_filename[, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None]) - - Link a shared object. *output_filename* is the name of the shared object that - will be created, while *objects* is a list of object filenames to link in. - Other arguments are as for the :meth:`link` method. - - - .. method:: CCompiler.preprocess(source[, output_file=None, macros=None, include_dirs=None, extra_preargs=None, extra_postargs=None]) - - Preprocess a single C/C++ source file, named in *source*. Output will be written - to file named *output_file*, or *stdout* if *output_file* not supplied. - *macros* is a list of macro definitions as for :meth:`compile`, which will - augment the macros set with :meth:`define_macro` and :meth:`undefine_macro`. - *include_dirs* is a list of directory names that will be added to the default - list, in the same way as :meth:`add_include_dir`. - - Raises :exc:`PreprocessError` on failure. - - The following utility methods are defined by the :class:`CCompiler` class, for - use by the various concrete subclasses. - - - .. method:: CCompiler.executable_filename(basename[, strip_dir=0, output_dir='']) - - Returns the filename of the executable for the given *basename*. Typically for - non-Windows platforms this is the same as the basename, while Windows will get - a :file:`.exe` added. - - - .. method:: CCompiler.library_filename(libname[, lib_type='static', strip_dir=0, output_dir='']) - - Returns the filename for the given library name on the current platform. On Unix - a library with *lib_type* of ``'static'`` will typically be of the form - :file:`liblibname.a`, while a *lib_type* of ``'dynamic'`` will be of the form - :file:`liblibname.so`. - - - .. method:: CCompiler.object_filenames(source_filenames[, strip_dir=0, output_dir='']) - - Returns the name of the object files for the given source files. - *source_filenames* should be a list of filenames. - - - .. method:: CCompiler.shared_object_filename(basename[, strip_dir=0, output_dir='']) - - Returns the name of a shared object file for the given file name *basename*. - - - .. method:: CCompiler.execute(func, args[, msg=None, level=1]) - - Invokes :func:`distutils.util.execute`. This method invokes a Python function - *func* with the given arguments *args*, after logging and taking into account - the *dry_run* flag. - - - .. method:: CCompiler.spawn(cmd) - - Invokes :func:`distutils.util.spawn`. This invokes an external process to run - the given command. - - - .. method:: CCompiler.mkpath(name[, mode=511]) - - Invokes :func:`distutils.dir_util.mkpath`. This creates a directory and any - missing ancestor directories. - - - .. method:: CCompiler.move_file(src, dst) - - Invokes :meth:`distutils.file_util.move_file`. Renames *src* to *dst*. - - - .. method:: CCompiler.announce(msg[, level=1]) - - Write a message using :func:`distutils.log.debug`. - - - .. method:: CCompiler.warn(msg) - - Write a warning message *msg* to standard error. - - - .. method:: CCompiler.debug_print(msg) - - If the *debug* flag is set on this :class:`CCompiler` instance, print *msg* to - standard output, otherwise do nothing. - -.. % \subsection{Compiler-specific modules} -.. % -.. % The following modules implement concrete subclasses of the abstract -.. % \class{CCompiler} class. They should not be instantiated directly, but should -.. % be created using \function{distutils.ccompiler.new_compiler()} factory -.. % function. - - -:mod:`distutils.unixccompiler` --- Unix C Compiler -================================================== - -.. module:: distutils.unixccompiler - :synopsis: UNIX C Compiler - - -This module provides the :class:`UnixCCompiler` class, a subclass of -:class:`CCompiler` that handles the typical Unix-style command-line C compiler: - -* macros defined with :option:`!-Dname[=value]` - -* macros undefined with :option:`!-Uname` - -* include search directories specified with :option:`!-Idir` - -* libraries specified with :option:`!-llib` - -* library search directories specified with :option:`!-Ldir` - -* compile handled by :program:`cc` (or similar) executable with :option:`!-c` - option: compiles :file:`.c` to :file:`.o` - -* link static library handled by :program:`ar` command (possibly with - :program:`ranlib`) - -* link shared library handled by :program:`cc` :option:`!-shared` - - -:mod:`distutils.msvccompiler` --- Microsoft Compiler -==================================================== - -.. module:: distutils.msvccompiler - :synopsis: Microsoft Compiler - -.. XXX: This is *waaaaay* out of date! - -This module provides :class:`MSVCCompiler`, an implementation of the abstract -:class:`CCompiler` class for Microsoft Visual Studio. Typically, extension -modules need to be compiled with the same compiler that was used to compile -Python. For Python 2.3 and earlier, the compiler was Visual Studio 6. For Python -2.4 and 2.5, the compiler is Visual Studio .NET 2003. - -:class:`MSVCCompiler` will normally choose the right compiler, linker etc. on -its own. To override this choice, the environment variables *DISTUTILS_USE_SDK* -and *MSSdk* must be both set. *MSSdk* indicates that the current environment has -been setup by the SDK's ``SetEnv.Cmd`` script, or that the environment variables -had been registered when the SDK was installed; *DISTUTILS_USE_SDK* indicates -that the distutils user has made an explicit choice to override the compiler -selection by :class:`MSVCCompiler`. - - -:mod:`distutils.bcppcompiler` --- Borland Compiler -================================================== - -.. module:: distutils.bcppcompiler - - -This module provides :class:`BorlandCCompiler`, a subclass of the abstract -:class:`CCompiler` class for the Borland C++ compiler. - - -:mod:`distutils.cygwincompiler` --- Cygwin Compiler -=================================================== - -.. module:: distutils.cygwinccompiler - - -This module provides the :class:`CygwinCCompiler` class, a subclass of -:class:`UnixCCompiler` that handles the Cygwin port of the GNU C compiler to -Windows. It also contains the Mingw32CCompiler class which handles the mingw32 -port of GCC (same as cygwin in no-cygwin mode). - - -:mod:`distutils.archive_util` --- Archiving utilities -====================================================== - -.. module:: distutils.archive_util - :synopsis: Utility functions for creating archive files (tarballs, zip files, ...) - - -This module provides a few functions for creating archive files, such as -tarballs or zipfiles. - - -.. function:: make_archive(base_name, format[, root_dir=None, base_dir=None, verbose=0, dry_run=0]) - - Create an archive file (eg. ``zip`` or ``tar``). *base_name* is the name of - the file to create, minus any format-specific extension; *format* is the - archive format: one of ``zip``, ``tar``, ``gztar``, ``bztar``, ``xztar``, or - ``ztar``. *root_dir* is a directory that will be the root directory of the - archive; ie. we typically ``chdir`` into *root_dir* before creating the - archive. *base_dir* is the directory where we start archiving from; ie. - *base_dir* will be the common prefix of all files and directories in the - archive. *root_dir* and *base_dir* both default to the current directory. - Returns the name of the archive file. - - .. versionchanged:: 3.5 - Added support for the ``xztar`` format. - - -.. function:: make_tarball(base_name, base_dir[, compress='gzip', verbose=0, dry_run=0]) - - 'Create an (optional compressed) archive as a tar file from all files in and - under *base_dir*. *compress* must be ``'gzip'`` (the default), - ``'bzip2'``, ``'xz'``, ``'compress'``, or ``None``. For the ``'compress'`` - method the compression utility named by :program:`compress` must be on the - default program search path, so this is probably Unix-specific. The output - tar file will be named :file:`base_dir.tar`, possibly plus the appropriate - compression extension (``.gz``, ``.bz2``, ``.xz`` or ``.Z``). Return the - output filename. - - .. versionchanged:: 3.5 - Added support for the ``xz`` compression. - - -.. function:: make_zipfile(base_name, base_dir[, verbose=0, dry_run=0]) - - Create a zip file from all files in and under *base_dir*. The output zip file - will be named *base_name* + :file:`.zip`. Uses either the :mod:`zipfile` Python - module (if available) or the InfoZIP :file:`zip` utility (if installed and - found on the default search path). If neither tool is available, raises - :exc:`DistutilsExecError`. Returns the name of the output zip file. - - -:mod:`distutils.dep_util` --- Dependency checking -================================================= - -.. module:: distutils.dep_util - :synopsis: Utility functions for simple dependency checking - - -This module provides functions for performing simple, timestamp-based -dependency of files and groups of files; also, functions based entirely on such -timestamp dependency analysis. - - -.. function:: newer(source, target) - - Return true if *source* exists and is more recently modified than *target*, or - if *source* exists and *target* doesn't. Return false if both exist and *target* - is the same age or newer than *source*. Raise :exc:`DistutilsFileError` if - *source* does not exist. - - -.. function:: newer_pairwise(sources, targets) - - Walk two filename lists in parallel, testing if each source is newer than its - corresponding target. Return a pair of lists (*sources*, *targets*) where - source is newer than target, according to the semantics of :func:`newer`. - - .. % % equivalent to a listcomp... - - -.. function:: newer_group(sources, target[, missing='error']) - - Return true if *target* is out-of-date with respect to any file listed in - *sources*. In other words, if *target* exists and is newer than every file in - *sources*, return false; otherwise return true. *missing* controls what we do - when a source file is missing; the default (``'error'``) is to blow up with an - :exc:`OSError` from inside :func:`os.stat`; if it is ``'ignore'``, we silently - drop any missing source files; if it is ``'newer'``, any missing source files - make us assume that *target* is out-of-date (this is handy in "dry-run" mode: - it'll make you pretend to carry out commands that wouldn't work because inputs - are missing, but that doesn't matter because you're not actually going to run - the commands). - - -:mod:`distutils.dir_util` --- Directory tree operations -======================================================= - -.. module:: distutils.dir_util - :synopsis: Utility functions for operating on directories and directory trees - - -This module provides functions for operating on directories and trees of -directories. - - -.. function:: mkpath(name[, mode=0o777, verbose=0, dry_run=0]) - - Create a directory and any missing ancestor directories. If the directory - already exists (or if *name* is the empty string, which means the current - directory, which of course exists), then do nothing. Raise - :exc:`DistutilsFileError` if unable to create some directory along the way (eg. - some sub-path exists, but is a file rather than a directory). If *verbose* is - true, print a one-line summary of each mkdir to stdout. Return the list of - directories actually created. - - -.. function:: create_tree(base_dir, files[, mode=0o777, verbose=0, dry_run=0]) - - Create all the empty directories under *base_dir* needed to put *files* there. - *base_dir* is just the name of a directory which doesn't necessarily exist - yet; *files* is a list of filenames to be interpreted relative to *base_dir*. - *base_dir* + the directory portion of every file in *files* will be created if - it doesn't already exist. *mode*, *verbose* and *dry_run* flags are as for - :func:`mkpath`. - - -.. function:: copy_tree(src, dst[, preserve_mode=1, preserve_times=1, preserve_symlinks=0, update=0, verbose=0, dry_run=0]) - - Copy an entire directory tree *src* to a new location *dst*. Both *src* and - *dst* must be directory names. If *src* is not a directory, raise - :exc:`DistutilsFileError`. If *dst* does not exist, it is created with - :func:`mkpath`. The end result of the copy is that every file in *src* is - copied to *dst*, and directories under *src* are recursively copied to *dst*. - Return the list of files that were copied or might have been copied, using their - output name. The return value is unaffected by *update* or *dry_run*: it is - simply the list of all files under *src*, with the names changed to be under - *dst*. - - *preserve_mode* and *preserve_times* are the same as for - :func:`distutils.file_util.copy_file`; note that they only apply to - regular files, not to - directories. If *preserve_symlinks* is true, symlinks will be copied as - symlinks (on platforms that support them!); otherwise (the default), the - destination of the symlink will be copied. *update* and *verbose* are the same - as for :func:`copy_file`. - - Files in *src* that begin with :file:`.nfs` are skipped (more information on - these files is available in answer D2 of the `NFS FAQ page - <http://nfs.sourceforge.net/#section_d>`_). - - .. versionchanged:: 3.3.1 - NFS files are ignored. - -.. function:: remove_tree(directory[, verbose=0, dry_run=0]) - - Recursively remove *directory* and all files and directories underneath it. Any - errors are ignored (apart from being reported to ``sys.stdout`` if *verbose* is - true). - - -:mod:`distutils.file_util` --- Single file operations -===================================================== - -.. module:: distutils.file_util - :synopsis: Utility functions for operating on single files - - -This module contains some utility functions for operating on individual files. - - -.. function:: copy_file(src, dst[, preserve_mode=1, preserve_times=1, update=0, link=None, verbose=0, dry_run=0]) - - Copy file *src* to *dst*. If *dst* is a directory, then *src* is copied there - with the same name; otherwise, it must be a filename. (If the file exists, it - will be ruthlessly clobbered.) If *preserve_mode* is true (the default), the - file's mode (type and permission bits, or whatever is analogous on the - current platform) is copied. If *preserve_times* is true (the default), the - last-modified and last-access times are copied as well. If *update* is true, - *src* will only be copied if *dst* does not exist, or if *dst* does exist but - is older than *src*. - - *link* allows you to make hard links (using :func:`os.link`) or symbolic links - (using :func:`os.symlink`) instead of copying: set it to ``'hard'`` or - ``'sym'``; if it is ``None`` (the default), files are copied. Don't set *link* - on systems that don't support it: :func:`copy_file` doesn't check if hard or - symbolic linking is available. It uses :func:`_copy_file_contents` to copy file - contents. - - Return a tuple ``(dest_name, copied)``: *dest_name* is the actual name of the - output file, and *copied* is true if the file was copied (or would have been - copied, if *dry_run* true). - - .. % XXX if the destination file already exists, we clobber it if - .. % copying, but blow up if linking. Hmmm. And I don't know what - .. % macostools.copyfile() does. Should definitely be consistent, and - .. % should probably blow up if destination exists and we would be - .. % changing it (ie. it's not already a hard/soft link to src OR - .. % (not update) and (src newer than dst)). - - -.. function:: move_file(src, dst[, verbose, dry_run]) - - Move file *src* to *dst*. If *dst* is a directory, the file will be moved into - it with the same name; otherwise, *src* is just renamed to *dst*. Returns the - new full name of the file. - - .. warning:: - - Handles cross-device moves on Unix using :func:`copy_file`. What about - other systems? - - -.. function:: write_file(filename, contents) - - Create a file called *filename* and write *contents* (a sequence of strings - without line terminators) to it. - - -:mod:`distutils.util` --- Miscellaneous other utility functions -=============================================================== - -.. module:: distutils.util - :synopsis: Miscellaneous other utility functions - - -This module contains other assorted bits and pieces that don't fit into any -other utility module. - - -.. function:: get_platform() - - Return a string that identifies the current platform. This is used mainly to - distinguish platform-specific build directories and platform-specific built - distributions. Typically includes the OS name and version and the - architecture (as supplied by 'os.uname()'), although the exact information - included depends on the OS; e.g., on Linux, the kernel version isn't - particularly important. - - Examples of returned values: - - * ``linux-i586`` - * ``linux-alpha`` - * ``solaris-2.6-sun4u`` - - For non-POSIX platforms, currently just returns ``sys.platform``. - - For macOS systems the OS version reflects the minimal version on which - binaries will run (that is, the value of ``MACOSX_DEPLOYMENT_TARGET`` - during the build of Python), not the OS version of the current system. - - For universal binary builds on macOS the architecture value reflects - the universal binary status instead of the architecture of the current - processor. For 32-bit universal binaries the architecture is ``fat``, - for 64-bit universal binaries the architecture is ``fat64``, and - for 4-way universal binaries the architecture is ``universal``. Starting - from Python 2.7 and Python 3.2 the architecture ``fat3`` is used for - a 3-way universal build (ppc, i386, x86_64) and ``intel`` is used for - a universal build with the i386 and x86_64 architectures - - Examples of returned values on macOS: - - * ``macosx-10.3-ppc`` - - * ``macosx-10.3-fat`` - - * ``macosx-10.5-universal`` - - * ``macosx-10.6-intel`` - - For AIX, Python 3.9 and later return a string starting with "aix", followed - by additional fields (separated by ``'-'``) that represent the combined - values of AIX Version, Release and Technology Level (first field), Build Date - (second field), and bit-size (third field). Python 3.8 and earlier returned - only a single additional field with the AIX Version and Release. - - Examples of returned values on AIX: - - * ``aix-5307-0747-32`` # 32-bit build on AIX ``oslevel -s``: 5300-07-00-0000 - - * ``aix-7105-1731-64`` # 64-bit build on AIX ``oslevel -s``: 7100-05-01-1731 - - * ``aix-7.2`` # Legacy form reported in Python 3.8 and earlier - - .. versionchanged:: 3.9 - The AIX platform string format now also includes the technology level, - build date, and ABI bit-size. - - -.. function:: convert_path(pathname) - - Return 'pathname' as a name that will work on the native filesystem, i.e. split - it on '/' and put it back together again using the current directory separator. - Needed because filenames in the setup script are always supplied in Unix style, - and have to be converted to the local convention before we can actually use them - in the filesystem. Raises :exc:`ValueError` on non-Unix-ish systems if - *pathname* either starts or ends with a slash. - - -.. function:: change_root(new_root, pathname) - - Return *pathname* with *new_root* prepended. If *pathname* is relative, this is - equivalent to ``os.path.join(new_root,pathname)`` Otherwise, it requires making - *pathname* relative and then joining the two, which is tricky on DOS/Windows. - - -.. function:: check_environ() - - Ensure that 'os.environ' has all the environment variables we guarantee that - users can use in config files, command-line options, etc. Currently this - includes: - - * :envvar:`HOME` - user's home directory (Unix only) - * :envvar:`PLAT` - description of the current platform, including hardware and - OS (see :func:`get_platform`) - - -.. function:: subst_vars(s, local_vars) - - Perform shell/Perl-style variable substitution on *s*. Every occurrence of - ``$`` followed by a name is considered a variable, and variable is substituted - by the value found in the *local_vars* dictionary, or in ``os.environ`` if it's - not in *local_vars*. *os.environ* is first checked/augmented to guarantee that - it contains certain values: see :func:`check_environ`. Raise :exc:`ValueError` - for any variables not found in either *local_vars* or ``os.environ``. - - Note that this is not a full-fledged string interpolation function. A valid - ``$variable`` can consist only of upper and lower case letters, numbers and an - underscore. No { } or ( ) style quoting is available. - - -.. function:: split_quoted(s) - - Split a string up according to Unix shell-like rules for quotes and backslashes. - In short: words are delimited by spaces, as long as those spaces are not escaped - by a backslash, or inside a quoted string. Single and double quotes are - equivalent, and the quote characters can be backslash-escaped. The backslash is - stripped from any two-character escape sequence, leaving only the escaped - character. The quote characters are stripped from any quoted string. Returns a - list of words. - - .. % Should probably be moved into the standard library. - - -.. function:: execute(func, args[, msg=None, verbose=0, dry_run=0]) - - Perform some action that affects the outside world (for instance, writing to the - filesystem). Such actions are special because they are disabled by the - *dry_run* flag. This method takes care of all that bureaucracy for you; all - you have to do is supply the function to call and an argument tuple for it (to - embody the "external action" being performed), and an optional message to print. - - -.. function:: strtobool(val) - - Convert a string representation of truth to true (1) or false (0). - - True values are ``y``, ``yes``, ``t``, ``true``, ``on`` and ``1``; false values - are ``n``, ``no``, ``f``, ``false``, ``off`` and ``0``. Raises - :exc:`ValueError` if *val* is anything else. - - -.. function:: byte_compile(py_files[, optimize=0, force=0, prefix=None, base_dir=None, verbose=1, dry_run=0, direct=None]) - - Byte-compile a collection of Python source files to :file:`.pyc` files in a - :file:`__pycache__` subdirectory (see :pep:`3147` and :pep:`488`). - *py_files* is a list of files to compile; any files that don't end in - :file:`.py` are silently skipped. *optimize* must be one of the following: - - * ``0`` - don't optimize - * ``1`` - normal optimization (like ``python -O``) - * ``2`` - extra optimization (like ``python -OO``) - - If *force* is true, all files are recompiled regardless of timestamps. - - The source filename encoded in each :term:`bytecode` file defaults to the filenames - listed in *py_files*; you can modify these with *prefix* and *basedir*. - *prefix* is a string that will be stripped off of each source filename, and - *base_dir* is a directory name that will be prepended (after *prefix* is - stripped). You can supply either or both (or neither) of *prefix* and - *base_dir*, as you wish. - - If *dry_run* is true, doesn't actually do anything that would affect the - filesystem. - - Byte-compilation is either done directly in this interpreter process with the - standard :mod:`py_compile` module, or indirectly by writing a temporary script - and executing it. Normally, you should let :func:`byte_compile` figure out to - use direct compilation or not (see the source for details). The *direct* flag - is used by the script generated in indirect mode; unless you know what you're - doing, leave it set to ``None``. - - .. versionchanged:: 3.2.3 - Create ``.pyc`` files with an :func:`import magic tag - <imp.get_tag>` in their name, in a :file:`__pycache__` subdirectory - instead of files without tag in the current directory. - - .. versionchanged:: 3.5 - Create ``.pyc`` files according to :pep:`488`. - - -.. function:: rfc822_escape(header) - - Return a version of *header* escaped for inclusion in an :rfc:`822` header, by - ensuring there are 8 spaces space after each newline. Note that it does no other - modification of the string. - - .. % this _can_ be replaced - -.. % \subsection{Distutils objects} - - -:mod:`distutils.dist` --- The Distribution class -================================================ - -.. module:: distutils.dist - :synopsis: Provides the Distribution class, which represents the module distribution being - built/installed/distributed - - -This module provides the :class:`~distutils.core.Distribution` class, which -represents the module distribution being built/installed/distributed. - - -:mod:`distutils.extension` --- The Extension class -================================================== - -.. module:: distutils.extension - :synopsis: Provides the Extension class, used to describe C/C++ extension modules in setup - scripts - - -This module provides the :class:`Extension` class, used to describe C/C++ -extension modules in setup scripts. - -.. % \subsection{Ungrouped modules} -.. % The following haven't been moved into a more appropriate section yet. - - -:mod:`distutils.debug` --- Distutils debug mode -=============================================== - -.. module:: distutils.debug - :synopsis: Provides the debug flag for distutils - - -This module provides the DEBUG flag. - - -:mod:`distutils.errors` --- Distutils exceptions -================================================ - -.. module:: distutils.errors - :synopsis: Provides standard distutils exceptions - - -Provides exceptions used by the Distutils modules. Note that Distutils modules -may raise standard exceptions; in particular, SystemExit is usually raised for -errors that are obviously the end-user's fault (eg. bad command-line arguments). - -This module is safe to use in ``from ... import *`` mode; it only exports -symbols whose names start with ``Distutils`` and end with ``Error``. - - -:mod:`distutils.fancy_getopt` --- Wrapper around the standard getopt module -=========================================================================== - -.. module:: distutils.fancy_getopt - :synopsis: Additional getopt functionality - - -This module provides a wrapper around the standard :mod:`getopt` module that -provides the following additional features: - -* short and long options are tied together - -* options have help strings, so :func:`fancy_getopt` could potentially create a - complete usage summary - -* options set attributes of a passed-in object - -* boolean options can have "negative aliases" --- eg. if :option:`!--quiet` is - the "negative alias" of :option:`!--verbose`, then :option:`!--quiet` on the - command line sets *verbose* to false. - -.. function:: fancy_getopt(options, negative_opt, object, args) - - Wrapper function. *options* is a list of ``(long_option, short_option, - help_string)`` 3-tuples as described in the constructor for - :class:`FancyGetopt`. *negative_opt* should be a dictionary mapping option names - to option names, both the key and value should be in the *options* list. - *object* is an object which will be used to store values (see the :meth:`getopt` - method of the :class:`FancyGetopt` class). *args* is the argument list. Will use - ``sys.argv[1:]`` if you pass ``None`` as *args*. - - -.. function:: wrap_text(text, width) - - Wraps *text* to less than *width* wide. - - -.. class:: FancyGetopt([option_table=None]) - - The option_table is a list of 3-tuples: ``(long_option, short_option, - help_string)`` - - If an option takes an argument, its *long_option* should have ``'='`` appended; - *short_option* should just be a single character, no ``':'`` in any case. - *short_option* should be ``None`` if a *long_option* doesn't have a - corresponding *short_option*. All option tuples must have long options. - -The :class:`FancyGetopt` class provides the following methods: - - -.. method:: FancyGetopt.getopt([args=None, object=None]) - - Parse command-line options in args. Store as attributes on *object*. - - If *args* is ``None`` or not supplied, uses ``sys.argv[1:]``. If *object* is - ``None`` or not supplied, creates a new :class:`OptionDummy` instance, stores - option values there, and returns a tuple ``(args, object)``. If *object* is - supplied, it is modified in place and :func:`getopt` just returns *args*; in - both cases, the returned *args* is a modified copy of the passed-in *args* list, - which is left untouched. - - .. % and args returned are? - - -.. method:: FancyGetopt.get_option_order() - - Returns the list of ``(option, value)`` tuples processed by the previous run of - :meth:`getopt` Raises :exc:`RuntimeError` if :meth:`getopt` hasn't been called - yet. - - -.. method:: FancyGetopt.generate_help([header=None]) - - Generate help text (a list of strings, one per suggested line of output) from - the option table for this :class:`FancyGetopt` object. - - If supplied, prints the supplied *header* at the top of the help. - - -:mod:`distutils.filelist` --- The FileList class -================================================ - -.. module:: distutils.filelist - :synopsis: The FileList class, used for poking about the file system and - building lists of files. - - -This module provides the :class:`FileList` class, used for poking about the -filesystem and building lists of files. - - -:mod:`distutils.log` --- Simple :pep:`282`-style logging -======================================================== - -.. module:: distutils.log - :synopsis: A simple logging mechanism, :pep:`282`-style - - -:mod:`distutils.spawn` --- Spawn a sub-process -============================================== - -.. module:: distutils.spawn - :synopsis: Provides the spawn() function - - -This module provides the :func:`spawn` function, a front-end to various -platform-specific functions for launching another program in a sub-process. -Also provides :func:`find_executable` to search the path for a given executable -name. - - -:mod:`distutils.sysconfig` --- System configuration information -=============================================================== - -.. module:: distutils.sysconfig - :synopsis: Low-level access to configuration information of the Python interpreter. -.. deprecated:: 3.10 - :mod:`distutils.sysconfig` has been merged into :mod:`sysconfig`. -.. moduleauthor:: Fred L. Drake, Jr. <fdrake@acm.org> -.. moduleauthor:: Greg Ward <gward@python.net> -.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org> - - -The :mod:`distutils.sysconfig` module provides access to Python's low-level -configuration information. The specific configuration variables available -depend heavily on the platform and configuration. The specific variables depend -on the build process for the specific version of Python being run; the variables -are those found in the :file:`Makefile` and configuration header that are -installed with Python on Unix systems. The configuration header is called -:file:`pyconfig.h` for Python versions starting with 2.2, and :file:`config.h` -for earlier versions of Python. - -Some additional functions are provided which perform some useful manipulations -for other parts of the :mod:`distutils` package. - - -.. data:: PREFIX - - The result of ``os.path.normpath(sys.prefix)``. - - -.. data:: EXEC_PREFIX - - The result of ``os.path.normpath(sys.exec_prefix)``. - - -.. function:: get_config_var(name) - - Return the value of a single variable. This is equivalent to - ``get_config_vars().get(name)``. - - -.. function:: get_config_vars(...) - - Return a set of variable definitions. If there are no arguments, this returns a - dictionary mapping names of configuration variables to values. If arguments are - provided, they should be strings, and the return value will be a sequence giving - the associated values. If a given name does not have a corresponding value, - ``None`` will be included for that variable. - - -.. function:: get_config_h_filename() - - Return the full path name of the configuration header. For Unix, this will be - the header generated by the :program:`configure` script; for other platforms the - header will have been supplied directly by the Python source distribution. The - file is a platform-specific text file. - - -.. function:: get_makefile_filename() - - Return the full path name of the :file:`Makefile` used to build Python. For - Unix, this will be a file generated by the :program:`configure` script; the - meaning for other platforms will vary. The file is a platform-specific text - file, if it exists. This function is only useful on POSIX platforms. - -The following functions are deprecated together with this module and they -have no direct replacement. - - -.. function:: get_python_inc([plat_specific[, prefix]]) - - Return the directory for either the general or platform-dependent C include - files. If *plat_specific* is true, the platform-dependent include directory is - returned; if false or omitted, the platform-independent directory is returned. - If *prefix* is given, it is used as either the prefix instead of - :const:`PREFIX`, or as the exec-prefix instead of :const:`EXEC_PREFIX` if - *plat_specific* is true. - - -.. function:: get_python_lib([plat_specific[, standard_lib[, prefix]]]) - - Return the directory for either the general or platform-dependent library - installation. If *plat_specific* is true, the platform-dependent include - directory is returned; if false or omitted, the platform-independent directory - is returned. If *prefix* is given, it is used as either the prefix instead of - :const:`PREFIX`, or as the exec-prefix instead of :const:`EXEC_PREFIX` if - *plat_specific* is true. If *standard_lib* is true, the directory for the - standard library is returned rather than the directory for the installation of - third-party extensions. - -The following function is only intended for use within the :mod:`distutils` -package. - - -.. function:: customize_compiler(compiler) - - Do any platform-specific customization of a - :class:`distutils.ccompiler.CCompiler` instance. - - This function is only needed on Unix at this time, but should be called - consistently to support forward-compatibility. It inserts the information that - varies across Unix flavors and is stored in Python's :file:`Makefile`. This - information includes the selected compiler, compiler and linker options, and the - extension used by the linker for shared objects. - -This function is even more special-purpose, and should only be used from -Python's own build procedures. - - -.. function:: set_python_build() - - Inform the :mod:`distutils.sysconfig` module that it is being used as part of - the build process for Python. This changes a lot of relative locations for - files, allowing them to be located in the build area rather than in an installed - Python. - - -:mod:`distutils.text_file` --- The TextFile class -================================================= - -.. module:: distutils.text_file - :synopsis: Provides the TextFile class, a simple interface to text files - - -This module provides the :class:`TextFile` class, which gives an interface to -text files that (optionally) takes care of stripping comments, ignoring blank -lines, and joining lines with backslashes. - - -.. class:: TextFile([filename=None, file=None, **options]) - - This class provides a file-like object that takes care of all the things you - commonly want to do when processing a text file that has some line-by-line - syntax: strip comments (as long as ``#`` is your comment character), skip blank - lines, join adjacent lines by escaping the newline (ie. backslash at end of - line), strip leading and/or trailing whitespace. All of these are optional and - independently controllable. - - The class provides a :meth:`warn` method so you can generate warning messages - that report physical line number, even if the logical line in question spans - multiple physical lines. Also provides :meth:`unreadline` for implementing - line-at-a-time lookahead. - - :class:`TextFile` instances are create with either *filename*, *file*, or both. - :exc:`RuntimeError` is raised if both are ``None``. *filename* should be a - string, and *file* a file object (or something that provides :meth:`readline` - and :meth:`close` methods). It is recommended that you supply at least - *filename*, so that :class:`TextFile` can include it in warning messages. If - *file* is not supplied, :class:`TextFile` creates its own using the - :func:`open` built-in function. - - The options are all boolean, and affect the values returned by :meth:`readline` - - .. tabularcolumns:: |l|L|l| - - +------------------+--------------------------------+---------+ - | option name | description | default | - +==================+================================+=========+ - | *strip_comments* | strip from ``'#'`` to | true | - | | end-of-line, as well as any | | - | | whitespace leading up to the | | - | | ``'#'``\ ---unless it is | | - | | escaped by a backslash | | - +------------------+--------------------------------+---------+ - | *lstrip_ws* | strip leading whitespace from | false | - | | each line before returning it | | - +------------------+--------------------------------+---------+ - | *rstrip_ws* | strip trailing whitespace | true | - | | (including line terminator!) | | - | | from each line before | | - | | returning it. | | - +------------------+--------------------------------+---------+ - | *skip_blanks* | skip lines that are empty | true | - | | \*after\* stripping comments | | - | | and whitespace. (If both | | - | | lstrip_ws and rstrip_ws are | | - | | false, then some lines may | | - | | consist of solely whitespace: | | - | | these will \*not\* be skipped, | | - | | even if *skip_blanks* is | | - | | true.) | | - +------------------+--------------------------------+---------+ - | *join_lines* | if a backslash is the last | false | - | | non-newline character on a | | - | | line after stripping comments | | - | | and whitespace, join the | | - | | following line to it to form | | - | | one logical line; if N | | - | | consecutive lines end with a | | - | | backslash, then N+1 physical | | - | | lines will be joined to form | | - | | one logical line. | | - +------------------+--------------------------------+---------+ - | *collapse_join* | strip leading whitespace from | false | - | | lines that are joined to their | | - | | predecessor; only matters if | | - | | ``(join_lines and not | | - | | lstrip_ws)`` | | - +------------------+--------------------------------+---------+ - - Note that since *rstrip_ws* can strip the trailing newline, the semantics of - :meth:`readline` must differ from those of the built-in file object's - :meth:`readline` method! In particular, :meth:`readline` returns ``None`` for - end-of-file: an empty string might just be a blank line (or an all-whitespace - line), if *rstrip_ws* is true but *skip_blanks* is not. - - - .. method:: TextFile.open(filename) - - Open a new file *filename*. This overrides any *file* or *filename* - constructor arguments. - - - .. method:: TextFile.close() - - Close the current file and forget everything we know about it (including the - filename and the current line number). - - - .. method:: TextFile.warn(msg[,line=None]) - - Print (to stderr) a warning message tied to the current logical line in the - current file. If the current logical line in the file spans multiple physical - lines, the warning refers to the whole range, such as ``"lines 3-5"``. If - *line* is supplied, it overrides the current line number; it may be a list or - tuple to indicate a range of physical lines, or an integer for a single - physical line. - - - .. method:: TextFile.readline() - - Read and return a single logical line from the current file (or from an internal - buffer if lines have previously been "unread" with :meth:`unreadline`). If the - *join_lines* option is true, this may involve reading multiple physical lines - concatenated into a single string. Updates the current line number, so calling - :meth:`warn` after :meth:`readline` emits a warning about the physical line(s) - just read. Returns ``None`` on end-of-file, since the empty string can occur - if *rstrip_ws* is true but *strip_blanks* is not. - - - .. method:: TextFile.readlines() - - Read and return the list of all logical lines remaining in the current file. - This updates the current line number to the last line of the file. - - - .. method:: TextFile.unreadline(line) - - Push *line* (a string) onto an internal buffer that will be checked by future - :meth:`readline` calls. Handy for implementing a parser with line-at-a-time - lookahead. Note that lines that are "unread" with :meth:`unreadline` are not - subsequently re-cleansed (whitespace stripped, or whatever) when read with - :meth:`readline`. If multiple calls are made to :meth:`unreadline` before a call - to :meth:`readline`, the lines will be returned most in most recent first order. - - -:mod:`distutils.version` --- Version number classes -=================================================== - -.. module:: distutils.version - :synopsis: Implements classes that represent module version numbers. - - -.. % todo -.. % \section{Distutils Commands} -.. % -.. % This part of Distutils implements the various Distutils commands, such -.. % as \code{build}, \code{install} \&c. Each command is implemented as a -.. % separate module, with the command name as the name of the module. - - -:mod:`distutils.cmd` --- Abstract base class for Distutils commands -=================================================================== - -.. module:: distutils.cmd - :synopsis: Provides the abstract base class :class:`~distutils.cmd.Command`. This class - is subclassed by the modules in the distutils.command subpackage. - - -This module supplies the abstract base class :class:`Command`. - - -.. class:: Command(dist) - - Abstract base class for defining command classes, the "worker bees" of the - Distutils. A useful analogy for command classes is to think of them as - subroutines with local variables called *options*. The options are declared - in :meth:`initialize_options` and defined (given their final values) in - :meth:`finalize_options`, both of which must be defined by every command - class. The distinction between the two is necessary because option values - might come from the outside world (command line, config file, ...), and any - options dependent on other options must be computed after these outside - influences have been processed --- hence :meth:`finalize_options`. The body - of the subroutine, where it does all its work based on the values of its - options, is the :meth:`run` method, which must also be implemented by every - command class. - - The class constructor takes a single argument *dist*, a - :class:`~distutils.core.Distribution` instance. - - -Creating a new Distutils command -================================ - -This section outlines the steps to create a new Distutils command. - -A new command lives in a module in the :mod:`distutils.command` package. There -is a sample template in that directory called :file:`command_template`. Copy -this file to a new module with the same name as the new command you're -implementing. This module should implement a class with the same name as the -module (and the command). So, for instance, to create the command -``peel_banana`` (so that users can run ``setup.py peel_banana``), you'd copy -:file:`command_template` to :file:`distutils/command/peel_banana.py`, then edit -it so that it's implementing the class :class:`peel_banana`, a subclass of -:class:`distutils.cmd.Command`. - -Subclasses of :class:`Command` must define the following methods. - -.. method:: Command.initialize_options() - - Set default values for all the options that this command supports. Note that - these defaults may be overridden by other commands, by the setup script, by - config files, or by the command-line. Thus, this is not the place to code - dependencies between options; generally, :meth:`initialize_options` - implementations are just a bunch of ``self.foo = None`` assignments. - - -.. method:: Command.finalize_options() - - Set final values for all the options that this command supports. This is - always called as late as possible, ie. after any option assignments from the - command-line or from other commands have been done. Thus, this is the place - to code option dependencies: if *foo* depends on *bar*, then it is safe to - set *foo* from *bar* as long as *foo* still has the same value it was - assigned in :meth:`initialize_options`. - - -.. method:: Command.run() - - A command's raison d'etre: carry out the action it exists to perform, controlled - by the options initialized in :meth:`initialize_options`, customized by other - commands, the setup script, the command-line, and config files, and finalized in - :meth:`finalize_options`. All terminal output and filesystem interaction should - be done by :meth:`run`. - - -.. attribute:: Command.sub_commands - - *sub_commands* formalizes the notion of a "family" of commands, - e.g. ``install`` as the parent with sub-commands ``install_lib``, - ``install_headers``, etc. The parent of a family of commands defines - *sub_commands* as a class attribute; it's a list of 2-tuples ``(command_name, - predicate)``, with *command_name* a string and *predicate* a function, a - string or ``None``. *predicate* is a method of the parent command that - determines whether the corresponding command is applicable in the current - situation. (E.g. ``install_headers`` is only applicable if we have any C - header files to install.) If *predicate* is ``None``, that command is always - applicable. - - *sub_commands* is usually defined at the *end* of a class, because - predicates can be methods of the class, so they must already have been - defined. The canonical example is the :command:`install` command. - - -:mod:`distutils.command` --- Individual Distutils commands -========================================================== - -.. module:: distutils.command - :synopsis: Contains one module for each standard Distutils command. - - -.. % \subsubsection{Individual Distutils commands} -.. % todo - - -:mod:`distutils.command.bdist` --- Build a binary installer -=========================================================== - -.. module:: distutils.command.bdist - :synopsis: Build a binary installer for a package - - -.. % todo - - -:mod:`distutils.command.bdist_packager` --- Abstract base class for packagers -============================================================================= - -.. module:: distutils.command.bdist_packager - :synopsis: Abstract base class for packagers - - -.. % todo - - -:mod:`distutils.command.bdist_dumb` --- Build a "dumb" installer -================================================================ - -.. module:: distutils.command.bdist_dumb - :synopsis: Build a "dumb" installer - a simple archive of files - - -.. % todo - - -:mod:`distutils.command.bdist_rpm` --- Build a binary distribution as a Redhat RPM and SRPM -=========================================================================================== - -.. module:: distutils.command.bdist_rpm - :synopsis: Build a binary distribution as a Redhat RPM and SRPM - - -.. % todo - - -:mod:`distutils.command.sdist` --- Build a source distribution -============================================================== - -.. module:: distutils.command.sdist - :synopsis: Build a source distribution - - -.. % todo - - -:mod:`distutils.command.build` --- Build all files of a package -=============================================================== - -.. module:: distutils.command.build - :synopsis: Build all files of a package - - -.. % todo - - -:mod:`distutils.command.build_clib` --- Build any C libraries in a package -========================================================================== - -.. module:: distutils.command.build_clib - :synopsis: Build any C libraries in a package - - -.. % todo - - -:mod:`distutils.command.build_ext` --- Build any extensions in a package -======================================================================== - -.. module:: distutils.command.build_ext - :synopsis: Build any extensions in a package - - -.. % todo - - -:mod:`distutils.command.build_py` --- Build the .py/.pyc files of a package -=========================================================================== - -.. module:: distutils.command.build_py - :synopsis: Build the .py/.pyc files of a package - - -.. class:: build_py - -.. class:: build_py_2to3 - - Alternative implementation of build_py which also runs the - 2to3 conversion library on each .py file that is going to be - installed. To use this in a setup.py file for a distribution - that is designed to run with both Python 2.x and 3.x, add:: - - try: - from distutils.command.build_py import build_py_2to3 as build_py - except ImportError: - from distutils.command.build_py import build_py - - to your setup.py, and later:: - - cmdclass = {'build_py': build_py} - - to the invocation of setup(). - - -:mod:`distutils.command.build_scripts` --- Build the scripts of a package -========================================================================= - -.. module:: distutils.command.build_scripts - :synopsis: Build the scripts of a package - - -.. % todo - - -:mod:`distutils.command.clean` --- Clean a package build area -============================================================= - -.. module:: distutils.command.clean - :synopsis: Clean a package build area - -This command removes the temporary files created by :command:`build` -and its subcommands, like intermediary compiled object files. With -the ``--all`` option, the complete build directory will be removed. - -Extension modules built :ref:`in place <distutils-build-ext-inplace>` -will not be cleaned, as they are not in the build directory. - - -:mod:`distutils.command.config` --- Perform package configuration -================================================================= - -.. module:: distutils.command.config - :synopsis: Perform package configuration - - -.. % todo - - -:mod:`distutils.command.install` --- Install a package -====================================================== - -.. module:: distutils.command.install - :synopsis: Install a package - - -.. % todo - - -:mod:`distutils.command.install_data` --- Install data files from a package -=========================================================================== - -.. module:: distutils.command.install_data - :synopsis: Install data files from a package - - -.. % todo - - -:mod:`distutils.command.install_headers` --- Install C/C++ header files from a package -====================================================================================== - -.. module:: distutils.command.install_headers - :synopsis: Install C/C++ header files from a package - - -.. % todo - - -:mod:`distutils.command.install_lib` --- Install library files from a package -============================================================================= - -.. module:: distutils.command.install_lib - :synopsis: Install library files from a package - - -.. % todo - - -:mod:`distutils.command.install_scripts` --- Install script files from a package -================================================================================ - -.. module:: distutils.command.install_scripts - :synopsis: Install script files from a package - - -.. % todo - - -:mod:`distutils.command.register` --- Register a module with the Python Package Index -===================================================================================== - -.. module:: distutils.command.register - :synopsis: Register a module with the Python Package Index - - -The ``register`` command registers the package with the Python Package Index. -This is described in more detail in :pep:`301`. - -.. % todo - - -:mod:`distutils.command.check` --- Check the meta-data of a package -=================================================================== - -.. module:: distutils.command.check - :synopsis: Check the meta-data of a package - - -The ``check`` command performs some tests on the meta-data of a package. -For example, it verifies that all required meta-data are provided as -the arguments passed to the :func:`setup` function. - -.. % todo diff --git a/Doc/distutils/builtdist.rst b/Doc/distutils/builtdist.rst deleted file mode 100644 index c1d9ea533dab6599a52f2ad3f5a5b7aca437323c..0000000000000000000000000000000000000000 --- a/Doc/distutils/builtdist.rst +++ /dev/null @@ -1,392 +0,0 @@ -.. _built-dist: - -**************************** -Creating Built Distributions -**************************** - -.. include:: ./_setuptools_disclaimer.rst - -A "built distribution" is what you're probably used to thinking of either as a -"binary package" or an "installer" (depending on your background). It's not -necessarily binary, though, because it might contain only Python source code -and/or byte-code; and we don't call it a package, because that word is already -spoken for in Python. (And "installer" is a term specific to the world of -mainstream desktop systems.) - -A built distribution is how you make life as easy as possible for installers of -your module distribution: for users of RPM-based Linux systems, it's a binary -RPM; for Windows users, it's an executable installer; for Debian-based Linux -users, it's a Debian package; and so forth. Obviously, no one person will be -able to create built distributions for every platform under the sun, so the -Distutils are designed to enable module developers to concentrate on their -specialty---writing code and creating source distributions---while an -intermediary species called *packagers* springs up to turn source distributions -into built distributions for as many platforms as there are packagers. - -Of course, the module developer could be their own packager; or the packager could -be a volunteer "out there" somewhere who has access to a platform which the -original developer does not; or it could be software periodically grabbing new -source distributions and turning them into built distributions for as many -platforms as the software has access to. Regardless of who they are, a packager -uses the setup script and the :command:`bdist` command family to generate built -distributions. - -As a simple example, if I run the following command in the Distutils source -tree:: - - python setup.py bdist - -then the Distutils builds my module distribution (the Distutils itself in this -case), does a "fake" installation (also in the :file:`build` directory), and -creates the default type of built distribution for my platform. The default -format for built distributions is a "dumb" tar file on Unix, and a simple -executable installer on Windows. (That tar file is considered "dumb" because it -has to be unpacked in a specific location to work.) - -Thus, the above command on a Unix system creates -:file:`Distutils-1.0.{plat}.tar.gz`; unpacking this tarball from the right place -installs the Distutils just as though you had downloaded the source distribution -and run ``python setup.py install``. (The "right place" is either the root of -the filesystem or Python's :file:`{prefix}` directory, depending on the options -given to the :command:`bdist_dumb` command; the default is to make dumb -distributions relative to :file:`{prefix}`.) - -Obviously, for pure Python distributions, this isn't any simpler than just -running ``python setup.py install``\ ---but for non-pure distributions, which -include extensions that would need to be compiled, it can mean the difference -between someone being able to use your extensions or not. And creating "smart" -built distributions, such as an RPM package or an executable installer for -Windows, is far more convenient for users even if your distribution doesn't -include any extensions. - -The :command:`bdist` command has a :option:`!--formats` option, similar to the -:command:`sdist` command, which you can use to select the types of built -distribution to generate: for example, :: - - python setup.py bdist --format=zip - -would, when run on a Unix system, create -:file:`Distutils-1.0.{plat}.zip`\ ---again, this archive would be unpacked -from the root directory to install the Distutils. - -The available formats for built distributions are: - -+-------------+------------------------------+---------+ -| Format | Description | Notes | -+=============+==============================+=========+ -| ``gztar`` | gzipped tar file | \(1) | -| | (:file:`.tar.gz`) | | -+-------------+------------------------------+---------+ -| ``bztar`` | bzipped tar file | | -| | (:file:`.tar.bz2`) | | -+-------------+------------------------------+---------+ -| ``xztar`` | xzipped tar file | | -| | (:file:`.tar.xz`) | | -+-------------+------------------------------+---------+ -| ``ztar`` | compressed tar file | \(3) | -| | (:file:`.tar.Z`) | | -+-------------+------------------------------+---------+ -| ``tar`` | tar file (:file:`.tar`) | | -+-------------+------------------------------+---------+ -| ``zip`` | zip file (:file:`.zip`) | (2),(4) | -+-------------+------------------------------+---------+ -| ``rpm`` | RPM | \(5) | -+-------------+------------------------------+---------+ -| ``pkgtool`` | Solaris :program:`pkgtool` | | -+-------------+------------------------------+---------+ -| ``sdux`` | HP-UX :program:`swinstall` | | -+-------------+------------------------------+---------+ -| ``msi`` | Microsoft Installer. | | -+-------------+------------------------------+---------+ - -.. versionchanged:: 3.5 - Added support for the ``xztar`` format. - - -Notes: - -(1) - default on Unix - -(2) - default on Windows - -(3) - requires external :program:`compress` utility. - -(4) - requires either external :program:`zip` utility or :mod:`zipfile` module (part - of the standard Python library since Python 1.6) - -(5) - requires external :program:`rpm` utility, version 3.0.4 or better (use ``rpm - --version`` to find out which version you have) - -You don't have to use the :command:`bdist` command with the :option:`!--formats` -option; you can also use the command that directly implements the format you're -interested in. Some of these :command:`bdist` "sub-commands" actually generate -several similar formats; for instance, the :command:`bdist_dumb` command -generates all the "dumb" archive formats (``tar``, ``gztar``, ``bztar``, -``xztar``, ``ztar``, and ``zip``), and :command:`bdist_rpm` generates both -binary and source RPMs. The :command:`bdist` sub-commands, and the formats -generated by each, are: - -+--------------------------+-------------------------------------+ -| Command | Formats | -+==========================+=====================================+ -| :command:`bdist_dumb` | tar, gztar, bztar, xztar, ztar, zip | -+--------------------------+-------------------------------------+ -| :command:`bdist_rpm` | rpm, srpm | -+--------------------------+-------------------------------------+ - -The following sections give details on the individual :command:`bdist_\*` -commands. - - -.. .. _creating-dumb: - -.. Creating dumb built distributions -.. ================================= - -.. XXX Need to document absolute vs. prefix-relative packages here, but first - I have to implement it! - - -.. _creating-rpms: - -Creating RPM packages -===================== - -The RPM format is used by many popular Linux distributions, including Red Hat, -SuSE, and Mandrake. If one of these (or any of the other RPM-based Linux -distributions) is your usual environment, creating RPM packages for other users -of that same distribution is trivial. Depending on the complexity of your module -distribution and differences between Linux distributions, you may also be able -to create RPMs that work on different RPM-based distributions. - -The usual way to create an RPM of your module distribution is to run the -:command:`bdist_rpm` command:: - - python setup.py bdist_rpm - -or the :command:`bdist` command with the :option:`!--format` option:: - - python setup.py bdist --formats=rpm - -The former allows you to specify RPM-specific options; the latter allows you to -easily specify multiple formats in one run. If you need to do both, you can -explicitly specify multiple :command:`bdist_\*` commands and their options:: - - python setup.py bdist_rpm --packager="John Doe <jdoe@example.org>" - -Creating RPM packages is driven by a :file:`.spec` file, much as using the -Distutils is driven by the setup script. To make your life easier, the -:command:`bdist_rpm` command normally creates a :file:`.spec` file based on the -information you supply in the setup script, on the command line, and in any -Distutils configuration files. Various options and sections in the -:file:`.spec` file are derived from options in the setup script as follows: - -+------------------------------------------+----------------------------------------------+ -| RPM :file:`.spec` file option or section | Distutils setup script option | -+==========================================+==============================================+ -| Name | ``name`` | -+------------------------------------------+----------------------------------------------+ -| Summary (in preamble) | ``description`` | -+------------------------------------------+----------------------------------------------+ -| Version | ``version`` | -+------------------------------------------+----------------------------------------------+ -| Vendor | ``author`` and ``author_email``, | -| | or --- & ``maintainer`` and | -| | ``maintainer_email`` | -+------------------------------------------+----------------------------------------------+ -| Copyright | ``license`` | -+------------------------------------------+----------------------------------------------+ -| Url | ``url`` | -+------------------------------------------+----------------------------------------------+ -| %description (section) | ``long_description`` | -+------------------------------------------+----------------------------------------------+ - -Additionally, there are many options in :file:`.spec` files that don't have -corresponding options in the setup script. Most of these are handled through -options to the :command:`bdist_rpm` command as follows: - -+-------------------------------+-----------------------------+-------------------------+ -| RPM :file:`.spec` file option | :command:`bdist_rpm` option | default value | -| or section | | | -+===============================+=============================+=========================+ -| Release | ``release`` | "1" | -+-------------------------------+-----------------------------+-------------------------+ -| Group | ``group`` | "Development/Libraries" | -+-------------------------------+-----------------------------+-------------------------+ -| Vendor | ``vendor`` | (see above) | -+-------------------------------+-----------------------------+-------------------------+ -| Packager | ``packager`` | (none) | -+-------------------------------+-----------------------------+-------------------------+ -| Provides | ``provides`` | (none) | -+-------------------------------+-----------------------------+-------------------------+ -| Requires | ``requires`` | (none) | -+-------------------------------+-----------------------------+-------------------------+ -| Conflicts | ``conflicts`` | (none) | -+-------------------------------+-----------------------------+-------------------------+ -| Obsoletes | ``obsoletes`` | (none) | -+-------------------------------+-----------------------------+-------------------------+ -| Distribution | ``distribution_name`` | (none) | -+-------------------------------+-----------------------------+-------------------------+ -| BuildRequires | ``build_requires`` | (none) | -+-------------------------------+-----------------------------+-------------------------+ -| Icon | ``icon`` | (none) | -+-------------------------------+-----------------------------+-------------------------+ - -Obviously, supplying even a few of these options on the command-line would be -tedious and error-prone, so it's usually best to put them in the setup -configuration file, :file:`setup.cfg`\ ---see section :ref:`setup-config`. If -you distribute or package many Python module distributions, you might want to -put options that apply to all of them in your personal Distutils configuration -file (:file:`~/.pydistutils.cfg`). If you want to temporarily disable -this file, you can pass the :option:`!--no-user-cfg` option to :file:`setup.py`. - -There are three steps to building a binary RPM package, all of which are -handled automatically by the Distutils: - -#. create a :file:`.spec` file, which describes the package (analogous to the - Distutils setup script; in fact, much of the information in the setup script - winds up in the :file:`.spec` file) - -#. create the source RPM - -#. create the "binary" RPM (which may or may not contain binary code, depending - on whether your module distribution contains Python extensions) - -Normally, RPM bundles the last two steps together; when you use the Distutils, -all three steps are typically bundled together. - -If you wish, you can separate these three steps. You can use the -:option:`!--spec-only` option to make :command:`bdist_rpm` just create the -:file:`.spec` file and exit; in this case, the :file:`.spec` file will be -written to the "distribution directory"---normally :file:`dist/`, but -customizable with the :option:`!--dist-dir` option. (Normally, the :file:`.spec` -file winds up deep in the "build tree," in a temporary directory created by -:command:`bdist_rpm`.) - -.. % \XXX{this isn't implemented yet---is it needed?!} -.. % You can also specify a custom \file{.spec} file with the -.. % \longprogramopt{spec-file} option; used in conjunction with -.. % \longprogramopt{spec-only}, this gives you an opportunity to customize -.. % the \file{.spec} file manually: -.. % -.. % \ begin{verbatim} -.. % > python setup.py bdist_rpm --spec-only -.. % # ...edit dist/FooBar-1.0.spec -.. % > python setup.py bdist_rpm --spec-file=dist/FooBar-1.0.spec -.. % \ end{verbatim} -.. % -.. % (Although a better way to do this is probably to override the standard -.. % \command{bdist\_rpm} command with one that writes whatever else you want -.. % to the \file{.spec} file.) - - -.. _cross-compile-windows: - -Cross-compiling on Windows -========================== - -Starting with Python 2.6, distutils is capable of cross-compiling between -Windows platforms. In practice, this means that with the correct tools -installed, you can use a 32bit version of Windows to create 64bit extensions -and vice-versa. - -To build for an alternate platform, specify the :option:`!--plat-name` option -to the build command. Valid values are currently 'win32', and 'win-amd64'. -For example, on a 32bit version of Windows, you could execute:: - - python setup.py build --plat-name=win-amd64 - -to build a 64bit version of your extension. - -would create a 64bit installation executable on your 32bit version of Windows. - -To cross-compile, you must download the Python source code and cross-compile -Python itself for the platform you are targeting - it is not possible from a -binary installation of Python (as the .lib etc file for other platforms are -not included.) In practice, this means the user of a 32 bit operating -system will need to use Visual Studio 2008 to open the -:file:`PCbuild/PCbuild.sln` solution in the Python source tree and build the -"x64" configuration of the 'pythoncore' project before cross-compiling -extensions is possible. - -Note that by default, Visual Studio 2008 does not install 64bit compilers or -tools. You may need to reexecute the Visual Studio setup process and select -these tools (using Control Panel->[Add/Remove] Programs is a convenient way to -check or modify your existing install.) - -.. _postinstallation-script: - -The Postinstallation script ---------------------------- - -Starting with Python 2.3, a postinstallation script can be specified with the -:option:`!--install-script` option. The basename of the script must be -specified, and the script filename must also be listed in the scripts argument -to the setup function. - -This script will be run at installation time on the target system after all the -files have been copied, with ``argv[1]`` set to :option:`!-install`, and again at -uninstallation time before the files are removed with ``argv[1]`` set to -:option:`!-remove`. - -The installation script runs embedded in the windows installer, every output -(``sys.stdout``, ``sys.stderr``) is redirected into a buffer and will be -displayed in the GUI after the script has finished. - -Some functions especially useful in this context are available as additional -built-in functions in the installation script. - - -.. function:: directory_created(path) - file_created(path) - - These functions should be called when a directory or file is created by the - postinstall script at installation time. It will register *path* with the - uninstaller, so that it will be removed when the distribution is uninstalled. - To be safe, directories are only removed if they are empty. - - -.. function:: get_special_folder_path(csidl_string) - - This function can be used to retrieve special folder locations on Windows like - the Start Menu or the Desktop. It returns the full path to the folder. - *csidl_string* must be one of the following strings:: - - "CSIDL_APPDATA" - - "CSIDL_COMMON_STARTMENU" - "CSIDL_STARTMENU" - - "CSIDL_COMMON_DESKTOPDIRECTORY" - "CSIDL_DESKTOPDIRECTORY" - - "CSIDL_COMMON_STARTUP" - "CSIDL_STARTUP" - - "CSIDL_COMMON_PROGRAMS" - "CSIDL_PROGRAMS" - - "CSIDL_FONTS" - - If the folder cannot be retrieved, :exc:`OSError` is raised. - - Which folders are available depends on the exact Windows version, and probably - also the configuration. For details refer to Microsoft's documentation of the - :c:func:`SHGetSpecialFolderPath` function. - - -.. function:: create_shortcut(target, description, filename[, arguments[, workdir[, iconpath[, iconindex]]]]) - - This function creates a shortcut. *target* is the path to the program to be - started by the shortcut. *description* is the description of the shortcut. - *filename* is the title of the shortcut that the user will see. *arguments* - specifies the command line arguments, if any. *workdir* is the working directory - for the program. *iconpath* is the file containing the icon for the shortcut, - and *iconindex* is the index of the icon in the file *iconpath*. Again, for - details consult the Microsoft documentation for the :class:`IShellLink` - interface. diff --git a/Doc/distutils/commandref.rst b/Doc/distutils/commandref.rst deleted file mode 100644 index 3e247e68d3a05f4333cdb64545c447f96e9e9ce9..0000000000000000000000000000000000000000 --- a/Doc/distutils/commandref.rst +++ /dev/null @@ -1,105 +0,0 @@ -.. _reference: - -***************** -Command Reference -***************** - -.. include:: ./_setuptools_disclaimer.rst - -.. % \section{Building modules: the \protect\command{build} command family} -.. % \label{build-cmds} -.. % \subsubsection{\protect\command{build}} -.. % \label{build-cmd} -.. % \subsubsection{\protect\command{build\_py}} -.. % \label{build-py-cmd} -.. % \subsubsection{\protect\command{build\_ext}} -.. % \label{build-ext-cmd} -.. % \subsubsection{\protect\command{build\_clib}} -.. % \label{build-clib-cmd} - - -.. _install-cmd: - -Installing modules: the :command:`install` command family -========================================================= - -The install command ensures that the build commands have been run and then runs -the subcommands :command:`install_lib`, :command:`install_data` and -:command:`install_scripts`. - -.. % \subsubsection{\protect\command{install\_lib}} -.. % \label{install-lib-cmd} - - -.. _install-data-cmd: - -:command:`install_data` ------------------------ - -This command installs all data files provided with the distribution. - - -.. _install-scripts-cmd: - -:command:`install_scripts` --------------------------- - -This command installs all (Python) scripts in the distribution. - -.. % \subsection{Cleaning up: the \protect\command{clean} command} -.. % \label{clean-cmd} - - -.. _sdist-cmd: - -Creating a source distribution: the :command:`sdist` command -============================================================ - -.. XXX fragment moved down from above: needs context! - -The manifest template commands are: - -+-------------------------------------------+-----------------------------------------------+ -| Command | Description | -+===========================================+===============================================+ -| :command:`include pat1 pat2 ...` | include all files matching any of the listed | -| | patterns | -+-------------------------------------------+-----------------------------------------------+ -| :command:`exclude pat1 pat2 ...` | exclude all files matching any of the listed | -| | patterns | -+-------------------------------------------+-----------------------------------------------+ -| :command:`recursive-include dir pat1 pat2 | include all files under *dir* matching any of | -| ...` | the listed patterns | -+-------------------------------------------+-----------------------------------------------+ -| :command:`recursive-exclude dir pat1 pat2 | exclude all files under *dir* matching any of | -| ...` | the listed patterns | -+-------------------------------------------+-----------------------------------------------+ -| :command:`global-include pat1 pat2 ...` | include all files anywhere in the source tree | -| | matching --- & any of the listed patterns | -+-------------------------------------------+-----------------------------------------------+ -| :command:`global-exclude pat1 pat2 ...` | exclude all files anywhere in the source tree | -| | matching --- & any of the listed patterns | -+-------------------------------------------+-----------------------------------------------+ -| :command:`prune dir` | exclude all files under *dir* | -+-------------------------------------------+-----------------------------------------------+ -| :command:`graft dir` | include all files under *dir* | -+-------------------------------------------+-----------------------------------------------+ - -The patterns here are Unix-style "glob" patterns: ``*`` matches any sequence of -regular filename characters, ``?`` matches any single regular filename -character, and ``[range]`` matches any of the characters in *range* (e.g., -``a-z``, ``a-zA-Z``, ``a-f0-9_.``). The definition of "regular filename -character" is platform-specific: on Unix it is anything except slash; on Windows -anything except backslash or colon. - -.. XXX Windows support not there yet - -.. % \section{Creating a built distribution: the -.. % \protect\command{bdist} command family} -.. % \label{bdist-cmds} - -.. % \subsection{\protect\command{bdist}} -.. % \subsection{\protect\command{bdist\_dumb}} -.. % \subsection{\protect\command{bdist\_rpm}} - - diff --git a/Doc/distutils/configfile.rst b/Doc/distutils/configfile.rst deleted file mode 100644 index 2a5c8329e318b7d244594ab626db24f2124c9ac2..0000000000000000000000000000000000000000 --- a/Doc/distutils/configfile.rst +++ /dev/null @@ -1,144 +0,0 @@ -.. _setup-config: - -************************************ -Writing the Setup Configuration File -************************************ - -.. include:: ./_setuptools_disclaimer.rst - -Often, it's not possible to write down everything needed to build a distribution -*a priori*: you may need to get some information from the user, or from the -user's system, in order to proceed. As long as that information is fairly -simple---a list of directories to search for C header files or libraries, for -example---then providing a configuration file, :file:`setup.cfg`, for users to -edit is a cheap and easy way to solicit it. Configuration files also let you -provide default values for any command option, which the installer can then -override either on the command-line or by editing the config file. - -The setup configuration file is a useful middle-ground between the setup -script---which, ideally, would be opaque to installers [#]_---and the command-line to -the setup script, which is outside of your control and entirely up to the -installer. In fact, :file:`setup.cfg` (and any other Distutils configuration -files present on the target system) are processed after the contents of the -setup script, but before the command-line. This has several useful -consequences: - -.. % (If you have more advanced needs, such as determining which extensions -.. % to build based on what capabilities are present on the target system, -.. % then you need the Distutils ``auto-configuration'' facility. This -.. % started to appear in Distutils 0.9 but, as of this writing, isn't mature -.. % or stable enough yet for real-world use.) - -* installers can override some of what you put in :file:`setup.py` by editing - :file:`setup.cfg` - -* you can provide non-standard defaults for options that are not easily set in - :file:`setup.py` - -* installers can override anything in :file:`setup.cfg` using the command-line - options to :file:`setup.py` - -The basic syntax of the configuration file is simple: - -.. code-block:: ini - - [command] - option=value - ... - -where *command* is one of the Distutils commands (e.g. :command:`build_py`, -:command:`install`), and *option* is one of the options that command supports. -Any number of options can be supplied for each command, and any number of -command sections can be included in the file. Blank lines are ignored, as are -comments, which run from a ``'#'`` character until the end of the line. Long -option values can be split across multiple lines simply by indenting the -continuation lines. - -You can find out the list of options supported by a particular command with the -universal :option:`!--help` option, e.g. - -.. code-block:: shell-session - - $ python setup.py --help build_ext - [...] - Options for 'build_ext' command: - --build-lib (-b) directory for compiled extension modules - --build-temp (-t) directory for temporary files (build by-products) - --inplace (-i) ignore build-lib and put compiled extensions into the - source directory alongside your pure Python modules - --include-dirs (-I) list of directories to search for header files - --define (-D) C preprocessor macros to define - --undef (-U) C preprocessor macros to undefine - --swig-opts list of SWIG command line options - [...] - -Note that an option spelled :option:`!--foo-bar` on the command-line is spelled -``foo_bar`` in configuration files. - -.. _distutils-build-ext-inplace: - -For example, say you want your extensions to be built "in-place"---that is, you -have an extension :mod:`pkg.ext`, and you want the compiled extension file -(:file:`ext.so` on Unix, say) to be put in the same source directory as your -pure Python modules :mod:`pkg.mod1` and :mod:`pkg.mod2`. You can always use the -:option:`!--inplace` option on the command-line to ensure this: - -.. code-block:: sh - - python setup.py build_ext --inplace - -But this requires that you always specify the :command:`build_ext` command -explicitly, and remember to provide :option:`!--inplace`. An easier way is to -"set and forget" this option, by encoding it in :file:`setup.cfg`, the -configuration file for this distribution: - -.. code-block:: ini - - [build_ext] - inplace=1 - -This will affect all builds of this module distribution, whether or not you -explicitly specify :command:`build_ext`. If you include :file:`setup.cfg` in -your source distribution, it will also affect end-user builds---which is -probably a bad idea for this option, since always building extensions in-place -would break installation of the module distribution. In certain peculiar cases, -though, modules are built right in their installation directory, so this is -conceivably a useful ability. (Distributing extensions that expect to be built -in their installation directory is almost always a bad idea, though.) - -Another example: certain commands take a lot of options that don't change from -run to run; for example, :command:`bdist_rpm` needs to know everything required -to generate a "spec" file for creating an RPM distribution. Some of this -information comes from the setup script, and some is automatically generated by -the Distutils (such as the list of files installed). But some of it has to be -supplied as options to :command:`bdist_rpm`, which would be very tedious to do -on the command-line for every run. Hence, here is a snippet from the Distutils' -own :file:`setup.cfg`: - -.. code-block:: ini - - [bdist_rpm] - release = 1 - packager = Greg Ward <gward@python.net> - doc_files = CHANGES.txt - README.txt - USAGE.txt - doc/ - examples/ - -Note that the ``doc_files`` option is simply a whitespace-separated string -split across multiple lines for readability. - - -.. seealso:: - - :ref:`inst-config-syntax` in "Installing Python Modules" - More information on the configuration files is available in the manual for - system administrators. - - -.. rubric:: Footnotes - -.. [#] This ideal probably won't be achieved until auto-configuration is fully - supported by the Distutils. - diff --git a/Doc/distutils/examples.rst b/Doc/distutils/examples.rst deleted file mode 100644 index e492b7f6057596b3af5a11178e4ebb2a5382f4e7..0000000000000000000000000000000000000000 --- a/Doc/distutils/examples.rst +++ /dev/null @@ -1,340 +0,0 @@ -.. _distutils_examples: - -****************** -Distutils Examples -****************** - -.. include:: ./_setuptools_disclaimer.rst - -This chapter provides a number of basic examples to help get started with -distutils. Additional information about using distutils can be found in the -Distutils Cookbook. - - -.. seealso:: - - `Distutils Cookbook <https://wiki.python.org/moin/Distutils/Cookbook>`_ - Collection of recipes showing how to achieve more control over distutils. - - -.. _pure-mod: - -Pure Python distribution (by module) -==================================== - -If you're just distributing a couple of modules, especially if they don't live -in a particular package, you can specify them individually using the -``py_modules`` option in the setup script. - -In the simplest case, you'll have two files to worry about: a setup script and -the single module you're distributing, :file:`foo.py` in this example:: - - <root>/ - setup.py - foo.py - -(In all diagrams in this section, *<root>* will refer to the distribution root -directory.) A minimal setup script to describe this situation would be:: - - from distutils.core import setup - setup(name='foo', - version='1.0', - py_modules=['foo'], - ) - -Note that the name of the distribution is specified independently with the -``name`` option, and there's no rule that says it has to be the same as -the name of the sole module in the distribution (although that's probably a good -convention to follow). However, the distribution name is used to generate -filenames, so you should stick to letters, digits, underscores, and hyphens. - -Since ``py_modules`` is a list, you can of course specify multiple -modules, eg. if you're distributing modules :mod:`foo` and :mod:`bar`, your -setup might look like this:: - - <root>/ - setup.py - foo.py - bar.py - -and the setup script might be :: - - from distutils.core import setup - setup(name='foobar', - version='1.0', - py_modules=['foo', 'bar'], - ) - -You can put module source files into another directory, but if you have enough -modules to do that, it's probably easier to specify modules by package rather -than listing them individually. - - -.. _pure-pkg: - -Pure Python distribution (by package) -===================================== - -If you have more than a couple of modules to distribute, especially if they are -in multiple packages, it's probably easier to specify whole packages rather than -individual modules. This works even if your modules are not in a package; you -can just tell the Distutils to process modules from the root package, and that -works the same as any other package (except that you don't have to have an -:file:`__init__.py` file). - -The setup script from the last example could also be written as :: - - from distutils.core import setup - setup(name='foobar', - version='1.0', - packages=[''], - ) - -(The empty string stands for the root package.) - -If those two files are moved into a subdirectory, but remain in the root -package, e.g.:: - - <root>/ - setup.py - src/ foo.py - bar.py - -then you would still specify the root package, but you have to tell the -Distutils where source files in the root package live:: - - from distutils.core import setup - setup(name='foobar', - version='1.0', - package_dir={'': 'src'}, - packages=[''], - ) - -More typically, though, you will want to distribute multiple modules in the same -package (or in sub-packages). For example, if the :mod:`foo` and :mod:`bar` -modules belong in package :mod:`foobar`, one way to layout your source tree is -:: - - <root>/ - setup.py - foobar/ - __init__.py - foo.py - bar.py - -This is in fact the default layout expected by the Distutils, and the one that -requires the least work to describe in your setup script:: - - from distutils.core import setup - setup(name='foobar', - version='1.0', - packages=['foobar'], - ) - -If you want to put modules in directories not named for their package, then you -need to use the ``package_dir`` option again. For example, if the -:file:`src` directory holds modules in the :mod:`foobar` package:: - - <root>/ - setup.py - src/ - __init__.py - foo.py - bar.py - -an appropriate setup script would be :: - - from distutils.core import setup - setup(name='foobar', - version='1.0', - package_dir={'foobar': 'src'}, - packages=['foobar'], - ) - -Or, you might put modules from your main package right in the distribution -root:: - - <root>/ - setup.py - __init__.py - foo.py - bar.py - -in which case your setup script would be :: - - from distutils.core import setup - setup(name='foobar', - version='1.0', - package_dir={'foobar': ''}, - packages=['foobar'], - ) - -(The empty string also stands for the current directory.) - -If you have sub-packages, they must be explicitly listed in ``packages``, -but any entries in ``package_dir`` automatically extend to sub-packages. -(In other words, the Distutils does *not* scan your source tree, trying to -figure out which directories correspond to Python packages by looking for -:file:`__init__.py` files.) Thus, if the default layout grows a sub-package:: - - <root>/ - setup.py - foobar/ - __init__.py - foo.py - bar.py - subfoo/ - __init__.py - blah.py - -then the corresponding setup script would be :: - - from distutils.core import setup - setup(name='foobar', - version='1.0', - packages=['foobar', 'foobar.subfoo'], - ) - - -.. _single-ext: - -Single extension module -======================= - -Extension modules are specified using the ``ext_modules`` option. -``package_dir`` has no effect on where extension source files are found; -it only affects the source for pure Python modules. The simplest case, a -single extension module in a single C source file, is:: - - <root>/ - setup.py - foo.c - -If the :mod:`foo` extension belongs in the root package, the setup script for -this could be :: - - from distutils.core import setup - from distutils.extension import Extension - setup(name='foobar', - version='1.0', - ext_modules=[Extension('foo', ['foo.c'])], - ) - -If the extension actually belongs in a package, say :mod:`foopkg`, then - -With exactly the same source tree layout, this extension can be put in the -:mod:`foopkg` package simply by changing the name of the extension:: - - from distutils.core import setup - from distutils.extension import Extension - setup(name='foobar', - version='1.0', - ext_modules=[Extension('foopkg.foo', ['foo.c'])], - ) - -Checking a package -================== - -The ``check`` command allows you to verify if your package meta-data -meet the minimum requirements to build a distribution. - -To run it, just call it using your :file:`setup.py` script. If something is -missing, ``check`` will display a warning. - -Let's take an example with a simple script:: - - from distutils.core import setup - - setup(name='foobar') - -Running the ``check`` command will display some warnings: - -.. code-block:: shell-session - - $ python setup.py check - running check - warning: check: missing required meta-data: version, url - warning: check: missing meta-data: either (author and author_email) or - (maintainer and maintainer_email) should be supplied - - -If you use the reStructuredText syntax in the ``long_description`` field and -`docutils`_ is installed you can check if the syntax is fine with the -``check`` command, using the ``restructuredtext`` option. - -For example, if the :file:`setup.py` script is changed like this:: - - from distutils.core import setup - - desc = """\ - My description - ============== - - This is the description of the ``foobar`` package. - """ - - setup(name='foobar', version='1', author='tarek', - author_email='tarek@ziade.org', - url='http://example.com', long_description=desc) - -Where the long description is broken, ``check`` will be able to detect it -by using the :mod:`docutils` parser: - -.. code-block:: shell-session - - $ python setup.py check --restructuredtext - running check - warning: check: Title underline too short. (line 2) - warning: check: Could not finish the parsing. - -Reading the metadata -===================== - -The :func:`distutils.core.setup` function provides a command-line interface -that allows you to query the metadata fields of a project through the -``setup.py`` script of a given project: - -.. code-block:: shell-session - - $ python setup.py --name - distribute - -This call reads the ``name`` metadata by running the -:func:`distutils.core.setup` function. Although, when a source or binary -distribution is created with Distutils, the metadata fields are written -in a static file called :file:`PKG-INFO`. When a Distutils-based project is -installed in Python, the :file:`PKG-INFO` file is copied alongside the modules -and packages of the distribution under :file:`NAME-VERSION-pyX.X.egg-info`, -where ``NAME`` is the name of the project, ``VERSION`` its version as defined -in the Metadata, and ``pyX.X`` the major and minor version of Python like -``2.7`` or ``3.2``. - -You can read back this static file, by using the -:class:`distutils.dist.DistributionMetadata` class and its -:func:`read_pkg_file` method:: - - >>> from distutils.dist import DistributionMetadata - >>> metadata = DistributionMetadata() - >>> metadata.read_pkg_file(open('distribute-0.6.8-py2.7.egg-info')) - >>> metadata.name - 'distribute' - >>> metadata.version - '0.6.8' - >>> metadata.description - 'Easily download, build, install, upgrade, and uninstall Python packages' - -Notice that the class can also be instantiated with a metadata file path to -loads its values:: - - >>> pkg_info_path = 'distribute-0.6.8-py2.7.egg-info' - >>> DistributionMetadata(pkg_info_path).name - 'distribute' - - -.. % \section{Multiple extension modules} -.. % \label{multiple-ext} - -.. % \section{Putting it all together} - - -.. _docutils: http://docutils.sourceforge.net diff --git a/Doc/distutils/extending.rst b/Doc/distutils/extending.rst deleted file mode 100644 index 1075e81779a7bae6806949bcd5cc089df856d3d0..0000000000000000000000000000000000000000 --- a/Doc/distutils/extending.rst +++ /dev/null @@ -1,98 +0,0 @@ -.. _extending-distutils: - -******************* -Extending Distutils -******************* - -.. include:: ./_setuptools_disclaimer.rst - -Distutils can be extended in various ways. Most extensions take the form of new -commands or replacements for existing commands. New commands may be written to -support new types of platform-specific packaging, for example, while -replacements for existing commands may be made to modify details of how the -command operates on a package. - -Most extensions of the distutils are made within :file:`setup.py` scripts that -want to modify existing commands; many simply add a few file extensions that -should be copied into packages in addition to :file:`.py` files as a -convenience. - -Most distutils command implementations are subclasses of the -:class:`distutils.cmd.Command` class. New commands may directly inherit from -:class:`Command`, while replacements often derive from :class:`Command` -indirectly, directly subclassing the command they are replacing. Commands are -required to derive from :class:`Command`. - -.. % \section{Extending existing commands} -.. % \label{extend-existing} - -.. % \section{Writing new commands} -.. % \label{new-commands} -.. % \XXX{Would an uninstall command be a good example here?} - - -Integrating new commands -======================== - -There are different ways to integrate new command implementations into -distutils. The most difficult is to lobby for the inclusion of the new features -in distutils itself, and wait for (and require) a version of Python that -provides that support. This is really hard for many reasons. - -The most common, and possibly the most reasonable for most needs, is to include -the new implementations with your :file:`setup.py` script, and cause the -:func:`distutils.core.setup` function use them:: - - from distutils.command.build_py import build_py as _build_py - from distutils.core import setup - - class build_py(_build_py): - """Specialized Python source builder.""" - - # implement whatever needs to be different... - - setup(cmdclass={'build_py': build_py}, - ...) - -This approach is most valuable if the new implementations must be used to use a -particular package, as everyone interested in the package will need to have the -new command implementation. - -Beginning with Python 2.4, a third option is available, intended to allow new -commands to be added which can support existing :file:`setup.py` scripts without -requiring modifications to the Python installation. This is expected to allow -third-party extensions to provide support for additional packaging systems, but -the commands can be used for anything distutils commands can be used for. A new -configuration option, ``command_packages`` (command-line option -:option:`!--command-packages`), can be used to specify additional packages to be -searched for modules implementing commands. Like all distutils options, this -can be specified on the command line or in a configuration file. This option -can only be set in the ``[global]`` section of a configuration file, or before -any commands on the command line. If set in a configuration file, it can be -overridden from the command line; setting it to an empty string on the command -line causes the default to be used. This should never be set in a configuration -file provided with a package. - -This new option can be used to add any number of packages to the list of -packages searched for command implementations; multiple package names should be -separated by commas. When not specified, the search is only performed in the -:mod:`distutils.command` package. When :file:`setup.py` is run with the option -``--command-packages distcmds,buildcmds``, however, the packages -:mod:`distutils.command`, :mod:`distcmds`, and :mod:`buildcmds` will be searched -in that order. New commands are expected to be implemented in modules of the -same name as the command by classes sharing the same name. Given the example -command line option above, the command :command:`bdist_openpkg` could be -implemented by the class :class:`distcmds.bdist_openpkg.bdist_openpkg` or -:class:`buildcmds.bdist_openpkg.bdist_openpkg`. - - -Adding new distribution types -============================= - -Commands that create distributions (files in the :file:`dist/` directory) need -to add ``(command, filename)`` pairs to ``self.distribution.dist_files`` so that -:command:`upload` can upload it to PyPI. The *filename* in the pair contains no -path information, only the name of the file itself. In dry-run mode, pairs -should still be added to represent what would have been created. - - diff --git a/Doc/distutils/index.rst b/Doc/distutils/index.rst deleted file mode 100644 index 2ccddc38b5f26ff674c1d4065755996518f2b5df..0000000000000000000000000000000000000000 --- a/Doc/distutils/index.rst +++ /dev/null @@ -1,49 +0,0 @@ -.. _distutils-index: - -############################################## - Distributing Python Modules (Legacy version) -############################################## - -:Authors: Greg Ward, Anthony Baxter -:Email: distutils-sig@python.org - -.. seealso:: - - :ref:`distributing-index` - The up to date module distribution documentations - -.. note:: - - The entire ``distutils`` package has been deprecated and will be - removed in Python 3.12. This documentation is retained as a - reference only, and will be removed with the package. See the - :ref:`What's New <distutils-deprecated>` entry for more information. - -.. include:: ./_setuptools_disclaimer.rst - -.. note:: - - This guide only covers the basic tools for building and distributing - extensions that are provided as part of this version of Python. Third party - tools offer easier to use and more secure alternatives. Refer to the `quick - recommendations section <https://packaging.python.org/guides/tool-recommendations/>`__ - in the Python Packaging User Guide for more information. - -This document describes the Python Distribution Utilities ("Distutils") from -the module developer's point of view, describing the underlying capabilities -that ``setuptools`` builds on to allow Python developers to make Python modules -and extensions readily available to a wider audience. - -.. toctree:: - :maxdepth: 2 - :numbered: - - introduction.rst - setupscript.rst - configfile.rst - sourcedist.rst - builtdist.rst - examples.rst - extending.rst - commandref.rst - apiref.rst diff --git a/Doc/distutils/introduction.rst b/Doc/distutils/introduction.rst deleted file mode 100644 index 87ed178e52bd4548b3e924c2b00e68f9a93f8725..0000000000000000000000000000000000000000 --- a/Doc/distutils/introduction.rst +++ /dev/null @@ -1,203 +0,0 @@ -.. _distutils-intro: - -**************************** -An Introduction to Distutils -**************************** - -.. include:: ./_setuptools_disclaimer.rst - -This document covers using the Distutils to distribute your Python modules, -concentrating on the role of developer/distributor: if you're looking for -information on installing Python modules, you should refer to the -:ref:`install-index` chapter. - - -.. _distutils-concepts: - -Concepts & Terminology -====================== - -Using the Distutils is quite simple, both for module developers and for -users/administrators installing third-party modules. As a developer, your -responsibilities (apart from writing solid, well-documented and well-tested -code, of course!) are: - -* write a setup script (:file:`setup.py` by convention) - -* (optional) write a setup configuration file - -* create a source distribution - -* (optional) create one or more built (binary) distributions - -Each of these tasks is covered in this document. - -Not all module developers have access to a multitude of platforms, so it's not -always feasible to expect them to create a multitude of built distributions. It -is hoped that a class of intermediaries, called *packagers*, will arise to -address this need. Packagers will take source distributions released by module -developers, build them on one or more platforms, and release the resulting built -distributions. Thus, users on the most popular platforms will be able to -install most popular Python module distributions in the most natural way for -their platform, without having to run a single setup script or compile a line of -code. - - -.. _distutils-simple-example: - -A Simple Example -================ - -The setup script is usually quite simple, although since it's written in Python, -there are no arbitrary limits to what you can do with it, though you should be -careful about putting arbitrarily expensive operations in your setup script. -Unlike, say, Autoconf-style configure scripts, the setup script may be run -multiple times in the course of building and installing your module -distribution. - -If all you want to do is distribute a module called :mod:`foo`, contained in a -file :file:`foo.py`, then your setup script can be as simple as this:: - - from distutils.core import setup - setup(name='foo', - version='1.0', - py_modules=['foo'], - ) - -Some observations: - -* most information that you supply to the Distutils is supplied as keyword - arguments to the :func:`setup` function - -* those keyword arguments fall into two categories: package metadata (name, - version number) and information about what's in the package (a list of pure - Python modules, in this case) - -* modules are specified by module name, not filename (the same will hold true - for packages and extensions) - -* it's recommended that you supply a little more metadata, in particular your - name, email address and a URL for the project (see section :ref:`setup-script` - for an example) - -To create a source distribution for this module, you would create a setup -script, :file:`setup.py`, containing the above code, and run this command from a -terminal:: - - python setup.py sdist - -For Windows, open a command prompt window (:menuselection:`Start --> -Accessories`) and change the command to:: - - setup.py sdist - -:command:`sdist` will create an archive file (e.g., tarball on Unix, ZIP file on Windows) -containing your setup script :file:`setup.py`, and your module :file:`foo.py`. -The archive file will be named :file:`foo-1.0.tar.gz` (or :file:`.zip`), and -will unpack into a directory :file:`foo-1.0`. - -If an end-user wishes to install your :mod:`foo` module, all they have to do is -download :file:`foo-1.0.tar.gz` (or :file:`.zip`), unpack it, and---from the -:file:`foo-1.0` directory---run :: - - python setup.py install - -which will ultimately copy :file:`foo.py` to the appropriate directory for -third-party modules in their Python installation. - -This simple example demonstrates some fundamental concepts of the Distutils. -First, both developers and installers have the same basic user interface, i.e. -the setup script. The difference is which Distutils *commands* they use: the -:command:`sdist` command is almost exclusively for module developers, while -:command:`install` is more often for installers (although most developers will -want to install their own code occasionally). - -Other useful built distribution formats are RPM, implemented by the -:command:`bdist_rpm` command, Solaris :program:`pkgtool` -(:command:`bdist_pkgtool`), and HP-UX :program:`swinstall` -(:command:`bdist_sdux`). For example, the following command will create an RPM -file called :file:`foo-1.0.noarch.rpm`:: - - python setup.py bdist_rpm - -(The :command:`bdist_rpm` command uses the :command:`rpm` executable, therefore -this has to be run on an RPM-based system such as Red Hat Linux, SuSE Linux, or -Mandrake Linux.) - -You can find out what distribution formats are available at any time by running -:: - - python setup.py bdist --help-formats - - -.. _python-terms: - -General Python terminology -========================== - -If you're reading this document, you probably have a good idea of what modules, -extensions, and so forth are. Nevertheless, just to be sure that everyone is -operating from a common starting point, we offer the following glossary of -common Python terms: - -module - the basic unit of code reusability in Python: a block of code imported by some - other code. Three types of modules concern us here: pure Python modules, - extension modules, and packages. - -pure Python module - a module written in Python and contained in a single :file:`.py` file (and - possibly associated :file:`.pyc` files). Sometimes referred to as a - "pure module." - -extension module - a module written in the low-level language of the Python implementation: C/C++ - for Python, Java for Jython. Typically contained in a single dynamically - loadable pre-compiled file, e.g. a shared object (:file:`.so`) file for Python - extensions on Unix, a DLL (given the :file:`.pyd` extension) for Python - extensions on Windows, or a Java class file for Jython extensions. (Note that - currently, the Distutils only handles C/C++ extensions for Python.) - -package - a module that contains other modules; typically contained in a directory in the - filesystem and distinguished from other directories by the presence of a file - :file:`__init__.py`. - -root package - the root of the hierarchy of packages. (This isn't really a package, since it - doesn't have an :file:`__init__.py` file. But we have to call it something.) - The vast majority of the standard library is in the root package, as are many - small, standalone third-party modules that don't belong to a larger module - collection. Unlike regular packages, modules in the root package can be found in - many directories: in fact, every directory listed in ``sys.path`` contributes - modules to the root package. - - -.. _distutils-term: - -Distutils-specific terminology -============================== - -The following terms apply more specifically to the domain of distributing Python -modules using the Distutils: - -module distribution - a collection of Python modules distributed together as a single downloadable - resource and meant to be installed *en masse*. Examples of some well-known - module distributions are NumPy, SciPy, Pillow, - or mxBase. (This would be called a *package*, except that term is - already taken in the Python context: a single module distribution may contain - zero, one, or many Python packages.) - -pure module distribution - a module distribution that contains only pure Python modules and packages. - Sometimes referred to as a "pure distribution." - -non-pure module distribution - a module distribution that contains at least one extension module. Sometimes - referred to as a "non-pure distribution." - -distribution root - the top-level directory of your source tree (or source distribution); the - directory where :file:`setup.py` exists. Generally :file:`setup.py` will be - run from this directory. diff --git a/Doc/distutils/packageindex.rst b/Doc/distutils/packageindex.rst deleted file mode 100644 index ccb9a598b2b7a2955e5377a0e47d24abdced6dea..0000000000000000000000000000000000000000 --- a/Doc/distutils/packageindex.rst +++ /dev/null @@ -1,16 +0,0 @@ -:orphan: - -.. _package-index: - -******************************* -The Python Package Index (PyPI) -******************************* - -The `Python Package Index (PyPI)`_ stores metadata describing distributions -packaged with distutils and other publishing tools, as well the distribution -archives themselves. - -References to up to date PyPI documentation can be found at -:ref:`publishing-python-packages`. - -.. _Python Package Index (PyPI): https://pypi.org diff --git a/Doc/distutils/setupscript.rst b/Doc/distutils/setupscript.rst deleted file mode 100644 index 4386a60b664bfb3581a8d554cdbf6278164a34dc..0000000000000000000000000000000000000000 --- a/Doc/distutils/setupscript.rst +++ /dev/null @@ -1,713 +0,0 @@ -.. _setup-script: - -************************ -Writing the Setup Script -************************ - -.. include:: ./_setuptools_disclaimer.rst - -The setup script is the centre of all activity in building, distributing, and -installing modules using the Distutils. The main purpose of the setup script is -to describe your module distribution to the Distutils, so that the various -commands that operate on your modules do the right thing. As we saw in section -:ref:`distutils-simple-example` above, the setup script consists mainly of a call to -:func:`setup`, and most information supplied to the Distutils by the module -developer is supplied as keyword arguments to :func:`setup`. - -Here's a slightly more involved example, which we'll follow for the next couple -of sections: the Distutils' own setup script. (Keep in mind that although the -Distutils are included with Python 1.6 and later, they also have an independent -existence so that Python 1.5.2 users can use them to install other module -distributions. The Distutils' own setup script, shown here, is used to install -the package into Python 1.5.2.) :: - - #!/usr/bin/env python - - from distutils.core import setup - - setup(name='Distutils', - version='1.0', - description='Python Distribution Utilities', - author='Greg Ward', - author_email='gward@python.net', - url='https://www.python.org/sigs/distutils-sig/', - packages=['distutils', 'distutils.command'], - ) - -There are only two differences between this and the trivial one-file -distribution presented in section :ref:`distutils-simple-example`: more metadata, and the -specification of pure Python modules by package, rather than by module. This is -important since the Distutils consist of a couple of dozen modules split into -(so far) two packages; an explicit list of every module would be tedious to -generate and difficult to maintain. For more information on the additional -meta-data, see section :ref:`meta-data`. - -Note that any pathnames (files or directories) supplied in the setup script -should be written using the Unix convention, i.e. slash-separated. The -Distutils will take care of converting this platform-neutral representation into -whatever is appropriate on your current platform before actually using the -pathname. This makes your setup script portable across operating systems, which -of course is one of the major goals of the Distutils. In this spirit, all -pathnames in this document are slash-separated. - -This, of course, only applies to pathnames given to Distutils functions. If -you, for example, use standard Python functions such as :func:`glob.glob` or -:func:`os.listdir` to specify files, you should be careful to write portable -code instead of hardcoding path separators:: - - glob.glob(os.path.join('mydir', 'subdir', '*.html')) - os.listdir(os.path.join('mydir', 'subdir')) - - -.. _listing-packages: - -Listing whole packages -====================== - -The ``packages`` option tells the Distutils to process (build, distribute, -install, etc.) all pure Python modules found in each package mentioned in the -``packages`` list. In order to do this, of course, there has to be a -correspondence between package names and directories in the filesystem. The -default correspondence is the most obvious one, i.e. package :mod:`distutils` is -found in the directory :file:`distutils` relative to the distribution root. -Thus, when you say ``packages = ['foo']`` in your setup script, you are -promising that the Distutils will find a file :file:`foo/__init__.py` (which -might be spelled differently on your system, but you get the idea) relative to -the directory where your setup script lives. If you break this promise, the -Distutils will issue a warning but still process the broken package anyway. - -If you use a different convention to lay out your source directory, that's no -problem: you just have to supply the ``package_dir`` option to tell the -Distutils about your convention. For example, say you keep all Python source -under :file:`lib`, so that modules in the "root package" (i.e., not in any -package at all) are in :file:`lib`, modules in the :mod:`foo` package are in -:file:`lib/foo`, and so forth. Then you would put :: - - package_dir = {'': 'lib'} - -in your setup script. The keys to this dictionary are package names, and an -empty package name stands for the root package. The values are directory names -relative to your distribution root. In this case, when you say ``packages = -['foo']``, you are promising that the file :file:`lib/foo/__init__.py` exists. - -Another possible convention is to put the :mod:`foo` package right in -:file:`lib`, the :mod:`foo.bar` package in :file:`lib/bar`, etc. This would be -written in the setup script as :: - - package_dir = {'foo': 'lib'} - -A ``package: dir`` entry in the ``package_dir`` dictionary implicitly -applies to all packages below *package*, so the :mod:`foo.bar` case is -automatically handled here. In this example, having ``packages = ['foo', -'foo.bar']`` tells the Distutils to look for :file:`lib/__init__.py` and -:file:`lib/bar/__init__.py`. (Keep in mind that although ``package_dir`` -applies recursively, you must explicitly list all packages in -``packages``: the Distutils will *not* recursively scan your source tree -looking for any directory with an :file:`__init__.py` file.) - - -.. _listing-modules: - -Listing individual modules -========================== - -For a small module distribution, you might prefer to list all modules rather -than listing packages---especially the case of a single module that goes in the -"root package" (i.e., no package at all). This simplest case was shown in -section :ref:`distutils-simple-example`; here is a slightly more involved example:: - - py_modules = ['mod1', 'pkg.mod2'] - -This describes two modules, one of them in the "root" package, the other in the -:mod:`pkg` package. Again, the default package/directory layout implies that -these two modules can be found in :file:`mod1.py` and :file:`pkg/mod2.py`, and -that :file:`pkg/__init__.py` exists as well. And again, you can override the -package/directory correspondence using the ``package_dir`` option. - - -.. _describing-extensions: - -Describing extension modules -============================ - -Just as writing Python extension modules is a bit more complicated than writing -pure Python modules, describing them to the Distutils is a bit more complicated. -Unlike pure modules, it's not enough just to list modules or packages and expect -the Distutils to go out and find the right files; you have to specify the -extension name, source file(s), and any compile/link requirements (include -directories, libraries to link with, etc.). - -.. XXX read over this section - -All of this is done through another keyword argument to :func:`setup`, the -``ext_modules`` option. ``ext_modules`` is just a list of -:class:`~distutils.core.Extension` instances, each of which describes a -single extension module. -Suppose your distribution includes a single extension, called :mod:`foo` and -implemented by :file:`foo.c`. If no additional instructions to the -compiler/linker are needed, describing this extension is quite simple:: - - Extension('foo', ['foo.c']) - -The :class:`Extension` class can be imported from :mod:`distutils.core` along -with :func:`setup`. Thus, the setup script for a module distribution that -contains only this one extension and nothing else might be:: - - from distutils.core import setup, Extension - setup(name='foo', - version='1.0', - ext_modules=[Extension('foo', ['foo.c'])], - ) - -The :class:`Extension` class (actually, the underlying extension-building -machinery implemented by the :command:`build_ext` command) supports a great deal -of flexibility in describing Python extensions, which is explained in the -following sections. - - -Extension names and packages ----------------------------- - -The first argument to the :class:`~distutils.core.Extension` constructor is -always the name of the extension, including any package names. For example, :: - - Extension('foo', ['src/foo1.c', 'src/foo2.c']) - -describes an extension that lives in the root package, while :: - - Extension('pkg.foo', ['src/foo1.c', 'src/foo2.c']) - -describes the same extension in the :mod:`pkg` package. The source files and -resulting object code are identical in both cases; the only difference is where -in the filesystem (and therefore where in Python's namespace hierarchy) the -resulting extension lives. - -If you have a number of extensions all in the same package (or all under the -same base package), use the ``ext_package`` keyword argument to -:func:`setup`. For example, :: - - setup(..., - ext_package='pkg', - ext_modules=[Extension('foo', ['foo.c']), - Extension('subpkg.bar', ['bar.c'])], - ) - -will compile :file:`foo.c` to the extension :mod:`pkg.foo`, and :file:`bar.c` to -:mod:`pkg.subpkg.bar`. - - -Extension source files ----------------------- - -The second argument to the :class:`~distutils.core.Extension` constructor is -a list of source -files. Since the Distutils currently only support C, C++, and Objective-C -extensions, these are normally C/C++/Objective-C source files. (Be sure to use -appropriate extensions to distinguish C++ source files: :file:`.cc` and -:file:`.cpp` seem to be recognized by both Unix and Windows compilers.) - -However, you can also include SWIG interface (:file:`.i`) files in the list; the -:command:`build_ext` command knows how to deal with SWIG extensions: it will run -SWIG on the interface file and compile the resulting C/C++ file into your -extension. - -.. XXX SWIG support is rough around the edges and largely untested! - -This warning notwithstanding, options to SWIG can be currently passed like -this:: - - setup(..., - ext_modules=[Extension('_foo', ['foo.i'], - swig_opts=['-modern', '-I../include'])], - py_modules=['foo'], - ) - -Or on the commandline like this:: - - > python setup.py build_ext --swig-opts="-modern -I../include" - -On some platforms, you can include non-source files that are processed by the -compiler and included in your extension. Currently, this just means Windows -message text (:file:`.mc`) files and resource definition (:file:`.rc`) files for -Visual C++. These will be compiled to binary resource (:file:`.res`) files and -linked into the executable. - - -Preprocessor options --------------------- - -Three optional arguments to :class:`~distutils.core.Extension` will help if -you need to specify include directories to search or preprocessor macros to -define/undefine: ``include_dirs``, ``define_macros``, and ``undef_macros``. - -For example, if your extension requires header files in the :file:`include` -directory under your distribution root, use the ``include_dirs`` option:: - - Extension('foo', ['foo.c'], include_dirs=['include']) - -You can specify absolute directories there; if you know that your extension will -only be built on Unix systems with X11R6 installed to :file:`/usr`, you can get -away with :: - - Extension('foo', ['foo.c'], include_dirs=['/usr/include/X11']) - -You should avoid this sort of non-portable usage if you plan to distribute your -code: it's probably better to write C code like :: - - #include <X11/Xlib.h> - -If you need to include header files from some other Python extension, you can -take advantage of the fact that header files are installed in a consistent way -by the Distutils :command:`install_headers` command. For example, the Numerical -Python header files are installed (on a standard Unix installation) to -:file:`/usr/local/include/python1.5/Numerical`. (The exact location will differ -according to your platform and Python installation.) Since the Python include -directory---\ :file:`/usr/local/include/python1.5` in this case---is always -included in the search path when building Python extensions, the best approach -is to write C code like :: - - #include <Numerical/arrayobject.h> - -If you must put the :file:`Numerical` include directory right into your header -search path, though, you can find that directory using the Distutils -:mod:`distutils.sysconfig` module:: - - from distutils.sysconfig import get_python_inc - incdir = os.path.join(get_python_inc(plat_specific=1), 'Numerical') - setup(..., - Extension(..., include_dirs=[incdir]), - ) - -Even though this is quite portable---it will work on any Python installation, -regardless of platform---it's probably easier to just write your C code in the -sensible way. - -You can define and undefine pre-processor macros with the ``define_macros`` and -``undef_macros`` options. ``define_macros`` takes a list of ``(name, value)`` -tuples, where ``name`` is the name of the macro to define (a string) and -``value`` is its value: either a string or ``None``. (Defining a macro ``FOO`` -to ``None`` is the equivalent of a bare ``#define FOO`` in your C source: with -most compilers, this sets ``FOO`` to the string ``1``.) ``undef_macros`` is -just a list of macros to undefine. - -For example:: - - Extension(..., - define_macros=[('NDEBUG', '1'), - ('HAVE_STRFTIME', None)], - undef_macros=['HAVE_FOO', 'HAVE_BAR']) - -is the equivalent of having this at the top of every C source file:: - - #define NDEBUG 1 - #define HAVE_STRFTIME - #undef HAVE_FOO - #undef HAVE_BAR - - -Library options ---------------- - -You can also specify the libraries to link against when building your extension, -and the directories to search for those libraries. The ``libraries`` option is -a list of libraries to link against, ``library_dirs`` is a list of directories -to search for libraries at link-time, and ``runtime_library_dirs`` is a list of -directories to search for shared (dynamically loaded) libraries at run-time. - -For example, if you need to link against libraries known to be in the standard -library search path on target systems :: - - Extension(..., - libraries=['gdbm', 'readline']) - -If you need to link with libraries in a non-standard location, you'll have to -include the location in ``library_dirs``:: - - Extension(..., - library_dirs=['/usr/X11R6/lib'], - libraries=['X11', 'Xt']) - -(Again, this sort of non-portable construct should be avoided if you intend to -distribute your code.) - -.. XXX Should mention clib libraries here or somewhere else! - - -Other options -------------- - -There are still some other options which can be used to handle special cases. - -The ``optional`` option is a boolean; if it is true, -a build failure in the extension will not abort the build process, but -instead simply not install the failing extension. - -The ``extra_objects`` option is a list of object files to be passed to the -linker. These files must not have extensions, as the default extension for the -compiler is used. - -``extra_compile_args`` and ``extra_link_args`` can be used to -specify additional command line options for the respective compiler and linker -command lines. - -``export_symbols`` is only useful on Windows. It can contain a list of -symbols (functions or variables) to be exported. This option is not needed when -building compiled extensions: Distutils will automatically add ``initmodule`` -to the list of exported symbols. - -The ``depends`` option is a list of files that the extension depends on -(for example header files). The build command will call the compiler on the -sources to rebuild extension if any on this files has been modified since the -previous build. - -Relationships between Distributions and Packages -================================================ - -A distribution may relate to packages in three specific ways: - -#. It can require packages or modules. - -#. It can provide packages or modules. - -#. It can obsolete packages or modules. - -These relationships can be specified using keyword arguments to the -:func:`distutils.core.setup` function. - -Dependencies on other Python modules and packages can be specified by supplying -the *requires* keyword argument to :func:`setup`. The value must be a list of -strings. Each string specifies a package that is required, and optionally what -versions are sufficient. - -To specify that any version of a module or package is required, the string -should consist entirely of the module or package name. Examples include -``'mymodule'`` and ``'xml.parsers.expat'``. - -If specific versions are required, a sequence of qualifiers can be supplied in -parentheses. Each qualifier may consist of a comparison operator and a version -number. The accepted comparison operators are:: - - < > == - <= >= != - -These can be combined by using multiple qualifiers separated by commas (and -optional whitespace). In this case, all of the qualifiers must be matched; a -logical AND is used to combine the evaluations. - -Let's look at a bunch of examples: - -+-------------------------+----------------------------------------------+ -| Requires Expression | Explanation | -+=========================+==============================================+ -| ``==1.0`` | Only version ``1.0`` is compatible | -+-------------------------+----------------------------------------------+ -| ``>1.0, !=1.5.1, <2.0`` | Any version after ``1.0`` and before ``2.0`` | -| | is compatible, except ``1.5.1`` | -+-------------------------+----------------------------------------------+ - -Now that we can specify dependencies, we also need to be able to specify what we -provide that other distributions can require. This is done using the *provides* -keyword argument to :func:`setup`. The value for this keyword is a list of -strings, each of which names a Python module or package, and optionally -identifies the version. If the version is not specified, it is assumed to match -that of the distribution. - -Some examples: - -+---------------------+----------------------------------------------+ -| Provides Expression | Explanation | -+=====================+==============================================+ -| ``mypkg`` | Provide ``mypkg``, using the distribution | -| | version | -+---------------------+----------------------------------------------+ -| ``mypkg (1.1)`` | Provide ``mypkg`` version 1.1, regardless of | -| | the distribution version | -+---------------------+----------------------------------------------+ - -A package can declare that it obsoletes other packages using the *obsoletes* -keyword argument. The value for this is similar to that of the *requires* -keyword: a list of strings giving module or package specifiers. Each specifier -consists of a module or package name optionally followed by one or more version -qualifiers. Version qualifiers are given in parentheses after the module or -package name. - -The versions identified by the qualifiers are those that are obsoleted by the -distribution being described. If no qualifiers are given, all versions of the -named module or package are understood to be obsoleted. - -.. _distutils-installing-scripts: - -Installing Scripts -================== - -So far we have been dealing with pure and non-pure Python modules, which are -usually not run by themselves but imported by scripts. - -Scripts are files containing Python source code, intended to be started from the -command line. Scripts don't require Distutils to do anything very complicated. -The only clever feature is that if the first line of the script starts with -``#!`` and contains the word "python", the Distutils will adjust the first line -to refer to the current interpreter location. By default, it is replaced with -the current interpreter location. The :option:`!--executable` (or :option:`!-e`) -option will allow the interpreter path to be explicitly overridden. - -The ``scripts`` option simply is a list of files to be handled in this -way. From the PyXML setup script:: - - setup(..., - scripts=['scripts/xmlproc_parse', 'scripts/xmlproc_val'] - ) - -.. versionchanged:: 3.1 - All the scripts will also be added to the ``MANIFEST`` file if no template is - provided. See :ref:`manifest`. - - -.. _distutils-installing-package-data: - -Installing Package Data -======================= - -Often, additional files need to be installed into a package. These files are -often data that's closely related to the package's implementation, or text files -containing documentation that might be of interest to programmers using the -package. These files are called :dfn:`package data`. - -Package data can be added to packages using the ``package_data`` keyword -argument to the :func:`setup` function. The value must be a mapping from -package name to a list of relative path names that should be copied into the -package. The paths are interpreted as relative to the directory containing the -package (information from the ``package_dir`` mapping is used if appropriate); -that is, the files are expected to be part of the package in the source -directories. They may contain glob patterns as well. - -The path names may contain directory portions; any necessary directories will be -created in the installation. - -For example, if a package should contain a subdirectory with several data files, -the files can be arranged like this in the source tree:: - - setup.py - src/ - mypkg/ - __init__.py - module.py - data/ - tables.dat - spoons.dat - forks.dat - -The corresponding call to :func:`setup` might be:: - - setup(..., - packages=['mypkg'], - package_dir={'mypkg': 'src/mypkg'}, - package_data={'mypkg': ['data/*.dat']}, - ) - - -.. versionchanged:: 3.1 - All the files that match ``package_data`` will be added to the ``MANIFEST`` - file if no template is provided. See :ref:`manifest`. - - -.. _distutils-additional-files: - -Installing Additional Files -=========================== - -The ``data_files`` option can be used to specify additional files needed -by the module distribution: configuration files, message catalogs, data files, -anything which doesn't fit in the previous categories. - -``data_files`` specifies a sequence of (*directory*, *files*) pairs in the -following way:: - - setup(..., - data_files=[('bitmaps', ['bm/b1.gif', 'bm/b2.gif']), - ('config', ['cfg/data.cfg'])], - ) - -Each (*directory*, *files*) pair in the sequence specifies the installation -directory and the files to install there. - -Each file name in *files* is interpreted relative to the :file:`setup.py` -script at the top of the package source distribution. Note that you can -specify the directory where the data files will be installed, but you cannot -rename the data files themselves. - -The *directory* should be a relative path. It is interpreted relative to the -installation prefix (Python's ``sys.prefix`` for system installations; -``site.USER_BASE`` for user installations). Distutils allows *directory* to be -an absolute installation path, but this is discouraged since it is -incompatible with the wheel packaging format. No directory information from -*files* is used to determine the final location of the installed file; only -the name of the file is used. - -You can specify the ``data_files`` options as a simple sequence of files -without specifying a target directory, but this is not recommended, and the -:command:`install` command will print a warning in this case. To install data -files directly in the target directory, an empty string should be given as the -directory. - -.. versionchanged:: 3.1 - All the files that match ``data_files`` will be added to the ``MANIFEST`` - file if no template is provided. See :ref:`manifest`. - - -.. _meta-data: - -Additional meta-data -==================== - -The setup script may include additional meta-data beyond the name and version. -This information includes: - -+----------------------+---------------------------+-----------------+--------+ -| Meta-Data | Description | Value | Notes | -+======================+===========================+=================+========+ -| ``name`` | name of the package | short string | \(1) | -+----------------------+---------------------------+-----------------+--------+ -| ``version`` | version of this release | short string | (1)(2) | -+----------------------+---------------------------+-----------------+--------+ -| ``author`` | package author's name | short string | \(3) | -+----------------------+---------------------------+-----------------+--------+ -| ``author_email`` | email address of the | email address | \(3) | -| | package author | | | -+----------------------+---------------------------+-----------------+--------+ -| ``maintainer`` | package maintainer's name | short string | \(3) | -+----------------------+---------------------------+-----------------+--------+ -| ``maintainer_email`` | email address of the | email address | \(3) | -| | package maintainer | | | -+----------------------+---------------------------+-----------------+--------+ -| ``url`` | home page for the package | URL | \(1) | -+----------------------+---------------------------+-----------------+--------+ -| ``description`` | short, summary | short string | | -| | description of the | | | -| | package | | | -+----------------------+---------------------------+-----------------+--------+ -| ``long_description`` | longer description of the | long string | \(4) | -| | package | | | -+----------------------+---------------------------+-----------------+--------+ -| ``download_url`` | location where the | URL | | -| | package may be downloaded | | | -+----------------------+---------------------------+-----------------+--------+ -| ``classifiers`` | a list of classifiers | list of strings | (6)(7) | -+----------------------+---------------------------+-----------------+--------+ -| ``platforms`` | a list of platforms | list of strings | (6)(8) | -+----------------------+---------------------------+-----------------+--------+ -| ``keywords`` | a list of keywords | list of strings | (6)(8) | -+----------------------+---------------------------+-----------------+--------+ -| ``license`` | license for the package | short string | \(5) | -+----------------------+---------------------------+-----------------+--------+ - -Notes: - -(1) - These fields are required. - -(2) - It is recommended that versions take the form *major.minor[.patch[.sub]]*. - -(3) - Either the author or the maintainer must be identified. If maintainer is - provided, distutils lists it as the author in :file:`PKG-INFO`. - -(4) - The ``long_description`` field is used by PyPI when you publish a package, - to build its project page. - -(5) - The ``license`` field is a text indicating the license covering the - package where the license is not a selection from the "License" Trove - classifiers. See the ``Classifier`` field. Notice that - there's a ``licence`` distribution option which is deprecated but still - acts as an alias for ``license``. - -(6) - This field must be a list. - -(7) - The valid classifiers are listed on - `PyPI <https://pypi.org/classifiers>`_. - -(8) - To preserve backward compatibility, this field also accepts a string. If - you pass a comma-separated string ``'foo, bar'``, it will be converted to - ``['foo', 'bar']``, Otherwise, it will be converted to a list of one - string. - -'short string' - A single line of text, not more than 200 characters. - -'long string' - Multiple lines of plain text in reStructuredText format (see - http://docutils.sourceforge.net/). - -'list of strings' - See below. - -Encoding the version information is an art in itself. Python packages generally -adhere to the version format *major.minor[.patch][sub]*. The major number is 0 -for initial, experimental releases of software. It is incremented for releases -that represent major milestones in a package. The minor number is incremented -when important new features are added to the package. The patch number -increments when bug-fix releases are made. Additional trailing version -information is sometimes used to indicate sub-releases. These are -"a1,a2,...,aN" (for alpha releases, where functionality and API may change), -"b1,b2,...,bN" (for beta releases, which only fix bugs) and "pr1,pr2,...,prN" -(for final pre-release release testing). Some examples: - -0.1.0 - the first, experimental release of a package - -1.0.1a2 - the second alpha release of the first patch version of 1.0 - -``classifiers`` must be specified in a list:: - - setup(..., - classifiers=[ - 'Development Status :: 4 - Beta', - 'Environment :: Console', - 'Environment :: Web Environment', - 'Intended Audience :: End Users/Desktop', - 'Intended Audience :: Developers', - 'Intended Audience :: System Administrators', - 'License :: OSI Approved :: Python Software Foundation License', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: POSIX', - 'Programming Language :: Python', - 'Topic :: Communications :: Email', - 'Topic :: Office/Business', - 'Topic :: Software Development :: Bug Tracking', - ], - ) - -.. versionchanged:: 3.7 - :class:`~distutils.core.setup` now warns when ``classifiers``, ``keywords`` - or ``platforms`` fields are not specified as a list or a string. - -.. _debug-setup-script: - -Debugging the setup script -========================== - -Sometimes things go wrong, and the setup script doesn't do what the developer -wants. - -Distutils catches any exceptions when running the setup script, and print a -simple error message before the script is terminated. The motivation for this -behaviour is to not confuse administrators who don't know much about Python and -are trying to install a package. If they get a big long traceback from deep -inside the guts of Distutils, they may think the package or the Python -installation is broken because they don't read all the way down to the bottom -and see that it's a permission problem. - -On the other hand, this doesn't help the developer to find the cause of the -failure. For this purpose, the :envvar:`DISTUTILS_DEBUG` environment variable can be set -to anything except an empty string, and distutils will now print detailed -information about what it is doing, dump the full traceback when an exception -occurs, and print the whole command line when an external program (like a C -compiler) fails. diff --git a/Doc/distutils/sourcedist.rst b/Doc/distutils/sourcedist.rst deleted file mode 100644 index b55d01157f3ee10561c236e8b22faf29cc80ab68..0000000000000000000000000000000000000000 --- a/Doc/distutils/sourcedist.rst +++ /dev/null @@ -1,245 +0,0 @@ -.. _source-dist: - -****************************** -Creating a Source Distribution -****************************** - -.. include:: ./_setuptools_disclaimer.rst - -As shown in section :ref:`distutils-simple-example`, you use the :command:`sdist` command -to create a source distribution. In the simplest case, :: - - python setup.py sdist - -(assuming you haven't specified any :command:`sdist` options in the setup script -or config file), :command:`sdist` creates the archive of the default format for -the current platform. The default format is a gzip'ed tar file -(:file:`.tar.gz`) on Unix, and ZIP file on Windows. - -You can specify as many formats as you like using the :option:`!--formats` -option, for example:: - - python setup.py sdist --formats=gztar,zip - -to create a gzipped tarball and a zip file. The available formats are: - -+-----------+-------------------------+-------------+ -| Format | Description | Notes | -+===========+=========================+=============+ -| ``zip`` | zip file (:file:`.zip`) | (1),(3) | -+-----------+-------------------------+-------------+ -| ``gztar`` | gzip'ed tar file | \(2) | -| | (:file:`.tar.gz`) | | -+-----------+-------------------------+-------------+ -| ``bztar`` | bzip2'ed tar file | \(5) | -| | (:file:`.tar.bz2`) | | -+-----------+-------------------------+-------------+ -| ``xztar`` | xz'ed tar file | \(5) | -| | (:file:`.tar.xz`) | | -+-----------+-------------------------+-------------+ -| ``ztar`` | compressed tar file | (4),(5) | -| | (:file:`.tar.Z`) | | -+-----------+-------------------------+-------------+ -| ``tar`` | tar file (:file:`.tar`) | \(5) | -+-----------+-------------------------+-------------+ - -.. versionchanged:: 3.5 - Added support for the ``xztar`` format. - -Notes: - -(1) - default on Windows - -(2) - default on Unix - -(3) - requires either external :program:`zip` utility or :mod:`zipfile` module (part - of the standard Python library since Python 1.6) - -(4) - requires the :program:`compress` program. Notice that this format is now - pending for deprecation and will be removed in the future versions of Python. -(5) - deprecated by `PEP 527 <https://peps.python.org/pep-0527/>`_; - `PyPI <https://pypi.org>`_ only accepts ``.zip`` and ``.tar.gz`` files. - -When using any ``tar`` format (``gztar``, ``bztar``, ``xztar``, ``ztar`` or -``tar``), under Unix you can specify the ``owner`` and ``group`` names -that will be set for each member of the archive. - -For example, if you want all files of the archive to be owned by root:: - - python setup.py sdist --owner=root --group=root - - -.. _manifest: - -Specifying the files to distribute -================================== - -If you don't supply an explicit list of files (or instructions on how to -generate one), the :command:`sdist` command puts a minimal default set into the -source distribution: - -* all Python source files implied by the ``py_modules`` and - ``packages`` options - -* all C source files mentioned in the ``ext_modules`` or - ``libraries`` options - - .. XXX getting C library sources currently broken---no - :meth:`get_source_files` method in :file:`build_clib.py`! - -* scripts identified by the ``scripts`` option - See :ref:`distutils-installing-scripts`. - -* anything that looks like a test script: :file:`test/test\*.py` (currently, the - Distutils don't do anything with test scripts except include them in source - distributions, but in the future there will be a standard for testing Python - module distributions) - -* Any of the standard README files (:file:`README`, :file:`README.txt`, - or :file:`README.rst`), :file:`setup.py` (or whatever you called your setup - script), and :file:`setup.cfg`. - -* all files that matches the ``package_data`` metadata. - See :ref:`distutils-installing-package-data`. - -* all files that matches the ``data_files`` metadata. - See :ref:`distutils-additional-files`. - -Sometimes this is enough, but usually you will want to specify additional files -to distribute. The typical way to do this is to write a *manifest template*, -called :file:`MANIFEST.in` by default. The manifest template is just a list of -instructions for how to generate your manifest file, :file:`MANIFEST`, which is -the exact list of files to include in your source distribution. The -:command:`sdist` command processes this template and generates a manifest based -on its instructions and what it finds in the filesystem. - -If you prefer to roll your own manifest file, the format is simple: one filename -per line, regular files (or symlinks to them) only. If you do supply your own -:file:`MANIFEST`, you must specify everything: the default set of files -described above does not apply in this case. - -.. versionchanged:: 3.1 - An existing generated :file:`MANIFEST` will be regenerated without - :command:`sdist` comparing its modification time to the one of - :file:`MANIFEST.in` or :file:`setup.py`. - -.. versionchanged:: 3.1.3 - :file:`MANIFEST` files start with a comment indicating they are generated. - Files without this comment are not overwritten or removed. - -.. versionchanged:: 3.2.2 - :command:`sdist` will read a :file:`MANIFEST` file if no :file:`MANIFEST.in` - exists, like it used to do. - -.. versionchanged:: 3.7 - :file:`README.rst` is now included in the list of distutils standard READMEs. - - -The manifest template has one command per line, where each command specifies a -set of files to include or exclude from the source distribution. For an -example, again we turn to the Distutils' own manifest template: - -.. code-block:: none - - include *.txt - recursive-include examples *.txt *.py - prune examples/sample?/build - -The meanings should be fairly clear: include all files in the distribution root -matching :file:`\*.txt`, all files anywhere under the :file:`examples` directory -matching :file:`\*.txt` or :file:`\*.py`, and exclude all directories matching -:file:`examples/sample?/build`. All of this is done *after* the standard -include set, so you can exclude files from the standard set with explicit -instructions in the manifest template. (Or, you can use the -:option:`!--no-defaults` option to disable the standard set entirely.) There are -several other commands available in the manifest template mini-language; see -section :ref:`sdist-cmd`. - -The order of commands in the manifest template matters: initially, we have the -list of default files as described above, and each command in the template adds -to or removes from that list of files. Once we have fully processed the -manifest template, we remove files that should not be included in the source -distribution: - -* all files in the Distutils "build" tree (default :file:`build/`) - -* all files in directories named :file:`RCS`, :file:`CVS`, :file:`.svn`, - :file:`.hg`, :file:`.git`, :file:`.bzr` or :file:`_darcs` - -Now we have our complete list of files, which is written to the manifest for -future reference, and then used to build the source distribution archive(s). - -You can disable the default set of included files with the -:option:`!--no-defaults` option, and you can disable the standard exclude set -with :option:`!--no-prune`. - -Following the Distutils' own manifest template, let's trace how the -:command:`sdist` command builds the list of files to include in the Distutils -source distribution: - -#. include all Python source files in the :file:`distutils` and - :file:`distutils/command` subdirectories (because packages corresponding to - those two directories were mentioned in the ``packages`` option in the - setup script---see section :ref:`setup-script`) - -#. include :file:`README.txt`, :file:`setup.py`, and :file:`setup.cfg` (standard - files) - -#. include :file:`test/test\*.py` (standard files) - -#. include :file:`\*.txt` in the distribution root (this will find - :file:`README.txt` a second time, but such redundancies are weeded out later) - -#. include anything matching :file:`\*.txt` or :file:`\*.py` in the sub-tree - under :file:`examples`, - -#. exclude all files in the sub-trees starting at directories matching - :file:`examples/sample?/build`\ ---this may exclude files included by the - previous two steps, so it's important that the ``prune`` command in the manifest - template comes after the ``recursive-include`` command - -#. exclude the entire :file:`build` tree, and any :file:`RCS`, :file:`CVS`, - :file:`.svn`, :file:`.hg`, :file:`.git`, :file:`.bzr` and :file:`_darcs` - directories - -Just like in the setup script, file and directory names in the manifest template -should always be slash-separated; the Distutils will take care of converting -them to the standard representation on your platform. That way, the manifest -template is portable across operating systems. - - -.. _manifest-options: - -Manifest-related options -======================== - -The normal course of operations for the :command:`sdist` command is as follows: - -* if the manifest file (:file:`MANIFEST` by default) exists and the first line - does not have a comment indicating it is generated from :file:`MANIFEST.in`, - then it is used as is, unaltered - -* if the manifest file doesn't exist or has been previously automatically - generated, read :file:`MANIFEST.in` and create the manifest - -* if neither :file:`MANIFEST` nor :file:`MANIFEST.in` exist, create a manifest - with just the default file set - -* use the list of files now in :file:`MANIFEST` (either just generated or read - in) to create the source distribution archive(s) - -There are a couple of options that modify this behaviour. First, use the -:option:`!--no-defaults` and :option:`!--no-prune` to disable the standard -"include" and "exclude" sets. - -Second, you might just want to (re)generate the manifest, but not create a source -distribution:: - - python setup.py sdist --manifest-only - -:option:`!-o` is a shortcut for :option:`!--manifest-only`. diff --git a/Doc/distutils/uploading.rst b/Doc/distutils/uploading.rst deleted file mode 100644 index 4c391cab072ea6a41d67b23c1f616123c4b9f1b3..0000000000000000000000000000000000000000 --- a/Doc/distutils/uploading.rst +++ /dev/null @@ -1,8 +0,0 @@ -:orphan: - -*************************************** -Uploading Packages to the Package Index -*************************************** - -References to up to date PyPI documentation can be found at -:ref:`publishing-python-packages`. diff --git a/Doc/extending/building.rst b/Doc/extending/building.rst index 53817074ab1ee5f573fb63f85f4ae77447efeba5..880bb33ee56718bfed60ad101852c592085380f7 100644 --- a/Doc/extending/building.rst +++ b/Doc/extending/building.rst @@ -11,7 +11,7 @@ A C extension for CPython is a shared library (e.g. a ``.so`` file on Linux, To be importable, the shared library must be available on :envvar:`PYTHONPATH`, and must be named after the module name, with an appropriate extension. -When using distutils, the correct filename is generated automatically. +When using setuptools, the correct filename is generated automatically. The initialization function has the signature: @@ -45,122 +45,12 @@ See the *"Multiple modules in one library"* section in :pep:`489` for details. .. highlight:: c -Building C and C++ Extensions with distutils -============================================ +.. _setuptools-index: -.. sectionauthor:: Martin v. Löwis <martin@v.loewis.de> +Building C and C++ Extensions with setuptools +============================================= -Extension modules can be built using distutils, which is included in Python. -Since distutils also supports creation of binary packages, users don't -necessarily need a compiler and distutils to install the extension. - -A distutils package contains a driver script, :file:`setup.py`. This is a plain -Python file, which, in the most simple case, could look like this: - -.. code-block:: python3 - - from distutils.core import setup, Extension - - module1 = Extension('demo', - sources = ['demo.c']) - - setup (name = 'PackageName', - version = '1.0', - description = 'This is a demo package', - ext_modules = [module1]) - - -With this :file:`setup.py`, and a file :file:`demo.c`, running :: - - python setup.py build - -will compile :file:`demo.c`, and produce an extension module named ``demo`` in -the :file:`build` directory. Depending on the system, the module file will end -up in a subdirectory :file:`build/lib.system`, and may have a name like -:file:`demo.so` or :file:`demo.pyd`. - -In the :file:`setup.py`, all execution is performed by calling the ``setup`` -function. This takes a variable number of keyword arguments, of which the -example above uses only a subset. Specifically, the example specifies -meta-information to build packages, and it specifies the contents of the -package. Normally, a package will contain additional modules, like Python -source modules, documentation, subpackages, etc. Please refer to the distutils -documentation in :ref:`distutils-index` to learn more about the features of -distutils; this section explains building extension modules only. - -It is common to pre-compute arguments to :func:`setup`, to better structure the -driver script. In the example above, the ``ext_modules`` argument to -:func:`~distutils.core.setup` is a list of extension modules, each of which is -an instance of -the :class:`~distutils.extension.Extension`. In the example, the instance -defines an extension named ``demo`` which is build by compiling a single source -file, :file:`demo.c`. - -In many cases, building an extension is more complex, since additional -preprocessor defines and libraries may be needed. This is demonstrated in the -example below. - -.. code-block:: python3 - - from distutils.core import setup, Extension - - module1 = Extension('demo', - define_macros = [('MAJOR_VERSION', '1'), - ('MINOR_VERSION', '0')], - include_dirs = ['/usr/local/include'], - libraries = ['tcl83'], - library_dirs = ['/usr/local/lib'], - sources = ['demo.c']) - - setup (name = 'PackageName', - version = '1.0', - description = 'This is a demo package', - author = 'Martin v. Loewis', - author_email = 'martin@v.loewis.de', - url = 'https://docs.python.org/extending/building', - long_description = ''' - This is really just a demo package. - ''', - ext_modules = [module1]) - - -In this example, :func:`~distutils.core.setup` is called with additional -meta-information, which -is recommended when distribution packages have to be built. For the extension -itself, it specifies preprocessor defines, include directories, library -directories, and libraries. Depending on the compiler, distutils passes this -information in different ways to the compiler. For example, on Unix, this may -result in the compilation commands :: - - gcc -DNDEBUG -g -O3 -Wall -Wstrict-prototypes -fPIC -DMAJOR_VERSION=1 -DMINOR_VERSION=0 -I/usr/local/include -I/usr/local/include/python2.2 -c demo.c -o build/temp.linux-i686-2.2/demo.o - - gcc -shared build/temp.linux-i686-2.2/demo.o -L/usr/local/lib -ltcl83 -o build/lib.linux-i686-2.2/demo.so - -These lines are for demonstration purposes only; distutils users should trust -that distutils gets the invocations right. - - -.. _distributing: - -Distributing your extension modules -=================================== - -When an extension has been successfully built, there are three ways to use it. - -End-users will typically want to install the module, they do so by running :: - - python setup.py install - -Module maintainers should produce source packages; to do so, they run :: - - python setup.py sdist - -In some cases, additional files need to be included in a source distribution; -this is done through a :file:`MANIFEST.in` file; see :ref:`manifest` for details. - -If the source distribution has been built successfully, maintainers can also -create binary distributions. Depending on the platform, one of the following -commands can be used to do so. :: - - python setup.py bdist_rpm - python setup.py bdist_dumb +Python 3.12 and newer no longer come with distutils. Please refer to the +``setuptools`` documentation at +https://setuptools.readthedocs.io/en/latest/setuptools.html +to learn more about how build and distribute C/C++ extensions with setuptools. diff --git a/Doc/extending/windows.rst b/Doc/extending/windows.rst index 28d0350f6f114d8ac90f8772b67b6129ae9b511b..1129b0968bc4e60e971451b3bd457d9c30cb1a04 100644 --- a/Doc/extending/windows.rst +++ b/Doc/extending/windows.rst @@ -34,10 +34,10 @@ A Cookbook Approach =================== There are two approaches to building extension modules on Windows, just as there -are on Unix: use the :mod:`distutils` package to control the build process, or -do things manually. The distutils approach works well for most extensions; -documentation on using :mod:`distutils` to build and package extension modules -is available in :ref:`distutils-index`. If you find you really need to do +are on Unix: use the ``setuptools`` package to control the build process, or +do things manually. The setuptools approach works well for most extensions; +documentation on using ``setuptools`` to build and package extension modules +is available in :ref:`setuptools-index`. If you find you really need to do things manually, it may be instructive to study the project file for the :source:`winsound <PCbuild/winsound.vcxproj>` standard library module. diff --git a/Doc/howto/enum.rst b/Doc/howto/enum.rst index 7b1cf75fa81f080aab3f1f0a42b4253f00e4fdc2..376934a0e7936510f3507e58936cc69fdb2d3403 100644 --- a/Doc/howto/enum.rst +++ b/Doc/howto/enum.rst @@ -945,23 +945,12 @@ but remain normal attributes. """""""""""""""""""" Enum members are instances of their enum class, and are normally accessed as -``EnumClass.member``. In Python versions ``3.5`` to ``3.10`` you could access -members from other members -- this practice was discouraged, and in ``3.11`` -:class:`Enum` returns to not allowing it:: - - >>> class FieldTypes(Enum): - ... name = 0 - ... value = 1 - ... size = 2 - ... - >>> FieldTypes.value.size - Traceback (most recent call last): - ... - AttributeError: <enum 'FieldTypes'> member has no attribute 'size' - +``EnumClass.member``. In Python versions starting with ``3.5`` you could access +members from other members -- this practice is discouraged, is deprecated +in ``3.12``, and will be removed in ``3.14``. .. versionchanged:: 3.5 -.. versionchanged:: 3.11 +.. versionchanged:: 3.12 Creating members that are mixed with other data types diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index 7f4fe3a63a70260282665e38cc14544b8f5d2b22..321c4bc510ad99054049fc2a3fc465cdf5d15ee5 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -219,7 +219,7 @@ messages should not. Here's how you can achieve this:: logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', datefmt='%m-%d %H:%M', - filename='/temp/myapp.log', + filename='/tmp/myapp.log', filemode='w') # define a Handler which writes INFO messages or higher to the sys.stderr console = logging.StreamHandler() @@ -270,6 +270,11 @@ are sent to both destinations. This example uses console and file handlers, but you can use any number and combination of handlers you choose. +Note that the above choice of log filename ``/tmp/myapp.log`` implies use of a +standard location for temporary files on POSIX systems. On Windows, you may need to +choose a different directory name for the log - just ensure that the directory exists +and that you have the permissions to create and update files in it. + Configuration server example ---------------------------- diff --git a/Doc/includes/sqlite3/executemany_1.py b/Doc/includes/sqlite3/executemany_1.py deleted file mode 100644 index edf6f8b7ebe61a839c187655bc141cbe9f7e57e6..0000000000000000000000000000000000000000 --- a/Doc/includes/sqlite3/executemany_1.py +++ /dev/null @@ -1,26 +0,0 @@ -import sqlite3 - -class IterChars: - def __init__(self): - self.count = ord('a') - - def __iter__(self): - return self - - def __next__(self): - if self.count > ord('z'): - raise StopIteration - self.count += 1 - return (chr(self.count - 1),) # this is a 1-tuple - -con = sqlite3.connect(":memory:") -cur = con.cursor() -cur.execute("create table characters(c)") - -theIter = IterChars() -cur.executemany("insert into characters(c) values (?)", theIter) - -cur.execute("select c from characters") -print(cur.fetchall()) - -con.close() diff --git a/Doc/includes/sqlite3/executemany_2.py b/Doc/includes/sqlite3/executemany_2.py deleted file mode 100644 index 02a594c861e15baff439090d811bf3260d61cbc1..0000000000000000000000000000000000000000 --- a/Doc/includes/sqlite3/executemany_2.py +++ /dev/null @@ -1,17 +0,0 @@ -import sqlite3 -import string - -def char_generator(): - for c in string.ascii_lowercase: - yield (c,) - -con = sqlite3.connect(":memory:") -cur = con.cursor() -cur.execute("create table characters(c)") - -cur.executemany("insert into characters(c) values (?)", char_generator()) - -cur.execute("select c from characters") -print(cur.fetchall()) - -con.close() diff --git a/Doc/includes/sqlite3/executescript.py b/Doc/includes/sqlite3/executescript.py deleted file mode 100644 index aea8943fbee598f657cdf4c1e9aec3381335a052..0000000000000000000000000000000000000000 --- a/Doc/includes/sqlite3/executescript.py +++ /dev/null @@ -1,25 +0,0 @@ -import sqlite3 - -con = sqlite3.connect(":memory:") -cur = con.cursor() -cur.executescript(""" - create table person( - firstname, - lastname, - age - ); - - create table book( - title, - author, - published - ); - - insert into book(title, author, published) - values ( - 'Dirk Gently''s Holistic Detective Agency', - 'Douglas Adams', - 1987 - ); - """) -con.close() diff --git a/Doc/includes/sqlite3/pysqlite_datetime.py b/Doc/includes/sqlite3/pysqlite_datetime.py deleted file mode 100644 index 5d843f906b3062dff450074fcffe8abec65dbd76..0000000000000000000000000000000000000000 --- a/Doc/includes/sqlite3/pysqlite_datetime.py +++ /dev/null @@ -1,22 +0,0 @@ -import sqlite3 -import datetime - -con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) -cur = con.cursor() -cur.execute("create table test(d date, ts timestamp)") - -today = datetime.date.today() -now = datetime.datetime.now() - -cur.execute("insert into test(d, ts) values (?, ?)", (today, now)) -cur.execute("select d, ts from test") -row = cur.fetchone() -print(today, "=>", row[0], type(row[0])) -print(now, "=>", row[1], type(row[1])) - -cur.execute('select current_date as "d [date]", current_timestamp as "ts [timestamp]"') -row = cur.fetchone() -print("current_date", row[0], type(row[0])) -print("current_timestamp", row[1], type(row[1])) - -con.close() diff --git a/Doc/install/index.rst b/Doc/install/index.rst index 63b64b95fc721ec127fdfe0d1a595043cc3c646e..0923267d06601acf5e3b9a07d1931b142654ece9 100644 --- a/Doc/install/index.rst +++ b/Doc/install/index.rst @@ -23,7 +23,11 @@ The up to date module installation documentation. For regular Python usage, you almost certainly want that document rather than this one. -.. include:: ../distutils/_setuptools_disclaimer.rst +.. note:: + + This document is being retained solely until the ``setuptools`` documentation + at https://setuptools.readthedocs.io/en/latest/setuptools.html + independently covers all of the relevant information currently included here. .. note:: diff --git a/Doc/library/_thread.rst b/Doc/library/_thread.rst index 75b3834b9a339cd6847e67a9c3e32e55b31b240b..d61ce9039349dba0d3478a3121d4b7d3f461ddae 100644 --- a/Doc/library/_thread.rst +++ b/Doc/library/_thread.rst @@ -140,7 +140,9 @@ This module defines the following constants and functions: information (4 KiB pages are common; using multiples of 4096 for the stack size is the suggested approach in the absence of more specific information). - .. availability:: Windows, systems with POSIX threads. + .. availability:: Windows, pthreads. + + Unix platforms with POSIX threads support. .. data:: TIMEOUT_MAX diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index b10aa7cd50d17300881888da32abf392800b028a..9aa545d82007fa282009611ebe80d9592d0446a3 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -45,7 +45,7 @@ Node classes This is the base of all AST node classes. The actual node classes are derived from the :file:`Parser/Python.asdl` file, which is reproduced - :ref:`below <abstract-grammar>`. They are defined in the :mod:`_ast` C + :ref:`above <abstract-grammar>`. They are defined in the :mod:`_ast` C module and re-exported in :mod:`ast`. There is one class defined for each left-hand side symbol in the abstract @@ -1028,10 +1028,11 @@ Control flow .. class:: For(target, iter, body, orelse, type_comment) A ``for`` loop. ``target`` holds the variable(s) the loop assigns to, as a - single :class:`Name`, :class:`Tuple` or :class:`List` node. ``iter`` holds - the item to be looped over, again as a single node. ``body`` and ``orelse`` - contain lists of nodes to execute. Those in ``orelse`` are executed if the - loop finishes normally, rather than via a ``break`` statement. + single :class:`Name`, :class:`Tuple`, :class:`List`, :class:`Attribute` or + :class:`Subscript` node. ``iter`` holds the item to be looped over, again + as a single node. ``body`` and ``orelse`` contain lists of nodes to execute. + Those in ``orelse`` are executed if the loop finishes normally, rather than + via a ``break`` statement. .. attribute:: type_comment @@ -1950,7 +1951,7 @@ and classes for traversing abstract syntax trees: If source contains a null character ('\0'), :exc:`ValueError` is raised. - .. warning:: + .. warning:: Note that successfully parsing source code into an AST object doesn't guarantee that the source code provided is valid Python code that can be executed as the compilation step can raise further :exc:`SyntaxError` diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 76969762dd9f556008d0ead180162b50013b1d66..a6b638c1124094e238d132c6f8decfe1ba1e0742 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -282,6 +282,24 @@ Creating Tasks Added the *context* parameter. +Task Cancellation +================= + +Tasks can easily and safely be cancelled. +When a task is cancelled, :exc:`asyncio.CancelledError` will be raised +in the task at the next opportunity. + +It is recommended that coroutines use ``try/finally`` blocks to robustly +perform clean-up logic. In case :exc:`asyncio.CancelledError` +is explicitly caught, it should generally be propagated when +clean-up is complete. Most code can safely ignore :exc:`asyncio.CancelledError`. + +Important asyncio components, like :class:`asyncio.TaskGroup` and the +:func:`asyncio.timeout` context manager, are implemented using cancellation +internally and might misbehave if a coroutine swallows +:exc:`asyncio.CancelledError`. + + Task Groups =========== @@ -537,6 +555,125 @@ Shielding From Cancellation Timeouts ======== +.. coroutinefunction:: timeout(delay) + + An :ref:`asynchronous context manager <async-context-managers>` + that can be used to limit the amount of time spent waiting on + something. + + *delay* can either be ``None``, or a float/int number of + seconds to wait. If *delay* is ``None``, no time limit will + be applied; this can be useful if the delay is unknown when + the context manager is created. + + In either case, the context manager can be rescheduled after + creation using :meth:`Timeout.reschedule`. + + Example:: + + async def main(): + async with asyncio.timeout(10): + await long_running_task() + + If ``long_running_task`` takes more than 10 seconds to complete, + the context manager will cancel the current task and handle + the resulting :exc:`asyncio.CancelledError` internally, transforming it + into an :exc:`asyncio.TimeoutError` which can be caught and handled. + + .. note:: + + The :func:`asyncio.timeout` context manager is what transforms + the :exc:`asyncio.CancelledError` into an :exc:`asyncio.TimeoutError`, + which means the :exc:`asyncio.TimeoutError` can only be caught + *outside* of the context manager. + + Example of catching :exc:`asyncio.TimeoutError`:: + + async def main(): + try: + async with asyncio.timeout(10): + await long_running_task() + except TimeoutError: + print("The long operation timed out, but we've handled it.") + + print("This statement will run regardless.") + + The context manager produced by :func:`asyncio.timeout` can be + rescheduled to a different deadline and inspected. + + .. class:: Timeout() + + An :ref:`asynchronous context manager <async-context-managers>` + that limits time spent inside of it. + + .. versionadded:: 3.11 + + .. method:: when() -> float | None + + Return the current deadline, or ``None`` if the current + deadline is not set. + + The deadline is a float, consistent with the time returned by + :meth:`loop.time`. + + .. method:: reschedule(when: float | None) + + Change the time the timeout will trigger. + + If *when* is `None`, any current deadline will be removed, and the + context manager will wait indefinitely. + + If *when* is a float, it is set as the new deadline. + + if *when* is in the past, the timeout will trigger on the next + iteration of the event loop. + + .. method:: expired() -> bool + + Return whether the context manager has exceeded its deadline + (expired). + + Example:: + + async def main(): + try: + # We do not know the timeout when starting, so we pass ``None``. + async with asyncio.timeout(None) as cm: + # We know the timeout now, so we reschedule it. + new_deadline = get_running_loop().time() + 10 + cm.reschedule(new_deadline) + + await long_running_task() + except TimeoutError: + pass + + if cm.expired: + print("Looks like we haven't finished on time.") + + Timeout context managers can be safely nested. + + .. versionadded:: 3.11 + +.. coroutinefunction:: timeout_at(when) + + Similar to :func:`asyncio.timeout`, except *when* is the absolute time + to stop waiting, or ``None``. + + Example:: + + async def main(): + loop = get_running_loop() + deadline = loop.time() + 20 + try: + async with asyncio.timeout_at(deadline): + await long_running_task() + except TimeoutError: + print("The long operation timed out, but we've handled it.") + + print("This statement will run regardless.") + + .. versionadded:: 3.11 + .. coroutinefunction:: wait_for(aw, timeout) Wait for the *aw* :ref:`awaitable <asyncio-awaitables>` diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst index d131408175fd16978dad604c3eddea646cf3010f..4a665f2254f8a6138a87ae3d4f760e9aa341f39f 100644 --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -1530,7 +1530,7 @@ functions can be used directly if desired. This module implements the ANSI codepage (CP_ACP). -.. availability:: Windows only. +.. availability:: Windows. .. versionchanged:: 3.3 Support any error handler. diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst index 8efbf0a3d59554320fd076d3352bb4324797d4a6..db5971e4d60fc9dcdbc95a0dbb2144f2e1b04128 100644 --- a/Doc/library/concurrent.futures.rst +++ b/Doc/library/concurrent.futures.rst @@ -149,6 +149,13 @@ And:: An :class:`Executor` subclass that uses a pool of at most *max_workers* threads to execute calls asynchronously. + All threads enqueued to ``ThreadPoolExecutor`` will be joined before the + interpreter can exit. Note that the exit handler which does this is + executed *before* any exit handlers added using `atexit`. This means + exceptions in the main thread must be caught and handled in order to + signal threads to exit gracefully. For this reason, it is recommended + that ``ThreadPoolExecutor`` not be used for long-running tasks. + *initializer* is an optional callable that is called at the start of each worker thread; *initargs* is a tuple of arguments passed to the initializer. Should *initializer* raise an exception, all currently diff --git a/Doc/library/crypt.rst b/Doc/library/crypt.rst index efba4236bcbcccfe9b7b2d4266ccaf173c7a68e6..f585bbcbc18b8e33e61d7179b00b813ea4a2c57c 100644 --- a/Doc/library/crypt.rst +++ b/Doc/library/crypt.rst @@ -36,7 +36,7 @@ the :manpage:`crypt(3)` routine in the running system. Therefore, any extensions available on the current implementation will also be available on this module. -.. availability:: Unix. Not available on VxWorks. +.. availability:: Unix, not VxWorks. Hashing Methods --------------- diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index ef1535c84bd5adb279e392706d17daef71a104a9..0f042374b6472d85f9575696fa82d1a54f504dc8 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -589,8 +589,8 @@ Supported operations: +-------------------------------+----------------------------------------------+ | Operation | Result | +===============================+==============================================+ -| ``date2 = date1 + timedelta`` | *date2* is ``timedelta.days`` days removed | -| | from *date1*. (1) | +| ``date2 = date1 + timedelta`` | *date2* will be ``timedelta.days`` days | +| | after *date1*. (1) | +-------------------------------+----------------------------------------------+ | ``date2 = date1 - timedelta`` | Computes *date2* such that ``date2 + | | | timedelta == date1``. (2) | @@ -1370,8 +1370,8 @@ Instance methods: time and this method relies on the platform C :c:func:`mktime` function to perform the conversion. Since :class:`.datetime` supports wider range of values than :c:func:`mktime` on many - platforms, this method may raise :exc:`OverflowError` for times far - in the past or far in the future. + platforms, this method may raise :exc:`OverflowError` or :exc:`OSError` + for times far in the past or far in the future. For aware :class:`.datetime` instances, the return value is computed as:: diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 9173c1bcf5e7ba98f60867a2d1de2cd01b63e87d..85bd94b4eae94937aa8aac64da7107c02df12d17 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -604,12 +604,6 @@ iterations of the loop. .. versionchanged:: 3.11 oparg set to be the stack depth, for efficient handling on frames. -.. opcode:: YIELD_FROM - - Pops TOS and delegates to it as a subiterator from a :term:`generator`. - - .. versionadded:: 3.3 - .. opcode:: SETUP_ANNOTATIONS diff --git a/Doc/library/distribution.rst b/Doc/library/distribution.rst index 8d4befe41b329cf93e98f13b769b7a9651776e37..bec1ca3cc3913713e5a561a8f911917c5719d653 100644 --- a/Doc/library/distribution.rst +++ b/Doc/library/distribution.rst @@ -9,7 +9,6 @@ with a local index server, or without any index server at all. .. toctree:: - distutils.rst ensurepip.rst venv.rst zipapp.rst diff --git a/Doc/library/distutils.rst b/Doc/library/distutils.rst deleted file mode 100644 index 31c4ae5b23906b0bd12ab644e424bd91e84ae26b..0000000000000000000000000000000000000000 --- a/Doc/library/distutils.rst +++ /dev/null @@ -1,49 +0,0 @@ -:mod:`distutils` --- Building and installing Python modules -=========================================================== - -.. module:: distutils - :synopsis: Support for building and installing Python modules into an - existing Python installation. - -.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org> - --------------- - -:mod:`distutils` is deprecated with removal planned for Python 3.12. -See the :ref:`What's New <distutils-deprecated>` entry for more information. - --------------- - -The :mod:`distutils` package provides support for building and installing -additional modules into a Python installation. The new modules may be either -100%-pure Python, or may be extension modules written in C, or may be -collections of Python packages which include modules coded in both Python and C. - -Most Python users will *not* want to use this module directly, but instead -use the cross-version tools maintained by the Python Packaging Authority. In -particular, -`setuptools <https://setuptools.readthedocs.io/en/latest/>`__ is an -enhanced alternative to :mod:`distutils` that provides: - -* support for declaring project dependencies -* additional mechanisms for configuring which files to include in source - releases (including plugins for integration with version control systems) -* the ability to declare project "entry points", which can be used as the - basis for application plugin systems -* the ability to automatically generate Windows command line executables at - installation time rather than needing to prebuild them -* consistent behaviour across all supported Python versions - -The recommended `pip <https://pip.pypa.io/>`__ installer runs all -``setup.py`` scripts with ``setuptools``, even if the script itself only -imports ``distutils``. Refer to the -`Python Packaging User Guide <https://packaging.python.org>`_ for more -information. - -For the benefits of packaging tool authors and users seeking a deeper -understanding of the details of the current packaging and distribution -system, the legacy :mod:`distutils` based user documentation and API -reference remain available: - -* :ref:`install-index` -* :ref:`distutils-index` diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index b1333c7dd5cf9d05d97456ff325ec2f159d04a71..01743b002ba96cd328a267a60b504f5629bb247a 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -176,13 +176,6 @@ Data Types >>> dir(Color) ['BLUE', 'GREEN', 'RED', '__class__', '__contains__', '__doc__', '__getitem__', '__init_subclass__', '__iter__', '__len__', '__members__', '__module__', '__name__', '__qualname__'] - .. method:: EnumType.__getattr__(cls, name) - - Returns the Enum member in *cls* matching *name*, or raises an :exc:`AttributeError`:: - - >>> Color.GREEN - <Color.GREEN: 2> - .. method:: EnumType.__getitem__(cls, name) Returns the Enum member in *cls* matching *name*, or raises an :exc:`KeyError`:: diff --git a/Doc/library/grp.rst b/Doc/library/grp.rst index fbfb922d3e0528ee4723d047910f696e67e05351..baa31752a2c750c73d7b0e8c79263fdd05a8c851 100644 --- a/Doc/library/grp.rst +++ b/Doc/library/grp.rst @@ -38,7 +38,7 @@ accessible via :func:`getgrnam` or :func:`getgrgid`.) It defines the following items: -.. function:: getgrgid(gid) +.. function:: getgrgid(id) Return the group database entry for the given numeric group ID. :exc:`KeyError` is raised if the entry asked for cannot be found. diff --git a/Doc/library/importlib.resources.abc.rst b/Doc/library/importlib.resources.abc.rst index 6b0e1e04c8852a7a9340167f7fc43fb83392fff5..57fffe0d905cbe7514e8145dd88f2913553de47e 100644 --- a/Doc/library/importlib.resources.abc.rst +++ b/Doc/library/importlib.resources.abc.rst @@ -1,3 +1,15 @@ +:mod:`importlib.resources.abc` -- Abstract base classes for resources +--------------------------------------------------------------------- + +.. module:: importlib.resources.abc + :synopsis: Abstract base classes for resources + +**Source code:** :source:`Lib/importlib/resources/abc.py` + +-------------- + +.. versionadded:: 3.11 + .. class:: ResourceReader *Superseded by TraversableResources* @@ -33,6 +45,9 @@ .. versionadded:: 3.7 + .. deprecated-removed:: 3.12 3.14 + Use :class:`importlib.resources.abc.TraversableResources` instead. + .. abstractmethod:: open_resource(resource) Returns an opened, :term:`file-like object` for binary reading @@ -72,251 +87,6 @@ The abstract method returns an iterable of no items. -.. class:: ResourceLoader - - An abstract base class for a :term:`loader` which implements the optional - :pep:`302` protocol for loading arbitrary resources from the storage - back-end. - - .. deprecated:: 3.7 - This ABC is deprecated in favour of supporting resource loading - through :class:`importlib.abc.ResourceReader`. - - .. abstractmethod:: get_data(path) - - An abstract method to return the bytes for the data located at *path*. - Loaders that have a file-like storage back-end - that allows storing arbitrary data - can implement this abstract method to give direct access - to the data stored. :exc:`OSError` is to be raised if the *path* cannot - be found. The *path* is expected to be constructed using a module's - :attr:`__file__` attribute or an item from a package's :attr:`__path__`. - - .. versionchanged:: 3.4 - Raises :exc:`OSError` instead of :exc:`NotImplementedError`. - - -.. class:: InspectLoader - - An abstract base class for a :term:`loader` which implements the optional - :pep:`302` protocol for loaders that inspect modules. - - .. method:: get_code(fullname) - - Return the code object for a module, or ``None`` if the module does not - have a code object (as would be the case, for example, for a built-in - module). Raise an :exc:`ImportError` if loader cannot find the - requested module. - - .. note:: - While the method has a default implementation, it is suggested that - it be overridden if possible for performance. - - .. index:: - single: universal newlines; importlib.abc.InspectLoader.get_source method - - .. versionchanged:: 3.4 - No longer abstract and a concrete implementation is provided. - - .. abstractmethod:: get_source(fullname) - - An abstract method to return the source of a module. It is returned as - a text string using :term:`universal newlines`, translating all - recognized line separators into ``'\n'`` characters. Returns ``None`` - if no source is available (e.g. a built-in module). Raises - :exc:`ImportError` if the loader cannot find the module specified. - - .. versionchanged:: 3.4 - Raises :exc:`ImportError` instead of :exc:`NotImplementedError`. - - .. method:: is_package(fullname) - - An optional method to return a true value if the module is a package, a - false value otherwise. :exc:`ImportError` is raised if the - :term:`loader` cannot find the module. - - .. versionchanged:: 3.4 - Raises :exc:`ImportError` instead of :exc:`NotImplementedError`. - - .. staticmethod:: source_to_code(data, path='<string>') - - Create a code object from Python source. - - The *data* argument can be whatever the :func:`compile` function - supports (i.e. string or bytes). The *path* argument should be - the "path" to where the source code originated from, which can be an - abstract concept (e.g. location in a zip file). - - With the subsequent code object one can execute it in a module by - running ``exec(code, module.__dict__)``. - - .. versionadded:: 3.4 - - .. versionchanged:: 3.5 - Made the method static. - - .. method:: exec_module(module) - - Implementation of :meth:`Loader.exec_module`. - - .. versionadded:: 3.4 - - .. method:: load_module(fullname) - - Implementation of :meth:`Loader.load_module`. - - .. deprecated:: 3.4 - use :meth:`exec_module` instead. - - -.. class:: ExecutionLoader - - An abstract base class which inherits from :class:`InspectLoader` that, - when implemented, helps a module to be executed as a script. The ABC - represents an optional :pep:`302` protocol. - - .. abstractmethod:: get_filename(fullname) - - An abstract method that is to return the value of :attr:`__file__` for - the specified module. If no path is available, :exc:`ImportError` is - raised. - - If source code is available, then the method should return the path to - the source file, regardless of whether a bytecode was used to load the - module. - - .. versionchanged:: 3.4 - Raises :exc:`ImportError` instead of :exc:`NotImplementedError`. - - -.. class:: FileLoader(fullname, path) - - An abstract base class which inherits from :class:`ResourceLoader` and - :class:`ExecutionLoader`, providing concrete implementations of - :meth:`ResourceLoader.get_data` and :meth:`ExecutionLoader.get_filename`. - - The *fullname* argument is a fully resolved name of the module the loader is - to handle. The *path* argument is the path to the file for the module. - - .. versionadded:: 3.3 - - .. attribute:: name - - The name of the module the loader can handle. - - .. attribute:: path - - Path to the file of the module. - - .. method:: load_module(fullname) - - Calls super's ``load_module()``. - - .. deprecated:: 3.4 - Use :meth:`Loader.exec_module` instead. - - .. abstractmethod:: get_filename(fullname) - - Returns :attr:`path`. - - .. abstractmethod:: get_data(path) - - Reads *path* as a binary file and returns the bytes from it. - - -.. class:: SourceLoader - - An abstract base class for implementing source (and optionally bytecode) - file loading. The class inherits from both :class:`ResourceLoader` and - :class:`ExecutionLoader`, requiring the implementation of: - - * :meth:`ResourceLoader.get_data` - * :meth:`ExecutionLoader.get_filename` - Should only return the path to the source file; sourceless - loading is not supported. - - The abstract methods defined by this class are to add optional bytecode - file support. Not implementing these optional methods (or causing them to - raise :exc:`NotImplementedError`) causes the loader to - only work with source code. Implementing the methods allows the loader to - work with source *and* bytecode files; it does not allow for *sourceless* - loading where only bytecode is provided. Bytecode files are an - optimization to speed up loading by removing the parsing step of Python's - compiler, and so no bytecode-specific API is exposed. - - .. method:: path_stats(path) - - Optional abstract method which returns a :class:`dict` containing - metadata about the specified path. Supported dictionary keys are: - - - ``'mtime'`` (mandatory): an integer or floating-point number - representing the modification time of the source code; - - ``'size'`` (optional): the size in bytes of the source code. - - Any other keys in the dictionary are ignored, to allow for future - extensions. If the path cannot be handled, :exc:`OSError` is raised. - - .. versionadded:: 3.3 - - .. versionchanged:: 3.4 - Raise :exc:`OSError` instead of :exc:`NotImplementedError`. - - .. method:: path_mtime(path) - - Optional abstract method which returns the modification time for the - specified path. - - .. deprecated:: 3.3 - This method is deprecated in favour of :meth:`path_stats`. You don't - have to implement it, but it is still available for compatibility - purposes. Raise :exc:`OSError` if the path cannot be handled. - - .. versionchanged:: 3.4 - Raise :exc:`OSError` instead of :exc:`NotImplementedError`. - - .. method:: set_data(path, data) - - Optional abstract method which writes the specified bytes to a file - path. Any intermediate directories which do not exist are to be created - automatically. - - When writing to the path fails because the path is read-only - (:attr:`errno.EACCES`/:exc:`PermissionError`), do not propagate the - exception. - - .. versionchanged:: 3.4 - No longer raises :exc:`NotImplementedError` when called. - - .. method:: get_code(fullname) - - Concrete implementation of :meth:`InspectLoader.get_code`. - - .. method:: exec_module(module) - - Concrete implementation of :meth:`Loader.exec_module`. - - .. versionadded:: 3.4 - - .. method:: load_module(fullname) - - Concrete implementation of :meth:`Loader.load_module`. - - .. deprecated:: 3.4 - Use :meth:`exec_module` instead. - - .. method:: get_source(fullname) - - Concrete implementation of :meth:`InspectLoader.get_source`. - - .. method:: is_package(fullname) - - Concrete implementation of :meth:`InspectLoader.is_package`. A module - is determined to be a package if its file path (as provided by - :meth:`ExecutionLoader.get_filename`) is a file named - ``__init__`` when the file extension is removed **and** the module name - itself does not end in ``__init__``. - - .. class:: Traversable An object with a subset of pathlib.Path methods suitable for @@ -324,6 +94,9 @@ .. versionadded:: 3.9 + .. deprecated-removed:: 3.12 3.14 + Use :class:`importlib.resources.abc.Traversable` instead. + .. attribute:: name Abstract. The base name of this object without any parent references. @@ -369,8 +142,8 @@ An abstract base class for resource readers capable of serving the :meth:`importlib.resources.files` interface. Subclasses - :class:`importlib.abc.ResourceReader` and provides - concrete implementations of the :class:`importlib.abc.ResourceReader`'s + :class:`importlib.resources.abc.ResourceReader` and provides + concrete implementations of the :class:`importlib.resources.abc.ResourceReader`'s abstract methods. Therefore, any loader supplying :class:`importlib.abc.TraversableReader` also supplies ResourceReader. @@ -379,7 +152,10 @@ .. versionadded:: 3.9 + .. deprecated-removed:: 3.12 3.14 + Use :class:`importlib.resources.abc.TraversableResources` instead. + .. abstractmethod:: files() - Returns a :class:`importlib.abc.Traversable` object for the loaded + Returns a :class:`importlib.resources.abc.Traversable` object for the loaded package. diff --git a/Doc/library/importlib.resources.rst b/Doc/library/importlib.resources.rst index b88c9882de44b880a26df3f32be82f8c4bfd7d80..d367dcee7c2072d9f4f32052f085fc72f7daee7f 100644 --- a/Doc/library/importlib.resources.rst +++ b/Doc/library/importlib.resources.rst @@ -17,7 +17,9 @@ text mode. Resources are roughly akin to files inside directories, though it's important to keep in mind that this is just a metaphor. Resources and packages **do -not** have to exist as physical files and directories on the file system. +not** have to exist as physical files and directories on the file system: +for example, a package and its resources can be imported from a zip file using +:py:mod:`zipimport`. .. note:: @@ -33,47 +35,36 @@ not** have to exist as physical files and directories on the file system. on `using importlib.resources <http://importlib-resources.readthedocs.io/en/latest/using.html>`_ and `migrating from pkg_resources to importlib.resources - <http://importlib-resources.readthedocs.io/en/latest/migration.html>`_ - and - `migrating legacy usage <https://importlib-resources.readthedocs.io/en/latest/using.html#migrating-from-legacy>`_. + <http://importlib-resources.readthedocs.io/en/latest/migration.html>`_. -Loaders that wish to support resource reading should implement a +:class:`Loaders <importlib.abc.Loader>` that wish to support resource reading should implement a ``get_resource_reader(fullname)`` method as specified by -:class:`importlib.abc.ResourceReader`. - -The following types are defined. +:class:`importlib.resources.abc.ResourceReader`. .. data:: Package - The ``Package`` type is defined as ``Union[str, ModuleType]``. This means - that where the function describes accepting a ``Package``, you can pass in - either a string or a module. Module objects must have a resolvable - ``__spec__.submodule_search_locations`` that is not ``None``. - -.. data:: Resource - - This type describes the resource names passed into the various functions - in this package. This is defined as ``Union[str, os.PathLike]``. - - -The following functions are available. + Whenever a function accepts a ``Package`` argument, you can pass in + either a :class:`module object <types.ModuleType>` or a module name + as a string. You can only pass module objects whose + ``__spec__.submodule_search_locations`` is not ``None``. + The ``Package`` type is defined as ``Union[str, ModuleType]``. .. function:: files(package) - Returns an :class:`importlib.resources.abc.Traversable` object + Returns a :class:`~importlib.resources.abc.Traversable` object representing the resource container for the package (think directory) and its resources (think files). A Traversable may contain other containers (think subdirectories). *package* is either a name or a module object which conforms to the - ``Package`` requirements. + :data:`Package` requirements. .. versionadded:: 3.9 .. function:: as_file(traversable) - Given a :class:`importlib.resources.abc.Traversable` object representing + Given a :class:`~importlib.resources.abc.Traversable` object representing a file, typically from :func:`importlib.resources.files`, return a context manager for use in a :keyword:`with` statement. The context manager provides a :class:`pathlib.Path` object. @@ -87,6 +78,22 @@ The following functions are available. .. versionadded:: 3.9 +Deprecated functions +-------------------- + +An older, deprecated set of functions is still available, but is +scheduled for removal in a future version of Python. +The main drawback of these functions is that they do not support +directories: they assume all resources are located directly within a *package*. + +.. data:: Resource + + For *resource* arguments of the functions below, you can pass in + the name of a resource as a string or + a :class:`path-like object <os.PathLike>`. + + The ``Resource`` type is defined as ``Union[str, os.PathLike]``. + .. function:: open_binary(package, resource) Open for binary reading the *resource* within *package*. @@ -97,7 +104,11 @@ The following functions are available. sub-resources (i.e. it cannot be a directory). This function returns a ``typing.BinaryIO`` instance, a binary I/O stream open for reading. - .. deprecated:: 3.11 + .. deprecated:: 3.11 + + Calls to this function can be replaced by:: + + files(package).joinpath(resource).open('rb') .. function:: open_text(package, resource, encoding='utf-8', errors='strict') @@ -114,7 +125,11 @@ The following functions are available. This function returns a ``typing.TextIO`` instance, a text I/O stream open for reading. - .. deprecated:: 3.11 + .. deprecated:: 3.11 + + Calls to this function can be replaced by:: + + files(package).joinpath(resource).open('r', encoding=encoding) .. function:: read_binary(package, resource) @@ -128,7 +143,11 @@ The following functions are available. sub-resources (i.e. it cannot be a directory). This function returns the contents of the resource as :class:`bytes`. - .. deprecated:: 3.11 + .. deprecated:: 3.11 + + Calls to this function can be replaced by:: + + files(package).joinpath(resource).read_bytes() .. function:: read_text(package, resource, encoding='utf-8', errors='strict') @@ -143,7 +162,11 @@ The following functions are available. have the same meaning as with built-in :func:`open`. This function returns the contents of the resource as :class:`str`. - .. deprecated:: 3.11 + .. deprecated:: 3.11 + + Calls to this function can be replaced by:: + + files(package).joinpath(resource).read_text(encoding=encoding) .. function:: path(package, resource) @@ -160,17 +183,26 @@ The following functions are available. within *package*; it may not contain path separators and it may not have sub-resources (i.e. it cannot be a directory). - .. deprecated:: 3.11 + .. deprecated:: 3.11 + + Calls to this function can be replaced using :func:`as_file`:: + + as_file(files(package).joinpath(resource)) .. function:: is_resource(package, name) Return ``True`` if there is a resource named *name* in the package, - otherwise ``False``. Remember that directories are *not* resources! + otherwise ``False``. + This function does not consider directories to be resources. *package* is either a name or a module object which conforms to the ``Package`` requirements. - .. deprecated:: 3.11 + .. deprecated:: 3.11 + + Calls to this function can be replaced by:: + + files(package).joinpath(resource).is_file() .. function:: contents(package) @@ -182,4 +214,8 @@ The following functions are available. *package* is either a name or a module object which conforms to the ``Package`` requirements. - .. deprecated:: 3.11 + .. deprecated:: 3.11 + + Calls to this function can be replaced by:: + + (resource.name for resource in files(package).iterdir() if resource.is_file()) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 44bf703e93a840798dccba881f4c9e3060d2a5cd..c29d69c143cfe6fadaed302fe970f35273bf2648 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -401,7 +401,7 @@ ABC hierarchy:: Loaders that wish to support resource reading should implement a :meth:`get_resource_reader` method as specified by - :class:`importlib.abc.ResourceReader`. + :class:`importlib.resources.abc.ResourceReader`. .. versionchanged:: 3.7 Introduced the optional :meth:`get_resource_reader` method. @@ -508,7 +508,250 @@ ABC hierarchy:: The import machinery now takes care of this automatically. -.. include:: importlib.resources.abc.rst +.. class:: ResourceLoader + + An abstract base class for a :term:`loader` which implements the optional + :pep:`302` protocol for loading arbitrary resources from the storage + back-end. + + .. deprecated:: 3.7 + This ABC is deprecated in favour of supporting resource loading + through :class:`importlib.resources.abc.ResourceReader`. + + .. abstractmethod:: get_data(path) + + An abstract method to return the bytes for the data located at *path*. + Loaders that have a file-like storage back-end + that allows storing arbitrary data + can implement this abstract method to give direct access + to the data stored. :exc:`OSError` is to be raised if the *path* cannot + be found. The *path* is expected to be constructed using a module's + :attr:`__file__` attribute or an item from a package's :attr:`__path__`. + + .. versionchanged:: 3.4 + Raises :exc:`OSError` instead of :exc:`NotImplementedError`. + + +.. class:: InspectLoader + + An abstract base class for a :term:`loader` which implements the optional + :pep:`302` protocol for loaders that inspect modules. + + .. method:: get_code(fullname) + + Return the code object for a module, or ``None`` if the module does not + have a code object (as would be the case, for example, for a built-in + module). Raise an :exc:`ImportError` if loader cannot find the + requested module. + + .. note:: + While the method has a default implementation, it is suggested that + it be overridden if possible for performance. + + .. index:: + single: universal newlines; importlib.abc.InspectLoader.get_source method + + .. versionchanged:: 3.4 + No longer abstract and a concrete implementation is provided. + + .. abstractmethod:: get_source(fullname) + + An abstract method to return the source of a module. It is returned as + a text string using :term:`universal newlines`, translating all + recognized line separators into ``'\n'`` characters. Returns ``None`` + if no source is available (e.g. a built-in module). Raises + :exc:`ImportError` if the loader cannot find the module specified. + + .. versionchanged:: 3.4 + Raises :exc:`ImportError` instead of :exc:`NotImplementedError`. + + .. method:: is_package(fullname) + + An optional method to return a true value if the module is a package, a + false value otherwise. :exc:`ImportError` is raised if the + :term:`loader` cannot find the module. + + .. versionchanged:: 3.4 + Raises :exc:`ImportError` instead of :exc:`NotImplementedError`. + + .. staticmethod:: source_to_code(data, path='<string>') + + Create a code object from Python source. + + The *data* argument can be whatever the :func:`compile` function + supports (i.e. string or bytes). The *path* argument should be + the "path" to where the source code originated from, which can be an + abstract concept (e.g. location in a zip file). + + With the subsequent code object one can execute it in a module by + running ``exec(code, module.__dict__)``. + + .. versionadded:: 3.4 + + .. versionchanged:: 3.5 + Made the method static. + + .. method:: exec_module(module) + + Implementation of :meth:`Loader.exec_module`. + + .. versionadded:: 3.4 + + .. method:: load_module(fullname) + + Implementation of :meth:`Loader.load_module`. + + .. deprecated:: 3.4 + use :meth:`exec_module` instead. + + +.. class:: ExecutionLoader + + An abstract base class which inherits from :class:`InspectLoader` that, + when implemented, helps a module to be executed as a script. The ABC + represents an optional :pep:`302` protocol. + + .. abstractmethod:: get_filename(fullname) + + An abstract method that is to return the value of :attr:`__file__` for + the specified module. If no path is available, :exc:`ImportError` is + raised. + + If source code is available, then the method should return the path to + the source file, regardless of whether a bytecode was used to load the + module. + + .. versionchanged:: 3.4 + Raises :exc:`ImportError` instead of :exc:`NotImplementedError`. + + +.. class:: FileLoader(fullname, path) + + An abstract base class which inherits from :class:`ResourceLoader` and + :class:`ExecutionLoader`, providing concrete implementations of + :meth:`ResourceLoader.get_data` and :meth:`ExecutionLoader.get_filename`. + + The *fullname* argument is a fully resolved name of the module the loader is + to handle. The *path* argument is the path to the file for the module. + + .. versionadded:: 3.3 + + .. attribute:: name + + The name of the module the loader can handle. + + .. attribute:: path + + Path to the file of the module. + + .. method:: load_module(fullname) + + Calls super's ``load_module()``. + + .. deprecated:: 3.4 + Use :meth:`Loader.exec_module` instead. + + .. abstractmethod:: get_filename(fullname) + + Returns :attr:`path`. + + .. abstractmethod:: get_data(path) + + Reads *path* as a binary file and returns the bytes from it. + + +.. class:: SourceLoader + + An abstract base class for implementing source (and optionally bytecode) + file loading. The class inherits from both :class:`ResourceLoader` and + :class:`ExecutionLoader`, requiring the implementation of: + + * :meth:`ResourceLoader.get_data` + * :meth:`ExecutionLoader.get_filename` + Should only return the path to the source file; sourceless + loading is not supported. + + The abstract methods defined by this class are to add optional bytecode + file support. Not implementing these optional methods (or causing them to + raise :exc:`NotImplementedError`) causes the loader to + only work with source code. Implementing the methods allows the loader to + work with source *and* bytecode files; it does not allow for *sourceless* + loading where only bytecode is provided. Bytecode files are an + optimization to speed up loading by removing the parsing step of Python's + compiler, and so no bytecode-specific API is exposed. + + .. method:: path_stats(path) + + Optional abstract method which returns a :class:`dict` containing + metadata about the specified path. Supported dictionary keys are: + + - ``'mtime'`` (mandatory): an integer or floating-point number + representing the modification time of the source code; + - ``'size'`` (optional): the size in bytes of the source code. + + Any other keys in the dictionary are ignored, to allow for future + extensions. If the path cannot be handled, :exc:`OSError` is raised. + + .. versionadded:: 3.3 + + .. versionchanged:: 3.4 + Raise :exc:`OSError` instead of :exc:`NotImplementedError`. + + .. method:: path_mtime(path) + + Optional abstract method which returns the modification time for the + specified path. + + .. deprecated:: 3.3 + This method is deprecated in favour of :meth:`path_stats`. You don't + have to implement it, but it is still available for compatibility + purposes. Raise :exc:`OSError` if the path cannot be handled. + + .. versionchanged:: 3.4 + Raise :exc:`OSError` instead of :exc:`NotImplementedError`. + + .. method:: set_data(path, data) + + Optional abstract method which writes the specified bytes to a file + path. Any intermediate directories which do not exist are to be created + automatically. + + When writing to the path fails because the path is read-only + (:attr:`errno.EACCES`/:exc:`PermissionError`), do not propagate the + exception. + + .. versionchanged:: 3.4 + No longer raises :exc:`NotImplementedError` when called. + + .. method:: get_code(fullname) + + Concrete implementation of :meth:`InspectLoader.get_code`. + + .. method:: exec_module(module) + + Concrete implementation of :meth:`Loader.exec_module`. + + .. versionadded:: 3.4 + + .. method:: load_module(fullname) + + Concrete implementation of :meth:`Loader.load_module`. + + .. deprecated:: 3.4 + Use :meth:`exec_module` instead. + + .. method:: get_source(fullname) + + Concrete implementation of :meth:`InspectLoader.get_source`. + + .. method:: is_package(fullname) + + Concrete implementation of :meth:`InspectLoader.is_package`. A module + is determined to be a package if its file path (as provided by + :meth:`ExecutionLoader.get_filename`) is a file named + ``__init__`` when the file extension is removed **and** the module name + itself does not end in ``__init__``. + :mod:`importlib.machinery` -- Importers and path hooks diff --git a/Doc/library/intro.rst b/Doc/library/intro.rst index 5bb33b9c10cc03db9379a132ab2fff7453a6b082..120b174dc3b1e70244c1545d438d9340109c2a0b 100644 --- a/Doc/library/intro.rst +++ b/Doc/library/intro.rst @@ -60,3 +60,7 @@ Notes on availability * If not separately noted, all functions that claim "Availability: Unix" are supported on macOS, which builds on a Unix core. +* If an availability note contains both a minimum Kernel version and a minimum + libc version, then both conditions must hold. For example a feature with note + *Availability: Linux >= 3.17 with glibc >= 2.27* requires both Linux 3.17 or + newer and glibc 2.27 or newer. diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst index 1447cabb9a1df00f0672adede3d37fd970e223e1..0dc05255db9cb8982c4a65cdac3b6fae7c10d4e4 100644 --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -1018,6 +1018,8 @@ possible, while any potentially slow operations (such as sending an email via have the task tracking API, which means that you can use :class:`~queue.SimpleQueue` instances for *queue*. + .. note:: If you are using :mod:`multiprocessing`, you should avoid using + :class:`~queue.SimpleQueue` and instead use :class:`multiprocessing.Queue`. .. method:: emit(record) @@ -1091,6 +1093,9 @@ possible, while any potentially slow operations (such as sending an email via task tracking API (though it's used if available), which means that you can use :class:`~queue.SimpleQueue` instances for *queue*. + .. note:: If you are using :mod:`multiprocessing`, you should avoid using + :class:`~queue.SimpleQueue` and instead use :class:`multiprocessing.Queue`. + If ``respect_handler_level`` is ``True``, a handler's level is respected (compared with the level for the message) when deciding whether to pass messages to that handler; otherwise, the behaviour is as in previous Python diff --git a/Doc/library/modules.rst b/Doc/library/modules.rst index 6cf6eb28a1e058f60a564d2768351d2685b0be06..8c5936a4d8de2b287c136672b97d121c6310c693 100644 --- a/Doc/library/modules.rst +++ b/Doc/library/modules.rst @@ -18,5 +18,6 @@ The full list of modules described in this chapter is: runpy.rst importlib.rst importlib.resources.rst + importlib.resources.abc.rst importlib.metadata.rst sys_path_init.rst diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index a8e35bc084747237b4f411108dab032ffff75379..3eb98791726de1598bd6bb2040e2be792363d23f 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -1706,7 +1706,7 @@ their parent process exits. The manager classes are defined in the shutdown times out, the process is terminated. If terminating the process also times out, the process is killed. - .. versionchanged: 3.11 + .. versionchanged:: 3.11 Added the *shutdown_timeout* parameter. .. method:: start([initializer[, initargs]]) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 4639a8b4afe593d40052298cf59d58c80aef0612..d3500d5a1b3298db5bc5daaaf6e7ff7e572b599c 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -301,7 +301,7 @@ process and user. and ``'surrogateescape'`` error handler. Use :func:`os.getenvb` if you would like to use a different encoding. - .. availability:: most flavors of Unix, Windows. + .. availability:: Unix, Windows. .. function:: getenvb(key, default=None) @@ -316,7 +316,7 @@ process and user. :func:`getenvb` is only available if :data:`supports_bytes_environ` is ``True``. - .. availability:: most flavors of Unix. + .. availability:: Unix. .. versionadded:: 3.2 @@ -706,7 +706,7 @@ process and user. :func:`socket.gethostname` or even ``socket.gethostbyaddr(socket.gethostname())``. - .. availability:: recent flavors of Unix. + .. availability:: Unix. .. versionchanged:: 3.3 Return type changed from a tuple to a tuple-like object @@ -824,7 +824,7 @@ as internal buffering of data. It will always copy no bytes and return 0 as if the file was empty because of a known Linux kernel issue. - .. availability:: Linux kernel >= 4.5 or glibc >= 2.27. + .. availability:: Linux >= 4.5 with glibc >= 2.27. .. versionadded:: 3.8 @@ -1164,7 +1164,7 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo descriptors are :ref:`non-inheritable <fd_inheritance>`. For a (slightly) more portable approach, use the :mod:`pty` module. - .. availability:: some flavors of Unix. + .. availability:: Unix. .. versionchanged:: 3.4 The new file descriptors are now non-inheritable. @@ -1190,7 +1190,7 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo Return a pair of file descriptors ``(r, w)`` usable for reading and writing, respectively. - .. availability:: some flavors of Unix. + .. availability:: Unix. .. versionadded:: 3.3 @@ -1269,9 +1269,9 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo Combine the functionality of :func:`os.readv` and :func:`os.pread`. - .. availability:: Linux 2.6.30 and newer, FreeBSD 6.0 and newer, - OpenBSD 2.7 and newer, AIX 7.1 and newer. Using flags requires - Linux 4.6 or newer. + .. availability:: Linux >= 2.6.30, FreeBSD >= 6.0, OpenBSD >= 2.7, AIX >= 7.1. + + Using flags requires Linux >= 4.6. .. versionadded:: 3.7 @@ -1286,7 +1286,7 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo If no bytes were read, it will return ``-1`` and set errno to :data:`errno.EAGAIN`. - .. availability:: Linux 4.14 and newer. + .. availability:: Linux >= 4.14. .. versionadded:: 3.7 @@ -1300,7 +1300,7 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo Currently, on Linux, this feature is usable only on a file descriptor opened using the :data:`O_DIRECT` flag. - .. availability:: Linux 4.6 and newer. + .. availability:: Linux >= 4.6. .. versionadded:: 3.7 @@ -1339,9 +1339,9 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo Combine the functionality of :func:`os.writev` and :func:`os.pwrite`. - .. availability:: Linux 2.6.30 and newer, FreeBSD 6.0 and newer, - OpenBSD 2.7 and newer, AIX 7.1 and newer. Using flags requires - Linux 4.7 or newer. + .. availability:: Linux >= 2.6.30, FreeBSD >= 6.0, OpenBSD >= 2.7, AIX >= 7.1. + + Using flags requires Linux >= 4.6. .. versionadded:: 3.7 @@ -1351,7 +1351,7 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo Provide a per-write equivalent of the :data:`O_DSYNC` :func:`os.open` flag. This flag effect applies only to the data range written by the system call. - .. availability:: Linux 4.7 and newer. + .. availability:: Linux >= 4.7. .. versionadded:: 3.7 @@ -1361,7 +1361,7 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo Provide a per-write equivalent of the :data:`O_SYNC` :func:`os.open` flag. This flag effect applies only to the data range written by the system call. - .. availability:: Linux 4.7 and newer. + .. availability:: Linux >= 4.7. .. versionadded:: 3.7 @@ -1375,7 +1375,7 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo appended to the end of the file. However, if the *offset* argument is ``-1``, the current file *offset* is updated. - .. availability:: Linux 4.16 and newer. + .. availability:: Linux >= 4.16. .. versionadded:: 3.10 @@ -1495,7 +1495,7 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo make sense to block because there are no writers connected to the write end of the pipe. - .. availability:: Linux kernel >= 2.6.17 and glibc >= 2.5 + .. availability:: Linux >= 2.6.17 with glibc >= 2.5 .. versionadded:: 3.10 @@ -3334,7 +3334,7 @@ features: the file descriptor, and as such multiple files can have the same name without any side effects. - .. availability:: Linux 3.17 or newer with glibc 2.27 or newer. + .. availability:: Linux >= 3.17 with glibc >= 2.27. .. versionadded:: 3.8 @@ -3359,8 +3359,9 @@ features: These flags can be passed to :func:`memfd_create`. - .. availability:: Linux 3.17 or newer with glibc 2.27 or newer. The - ``MFD_HUGE*`` flags are only available since Linux 4.14. + .. availability:: Linux >= 3.17 with glibc >= 2.27 + + The ``MFD_HUGE*`` flags are only available since Linux 4.14. .. versionadded:: 3.8 @@ -3412,7 +3413,7 @@ features: finally: os.close(fd) - .. availability:: Linux 2.6.27 or newer with glibc 2.8 or newer. + .. availability:: Linux >= 2.6.27 with glibc >= 2.8 .. versionadded:: 3.10 @@ -3421,7 +3422,7 @@ features: Read value from an :func:`eventfd` file descriptor and return a 64 bit unsigned int. The function does not verify that *fd* is an :func:`eventfd`. - .. availability:: See :func:`eventfd` + .. availability:: Linux >= 2.6.27 .. versionadded:: 3.10 @@ -3430,7 +3431,7 @@ features: Add value to an :func:`eventfd` file descriptor. *value* must be a 64 bit unsigned int. The function does not verify that *fd* is an :func:`eventfd`. - .. availability:: See :func:`eventfd` + .. availability:: Linux >= 2.6.27 .. versionadded:: 3.10 @@ -3438,7 +3439,7 @@ features: Set close-on-exec flag for new :func:`eventfd` file descriptor. - .. availability:: See :func:`eventfd` + .. availability:: Linux >= 2.6.27 .. versionadded:: 3.10 @@ -3447,7 +3448,7 @@ features: Set :const:`O_NONBLOCK` status flag for new :func:`eventfd` file descriptor. - .. availability:: See :func:`eventfd` + .. availability:: Linux >= 2.6.27 .. versionadded:: 3.10 @@ -3456,7 +3457,7 @@ features: Provide semaphore-like semantics for reads from a :func:`eventfd` file descriptor. On read the internal counter is decremented by one. - .. availability:: Linux 2.6.30 or newer with glibc 2.8 or newer. + .. availability:: Linux >= 2.6.30 .. versionadded:: 3.10 @@ -3861,7 +3862,7 @@ written in Python, such as a mail server's external command delivery program. Calling ``forkpty()`` in a subinterpreter is no longer supported (:exc:`RuntimeError` is raised). - .. availability:: some flavors of Unix. + .. availability:: Unix. .. function:: kill(pid, sig) @@ -3917,7 +3918,7 @@ written in Python, such as a mail server's external command delivery program. See the :manpage:`pidfd_open(2)` man page for more details. - .. availability:: Linux 5.3+ + .. availability:: Linux >= 5.3 .. versionadded:: 3.9 .. data:: PIDFD_NONBLOCK @@ -3927,7 +3928,7 @@ written in Python, such as a mail server's external command delivery program. then an attempt to wait on the file descriptor using :manpage:`waitid(2)` will immediately return the error :data:`~errno.EAGAIN` rather than blocking. - .. availability:: Linux 5.10+ + .. availability:: Linux >= 5.10 .. versionadded:: 3.12 @@ -4077,7 +4078,9 @@ written in Python, such as a mail server's external command delivery program. .. versionadded:: 3.8 - .. availability:: See :func:`posix_spawn` documentation. + .. availability:: POSIX + + See :func:`posix_spawn` documentation. .. function:: register_at_fork(*, before=None, after_in_parent=None, \ @@ -4177,7 +4180,9 @@ written in Python, such as a mail server's external command delivery program. .. audit-event:: os.spawn mode,path,args,env os.spawnl - .. availability:: Unix, Windows. :func:`spawnlp`, :func:`spawnlpe`, :func:`spawnvp` + .. availability:: Unix, Windows. + + :func:`spawnlp`, :func:`spawnlpe`, :func:`spawnvp` and :func:`spawnvpe` are not available on Windows. :func:`spawnle` and :func:`spawnve` are not thread-safe on Windows; we advise you to use the :mod:`subprocess` module instead. @@ -4381,7 +4386,7 @@ written in Python, such as a mail server's external command delivery program. This is a Linux-specific *idtype* that indicates that *id* is a file descriptor that refers to a process. - .. availability:: Linux 5.4+ + .. availability:: Linux >= 5.4 .. versionadded:: 3.9 @@ -4523,7 +4528,9 @@ written in Python, such as a mail server's external command delivery program. This option causes child processes to be reported if they have been continued from a job control stop since their status was last reported. - .. availability:: some Unix systems. + .. availability:: Unix. + + Some Unix systems. .. data:: WUNTRACED @@ -4929,7 +4936,7 @@ Random numbers See also the `Linux getrandom() manual page <http://man7.org/linux/man-pages/man2/getrandom.2.html>`_. - .. availability:: Linux 3.17 and newer. + .. availability:: Linux >= 3.17. .. versionadded:: 3.6 diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 2b798698385fd1e2e915b8cb9ba40b7cc41ce9eb..19944bd7bd0a8912de5a4f53e12abdb3f99be404 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -946,6 +946,101 @@ call fails (for example because the path doesn't exist). to the directory after creating the iterator, whether a path object for that file be included is unspecified. +.. method:: Path.walk(top_down=True, on_error=None, follow_symlinks=False) + + Generate the file names in a directory tree by walking the tree + either top-down or bottom-up. + + For each directory in the directory tree rooted at *self* (including + *self* but excluding '.' and '..'), the method yields a 3-tuple of + ``(dirpath, dirnames, filenames)``. + + *dirpath* is a :class:`Path` to the directory currently being walked, + *dirnames* is a list of strings for the names of subdirectories in *dirpath* + (excluding ``'.'`` and ``'..'``), and *filenames* is a list of strings for + the names of the non-directory files in *dirpath*. To get a full path + (which begins with *self*) to a file or directory in *dirpath*, do + ``dirpath / name``. Whether or not the lists are sorted is file + system-dependent. + + If the optional argument *top_down* is true (which is the default), the triple for a + directory is generated before the triples for any of its subdirectories + (directories are walked top-down). If *top_down* is false, the triple + for a directory is generated after the triples for all of its subdirectories + (directories are walked bottom-up). No matter the value of *top_down*, the + list of subdirectories is retrieved before the triples for the directory and + its subdirectories are walked. + + When *top_down* is true, the caller can modify the *dirnames* list in-place + (for example, using :keyword:`del` or slice assignment), and :meth:`Path.walk` + will only recurse into the subdirectories whose names remain in *dirnames*. + This can be used to prune the search, or to impose a specific order of visiting, + or even to inform :meth:`Path.walk` about directories the caller creates or + renames before it resumes :meth:`Path.walk` again. Modifying *dirnames* when + *top_down* is false has no effect on the behavior of :meth:`Path.walk()` since the + directories in *dirnames* have already been generated by the time *dirnames* + is yielded to the caller. + + By default, errors from :func:`os.scandir` are ignored. If the optional + argument *on_error* is specified, it should be a callable; it will be + called with one argument, an :exc:`OSError` instance. The callable can handle the + error to continue the walk or re-raise it to stop the walk. Note that the + filename is available as the ``filename`` attribute of the exception object. + + By default, :meth:`Path.walk` does not follow symbolic links, and instead adds them + to the *filenames* list. Set *follow_symlinks* to true to resolve symlinks + and place them in *dirnames* and *filenames* as appropriate for their targets, and + consequently visit directories pointed to by symlinks (where supported). + + .. note:: + + Be aware that setting *follow_symlinks* to true can lead to infinite + recursion if a link points to a parent directory of itself. :meth:`Path.walk` + does not keep track of the directories it has already visited. + + .. note:: + :meth:`Path.walk` assumes the directories it walks are not modified during + execution. For example, if a directory from *dirnames* has been replaced + with a symlink and *follow_symlinks* is false, :meth:`Path.walk` will + still try to descend into it. To prevent such behavior, remove directories + from *dirnames* as appropriate. + + .. note:: + + Unlike :func:`os.walk`, :meth:`Path.walk` lists symlinks to directories in + *filenames* if *follow_symlinks* is false. + + This example displays the number of bytes used by all files in each directory, + while ignoring ``__pycache__`` directories:: + + from pathlib import Path + for root, dirs, files in Path("cpython/Lib/concurrent").walk(on_error=print): + print( + root, + "consumes", + sum((root / file).stat().st_size for file in files), + "bytes in", + len(files), + "non-directory files" + ) + if '__pycache__' in dirs: + dirs.remove('__pycache__') + + This next example is a simple implementation of :func:`shutil.rmtree`. + Walking the tree bottom-up is essential as :func:`rmdir` doesn't allow + deleting a directory before it is empty:: + + # Delete everything reachable from the directory "top". + # CAUTION: This is dangerous! For example, if top == Path('/'), + # it could delete all of your files. + for root, dirs, files in top.walk(topdown=False): + for name in files: + (root / name).unlink() + for name in dirs: + (root / name).rmdir() + + .. versionadded:: 3.12 + .. method:: Path.lchmod(mode) Like :meth:`Path.chmod` but, if the path points to a symbolic link, the @@ -1122,8 +1217,8 @@ call fails (for example because the path doesn't exist). .. method:: Path.rglob(pattern) - This is like calling :func:`Path.glob` with "``**/``" added in front of the - given relative *pattern*:: + Glob the given relative *pattern* recursively. This is like calling + :func:`Path.glob` with "``**/``" added in front of the *pattern*:: >>> sorted(Path().rglob("*.py")) [PosixPath('build/lib/pathlib.py'), @@ -1285,6 +1380,7 @@ Below is a table mapping various :mod:`os` functions to their corresponding :func:`os.path.expanduser` :meth:`Path.expanduser` and :meth:`Path.home` :func:`os.listdir` :meth:`Path.iterdir` +:func:`os.walk` :meth:`Path.walk` :func:`os.path.isdir` :meth:`Path.is_dir` :func:`os.path.isfile` :meth:`Path.is_file` :func:`os.path.islink` :meth:`Path.is_symlink` @@ -1300,7 +1396,8 @@ Below is a table mapping various :mod:`os` functions to their corresponding :func:`os.path.basename` :data:`PurePath.name` :func:`os.path.dirname` :data:`PurePath.parent` :func:`os.path.samefile` :meth:`Path.samefile` -:func:`os.path.splitext` :data:`PurePath.suffix` +:func:`os.path.splitext` :data:`PurePath.stem` and + :data:`PurePath.suffix` ==================================== ============================== .. rubric:: Footnotes diff --git a/Doc/library/pipes.rst b/Doc/library/pipes.rst index 245dd0d25208814a42adfbff44a90d8f678bb585..471ae0dbc9768a17b2c811be9b6beeaaced4578d 100644 --- a/Doc/library/pipes.rst +++ b/Doc/library/pipes.rst @@ -23,7 +23,7 @@ The :mod:`pipes` module defines a class to abstract the concept of a *pipeline* Because the module uses :program:`/bin/sh` command lines, a POSIX or compatible shell for :func:`os.system` and :func:`os.popen` is required. -.. availability:: Unix. Not available on VxWorks. +.. availability:: Unix, not VxWorks. The :mod:`pipes` module defines the following class: diff --git a/Doc/library/random.rst b/Doc/library/random.rst index 613fbce0fdf20d0a238ef40d1290a1b528656e67..78c2b030d6095fc8cd514d6786d463836b937c92 100644 --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -258,6 +258,28 @@ Functions for sequences The *population* must be a sequence. Automatic conversion of sets to lists is no longer supported. +Discrete distributions +---------------------- + +The following function generates a discrete distribution. + +.. function:: binomialvariate(n=1, p=0.5) + + `Binomial distribution + <http://mathworld.wolfram.com/BinomialDistribution.html>`_. + Return the number of successes for *n* independent trials with the + probability of success in each trial being *p*: + + Mathematically equivalent to:: + + sum(random() < p for i in range(n)) + + The number of trials *n* should be a non-negative integer. + The probability of success *p* should be between ``0.0 <= p <= 1.0``. + The result is an integer in the range ``0 <= X <= n``. + + .. versionadded:: 3.12 + .. _real-valued-distributions: @@ -452,16 +474,13 @@ Simulations:: >>> # Deal 20 cards without replacement from a deck >>> # of 52 playing cards, and determine the proportion of cards >>> # with a ten-value: ten, jack, queen, or king. - >>> dealt = sample(['tens', 'low cards'], counts=[16, 36], k=20) - >>> dealt.count('tens') / 20 + >>> deal = sample(['tens', 'low cards'], counts=[16, 36], k=20) + >>> deal.count('tens') / 20 0.15 >>> # Estimate the probability of getting 5 or more heads from 7 spins >>> # of a biased coin that settles on heads 60% of the time. - >>> def trial(): - ... return choices('HT', cum_weights=(0.60, 1.00), k=7).count('H') >= 5 - ... - >>> sum(trial() for i in range(10_000)) / 10_000 + >>> sum(binomialvariate(n=7, p=0.6) >= 5 for i in range(10_000)) / 10_000 0.4169 >>> # Probability of the median of 5 samples being in middle two quartiles diff --git a/Doc/library/resource.rst b/Doc/library/resource.rst index 67e9b44fe48c466c97b564e6835da0d467a1b1cb..7c9c5a0819b0a73ca1d9a21462dd92842ab5083f 100644 --- a/Doc/library/resource.rst +++ b/Doc/library/resource.rst @@ -99,7 +99,7 @@ this module for those platforms. .. audit-event:: resource.prlimit pid,resource,limits resource.prlimit - .. availability:: Linux 2.6.36 or later with glibc 2.13 or later. + .. availability:: Linux >= 2.6.36 with glibc >= 2.13. .. versionadded:: 3.4 @@ -185,7 +185,7 @@ platform. The number of bytes that can be allocated for POSIX message queues. - .. availability:: Linux 2.6.8 or later. + .. availability:: Linux >= 2.6.8. .. versionadded:: 3.4 @@ -194,7 +194,7 @@ platform. The ceiling for the process's nice level (calculated as 20 - rlim_cur). - .. availability:: Linux 2.6.12 or later. + .. availability:: Linux >= 2.6.12. .. versionadded:: 3.4 @@ -203,7 +203,7 @@ platform. The ceiling of the real-time priority. - .. availability:: Linux 2.6.12 or later. + .. availability:: Linux >= 2.6.12. .. versionadded:: 3.4 @@ -213,7 +213,7 @@ platform. The time limit (in microseconds) on CPU time that a process can spend under real-time scheduling without making a blocking syscall. - .. availability:: Linux 2.6.25 or later. + .. availability:: Linux >= 2.6.25. .. versionadded:: 3.4 @@ -222,7 +222,7 @@ platform. The number of signals which the process may queue. - .. availability:: Linux 2.6.8 or later. + .. availability:: Linux >= 2.6.8. .. versionadded:: 3.4 @@ -232,7 +232,7 @@ platform. This limits the amount of network memory, and hence the amount of mbufs, that this user may hold at any time. - .. availability:: FreeBSD 9 or later. + .. availability:: FreeBSD. .. versionadded:: 3.4 @@ -245,7 +245,7 @@ platform. `tuning(7) <https://www.freebsd.org/cgi/man.cgi?query=tuning&sektion=7>`__ for a complete description of this sysctl. - .. availability:: FreeBSD 9 or later. + .. availability:: FreeBSD. .. versionadded:: 3.4 @@ -253,7 +253,7 @@ platform. The maximum number of pseudo-terminals created by this user id. - .. availability:: FreeBSD 9 or later. + .. availability:: FreeBSD. .. versionadded:: 3.4 @@ -261,7 +261,7 @@ platform. The maximum number of kqueues this user id is allowed to create. - .. availability:: FreeBSD 11 or later. + .. availability:: FreeBSD >= 11. .. versionadded:: 3.10 diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst index d850639d242abef05cdfc1cd216a6aedd238ac71..72b8f03fc16df77cc7b19c51f68beaeb20c0a2da 100644 --- a/Doc/library/signal.rst +++ b/Doc/library/signal.rst @@ -95,8 +95,10 @@ The signal module defines three enums: :class:`enum.IntEnum` collection the constants :const:`SIG_BLOCK`, :const:`SIG_UNBLOCK` and :const:`SIG_SETMASK`. - Availability: Unix. See the man page :manpage:`sigprocmask(2)` and - :manpage:`pthread_sigmask(3)` for further information. + .. availability:: Unix. + + See the man page :manpage:`sigprocmask(2)` and + :manpage:`pthread_sigmask(3)` for further information. .. versionadded:: 3.5 @@ -205,7 +207,9 @@ The variables defined in the :mod:`signal` module are: Stack fault on coprocessor. The Linux kernel does not raise this signal: it can only be raised in user space. - .. availability:: Linux, on architectures where the signal is available. See + .. availability:: Linux. + + On architectures where the signal is available. See the man page :manpage:`signal(7)` for further information. .. versionadded:: 3.11 @@ -337,8 +341,9 @@ The :mod:`signal` module defines the following functions: delivered. If *time* is zero, no alarm is scheduled, and any scheduled alarm is canceled. If the return value is zero, no alarm is currently scheduled. - .. availability:: Unix. See the man page :manpage:`alarm(2)` for further - information. + .. availability:: Unix. + + See the man page :manpage:`alarm(2)` for further information. .. function:: getsignal(signalnum) @@ -375,8 +380,9 @@ The :mod:`signal` module defines the following functions: Cause the process to sleep until a signal is received; the appropriate handler will then be called. Returns nothing. - .. availability:: Unix. See the man page :manpage:`signal(2)` for further - information. + .. availability:: Unix. + + See the man page :manpage:`signal(2)` for further information. See also :func:`sigwait`, :func:`sigwaitinfo`, :func:`sigtimedwait` and :func:`sigpending`. @@ -398,7 +404,7 @@ The :mod:`signal` module defines the following functions: See the :manpage:`pidfd_send_signal(2)` man page for more information. - .. availability:: Linux 5.1+ + .. availability:: Linux >= 5.1 .. versionadded:: 3.9 @@ -421,8 +427,9 @@ The :mod:`signal` module defines the following functions: .. audit-event:: signal.pthread_kill thread_id,signalnum signal.pthread_kill - .. availability:: Unix. See the man page :manpage:`pthread_kill(3)` for further - information. + .. availability:: Unix. + + See the man page :manpage:`pthread_kill(3)` for further information. See also :func:`os.kill`. @@ -454,7 +461,9 @@ The :mod:`signal` module defines the following functions: :data:`SIGKILL` and :data:`SIGSTOP` cannot be blocked. - .. availability:: Unix. See the man page :manpage:`sigprocmask(2)` and + .. availability:: Unix. + + See the man page :manpage:`sigprocmask(2)` and :manpage:`pthread_sigmask(3)` for further information. See also :func:`pause`, :func:`sigpending` and :func:`sigwait`. @@ -542,8 +551,9 @@ The :mod:`signal` module defines the following functions: calls will be restarted when interrupted by signal *signalnum*, otherwise system calls will be interrupted. Returns nothing. - .. availability:: Unix. See the man page :manpage:`siginterrupt(3)` - for further information. + .. availability:: Unix. + + See the man page :manpage:`siginterrupt(3)` for further information. Note that installing a signal handler with :func:`signal` will reset the restart behaviour to interruptible by implicitly calling @@ -583,8 +593,9 @@ The :mod:`signal` module defines the following functions: thread (i.e., the signals which have been raised while blocked). Return the set of the pending signals. - .. availability:: Unix. See the man page :manpage:`sigpending(2)` for further - information. + .. availability:: Unix. + + See the man page :manpage:`sigpending(2)` for further information. See also :func:`pause`, :func:`pthread_sigmask` and :func:`sigwait`. @@ -597,8 +608,9 @@ The :mod:`signal` module defines the following functions: signals specified in the signal set *sigset*. The function accepts the signal (removes it from the pending list of signals), and returns the signal number. - .. availability:: Unix. See the man page :manpage:`sigwait(3)` for further - information. + .. availability:: Unix. + + See the man page :manpage:`sigwait(3)` for further information. See also :func:`pause`, :func:`pthread_sigmask`, :func:`sigpending`, :func:`sigwaitinfo` and :func:`sigtimedwait`. @@ -622,8 +634,9 @@ The :mod:`signal` module defines the following functions: :attr:`si_errno`, :attr:`si_pid`, :attr:`si_uid`, :attr:`si_status`, :attr:`si_band`. - .. availability:: Unix. See the man page :manpage:`sigwaitinfo(2)` for further - information. + .. availability:: Unix. + + See the man page :manpage:`sigwaitinfo(2)` for further information. See also :func:`pause`, :func:`sigwait` and :func:`sigtimedwait`. @@ -641,8 +654,9 @@ The :mod:`signal` module defines the following functions: specifying a timeout. If *timeout* is specified as :const:`0`, a poll is performed. Returns :const:`None` if a timeout occurs. - .. availability:: Unix. See the man page :manpage:`sigtimedwait(2)` for further - information. + .. availability:: Unix. + + See the man page :manpage:`sigtimedwait(2)` for further information. See also :func:`pause`, :func:`sigwait` and :func:`sigwaitinfo`. diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 84b6d797ddc0130538517cc2a10444b1c0f794ca..8eb254ce898e120a865072f4857f66e4b73dc7c5 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -165,7 +165,9 @@ created. Socket addresses are represented as follows: - *feat* and *mask* are unsigned 32bit integers. - .. availability:: Linux 2.6.38, some algorithm types require more recent Kernels. + .. availability:: Linux >= 2.6.38. + + Some algorithm types require more recent Kernels. .. versionadded:: 3.6 @@ -173,7 +175,9 @@ created. Socket addresses are represented as follows: their hosts. The sockets are represented as a ``(CID, port)`` tuple where the context ID or CID and port are integers. - .. availability:: Linux >= 4.8 QEMU >= 2.8 ESX >= 4.0 ESX Workstation >= 6.5. + .. availability:: Linux >= 3.9 + + See :manpage:`vsock(7)` .. versionadded:: 3.7 @@ -221,7 +225,7 @@ created. Socket addresses are represented as follows: ``socket(AF_INET, SOCK_DGRAM, IPPROTO_UDPLITE)`` for IPv4 or ``socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDPLITE)`` for IPv6. - .. availability:: Linux >= 2.6.20, FreeBSD >= 10.1-RELEASE + .. availability:: Linux >= 2.6.20, FreeBSD >= 10.1 .. versionadded:: 3.9 @@ -1080,7 +1084,7 @@ The :mod:`socket` module also offers various network-related services: both the value of *address_family* and the underlying implementation of :c:func:`inet_pton`. - .. availability:: Unix (maybe not all platforms), Windows. + .. availability:: Unix, Windows. .. versionchanged:: 3.4 Windows support added @@ -1100,7 +1104,7 @@ The :mod:`socket` module also offers various network-related services: length for the specified address family, :exc:`ValueError` will be raised. :exc:`OSError` is raised for errors from the call to :func:`inet_ntop`. - .. availability:: Unix (maybe not all platforms), Windows. + .. availability:: Unix, Windows. .. versionchanged:: 3.4 Windows support added @@ -1126,7 +1130,9 @@ The :mod:`socket` module also offers various network-related services: buffer. Raises :exc:`OverflowError` if *length* is outside the permissible range of values. - .. availability:: most Unix platforms, possibly others. + .. availability:: Unix. + + Most Unix platforms. .. versionadded:: 3.3 @@ -1147,7 +1153,9 @@ The :mod:`socket` module also offers various network-related services: amount of ancillary data that can be received, since additional data may be able to fit into the padding area. - .. availability:: most Unix platforms, possibly others. + .. availability:: Unix. + + most Unix platforms. .. versionadded:: 3.3 @@ -1246,7 +1254,10 @@ The :mod:`socket` module also offers various network-related services: The *fds* parameter is a sequence of file descriptors. Consult :meth:`sendmsg` for the documentation of these parameters. - .. availability:: Unix supporting :meth:`~socket.sendmsg` and :const:`SCM_RIGHTS` mechanism. + .. availability:: Unix. + + Unix platforms supporting :meth:`~socket.sendmsg` + and :const:`SCM_RIGHTS` mechanism. .. versionadded:: 3.9 @@ -1257,7 +1268,10 @@ The :mod:`socket` module also offers various network-related services: Return ``(msg, list(fds), flags, addr)``. Consult :meth:`recvmsg` for the documentation of these parameters. - .. availability:: Unix supporting :meth:`~socket.recvmsg` and :const:`SCM_RIGHTS` mechanism. + .. availability:: Unix. + + Unix platforms supporting :meth:`~socket.sendmsg` + and :const:`SCM_RIGHTS` mechanism. .. versionadded:: 3.9 @@ -1592,7 +1606,9 @@ to sockets. fds.frombytes(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) return msg, list(fds) - .. availability:: most Unix platforms, possibly others. + .. availability:: Unix. + + Most Unix platforms. .. versionadded:: 3.3 @@ -1634,7 +1650,9 @@ to sockets. >>> [b1, b2, b3] [bytearray(b'Mary'), bytearray(b'01 had a 9'), bytearray(b'little lamb---')] - .. availability:: most Unix platforms, possibly others. + .. availability:: Unix. + + Most Unix platforms. .. versionadded:: 3.3 @@ -1740,7 +1758,9 @@ to sockets. def send_fds(sock, msg, fds): return sock.sendmsg([msg], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, array.array("i", fds))]) - .. availability:: most Unix platforms, possibly others. + .. availability:: Unix. + + Most Unix platforms. .. audit-event:: socket.sendmsg self,address socket.socket.sendmsg diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index bdff071b34ca05573fe5adc999d1174168922260..3df41b541949553df524e814753e164cc03ea354 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -8,7 +8,11 @@ **Source code:** :source:`Lib/sqlite3/` --------------- + +.. _sqlite3-intro: + +Introduction +------------ SQLite is a C library that provides a lightweight disk-based database that doesn't require a separate server process and allows accessing the database @@ -21,6 +25,12 @@ The sqlite3 module was written by Gerhard Häring. It provides an SQL interface compliant with the DB-API 2.0 specification described by :pep:`249`, and requires SQLite 3.7.15 or newer. + +.. _sqlite3-tutorial: + +Tutorial +-------- + To use the module, start by creating a :class:`Connection` object that represents the database. Here the data will be stored in the :file:`example.db` file:: @@ -57,15 +67,28 @@ after restarting the Python interpreter:: con = sqlite3.connect('example.db') cur = con.cursor() -To retrieve data after executing a SELECT statement, either treat the cursor as -an :term:`iterator`, call the cursor's :meth:`~Cursor.fetchone` method to -retrieve a single matching row, or call :meth:`~Cursor.fetchall` to get a list -of the matching rows. +At this point, our database only contains one row:: -This example uses the iterator form:: + >>> res = cur.execute('SELECT count(rowid) FROM stocks') + >>> print(res.fetchone()) + (1,) + +The result is a one-item :class:`tuple`: +one row, with one column. +Now, let us insert three more rows of data, +using :meth:`~Cursor.executemany`:: + + >>> data = [ + ... ('2006-03-28', 'BUY', 'IBM', 1000, 45.0), + ... ('2006-04-05', 'BUY', 'MSFT', 1000, 72.0), + ... ('2006-04-06', 'SELL', 'IBM', 500, 53.0), + ... ] + >>> cur.executemany('INSERT INTO stocks VALUES(?, ?, ?, ?, ?)', data) + +Then, retrieve the data by iterating over the result of a ``SELECT`` statement:: >>> for row in cur.execute('SELECT * FROM stocks ORDER BY price'): - print(row) + ... print(row) ('2006-01-05', 'BUY', 'RHAT', 100, 35.14) ('2006-03-28', 'BUY', 'IBM', 1000, 45.0) @@ -139,8 +162,8 @@ Module functions and constants .. data:: version - The version number of this module, as a string. This is not the version of - the SQLite library. + Version number of this module as a :class:`string <str>`. + This is not the version of the SQLite library. .. deprecated-removed:: 3.12 3.14 This constant used to reflect the version number of the ``pysqlite`` @@ -150,8 +173,8 @@ Module functions and constants .. data:: version_info - The version number of this module, as a tuple of integers. This is not the - version of the SQLite library. + Version number of this module as a :class:`tuple` of :class:`integers <int>`. + This is not the version of the SQLite library. .. deprecated-removed:: 3.12 3.14 This constant used to reflect the version number of the ``pysqlite`` @@ -161,12 +184,13 @@ Module functions and constants .. data:: sqlite_version - The version number of the run-time SQLite library, as a string. + Version number of the runtime SQLite library as a :class:`string <str>`. .. data:: sqlite_version_info - The version number of the run-time SQLite library, as a tuple of integers. + Version number of the runtime SQLite library as a :class:`tuple` of + :class:`integers <int>`. .. data:: threadsafety @@ -286,7 +310,7 @@ Module functions and constants Can be ``"DEFERRED"`` (default), ``"EXCLUSIVE"`` or ``"IMMEDIATE"``; or :const:`None` to disable opening transactions implicitly. See :ref:`sqlite3-controlling-transactions` for more. - :type isolation_level: str | None + :type isolation_level: str | :const:`None` :param check_same_thread: If :const:`True` (default), only the creating thread may use the connection. @@ -316,7 +340,7 @@ Module functions and constants enabling various :ref:`sqlite3-uri-tricks`. :type uri: bool - :rtype: sqlite3.Connection + :rtype: Connection .. audit-event:: sqlite3.connect database sqlite3.connect .. audit-event:: sqlite3.connect/handle connection_handle sqlite3.connect @@ -369,6 +393,7 @@ Module functions and constants .. function:: enable_callback_tracebacks(flag, /) + Enable or disable callback tracebacks. By default you will not get any tracebacks in user-defined functions, aggregates, converters, authorizer callbacks etc. If you want to debug them, you can call this function with *flag* set to :const:`True`. Afterwards, you @@ -401,6 +426,16 @@ Connection Objects .. class:: Connection + Each open SQLite database is represented by a ``Connection`` object, + which is created using :func:`sqlite3.connect`. + Their main purpose is creating :class:`Cursor` objects, + and :ref:`sqlite3-controlling-transactions`. + + .. seealso:: + + * :ref:`sqlite3-connection-shortcuts` + * :ref:`sqlite3-connection-context-manager` + An SQLite database connection has the following attributes and methods: .. attribute:: isolation_level @@ -428,19 +463,43 @@ Connection Objects .. method:: cursor(factory=Cursor) + Create and return a :class:`Cursor` object. The cursor method accepts a single optional parameter *factory*. If supplied, this must be a callable returning an instance of :class:`Cursor` or its subclasses. .. method:: blobopen(table, column, row, /, *, readonly=False, name="main") - Open a :class:`Blob` handle to the :abbr:`BLOB (Binary Large OBject)` - located in table name *table*, column name *column*, and row index *row* - of database *name*. - When *readonly* is :const:`True` the blob is opened without write - permissions. - Trying to open a blob in a ``WITHOUT ROWID`` table will raise - :exc:`OperationalError`. + Open a :class:`Blob` handle to an existing + :abbr:`BLOB (Binary Large OBject)`. + + :param table: + The name of the table where the blob is located. + :type table: str + + :param column: + The name of the column where the blob is located. + :type column: str + + :param row: + The name of the row where the blob is located. + :type row: str + + :param readonly: + Set to :const:`True` if the blob should be opened without write + permissions. + Defaults to :const:`False`. + :type readonly: bool + + :param name: + The name of the database where the blob is located. + Defaults to ``"main"``. + :type name: str + + :raises OperationalError: + When trying to open a blob in a ``WITHOUT ROWID`` table. + + :rtype: Blob .. note:: @@ -466,19 +525,19 @@ Connection Objects make sure to :meth:`commit` before closing to avoid losing pending changes. - .. method:: execute(sql[, parameters]) + .. method:: execute(sql, parameters=(), /) Create a new :class:`Cursor` object and call :meth:`~Cursor.execute` on it with the given *sql* and *parameters*. Return the new cursor object. - .. method:: executemany(sql[, parameters]) + .. method:: executemany(sql, parameters, /) Create a new :class:`Cursor` object and call :meth:`~Cursor.executemany` on it with the given *sql* and *parameters*. Return the new cursor object. - .. method:: executescript(sql_script) + .. method:: executescript(sql_script, /) Create a new :class:`Cursor` object and call :meth:`~Cursor.executescript` on it with the given *sql_script*. @@ -486,21 +545,35 @@ Connection Objects .. method:: create_function(name, narg, func, *, deterministic=False) - Creates a user-defined function that you can later use from within SQL - statements under the function name *name*. *narg* is the number of - parameters the function accepts (if *narg* is -1, the function may - take any number of arguments), and *func* is a Python callable that is - called as the SQL function. If *deterministic* is true, the created function - is marked as `deterministic <https://sqlite.org/deterministic.html>`_, which - allows SQLite to perform additional optimizations. This flag is supported by - SQLite 3.8.3 or higher, :exc:`NotSupportedError` will be raised if used - with older versions. + Create or remove a user-defined SQL function. - The function can return any of - :ref:`the types natively supported by SQLite <sqlite3-types>`. + :param name: + The name of the SQL function. + :type name: str - .. versionchanged:: 3.8 - The *deterministic* parameter was added. + :param narg: + The number of arguments the SQL function can accept. + If ``-1``, it may take any number of arguments. + :type narg: int + + :param func: + A callable that is called when the SQL function is invoked. + The callable must return :ref:`a type natively supported by SQLite + <sqlite3-types>`. + Set to :const:`None` to remove an existing SQL function. + :type func: :term:`callback` | :const:`None` + + :param deterministic: + If :const:`True`, the created SQL function is marked as + `deterministic <https://sqlite.org/deterministic.html>`_, + which allows SQLite to perform additional optimizations. + :type deterministic: bool + + :raises NotSupportedError: + If *deterministic* is used with SQLite versions older than 3.8.3. + + .. versionadded:: 3.8 + The *deterministic* parameter. Example: @@ -509,15 +582,29 @@ Connection Objects .. method:: create_aggregate(name, /, n_arg, aggregate_class) - Creates a user-defined aggregate function. + Create or remove a user-defined SQL aggregate function. + + :param name: + The name of the SQL aggregate function. + :type name: str + + :param n_arg: + The number of arguments the SQL aggregate function can accept. + If ``-1``, it may take any number of arguments. + :type n_arg: int + + :param aggregate_class: + A class must implement the following methods: - The aggregate class must implement a ``step`` method, which accepts the number - of parameters *n_arg* (if *n_arg* is -1, the function may take - any number of arguments), and a ``finalize`` method which will return the - final result of the aggregate. + * ``step()``: Add a row to the aggregate. + * ``finalize()``: Return the final result of the aggregate as + :ref:`a type natively supported by SQLite <sqlite3-types>`. - The ``finalize`` method can return any of - :ref:`the types natively supported by SQLite <sqlite3-types>`. + The number of arguments that the ``step()`` method must accept + is controlled by *n_arg*. + + Set to :const:`None` to remove an existing SQL aggregate function. + :type aggregate_class: :term:`class` | :const:`None` Example: @@ -526,25 +613,36 @@ Connection Objects .. method:: create_window_function(name, num_params, aggregate_class, /) - Creates user-defined aggregate window function *name*. + Create or remove a user-defined aggregate window function. + + :param name: + The name of the SQL aggregate window function to create or remove. + :type name: str + + :param num_params: + The number of arguments the SQL aggregate window function can accept. + If ``-1``, it may take any number of arguments. + :type num_params: int + + :param aggregate_class: + A class that must implement the following methods: - *aggregate_class* must implement the following methods: + * ``step()``: Add a row to the current window. + * ``value()``: Return the current value of the aggregate. + * ``inverse()``: Remove a row from the current window. + * ``finalize()``: Return the final result of the aggregate as + :ref:`a type natively supported by SQLite <sqlite3-types>`. - * ``step``: adds a row to the current window - * ``value``: returns the current value of the aggregate - * ``inverse``: removes a row from the current window - * ``finalize``: returns the final value of the aggregate + The number of arguments that the ``step()`` and ``value()`` methods + must accept is controlled by *num_params*. - ``step`` and ``value`` accept *num_params* number of parameters, - unless *num_params* is ``-1``, in which case they may take any number of - arguments. - ``finalize`` and ``value`` can return any of - :ref:`the types natively supported by SQLite <sqlite3-types>`. - Call :meth:`create_window_function` with - *aggregate_class* set to :const:`None` to clear window function *name*. + Set to :const:`None` to remove an existing SQL aggregate window function. - Aggregate window functions are supported by SQLite 3.25.0 and higher. - :exc:`NotSupportedError` will be raised if used with older versions. + :raises NotSupportedError: + If used with a version of SQLite older than 3.25.0, + which does not support aggregate window functions. + + :type aggregate_class: :term:`class` | :const:`None` .. versionadded:: 3.11 @@ -576,14 +674,14 @@ Connection Objects .. method:: interrupt() - You can call this method from a different thread to abort any queries that might - be executing on the connection. The query will then abort and the caller will - get an exception. + Call this method from a different thread to abort any queries that might + be executing on the connection. + Aborted queries will raise an exception. .. method:: set_authorizer(authorizer_callback) - This routine registers a callback. The callback is invoked for each attempt to + Register callable *authorizer_callback* to be invoked for each attempt to access a column of a table in the database. The callback should return :const:`SQLITE_OK` if access is allowed, :const:`SQLITE_DENY` if the entire SQL statement should be aborted with an error and :const:`SQLITE_IGNORE` if the @@ -609,7 +707,7 @@ Connection Objects .. method:: set_progress_handler(progress_handler, n) - This routine registers a callback. The callback is invoked for every *n* + Register callable *progress_handler* to be invoked for every *n* instructions of the SQLite virtual machine. This is useful if you want to get called from SQLite during long-running operations, for example to update a GUI. @@ -624,8 +722,8 @@ Connection Objects .. method:: set_trace_callback(trace_callback) - Registers *trace_callback* to be called for each SQL statement that is - actually executed by the SQLite backend. + Register callable *trace_callback* to be invoked for each SQL statement + that is actually executed by the SQLite backend. The only argument passed to the callback is the statement (as :class:`str`) that is being executed. The return value of the callback is @@ -648,8 +746,10 @@ Connection Objects .. method:: enable_load_extension(enabled, /) - This routine allows/disallows the SQLite engine to load SQLite extensions - from shared libraries. SQLite extensions can define new functions, + Enable the SQLite engine to load SQLite extensions from shared libraries + if *enabled* is :const:`True`; + else, disallow loading SQLite extensions. + SQLite extensions can define new functions, aggregates or whole new virtual table implementations. One well-known extension is the fulltext-search extension distributed with SQLite. @@ -666,9 +766,9 @@ Connection Objects .. method:: load_extension(path, /) - This routine loads an SQLite extension from a shared library. You have to - enable extension loading with :meth:`enable_load_extension` before you can - use this routine. + Load an SQLite extension from a shared library located at *path*. + Enable extension loading with :meth:`enable_load_extension` before + calling this method. Loadable extensions are disabled by default. See [#f1]_. @@ -681,10 +781,9 @@ Connection Objects .. attribute:: row_factory - You can change this attribute to a callable that accepts the cursor and the - original row as a tuple and will return the real result row. This way, you can - implement more advanced ways of returning results, such as returning an object - that can also access columns by name. + A callable that accepts two arguments, + a :class:`Cursor` object and the raw row results as a :class:`tuple`, + and returns a custom object representing an SQLite row. Example: @@ -702,31 +801,28 @@ Connection Objects .. attribute:: text_factory - Using this attribute you can control what objects are returned for the ``TEXT`` - data type. By default, this attribute is set to :class:`str` and the - :mod:`sqlite3` module will return :class:`str` objects for ``TEXT``. - If you want to return :class:`bytes` instead, you can set it to :class:`bytes`. - - You can also set it to any other callable that accepts a single bytestring - parameter and returns the resulting object. + A callable that accepts a :class:`bytes` parameter and returns a text + representation of it. + The callable is invoked for SQLite values with the ``TEXT`` data type. + By default, this attribute is set to :class:`str`. + If you want to return ``bytes`` instead, set *text_factory* to ``bytes``. - See the following example code for illustration: + Example: .. literalinclude:: ../includes/sqlite3/text_factory.py .. attribute:: total_changes - Returns the total number of database rows that have been modified, inserted, or + Return the total number of database rows that have been modified, inserted, or deleted since the database connection was opened. .. method:: iterdump - Returns an iterator to dump the database in an SQL text format. Useful when - saving an in-memory database for later restoration. This function provides - the same capabilities as the :kbd:`.dump` command in the :program:`sqlite3` - shell. + Return an :term:`iterator` to dump the database as SQL source code. + Useful when saving an in-memory database for later restoration. + Similar to the ``.dump`` command in the :program:`sqlite3` shell. Example:: @@ -742,29 +838,43 @@ Connection Objects .. method:: backup(target, *, pages=-1, progress=None, name="main", sleep=0.250) - This method makes a backup of an SQLite database even while it's being accessed - by other clients, or concurrently by the same connection. The copy will be - written into the mandatory argument *target*, that must be another - :class:`Connection` instance. - - By default, or when *pages* is either ``0`` or a negative integer, the entire - database is copied in a single step; otherwise the method performs a loop - copying up to *pages* pages at a time. - - If *progress* is specified, it must either be ``None`` or a callable object that - will be executed at each iteration with three integer arguments, respectively - the *status* of the last iteration, the *remaining* number of pages still to be - copied and the *total* number of pages. - - The *name* argument specifies the database name that will be copied: it must be - a string containing either ``"main"``, the default, to indicate the main - database, ``"temp"`` to indicate the temporary database or the name specified - after the ``AS`` keyword in an ``ATTACH DATABASE`` statement for an attached - database. - - The *sleep* argument specifies the number of seconds to sleep by between - successive attempts to backup remaining pages, can be specified either as an - integer or a floating point value. + Create a backup of an SQLite database. + + Works even if the database is being accessed by other clients + or concurrently by the same connection. + + :param target: + The database connection to save the backup to. + :type target: Connection + + :param pages: + The number of pages to copy at a time. + If equal to or less than ``0``, + the entire database is copied in a single step. + Defaults to ``-1``. + :type pages: int + + :param progress: + If set to a callable, it is invoked with three integer arguments for + every backup iteration: + the *status* of the last iteration, + the *remaining* number of pages still to be copied, + and the *total* number of pages. + Defaults to :const:`None`. + :type progress: :term:`callback` | :const:`None` + + :param name: + The name of the database to back up. + Either ``"main"`` (the default) for the main database, + ``"temp"`` for the temporary database, + or the name of a custom database as attached using the + ``ATTACH DATABASE`` SQL statment. + :type name: str + + :param sleep: + The number of seconds to sleep between successive attempts + to back up remaining pages. + :type sleep: float Example 1, copy an existing database into another:: @@ -793,7 +903,7 @@ Connection Objects .. method:: getlimit(category, /) - Get a connection run-time limit. *category* is the limit category to be + Get a connection runtime limit. *category* is the limit category to be queried. Example, query the maximum length of an SQL statement:: @@ -808,7 +918,7 @@ Connection Objects .. method:: setlimit(category, limit, /) - Set a connection run-time limit. *category* is the limit category to be + Set a connection runtime limit. *category* is the limit category to be set. *limit* is the new limit. If the new limit is a negative number, the limit is unchanged. @@ -827,7 +937,7 @@ Connection Objects .. method:: serialize(*, name="main") - This method serializes a database into a :class:`bytes` object. For an + Serialize a database into a :class:`bytes` object. For an ordinary on-disk database file, the serialization is just a copy of the disk file. For an in-memory database or a "temp" database, the serialization is the same sequence of bytes which would be written to @@ -846,6 +956,8 @@ Connection Objects .. method:: deserialize(data, /, *, name="main") + Deserialize a :meth:`serialized <serialize>` database into a + :class:`Connection`. This method causes the database connection to disconnect from database *name*, and reopen *name* as an in-memory database based on the serialization contained in *data*. Deserialization will raise @@ -868,6 +980,22 @@ Connection Objects Cursor Objects -------------- + A ``Cursor`` object represents a `database cursor`_ + which is used to execute SQL statements, + and manage the context of a fetch operation. + Cursors are created using :meth:`Connection.cursor`, + or by using any of the :ref:`connection shortcut methods + <sqlite3-connection-shortcuts>`. + + Cursor objects are :term:`iterators <iterator>`, + meaning that if you :meth:`~Cursor.execute` a ``SELECT`` query, + you can simply iterate over the cursor to fetch the resulting rows:: + + for row in cur.execute("select * from data"): + print(row) + + .. _database cursor: https://en.wikipedia.org/wiki/Cursor_(databases) + .. class:: Cursor A :class:`Cursor` instance has the following attributes and methods. @@ -877,8 +1005,10 @@ Cursor Objects .. method:: execute(sql, parameters=(), /) - Execute an SQL statement. Values may be bound to the statement using - :ref:`placeholders <sqlite3-placeholders>`. + Execute SQL statement *sql*. + Bind values to the statement using :ref:`placeholders + <sqlite3-placeholders>` that map to the :term:`sequence` or :class:`dict` + *parameters*. :meth:`execute` will only execute a single SQL statement. If you try to execute more than one statement with it, it will raise a :exc:`ProgrammingError`. Use @@ -891,24 +1021,26 @@ Cursor Objects a transaction is implicitly opened before executing *sql*. - .. method:: executemany(sql, seq_of_parameters, /) + .. method:: executemany(sql, parameters, /) - Execute a :ref:`parameterized <sqlite3-placeholders>` SQL command + Execute :ref:`parameterized <sqlite3-placeholders>` SQL statement *sql* against all parameter sequences or mappings found in the sequence - *seq_of_parameters*. It is also possible to use an + *parameters*. It is also possible to use an :term:`iterator` yielding parameters instead of a sequence. Uses the same implicit transaction handling as :meth:`~Cursor.execute`. - .. literalinclude:: ../includes/sqlite3/executemany_1.py - - Here's a shorter example using a :term:`generator`: - - .. literalinclude:: ../includes/sqlite3/executemany_2.py + Example:: + data = [ + ("row1",), + ("row2",), + ] + # cur is an sqlite3.Cursor object + cur.executemany("insert into t values(?)", data) .. method:: executescript(sql_script, /) - Execute multiple SQL statements at once. + Execute the SQL statements in *sql_script*. If there is a pending transaciton, an implicit ``COMMIT`` statement is executed first. No other implicit transaction control is performed; @@ -916,27 +1048,34 @@ Cursor Objects *sql_script* must be a :class:`string <str>`. - Example: + Example:: - .. literalinclude:: ../includes/sqlite3/executescript.py + # cur is an sqlite3.Cursor object + cur.executescript(""" + begin; + create table person(firstname, lastname, age); + create table book(title, author, published); + create table publisher(name, address); + commit; + """) .. method:: fetchone() - Fetches the next row of a query result set, returning a single sequence, - or :const:`None` when no more data is available. + Fetch the next row of a query result set as a :class:`tuple`. + Return :const:`None` if no more data is available. .. method:: fetchmany(size=cursor.arraysize) - Fetches the next set of rows of a query result, returning a list. An empty - list is returned when no more rows are available. + Fetch the next set of rows of a query result as a :class:`list`. + Return an empty list if no more rows are available. The number of rows to fetch per call is specified by the *size* parameter. - If it is not given, the cursor's arraysize determines the number of rows - to be fetched. The method should try to fetch as many rows as indicated by - the size parameter. If this is not possible due to the specified number of - rows not being available, fewer rows may be returned. + If *size* is not given, :attr:`arraysize` determines the number of rows + to be fetched. + If fewer than *size* rows are available, + as many rows as are available are returned. Note there are performance considerations involved with the *size* parameter. For optimal performance, it is usually best to use the arraysize attribute. @@ -945,9 +1084,10 @@ Cursor Objects .. method:: fetchall() - Fetches all (remaining) rows of a query result, returning a list. Note that - the cursor's arraysize attribute can affect the performance of this operation. - An empty list is returned when no rows are available. + Fetch all (remaining) rows of a query result as a :class:`list`. + Return an empty list if no rows are available. + Note that the :attr:`arraysize` attribute can affect the performance of + this operation. .. method:: close() @@ -966,22 +1106,15 @@ Cursor Objects .. attribute:: rowcount - Although the :class:`Cursor` class of the :mod:`sqlite3` module implements this - attribute, the database engine's own support for the determination of "rows - affected"/"rows selected" is quirky. - - For :meth:`executemany` statements, the number of modifications are summed up - into :attr:`rowcount`. - - As required by the Python DB API Spec, the :attr:`rowcount` attribute "is -1 in - case no ``executeXX()`` has been performed on the cursor or the rowcount of the - last operation is not determinable by the interface". This includes ``SELECT`` - statements because we cannot determine the number of rows a query produced - until all rows were fetched. + Read-only attribute that provides the number of modified rows for + ``INSERT``, ``UPDATE``, ``DELETE``, and ``REPLACE`` statements; + is ``-1`` for other statements, + including :abbr:`CTE (Common Table Expression)` queries. + It is only updated by the :meth:`execute` and :meth:`executemany` methods. .. attribute:: lastrowid - This read-only attribute provides the row id of the last inserted row. It + Read-only attribute that provides the row id of the last inserted row. It is only updated after successful ``INSERT`` or ``REPLACE`` statements using the :meth:`execute` method. For other statements, after :meth:`executemany` or :meth:`executescript`, or if the insertion failed, @@ -1001,7 +1134,7 @@ Cursor Objects .. attribute:: description - This read-only attribute provides the column names of the last query. To + Read-only attribute that provides the column names of the last query. To remain compatible with the Python DB API, it returns a 7-tuple for each column where the last six items of each tuple are :const:`None`. @@ -1009,8 +1142,8 @@ Cursor Objects .. attribute:: connection - This read-only attribute provides the SQLite database :class:`Connection` - used by the :class:`Cursor` object. A :class:`Cursor` object created by + Read-only attribute that provides the SQLite database :class:`Connection` + belonging to the cursor. A :class:`Cursor` object created by calling :meth:`con.cursor() <Connection.cursor>` will have a :attr:`connection` attribute that refers to *con*:: @@ -1028,17 +1161,16 @@ Row Objects A :class:`Row` instance serves as a highly optimized :attr:`~Connection.row_factory` for :class:`Connection` objects. - It tries to mimic a tuple in most of its features. + It tries to mimic a :class:`tuple` in most of its features, + and supports iteration, :func:`repr`, equality testing, :func:`len`, + and :term:`mapping` access by column name and index. - It supports mapping access by column name and index, iteration, - representation, equality testing and :func:`len`. - - If two :class:`Row` objects have exactly the same columns and their - members are equal, they compare equal. + Two row objects compare equal if have equal columns and equal members. .. method:: keys - This method returns a list of column names. Immediately after a query, + Return a :class:`list` of column names as :class:`strings <str>`. + Immediately after a query, it is the first member of each tuple in :attr:`Cursor.description`. .. versionchanged:: 3.5 @@ -1333,6 +1465,8 @@ This function can then be registered using :func:`register_adapter`. .. literalinclude:: ../includes/sqlite3/adapter_point_2.py +.. _sqlite3-converters: + Converting SQLite values to custom Python types ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1366,34 +1500,35 @@ of :func:`connect`. There are three options: * Explicit: set *detect_types* to :const:`PARSE_COLNAMES` * Both: set *detect_types* to ``sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES``. - Colum names take precedence over declared types. + Column names take precedence over declared types. The following example illustrates the implicit and explicit approaches: .. literalinclude:: ../includes/sqlite3/converter_point.py -Default adapters and converters -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. _sqlite3-default-converters: -There are default adapters for the date and datetime types in the datetime -module. They will be sent as ISO dates/ISO timestamps to SQLite. +Default adapters and converters (deprecated) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The default converters are registered under the name "date" for -:class:`datetime.date` and under the name "timestamp" for -:class:`datetime.datetime`. - -This way, you can use date/timestamps from Python without any additional -fiddling in most cases. The format of the adapters is also compatible with the -experimental SQLite date/time functions. +.. note:: -The following example demonstrates this. + The default adapters and converters are deprecated as of Python 3.12. + Instead, use the :ref:`sqlite3-adapter-converter-recipes` + and tailor them to your needs. -.. literalinclude:: ../includes/sqlite3/pysqlite_datetime.py +The deprecated default adapters and converters consist of: -If a timestamp stored in SQLite has a fractional part longer than 6 -numbers, its value will be truncated to microsecond precision by the -timestamp converter. +* An adapter for :class:`datetime.date` objects to :class:`strings <str>` in + `ISO 8601`_ format. +* An adapter for :class:`datetime.datetime` objects to strings in + ISO 8601 format. +* A converter for :ref:`declared <sqlite3-converters>` "date" types to + :class:`datetime.date` objects. +* A converter for declared "timestamp" types to + :class:`datetime.datetime` objects. + Fractional parts will be truncated to 6 digits (microsecond precision). .. note:: @@ -1402,6 +1537,10 @@ timestamp converter. offsets in timestamps, either leave converters disabled, or register an offset-aware converter with :func:`register_converter`. +.. deprecated:: 3.12 + +.. _ISO 8601: https://en.wikipedia.org/wiki/ISO_8601 + .. _sqlite3-adapter-converter-recipes: @@ -1525,11 +1664,14 @@ Using :mod:`sqlite3` efficiently -------------------------------- -Using shortcut methods -^^^^^^^^^^^^^^^^^^^^^^ +.. _sqlite3-connection-shortcuts: + +Using connection shortcut methods +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Using the nonstandard :meth:`execute`, :meth:`executemany` and -:meth:`executescript` methods of the :class:`Connection` object, your code can +Using the :meth:`~Connection.execute`, +:meth:`~Connection.executemany`, and :meth:`~Connection.executescript` +methods of the :class:`Connection` class, your code can be written more concisely because you don't have to create the (often superfluous) :class:`Cursor` objects explicitly. Instead, the :class:`Cursor` objects are created implicitly and these shortcut methods return the cursor diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 19225c85ff7624686a05596d4a6d9190b8874842..e6e9a08e0a7197f9489b90c56503fb578a5b3450 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -410,9 +410,6 @@ Certificate handling * :attr:`openssl_capath_env` - OpenSSL's environment key that points to a capath, * :attr:`openssl_capath` - hard coded path to a capath directory - .. availability:: LibreSSL ignores the environment vars - :attr:`openssl_cafile_env` and :attr:`openssl_capath_env`. - .. versionadded:: 3.4 .. function:: enum_certificates(store_name) diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index 347a1be8321e45cf9ca6531a5bc29c1db82d6987..5aef6f6f05d639cc8e02a15698aee42456cb2f97 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -35,6 +35,35 @@ and implementation-dependent. If your input data consists of mixed types, you may be able to use :func:`map` to ensure a consistent result, for example: ``map(float, input_data)``. +Some datasets use ``NaN`` (not a number) values to represent missing data. +Since NaNs have unusual comparison semantics, they cause surprising or +undefined behaviors in the statistics functions that sort data or that count +occurrences. The functions affected are ``median()``, ``median_low()``, +``median_high()``, ``median_grouped()``, ``mode()``, ``multimode()``, and +``quantiles()``. The ``NaN`` values should be stripped before calling these +functions:: + + >>> from statistics import median + >>> from math import isnan + >>> from itertools import filterfalse + + >>> data = [20.7, float('NaN'),19.2, 18.3, float('NaN'), 14.4] + >>> sorted(data) # This has surprising behavior + [20.7, nan, 14.4, 18.3, 19.2, nan] + >>> median(data) # This result is unexpected + 16.35 + + >>> sum(map(isnan, data)) # Number of missing values + 2 + >>> clean = list(filterfalse(isnan, data)) # Strip NaN values + >>> clean + [20.7, 19.2, 18.3, 14.4] + >>> sorted(clean) # Sorting now works as expected + [14.4, 18.3, 19.2, 20.7] + >>> median(clean) # This result is now well defined + 18.75 + + Averages and measures of central location ----------------------------------------- diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index 0a996feb22cef7bc79b91a04e8ca49bc75983391..fae81f8ac28ff40885b45ad98982f8a6821c863d 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -1473,7 +1473,7 @@ handling consistency are valid for these functions. >>> subprocess.getstatusoutput('/bin/kill $$') (-15, '') - .. availability:: POSIX & Windows. + .. availability:: Unix, Windows. .. versionchanged:: 3.3.4 Windows support was added. @@ -1495,7 +1495,7 @@ handling consistency are valid for these functions. >>> subprocess.getoutput('ls /bin/ls') '/bin/ls' - .. availability:: POSIX & Windows. + .. availability:: Unix, Windows. .. versionchanged:: 3.3.4 Windows support added diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 7e2468446eb96cb249f81aaae259b1c00630fc73..e7ad6a6c67bd19805cdbe60362ca441ef05bf53a 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -338,7 +338,7 @@ always available. | | memory support. | +-----------------------------+----------------------------------------------+ - .. availability:: WebAssembly Emscripten platform (*wasm32-emscripten*). + .. availability:: Emscripten. .. versionadded:: 3.11 @@ -774,7 +774,7 @@ always available. that is deeper than the call stack, :exc:`ValueError` is raised. The default for *depth* is zero, returning the frame at the top of the call stack. - .. audit-event:: sys._getframe "" sys._getframe + .. audit-event:: sys._getframe frame sys._getframe .. impl-detail:: @@ -1158,7 +1158,7 @@ always available. line option or the :envvar:`PYTHONSAFEPATH` environment variable? A program is free to modify this list for its own purposes. Only strings - and bytes should be added to :data:`sys.path`; all other data types are + should be added to :data:`sys.path`; all other data types are ignored during import. @@ -1658,6 +1658,8 @@ always available. | | | | | * ``'nt'``: Windows threads | | | * ``'pthread'``: POSIX threads | + | | * ``'pthread-stubs'``: stub POSIX threads | + | | (on WebAssembly platforms without threading support) | | | * ``'solaris'``: Solaris threads | +------------------+---------------------------------------------------------+ | :const:`lock` | Name of the lock implementation: | diff --git a/Doc/library/sysconfig.rst b/Doc/library/sysconfig.rst index fa18d62d22af51e42c829587e7cb1b759fc65757..024988777030f84ec0ff588da7edd92d45fd191d 100644 --- a/Doc/library/sysconfig.rst +++ b/Doc/library/sysconfig.rst @@ -25,7 +25,7 @@ Configuration variables A Python distribution contains a :file:`Makefile` and a :file:`pyconfig.h` header file that are necessary to build both the Python binary itself and -third-party C extensions compiled using :mod:`distutils`. +third-party C extensions compiled using ``setuptools``. :mod:`sysconfig` puts all variables found in these files in a dictionary that can be accessed using :func:`get_config_vars` or :func:`get_config_var`. diff --git a/Doc/library/syslog.rst b/Doc/library/syslog.rst index d264a3340c98b01fcc6f568025760ad70140b91d..ce51856ab7be1379568becbc185ddb28d843b2aa 100644 --- a/Doc/library/syslog.rst +++ b/Doc/library/syslog.rst @@ -29,10 +29,15 @@ The module defines the following functions: value given in the :func:`openlog` call is used. If :func:`openlog` has not been called prior to the call to :func:`syslog`, - ``openlog()`` will be called with no arguments. + :func:`openlog` will be called with no arguments. .. audit-event:: syslog.syslog priority,message syslog.syslog + .. versionchanged:: 3.2 + In previous versions, :func:`openlog` would not be called automatically if + it wasn't called prior to the call to :func:`syslog`, deferring to the syslog + implementation to call ``openlog()``. + .. function:: openlog([ident[, logoption[, facility]]]) @@ -51,8 +56,7 @@ The module defines the following functions: .. versionchanged:: 3.2 In previous versions, keyword arguments were not allowed, and *ident* was - required. The default for *ident* was dependent on the system libraries, - and often was ``python`` instead of the name of the Python program file. + required. .. function:: closelog() diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst index 58e4ad786fe17f85850a8bf97ad57fa751b43a92..8e69c2c404f63a5a677e84c6a21362414c500aed 100644 --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -192,7 +192,9 @@ This module defines the following functions: information (4 KiB pages are common; using multiples of 4096 for the stack size is the suggested approach in the absence of more specific information). - .. availability:: Windows, systems with POSIX threads. + .. availability:: Windows, pthreads. + + Unix platforms with POSIX threads support. This module also defines the following constant: @@ -429,7 +431,7 @@ since it is impossible to detect the termination of alien threads. system-wide) from the time the thread is created until the thread has been terminated. - .. availability:: Requires :func:`get_native_id` function. + .. availability:: Windows, FreeBSD, Linux, macOS, OpenBSD, NetBSD, AIX, DragonFlyBSD. .. versionadded:: 3.8 diff --git a/Doc/library/time.rst b/Doc/library/time.rst index be17fa68eb7b581380a12a017e57c4c13ed5d932..9f23a6fc7d534130d1f9cfedd3446648d4c09ac7 100644 --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -144,8 +144,10 @@ Functions Passing an invalid or expired *thread_id* may result in undefined behavior, such as segmentation fault. - .. availability:: Unix (see the man page for :manpage:`pthread_getcpuclockid(3)` for - further information). + .. availability:: Unix + + See the man page for :manpage:`pthread_getcpuclockid(3)` for + further information. .. versionadded:: 3.7 @@ -651,8 +653,9 @@ Functions Use :func:`thread_time_ns` to avoid the precision loss caused by the :class:`float` type. - .. availability:: Windows, Linux, Unix systems supporting - ``CLOCK_THREAD_CPUTIME_ID``. + .. availability:: Linux, Unix, Windows. + + Unix systems supporting ``CLOCK_THREAD_CPUTIME_ID``. .. versionadded:: 3.7 @@ -770,7 +773,7 @@ These constants are used as parameters for :func:`clock_getres` and have discontinuities if the time is changed using ``settimeofday()`` or similar. - .. availability:: Linux 2.6.39 or later. + .. availability:: Linux >= 2.6.39. .. versionadded:: 3.7 @@ -801,7 +804,7 @@ These constants are used as parameters for :func:`clock_getres` and Similar to :data:`CLOCK_MONOTONIC`, but provides access to a raw hardware-based time that is not subject to NTP adjustments. - .. availability:: Linux 2.6.28 and newer, macOS 10.12 and newer. + .. availability:: Linux >= 2.6.28, macOS >= 10.12. .. versionadded:: 3.3 @@ -819,7 +822,7 @@ These constants are used as parameters for :func:`clock_getres` and High-resolution per-process timer from the CPU. - .. availability:: FreeBSD, NetBSD 7 or later, OpenBSD. + .. availability:: FreeBSD, NetBSD >= 7, OpenBSD. .. versionadded:: 3.7 @@ -849,7 +852,7 @@ These constants are used as parameters for :func:`clock_getres` and suspended, providing accurate uptime measurement, both absolute and interval. - .. availability:: FreeBSD, OpenBSD 5.5 or later. + .. availability:: FreeBSD, OpenBSD >= 5.5. .. versionadded:: 3.7 @@ -860,7 +863,7 @@ These constants are used as parameters for :func:`clock_getres` and point, unaffected by frequency or time adjustments and not incremented while the system is asleep. - .. availability:: macOS 10.12 and newer. + .. availability:: macOS >= 10.12. .. versionadded:: 3.8 diff --git a/Doc/library/traceback.rst b/Doc/library/traceback.rst index 796309c6cf0bb9eb96e0154058598be1fe639710..8cb6af9bc840b59bb2788f88b395369184070a75 100644 --- a/Doc/library/traceback.rst +++ b/Doc/library/traceback.rst @@ -341,6 +341,10 @@ capture data for later printing in a lightweight fashion. local variables in each :class:`FrameSummary` are captured as object representations. + .. versionchanged:: 3.12 + Exceptions raised from :func:`repr` on a local variable (when + *capture_locals* is ``True``) are no longer propagated to the caller. + .. classmethod:: from_list(a_list) Construct a :class:`StackSummary` object from a supplied list of @@ -464,32 +468,27 @@ The output for the example would look similar to this: *** print_tb: File "<doctest...>", line 10, in <module> lumberjack() - ^^^^^^^^^^^^ *** print_exception: Traceback (most recent call last): File "<doctest...>", line 10, in <module> lumberjack() - ^^^^^^^^^^^^ File "<doctest...>", line 4, in lumberjack bright_side_of_death() - ^^^^^^^^^^^^^^^^^^^^^^ IndexError: tuple index out of range *** print_exc: Traceback (most recent call last): File "<doctest...>", line 10, in <module> lumberjack() - ^^^^^^^^^^^^ File "<doctest...>", line 4, in lumberjack bright_side_of_death() - ^^^^^^^^^^^^^^^^^^^^^^ IndexError: tuple index out of range *** format_exc, first and last line: Traceback (most recent call last): IndexError: tuple index out of range *** format_exception: ['Traceback (most recent call last):\n', - ' File "<doctest default[0]>", line 10, in <module>\n lumberjack()\n ^^^^^^^^^^^^\n', - ' File "<doctest default[0]>", line 4, in lumberjack\n bright_side_of_death()\n ^^^^^^^^^^^^^^^^^^^^^^\n', + ' File "<doctest default[0]>", line 10, in <module>\n lumberjack()\n', + ' File "<doctest default[0]>", line 4, in lumberjack\n bright_side_of_death()\n', ' File "<doctest default[0]>", line 7, in bright_side_of_death\n return tuple()[0]\n ~~~~~~~^^^\n', 'IndexError: tuple index out of range\n'] *** extract_tb: @@ -497,8 +496,8 @@ The output for the example would look similar to this: <FrameSummary file <doctest...>, line 4 in lumberjack>, <FrameSummary file <doctest...>, line 7 in bright_side_of_death>] *** format_tb: - [' File "<doctest default[0]>", line 10, in <module>\n lumberjack()\n ^^^^^^^^^^^^\n', - ' File "<doctest default[0]>", line 4, in lumberjack\n bright_side_of_death()\n ^^^^^^^^^^^^^^^^^^^^^^\n', + [' File "<doctest default[0]>", line 10, in <module>\n lumberjack()\n', + ' File "<doctest default[0]>", line 4, in lumberjack\n bright_side_of_death()\n', ' File "<doctest default[0]>", line 7, in bright_side_of_death\n return tuple()[0]\n ~~~~~~~^^^\n'] *** tb_lineno: 10 diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index fceb43aec9be378cdca06b487c110747cc94f4c2..4d422f539ad1845e757c88d4a5a849815dde845d 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -683,7 +683,7 @@ These can be used as types in annotations and do not support ``[]``. from typing import Self class Foo: - def returns_self(self) -> Self: + def return_self(self) -> Self: ... return self @@ -696,7 +696,7 @@ These can be used as types in annotations and do not support ``[]``. Self = TypeVar("Self", bound="Foo") class Foo: - def returns_self(self: Self) -> Self: + def return_self(self: Self) -> Self: ... return self @@ -707,7 +707,7 @@ These can be used as types in annotations and do not support ``[]``. ... return self - You should use use :data:`Self` as calls to ``SubclassOfFoo.returns_self`` would have + You should use :data:`Self` as calls to ``SubclassOfFoo.return_self`` would have ``Foo`` as the return type and not ``SubclassOfFoo``. Other common use cases include: @@ -2215,6 +2215,9 @@ Corresponding to other types in :mod:`collections.abc` An alias to :class:`collections.abc.Hashable`. + .. deprecated:: 3.12 + Use :class:`collections.abc.Hashable` directly instead. + .. class:: Reversible(Iterable[T_co]) A generic version of :class:`collections.abc.Reversible`. @@ -2227,6 +2230,9 @@ Corresponding to other types in :mod:`collections.abc` An alias to :class:`collections.abc.Sized`. + .. deprecated:: 3.12 + Use :class:`collections.abc.Sized` directly instead. + Asynchronous programming """""""""""""""""""""""" @@ -2849,3 +2855,6 @@ convenience. This is subject to change, and not all deprecations are listed. +----------------------------------+---------------+-------------------+----------------+ | ``typing.Text`` | 3.11 | Undecided | :gh:`92332` | +----------------------------------+---------------+-------------------+----------------+ +| ``typing.Hashable`` and | 3.12 | Undecided | :gh:`94309` | +| ``typing.Sized`` | | | | ++----------------------------------+---------------+-------------------+----------------+ diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index 331f67cba23b5f52f95d8b8e08346fe0e1ca237a..38be6b82b492d42c5cdfb97b5a18b01f39cf37a6 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -1150,8 +1150,8 @@ Test cases Example:: with self.assertLogs('foo', level='INFO') as cm: - logging.getLogger('foo').info('first message') - logging.getLogger('foo.bar').error('second message') + logging.getLogger('foo').info('first message') + logging.getLogger('foo.bar').error('second message') self.assertEqual(cm.output, ['INFO:foo:first message', 'ERROR:foo.bar:second message']) diff --git a/Doc/library/venv.rst b/Doc/library/venv.rst index 3cf143d552ac88f649d26bb6eef278df29cb1aaf..513a982c6ede6a4b7a79f3b422ff4946aa0e5438 100644 --- a/Doc/library/venv.rst +++ b/Doc/library/venv.rst @@ -64,7 +64,7 @@ Creating virtual environments Python installation). When a virtual environment is active, any options that change the - installation path will be ignored from all :mod:`distutils` configuration + installation path will be ignored from all ``setuptools`` configuration files to prevent projects being inadvertently installed outside of the virtual environment. diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index 688407195f05ddb1a24fc07165ba671fa3d57cb3..93c1720220f0439d2fb172c1db184888aefea2e4 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -1495,7 +1495,7 @@ Is semantically equivalent to:: else: SUITE2 -See also :meth:`__aiter__` and :meth:`__anext__` for details. +See also :meth:`~object.__aiter__` and :meth:`~object.__anext__` for details. It is a :exc:`SyntaxError` to use an ``async for`` statement outside the body of a coroutine function. @@ -1537,7 +1537,7 @@ is semantically equivalent to:: if not hit_except: await aexit(manager, None, None, None) -See also :meth:`__aenter__` and :meth:`__aexit__` for details. +See also :meth:`~object.__aenter__` and :meth:`~object.__aexit__` for details. It is a :exc:`SyntaxError` to use an ``async with`` statement outside the body of a coroutine function. diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst index 29d402ebcf492aaff107342d1978bd998d4d4639..1e6b08f32a7aca5506188e54ce1e87dca899fdf0 100644 --- a/Doc/reference/import.rst +++ b/Doc/reference/import.rst @@ -800,10 +800,8 @@ environment variable and various other installation- and implementation-specific defaults. Entries in :data:`sys.path` can name directories on the file system, zip files, and potentially other "locations" (see the :mod:`site` module) that should be searched for modules, such as -URLs, or database queries. Only strings and bytes should be present on -:data:`sys.path`; all other data types are ignored. The encoding of bytes -entries is determined by the individual :term:`path entry finders <path entry -finder>`. +URLs, or database queries. Only strings should be present on +:data:`sys.path`; all other data types are ignored. The :term:`path based finder` is a :term:`meta path finder`, so the import machinery begins the :term:`import path` search by calling the path diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py index 8ac0028cc4f412e2b6dca6bc578cb0e8d745369a..20c372e2495697ca6945b12a5d19fac40c61a9bb 100644 --- a/Doc/tools/extensions/pyspecific.py +++ b/Doc/tools/extensions/pyspecific.py @@ -134,11 +134,22 @@ def run(self): class Availability(Directive): - has_content = False + has_content = True required_arguments = 1 optional_arguments = 0 final_argument_whitespace = True + # known platform, libc, and threading implementations + known_platforms = frozenset({ + "AIX", "Android", "BSD", "DragonFlyBSD", "Emscripten", "FreeBSD", + "Linux", "NetBSD", "OpenBSD", "POSIX", "Solaris", "Unix", "VxWorks", + "WASI", "Windows", "macOS", + # libc + "BSD libc", "glibc", "musl", + # POSIX platforms with pthreads + "pthreads", + }) + def run(self): availability_ref = ':ref:`Availability <availability>`: ' pnode = nodes.paragraph(availability_ref + self.arguments[0], @@ -147,8 +158,53 @@ def run(self): pnode.extend(n + m) n, m = self.state.inline_text(self.arguments[0], self.lineno) pnode.extend(n + m) + if self.content: + content = " " + " ".join(self.content) + n, m = self.state.inline_text(content, self.content_offset) + pnode.extend(n + m) + + self.parse_platforms() + return [pnode] + def parse_platforms(self): + """Parse platform information from arguments + + Arguments is a comma-separated string of platforms. A platform may + be prefixed with "not " to indicate that a feature is not available. + + Example:: + + .. availability:: Windows, Linux >= 4.2, not Emscripten, not WASI + + Arguments like "Linux >= 3.17 with glibc >= 2.27" are currently not + parsed into separate tokens. + """ + platforms = {} + for arg in self.arguments[0].rstrip(".").split(","): + arg = arg.strip() + platform, _, version = arg.partition(" >= ") + if platform.startswith("not "): + version = False + platform = platform[4:] + elif not version: + version = True + platforms[platform] = version + + unknown = set(platforms).difference(self.known_platforms) + if unknown: + cls = type(self) + logger = logging.getLogger(cls.__qualname__) + logger.warn( + f"Unknown platform(s) or syntax '{' '.join(sorted(unknown))}' " + f"in '.. availability:: {self.arguments[0]}', see " + f"{__file__}:{cls.__qualname__}.known_platforms for a set " + "known platforms." + ) + + return platforms + + # Support for documenting audit event diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst index 324238228d62659bbaa76007557cd12019650e3e..d3414005a534352a5d87b554d827e05a5a4b74b9 100644 --- a/Doc/tutorial/inputoutput.rst +++ b/Doc/tutorial/inputoutput.rst @@ -166,7 +166,7 @@ are referred to by using the name of the argument. :: Positional and keyword arguments can be arbitrarily combined:: >>> print('The story of {0}, {1}, and {other}.'.format('Bill', 'Manfred', - other='Georg')) + ... other='Georg')) The story of Bill, Manfred, and Georg. If you have a really long format string that you don't want to split up, it diff --git a/Doc/tutorial/stdlib.rst b/Doc/tutorial/stdlib.rst index b32a552d5570cf1bc929338591ca3418ba7ee109..4f5ada90eb57bc784a901c137ed8810883c733ac 100644 --- a/Doc/tutorial/stdlib.rst +++ b/Doc/tutorial/stdlib.rst @@ -65,11 +65,15 @@ Command Line Arguments Common utility scripts often need to process command line arguments. These arguments are stored in the :mod:`sys` module's *argv* attribute as a list. For -instance the following output results from running ``python demo.py one two -three`` at the command line:: +instance, let's take the following :file:`demo.py` file:: + + # File demo.py + import sys + print(sys.argv) + +Here is the output from running ``python demo.py one two three`` at the command +line:: - >>> import sys - >>> print(sys.argv) ['demo.py', 'one', 'two', 'three'] The :mod:`argparse` module provides a more sophisticated mechanism to process diff --git a/Doc/tutorial/stdlib2.rst b/Doc/tutorial/stdlib2.rst index abdf5abda984f5eb92048ffdbd03781b279eba2e..0c101c1f20723503b6712b872d9b030ce5f6090b 100644 --- a/Doc/tutorial/stdlib2.rst +++ b/Doc/tutorial/stdlib2.rst @@ -108,6 +108,7 @@ placeholders such as the current date, image sequence number, or file format:: >>> photofiles = ['img_1074.jpg', 'img_1076.jpg', 'img_1077.jpg'] >>> class BatchRename(Template): ... delimiter = '%' + ... >>> fmt = input('Enter rename style (%d-date %n-seqnum %f-format): ') Enter rename style (%d-date %n-seqnum %f-format): Ashley_%n%f diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index bc92e0e44b9b298e13e5bead42024390f406a0b9..2d376ec7b40fd0fa4cd04f58db490b798b0a240d 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -981,7 +981,7 @@ conflict. order to force the interpreter to use ``ASCII`` instead of ``UTF-8`` for system interfaces. - .. availability:: \*nix. + .. availability:: Unix. .. versionadded:: 3.7 See :pep:`538` for more details. diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index 80c0dc08dae732fbbe3782080f3d9c4f54246e0e..580cbd814f786e6da24e46e497acf108a65d08cf 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -599,7 +599,7 @@ Main files of the build system * :file:`pyconfig.h` (created by :file:`configure`); * :file:`Modules/Setup`: C extensions built by the Makefile using :file:`Module/makesetup` shell script; -* :file:`setup.py`: C extensions built using the :mod:`distutils` module. +* :file:`setup.py`: C extensions built using the ``setuptools`` package. Main build steps ---------------- diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index d7e0a5e13825a5fb87090c32969c71515b3ba67e..1025c14e397df262dcd194b61315daec380acbe1 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -34,7 +34,7 @@ developers using Python for any kind of project. :ref:`windows-store` is a simple installation of Python that is suitable for running scripts and packages, and using IDLE or other development environments. -It requires Windows 10, but can be safely installed without corrupting other +It requires Windows 10 and above, but can be safely installed without corrupting other programs. It also provides many convenient commands for launching Python and its tools. @@ -348,14 +348,42 @@ Python in Start and right-click to select Uninstall. Uninstalling will remove all packages you installed directly into this Python installation, but will not remove any virtual environments -Known Issues +Known issues ------------ +Redirection of local data, registry, and temporary paths +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Because of restrictions on Microsoft Store apps, Python scripts may not have -full write access to shared locations such as ``TEMP`` and the registry. +full write access to shared locations such as :envvar:`TEMP` and the registry. Instead, it will write to a private copy. If your scripts must modify the shared locations, you will need to install the full installer. +At runtime, Python will use a private copy of well-known Windows folders and the registry. +For example, if the environment variable :envvar:`%APPDATA%` is :file:`c:\\Users\\<user>\\AppData\\`, +then when writing to :file:`C:\\Users\\<user>\\AppData\\Local` will write to +:file:`C:\\Users\\<user>\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\\LocalCache\\Local\\`. + +When reading files, Windows will return the file from the private folder, or if that does not exist, the +real Windows directory. For example reading :file:`C:\\Windows\\System32` returns the contents of :file:`C:\\Windows\\System32` +plus the contents of :file:`C:\\Program Files\\WindowsApps\\package_name\\VFS\\SystemX86`. + +You can find the real path of any existing file using :func:`os.path.realpath`: + +.. code-block:: python + + >>> import os + >>> test_file = 'C:\\Users\\example\\AppData\\Local\\test.txt' + >>> os.path.realpath(test_file) + 'C:\\Users\\example\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\\LocalCache\\Local\\test.txt' + +When writing to the Windows Registry, the following behaviors exist: + +* Reading from ``HKLM\\Software`` is allowed and results are merged with the :file:`registry.dat` file in the package. +* Writing to ``HKLM\\Software`` is not allowed if the corresponding key/value exists, i.e. modifying existing keys. +* Writing to ``HKLM\\Software`` is allowed as long as a corresponding key/value does not exist in the package + and the user has the correct access permissions. + For more detail on the technical basis for these limitations, please consult Microsoft's documentation on packaged full-trust apps, currently available at `docs.microsoft.com/en-us/windows/msix/desktop/desktop-to-uwp-behind-the-scenes @@ -1159,11 +1187,10 @@ shipped with PyWin32. It is an embeddable IDE with a built-in debugger. cx_Freeze --------- -`cx_Freeze <https://cx-freeze.readthedocs.io/en/latest/>`_ is a :mod:`distutils` -extension (see :ref:`extending-distutils`) which wraps Python scripts into -executable Windows programs (:file:`{*}.exe` files). When you have done this, -you can distribute your application without requiring your users to install -Python. +`cx_Freeze <https://cx-freeze.readthedocs.io/en/latest/>`_ is a ``distutils`` +extension which wraps Python scripts into executable Windows programs +(:file:`{*}.exe` files). When you have done this, you can distribute your +application without requiring your users to install Python. Compiling Python on Windows diff --git a/Doc/whatsnew/2.0.rst b/Doc/whatsnew/2.0.rst index 24fc39be6161cb3d226aabfe5169d4c2a099c538..9b28dbc190337d49cc0ef3fdfb63268c3e784bb3 100644 --- a/Doc/whatsnew/2.0.rst +++ b/Doc/whatsnew/2.0.rst @@ -820,7 +820,7 @@ packages, which made administering a Python installation something of a chore. The SIG for distribution utilities, shepherded by Greg Ward, has created the Distutils, a system to make package installation much easier. They form the -:mod:`distutils` package, a new part of Python's standard library. In the best +``distutils`` package, a new part of Python's standard library. In the best case, installing a Python module from source will require the same steps: first you simply mean unpack the tarball or zip archive, and the run "``python setup.py install``". The platform will be automatically detected, the compiler diff --git a/Doc/whatsnew/2.7.rst b/Doc/whatsnew/2.7.rst index f753055c16ee2a5af976ea261fbdd08fa2aeea88..59d68a192b8f7db43326f5911c2082b41747e75a 100644 --- a/Doc/whatsnew/2.7.rst +++ b/Doc/whatsnew/2.7.rst @@ -2697,7 +2697,7 @@ projects. However, as this migration is currently still incomplete, the legacy versions of those guides remaining available as :ref:`install-index` -and :ref:`distutils-index`. +and :ref:`setuptools-index`. .. seealso:: diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index e6e97d98f87f2be4b018f67c06a8c64418183216..d0fbf0d216de367f2e94c3d5bf4e569515fb3533 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -230,7 +230,7 @@ have been incorporated. Some of the most notable ones are as follows: ^ SyntaxError: expected ':' - (Contributed by Pablo Galindo in :issue:`42997`) + (Contributed by Pablo Galindo in :issue:`42997`.) * Unparenthesised tuples in comprehensions targets: @@ -242,7 +242,7 @@ have been incorporated. Some of the most notable ones are as follows: ^ SyntaxError: did you forget parentheses around the comprehension target? - (Contributed by Pablo Galindo in :issue:`43017`) + (Contributed by Pablo Galindo in :issue:`43017`.) * Missing commas in collection literals and between expressions: @@ -257,7 +257,7 @@ have been incorporated. Some of the most notable ones are as follows: ^ SyntaxError: invalid syntax. Perhaps you forgot a comma? - (Contributed by Pablo Galindo in :issue:`43822`) + (Contributed by Pablo Galindo in :issue:`43822`.) * Multiple Exception types without parentheses: @@ -271,7 +271,7 @@ have been incorporated. Some of the most notable ones are as follows: ^ SyntaxError: multiple exception types must be parenthesized - (Contributed by Pablo Galindo in :issue:`43149`) + (Contributed by Pablo Galindo in :issue:`43149`.) * Missing ``:`` and values in dictionary literals: @@ -293,7 +293,7 @@ have been incorporated. Some of the most notable ones are as follows: ^ SyntaxError: ':' expected after dictionary key - (Contributed by Pablo Galindo in :issue:`43823`) + (Contributed by Pablo Galindo in :issue:`43823`.) * ``try`` blocks without ``except`` or ``finally`` blocks: @@ -307,7 +307,7 @@ have been incorporated. Some of the most notable ones are as follows: ^^^^^^^^^ SyntaxError: expected 'except' or 'finally' block - (Contributed by Pablo Galindo in :issue:`44305`) + (Contributed by Pablo Galindo in :issue:`44305`.) * Usage of ``=`` instead of ``==`` in comparisons: @@ -319,7 +319,7 @@ have been incorporated. Some of the most notable ones are as follows: ^ SyntaxError: cannot assign to attribute here. Maybe you meant '==' instead of '='? - (Contributed by Pablo Galindo in :issue:`43797`) + (Contributed by Pablo Galindo in :issue:`43797`.) * Usage of ``*`` in f-strings: @@ -331,7 +331,7 @@ have been incorporated. Some of the most notable ones are as follows: ^ SyntaxError: f-string: cannot use starred expression here - (Contributed by Pablo Galindo in :issue:`41064`) + (Contributed by Pablo Galindo in :issue:`41064`.) IndentationErrors ~~~~~~~~~~~~~~~~~ @@ -1048,7 +1048,7 @@ keyword-only. This will probably be the most common usage: Here, ``z`` and ``t`` are keyword-only parameters, while ``x`` and ``y`` are not. -(Contributed by Eric V. Smith in :issue:`43532`) +(Contributed by Eric V. Smith in :issue:`43532`.) .. _distutils-deprecated: @@ -1266,11 +1266,11 @@ pathlib ------- Add slice support to :attr:`PurePath.parents <pathlib.PurePath.parents>`. -(Contributed by Joshua Cannon in :issue:`35498`) +(Contributed by Joshua Cannon in :issue:`35498`.) Add negative indexing support to :attr:`PurePath.parents <pathlib.PurePath.parents>`. -(Contributed by Yaroslav Pankovych in :issue:`21041`) +(Contributed by Yaroslav Pankovych in :issue:`21041`.) Add :meth:`Path.hardlink_to <pathlib.Path.hardlink_to>` method that supersedes :meth:`~pathlib.Path.link_to`. The new method has the same argument @@ -1288,7 +1288,7 @@ platform Add :func:`platform.freedesktop_os_release()` to retrieve operation system identification from `freedesktop.org os-release <https://www.freedesktop.org/software/systemd/man/os-release.html>`_ standard file. -(Contributed by Christian Heimes in :issue:`28468`) +(Contributed by Christian Heimes in :issue:`28468`.) pprint ------ @@ -1473,7 +1473,7 @@ and to match the behavior of static type checkers specified in the PEP. Add new function :func:`typing.is_typeddict` to introspect if an annotation is a :class:`typing.TypedDict`. -(Contributed by Patrick Reader in :issue:`41792`) +(Contributed by Patrick Reader in :issue:`41792`.) Subclasses of ``typing.Protocol`` which only have data variables declared will now raise a ``TypeError`` when checked with ``isinstance`` unless they @@ -1481,14 +1481,14 @@ are decorated with :func:`runtime_checkable`. Previously, these checks passed silently. Users should decorate their subclasses with the :func:`runtime_checkable` decorator if they want runtime protocols. -(Contributed by Yurii Karabas in :issue:`38908`) +(Contributed by Yurii Karabas in :issue:`38908`.) Importing from the ``typing.io`` and ``typing.re`` submodules will now emit :exc:`DeprecationWarning`. These submodules have been deprecated since Python 3.8 and will be removed in a future version of Python. Anything belonging to those submodules should be imported directly from :mod:`typing` instead. -(Contributed by Sebastian Rittau in :issue:`38291`) +(Contributed by Sebastian Rittau in :issue:`38291`.) unittest -------- @@ -1566,7 +1566,7 @@ Optimizations strings, and the function object lazily converts this into the annotations dict on demand. This optimization cuts the CPU time needed to define an annotated function by half. - (Contributed by Yurii Karabas and Inada Naoki in :issue:`42202`) + (Contributed by Yurii Karabas and Inada Naoki in :issue:`42202`.) * Substring search functions such as ``str1 in str2`` and ``str2.find(str1)`` now sometimes use Crochemore & Perrin's "Two-Way" string searching @@ -1575,16 +1575,16 @@ Optimizations * Add micro-optimizations to ``_PyType_Lookup()`` to improve type attribute cache lookup performance in the common case of cache hits. This makes the interpreter 1.04 times faster - on average. (Contributed by Dino Viehland in :issue:`43452`) + on average. (Contributed by Dino Viehland in :issue:`43452`.) * The following built-in functions now support the faster :pep:`590` vectorcall calling convention: :func:`map`, :func:`filter`, :func:`reversed`, :func:`bool` and :func:`float`. - (Contributed by Dong-hee Na and Jeroen Demeyer in :issue:`43575`, :issue:`43287`, :issue:`41922`, :issue:`41873` and :issue:`41870`) + (Contributed by Dong-hee Na and Jeroen Demeyer in :issue:`43575`, :issue:`43287`, :issue:`41922`, :issue:`41873` and :issue:`41870`.) * :class:`BZ2File` performance is improved by removing internal ``RLock``. This makes :class:`BZ2File` thread unsafe in the face of multiple simultaneous readers or writers, just like its equivalent classes in :mod:`gzip` and - :mod:`lzma` have always been. (Contributed by Inada Naoki in :issue:`43785`). + :mod:`lzma` have always been. (Contributed by Inada Naoki in :issue:`43785`.) .. _whatsnew310-deprecated: @@ -1600,7 +1600,7 @@ Deprecated :keyword:`for`, :keyword:`if`, :keyword:`in`, :keyword:`is` and :keyword:`or`. In future releases it will be changed to syntax warning, and finally to syntax error. - (Contributed by Serhiy Storchaka in :issue:`43833`). + (Contributed by Serhiy Storchaka in :issue:`43833`.) * Starting in this release, there will be a concerted effort to begin cleaning up old import semantics that were kept for Python 2.7 @@ -1788,7 +1788,7 @@ Deprecated :exc:`DeprecationWarning`. These submodules will be removed in a future version of Python. Anything belonging to these submodules should be imported directly from :mod:`typing` instead. - (Contributed by Sebastian Rittau in :issue:`38291`) + (Contributed by Sebastian Rittau in :issue:`38291`.) .. _whatsnew310-removed: @@ -1871,7 +1871,7 @@ Changes in the Python syntax syntax error. To get rid of the warning and make the code compatible with future releases just add a space between the numeric literal and the following keyword. - (Contributed by Serhiy Storchaka in :issue:`43833`). + (Contributed by Serhiy Storchaka in :issue:`43833`.) .. _changes-python-api: @@ -1981,7 +1981,7 @@ CPython bytecode changes * The ``MAKE_FUNCTION`` instruction now accepts either a dict or a tuple of strings as the function's annotations. - (Contributed by Yurii Karabas and Inada Naoki in :issue:`42202`) + (Contributed by Yurii Karabas and Inada Naoki in :issue:`42202`.) Build Changes ============= @@ -2197,7 +2197,7 @@ Porting to Python 3.10 directory. These files must not be included directly, as they are already included in ``Python.h``: :ref:`Include Files <api-includes>`. If they have been included directly, consider including ``Python.h`` instead. - (Contributed by Nicholas Sim in :issue:`35134`) + (Contributed by Nicholas Sim in :issue:`35134`.) * Use the :c:data:`Py_TPFLAGS_IMMUTABLETYPE` type flag to create immutable type objects. Do not rely on :c:data:`Py_TPFLAGS_HEAPTYPE` to decide if a type @@ -2207,7 +2207,7 @@ Porting to Python 3.10 * The undocumented function ``Py_FrozenMain`` has been removed from the limited API. The function is mainly useful for custom builds of Python. - (Contributed by Petr Viktorin in :issue:`26241`) + (Contributed by Petr Viktorin in :issue:`26241`.) Deprecated ---------- diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 95991528444c7cf4d8ebf4015581cadde74d1936..1b3a685dbacb91831044d5fc3a0f9f648dc52370 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -117,7 +117,6 @@ when dealing with deeply nested dictionary objects and multiple function calls, Traceback (most recent call last): File "query.py", line 37, in <module> magic_arithmetic('foo') - ^^^^^^^^^^^^^^^^^^^^^^^ File "query.py", line 18, in magic_arithmetic return add_counts(x) / 25 ^^^^^^^^^^^^^ @@ -384,6 +383,13 @@ Other Language Changes coerces negative zero to zero after rounding to the format precision. See :pep:`682` for more details. (Contributed by John Belmonte in :gh:`90153`.) +* Bytes are no longer accepted on :attr:`sys.path`. Support broke sometime + between Python 3.2 and 3.6 with no one noticing until after Python 3.10.0 + was released. Bringing back support would also be problematic due to + interactions between :option:`-b` and :attr:`sys.path_importer_cache` when + there is a mixture of strings and bytes keys. + (Contributed by Thomas Grainger in :gh:`91181`.) + Other CPython Implementation Changes ==================================== @@ -540,7 +546,7 @@ inspect line number, column and end column). The affected functions are: :func:`inspect.getframeinfo`, :func:`inspect.getouterframes`, :func:`inspect.getinnerframes`, :func:`inspect.stack` and :func:`inspect.trace`. (Contributed by Pablo Galindo in - :gh:`88116`) + :gh:`88116`.) locale ------ @@ -615,7 +621,7 @@ socket * :meth:`~socket.create_connection` has an option to raise, in case of failure to connect, an :exc:`ExceptionGroup` containing all errors instead of only raising the last error. - (Contributed by Irit Katriel in :issue:`29980`). + (Contributed by Irit Katriel in :issue:`29980`.) sqlite3 ------- @@ -665,7 +671,7 @@ sqlite3 * Add :meth:`~sqlite3.Connection.blobopen` to :class:`sqlite3.Connection`. :class:`sqlite3.Blob` allows incremental I/O operations on blobs. - (Contributed by Aviv Palivoda and Erlend E. Aasland in :issue:`24905`) + (Contributed by Aviv Palivoda and Erlend E. Aasland in :issue:`24905`.) sys @@ -688,7 +694,7 @@ sys sysconfig --------- -* Two new :ref:`installation schemes <installation_paths>` +* Three new :ref:`installation schemes <installation_paths>` (*posix_venv*, *nt_venv* and *venv*) were added and are used when Python creates new virtual environments or when it is running from a virtual environment. @@ -809,7 +815,7 @@ tkinter unicodedata ----------- -* The Unicode database has been updated to version 14.0.0. (:issue:`45190`). +* The Unicode database has been updated to version 14.0.0. (Contributed by Benjamin Peterson in :issue:`45190`). unittest @@ -894,7 +900,7 @@ Optimizations Faster CPython ============== -CPython 3.11 is on average `25% faster <https://github.com/faster-cpython/ideas/blob/main/main-vs-310.rst>`_ +CPython 3.11 is on average `25% faster <https://github.com/faster-cpython/ideas#published-results>`_ than CPython 3.10 when measured with the `pyperformance <https://github.com/python/pyperformance>`_ benchmark suite, and compiled with GCC on Ubuntu Linux. Depending on your workload, the speedup @@ -1467,13 +1473,6 @@ Changes in the Python API the ``'utf-8'`` encoding. (Contributed by Srinivas Reddy Thatiparthy (శ్రీనివాస్ రెడ్డి తాటిపర్తి) in :issue:`41137`.) -* When sorting using tuples as keys, the order of the result may differ - from earlier releases if the tuple elements don't define a total - ordering (see :ref:`expressions-value-comparisons` for - information on total ordering). It's generally true that the result - of sorting simply isn't well-defined in the absence of a total ordering - on list elements. - * :mod:`calendar`: The :class:`calendar.LocaleTextCalendar` and :class:`calendar.LocaleHTMLCalendar` classes now use :func:`locale.getlocale`, instead of using :func:`locale.getdefaultlocale`, @@ -1495,6 +1494,10 @@ Changes in the Python API is larger than the population size, a :exc:`ValueError` is raised. (Contributed by Raymond Hettinger in :issue:`40465`.) +* :class:`ast.AST` node positions are now validated when provided to + :func:`compile` and other related functions. If invalid positions are detected, + a :exc:`ValueError` will be raised. (Contributed by Pablo Galindo in :gh:`93351`) + Build Changes ============= @@ -1527,7 +1530,7 @@ Build Changes * Freelists for object structs can now be disabled. A new :program:`configure` option :option:`!--without-freelists` can be used to disable all freelists except empty tuple singleton. - (Contributed by Christian Heimes in :issue:`45522`) + (Contributed by Christian Heimes in :issue:`45522`.) * ``Modules/Setup`` and ``Modules/makesetup`` have been improved and tied up. Extension modules can now be built through ``makesetup``. All except some @@ -1548,10 +1551,19 @@ Build Changes The :program:`configure` options ``--with-tcltk-includes`` and ``--with-tcltk-libs`` have been removed. -* CPython now has experimental support for cross compiling to WebAssembly - platform ``wasm32-emscripten``. The effort is inspired by previous work - like Pyodide. - (Contributed by Christian Heimes and Ethan Smith in :issue:`40280`.) +* CPython now has :pep:`11` tier 3 support for cross compiling to WebAssembly + platform ``wasm32-unknown-emscripten`` (Python in the browser). The effort + is inspired by previous work like `Pyodide <https://pyodide.org/>`_. + Emscripten provides a limited subset of POSIX APIs. Python standard + libraries features and modules related to networking, processes, threading, + signals, mmap, and users/groups are not available or don't work. + (Contributed by Christian Heimes and Ethan Smith in :gh:`84461`, + promoted in :gh:`95085`) + +* CPython now has :pep:`11` tier 3 support for cross compiling to WebAssembly + platform ``wasm32-unknown-wasi`` (WebAssembly System Interface). Like on + Emscripten, only a subset of Python's standard library is available on WASI. + (Contributed by Christian Heimes in :gh:`90473`, promoted in :gh:`95085`) * CPython will now use 30-bit digits by default for the Python :class:`int` implementation. Previously, the default was to use 30-bit digits on platforms diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 85b576c47c021a8b76c4a9c66e3fba54eeef3b6f..0c53bc0c1111d73bcb6a6fca72713411527e2841 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -132,9 +132,18 @@ CPython bytecode changes Deprecated ========== +* :class:`typing.Hashable` and :class:`typing.Sized` aliases for :class:`collections.abc.Hashable` + and :class:`collections.abc.Sized`. (:gh:`94309`.) + +* The :mod:`sqlite3` :ref:`default adapters and converters + <sqlite3-default-converters>` are now deprecated. + Instead, use the :ref:`sqlite3-adapter-converter-recipes` + and tailor them to your needs. + (Contributed by Erlend E. Aasland in :gh:`90016`.) + Pending Removal in Python 3.13 -============================== +------------------------------ The following modules and APIs have been deprecated in earlier Python releases, and will be removed in Python 3.13. @@ -171,8 +180,26 @@ APIs: * :func:`unittest.getTestCaseNames` (:gh:`50096`) * :class:`webbrowser.MacOSX` (:gh:`86421`) +Pending Removal in Python 3.14 +============================== + +* Deprecated the following :mod:`importlib.abc` classes, scheduled for removal in + Python 3.14: + + * :class:`importlib.abc.ResourceReader` + * :class:`importlib.abc.Traversable` + * :class:`importlib.abc.TraversableResources` + + Use :mod:`importlib.resources.abc` classes instead: + + * :class:`importlib.resources.abc.TraversableResources` + * :class:`importlib.resources.abc.Traversable` + * :class:`importlib.resources.abc.TraversableResources` + + (Contributed by Jason R. Coombs and Hugo van Kemenade in :gh:`93963`.) + Pending Removal in Future Versions -================================== +---------------------------------- The following APIs were deprecated in earlier Python versions and will be removed, although there is currently no date scheduled for their removal. @@ -255,7 +282,7 @@ Removed ``OptimizedUnicode`` can either use ``str`` explicitly, or rely on the default value which is also ``str``. - (Contributed by Erlend E. Aasland in :gh:`92548`) + (Contributed by Erlend E. Aasland in :gh:`92548`.) * The ``--experimental-isolated-subinterpreters`` configure flag (and corresponding ``EXPERIMENTAL_ISOLATED_SUBINTERPRETERS``) @@ -353,6 +380,12 @@ Changes in the Python API Build Changes ============= +* Python no longer uses ``setup.py`` to build shared C extension modules. + Build parameters like headers and libraries are detected in ``configure`` + script. Extensions are built by ``Makefile``. Most extensions use + ``pkg-config`` and fall back to manual detection. + (Contributed by Christian Heimes in :gh:`93939`.) + * ``va_start()`` with two parameters, like ``va_start(args, format),`` is now required to build Python. ``va_start()`` is no longer called with a single parameter. @@ -380,6 +413,13 @@ Porting to Python 3.12 ``Py_UNICODE*`` based format (e.g. ``u``, ``Z``) anymore. Please migrate to other formats for Unicode like ``s``, ``z``, ``es``, and ``U``. +* ``tp_weaklist`` for all static builtin types is always ``NULL``. + This is an internal-only field on ``PyTypeObject`` + but we're pointing out the change in case someone happens to be + accessing the field directly anyway. To avoid breakage, consider + using the existing public C-API instead, or, if necessary, the + (internal-only) ``_PyObject_GET_WEAKREFS_LISTPTR()`` macro. + Deprecated ---------- diff --git a/Doc/whatsnew/3.2.rst b/Doc/whatsnew/3.2.rst index 9dd849f9e9e720bdc7113bb8f29b1d650bcdfe79..31f2ea85ffd233136349c94d4bc7a2693c1eee98 100644 --- a/Doc/whatsnew/3.2.rst +++ b/Doc/whatsnew/3.2.rst @@ -2056,7 +2056,7 @@ information: such as "3.2". It also provides access to the paths and variables corresponding to one of -seven named schemes used by :mod:`distutils`. Those include *posix_prefix*, +seven named schemes used by ``distutils``. Those include *posix_prefix*, *posix_home*, *posix_user*, *nt*, *nt_user*, *os2*, *os2_home*: * :func:`~sysconfig.get_paths` makes a dictionary containing installation paths diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst index a09b60ffb331ec19fe9b226b98441630758c5baa..95e86550bc0323567a0081d4c7f59d58df0723c6 100644 --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -247,7 +247,7 @@ projects. However, as this migration is currently still incomplete, the legacy versions of those guides remaining available as :ref:`install-index` -and :ref:`distutils-index`. +and :ref:`setuptools-index`. .. seealso:: diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst index 1defee4090f288446dcbda87e1c2694640c8f4b1..537007b42fc6bf2851adc02c036442ad7a9e8297 100644 --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -1079,7 +1079,7 @@ Both the ``build`` and ``build_ext`` commands now accept a ``-j`` option to enable parallel building of extension modules. (Contributed by Antoine Pitrou in :issue:`5309`.) -The :mod:`distutils` module now supports ``xz`` compression, and can be +The ``distutils`` module now supports ``xz`` compression, and can be enabled by passing ``xztar`` as an argument to ``bdist --format``. (Contributed by Serhiy Storchaka in :issue:`16314`.) diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index e54475fd83c975dc88737ab8acae3f097cca5018..a587086ea776320f0211490fa4116178de24fc87 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -1012,7 +1012,7 @@ distutils --------- The ``default_format`` attribute has been removed from -:class:`distutils.command.sdist.sdist` and the ``formats`` +``distutils.command.sdist.sdist`` and the ``formats`` attribute defaults to ``['gztar']``. Although not anticipated, any code relying on the presence of ``default_format`` may need to be adapted. See :issue:`27819` for more details. @@ -1986,7 +1986,7 @@ distutils ~~~~~~~~~ The undocumented ``extra_path`` argument to the -:class:`~distutils.Distribution` constructor is now considered deprecated +``distutils.Distribution`` constructor is now considered deprecated and will raise a warning if set. Support for this parameter will be removed in a future Python release. See :issue:`27919` for details. @@ -2243,7 +2243,7 @@ Changes in the Python API accepting additional keyword arguments will need to adjust their calls to :meth:`type.__new__` (whether direct or via :class:`super`) accordingly. -* In :class:`distutils.command.sdist.sdist`, the ``default_format`` +* In ``distutils.command.sdist.sdist``, the ``default_format`` attribute has been removed and is no longer honored. Instead, the gzipped tarfile format is the default on all platforms and no platform-specific selection is made. diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 68901fa27eccfeba869a93d6bfb1d4077371580e..fd99682f3a4fac64651be57b42a7eff6ab10cdf7 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -1906,7 +1906,7 @@ Other CPython Implementation Changes variables were defined. Previously, the order was undefined. (Contributed by Raymond Hettinger in :issue:`32690`.) -* The :mod:`distutils` ``upload`` command no longer tries to change CR +* The ``distutils`` ``upload`` command no longer tries to change CR end-of-line characters to CRLF. This fixes a corruption issue with sdists that ended with a byte equivalent to CR. (Contributed by Bo Bayles in :issue:`32304`.) @@ -2181,7 +2181,7 @@ The following features and APIs have been removed from Python 3.7: :func:`ssl.wrap_socket` or :class:`ssl.SSLContext`. (Contributed by Christian Heimes in :issue:`32951`.) -* The unused :mod:`distutils` ``install_misc`` command has been removed. +* The unused ``distutils`` ``install_misc`` command has been removed. (Contributed by Eric N. Vander Weele in :issue:`29218`.) diff --git a/Grammar/python.gram b/Grammar/python.gram index 91d73a9fffd1938cbc4101f82afc1464145347da..6a81e14decbde00943967468e148cf80afaf14c1 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -391,7 +391,7 @@ for_stmt[stmt_ty]: with_stmt[stmt_ty]: | invalid_with_stmt_indent | 'with' '(' a[asdl_withitem_seq*]=','.with_item+ ','? ')' ':' b=block { - _PyAST_With(a, b, NULL, EXTRA) } + CHECK_VERSION(stmt_ty, 9, "Parenthesized context managers are", _PyAST_With(a, b, NULL, EXTRA)) } | 'with' a[asdl_withitem_seq*]=','.with_item+ ':' tc=[TYPE_COMMENT] b=block { _PyAST_With(a, b, NEW_TYPE_COMMENT(p, tc), EXTRA) } | ASYNC 'with' '(' a[asdl_withitem_seq*]=','.with_item+ ','? ')' ':' b=block { @@ -660,7 +660,9 @@ star_named_expression[expr_ty]: | named_expression assignment_expression[expr_ty]: - | a=NAME ':=' ~ b=expression { _PyAST_NamedExpr(CHECK(expr_ty, _PyPegen_set_expr_context(p, a, Store)), b, EXTRA) } + | a=NAME ':=' ~ b=expression { + CHECK_VERSION(expr_ty, 8, "Assignment expressions are", + _PyAST_NamedExpr(CHECK(expr_ty, _PyPegen_set_expr_context(p, a, Store)), b, EXTRA)) } named_expression[expr_ty]: | assignment_expression diff --git a/Include/cpython/dictobject.h b/Include/cpython/dictobject.h index 565ad791a6cb286631796adb17122b44c81884a9..c2e4a46e76195bcf406e851e6999bc4f141bf792 100644 --- a/Include/cpython/dictobject.h +++ b/Include/cpython/dictobject.h @@ -83,3 +83,6 @@ typedef struct { PyAPI_FUNC(PyObject *) _PyDictView_New(PyObject *, PyTypeObject *); PyAPI_FUNC(PyObject *) _PyDictView_Intersect(PyObject* self, PyObject *other); + +PyAPI_FUNC(int) _PyObject_VisitManagedDict(PyObject *self, visitproc visit, void *arg); +PyAPI_FUNC(void) _PyObject_ClearManagedDict(PyObject *self); diff --git a/Include/cpython/object.h b/Include/cpython/object.h index 614d6c18ee0b4a48c54fe6dc96d455e3e4308edd..026803320a11b2b643868f00c11ebc9f281a18c7 100644 --- a/Include/cpython/object.h +++ b/Include/cpython/object.h @@ -219,7 +219,7 @@ struct _typeobject { PyObject *tp_mro; /* method resolution order */ PyObject *tp_cache; PyObject *tp_subclasses; - PyObject *tp_weaklist; + PyObject *tp_weaklist; /* not used for static builtin types */ destructor tp_del; /* Type attribute cache version tag. Added in version 2.6 */ @@ -227,6 +227,7 @@ struct _typeobject { destructor tp_finalize; vectorcallfunc tp_vectorcall; + size_t tp_static_builtin_index; /* 0 means "not initialized" */ }; /* This struct is used by the specializer diff --git a/Include/cpython/pthread_stubs.h b/Include/cpython/pthread_stubs.h new file mode 100644 index 0000000000000000000000000000000000000000..d95ee03d8308ce47a63c8f424bd71b0316b7f889 --- /dev/null +++ b/Include/cpython/pthread_stubs.h @@ -0,0 +1,88 @@ +#ifndef Py_CPYTHON_PTRHEAD_STUBS_H +#define Py_CPYTHON_PTRHEAD_STUBS_H + +#if !defined(HAVE_PTHREAD_STUBS) +# error "this header file requires stubbed pthreads." +#endif + +#ifndef _POSIX_THREADS +# define _POSIX_THREADS 1 +#endif + +/* Minimal pthread stubs for CPython. + * + * The stubs implement the minimum pthread API for CPython. + * - pthread_create() fails. + * - pthread_exit() calls exit(0). + * - pthread_key_*() functions implement minimal TSS without destructor. + * - all other functions do nothing and return 0. + */ + +#ifdef __wasi__ +// WASI's bits/alltypes.h provides type definitions when __NEED_ is set. +// The header file can be included multiple times. +# define __NEED_pthread_cond_t 1 +# define __NEED_pthread_condattr_t 1 +# define __NEED_pthread_mutex_t 1 +# define __NEED_pthread_mutexattr_t 1 +# define __NEED_pthread_key_t 1 +# define __NEED_pthread_t 1 +# define __NEED_pthread_attr_t 1 +# include <bits/alltypes.h> +#else +typedef struct { void *__x; } pthread_cond_t; +typedef struct { unsigned __attr; } pthread_condattr_t; +typedef struct { void *__x; } pthread_mutex_t; +typedef struct { unsigned __attr; } pthread_mutexattr_t; +typedef unsigned pthread_key_t; +typedef unsigned pthread_t; +typedef struct { unsigned __attr; } pthread_attr_t; +#endif + +// mutex +PyAPI_FUNC(int) pthread_mutex_init(pthread_mutex_t *restrict mutex, + const pthread_mutexattr_t *restrict attr); +PyAPI_FUNC(int) pthread_mutex_destroy(pthread_mutex_t *mutex); +PyAPI_FUNC(int) pthread_mutex_trylock(pthread_mutex_t *mutex); +PyAPI_FUNC(int) pthread_mutex_lock(pthread_mutex_t *mutex); +PyAPI_FUNC(int) pthread_mutex_unlock(pthread_mutex_t *mutex); + +// condition +PyAPI_FUNC(int) pthread_cond_init(pthread_cond_t *restrict cond, + const pthread_condattr_t *restrict attr); +PyAPI_FUNC(int) pthread_cond_destroy(pthread_cond_t *cond); +PyAPI_FUNC(int) pthread_cond_wait(pthread_cond_t *restrict cond, + pthread_mutex_t *restrict mutex); +PyAPI_FUNC(int) pthread_cond_timedwait(pthread_cond_t *restrict cond, + pthread_mutex_t *restrict mutex, + const struct timespec *restrict abstime); +PyAPI_FUNC(int) pthread_cond_signal(pthread_cond_t *cond); +PyAPI_FUNC(int) pthread_condattr_init(pthread_condattr_t *attr); +PyAPI_FUNC(int) pthread_condattr_setclock( + pthread_condattr_t *attr, clockid_t clock_id); + +// pthread +PyAPI_FUNC(int) pthread_create(pthread_t *restrict thread, + const pthread_attr_t *restrict attr, + void *(*start_routine)(void *), + void *restrict arg); +PyAPI_FUNC(int) pthread_detach(pthread_t thread); +PyAPI_FUNC(pthread_t) pthread_self(void); +PyAPI_FUNC(int) pthread_exit(void *retval) __attribute__ ((__noreturn__)); +PyAPI_FUNC(int) pthread_attr_init(pthread_attr_t *attr); +PyAPI_FUNC(int) pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); +PyAPI_FUNC(int) pthread_attr_destroy(pthread_attr_t *attr); + + +// pthread_key +#ifndef PTHREAD_KEYS_MAX +# define PTHREAD_KEYS_MAX 128 +#endif + +PyAPI_FUNC(int) pthread_key_create(pthread_key_t *key, + void (*destr_function)(void *)); +PyAPI_FUNC(int) pthread_key_delete(pthread_key_t key); +PyAPI_FUNC(void *) pthread_getspecific(pthread_key_t key); +PyAPI_FUNC(int) pthread_setspecific(pthread_key_t key, const void *value); + +#endif // Py_CPYTHON_PTRHEAD_STUBS_H diff --git a/Include/cpython/pythread.h b/Include/cpython/pythread.h index 1fd86a6a90f9af65d0263f8ee511020b1f425e7a..ce4ec8f65b15ea016a86c6e2452560e3b6ecb47b 100644 --- a/Include/cpython/pythread.h +++ b/Include/cpython/pythread.h @@ -20,6 +20,9 @@ PyAPI_FUNC(int) _PyThread_at_fork_reinit(PyThread_type_lock *lock); but hardcode the unsigned long to avoid errors for include directive. */ # define NATIVE_TSS_KEY_T unsigned long +#elif defined(HAVE_PTHREAD_STUBS) +# include "cpython/pthread_stubs.h" +# define NATIVE_TSS_KEY_T pthread_key_t #else # error "Require native threads. See https://bugs.python.org/issue31370" #endif diff --git a/Include/internal/pycore_accu.h b/Include/internal/pycore_accu.h deleted file mode 100644 index d346222e4dd0c9789f01ca1b97c96124bc01abae..0000000000000000000000000000000000000000 --- a/Include/internal/pycore_accu.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef Py_LIMITED_API -#ifndef Py_INTERNAL_ACCU_H -#define Py_INTERNAL_ACCU_H -#ifdef __cplusplus -extern "C" { -#endif - -/*** This is a private API for use by the interpreter and the stdlib. - *** Its definition may be changed or removed at any moment. - ***/ - -#ifndef Py_BUILD_CORE -# error "this header requires Py_BUILD_CORE define" -#endif - -/* - * A two-level accumulator of unicode objects that avoids both the overhead - * of keeping a huge number of small separate objects, and the quadratic - * behaviour of using a naive repeated concatenation scheme. - */ - -#undef small /* defined by some Windows headers */ - -typedef struct { - PyObject *large; /* A list of previously accumulated large strings */ - PyObject *small; /* Pending small strings */ -} _PyAccu; - -PyAPI_FUNC(int) _PyAccu_Init(_PyAccu *acc); -PyAPI_FUNC(int) _PyAccu_Accumulate(_PyAccu *acc, PyObject *unicode); -PyAPI_FUNC(PyObject *) _PyAccu_FinishAsList(_PyAccu *acc); -PyAPI_FUNC(PyObject *) _PyAccu_Finish(_PyAccu *acc); -PyAPI_FUNC(void) _PyAccu_Destroy(_PyAccu *acc); - -#ifdef __cplusplus -} -#endif -#endif /* !Py_INTERNAL_ACCU_H */ -#endif /* !Py_LIMITED_API */ diff --git a/Include/internal/pycore_ast_state.h b/Include/internal/pycore_ast_state.h index da78bba3b69bdfb9011a58f9ca1a8654d7842ec0..f15b4905eed14b626b6aae9d0d34a81fd64c64e8 100644 --- a/Include/internal/pycore_ast_state.h +++ b/Include/internal/pycore_ast_state.h @@ -12,6 +12,8 @@ extern "C" { struct ast_state { int initialized; + int recursion_depth; + int recursion_limit; PyObject *AST_type; PyObject *Add_singleton; PyObject *Add_type; diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index c975f1cb74f3d7d68d31843046f917cf32f31c6d..61e40eb8a94c2483faf9d47047e13ae3c6bac878 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -390,6 +390,19 @@ read_obj(uint16_t *p) return (PyObject *)val; } +/* See Objects/exception_handling_notes.txt for details. + */ +static inline unsigned char * +parse_varint(unsigned char *p, int *result) { + int val = p[0] & 63; + while (p[0] & 64) { + p++; + val = (val << 6) | (p[0] & 63); + } + *result = val; + return p+1; +} + static inline int write_varint(uint8_t *ptr, unsigned int val) { diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 6ce2945cd9fb7b7eff48afca0474a4d8f8a460bb..d71386953a0dd0ade83880c174cd84689cb64cbc 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -173,7 +173,7 @@ struct _is { struct _Py_exc_state exc_state; struct ast_state ast; - struct type_cache type_cache; + struct types_state types; struct callable_cache callable_cache; /* The following fields are here to avoid allocation during init. diff --git a/Include/internal/pycore_list.h b/Include/internal/pycore_list.h index 7721f6c2e222a028c11c975ddaf516b7f258a545..691d13bc8d9ffab36646714f489e9a40a4100149 100644 --- a/Include/internal/pycore_list.h +++ b/Include/internal/pycore_list.h @@ -56,6 +56,19 @@ _PyList_AppendTakeRef(PyListObject *self, PyObject *newitem) return _PyList_AppendTakeRefListResize(self, newitem); } +// Repeat the bytes of a buffer in place +static inline void +_Py_memory_repeat(char* dest, Py_ssize_t len_dest, Py_ssize_t len_src) +{ + assert(len_src > 0); + Py_ssize_t copied = len_src; + while (copied < len_dest) { + Py_ssize_t bytes_to_copy = Py_MIN(copied, len_dest - copied); + memcpy(dest + copied, dest, bytes_to_copy); + copied += bytes_to_copy; + } +} + typedef struct { PyObject_HEAD Py_ssize_t it_index; diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index d4f66b65cc9ff29084f31dc107091b1b50e5acca..9f061d8b08772c84c8719273e488fad7629b7cae 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -14,9 +14,14 @@ extern "C" { #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_runtime.h" // _PyRuntime +/* This value provides *effective* immortality, meaning the object should never + be deallocated (until runtime finalization). See PEP 683 for more details about + immortality, as well as a proposed mechanism for proper immortality. */ +#define _PyObject_IMMORTAL_REFCNT 999999999 + #define _PyObject_IMMORTAL_INIT(type) \ { \ - .ob_refcnt = 999999999, \ + .ob_refcnt = _PyObject_IMMORTAL_REFCNT, \ .ob_type = (type), \ } #define _PyVarObject_IMMORTAL_INIT(type, size) \ @@ -32,6 +37,16 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc( #define _Py_FatalRefcountError(message) \ _Py_FatalRefcountErrorFunc(__func__, (message)) +// Increment reference count by n +static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n) +{ +#ifdef Py_REF_DEBUG + _Py_RefTotal += n; +#endif + op->ob_refcnt += n; +} +#define _Py_RefcntAdd(op, n) _Py_RefcntAdd(_PyObject_CAST(op), n) + static inline void _Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct) { @@ -205,6 +220,12 @@ extern void _Py_PrintReferenceAddresses(FILE *); static inline PyObject ** _PyObject_GET_WEAKREFS_LISTPTR(PyObject *op) { + if (PyType_Check(op) && + ((PyTypeObject *)op)->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) { + static_builtin_state *state = _PyStaticType_GetState( + (PyTypeObject *)op); + return _PyStaticType_GET_WEAKREFS_LISTPTR(state); + } Py_ssize_t offset = Py_TYPE(op)->tp_weaklistoffset; return (PyObject **)((char *)op + offset); } diff --git a/Include/internal/pycore_opcode.h b/Include/internal/pycore_opcode.h index 3ca678d3dd85b83fbec65e0c8330e5ce86c27fb9..90bf5bbd1baa02e4a785ac4c4fbe72e8b9a4ef10 100644 --- a/Include/internal/pycore_opcode.h +++ b/Include/internal/pycore_opcode.h @@ -16,8 +16,6 @@ extern const uint8_t _PyOpcode_Caches[256]; extern const uint8_t _PyOpcode_Deopt[256]; -extern const uint8_t _PyOpcode_Original[256]; - #ifdef NEED_OPCODE_TABLES static const uint32_t _PyOpcode_RelativeJump[9] = { 0U, @@ -240,192 +238,6 @@ const uint8_t _PyOpcode_Deopt[256] = { [WITH_EXCEPT_START] = WITH_EXCEPT_START, [YIELD_VALUE] = YIELD_VALUE, }; - -const uint8_t _PyOpcode_Original[256] = { - [ASYNC_GEN_WRAP] = ASYNC_GEN_WRAP, - [BEFORE_ASYNC_WITH] = BEFORE_ASYNC_WITH, - [BEFORE_WITH] = BEFORE_WITH, - [BINARY_OP] = BINARY_OP, - [BINARY_OP_ADAPTIVE] = BINARY_OP, - [BINARY_OP_ADD_FLOAT] = BINARY_OP, - [BINARY_OP_ADD_INT] = BINARY_OP, - [BINARY_OP_ADD_UNICODE] = BINARY_OP, - [BINARY_OP_INPLACE_ADD_UNICODE] = BINARY_OP, - [BINARY_OP_MULTIPLY_FLOAT] = BINARY_OP, - [BINARY_OP_MULTIPLY_INT] = BINARY_OP, - [BINARY_OP_SUBTRACT_FLOAT] = BINARY_OP, - [BINARY_OP_SUBTRACT_INT] = BINARY_OP, - [BINARY_SLICE] = BINARY_SLICE, - [BINARY_SUBSCR] = BINARY_SUBSCR, - [BINARY_SUBSCR_ADAPTIVE] = BINARY_SUBSCR, - [BINARY_SUBSCR_DICT] = BINARY_SUBSCR, - [BINARY_SUBSCR_GETITEM] = BINARY_SUBSCR, - [BINARY_SUBSCR_LIST_INT] = BINARY_SUBSCR, - [BINARY_SUBSCR_TUPLE_INT] = BINARY_SUBSCR, - [BUILD_CONST_KEY_MAP] = BUILD_CONST_KEY_MAP, - [BUILD_LIST] = BUILD_LIST, - [BUILD_MAP] = BUILD_MAP, - [BUILD_SET] = BUILD_SET, - [BUILD_SLICE] = BUILD_SLICE, - [BUILD_STRING] = BUILD_STRING, - [BUILD_TUPLE] = BUILD_TUPLE, - [CACHE] = CACHE, - [CALL] = CALL, - [CALL_ADAPTIVE] = CALL, - [CALL_BOUND_METHOD_EXACT_ARGS] = CALL, - [CALL_BUILTIN_CLASS] = CALL, - [CALL_BUILTIN_FAST_WITH_KEYWORDS] = CALL, - [CALL_FUNCTION_EX] = CALL_FUNCTION_EX, - [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = CALL, - [CALL_NO_KW_BUILTIN_FAST] = CALL, - [CALL_NO_KW_BUILTIN_O] = CALL, - [CALL_NO_KW_ISINSTANCE] = CALL, - [CALL_NO_KW_LEN] = CALL, - [CALL_NO_KW_LIST_APPEND] = CALL, - [CALL_NO_KW_METHOD_DESCRIPTOR_FAST] = CALL, - [CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = CALL, - [CALL_NO_KW_METHOD_DESCRIPTOR_O] = CALL, - [CALL_NO_KW_STR_1] = CALL, - [CALL_NO_KW_TUPLE_1] = CALL, - [CALL_NO_KW_TYPE_1] = CALL, - [CALL_PY_EXACT_ARGS] = CALL, - [CALL_PY_WITH_DEFAULTS] = CALL, - [CHECK_EG_MATCH] = CHECK_EG_MATCH, - [CHECK_EXC_MATCH] = CHECK_EXC_MATCH, - [COMPARE_OP] = COMPARE_OP, - [COMPARE_OP_ADAPTIVE] = COMPARE_OP, - [COMPARE_OP_FLOAT_JUMP] = COMPARE_OP, - [COMPARE_OP_INT_JUMP] = COMPARE_OP, - [COMPARE_OP_STR_JUMP] = COMPARE_OP, - [CONTAINS_OP] = CONTAINS_OP, - [COPY] = COPY, - [COPY_FREE_VARS] = COPY_FREE_VARS, - [DELETE_ATTR] = DELETE_ATTR, - [DELETE_DEREF] = DELETE_DEREF, - [DELETE_FAST] = DELETE_FAST, - [DELETE_GLOBAL] = DELETE_GLOBAL, - [DELETE_NAME] = DELETE_NAME, - [DELETE_SUBSCR] = DELETE_SUBSCR, - [DICT_MERGE] = DICT_MERGE, - [DICT_UPDATE] = DICT_UPDATE, - [END_ASYNC_FOR] = END_ASYNC_FOR, - [EXTENDED_ARG] = EXTENDED_ARG_QUICK, - [EXTENDED_ARG_QUICK] = EXTENDED_ARG_QUICK, - [FORMAT_VALUE] = FORMAT_VALUE, - [FOR_ITER] = FOR_ITER, - [FOR_ITER_ADAPTIVE] = FOR_ITER, - [FOR_ITER_LIST] = FOR_ITER, - [FOR_ITER_RANGE] = FOR_ITER, - [GET_AITER] = GET_AITER, - [GET_ANEXT] = GET_ANEXT, - [GET_AWAITABLE] = GET_AWAITABLE, - [GET_ITER] = GET_ITER, - [GET_LEN] = GET_LEN, - [GET_YIELD_FROM_ITER] = GET_YIELD_FROM_ITER, - [IMPORT_FROM] = IMPORT_FROM, - [IMPORT_NAME] = IMPORT_NAME, - [IMPORT_STAR] = IMPORT_STAR, - [IS_OP] = IS_OP, - [JUMP_BACKWARD] = JUMP_BACKWARD, - [JUMP_BACKWARD_NO_INTERRUPT] = JUMP_BACKWARD_NO_INTERRUPT, - [JUMP_BACKWARD_QUICK] = JUMP_BACKWARD, - [JUMP_FORWARD] = JUMP_FORWARD, - [JUMP_IF_FALSE_OR_POP] = JUMP_IF_FALSE_OR_POP, - [JUMP_IF_TRUE_OR_POP] = JUMP_IF_TRUE_OR_POP, - [KW_NAMES] = KW_NAMES, - [LIST_APPEND] = LIST_APPEND, - [LIST_EXTEND] = LIST_EXTEND, - [LIST_TO_TUPLE] = LIST_TO_TUPLE, - [LOAD_ASSERTION_ERROR] = LOAD_ASSERTION_ERROR, - [LOAD_ATTR] = LOAD_ATTR, - [LOAD_ATTR_ADAPTIVE] = LOAD_ATTR, - [LOAD_ATTR_CLASS] = LOAD_ATTR, - [LOAD_ATTR_INSTANCE_VALUE] = LOAD_ATTR, - [LOAD_ATTR_METHOD_LAZY_DICT] = LOAD_ATTR, - [LOAD_ATTR_METHOD_NO_DICT] = LOAD_ATTR, - [LOAD_ATTR_METHOD_WITH_DICT] = LOAD_ATTR, - [LOAD_ATTR_METHOD_WITH_VALUES] = LOAD_ATTR, - [LOAD_ATTR_MODULE] = LOAD_ATTR, - [LOAD_ATTR_PROPERTY] = LOAD_ATTR, - [LOAD_ATTR_SLOT] = LOAD_ATTR, - [LOAD_ATTR_WITH_HINT] = LOAD_ATTR, - [LOAD_BUILD_CLASS] = LOAD_BUILD_CLASS, - [LOAD_CLASSDEREF] = LOAD_CLASSDEREF, - [LOAD_CLOSURE] = LOAD_CLOSURE, - [LOAD_CONST] = LOAD_CONST, - [LOAD_CONST__LOAD_FAST] = LOAD_CONST, - [LOAD_DEREF] = LOAD_DEREF, - [LOAD_FAST] = LOAD_FAST, - [LOAD_FAST_CHECK] = LOAD_FAST_CHECK, - [LOAD_FAST__LOAD_CONST] = LOAD_FAST, - [LOAD_FAST__LOAD_FAST] = LOAD_FAST, - [LOAD_GLOBAL] = LOAD_GLOBAL, - [LOAD_GLOBAL_ADAPTIVE] = LOAD_GLOBAL, - [LOAD_GLOBAL_BUILTIN] = LOAD_GLOBAL, - [LOAD_GLOBAL_MODULE] = LOAD_GLOBAL, - [LOAD_NAME] = LOAD_NAME, - [MAKE_CELL] = MAKE_CELL, - [MAKE_FUNCTION] = MAKE_FUNCTION, - [MAP_ADD] = MAP_ADD, - [MATCH_CLASS] = MATCH_CLASS, - [MATCH_KEYS] = MATCH_KEYS, - [MATCH_MAPPING] = MATCH_MAPPING, - [MATCH_SEQUENCE] = MATCH_SEQUENCE, - [NOP] = NOP, - [POP_EXCEPT] = POP_EXCEPT, - [POP_JUMP_BACKWARD_IF_FALSE] = POP_JUMP_BACKWARD_IF_FALSE, - [POP_JUMP_BACKWARD_IF_NONE] = POP_JUMP_BACKWARD_IF_NONE, - [POP_JUMP_BACKWARD_IF_NOT_NONE] = POP_JUMP_BACKWARD_IF_NOT_NONE, - [POP_JUMP_BACKWARD_IF_TRUE] = POP_JUMP_BACKWARD_IF_TRUE, - [POP_JUMP_FORWARD_IF_FALSE] = POP_JUMP_FORWARD_IF_FALSE, - [POP_JUMP_FORWARD_IF_NONE] = POP_JUMP_FORWARD_IF_NONE, - [POP_JUMP_FORWARD_IF_NOT_NONE] = POP_JUMP_FORWARD_IF_NOT_NONE, - [POP_JUMP_FORWARD_IF_TRUE] = POP_JUMP_FORWARD_IF_TRUE, - [POP_TOP] = POP_TOP, - [PREP_RERAISE_STAR] = PREP_RERAISE_STAR, - [PRINT_EXPR] = PRINT_EXPR, - [PUSH_EXC_INFO] = PUSH_EXC_INFO, - [PUSH_NULL] = PUSH_NULL, - [RAISE_VARARGS] = RAISE_VARARGS, - [RERAISE] = RERAISE, - [RESUME] = RESUME, - [RESUME_QUICK] = RESUME, - [RETURN_GENERATOR] = RETURN_GENERATOR, - [RETURN_VALUE] = RETURN_VALUE, - [SEND] = SEND, - [SETUP_ANNOTATIONS] = SETUP_ANNOTATIONS, - [SET_ADD] = SET_ADD, - [SET_UPDATE] = SET_UPDATE, - [STORE_ATTR] = STORE_ATTR, - [STORE_ATTR_ADAPTIVE] = STORE_ATTR, - [STORE_ATTR_INSTANCE_VALUE] = STORE_ATTR, - [STORE_ATTR_SLOT] = STORE_ATTR, - [STORE_ATTR_WITH_HINT] = STORE_ATTR, - [STORE_DEREF] = STORE_DEREF, - [STORE_FAST] = STORE_FAST, - [STORE_FAST__LOAD_FAST] = STORE_FAST, - [STORE_FAST__STORE_FAST] = STORE_FAST, - [STORE_GLOBAL] = STORE_GLOBAL, - [STORE_NAME] = STORE_NAME, - [STORE_SLICE] = STORE_SLICE, - [STORE_SUBSCR] = STORE_SUBSCR, - [STORE_SUBSCR_ADAPTIVE] = STORE_SUBSCR, - [STORE_SUBSCR_DICT] = STORE_SUBSCR, - [STORE_SUBSCR_LIST_INT] = STORE_SUBSCR, - [SWAP] = SWAP, - [UNARY_INVERT] = UNARY_INVERT, - [UNARY_NEGATIVE] = UNARY_NEGATIVE, - [UNARY_NOT] = UNARY_NOT, - [UNARY_POSITIVE] = UNARY_POSITIVE, - [UNPACK_EX] = UNPACK_EX, - [UNPACK_SEQUENCE] = UNPACK_SEQUENCE, - [UNPACK_SEQUENCE_ADAPTIVE] = UNPACK_SEQUENCE, - [UNPACK_SEQUENCE_LIST] = UNPACK_SEQUENCE, - [UNPACK_SEQUENCE_TUPLE] = UNPACK_SEQUENCE, - [UNPACK_SEQUENCE_TWO_TUPLE] = UNPACK_SEQUENCE, - [WITH_EXCEPT_START] = WITH_EXCEPT_START, - [YIELD_VALUE] = YIELD_VALUE, -}; #endif // NEED_OPCODE_TABLES #ifdef Py_DEBUG diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index b4a39b62b76a1d1f15c32ab2a36b0ea8b2eafade..51d119c23e731ba2db98fc3b7bd98fa690b8ab51 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -131,8 +131,9 @@ PyAPI_FUNC(void) _PyThreadState_DeleteExcept( static inline void _PyThreadState_UpdateTracingState(PyThreadState *tstate) { - int use_tracing = (tstate->c_tracefunc != NULL - || tstate->c_profilefunc != NULL); + bool use_tracing = + (tstate->tracing == 0) && + (tstate->c_tracefunc != NULL || tstate->c_profilefunc != NULL); tstate->cframe->use_tracing = (use_tracing ? 255 : 0); } diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index ddaab07727b81ebed8ff46e6561917bbf397978f..9fe7c31dcb449879d9d773dec608c4caac1b6cc6 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -1740,6 +1740,4408 @@ _PyUnicode_InitStaticStrings(void) { string = &_Py_ID(write); PyUnicode_InternInPlace(&string); } + +#ifdef Py_DEBUG +static inline void +_PyStaticObjects_CheckRefcnt(void) { + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + -5]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + -5]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + -4]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + -4]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + -3]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + -3]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + -2]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + -2]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + -1]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + -1]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 0]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 0]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 1]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 1]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 2]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 2]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 3]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 3]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 4]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 4]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 5]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 5]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 6]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 6]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 7]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 7]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 8]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 8]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 9]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 9]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 10]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 10]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 11]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 11]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 12]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 12]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 13]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 13]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 14]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 14]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 15]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 15]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 16]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 16]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 17]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 17]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 18]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 18]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 19]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 19]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 20]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 20]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 21]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 21]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 22]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 22]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 23]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 23]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 24]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 24]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 25]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 25]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 26]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 26]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 27]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 27]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 28]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 28]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 29]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 29]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 30]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 30]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 31]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 31]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 32]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 32]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 33]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 33]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 34]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 34]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 35]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 35]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 36]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 36]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 37]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 37]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 38]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 38]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 39]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 39]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 40]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 40]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 41]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 41]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 42]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 42]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 43]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 43]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 44]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 44]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 45]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 45]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 46]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 46]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 47]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 47]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 48]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 48]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 49]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 49]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 50]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 50]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 51]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 51]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 52]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 52]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 53]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 53]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 54]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 54]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 55]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 55]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 56]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 56]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 57]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 57]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 58]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 58]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 59]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 59]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 60]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 60]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 61]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 61]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 62]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 62]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 63]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 63]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 64]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 64]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 65]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 65]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 66]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 66]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 67]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 67]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 68]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 68]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 69]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 69]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 70]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 70]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 71]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 71]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 72]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 72]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 73]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 73]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 74]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 74]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 75]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 75]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 76]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 76]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 77]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 77]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 78]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 78]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 79]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 79]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 80]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 80]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 81]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 81]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 82]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 82]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 83]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 83]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 84]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 84]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 85]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 85]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 86]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 86]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 87]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 87]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 88]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 88]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 89]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 89]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 90]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 90]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 91]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 91]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 92]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 92]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 93]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 93]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 94]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 94]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 95]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 95]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 96]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 96]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 97]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 97]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 98]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 98]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 99]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 99]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 100]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 100]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 101]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 101]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 102]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 102]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 103]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 103]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 104]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 104]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 105]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 105]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 106]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 106]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 107]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 107]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 108]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 108]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 109]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 109]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 110]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 110]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 111]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 111]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 112]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 112]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 113]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 113]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 114]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 114]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 115]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 115]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 116]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 116]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 117]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 117]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 118]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 118]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 119]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 119]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 120]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 120]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 121]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 121]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 122]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 122]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 123]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 123]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 124]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 124]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 125]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 125]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 126]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 126]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 127]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 127]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 129]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 129]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 130]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 130]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 131]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 131]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 132]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 132]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 133]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 133]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 134]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 134]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 135]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 135]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 136]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 136]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 137]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 137]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 138]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 138]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 139]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 139]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 140]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 140]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 141]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 141]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 142]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 142]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 143]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 143]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 144]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 144]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 145]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 145]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 146]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 146]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 147]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 147]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 148]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 148]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 149]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 149]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 150]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 150]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 151]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 151]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 152]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 152]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 153]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 153]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 154]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 154]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 155]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 155]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 156]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 156]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 157]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 157]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 158]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 158]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 159]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 159]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 160]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 160]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 161]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 161]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 162]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 162]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 163]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 163]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 164]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 164]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 165]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 165]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 166]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 166]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 167]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 167]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 168]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 168]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 169]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 169]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 170]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 170]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 171]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 171]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 172]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 172]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 173]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 173]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 174]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 174]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 175]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 175]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 176]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 176]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 177]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 177]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 178]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 178]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 179]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 179]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 180]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 180]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 181]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 181]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 182]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 182]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 183]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 183]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 184]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 184]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 185]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 185]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 186]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 186]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 187]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 187]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 188]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 188]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 189]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 189]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 190]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 190]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 191]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 191]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 192]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 192]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 193]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 193]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 194]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 194]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 195]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 195]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 196]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 196]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 197]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 197]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 198]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 198]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 199]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 199]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 200]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 200]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 201]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 201]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 202]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 202]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 203]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 203]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 204]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 204]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 205]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 205]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 206]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 206]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 207]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 207]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 208]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 208]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 209]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 209]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 210]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 210]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 211]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 211]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 212]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 212]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 213]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 213]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 214]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 214]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 215]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 215]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 216]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 216]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 217]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 217]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 218]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 218]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 219]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 219]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 220]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 220]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 221]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 221]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 222]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 222]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 223]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 223]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 224]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 224]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 225]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 225]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 226]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 226]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 227]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 227]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 228]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 228]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 229]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 229]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 230]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 230]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 231]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 231]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 232]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 232]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 233]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 233]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 234]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 234]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 235]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 235]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 236]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 236]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 237]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 237]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 238]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 238]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 239]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 239]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 240]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 240]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 241]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 241]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 242]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 242]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 243]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 243]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 244]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 244]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 245]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 245]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 246]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 246]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 247]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 247]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 248]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 248]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 249]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 249]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 250]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 250]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 251]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 251]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 252]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 252]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 253]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 253]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 254]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 254]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 255]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 255]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 256]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + 256]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_empty)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_empty)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[0]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[0]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[1]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[1]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[2]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[2]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[3]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[3]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[4]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[4]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[5]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[5]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[6]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[6]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[7]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[7]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[8]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[8]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[9]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[9]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[10]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[10]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[11]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[11]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[12]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[12]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[13]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[13]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[14]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[14]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[15]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[15]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[16]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[16]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[17]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[17]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[18]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[18]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[19]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[19]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[20]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[20]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[21]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[21]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[22]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[22]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[23]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[23]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[24]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[24]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[25]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[25]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[26]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[26]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[27]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[27]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[28]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[28]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[29]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[29]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[30]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[30]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[31]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[31]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[32]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[32]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[33]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[33]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[34]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[34]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[35]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[35]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[36]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[36]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[37]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[37]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[38]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[38]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[39]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[39]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[40]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[40]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[41]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[41]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[42]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[42]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[43]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[43]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[44]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[44]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[45]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[45]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[46]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[46]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[47]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[47]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[48]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[48]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[49]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[49]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[50]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[50]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[51]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[51]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[52]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[52]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[53]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[53]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[54]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[54]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[55]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[55]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[56]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[56]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[57]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[57]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[58]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[58]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[59]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[59]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[60]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[60]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[61]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[61]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[62]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[62]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[63]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[63]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[64]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[64]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[65]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[65]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[66]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[66]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[67]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[67]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[68]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[68]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[69]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[69]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[70]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[70]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[71]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[71]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[72]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[72]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[73]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[73]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[74]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[74]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[75]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[75]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[76]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[76]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[77]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[77]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[78]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[78]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[79]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[79]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[80]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[80]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[81]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[81]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[82]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[82]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[83]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[83]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[84]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[84]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[85]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[85]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[86]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[86]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[87]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[87]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[88]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[88]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[89]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[89]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[90]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[90]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[91]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[91]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[92]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[92]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[93]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[93]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[94]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[94]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[95]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[95]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[96]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[96]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[97]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[97]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[98]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[98]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[99]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[99]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[100]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[100]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[101]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[101]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[102]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[102]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[103]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[103]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[104]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[104]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[105]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[105]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[106]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[106]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[107]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[107]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[108]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[108]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[109]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[109]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[110]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[110]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[111]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[111]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[112]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[112]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[113]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[113]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[114]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[114]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[115]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[115]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[116]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[116]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[117]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[117]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[118]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[118]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[119]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[119]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[120]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[120]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[121]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[121]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[122]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[122]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[123]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[123]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[124]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[124]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[125]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[125]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[126]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[126]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[127]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[127]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[129]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[129]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[130]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[130]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[131]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[131]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[132]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[132]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[133]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[133]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[134]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[134]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[135]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[135]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[136]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[136]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[137]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[137]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[138]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[138]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[139]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[139]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[140]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[140]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[141]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[141]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[142]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[142]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[143]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[143]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[144]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[144]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[145]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[145]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[146]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[146]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[147]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[147]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[148]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[148]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[149]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[149]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[150]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[150]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[151]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[151]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[152]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[152]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[153]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[153]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[154]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[154]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[155]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[155]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[156]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[156]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[157]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[157]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[158]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[158]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[159]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[159]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[160]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[160]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[161]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[161]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[162]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[162]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[163]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[163]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[164]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[164]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[165]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[165]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[166]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[166]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[167]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[167]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[168]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[168]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[169]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[169]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[170]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[170]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[171]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[171]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[172]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[172]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[173]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[173]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[174]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[174]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[175]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[175]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[176]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[176]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[177]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[177]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[178]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[178]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[179]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[179]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[180]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[180]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[181]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[181]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[182]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[182]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[183]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[183]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[184]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[184]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[185]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[185]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[186]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[186]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[187]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[187]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[188]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[188]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[189]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[189]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[190]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[190]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[191]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[191]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[192]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[192]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[193]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[193]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[194]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[194]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[195]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[195]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[196]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[196]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[197]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[197]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[198]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[198]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[199]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[199]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[200]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[200]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[201]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[201]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[202]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[202]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[203]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[203]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[204]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[204]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[205]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[205]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[206]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[206]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[207]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[207]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[208]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[208]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[209]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[209]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[210]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[210]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[211]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[211]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[212]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[212]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[213]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[213]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[214]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[214]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[215]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[215]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[216]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[216]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[217]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[217]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[218]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[218]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[219]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[219]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[220]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[220]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[221]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[221]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[222]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[222]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[223]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[223]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[224]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[224]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[225]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[225]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[226]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[226]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[227]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[227]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[228]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[228]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[229]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[229]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[230]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[230]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[231]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[231]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[232]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[232]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[233]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[233]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[234]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[234]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[235]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[235]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[236]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[236]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[237]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[237]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[238]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[238]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[239]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[239]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[240]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[240]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[241]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[241]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[242]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[242]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[243]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[243]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[244]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[244]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[245]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[245]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[246]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[246]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[247]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[247]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[248]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[248]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[249]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[249]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[250]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[250]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[251]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[251]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[252]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[252]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[253]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[253]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[254]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[254]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(bytes_characters)[255]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(bytes_characters)[255]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(anon_dictcomp)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(anon_dictcomp)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(anon_genexpr)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(anon_genexpr)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(anon_lambda)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(anon_lambda)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(anon_listcomp)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(anon_listcomp)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(anon_module)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(anon_module)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(anon_setcomp)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(anon_setcomp)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(anon_string)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(anon_string)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(anon_unknown)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(anon_unknown)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(close_br)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(close_br)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(comma_sep)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(comma_sep)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(dbl_close_br)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(dbl_close_br)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(dbl_open_br)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(dbl_open_br)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(dbl_percent)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(dbl_percent)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(dot)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(dot)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(dot_locals)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(dot_locals)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(empty)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(empty)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(list_err)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(list_err)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(newline)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(newline)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(open_br)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(open_br)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(percent)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(percent)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_STR(utf_8)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_STR(utf_8)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(False)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(False)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(Py_Repr)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(Py_Repr)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(TextIOWrapper)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(TextIOWrapper)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(True)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(True)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(WarningMessage)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(WarningMessage)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__IOBase_closed)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__IOBase_closed)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__abc_tpflags__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__abc_tpflags__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__abs__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__abs__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__abstractmethods__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__abstractmethods__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__add__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__add__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__aenter__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__aenter__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__aexit__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__aexit__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__aiter__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__aiter__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__all__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__all__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__and__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__and__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__anext__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__anext__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__annotations__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__annotations__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__args__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__args__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__await__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__await__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__bases__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__bases__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__bool__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__bool__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__build_class__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__build_class__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__builtins__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__builtins__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__bytes__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__bytes__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__call__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__call__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__cantrace__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__cantrace__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__class__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__class__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__class_getitem__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__class_getitem__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__classcell__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__classcell__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__complex__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__complex__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__contains__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__contains__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__copy__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__copy__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__del__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__del__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__delattr__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__delattr__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__delete__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__delete__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__delitem__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__delitem__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__dict__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__dict__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__dictoffset__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__dictoffset__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__dir__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__dir__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__divmod__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__divmod__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__doc__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__doc__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__enter__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__enter__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__eq__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__eq__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__exit__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__exit__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__file__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__file__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__float__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__float__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__floordiv__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__floordiv__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__format__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__format__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__fspath__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__fspath__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__ge__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__ge__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__get__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__get__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__getattr__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__getattr__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__getattribute__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__getattribute__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__getinitargs__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__getinitargs__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__getitem__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__getitem__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__getnewargs__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__getnewargs__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__getnewargs_ex__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__getnewargs_ex__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__getstate__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__getstate__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__gt__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__gt__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__hash__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__hash__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__iadd__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__iadd__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__iand__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__iand__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__ifloordiv__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__ifloordiv__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__ilshift__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__ilshift__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__imatmul__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__imatmul__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__imod__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__imod__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__import__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__import__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__imul__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__imul__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__index__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__index__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__init__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__init__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__init_subclass__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__init_subclass__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__instancecheck__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__instancecheck__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__int__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__int__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__invert__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__invert__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__ior__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__ior__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__ipow__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__ipow__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__irshift__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__irshift__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__isabstractmethod__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__isabstractmethod__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__isub__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__isub__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__iter__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__iter__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__itruediv__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__itruediv__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__ixor__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__ixor__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__le__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__le__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__len__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__len__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__length_hint__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__length_hint__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__lltrace__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__lltrace__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__loader__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__loader__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__lshift__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__lshift__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__lt__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__lt__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__main__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__main__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__matmul__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__matmul__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__missing__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__missing__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__mod__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__mod__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__module__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__module__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__mro_entries__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__mro_entries__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__mul__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__mul__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__name__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__name__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__ne__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__ne__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__neg__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__neg__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__new__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__new__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__newobj__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__newobj__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__newobj_ex__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__newobj_ex__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__next__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__next__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__notes__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__notes__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__or__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__or__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__orig_class__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__orig_class__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__origin__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__origin__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__package__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__package__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__parameters__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__parameters__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__path__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__path__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__pos__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__pos__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__pow__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__pow__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__prepare__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__prepare__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__qualname__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__qualname__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__radd__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__radd__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__rand__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__rand__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__rdivmod__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__rdivmod__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__reduce__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__reduce__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__reduce_ex__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__reduce_ex__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__repr__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__repr__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__reversed__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__reversed__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__rfloordiv__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__rfloordiv__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__rlshift__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__rlshift__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__rmatmul__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__rmatmul__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__rmod__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__rmod__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__rmul__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__rmul__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__ror__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__ror__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__round__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__round__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__rpow__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__rpow__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__rrshift__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__rrshift__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__rshift__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__rshift__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__rsub__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__rsub__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__rtruediv__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__rtruediv__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__rxor__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__rxor__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__set__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__set__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__set_name__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__set_name__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__setattr__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__setattr__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__setitem__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__setitem__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__setstate__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__setstate__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__sizeof__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__sizeof__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__slotnames__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__slotnames__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__slots__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__slots__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__spec__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__spec__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__str__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__str__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__sub__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__sub__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__subclasscheck__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__subclasscheck__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__subclasshook__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__subclasshook__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__truediv__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__truediv__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__trunc__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__trunc__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__typing_is_unpacked_typevartuple__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__typing_is_unpacked_typevartuple__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__typing_prepare_subst__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__typing_prepare_subst__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__typing_subst__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__typing_subst__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__typing_unpacked_tuple_args__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__typing_unpacked_tuple_args__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__warningregistry__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__warningregistry__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__weaklistoffset__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__weaklistoffset__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__weakref__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__weakref__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(__xor__)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(__xor__)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_abc_impl)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_abc_impl)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_annotation)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_annotation)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_blksize)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_blksize)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_bootstrap)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_bootstrap)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_dealloc_warn)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_dealloc_warn)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_finalizing)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_finalizing)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_find_and_load)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_find_and_load)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_fix_up_module)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_fix_up_module)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_get_sourcefile)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_get_sourcefile)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_handle_fromlist)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_handle_fromlist)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_initializing)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_initializing)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_is_text_encoding)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_is_text_encoding)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_lock_unlock_module)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_lock_unlock_module)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_showwarnmsg)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_showwarnmsg)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_shutdown)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_shutdown)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_slotnames)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_slotnames)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_uninitialized_submodules)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_uninitialized_submodules)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_warn_unawaited_coroutine)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_warn_unawaited_coroutine)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(_xoptions)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(_xoptions)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(add)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(add)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(append)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(append)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(big)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(big)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(buffer)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(buffer)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(builtins)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(builtins)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(c_call)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(c_call)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(c_exception)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(c_exception)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(c_return)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(c_return)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(call)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(call)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(clear)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(clear)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(close)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(close)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(closed)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(closed)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(code)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(code)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(copy)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(copy)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(copyreg)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(copyreg)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(decode)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(decode)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(default)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(default)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(defaultaction)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(defaultaction)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(dictcomp)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(dictcomp)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(difference_update)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(difference_update)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(dispatch_table)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(dispatch_table)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(displayhook)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(displayhook)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(encode)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(encode)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(encoding)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(encoding)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(end_lineno)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(end_lineno)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(end_offset)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(end_offset)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(errors)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(errors)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(excepthook)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(excepthook)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(exception)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(exception)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(extend)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(extend)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(filename)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(filename)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(fileno)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(fileno)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(fillvalue)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(fillvalue)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(filters)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(filters)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(find_class)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(find_class)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(flush)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(flush)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(genexpr)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(genexpr)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(get)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(get)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(get_source)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(get_source)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(getattr)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(getattr)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(getstate)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(getstate)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(ignore)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(ignore)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(importlib)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(importlib)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(inf)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(inf)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(intersection)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(intersection)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(isatty)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(isatty)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(isinstance)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(isinstance)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(items)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(items)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(iter)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(iter)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(join)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(join)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(keys)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(keys)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(lambda)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(lambda)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(last_traceback)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(last_traceback)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(last_type)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(last_type)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(last_value)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(last_value)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(latin1)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(latin1)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(len)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(len)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(line)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(line)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(lineno)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(lineno)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(listcomp)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(listcomp)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(little)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(little)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(locale)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(locale)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(match)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(match)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(metaclass)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(metaclass)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(mode)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(mode)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(modules)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(modules)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(mro)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(mro)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(msg)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(msg)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(n_fields)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(n_fields)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(n_sequence_fields)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(n_sequence_fields)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(n_unnamed_fields)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(n_unnamed_fields)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(name)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(name)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(newlines)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(newlines)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(next)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(next)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(obj)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(obj)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(offset)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(offset)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(onceregistry)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(onceregistry)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(opcode)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(opcode)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(open)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(open)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(parent)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(parent)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(path)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(path)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(peek)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(peek)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(persistent_id)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(persistent_id)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(persistent_load)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(persistent_load)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(print_file_and_line)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(print_file_and_line)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(ps1)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(ps1)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(ps2)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(ps2)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(raw)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(raw)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(read)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(read)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(read1)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(read1)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(readable)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(readable)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(readall)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(readall)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(readinto)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(readinto)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(readinto1)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(readinto1)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(readline)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(readline)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(reducer_override)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(reducer_override)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(reload)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(reload)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(replace)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(replace)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(reset)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(reset)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(return)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(return)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(reversed)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(reversed)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(seek)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(seek)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(seekable)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(seekable)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(send)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(send)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(setcomp)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(setcomp)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(setstate)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(setstate)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(sort)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(sort)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(stderr)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(stderr)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(stdin)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(stdin)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(stdout)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(stdout)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(strict)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(strict)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(symmetric_difference_update)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(symmetric_difference_update)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(tell)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(tell)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(text)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(text)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(threading)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(threading)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(throw)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(throw)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(top)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(top)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(truncate)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(truncate)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(unraisablehook)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(unraisablehook)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(values)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(values)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(version)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(version)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(warnings)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(warnings)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(warnoptions)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(warnoptions)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(writable)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(writable)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(write)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(write)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[0]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[0]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[1]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[1]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[2]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[2]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[3]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[3]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[4]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[4]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[5]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[5]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[6]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[6]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[7]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[7]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[8]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[8]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[9]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[9]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[10]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[10]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[11]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[11]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[12]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[12]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[13]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[13]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[14]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[14]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[15]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[15]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[16]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[16]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[17]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[17]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[18]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[18]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[19]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[19]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[20]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[20]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[21]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[21]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[22]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[22]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[23]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[23]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[24]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[24]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[25]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[25]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[26]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[26]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[27]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[27]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[28]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[28]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[29]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[29]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[30]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[30]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[31]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[31]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[32]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[32]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[33]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[33]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[34]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[34]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[35]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[35]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[36]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[36]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[37]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[37]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[38]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[38]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[39]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[39]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[40]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[40]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[41]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[41]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[42]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[42]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[43]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[43]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[44]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[44]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[45]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[45]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[46]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[46]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[47]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[47]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[48]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[48]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[49]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[49]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[50]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[50]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[51]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[51]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[52]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[52]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[53]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[53]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[54]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[54]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[55]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[55]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[56]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[56]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[57]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[57]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[58]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[58]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[59]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[59]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[60]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[60]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[61]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[61]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[62]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[62]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[63]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[63]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[64]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[64]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[65]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[65]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[66]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[66]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[67]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[67]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[68]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[68]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[69]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[69]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[70]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[70]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[71]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[71]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[72]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[72]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[73]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[73]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[74]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[74]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[75]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[75]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[76]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[76]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[77]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[77]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[78]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[78]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[79]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[79]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[80]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[80]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[81]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[81]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[82]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[82]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[83]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[83]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[84]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[84]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[85]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[85]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[86]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[86]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[87]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[87]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[88]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[88]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[89]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[89]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[90]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[90]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[91]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[91]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[92]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[92]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[93]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[93]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[94]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[94]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[95]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[95]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[96]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[96]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[97]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[97]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[98]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[98]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[99]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[99]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[100]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[100]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[101]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[101]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[102]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[102]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[103]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[103]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[104]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[104]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[105]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[105]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[106]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[106]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[107]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[107]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[108]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[108]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[109]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[109]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[110]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[110]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[111]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[111]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[112]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[112]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[113]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[113]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[114]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[114]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[115]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[115]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[116]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[116]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[117]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[117]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[118]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[118]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[119]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[119]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[120]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[120]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[121]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[121]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[122]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[122]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[123]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[123]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[124]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[124]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[125]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[125]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[126]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[126]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).ascii[127]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).ascii[127]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[128 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[128 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[129 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[129 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[130 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[130 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[131 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[131 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[132 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[132 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[133 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[133 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[134 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[134 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[135 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[135 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[136 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[136 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[137 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[137 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[138 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[138 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[139 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[139 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[140 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[140 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[141 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[141 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[142 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[142 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[143 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[143 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[144 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[144 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[145 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[145 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[146 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[146 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[147 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[147 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[148 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[148 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[149 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[149 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[150 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[150 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[151 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[151 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[152 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[152 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[153 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[153 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[154 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[154 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[155 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[155 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[156 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[156 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[157 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[157 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[158 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[158 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[159 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[159 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[160 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[160 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[161 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[161 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[162 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[162 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[163 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[163 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[164 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[164 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[165 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[165 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[166 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[166 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[167 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[167 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[168 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[168 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[169 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[169 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[170 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[170 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[171 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[171 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[172 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[172 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[173 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[173 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[174 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[174 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[175 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[175 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[176 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[176 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[177 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[177 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[178 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[178 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[179 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[179 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[180 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[180 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[181 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[181 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[182 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[182 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[183 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[183 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[184 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[184 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[185 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[185 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[186 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[186 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[187 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[187 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[188 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[188 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[189 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[189 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[190 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[190 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[191 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[191 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[192 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[192 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[193 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[193 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[194 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[194 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[195 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[195 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[196 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[196 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[197 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[197 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[198 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[198 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[199 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[199 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[200 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[200 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[201 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[201 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[202 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[202 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[203 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[203 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[204 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[204 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[205 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[205 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[206 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[206 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[207 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[207 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[208 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[208 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[209 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[209 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[210 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[210 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[211 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[211 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[212 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[212 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[213 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[213 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[214 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[214 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[215 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[215 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[216 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[216 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[217 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[217 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[218 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[218 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[219 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[219 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[220 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[220 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[221 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[221 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[222 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[222 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[223 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[223 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[224 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[224 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[225 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[225 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[226 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[226 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[227 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[227 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[228 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[228 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[229 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[229 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[230 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[230 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[231 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[231 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[232 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[232 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[233 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[233 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[234 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[234 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[235 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[235 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[236 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[236 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[237 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[237 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[238 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[238 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[239 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[239 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[240 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[240 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[241 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[241 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[242 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[242 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[243 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[243 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[244 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[244 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[245 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[245 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[246 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[246 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[247 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[247 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[248 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[248 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[249 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[249 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[250 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[250 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[251 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[251 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[252 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[252 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[253 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[253 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[254 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[254 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(strings).latin1[255 - 128]) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(strings).latin1[255 - 128]); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_SINGLETON(tuple_empty)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_SINGLETON(tuple_empty)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; +} +#endif /* End auto-generated code */ #ifdef __cplusplus } diff --git a/Include/internal/pycore_structseq.h b/Include/internal/pycore_structseq.h index 0199c790e24cecfcfbceac226e15c3b353c9b731..d10a921c55ff8bc5393e723086cde3c077146ad9 100644 --- a/Include/internal/pycore_structseq.h +++ b/Include/internal/pycore_structseq.h @@ -15,11 +15,18 @@ PyAPI_FUNC(PyTypeObject *) _PyStructSequence_NewType( PyStructSequence_Desc *desc, unsigned long tp_flags); -PyAPI_FUNC(int) _PyStructSequence_InitType( +PyAPI_FUNC(int) _PyStructSequence_InitBuiltinWithFlags( PyTypeObject *type, PyStructSequence_Desc *desc, unsigned long tp_flags); +static inline int +_PyStructSequence_InitBuiltin(PyTypeObject *type, + PyStructSequence_Desc *desc) +{ + return _PyStructSequence_InitBuiltinWithFlags(type, desc, 0); +} + extern void _PyStructSequence_FiniType(PyTypeObject *type); #ifdef __cplusplus diff --git a/Include/internal/pycore_typeobject.h b/Include/internal/pycore_typeobject.h index c480a3a57b436c958f7db7c2a0b1cb2acfa7cda7..4f9d6b1c4d4ba20cc320a629a571d42ddee9a55d 100644 --- a/Include/internal/pycore_typeobject.h +++ b/Include/internal/pycore_typeobject.h @@ -39,8 +39,38 @@ struct type_cache { #endif }; +/* For now we hard-code this to a value for which we are confident + all the static builtin types will fit (for all builds). */ +#define _Py_MAX_STATIC_BUILTIN_TYPES 200 + +typedef struct { + PyTypeObject *type; + /* We never clean up weakrefs for static builtin types since + they will effectively never get triggered. However, there + are also some diagnostic uses for the list of weakrefs, + so we still keep it. */ + PyObject *tp_weaklist; +} static_builtin_state; + +static inline PyObject ** +_PyStaticType_GET_WEAKREFS_LISTPTR(static_builtin_state *state) +{ + assert(state != NULL); + return &state->tp_weaklist; +} + +struct types_state { + struct type_cache type_cache; + size_t num_builtins_initialized; + static_builtin_state builtins[_Py_MAX_STATIC_BUILTIN_TYPES]; +}; + + extern PyStatus _PyTypes_InitSlotDefs(void); +extern int _PyStaticType_InitBuiltin(PyTypeObject *type); +extern static_builtin_state * _PyStaticType_GetState(PyTypeObject *); +extern void _PyStaticType_ClearWeakRefs(PyTypeObject *type); extern void _PyStaticType_Dealloc(PyTypeObject *type); diff --git a/Include/object.h b/Include/object.h index a12b754c8ed8f32024d60e69a69709cd45cbee97..c00b9eb583420a1ce0c96726c98c752529c82485 100644 --- a/Include/object.h +++ b/Include/object.h @@ -352,6 +352,9 @@ given type object has a specified feature. #ifndef Py_LIMITED_API +/* Track types initialized using _PyStaticType_InitBuiltin(). */ +#define _Py_TPFLAGS_STATIC_BUILTIN (1 << 1) + /* Placement of dict (and values) pointers are managed by the VM, not by the type. * The VM will automatically set tp_dictoffset. Should not be used for variable sized * classes, such as classes that extend tuple. diff --git a/Include/pyport.h b/Include/pyport.h index 313bc8d21c83fd352023fccd50e26c31faad3b1d..b3ff2f4882e90f61ac728f1db6bdaae25f4fee7d 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -14,62 +14,14 @@ #endif -// Macro to use C++ static_cast<>, reinterpret_cast<> and const_cast<> -// in the Python C API. -// -// In C++, _Py_CAST(type, expr) converts a constant expression to a -// non constant type using const_cast<type>. For example, -// _Py_CAST(PyObject*, op) can convert a "const PyObject*" to -// "PyObject*". -// -// The type argument must not be a constant type. +// Macro to use C++ static_cast<> in the Python C API. #ifdef __cplusplus -#include <cstddef> # define _Py_STATIC_CAST(type, expr) static_cast<type>(expr) -extern "C++" { - namespace { - template <typename type> - inline type _Py_CAST_impl(long int ptr) { - return reinterpret_cast<type>(ptr); - } - template <typename type> - inline type _Py_CAST_impl(int ptr) { - return reinterpret_cast<type>(ptr); - } -#if __cplusplus >= 201103 - template <typename type> - inline type _Py_CAST_impl(std::nullptr_t) { - return static_cast<type>(nullptr); - } -#endif - - template <typename type, typename expr_type> - inline type _Py_CAST_impl(expr_type *expr) { - return reinterpret_cast<type>(expr); - } - - template <typename type, typename expr_type> - inline type _Py_CAST_impl(expr_type const *expr) { - return reinterpret_cast<type>(const_cast<expr_type *>(expr)); - } - - template <typename type, typename expr_type> - inline type _Py_CAST_impl(expr_type &expr) { - return static_cast<type>(expr); - } - - template <typename type, typename expr_type> - inline type _Py_CAST_impl(expr_type const &expr) { - return static_cast<type>(const_cast<expr_type &>(expr)); - } - } -} -# define _Py_CAST(type, expr) _Py_CAST_impl<type>(expr) - #else # define _Py_STATIC_CAST(type, expr) ((type)(expr)) -# define _Py_CAST(type, expr) ((type)(expr)) #endif +// Macro to use the more powerful/dangerous C-style cast even in C++. +#define _Py_CAST(type, expr) ((type)(expr)) // Static inline functions should use _Py_NULL rather than using directly NULL // to prevent C++ compiler warnings. On C++11 and newer, _Py_NULL is defined as diff --git a/Lib/_bootsubprocess.py b/Lib/_bootsubprocess.py deleted file mode 100644 index 014782f616c823bae543909e3b17dad3dccc8cd0..0000000000000000000000000000000000000000 --- a/Lib/_bootsubprocess.py +++ /dev/null @@ -1,97 +0,0 @@ -""" -Basic subprocess implementation for POSIX which only uses os functions. Only -implement features required by setup.py to build C extension modules when -subprocess is unavailable. setup.py is not used on Windows. -""" -import os - - -# distutils.spawn used by distutils.command.build_ext -# calls subprocess.Popen().wait() -class Popen: - def __init__(self, cmd, env=None): - self._cmd = cmd - self._env = env - self.returncode = None - - def wait(self): - pid = os.fork() - if pid == 0: - # Child process - try: - if self._env is not None: - os.execve(self._cmd[0], self._cmd, self._env) - else: - os.execv(self._cmd[0], self._cmd) - finally: - os._exit(1) - else: - # Parent process - _, status = os.waitpid(pid, 0) - self.returncode = os.waitstatus_to_exitcode(status) - - return self.returncode - - -def _check_cmd(cmd): - # Use regex [a-zA-Z0-9./-]+: reject empty string, space, etc. - safe_chars = [] - for first, last in (("a", "z"), ("A", "Z"), ("0", "9")): - for ch in range(ord(first), ord(last) + 1): - safe_chars.append(chr(ch)) - safe_chars.append("./-") - safe_chars = ''.join(safe_chars) - - if isinstance(cmd, (tuple, list)): - check_strs = cmd - elif isinstance(cmd, str): - check_strs = [cmd] - else: - return False - - for arg in check_strs: - if not isinstance(arg, str): - return False - if not arg: - # reject empty string - return False - for ch in arg: - if ch not in safe_chars: - return False - - return True - - -# _aix_support used by distutil.util calls subprocess.check_output() -def check_output(cmd, **kwargs): - if kwargs: - raise NotImplementedError(repr(kwargs)) - - if not _check_cmd(cmd): - raise ValueError(f"unsupported command: {cmd!r}") - - tmp_filename = "check_output.tmp" - if not isinstance(cmd, str): - cmd = " ".join(cmd) - cmd = f"{cmd} >{tmp_filename}" - - try: - # system() spawns a shell - status = os.system(cmd) - exitcode = os.waitstatus_to_exitcode(status) - if exitcode: - raise ValueError(f"Command {cmd!r} returned non-zero " - f"exit status {exitcode!r}") - - try: - with open(tmp_filename, "rb") as fp: - stdout = fp.read() - except FileNotFoundError: - stdout = b'' - finally: - try: - os.unlink(tmp_filename) - except OSError: - pass - - return stdout diff --git a/Lib/ast.py b/Lib/ast.py index 4e2ae859245f99b76f70a3108bc1c6c39091f761..ebf4529f79b0609b8ee29ba0b0c832efa52f9d20 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -42,7 +42,8 @@ def parse(source, filename='<unknown>', mode='exec', *, flags |= PyCF_TYPE_COMMENTS if isinstance(feature_version, tuple): major, minor = feature_version # Should be a 2-tuple. - assert major == 3 + if major != 3: + raise ValueError(f"Unsupported major version: {major}") feature_version = minor elif feature_version is None: feature_version = -1 diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index 08c79e7b5109bfa55cb76f35ebd3bb72f65d8ed4..4bd9629e9eb62b6326e3db4ce7f9059a2c02f430 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -206,7 +206,7 @@ def result(self): raise exceptions.InvalidStateError('Result is not ready.') self.__log_traceback = False if self._exception is not None: - raise self._exception + raise self._exception.with_traceback(self._exception_tb) return self._result def exception(self): @@ -282,6 +282,7 @@ def set_exception(self, exception): raise TypeError("StopIteration interacts badly with generators " "and cannot be raised into a Future") self._exception = exception + self._exception_tb = exception.__traceback__ self._state = _FINISHED self.__schedule_callbacks() self.__log_traceback = True diff --git a/Lib/asyncio/runners.py b/Lib/asyncio/runners.py index 7489a50f8e48da8023685da8811d15a526fc606c..a8b74d532fcd3e292a3fb14ff86f4905ea17aeff 100644 --- a/Lib/asyncio/runners.py +++ b/Lib/asyncio/runners.py @@ -118,10 +118,11 @@ def run(self, coro, *, context=None): events.set_event_loop(self._loop) return self._loop.run_until_complete(task) except exceptions.CancelledError: - if self._interrupt_count > 0 and task.uncancel() == 0: - raise KeyboardInterrupt() - else: - raise # CancelledError + if self._interrupt_count > 0: + uncancel = getattr(task, "uncancel", None) + if uncancel is not None and uncancel() == 0: + raise KeyboardInterrupt() + raise # CancelledError finally: if (sigint_handler is not None and signal.getsignal(signal.SIGINT) is sigint_handler diff --git a/Lib/asyncio/timeouts.py b/Lib/asyncio/timeouts.py index a89205348ff24ca7043997e83c5870323ed4a86a..94d25535fbc0595760877415166bfc8edd6ba1a8 100644 --- a/Lib/asyncio/timeouts.py +++ b/Lib/asyncio/timeouts.py @@ -52,10 +52,10 @@ def reschedule(self, when: Optional[float]) -> None: self._timeout_handler = None else: loop = events.get_running_loop() - self._timeout_handler = loop.call_at( - when, - self._on_timeout, - ) + if when <= loop.time(): + self._timeout_handler = loop.call_soon(self._on_timeout) + else: + self._timeout_handler = loop.call_at(when, self._on_timeout) def expired(self) -> bool: """Is timeout expired during execution?""" diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py index d7e7e41967cc213914b115a8d084fb7a68d88adc..6742a07753c9217802f8a267f20e7fe6ffc28fb6 100644 --- a/Lib/concurrent/futures/_base.py +++ b/Lib/concurrent/futures/_base.py @@ -310,6 +310,18 @@ def wait(fs, timeout=None, return_when=ALL_COMPLETED): done.update(waiter.finished_futures) return DoneAndNotDoneFutures(done, fs - done) + +def _result_or_cancel(fut, timeout=None): + try: + try: + return fut.result(timeout) + finally: + fut.cancel() + finally: + # Break a reference cycle with the exception in self._exception + del fut + + class Future(object): """Represents the result of an asynchronous computation.""" @@ -604,9 +616,9 @@ def result_iterator(): while fs: # Careful not to keep a reference to the popped future if timeout is None: - yield fs.pop().result() + yield _result_or_cancel(fs.pop()) else: - yield fs.pop().result(end_time - time.monotonic()) + yield _result_or_cancel(fs.pop(), end_time - time.monotonic()) finally: for future in fs: future.cancel() diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 69cab8c563ea9869671720a520a1685fe43a592f..a567a33d646f446ef017b39e9fafea5c6c4af3e8 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1193,19 +1193,18 @@ def _add_slots(cls, is_frozen, weakref_slot): def dataclass(cls=None, /, *, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False, weakref_slot=False): - """Returns the same class as was passed in, with dunder methods - added based on the fields defined in the class. + """Add dunder methods based on the fields defined in the class. Examines PEP 526 __annotations__ to determine fields. - If init is true, an __init__() method is added to the class. If - repr is true, a __repr__() method is added. If order is true, rich + If init is true, an __init__() method is added to the class. If repr + is true, a __repr__() method is added. If order is true, rich comparison dunder methods are added. If unsafe_hash is true, a - __hash__() method function is added. If frozen is true, fields may - not be assigned to after instance creation. If match_args is true, - the __match_args__ tuple is added. If kw_only is true, then by - default all fields are keyword-only. If slots is true, an - __slots__ attribute is added. + __hash__() method is added. If frozen is true, fields may not be + assigned to after instance creation. If match_args is true, the + __match_args__ tuple is added. If kw_only is true, then by default + all fields are keyword-only. If slots is true, a new class with a + __slots__ attribute is returned. """ def wrap(cls): @@ -1256,7 +1255,7 @@ def asdict(obj, *, dict_factory=dict): """Return the fields of a dataclass instance as a new dictionary mapping field names to field values. - Example usage: + Example usage:: @dataclass class C: @@ -1327,8 +1326,8 @@ class C: x: int y: int - c = C(1, 2) - assert astuple(c) == (1, 2) + c = C(1, 2) + assert astuple(c) == (1, 2) If given, 'tuple_factory' will be used instead of built-in tuple. The function applies recursively to field values that are @@ -1377,11 +1376,11 @@ def make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, The dataclass name will be 'cls_name'. 'fields' is an iterable of either (name), (name, type) or (name, type, Field) objects. If type is omitted, use the string 'typing.Any'. Field objects are created by - the equivalent of calling 'field(name, type [, Field-info])'. + the equivalent of calling 'field(name, type [, Field-info])'.:: C = make_dataclass('C', ['x', ('y', int), ('z', int, field(init=False))], bases=(Base,)) - is equivalent to: + is equivalent to:: @dataclass class C(Base): @@ -1445,7 +1444,7 @@ def exec_body_callback(ns): def replace(obj, /, **changes): """Return a new object replacing specified fields with new values. - This is especially useful for frozen classes. Example usage: + This is especially useful for frozen classes. Example usage:: @dataclass(frozen=True) class C: @@ -1455,7 +1454,7 @@ class C: c = C(1, 2) c1 = replace(c, x=3) assert c1.x == 3 and c1.y == 2 - """ + """ # We're going to mutate 'changes', but that's okay because it's a # new dict, even if called with 'replace(obj, **my_changes)'. diff --git a/Lib/distutils/tests/test_dir_util.py b/Lib/distutils/tests/test_dir_util.py index f3ba0ee33b4bc11f61d7955c72bba979911f3449..ebd89f320dca89381176c82995b5057c5c86c178 100644 --- a/Lib/distutils/tests/test_dir_util.py +++ b/Lib/distutils/tests/test_dir_util.py @@ -11,7 +11,7 @@ from distutils import log from distutils.tests import support -from test.support import run_unittest, is_emscripten +from test.support import run_unittest, is_emscripten, is_wasi class DirUtilTestCase(support.TempdirManager, unittest.TestCase): @@ -55,7 +55,10 @@ def test_mkpath_remove_tree_verbosity(self): @unittest.skipIf(sys.platform.startswith('win'), "This test is only appropriate for POSIX-like systems.") - @unittest.skipIf(is_emscripten, "Emscripten's umask is a stub.") + @unittest.skipIf( + is_emscripten or is_wasi, + "Emscripten's/WASI's umask is a stub." + ) def test_mkpath_with_custom_mode(self): # Get and set the current umask value for testing mode bits. umask = os.umask(0o002) diff --git a/Lib/email/_parseaddr.py b/Lib/email/_parseaddr.py index ba5ad5a36d06b740d6d515aa7bd47d8464483155..febe411355d6be3be8b60bd8c845479451149d6f 100644 --- a/Lib/email/_parseaddr.py +++ b/Lib/email/_parseaddr.py @@ -95,6 +95,8 @@ def _parsedate_tz(data): return None data = data[:5] [dd, mm, yy, tm, tz] = data + if not (dd and mm and yy): + return None mm = mm.lower() if mm not in _monthnames: dd, mm = mm, dd.lower() @@ -110,6 +112,8 @@ def _parsedate_tz(data): yy, tm = tm, yy if yy[-1] == ',': yy = yy[:-1] + if not yy: + return None if not yy[0].isdigit(): yy, tz = tz, yy if tm[-1] == ',': diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py index 1f25825f3febfdbb294d8d56cfd404a6f384a2e5..885a1edf4b3804748be3686c8d2c525fd6a4f118 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -10,8 +10,8 @@ __all__ = ["version", "bootstrap"] _PACKAGE_NAMES = ('setuptools', 'pip') -_SETUPTOOLS_VERSION = "58.1.0" -_PIP_VERSION = "22.0.4" +_SETUPTOOLS_VERSION = "63.2.0" +_PIP_VERSION = "22.2.1" _PROJECTS = [ ("setuptools", _SETUPTOOLS_VERSION, "py3"), ("pip", _PIP_VERSION, "py3"), diff --git a/Lib/ensurepip/_bundled/pip-22.0.4-py3-none-any.whl b/Lib/ensurepip/_bundled/pip-22.0.4-py3-none-any.whl deleted file mode 100644 index 7ba048e245227d3325413220e1eb8da42c66dead..0000000000000000000000000000000000000000 Binary files a/Lib/ensurepip/_bundled/pip-22.0.4-py3-none-any.whl and /dev/null differ diff --git a/Lib/ensurepip/_bundled/pip-22.2.1-py3-none-any.whl b/Lib/ensurepip/_bundled/pip-22.2.1-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..4654c00136cd0cd37c7de529a63c64e2498b54f8 Binary files /dev/null and b/Lib/ensurepip/_bundled/pip-22.2.1-py3-none-any.whl differ diff --git a/Lib/ensurepip/_bundled/setuptools-58.1.0-py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-58.1.0-py3-none-any.whl deleted file mode 100644 index 18c8c22958f1f1bc9d50afc4c9c3d585c14246e3..0000000000000000000000000000000000000000 Binary files a/Lib/ensurepip/_bundled/setuptools-58.1.0-py3-none-any.whl and /dev/null differ diff --git a/Lib/ensurepip/_bundled/setuptools-63.2.0-py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-63.2.0-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..e3b5446eb59cb5ac608742261a3608b412bcff08 Binary files /dev/null and b/Lib/ensurepip/_bundled/setuptools-63.2.0-py3-none-any.whl differ diff --git a/Lib/enum.py b/Lib/enum.py index 652878ce1e1dfa2c47646321ecf90e52cfbe13cf..8ef69589a14699d7cf4e485525ae56217b5bd77f 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -185,19 +185,35 @@ class property(DynamicClassAttribute): a corresponding enum member. """ + member = None + def __get__(self, instance, ownerclass=None): if instance is None: - try: - return ownerclass._member_map_[self.name] - except KeyError: + if self.member is not None: + return self.member + else: raise AttributeError( '%r has no attribute %r' % (ownerclass, self.name) ) else: if self.fget is None: - raise AttributeError( - '%r member has no attribute %r' % (ownerclass, self.name) + if self.member is None: # not sure this can happen, but just in case + raise AttributeError( + '%r has no attribute %r' % (ownerclass, self.name) + ) + # issue warning deprecating this behavior + import warnings + warnings.warn( + "`member.member` access (e.g. `Color.RED.BLUE`) is " + "deprecated and will be removed in 3.14.", + DeprecationWarning, + stacklevel=2, ) + return self.member + # XXX: uncomment in 3.14 and remove warning above + # raise AttributeError( + # '%r member has no attribute %r' % (ownerclass, self.name) + # ) else: return self.fget(instance) @@ -247,7 +263,10 @@ def __set_name__(self, enum_class, member_name): if not enum_class._use_args_: enum_member = enum_class._new_member_(enum_class) if not hasattr(enum_member, '_value_'): - enum_member._value_ = value + try: + enum_member._value_ = enum_class._member_type_(*args) + except Exception as exc: + enum_member._value_ = value else: enum_member = enum_class._new_member_(enum_class, *args) if not hasattr(enum_member, '_value_'): @@ -296,30 +315,20 @@ def __set_name__(self, enum_class, member_name): enum_class._member_names_.append(member_name) # get redirect in place before adding to _member_map_ # but check for other instances in parent classes first - need_override = False descriptor = None for base in enum_class.__mro__[1:]: descriptor = base.__dict__.get(member_name) if descriptor is not None: if isinstance(descriptor, (property, DynamicClassAttribute)): break - else: - need_override = True - # keep looking for an enum.property - if descriptor and not need_override: - # previous enum.property found, no further action needed - pass - elif descriptor and need_override: - redirect = property() - redirect.__set_name__(enum_class, member_name) - # Previous enum.property found, but some other inherited attribute - # is in the way; copy fget, fset, fdel to this one. - redirect.fget = descriptor.fget - redirect.fset = descriptor.fset - redirect.fdel = descriptor.fdel - setattr(enum_class, member_name, redirect) - else: - setattr(enum_class, member_name, enum_member) + redirect = property() + redirect.member = enum_member + redirect.__set_name__(enum_class, member_name) + if descriptor: + redirect.fget = getattr(descriptor, 'fget', None) + redirect.fset = getattr(descriptor, 'fset', None) + redirect.fdel = getattr(descriptor, 'fdel', None) + setattr(enum_class, member_name, redirect) # now add to _member_map_ (even aliases) enum_class._member_map_[member_name] = enum_member try: @@ -562,7 +571,13 @@ def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **k classdict['__str__'] = enum_class.__str__ for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'): if name not in classdict: - setattr(enum_class, name, getattr(first_enum, name)) + # check for mixin overrides before replacing + enum_method = getattr(first_enum, name) + found_method = getattr(enum_class, name) + object_method = getattr(object, name) + data_type_method = getattr(member_type, name) + if found_method in (data_type_method, object_method): + setattr(enum_class, name, enum_method) # # for Flag, add __or__, __and__, __xor__, and __invert__ if Flag is not None and issubclass(enum_class, Flag): @@ -731,22 +746,6 @@ def __dir__(cls): # return whatever mixed-in data type has return sorted(set(dir(cls._member_type_)) | interesting) - def __getattr__(cls, name): - """ - Return the enum member matching `name` - - We use __getattr__ instead of descriptors or inserting into the enum - class' __dict__ in order to support `name` and `value` being both - properties for enum members (which live in the class' __dict__) and - enum members themselves. - """ - if _is_dunder(name): - raise AttributeError(name) - try: - return cls._member_map_[name] - except KeyError: - raise AttributeError(name) from None - def __getitem__(cls, name): """ Return the member matching `name`. @@ -937,16 +936,18 @@ def _find_data_repr_(mcls, class_name, bases): @classmethod def _find_data_type_(mcls, class_name, bases): data_types = set() + base_chain = set() for chain in bases: candidate = None for base in chain.__mro__: + base_chain.add(base) if base is object: continue elif issubclass(base, Enum): if base._member_type_ is not object: data_types.add(base._member_type_) break - elif '__new__' in base.__dict__: + elif '__new__' in base.__dict__ or '__init__' in base.__dict__: if issubclass(base, Enum): continue data_types.add(candidate or base) @@ -1189,10 +1190,10 @@ def __reduce_ex__(self, proto): # enum.property is used to provide access to the `name` and # `value` attributes of enum members while keeping some measure of # protection from modification, while still allowing for an enumeration - # to have members named `name` and `value`. This works because enumeration - # members are not set directly on the enum class; they are kept in a - # separate structure, _member_map_, which is where enum.property looks for - # them + # to have members named `name` and `value`. This works because each + # instance of enum.property saves its companion member, which it returns + # on class lookup; on instance lookup it either executes a provided function + # or raises an AttributeError. @property def name(self): @@ -1650,7 +1651,13 @@ def convert_class(cls): enum_class = type(cls_name, (etype, ), body, boundary=boundary, _simple=True) for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'): if name not in body: - setattr(enum_class, name, getattr(etype, name)) + # check for mixin overrides before replacing + enum_method = getattr(etype, name) + found_method = getattr(enum_class, name) + object_method = getattr(object, name) + data_type_method = getattr(member_type, name) + if found_method in (data_type_method, object_method): + setattr(enum_class, name, enum_method) gnv_last_values = [] if issubclass(enum_class, Flag): # Flag / IntFlag @@ -1660,10 +1667,12 @@ def convert_class(cls): value = gnv(name, 1, len(member_names), gnv_last_values) if value in value2member_map: # an alias to an existing member + member = value2member_map[value] redirect = property() + redirect.member = member redirect.__set_name__(enum_class, name) setattr(enum_class, name, redirect) - member_map[name] = value2member_map[value] + member_map[name] = member else: # create the member if use_args: @@ -1679,6 +1688,7 @@ def convert_class(cls): member.__objclass__ = enum_class member.__init__(value) redirect = property() + redirect.member = member redirect.__set_name__(enum_class, name) setattr(enum_class, name, redirect) member_map[name] = member @@ -1706,10 +1716,12 @@ def convert_class(cls): value = value.value if value in value2member_map: # an alias to an existing member + member = value2member_map[value] redirect = property() + redirect.member = member redirect.__set_name__(enum_class, name) setattr(enum_class, name, redirect) - member_map[name] = value2member_map[value] + member_map[name] = member else: # create the member if use_args: @@ -1726,6 +1738,7 @@ def convert_class(cls): member.__init__(value) member._sort_order_ = len(member_names) redirect = property() + redirect.member = member redirect.__set_name__(enum_class, name) setattr(enum_class, name, redirect) member_map[name] = member @@ -1981,7 +1994,6 @@ def _old_convert_(etype, name, module, filter, source=None, *, boundary=None): members.sort(key=lambda t: t[0]) cls = etype(name, members, module=module, boundary=boundary or KEEP) cls.__reduce_ex__ = _reduce_ex_by_global_name - cls.__repr__ = global_enum_repr return cls _stdlib_enums = IntEnum, StrEnum, IntFlag diff --git a/Lib/fileinput.py b/Lib/fileinput.py index 9f41c18510decf66d6223af732d2c18249e944f1..e234dc9ea65f15ab389635865733fea9eaccc40a 100644 --- a/Lib/fileinput.py +++ b/Lib/fileinput.py @@ -335,18 +335,21 @@ def _readline(self): pass # The next few lines may raise OSError os.rename(self._filename, self._backupfilename) - self._file = open(self._backupfilename, self._mode, encoding=encoding) + self._file = open(self._backupfilename, self._mode, + encoding=encoding, errors=self._errors) try: perm = os.fstat(self._file.fileno()).st_mode except OSError: - self._output = open(self._filename, self._write_mode, encoding=encoding) + self._output = open(self._filename, self._write_mode, + encoding=encoding, errors=self._errors) else: mode = os.O_CREAT | os.O_WRONLY | os.O_TRUNC if hasattr(os, 'O_BINARY'): mode |= os.O_BINARY fd = os.open(self._filename, mode, perm) - self._output = os.fdopen(fd, self._write_mode, encoding=encoding) + self._output = os.fdopen(fd, self._write_mode, + encoding=encoding, errors=self._errors) try: os.chmod(self._filename, perm) except OSError: diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 441ec41ed76b2cfe70c77fa1e1607002f43cc081..ffb090aa45a465f759b2206d0a69ed1acc70e4ed 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,8 @@ What's New in IDLE 3.11.0 Released on 2022-10-03 ========================= +gh-89610: Add .pyi as a recognized extension for IDLE on macOS. This allows +opening stub files by double clicking on them in the Finder. bpo-28950: Apply IDLE syntax highlighting to `.pyi` files. Add util.py for common components. Patch by Alex Waygood and Terry Jan Reedy. @@ -29,6 +31,7 @@ What's New in IDLE 3.10.0 Released on 2021-10-04 ========================= +bpo-45193: Make completion boxes appear on Ubuntu again. bpo-40128: Mostly fix completions on macOS when not using tcl/tk 8.6.11 (as with 3.9). diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 6c52efd655e12192782f0376cc9b6ca33cf24ac0..859a288b4bc6772aa8c00d23a9581e73c70ed989 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -1301,7 +1301,7 @@ def smart_backspace_event(self, event): want = ((have - 1) // self.indentwidth) * self.indentwidth # Debug prompt is multilined.... ncharsdeleted = 0 - while 1: + while True: chars = chars[:-1] ncharsdeleted = ncharsdeleted + 1 have = len(chars.expandtabs(tabwidth)) diff --git a/Lib/idlelib/history.py b/Lib/idlelib/history.py index 100f505256a9400d3be062acc8922cb9b5a7df2e..5a9b32aaf6bb815559d19ccca55611764abdaf16 100644 --- a/Lib/idlelib/history.py +++ b/Lib/idlelib/history.py @@ -65,7 +65,7 @@ def fetch(self, reverse): self.text.bell() return nprefix = len(prefix) - while 1: + while True: pointer += -1 if reverse else 1 if pointer < 0 or pointer >= nhist: self.text.bell() diff --git a/Lib/idlelib/hyperparser.py b/Lib/idlelib/hyperparser.py index 77baca782b3fdc07c89a93aaffde082fed2988d2..76144ee8fb30f5eb143d4fe50343393892c23154 100644 --- a/Lib/idlelib/hyperparser.py +++ b/Lib/idlelib/hyperparser.py @@ -237,9 +237,9 @@ def get_expression(self): last_identifier_pos = pos postdot_phase = True - while 1: + while True: # Eat whitespaces, comments, and if postdot_phase is False - a dot - while 1: + while True: if pos>brck_limit and rawtext[pos-1] in self._whitespace_chars: # Eat a whitespace pos -= 1 diff --git a/Lib/idlelib/idle_test/test_run.py b/Lib/idlelib/idle_test/test_run.py index d859ffc153fcddcc064ad3932c4b8d5d79f246ea..ec4637c5ca617a9eb380d46825ee32c429520edc 100644 --- a/Lib/idlelib/idle_test/test_run.py +++ b/Lib/idlelib/idle_test/test_run.py @@ -3,7 +3,7 @@ from idlelib import run import io import sys -from test.support import captured_output, captured_stderr, has_no_debug_ranges +from test.support import captured_output, captured_stderr import unittest from unittest import mock import idlelib @@ -33,14 +33,9 @@ def __eq__(self, other): run.print_exception() tb = output.getvalue().strip().splitlines() - if has_no_debug_ranges(): - self.assertEqual(11, len(tb)) - self.assertIn('UnhashableException: ex2', tb[3]) - self.assertIn('UnhashableException: ex1', tb[10]) - else: - self.assertEqual(13, len(tb)) - self.assertIn('UnhashableException: ex2', tb[4]) - self.assertIn('UnhashableException: ex1', tb[12]) + self.assertEqual(11, len(tb)) + self.assertIn('UnhashableException: ex2', tb[3]) + self.assertIn('UnhashableException: ex1', tb[10]) data = (('1/0', ZeroDivisionError, "division by zero\n"), ('abc', NameError, "name 'abc' is not defined. " diff --git a/Lib/idlelib/rpc.py b/Lib/idlelib/rpc.py index 8efcf048fa3aa20d60efa1ff7973778f642922dd..62eec84c9c8d090f79505f1873b190161f7129b6 100644 --- a/Lib/idlelib/rpc.py +++ b/Lib/idlelib/rpc.py @@ -307,7 +307,7 @@ def _getresponse(self, myseq, wait): self.debug("_getresponse:myseq:", myseq) if threading.current_thread() is self.sockthread: # this thread does all reading of requests or responses - while 1: + while True: response = self.pollresponse(myseq, wait) if response is not None: return response @@ -417,7 +417,7 @@ def pollresponse(self, myseq, wait): self.responses and notify the owning thread. """ - while 1: + while True: # send queued response if there is one available try: qmsg = response_queue.get(0) diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py index aaa9b5ce8d181f5dc3ea001aefe929b56b486ba2..577c49eb67b20d1f83095b3224d341cd88ad1656 100644 --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -145,7 +145,7 @@ def main(del_exitfunc=False): args=((LOCALHOST, port),)) sockthread.daemon = True sockthread.start() - while 1: + while True: try: if exit_now: try: diff --git a/Lib/idlelib/searchengine.py b/Lib/idlelib/searchengine.py index eddef581ab40a752b287ee43b052d2e65731d12d..0684142f43644af5ad3a3a9f98d99111f51ed431 100644 --- a/Lib/idlelib/searchengine.py +++ b/Lib/idlelib/searchengine.py @@ -165,7 +165,7 @@ def search_backward(self, text, prog, line, col, wrap, ok=0): wrapped = 0 startline = line chars = text.get("%d.0" % line, "%d.0" % (line+1)) - while 1: + while True: m = search_reverse(prog, chars[:-1], col) if m: if ok or m.start() < col: diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 007127b9fd42672925fe0b6b0eb67d2284cb4491..b6c6716e90773418f20dc74c8196ff710001258b 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -1475,7 +1475,7 @@ def _get_spec(cls, fullname, path, target=None): # the list of paths that will become its __path__ namespace_path = [] for entry in path: - if not isinstance(entry, (str, bytes)): + if not isinstance(entry, str): continue finder = cls._path_importer_cache(entry) if finder is not None: diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 69e7d558a056fc48093fef7e6300de9fced9554b..2aee71742b23e4d28a7139aeb631a990e7ba899b 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -299,6 +299,8 @@ def __init__(self, pat, child_parts, flavour): def _select_from(self, parent_path, is_dir, exists, scandir): try: + # We must close the scandir() object before proceeding to + # avoid exhausting file descriptors when globbing deep trees. with scandir(parent_path) as scandir_it: entries = list(scandir_it) for entry in entries: @@ -330,6 +332,8 @@ def __init__(self, pat, child_parts, flavour): def _iterate_directories(self, parent_path, is_dir, scandir): yield parent_path try: + # We must close the scandir() object before proceeding to + # avoid exhausting file descriptors when globbing deep trees. with scandir(parent_path) as scandir_it: entries = list(scandir_it) for entry in entries: @@ -1317,6 +1321,49 @@ def expanduser(self): return self + def walk(self, top_down=True, on_error=None, follow_symlinks=False): + """Walk the directory tree from this directory, similar to os.walk().""" + sys.audit("pathlib.Path.walk", self, on_error, follow_symlinks) + return self._walk(top_down, on_error, follow_symlinks) + + def _walk(self, top_down, on_error, follow_symlinks): + # We may not have read permission for self, in which case we can't + # get a list of the files the directory contains. os.walk + # always suppressed the exception then, rather than blow up for a + # minor reason when (say) a thousand readable directories are still + # left to visit. That logic is copied here. + try: + scandir_it = self._scandir() + except OSError as error: + if on_error is not None: + on_error(error) + return + + with scandir_it: + dirnames = [] + filenames = [] + for entry in scandir_it: + try: + is_dir = entry.is_dir(follow_symlinks=follow_symlinks) + except OSError: + # Carried over from os.path.isdir(). + is_dir = False + + if is_dir: + dirnames.append(entry.name) + else: + filenames.append(entry.name) + + if top_down: + yield self, dirnames, filenames + + for dirname in dirnames: + dirpath = self._make_child_relpath(dirname) + yield from dirpath._walk(top_down, on_error, follow_symlinks) + + if not top_down: + yield self, dirnames, filenames + class PosixPath(Path, PurePosixPath): """Path subclass for non-Windows systems. diff --git a/Lib/platform.py b/Lib/platform.py index c272c407c77768323198747107e1873ab270bb84..df8faac88ca88a1c472fcdca5cdae29b9ce0abd5 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -561,7 +561,7 @@ def _platform(*args): platform = platform.replace('unknown', '') # Fold '--'s and remove trailing '-' - while 1: + while True: cleaned = platform.replace('--', '-') if cleaned == platform: break diff --git a/Lib/pprint.py b/Lib/pprint.py index 575688d8eb6f4a3c224dd6dd57487fcae8a91f31..34ed12637e228867cd162ae7d21b56d68421836b 100644 --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -637,19 +637,6 @@ def _recursion(object): % (type(object).__name__, id(object))) -def _perfcheck(object=None): - import time - if object is None: - object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000 - p = PrettyPrinter() - t1 = time.perf_counter() - p._safe_repr(object, {}, None, 0, True) - t2 = time.perf_counter() - p.pformat(object) - t3 = time.perf_counter() - print("_safe_repr:", t2 - t1) - print("pformat:", t3 - t2) - def _wrap_bytes_repr(object, width, allowance): current = b'' last = len(object) // 4 * 4 @@ -666,6 +653,3 @@ def _wrap_bytes_repr(object, width, allowance): current = candidate if current: yield repr(current) - -if __name__ == "__main__": - _perfcheck() diff --git a/Lib/random.py b/Lib/random.py index 2166474af0554b6d77543eaf5d736318323310a3..76627309e288b98444b37fa6fb5c8d7668d2abb3 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -24,6 +24,7 @@ negative exponential gamma beta + binomial pareto Weibull @@ -49,6 +50,7 @@ from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin from math import tau as TWOPI, floor as _floor, isfinite as _isfinite +from math import lgamma as _lgamma, fabs as _fabs, log2 as _log2 from os import urandom as _urandom from _collections_abc import Sequence as _Sequence from operator import index as _index @@ -68,6 +70,7 @@ "Random", "SystemRandom", "betavariate", + "binomialvariate", "choice", "choices", "expovariate", @@ -725,6 +728,91 @@ def betavariate(self, alpha, beta): return y / (y + self.gammavariate(beta, 1.0)) return 0.0 + + def binomialvariate(self, n=1, p=0.5): + """Binomial random variable. + + Gives the number of successes for *n* independent trials + with the probability of success in each trial being *p*: + + sum(random() < p for i in range(n)) + + Returns an integer in the range: 0 <= X <= n + + """ + # Error check inputs and handle edge cases + if n < 0: + raise ValueError("n must be non-negative") + if p <= 0.0 or p >= 1.0: + if p == 0.0: + return 0 + if p == 1.0: + return n + raise ValueError("p must be in the range 0.0 <= p <= 1.0") + + random = self.random + + # Fast path for a common case + if n == 1: + return _index(random() < p) + + # Exploit symmetry to establish: p <= 0.5 + if p > 0.5: + return n - self.binomialvariate(n, 1.0 - p) + + if n * p < 10.0: + # BG: Geometric method by Devroye with running time of O(np). + # https://dl.acm.org/doi/pdf/10.1145/42372.42381 + x = y = 0 + c = _log2(1.0 - p) + if not c: + return x + while True: + y += _floor(_log2(random()) / c) + 1 + if y > n: + return x + x += 1 + + # BTRS: Transformed rejection with squeeze method by Wolfgang Hörmann + # https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.47.8407&rep=rep1&type=pdf + assert n*p >= 10.0 and p <= 0.5 + setup_complete = False + + spq = _sqrt(n * p * (1.0 - p)) # Standard deviation of the distribution + b = 1.15 + 2.53 * spq + a = -0.0873 + 0.0248 * b + 0.01 * p + c = n * p + 0.5 + vr = 0.92 - 4.2 / b + + while True: + + u = random() + u -= 0.5 + us = 0.5 - _fabs(u) + k = _floor((2.0 * a / us + b) * u + c) + if k < 0 or k > n: + continue + + # The early-out "squeeze" test substantially reduces + # the number of acceptance condition evaluations. + v = random() + if us >= 0.07 and v <= vr: + return k + + # Acceptance-rejection test. + # Note, the original paper errorneously omits the call to log(v) + # when comparing to the log of the rescaled binomial distribution. + if not setup_complete: + alpha = (2.83 + 5.1 / b) * spq + lpq = _log(p / (1.0 - p)) + m = _floor((n + 1) * p) # Mode of the distribution + h = _lgamma(m + 1) + _lgamma(n - m + 1) + setup_complete = True # Only needs to be done once + v *= alpha / (a / (us * us) + b) + if _log(v) <= h - _lgamma(k + 1) - _lgamma(n - k + 1) + (k - m) * lpq: + return k + + def paretovariate(self, alpha): """Pareto distribution. alpha is the shape parameter.""" # Jain, pg. 495 @@ -810,6 +898,7 @@ def _notimplemented(self, *args, **kwds): gammavariate = _inst.gammavariate gauss = _inst.gauss betavariate = _inst.betavariate +binomialvariate = _inst.binomialvariate paretovariate = _inst.paretovariate weibullvariate = _inst.weibullvariate getstate = _inst.getstate @@ -834,15 +923,17 @@ def _test_generator(n, func, args): low = min(data) high = max(data) - print(f'{t1 - t0:.3f} sec, {n} times {func.__name__}') + print(f'{t1 - t0:.3f} sec, {n} times {func.__name__}{args!r}') print('avg %g, stddev %g, min %g, max %g\n' % (xbar, sigma, low, high)) -def _test(N=2000): +def _test(N=10_000): _test_generator(N, random, ()) _test_generator(N, normalvariate, (0.0, 1.0)) _test_generator(N, lognormvariate, (0.0, 1.0)) _test_generator(N, vonmisesvariate, (0.0, 1.0)) + _test_generator(N, binomialvariate, (15, 0.60)) + _test_generator(N, binomialvariate, (100, 0.75)) _test_generator(N, gammavariate, (0.01, 1.0)) _test_generator(N, gammavariate, (0.1, 1.0)) _test_generator(N, gammavariate, (0.1, 2.0)) diff --git a/Lib/shutil.py b/Lib/shutil.py index f4128647861b81c60720ebe48f8622bfbf1099ef..b49437cd1f3e87ce08ca23c325397f92d4147299 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1118,6 +1118,8 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, save_cwd = None if root_dir is not None: if support_root_dir: + # Support path-like base_name here for backwards-compatibility. + base_name = os.fspath(base_name) kwargs['root_dir'] = root_dir else: save_cwd = os.getcwd() diff --git a/Lib/sqlite3/dbapi2.py b/Lib/sqlite3/dbapi2.py index 3b6d2f7ba2d5956a75414fe1ef695d8ee6cc17ef..56fc0461e6c92249a9bbe6e9a775ac8b4a28bd59 100644 --- a/Lib/sqlite3/dbapi2.py +++ b/Lib/sqlite3/dbapi2.py @@ -55,16 +55,25 @@ def TimestampFromTicks(ticks): collections.abc.Sequence.register(Row) def register_adapters_and_converters(): + from warnings import warn + + msg = ("The default {what} is deprecated as of Python 3.12; " + "see the sqlite3 documentation for suggested replacement recipes") + def adapt_date(val): + warn(msg.format(what="date adapter"), DeprecationWarning, stacklevel=2) return val.isoformat() def adapt_datetime(val): + warn(msg.format(what="datetime adapter"), DeprecationWarning, stacklevel=2) return val.isoformat(" ") def convert_date(val): + warn(msg.format(what="date converter"), DeprecationWarning, stacklevel=2) return datetime.date(*map(int, val.split(b"-"))) def convert_timestamp(val): + warn(msg.format(what="timestamp converter"), DeprecationWarning, stacklevel=2) datepart, timepart = val.split(b" ") year, month, day = map(int, datepart.split(b"-")) timepart_full = timepart.split(b".") diff --git a/Lib/statistics.py b/Lib/statistics.py index 2d66b0522f19d52632c0f24d73df7c93d9b326bc..c78d64518853e77003e2d6c0ff5bc30c99f38303 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -298,7 +298,7 @@ def _exact_ratio(x): # The integer ratios for binary floats can have numerators or # denominators with over 300 decimal digits. The problem is more - # acute with decimal floats where the the default decimal context + # acute with decimal floats where the default decimal context # supports a huge range of exponents from Emin=-999999 to # Emax=999999. When expanded with as_integer_ratio(), numbers like # Decimal('3.14E+5000') and Decimal('3.14E-5000') have large @@ -1193,7 +1193,7 @@ def samples(self, n, *, seed=None): "Generate *n* samples for a given mean and standard deviation." gauss = random.gauss if seed is None else random.Random(seed).gauss mu, sigma = self._mu, self._sigma - return [gauss(mu, sigma) for i in range(n)] + return [gauss(mu, sigma) for _ in repeat(None, n)] def pdf(self, x): "Probability density function. P(x <= X < x+dx) / dx" @@ -1221,8 +1221,6 @@ def inv_cdf(self, p): """ if p <= 0.0 or p >= 1.0: raise StatisticsError('p must be in the range 0.0 < p < 1.0') - if self._sigma <= 0.0: - raise StatisticsError('cdf() not defined when sigma at or below zero') return _normal_dist_inv_cdf(p, self._mu, self._sigma) def quantiles(self, n=4): diff --git a/Lib/subprocess.py b/Lib/subprocess.py index e10b01047ebef5f4357182c911c6be4aa67e7f30..7ae8df154b481f995444f1f88132181115592d18 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -102,8 +102,19 @@ else: if _can_fork_exec: from _posixsubprocess import fork_exec as _fork_exec + # used in methods that are called by __del__ + _waitpid = os.waitpid + _waitstatus_to_exitcode = os.waitstatus_to_exitcode + _WIFSTOPPED = os.WIFSTOPPED + _WSTOPSIG = os.WSTOPSIG + _WNOHANG = os.WNOHANG else: _fork_exec = None + _waitpid = None + _waitstatus_to_exitcode = None + _WIFSTOPPED = None + _WSTOPSIG = None + _WNOHANG = None import select import selectors @@ -1890,19 +1901,19 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, def _handle_exitstatus(self, sts, - waitstatus_to_exitcode=os.waitstatus_to_exitcode, - _WIFSTOPPED=os.WIFSTOPPED, - _WSTOPSIG=os.WSTOPSIG): + _waitstatus_to_exitcode=_waitstatus_to_exitcode, + _WIFSTOPPED=_WIFSTOPPED, + _WSTOPSIG=_WSTOPSIG): """All callers to this function MUST hold self._waitpid_lock.""" # This method is called (indirectly) by __del__, so it cannot # refer to anything outside of its local scope. if _WIFSTOPPED(sts): self.returncode = -_WSTOPSIG(sts) else: - self.returncode = waitstatus_to_exitcode(sts) + self.returncode = _waitstatus_to_exitcode(sts) - def _internal_poll(self, _deadstate=None, _waitpid=os.waitpid, - _WNOHANG=os.WNOHANG, _ECHILD=errno.ECHILD): + def _internal_poll(self, _deadstate=None, _waitpid=_waitpid, + _WNOHANG=_WNOHANG, _ECHILD=errno.ECHILD): """Check if child process has terminated. Returns returncode attribute. diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 75969975af35ba0f3b518fd28eeaabb6c10c7976..b78586c560a68a5dff4d2d3392a292f8ecea5185 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -3973,7 +3973,7 @@ def test_shared_memory_recreate(self): 'multiprocessing.shared_memory._make_filename') as mock_make_filename: NAME_PREFIX = shared_memory._SHM_NAME_PREFIX - names = ['test01_fn', 'test02_fn'] + names = [self._new_shm_name('test03_fn'), self._new_shm_name('test04_fn')] # Prepend NAME_PREFIX which can be '/psm_' or 'wnsm_', necessary # because some POSIX compliant systems require name to start with / names = [NAME_PREFIX + name for name in names] @@ -6020,3 +6020,15 @@ def tearDownModule(): remote_globs['setUpModule'] = setUpModule remote_globs['tearDownModule'] = tearDownModule + + +@unittest.skipIf(not hasattr(_multiprocessing, 'SemLock'), 'SemLock not available') +@unittest.skipIf(sys.platform != "linux", "Linux only") +class SemLockTests(unittest.TestCase): + + def test_semlock_subclass(self): + class SemLock(_multiprocessing.SemLock): + pass + name = f'test_semlock_subclass-{os.getpid()}' + s = SemLock(1, 0, 10, name, 0) + _multiprocessing.sem_unlink(name) diff --git a/Lib/test/_testcppext.cpp b/Lib/test/_testcppext.cpp index b6d35407a61edc85d2c1b4688558e55962b854e6..0e381a78c5ceed72fa26624c05bf1c5c149c76c1 100644 --- a/Lib/test/_testcppext.cpp +++ b/Lib/test/_testcppext.cpp @@ -12,6 +12,9 @@ # define NAME _testcpp03ext #endif +#define _STR(NAME) #NAME +#define STR(NAME) _STR(NAME) + PyDoc_STRVAR(_testcppext_add_doc, "add(x, y)\n" "\n" @@ -123,11 +126,80 @@ test_unicode(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) Py_RETURN_NONE; } +/* Test a `new`-allocated object with a virtual method. + * (https://github.com/python/cpython/issues/94731) */ + +class VirtualPyObject : public PyObject { +public: + VirtualPyObject(); + virtual ~VirtualPyObject() { + delete [] internal_data; + --instance_count; + } + virtual void set_internal_data() { + internal_data[0] = 1; + } + static void dealloc(PyObject* o) { + delete static_cast<VirtualPyObject*>(o); + } + + // Number of "living" instances + static int instance_count; +private: + // buffer that can get corrupted + int* internal_data; +}; + +int VirtualPyObject::instance_count = 0; + +PyType_Slot VirtualPyObject_Slots[] = { + {Py_tp_free, (void*)VirtualPyObject::dealloc}, + {0, _Py_NULL}, +}; + +PyType_Spec VirtualPyObject_Spec = { + /* .name */ STR(NAME) ".VirtualPyObject", + /* .basicsize */ sizeof(VirtualPyObject), + /* .itemsize */ 0, + /* .flags */ Py_TPFLAGS_DEFAULT, + /* .slots */ VirtualPyObject_Slots, +}; + +VirtualPyObject::VirtualPyObject() { + // Create a temporary type (just so we don't need to store it) + PyObject *type = PyType_FromSpec(&VirtualPyObject_Spec); + // no good way to signal failure from a C++ constructor, so use assert + // for error handling + assert(type); + assert(PyObject_Init(this, (PyTypeObject *)type)); + Py_DECREF(type); + internal_data = new int[50]; + ++instance_count; +} + +static PyObject * +test_virtual_object(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) +{ + VirtualPyObject* obj = new VirtualPyObject(); + obj->set_internal_data(); + Py_DECREF(obj); + if (VirtualPyObject::instance_count != 0) { + return PyErr_Format( + PyExc_AssertionError, + "instance_count should be 0, got %d", + VirtualPyObject::instance_count); + } + Py_RETURN_NONE; +} static PyMethodDef _testcppext_methods[] = { {"add", _testcppext_add, METH_VARARGS, _testcppext_add_doc}, {"test_api_casts", test_api_casts, METH_NOARGS, _Py_NULL}, {"test_unicode", test_unicode, METH_NOARGS, _Py_NULL}, + {"test_virtual_object", test_virtual_object, METH_NOARGS, _Py_NULL}, + // Note: _testcppext_exec currently runs all test functions directly. + // When adding a new one, add a call there. + {_Py_NULL, _Py_NULL, 0, _Py_NULL} /* sentinel */ }; @@ -138,6 +210,21 @@ _testcppext_exec(PyObject *module) if (PyModule_AddIntMacro(module, __cplusplus) < 0) { return -1; } + + PyObject *result; + + result = PyObject_CallMethod(module, "test_api_casts", ""); + if (!result) return -1; + Py_DECREF(result); + + result = PyObject_CallMethod(module, "test_unicode", ""); + if (!result) return -1; + Py_DECREF(result); + + result = PyObject_CallMethod(module, "test_virtual_object", ""); + if (!result) return -1; + Py_DECREF(result); + return 0; } @@ -149,9 +236,6 @@ static PyModuleDef_Slot _testcppext_slots[] = { PyDoc_STRVAR(_testcppext_doc, "C++ test extension."); -#define _STR(NAME) #NAME -#define STR(NAME) _STR(NAME) - static struct PyModuleDef _testcppext_module = { PyModuleDef_HEAD_INIT, // m_base STR(NAME), // m_name diff --git a/Lib/test/audit-tests.py b/Lib/test/audit-tests.py index ccec9fedc4460d74feb7a503990776b39fbb633c..00333cc9036a3c0b075b6cdad1887ebc26407b7c 100644 --- a/Lib/test/audit-tests.py +++ b/Lib/test/audit-tests.py @@ -408,6 +408,17 @@ def hook(event, *args): raise RuntimeError("Expected sqlite3.load_extension to fail") +def test_sys_getframe(): + import sys + + def hook(event, args): + if event.startswith("sys."): + print(event, args[0].f_code.co_name) + + sys.addaudithook(hook) + sys._getframe() + + if __name__ == "__main__": from test.support import suppress_msvcrt_asserts diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index 172c03f30231cd05f936bac9f14bb948bc82bece..adc211b3e2169c4bab7ab6da425cb595299a518e 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -588,8 +588,8 @@ def collect_socket(info_add): try: hostname = socket.gethostname() - except OSError: - # WASI SDK 15.0 does not have gethostname(2). + except (OSError, AttributeError): + # WASI SDK 16.0 does not have gethostname(2). if sys.platform != "wasi": raise else: diff --git a/Lib/test/setup_testcppext.py b/Lib/test/setup_testcppext.py index 892e24a6376c5ea4dbed6f33e09c3891204b35f5..c6b68104d1333c442fb8246951df60ef35bb0795 100644 --- a/Lib/test/setup_testcppext.py +++ b/Lib/test/setup_testcppext.py @@ -17,8 +17,6 @@ # a C++ extension using the Python C API does not emit C++ compiler # warnings '-Werror', - # Warn on old-style cast (C cast) like: (PyObject*)op - '-Wold-style-cast', ] else: # Don't pass any compiler flag to MSVC @@ -37,16 +35,13 @@ def main(): name = '_testcpp11ext' cppflags = [*CPPFLAGS, f'-std={std}'] - if std == 'c++11': - # Warn when using NULL rather than _Py_NULL in static inline functions - cppflags.append('-Wzero-as-null-pointer-constant') cpp_ext = Extension( name, sources=[SOURCE], language='c++', extra_compile_args=cppflags) - setup(name=name, ext_modules=[cpp_ext]) + setup(name='internal' + name, version='0.0', ext_modules=[cpp_ext]) if __name__ == "__main__": diff --git a/Lib/test/support/os_helper.py b/Lib/test/support/os_helper.py index 4edb1abec202a157c62d350036e077c431fe21d4..f37a442aa0e6c8e64bdd4d06e42c6c5fd4db2c9f 100644 --- a/Lib/test/support/os_helper.py +++ b/Lib/test/support/os_helper.py @@ -572,7 +572,7 @@ def fs_is_case_insensitive(directory): class FakePath: - """Simple implementing of the path protocol. + """Simple implementation of the path protocol. """ def __init__(self, path): self.path = path @@ -658,6 +658,11 @@ def temp_umask(umask): yield finally: os.umask(oldmask) +else: + @contextlib.contextmanager + def temp_umask(umask): + """no-op on platforms without umask()""" + yield class EnvironmentVarGuard(collections.abc.MutableMapping): diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 225892414b8c19ad39bfff143aebfb19c42001ce..de34ccff2ef0539af14229b22a185578225ce739 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -738,11 +738,30 @@ def test_ast_asdl_signature(self): expressions[0] = f"expr = {ast.expr.__subclasses__()[0].__doc__}" self.assertCountEqual(ast.expr.__doc__.split("\n"), expressions) + def test_parenthesized_with_feature_version(self): + ast.parse('with (CtxManager() as example): ...', feature_version=(3, 10)) + # While advertised as a feature in Python 3.10, this was allowed starting 3.9 + ast.parse('with (CtxManager() as example): ...', feature_version=(3, 9)) + with self.assertRaises(SyntaxError): + ast.parse('with (CtxManager() as example): ...', feature_version=(3, 8)) + ast.parse('with CtxManager() as example: ...', feature_version=(3, 8)) + def test_issue40614_feature_version(self): ast.parse('f"{x=}"', feature_version=(3, 8)) with self.assertRaises(SyntaxError): ast.parse('f"{x=}"', feature_version=(3, 7)) + def test_assignment_expression_feature_version(self): + ast.parse('(x := 0)', feature_version=(3, 8)) + with self.assertRaises(SyntaxError): + ast.parse('(x := 0)', feature_version=(3, 7)) + + def test_invalid_major_feature_version(self): + with self.assertRaises(ValueError): + ast.parse('pass', feature_version=(2, 7)) + with self.assertRaises(ValueError): + ast.parse('pass', feature_version=(4, 0)) + def test_constant_as_name(self): for constant in "True", "False", "None": expr = ast.Expression(ast.Name(constant, ast.Load())) @@ -780,6 +799,27 @@ def next(self): return self enum._test_simple_enum(_Precedence, ast._Precedence) + @support.cpython_only + def test_ast_recursion_limit(self): + fail_depth = sys.getrecursionlimit() * 3 + crash_depth = sys.getrecursionlimit() * 300 + success_depth = int(fail_depth * 0.75) + + def check_limit(prefix, repeated): + expect_ok = prefix + repeated * success_depth + ast.parse(expect_ok) + for depth in (fail_depth, crash_depth): + broken = prefix + repeated * depth + details = "Compiling ({!r} + {!r} * {})".format( + prefix, repeated, depth) + with self.assertRaises(RecursionError, msg=details): + ast.parse(broken) + + check_limit("a", "()") + check_limit("a", ".b") + check_limit("a", "[0]") + check_limit("a", "*a") + class ASTHelpers_Test(unittest.TestCase): maxDiff = None diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index c6671bd0ad3d852c1a9a849491dd7ac9ee4ab39d..063174adacfa37f7e7ef3e1a3edf79d4a265a358 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -40,7 +40,6 @@ def mock_socket_module(): m_socket.socket = mock.MagicMock() m_socket.socket.return_value = test_utils.mock_nonblocking_socket() - m_socket.getaddrinfo._is_coroutine = False return m_socket @@ -1286,9 +1285,7 @@ def _test_create_connection_ip_addr(self, m_socket, allow_inet_pton): sock = m_socket.socket.return_value self.loop._add_reader = mock.Mock() - self.loop._add_reader._is_coroutine = False self.loop._add_writer = mock.Mock() - self.loop._add_writer._is_coroutine = False coro = self.loop.create_connection(asyncio.Protocol, '1.2.3.4', 80) t, p = self.loop.run_until_complete(coro) @@ -1330,9 +1327,7 @@ def test_create_connection_ipv6_scope(self, m_socket): sock.family = socket.AF_INET6 self.loop._add_reader = mock.Mock() - self.loop._add_reader._is_coroutine = False self.loop._add_writer = mock.Mock() - self.loop._add_writer._is_coroutine = False coro = self.loop.create_connection(asyncio.Protocol, 'fe80::1%1', 80) t, p = self.loop.run_until_complete(coro) @@ -1359,9 +1354,7 @@ def test_create_connection_service_name(self, m_socket): sock = m_socket.socket.return_value self.loop._add_reader = mock.Mock() - self.loop._add_reader._is_coroutine = False self.loop._add_writer = mock.Mock() - self.loop._add_writer._is_coroutine = False for service, port in ('http', 80), (b'http', 80): coro = self.loop.create_connection(asyncio.Protocol, @@ -1590,7 +1583,6 @@ class Err(OSError): m_socket.getaddrinfo.return_value = [ (2, 1, 6, '', ('127.0.0.1', 10100))] - m_socket.getaddrinfo._is_coroutine = False m_sock = m_socket.socket.return_value = mock.Mock() m_sock.bind.side_effect = Err @@ -1601,7 +1593,6 @@ class Err(OSError): @patch_socket def test_create_datagram_endpoint_no_addrinfo(self, m_socket): m_socket.getaddrinfo.return_value = [] - m_socket.getaddrinfo._is_coroutine = False coro = self.loop.create_datagram_endpoint( MyDatagramProto, local_addr=('localhost', 0)) @@ -1835,7 +1826,6 @@ def getaddrinfo(*args, **kw): m_socket.getaddrinfo = getaddrinfo m_socket.socket.return_value.bind = bind = mock.Mock() self.loop._add_reader = mock.Mock() - self.loop._add_reader._is_coroutine = False reuseport_supported = hasattr(socket, 'SO_REUSEPORT') coro = self.loop.create_datagram_endpoint( diff --git a/Lib/test/test_asyncio/test_futures2.py b/Lib/test/test_asyncio/test_futures2.py index 60b58850369f053fd832f49bae461af4c10b4020..71279b69c7929ea958327287271a21b55b5bf3db 100644 --- a/Lib/test/test_asyncio/test_futures2.py +++ b/Lib/test/test_asyncio/test_futures2.py @@ -1,13 +1,42 @@ # IsolatedAsyncioTestCase based tests import asyncio +import traceback import unittest +from asyncio import tasks def tearDownModule(): asyncio.set_event_loop_policy(None) -class FutureTests(unittest.IsolatedAsyncioTestCase): +class FutureTests: + + async def test_future_traceback(self): + + async def raise_exc(): + raise TypeError(42) + + future = self.cls(raise_exc()) + + for _ in range(5): + try: + await future + except TypeError as e: + tb = ''.join(traceback.format_tb(e.__traceback__)) + self.assertEqual(tb.count("await future"), 1) + else: + self.fail('TypeError was not raised') + +@unittest.skipUnless(hasattr(tasks, '_CTask'), + 'requires the C _asyncio module') +class CFutureTests(FutureTests, unittest.IsolatedAsyncioTestCase): + cls = tasks._CTask + +class PyFutureTests(FutureTests, unittest.IsolatedAsyncioTestCase): + cls = tasks._PyTask + +class FutureReprTests(unittest.IsolatedAsyncioTestCase): + async def test_recursive_repr_for_pending_tasks(self): # The call crashes if the guard for recursive call # in base_futures:_future_repr_info is absent diff --git a/Lib/test/test_asyncio/test_runners.py b/Lib/test/test_asyncio/test_runners.py index 1f6a4983690cdc6e00f4051caf702f69e23759fd..d61d073a3674922b5a75a10914fd303d97ed473f 100644 --- a/Lib/test/test_asyncio/test_runners.py +++ b/Lib/test/test_asyncio/test_runners.py @@ -5,10 +5,9 @@ import signal import threading import unittest - +from test.test_asyncio import utils as test_utils from unittest import mock from unittest.mock import patch -from test.test_asyncio import utils as test_utils def tearDownModule(): @@ -210,6 +209,54 @@ async def main(): asyncio.run(main()) self.assertTrue(policy.set_event_loop.called) + def test_asyncio_run_without_uncancel(self): + # See https://github.com/python/cpython/issues/95097 + class Task: + def __init__(self, loop, coro, **kwargs): + self._task = asyncio.Task(coro, loop=loop, **kwargs) + + def cancel(self, *args, **kwargs): + return self._task.cancel(*args, **kwargs) + + def add_done_callback(self, *args, **kwargs): + return self._task.add_done_callback(*args, **kwargs) + + def remove_done_callback(self, *args, **kwargs): + return self._task.remove_done_callback(*args, **kwargs) + + @property + def _asyncio_future_blocking(self): + return self._task._asyncio_future_blocking + + def result(self, *args, **kwargs): + return self._task.result(*args, **kwargs) + + def done(self, *args, **kwargs): + return self._task.done(*args, **kwargs) + + def cancelled(self, *args, **kwargs): + return self._task.cancelled(*args, **kwargs) + + def exception(self, *args, **kwargs): + return self._task.exception(*args, **kwargs) + + def get_loop(self, *args, **kwargs): + return self._task.get_loop(*args, **kwargs) + + + async def main(): + interrupt_self() + await asyncio.Event().wait() + + def new_event_loop(): + loop = self.new_loop() + loop.set_task_factory(Task) + return loop + + asyncio.set_event_loop_policy(TestPolicy(new_event_loop)) + with self.assertRaises(asyncio.CancelledError): + asyncio.run(main()) + class RunnerTests(BaseTest): diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index d9d30fc25b513bbede8aefbe44a170b776c203ac..22dcfb23083522cbc99efdb2431bc0a014140829 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -61,7 +61,6 @@ def setUp(self): def test_make_socket_transport(self): m = mock.Mock() self.loop.add_reader = mock.Mock() - self.loop.add_reader._is_coroutine = False transport = self.loop._make_socket_transport(m, asyncio.Protocol()) self.assertIsInstance(transport, _SelectorSocketTransport) diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index 09a5c390b36299ddb939b01673f497ab4fdd83f8..961c463f8dc11b727a2381d022e8f79116470310 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -50,8 +50,6 @@ def setUp(self): def create_transport(self, waiter=None): protocol = mock.Mock() - protocol.connection_made._is_coroutine = False - protocol.process_exited._is_coroutine = False transport = TestSubprocessTransport( self.loop, protocol, ['test'], False, None, None, None, 0, waiter=waiter) @@ -702,34 +700,40 @@ class SubprocessPidfdWatcherTests(SubprocessWatcherMixin, test_utils.TestCase): Watcher = unix_events.PidfdChildWatcher -else: - # Windows - class SubprocessProactorTests(SubprocessMixin, test_utils.TestCase): - - def setUp(self): - super().setUp() - self.loop = asyncio.ProactorEventLoop() - self.set_event_loop(self.loop) + class GenericWatcherTests(test_utils.TestCase): -class GenericWatcherTests: + def test_create_subprocess_fails_with_inactive_watcher(self): + watcher = mock.create_autospec( + asyncio.AbstractChildWatcher, + **{"__enter__.return_value.is_active.return_value": False} + ) - def test_create_subprocess_fails_with_inactive_watcher(self): + async def execute(): + asyncio.set_child_watcher(watcher) - async def execute(): - watcher = mock.create_authspec(asyncio.AbstractChildWatcher) - watcher.is_active.return_value = False - asyncio.set_child_watcher(watcher) + with self.assertRaises(RuntimeError): + await subprocess.create_subprocess_exec( + os_helper.FakePath(sys.executable), '-c', 'pass') - with self.assertRaises(RuntimeError): - await subprocess.create_subprocess_exec( - os_helper.FakePath(sys.executable), '-c', 'pass') + watcher.add_child_handler.assert_not_called() - watcher.add_child_handler.assert_not_called() - - self.assertIsNone(self.loop.run_until_complete(execute())) + with asyncio.Runner(loop_factory=asyncio.new_event_loop) as runner: + self.assertIsNone(runner.run(execute())) + self.assertListEqual(watcher.mock_calls, [ + mock.call.__enter__(), + mock.call.__enter__().is_active(), + mock.call.__exit__(RuntimeError, mock.ANY, mock.ANY), + ]) +else: + # Windows + class SubprocessProactorTests(SubprocessMixin, test_utils.TestCase): + def setUp(self): + super().setUp() + self.loop = asyncio.ProactorEventLoop() + self.set_event_loop(self.loop) if __name__ == '__main__': diff --git a/Lib/test/test_asyncio/test_timeouts.py b/Lib/test/test_asyncio/test_timeouts.py index 9801541e55b7f8c02f50b8a3fd3cc1b118c09080..b9bac6f783776b6b8ba324bdeea241233c51de4b 100644 --- a/Lib/test/test_asyncio/test_timeouts.py +++ b/Lib/test/test_asyncio/test_timeouts.py @@ -105,6 +105,30 @@ async def test_timeout_zero(self): self.assertLess(t1-t0, 2) self.assertTrue(t0 <= cm.when() <= t1) + async def test_timeout_zero_sleep_zero(self): + loop = asyncio.get_running_loop() + t0 = loop.time() + with self.assertRaises(TimeoutError): + async with asyncio.timeout(0) as cm: + await asyncio.sleep(0) + t1 = loop.time() + self.assertTrue(cm.expired()) + # 2 sec for slow CI boxes + self.assertLess(t1-t0, 2) + self.assertTrue(t0 <= cm.when() <= t1) + + async def test_timeout_in_the_past_sleep_zero(self): + loop = asyncio.get_running_loop() + t0 = loop.time() + with self.assertRaises(TimeoutError): + async with asyncio.timeout(-11) as cm: + await asyncio.sleep(0) + t1 = loop.time() + self.assertTrue(cm.expired()) + # 2 sec for slow CI boxes + self.assertLess(t1-t0, 2) + self.assertTrue(t0 >= cm.when() <= t1) + async def test_foreign_exception_passed(self): with self.assertRaises(KeyError): async with asyncio.timeout(0.01) as cm: diff --git a/Lib/test/test_audit.py b/Lib/test/test_audit.py index 0fa2d74835cba6f1926fdca4a3c9824a6b53fbb1..a7ff038c0936e865f78b3fa65bd3ede5051b0c5e 100644 --- a/Lib/test/test_audit.py +++ b/Lib/test/test_audit.py @@ -155,10 +155,7 @@ def test_http(self): def test_sqlite3(self): - try: - import sqlite3 - except ImportError: - return + sqlite3 = import_helper.import_module("sqlite3") returncode, events, stderr = self.run_python("test_sqlite3") if returncode: self.fail(stderr) @@ -176,5 +173,17 @@ def test_sqlite3(self): self.assertEqual(actual, expected) + def test_sys_getframe(self): + returncode, events, stderr = self.run_python("test_sys_getframe") + if returncode: + self.fail(stderr) + + if support.verbose: + print(*events, sep='\n') + actual = [(ev[0], ev[2]) for ev in events] + expected = [("sys._getframe", "test_sys_getframe")] + + self.assertEqual(actual, expected) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_bool.py b/Lib/test/test_bool.py index 4b32aad2419f4a567a898a4c120def43a4b4cccd..f46f21da8da35178f40221befb46567ec5919d15 100644 --- a/Lib/test/test_bool.py +++ b/Lib/test/test_bool.py @@ -369,6 +369,13 @@ def f(x): f(x) self.assertGreaterEqual(x.count, 1) + def test_bool_new(self): + self.assertIs(bool.__new__(bool), False) + self.assertIs(bool.__new__(bool, 1), True) + self.assertIs(bool.__new__(bool, 0), False) + self.assertIs(bool.__new__(bool, False), False) + self.assertIs(bool.__new__(bool, True), True) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index b457ff6ca849c5d197f4f18c24a6b90d6d9f85bf..521e391b8d5f9db0ebb6986f574a50f599361b12 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -1710,6 +1710,23 @@ def test_repeat_after_setslice(self): self.assertEqual(b1, b) self.assertEqual(b3, b'xcxcxc') + def test_mutating_index(self): + class Boom: + def __index__(self): + b.clear() + return 0 + + with self.subTest("tp_as_mapping"): + b = bytearray(b'Now you see me...') + with self.assertRaises(IndexError): + b[0] = Boom() + + with self.subTest("tp_as_sequence"): + _testcapi = import_helper.import_module('_testcapi') + b = bytearray(b'Now you see me...') + with self.assertRaises(IndexError): + _testcapi.sequence_setitem(b, 0, Boom()) + class AssortedBytesTest(unittest.TestCase): # diff --git a/Lib/test/test_call.py b/Lib/test/test_call.py index 07355e8fa0616c09380fe824d85f9aab404ca02a..a2eec419ab5b413b25a97573e33d863997951985 100644 --- a/Lib/test/test_call.py +++ b/Lib/test/test_call.py @@ -11,6 +11,19 @@ import contextlib +class BadStr(str): + def __eq__(self, other): + return True + def __hash__(self): + # Guaranteed different hash + return str.__hash__(self) ^ 3 + + def __eq__(self, other): + return False + def __hash__(self): + return str.__hash__(self) + + class FunctionCalls(unittest.TestCase): def test_kwargs_order(self): @@ -145,6 +158,18 @@ def test_varargs17_kw(self): self.assertRaisesRegex(TypeError, msg, print, 0, sep=1, end=2, file=3, flush=4, foo=5) + def test_varargs18_kw(self): + # _PyArg_UnpackKeywordsWithVararg() + msg = r"invalid keyword argument for print\(\)$" + with self.assertRaisesRegex(TypeError, msg): + print(0, 1, **{BadStr('foo'): ','}) + + def test_varargs19_kw(self): + # _PyArg_UnpackKeywords() + msg = r"invalid keyword argument for round\(\)$" + with self.assertRaisesRegex(TypeError, msg): + round(1.75, **{BadStr('foo'): 1}) + def test_oldargs0_1(self): msg = r"keys\(\) takes no arguments \(1 given\)" self.assertRaisesRegex(TypeError, msg, {}.keys, 0) diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 7e571ab4f9e593e44e4f3d9114e26228de36c680..a88a17d3c55788cd3590bc33362f459a9d4ded1c 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -722,6 +722,20 @@ def test_export_symbols(self): with self.subTest(name=name): self.assertTrue(hasattr(ctypes.pythonapi, name)) + def test_clear_managed_dict(self): + + class C: + def __init__(self): + self.a = 1 + + c = C() + _testcapi.clear_managed_dict(c) + self.assertEqual(c.__dict__, {}) + c = C() + self.assertEqual(c.__dict__, {'a':1}) + _testcapi.clear_managed_dict(c) + self.assertEqual(c.__dict__, {}) + class TestPendingCalls(unittest.TestCase): diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py index d783af65839ad9d2aa8ccb24b9d9487e0b41acab..9e98edf2146ca942dcb3e1f70da783e5bb03e632 100644 --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -549,10 +549,10 @@ def test_pep_409_verbiage(self): script_name = _make_test_script(script_dir, 'script', script) exitcode, stdout, stderr = assert_python_failure(script_name) text = stderr.decode('ascii').split('\n') - self.assertEqual(len(text), 6) + self.assertEqual(len(text), 5) self.assertTrue(text[0].startswith('Traceback')) self.assertTrue(text[1].startswith(' File ')) - self.assertTrue(text[4].startswith('NameError')) + self.assertTrue(text[3].startswith('NameError')) def test_non_ascii(self): # Mac OS X denies the creation of a file with an invalid UTF-8 name. diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index ab1685d3e5b8a99ea6b18ef9138e9edbb58cfd68..e6194460b787d3616084c72540cd2790f42a5c10 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -108,6 +108,7 @@ def __getitem__(self, key): exec('z = a', g, d) self.assertEqual(d['z'], 12) + @unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI") def test_extended_arg(self): # default: 1000 * 2.5 = 2500 repetitions repeat = int(sys.getrecursionlimit() * 2.5) @@ -542,6 +543,7 @@ def test_yet_more_evil_still_undecodable(self): self.assertIn(b"Non-UTF-8", res.err) @support.cpython_only + @unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI") def test_compiler_recursion_limit(self): # Expected limit is sys.getrecursionlimit() * the scaling factor # in symtable.c (currently 3) @@ -1181,6 +1183,125 @@ def test_complex_single_line_expression(self): self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP', line=1, end_line=1, column=0, end_column=27, occurrence=4) + def test_multiline_assert_rewritten_as_method_call(self): + # GH-94694: Don't crash if pytest rewrites a multiline assert as a + # method call with the same location information: + tree = ast.parse("assert (\n42\n)") + old_node = tree.body[0] + new_node = ast.Expr( + ast.Call( + ast.Attribute( + ast.Name("spam", ast.Load()), + "eggs", + ast.Load(), + ), + [], + [], + ) + ) + ast.copy_location(new_node, old_node) + ast.fix_missing_locations(new_node) + tree.body[0] = new_node + compile(tree, "<test>", "exec") + + def test_push_null_load_global_positions(self): + source_template = """ + import abc, dis + import ast as art + + abc = None + dix = dis + ast = art + + def f(): + {} + """ + for body in [ + " abc.a()", + " art.a()", + " ast.a()", + " dis.a()", + " dix.a()", + " abc[...]()", + " art()()", + " (ast or ...)()", + " [dis]()", + " (dix + ...)()", + ]: + with self.subTest(body): + namespace = {} + source = textwrap.dedent(source_template.format(body)) + exec(source, namespace) + code = namespace["f"].__code__ + self.assertOpcodeSourcePositionIs( + code, + "LOAD_GLOBAL", + line=10, + end_line=10, + column=4, + end_column=7, + ) + + def test_attribute_augassign(self): + source = "(\n lhs \n . \n rhs \n ) += 42" + code = compile(source, "<test>", "exec") + self.assertOpcodeSourcePositionIs( + code, "LOAD_ATTR", line=4, end_line=4, column=5, end_column=8 + ) + self.assertOpcodeSourcePositionIs( + code, "STORE_ATTR", line=4, end_line=4, column=5, end_column=8 + ) + + def test_attribute_del(self): + source = "del (\n lhs \n . \n rhs \n )" + code = compile(source, "<test>", "exec") + self.assertOpcodeSourcePositionIs( + code, "DELETE_ATTR", line=4, end_line=4, column=5, end_column=8 + ) + + def test_attribute_load(self): + source = "(\n lhs \n . \n rhs \n )" + code = compile(source, "<test>", "exec") + self.assertOpcodeSourcePositionIs( + code, "LOAD_ATTR", line=4, end_line=4, column=5, end_column=8 + ) + + def test_attribute_store(self): + source = "(\n lhs \n . \n rhs \n ) = 42" + code = compile(source, "<test>", "exec") + self.assertOpcodeSourcePositionIs( + code, "STORE_ATTR", line=4, end_line=4, column=5, end_column=8 + ) + + def test_method_call(self): + source = "(\n lhs \n . \n rhs \n )()" + code = compile(source, "<test>", "exec") + self.assertOpcodeSourcePositionIs( + code, "LOAD_ATTR", line=4, end_line=4, column=5, end_column=8 + ) + self.assertOpcodeSourcePositionIs( + code, "CALL", line=4, end_line=5, column=5, end_column=10 + ) + + def test_weird_attribute_position_regressions(self): + def f(): + (bar. + baz) + (bar. + baz( + )) + files().setdefault( + 0 + ).setdefault( + 0 + ) + for line, end_line, column, end_column in f.__code__.co_positions(): + self.assertIsNotNone(line) + self.assertIsNotNone(end_line) + self.assertIsNotNone(column) + self.assertIsNotNone(end_column) + self.assertLessEqual((line, column), (end_line, end_column)) + class TestExpressionStackSize(unittest.TestCase): # These tests check that the computed stack size for a code object diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py index f50255bd575601ba18920c7c01f9a94d86a25b63..fe9fdc4f44d37ba9a918844dbd23a5ac86d4014b 100644 --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -485,7 +485,7 @@ def test_cancel_futures_wait_false(self): t = ThreadPoolExecutor() t.submit(sleep_and_print, .1, "apple") t.shutdown(wait=False, cancel_futures=True) - """.format(executor_type=self.executor_type.__name__)) + """) # Errors in atexit hooks don't change the process exit code, check # stderr manually. self.assertFalse(err) @@ -932,6 +932,33 @@ def submit(pool): with futures.ProcessPoolExecutor(1, mp_context=mp.get_context('fork')) as workers: workers.submit(tuple) + def test_executor_map_current_future_cancel(self): + stop_event = threading.Event() + log = [] + + def log_n_wait(ident): + log.append(f"{ident=} started") + try: + stop_event.wait() + finally: + log.append(f"{ident=} stopped") + + with self.executor_type(max_workers=1) as pool: + # submit work to saturate the pool + fut = pool.submit(log_n_wait, ident="first") + try: + with contextlib.closing( + pool.map(log_n_wait, ["second", "third"], timeout=0) + ) as gen: + with self.assertRaises(TimeoutError): + next(gen) + finally: + stop_event.set() + fut.result() + # ident='second' is cancelled as a result of raising a TimeoutError + # ident='third' is cancelled because it remained in the collection of futures + self.assertListEqual(log, ["ident='first' started", "ident='first' stopped"]) + class ProcessPoolExecutorTest(ExecutorTest): diff --git a/Lib/test/test_cppext.py b/Lib/test/test_cppext.py index 8673911ecfae5d9656409135d0364003cf553a2c..465894d24e7dfc6638cd3674deb1d143d1611a93 100644 --- a/Lib/test/test_cppext.py +++ b/Lib/test/test_cppext.py @@ -4,6 +4,7 @@ import sys import unittest import subprocess +import sysconfig from test import support from test.support import os_helper @@ -17,22 +18,27 @@ @support.requires_subprocess() class TestCPPExt(unittest.TestCase): def test_build_cpp11(self): - self.check_build(False) + self.check_build(False, '_testcpp11ext') def test_build_cpp03(self): - self.check_build(True) + self.check_build(True, '_testcpp03ext') # With MSVC, the linker fails with: cannot open file 'python311.lib' # https://github.com/python/cpython/pull/32175#issuecomment-1111175897 @unittest.skipIf(MS_WINDOWS, 'test fails on Windows') + # Building and running an extension in clang sanitizing mode is not + # straightforward + @unittest.skipIf( + '-fsanitize' in (sysconfig.get_config_var('PY_CFLAGS') or ''), + 'test does not work with analyzing builds') # the test uses venv+pip: skip if it's not available @support.requires_venv_with_pip() - def check_build(self, std_cpp03): + def check_build(self, std_cpp03, extension_name): # Build in a temporary directory with os_helper.temp_cwd(): - self._check_build(std_cpp03) + self._check_build(std_cpp03, extension_name) - def _check_build(self, std_cpp03): + def _check_build(self, std_cpp03, extension_name): venv_dir = 'env' verbose = support.verbose @@ -52,22 +58,47 @@ def _check_build(self, std_cpp03): else: python = os.path.join(venv_dir, 'bin', python_exe) + def run_cmd(operation, cmd): + if verbose: + print('Run:', ' '.join(cmd)) + subprocess.run(cmd, check=True) + else: + proc = subprocess.run(cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True) + if proc.returncode: + print(proc.stdout, end='') + self.fail( + f"{operation} failed with exit code {proc.returncode}") + # Build the C++ extension cmd = [python, '-X', 'dev', SETUP_TESTCPPEXT, 'build_ext', '--verbose'] if std_cpp03: cmd.append('-std=c++03') - if verbose: - print('Run:', ' '.join(cmd)) - subprocess.run(cmd, check=True) - else: - proc = subprocess.run(cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True) - if proc.returncode: - print(proc.stdout, end='') - self.fail(f"Build failed with exit code {proc.returncode}") + run_cmd('Build', cmd) + + # Install the C++ extension + cmd = [python, '-X', 'dev', + SETUP_TESTCPPEXT, 'install'] + run_cmd('Install', cmd) + + # Do a reference run. Until we test that running python + # doesn't leak references (gh-94755), run it so one can manually check + # -X showrefcount results against this baseline. + cmd = [python, + '-X', 'dev', + '-X', 'showrefcount', + '-c', 'pass'] + run_cmd('Reference run', cmd) + + # Import the C++ extension + cmd = [python, + '-X', 'dev', + '-X', 'showrefcount', + '-c', f"import {extension_name}"] + run_cmd('Import', cmd) if __name__ == "__main__": diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index b5f1bd4af888d3434715721be7ad3defbc0d08d3..4386e113745a4f6dbc58378a547cb5c51bcabaed 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -21,6 +21,11 @@ except ImportError: _testcapi = None +try: + import xxsubtype +except ImportError: + xxsubtype = None + class OperatorsTest(unittest.TestCase): @@ -299,6 +304,7 @@ def test_explicit_reverse_methods(self): self.assertEqual(float.__rsub__(3.0, 1), -2.0) @support.impl_detail("the module 'xxsubtype' is internal") + @unittest.skipIf(xxsubtype is None, "requires xxsubtype module") def test_spam_lists(self): # Testing spamlist operations... import copy, xxsubtype as spam @@ -343,6 +349,7 @@ def foo(self): return 1 self.assertEqual(a.getstate(), 42) @support.impl_detail("the module 'xxsubtype' is internal") + @unittest.skipIf(xxsubtype is None, "requires xxsubtype module") def test_spam_dicts(self): # Testing spamdict operations... import copy, xxsubtype as spam @@ -1600,6 +1607,7 @@ def test_refleaks_in_classmethod___init__(self): self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) @support.impl_detail("the module 'xxsubtype' is internal") + @unittest.skipIf(xxsubtype is None, "requires xxsubtype module") def test_classmethods_in_c(self): # Testing C-based class methods... import xxsubtype as spam @@ -1683,6 +1691,7 @@ def test_refleaks_in_staticmethod___init__(self): self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) @support.impl_detail("the module 'xxsubtype' is internal") + @unittest.skipIf(xxsubtype is None, "requires xxsubtype module") def test_staticmethods_in_c(self): # Testing C-based static methods... import xxsubtype as spam diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 440e4ed5eacfb0b0197a6f1e8810ab7cac973860..f07e7c8605478287800ee5c937b268315ddb2fa4 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -744,7 +744,7 @@ def extended_arg_quick(): %3d 0 RESUME 0 %3d 2 LOAD_CONST 1 (Ellipsis) - 4 EXTENDED_ARG_QUICK 1 + 4 EXTENDED_ARG 1 6 UNPACK_EX 256 8 STORE_FAST 0 (_) 10 STORE_FAST 0 (_) diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py index 7c799697d9c225fdc20e80886773a8a16ffa73d9..65e215f1cdda4a6f8e5f098fd7e3019a04d0230a 100644 --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -2854,7 +2854,7 @@ def test_testmod(): r""" # Skip the test: the filesystem encoding is unable to encode the filename supports_unicode = False -if supports_unicode and not support.has_no_debug_ranges(): +if supports_unicode: def test_unicode(): """ Check doctest with a non-ascii filename: @@ -2876,10 +2876,8 @@ def test_unicode(): """ Traceback (most recent call last): File ... exec(compile(example.source, filename, "single", - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "<doctest foo-bär@baz[0]>", line 1, in <module> raise Exception('clé') - ^^^^^^^^^^^^^^^^^^^^^^ Exception: clé TestResults(failed=1, attempted=1) """ diff --git a/Lib/test/test_dynamic.py b/Lib/test/test_dynamic.py index 3e0fcf4d158f8a516fa9a2c43b031c28130c3899..e896fc703c9a8b44ababea802880e1e1e7252e2b 100644 --- a/Lib/test/test_dynamic.py +++ b/Lib/test/test_dynamic.py @@ -1,6 +1,7 @@ # Test the most dynamic corner cases of Python's runtime semantics. import builtins +import sys import unittest from test.support import swap_item, swap_attr @@ -139,12 +140,14 @@ class MyGlobals(dict): def __missing__(self, key): return int(key.removeprefix("_number_")) - code = "lambda: " + "+".join(f"_number_{i}" for i in range(1000)) - sum_1000 = eval(code, MyGlobals()) - expected = sum(range(1000)) + # 1,000 on most systems + limit = sys.getrecursionlimit() + code = "lambda: " + "+".join(f"_number_{i}" for i in range(limit)) + sum_func = eval(code, MyGlobals()) + expected = sum(range(limit)) # Warm up the the function for quickening (PEP 659) for _ in range(30): - self.assertEqual(sum_1000(), expected) + self.assertEqual(sum_func(), expected) if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index 0bf679b4c56ca0e70c2edab038c618fec4defbb8..44b405740c440313303d899d4e1cd5cff17fac92 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -3047,33 +3047,43 @@ def test_formatdate_usegmt(self): # parsedate and parsedate_tz will become deprecated interfaces someday def test_parsedate_returns_None_for_invalid_strings(self): - self.assertIsNone(utils.parsedate('')) - self.assertIsNone(utils.parsedate_tz('')) - self.assertIsNone(utils.parsedate(' ')) - self.assertIsNone(utils.parsedate_tz(' ')) - self.assertIsNone(utils.parsedate('0')) - self.assertIsNone(utils.parsedate_tz('0')) - self.assertIsNone(utils.parsedate('A Complete Waste of Time')) - self.assertIsNone(utils.parsedate_tz('A Complete Waste of Time')) - self.assertIsNone(utils.parsedate_tz('Wed, 3 Apr 2002 12.34.56.78+0800')) + # See also test_parsedate_to_datetime_with_invalid_raises_valueerror + # in test_utils. + invalid_dates = [ + '', + ' ', + '0', + 'A Complete Waste of Time', + 'Wed, 3 Apr 2002 12.34.56.78+0800', + '17 June , 2022', + 'Friday, -Nov-82 16:14:55 EST', + 'Friday, Nov--82 16:14:55 EST', + 'Friday, 19-Nov- 16:14:55 EST', + ] + for dtstr in invalid_dates: + with self.subTest(dtstr=dtstr): + self.assertIsNone(utils.parsedate(dtstr)) + self.assertIsNone(utils.parsedate_tz(dtstr)) # Not a part of the spec but, but this has historically worked: self.assertIsNone(utils.parsedate(None)) self.assertIsNone(utils.parsedate_tz(None)) def test_parsedate_compact(self): + self.assertEqual(utils.parsedate_tz('Wed, 3 Apr 2002 14:58:26 +0800'), + (2002, 4, 3, 14, 58, 26, 0, 1, -1, 28800)) # The FWS after the comma is optional - self.assertEqual(utils.parsedate('Wed,3 Apr 2002 14:58:26 +0800'), - utils.parsedate('Wed, 3 Apr 2002 14:58:26 +0800')) + self.assertEqual(utils.parsedate_tz('Wed,3 Apr 2002 14:58:26 +0800'), + (2002, 4, 3, 14, 58, 26, 0, 1, -1, 28800)) + # The comma is optional + self.assertEqual(utils.parsedate_tz('Wed 3 Apr 2002 14:58:26 +0800'), + (2002, 4, 3, 14, 58, 26, 0, 1, -1, 28800)) def test_parsedate_no_dayofweek(self): - eq = self.assertEqual - eq(utils.parsedate_tz('25 Feb 2003 13:47:26 -0800'), - (2003, 2, 25, 13, 47, 26, 0, 1, -1, -28800)) - - def test_parsedate_compact_no_dayofweek(self): eq = self.assertEqual eq(utils.parsedate_tz('5 Feb 2003 13:47:26 -0800'), (2003, 2, 5, 13, 47, 26, 0, 1, -1, -28800)) + eq(utils.parsedate_tz('February 5, 2003 13:47:26 -0800'), + (2003, 2, 5, 13, 47, 26, 0, 1, -1, -28800)) def test_parsedate_no_space_before_positive_offset(self): self.assertEqual(utils.parsedate_tz('Wed, 3 Apr 2002 14:58:26+0800'), @@ -3084,7 +3094,6 @@ def test_parsedate_no_space_before_negative_offset(self): self.assertEqual(utils.parsedate_tz('Wed, 3 Apr 2002 14:58:26-0800'), (2002, 4, 3, 14, 58, 26, 0, 1, -1, -28800)) - def test_parsedate_accepts_time_with_dots(self): eq = self.assertEqual eq(utils.parsedate_tz('5 Feb 2003 13.47.26 -0800'), @@ -3092,6 +3101,20 @@ def test_parsedate_accepts_time_with_dots(self): eq(utils.parsedate_tz('5 Feb 2003 13.47 -0800'), (2003, 2, 5, 13, 47, 0, 0, 1, -1, -28800)) + def test_parsedate_rfc_850(self): + self.assertEqual(utils.parsedate_tz('Friday, 19-Nov-82 16:14:55 EST'), + (1982, 11, 19, 16, 14, 55, 0, 1, -1, -18000)) + + def test_parsedate_no_seconds(self): + self.assertEqual(utils.parsedate_tz('Wed, 3 Apr 2002 14:58 +0800'), + (2002, 4, 3, 14, 58, 0, 0, 1, -1, 28800)) + + def test_parsedate_dot_time_delimiter(self): + self.assertEqual(utils.parsedate_tz('Wed, 3 Apr 2002 14.58.26 +0800'), + (2002, 4, 3, 14, 58, 26, 0, 1, -1, 28800)) + self.assertEqual(utils.parsedate_tz('Wed, 3 Apr 2002 14.58 +0800'), + (2002, 4, 3, 14, 58, 0, 0, 1, -1, 28800)) + def test_parsedate_acceptable_to_time_functions(self): eq = self.assertEqual timetup = utils.parsedate('5 Feb 2003 13:47:26 -0800') diff --git a/Lib/test/test_email/test_utils.py b/Lib/test/test_email/test_utils.py index e3d3eaebc93693a911f657537ec05b4ef7dffee1..78afb358035e8122cd7d76b9f7bc40d260239f60 100644 --- a/Lib/test/test_email/test_utils.py +++ b/Lib/test/test_email/test_utils.py @@ -49,12 +49,21 @@ def test_parsedate_to_datetime_naive(self): self.naive_dt) def test_parsedate_to_datetime_with_invalid_raises_valueerror(self): - invalid_dates = ['', - '0', - 'A Complete Waste of Time' - 'Tue, 06 Jun 2017 27:39:33 +0600', - 'Tue, 06 Jun 2017 07:39:33 +2600', - 'Tue, 06 Jun 2017 27:39:33'] + # See also test_parsedate_returns_None_for_invalid_strings in test_email. + invalid_dates = [ + '', + ' ', + '0', + 'A Complete Waste of Time', + 'Wed, 3 Apr 2002 12.34.56.78+0800' + 'Tue, 06 Jun 2017 27:39:33 +0600', + 'Tue, 06 Jun 2017 07:39:33 +2600', + 'Tue, 06 Jun 2017 27:39:33', + '17 June , 2022', + 'Friday, -Nov-82 16:14:55 EST', + 'Friday, Nov--82 16:14:55 EST', + 'Friday, 19-Nov- 16:14:55 EST', + ] for dtstr in invalid_dates: with self.subTest(dtstr=dtstr): self.assertRaises(ValueError, utils.parsedate_to_datetime, dtstr) diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py index aec18c79f7249e65a40da5fbdaaaae7007ca7d80..9d16fbc2777d70029ce7e171e95197824503996d 100644 --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -2646,7 +2646,10 @@ class Private(Enum): self.assertEqual(Private._Private__corporal, 'Radar') self.assertEqual(Private._Private__major_, 'Hoolihan') - @unittest.skip("Accessing all values retained for performance reasons, see GH-93910") + @unittest.skipIf( + python_version <= (3, 13), + 'member.member access currently deprecated', + ) def test_exception_for_member_from_member_access(self): with self.assertRaisesRegex(AttributeError, "<enum .Di.> member has no attribute .NO."): class Di(Enum): @@ -2654,6 +2657,17 @@ class Di(Enum): NO = 0 nope = Di.YES.NO + @unittest.skipIf( + python_version > (3, 13), + 'member.member access now raises', + ) + def test_warning_for_member_from_member_access(self): + with self.assertWarnsRegex(DeprecationWarning, '`member.member` access .* is deprecated and will be removed in 3.14'): + class Di(Enum): + YES = 1 + NO = 0 + warn = Di.YES.NO + self.assertIs(warn, Di.NO) def test_dynamic_members_with_static_methods(self): # @@ -2688,12 +2702,15 @@ def test_repr_with_dataclass(self): @dataclass class Foo: __qualname__ = 'Foo' - a: int = 0 + a: int class Entries(Foo, Enum): - ENTRY1 = Foo(1) + ENTRY1 = 1 + self.assertTrue(isinstance(Entries.ENTRY1, Foo)) + self.assertTrue(Entries._member_type_ is Foo, Entries._member_type_) + self.assertTrue(Entries.ENTRY1.value == Foo(1), Entries.ENTRY1.value) self.assertEqual(repr(Entries.ENTRY1), '<Entries.ENTRY1: Foo(a=1)>') - def test_repr_with_non_data_type_mixin(self): + def test_repr_with_init_data_type_mixin(self): # non-data_type is a mixin that doesn't define __new__ class Foo: def __init__(self, a): @@ -2701,10 +2718,23 @@ def __init__(self, a): def __repr__(self): return f'Foo(a={self.a!r})' class Entries(Foo, Enum): - ENTRY1 = Foo(1) - + ENTRY1 = 1 + # self.assertEqual(repr(Entries.ENTRY1), '<Entries.ENTRY1: Foo(a=1)>') + def test_repr_and_str_with_non_data_type_mixin(self): + # non-data_type is a mixin that doesn't define __new__ + class Foo: + def __repr__(self): + return 'Foo' + def __str__(self): + return 'ooF' + class Entries(Foo, Enum): + ENTRY1 = 1 + # + self.assertEqual(repr(Entries.ENTRY1), 'Foo') + self.assertEqual(str(Entries.ENTRY1), 'ooF') + def test_value_backup_assign(self): # check that enum will add missing values when custom __new__ does not class Some(Enum): diff --git a/Lib/test/test_fileinput.py b/Lib/test/test_fileinput.py index 819200010a2230c21c8934cb3901c24b7d475640..ac20c74baa09e27df2a0f52ca522e00830aa37c0 100644 --- a/Lib/test/test_fileinput.py +++ b/Lib/test/test_fileinput.py @@ -326,6 +326,16 @@ def test_inplace_binary_write_mode(self): with open(temp_file, 'rb') as f: self.assertEqual(f.read(), b'New line.') + def test_inplace_encoding_errors(self): + temp_file = self.writeTmp(b'Initial text \x88', mode='wb') + with FileInput(temp_file, inplace=True, + encoding="ascii", errors="replace") as fobj: + line = fobj.readline() + self.assertEqual(line, 'Initial text \ufffd') + print("New line \x88") + with open(temp_file, 'rb') as f: + self.assertEqual(f.read().rstrip(b'\r\n'), b'New line ?') + def test_file_hook_backward_compatibility(self): def old_hook(filename, mode): return io.StringIO("I used to receive only filename and mode") diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index 672ec141155530b3279d6d8e671565ced9786747..b5e271abc86a5ec5b1a0a2741ec39db3cd43182c 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -831,6 +831,11 @@ def test_inf_nan(self): self.assertRaises(TypeError, round, NAN, "ceci n'est pas un integer") self.assertRaises(TypeError, round, -0.0, 1j) + def test_inf_nan_ndigits(self): + self.assertEqual(round(INF, 0), INF) + self.assertEqual(round(-INF, 0), -INF) + self.assertTrue(math.isnan(round(NAN, 0))) + def test_large_n(self): for n in [324, 325, 400, 2**31-1, 2**31, 2**32, 2**100]: self.assertEqual(round(123.456, n), 123.456) diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index 9815b7c28f2f40dd4ee54a4b74e071aee730f616..bf3a5b0bbccdfb968d74f55a14edd73682cc921d 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -346,10 +346,39 @@ def test_ast_line_numbers_multiline_fstring(self): self.assertEqual(binop.lineno, 4) self.assertEqual(binop.left.lineno, 4) self.assertEqual(binop.right.lineno, 6) - self.assertEqual(binop.col_offset, 4) - self.assertEqual(binop.left.col_offset, 4) + self.assertEqual(binop.col_offset, 3) + self.assertEqual(binop.left.col_offset, 3) self.assertEqual(binop.right.col_offset, 7) + expr = """ +a = f''' + {blech} + ''' +""" + t = ast.parse(expr) + self.assertEqual(type(t), ast.Module) + self.assertEqual(len(t.body), 1) + # Check f'...' + self.assertEqual(type(t.body[0]), ast.Assign) + self.assertEqual(type(t.body[0].value), ast.JoinedStr) + self.assertEqual(len(t.body[0].value.values), 3) + self.assertEqual(type(t.body[0].value.values[1]), ast.FormattedValue) + self.assertEqual(t.body[0].lineno, 2) + self.assertEqual(t.body[0].value.lineno, 2) + self.assertEqual(t.body[0].value.values[0].lineno, 2) + self.assertEqual(t.body[0].value.values[1].lineno, 2) + self.assertEqual(t.body[0].value.values[2].lineno, 2) + self.assertEqual(t.body[0].col_offset, 0) + self.assertEqual(t.body[0].value.col_offset, 4) + self.assertEqual(t.body[0].value.values[0].col_offset, 4) + self.assertEqual(t.body[0].value.values[1].col_offset, 4) + self.assertEqual(t.body[0].value.values[2].col_offset, 4) + # Check {blech} + self.assertEqual(t.body[0].value.values[1].value.lineno, 3) + self.assertEqual(t.body[0].value.values[1].value.end_lineno, 3) + self.assertEqual(t.body[0].value.values[1].value.col_offset, 11) + self.assertEqual(t.body[0].value.values[1].value.end_col_offset, 16) + def test_ast_line_numbers_with_parentheses(self): expr = """ x = ( diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 767d2a9c1aea96b20762cfb9a632029923bacd27..a4b098a2a5b8ede600d046b460497185a3836607 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -2003,7 +2003,7 @@ class D(collections.defaultdict): c.MutableSequence.register(D) bases = [c.MutableSequence, c.MutableMapping] for haystack in permutations(bases): - m = mro(D, bases) + m = mro(D, haystack) self.assertEqual(m, [D, c.MutableSequence, c.Sequence, c.Reversible, collections.defaultdict, dict, c.MutableMapping, c.Mapping, c.Collection, c.Sized, c.Iterable, c.Container, diff --git a/Lib/test/test_getargs2.py b/Lib/test/test_getargs2.py index 7c11c6cd33a84da95091fb6587e7c042d8e38ee6..1d5c7fbaa1510ae6bac54a70b17bc9b7a05c53f7 100644 --- a/Lib/test/test_getargs2.py +++ b/Lib/test/test_getargs2.py @@ -746,6 +746,33 @@ def test_surrogate_keyword(self): "'\udc80' is an invalid keyword argument for this function"): getargs_keyword_only(1, 2, **{'\uDC80': 10}) + def test_weird_str_subclass(self): + class BadStr(str): + def __eq__(self, other): + return True + def __hash__(self): + # Guaranteed different hash + return str.__hash__(self) ^ 3 + with self.assertRaisesRegex(TypeError, + "invalid keyword argument for this function"): + getargs_keyword_only(1, 2, **{BadStr("keyword_only"): 3}) + with self.assertRaisesRegex(TypeError, + "invalid keyword argument for this function"): + getargs_keyword_only(1, 2, **{BadStr("monster"): 666}) + + def test_weird_str_subclass2(self): + class BadStr(str): + def __eq__(self, other): + return False + def __hash__(self): + return str.__hash__(self) + with self.assertRaisesRegex(TypeError, + "invalid keyword argument for this function"): + getargs_keyword_only(1, 2, **{BadStr("keyword_only"): 3}) + with self.assertRaisesRegex(TypeError, + "invalid keyword argument for this function"): + getargs_keyword_only(1, 2, **{BadStr("monster"): 666}) + class PositionalOnlyAndKeywords_TestCase(unittest.TestCase): from _testcapi import getargs_positional_only_and_keywords as getargs @@ -877,9 +904,19 @@ def test_s_hash(self): def test_s_hash_int(self): # "s#" without PY_SSIZE_T_CLEAN defined. from _testcapi import getargs_s_hash_int - self.assertRaises(SystemError, getargs_s_hash_int, "abc") - self.assertRaises(SystemError, getargs_s_hash_int, x=42) - # getargs_s_hash_int() don't raise SystemError because skipitem() is not called. + from _testcapi import getargs_s_hash_int2 + buf = bytearray([1, 2]) + self.assertRaises(SystemError, getargs_s_hash_int, buf, "abc") + self.assertRaises(SystemError, getargs_s_hash_int, buf, x=42) + self.assertRaises(SystemError, getargs_s_hash_int, buf, x="abc") + self.assertRaises(SystemError, getargs_s_hash_int2, buf, ("abc",)) + self.assertRaises(SystemError, getargs_s_hash_int2, buf, x=42) + self.assertRaises(SystemError, getargs_s_hash_int2, buf, x="abc") + buf.append(3) # still mutable -- not locked by a buffer export + # getargs_s_hash_int(buf) may not raise SystemError because skipitem() + # is not called. But it is an implementation detail. + # getargs_s_hash_int(buf) + # getargs_s_hash_int2(buf) def test_z(self): from _testcapi import getargs_z diff --git a/Lib/test/test_importlib/data01/__init__.py b/Lib/test/test_importlib/resources/data01/__init__.py similarity index 100% rename from Lib/test/test_importlib/data01/__init__.py rename to Lib/test/test_importlib/resources/data01/__init__.py diff --git a/Lib/test/test_importlib/data01/binary.file b/Lib/test/test_importlib/resources/data01/binary.file similarity index 100% rename from Lib/test/test_importlib/data01/binary.file rename to Lib/test/test_importlib/resources/data01/binary.file diff --git a/Lib/test/test_importlib/data01/subdirectory/__init__.py b/Lib/test/test_importlib/resources/data01/subdirectory/__init__.py similarity index 100% rename from Lib/test/test_importlib/data01/subdirectory/__init__.py rename to Lib/test/test_importlib/resources/data01/subdirectory/__init__.py diff --git a/Lib/test/test_importlib/data01/subdirectory/binary.file b/Lib/test/test_importlib/resources/data01/subdirectory/binary.file similarity index 100% rename from Lib/test/test_importlib/data01/subdirectory/binary.file rename to Lib/test/test_importlib/resources/data01/subdirectory/binary.file diff --git a/Lib/test/test_importlib/data01/utf-16.file b/Lib/test/test_importlib/resources/data01/utf-16.file similarity index 100% rename from Lib/test/test_importlib/data01/utf-16.file rename to Lib/test/test_importlib/resources/data01/utf-16.file diff --git a/Lib/test/test_importlib/data01/utf-8.file b/Lib/test/test_importlib/resources/data01/utf-8.file similarity index 100% rename from Lib/test/test_importlib/data01/utf-8.file rename to Lib/test/test_importlib/resources/data01/utf-8.file diff --git a/Lib/test/test_importlib/data02/__init__.py b/Lib/test/test_importlib/resources/data02/__init__.py similarity index 100% rename from Lib/test/test_importlib/data02/__init__.py rename to Lib/test/test_importlib/resources/data02/__init__.py diff --git a/Lib/test/test_importlib/data02/one/__init__.py b/Lib/test/test_importlib/resources/data02/one/__init__.py similarity index 100% rename from Lib/test/test_importlib/data02/one/__init__.py rename to Lib/test/test_importlib/resources/data02/one/__init__.py diff --git a/Lib/test/test_importlib/data02/one/resource1.txt b/Lib/test/test_importlib/resources/data02/one/resource1.txt similarity index 100% rename from Lib/test/test_importlib/data02/one/resource1.txt rename to Lib/test/test_importlib/resources/data02/one/resource1.txt diff --git a/Lib/test/test_importlib/data02/two/__init__.py b/Lib/test/test_importlib/resources/data02/two/__init__.py similarity index 100% rename from Lib/test/test_importlib/data02/two/__init__.py rename to Lib/test/test_importlib/resources/data02/two/__init__.py diff --git a/Lib/test/test_importlib/data02/two/resource2.txt b/Lib/test/test_importlib/resources/data02/two/resource2.txt similarity index 100% rename from Lib/test/test_importlib/data02/two/resource2.txt rename to Lib/test/test_importlib/resources/data02/two/resource2.txt diff --git a/Lib/test/test_importlib/data03/__init__.py b/Lib/test/test_importlib/resources/data03/__init__.py similarity index 100% rename from Lib/test/test_importlib/data03/__init__.py rename to Lib/test/test_importlib/resources/data03/__init__.py diff --git a/Lib/test/test_importlib/data03/namespace/portion1/__init__.py b/Lib/test/test_importlib/resources/data03/namespace/portion1/__init__.py similarity index 100% rename from Lib/test/test_importlib/data03/namespace/portion1/__init__.py rename to Lib/test/test_importlib/resources/data03/namespace/portion1/__init__.py diff --git a/Lib/test/test_importlib/data03/namespace/portion2/__init__.py b/Lib/test/test_importlib/resources/data03/namespace/portion2/__init__.py similarity index 100% rename from Lib/test/test_importlib/data03/namespace/portion2/__init__.py rename to Lib/test/test_importlib/resources/data03/namespace/portion2/__init__.py diff --git a/Lib/test/test_importlib/data03/namespace/resource1.txt b/Lib/test/test_importlib/resources/data03/namespace/resource1.txt similarity index 100% rename from Lib/test/test_importlib/data03/namespace/resource1.txt rename to Lib/test/test_importlib/resources/data03/namespace/resource1.txt diff --git a/Lib/test/test_importlib/namespacedata01/binary.file b/Lib/test/test_importlib/resources/namespacedata01/binary.file similarity index 100% rename from Lib/test/test_importlib/namespacedata01/binary.file rename to Lib/test/test_importlib/resources/namespacedata01/binary.file diff --git a/Lib/test/test_importlib/namespacedata01/utf-16.file b/Lib/test/test_importlib/resources/namespacedata01/utf-16.file similarity index 100% rename from Lib/test/test_importlib/namespacedata01/utf-16.file rename to Lib/test/test_importlib/resources/namespacedata01/utf-16.file diff --git a/Lib/test/test_importlib/namespacedata01/utf-8.file b/Lib/test/test_importlib/resources/namespacedata01/utf-8.file similarity index 100% rename from Lib/test/test_importlib/namespacedata01/utf-8.file rename to Lib/test/test_importlib/resources/namespacedata01/utf-8.file diff --git a/Lib/test/test_importlib/test_compatibilty_files.py b/Lib/test/test_importlib/resources/test_compatibilty_files.py similarity index 99% rename from Lib/test/test_importlib/test_compatibilty_files.py rename to Lib/test/test_importlib/resources/test_compatibilty_files.py index 9a823f2d9305837c2ac9c440bb4e901b6d845480..6fa18a24973f6444370de77159212ec91fdd003a 100644 --- a/Lib/test/test_importlib/test_compatibilty_files.py +++ b/Lib/test/test_importlib/resources/test_compatibilty_files.py @@ -8,7 +8,7 @@ wrap_spec, ) -from .resources import util +from . import util class CompatibilityFilesTests(unittest.TestCase): diff --git a/Lib/test/test_importlib/test_contents.py b/Lib/test/test_importlib/resources/test_contents.py similarity index 97% rename from Lib/test/test_importlib/test_contents.py rename to Lib/test/test_importlib/resources/test_contents.py index 3323bf5b5cf5688ec78496a88c0e430efcfca1ff..1a13f043a86f034d709810289d9d524f734fbf33 100644 --- a/Lib/test/test_importlib/test_contents.py +++ b/Lib/test/test_importlib/resources/test_contents.py @@ -2,7 +2,7 @@ from importlib import resources from . import data01 -from .resources import util +from . import util class ContentsTests: diff --git a/Lib/test/test_importlib/test_files.py b/Lib/test/test_importlib/resources/test_files.py similarity index 94% rename from Lib/test/test_importlib/test_files.py rename to Lib/test/test_importlib/resources/test_files.py index b9170d83bea912ae76e0ede26098fa01fd0e61b1..779e5a12b5d536be08318ec7b000ef354533bffd 100644 --- a/Lib/test/test_importlib/test_files.py +++ b/Lib/test/test_importlib/resources/test_files.py @@ -2,9 +2,9 @@ import unittest from importlib import resources -from importlib.abc import Traversable +from importlib.resources.abc import Traversable from . import data01 -from .resources import util +from . import util class FilesTests: diff --git a/Lib/test/test_importlib/test_open.py b/Lib/test/test_importlib/resources/test_open.py similarity index 98% rename from Lib/test/test_importlib/test_open.py rename to Lib/test/test_importlib/resources/test_open.py index df75e343d2c5b7770bb3709fa447dbdd2d62ad86..0554c41ba67d0ef723beda0dcf252953d1d1994a 100644 --- a/Lib/test/test_importlib/test_open.py +++ b/Lib/test/test_importlib/resources/test_open.py @@ -2,7 +2,7 @@ from importlib import resources from . import data01 -from .resources import util +from . import util class CommonBinaryTests(util.CommonTests, unittest.TestCase): diff --git a/Lib/test/test_importlib/test_path.py b/Lib/test/test_importlib/resources/test_path.py similarity index 98% rename from Lib/test/test_importlib/test_path.py rename to Lib/test/test_importlib/resources/test_path.py index 6fc41f301d1cab196a26bacb7b8bd1a1535a62c3..adcf75feea78ec000037f5289e330e79c1756c79 100644 --- a/Lib/test/test_importlib/test_path.py +++ b/Lib/test/test_importlib/resources/test_path.py @@ -3,7 +3,7 @@ from importlib import resources from . import data01 -from .resources import util +from . import util class CommonTests(util.CommonTests, unittest.TestCase): diff --git a/Lib/test/test_importlib/test_read.py b/Lib/test/test_importlib/resources/test_read.py similarity index 98% rename from Lib/test/test_importlib/test_read.py rename to Lib/test/test_importlib/resources/test_read.py index ebd72267776d969bd72a816e7d5cc21713406935..0ca8ee9d02856b6a796292812039e415733f9a05 100644 --- a/Lib/test/test_importlib/test_read.py +++ b/Lib/test/test_importlib/resources/test_read.py @@ -2,7 +2,7 @@ from importlib import import_module, resources from . import data01 -from .resources import util +from . import util class CommonBinaryTests(util.CommonTests, unittest.TestCase): diff --git a/Lib/test/test_importlib/test_reader.py b/Lib/test/test_importlib/resources/test_reader.py similarity index 100% rename from Lib/test/test_importlib/test_reader.py rename to Lib/test/test_importlib/resources/test_reader.py diff --git a/Lib/test/test_importlib/test_resource.py b/Lib/test/test_importlib/resources/test_resource.py similarity index 99% rename from Lib/test/test_importlib/test_resource.py rename to Lib/test/test_importlib/resources/test_resource.py index 834b8bd8a28189718cdadf459ce784fb62f3035e..1d6df0cc8431730fc453ceff5f7b34549591a176 100644 --- a/Lib/test/test_importlib/test_resource.py +++ b/Lib/test/test_importlib/resources/test_resource.py @@ -5,7 +5,7 @@ from . import data01 from . import zipdata01, zipdata02 -from .resources import util +from . import util from importlib import resources, import_module from test.support import import_helper from test.support.os_helper import unlink diff --git a/Lib/test/test_importlib/update-zips.py b/Lib/test/test_importlib/resources/update-zips.py similarity index 100% rename from Lib/test/test_importlib/update-zips.py rename to Lib/test/test_importlib/resources/update-zips.py diff --git a/Lib/test/test_importlib/resources/util.py b/Lib/test/test_importlib/resources/util.py index 11c8aa80806dceb4e0cd15b5c35ab9b4f217120d..eb2291f15de1228c170cd08551e17f6828d3eb37 100644 --- a/Lib/test/test_importlib/resources/util.py +++ b/Lib/test/test_importlib/resources/util.py @@ -5,9 +5,9 @@ import types from pathlib import Path, PurePath -from .. import data01 -from .. import zipdata01 -from importlib.abc import ResourceReader +from . import data01 +from . import zipdata01 +from importlib.resources.abc import ResourceReader from test.support import import_helper diff --git a/Lib/test/test_importlib/zipdata01/__init__.py b/Lib/test/test_importlib/resources/zipdata01/__init__.py similarity index 100% rename from Lib/test/test_importlib/zipdata01/__init__.py rename to Lib/test/test_importlib/resources/zipdata01/__init__.py diff --git a/Lib/test/test_importlib/zipdata01/ziptestdata.zip b/Lib/test/test_importlib/resources/zipdata01/ziptestdata.zip similarity index 100% rename from Lib/test/test_importlib/zipdata01/ziptestdata.zip rename to Lib/test/test_importlib/resources/zipdata01/ziptestdata.zip diff --git a/Lib/test/test_importlib/zipdata02/__init__.py b/Lib/test/test_importlib/resources/zipdata02/__init__.py similarity index 100% rename from Lib/test/test_importlib/zipdata02/__init__.py rename to Lib/test/test_importlib/resources/zipdata02/__init__.py diff --git a/Lib/test/test_importlib/zipdata02/ziptestdata.zip b/Lib/test/test_importlib/resources/zipdata02/ziptestdata.zip similarity index 100% rename from Lib/test/test_importlib/zipdata02/ziptestdata.zip rename to Lib/test/test_importlib/resources/zipdata02/ziptestdata.zip diff --git a/Lib/test/test_launcher.py b/Lib/test/test_launcher.py index cd7b944f98f586dd349396d3377b45b6b7804996..c8ea4f62170eac97ced1d14cf93e89322ce275bb 100644 --- a/Lib/test/test_launcher.py +++ b/Lib/test/test_launcher.py @@ -69,7 +69,7 @@ TEST_PY_COMMANDS = "\n".join([ "[defaults]", - *[f"{k.lower()}={v}" for k, v in TEST_PY_ENV.items()] + *[f"{k[3:].lower()}={v}" for k, v in TEST_PY_ENV.items()] ]) @@ -149,7 +149,7 @@ class RunPyMixin: @classmethod def find_py(cls): py_exe = None - if sysconfig.is_python_build(True): + if sysconfig.is_python_build(): py_exe = Path(sys.executable).parent / PY_EXE else: for p in os.getenv("PATH").split(";"): @@ -187,7 +187,7 @@ def find_py(cls): ) return py_exe - def run_py(self, args, env=None, allow_fail=False, expect_returncode=0): + def run_py(self, args, env=None, allow_fail=False, expect_returncode=0, argv=None): if not self.py_exe: self.py_exe = self.find_py() @@ -198,9 +198,12 @@ def run_py(self, args, env=None, allow_fail=False, expect_returncode=0): "PYLAUNCHER_DEBUG": "1", "PYLAUNCHER_DRYRUN": "1", } + if not argv: + argv = [self.py_exe, *args] with subprocess.Popen( - [self.py_exe, *args], + argv, env=env, + executable=self.py_exe, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, @@ -515,6 +518,39 @@ def test_py3_shebang(self): self.assertEqual("3.100-arm64", data["SearchInfo.tag"]) self.assertEqual(f"X.Y-arm64.exe -X fake_arg_for_test -prearg {script} -postarg", data["stdout"].strip()) + def test_py_shebang_nl(self): + with self.py_ini(TEST_PY_COMMANDS): + with self.script("#! /usr/bin/env python -prearg\n") as script: + data = self.run_py([script, "-postarg"]) + self.assertEqual("PythonTestSuite", data["SearchInfo.company"]) + self.assertEqual("3.100", data["SearchInfo.tag"]) + self.assertEqual(f"X.Y.exe -prearg {script} -postarg", data["stdout"].strip()) + + def test_py2_shebang_nl(self): + with self.py_ini(TEST_PY_COMMANDS): + with self.script("#! /usr/bin/env python2 -prearg\n") as script: + data = self.run_py([script, "-postarg"]) + self.assertEqual("PythonTestSuite", data["SearchInfo.company"]) + self.assertEqual("3.100-32", data["SearchInfo.tag"]) + self.assertEqual(f"X.Y-32.exe -prearg {script} -postarg", data["stdout"].strip()) + + def test_py3_shebang_nl(self): + with self.py_ini(TEST_PY_COMMANDS): + with self.script("#! /usr/bin/env python3 -prearg\n") as script: + data = self.run_py([script, "-postarg"]) + self.assertEqual("PythonTestSuite", data["SearchInfo.company"]) + self.assertEqual("3.100-arm64", data["SearchInfo.tag"]) + self.assertEqual(f"X.Y-arm64.exe -X fake_arg_for_test -prearg {script} -postarg", data["stdout"].strip()) + + def test_py_shebang_short_argv0(self): + with self.py_ini(TEST_PY_COMMANDS): + with self.script("#! /usr/bin/env python -prearg") as script: + # Override argv to only pass "py.exe" as the command + data = self.run_py([script, "-postarg"], argv=f'"py.exe" "{script}" -postarg') + self.assertEqual("PythonTestSuite", data["SearchInfo.company"]) + self.assertEqual("3.100", data["SearchInfo.tag"]) + self.assertEqual(f'X.Y.exe -prearg "{script}" -postarg', data["stdout"].strip()) + def test_install(self): data = self.run_py(["-V:3.10"], env={"PYLAUNCHER_ALWAYS_INSTALL": "1"}, expect_returncode=111) cmd = data["stdout"].strip() diff --git a/Lib/test/test_opcache.py b/Lib/test/test_opcache.py index 61f337d70ea7870813e1e42dfcf08534fbe3784c..5c032d59b13f162ea03004b00c1635bbae8ffb9f 100644 --- a/Lib/test/test_opcache.py +++ b/Lib/test/test_opcache.py @@ -1,5 +1,6 @@ import unittest + class TestLoadAttrCache(unittest.TestCase): def test_descriptor_added_after_optimization(self): class Descriptor: @@ -21,3 +22,346 @@ def f(o): Descriptor.__set__ = lambda *args: None self.assertEqual(f(o), 2) + + def test_metaclass_descriptor_added_after_optimization(self): + class Descriptor: + pass + + class Metaclass(type): + attribute = Descriptor() + + class Class(metaclass=Metaclass): + attribute = True + + def __get__(self, instance, owner): + return False + + def __set__(self, instance, value): + return None + + def f(): + return Class.attribute + + for _ in range(1025): + self.assertTrue(f()) + + Descriptor.__get__ = __get__ + Descriptor.__set__ = __set__ + + for _ in range(1025): + self.assertFalse(f()) + + def test_metaclass_descriptor_shadows_class_attribute(self): + class Metaclass(type): + @property + def attribute(self): + return True + + class Class(metaclass=Metaclass): + attribute = False + + def f(): + return Class.attribute + + for _ in range(1025): + self.assertTrue(f()) + + def test_metaclass_set_descriptor_after_optimization(self): + class Metaclass(type): + pass + + class Class(metaclass=Metaclass): + attribute = True + + @property + def attribute(self): + return False + + def f(): + return Class.attribute + + for _ in range(1025): + self.assertTrue(f()) + + Metaclass.attribute = attribute + + for _ in range(1025): + self.assertFalse(f()) + + def test_metaclass_del_descriptor_after_optimization(self): + class Metaclass(type): + @property + def attribute(self): + return True + + class Class(metaclass=Metaclass): + attribute = False + + def f(): + return Class.attribute + + for _ in range(1025): + self.assertTrue(f()) + + del Metaclass.attribute + + for _ in range(1025): + self.assertFalse(f()) + + def test_type_descriptor_shadows_attribute_method(self): + class Class: + mro = None + + def f(): + return Class.mro + + for _ in range(1025): + self.assertIsNone(f()) + + def test_type_descriptor_shadows_attribute_member(self): + class Class: + __base__ = None + + def f(): + return Class.__base__ + + for _ in range(1025): + self.assertIs(f(), object) + + def test_type_descriptor_shadows_attribute_getset(self): + class Class: + __name__ = "Spam" + + def f(): + return Class.__name__ + + for _ in range(1025): + self.assertEqual(f(), "Class") + + def test_metaclass_getattribute(self): + class Metaclass(type): + def __getattribute__(self, name): + return True + + class Class(metaclass=Metaclass): + attribute = False + + def f(): + return Class.attribute + + for _ in range(1025): + self.assertTrue(f()) + + def test_metaclass_swap(self): + class OldMetaclass(type): + @property + def attribute(self): + return True + + class NewMetaclass(type): + @property + def attribute(self): + return False + + class Class(metaclass=OldMetaclass): + pass + + def f(): + return Class.attribute + + for _ in range(1025): + self.assertTrue(f()) + + Class.__class__ = NewMetaclass + + for _ in range(1025): + self.assertFalse(f()) + + +class TestLoadMethodCache(unittest.TestCase): + def test_descriptor_added_after_optimization(self): + class Descriptor: + pass + + class Class: + attribute = Descriptor() + + def __get__(self, instance, owner): + return lambda: False + + def __set__(self, instance, value): + return None + + def attribute(): + return True + + instance = Class() + instance.attribute = attribute + + def f(): + return instance.attribute() + + for _ in range(1025): + self.assertTrue(f()) + + Descriptor.__get__ = __get__ + Descriptor.__set__ = __set__ + + for _ in range(1025): + self.assertFalse(f()) + + def test_metaclass_descriptor_added_after_optimization(self): + class Descriptor: + pass + + class Metaclass(type): + attribute = Descriptor() + + class Class(metaclass=Metaclass): + def attribute(): + return True + + def __get__(self, instance, owner): + return lambda: False + + def __set__(self, instance, value): + return None + + def f(): + return Class.attribute() + + for _ in range(1025): + self.assertTrue(f()) + + Descriptor.__get__ = __get__ + Descriptor.__set__ = __set__ + + for _ in range(1025): + self.assertFalse(f()) + + def test_metaclass_descriptor_shadows_class_attribute(self): + class Metaclass(type): + @property + def attribute(self): + return lambda: True + + class Class(metaclass=Metaclass): + def attribute(): + return False + + def f(): + return Class.attribute() + + for _ in range(1025): + self.assertTrue(f()) + + def test_metaclass_set_descriptor_after_optimization(self): + class Metaclass(type): + pass + + class Class(metaclass=Metaclass): + def attribute(): + return True + + @property + def attribute(self): + return lambda: False + + def f(): + return Class.attribute() + + for _ in range(1025): + self.assertTrue(f()) + + Metaclass.attribute = attribute + + for _ in range(1025): + self.assertFalse(f()) + + def test_metaclass_del_descriptor_after_optimization(self): + class Metaclass(type): + @property + def attribute(self): + return lambda: True + + class Class(metaclass=Metaclass): + def attribute(): + return False + + def f(): + return Class.attribute() + + for _ in range(1025): + self.assertTrue(f()) + + del Metaclass.attribute + + for _ in range(1025): + self.assertFalse(f()) + + def test_type_descriptor_shadows_attribute_method(self): + class Class: + def mro(): + return ["Spam", "eggs"] + + def f(): + return Class.mro() + + for _ in range(1025): + self.assertEqual(f(), ["Spam", "eggs"]) + + def test_type_descriptor_shadows_attribute_member(self): + class Class: + def __base__(): + return "Spam" + + def f(): + return Class.__base__() + + for _ in range(1025): + self.assertNotEqual(f(), "Spam") + + def test_metaclass_getattribute(self): + class Metaclass(type): + def __getattribute__(self, name): + return lambda: True + + class Class(metaclass=Metaclass): + def attribute(): + return False + + def f(): + return Class.attribute() + + for _ in range(1025): + self.assertTrue(f()) + + def test_metaclass_swap(self): + class OldMetaclass(type): + @property + def attribute(self): + return lambda: True + + class NewMetaclass(type): + @property + def attribute(self): + return lambda: False + + class Class(metaclass=OldMetaclass): + pass + + def f(): + return Class.attribute() + + for _ in range(1025): + self.assertTrue(f()) + + Class.__class__ = NewMetaclass + + for _ in range(1025): + self.assertFalse(f()) + + +if __name__ == "__main__": + import unittest + unittest.main() diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 29f69a8f475b206fc097b7daf9e7cb36b941aff6..2dafb78ebe0ec2fe4ad462e64f5f7d176ebfe5a6 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -1607,6 +1607,10 @@ def test_mode(self): self.assertEqual(os.stat(path).st_mode & 0o777, 0o555) self.assertEqual(os.stat(parent).st_mode & 0o777, 0o775) + @unittest.skipIf( + support.is_emscripten or support.is_wasi, + "Emscripten's/WASI's umask is a stub." + ) def test_exist_ok_existing_directory(self): path = os.path.join(os_helper.TESTFN, 'dir1') mode = 0o777 @@ -1621,6 +1625,10 @@ def test_exist_ok_existing_directory(self): # Issue #25583: A drive root could raise PermissionError on Windows os.makedirs(os.path.abspath('/'), exist_ok=True) + @unittest.skipIf( + support.is_emscripten or support.is_wasi, + "Emscripten's/WASI's umask is a stub." + ) def test_exist_ok_s_isgid_directory(self): path = os.path.join(os_helper.TESTFN, 'dir1') S_ISGID = stat.S_ISGID @@ -3657,6 +3665,19 @@ def test_stty_match(self): raise self.assertEqual(expected, actual) + @unittest.skipUnless(sys.platform == 'win32', 'Windows specific test') + def test_windows_fd(self): + """Check if get_terminal_size() returns a meaningful value in Windows""" + try: + conout = open('conout$', 'w') + except OSError: + self.skipTest('failed to open conout$') + with conout: + size = os.get_terminal_size(conout.fileno()) + + self.assertGreaterEqual(size.columns, 0) + self.assertGreaterEqual(size.lines, 0) + @unittest.skipUnless(hasattr(os, 'memfd_create'), 'requires os.memfd_create') @support.requires_linux_version(3, 17) diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index a42619853399f2bfa904bb6876ce6295b874966c..e14b0fca55360faca11327efd7afeb4eb7c1522c 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -2478,6 +2478,204 @@ def test_complex_symlinks_relative(self): def test_complex_symlinks_relative_dot_dot(self): self._check_complex_symlinks(os.path.join('dirA', '..')) +class WalkTests(unittest.TestCase): + + def setUp(self): + self.addCleanup(os_helper.rmtree, os_helper.TESTFN) + + # Build: + # TESTFN/ + # TEST1/ a file kid and two directory kids + # tmp1 + # SUB1/ a file kid and a directory kid + # tmp2 + # SUB11/ no kids + # SUB2/ a file kid and a dirsymlink kid + # tmp3 + # SUB21/ not readable + # tmp5 + # link/ a symlink to TEST2 + # broken_link + # broken_link2 + # broken_link3 + # TEST2/ + # tmp4 a lone file + self.walk_path = pathlib.Path(os_helper.TESTFN, "TEST1") + self.sub1_path = self.walk_path / "SUB1" + self.sub11_path = self.sub1_path / "SUB11" + self.sub2_path = self.walk_path / "SUB2" + sub21_path= self.sub2_path / "SUB21" + tmp1_path = self.walk_path / "tmp1" + tmp2_path = self.sub1_path / "tmp2" + tmp3_path = self.sub2_path / "tmp3" + tmp5_path = sub21_path / "tmp3" + self.link_path = self.sub2_path / "link" + t2_path = pathlib.Path(os_helper.TESTFN, "TEST2") + tmp4_path = pathlib.Path(os_helper.TESTFN, "TEST2", "tmp4") + broken_link_path = self.sub2_path / "broken_link" + broken_link2_path = self.sub2_path / "broken_link2" + broken_link3_path = self.sub2_path / "broken_link3" + + os.makedirs(self.sub11_path) + os.makedirs(self.sub2_path) + os.makedirs(sub21_path) + os.makedirs(t2_path) + + for path in tmp1_path, tmp2_path, tmp3_path, tmp4_path, tmp5_path: + with open(path, "x", encoding='utf-8') as f: + f.write(f"I'm {path} and proud of it. Blame test_pathlib.\n") + + if os_helper.can_symlink(): + os.symlink(os.path.abspath(t2_path), self.link_path) + os.symlink('broken', broken_link_path, True) + os.symlink(pathlib.Path('tmp3', 'broken'), broken_link2_path, True) + os.symlink(pathlib.Path('SUB21', 'tmp5'), broken_link3_path, True) + self.sub2_tree = (self.sub2_path, ["SUB21"], + ["broken_link", "broken_link2", "broken_link3", + "link", "tmp3"]) + else: + self.sub2_tree = (self.sub2_path, ["SUB21"], ["tmp3"]) + + if not is_emscripten: + # Emscripten fails with inaccessible directories. + os.chmod(sub21_path, 0) + try: + os.listdir(sub21_path) + except PermissionError: + self.addCleanup(os.chmod, sub21_path, stat.S_IRWXU) + else: + os.chmod(sub21_path, stat.S_IRWXU) + os.unlink(tmp5_path) + os.rmdir(sub21_path) + del self.sub2_tree[1][:1] + + def test_walk_topdown(self): + all = list(self.walk_path.walk()) + + self.assertEqual(len(all), 4) + # We can't know which order SUB1 and SUB2 will appear in. + # Not flipped: TESTFN, SUB1, SUB11, SUB2 + # flipped: TESTFN, SUB2, SUB1, SUB11 + flipped = all[0][1][0] != "SUB1" + all[0][1].sort() + all[3 - 2 * flipped][-1].sort() + all[3 - 2 * flipped][1].sort() + self.assertEqual(all[0], (self.walk_path, ["SUB1", "SUB2"], ["tmp1"])) + self.assertEqual(all[1 + flipped], (self.sub1_path, ["SUB11"], ["tmp2"])) + self.assertEqual(all[2 + flipped], (self.sub11_path, [], [])) + self.assertEqual(all[3 - 2 * flipped], self.sub2_tree) + + def test_walk_prune(self, walk_path=None): + if walk_path is None: + walk_path = self.walk_path + # Prune the search. + all = [] + for root, dirs, files in walk_path.walk(): + all.append((root, dirs, files)) + if 'SUB1' in dirs: + # Note that this also mutates the dirs we appended to all! + dirs.remove('SUB1') + + self.assertEqual(len(all), 2) + self.assertEqual(all[0], (self.walk_path, ["SUB2"], ["tmp1"])) + + all[1][-1].sort() + all[1][1].sort() + self.assertEqual(all[1], self.sub2_tree) + + def test_file_like_path(self): + self.test_walk_prune(FakePath(self.walk_path).__fspath__()) + + def test_walk_bottom_up(self): + all = list(self.walk_path.walk( top_down=False)) + + self.assertEqual(len(all), 4, all) + # We can't know which order SUB1 and SUB2 will appear in. + # Not flipped: SUB11, SUB1, SUB2, TESTFN + # flipped: SUB2, SUB11, SUB1, TESTFN + flipped = all[3][1][0] != "SUB1" + all[3][1].sort() + all[2 - 2 * flipped][-1].sort() + all[2 - 2 * flipped][1].sort() + self.assertEqual(all[3], + (self.walk_path, ["SUB1", "SUB2"], ["tmp1"])) + self.assertEqual(all[flipped], + (self.sub11_path, [], [])) + self.assertEqual(all[flipped + 1], + (self.sub1_path, ["SUB11"], ["tmp2"])) + self.assertEqual(all[2 - 2 * flipped], + self.sub2_tree) + + @os_helper.skip_unless_symlink + def test_walk_follow_symlinks(self): + walk_it = self.walk_path.walk(follow_symlinks=True) + for root, dirs, files in walk_it: + if root == self.link_path: + self.assertEqual(dirs, []) + self.assertEqual(files, ["tmp4"]) + break + else: + self.fail("Didn't follow symlink with follow_symlinks=True") + + @os_helper.skip_unless_symlink + def test_walk_symlink_location(self): + # Tests whether symlinks end up in filenames or dirnames depending + # on the `follow_symlinks` argument. + walk_it = self.walk_path.walk(follow_symlinks=False) + for root, dirs, files in walk_it: + if root == self.sub2_path: + self.assertIn("link", files) + break + else: + self.fail("symlink not found") + + walk_it = self.walk_path.walk(follow_symlinks=True) + for root, dirs, files in walk_it: + if root == self.sub2_path: + self.assertIn("link", dirs) + break + + def test_walk_bad_dir(self): + errors = [] + walk_it = self.walk_path.walk(on_error=errors.append) + root, dirs, files = next(walk_it) + self.assertEqual(errors, []) + dir1 = 'SUB1' + path1 = root / dir1 + path1new = (root / dir1).with_suffix(".new") + path1.rename(path1new) + try: + roots = [r for r, _, _ in walk_it] + self.assertTrue(errors) + self.assertNotIn(path1, roots) + self.assertNotIn(path1new, roots) + for dir2 in dirs: + if dir2 != dir1: + self.assertIn(root / dir2, roots) + finally: + path1new.rename(path1) + + def test_walk_many_open_files(self): + depth = 30 + base = pathlib.Path(os_helper.TESTFN, 'deep') + path = pathlib.Path(base, *(['d']*depth)) + path.mkdir(parents=True) + + iters = [base.walk(top_down=False) for _ in range(100)] + for i in range(depth + 1): + expected = (path, ['d'] if i else [], []) + for it in iters: + self.assertEqual(next(it), expected) + path = path.parent + + iters = [base.walk(top_down=True) for _ in range(100)] + path = base + for i in range(depth + 1): + expected = (path, ['d'] if i < depth else [], []) + for it in iters: + self.assertEqual(next(it), expected) + path = path / 'd' + class PathTest(_BasePathTest, unittest.TestCase): cls = pathlib.Path diff --git a/Lib/test/test_patma.py b/Lib/test/test_patma.py index db198f7715783142aa37037d121a466cefa01550..0ed54079c99b302525dcdab986895d4973118795 100644 --- a/Lib/test/test_patma.py +++ b/Lib/test/test_patma.py @@ -2654,6 +2654,20 @@ def get(key, default=None): self.assertEqual(y, 'bar') + def test_patma_249(self): + class C: + __attr = "eggs" # mangled to _C__attr + _Outer__attr = "bacon" + class Outer: + def f(self, x): + match x: + # looks up __attr, not _C__attr or _Outer__attr + case C(__attr=y): + return y + c = C() + setattr(c, "__attr", "spam") # setattr is needed because we're in a class scope + self.assertEqual(Outer().f(c), "spam") + class TestSyntaxErrors(unittest.TestCase): diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index fcf17a949c2a62126f007f0da62cb9554c722b44..1e825c3572d20aa2e9d39ce967973d1a48ebbaed 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -1045,6 +1045,9 @@ def test_constant(self): (g.lognormvariate, (0.0, 0.0), 1.0), (g.lognormvariate, (-float('inf'), 0.0), 0.0), (g.normalvariate, (10.0, 0.0), 10.0), + (g.binomialvariate, (0, 0.5), 0), + (g.binomialvariate, (10, 0.0), 0), + (g.binomialvariate, (10, 1.0), 10), (g.paretovariate, (float('inf'),), 1.0), (g.weibullvariate, (10.0, float('inf')), 10.0), (g.weibullvariate, (0.0, 10.0), 0.0), @@ -1052,6 +1055,59 @@ def test_constant(self): for i in range(N): self.assertEqual(variate(*args), expected) + def test_binomialvariate(self): + B = random.binomialvariate + + # Cover all the code paths + with self.assertRaises(ValueError): + B(n=-1) # Negative n + with self.assertRaises(ValueError): + B(n=1, p=-0.5) # Negative p + with self.assertRaises(ValueError): + B(n=1, p=1.5) # p > 1.0 + self.assertEqual(B(10, 0.0), 0) # p == 0.0 + self.assertEqual(B(10, 1.0), 10) # p == 1.0 + self.assertTrue(B(1, 0.3) in {0, 1}) # n == 1 fast path + self.assertTrue(B(1, 0.9) in {0, 1}) # n == 1 fast path + self.assertTrue(B(1, 0.0) in {0}) # n == 1 fast path + self.assertTrue(B(1, 1.0) in {1}) # n == 1 fast path + + # BG method p <= 0.5 and n*p=1.25 + self.assertTrue(B(5, 0.25) in set(range(6))) + + # BG method p >= 0.5 and n*(1-p)=1.25 + self.assertTrue(B(5, 0.75) in set(range(6))) + + # BTRS method p <= 0.5 and n*p=25 + self.assertTrue(B(100, 0.25) in set(range(101))) + + # BTRS method p > 0.5 and n*(1-p)=25 + self.assertTrue(B(100, 0.75) in set(range(101))) + + # Statistical tests chosen such that they are + # exceedingly unlikely to ever fail for correct code. + + # BG code path + # Expected dist: [31641, 42188, 21094, 4688, 391] + c = Counter(B(4, 0.25) for i in range(100_000)) + self.assertTrue(29_641 <= c[0] <= 33_641, c) + self.assertTrue(40_188 <= c[1] <= 44_188) + self.assertTrue(19_094 <= c[2] <= 23_094) + self.assertTrue(2_688 <= c[3] <= 6_688) + self.assertEqual(set(c), {0, 1, 2, 3, 4}) + + # BTRS code path + # Sum of c[20], c[21], c[22], c[23], c[24] expected to be 36,214 + c = Counter(B(100, 0.25) for i in range(100_000)) + self.assertTrue(34_214 <= c[20]+c[21]+c[22]+c[23]+c[24] <= 38_214) + self.assertTrue(set(c) <= set(range(101))) + self.assertEqual(c.total(), 100_000) + + # Demonstrate the BTRS works for huge values of n + self.assertTrue(19_000_000 <= B(100_000_000, 0.2) <= 21_000_000) + self.assertTrue(89_000_000 <= B(100_000_000, 0.9) <= 91_000_000) + + def test_von_mises_range(self): # Issue 17149: von mises variates were not consistently in the # range [0, 2*PI]. diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 1700b429ab07ca75c86e213b8527ced1e0711bae..f1b57fc407103262913b3efd0b56267cfa6e10b7 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -965,6 +965,19 @@ def testWindowsSpecificConstants(self): socket.IPPROTO_L2TP socket.IPPROTO_SCTP + @unittest.skipIf(support.is_wasi, "WASI is missing these methods") + def test_socket_methods(self): + # socket methods that depend on a configure HAVE_ check. They should + # be present on all platforms except WASI. + names = [ + "_accept", "bind", "connect", "connect_ex", "getpeername", + "getsockname", "listen", "recvfrom", "recvfrom_into", "sendto", + "setsockopt", "shutdown" + ] + for name in names: + if not hasattr(socket.socket, name): + self.fail(f"socket method {name} is missing") + @unittest.skipUnless(sys.platform == 'darwin', 'macOS specific test') @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'IPv6 required for this test') def test3542SocketOptions(self): @@ -5543,6 +5556,20 @@ def testBytearrayName(self): s.bind(bytearray(b"\x00python\x00test\x00")) self.assertEqual(s.getsockname(), b"\x00python\x00test\x00") + def testAutobind(self): + # Check that binding to an empty string binds to an available address + # in the abstract namespace as specified in unix(7) "Autobind feature". + abstract_address = b"^\0[0-9a-f]{5}" + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s1: + s1.bind("") + self.assertRegex(s1.getsockname(), abstract_address) + # Each socket is bound to a different abstract address. + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s2: + s2.bind("") + self.assertRegex(s2.getsockname(), abstract_address) + self.assertNotEqual(s1.getsockname(), s2.getsockname()) + + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'test needs socket.AF_UNIX') class TestUnixDomain(unittest.TestCase): @@ -5612,6 +5639,11 @@ def testUnencodableAddr(self): self.addCleanup(os_helper.unlink, path) self.assertEqual(self.sock.getsockname(), path) + @unittest.skipIf(sys.platform == 'linux', 'Linux specific test') + def testEmptyAddress(self): + # Test that binding empty address fails. + self.assertRaises(OSError, self.sock.bind, "") + class BufferIOTest(SocketConnectedTest): """ diff --git a/Lib/test/test_sqlite3/__init__.py b/Lib/test/test_sqlite3/__init__.py index c3cab8f0acdc0ba03728381eeccd02141fd07021..d777fca82da4b0d8d9ce14ffff4d748081787dab 100644 --- a/Lib/test/test_sqlite3/__init__.py +++ b/Lib/test/test_sqlite3/__init__.py @@ -12,6 +12,4 @@ def load_tests(*args): return load_package_tests(pkg_dir, *args) if verbose: - print("test_sqlite3: testing with version", - "{!r}, sqlite_version {!r}".format(sqlite3.version, - sqlite3.sqlite_version)) + print(f"test_sqlite3: testing with SQLite version {sqlite3.sqlite_version}") diff --git a/Lib/test/test_sqlite3/__main__.py b/Lib/test/test_sqlite3/__main__.py index 51eddc3c2fde02d01d49c88904d584b92459d559..ca6a8347fbd231154f8b7e4a8302c3718f4de84a 100644 --- a/Lib/test/test_sqlite3/__main__.py +++ b/Lib/test/test_sqlite3/__main__.py @@ -1,5 +1,4 @@ from test.test_sqlite3 import load_tests # Needed for the "load tests" protocol. import unittest -if __name__ == "__main__": - unittest.main() +unittest.main() diff --git a/Lib/test/test_sqlite3/test_factory.py b/Lib/test/test_sqlite3/test_factory.py index 71603faa02840f8ec1b5d4c7f59075e0ab284b54..7fdc45ab69243dfac3ac760ab0692fbde8cd39de 100644 --- a/Lib/test/test_sqlite3/test_factory.py +++ b/Lib/test/test_sqlite3/test_factory.py @@ -50,6 +50,26 @@ def __init__(self, *args, **kwargs): con = sqlite.connect(":memory:", factory=factory) self.assertIsInstance(con, factory) + def test_connection_factory_relayed_call(self): + # gh-95132: keyword args must not be passed as positional args + class Factory(sqlite.Connection): + def __init__(self, *args, **kwargs): + kwargs["isolation_level"] = None + super(Factory, self).__init__(*args, **kwargs) + + con = sqlite.connect(":memory:", factory=Factory) + self.assertIsNone(con.isolation_level) + self.assertIsInstance(con, Factory) + + def test_connection_factory_as_positional_arg(self): + class Factory(sqlite.Connection): + def __init__(self, *args, **kwargs): + super(Factory, self).__init__(*args, **kwargs) + + con = sqlite.connect(":memory:", 5.0, 0, None, True, Factory) + self.assertIsNone(con.isolation_level) + self.assertIsInstance(con, Factory) + class CursorFactoryTests(unittest.TestCase): def setUp(self): diff --git a/Lib/test/test_sqlite3/test_regression.py b/Lib/test/test_sqlite3/test_regression.py index 0b727cecb0e8cb8a9ae0f3aa2ce1f0ce292583b8..ad83a97c8c40d69c0c75bd1e3697faf63358c54a 100644 --- a/Lib/test/test_sqlite3/test_regression.py +++ b/Lib/test/test_sqlite3/test_regression.py @@ -129,7 +129,8 @@ def test_type_map_usage(self): con = sqlite.connect(":memory:",detect_types=sqlite.PARSE_DECLTYPES) cur = con.cursor() cur.execute("create table foo(bar timestamp)") - cur.execute("insert into foo(bar) values (?)", (datetime.datetime.now(),)) + with self.assertWarnsRegex(DeprecationWarning, "adapter"): + cur.execute("insert into foo(bar) values (?)", (datetime.datetime.now(),)) cur.execute(SELECT) cur.execute("drop table foo") cur.execute("create table foo(bar integer)") @@ -305,7 +306,8 @@ def test_convert_timestamp_microsecond_padding(self): cur.execute("INSERT INTO t (x) VALUES ('2012-04-04 15:06:00.123456789')") cur.execute("SELECT * FROM t") - values = [x[0] for x in cur.fetchall()] + with self.assertWarnsRegex(DeprecationWarning, "converter"): + values = [x[0] for x in cur.fetchall()] self.assertEqual(values, [ datetime.datetime(2012, 4, 4, 15, 6, 0, 456000), diff --git a/Lib/test/test_sqlite3/test_types.py b/Lib/test/test_sqlite3/test_types.py index 177cd102350397553596c5b2aedab2c73bdabc02..62318823510d40837e7153aacf71aff99c6113f7 100644 --- a/Lib/test/test_sqlite3/test_types.py +++ b/Lib/test/test_sqlite3/test_types.py @@ -496,38 +496,51 @@ def tearDown(self): def test_sqlite_date(self): d = sqlite.Date(2004, 2, 14) - self.cur.execute("insert into test(d) values (?)", (d,)) + with self.assertWarnsRegex(DeprecationWarning, "adapter") as cm: + self.cur.execute("insert into test(d) values (?)", (d,)) + self.assertEqual(cm.filename, __file__) self.cur.execute("select d from test") - d2 = self.cur.fetchone()[0] + with self.assertWarnsRegex(DeprecationWarning, "converter") as cm: + d2 = self.cur.fetchone()[0] + self.assertEqual(cm.filename, __file__) self.assertEqual(d, d2) def test_sqlite_timestamp(self): ts = sqlite.Timestamp(2004, 2, 14, 7, 15, 0) - self.cur.execute("insert into test(ts) values (?)", (ts,)) + with self.assertWarnsRegex(DeprecationWarning, "adapter") as cm: + self.cur.execute("insert into test(ts) values (?)", (ts,)) + self.assertEqual(cm.filename, __file__) self.cur.execute("select ts from test") - ts2 = self.cur.fetchone()[0] + with self.assertWarnsRegex(DeprecationWarning, "converter") as cm: + ts2 = self.cur.fetchone()[0] + self.assertEqual(cm.filename, __file__) self.assertEqual(ts, ts2) def test_sql_timestamp(self): now = datetime.datetime.utcnow() self.cur.execute("insert into test(ts) values (current_timestamp)") self.cur.execute("select ts from test") - ts = self.cur.fetchone()[0] + with self.assertWarnsRegex(DeprecationWarning, "converter"): + ts = self.cur.fetchone()[0] self.assertEqual(type(ts), datetime.datetime) self.assertEqual(ts.year, now.year) def test_date_time_sub_seconds(self): ts = sqlite.Timestamp(2004, 2, 14, 7, 15, 0, 500000) - self.cur.execute("insert into test(ts) values (?)", (ts,)) + with self.assertWarnsRegex(DeprecationWarning, "adapter"): + self.cur.execute("insert into test(ts) values (?)", (ts,)) self.cur.execute("select ts from test") - ts2 = self.cur.fetchone()[0] + with self.assertWarnsRegex(DeprecationWarning, "converter"): + ts2 = self.cur.fetchone()[0] self.assertEqual(ts, ts2) def test_date_time_sub_seconds_floating_point(self): ts = sqlite.Timestamp(2004, 2, 14, 7, 15, 0, 510241) - self.cur.execute("insert into test(ts) values (?)", (ts,)) + with self.assertWarnsRegex(DeprecationWarning, "adapter"): + self.cur.execute("insert into test(ts) values (?)", (ts,)) self.cur.execute("select ts from test") - ts2 = self.cur.fetchone()[0] + with self.assertWarnsRegex(DeprecationWarning, "converter"): + ts2 = self.cur.fetchone()[0] self.assertEqual(ts, ts2) diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 65f5d4a6d70940447c2357d1bb565abc2820f7e6..5007e08f321b5a64bd8bd03917825e9f5a0abdfe 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -47,7 +47,7 @@ PROTOCOL_TO_TLS_VERSION = {} for proto, ver in ( - ("PROTOCOL_SSLv23", "SSLv3"), + ("PROTOCOL_SSLv3", "SSLv3"), ("PROTOCOL_TLSv1", "TLSv1"), ("PROTOCOL_TLSv1_1", "TLSv1_1"), ): @@ -938,8 +938,20 @@ def test_get_ciphers(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) ctx.set_ciphers('AESGCM') names = set(d['name'] for d in ctx.get_ciphers()) - self.assertIn('AES256-GCM-SHA384', names) - self.assertIn('AES128-GCM-SHA256', names) + expected = { + 'AES128-GCM-SHA256', + 'ECDHE-ECDSA-AES128-GCM-SHA256', + 'ECDHE-RSA-AES128-GCM-SHA256', + 'DHE-RSA-AES128-GCM-SHA256', + 'AES256-GCM-SHA384', + 'ECDHE-ECDSA-AES256-GCM-SHA384', + 'ECDHE-RSA-AES256-GCM-SHA384', + 'DHE-RSA-AES256-GCM-SHA384', + } + intersection = names.intersection(expected) + self.assertGreaterEqual( + len(intersection), 2, f"\ngot: {sorted(names)}\nexpected: {sorted(expected)}" + ) def test_options(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index 6de98241c294d79d3070115b4ec8a9b749f7be6e..bf85525dd129a55a407f9b8404254b33f2f67fc1 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -2801,9 +2801,10 @@ def test_inv_cdf(self): iq.inv_cdf(1.0) # p is one with self.assertRaises(self.module.StatisticsError): iq.inv_cdf(1.1) # p over one - with self.assertRaises(self.module.StatisticsError): - iq = NormalDist(100, 0) # sigma is zero - iq.inv_cdf(0.5) + + # Supported case: + iq = NormalDist(100, 0) # sigma is zero + self.assertEqual(iq.inv_cdf(0.5), 100) # Special values self.assertTrue(math.isnan(Z.inv_cdf(float('NaN')))) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 1dc10d8b0a39ac3df4b7b91016565a2d073a2c63..c4798afc92016c1b6b1957225a743e8d2d6fa0bc 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -626,7 +626,7 @@ def test_attributes(self): def test_thread_info(self): info = sys.thread_info self.assertEqual(len(info), 3) - self.assertIn(info.name, ('nt', 'pthread', 'solaris', None)) + self.assertIn(info.name, ('nt', 'pthread', 'pthread-stubs', 'solaris', None)) self.assertIn(info.lock, ('semaphore', 'mutex+cond', None)) @unittest.skipUnless(support.is_emscripten, "only available on Emscripten") @@ -1507,7 +1507,7 @@ def delx(self): del self.__x check((1,2,3), vsize('') + 3*self.P) # type # static type: PyTypeObject - fmt = 'P2nPI13Pl4Pn9Pn12PIP' + fmt = 'P2nPI13Pl4Pn9Pn12PIPI' s = vsize('2P' + fmt) check(int, s) # class diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index f03b03e19a2528b3ffc1472cd30d91c223fba1df..9f1aa81dbcd249ce60769c3179b417d713dc1173 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -1571,6 +1571,28 @@ def func(): self.run_and_compare(func, EXPECTED_EVENTS) + def test_very_large_function(self): + # There is a separate code path when the number of lines > (1 << 15). + d = {} + exec("""def f(): # line 0 + x = 0 # line 1 + y = 1 # line 2 + %s # lines 3 through (1 << 16) + x += 1 # + return""" % ('\n' * (1 << 16),), d) + f = d['f'] + + EXPECTED_EVENTS = [ + (0, 'call'), + (1, 'line'), + (2, 'line'), + (65540, 'line'), + (65541, 'line'), + (65541, 'return'), + ] + + self.run_and_compare(f, EXPECTED_EVENTS) + EVENT_NAMES = [ 'call', @@ -1857,7 +1879,7 @@ def test_jump_out_of_block_backwards(output): output.append(6) output.append(7) - @async_jump_test(4, 5, [3], (ValueError, 'into')) + @async_jump_test(4, 5, [3, 5]) async def test_jump_out_of_async_for_block_forwards(output): for i in [1]: async for i in asynciter([1, 2]): @@ -1899,7 +1921,7 @@ def test_jump_in_nested_finally(output): output.append(8) output.append(9) - @jump_test(6, 7, [2], (ValueError, 'within')) + @jump_test(6, 7, [2, 7], (ZeroDivisionError, '')) def test_jump_in_nested_finally_2(output): try: output.append(2) @@ -1910,7 +1932,7 @@ def test_jump_in_nested_finally_2(output): output.append(7) output.append(8) - @jump_test(6, 11, [2], (ValueError, 'within')) + @jump_test(6, 11, [2, 11], (ZeroDivisionError, '')) def test_jump_in_nested_finally_3(output): try: output.append(2) @@ -2021,8 +2043,8 @@ def test_jump_backwards_out_of_try_except_block(output): output.append(5) raise - @jump_test(5, 7, [4], (ValueError, 'within')) - def test_no_jump_between_except_blocks(output): + @jump_test(5, 7, [4, 7, 8]) + def test_jump_between_except_blocks(output): try: 1/0 except ZeroDivisionError: @@ -2032,8 +2054,19 @@ def test_no_jump_between_except_blocks(output): output.append(7) output.append(8) - @jump_test(5, 6, [4], (ValueError, 'within')) - def test_no_jump_within_except_block(output): + @jump_test(5, 7, [4, 7, 8]) + def test_jump_from_except_to_finally(output): + try: + 1/0 + except ZeroDivisionError: + output.append(4) + output.append(5) + finally: + output.append(7) + output.append(8) + + @jump_test(5, 6, [4, 6, 7]) + def test_jump_within_except_block(output): try: 1/0 except: @@ -2268,7 +2301,7 @@ def test_no_jump_backwards_into_for_block(output): output.append(2) output.append(3) - @async_jump_test(3, 2, [2, 2], (ValueError, 'within')) + @async_jump_test(3, 2, [2, 2], (ValueError, "can't jump into the body of a for loop")) async def test_no_jump_backwards_into_async_for_block(output): async for i in asynciter([1, 2]): output.append(2) @@ -2333,8 +2366,8 @@ def test_jump_backwards_into_try_except_block(output): output.append(6) # 'except' with a variable creates an implicit finally block - @jump_test(5, 7, [4], (ValueError, 'within')) - def test_no_jump_between_except_blocks_2(output): + @jump_test(5, 7, [4, 7, 8]) + def test_jump_between_except_blocks_2(output): try: 1/0 except ZeroDivisionError: @@ -2370,7 +2403,7 @@ def test_jump_out_of_finally_block(output): finally: output.append(5) - @jump_test(1, 5, [], (ValueError, "into an exception")) + @jump_test(1, 5, [], (ValueError, "can't jump into an 'except' block as there's no exception")) def test_no_jump_into_bare_except_block(output): output.append(1) try: @@ -2378,7 +2411,7 @@ def test_no_jump_into_bare_except_block(output): except: output.append(5) - @jump_test(1, 5, [], (ValueError, "into an exception")) + @jump_test(1, 5, [], (ValueError, "can't jump into an 'except' block as there's no exception")) def test_no_jump_into_qualified_except_block(output): output.append(1) try: @@ -2386,7 +2419,7 @@ def test_no_jump_into_qualified_except_block(output): except Exception: output.append(5) - @jump_test(3, 6, [2, 5, 6], (ValueError, "into an exception")) + @jump_test(3, 6, [2, 5, 6], (ValueError, "can't jump into an 'except' block as there's no exception")) def test_no_jump_into_bare_except_block_from_try_block(output): try: output.append(2) @@ -2397,7 +2430,7 @@ def test_no_jump_into_bare_except_block_from_try_block(output): raise output.append(8) - @jump_test(3, 6, [2], (ValueError, "into an exception")) + @jump_test(3, 6, [2], (ValueError, "can't jump into an 'except' block as there's no exception")) def test_no_jump_into_qualified_except_block_from_try_block(output): try: output.append(2) @@ -2408,8 +2441,8 @@ def test_no_jump_into_qualified_except_block_from_try_block(output): raise output.append(8) - @jump_test(7, 1, [1, 3, 6], (ValueError, "within")) - def test_no_jump_out_of_bare_except_block(output): + @jump_test(7, 1, [1, 3, 6, 1, 3, 6, 7]) + def test_jump_out_of_bare_except_block(output): output.append(1) try: output.append(3) @@ -2418,8 +2451,8 @@ def test_no_jump_out_of_bare_except_block(output): output.append(6) output.append(7) - @jump_test(7, 1, [1, 3, 6], (ValueError, "within")) - def test_no_jump_out_of_qualified_except_block(output): + @jump_test(7, 1, [1, 3, 6, 1, 3, 6, 7]) + def test_jump_out_of_qualified_except_block(output): output.append(1) try: output.append(3) @@ -2652,6 +2685,42 @@ def test_jump_with_null_on_stack_load_attr(output): ) output.append(15) + @jump_test(2, 3, [1, 3]) + def test_jump_extended_args_unpack_ex_simple(output): + output.append(1) + _, *_, _ = output.append(2) or "Spam" + output.append(3) + + @jump_test(3, 4, [1, 4, 4, 5]) + def test_jump_extended_args_unpack_ex_tricky(output): + output.append(1) + ( + _, *_, _ + ) = output.append(4) or "Spam" + output.append(5) + + 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: + source = [ + "def f(output):", + " output.append(1)", + " for _ in spam:", + *(f" output.append({i})" for i in range(3, 100_000)), + f" output.append(100_000)", + ] + namespace = {} + exec("\n".join(source), namespace) + f = namespace["f"] + self.run_test(f, 2, 100_000, [1, 100_000]) + + @jump_test(2, 3, [1, 3]) + def test_jump_or_pop(output): + output.append(1) + _ = output.append(2) and "Spam" + output.append(3) + + class TestExtendedArgs(unittest.TestCase): def setUp(self): diff --git a/Lib/test/test_threadsignals.py b/Lib/test/test_threadsignals.py index e0ac18c9463986a3e82e9c02b7130f30f3aa5df8..6a53d655015cdb47457bb23a94e8ce3325d495b3 100644 --- a/Lib/test/test_threadsignals.py +++ b/Lib/test/test_threadsignals.py @@ -36,7 +36,9 @@ def send_signals(): os.kill(process_pid, signal.SIGUSR2) signalled_all.release() + @threading_helper.requires_working_threading() +@unittest.skipUnless(hasattr(signal, "alarm"), "test requires signal.alarm") class ThreadSignals(unittest.TestCase): def test_signals(self): diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 722c265a6a8a519730e075971cd5fb123a3f9007..2089050cadfc2c9971d136015dc09188ea295128 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -252,7 +252,7 @@ def do_test(firstlines, message, charset, lineno): self.assertTrue(stdout[2].endswith(err_line), "Invalid traceback line: {0!r} instead of {1!r}".format( stdout[2], err_line)) - actual_err_msg = stdout[3 if has_no_debug_ranges() else 4] + actual_err_msg = stdout[3] self.assertTrue(actual_err_msg == err_msg, "Invalid error message: {0!r} instead of {1!r}".format( actual_err_msg, err_msg)) @@ -386,18 +386,19 @@ def get_exception(self, callable): callable_line = get_exception.__code__.co_firstlineno + 2 def test_basic_caret(self): + # NOTE: In caret tests, "if True:" is used as a way to force indicator + # display, since the raising expression spans only part of the line. def f(): - raise ValueError("basic caret tests") + if True: raise ValueError("basic caret tests") lineno_f = f.__code__.co_firstlineno expected_f = ( 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' - ' ^^^^^^^^^^\n' f' File "{__file__}", line {lineno_f+1}, in f\n' - ' raise ValueError("basic caret tests")\n' - ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' + ' if True: raise ValueError("basic caret tests")\n' + ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' ) result_lines = self.get_exception(f) self.assertEqual(result_lines, expected_f.splitlines()) @@ -406,17 +407,16 @@ def test_line_with_unicode(self): # Make sure that even if a line contains multi-byte unicode characters # the correct carets are printed. def f_with_unicode(): - raise ValueError("Ĥellö Wörld") + if True: raise ValueError("Ĥellö Wörld") lineno_f = f_with_unicode.__code__.co_firstlineno expected_f = ( 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' - ' ^^^^^^^^^^\n' f' File "{__file__}", line {lineno_f+1}, in f_with_unicode\n' - ' raise ValueError("Ĥellö Wörld")\n' - ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' + ' if True: raise ValueError("Ĥellö Wörld")\n' + ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' ) result_lines = self.get_exception(f_with_unicode) self.assertEqual(result_lines, expected_f.splitlines()) @@ -431,7 +431,6 @@ def foo(a: THIS_DOES_NOT_EXIST ) -> int: 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' - ' ^^^^^^^^^^\n' f' File "{__file__}", line {lineno_f+1}, in f_with_type\n' ' def foo(a: THIS_DOES_NOT_EXIST ) -> int:\n' ' ^^^^^^^^^^^^^^^^^^^\n' @@ -443,7 +442,7 @@ def test_caret_multiline_expression(self): # Make sure no carets are printed for expressions spanning multiple # lines. def f_with_multiline(): - raise ValueError( + if True: raise ValueError( "error over multiple lines" ) @@ -452,10 +451,9 @@ def f_with_multiline(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' - ' ^^^^^^^^^^\n' f' File "{__file__}", line {lineno_f+1}, in f_with_multiline\n' - ' raise ValueError(\n' - ' ^^^^^^^^^^^^^^^^^' + ' if True: raise ValueError(\n' + ' ^^^^^^^^^^^^^^^^^' ) result_lines = self.get_exception(f_with_multiline) self.assertEqual(result_lines, expected_f.splitlines()) @@ -484,7 +482,6 @@ def f_with_multiline(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' - ' ^^^^^^^^^^\n' f' File "{__file__}", line {lineno_f+2}, in f_with_multiline\n' ' return compile(code, "?", "exec")\n' ' ^^^^^^^^^^^^^^^^^^^^^^^^^^\n' @@ -501,9 +498,8 @@ def test_caret_multiline_expression_bin_op(self): # lines. def f_with_multiline(): return ( - 1 / - 0 + - 2 + 2 + 1 / + 0 ) lineno_f = f_with_multiline.__code__.co_firstlineno @@ -511,10 +507,9 @@ def f_with_multiline(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' - ' ^^^^^^^^^^\n' f' File "{__file__}", line {lineno_f+2}, in f_with_multiline\n' - ' 1 /\n' - ' ^^^' + ' 2 + 1 /\n' + ' ^^^' ) result_lines = self.get_exception(f_with_multiline) self.assertEqual(result_lines, expected_f.splitlines()) @@ -529,7 +524,6 @@ def f_with_binary_operator(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' - ' ^^^^^^^^^^\n' f' File "{__file__}", line {lineno_f+2}, in f_with_binary_operator\n' ' return 10 + divisor / 0 + 30\n' ' ~~~~~~~~^~~\n' @@ -547,7 +541,6 @@ def f_with_binary_operator(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' - ' ^^^^^^^^^^\n' f' File "{__file__}", line {lineno_f+2}, in f_with_binary_operator\n' ' return 10 + divisor // 0 + 30\n' ' ~~~~~~~~^^~~\n' @@ -565,7 +558,6 @@ def f_with_subscript(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' - ' ^^^^^^^^^^\n' f' File "{__file__}", line {lineno_f+2}, in f_with_subscript\n' " return some_dict['x']['y']['z']\n" ' ~~~~~~~~~~~~~~~~~~~^^^^^\n' @@ -589,7 +581,6 @@ def test_traceback_specialization_with_syntax_error(self): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' - ' ^^^^^^^^^^\n' f' File "{TESTFN}", line {lineno_f}, in <module>\n' " 1 $ 0 / 1 / 2\n" ' ^^^^^\n' @@ -597,7 +588,7 @@ def test_traceback_specialization_with_syntax_error(self): self.assertEqual(result_lines, expected_error.splitlines()) def test_traceback_very_long_line(self): - source = "a" * 256 + source = "if True: " + "a" * 256 bytecode = compile(source, TESTFN, "exec") with open(TESTFN, "w") as file: @@ -612,13 +603,54 @@ def test_traceback_very_long_line(self): 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' - ' ^^^^^^^^^^\n' f' File "{TESTFN}", line {lineno_f}, in <module>\n' f' {source}\n' - f' {"^"*len(source)}\n' + f' {" "*len("if True: ") + "^"*256}\n' ) self.assertEqual(result_lines, expected_error.splitlines()) + def test_secondary_caret_not_elided(self): + # Always show a line's indicators if they include the secondary character. + def f_with_subscript(): + some_dict = {'x': {'y': None}} + some_dict['x']['y']['z'] + + lineno_f = f_with_subscript.__code__.co_firstlineno + expected_error = ( + 'Traceback (most recent call last):\n' + f' File "{__file__}", line {self.callable_line}, in get_exception\n' + ' callable()\n' + f' File "{__file__}", line {lineno_f+2}, in f_with_subscript\n' + " some_dict['x']['y']['z']\n" + ' ~~~~~~~~~~~~~~~~~~~^^^^^\n' + ) + result_lines = self.get_exception(f_with_subscript) + self.assertEqual(result_lines, expected_error.splitlines()) + + def test_caret_exception_group(self): + # Notably, this covers whether indicators handle margin strings correctly. + # (Exception groups use margin strings to display vertical indicators.) + # The implementation must account for both "indent" and "margin" offsets. + + def exc(): + if True: raise ExceptionGroup("eg", [ValueError(1), TypeError(2)]) + + expected_error = ( + f' + Exception Group Traceback (most recent call last):\n' + f' | File "{__file__}", line {self.callable_line}, in get_exception\n' + f' | callable()\n' + f' | File "{__file__}", line {exc.__code__.co_firstlineno + 1}, in exc\n' + f' | if True: raise ExceptionGroup("eg", [ValueError(1), TypeError(2)])\n' + f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' + f' | ExceptionGroup: eg (2 sub-exceptions)\n' + f' +-+---------------- 1 ----------------\n' + f' | ValueError: 1\n' + f' +---------------- 2 ----------------\n' + f' | TypeError: 2\n') + + result_lines = self.get_exception(exc) + self.assertEqual(result_lines, expected_error.splitlines()) + def assertSpecialized(self, func, expected_specialization): result_lines = self.get_exception(func) specialization_line = result_lines[-1] @@ -672,13 +704,11 @@ def g(): pass 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' - ' ^^^^^^^^^^\n' f' File "{__file__}", line {lineno_applydescs + 1}, in applydecs\n' ' @dec_error\n' ' ^^^^^^^^^\n' f' File "{__file__}", line {lineno_dec_error + 1}, in dec_error\n' ' raise TypeError\n' - ' ^^^^^^^^^^^^^^^\n' ) self.assertEqual(result_lines, expected_error.splitlines()) @@ -692,16 +722,61 @@ class A: pass 'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' ' callable()\n' - ' ^^^^^^^^^^\n' f' File "{__file__}", line {lineno_applydescs_class + 1}, in applydecs_class\n' ' @dec_error\n' ' ^^^^^^^^^\n' f' File "{__file__}", line {lineno_dec_error + 1}, in dec_error\n' ' raise TypeError\n' - ' ^^^^^^^^^^^^^^^\n' ) self.assertEqual(result_lines, expected_error.splitlines()) + def test_multiline_method_call_a(self): + def f(): + (None + .method + )() + actual = self.get_exception(f) + expected = [ + f"Traceback (most recent call last):", + f" File \"{__file__}\", line {self.callable_line}, in get_exception", + f" callable()", + f" File \"{__file__}\", line {f.__code__.co_firstlineno + 2}, in f", + f" .method", + f" ^^^^^^", + ] + self.assertEqual(actual, expected) + + def test_multiline_method_call_b(self): + def f(): + (None. + method + )() + actual = self.get_exception(f) + expected = [ + f"Traceback (most recent call last):", + f" File \"{__file__}\", line {self.callable_line}, in get_exception", + f" callable()", + f" File \"{__file__}\", line {f.__code__.co_firstlineno + 2}, in f", + f" method", + ] + self.assertEqual(actual, expected) + + def test_multiline_method_call_c(self): + def f(): + (None + . method + )() + actual = self.get_exception(f) + expected = [ + f"Traceback (most recent call last):", + f" File \"{__file__}\", line {self.callable_line}, in get_exception", + f" callable()", + f" File \"{__file__}\", line {f.__code__.co_firstlineno + 2}, in f", + f" . method", + f" ^^^^^^", + ] + self.assertEqual(actual, expected) + @cpython_only @requires_debug_ranges() class CPythonTracebackErrorCaretTests(TracebackErrorLocationCaretTests): @@ -765,12 +840,8 @@ def check_traceback_format(self, cleanup_func=None): # Make sure that the traceback is properly indented. tb_lines = python_fmt.splitlines() banner = tb_lines[0] - if has_no_debug_ranges(): - self.assertEqual(len(tb_lines), 5) - location, source_line = tb_lines[-2], tb_lines[-1] - else: - self.assertEqual(len(tb_lines), 7) - location, source_line = tb_lines[-3], tb_lines[-2] + self.assertEqual(len(tb_lines), 5) + location, source_line = tb_lines[-2], tb_lines[-1] self.assertTrue(banner.startswith('Traceback')) self.assertTrue(location.startswith(' File')) self.assertTrue(source_line.startswith(' raise')) @@ -834,16 +905,12 @@ def f(): 'Traceback (most recent call last):\n' f' File "{__file__}", line {lineno_f+5}, in _check_recursive_traceback_display\n' ' f()\n' - ' ^^^\n' f' File "{__file__}", line {lineno_f+1}, in f\n' ' f()\n' - ' ^^^\n' f' File "{__file__}", line {lineno_f+1}, in f\n' ' f()\n' - ' ^^^\n' f' File "{__file__}", line {lineno_f+1}, in f\n' ' f()\n' - ' ^^^\n' # XXX: The following line changes depending on whether the tests # are run through the interactive interpreter or with -m # It also varies depending on the platform (stack size) @@ -894,14 +961,12 @@ def g(count=10): ' [Previous line repeated 7 more times]\n' f' File "{__file__}", line {lineno_g+3}, in g\n' ' raise ValueError\n' - ' ^^^^^^^^^^^^^^^^\n' 'ValueError\n' ) tb_line = ( 'Traceback (most recent call last):\n' f' File "{__file__}", line {lineno_g+7}, in _check_recursive_traceback_display\n' ' g()\n' - ' ^^^\n' ) expected = (tb_line + result_g).splitlines() actual = stderr_g.getvalue().splitlines() @@ -926,7 +991,6 @@ def h(count=10): 'Traceback (most recent call last):\n' f' File "{__file__}", line {lineno_h+7}, in _check_recursive_traceback_display\n' ' h()\n' - ' ^^^\n' f' File "{__file__}", line {lineno_h+2}, in h\n' ' return h(count-1)\n' ' ^^^^^^^^^^\n' @@ -939,7 +1003,6 @@ def h(count=10): ' [Previous line repeated 7 more times]\n' f' File "{__file__}", line {lineno_h+3}, in h\n' ' g()\n' - ' ^^^\n' ) expected = (result_h + result_g).splitlines() actual = stderr_h.getvalue().splitlines() @@ -965,14 +1028,12 @@ def h(count=10): ' ^^^^^^^^^^\n' f' File "{__file__}", line {lineno_g+3}, in g\n' ' raise ValueError\n' - ' ^^^^^^^^^^^^^^^^\n' 'ValueError\n' ) tb_line = ( 'Traceback (most recent call last):\n' - f' File "{__file__}", line {lineno_g+81}, in _check_recursive_traceback_display\n' + f' File "{__file__}", line {lineno_g+77}, in _check_recursive_traceback_display\n' ' g(traceback._RECURSIVE_CUTOFF)\n' - ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' ) expected = (tb_line + result_g).splitlines() actual = stderr_g.getvalue().splitlines() @@ -999,14 +1060,12 @@ def h(count=10): ' [Previous line repeated 1 more time]\n' f' File "{__file__}", line {lineno_g+3}, in g\n' ' raise ValueError\n' - ' ^^^^^^^^^^^^^^^^\n' 'ValueError\n' ) tb_line = ( 'Traceback (most recent call last):\n' - f' File "{__file__}", line {lineno_g+114}, in _check_recursive_traceback_display\n' + f' File "{__file__}", line {lineno_g+108}, in _check_recursive_traceback_display\n' ' g(traceback._RECURSIVE_CUTOFF + 1)\n' - ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' ) expected = (tb_line + result_g).splitlines() actual = stderr_g.getvalue().splitlines() @@ -1059,16 +1118,10 @@ def __eq__(self, other): exception_print(exc_val) tb = stderr_f.getvalue().strip().splitlines() - if has_no_debug_ranges(): - self.assertEqual(11, len(tb)) - self.assertEqual(context_message.strip(), tb[5]) - self.assertIn('UnhashableException: ex2', tb[3]) - self.assertIn('UnhashableException: ex1', tb[10]) - else: - self.assertEqual(13, len(tb)) - self.assertEqual(context_message.strip(), tb[6]) - self.assertIn('UnhashableException: ex2', tb[4]) - self.assertIn('UnhashableException: ex1', tb[12]) + self.assertEqual(11, len(tb)) + self.assertEqual(context_message.strip(), tb[5]) + self.assertIn('UnhashableException: ex2', tb[3]) + self.assertIn('UnhashableException: ex1', tb[10]) def deep_eg(self): e = TypeError(1) @@ -1204,12 +1257,8 @@ def test_context_suppression(self): except ZeroDivisionError as _: e = _ lines = self.get_report(e).splitlines() - if has_no_debug_ranges(): - self.assertEqual(len(lines), 4) - self.assertTrue(lines[3].startswith('ZeroDivisionError')) - else: - self.assertEqual(len(lines), 5) - self.assertTrue(lines[4].startswith('ZeroDivisionError')) + self.assertEqual(len(lines), 4) + self.assertTrue(lines[3].startswith('ZeroDivisionError')) self.assertTrue(lines[0].startswith('Traceback')) self.assertTrue(lines[1].startswith(' File')) self.assertIn('ZeroDivisionError from None', lines[2]) @@ -1428,6 +1477,21 @@ def __str__(self): exp = "%s: %s\n" % (str_name, str_value) self.assertEqual(exp, err) + def test_exception_angle_bracketed_filename(self): + src = textwrap.dedent(""" + try: + raise ValueError(42) + except Exception as e: + exc = e + """) + + code = compile(src, "<does not exist>", "exec") + g, l = {}, {} + exec(code, g, l) + err = self.get_report(l['exc']) + exp = ' File "<does not exist>", line 3, in <module>\nValueError: 42\n' + self.assertIn(exp, err) + def test_exception_modulename_not_unicode(self): class X(Exception): def __str__(self): @@ -1459,10 +1523,8 @@ def exc(): f' + Exception Group Traceback (most recent call last):\n' f' | File "{__file__}", line {self.callable_line}, in get_exception\n' f' | exception_or_callable()\n' - f' | ^^^^^^^^^^^^^^^^^^^^^^^\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 1}, in exc\n' f' | raise ExceptionGroup("eg", [ValueError(1), TypeError(2)])\n' - f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' f' | ExceptionGroup: eg (2 sub-exceptions)\n' f' +-+---------------- 1 ----------------\n' f' | ValueError: 1\n' @@ -1484,7 +1546,6 @@ def exc(): expected = (f' + Exception Group Traceback (most recent call last):\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 3}, in exc\n' f' | raise EG("eg1", [ValueError(1), TypeError(2)])\n' - f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' f' | ExceptionGroup: eg1 (2 sub-exceptions)\n' f' +-+---------------- 1 ----------------\n' f' | ValueError: 1\n' @@ -1497,10 +1558,8 @@ def exc(): f' + Exception Group Traceback (most recent call last):\n' f' | File "{__file__}", line {self.callable_line}, in get_exception\n' f' | exception_or_callable()\n' - f' | ^^^^^^^^^^^^^^^^^^^^^^^\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 5}, in exc\n' f' | raise EG("eg2", [ValueError(3), TypeError(4)]) from e\n' - f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' f' | ExceptionGroup: eg2 (2 sub-exceptions)\n' f' +-+---------------- 1 ----------------\n' f' | ValueError: 3\n' @@ -1526,7 +1585,6 @@ def exc(): f' + Exception Group Traceback (most recent call last):\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 4}, in exc\n' f' | raise EG("eg1", [ValueError(1), TypeError(2)])\n' - f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' f' | ExceptionGroup: eg1 (2 sub-exceptions)\n' f' +-+---------------- 1 ----------------\n' f' | ValueError: 1\n' @@ -1539,7 +1597,6 @@ def exc(): f' + Exception Group Traceback (most recent call last):\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 6}, in exc\n' f' | raise EG("eg2", [ValueError(3), TypeError(4)])\n' - f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' f' | ExceptionGroup: eg2 (2 sub-exceptions)\n' f' +-+---------------- 1 ----------------\n' f' | ValueError: 3\n' @@ -1552,10 +1609,8 @@ def exc(): f'Traceback (most recent call last):\n' f' File "{__file__}", line {self.callable_line}, in get_exception\n' f' exception_or_callable()\n' - f' ^^^^^^^^^^^^^^^^^^^^^^^\n' f' File "{__file__}", line {exc.__code__.co_firstlineno + 8}, in exc\n' f' raise ImportError(5)\n' - f' ^^^^^^^^^^^^^^^^^^^^\n' f'ImportError: 5\n') report = self.get_report(exc) @@ -1578,7 +1633,6 @@ def exc(): expected = (f' + Exception Group Traceback (most recent call last):\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 9}, in exc\n' f' | raise EG("eg", [VE(1), exc, VE(4)])\n' - f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' f' | ExceptionGroup: eg (3 sub-exceptions)\n' f' +-+---------------- 1 ----------------\n' f' | ValueError: 1\n' @@ -1586,7 +1640,6 @@ def exc(): f' | Exception Group Traceback (most recent call last):\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 6}, in exc\n' f' | raise EG("nested", [TE(2), TE(3)])\n' - f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' f' | ExceptionGroup: nested (2 sub-exceptions)\n' f' +-+---------------- 1 ----------------\n' f' | TypeError: 2\n' @@ -1602,10 +1655,8 @@ def exc(): f' + Exception Group Traceback (most recent call last):\n' f' | File "{__file__}", line {self.callable_line}, in get_exception\n' f' | exception_or_callable()\n' - f' | ^^^^^^^^^^^^^^^^^^^^^^^\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 11}, in exc\n' f' | raise EG("top", [VE(5)])\n' - f' | ^^^^^^^^^^^^^^^^^^^^^^^^\n' f' | ExceptionGroup: top (1 sub-exception)\n' f' +-+---------------- 1 ----------------\n' f' | ValueError: 5\n' @@ -1763,10 +1814,8 @@ def exc(): expected = (f' + Exception Group Traceback (most recent call last):\n' f' | File "{__file__}", line {self.callable_line}, in get_exception\n' f' | exception_or_callable()\n' - f' | ^^^^^^^^^^^^^^^^^^^^^^^\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 9}, in exc\n' f' | raise ExceptionGroup("nested", excs)\n' - f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' f' | ExceptionGroup: nested (2 sub-exceptions)\n' f' | >> Multi line note\n' f' | >> Because I am such\n' @@ -1778,14 +1827,12 @@ def exc(): f' | Traceback (most recent call last):\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 5}, in exc\n' f' | raise ValueError(msg)\n' - f' | ^^^^^^^^^^^^^^^^^^^^^\n' f' | ValueError: bad value\n' f' | the bad value\n' f' +---------------- 2 ----------------\n' f' | Traceback (most recent call last):\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 5}, in exc\n' f' | raise ValueError(msg)\n' - f' | ^^^^^^^^^^^^^^^^^^^^^\n' f' | ValueError: terrible value\n' f' | the terrible value\n' f' +------------------------------------\n') @@ -1818,10 +1865,8 @@ def exc(): expected = (f' + Exception Group Traceback (most recent call last):\n' f' | File "{__file__}", line {self.callable_line}, in get_exception\n' f' | exception_or_callable()\n' - f' | ^^^^^^^^^^^^^^^^^^^^^^^\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 10}, in exc\n' f' | raise ExceptionGroup("nested", excs)\n' - f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' f' | ExceptionGroup: nested (2 sub-exceptions)\n' f' | >> Multi line note\n' f' | >> Because I am such\n' @@ -1834,7 +1879,6 @@ def exc(): f' | Traceback (most recent call last):\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 5}, in exc\n' f' | raise ValueError(msg)\n' - f' | ^^^^^^^^^^^^^^^^^^^^^\n' f' | ValueError: bad value\n' f' | the bad value\n' f' | Goodbye bad value\n' @@ -1842,7 +1886,6 @@ def exc(): f' | Traceback (most recent call last):\n' f' | File "{__file__}", line {exc.__code__.co_firstlineno + 5}, in exc\n' f' | raise ValueError(msg)\n' - f' | ^^^^^^^^^^^^^^^^^^^^^\n' f' | ValueError: terrible value\n' f' | the terrible value\n' f' | Goodbye terrible value\n' @@ -2247,6 +2290,9 @@ def format_frame_summary(self, frame_summary): f' File "{__file__}", line {lno}, in f\n 1/0\n' ) +class Unrepresentable: + def __repr__(self) -> str: + raise Exception("Unrepresentable") class TestTracebackException(unittest.TestCase): @@ -2514,12 +2560,13 @@ def test_locals(self): linecache.updatecache('/foo.py', globals()) e = Exception("uh oh") c = test_code('/foo.py', 'method') - f = test_frame(c, globals(), {'something': 1, 'other': 'string'}) + f = test_frame(c, globals(), {'something': 1, 'other': 'string', 'unrepresentable': Unrepresentable()}) tb = test_tb(f, 6, None, 0) exc = traceback.TracebackException( Exception, e, tb, capture_locals=True) self.assertEqual( - exc.stack[0].locals, {'something': '1', 'other': "'string'"}) + exc.stack[0].locals, + {'something': '1', 'other': "'string'", 'unrepresentable': '<local repr() failed>'}) def test_no_locals(self): linecache.updatecache('/foo.py', globals()) @@ -2618,19 +2665,16 @@ def test_exception_group_format(self): f' + Exception Group Traceback (most recent call last):', f' | File "{__file__}", line {lno_g+23}, in _get_exception_group', f' | raise ExceptionGroup("eg2", [exc3, exc4])', - f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^', f' | ExceptionGroup: eg2 (2 sub-exceptions)', f' +-+---------------- 1 ----------------', f' | Exception Group Traceback (most recent call last):', f' | File "{__file__}", line {lno_g+16}, in _get_exception_group', f' | raise ExceptionGroup("eg1", [exc1, exc2])', - f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^', f' | ExceptionGroup: eg1 (2 sub-exceptions)', f' +-+---------------- 1 ----------------', f' | Traceback (most recent call last):', f' | File "{__file__}", line {lno_g+9}, in _get_exception_group', f' | f()', - f' | ^^^', f' | File "{__file__}", line {lno_f+1}, in f', f' | 1/0', f' | ~^~', @@ -2639,20 +2683,16 @@ def test_exception_group_format(self): f' | Traceback (most recent call last):', f' | File "{__file__}", line {lno_g+13}, in _get_exception_group', f' | g(42)', - f' | ^^^^^', f' | File "{__file__}", line {lno_g+1}, in g', f' | raise ValueError(v)', - f' | ^^^^^^^^^^^^^^^^^^^', f' | ValueError: 42', f' +------------------------------------', f' +---------------- 2 ----------------', f' | Traceback (most recent call last):', f' | File "{__file__}", line {lno_g+20}, in _get_exception_group', f' | g(24)', - f' | ^^^^^', f' | File "{__file__}", line {lno_g+1}, in g', f' | raise ValueError(v)', - f' | ^^^^^^^^^^^^^^^^^^^', f' | ValueError: 24', f' +------------------------------------', f''] diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py index fd2739dd89ac064459ea741f4d5ba1d9aa846123..52d43bdead67f8efecf123c76944006c26b14a86 100644 --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -742,7 +742,8 @@ def testBytesPath(self): z.writestr(zinfo, test_src) zipimport.zipimporter(filename) - zipimport.zipimporter(os.fsencode(filename)) + with self.assertRaises(TypeError): + zipimport.zipimporter(os.fsencode(filename)) with self.assertRaises(TypeError): zipimport.zipimporter(bytearray(os.fsencode(filename))) with self.assertRaises(TypeError): diff --git a/Lib/traceback.py b/Lib/traceback.py index 3afe49d1d8a0e655f156621d2b960f436a19f538..b1a5fd0a26d40a817d0968adc810c4e82946fa23 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -279,7 +279,8 @@ def __init__(self, filename, lineno, name, *, lookup_line=True, self._line = line if lookup_line: self.line - self.locals = {k: repr(v) for k, v in locals.items()} if locals else None + self.locals = {k: _safe_string(v, 'local', func=repr) + for k, v in locals.items()} if locals else None self.end_lineno = end_lineno self.colno = colno self.end_colno = end_colno @@ -465,7 +466,8 @@ def format_frame_summary(self, frame_summary): row.append(' File "{}", line {}, in {}\n'.format( frame_summary.filename, frame_summary.lineno, frame_summary.name)) if frame_summary.line: - row.append(' {}\n'.format(frame_summary.line.strip())) + stripped_line = frame_summary.line.strip() + row.append(' {}\n'.format(stripped_line)) orig_line_len = len(frame_summary._original_line) frame_line_len = len(frame_summary.line.lstrip()) @@ -486,19 +488,22 @@ def format_frame_summary(self, frame_summary): frame_summary._original_line[colno - 1:end_colno - 1] ) else: - end_colno = stripped_characters + len(frame_summary.line.strip()) - - row.append(' ') - row.append(' ' * (colno - stripped_characters)) - - if anchors: - row.append(anchors.primary_char * (anchors.left_end_offset)) - row.append(anchors.secondary_char * (anchors.right_start_offset - anchors.left_end_offset)) - row.append(anchors.primary_char * (end_colno - colno - anchors.right_start_offset)) - else: - row.append('^' * (end_colno - colno)) + end_colno = stripped_characters + len(stripped_line) + + # show indicators if primary char doesn't span the frame line + if end_colno - colno < len(stripped_line) or ( + anchors and anchors.right_start_offset - anchors.left_end_offset > 0): + row.append(' ') + row.append(' ' * (colno - stripped_characters)) + + if anchors: + row.append(anchors.primary_char * (anchors.left_end_offset)) + row.append(anchors.secondary_char * (anchors.right_start_offset - anchors.left_end_offset)) + row.append(anchors.primary_char * (end_colno - colno - anchors.right_start_offset)) + else: + row.append('^' * (end_colno - colno)) - row.append('\n') + row.append('\n') if frame_summary.locals: for name, value in sorted(frame_summary.locals.items()): diff --git a/Lib/typing.py b/Lib/typing.py index 66c26e416bd0ba7d760891c7ef7e74c7c4752a01..43ef07e50cfefce6be549d44c1c7e3fc1a568cd8 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -569,7 +569,7 @@ def Self(self, parameters): from typing import Self class Foo: - def returns_self(self) -> Self: + def return_self(self) -> Self: ... return self diff --git a/Lib/uuid.py b/Lib/uuid.py index f179d68e8265ac6113ce1cf5ac3798d54c7d276b..8fe2479f3f22cfec686e5c01d9d9b104f7ef90ff 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -524,6 +524,8 @@ def _ip_getnode(): def _arp_getnode(): """Get the hardware address on Unix by running arp.""" import os, socket + if not hasattr(socket, "gethostbyname"): + return None try: ip_addr = socket.gethostbyname(socket.gethostname()) except OSError: diff --git a/Lib/wsgiref/types.py b/Lib/wsgiref/types.py index 9e74a6c7312b19b051fb67b0c480660964fe01f3..ef0aead5b28b647bd1ad49fef80a490fbd2dc1a8 100644 --- a/Lib/wsgiref/types.py +++ b/Lib/wsgiref/types.py @@ -1,6 +1,6 @@ """WSGI-related types for static type checking""" -from collections.abc import Callable, Iterable +from collections.abc import Callable, Iterable, Iterator from types import TracebackType from typing import Any, Protocol, TypeAlias @@ -35,7 +35,7 @@ class InputStream(Protocol): def read(self, size: int = ..., /) -> bytes: ... def readline(self, size: int = ..., /) -> bytes: ... def readlines(self, hint: int = ..., /) -> list[bytes]: ... - def __iter__(self) -> Iterable[bytes]: ... + def __iter__(self) -> Iterator[bytes]: ... class ErrorStream(Protocol): """WSGI error stream as defined in PEP 3333""" diff --git a/Lib/zipimport.py b/Lib/zipimport.py index d0394107c2c5facbf8ab518d31b24eb31c0b227c..016f1b8a79798849ea41b486bcf86c90f31117c0 100644 --- a/Lib/zipimport.py +++ b/Lib/zipimport.py @@ -63,8 +63,7 @@ class zipimporter(_bootstrap_external._LoaderBasics): # if found, or else read it from the archive. def __init__(self, path): if not isinstance(path, str): - import os - path = os.fsdecode(path) + raise TypeError(f"expected str, not {type(path)!r}") if not path: raise ZipImportError('archive path is empty', path=path) if alt_path_sep: diff --git a/Mac/IDLE/IDLE.app/Contents/Info.plist b/Mac/IDLE/IDLE.app/Contents/Info.plist index d197c77ed4b1a3e6b1cac1fb1c7ffe4f25cd7442..799a164cbdf2ed72ffed9897c765f49162402ccd 100644 --- a/Mac/IDLE/IDLE.app/Contents/Info.plist +++ b/Mac/IDLE/IDLE.app/Contents/Info.plist @@ -10,6 +10,7 @@ <key>CFBundleTypeExtensions</key> <array> <string>py</string> + <string>pyi</string> <string>pyw</string> </array> <key>CFBundleTypeIconFile</key> diff --git a/Makefile.pre.in b/Makefile.pre.in index e1dc503059ec286283d85cc62bd06702908921de..746ff4226e6c43bc25bde73d99b3fb52381b449f 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -211,12 +211,6 @@ ENSUREPIP= @ENSUREPIP@ LIBMPDEC_A= Modules/_decimal/libmpdec/libmpdec.a LIBEXPAT_A= Modules/expat/libexpat.a -# OpenSSL options for setup.py so sysconfig can pick up AC_SUBST() vars. -OPENSSL_INCLUDES=@OPENSSL_INCLUDES@ -OPENSSL_LIBS=@OPENSSL_LIBS@ -OPENSSL_LDFLAGS=@OPENSSL_LDFLAGS@ -OPENSSL_RPATH=@OPENSSL_RPATH@ - # Module state, compiler flags and linker flags # Empty CFLAGS and LDFLAGS are omitted. # states: @@ -318,7 +312,8 @@ PROFILE_TASK= @PROFILE_TASK@ # report files for gcov / lcov coverage report COVERAGE_INFO= $(abs_builddir)/coverage.info COVERAGE_REPORT=$(abs_builddir)/lcov-report -COVERAGE_REPORT_OPTIONS=--no-branch-coverage --title "CPython lcov report" +COVERAGE_LCOV_OPTIONS=--rc lcov_branch_coverage=1 +COVERAGE_REPORT_OPTIONS=--rc lcov_branch_coverage=1 --branch-coverage --title "CPython $(VERSION) LCOV report [commit $(shell $(GITVERSION))]" # === Definitions added by makesetup === @@ -440,7 +435,6 @@ PYTHON_OBJS= \ # Objects OBJECT_OBJS= \ Objects/abstract.o \ - Objects/accu.o \ Objects/boolobject.o \ Objects/bytes_methods.o \ Objects/bytearrayobject.o \ @@ -581,9 +575,10 @@ LIBEXPAT_HEADERS= \ # Default target all: @DEF_MAKE_ALL_RULE@ -build_all: check-clean-src $(BUILDPYTHON) platform oldsharedmods sharedmods \ - gdbhooks Programs/_testembed scripts -build_wasm: check-clean-src $(BUILDPYTHON) platform oldsharedmods python-config +build_all: check-clean-src $(BUILDPYTHON) platform sharedmods \ + gdbhooks Programs/_testembed scripts checksharedmods +build_wasm: check-clean-src $(BUILDPYTHON) platform sharedmods \ + python-config checksharedmods # Check that the source is clean when building out of source. check-clean-src: @@ -651,25 +646,24 @@ profile-opt: profile-run-stamp coverage: @echo "Building with support for coverage checking:" $(MAKE) clean - $(MAKE) @DEF_MAKE_RULE@ CFLAGS="$(CFLAGS) -O0 -pg --coverage" LIBS="$(LIBS) --coverage" + $(MAKE) @DEF_MAKE_RULE@ CFLAGS="$(CFLAGS) -O0 -pg --coverage" LDFLAGS="$(LDFLAGS) --coverage" coverage-lcov: @echo "Creating Coverage HTML report with LCOV:" @rm -f $(COVERAGE_INFO) @rm -rf $(COVERAGE_REPORT) - @lcov --capture --directory $(abs_builddir) \ + @lcov $(COVERAGE_LCOV_OPTIONS) --capture \ + --directory $(abs_builddir) \ --base-directory $(realpath $(abs_builddir)) \ --path $(realpath $(abs_srcdir)) \ --output-file $(COVERAGE_INFO) @ # remove 3rd party modules, system headers and internal files with @ # debug, test or dummy functions. - @lcov --remove $(COVERAGE_INFO) \ + @lcov $(COVERAGE_LCOV_OPTIONS) --remove $(COVERAGE_INFO) \ '*/Modules/_blake2/impl/*' \ '*/Modules/_ctypes/libffi*/*' \ '*/Modules/_decimal/libmpdec/*' \ '*/Modules/expat/*' \ - '*/Modules/zlib/*' \ - '*/Include/*' \ '*/Modules/xx*.c' \ '*/Python/pyfpe.c' \ '*/Python/pystrcmp.c' \ @@ -677,7 +671,8 @@ coverage-lcov: '/usr/local/include/*' \ '/usr/lib/gcc/*' \ --output-file $(COVERAGE_INFO) - @genhtml $(COVERAGE_INFO) --output-directory $(COVERAGE_REPORT) \ + @genhtml $(COVERAGE_INFO) \ + --output-directory $(COVERAGE_REPORT) \ $(COVERAGE_REPORT_OPTIONS) @echo @echo "lcov report at $(COVERAGE_REPORT)/index.html" @@ -725,22 +720,6 @@ $(srcdir)/Modules/_blake2/blake2s_impl.c: $(srcdir)/Modules/_blake2/blake2b_impl $(PYTHON_FOR_REGEN) $(srcdir)/Modules/_blake2/blake2b2s.py $(PYTHON_FOR_REGEN) $(srcdir)/Tools/clinic/clinic.py -f $@ -# Build the shared modules -# Under GNU make, MAKEFLAGS are sorted and normalized; the 's' for -# -s, --silent or --quiet is always the first char. -# Under BSD make, MAKEFLAGS might be " -s -v x=y". -# Ignore macros passed by GNU make, passed after -- -sharedmods: $(PYTHON_FOR_BUILD_DEPS) pybuilddir.txt @LIBMPDEC_INTERNAL@ @LIBEXPAT_INTERNAL@ - @case "`echo X $$MAKEFLAGS | sed 's/^X //;s/ -- .*//'`" in \ - *\ -s*|s*) quiet="-q";; \ - *) quiet="";; \ - esac; \ - echo "$(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ - $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build"; \ - $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ - $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build - - # Build static library $(LIBRARY): $(LIBRARY_OBJS) -rm -f $@ @@ -831,10 +810,6 @@ python.worker.js: $(srcdir)/Tools/wasm/python.worker.js # Build static libmpdec.a LIBMPDEC_CFLAGS=@LIBMPDEC_CFLAGS@ $(PY_STDMODULE_CFLAGS) $(CCSHARED) -# for setup.py -DECIMAL_CFLAGS=@LIBMPDEC_CFLAGS@ -DECIMAL_LDFLAGS=@LIBMPDEC_LDFLAGS@ - # "%.o: %c" is not portable Modules/_decimal/libmpdec/basearith.o: $(srcdir)/Modules/_decimal/libmpdec/basearith.c $(LIBMPDEC_HEADERS) $(PYTHON_HEADERS) $(CC) -c $(LIBMPDEC_CFLAGS) -o $@ $(srcdir)/Modules/_decimal/libmpdec/basearith.c @@ -889,10 +864,6 @@ $(LIBMPDEC_A): $(LIBMPDEC_OBJS) # Build static libexpat.a LIBEXPAT_CFLAGS=@LIBEXPAT_CFLAGS@ $(PY_STDMODULE_CFLAGS) $(CCSHARED) -# for setup.py -EXPAT_CFLAGS=@LIBEXPAT_CFLAGS@ -EXPAT_LDFLAGS=@LIBEXPAT_LDFLAGS@ - Modules/expat/xmlparse.o: $(srcdir)/Modules/expat/xmlparse.c $(LIBEXPAT_HEADERS) $(PYTHON_HEADERS) $(CC) -c $(LIBEXPAT_CFLAGS) -o $@ $(srcdir)/Modules/expat/xmlparse.c @@ -909,7 +880,7 @@ $(LIBEXPAT_A): $(LIBEXPAT_OBJS) # create relative links from build/lib.platform/egg.so to Modules/egg.so # pybuilddir.txt is created too late. We cannot use it in Makefile # targets. ln --relative is not portable. -oldsharedmods: $(SHAREDMODS) pybuilddir.txt +sharedmods: $(SHAREDMODS) pybuilddir.txt @target=`cat pybuilddir.txt`; \ $(MKDIR_P) $$target; \ for mod in X $(SHAREDMODS); do \ @@ -918,7 +889,8 @@ oldsharedmods: $(SHAREDMODS) pybuilddir.txt fi; \ done -checksharedmods: oldsharedmods sharedmods $(PYTHON_FOR_BUILD_DEPS) +# dependency on BUILDPYTHON ensures that the target is run last +checksharedmods: sharedmods $(PYTHON_FOR_BUILD_DEPS) $(BUILDPYTHON) @$(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/Tools/scripts/check_extension_modules.py Modules/Setup.local: @@ -941,7 +913,7 @@ Makefile Modules/config.c: Makefile.pre \ $(SHELL) $(MAKESETUP) -c $(srcdir)/Modules/config.c.in \ -s Modules \ Modules/Setup.local \ - @MODULES_SETUP_STDLIB@ \ + Modules/Setup.stdlib \ Modules/Setup.bootstrap \ $(srcdir)/Modules/Setup @mv config.c Modules @@ -1572,6 +1544,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/cpython/objimpl.h \ $(srcdir)/Include/cpython/odictobject.h \ $(srcdir)/Include/cpython/picklebufobject.h \ + $(srcdir)/Include/cpython/pthread_stubs.h \ $(srcdir)/Include/cpython/pyctype.h \ $(srcdir)/Include/cpython/pydebug.h \ $(srcdir)/Include/cpython/pyerrors.h \ @@ -1592,7 +1565,6 @@ PYTHON_HEADERS= \ $(srcdir)/Include/cpython/weakrefobject.h \ \ $(srcdir)/Include/internal/pycore_abstract.h \ - $(srcdir)/Include/internal/pycore_accu.h \ $(srcdir)/Include/internal/pycore_asdl.h \ $(srcdir)/Include/internal/pycore_ast.h \ $(srcdir)/Include/internal/pycore_ast_state.h \ @@ -1761,13 +1733,13 @@ altinstall: commoninstall commoninstall: check-clean-src @FRAMEWORKALTINSTALLFIRST@ \ altbininstall libinstall inclinstall libainstall \ - sharedinstall oldsharedinstall altmaninstall \ + sharedinstall altmaninstall \ @FRAMEWORKALTINSTALLLAST@ # Install shared libraries enabled by Setup DESTDIRS= $(exec_prefix) $(LIBDIR) $(BINLIBDEST) $(DESTSHARED) -oldsharedinstall: $(DESTSHARED) all +sharedinstall: $(DESTSHARED) all @for i in X $(SHAREDMODS); do \ if test $$i != X; then \ echo $(INSTALL_SHARED) $$i $(DESTSHARED)/`basename $$i`; \ @@ -1953,15 +1925,6 @@ TESTSUBDIRS= distutils/tests \ test/test_importlib \ test/test_importlib/builtin \ test/test_importlib/data \ - test/test_importlib/data01 \ - test/test_importlib/data01/subdirectory \ - test/test_importlib/data02 \ - test/test_importlib/data02/one \ - test/test_importlib/data02/two \ - test/test_importlib/data03 \ - test/test_importlib/data03/namespace \ - test/test_importlib/data03/namespace/portion1 \ - test/test_importlib/data03/namespace/portion2 \ test/test_importlib/extension \ test/test_importlib/frozen \ test/test_importlib/import_ \ @@ -1985,12 +1948,21 @@ TESTSUBDIRS= distutils/tests \ test/test_importlib/namespace_pkgs/project3 \ test/test_importlib/namespace_pkgs/project3/parent \ test/test_importlib/namespace_pkgs/project3/parent/child \ - test/test_importlib/namespacedata01 \ test/test_importlib/partial \ test/test_importlib/resources \ + test/test_importlib/resources/data01 \ + test/test_importlib/resources/data01/subdirectory \ + test/test_importlib/resources/data02 \ + test/test_importlib/resources/data02/one \ + test/test_importlib/resources/data02/two \ + test/test_importlib/resources/data03 \ + test/test_importlib/resources/data03/namespace \ + test/test_importlib/resources/data03/namespace/portion1 \ + test/test_importlib/resources/data03/namespace/portion2 \ + test/test_importlib/resources/namespacedata01 \ + test/test_importlib/resources/zipdata01 \ + test/test_importlib/resources/zipdata02 \ test/test_importlib/source \ - test/test_importlib/zipdata01 \ - test/test_importlib/zipdata02 \ test/test_json \ test/test_lib2to3 \ test/test_lib2to3/data \ @@ -2251,17 +2223,6 @@ libainstall: all scripts else true; \ fi -# Install the dynamically loadable modules -# This goes into $(exec_prefix) -sharedinstall: all - $(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/setup.py install \ - --prefix=$(prefix) \ - --install-scripts=$(BINDIR) \ - --install-platlib=$(DESTSHARED) \ - --root=$(DESTDIR)/ - -rm $(DESTDIR)$(DESTSHARED)/_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).py - -rm -r $(DESTDIR)$(DESTSHARED)/__pycache__ - # Here are a couple of targets for MacOSX again, to install a full # framework-based Python. frameworkinstall installs everything, the # subtargets install specific parts. Much of the actual work is offloaded to @@ -2535,10 +2496,10 @@ update-config: Python/thread.o: @THREADHEADERS@ $(srcdir)/Python/condvar.h # Declare targets that aren't real files -.PHONY: all build_all build_wasm sharedmods check-clean-src -.PHONY: oldsharedmods checksharedmods test quicktest -.PHONY: install altinstall oldsharedinstall bininstall altbininstall -.PHONY: maninstall libinstall inclinstall libainstall sharedinstall +.PHONY: all build_all build_wasm check-clean-src +.PHONY: sharedmods checksharedmods test quicktest +.PHONY: install altinstall sharedinstall bininstall altbininstall +.PHONY: maninstall libinstall inclinstall libainstall .PHONY: frameworkinstall frameworkinstallframework frameworkinstallstructure .PHONY: frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools .PHONY: frameworkaltinstallunixtools recheck clean clobber distclean @@ -2566,7 +2527,7 @@ MODULE__SHA1_DEPS=$(srcdir)/Modules/hashlib.h MODULE__SHA256_DEPS=$(srcdir)/Modules/hashlib.h MODULE__SHA3_DEPS=$(srcdir)/Modules/_sha3/sha3.c $(srcdir)/Modules/_sha3/sha3.h $(srcdir)/Modules/hashlib.h MODULE__SHA512_DEPS=$(srcdir)/Modules/hashlib.h -MODULE__SOCKET_DEPS=$(srcdir)/Modules/socketmodule.h +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_long.h $(srcdir)/Modules/_testcapi/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 diff --git a/Misc/ACKS b/Misc/ACKS index b6340414cf701237d05b3bc9596879f9ab73b60d..32475f874c36db74e19746276cf253582d5330f2 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1590,6 +1590,7 @@ Ed Schouten Scott Schram Robin Schreiber Chad J. Schroeder +Simon-Martin Schroeder Christian Schubert Sam Schulenburg Andreas Schwab diff --git a/Misc/NEWS.d/3.10.0a1.rst b/Misc/NEWS.d/3.10.0a1.rst index 1c1c2d54e8c20a2a575634981d1f4cac9fa3724e..471811662644bf6c5e468ec4f09e19201734ee7d 100644 --- a/Misc/NEWS.d/3.10.0a1.rst +++ b/Misc/NEWS.d/3.10.0a1.rst @@ -2204,7 +2204,7 @@ Handle cases where the ``end_lineno`` is ``None`` on .. nonce: zwl5Hc .. section: Library -:mod:`distutils` upload creates SHA2-256 and Blake2b-256 digests. MD5 +``distutils`` upload creates SHA2-256 and Blake2b-256 digests. MD5 digests is skipped if platform blocks MD5. .. diff --git a/Misc/NEWS.d/3.10.0b1.rst b/Misc/NEWS.d/3.10.0b1.rst index 2a3d358edde902846b1603bc93ae7899539d789a..f29fc6632db26ce186e4d5d882e0d0188540e40b 100644 --- a/Misc/NEWS.d/3.10.0b1.rst +++ b/Misc/NEWS.d/3.10.0b1.rst @@ -1142,7 +1142,7 @@ name>`` instead of ``SQL logic error``. Patch by Erlend E. Aasland. .. nonce: GK9a0l .. section: Library -Install schemes in :mod:`distutils.command.install` are now loaded from +Install schemes in ``distutils.command.install`` are now loaded from :mod:`sysconfig`. .. @@ -1152,7 +1152,7 @@ Install schemes in :mod:`distutils.command.install` are now loaded from .. nonce: SenEje .. section: Library -:mod:`distutils.sysconfig` has been merged to :mod:`sysconfig`. +``distutils.sysconfig`` has been merged to :mod:`sysconfig`. .. diff --git a/Misc/NEWS.d/3.11.0a1.rst b/Misc/NEWS.d/3.11.0a1.rst index 33841d9e4e39bba73e8843c6b08801c587dbc8fa..7670e482ede5b613f0e2b440687e4962027d060e 100644 --- a/Misc/NEWS.d/3.11.0a1.rst +++ b/Misc/NEWS.d/3.11.0a1.rst @@ -1445,7 +1445,7 @@ asynchronous. .. nonce: NOwcDJ .. section: Library -Fix clang rpath issue in :mod:`distutils`. The UnixCCompiler now uses +Fix clang rpath issue in ``distutils``. The UnixCCompiler now uses correct clang option to add a runtime library directory (rpath) to a shared library. @@ -2798,7 +2798,7 @@ documentation for deprecations. .. nonce: rvyf2v .. section: Library -Restore back :func:`parse_makefile` in :mod:`distutils.sysconfig` because it +Restore back :func:`parse_makefile` in ``distutils.sysconfig`` because it behaves differently than the similar implementation in :mod:`sysconfig`. .. diff --git a/Misc/NEWS.d/3.11.0a2.rst b/Misc/NEWS.d/3.11.0a2.rst index 1f742a29ebcc9bb38ddb9d45d92af2979db27bec..8ae8847d846b126a6f3f09e7fe30670ef82b6082 100644 --- a/Misc/NEWS.d/3.11.0a2.rst +++ b/Misc/NEWS.d/3.11.0a2.rst @@ -702,16 +702,6 @@ details. Patch by Jochem Schulenklopper. .. -.. bpo: 10572 -.. date: 2021-01-07-01-25-38 -.. nonce: gEEZ9z -.. section: Library - -Move :mod:`sqlite3` tests to ``/Lib/test/test_sqlite3``. Patch by Erlend E. -Aasland. - -.. - .. bpo: 41374 .. date: 2020-07-27-19-21-05 .. nonce: cd-kFL @@ -956,6 +946,16 @@ use a stricter regular expression. Patch by Victor Stinner. .. +.. bpo: 10572 +.. date: 2021-01-07-01-25-38 +.. nonce: gEEZ9z +.. section: Tests + +Rename :mod:`sqlite3` tests from ``test_sqlite`` to ``test_sqlite3``, and +relocate them to ``Lib/test/test_sqlite3``. Patch by Erlend E. Aasland. + +.. + .. bpo: 43158 .. date: 2021-11-01-12-51-46 .. nonce: fghS6w diff --git a/Misc/NEWS.d/3.8.0a1.rst b/Misc/NEWS.d/3.8.0a1.rst index d95055a59da3282aa8917a0ef3886ffec856d862..991bbc128670b2568f3efe0c5040961389e06652 100644 --- a/Misc/NEWS.d/3.8.0a1.rst +++ b/Misc/NEWS.d/3.8.0a1.rst @@ -17,7 +17,7 @@ malicious or buggy certificate can result into segfault. Vulnerability .. section: Security The :option:`-I` command line option (run Python in isolated mode) is now -also copied by the :mod:`multiprocessing` and :mod:`distutils` modules when +also copied by the :mod:`multiprocessing` and ``distutils`` modules when spawning child processes. Previously, only :option:`-E` and :option:`-s` options (enabled by :option:`-I`) were copied. @@ -2270,7 +2270,7 @@ last release was in 2000. Mac OS 9 last release was in 2001. .. nonce: laV_IE .. section: Library -:func:`~distutils.utils.check_environ` of :mod:`distutils.utils` now catches +:func:`~distutils.utils.check_environ` of ``distutils.utils`` now catches :exc:`KeyError` on calling :func:`pwd.getpwuid`: don't create the ``HOME`` environment variable in this case. @@ -3070,7 +3070,7 @@ Add deprecation warning when `loop` is used in methods: `asyncio.sleep`, .. nonce: Pr3-iG .. section: Library -ZIP files created by :mod:`distutils` will now include entries for +ZIP files created by ``distutils`` will now include entries for directories. .. @@ -3720,7 +3720,7 @@ Deprecate passing non-ThreadPoolExecutor instances to .. section: Library Restore ``msilib.Win64`` to preserve backwards compatibility since it's -already used by :mod:`distutils`' ``bdist_msi`` command. +already used by ``distutils``' ``bdist_msi`` command. .. diff --git a/Misc/NEWS.d/3.8.0a4.rst b/Misc/NEWS.d/3.8.0a4.rst index fc952fa9dcc8e1b3ac2d8d8c09b878aad880b322..a21de196aa9652c5ad2b683ae6abd4653507c681 100644 --- a/Misc/NEWS.d/3.8.0a4.rst +++ b/Misc/NEWS.d/3.8.0a4.rst @@ -338,7 +338,7 @@ unexpected cache miss. .. nonce: MW1TLt .. section: Library -Fix :mod:`distutils.sysconfig` if :data:`sys.executable` is ``None`` or an +Fix ``distutils.sysconfig`` if :data:`sys.executable` is ``None`` or an empty string: use :func:`os.getcwd` to initialize ``project_base``. Fix also the distutils build command: don't use :data:`sys.executable` if it is ``None`` or an empty string. @@ -350,7 +350,7 @@ also the distutils build command: don't use :data:`sys.executable` if it is .. nonce: Fg4EXb .. section: Library -:func:`shutil.which` and :func:`distutils.spawn.find_executable` now use +:func:`shutil.which` and ``distutils.spawn.find_executable`` now use ``os.confstr("CS_PATH")`` if available instead of :data:`os.defpath`, if the ``PATH`` environment variable is not set. Moreover, don't use ``os.confstr("CS_PATH")`` nor :data:`os.defpath` if the ``PATH`` environment diff --git a/Misc/NEWS.d/3.9.0a5.rst b/Misc/NEWS.d/3.9.0a5.rst index 49a118ad7e4308b6769080de4e45db5d56294198..25342d21d8f0b17f4a5c4aa87d7dbeda0f9b37e8 100644 --- a/Misc/NEWS.d/3.9.0a5.rst +++ b/Misc/NEWS.d/3.9.0a5.rst @@ -623,7 +623,7 @@ connections. .. nonce: 5a822c .. section: Library -Reimplement :func:`distutils.spawn.spawn` function with the +Reimplement ``distutils.spawn.spawn`` function with the :mod:`subprocess` module. .. @@ -1022,7 +1022,7 @@ lock-related objects from :mod:`threading`) around 49-day uptime. .. nonce: MnHdYl .. section: Windows -:mod:`distutils` will no longer statically link :file:`vcruntime140.dll` +``distutils`` will no longer statically link :file:`vcruntime140.dll` when a redistributable version is unavailable. All future releases of CPython will include a copy of this DLL to ensure distributed extensions can continue to load. diff --git a/Misc/NEWS.d/next/Build/2022-06-28-09-42-10.gh-issue-93939._VWxKW.rst b/Misc/NEWS.d/next/Build/2022-06-28-09-42-10.gh-issue-93939._VWxKW.rst new file mode 100644 index 0000000000000000000000000000000000000000..ab873bc839f4e5aa54d5bfef022fb3a1f131e7c8 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-06-28-09-42-10.gh-issue-93939._VWxKW.rst @@ -0,0 +1,2 @@ +C extension modules are now built by ``configure`` and ``make`` +instead of ``distutils`` and ``setup.py``. diff --git a/Misc/NEWS.d/next/Build/2022-07-12-13-39-18.gh-issue-94773.koHKm5.rst b/Misc/NEWS.d/next/Build/2022-07-12-13-39-18.gh-issue-94773.koHKm5.rst new file mode 100644 index 0000000000000000000000000000000000000000..ed7e40c91103d6b169116f32281d336176b904d9 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-07-12-13-39-18.gh-issue-94773.koHKm5.rst @@ -0,0 +1,2 @@ +``deepfreeze.py`` now supports code object with frozensets that contain +incompatible, unsortable types. diff --git a/Misc/NEWS.d/next/Build/2022-07-13-10-13-10.gh-issue-94801.3xUB24.rst b/Misc/NEWS.d/next/Build/2022-07-13-10-13-10.gh-issue-94801.3xUB24.rst new file mode 100644 index 0000000000000000000000000000000000000000..5caf84f96da131d42edc299533e22b166e523814 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-07-13-10-13-10.gh-issue-94801.3xUB24.rst @@ -0,0 +1,2 @@ +``configure`` now uses custom flags like ``ZLIB_CFLAGS`` and ``ZLIB_LIBS`` +when searching for headers and libraries. diff --git a/Misc/NEWS.d/next/Build/2022-07-14-02-45-44.gh-issue-94841.lLRTdf.rst b/Misc/NEWS.d/next/Build/2022-07-14-02-45-44.gh-issue-94841.lLRTdf.rst new file mode 100644 index 0000000000000000000000000000000000000000..f7ad4f88a51db04e5a235321697549a068500748 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-07-14-02-45-44.gh-issue-94841.lLRTdf.rst @@ -0,0 +1 @@ +Fix the possible performance regression of :c:func:`PyObject_Free` compiled with MSVC version 1932. diff --git a/Misc/NEWS.d/next/Build/2022-07-14-11-13-26.gh-issue-94847.s3Kr5p.rst b/Misc/NEWS.d/next/Build/2022-07-14-11-13-26.gh-issue-94847.s3Kr5p.rst new file mode 100644 index 0000000000000000000000000000000000000000..a6d1e7277da4c050a4a959c6fec527d00ad2b094 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-07-14-11-13-26.gh-issue-94847.s3Kr5p.rst @@ -0,0 +1,2 @@ +Fixed ``_decimal`` module build issue on GCC when compiling with LTO and +pydebug. Debug builds no longer force inlining of functions. diff --git a/Misc/NEWS.d/next/Build/2022-07-21-09-17-01.gh-issue-95085.E9x2S_.rst b/Misc/NEWS.d/next/Build/2022-07-21-09-17-01.gh-issue-95085.E9x2S_.rst new file mode 100644 index 0000000000000000000000000000000000000000..02dbd2b8b3118fd973e94beb50a99afd9ebc71d8 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-07-21-09-17-01.gh-issue-95085.E9x2S_.rst @@ -0,0 +1,2 @@ +Platforms ``wasm32-unknown-emscripten`` and ``wasm32-unknown-wasi`` have +been promoted to :pep:`11` tier 3 platform support. diff --git a/Misc/NEWS.d/next/Build/2022-07-23-21-39-09.gh-issue-95174.7cYMZR.rst b/Misc/NEWS.d/next/Build/2022-07-23-21-39-09.gh-issue-95174.7cYMZR.rst new file mode 100644 index 0000000000000000000000000000000000000000..72ce183ac8329da8313c0feb027ab002690749dd --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-07-23-21-39-09.gh-issue-95174.7cYMZR.rst @@ -0,0 +1 @@ +Python now skips missing :mod:`socket` functions and methods on WASI. WASI can only create sockets from existing fd / accept and has no netdb. diff --git a/Misc/NEWS.d/next/Build/2022-07-25-08-59-35.gh-issue-95174.g8woUW.rst b/Misc/NEWS.d/next/Build/2022-07-25-08-59-35.gh-issue-95174.g8woUW.rst new file mode 100644 index 0000000000000000000000000000000000000000..05f29955072c546a7c71b1598630afc7cfef46a9 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-07-25-08-59-35.gh-issue-95174.g8woUW.rst @@ -0,0 +1,2 @@ +Python now detects missing ``dup`` function in WASI and works around some +missing :mod:`errno`, :mod:`select`, and :mod:`socket` constants. diff --git a/Misc/NEWS.d/next/Build/2022-07-25-09-48-43.gh-issue-95145.ZNS3dj.rst b/Misc/NEWS.d/next/Build/2022-07-25-09-48-43.gh-issue-95145.ZNS3dj.rst new file mode 100644 index 0000000000000000000000000000000000000000..c751b5e3adc474c1c6a7619aeacf86c6138661b4 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-07-25-09-48-43.gh-issue-95145.ZNS3dj.rst @@ -0,0 +1,2 @@ +wasm32-wasi builds no longer depend on WASIX's pthread stubs. Python now has +its own stubbed pthread API. diff --git a/Misc/NEWS.d/next/Build/2022-07-26-18-13-34.gh-issue-94801.9fREfy.rst b/Misc/NEWS.d/next/Build/2022-07-26-18-13-34.gh-issue-94801.9fREfy.rst new file mode 100644 index 0000000000000000000000000000000000000000..a58be30e81b057dd22c03376db1aa5e9fdf33cbc --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-07-26-18-13-34.gh-issue-94801.9fREfy.rst @@ -0,0 +1,2 @@ +Fix a regression in ``configure`` script that caused some header checks to +ignore custom ``CPPFLAGS``. The regression was introduced in :gh:`94802`. diff --git a/Misc/NEWS.d/next/C API/2022-04-13-16-10-55.gh-issue-59121.-B7mKp.rst b/Misc/NEWS.d/next/C API/2022-04-13-16-10-55.gh-issue-59121.-B7mKp.rst new file mode 100644 index 0000000000000000000000000000000000000000..d52866ea08f71373115d48e2496fa4f62e01d352 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2022-04-13-16-10-55.gh-issue-59121.-B7mKp.rst @@ -0,0 +1 @@ +Fixed an assert that prevented ``PyRun_InteractiveOne`` from providing tracebacks when parsing from the provided FD. diff --git a/Misc/NEWS.d/next/C API/2022-07-12-17-39-32.gh-issue-94731.9CPJNU.rst b/Misc/NEWS.d/next/C API/2022-07-12-17-39-32.gh-issue-94731.9CPJNU.rst new file mode 100644 index 0000000000000000000000000000000000000000..b7816d28215e7b2bc513aaa6cc28465363e6d4ec --- /dev/null +++ b/Misc/NEWS.d/next/C API/2022-07-12-17-39-32.gh-issue-94731.9CPJNU.rst @@ -0,0 +1,3 @@ +Python again uses C-style casts for most casting operations when compiled +with C++. This may trigger compiler warnings, if they are enabled with e.g. +``-Wold-style-cast `` or ``-Wzero-as-null-pointer-constant`` options for ``g++``. diff --git a/Misc/NEWS.d/next/C API/2022-07-17-18-21-40.gh-issue-94930.gPFGDL.rst b/Misc/NEWS.d/next/C API/2022-07-17-18-21-40.gh-issue-94930.gPFGDL.rst new file mode 100644 index 0000000000000000000000000000000000000000..5b79d757b1e4aa9fee5306d5da7acbf605f1449f --- /dev/null +++ b/Misc/NEWS.d/next/C API/2022-07-17-18-21-40.gh-issue-94930.gPFGDL.rst @@ -0,0 +1,2 @@ +Fix ``SystemError`` raised when :c:func:`PyArg_ParseTupleAndKeywords` is +used with ``#`` in ``(...)`` but without ``PY_SSIZE_T_CLEAN`` defined. diff --git a/Misc/NEWS.d/next/C API/2022-07-25-15-54-27.gh-issue-92678.ziZpxz.rst b/Misc/NEWS.d/next/C API/2022-07-25-15-54-27.gh-issue-92678.ziZpxz.rst new file mode 100644 index 0000000000000000000000000000000000000000..52473c9dfab946bdbdeb89be158be295ae216a5e --- /dev/null +++ b/Misc/NEWS.d/next/C API/2022-07-25-15-54-27.gh-issue-92678.ziZpxz.rst @@ -0,0 +1,3 @@ +Adds unstable C-API functions ``_PyObject_VisitManagedDict`` and +``_PyObject_ClearManagedDict`` to allow C extensions to allow the VM to +manage their object's dictionaries. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-03-22-13-12-27.bpo-47091.tJcy-P.rst b/Misc/NEWS.d/next/Core and Builtins/2022-03-22-13-12-27.bpo-47091.tJcy-P.rst new file mode 100644 index 0000000000000000000000000000000000000000..72a39b5ebc710955a6e3b69336978f0f6524f0ee --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-03-22-13-12-27.bpo-47091.tJcy-P.rst @@ -0,0 +1 @@ +Improve performance of repetition of :class:`list` and :class:`tuple` by using ``memcpy`` to copy data and performing the reference increments in one step. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-05-11-09-16-54.gh-issue-91102.lenv9h.rst b/Misc/NEWS.d/next/Core and Builtins/2022-05-11-09-16-54.gh-issue-91102.lenv9h.rst new file mode 100644 index 0000000000000000000000000000000000000000..b2bdf9d5322f3710593f74c3f9121764bad3b886 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-05-11-09-16-54.gh-issue-91102.lenv9h.rst @@ -0,0 +1 @@ +:meth:`_warnings.warn_explicit` is ported to Argument Clinic. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-06-24-14-06-20.gh-issue-93883.8jVQQ4.rst b/Misc/NEWS.d/next/Core and Builtins/2022-06-24-14-06-20.gh-issue-93883.8jVQQ4.rst new file mode 100644 index 0000000000000000000000000000000000000000..53345577036a5ad454ff4ebff4dfe09f1765bef7 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-06-24-14-06-20.gh-issue-93883.8jVQQ4.rst @@ -0,0 +1 @@ +Revise the display strategy of traceback enhanced error locations. The indicators are only shown when the location doesn't span the whole line. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-08-16-44-11.gh-issue-94694.VkL2CM.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-08-16-44-11.gh-issue-94694.VkL2CM.rst new file mode 100644 index 0000000000000000000000000000000000000000..6434788140f420129bc1b35371cf3e36dd442e74 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-08-16-44-11.gh-issue-94694.VkL2CM.rst @@ -0,0 +1,4 @@ +Fix an issue that could cause code with multi-line method lookups to have +misleading or incorrect column offset information. In some cases (when +compiling a hand-built AST) this could have resulted in a hard crash of the +interpreter. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-14-10-07-53.gh-issue-90699.x3aG9m.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-14-10-07-53.gh-issue-90699.x3aG9m.rst new file mode 100644 index 0000000000000000000000000000000000000000..795f4df987eb909d80cc99fa91ebddbdd2560b3b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-14-10-07-53.gh-issue-90699.x3aG9m.rst @@ -0,0 +1 @@ +Fix reference counting bug in :meth:`bool.__repr__`. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-15-16-15-04.gh-issue-91153.HiBmtt.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-15-16-15-04.gh-issue-91153.HiBmtt.rst new file mode 100644 index 0000000000000000000000000000000000000000..2caa0170f75bcaf60f1eefae2c73f45d87f1f1a8 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-15-16-15-04.gh-issue-91153.HiBmtt.rst @@ -0,0 +1,2 @@ +Fix an issue where a :class:`bytearray` item assignment could crash if it's +resized by the new value's :meth:`__index__` method. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-15-22-16-08.gh-issue-94822.zRRzBN.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-15-22-16-08.gh-issue-94822.zRRzBN.rst new file mode 100644 index 0000000000000000000000000000000000000000..5b24918e497706698b16f0a2c955b7475e35f6f3 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-15-22-16-08.gh-issue-94822.zRRzBN.rst @@ -0,0 +1,2 @@ +Fix an issue where lookups of metaclass descriptors may be ignored when an +identically-named attribute also exists on the class itself. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-15-22-47-44.gh-issue-94893.YiJYcW.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-15-22-47-44.gh-issue-94893.YiJYcW.rst new file mode 100644 index 0000000000000000000000000000000000000000..6384ef92c6543a3bb1f90c578132dea2a537535e --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-15-22-47-44.gh-issue-94893.YiJYcW.rst @@ -0,0 +1,2 @@ +Fix an issue where frame object manipulations could corrupt inline bytecode +caches. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-16-08-14-17.gh-issue-94869.eRwMsX.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-16-08-14-17.gh-issue-94869.eRwMsX.rst new file mode 100644 index 0000000000000000000000000000000000000000..2ccf91b0cd99afaab4cdf5a8755ab9e98b0e347d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-16-08-14-17.gh-issue-94869.eRwMsX.rst @@ -0,0 +1,2 @@ +Fix the column offsets for some expressions in multi-line f-strings +:mod:`ast` nodes. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-17-15-54-29.gh-issue-91256.z7i7Q5.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-17-15-54-29.gh-issue-91256.z7i7Q5.rst new file mode 100644 index 0000000000000000000000000000000000000000..802a614fd48d72c2e39ffc985526148dfb55272a --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-17-15-54-29.gh-issue-91256.z7i7Q5.rst @@ -0,0 +1 @@ +Ensures the program name is known for help text during interpreter startup. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-18-04-48-34.gh-issue-94947.df9gUw.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-18-04-48-34.gh-issue-94947.df9gUw.rst new file mode 100644 index 0000000000000000000000000000000000000000..360ea67048fe224daaa04925e6972ecb79948477 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-18-04-48-34.gh-issue-94947.df9gUw.rst @@ -0,0 +1 @@ +:func:`ast.parse` will no longer parse assignment expressions when passed ``feature_version`` less than ``(3, 8)``. Patch by Shantanu Jain. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-18-05-10-29.gh-issue-94949.OsZ7_s.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-18-05-10-29.gh-issue-94949.OsZ7_s.rst new file mode 100644 index 0000000000000000000000000000000000000000..bc452d434da0f6f79676653386f0efc9d0e3dd2c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-18-05-10-29.gh-issue-94949.OsZ7_s.rst @@ -0,0 +1 @@ +:func:`ast.parse` will no longer parse parenthesized context managers when passed ``feature_version`` less than ``(3, 9)``. Patch by Shantanu Jain. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-18-14-19-21.gh-issue-94739.NQJQi7.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-18-14-19-21.gh-issue-94739.NQJQi7.rst new file mode 100644 index 0000000000000000000000000000000000000000..7476892c423b1a25ea23f054c7d24cff22839da9 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-18-14-19-21.gh-issue-94739.NQJQi7.rst @@ -0,0 +1 @@ +Allow jumping within, out of, and across exception handlers in the debugger. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-19-09-41-55.gh-issue-94938.xYBlM7.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-19-09-41-55.gh-issue-94938.xYBlM7.rst new file mode 100644 index 0000000000000000000000000000000000000000..cc4feae685f23c85bef5c2453fedc73732352c08 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-19-09-41-55.gh-issue-94938.xYBlM7.rst @@ -0,0 +1,3 @@ +Fix error detection in some builtin functions when keyword argument name is +an instance of a str subclass with overloaded ``__eq__`` and ``__hash__``. +Previously it could cause SystemError or other undesired behavior. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-19-16-30-59.gh-issue-94036._6Utkm.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-19-16-30-59.gh-issue-94036._6Utkm.rst new file mode 100644 index 0000000000000000000000000000000000000000..b0f036773626312af3c69ef566bae43af6b5046b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-19-16-30-59.gh-issue-94036._6Utkm.rst @@ -0,0 +1,2 @@ +Fix incorrect source location info for some multi-line attribute accesses +and method calls. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-20-13-46-01.gh-issue-91409.dhL8Zo.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-20-13-46-01.gh-issue-91409.dhL8Zo.rst new file mode 100644 index 0000000000000000000000000000000000000000..2bc0d8224c6a0005e2b193ff2b9a266f948b0ec3 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-20-13-46-01.gh-issue-91409.dhL8Zo.rst @@ -0,0 +1,2 @@ +Fix incorrect source location info caused by certain optimizations in the +bytecode compiler. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-21-17-54-52.gh-issue-95113.NnSLpT.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-21-17-54-52.gh-issue-95113.NnSLpT.rst new file mode 100644 index 0000000000000000000000000000000000000000..c2ff6c90ac8c1156cec89fe670e535b345fcd7c4 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-21-17-54-52.gh-issue-95113.NnSLpT.rst @@ -0,0 +1,4 @@ +Replace all ``EXTENDED_ARG_QUICK`` instructions with basic +:opcode:`EXTENDED_ARG` instructions in unquickened code. Consumers of +non-adaptive bytecode should be able to handle extended arguments the same +way they were handled in CPython 3.10 and older. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-21-19-19-20.gh-issue-95060.4xdT1f.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-21-19-19-20.gh-issue-95060.4xdT1f.rst new file mode 100644 index 0000000000000000000000000000000000000000..160999e82bf0811463f6d3e5169425a50644699d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-21-19-19-20.gh-issue-95060.4xdT1f.rst @@ -0,0 +1,2 @@ +Undocumented ``PyCode_Addr2Location`` function now properly returns when +``addrq`` argument is less than zero. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-22-12-53-34.gh-issue-94438.hNqACc.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-22-12-53-34.gh-issue-94438.hNqACc.rst new file mode 100644 index 0000000000000000000000000000000000000000..2a7249a833c2ed1b9f58faf1799745a8cd5678b9 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-22-12-53-34.gh-issue-94438.hNqACc.rst @@ -0,0 +1,4 @@ +Fix an issue that caused extended opcode arguments and some conditional pops +to be ignored when calculating valid jump targets for assignments to the +``f_lineno`` attribute of frame objects. In some cases, this could cause +inconsistent internal state, resulting in a hard crash of the interpreter. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-23-19-16-25.gh-issue-93351.0Jyvu-.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-23-19-16-25.gh-issue-93351.0Jyvu-.rst new file mode 100644 index 0000000000000000000000000000000000000000..97cf8055ac54b16e39e09307ab9f384c3e767f16 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-23-19-16-25.gh-issue-93351.0Jyvu-.rst @@ -0,0 +1,3 @@ +:class:`ast.AST` node positions are now validated when provided to +:func:`compile` and other related functions. If invalid positions are +detected, a :exc:`ValueError` will be raised. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-24-00-27-47.gh-issue-95185.ghYTZx.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-24-00-27-47.gh-issue-95185.ghYTZx.rst new file mode 100644 index 0000000000000000000000000000000000000000..de156bab2f51f11df826bc68d1af0fe3444da454 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-24-00-27-47.gh-issue-95185.ghYTZx.rst @@ -0,0 +1,3 @@ +Prevented crashes in the AST constructor when compiling some absurdly long +expressions like ``"+0"*1000000``. :exc:`RecursionError` is now raised +instead. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-26-09-31-12.gh-issue-93678.W8vvgT.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-26-09-31-12.gh-issue-93678.W8vvgT.rst new file mode 100644 index 0000000000000000000000000000000000000000..6ff816a172cc27167ba8c45009527db725929554 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-26-09-31-12.gh-issue-93678.W8vvgT.rst @@ -0,0 +1 @@ +Add cfg_builder struct and refactor the relevant code so that a cfg can be constructed without an instance of the compiler struct. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-27-14-05-07.gh-issue-95324.28Q5u7.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-27-14-05-07.gh-issue-95324.28Q5u7.rst new file mode 100644 index 0000000000000000000000000000000000000000..250385270e94871a5f72b0d4d1e31aacf599fd44 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-27-14-05-07.gh-issue-95324.28Q5u7.rst @@ -0,0 +1,2 @@ +Emit a warning in debug mode if an object does not call +:c:func:`PyObject_GC_UnTrack` before deallocation. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-27-14-21-57.gh-issue-90081.HVAS5x.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-27-14-21-57.gh-issue-90081.HVAS5x.rst new file mode 100644 index 0000000000000000000000000000000000000000..a3be34c175af6e9277145e3458d74057901601dc --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-27-14-21-57.gh-issue-90081.HVAS5x.rst @@ -0,0 +1,2 @@ +Run Python code in tracer/profiler function at full speed. Fixes slowdown in +earlier versions of 3.11. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-28-08-33-31.gh-issue-95355.yN4XVk.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-28-08-33-31.gh-issue-95355.yN4XVk.rst new file mode 100644 index 0000000000000000000000000000000000000000..6a289991e0d60fa6b9f7f95a07e77a861a02cbb0 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-28-08-33-31.gh-issue-95355.yN4XVk.rst @@ -0,0 +1 @@ +``_PyPegen_Parser_New`` now properly detects token memory allocation errors. Patch by Honglin Zhu. diff --git a/Misc/NEWS.d/next/Documentation/2022-06-19-18-18-22.gh-issue-86128.39DDTD.rst b/Misc/NEWS.d/next/Documentation/2022-06-19-18-18-22.gh-issue-86128.39DDTD.rst new file mode 100644 index 0000000000000000000000000000000000000000..bab006856deea7eaf121647187cf1918274bc9a2 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2022-06-19-18-18-22.gh-issue-86128.39DDTD.rst @@ -0,0 +1 @@ +Document a limitation in ThreadPoolExecutor where its exit handler is executed before any handlers in atexit. diff --git a/Misc/NEWS.d/next/Documentation/2022-07-29-09-04-02.gh-issue-95415.LKTyw6.rst b/Misc/NEWS.d/next/Documentation/2022-07-29-09-04-02.gh-issue-95415.LKTyw6.rst new file mode 100644 index 0000000000000000000000000000000000000000..ece36bc4d1cedb1041e0128698d04f9966c88513 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2022-07-29-09-04-02.gh-issue-95415.LKTyw6.rst @@ -0,0 +1,2 @@ +Use consistent syntax for platform availability. The directive now supports +a content body and emits a warning when it encounters an unknown platform. diff --git a/Misc/NEWS.d/next/IDLE/2022-07-28-18-56-57.gh-issue-89610.hcosiM.rst b/Misc/NEWS.d/next/IDLE/2022-07-28-18-56-57.gh-issue-89610.hcosiM.rst new file mode 100644 index 0000000000000000000000000000000000000000..0d283711e3e86701b0931ab1e2bf286d1a49c422 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2022-07-28-18-56-57.gh-issue-89610.hcosiM.rst @@ -0,0 +1,2 @@ +Add .pyi as a recognized extension for IDLE on macOS. This allows opening +stub files by double clicking on them in the Finder. diff --git a/Misc/NEWS.d/next/Library/2021-12-27-15-32-15.bpo-45924.0ZpHX2.rst b/Misc/NEWS.d/next/Library/2021-12-27-15-32-15.bpo-45924.0ZpHX2.rst new file mode 100644 index 0000000000000000000000000000000000000000..5cda22737adb7968ae2df537d54bc8e5bfd9ba36 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-27-15-32-15.bpo-45924.0ZpHX2.rst @@ -0,0 +1 @@ +Fix :mod:`asyncio` incorrect traceback when future's exception is raised multiple times. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Library/2022-03-16-14-24-14.bpo-47025.qtT3CE.rst b/Misc/NEWS.d/next/Library/2022-03-16-14-24-14.bpo-47025.qtT3CE.rst new file mode 100644 index 0000000000000000000000000000000000000000..1c7c7ace9706d76bceaca088275d86cbd7091c4e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-03-16-14-24-14.bpo-47025.qtT3CE.rst @@ -0,0 +1 @@ +Drop support for :class:`bytes` on :attr:`sys.path`. diff --git a/Misc/NEWS.d/next/Library/2022-05-10-16-30-40.gh-issue-90385.1_wBRQ.rst b/Misc/NEWS.d/next/Library/2022-05-10-16-30-40.gh-issue-90385.1_wBRQ.rst new file mode 100644 index 0000000000000000000000000000000000000000..24aa4403f8a68a6fe3ad2ce7c954edce309d8e8e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-05-10-16-30-40.gh-issue-90385.1_wBRQ.rst @@ -0,0 +1 @@ +Add :meth:`pathlib.Path.walk` as an alternative to :func:`os.walk`. diff --git a/Misc/NEWS.d/next/Library/2022-06-25-23-44-44.gh-issue-90016.EB409s.rst b/Misc/NEWS.d/next/Library/2022-06-25-23-44-44.gh-issue-90016.EB409s.rst new file mode 100644 index 0000000000000000000000000000000000000000..040ba44be2b912956e40feaf3aabf80dee25202c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-06-25-23-44-44.gh-issue-90016.EB409s.rst @@ -0,0 +1,2 @@ +Deprecate :mod:`sqlite3` :ref:`default adapters and converters +<sqlite3-default-converters>`. Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2022-07-03-16-41-03.gh-issue-94382.zuVZeM.rst b/Misc/NEWS.d/next/Library/2022-07-03-16-41-03.gh-issue-94382.zuVZeM.rst new file mode 100644 index 0000000000000000000000000000000000000000..d79300778f762c127513f084344430e89c6d8382 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-03-16-41-03.gh-issue-94382.zuVZeM.rst @@ -0,0 +1 @@ +Port static types of ``_multiprocessing`` module to heap types. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Library/2022-07-06-21-24-03.gh-issue-92546.s5Upkh.rst b/Misc/NEWS.d/next/Library/2022-07-06-21-24-03.gh-issue-92546.s5Upkh.rst new file mode 100644 index 0000000000000000000000000000000000000000..0ea676ef5b0d8d2f3d26e78fd789eb9957e541c3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-06-21-24-03.gh-issue-92546.s5Upkh.rst @@ -0,0 +1,2 @@ +An undocumented ``python -m pprint`` benchmark is moved into ``pprint`` +suite of pyperformance. Patch by Oleg Iarygin. diff --git a/Misc/NEWS.d/next/Library/2022-07-06-22-41-51.gh-issue-94309._XswsX.rst b/Misc/NEWS.d/next/Library/2022-07-06-22-41-51.gh-issue-94309._XswsX.rst new file mode 100644 index 0000000000000000000000000000000000000000..b1d45586e9c4962d6dbd79894f81411e1cae1fad --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-06-22-41-51.gh-issue-94309._XswsX.rst @@ -0,0 +1 @@ +Deprecate aliases :class:`typing.Hashable` and :class:`typing.Sized` diff --git a/Misc/NEWS.d/next/Library/2022-07-08-17-49-12.gh-issue-87822.F9dzkf.rst b/Misc/NEWS.d/next/Library/2022-07-08-17-49-12.gh-issue-87822.F9dzkf.rst new file mode 100644 index 0000000000000000000000000000000000000000..7b27f5df45ba207fd5bedc0e755efd37edd57ea7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-08-17-49-12.gh-issue-87822.F9dzkf.rst @@ -0,0 +1 @@ +When called with ``capture_locals=True``, the :mod:`traceback` module functions swallow exceptions raised from calls to ``repr()`` on local variables of frames. This is in order to prioritize the original exception over rendering errors. An indication of the failure is printed in place of the missing value. (Patch by Simon-Martin Schroeder). diff --git a/Misc/NEWS.d/next/Library/2022-07-09-15-17-02.gh-issue-81620.L0O_bV.rst b/Misc/NEWS.d/next/Library/2022-07-09-15-17-02.gh-issue-81620.L0O_bV.rst new file mode 100644 index 0000000000000000000000000000000000000000..b4ccea4924ff67bfec5fb5ee3f996f27818a1514 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-09-15-17-02.gh-issue-81620.L0O_bV.rst @@ -0,0 +1 @@ +Add random.binomialvariate(). diff --git a/Misc/NEWS.d/next/Library/2022-07-11-10-41-48.gh-issue-94736.EbsgeK.rst b/Misc/NEWS.d/next/Library/2022-07-11-10-41-48.gh-issue-94736.EbsgeK.rst new file mode 100644 index 0000000000000000000000000000000000000000..3080672ecdfbb837b3e7bb01681f3a4c39d94ee6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-11-10-41-48.gh-issue-94736.EbsgeK.rst @@ -0,0 +1 @@ +Fix crash when deallocating an instance of a subclass of ``_multiprocessing.SemLock``. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Library/2022-07-14-00-43-52.gh-issue-94821.e17ghU.rst b/Misc/NEWS.d/next/Library/2022-07-14-00-43-52.gh-issue-94821.e17ghU.rst new file mode 100644 index 0000000000000000000000000000000000000000..bf7885aef8cbf9d271b5bfcc7a7c65c4f8a1c662 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-14-00-43-52.gh-issue-94821.e17ghU.rst @@ -0,0 +1,2 @@ +Fix binding of unix socket to empty address on Linux to use an available +address from the abstract namespace, instead of "\0". diff --git a/Misc/NEWS.d/next/Library/2022-07-15-08-13-51.gh-issue-94857.9_KvZJ.rst b/Misc/NEWS.d/next/Library/2022-07-15-08-13-51.gh-issue-94857.9_KvZJ.rst new file mode 100644 index 0000000000000000000000000000000000000000..e684415595d1d247e9db28c08cfcd01fccb818f9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-15-08-13-51.gh-issue-94857.9_KvZJ.rst @@ -0,0 +1 @@ +Fix refleak in ``_io.TextIOWrapper.reconfigure``. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Library/2022-07-19-15-37-11.gh-issue-95005.iRmZ74.rst b/Misc/NEWS.d/next/Library/2022-07-19-15-37-11.gh-issue-95005.iRmZ74.rst new file mode 100644 index 0000000000000000000000000000000000000000..787f3146ab7770bd5fd7f38e437f3fadbbdd33a4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-19-15-37-11.gh-issue-95005.iRmZ74.rst @@ -0,0 +1,2 @@ +Replace :c:expr:`_PyAccu` with :c:expr:`_PyUnicodeWriter` in JSON encoder +and StringIO and remove the :c:expr:`_PyAccu` implementation. diff --git a/Misc/NEWS.d/next/Library/2022-07-20-22-49-48.gh-issue-95066.TuCu0E.rst b/Misc/NEWS.d/next/Library/2022-07-20-22-49-48.gh-issue-95066.TuCu0E.rst new file mode 100644 index 0000000000000000000000000000000000000000..05ae4a6a2761afa5dcb50809ad9e9635dcc37bb8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-20-22-49-48.gh-issue-95066.TuCu0E.rst @@ -0,0 +1 @@ +Replaced assert with exception in :func:`ast.parse`, when ``feature_version`` has an invalid major version. Patch by Shantanu Jain. diff --git a/Misc/NEWS.d/next/Library/2022-07-21-19-55-49.gh-issue-95105.BIX2Km.rst b/Misc/NEWS.d/next/Library/2022-07-21-19-55-49.gh-issue-95105.BIX2Km.rst new file mode 100644 index 0000000000000000000000000000000000000000..58af62b1edc871e8e3b38df40c4c21bfa630e344 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-21-19-55-49.gh-issue-95105.BIX2Km.rst @@ -0,0 +1 @@ +:meth:`wsgiref.types.InputStream.__iter__` should return ``Iterator[bytes]``, not ``Iterable[bytes]``. Patch by Shantanu Jain. diff --git a/Misc/NEWS.d/next/Library/2022-07-21-22-59-22.gh-issue-95109.usxA9r.rst b/Misc/NEWS.d/next/Library/2022-07-21-22-59-22.gh-issue-95109.usxA9r.rst new file mode 100644 index 0000000000000000000000000000000000000000..40196dd214a283f235f5b041d0bb8aa85baa02a9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-21-22-59-22.gh-issue-95109.usxA9r.rst @@ -0,0 +1 @@ +Ensure that timeouts scheduled with :class:`asyncio.Timeout` that have already expired are delivered promptly. diff --git a/Misc/NEWS.d/next/Library/2022-07-22-00-58-49.gh-issue-95077.4Z6CNC.rst b/Misc/NEWS.d/next/Library/2022-07-22-00-58-49.gh-issue-95077.4Z6CNC.rst new file mode 100644 index 0000000000000000000000000000000000000000..09f350067cd31bff6016e80eb54890bb290dfa85 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-22-00-58-49.gh-issue-95077.4Z6CNC.rst @@ -0,0 +1 @@ +Add deprecation warning for enum ``member.member`` access (e.g. ``Color.RED.BLUE``). diff --git a/Misc/NEWS.d/next/Library/2022-07-22-17-19-57.gh-issue-93157.RXByAk.rst b/Misc/NEWS.d/next/Library/2022-07-22-17-19-57.gh-issue-93157.RXByAk.rst new file mode 100644 index 0000000000000000000000000000000000000000..054b318ec63f0c44f8cef8691aaf0647298044dd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-22-17-19-57.gh-issue-93157.RXByAk.rst @@ -0,0 +1,2 @@ +Fix :mod:`fileinput` module didn't support ``errors`` option when +``inplace`` is true. diff --git a/Misc/NEWS.d/next/Library/2022-07-22-21-18-17.gh-issue-95132.n9anlw.rst b/Misc/NEWS.d/next/Library/2022-07-22-21-18-17.gh-issue-95132.n9anlw.rst new file mode 100644 index 0000000000000000000000000000000000000000..64666ad84fb4a6d0cc393c8372c72436d2e36ae1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-22-21-18-17.gh-issue-95132.n9anlw.rst @@ -0,0 +1,4 @@ +Fix a :mod:`sqlite3` regression where ``*args`` and ``**kwds`` were +incorrectly relayed from :py:func:`~sqlite3.connect` to the +:class:`~sqlite3.Connection` factory. The regression was introduced in 3.11a1 +with PR 24421 (:gh:`85128`). Patch by Erlend E. Aasland.` diff --git a/Misc/NEWS.d/next/Library/2022-07-23-10-42-05.gh-issue-95166.xw6p3C.rst b/Misc/NEWS.d/next/Library/2022-07-23-10-42-05.gh-issue-95166.xw6p3C.rst new file mode 100644 index 0000000000000000000000000000000000000000..34b017078436d2d31a1cd6c72317337e0a591cb0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-23-10-42-05.gh-issue-95166.xw6p3C.rst @@ -0,0 +1 @@ +Fix :meth:`concurrent.futures.Executor.map` to cancel the currently waiting on future on an error - e.g. TimeoutError or KeyboardInterrupt. diff --git a/Misc/NEWS.d/next/Library/2022-07-23-10-50-05.gh-issue-93899.VT34A5.rst b/Misc/NEWS.d/next/Library/2022-07-23-10-50-05.gh-issue-93899.VT34A5.rst new file mode 100644 index 0000000000000000000000000000000000000000..e63475f8ba96f6279f41b3b5a6194c88695fec79 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-23-10-50-05.gh-issue-93899.VT34A5.rst @@ -0,0 +1 @@ +Fix check for existence of :data:`os.EFD_CLOEXEC`, :data:`os.EFD_NONBLOCK` and :data:`os.EFD_SEMAPHORE` flags on older kernel versions where these flags are not present. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Library/2022-07-24-09-15-35.gh-issue-95194.ERVmqG.rst b/Misc/NEWS.d/next/Library/2022-07-24-09-15-35.gh-issue-95194.ERVmqG.rst new file mode 100644 index 0000000000000000000000000000000000000000..c69651923b410ea3c771e90ef4f910fee77cfe94 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-24-09-15-35.gh-issue-95194.ERVmqG.rst @@ -0,0 +1 @@ +Upgrade bundled pip to 22.2. diff --git a/Misc/NEWS.d/next/Library/2022-07-24-12-00-06.gh-issue-95199.-5A64k.rst b/Misc/NEWS.d/next/Library/2022-07-24-12-00-06.gh-issue-95199.-5A64k.rst new file mode 100644 index 0000000000000000000000000000000000000000..f3d9cf3306b8d04778efbf810005147d9125d299 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-24-12-00-06.gh-issue-95199.-5A64k.rst @@ -0,0 +1 @@ +Upgrade bundled setuptools to 63.2.0. diff --git a/Misc/NEWS.d/next/Library/2022-07-24-12-59-02.gh-issue-95087.VvqXkN.rst b/Misc/NEWS.d/next/Library/2022-07-24-12-59-02.gh-issue-95087.VvqXkN.rst new file mode 100644 index 0000000000000000000000000000000000000000..48a5c1af74907ade8c8a1b369380d11bec72037a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-24-12-59-02.gh-issue-95087.VvqXkN.rst @@ -0,0 +1 @@ +Fix IndexError in parsing invalid date in the :mod:`email` module. diff --git a/Misc/NEWS.d/next/Library/2022-07-24-18-00-42.gh-issue-95097.lu5qNf.rst b/Misc/NEWS.d/next/Library/2022-07-24-18-00-42.gh-issue-95097.lu5qNf.rst new file mode 100644 index 0000000000000000000000000000000000000000..2840f057a9c1dc63cdeefa8e87ef00b1cbee3f2d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-24-18-00-42.gh-issue-95097.lu5qNf.rst @@ -0,0 +1 @@ +Fix :func:`asyncio.run` for :class:`asyncio.Task` implementations without :meth:`~asyncio.Task.uncancel` method. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Library/2022-07-27-11-35-45.gh-issue-95045.iysT-Q.rst b/Misc/NEWS.d/next/Library/2022-07-27-11-35-45.gh-issue-95045.iysT-Q.rst new file mode 100644 index 0000000000000000000000000000000000000000..d4ab325e03658333aab2a63158a2a9a1fbf1f1f7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-27-11-35-45.gh-issue-95045.iysT-Q.rst @@ -0,0 +1 @@ +Fix GC crash when deallocating ``_lsprof.Profiler`` by untracking it before calling any callbacks. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Library/2022-07-27-19-43-07.gh-issue-95339.NuVQ68.rst b/Misc/NEWS.d/next/Library/2022-07-27-19-43-07.gh-issue-95339.NuVQ68.rst new file mode 100644 index 0000000000000000000000000000000000000000..6674a4a2695398072b1eca6a4e261db79d0fde2e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-27-19-43-07.gh-issue-95339.NuVQ68.rst @@ -0,0 +1 @@ +Update bundled pip to 22.2.1. diff --git a/Misc/NEWS.d/next/Tests/2022-07-05-17-53-13.gh-issue-91330.Qys5IL.rst b/Misc/NEWS.d/next/Tests/2022-07-05-17-53-13.gh-issue-91330.Qys5IL.rst index 315521102f4ec37b46ad6b620474d73158049385..6f44dcfd7e66a2444ef4a872e96599d5016798d6 100644 --- a/Misc/NEWS.d/next/Tests/2022-07-05-17-53-13.gh-issue-91330.Qys5IL.rst +++ b/Misc/NEWS.d/next/Tests/2022-07-05-17-53-13.gh-issue-91330.Qys5IL.rst @@ -1,7 +1,2 @@ Added more tests for :mod:`dataclasses` to cover behavior with data descriptor-based fields. - -# Write your Misc/NEWS entry below. It should be a simple ReST paragraph. # -Don't start with "- Issue #<n>: " or "- gh-issue-<n>: " or that sort of -stuff. -########################################################################### diff --git a/Misc/NEWS.d/next/Tests/2022-07-24-16-28-31.gh-issue-93963.UB9azu.rst b/Misc/NEWS.d/next/Tests/2022-07-24-16-28-31.gh-issue-93963.UB9azu.rst new file mode 100644 index 0000000000000000000000000000000000000000..89ce124c55f22610baa6fd31b1f90403b64511d1 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2022-07-24-16-28-31.gh-issue-93963.UB9azu.rst @@ -0,0 +1 @@ +Updated tests to use preferred location for ``importlib.resources`` ABCs. diff --git a/Misc/NEWS.d/next/Tests/2022-07-24-17-24-42.gh-issue-95218.zfBLtu.rst b/Misc/NEWS.d/next/Tests/2022-07-24-17-24-42.gh-issue-95218.zfBLtu.rst new file mode 100644 index 0000000000000000000000000000000000000000..7326689657a7acc01ff7910eb54f114da9660dc8 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2022-07-24-17-24-42.gh-issue-95218.zfBLtu.rst @@ -0,0 +1 @@ +Move tests for importlib.resources into test_importlib.resources. diff --git a/Misc/NEWS.d/next/Tests/2022-07-24-20-19-05.gh-issue-95212.fHiU4e.rst b/Misc/NEWS.d/next/Tests/2022-07-24-20-19-05.gh-issue-95212.fHiU4e.rst new file mode 100644 index 0000000000000000000000000000000000000000..44cea181cc1f1e19d3d7a12ee8e094cb1f4abb9c --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2022-07-24-20-19-05.gh-issue-95212.fHiU4e.rst @@ -0,0 +1,2 @@ +Make multiprocessing test case ``test_shared_memory_recreate`` +parallel-safe. diff --git a/Misc/NEWS.d/next/Tests/2022-07-26-15-22-19.gh-issue-95280.h8HvbP.rst b/Misc/NEWS.d/next/Tests/2022-07-26-15-22-19.gh-issue-95280.h8HvbP.rst new file mode 100644 index 0000000000000000000000000000000000000000..523d9d5f2f8bf3c2f24932719264b6b97789a203 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2022-07-26-15-22-19.gh-issue-95280.h8HvbP.rst @@ -0,0 +1,2 @@ +Fix problem with ``test_ssl`` ``test_get_ciphers`` on systems that require +perfect forward secrecy (PFS) ciphers. diff --git a/Misc/NEWS.d/next/Windows/2022-05-28-19-36-13.gh-issue-43414.NGMJ3g.rst b/Misc/NEWS.d/next/Windows/2022-05-28-19-36-13.gh-issue-43414.NGMJ3g.rst new file mode 100644 index 0000000000000000000000000000000000000000..553e8762d5d1e6f4bd4de6223df8c505a16f6dcc --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2022-05-28-19-36-13.gh-issue-43414.NGMJ3g.rst @@ -0,0 +1,2 @@ +:func:`os.get_terminal_size` now attempts to read the size from any provided +handle, rather than only supporting file descriptors 0, 1 and 2. diff --git a/Misc/NEWS.d/next/Windows/2022-07-12-20-45-43.gh-issue-94772.uNMmdG.rst b/Misc/NEWS.d/next/Windows/2022-07-12-20-45-43.gh-issue-94772.uNMmdG.rst new file mode 100644 index 0000000000000000000000000000000000000000..bb5ab754484eb335a99e6be3dd0f3a990f903f20 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2022-07-12-20-45-43.gh-issue-94772.uNMmdG.rst @@ -0,0 +1 @@ +Fix incorrect handling of shebang lines in py.exe launcher diff --git a/Misc/NEWS.d/next/Windows/2022-07-16-16-18-32.gh-issue-90844.vwITT3.rst b/Misc/NEWS.d/next/Windows/2022-07-16-16-18-32.gh-issue-90844.vwITT3.rst new file mode 100644 index 0000000000000000000000000000000000000000..8d9e850a5b5b7ca25d2b347b893da363c619668d --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2022-07-16-16-18-32.gh-issue-90844.vwITT3.rst @@ -0,0 +1,2 @@ +Allow virtual environments to correctly launch when they have spaces in the +path. diff --git a/Misc/NEWS.d/next/Windows/2022-07-26-20-33-12.gh-issue-95285.w6fa22.rst b/Misc/NEWS.d/next/Windows/2022-07-26-20-33-12.gh-issue-95285.w6fa22.rst new file mode 100644 index 0000000000000000000000000000000000000000..76b38e7803ccac1e125143565d0dffdaa1e7c4fe --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2022-07-26-20-33-12.gh-issue-95285.w6fa22.rst @@ -0,0 +1,2 @@ +Fix :ref:`launcher` handling of command lines where it is only passed a +short executable name. diff --git a/Misc/NEWS.d/next/Windows/2022-07-28-20-21-38.gh-issue-95359.ywMrgu.rst b/Misc/NEWS.d/next/Windows/2022-07-28-20-21-38.gh-issue-95359.ywMrgu.rst new file mode 100644 index 0000000000000000000000000000000000000000..513a2be28a9c20deaec3affcfed6cc588f3d8a34 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2022-07-28-20-21-38.gh-issue-95359.ywMrgu.rst @@ -0,0 +1,3 @@ +Fix :ref:`launcher` handling of :file:`py.ini` commands (it was incorrectly +expecting a ``py_`` prefix on keys) and crashes when reading per-user +configuration file. diff --git a/Modules/Setup b/Modules/Setup index d3647ecb995928a5e2571f3a164b3cc571bbd02e..8fe79512787cdea4753910b2d04c17d5b7316bc0 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -275,7 +275,7 @@ PYTHONPATH=$(COREPYTHONPATH) #xx xxmodule.c #xxlimited xxlimited.c #xxlimited_35 xxlimited_35.c -xxsubtype xxsubtype.c # Required for the test suite to pass! +#xxsubtype xxsubtype.c # Testing diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 581a5c7f979d11f95598bf0e99509dd577a36af6..09eca9f980db14df8251212432d22646ae32e8ca 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -165,6 +165,7 @@ ############################################################################ # Test modules +@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 diff --git a/Modules/_abc.c b/Modules/_abc.c index 641d6198d1fec43deeda869cc5a2d30ee975bb8a..b22daa81e3ae1937ecd9a6f453437e7327583a29 100644 --- a/Modules/_abc.c +++ b/Modules/_abc.c @@ -63,6 +63,7 @@ abc_data_clear(_abc_data *self) static void abc_data_dealloc(_abc_data *self) { + PyObject_GC_UnTrack(self); PyTypeObject *tp = Py_TYPE(self); (void)abc_data_clear(self); tp->tp_free(self); diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index bb7c5a7c3ec550fc077fd3f634acc560e070367e..46175ccb8eb3cb4911aa8309b540920e5783699f 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -70,6 +70,7 @@ typedef enum { PyObject *prefix##_context0; \ PyObject *prefix##_callbacks; \ PyObject *prefix##_exception; \ + PyObject *prefix##_exception_tb; \ PyObject *prefix##_result; \ PyObject *prefix##_source_tb; \ PyObject *prefix##_cancel_msg; \ @@ -495,6 +496,7 @@ future_init(FutureObj *fut, PyObject *loop) Py_CLEAR(fut->fut_callbacks); Py_CLEAR(fut->fut_result); Py_CLEAR(fut->fut_exception); + Py_CLEAR(fut->fut_exception_tb); Py_CLEAR(fut->fut_source_tb); Py_CLEAR(fut->fut_cancel_msg); Py_CLEAR(fut->fut_cancelled_exc); @@ -601,7 +603,9 @@ future_set_exception(FutureObj *fut, PyObject *exc) } assert(!fut->fut_exception); + assert(!fut->fut_exception_tb); fut->fut_exception = exc_val; + fut->fut_exception_tb = PyException_GetTraceback(exc_val); fut->fut_state = STATE_FINISHED; if (future_schedule_callbacks(fut) == -1) { @@ -656,8 +660,16 @@ future_get_result(FutureObj *fut, PyObject **result) fut->fut_log_tb = 0; if (fut->fut_exception != NULL) { + PyObject *tb = fut->fut_exception_tb; + if (tb == NULL) { + tb = Py_None; + } + if (PyException_SetTraceback(fut->fut_exception, tb) < 0) { + return -1; + } Py_INCREF(fut->fut_exception); *result = fut->fut_exception; + Py_CLEAR(fut->fut_exception_tb); return 1; } @@ -799,6 +811,7 @@ FutureObj_clear(FutureObj *fut) Py_CLEAR(fut->fut_callbacks); Py_CLEAR(fut->fut_result); Py_CLEAR(fut->fut_exception); + Py_CLEAR(fut->fut_exception_tb); Py_CLEAR(fut->fut_source_tb); Py_CLEAR(fut->fut_cancel_msg); Py_CLEAR(fut->fut_cancelled_exc); @@ -815,6 +828,7 @@ FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg) Py_VISIT(fut->fut_callbacks); Py_VISIT(fut->fut_result); Py_VISIT(fut->fut_exception); + Py_VISIT(fut->fut_exception_tb); Py_VISIT(fut->fut_source_tb); Py_VISIT(fut->fut_cancel_msg); Py_VISIT(fut->fut_cancelled_exc); diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index c7234fbb18a0fa8e60ae6a717e5e292382903795..13ed8b7eda65557fe036a8e251adab23d55976c5 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -279,6 +279,7 @@ PyCField_clear(CFieldObject *self) static void PyCField_dealloc(PyObject *self) { + PyObject_GC_UnTrack(self); PyCField_clear((CFieldObject *)self); Py_TYPE(self)->tp_free((PyObject *)self); } diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index 3fe02d35924f8009f7981b3835b8b7b87d746801..0f31c172499ac3296dfe8056d346d0beeea78488 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -1,7 +1,6 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" #include <stddef.h> // offsetof() -#include "pycore_accu.h" #include "pycore_object.h" #include "_iomodule.h" @@ -27,12 +26,12 @@ typedef struct { /* The stringio object can be in two states: accumulating or realized. In accumulating state, the internal buffer contains nothing and - the contents are given by the embedded _PyAccu structure. + the contents are given by the embedded _PyUnicodeWriter structure. In realized state, the internal buffer is meaningful and the - _PyAccu is destroyed. + _PyUnicodeWriter is destroyed. */ int state; - _PyAccu accu; + _PyUnicodeWriter writer; char ok; /* initialized? */ char closed; @@ -126,12 +125,14 @@ resize_buffer(stringio *self, size_t size) static PyObject * make_intermediate(stringio *self) { - PyObject *intermediate = _PyAccu_Finish(&self->accu); + PyObject *intermediate = _PyUnicodeWriter_Finish(&self->writer); self->state = STATE_REALIZED; if (intermediate == NULL) return NULL; - if (_PyAccu_Init(&self->accu) || - _PyAccu_Accumulate(&self->accu, intermediate)) { + + _PyUnicodeWriter_Init(&self->writer); + self->writer.overallocate = 1; + if (_PyUnicodeWriter_WriteStr(&self->writer, intermediate)) { Py_DECREF(intermediate); return NULL; } @@ -150,7 +151,7 @@ realize(stringio *self) assert(self->state == STATE_ACCUMULATING); self->state = STATE_REALIZED; - intermediate = _PyAccu_Finish(&self->accu); + intermediate = _PyUnicodeWriter_Finish(&self->writer); if (intermediate == NULL) return -1; @@ -218,7 +219,7 @@ write_str(stringio *self, PyObject *obj) if (self->state == STATE_ACCUMULATING) { if (self->string_size == self->pos) { - if (_PyAccu_Accumulate(&self->accu, decoded)) + if (_PyUnicodeWriter_WriteStr(&self->writer, decoded)) goto fail; goto success; } @@ -572,7 +573,7 @@ _io_StringIO_close_impl(stringio *self) /* Free up some memory */ if (resize_buffer(self, 0) < 0) return NULL; - _PyAccu_Destroy(&self->accu); + _PyUnicodeWriter_Dealloc(&self->writer); Py_CLEAR(self->readnl); Py_CLEAR(self->writenl); Py_CLEAR(self->decoder); @@ -602,7 +603,7 @@ stringio_dealloc(stringio *self) PyMem_Free(self->buf); self->buf = NULL; } - _PyAccu_Destroy(&self->accu); + _PyUnicodeWriter_Dealloc(&self->writer); Py_CLEAR(self->readnl); Py_CLEAR(self->writenl); Py_CLEAR(self->decoder); @@ -687,7 +688,7 @@ _io_StringIO___init___impl(stringio *self, PyObject *value, self->ok = 0; - _PyAccu_Destroy(&self->accu); + _PyUnicodeWriter_Dealloc(&self->writer); Py_CLEAR(self->readnl); Py_CLEAR(self->writenl); Py_CLEAR(self->decoder); @@ -742,8 +743,8 @@ _io_StringIO___init___impl(stringio *self, PyObject *value, /* Empty stringio object, we can start by accumulating */ if (resize_buffer(self, 0) < 0) return -1; - if (_PyAccu_Init(&self->accu)) - return -1; + _PyUnicodeWriter_Init(&self->writer); + self->writer.overallocate = 1; self->state = STATE_ACCUMULATING; } self->pos = 0; diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 660396b8b03ead065f9336a69bdbfecf4cad7611..3369694653fd9693818a3267bdda2129fe5b3d49 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -1247,6 +1247,7 @@ textiowrapper_change_encoding(textio *self, PyObject *encoding, if (errors == Py_None) { errors = self->errors; } + Py_INCREF(encoding); } else { if (_PyUnicode_EqualToASCIIString(encoding, "locale")) { @@ -1254,6 +1255,8 @@ textiowrapper_change_encoding(textio *self, PyObject *encoding, if (encoding == NULL) { return -1; } + } else { + Py_INCREF(encoding); } if (errors == Py_None) { errors = &_Py_ID(strict); @@ -1262,6 +1265,7 @@ textiowrapper_change_encoding(textio *self, PyObject *encoding, const char *c_errors = PyUnicode_AsUTF8(errors); if (c_errors == NULL) { + Py_DECREF(encoding); return -1; } @@ -1269,16 +1273,17 @@ textiowrapper_change_encoding(textio *self, PyObject *encoding, PyObject *codec_info = _PyCodec_LookupTextEncoding( PyUnicode_AsUTF8(encoding), "codecs.open()"); if (codec_info == NULL) { + Py_DECREF(encoding); return -1; } if (_textiowrapper_set_decoder(self, codec_info, c_errors) != 0 || _textiowrapper_set_encoder(self, codec_info, c_errors) != 0) { Py_DECREF(codec_info); + Py_DECREF(encoding); return -1; } Py_DECREF(codec_info); - Py_INCREF(encoding); Py_INCREF(errors); Py_SETREF(self->encoding, encoding); Py_SETREF(self->errors, errors); @@ -2239,7 +2244,7 @@ _textiowrapper_readline(textio *self, Py_ssize_t limit) Py_CLEAR(chunks); } if (line == NULL) { - line = &_Py_STR(empty); + line = Py_NewRef(&_Py_STR(empty)); } return line; diff --git a/Modules/_json.c b/Modules/_json.c index 89f55047abe42100c397021a6ee26a3624e1018c..7ea84efdb911bd5164622795d2b0c3b33eaabf83 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -12,7 +12,6 @@ #include "Python.h" #include "pycore_ceval.h" // _Py_EnterRecursiveCall() #include "structmember.h" // PyMemberDef -#include "pycore_accu.h" typedef struct _PyScannerObject { @@ -85,11 +84,11 @@ encoder_dealloc(PyObject *self); static int encoder_clear(PyEncoderObject *self); static int -encoder_listencode_list(PyEncoderObject *s, _PyAccu *acc, PyObject *seq, Py_ssize_t indent_level); +encoder_listencode_list(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *seq, Py_ssize_t indent_level); static int -encoder_listencode_obj(PyEncoderObject *s, _PyAccu *acc, PyObject *obj, Py_ssize_t indent_level); +encoder_listencode_obj(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *obj, Py_ssize_t indent_level); static int -encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc, PyObject *dct, Py_ssize_t indent_level); +encoder_listencode_dict(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *dct, Py_ssize_t indent_level); static PyObject * _encoded_const(PyObject *obj); static void @@ -1280,19 +1279,29 @@ encoder_call(PyEncoderObject *self, PyObject *args, PyObject *kwds) { /* Python callable interface to encode_listencode_obj */ static char *kwlist[] = {"obj", "_current_indent_level", NULL}; - PyObject *obj; + PyObject *obj, *result; Py_ssize_t indent_level; - _PyAccu acc; + _PyUnicodeWriter writer; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "On:_iterencode", kwlist, &obj, &indent_level)) return NULL; - if (_PyAccu_Init(&acc)) + + _PyUnicodeWriter_Init(&writer); + writer.overallocate = 1; + + if (encoder_listencode_obj(self, &writer, obj, indent_level)) { + _PyUnicodeWriter_Dealloc(&writer); return NULL; - if (encoder_listencode_obj(self, &acc, obj, indent_level)) { - _PyAccu_Destroy(&acc); + } + + result = PyTuple_New(1); + if (result == NULL || + PyTuple_SetItem(result, 0, _PyUnicodeWriter_Finish(&writer)) < 0) { + Py_XDECREF(result); return NULL; } - return _PyAccu_FinishAsList(&acc); + return result; } static PyObject * @@ -1376,58 +1385,60 @@ encoder_encode_string(PyEncoderObject *s, PyObject *obj) } static int -_steal_accumulate(_PyAccu *acc, PyObject *stolen) +_steal_accumulate(_PyUnicodeWriter *writer, PyObject *stolen) { /* Append stolen and then decrement its reference count */ - int rval = _PyAccu_Accumulate(acc, stolen); + int rval = _PyUnicodeWriter_WriteStr(writer, stolen); Py_DECREF(stolen); return rval; } static int -encoder_listencode_obj(PyEncoderObject *s, _PyAccu *acc, +encoder_listencode_obj(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *obj, Py_ssize_t indent_level) { /* Encode Python object obj to a JSON term */ PyObject *newobj; int rv; - if (obj == Py_None || obj == Py_True || obj == Py_False) { - PyObject *cstr = _encoded_const(obj); - if (cstr == NULL) - return -1; - return _steal_accumulate(acc, cstr); + if (obj == Py_None) { + return _PyUnicodeWriter_WriteASCIIString(writer, "null", 4); + } + else if (obj == Py_True) { + return _PyUnicodeWriter_WriteASCIIString(writer, "true", 4); + } + else if (obj == Py_False) { + return _PyUnicodeWriter_WriteASCIIString(writer, "false", 5); } - else if (PyUnicode_Check(obj)) - { + else if (PyUnicode_Check(obj)) { PyObject *encoded = encoder_encode_string(s, obj); if (encoded == NULL) return -1; - return _steal_accumulate(acc, encoded); + return _steal_accumulate(writer, encoded); } else if (PyLong_Check(obj)) { PyObject *encoded = PyLong_Type.tp_repr(obj); if (encoded == NULL) return -1; - return _steal_accumulate(acc, encoded); + return _steal_accumulate(writer, encoded); } else if (PyFloat_Check(obj)) { PyObject *encoded = encoder_encode_float(s, obj); if (encoded == NULL) return -1; - return _steal_accumulate(acc, encoded); + return _steal_accumulate(writer, encoded); } else if (PyList_Check(obj) || PyTuple_Check(obj)) { if (_Py_EnterRecursiveCall(" while encoding a JSON object")) return -1; - rv = encoder_listencode_list(s, acc, obj, indent_level); + rv = encoder_listencode_list(s, writer, obj, indent_level); _Py_LeaveRecursiveCall(); return rv; } else if (PyDict_Check(obj)) { if (_Py_EnterRecursiveCall(" while encoding a JSON object")) return -1; - rv = encoder_listencode_dict(s, acc, obj, indent_level); + rv = encoder_listencode_dict(s, writer, obj, indent_level); _Py_LeaveRecursiveCall(); return rv; } @@ -1461,7 +1472,7 @@ encoder_listencode_obj(PyEncoderObject *s, _PyAccu *acc, Py_XDECREF(ident); return -1; } - rv = encoder_listencode_obj(s, acc, newobj, indent_level); + rv = encoder_listencode_obj(s, writer, newobj, indent_level); _Py_LeaveRecursiveCall(); Py_DECREF(newobj); @@ -1481,16 +1492,10 @@ encoder_listencode_obj(PyEncoderObject *s, _PyAccu *acc, } static int -encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc, +encoder_listencode_dict(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *dct, Py_ssize_t indent_level) { /* Encode Python dict dct a JSON term */ - _Py_static_string(PyId_open_dict, "{"); - _Py_static_string(PyId_close_dict, "}"); - _Py_static_string(PyId_empty_dict, "{}"); - PyObject *open_dict = _PyUnicode_FromId(&PyId_open_dict); // borrowed ref - PyObject *close_dict = _PyUnicode_FromId(&PyId_close_dict); // borrowed ref - PyObject *empty_dict = _PyUnicode_FromId(&PyId_empty_dict); // borrowed ref PyObject *kstr = NULL; PyObject *ident = NULL; PyObject *it = NULL; @@ -1498,11 +1503,8 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc, PyObject *item = NULL; Py_ssize_t idx; - if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) { - return -1; - } if (PyDict_GET_SIZE(dct) == 0) /* Fast path */ - return _PyAccu_Accumulate(acc, empty_dict); + return _PyUnicodeWriter_WriteASCIIString(writer, "{}", 2); if (s->markers != Py_None) { int has_key; @@ -1520,7 +1522,7 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc, } } - if (_PyAccu_Accumulate(acc, open_dict)) + if (_PyUnicodeWriter_WriteChar(writer, '{')) goto bail; if (s->indent != Py_None) { @@ -1586,7 +1588,7 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc, } if (idx) { - if (_PyAccu_Accumulate(acc, s->item_separator)) + if (_PyUnicodeWriter_WriteStr(writer, s->item_separator)) goto bail; } @@ -1594,16 +1596,16 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc, Py_CLEAR(kstr); if (encoded == NULL) goto bail; - if (_PyAccu_Accumulate(acc, encoded)) { + if (_PyUnicodeWriter_WriteStr(writer, encoded)) { Py_DECREF(encoded); goto bail; } Py_DECREF(encoded); - if (_PyAccu_Accumulate(acc, s->key_separator)) + if (_PyUnicodeWriter_WriteStr(writer, s->key_separator)) goto bail; value = PyTuple_GET_ITEM(item, 1); - if (encoder_listencode_obj(s, acc, value, indent_level)) + if (encoder_listencode_obj(s, writer, value, indent_level)) goto bail; idx += 1; Py_DECREF(item); @@ -1623,7 +1625,7 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc, yield '\n' + (' ' * (_indent * _current_indent_level)) }*/ - if (_PyAccu_Accumulate(acc, close_dict)) + if (_PyUnicodeWriter_WriteChar(writer, '}')) goto bail; return 0; @@ -1637,30 +1639,20 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc, static int -encoder_listencode_list(PyEncoderObject *s, _PyAccu *acc, +encoder_listencode_list(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *seq, Py_ssize_t indent_level) { - /* Encode Python list seq to a JSON term */ - _Py_static_string(PyId_open_array, "["); - _Py_static_string(PyId_close_array, "]"); - _Py_static_string(PyId_empty_array, "[]"); - PyObject *open_array = _PyUnicode_FromId(&PyId_open_array); // borrowed ref - PyObject *close_array = _PyUnicode_FromId(&PyId_close_array); // borrowed ref - PyObject *empty_array = _PyUnicode_FromId(&PyId_empty_array); // borrowed ref PyObject *ident = NULL; PyObject *s_fast = NULL; Py_ssize_t i; - if (open_array == NULL || close_array == NULL || empty_array == NULL) { - return -1; - } ident = NULL; s_fast = PySequence_Fast(seq, "_iterencode_list needs a sequence"); if (s_fast == NULL) return -1; if (PySequence_Fast_GET_SIZE(s_fast) == 0) { Py_DECREF(s_fast); - return _PyAccu_Accumulate(acc, empty_array); + return _PyUnicodeWriter_WriteASCIIString(writer, "[]", 2); } if (s->markers != Py_None) { @@ -1679,7 +1671,7 @@ encoder_listencode_list(PyEncoderObject *s, _PyAccu *acc, } } - if (_PyAccu_Accumulate(acc, open_array)) + if (_PyUnicodeWriter_WriteChar(writer, '[')) goto bail; if (s->indent != Py_None) { /* TODO: DOES NOT RUN */ @@ -1693,10 +1685,10 @@ encoder_listencode_list(PyEncoderObject *s, _PyAccu *acc, for (i = 0; i < PySequence_Fast_GET_SIZE(s_fast); i++) { PyObject *obj = PySequence_Fast_GET_ITEM(s_fast, i); if (i) { - if (_PyAccu_Accumulate(acc, s->item_separator)) + if (_PyUnicodeWriter_WriteStr(writer, s->item_separator)) goto bail; } - if (encoder_listencode_obj(s, acc, obj, indent_level)) + if (encoder_listencode_obj(s, writer, obj, indent_level)) goto bail; } if (ident != NULL) { @@ -1711,7 +1703,7 @@ encoder_listencode_list(PyEncoderObject *s, _PyAccu *acc, yield '\n' + (' ' * (_indent * _current_indent_level)) }*/ - if (_PyAccu_Accumulate(acc, close_array)) + if (_PyUnicodeWriter_WriteChar(writer, ']')) goto bail; Py_DECREF(s_fast); return 0; diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index 0e8432fda01ecf4667c74dc6416c77a5fb34a24b..a0e262bdac26c63dcd890560a8aa40a89b87f75c 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -747,6 +747,7 @@ profiler_traverse(ProfilerObject *op, visitproc visit, void *arg) static void profiler_dealloc(ProfilerObject *op) { + PyObject_GC_UnTrack(op); if (op->flags & POF_ENABLED) { PyThreadState *tstate = _PyThreadState_GET(); if (_PyEval_SetProfile(tstate, NULL, NULL) < 0) { diff --git a/Modules/_multiprocessing/multiprocessing.c b/Modules/_multiprocessing/multiprocessing.c index ed89a1e29a433fd8644ca6e221455eaf798dd399..2463e1e1a8bf7efd371ab19d40f1c6ac40e9ef08 100644 --- a/Modules/_multiprocessing/multiprocessing.c +++ b/Modules/_multiprocessing/multiprocessing.c @@ -196,33 +196,39 @@ multiprocessing_exec(PyObject *module) { #ifdef HAVE_MP_SEMAPHORE - /* Add _PyMp_SemLock type to module */ - if (PyModule_AddType(module, &_PyMp_SemLockType) < 0) { + PyTypeObject *semlock_type = (PyTypeObject *)PyType_FromModuleAndSpec( + module, &_PyMp_SemLockType_spec, NULL); + + if (semlock_type == NULL) { + return -1; + } + int rc = PyModule_AddType(module, semlock_type); + Py_DECREF(semlock_type); + if (rc < 0) { return -1; } - { - PyObject *py_sem_value_max; - /* Some systems define SEM_VALUE_MAX as an unsigned value that - * causes it to be negative when used as an int (NetBSD). - * - * Issue #28152: Use (0) instead of 0 to fix a warning on dead code - * when using clang -Wunreachable-code. */ - if ((int)(SEM_VALUE_MAX) < (0)) - py_sem_value_max = PyLong_FromLong(INT_MAX); - else - py_sem_value_max = PyLong_FromLong(SEM_VALUE_MAX); - - if (py_sem_value_max == NULL) { - return -1; - } - if (PyDict_SetItemString(_PyMp_SemLockType.tp_dict, "SEM_VALUE_MAX", - py_sem_value_max) < 0) { - Py_DECREF(py_sem_value_max); - return -1; - } + PyObject *py_sem_value_max; + /* Some systems define SEM_VALUE_MAX as an unsigned value that + * causes it to be negative when used as an int (NetBSD). + * + * Issue #28152: Use (0) instead of 0 to fix a warning on dead code + * when using clang -Wunreachable-code. */ + if ((int)(SEM_VALUE_MAX) < (0)) { + py_sem_value_max = PyLong_FromLong(INT_MAX); + } + else { + py_sem_value_max = PyLong_FromLong(SEM_VALUE_MAX); + } + if (py_sem_value_max == NULL) { + return -1; + } + if (PyDict_SetItemString(semlock_type->tp_dict, "SEM_VALUE_MAX", + py_sem_value_max) < 0) { Py_DECREF(py_sem_value_max); + return -1; } + Py_DECREF(py_sem_value_max); #endif @@ -276,6 +282,7 @@ static PyModuleDef_Slot multiprocessing_slots[] = { static struct PyModuleDef multiprocessing_module = { PyModuleDef_HEAD_INIT, .m_name = "_multiprocessing", + .m_size = 0, .m_methods = module_methods, .m_slots = multiprocessing_slots, }; diff --git a/Modules/_multiprocessing/multiprocessing.h b/Modules/_multiprocessing/multiprocessing.h index 3a8314b1db8331d0adbfbb5d163af495dec307a0..b595e5a8dd18de4522d036d6868d999194e02e37 100644 --- a/Modules/_multiprocessing/multiprocessing.h +++ b/Modules/_multiprocessing/multiprocessing.h @@ -89,7 +89,7 @@ PyObject *_PyMp_SetError(PyObject *Type, int num); * Externs - not all will really exist on all platforms */ -extern PyTypeObject _PyMp_SemLockType; +extern PyType_Spec _PyMp_SemLockType_spec; extern PyObject *_PyMp_sem_unlink(const char *name); #endif /* MULTIPROCESSING_H */ diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c index 8607476aff10ff72244e84986b2fde3afcf7aae7..58fb0eb96aeeed7c0f6851b850e3064a83af9e07 100644 --- a/Modules/_multiprocessing/semaphore.c +++ b/Modules/_multiprocessing/semaphore.c @@ -454,9 +454,7 @@ static PyObject * newsemlockobject(PyTypeObject *type, SEM_HANDLE handle, int kind, int maxvalue, char *name) { - SemLockObject *self; - - self = PyObject_New(SemLockObject, type); + SemLockObject *self = (SemLockObject *)type->tp_alloc(type, 0); if (!self) return NULL; self->handle = handle; @@ -570,10 +568,13 @@ _multiprocessing_SemLock__rebuild_impl(PyTypeObject *type, SEM_HANDLE handle, static void semlock_dealloc(SemLockObject* self) { + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); if (self->handle != SEM_FAILED) SEM_CLOSE(self->handle); PyMem_Free(self->name); - PyObject_Free(self); + tp->tp_free(self); + Py_DECREF(tp); } /*[clinic input] @@ -703,6 +704,13 @@ _multiprocessing_SemLock___exit___impl(SemLockObject *self, return _multiprocessing_SemLock_release_impl(self); } +static int +semlock_traverse(SemLockObject *s, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(s)); + return 0; +} + /* * Semaphore methods */ @@ -741,45 +749,26 @@ static PyMemberDef semlock_members[] = { * Semaphore type */ -PyTypeObject _PyMp_SemLockType = { - PyVarObject_HEAD_INIT(NULL, 0) - /* tp_name */ "_multiprocessing.SemLock", - /* tp_basicsize */ sizeof(SemLockObject), - /* tp_itemsize */ 0, - /* tp_dealloc */ (destructor)semlock_dealloc, - /* tp_vectorcall_offset */ 0, - /* tp_getattr */ 0, - /* tp_setattr */ 0, - /* tp_as_async */ 0, - /* tp_repr */ 0, - /* tp_as_number */ 0, - /* tp_as_sequence */ 0, - /* tp_as_mapping */ 0, - /* tp_hash */ 0, - /* tp_call */ 0, - /* tp_str */ 0, - /* tp_getattro */ 0, - /* tp_setattro */ 0, - /* tp_as_buffer */ 0, - /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - /* tp_doc */ "Semaphore/Mutex type", - /* tp_traverse */ 0, - /* tp_clear */ 0, - /* tp_richcompare */ 0, - /* tp_weaklistoffset */ 0, - /* tp_iter */ 0, - /* tp_iternext */ 0, - /* tp_methods */ semlock_methods, - /* tp_members */ semlock_members, - /* tp_getset */ 0, - /* tp_base */ 0, - /* tp_dict */ 0, - /* tp_descr_get */ 0, - /* tp_descr_set */ 0, - /* tp_dictoffset */ 0, - /* tp_init */ 0, - /* tp_alloc */ 0, - /* tp_new */ _multiprocessing_SemLock, +static PyType_Slot _PyMp_SemLockType_slots[] = { + {Py_tp_dealloc, semlock_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_setattro, PyObject_GenericSetAttr}, + {Py_tp_methods, semlock_methods}, + {Py_tp_members, semlock_members}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, _multiprocessing_SemLock}, + {Py_tp_traverse, semlock_traverse}, + {Py_tp_free, PyObject_GC_Del}, + {Py_tp_doc, (void *)PyDoc_STR("Semaphore/Mutex type")}, + {0, 0}, +}; + +PyType_Spec _PyMp_SemLockType_spec = { + .name = "_multiprocessing.SemLock", + .basicsize = sizeof(SemLockObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), + .slots = _PyMp_SemLockType_slots, }; /* diff --git a/Modules/_sqlite/clinic/module.c.h b/Modules/_sqlite/clinic/module.c.h index ef0dd4d1c103ea495cae8daef861353e75f948bf..3e932a6117eb29a2c0b7ae14df3c4c947e995cdf 100644 --- a/Modules/_sqlite/clinic/module.c.h +++ b/Modules/_sqlite/clinic/module.c.h @@ -2,116 +2,6 @@ preserve [clinic start generated code]*/ -PyDoc_STRVAR(pysqlite_connect__doc__, -"connect($module, /, database, timeout=5.0, detect_types=0,\n" -" isolation_level=<unrepresentable>, check_same_thread=True,\n" -" factory=ConnectionType, cached_statements=128, uri=False)\n" -"--\n" -"\n" -"Opens a connection to the SQLite database file database.\n" -"\n" -"You can use \":memory:\" to open a database connection to a database that resides\n" -"in RAM instead of on disk."); - -#define PYSQLITE_CONNECT_METHODDEF \ - {"connect", _PyCFunction_CAST(pysqlite_connect), METH_FASTCALL|METH_KEYWORDS, pysqlite_connect__doc__}, - -static PyObject * -pysqlite_connect_impl(PyObject *module, PyObject *database, double timeout, - int detect_types, PyObject *isolation_level, - int check_same_thread, PyObject *factory, - int cached_statements, int uri); - -static PyObject * -pysqlite_connect(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - static const char * const _keywords[] = {"database", "timeout", "detect_types", "isolation_level", "check_same_thread", "factory", "cached_statements", "uri", NULL}; - static _PyArg_Parser _parser = {NULL, _keywords, "connect", 0}; - PyObject *argsbuf[8]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - PyObject *database; - double timeout = 5.0; - int detect_types = 0; - PyObject *isolation_level = NULL; - int check_same_thread = 1; - PyObject *factory = (PyObject*)clinic_state()->ConnectionType; - int cached_statements = 128; - int uri = 0; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 8, 0, argsbuf); - if (!args) { - goto exit; - } - database = args[0]; - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - if (PyFloat_CheckExact(args[1])) { - timeout = PyFloat_AS_DOUBLE(args[1]); - } - else - { - timeout = PyFloat_AsDouble(args[1]); - if (timeout == -1.0 && PyErr_Occurred()) { - goto exit; - } - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (args[2]) { - detect_types = _PyLong_AsInt(args[2]); - if (detect_types == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (args[3]) { - isolation_level = args[3]; - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (args[4]) { - check_same_thread = _PyLong_AsInt(args[4]); - if (check_same_thread == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (args[5]) { - factory = args[5]; - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (args[6]) { - cached_statements = _PyLong_AsInt(args[6]); - if (cached_statements == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - uri = PyObject_IsTrue(args[7]); - if (uri < 0) { - goto exit; - } -skip_optional_pos: - return_value = pysqlite_connect_impl(module, database, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri); - -exit: - return return_value; -} - PyDoc_STRVAR(pysqlite_complete_statement__doc__, "complete_statement($module, /, statement)\n" "--\n" @@ -292,4 +182,4 @@ skip_optional: exit: return return_value; } -/*[clinic end generated code: output=9ac18606b0eaec03 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d7f142e9a7a80468 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index b6b7417fc0a6c1405ac3cfad300516bf324b8d83..ceb77bbf8420ffad83cc809b624878c8d4b36fb5 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -140,6 +140,7 @@ class IsolationLevel_converter(CConverter): [python start generated code]*/ /*[python end generated code: output=da39a3ee5e6b4b0d input=cbcfe85b253061c2]*/ +// NB: This needs to be in sync with the sqlite3.connect docstring /*[clinic input] _sqlite3.Connection.__init__ as pysqlite_connection_init diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index eca25b94a4817d404f9446235f830b7fcc2c741e..707aae160ab4f3e38b06659dbb5f227f0d07c367 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -42,47 +42,44 @@ module _sqlite3 [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=81e330492d57488e]*/ -// NOTE: This must equal sqlite3.Connection.__init__ argument spec! -/*[clinic input] -_sqlite3.connect as pysqlite_connect - - database: object - timeout: double = 5.0 - detect_types: int = 0 - isolation_level: object = NULL - check_same_thread: bool(accept={int}) = True - factory: object(c_default='(PyObject*)clinic_state()->ConnectionType') = ConnectionType - cached_statements: int = 128 - uri: bool = False - -Opens a connection to the SQLite database file database. - -You can use ":memory:" to open a database connection to a database that resides -in RAM instead of on disk. -[clinic start generated code]*/ +// NB: This needs to be in sync with the Connection.__init__ docstring. +PyDoc_STRVAR(module_connect_doc, +"connect($module, /, database, timeout=5.0, detect_types=0,\n" +" isolation_level='', check_same_thread=True,\n" +" factory=ConnectionType, cached_statements=128, uri=False)\n" +"--\n" +"\n" +"Opens a connection to the SQLite database file database.\n" +"\n" +"You can use \":memory:\" to open a database connection to a database that resides\n" +"in RAM instead of on disk."); + +#define PYSQLITE_CONNECT_METHODDEF \ + {"connect", _PyCFunction_CAST(module_connect), METH_FASTCALL|METH_KEYWORDS, module_connect_doc}, static PyObject * -pysqlite_connect_impl(PyObject *module, PyObject *database, double timeout, - int detect_types, PyObject *isolation_level, - int check_same_thread, PyObject *factory, - int cached_statements, int uri) -/*[clinic end generated code: output=450ac9078b4868bb input=e16914663ddf93ce]*/ +module_connect(PyObject *module, PyObject *const *args, Py_ssize_t nargsf, + PyObject *kwnames) { - if (isolation_level == NULL) { - isolation_level = PyUnicode_FromString(""); - if (isolation_level == NULL) { - return NULL; - } + pysqlite_state *state = pysqlite_get_state(module); + PyObject *factory = (PyObject *)state->ConnectionType; + + static const int FACTORY_POS = 5; + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + if (nargs > FACTORY_POS) { + factory = args[FACTORY_POS]; } - else { - Py_INCREF(isolation_level); + else if (kwnames != NULL) { + for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(kwnames); i++) { + PyObject *item = PyTuple_GET_ITEM(kwnames, i); // borrowed ref. + if (PyUnicode_CompareWithASCIIString(item, "factory") == 0) { + factory = args[nargs + i]; + break; + } + } } - PyObject *res = PyObject_CallFunction(factory, "OdiOiOii", database, - timeout, detect_types, - isolation_level, check_same_thread, - factory, cached_statements, uri); - Py_DECREF(isolation_level); - return res; + + return PyObject_Vectorcall(factory, args, nargsf, kwnames); } /*[clinic input] diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 78c02c1cd82fb532eead181603c878a005e3e7c9..bf8bd9dea89b6b9f8f58f5269dcbdea051b3a625 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -3515,7 +3515,7 @@ set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what) static PyObject * get_minimum_version(PySSLContext *self, void *c) { - int v = SSL_CTX_ctrl(self->ctx, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL); + int v = SSL_CTX_get_min_proto_version(self->ctx); if (v == 0) { v = PY_PROTO_MINIMUM_SUPPORTED; } @@ -3531,7 +3531,7 @@ set_minimum_version(PySSLContext *self, PyObject *arg, void *c) static PyObject * get_maximum_version(PySSLContext *self, void *c) { - int v = SSL_CTX_ctrl(self->ctx, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL); + int v = SSL_CTX_get_max_proto_version(self->ctx); if (v == 0) { v = PY_PROTO_MAXIMUM_SUPPORTED; } diff --git a/Modules/_statisticsmodule.c b/Modules/_statisticsmodule.c index 78c0676a01f027b95be93463bb71938f84b4bc85..b9d1e4f1616036095873f98cffef2de10e33a577 100644 --- a/Modules/_statisticsmodule.c +++ b/Modules/_statisticsmodule.c @@ -31,7 +31,7 @@ _statistics__normal_dist_inv_cdf_impl(PyObject *module, double p, double mu, /*[clinic end generated code: output=02fd19ddaab36602 input=24715a74be15296a]*/ { double q, num, den, r, x; - if (p <= 0.0 || p >= 1.0 || sigma <= 0.0) { + if (p <= 0.0 || p >= 1.0) { goto error; } diff --git a/Modules/_testcapi/parts.h b/Modules/_testcapi/parts.h index 1111021e1852b3ade5d4cb3909bda24727bd7f9f..54cddf4b0929f215a7a2835ac14de7efd484a259 100644 --- a/Modules/_testcapi/parts.h +++ b/Modules/_testcapi/parts.h @@ -1,3 +1,3 @@ #include "Python.h" -PyAPI_FUNC(int) _PyTestCapi_Init_Vectorcall(PyObject *module); +int _PyTestCapi_Init_Vectorcall(PyObject *module); diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 436c701a7a3faf23d94217a032b249a64ee8badb..b9f75d154ee5c05e4a06e356eedf7d31b815010c 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -5484,6 +5484,21 @@ sequence_getitem(PyObject *self, PyObject *args) } +static PyObject * +sequence_setitem(PyObject *self, PyObject *args) +{ + Py_ssize_t i; + PyObject *seq, *val; + if (!PyArg_ParseTuple(args, "OnO", &seq, &i, &val)) { + return NULL; + } + if (PySequence_SetItem(seq, i, val)) { + return NULL; + } + Py_RETURN_NONE; +} + + /* Functions for testing C calling conventions (METH_*) are named meth_*, * e.g. "meth_varargs" for METH_VARARGS. * @@ -5994,6 +6009,13 @@ settrace_to_record(PyObject *self, PyObject *list) Py_RETURN_NONE; } +static PyObject * +clear_managed_dict(PyObject *self, PyObject *obj) +{ + _PyObject_ClearManagedDict(obj); + Py_RETURN_NONE; +} + static PyObject * test_macros(PyObject *self, PyObject *Py_UNUSED(args)) @@ -6035,6 +6057,7 @@ test_macros(PyObject *self, PyObject *Py_UNUSED(args)) static PyObject *negative_dictoffset(PyObject *, PyObject *); static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *); static PyObject *getargs_s_hash_int(PyObject *, PyObject *, PyObject*); +static PyObject *getargs_s_hash_int2(PyObject *, PyObject *, PyObject*); static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, @@ -6157,6 +6180,8 @@ static PyMethodDef TestMethods[] = { {"getargs_s_hash", getargs_s_hash, METH_VARARGS}, {"getargs_s_hash_int", _PyCFunction_CAST(getargs_s_hash_int), METH_VARARGS|METH_KEYWORDS}, + {"getargs_s_hash_int2", _PyCFunction_CAST(getargs_s_hash_int2), + METH_VARARGS|METH_KEYWORDS}, {"getargs_z", getargs_z, METH_VARARGS}, {"getargs_z_star", getargs_z_star, METH_VARARGS}, {"getargs_z_hash", getargs_z_hash, METH_VARARGS}, @@ -6300,6 +6325,7 @@ static PyMethodDef TestMethods[] = { #endif {"write_unraisable_exc", test_write_unraisable_exc, METH_VARARGS}, {"sequence_getitem", sequence_getitem, METH_VARARGS}, + {"sequence_setitem", sequence_setitem, METH_VARARGS}, {"meth_varargs", meth_varargs, METH_VARARGS}, {"meth_varargs_keywords", _PyCFunction_CAST(meth_varargs_keywords), METH_VARARGS|METH_KEYWORDS}, {"meth_o", meth_o, METH_O}, @@ -6328,6 +6354,7 @@ static PyMethodDef TestMethods[] = { {"test_code_api", test_code_api, METH_NOARGS, NULL}, {"settrace_to_record", settrace_to_record, METH_O, NULL}, {"test_macros", test_macros, METH_NOARGS, NULL}, + {"clear_managed_dict", clear_managed_dict, METH_O, NULL}, {NULL, NULL} /* sentinel */ }; @@ -7794,11 +7821,27 @@ PyAPI_FUNC(int) PyArg_ParseTupleAndKeywords(PyObject *, PyObject *, static PyObject * getargs_s_hash_int(PyObject *self, PyObject *args, PyObject *kwargs) { - static char *keywords[] = {"", "x", NULL}; + static char *keywords[] = {"", "", "x", NULL}; + Py_buffer buf = {NULL}; + const char *s; + int len; + int i = 0; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "w*|s#i", keywords, &buf, &s, &len, &i)) + return NULL; + PyBuffer_Release(&buf); + Py_RETURN_NONE; +} + +static PyObject * +getargs_s_hash_int2(PyObject *self, PyObject *args, PyObject *kwargs) +{ + static char *keywords[] = {"", "", "x", NULL}; + Py_buffer buf = {NULL}; const char *s; int len; int i = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s#i", keywords, &s, &len, &i)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "w*|(s#)i", keywords, &buf, &s, &len, &i)) return NULL; + PyBuffer_Release(&buf); Py_RETURN_NONE; } diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index ace0282ea6fce6cba476da0894fa49136431362e..4ac90dc8068934a7ed324b93ba673c8e3b85b8b3 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -57,6 +57,7 @@ lock_traverse(lockobject *self, visitproc visit, void *arg) static void lock_dealloc(lockobject *self) { + PyObject_GC_UnTrack(self); if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) self); } @@ -333,6 +334,7 @@ rlock_traverse(rlockobject *self, visitproc visit, void *arg) static void rlock_dealloc(rlockobject *self) { + PyObject_GC_UnTrack(self); if (self->in_weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) self); /* self->rlock_lock can be NULL if PyThread_allocate_lock() failed diff --git a/Modules/addrinfo.h b/Modules/addrinfo.h index c3c86248dd436044bac68a6b7c78816840f02ed3..66e5a795f86f1942285e4ebc5a5dead948f37d84 100644 --- a/Modules/addrinfo.h +++ b/Modules/addrinfo.h @@ -162,7 +162,9 @@ struct sockaddr_storage { #ifdef __cplusplus extern "C" { #endif +#ifdef ENABLE_IPV6 extern void freehostent(struct hostent *); +#endif #ifdef __cplusplus } #endif diff --git a/Modules/clinic/overlapped.c.h b/Modules/clinic/overlapped.c.h index cac44d0a5764ce9a21632e2ab9ffcd6cd3d4d601..721b38c75ceef32e504384b67795bebc6caee7c7 100644 --- a/Modules/clinic/overlapped.c.h +++ b/Modules/clinic/overlapped.c.h @@ -26,8 +26,22 @@ _overlapped_CreateIoCompletionPort(PyObject *module, PyObject *const *args, Py_s ULONG_PTR CompletionKey; DWORD NumberOfConcurrentThreads; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE""F_HANDLE""F_ULONG_PTR"k:CreateIoCompletionPort", - &FileHandle, &ExistingCompletionPort, &CompletionKey, &NumberOfConcurrentThreads)) { + if (!_PyArg_CheckPositional("CreateIoCompletionPort", nargs, 4, 4)) { + goto exit; + } + FileHandle = PyLong_AsVoidPtr(args[0]); + if (!FileHandle && PyErr_Occurred()) { + goto exit; + } + ExistingCompletionPort = PyLong_AsVoidPtr(args[1]); + if (!ExistingCompletionPort && PyErr_Occurred()) { + goto exit; + } + CompletionKey = PyLong_AsVoidPtr(args[2]); + if (!CompletionKey && PyErr_Occurred()) { + goto exit; + } + if (!_PyLong_UnsignedLong_Converter(args[3], &NumberOfConcurrentThreads)) { goto exit; } return_value = _overlapped_CreateIoCompletionPort_impl(module, FileHandle, ExistingCompletionPort, CompletionKey, NumberOfConcurrentThreads); @@ -59,8 +73,14 @@ _overlapped_GetQueuedCompletionStatus(PyObject *module, PyObject *const *args, P HANDLE CompletionPort; DWORD Milliseconds; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"k:GetQueuedCompletionStatus", - &CompletionPort, &Milliseconds)) { + if (!_PyArg_CheckPositional("GetQueuedCompletionStatus", nargs, 2, 2)) { + goto exit; + } + CompletionPort = PyLong_AsVoidPtr(args[0]); + if (!CompletionPort && PyErr_Occurred()) { + goto exit; + } + if (!_PyLong_UnsignedLong_Converter(args[1], &Milliseconds)) { goto exit; } return_value = _overlapped_GetQueuedCompletionStatus_impl(module, CompletionPort, Milliseconds); @@ -94,8 +114,22 @@ _overlapped_PostQueuedCompletionStatus(PyObject *module, PyObject *const *args, ULONG_PTR CompletionKey; OVERLAPPED *Overlapped; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"k"F_ULONG_PTR""F_POINTER":PostQueuedCompletionStatus", - &CompletionPort, &NumberOfBytes, &CompletionKey, &Overlapped)) { + if (!_PyArg_CheckPositional("PostQueuedCompletionStatus", nargs, 4, 4)) { + goto exit; + } + CompletionPort = PyLong_AsVoidPtr(args[0]); + if (!CompletionPort && PyErr_Occurred()) { + goto exit; + } + if (!_PyLong_UnsignedLong_Converter(args[1], &NumberOfBytes)) { + goto exit; + } + CompletionKey = PyLong_AsVoidPtr(args[2]); + if (!CompletionKey && PyErr_Occurred()) { + goto exit; + } + Overlapped = PyLong_AsVoidPtr(args[3]); + if (!Overlapped && PyErr_Occurred()) { goto exit; } return_value = _overlapped_PostQueuedCompletionStatus_impl(module, CompletionPort, NumberOfBytes, CompletionKey, Overlapped); @@ -129,8 +163,22 @@ _overlapped_RegisterWaitWithQueue(PyObject *module, PyObject *const *args, Py_ss OVERLAPPED *Overlapped; DWORD Milliseconds; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE""F_HANDLE""F_POINTER"k:RegisterWaitWithQueue", - &Object, &CompletionPort, &Overlapped, &Milliseconds)) { + if (!_PyArg_CheckPositional("RegisterWaitWithQueue", nargs, 4, 4)) { + goto exit; + } + Object = PyLong_AsVoidPtr(args[0]); + if (!Object && PyErr_Occurred()) { + goto exit; + } + CompletionPort = PyLong_AsVoidPtr(args[1]); + if (!CompletionPort && PyErr_Occurred()) { + goto exit; + } + Overlapped = PyLong_AsVoidPtr(args[2]); + if (!Overlapped && PyErr_Occurred()) { + goto exit; + } + if (!_PyLong_UnsignedLong_Converter(args[3], &Milliseconds)) { goto exit; } return_value = _overlapped_RegisterWaitWithQueue_impl(module, Object, CompletionPort, Overlapped, Milliseconds); @@ -157,7 +205,8 @@ _overlapped_UnregisterWait(PyObject *module, PyObject *arg) PyObject *return_value = NULL; HANDLE WaitHandle; - if (!PyArg_Parse(arg, ""F_HANDLE":UnregisterWait", &WaitHandle)) { + WaitHandle = PyLong_AsVoidPtr(arg); + if (!WaitHandle && PyErr_Occurred()) { goto exit; } return_value = _overlapped_UnregisterWait_impl(module, WaitHandle); @@ -186,8 +235,15 @@ _overlapped_UnregisterWaitEx(PyObject *module, PyObject *const *args, Py_ssize_t HANDLE WaitHandle; HANDLE Event; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE""F_HANDLE":UnregisterWaitEx", - &WaitHandle, &Event)) { + if (!_PyArg_CheckPositional("UnregisterWaitEx", nargs, 2, 2)) { + goto exit; + } + WaitHandle = PyLong_AsVoidPtr(args[0]); + if (!WaitHandle && PyErr_Occurred()) { + goto exit; + } + Event = PyLong_AsVoidPtr(args[1]); + if (!Event && PyErr_Occurred()) { goto exit; } return_value = _overlapped_UnregisterWaitEx_impl(module, WaitHandle, Event); @@ -222,8 +278,29 @@ _overlapped_CreateEvent(PyObject *module, PyObject *const *args, Py_ssize_t narg BOOL InitialState; const Py_UNICODE *Name; - if (!_PyArg_ParseStack(args, nargs, "OiiO&:CreateEvent", - &EventAttributes, &ManualReset, &InitialState, _PyUnicode_WideCharString_Opt_Converter, &Name)) { + if (!_PyArg_CheckPositional("CreateEvent", nargs, 4, 4)) { + goto exit; + } + EventAttributes = args[0]; + ManualReset = _PyLong_AsInt(args[1]); + if (ManualReset == -1 && PyErr_Occurred()) { + goto exit; + } + InitialState = _PyLong_AsInt(args[2]); + if (InitialState == -1 && PyErr_Occurred()) { + goto exit; + } + if (args[3] == Py_None) { + Name = NULL; + } + else if (PyUnicode_Check(args[3])) { + Name = PyUnicode_AsWideCharString(args[3], NULL); + if (Name == NULL) { + goto exit; + } + } + else { + _PyArg_BadArgument("CreateEvent", "argument 4", "str or None", args[3]); goto exit; } return_value = _overlapped_CreateEvent_impl(module, EventAttributes, ManualReset, InitialState, Name); @@ -253,7 +330,8 @@ _overlapped_SetEvent(PyObject *module, PyObject *arg) PyObject *return_value = NULL; HANDLE Handle; - if (!PyArg_Parse(arg, ""F_HANDLE":SetEvent", &Handle)) { + Handle = PyLong_AsVoidPtr(arg); + if (!Handle && PyErr_Occurred()) { goto exit; } return_value = _overlapped_SetEvent_impl(module, Handle); @@ -280,7 +358,8 @@ _overlapped_ResetEvent(PyObject *module, PyObject *arg) PyObject *return_value = NULL; HANDLE Handle; - if (!PyArg_Parse(arg, ""F_HANDLE":ResetEvent", &Handle)) { + Handle = PyLong_AsVoidPtr(arg); + if (!Handle && PyErr_Occurred()) { goto exit; } return_value = _overlapped_ResetEvent_impl(module, Handle); @@ -310,8 +389,15 @@ _overlapped_BindLocal(PyObject *module, PyObject *const *args, Py_ssize_t nargs) HANDLE Socket; int Family; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"i:BindLocal", - &Socket, &Family)) { + if (!_PyArg_CheckPositional("BindLocal", nargs, 2, 2)) { + goto exit; + } + Socket = PyLong_AsVoidPtr(args[0]); + if (!Socket && PyErr_Occurred()) { + goto exit; + } + Family = _PyLong_AsInt(args[1]); + if (Family == -1 && PyErr_Occurred()) { goto exit; } return_value = _overlapped_BindLocal_impl(module, Socket, Family); @@ -338,7 +424,7 @@ _overlapped_FormatMessage(PyObject *module, PyObject *arg) PyObject *return_value = NULL; DWORD code; - if (!PyArg_Parse(arg, "k:FormatMessage", &code)) { + if (!_PyLong_UnsignedLong_Converter(arg, &code)) { goto exit; } return_value = _overlapped_FormatMessage_impl(module, code); @@ -361,13 +447,25 @@ _overlapped_Overlapped(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; static const char * const _keywords[] = {"event", NULL}; - static _PyArg_Parser _parser = {"|"F_HANDLE":Overlapped", _keywords, 0}; + static _PyArg_Parser _parser = {NULL, _keywords, "Overlapped", 0}; + PyObject *argsbuf[1]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0; HANDLE event = INVALID_HANDLE_VALUE; - if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser, - &event)) { + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 0, 1, 0, argsbuf); + if (!fastargs) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + event = PyLong_AsVoidPtr(fastargs[0]); + if (!event && PyErr_Occurred()) { goto exit; } +skip_optional_pos: return_value = _overlapped_Overlapped_impl(type, event); exit: @@ -413,10 +511,17 @@ _overlapped_Overlapped_getresult(OverlappedObject *self, PyObject *const *args, PyObject *return_value = NULL; BOOL wait = FALSE; - if (!_PyArg_ParseStack(args, nargs, "|i:getresult", - &wait)) { + if (!_PyArg_CheckPositional("getresult", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + wait = _PyLong_AsInt(args[0]); + if (wait == -1 && PyErr_Occurred()) { goto exit; } +skip_optional: return_value = _overlapped_Overlapped_getresult_impl(self, wait); exit: @@ -443,8 +548,14 @@ _overlapped_Overlapped_ReadFile(OverlappedObject *self, PyObject *const *args, P HANDLE handle; DWORD size; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"k:ReadFile", - &handle, &size)) { + if (!_PyArg_CheckPositional("ReadFile", nargs, 2, 2)) { + goto exit; + } + handle = PyLong_AsVoidPtr(args[0]); + if (!handle && PyErr_Occurred()) { + goto exit; + } + if (!_PyLong_UnsignedLong_Converter(args[1], &size)) { goto exit; } return_value = _overlapped_Overlapped_ReadFile_impl(self, handle, size); @@ -473,8 +584,18 @@ _overlapped_Overlapped_ReadFileInto(OverlappedObject *self, PyObject *const *arg HANDLE handle; Py_buffer bufobj = {NULL, NULL}; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"y*:ReadFileInto", - &handle, &bufobj)) { + if (!_PyArg_CheckPositional("ReadFileInto", nargs, 2, 2)) { + goto exit; + } + handle = PyLong_AsVoidPtr(args[0]); + if (!handle && PyErr_Occurred()) { + goto exit; + } + if (PyObject_GetBuffer(args[1], &bufobj, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!PyBuffer_IsContiguous(&bufobj, 'C')) { + _PyArg_BadArgument("ReadFileInto", "argument 2", "contiguous buffer", args[1]); goto exit; } return_value = _overlapped_Overlapped_ReadFileInto_impl(self, handle, &bufobj); @@ -509,10 +630,23 @@ _overlapped_Overlapped_WSARecv(OverlappedObject *self, PyObject *const *args, Py DWORD size; DWORD flags = 0; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"k|k:WSARecv", - &handle, &size, &flags)) { + if (!_PyArg_CheckPositional("WSARecv", nargs, 2, 3)) { + goto exit; + } + handle = PyLong_AsVoidPtr(args[0]); + if (!handle && PyErr_Occurred()) { + goto exit; + } + if (!_PyLong_UnsignedLong_Converter(args[1], &size)) { goto exit; } + if (nargs < 3) { + goto skip_optional; + } + if (!_PyLong_UnsignedLong_Converter(args[2], &flags)) { + goto exit; + } +skip_optional: return_value = _overlapped_Overlapped_WSARecv_impl(self, handle, size, flags); exit: @@ -541,8 +675,21 @@ _overlapped_Overlapped_WSARecvInto(OverlappedObject *self, PyObject *const *args Py_buffer bufobj = {NULL, NULL}; DWORD flags; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"y*k:WSARecvInto", - &handle, &bufobj, &flags)) { + if (!_PyArg_CheckPositional("WSARecvInto", nargs, 3, 3)) { + goto exit; + } + handle = PyLong_AsVoidPtr(args[0]); + if (!handle && PyErr_Occurred()) { + goto exit; + } + if (PyObject_GetBuffer(args[1], &bufobj, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!PyBuffer_IsContiguous(&bufobj, 'C')) { + _PyArg_BadArgument("WSARecvInto", "argument 2", "contiguous buffer", args[1]); + goto exit; + } + if (!_PyLong_UnsignedLong_Converter(args[2], &flags)) { goto exit; } return_value = _overlapped_Overlapped_WSARecvInto_impl(self, handle, &bufobj, flags); @@ -576,8 +723,18 @@ _overlapped_Overlapped_WriteFile(OverlappedObject *self, PyObject *const *args, HANDLE handle; Py_buffer bufobj = {NULL, NULL}; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"y*:WriteFile", - &handle, &bufobj)) { + if (!_PyArg_CheckPositional("WriteFile", nargs, 2, 2)) { + goto exit; + } + handle = PyLong_AsVoidPtr(args[0]); + if (!handle && PyErr_Occurred()) { + goto exit; + } + if (PyObject_GetBuffer(args[1], &bufobj, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!PyBuffer_IsContiguous(&bufobj, 'C')) { + _PyArg_BadArgument("WriteFile", "argument 2", "contiguous buffer", args[1]); goto exit; } return_value = _overlapped_Overlapped_WriteFile_impl(self, handle, &bufobj); @@ -612,8 +769,21 @@ _overlapped_Overlapped_WSASend(OverlappedObject *self, PyObject *const *args, Py Py_buffer bufobj = {NULL, NULL}; DWORD flags; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"y*k:WSASend", - &handle, &bufobj, &flags)) { + if (!_PyArg_CheckPositional("WSASend", nargs, 3, 3)) { + goto exit; + } + handle = PyLong_AsVoidPtr(args[0]); + if (!handle && PyErr_Occurred()) { + goto exit; + } + if (PyObject_GetBuffer(args[1], &bufobj, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!PyBuffer_IsContiguous(&bufobj, 'C')) { + _PyArg_BadArgument("WSASend", "argument 2", "contiguous buffer", args[1]); + goto exit; + } + if (!_PyLong_UnsignedLong_Converter(args[2], &flags)) { goto exit; } return_value = _overlapped_Overlapped_WSASend_impl(self, handle, &bufobj, flags); @@ -648,8 +818,15 @@ _overlapped_Overlapped_AcceptEx(OverlappedObject *self, PyObject *const *args, P HANDLE ListenSocket; HANDLE AcceptSocket; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE""F_HANDLE":AcceptEx", - &ListenSocket, &AcceptSocket)) { + if (!_PyArg_CheckPositional("AcceptEx", nargs, 2, 2)) { + goto exit; + } + ListenSocket = PyLong_AsVoidPtr(args[0]); + if (!ListenSocket && PyErr_Occurred()) { + goto exit; + } + AcceptSocket = PyLong_AsVoidPtr(args[1]); + if (!AcceptSocket && PyErr_Occurred()) { goto exit; } return_value = _overlapped_Overlapped_AcceptEx_impl(self, ListenSocket, AcceptSocket); @@ -681,10 +858,18 @@ _overlapped_Overlapped_ConnectEx(OverlappedObject *self, PyObject *const *args, HANDLE ConnectSocket; PyObject *AddressObj; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"O!:ConnectEx", - &ConnectSocket, &PyTuple_Type, &AddressObj)) { + if (!_PyArg_CheckPositional("ConnectEx", nargs, 2, 2)) { + goto exit; + } + ConnectSocket = PyLong_AsVoidPtr(args[0]); + if (!ConnectSocket && PyErr_Occurred()) { goto exit; } + if (!PyTuple_Check(args[1])) { + _PyArg_BadArgument("ConnectEx", "argument 2", "tuple", args[1]); + goto exit; + } + AddressObj = args[1]; return_value = _overlapped_Overlapped_ConnectEx_impl(self, ConnectSocket, AddressObj); exit: @@ -710,8 +895,14 @@ _overlapped_Overlapped_DisconnectEx(OverlappedObject *self, PyObject *const *arg HANDLE Socket; DWORD flags; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"k:DisconnectEx", - &Socket, &flags)) { + if (!_PyArg_CheckPositional("DisconnectEx", nargs, 2, 2)) { + goto exit; + } + Socket = PyLong_AsVoidPtr(args[0]); + if (!Socket && PyErr_Occurred()) { + goto exit; + } + if (!_PyLong_UnsignedLong_Converter(args[1], &flags)) { goto exit; } return_value = _overlapped_Overlapped_DisconnectEx_impl(self, Socket, flags); @@ -749,8 +940,30 @@ _overlapped_Overlapped_TransmitFile(OverlappedObject *self, PyObject *const *arg DWORD count_per_send; DWORD flags; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE""F_HANDLE"kkkkk:TransmitFile", - &Socket, &File, &offset, &offset_high, &count_to_write, &count_per_send, &flags)) { + if (!_PyArg_CheckPositional("TransmitFile", nargs, 7, 7)) { + goto exit; + } + Socket = PyLong_AsVoidPtr(args[0]); + if (!Socket && PyErr_Occurred()) { + goto exit; + } + File = PyLong_AsVoidPtr(args[1]); + if (!File && PyErr_Occurred()) { + goto exit; + } + if (!_PyLong_UnsignedLong_Converter(args[2], &offset)) { + goto exit; + } + if (!_PyLong_UnsignedLong_Converter(args[3], &offset_high)) { + goto exit; + } + if (!_PyLong_UnsignedLong_Converter(args[4], &count_to_write)) { + goto exit; + } + if (!_PyLong_UnsignedLong_Converter(args[5], &count_per_send)) { + goto exit; + } + if (!_PyLong_UnsignedLong_Converter(args[6], &flags)) { goto exit; } return_value = _overlapped_Overlapped_TransmitFile_impl(self, Socket, File, offset, offset_high, count_to_write, count_per_send, flags); @@ -778,7 +991,8 @@ _overlapped_Overlapped_ConnectNamedPipe(OverlappedObject *self, PyObject *arg) PyObject *return_value = NULL; HANDLE Pipe; - if (!PyArg_Parse(arg, ""F_HANDLE":ConnectNamedPipe", &Pipe)) { + Pipe = PyLong_AsVoidPtr(arg); + if (!Pipe && PyErr_Occurred()) { goto exit; } return_value = _overlapped_Overlapped_ConnectNamedPipe_impl(self, Pipe); @@ -843,10 +1057,14 @@ _overlapped_WSAConnect(PyObject *module, PyObject *const *args, Py_ssize_t nargs HANDLE ConnectSocket; PyObject *AddressObj; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"O:WSAConnect", - &ConnectSocket, &AddressObj)) { + if (!_PyArg_CheckPositional("WSAConnect", nargs, 2, 2)) { + goto exit; + } + ConnectSocket = PyLong_AsVoidPtr(args[0]); + if (!ConnectSocket && PyErr_Occurred()) { goto exit; } + AddressObj = args[1]; return_value = _overlapped_WSAConnect_impl(module, ConnectSocket, AddressObj); exit: @@ -876,10 +1094,24 @@ _overlapped_Overlapped_WSASendTo(OverlappedObject *self, PyObject *const *args, DWORD flags; PyObject *AddressObj; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"y*kO:WSASendTo", - &handle, &bufobj, &flags, &AddressObj)) { + if (!_PyArg_CheckPositional("WSASendTo", nargs, 4, 4)) { goto exit; } + handle = PyLong_AsVoidPtr(args[0]); + if (!handle && PyErr_Occurred()) { + goto exit; + } + if (PyObject_GetBuffer(args[1], &bufobj, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!PyBuffer_IsContiguous(&bufobj, 'C')) { + _PyArg_BadArgument("WSASendTo", "argument 2", "contiguous buffer", args[1]); + goto exit; + } + if (!_PyLong_UnsignedLong_Converter(args[2], &flags)) { + goto exit; + } + AddressObj = args[3]; return_value = _overlapped_Overlapped_WSASendTo_impl(self, handle, &bufobj, flags, AddressObj); exit: @@ -913,10 +1145,23 @@ _overlapped_Overlapped_WSARecvFrom(OverlappedObject *self, PyObject *const *args DWORD size; DWORD flags = 0; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"k|k:WSARecvFrom", - &handle, &size, &flags)) { + if (!_PyArg_CheckPositional("WSARecvFrom", nargs, 2, 3)) { goto exit; } + handle = PyLong_AsVoidPtr(args[0]); + if (!handle && PyErr_Occurred()) { + goto exit; + } + if (!_PyLong_UnsignedLong_Converter(args[1], &size)) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + if (!_PyLong_UnsignedLong_Converter(args[2], &flags)) { + goto exit; + } +skip_optional: return_value = _overlapped_Overlapped_WSARecvFrom_impl(self, handle, size, flags); exit: @@ -946,10 +1191,30 @@ _overlapped_Overlapped_WSARecvFromInto(OverlappedObject *self, PyObject *const * DWORD size; DWORD flags = 0; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"y*k|k:WSARecvFromInto", - &handle, &bufobj, &size, &flags)) { + if (!_PyArg_CheckPositional("WSARecvFromInto", nargs, 3, 4)) { + goto exit; + } + handle = PyLong_AsVoidPtr(args[0]); + if (!handle && PyErr_Occurred()) { + goto exit; + } + if (PyObject_GetBuffer(args[1], &bufobj, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!PyBuffer_IsContiguous(&bufobj, 'C')) { + _PyArg_BadArgument("WSARecvFromInto", "argument 2", "contiguous buffer", args[1]); + goto exit; + } + if (!_PyLong_UnsignedLong_Converter(args[2], &size)) { + goto exit; + } + if (nargs < 4) { + goto skip_optional; + } + if (!_PyLong_UnsignedLong_Converter(args[3], &flags)) { goto exit; } +skip_optional: return_value = _overlapped_Overlapped_WSARecvFromInto_impl(self, handle, &bufobj, size, flags); exit: @@ -960,4 +1225,4 @@ exit: return return_value; } -/*[clinic end generated code: output=9078d9f9984864a2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d90cda84e49a7c23 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 1ce7d86204e6f39544e8cc22d232996894d12564..ddd41cae3ec45216693478226070999e44121b1a 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -4685,6 +4685,8 @@ exit: return return_value; } +#if ((defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))) + PyDoc_STRVAR(os_dup2__doc__, "dup2($module, /, fd, fd2, inheritable=True)\n" "--\n" @@ -4740,6 +4742,8 @@ exit: return return_value; } +#endif /* ((defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))) */ + #if defined(HAVE_LOCKF) PyDoc_STRVAR(os_lockf__doc__, @@ -7869,7 +7873,7 @@ exit: #endif /* defined(HAVE_MEMFD_CREATE) */ -#if defined(HAVE_EVENTFD) +#if (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) PyDoc_STRVAR(os_eventfd__doc__, "eventfd($module, /, initval, flags=EFD_CLOEXEC)\n" @@ -7915,9 +7919,9 @@ exit: return return_value; } -#endif /* defined(HAVE_EVENTFD) */ +#endif /* (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) */ -#if defined(HAVE_EVENTFD) +#if (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) PyDoc_STRVAR(os_eventfd_read__doc__, "eventfd_read($module, /, fd)\n" @@ -7953,9 +7957,9 @@ exit: return return_value; } -#endif /* defined(HAVE_EVENTFD) */ +#endif /* (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) */ -#if defined(HAVE_EVENTFD) +#if (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) PyDoc_STRVAR(os_eventfd_write__doc__, "eventfd_write($module, /, fd, value)\n" @@ -7995,7 +7999,7 @@ exit: return return_value; } -#endif /* defined(HAVE_EVENTFD) */ +#endif /* (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) */ #if (defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)) @@ -9105,6 +9109,10 @@ exit: #define OS_TCSETPGRP_METHODDEF #endif /* !defined(OS_TCSETPGRP_METHODDEF) */ +#ifndef OS_DUP2_METHODDEF + #define OS_DUP2_METHODDEF +#endif /* !defined(OS_DUP2_METHODDEF) */ + #ifndef OS_LOCKF_METHODDEF #define OS_LOCKF_METHODDEF #endif /* !defined(OS_LOCKF_METHODDEF) */ @@ -9352,4 +9360,4 @@ exit: #ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF #define OS_WAITSTATUS_TO_EXITCODE_METHODDEF #endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */ -/*[clinic end generated code: output=bae15f09a1b3d2e7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c22a8b6de4a0ccb7 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/resource.c.h b/Modules/clinic/resource.c.h index c591823ed7170c5c1fed02b8a035c7a173c0738e..f95321176a73a36f59007141e8daa69381cb04bf 100644 --- a/Modules/clinic/resource.c.h +++ b/Modules/clinic/resource.c.h @@ -95,41 +95,42 @@ exit: #if defined(HAVE_PRLIMIT) PyDoc_STRVAR(resource_prlimit__doc__, -"prlimit(pid, resource, [limits])"); +"prlimit($module, pid, resource, limits=None, /)\n" +"--\n" +"\n"); #define RESOURCE_PRLIMIT_METHODDEF \ - {"prlimit", (PyCFunction)resource_prlimit, METH_VARARGS, resource_prlimit__doc__}, + {"prlimit", _PyCFunction_CAST(resource_prlimit), METH_FASTCALL, resource_prlimit__doc__}, static PyObject * resource_prlimit_impl(PyObject *module, pid_t pid, int resource, - int group_right_1, PyObject *limits); + PyObject *limits); static PyObject * -resource_prlimit(PyObject *module, PyObject *args) +resource_prlimit(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; pid_t pid; int resource; - int group_right_1 = 0; - PyObject *limits = NULL; - - switch (PyTuple_GET_SIZE(args)) { - case 2: - if (!PyArg_ParseTuple(args, "" _Py_PARSE_PID "i:prlimit", &pid, &resource)) { - goto exit; - } - break; - case 3: - if (!PyArg_ParseTuple(args, "" _Py_PARSE_PID "iO:prlimit", &pid, &resource, &limits)) { - goto exit; - } - group_right_1 = 1; - break; - default: - PyErr_SetString(PyExc_TypeError, "resource.prlimit requires 2 to 3 arguments"); - goto exit; + PyObject *limits = Py_None; + + if (!_PyArg_CheckPositional("prlimit", nargs, 2, 3)) { + goto exit; + } + pid = PyLong_AsPid(args[0]); + if (pid == -1 && PyErr_Occurred()) { + goto exit; + } + resource = _PyLong_AsInt(args[1]); + if (resource == -1 && PyErr_Occurred()) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; } - return_value = resource_prlimit_impl(module, pid, resource, group_right_1, limits); + limits = args[2]; +skip_optional: + return_value = resource_prlimit_impl(module, pid, resource, limits); exit: return return_value; @@ -171,4 +172,4 @@ exit: #ifndef RESOURCE_PRLIMIT_METHODDEF #define RESOURCE_PRLIMIT_METHODDEF #endif /* !defined(RESOURCE_PRLIMIT_METHODDEF) */ -/*[clinic end generated code: output=7c57d4f3688d3f07 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=13441806729c6eaa input=a9049054013a1b77]*/ diff --git a/Modules/errnomodule.c b/Modules/errnomodule.c index bf6766e02349c0037beb4db84c3ab5a02da20735..0516e7367050c2f187ccf928a74233c61c7ccefd 100644 --- a/Modules/errnomodule.c +++ b/Modules/errnomodule.c @@ -280,6 +280,10 @@ errno_exec(PyObject *module) #ifdef ENOANO add_errcode("ENOANO", ENOANO, "No anode"); #endif +#if defined(__wasi__) && !defined(ESHUTDOWN) + // WASI SDK 16 does not have ESHUTDOWN, shutdown results in EPIPE. + #define ESHUTDOWN EPIPE +#endif #ifdef ESHUTDOWN add_errcode("ESHUTDOWN", ESHUTDOWN, "Cannot send after transport endpoint shutdown"); #else diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 3bda6e4bb8c021bd2c5648de6463b88c8213cc06..dcd46feff0cc48bf8cf290f8404f0e1198eb84fc 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -2347,6 +2347,13 @@ PyObject_GC_Del(void *op) size_t presize = _PyType_PreHeaderSize(((PyObject *)op)->ob_type); PyGC_Head *g = AS_GC(op); if (_PyObject_GC_IS_TRACKED(op)) { +#ifdef Py_DEBUG + if (PyErr_WarnExplicitFormat(PyExc_ResourceWarning, "gc", 0, + "gc", NULL, "Object of type %s is not untracked before destruction", + ((PyObject*)op)->ob_type->tp_name)) { + PyErr_WriteUnraisable(NULL); + } +#endif gc_list_remove(g); } GCState *gcstate = get_gc_state(); diff --git a/Modules/getaddrinfo.c b/Modules/getaddrinfo.c index 5aaa6e7c8144f7dc5c06f2292d44ffcecbcf5ee5..0b4620ed683de9d63c5af77cf4d13bb977616d83 100644 --- a/Modules/getaddrinfo.c +++ b/Modules/getaddrinfo.c @@ -61,6 +61,9 @@ # define FAITH #endif +#ifdef HAVE_NETDB_H +#define HAVE_GETADDRINFO 1 + #define SUCCESS 0 #define GAI_ANY 0 #define YES 1 @@ -636,3 +639,5 @@ get_addr(hostname, af, res, pai, port0) *res = NULL; return error; } + +#endif // HAVE_NETDB_H diff --git a/Modules/getnameinfo.c b/Modules/getnameinfo.c index db3e8eedd217c093cabd76225aa8fe08a53a914b..335021f79bafea34b5c75589f969743d98c8751c 100644 --- a/Modules/getnameinfo.c +++ b/Modules/getnameinfo.c @@ -48,6 +48,9 @@ #include "addrinfo.h" #endif +#ifdef HAVE_NETDB_H +#define HAVE_GETNAMEINFO 1 + #define SUCCESS 0 #define YES 1 #define NO 0 @@ -211,3 +214,4 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) } return SUCCESS; } +#endif // HAVE_NETDB_H diff --git a/Modules/main.c b/Modules/main.c index 90f237293b8565cfbdfeaa063fbab5dca1a50fd5..aa523fc58d93fbf960fbba57a9216d5697927f47 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -649,7 +649,7 @@ exit_sigint(void) * SIG_DFL handler for SIGINT if KeyboardInterrupt went unhandled. * If we don't, a calling process such as a shell may not know * about the user's ^C. https://www.cons.org/cracauer/sigint.html */ -#if defined(HAVE_GETPID) && !defined(MS_WINDOWS) +#if defined(HAVE_GETPID) && defined(HAVE_KILL) && !defined(MS_WINDOWS) if (PyOS_setsig(SIGINT, SIG_DFL) == SIG_ERR) { perror("signal"); /* Impossible in normal environments. */ } else { diff --git a/Modules/overlapped.c b/Modules/overlapped.c index 19d25a53af7bb50ca55dac6ce88722595c017bb0..0cec9eedc87f0988be65afecc77da6e93109e2c6 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -32,27 +32,33 @@ #define T_HANDLE T_POINTER /*[python input] -class OVERLAPPED_converter(CConverter): - type = 'OVERLAPPED *' +class pointer_converter(CConverter): format_unit = '"F_POINTER"' -class HANDLE_converter(CConverter): + def parse_arg(self, argname, displayname): + return """ + {paramname} = PyLong_AsVoidPtr({argname}); + if (!{paramname} && PyErr_Occurred()) {{{{ + goto exit; + }}}} + """.format(argname=argname, paramname=self.parser_name) + +class OVERLAPPED_converter(pointer_converter): + type = 'OVERLAPPED *' + +class HANDLE_converter(pointer_converter): type = 'HANDLE' - format_unit = '"F_HANDLE"' -class ULONG_PTR_converter(CConverter): +class ULONG_PTR_converter(pointer_converter): type = 'ULONG_PTR' - format_unit = '"F_ULONG_PTR"' -class DWORD_converter(CConverter): +class DWORD_converter(unsigned_long_converter): type = 'DWORD' - format_unit = 'k' -class BOOL_converter(CConverter): +class BOOL_converter(int_converter): type = 'BOOL' - format_unit = 'i' [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=83bb8c2c2514f2a8]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=a19133a9e14fae9c]*/ /*[clinic input] module _overlapped diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 40229bce0f40339a4d64fd7067cbb553788ff709..d45fa231ae5e2aa703b0b3543c4daab7589c8566 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -9316,7 +9316,9 @@ os_dup_impl(PyObject *module, int fd) return _Py_dup(fd); } - +// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS(). +// dup2.c provides working dup2() if and only if F_DUPFD is available. +#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS)) /*[clinic input] os.dup2 -> int fd: int @@ -9416,6 +9418,7 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) return res; } +#endif #ifdef HAVE_LOCKF @@ -13104,7 +13107,7 @@ os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags) } #endif -#ifdef HAVE_EVENTFD +#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC) /*[clinic input] os.eventfd @@ -13175,7 +13178,7 @@ os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value) } Py_RETURN_NONE; } -#endif /* HAVE_EVENTFD */ +#endif /* HAVE_EVENTFD && EFD_CLOEXEC */ /* Terminal size querying */ @@ -13244,24 +13247,11 @@ os_get_terminal_size_impl(PyObject *module, int fd) #ifdef TERMSIZE_USE_CONIO { - DWORD nhandle; HANDLE handle; CONSOLE_SCREEN_BUFFER_INFO csbi; - switch (fd) { - case 0: nhandle = STD_INPUT_HANDLE; - break; - case 1: nhandle = STD_OUTPUT_HANDLE; - break; - case 2: nhandle = STD_ERROR_HANDLE; - break; - default: - return PyErr_Format(PyExc_ValueError, "bad file descriptor"); - } - handle = GetStdHandle(nhandle); - if (handle == NULL) - return PyErr_Format(PyExc_OSError, "handle cannot be retrieved"); + handle = _Py_get_osfhandle(fd); if (handle == INVALID_HANDLE_VALUE) - return PyErr_SetFromWindowsErr(0); + return NULL; if (!GetConsoleScreenBufferInfo(handle, &csbi)) return PyErr_SetFromWindowsErr(0); @@ -15462,11 +15452,15 @@ all_ins(PyObject *m) #endif #endif /* HAVE_MEMFD_CREATE */ -#ifdef HAVE_EVENTFD +#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC) if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1; +#ifdef EFD_NONBLOCK if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1; +#endif +#ifdef EFD_SEMAPHORE if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1; #endif +#endif /* HAVE_EVENTFD && EFD_CLOEXEC */ #if defined(__APPLE__) if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1; diff --git a/Modules/resource.c b/Modules/resource.c index d8bba2e39847a1c502e9aa76e20b65883ba7875c..a97fb870062b822a50ee7d260ee385427ea9a2ff 100644 --- a/Modules/resource.c +++ b/Modules/resource.c @@ -24,8 +24,16 @@ module resource class pid_t_converter(CConverter): type = 'pid_t' format_unit = '" _Py_PARSE_PID "' + + def parse_arg(self, argname, displayname): + return """ + {paramname} = PyLong_AsPid({argname}); + if ({paramname} == -1 && PyErr_Occurred()) {{{{ + goto exit; + }}}} + """.format(argname=argname, paramname=self.parser_name) [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=0c1d19f640d57e48]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=5af1c116d56cbb5a]*/ #include "clinic/resource.c.h" @@ -268,17 +276,15 @@ resource.prlimit pid: pid_t resource: int - [ - limits: object - ] + limits: object = None / [clinic start generated code]*/ static PyObject * resource_prlimit_impl(PyObject *module, pid_t pid, int resource, - int group_right_1, PyObject *limits) -/*[clinic end generated code: output=ee976b393187a7a3 input=b77743bdccc83564]*/ + PyObject *limits) +/*[clinic end generated code: output=6ebc49ff8c3a816e input=54bb69c9585e33bf]*/ { struct rlimit old_limit, new_limit; int retval; @@ -294,7 +300,7 @@ resource_prlimit_impl(PyObject *module, pid_t pid, int resource, return NULL; } - if (group_right_1) { + if (limits != Py_None) { if (py2rlimit(limits, &new_limit) < 0) { return NULL; } diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index 5c36eaaedeb70b2d62da4e4c42b12cdc503fb85c..4eea928a2683ae6444004317188bc960b808ede2 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -63,6 +63,11 @@ extern void bzero(void *, int); # define SOCKET int #endif +// WASI SDK 16 does not have POLLPRIO, define as no-op +#if defined(__wasi__) && !defined(POLLPRI) +# define POLLPRI 0 +#endif + typedef struct { PyObject *close; PyTypeObject *poll_Type; diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 55e19ffab5cba4f6220be0f7ac9e3830ae7482e8..869bacde924d8333ed0fb3f60e9b69944e01f76f 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -227,7 +227,7 @@ shutdown(how) -- shut down traffic in one or both directions\n\ #define HAVE_INET_PTON #include <netdb.h> -#endif +#endif // __sgi /* Solaris fails to define this variable at all. */ #if (defined(__sun) && defined(__SVR4)) && !defined(INET_ADDRSTRLEN) @@ -256,7 +256,9 @@ shutdown(how) -- shut down traffic in one or both directions\n\ #ifndef MS_WINDOWS /* Non-MS WINDOWS includes */ -# include <netdb.h> +#ifdef HAVE_NETDB_H +# include <netdb.h> +#endif # include <unistd.h> /* Headers needed for inet_ntoa() and inet_addr() */ @@ -439,10 +441,11 @@ remove_unusable_flags(PyObject *m) #define freeaddrinfo fake_freeaddrinfo #include "getaddrinfo.c" #endif + #if !defined(HAVE_GETNAMEINFO) #define getnameinfo fake_getnameinfo #include "getnameinfo.c" -#endif +#endif // HAVE_GETNAMEINFO #ifdef MS_WINDOWS #define SOCKETCLOSE closesocket @@ -623,6 +626,7 @@ set_error(void) } +#if defined(HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYNAME) || defined (HAVE_GETHOSTBYADDR) static PyObject * set_herror(int h_error) { @@ -640,8 +644,10 @@ set_herror(int h_error) return NULL; } +#endif +#ifdef HAVE_GETADDRINFO static PyObject * set_gaierror(int error) { @@ -665,6 +671,7 @@ set_gaierror(int error) return NULL; } +#endif /* Function to perform the setting of socket blocking mode internally. block = (1 | 0). */ @@ -1046,6 +1053,7 @@ static PyThread_type_lock netdb_lock; #endif +#ifdef HAVE_GETADDRINFO /* Convert a string specifying a host name or one of a few symbolic names to a numeric IP address. This usually calls gethostbyname() to do the work; the names "" and "<broadcast>" are special. @@ -1202,7 +1210,7 @@ setipaddr(const char *name, struct sockaddr *addr_ret, size_t addr_ret_size, int return -1; } } - +#endif // HAVE_GETADDRINFO /* Convert IPv4 sockaddr to a Python str. */ @@ -1626,6 +1634,7 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto) } } +#if defined(HAVE_BIND) || defined(HAVE_CONNECTTO) || defined(CMSG_LEN) /* Helper for getsockaddrarg: bypass IDNA for ASCII-only host names (in particular, numeric IP addresses). */ struct maybe_idna { @@ -1724,8 +1733,10 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, struct sockaddr_un* addr = &addrbuf->un; #ifdef __linux__ - if (path.len > 0 && *(const char *)path.buf == 0) { - /* Linux abstract namespace extension */ + if (path.len == 0 || *(const char *)path.buf == 0) { + /* Linux abstract namespace extension: + - Empty address auto-binding to an abstract address + - Address that starts with null byte */ if ((size_t)path.len > sizeof addr->sun_path) { PyErr_SetString(PyExc_OSError, "AF_UNIX path too long"); @@ -2488,6 +2499,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, } } +#endif // defined(HAVE_BIND) || defined(HAVE_CONNECTTO) || defined(CMSG_LEN) /* Get the address length according to the socket object's address family. @@ -2785,6 +2797,7 @@ struct sock_accept { SOCKET_T result; }; +#if defined(HAVE_ACCEPT) || defined(HAVE_ACCEPT4) #if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) /* accept4() is available on Linux 2.6.28+ and glibc 2.10 */ static int accept4_works = -1; @@ -2898,6 +2911,8 @@ PyDoc_STRVAR(accept_doc, Wait for an incoming connection. Return a new socket file descriptor\n\ representing the connection, and the address of the client.\n\ For IP sockets, the address info is a pair (hostaddr, port)."); +#endif // defined(HAVE_ACCEPT) || defined(HAVE_ACCEPT4) + /* s.setblocking(flag) method. Argument: False -- non-blocking mode; same as settimeout(0) @@ -3062,6 +3077,7 @@ Returns the timeout in seconds (float) associated with socket\n\ operations. A timeout of None indicates that timeouts on socket\n\ operations are disabled."); +#ifdef HAVE_SETSOCKOPT /* s.setsockopt() method. With an integer third argument, sets an integer optval with optlen=4. With None as third argument and an integer fourth argument, set @@ -3151,7 +3167,7 @@ setsockopt(level, option, None, optlen: int)\n\ Set a socket option. See the Unix manual for level and option.\n\ The value argument can either be an integer, a string buffer, or\n\ None, optlen."); - +#endif /* s.getsockopt() method. With two arguments, retrieves an integer option. @@ -3225,6 +3241,7 @@ If a nonzero buffersize argument is given, the return value is a\n\ string of that length; otherwise it is an integer."); +#ifdef HAVE_BIND /* s.bind(sockaddr) method */ static PyObject * @@ -3256,6 +3273,7 @@ PyDoc_STRVAR(bind_doc, Bind the socket to a local address. For IP sockets, the address is a\n\ pair (host, port); the host must refer to the local host. For raw packet\n\ sockets the address is a tuple (ifname, proto [,pkttype [,hatype [,addr]]])"); +#endif /* s.close() method. @@ -3308,6 +3326,7 @@ Close the socket object without closing the underlying file descriptor.\n\ The object cannot be used after this call, but the file descriptor\n\ can be reused for other purposes. The file descriptor is returned."); +#ifdef HAVE_CONNECT static int sock_connect_impl(PySocketSockObject *s, void* Py_UNUSED(data)) { @@ -3455,6 +3474,7 @@ PyDoc_STRVAR(connect_ex_doc, \n\ This is like connect(address), but returns an error code (the errno value)\n\ instead of raising an exception when an error occurs."); +#endif // HAVE_CONNECT /* s.fileno() method */ @@ -3471,6 +3491,7 @@ PyDoc_STRVAR(fileno_doc, Return the integer file descriptor of the socket."); +#ifdef HAVE_GETSOCKNAME /* s.getsockname() method */ static PyObject * @@ -3498,6 +3519,7 @@ PyDoc_STRVAR(getsockname_doc, Return the address of the local endpoint. The format depends on the\n\ address family. For IPv4 sockets, the address info is a pair\n\ (hostaddr, port)."); +#endif #ifdef HAVE_GETPEERNAME /* Cray APP doesn't have this :-( */ @@ -3531,6 +3553,7 @@ info is a pair (hostaddr, port)."); #endif /* HAVE_GETPEERNAME */ +#ifdef HAVE_LISTEN /* s.listen(n) method */ static PyObject * @@ -3563,6 +3586,7 @@ Enable a server to accept connections. If backlog is specified, it must be\n\ at least 0 (if it is lower, it is set to 0); it specifies the number of\n\ unaccepted connections that the system will allow before refusing new\n\ connections. If not specified, a default reasonable value is chosen."); +#endif struct sock_recv { char *cbuf; @@ -3739,6 +3763,7 @@ struct sock_recvfrom { Py_ssize_t result; }; +#ifdef HAVE_RECVFROM static int sock_recvfrom_impl(PySocketSockObject *s, void *data) { @@ -3911,6 +3936,7 @@ PyDoc_STRVAR(recvfrom_into_doc, "recvfrom_into(buffer[, nbytes[, flags]]) -> (nbytes, address info)\n\ \n\ Like recv_into(buffer[, nbytes[, flags]]) but also return the sender's address info."); +#endif /* The sendmsg() and recvmsg[_into]() methods require a working CMSG_LEN(). See the comment near get_CMSG_LEN(). */ @@ -4377,6 +4403,7 @@ until all data is sent. If an error occurs, it's impossible\n\ to tell how much data has been sent."); +#ifdef HAVE_SENDTO struct sock_sendto { char *buf; Py_ssize_t len; @@ -4469,6 +4496,7 @@ PyDoc_STRVAR(sendto_doc, \n\ Like send(data, flags) but allows specifying the destination address.\n\ For IP sockets, the address is a pair (hostaddr, port)."); +#endif /* The sendmsg() and recvmsg[_into]() methods require a working @@ -5032,16 +5060,22 @@ socket.fromshare()."); /* List of methods for socket objects */ static PyMethodDef sock_methods[] = { +#if defined(HAVE_ACCEPT) || defined(HAVE_ACCEPT4) {"_accept", (PyCFunction)sock_accept, METH_NOARGS, accept_doc}, +#endif +#ifdef HAVE_BIND {"bind", (PyCFunction)sock_bind, METH_O, bind_doc}, +#endif {"close", (PyCFunction)sock_close, METH_NOARGS, sock_close_doc}, +#ifdef HAVE_CONNECT {"connect", (PyCFunction)sock_connect, METH_O, connect_doc}, {"connect_ex", (PyCFunction)sock_connect_ex, METH_O, connect_ex_doc}, +#endif {"detach", (PyCFunction)sock_detach, METH_NOARGS, detach_doc}, {"fileno", (PyCFunction)sock_fileno, METH_NOARGS, @@ -5050,8 +5084,10 @@ static PyMethodDef sock_methods[] = { {"getpeername", (PyCFunction)sock_getpeername, METH_NOARGS, getpeername_doc}, #endif +#ifdef HAVE_GETSOCKNAME {"getsockname", (PyCFunction)sock_getsockname, METH_NOARGS, getsockname_doc}, +#endif {"getsockopt", (PyCFunction)sock_getsockopt, METH_VARARGS, getsockopt_doc}, #if defined(MS_WINDOWS) && defined(SIO_RCVALL) @@ -5062,22 +5098,28 @@ static PyMethodDef sock_methods[] = { {"share", (PyCFunction)sock_share, METH_VARARGS, sock_share_doc}, #endif +#ifdef HAVE_LISTEN {"listen", (PyCFunction)sock_listen, METH_VARARGS, listen_doc}, +#endif {"recv", (PyCFunction)sock_recv, METH_VARARGS, recv_doc}, {"recv_into", _PyCFunction_CAST(sock_recv_into), METH_VARARGS | METH_KEYWORDS, recv_into_doc}, +#ifdef HAVE_RECVFROM {"recvfrom", (PyCFunction)sock_recvfrom, METH_VARARGS, recvfrom_doc}, {"recvfrom_into", _PyCFunction_CAST(sock_recvfrom_into), METH_VARARGS | METH_KEYWORDS, recvfrom_into_doc}, +#endif {"send", (PyCFunction)sock_send, METH_VARARGS, send_doc}, {"sendall", (PyCFunction)sock_sendall, METH_VARARGS, sendall_doc}, +#ifdef HAVE_SENDTO {"sendto", (PyCFunction)sock_sendto, METH_VARARGS, sendto_doc}, +#endif {"setblocking", (PyCFunction)sock_setblocking, METH_O, setblocking_doc}, {"getblocking", (PyCFunction)sock_getblocking, METH_NOARGS, @@ -5086,8 +5128,10 @@ static PyMethodDef sock_methods[] = { settimeout_doc}, {"gettimeout", (PyCFunction)sock_gettimeout, METH_NOARGS, gettimeout_doc}, +#ifdef HAVE_SETSOCKOPT {"setsockopt", (PyCFunction)sock_setsockopt, METH_VARARGS, setsockopt_doc}, +#endif #ifdef HAVE_SHUTDOWN {"shutdown", (PyCFunction)sock_shutdown, METH_O, shutdown_doc}, @@ -5223,6 +5267,16 @@ static int sock_cloexec_works = -1; /*ARGSUSED*/ +#ifndef HAVE_SOCKET +#define socket stub_socket +static int +socket(int domain, int type, int protocol) +{ + errno = ENOTSUP; + return INVALID_SOCKET; +} +#endif + /*[clinic input] _socket.socket.__init__ as sock_initobj family: int = -1 @@ -5309,6 +5363,7 @@ sock_initobj_impl(PySocketSockObject *self, int family, int type, int proto, socklen_t addrlen = sizeof(sock_addr_t); memset(&addrbuf, 0, addrlen); +#ifdef HAVE_GETSOCKNAME if (getsockname(fd, SAS2SA(&addrbuf), &addrlen) == 0) { if (family == -1) { family = SAS2SA(&addrbuf)->sa_family; @@ -5327,6 +5382,7 @@ sock_initobj_impl(PySocketSockObject *self, int family, int type, int proto, return -1; } } +#endif // HAVE_GETSOCKNAME #ifdef SO_TYPE if (type == -1) { int tmp; @@ -5505,6 +5561,7 @@ static PyTypeObject sock_type = { }; +#ifdef HAVE_GETHOSTNAME /* Python interface to gethostname(). */ /*ARGSUSED*/ @@ -5568,6 +5625,7 @@ PyDoc_STRVAR(gethostname_doc, "gethostname() -> string\n\ \n\ Return the current host name."); +#endif #ifdef HAVE_SETHOSTNAME PyDoc_STRVAR(sethostname_doc, @@ -5611,6 +5669,7 @@ extern int sethostname(const char *, size_t); } #endif +#ifdef HAVE_GETADDRINFO /* Python interface to gethostbyname(name). */ /*ARGSUSED*/ @@ -5638,8 +5697,10 @@ PyDoc_STRVAR(gethostbyname_doc, "gethostbyname(host) -> address\n\ \n\ Return the IP address (a string of the form '255.255.255.255') for a host."); +#endif +#if defined(HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYNAME) || defined (HAVE_GETHOSTBYADDR) static PyObject* sock_decode_hostname(const char *name) { @@ -5781,8 +5842,9 @@ gethost_common(struct hostent *h, struct sockaddr *addr, size_t alen, int af) Py_XDECREF(addr_list); return rtn_tuple; } +#endif - +#if defined(HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYNAME) /* Python interface to gethostbyname_ex(name). */ /*ARGSUSED*/ @@ -5855,8 +5917,9 @@ PyDoc_STRVAR(ghbn_ex_doc, \n\ Return the true host name, a list of aliases, and a list of IP addresses,\n\ for a host. The host argument is a string giving a host name or IP number."); +#endif - +#if defined(HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYADDR) /* Python interface to gethostbyaddr(IP). */ /*ARGSUSED*/ @@ -5951,8 +6014,9 @@ PyDoc_STRVAR(gethostbyaddr_doc, \n\ Return the true host name, a list of aliases, and a list of IP addresses,\n\ for a host. The host argument is a string giving a host name or IP number."); +#endif - +#ifdef HAVE_GETSERVBYNAME /* Python interface to getservbyname(name). This only returns the port number, since the other info is already known or not useful (like the list of aliases). */ @@ -5986,8 +6050,9 @@ PyDoc_STRVAR(getservbyname_doc, Return a port number from a service name and protocol name.\n\ The optional protocol name, if given, should be 'tcp' or 'udp',\n\ otherwise any protocol will match."); +#endif - +#ifdef HAVE_GETSERVBYPORT /* Python interface to getservbyport(port). This only returns the service name, since the other info is already known or not useful (like the list of aliases). */ @@ -6028,7 +6093,9 @@ PyDoc_STRVAR(getservbyport_doc, Return the service name from a port number and protocol name.\n\ The optional protocol name, if given, should be 'tcp' or 'udp',\n\ otherwise any protocol will match."); +#endif +#ifdef HAVE_GETPROTOBYNAME /* Python interface to getprotobyname(name). This only returns the protocol number, since the other info is already known or not useful (like the list of aliases). */ @@ -6055,6 +6122,7 @@ PyDoc_STRVAR(getprotobyname_doc, "getprotobyname(name) -> integer\n\ \n\ Return the protocol number for the named protocol. (Rarely used.)"); +#endif static PyObject * socket_close(PyObject *self, PyObject *fdobj) @@ -6424,6 +6492,7 @@ socket_inet_aton(PyObject *self, PyObject *args) #endif } +#ifdef HAVE_INET_NTOA PyDoc_STRVAR(inet_ntoa_doc, "inet_ntoa(packed_ip) -> ip_address_string\n\ \n\ @@ -6452,6 +6521,7 @@ socket_inet_ntoa(PyObject *self, PyObject *args) SUPPRESS_DEPRECATED_CALL return PyUnicode_FromString(inet_ntoa(packed_addr)); } +#endif // HAVE_INET_NTOA #ifdef HAVE_INET_PTON @@ -6563,6 +6633,7 @@ socket_inet_ntop(PyObject *self, PyObject *args) #endif /* HAVE_INET_PTON */ +#ifdef HAVE_GETADDRINFO /* Python interface to getaddrinfo(host, port). */ /*ARGSUSED*/ @@ -6690,7 +6761,9 @@ PyDoc_STRVAR(getaddrinfo_doc, -> list of (family, type, proto, canonname, sockaddr)\n\ \n\ Resolve host and port into addrinfo struct."); +#endif // HAVE_GETADDRINFO +#ifdef HAVE_GETNAMEINFO /* Python interface to getnameinfo(sa, flags). */ /*ARGSUSED*/ @@ -6791,7 +6864,7 @@ PyDoc_STRVAR(getnameinfo_doc, "getnameinfo(sockaddr, flags) --> (host, port)\n\ \n\ Get host and port for a sockaddr."); - +#endif // HAVE_GETNAMEINFO /* Python API to getting and setting the default timeout value. */ @@ -7047,24 +7120,38 @@ range of values."); /* List of functions exported by this module. */ static PyMethodDef socket_methods[] = { +#ifdef HAVE_GETADDRINFO {"gethostbyname", socket_gethostbyname, METH_VARARGS, gethostbyname_doc}, +#endif +#if defined(HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYNAME) {"gethostbyname_ex", socket_gethostbyname_ex, METH_VARARGS, ghbn_ex_doc}, +#endif +#if defined(HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYADDR) {"gethostbyaddr", socket_gethostbyaddr, METH_VARARGS, gethostbyaddr_doc}, +#endif +#ifdef HAVE_GETHOSTNAME {"gethostname", socket_gethostname, METH_NOARGS, gethostname_doc}, +#endif #ifdef HAVE_SETHOSTNAME {"sethostname", socket_sethostname, METH_VARARGS, sethostname_doc}, #endif +#ifdef HAVE_GETSERVBYNAME {"getservbyname", socket_getservbyname, METH_VARARGS, getservbyname_doc}, +#endif +#ifdef HAVE_GETSERVBYPORT {"getservbyport", socket_getservbyport, METH_VARARGS, getservbyport_doc}, +#endif +#ifdef HAVE_GETPROTOBYNAME {"getprotobyname", socket_getprotobyname, METH_VARARGS, getprotobyname_doc}, +#endif {"close", socket_close, METH_O, close_doc}, #ifndef NO_DUP @@ -7085,18 +7172,24 @@ static PyMethodDef socket_methods[] = { METH_O, htonl_doc}, {"inet_aton", socket_inet_aton, METH_VARARGS, inet_aton_doc}, +#ifdef HAVE_INET_NTOA {"inet_ntoa", socket_inet_ntoa, METH_VARARGS, inet_ntoa_doc}, +#endif #ifdef HAVE_INET_PTON {"inet_pton", socket_inet_pton, METH_VARARGS, inet_pton_doc}, {"inet_ntop", socket_inet_ntop, METH_VARARGS, inet_ntop_doc}, #endif +#ifdef HAVE_GETADDRINFO {"getaddrinfo", _PyCFunction_CAST(socket_getaddrinfo), METH_VARARGS | METH_KEYWORDS, getaddrinfo_doc}, +#endif +#ifdef HAVE_GETNAMEINFO {"getnameinfo", socket_getnameinfo, METH_VARARGS, getnameinfo_doc}, +#endif {"getdefaulttimeout", socket_getdefaulttimeout, METH_NOARGS, getdefaulttimeout_doc}, {"setdefaulttimeout", socket_setdefaulttimeout, @@ -7626,7 +7719,9 @@ PyInit__socket(void) /* SOCK_RAW is marked as optional in the POSIX specification */ PyModule_AddIntMacro(m, SOCK_RAW); #endif +#ifdef SOCK_SEQPACKET PyModule_AddIntMacro(m, SOCK_SEQPACKET); +#endif #if defined(SOCK_RDM) PyModule_AddIntMacro(m, SOCK_RDM); #endif @@ -7784,6 +7879,10 @@ PyInit__socket(void) PyModule_AddIntMacro(m, MSG_EOR); #endif #ifdef MSG_TRUNC + // workaround for https://github.com/WebAssembly/wasi-libc/issues/305 + #if defined(__wasi__) && !defined(__WASI_RIFLAGS_RECV_DATA_TRUNCATED) + # define __WASI_RIFLAGS_RECV_DATA_TRUNCATED 2 + #endif PyModule_AddIntMacro(m, MSG_TRUNC); #endif #ifdef MSG_CTRUNC diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c index 2655a0c94bbd95981bb9f40dbc8cac2ba537487a..c409fe968f8894a6337092ff9ba2eb458ade5f8a 100644 --- a/Modules/syslogmodule.c +++ b/Modules/syslogmodule.c @@ -87,6 +87,10 @@ syslog_get_argv(void) } scriptobj = PyList_GetItem(argv, 0); + if (scriptobj == NULL) { + PyErr_Clear(); + return NULL; + } if (!PyUnicode_Check(scriptobj)) { return(NULL); } @@ -96,16 +100,16 @@ syslog_get_argv(void) } slash = PyUnicode_FindChar(scriptobj, SEP, 0, scriptlen, -1); - if (slash == -2) + if (slash == -2) { + PyErr_Clear(); return NULL; + } if (slash != -1) { return PyUnicode_Substring(scriptobj, slash + 1, scriptlen); } else { Py_INCREF(scriptobj); return(scriptobj); } - - return(NULL); } @@ -114,42 +118,41 @@ syslog_openlog(PyObject * self, PyObject * args, PyObject *kwds) { long logopt = 0; long facility = LOG_USER; - PyObject *new_S_ident_o = NULL; + PyObject *ident = NULL; static char *keywords[] = {"ident", "logoption", "facility", 0}; - const char *ident = NULL; + const char *ident_str = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwds, - "|Ull:openlog", keywords, &new_S_ident_o, &logopt, &facility)) + "|Ull:openlog", keywords, &ident, &logopt, &facility)) return NULL; - if (new_S_ident_o) { - Py_INCREF(new_S_ident_o); + if (ident) { + Py_INCREF(ident); } - - /* get sys.argv[0] or NULL if we can't for some reason */ - if (!new_S_ident_o) { - new_S_ident_o = syslog_get_argv(); + else { + /* get sys.argv[0] or NULL if we can't for some reason */ + ident = syslog_get_argv(); } - Py_XDECREF(S_ident_o); - S_ident_o = new_S_ident_o; - - /* At this point, S_ident_o should be INCREF()ed. openlog(3) does not - * make a copy, and syslog(3) later uses it. We can't garbagecollect it + /* At this point, ident should be INCREF()ed. openlog(3) does not + * make a copy, and syslog(3) later uses it. We can't garbagecollect it. * If NULL, just let openlog figure it out (probably using C argv[0]). */ - if (S_ident_o) { - ident = PyUnicode_AsUTF8(S_ident_o); - if (ident == NULL) + if (ident) { + ident_str = PyUnicode_AsUTF8(ident); + if (ident_str == NULL) { + Py_DECREF(ident); return NULL; + } } - - if (PySys_Audit("syslog.openlog", "sll", ident, logopt, facility) < 0) { + if (PySys_Audit("syslog.openlog", "Oll", ident ? ident : Py_None, logopt, facility) < 0) { + Py_DECREF(ident); return NULL; } - openlog(ident, logopt, facility); + openlog(ident_str, logopt, facility); S_log_open = 1; + Py_XSETREF(S_ident_o, ident); Py_RETURN_NONE; } @@ -188,14 +191,26 @@ syslog_syslog(PyObject * self, PyObject * args) */ if ((openargs = PyTuple_New(0))) { PyObject *openlog_ret = syslog_openlog(self, openargs, NULL); - Py_XDECREF(openlog_ret); Py_DECREF(openargs); + if (openlog_ret == NULL) { + return NULL; + } + Py_DECREF(openlog_ret); + } + else { + return NULL; } } + /* Incref ident, because it can be decrefed if syslog.openlog() is + * called when the GIL is released. + */ + PyObject *ident = S_ident_o; + Py_XINCREF(ident); Py_BEGIN_ALLOW_THREADS; syslog(priority, "%s", message); Py_END_ALLOW_THREADS; + Py_XDECREF(ident); Py_RETURN_NONE; } @@ -355,4 +370,4 @@ PyMODINIT_FUNC PyInit_syslog(void) { return PyModuleDef_Init(&syslogmodule); -} \ No newline at end of file +} diff --git a/Modules/xxlimited.c b/Modules/xxlimited.c index 5177ecd6b515d71da5f9369c9ecea9f18f8996de..e234504e3319459e437ca2b2001c4ad1964b47f4 100644 --- a/Modules/xxlimited.c +++ b/Modules/xxlimited.c @@ -138,6 +138,7 @@ Xxo_finalize(PyObject *self_obj) static void Xxo_dealloc(PyObject *self) { + PyObject_GC_UnTrack(self); Xxo_finalize(self); PyTypeObject *tp = Py_TYPE(self); freefunc free = PyType_GetSlot(tp, Py_tp_free); diff --git a/Objects/accu.c b/Objects/accu.c deleted file mode 100644 index c8b5d382e388b76fd6ead7b7c25ea3a0dde11b1d..0000000000000000000000000000000000000000 --- a/Objects/accu.c +++ /dev/null @@ -1,115 +0,0 @@ -/* Accumulator struct implementation */ - -#include "Python.h" -#include "pycore_accu.h" - -static PyObject * -join_list_unicode(PyObject *lst) -{ - /* return ''.join(lst) */ - PyObject *sep, *ret; - sep = PyUnicode_FromStringAndSize("", 0); - ret = PyUnicode_Join(sep, lst); - Py_DECREF(sep); - return ret; -} - -int -_PyAccu_Init(_PyAccu *acc) -{ - /* Lazily allocated */ - acc->large = NULL; - acc->small = PyList_New(0); - if (acc->small == NULL) - return -1; - return 0; -} - -static int -flush_accumulator(_PyAccu *acc) -{ - Py_ssize_t nsmall = PyList_GET_SIZE(acc->small); - if (nsmall) { - int ret; - PyObject *joined; - if (acc->large == NULL) { - acc->large = PyList_New(0); - if (acc->large == NULL) - return -1; - } - joined = join_list_unicode(acc->small); - if (joined == NULL) - return -1; - if (PyList_SetSlice(acc->small, 0, nsmall, NULL)) { - Py_DECREF(joined); - return -1; - } - ret = PyList_Append(acc->large, joined); - Py_DECREF(joined); - return ret; - } - return 0; -} - -int -_PyAccu_Accumulate(_PyAccu *acc, PyObject *unicode) -{ - Py_ssize_t nsmall; - assert(PyUnicode_Check(unicode)); - - if (PyList_Append(acc->small, unicode)) - return -1; - nsmall = PyList_GET_SIZE(acc->small); - /* Each item in a list of unicode objects has an overhead (in 64-bit - * builds) of: - * - 8 bytes for the list slot - * - 56 bytes for the header of the unicode object - * that is, 64 bytes. 100000 such objects waste more than 6 MiB - * compared to a single concatenated string. - */ - if (nsmall < 100000) - return 0; - return flush_accumulator(acc); -} - -PyObject * -_PyAccu_FinishAsList(_PyAccu *acc) -{ - int ret; - PyObject *res; - - ret = flush_accumulator(acc); - Py_CLEAR(acc->small); - if (ret) { - Py_CLEAR(acc->large); - return NULL; - } - res = acc->large; - acc->large = NULL; - return res; -} - -PyObject * -_PyAccu_Finish(_PyAccu *acc) -{ - PyObject *list, *res; - if (acc->large == NULL) { - list = acc->small; - acc->small = NULL; - } - else { - list = _PyAccu_FinishAsList(acc); - if (!list) - return NULL; - } - res = join_list_unicode(list); - Py_DECREF(list); - return res; -} - -void -_PyAccu_Destroy(_PyAccu *acc) -{ - Py_CLEAR(acc->small); - Py_CLEAR(acc->large); -} diff --git a/Objects/boolobject.c b/Objects/boolobject.c index ff7218760ab361f11c23fb272a16b3b680bb28f2..8a20e368d4a42bc65a69e7fb9a4e7bb06996e286 100644 --- a/Objects/boolobject.c +++ b/Objects/boolobject.c @@ -9,7 +9,8 @@ static PyObject * bool_repr(PyObject *self) { - return self == Py_True ? &_Py_ID(True) : &_Py_ID(False); + PyObject *res = self == Py_True ? &_Py_ID(True) : &_Py_ID(False); + return Py_NewRef(res); } /* Function to return a bool from a C long */ diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index d0179626414874e04b6022372d0722f287376c37..b2962fd137d93efec76826e0245352188e75842d 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -563,22 +563,28 @@ bytearray_setslice(PyByteArrayObject *self, Py_ssize_t lo, Py_ssize_t hi, static int bytearray_setitem(PyByteArrayObject *self, Py_ssize_t i, PyObject *value) { - int ival; + int ival = -1; - if (i < 0) + // GH-91153: We need to do this *before* the size check, in case value has a + // nasty __index__ method that changes the size of the bytearray: + if (value && !_getbytevalue(value, &ival)) { + return -1; + } + + if (i < 0) { i += Py_SIZE(self); + } if (i < 0 || i >= Py_SIZE(self)) { PyErr_SetString(PyExc_IndexError, "bytearray index out of range"); return -1; } - if (value == NULL) + if (value == NULL) { return bytearray_setslice(self, i, i+1, NULL); + } - if (!_getbytevalue(value, &ival)) - return -1; - + assert(0 <= ival && ival < 256); PyByteArray_AS_STRING(self)[i] = ival; return 0; } @@ -593,11 +599,21 @@ bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *valu if (_PyIndex_Check(index)) { Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) + if (i == -1 && PyErr_Occurred()) { return -1; + } - if (i < 0) + int ival = -1; + + // GH-91153: We need to do this *before* the size check, in case values + // has a nasty __index__ method that changes the size of the bytearray: + if (values && !_getbytevalue(values, &ival)) { + return -1; + } + + if (i < 0) { i += PyByteArray_GET_SIZE(self); + } if (i < 0 || i >= Py_SIZE(self)) { PyErr_SetString(PyExc_IndexError, "bytearray index out of range"); @@ -612,9 +628,7 @@ bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *valu slicelen = 1; } else { - int ival; - if (!_getbytevalue(values, &ival)) - return -1; + assert(0 <= ival && ival < 256); buf[i] = (char)ival; return 0; } diff --git a/Objects/codeobject.c b/Objects/codeobject.c index d4fa0e38aed629adc7ad3c2012308afc75c63da1..2f757c4d8a9868759e6a4854b1598fd4ce2b0108 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -971,6 +971,7 @@ PyCode_Addr2Location(PyCodeObject *co, int addrq, if (addrq < 0) { *start_line = *end_line = co->co_firstlineno; *start_column = *end_column = 0; + return 1; } assert(addrq >= 0 && addrq < _PyCode_NBYTES(co)); PyCodeAddressRange bounds; @@ -1417,7 +1418,7 @@ deopt_code(_Py_CODEUNIT *instructions, Py_ssize_t len) { for (int i = 0; i < len; i++) { _Py_CODEUNIT instruction = instructions[i]; - int opcode = _PyOpcode_Original[_Py_OPCODE(instruction)]; + int opcode = _PyOpcode_Deopt[_Py_OPCODE(instruction)]; int caches = _PyOpcode_Caches[opcode]; instructions[i] = _Py_MAKECODEUNIT(opcode, _Py_OPARG(instruction)); while (caches--) { diff --git a/Objects/dictobject.c b/Objects/dictobject.c index ebbd22ee7c145ead02dd50741df1e5ce1908d348..25e191fb8eadbe8568943ec70099c6901f1399af 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -5583,6 +5583,35 @@ _PyObject_FreeInstanceAttributes(PyObject *self) free_values(*values_ptr); } +int +_PyObject_VisitManagedDict(PyObject *self, visitproc visit, void *arg) +{ + PyTypeObject *tp = Py_TYPE(self); + if((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) { + return 0; + } + assert(tp->tp_dictoffset); + int err = _PyObject_VisitInstanceAttributes(self, visit, arg); + if (err) { + return err; + } + Py_VISIT(*_PyObject_ManagedDictPointer(self)); + return 0; +} + + +void +_PyObject_ClearManagedDict(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + if((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) { + return; + } + _PyObject_FreeInstanceAttributes(self); + *_PyObject_ValuesPointer(self) = NULL; + Py_CLEAR(*_PyObject_ManagedDictPointer(self)); +} + PyObject * PyObject_GenericGetDict(PyObject *obj, void *context) { diff --git a/Objects/exceptions.c b/Objects/exceptions.c index e212e02352efb37e57a792c442598206b9788926..c56886870d3c8d948328da67e17a2c4bfd3b5e3d 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -600,17 +600,9 @@ StopIteration_traverse(PyStopIterationObject *self, visitproc visit, void *arg) return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); } -ComplexExtendsException( - PyExc_Exception, /* base */ - StopIteration, /* name */ - StopIteration, /* prefix for *_init, etc */ - 0, /* new */ - 0, /* methods */ - StopIteration_members, /* members */ - 0, /* getset */ - 0, /* str */ - "Signal the end from iterator.__next__()." -); +ComplexExtendsException(PyExc_Exception, StopIteration, StopIteration, + 0, 0, StopIteration_members, 0, 0, + "Signal the end from iterator.__next__()."); /* @@ -1114,6 +1106,7 @@ exceptiongroup_split_recursive(PyObject *exc, assert(PyList_CheckExact(match_list)); if (PyList_Append(match_list, rec_result.match) < 0) { Py_DECREF(rec_result.match); + Py_XDECREF(rec_result.rest); goto done; } Py_DECREF(rec_result.match); @@ -3222,6 +3215,7 @@ MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) self = state->memerrors_freelist; self->args = PyTuple_New(0); /* This shouldn't happen since the empty tuple is persistent */ + if (self->args == NULL) { return NULL; } @@ -3237,6 +3231,8 @@ MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void MemoryError_dealloc(PyBaseExceptionObject *self) { + _PyObject_GC_UNTRACK(self); + BaseException_clear(self); /* If this is a subclass of MemoryError, we don't need to @@ -3246,8 +3242,6 @@ MemoryError_dealloc(PyBaseExceptionObject *self) return; } - _PyObject_GC_UNTRACK(self); - struct _Py_exc_state *state = get_exc_state(); if (state->memerrors_numfree >= MEMERRORS_SAVE) { Py_TYPE(self)->tp_free((PyObject *)self); @@ -3564,8 +3558,7 @@ _PyExc_InitTypes(PyInterpreterState *interp) for (size_t i=0; i < Py_ARRAY_LENGTH(static_exceptions); i++) { PyTypeObject *exc = static_exceptions[i].exc; - - if (PyType_Ready(exc) < 0) { + if (_PyStaticType_InitBuiltin(exc) < 0) { return -1; } } diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 47d308b8eb3702b03d760509a07d53452e96b2c7..4b1b24f2e702a471becec5a9621ac00ff3d68b28 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -1992,7 +1992,8 @@ _PyFloat_InitTypes(PyInterpreterState *interp) /* Init float info */ if (FloatInfoType.tp_name == NULL) { - if (PyStructSequence_InitType2(&FloatInfoType, &floatinfo_desc) < 0) { + if (_PyStructSequence_InitBuiltin(&FloatInfoType, + &floatinfo_desc) < 0) { return _PyStatus_ERR("can't init float info type"); } } diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 6f4de65cc7c0d0f77b572b8ea58825c8f6681fd8..26b38bae780c70e7ed8f6b03971aa234ae6c6f19 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -138,6 +138,7 @@ typedef enum kind { Except = 2, Object = 3, Null = 4, + Lasti = 5, } Kind; static int @@ -162,6 +163,8 @@ compatible_kind(Kind from, Kind to) { #define MAX_STACK_ENTRIES (63/BITS_PER_BLOCK) #define WILL_OVERFLOW (1ULL<<((MAX_STACK_ENTRIES-1)*BITS_PER_BLOCK)) +#define EMPTY_STACK 0 + static inline int64_t push_value(int64_t stack, Kind kind) { @@ -179,12 +182,97 @@ pop_value(int64_t stack) return Py_ARITHMETIC_RIGHT_SHIFT(int64_t, stack, BITS_PER_BLOCK); } +#define MASK ((1<<BITS_PER_BLOCK)-1) + static inline Kind top_of_stack(int64_t stack) { - return stack & ((1<<BITS_PER_BLOCK)-1); + return stack & MASK; +} + +static inline Kind +peek(int64_t stack, int n) +{ + assert(n >= 1); + return (stack>>(BITS_PER_BLOCK*(n-1))) & MASK; +} + +static Kind +stack_swap(int64_t stack, int n) +{ + assert(n >= 1); + Kind to_swap = peek(stack, n); + Kind top = top_of_stack(stack); + int shift = BITS_PER_BLOCK*(n-1); + int64_t replaced_low = (stack & ~(MASK << shift)) | (top << shift); + int64_t replaced_top = (replaced_low & ~MASK) | to_swap; + return replaced_top; +} + +static int64_t +pop_to_level(int64_t stack, int level) { + if (level == 0) { + return EMPTY_STACK; + } + int64_t max_item = (1<<BITS_PER_BLOCK) - 1; + int64_t level_max_stack = max_item << ((level-1) * BITS_PER_BLOCK); + while (stack > level_max_stack) { + stack = pop_value(stack); + } + return stack; +} + +#if 0 +/* These functions are useful for debugging the stack marking code */ + +static char +tos_char(int64_t stack) { + switch(top_of_stack(stack)) { + case Iterator: + return 'I'; + case Except: + return 'E'; + case Object: + return 'O'; + case Lasti: + return 'L'; + case Null: + return 'N'; + } + return '?'; +} + +static void +print_stack(int64_t stack) { + if (stack < 0) { + if (stack == UNINITIALIZED) { + printf("---"); + } + else if (stack == OVERFLOWED) { + printf("OVERFLOWED"); + } + else { + printf("??"); + } + return; + } + while (stack) { + printf("%c", tos_char(stack)); + stack = pop_value(stack); + } } +static void +print_stacks(int64_t *stacks, int n) { + for (int i = 0; i < n; i++) { + printf("%d: ", i); + print_stack(stacks[i]); + printf("\n"); + } +} + +#endif + static int64_t * mark_stacks(PyCodeObject *code_obj, int len) { @@ -204,7 +292,7 @@ mark_stacks(PyCodeObject *code_obj, int len) for (int i = 1; i <= len; i++) { stacks[i] = UNINITIALIZED; } - stacks[0] = 0; + stacks[0] = EMPTY_STACK; if (code_obj->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) { // Generators get sent None while starting: @@ -213,6 +301,7 @@ mark_stacks(PyCodeObject *code_obj, int len) int todo = 1; while (todo) { todo = 0; + /* Scan instructions */ for (i = 0; i < len; i++) { int64_t next_stack = stacks[i]; if (next_stack == UNINITIALIZED) { @@ -230,11 +319,15 @@ mark_stacks(PyCodeObject *code_obj, int len) int64_t target_stack; int j = get_arg(code, i); if (opcode == POP_JUMP_FORWARD_IF_FALSE || - opcode == POP_JUMP_FORWARD_IF_TRUE) { + opcode == POP_JUMP_FORWARD_IF_TRUE || + opcode == JUMP_IF_FALSE_OR_POP || + opcode == JUMP_IF_TRUE_OR_POP) + { j += i + 1; } - else if (opcode == POP_JUMP_BACKWARD_IF_FALSE || - opcode == POP_JUMP_BACKWARD_IF_TRUE) { + else { + assert(opcode == POP_JUMP_BACKWARD_IF_FALSE || + opcode == POP_JUMP_BACKWARD_IF_TRUE); j = i + 1 - j; } assert(j < len); @@ -296,23 +389,26 @@ mark_stacks(PyCodeObject *code_obj, int len) break; } case END_ASYNC_FOR: - next_stack = pop_value(pop_value(pop_value(next_stack))); + next_stack = pop_value(pop_value(next_stack)); stacks[i+1] = next_stack; break; case PUSH_EXC_INFO: + next_stack = push_value(next_stack, Except); + stacks[i+1] = next_stack; + break; case POP_EXCEPT: - /* These instructions only appear in exception handlers, which - * skip this switch ever since the move to zero-cost exceptions - * (their stack remains UNINITIALIZED because nothing sets it). - * - * Note that explain_incompatible_stack interprets an - * UNINITIALIZED stack as belonging to an exception handler. - */ - Py_UNREACHABLE(); + assert(top_of_stack(next_stack) == Except); + next_stack = pop_value(next_stack); + stacks[i+1] = next_stack; break; case RETURN_VALUE: + assert(pop_value(next_stack) == EMPTY_STACK); + assert(top_of_stack(next_stack) == Object); + break; case RAISE_VARARGS: + break; case RERAISE: + assert(top_of_stack(next_stack) == Except); /* End of block */ break; case PUSH_NULL: @@ -331,6 +427,7 @@ mark_stacks(PyCodeObject *code_obj, int len) } case LOAD_ATTR: { + assert(top_of_stack(next_stack) == Object); int j = get_arg(code, i); if (j & 1) { next_stack = pop_value(next_stack); @@ -340,9 +437,34 @@ mark_stacks(PyCodeObject *code_obj, int len) stacks[i+1] = next_stack; break; } + case CALL: + { + int args = get_arg(code, i); + for (int j = 0; j < args+2; j++) { + next_stack = pop_value(next_stack); + } + next_stack = push_value(next_stack, Object); + stacks[i+1] = next_stack; + break; + } + case SWAP: + { + int n = get_arg(code, i); + next_stack = stack_swap(next_stack, n); + stacks[i+1] = next_stack; + break; + } + case COPY: + { + int n = get_arg(code, i); + next_stack = push_value(next_stack, peek(next_stack, n)); + stacks[i+1] = next_stack; + break; + } default: { - int delta = PyCompile_OpcodeStackEffect(opcode, _Py_OPARG(code[i])); + int delta = PyCompile_OpcodeStackEffect(opcode, get_arg(code, i)); + assert(delta != PY_INVALID_STACK_EFFECT); while (delta < 0) { next_stack = pop_value(next_stack); delta++; @@ -355,6 +477,34 @@ mark_stacks(PyCodeObject *code_obj, int len) } } } + /* Scan exception table */ + unsigned char *start = (unsigned char *)PyBytes_AS_STRING(code_obj->co_exceptiontable); + unsigned char *end = start + PyBytes_GET_SIZE(code_obj->co_exceptiontable); + unsigned char *scan = start; + while (scan < end) { + int start_offset, size, handler; + scan = parse_varint(scan, &start_offset); + assert(start_offset >= 0 && start_offset < len); + scan = parse_varint(scan, &size); + assert(size >= 0 && start_offset+size <= len); + scan = parse_varint(scan, &handler); + assert(handler >= 0 && handler < len); + int depth_and_lasti; + scan = parse_varint(scan, &depth_and_lasti); + int level = depth_and_lasti >> 1; + int lasti = depth_and_lasti & 1; + if (stacks[start_offset] != UNINITIALIZED) { + if (stacks[handler] == UNINITIALIZED) { + todo = 1; + uint64_t target_stack = pop_to_level(stacks[start_offset], level); + if (lasti) { + target_stack = push_value(target_stack, Lasti); + } + target_stack = push_value(target_stack, Except); + stacks[handler] = target_stack; + } + } + } } Py_DECREF(co_code); return stacks; @@ -395,6 +545,8 @@ explain_incompatible_stack(int64_t to_stack) switch(target_kind) { case Except: return "can't jump into an 'except' block as there's no exception"; + case Lasti: + return "can't jump into a re-raising block as there's no location"; case Object: case Null: return "incompatible stacks"; @@ -446,13 +598,6 @@ first_line_not_before(int *lines, int len, int line) return result; } -static void -frame_stack_pop(PyFrameObject *f) -{ - PyObject *v = _PyFrame_StackPop(f->f_frame); - Py_XDECREF(v); -} - static PyFrameState _PyFrame_GetState(PyFrameObject *frame) { @@ -493,7 +638,8 @@ add_load_fast_null_checks(PyCodeObject *co) int changed = 0; _Py_CODEUNIT *instructions = _PyCode_CODE(co); for (Py_ssize_t i = 0; i < Py_SIZE(co); i++) { - switch (_Py_OPCODE(instructions[i])) { + int opcode = _Py_OPCODE(instructions[i]); + switch (opcode) { case LOAD_FAST: case LOAD_FAST__LOAD_FAST: case LOAD_FAST__LOAD_CONST: @@ -509,6 +655,7 @@ add_load_fast_null_checks(PyCodeObject *co) _Py_SET_OPCODE(instructions[i], STORE_FAST); break; } + i += _PyOpcode_Caches[_PyOpcode_Deopt[opcode]]; } if (changed) { // invalidate cached co_code object @@ -650,7 +797,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore msg = "stack to deep to analyze"; } else if (start_stack == UNINITIALIZED) { - msg = "can't jump from within an exception handler"; + msg = "can't jump from unreachable code"; } else { msg = explain_incompatible_stack(target_stack); @@ -670,7 +817,20 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore start_stack = pop_value(start_stack); } while (start_stack > best_stack) { - frame_stack_pop(f); + if (top_of_stack(start_stack) == Except) { + /* Pop exception stack as well as the evaluation stack */ + PyThreadState *tstate = _PyThreadState_GET(); + _PyErr_StackItem *exc_info = tstate->exc_info; + PyObject *value = exc_info->exc_value; + PyObject *exc = _PyFrame_StackPop(f->f_frame); + assert(PyExceptionInstance_Check(exc) || exc == Py_None); + exc_info->exc_value = exc; + Py_XDECREF(value); + } + else { + PyObject *v = _PyFrame_StackPop(f->f_frame); + Py_XDECREF(v); + } start_stack = pop_value(start_stack); } /* Finally set the new lasti and return OK. */ diff --git a/Objects/listobject.c b/Objects/listobject.c index 83dfb7da01dfc3b7ea79e63ce290662834b38b60..9afa68f9fe100cf7dbe74646603cc04583edb694 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -551,47 +551,41 @@ list_concat(PyListObject *a, PyObject *bb) static PyObject * list_repeat(PyListObject *a, Py_ssize_t n) { - Py_ssize_t size; - PyListObject *np; - if (n < 0) - n = 0; - if (n > 0 && Py_SIZE(a) > PY_SSIZE_T_MAX / n) - return PyErr_NoMemory(); - size = Py_SIZE(a) * n; - if (size == 0) + const Py_ssize_t input_size = Py_SIZE(a); + if (input_size == 0 || n <= 0) return PyList_New(0); - np = (PyListObject *) list_new_prealloc(size); + assert(n > 0); + + if (input_size > PY_SSIZE_T_MAX / n) + return PyErr_NoMemory(); + Py_ssize_t output_size = input_size * n; + + PyListObject *np = (PyListObject *) list_new_prealloc(output_size); if (np == NULL) return NULL; + PyObject **dest = np->ob_item; - PyObject **dest_end = dest + size; - if (Py_SIZE(a) == 1) { + if (input_size == 1) { PyObject *elem = a->ob_item[0]; - Py_SET_REFCNT(elem, Py_REFCNT(elem) + n); -#ifdef Py_REF_DEBUG - _Py_RefTotal += n; -#endif + _Py_RefcntAdd(elem, n); + PyObject **dest_end = dest + output_size; while (dest < dest_end) { *dest++ = elem; } } else { PyObject **src = a->ob_item; - PyObject **src_end = src + Py_SIZE(a); + PyObject **src_end = src + input_size; while (src < src_end) { - Py_SET_REFCNT(*src, Py_REFCNT(*src) + n); -#ifdef Py_REF_DEBUG - _Py_RefTotal += n; -#endif - *dest++ = *src++; - } - // Now src chases after dest in the same buffer - src = np->ob_item; - while (dest < dest_end) { + _Py_RefcntAdd(*src, n); *dest++ = *src++; } + + _Py_memory_repeat((char *)np->ob_item, sizeof(PyObject *)*output_size, + sizeof(PyObject *)*input_size); } - Py_SET_SIZE(np, size); + + Py_SET_SIZE(np, output_size); return (PyObject *) np; } @@ -743,12 +737,8 @@ PyList_SetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v) static PyObject * list_inplace_repeat(PyListObject *self, Py_ssize_t n) { - PyObject **items; - Py_ssize_t size, i, j, p; - - - size = PyList_GET_SIZE(self); - if (size == 0 || n == 1) { + Py_ssize_t input_size = PyList_GET_SIZE(self); + if (input_size == 0 || n == 1) { Py_INCREF(self); return (PyObject *)self; } @@ -759,22 +749,21 @@ list_inplace_repeat(PyListObject *self, Py_ssize_t n) return (PyObject *)self; } - if (size > PY_SSIZE_T_MAX / n) { + if (input_size > PY_SSIZE_T_MAX / n) { return PyErr_NoMemory(); } + Py_ssize_t output_size = input_size * n; - if (list_resize(self, size*n) < 0) + if (list_resize(self, output_size) < 0) return NULL; - p = size; - items = self->ob_item; - for (i = 1; i < n; i++) { /* Start counting at 1, not 0 */ - for (j = 0; j < size; j++) { - PyObject *o = items[j]; - Py_INCREF(o); - items[p++] = o; - } + PyObject **items = self->ob_item; + for (Py_ssize_t j = 0; j < input_size; j++) { + _Py_RefcntAdd(items[j], n-1); } + _Py_memory_repeat((char *)items, sizeof(PyObject *)*output_size, + sizeof(PyObject *)*input_size); + Py_INCREF(self); return (PyObject *)self; } @@ -1226,13 +1215,6 @@ struct s_MergeState { * of tuples. It may be set to safe_object_compare, but the idea is that hopefully * we can assume more, and use one of the special-case compares. */ int (*tuple_elem_compare)(PyObject *, PyObject *, MergeState *); - - /* Used by unsafe_tuple_compare to record whether the very first tuple - * elements resolved the last comparison attempt. If so, next time a - * method that may avoid PyObject_RichCompareBool() entirely is tried. - * 0 for false, 1 for true. - */ - int first_tuple_items_resolved_it; }; /* binarysort is the best method for sorting small arrays: it does @@ -2205,24 +2187,7 @@ unsafe_float_compare(PyObject *v, PyObject *w, MergeState *ms) * using the same pre-sort check as we use for ms->key_compare, * but run on the list [x[0] for x in L]. This allows us to optimize compares * on two levels (as long as [x[0] for x in L] is type-homogeneous.) The idea is - * that most tuple compares don't involve x[1:]. - * However, that may not be right. When it is right, we can win by calling the - * relatively cheap ms->tuple_elem_compare on the first pair of elements, to - * see whether v[0] < w[0] or w[0] < v[0]. If either are so, we're done. - * Else we proceed as in the tuple compare, comparing the remaining pairs via - * the probably more expensive PyObject_RichCompareBool(..., Py_EQ) until (if - * ever) that says "no, not equal!". Then, if we're still on the first pair, - * ms->tuple_elem_compare can resolve it, else PyObject_RichCompareBool(..., - * Py_LT) finishes the job. - * In any case, ms->first_tuple_items_resolved_it keeps track of whether the - * most recent tuple comparison was resolved by the first pair. If so, the - * next attempt starts by trying the cheap tests on the first pair again, else - * PyObject_RichCompareBool(..., Py_EQ) is used from the start. - * There are cases where PyObject_RichCompareBool(..., Py_EQ) is much cheaper! - * For example, that can return "almost immediately" if passed the same - * object twice (it special-cases object identity for Py_EQ), which can, - * potentially, be unboundedly faster than ms->tuple_elem_compare. - */ + * that most tuple compares don't involve x[1:]. */ static int unsafe_tuple_compare(PyObject *v, PyObject *w, MergeState *ms) { @@ -2238,52 +2203,26 @@ unsafe_tuple_compare(PyObject *v, PyObject *w, MergeState *ms) vt = (PyTupleObject *)v; wt = (PyTupleObject *)w; - i = 0; - if (ms->first_tuple_items_resolved_it) { - /* See whether fast compares of the first elements settle it. */ - k = ms->tuple_elem_compare(vt->ob_item[0], wt->ob_item[0], ms); - if (k) /* error, or v < w */ - return k; - k = ms->tuple_elem_compare(wt->ob_item[0], vt->ob_item[0], ms); - if (k > 0) /* w < v */ - return 0; - if (k < 0) /* error */ - return -1; - /* We have - * not (v[0] < w[0]) and not (w[0] < v[0]) - * which implies, for a total order, that the first elements are - * equal. So skip them in the loop. - */ - i = 1; - ms->first_tuple_items_resolved_it = 0; - } - /* Now first_tuple_items_resolved_it was 0 on entry, or was forced to 0 - * at the end of the `if` block just above. - */ - assert(! ms->first_tuple_items_resolved_it); vlen = Py_SIZE(vt); wlen = Py_SIZE(wt); - for (; i < vlen && i < wlen; i++) { + + for (i = 0; i < vlen && i < wlen; i++) { k = PyObject_RichCompareBool(vt->ob_item[i], wt->ob_item[i], Py_EQ); - if (!k) { /* not equal */ - if (i) { - return PyObject_RichCompareBool(vt->ob_item[i], wt->ob_item[i], - Py_LT); - } - else { - ms->first_tuple_items_resolved_it = 1; - return ms->tuple_elem_compare(vt->ob_item[0], wt->ob_item[0], - ms); - } - } if (k < 0) return -1; + if (!k) + break; } - /* all equal until we fell off the end */ - return vlen < wlen; - } + if (i >= vlen || i >= wlen) + return vlen < wlen; + + if (i == 0) + return ms->tuple_elem_compare(vt->ob_item[i], wt->ob_item[i], ms); + else + return PyObject_RichCompareBool(vt->ob_item[i], wt->ob_item[i], Py_LT); +} /* An adaptive, stable, natural mergesort. See listsort.txt. * Returns Py_None on success, NULL on error. Even in case of error, the @@ -2466,7 +2405,6 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse) } ms.key_compare = unsafe_tuple_compare; - ms.first_tuple_items_resolved_it = 1; /* be optimistic */ } } /* End of pre-sort check: ms is now set properly! */ diff --git a/Objects/longobject.c b/Objects/longobject.c index 4a1e5caf5a284392ee8c40c4dabd046d6193abbd..90ed02b8c27a19853c2ba6f9119eeee12a59377f 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -6135,7 +6135,7 @@ _PyLong_InitTypes(PyInterpreterState *interp) /* initialize int_info */ if (Int_InfoType.tp_name == NULL) { - if (PyStructSequence_InitType2(&Int_InfoType, &int_info_desc) < 0) { + if (_PyStructSequence_InitBuiltin(&Int_InfoType, &int_info_desc) < 0) { return _PyStatus_ERR("can't init int info type"); } } diff --git a/Objects/object.c b/Objects/object.c index 75aee909a3b4965414245badb44ae79ce92fa042..758b79eff5b3e30eac8579f1e4613bc5312a3701 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1975,8 +1975,8 @@ _PyTypes_InitTypes(PyInterpreterState *interp) // All other static types (unless initialized elsewhere) for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) { PyTypeObject *type = static_types[i]; - if (PyType_Ready(type) < 0) { - return _PyStatus_ERR("Can't initialize types"); + if (_PyStaticType_InitBuiltin(type) < 0) { + return _PyStatus_ERR("Can't initialize builtin type"); } if (type == &PyType_Type) { // Sanitify checks of the two most important types diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 78a6f01a0964ed08db3a69a4b49aded15eb10593..1d487d8e807a22ad46a00a85ff0e30ef05483094 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -1446,7 +1446,7 @@ static arena_map_bot_t arena_map_root; /* Return a pointer to a bottom tree node, return NULL if it doesn't exist or * it cannot be created */ -static arena_map_bot_t * +static Py_ALWAYS_INLINE arena_map_bot_t * arena_map_get(block *p, int create) { #ifdef USE_INTERIOR_NODES diff --git a/Objects/structseq.c b/Objects/structseq.c index 229e3d893ff6aa871c9a3569c8e4af0cd98bab1e..24cd0e705969b20c4a239ab926b3e6d8a716af32 100644 --- a/Objects/structseq.c +++ b/Objects/structseq.c @@ -432,11 +432,21 @@ initialize_structseq_dict(PyStructSequence_Desc *desc, PyObject* dict, return -1; } -static void -initialize_members(PyStructSequence_Desc *desc, PyMemberDef* members, - Py_ssize_t n_members) { - Py_ssize_t i, k; +static PyMemberDef * +initialize_members(PyStructSequence_Desc *desc, + Py_ssize_t *pn_members, Py_ssize_t *pn_unnamed_members) +{ + PyMemberDef *members; + Py_ssize_t n_members, n_unnamed_members; + + n_members = count_members(desc, &n_unnamed_members); + members = PyMem_NEW(PyMemberDef, n_members - n_unnamed_members + 1); + if (members == NULL) { + PyErr_NoMemory(); + return NULL; + } + Py_ssize_t i, k; for (i = k = 0; i < n_members; ++i) { if (desc->fields[i].name == PyStructSequence_UnnamedField) { continue; @@ -453,30 +463,17 @@ initialize_members(PyStructSequence_Desc *desc, PyMemberDef* members, k++; } members[k].name = NULL; + + *pn_members = n_members; + *pn_unnamed_members = n_unnamed_members; + return members; } -int -_PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc, - unsigned long tp_flags) +static void +initialize_static_fields(PyTypeObject *type, PyStructSequence_Desc *desc, + PyMemberDef *tp_members, unsigned long tp_flags) { - PyMemberDef *members; - Py_ssize_t n_members, n_unnamed_members; - -#ifdef Py_TRACE_REFS - /* if the type object was chained, unchain it first - before overwriting its storage */ - if (type->ob_base.ob_base._ob_next) { - _Py_ForgetReference((PyObject *)type); - } -#endif - - /* PyTypeObject has already been initialized */ - if (Py_REFCNT(type) != 0) { - PyErr_BadInternalCall(); - return -1; - } - type->tp_name = desc->name; type->tp_basicsize = sizeof(PyStructSequence) - sizeof(PyObject *); type->tp_itemsize = sizeof(PyObject *); @@ -488,25 +485,20 @@ _PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc, type->tp_new = structseq_new; type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | tp_flags; type->tp_traverse = (traverseproc) structseq_traverse; + type->tp_members = tp_members; +} - n_members = count_members(desc, &n_unnamed_members); - members = PyMem_NEW(PyMemberDef, n_members - n_unnamed_members + 1); - if (members == NULL) { - PyErr_NoMemory(); - return -1; - } - initialize_members(desc, members, n_members); - type->tp_members = members; - +static int +initialize_static_type(PyTypeObject *type, PyStructSequence_Desc *desc, + Py_ssize_t n_members, Py_ssize_t n_unnamed_members) { + /* initialize_static_fields() should have been called already. */ if (PyType_Ready(type) < 0) { - PyMem_Free(members); return -1; } Py_INCREF(type); if (initialize_structseq_dict( desc, type->tp_dict, n_members, n_unnamed_members) < 0) { - PyMem_Free(members); Py_DECREF(type); return -1; } @@ -514,10 +506,63 @@ _PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc, return 0; } +int +_PyStructSequence_InitBuiltinWithFlags(PyTypeObject *type, + PyStructSequence_Desc *desc, + unsigned long tp_flags) +{ + PyMemberDef *members; + Py_ssize_t n_members, n_unnamed_members; + + members = initialize_members(desc, &n_members, &n_unnamed_members); + if (members == NULL) { + return -1; + } + initialize_static_fields(type, desc, members, tp_flags); + if (_PyStaticType_InitBuiltin(type) < 0) { + PyMem_Free(members); + PyErr_Format(PyExc_RuntimeError, + "Can't initialize builtin type %s", + desc->name); + return -1; + } + if (initialize_static_type(type, desc, n_members, n_unnamed_members) < 0) { + PyMem_Free(members); + return -1; + } + return 0; +} + int PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc) { - return _PyStructSequence_InitType(type, desc, 0); + PyMemberDef *members; + Py_ssize_t n_members, n_unnamed_members; + +#ifdef Py_TRACE_REFS + /* if the type object was chained, unchain it first + before overwriting its storage */ + if (type->ob_base.ob_base._ob_next) { + _Py_ForgetReference((PyObject *)type); + } +#endif + + /* PyTypeObject has already been initialized */ + if (Py_REFCNT(type) != 0) { + PyErr_BadInternalCall(); + return -1; + } + + members = initialize_members(desc, &n_members, &n_unnamed_members); + if (members == NULL) { + return -1; + } + initialize_static_fields(type, desc, members, 0); + if (initialize_static_type(type, desc, n_members, n_unnamed_members) < 0) { + PyMem_Free(members); + return -1; + } + return 0; } void @@ -569,13 +614,10 @@ _PyStructSequence_NewType(PyStructSequence_Desc *desc, unsigned long tp_flags) Py_ssize_t n_members, n_unnamed_members; /* Initialize MemberDefs */ - n_members = count_members(desc, &n_unnamed_members); - members = PyMem_NEW(PyMemberDef, n_members - n_unnamed_members + 1); + members = initialize_members(desc, &n_members, &n_unnamed_members); if (members == NULL) { - PyErr_NoMemory(); return NULL; } - initialize_members(desc, members, n_members); /* Initialize Slots */ slots[0] = (PyType_Slot){Py_tp_dealloc, (destructor)structseq_dealloc}; diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index dfb8597b876e5cbe67486d9895b09c7b18d73289..240af0a90752717fe8c733e106292f80ff5cded2 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -495,9 +495,8 @@ tupleconcat(PyTupleObject *a, PyObject *bb) static PyObject * tuplerepeat(PyTupleObject *a, Py_ssize_t n) { - Py_ssize_t size; - PyTupleObject *np; - if (Py_SIZE(a) == 0 || n == 1) { + const Py_ssize_t input_size = Py_SIZE(a); + if (input_size == 0 || n == 1) { if (PyTuple_CheckExact(a)) { /* Since tuples are immutable, we can return a shared copy in this case */ @@ -505,42 +504,38 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n) return (PyObject *)a; } } - if (Py_SIZE(a) == 0 || n <= 0) { + if (input_size == 0 || n <= 0) { return tuple_get_empty(); } - if (n > PY_SSIZE_T_MAX / Py_SIZE(a)) + assert(n>0); + + if (input_size > PY_SSIZE_T_MAX / n) return PyErr_NoMemory(); - size = Py_SIZE(a) * n; - np = tuple_alloc(size); + Py_ssize_t output_size = input_size * n; + + PyTupleObject *np = tuple_alloc(output_size); if (np == NULL) return NULL; + PyObject **dest = np->ob_item; - PyObject **dest_end = dest + size; - if (Py_SIZE(a) == 1) { + if (input_size == 1) { PyObject *elem = a->ob_item[0]; - Py_SET_REFCNT(elem, Py_REFCNT(elem) + n); -#ifdef Py_REF_DEBUG - _Py_RefTotal += n; -#endif + _Py_RefcntAdd(elem, n); + PyObject **dest_end = dest + output_size; while (dest < dest_end) { *dest++ = elem; } } else { PyObject **src = a->ob_item; - PyObject **src_end = src + Py_SIZE(a); + PyObject **src_end = src + input_size; while (src < src_end) { - Py_SET_REFCNT(*src, Py_REFCNT(*src) + n); -#ifdef Py_REF_DEBUG - _Py_RefTotal += n; -#endif - *dest++ = *src++; - } - // Now src chases after dest in the same buffer - src = np->ob_item; - while (dest < dest_end) { + _Py_RefcntAdd(*src, n); *dest++ = *src++; } + + _Py_memory_repeat((char *)np->ob_item, sizeof(PyObject *)*output_size, + sizeof(PyObject *)*input_size); } _PyObject_GC_TRACK(np); return (PyObject *) np; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 5ebff6084f4a9726fd460886f6bcc329dc1c48b6..e4adf1c4e12f8ccccd3a2bef7046cfa2109d6c6f 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -65,6 +65,93 @@ lookup_maybe_method(PyObject *self, PyObject *attr, int *unbound); static int slot_tp_setattro(PyObject *self, PyObject *name, PyObject *value); +static inline PyTypeObject * subclass_from_ref(PyObject *ref); + + +/* helpers for for static builtin types */ + +static inline int +static_builtin_index_is_set(PyTypeObject *self) +{ + return self->tp_static_builtin_index > 0; +} + +static inline size_t +static_builtin_index_get(PyTypeObject *self) +{ + assert(static_builtin_index_is_set(self)); + /* We store a 1-based index so 0 can mean "not initialized". */ + return self->tp_static_builtin_index - 1; +} + +static inline void +static_builtin_index_set(PyTypeObject *self, size_t index) +{ + assert(index < _Py_MAX_STATIC_BUILTIN_TYPES); + /* We store a 1-based index so 0 can mean "not initialized". */ + self->tp_static_builtin_index = index + 1; +} + +static inline void +static_builtin_index_clear(PyTypeObject *self) +{ + self->tp_static_builtin_index = 0; +} + +static inline static_builtin_state * +static_builtin_state_get(PyInterpreterState *interp, PyTypeObject *self) +{ + return &(interp->types.builtins[static_builtin_index_get(self)]); +} + +/* For static types we store some state in an array on each interpreter. */ +static_builtin_state * +_PyStaticType_GetState(PyTypeObject *self) +{ + assert(self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN); + PyInterpreterState *interp = _PyInterpreterState_GET(); + return static_builtin_state_get(interp, self); +} + +static void +static_builtin_state_init(PyTypeObject *self) +{ + /* Set the type's per-interpreter state. */ + PyInterpreterState *interp = _PyInterpreterState_GET(); + + /* It should only be called once for each builtin type. */ + assert(!static_builtin_index_is_set(self)); + + static_builtin_index_set(self, interp->types.num_builtins_initialized); + interp->types.num_builtins_initialized++; + + static_builtin_state *state = static_builtin_state_get(interp, self); + state->type = self; + /* state->tp_weaklist is left NULL until insert_head() or insert_after() + (in weakrefobject.c) sets it. */ +} + +static void +static_builtin_state_clear(PyTypeObject *self) +{ + /* Reset the type's per-interpreter state. + This basically undoes what static_builtin_state_init() did. */ + PyInterpreterState *interp = _PyInterpreterState_GET(); + + static_builtin_state *state = static_builtin_state_get(interp, self); + state->type = NULL; + assert(state->tp_weaklist == NULL); // It was already cleared out. + static_builtin_index_clear(self); + + assert(interp->types.num_builtins_initialized > 0); + interp->types.num_builtins_initialized--; +} + +// Also see _PyStaticType_InitBuiltin() and _PyStaticType_Dealloc(). + +/* end static builtin helpers */ + + /* * finds the beginning of the docstring's introspection signature. * if present, returns a pointer pointing to the first '('. @@ -204,7 +291,7 @@ static struct type_cache* get_type_cache(void) { PyInterpreterState *interp = _PyInterpreterState_GET(); - return &interp->type_cache; + return &interp->types.type_cache; } @@ -223,7 +310,7 @@ type_cache_clear(struct type_cache *cache, PyObject *value) void _PyType_InitCache(PyInterpreterState *interp) { - struct type_cache *cache = &interp->type_cache; + struct type_cache *cache = &interp->types.type_cache; for (Py_ssize_t i = 0; i < (1 << MCACHE_SIZE_EXP); i++) { struct type_cache_entry *entry = &cache->hashtable[i]; assert(entry->name == NULL); @@ -240,7 +327,7 @@ _PyType_InitCache(PyInterpreterState *interp) static unsigned int _PyType_ClearCache(PyInterpreterState *interp) { - struct type_cache *cache = &interp->type_cache; + struct type_cache *cache = &interp->types.type_cache; #if MCACHE_STATS size_t total = cache->hits + cache->collisions + cache->misses; fprintf(stderr, "-- Method cache hits = %zd (%d%%)\n", @@ -272,11 +359,17 @@ PyType_ClearCache(void) void _PyTypes_Fini(PyInterpreterState *interp) { - struct type_cache *cache = &interp->type_cache; + struct type_cache *cache = &interp->types.type_cache; type_cache_clear(cache, NULL); if (_Py_IsMainInterpreter(interp)) { clear_slotdefs(); } + + assert(interp->types.num_builtins_initialized == 0); + // All the static builtin types should have been finalized already. + for (size_t i = 0; i < _Py_MAX_STATIC_BUILTIN_TYPES; i++) { + assert(interp->types.builtins[i].type == NULL); + } } @@ -309,12 +402,11 @@ PyType_Modified(PyTypeObject *type) Py_ssize_t i = 0; PyObject *ref; while (PyDict_Next(subclasses, &i, NULL, &ref)) { - assert(PyWeakref_CheckRef(ref)); - PyObject *obj = PyWeakref_GET_OBJECT(ref); - if (obj == Py_None) { + PyTypeObject *subclass = subclass_from_ref(ref); // borrowed + if (subclass == NULL) { continue; } - PyType_Modified(_PyType_CAST(obj)); + PyType_Modified(subclass); } } @@ -413,6 +505,8 @@ static PyMemberDef type_members[] = { {"__basicsize__", T_PYSSIZET, offsetof(PyTypeObject,tp_basicsize),READONLY}, {"__itemsize__", T_PYSSIZET, offsetof(PyTypeObject, tp_itemsize), READONLY}, {"__flags__", T_ULONG, offsetof(PyTypeObject, tp_flags), READONLY}, + /* Note that this value is misleading for static builtin types, + since the memory at this offset will always be NULL. */ {"__weakrefoffset__", T_PYSSIZET, offsetof(PyTypeObject, tp_weaklistoffset), READONLY}, {"__base__", T_OBJECT, offsetof(PyTypeObject, tp_base), READONLY}, @@ -4211,23 +4305,50 @@ type_dealloc_common(PyTypeObject *type) } -void -_PyStaticType_Dealloc(PyTypeObject *type) +static void +clear_static_tp_subclasses(PyTypeObject *type) { - // If a type still has subtypes, it cannot be deallocated. - // A subtype can inherit attributes and methods of its parent type, - // and a type must no longer be used once it's deallocated. - if (type->tp_subclasses != NULL) { + if (type->tp_subclasses == NULL) { return; } + /* Normally it would be a problem to finalize the type if its + tp_subclasses wasn't cleared first. However, this is only + ever called at the end of runtime finalization, so we can be + more liberal in cleaning up. If the given type still has + subtypes at this point then some extension module did not + correctly finalize its objects. + + We can safely obliterate such subtypes since the extension + module and its objects won't be used again, except maybe if + the runtime were re-initialized. In that case the sticky + situation would only happen if the module were re-imported + then and only if the subtype were stored in a global and only + if that global were not overwritten during import. We'd be + fine since the extension is otherwise unsafe and unsupported + in that situation, and likely problematic already. + + In any case, this situation means at least some memory is + going to leak. This mostly only affects embedding scenarios. + */ + + // For now we just clear tp_subclasses. + + Py_CLEAR(type->tp_subclasses); +} + +void +_PyStaticType_Dealloc(PyTypeObject *type) +{ + assert(!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)); + type_dealloc_common(type); Py_CLEAR(type->tp_dict); Py_CLEAR(type->tp_bases); Py_CLEAR(type->tp_mro); Py_CLEAR(type->tp_cache); - // type->tp_subclasses is NULL + clear_static_tp_subclasses(type); // PyObject_ClearWeakRefs() raises an exception if Py_REFCNT() != 0 if (Py_REFCNT(type) == 0) { @@ -4235,6 +4356,12 @@ _PyStaticType_Dealloc(PyTypeObject *type) } type->tp_flags &= ~Py_TPFLAGS_READY; + + if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) { + _PyStaticType_ClearWeakRefs(type); + static_builtin_state_clear(type); + /* We leave _Py_TPFLAGS_STATIC_BUILTIN set on tp_flags. */ + } } @@ -4296,14 +4423,12 @@ _PyType_GetSubclasses(PyTypeObject *self) Py_ssize_t i = 0; PyObject *ref; // borrowed ref while (PyDict_Next(subclasses, &i, NULL, &ref)) { - assert(PyWeakref_CheckRef(ref)); - PyObject *obj = PyWeakref_GET_OBJECT(ref); // borrowed ref - if (obj == Py_None) { + PyTypeObject *subclass = subclass_from_ref(ref); // borrowed + if (subclass == NULL) { continue; } - assert(PyType_Check(obj)); - if (PyList_Append(list, obj) < 0) { + if (PyList_Append(list, _PyObject_CAST(subclass)) < 0) { Py_DECREF(list); return NULL; } @@ -6650,6 +6775,20 @@ PyType_Ready(PyTypeObject *type) return 0; } +int +_PyStaticType_InitBuiltin(PyTypeObject *self) +{ + self->tp_flags = self->tp_flags | _Py_TPFLAGS_STATIC_BUILTIN; + + static_builtin_state_init(self); + + int res = PyType_Ready(self); + if (res < 0) { + static_builtin_state_clear(self); + } + return res; +} + static int add_subclass(PyTypeObject *base, PyTypeObject *type) @@ -6700,6 +6839,42 @@ add_all_subclasses(PyTypeObject *type, PyObject *bases) return res; } +static inline PyTypeObject * +subclass_from_ref(PyObject *ref) +{ + assert(PyWeakref_CheckRef(ref)); + PyObject *obj = PyWeakref_GET_OBJECT(ref); // borrowed ref + assert(obj != NULL); + if (obj == Py_None) { + return NULL; + } + assert(PyType_Check(obj)); + return _PyType_CAST(obj); +} + +static PyObject * +get_subclasses_key(PyTypeObject *type, PyTypeObject *base) +{ + PyObject *key = PyLong_FromVoidPtr((void *) type); + if (key != NULL) { + return key; + } + PyErr_Clear(); + + /* This basically means we're out of memory. + We fall back to manually traversing the values. */ + Py_ssize_t i = 0; + PyObject *ref; // borrowed ref + while (PyDict_Next((PyObject *)base->tp_subclasses, &i, &key, &ref)) { + PyTypeObject *subclass = subclass_from_ref(ref); // borrowed + if (subclass == type) { + return Py_NewRef(key); + } + } + /* It wasn't found. */ + return NULL; +} + static void remove_subclass(PyTypeObject *base, PyTypeObject *type) { @@ -6709,8 +6884,8 @@ remove_subclass(PyTypeObject *base, PyTypeObject *type) } assert(PyDict_CheckExact(subclasses)); - PyObject *key = PyLong_FromVoidPtr((void *) type); - if (key == NULL || PyDict_DelItem(subclasses, key)) { + PyObject *key = get_subclasses_key(type, base); + if (key != NULL && PyDict_DelItem(subclasses, key)) { /* This can happen if the type initialization errored out before the base subclasses were updated (e.g. a non-str __qualname__ was passed in the type dict). */ @@ -8803,13 +8978,10 @@ recurse_down_subclasses(PyTypeObject *type, PyObject *attr_name, Py_ssize_t i = 0; PyObject *ref; while (PyDict_Next(subclasses, &i, NULL, &ref)) { - assert(PyWeakref_CheckRef(ref)); - PyObject *obj = PyWeakref_GET_OBJECT(ref); - assert(obj != NULL); - if (obj == Py_None) { + PyTypeObject *subclass = subclass_from_ref(ref); // borrowed + if (subclass == NULL) { continue; } - PyTypeObject *subclass = _PyType_CAST(obj); /* Avoid recursing down into unaffected classes */ PyObject *dict = subclass->tp_dict; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 669ffe70727468ce3c60c1f82d393c9a43cc816b..ad16ada16fe3bde8926f246f8a00ea2af8ffa9bb 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -2843,7 +2843,7 @@ PyUnicode_AsWideCharString(PyObject *unicode, } buflen = unicode_get_widechar_size(unicode); - buffer = (wchar_t *) PyMem_NEW(wchar_t, (buflen + 1)); + buffer = (wchar_t *) PyMem_New(wchar_t, (buflen + 1)); if (buffer == NULL) { PyErr_NoMemory(); return NULL; @@ -14604,13 +14604,13 @@ _PyUnicode_InitTypes(PyInterpreterState *interp) return _PyStatus_OK(); } - if (PyType_Ready(&EncodingMapType) < 0) { + if (_PyStaticType_InitBuiltin(&EncodingMapType) < 0) { goto error; } - if (PyType_Ready(&PyFieldNameIter_Type) < 0) { + if (_PyStaticType_InitBuiltin(&PyFieldNameIter_Type) < 0) { goto error; } - if (PyType_Ready(&PyFormatterIter_Type) < 0) { + if (_PyStaticType_InitBuiltin(&PyFormatterIter_Type) < 0) { goto error; } return _PyStatus_OK(); diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c index 2b4361e63ca4133dda4240585bd91d68818acd9c..cf89a9231d204d760a5b48176dc7c0d25db8dd20 100644 --- a/Objects/weakrefobject.c +++ b/Objects/weakrefobject.c @@ -558,6 +558,7 @@ proxy_bool(PyWeakReference *proxy) static void proxy_dealloc(PyWeakReference *self) { + PyObject_GC_UnTrack(self); if (self->wr_callback != NULL) PyObject_GC_UnTrack((PyObject *)self); clear_weakref(self); @@ -1018,3 +1019,22 @@ PyObject_ClearWeakRefs(PyObject *object) PyErr_Restore(err_type, err_value, err_tb); } } + +/* This function is called by _PyStaticType_Dealloc() to clear weak references. + * + * This is called at the end of runtime finalization, so we can just + * wipe out the type's weaklist. We don't bother with callbacks + * or anything else. + */ +void +_PyStaticType_ClearWeakRefs(PyTypeObject *type) +{ + static_builtin_state *state = _PyStaticType_GetState(type); + PyObject **list = _PyStaticType_GET_WEAKREFS_LISTPTR(state); + while (*list != NULL) { + /* Note that clear_weakref() pops the first ref off the type's + weaklist before clearing its wr_object and wr_callback. + That is how we're able to loop over the list. */ + clear_weakref((PyWeakReference *)*list); + } +} diff --git a/PC/launcher.c b/PC/launcher.c index de7abeb4e86abdcc153e4a5ef2263291962311b7..da566a180168c5d80104e68b3595f140c4ba989f 100644 --- a/PC/launcher.c +++ b/PC/launcher.c @@ -1926,27 +1926,35 @@ process(int argc, wchar_t ** argv) if (!cch) { error(0, L"Cannot determine memory for home path"); } - cch += (DWORD)wcslen(PYTHON_EXECUTABLE) + 1 + 1; /* include sep and null */ + cch += (DWORD)wcslen(PYTHON_EXECUTABLE) + 4; /* include sep, null and quotes */ executable = (wchar_t *)malloc(cch * sizeof(wchar_t)); if (executable == NULL) { error(RC_NO_MEMORY, L"A memory allocation failed"); } - cch_actual = MultiByteToWideChar(CP_UTF8, 0, start, len, executable, cch); + /* start with a quote - we'll skip this ahead, but want it for the final string */ + executable[0] = L'"'; + cch_actual = MultiByteToWideChar(CP_UTF8, 0, start, len, &executable[1], cch - 1); if (!cch_actual) { error(RC_BAD_VENV_CFG, L"Cannot decode home path in '%ls'", venv_cfg_path); } + cch_actual += 1; /* account for the first quote */ + executable[cch_actual] = L'\0'; if (executable[cch_actual - 1] != L'\\') { executable[cch_actual++] = L'\\'; executable[cch_actual] = L'\0'; } - if (wcscat_s(executable, cch, PYTHON_EXECUTABLE)) { + if (wcscat_s(&executable[1], cch - 1, PYTHON_EXECUTABLE)) { error(RC_BAD_VENV_CFG, L"Cannot create executable path from '%ls'", venv_cfg_path); } - if (GetFileAttributesW(executable) == INVALID_FILE_ATTRIBUTES) { + /* there's no trailing quote, so we only have to skip one character for the test */ + if (GetFileAttributesW(&executable[1]) == INVALID_FILE_ATTRIBUTES) { error(RC_NO_PYTHON, L"No Python at '%ls'", executable); } + /* now append the final quote */ + wcscat_s(executable, cch, L"\""); + /* smuggle our original path through */ if (!SetEnvironmentVariableW(L"__PYVENV_LAUNCHER__", argv0)) { error(0, L"Failed to set launcher environment"); } diff --git a/PC/launcher2.c b/PC/launcher2.c index ae11f4f024a9040ad991c90e0f136fdef1ad14c3..033218ee2f408e7f0e0c88758c4191db3da7e3b1 100644 --- a/PC/launcher2.c +++ b/PC/launcher2.c @@ -580,6 +580,9 @@ parseCommandLine(SearchInfo *search) break; } } + if (tail == search->originalCmdLine && tail[0] == L'"') { + ++tail; + } // Without special cases, we can now fill in the search struct int tailLen = (int)(end ? (end - tail) : wcsnlen_s(tail, MAXLEN)); search->executableLength = -1; @@ -758,7 +761,7 @@ _readIni(const wchar_t *section, const wchar_t *settingName, wchar_t *buffer, in n = GetPrivateProfileStringW(section, settingName, NULL, buffer, bufferLength, iniPath); if (n) { debug(L"# Found %s in %s\n", settingName, iniPath); - return true; + return n; } else if (GetLastError() == ERROR_FILE_NOT_FOUND) { debug(L"# Did not find file %s\n", iniPath); } else { @@ -874,7 +877,9 @@ checkShebang(SearchInfo *search) while (--bytesRead > 0 && *++b != '\r' && *b != '\n') { } wchar_t *shebang; int shebangLength; - int exitCode = _decodeShebang(search, start, (int)(b - start + 1), onlyUtf8, &shebang, &shebangLength); + // We add 1 when bytesRead==0, as in that case we hit EOF and b points + // to the last character in the file, not the newline + int exitCode = _decodeShebang(search, start, (int)(b - start + (bytesRead == 0)), onlyUtf8, &shebang, &shebangLength); if (exitCode) { return exitCode; } @@ -941,13 +946,17 @@ checkDefaults(SearchInfo *search) // If tag is only a major version number, expand it from the environment // or an ini file - const wchar_t *settingName = NULL; + const wchar_t *iniSettingName = NULL; + const wchar_t *envSettingName = NULL; if (!search->tag || !search->tagLength) { - settingName = L"py_python"; + iniSettingName = L"python"; + envSettingName = L"py_python"; } else if (0 == wcsncmp(search->tag, L"3", search->tagLength)) { - settingName = L"py_python3"; + iniSettingName = L"python3"; + envSettingName = L"py_python3"; } else if (0 == wcsncmp(search->tag, L"2", search->tagLength)) { - settingName = L"py_python2"; + iniSettingName = L"python2"; + envSettingName = L"py_python2"; } else { debug(L"# Cannot select defaults for tag '%.*s'\n", search->tagLength, search->tag); return 0; @@ -955,11 +964,11 @@ checkDefaults(SearchInfo *search) // First, try to read an environment variable wchar_t buffer[MAXLEN]; - int n = GetEnvironmentVariableW(settingName, buffer, MAXLEN); + int n = GetEnvironmentVariableW(envSettingName, buffer, MAXLEN); // If none found, check in our two .ini files instead if (!n) { - n = _readIni(L"defaults", settingName, buffer, MAXLEN); + n = _readIni(L"defaults", iniSettingName, buffer, MAXLEN); } if (n) { diff --git a/PC/pyconfig.h b/PC/pyconfig.h index 87d55fa07e51e380d0710937834f2653b0e0ba02..1a33d4c5a1e4fcf982698073bde678415ac0302c 100644 --- a/PC/pyconfig.h +++ b/PC/pyconfig.h @@ -675,8 +675,28 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ /* Define to 1 if you have the `erfc' function. */ #define HAVE_ERFC 1 -/* Define if you have the 'inet_pton' function. */ +// netdb.h functions (provided by winsock.h) +#define HAVE_GETHOSTNAME 1 +#define HAVE_GETHOSTBYADDR 1 +#define HAVE_GETHOSTBYNAME 1 +#define HAVE_GETPROTOBYNAME 1 +#define HAVE_GETSERVBYNAME 1 +#define HAVE_GETSERVBYPORT 1 +// sys/socket.h functions (provided by winsock.h) #define HAVE_INET_PTON 1 +#define HAVE_INET_NTOA 1 +#define HAVE_ACCEPT 1 +#define HAVE_BIND 1 +#define HAVE_CONNECT 1 +#define HAVE_GETSOCKNAME 1 +#define HAVE_LISTEN 1 +#define HAVE_RECVFROM 1 +#define HAVE_SENDTO 1 +#define HAVE_SETSOCKOPT 1 +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the `dup' function. */ +#define HAVE_DUP 1 /* framework name */ #define _PYTHONFRAMEWORK "" diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index 0a74f5850a1e8e1d9bb2bc27d37afb15eb18283f..5821c3d9e4d8600ce08ea99601b5e3883e619679 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -120,7 +120,6 @@ <ClCompile Include="..\Modules\_io\textio.c" /> <ClCompile Include="..\Modules\_io\winconsoleio.c" /> <ClCompile Include="..\Objects\abstract.c" /> - <ClCompile Include="..\Objects\accu.c" /> <ClCompile Include="..\Objects\boolobject.c" /> <ClCompile Include="..\Objects\bytearrayobject.c" /> <ClCompile Include="..\Objects\bytes_methods.c" /> diff --git a/PCbuild/_freeze_module.vcxproj.filters b/PCbuild/_freeze_module.vcxproj.filters index d107849c856213cb566c95d0ef25c664db620415..b657f56e28f248b6a3f4a626540747a9f8a63164 100644 --- a/PCbuild/_freeze_module.vcxproj.filters +++ b/PCbuild/_freeze_module.vcxproj.filters @@ -25,9 +25,6 @@ <ClCompile Include="..\Objects\abstract.c"> <Filter>Source Files</Filter> </ClCompile> - <ClCompile Include="..\Objects\accu.c"> - <Filter>Source Files</Filter> - </ClCompile> <ClCompile Include="..\Python\asdl.c"> <Filter>Source Files</Filter> </ClCompile> @@ -476,4 +473,4 @@ </None> <!-- END frozen modules --> </ItemGroup> -</Project> \ No newline at end of file +</Project> diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props index df3efc631d154f3aa028a7cfd578dd5226d574c6..e398b333572e9d20f8e9758a6e92b6122fd7e39c 100644 --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -229,7 +229,7 @@ public override bool Execute() { </Target> <Target Name="FindPythonForBuild" Condition="$(PythonForBuild) == ''"> - <Exec Command="$(MSBuildThisFileDirectory)\find_python.bat -q" + <Exec Command=""$(MSBuildThisFileDirectory)\find_python.bat" -q" EchoOff="true" ConsoleToMsBuild="true"> <Output TaskParameter="ConsoleOutput" ItemName="_CmdExeLines" /> diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index b5b4fce142b1eb5735fc8af4632f24bc179979da..3ff4be518724852d5234d708c43c64b9ad688ff9 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -193,7 +193,6 @@ <ClInclude Include="..\Include\frameobject.h" /> <ClInclude Include="..\Include\import.h" /> <ClInclude Include="..\Include\internal\pycore_abstract.h" /> - <ClInclude Include="..\Include\internal\pycore_accu.h" /> <ClInclude Include="..\Include\internal\pycore_asdl.h" /> <ClInclude Include="..\Include\internal\pycore_ast.h" /> <ClInclude Include="..\Include\internal\pycore_ast_state.h" /> @@ -422,7 +421,6 @@ <ClCompile Include="..\Modules\cjkcodecs\multibytecodec.c" /> <ClCompile Include="..\Modules\_winapi.c" /> <ClCompile Include="..\Objects\abstract.c" /> - <ClCompile Include="..\Objects\accu.c" /> <ClCompile Include="..\Objects\boolobject.c" /> <ClCompile Include="..\Objects\bytearrayobject.c" /> <ClCompile Include="..\Objects\bytes_methods.c" /> diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 774b4b5b2e2e47b9f70a0e99299f530f782fbe69..64d248dfafd81ee192d294c418c925998218c738 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -486,9 +486,6 @@ <ClInclude Include="..\Include\internal\pycore_abstract.h"> <Filter>Include\internal</Filter> </ClInclude> - <ClInclude Include="..\Include\internal\pycore_accu.h"> - <Filter>Include\internal</Filter> - </ClInclude> <ClInclude Include="..\Include\internal\pycore_asdl.h"> <Filter>Include\internal</Filter> </ClInclude> diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index bf391a3ae16533e388467151d1b297da23262267..13dd44ca0cdc3f650b794e67b5f264a17b13b684 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1112,6 +1112,8 @@ def visitModule(self, mod): for dfn in mod.dfns: self.visit(dfn) self.file.write(textwrap.dedent(''' + state->recursion_depth = 0; + state->recursion_limit = 0; state->initialized = 1; return 1; } @@ -1259,8 +1261,14 @@ def func_begin(self, name): self.emit('if (!o) {', 1) self.emit("Py_RETURN_NONE;", 2) self.emit("}", 1) + self.emit("if (++state->recursion_depth > state->recursion_limit) {", 1) + self.emit("PyErr_SetString(PyExc_RecursionError,", 2) + self.emit('"maximum recursion depth exceeded during ast construction");', 3) + self.emit("return 0;", 2) + self.emit("}", 1) def func_end(self): + self.emit("state->recursion_depth--;", 1) self.emit("return result;", 1) self.emit("failed:", 0) self.emit("Py_XDECREF(value);", 1) @@ -1371,7 +1379,32 @@ class PartingShots(StaticVisitor): if (state == NULL) { return NULL; } - return ast2obj_mod(state, t); + + int recursion_limit = Py_GetRecursionLimit(); + int starting_recursion_depth; + /* Be careful here to prevent overflow. */ + int COMPILER_STACK_FRAME_SCALE = 3; + PyThreadState *tstate = _PyThreadState_GET(); + if (!tstate) { + return 0; + } + state->recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? + recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit; + int recursion_depth = tstate->recursion_limit - tstate->recursion_remaining; + starting_recursion_depth = (recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? + recursion_depth * COMPILER_STACK_FRAME_SCALE : recursion_depth; + state->recursion_depth = starting_recursion_depth; + + PyObject *result = ast2obj_mod(state, t); + + /* Check that the recursion depth counting balanced correctly */ + if (result && state->recursion_depth != starting_recursion_depth) { + PyErr_Format(PyExc_SystemError, + "AST constructor recursion depth mismatch (before=%d, after=%d)", + starting_recursion_depth, state->recursion_depth); + return 0; + } + return result; } /* mode is 0 for "exec", 1 for "eval" and 2 for "single" input */ @@ -1437,6 +1470,8 @@ def visit(self, object): def generate_ast_state(module_state, f): f.write('struct ast_state {\n') f.write(' int initialized;\n') + f.write(' int recursion_depth;\n') + f.write(' int recursion_limit;\n') for s in module_state: f.write(' PyObject *' + s + ';\n') f.write('};') diff --git a/Parser/parser.c b/Parser/parser.c index 3d59d4a704c2397d9a316c90e20f243d3d344453..f4082aba56a2726e2312d709b1d583476f796c95 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -6515,7 +6515,7 @@ with_stmt_rule(Parser *p) UNUSED(_end_lineno); // Only used by EXTRA macro int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro - _res = _PyAST_With ( a , b , NULL , EXTRA ); + _res = CHECK_VERSION ( stmt_ty , 9 , "Parenthesized context managers are" , _PyAST_With ( a , b , NULL , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; p->level--; @@ -11223,7 +11223,7 @@ assignment_expression_rule(Parser *p) UNUSED(_end_lineno); // Only used by EXTRA macro int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro - _res = _PyAST_NamedExpr ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , b , EXTRA ); + _res = CHECK_VERSION ( expr_ty , 8 , "Assignment expressions are" , _PyAST_NamedExpr ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , b , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; p->level--; diff --git a/Parser/pegen.c b/Parser/pegen.c index dbf105aedcf427a464482bdc5d3421a97d36847d..31e3ec05a105304b7e6244b55ff3437be342deb1 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -738,7 +738,7 @@ _PyPegen_Parser_New(struct tok_state *tok, int start_rule, int flags, return (Parser *) PyErr_NoMemory(); } p->tokens[0] = PyMem_Calloc(1, sizeof(Token)); - if (!p->tokens) { + if (!p->tokens[0]) { PyMem_Free(p->tokens); PyMem_Free(p); return (Parser *) PyErr_NoMemory(); diff --git a/Parser/pegen_errors.c b/Parser/pegen_errors.c index 5703088443eded68bf436e8acaf374ea04071168..c87d50abd2c71a0b5579ef2fbcde9902b354b315 100644 --- a/Parser/pegen_errors.c +++ b/Parser/pegen_errors.c @@ -245,7 +245,7 @@ get_error_line_from_tokenizer_buffers(Parser *p, Py_ssize_t lineno) * (multi-line) statement are stored in p->tok->interactive_src_start. * If not, we're parsing from a string, which means that the whole source * is stored in p->tok->str. */ - assert((p->tok->fp == NULL && p->tok->str != NULL) || p->tok->fp == stdin); + assert((p->tok->fp == NULL && p->tok->str != NULL) || p->tok->fp != NULL); char *cur_line = p->tok->fp_interactive ? p->tok->interactive_src_start : p->tok->str; if (cur_line == NULL) { diff --git a/Parser/string_parser.c b/Parser/string_parser.c index 984c05d39c1a1735dddbe783d39ed01fd4ffd302..9bc3b082136be53a6ae0068af91cc353cd1f4e49 100644 --- a/Parser/string_parser.c +++ b/Parser/string_parser.c @@ -326,6 +326,9 @@ fstring_find_expr_location(Token *parent, const char* expr_start, char *expr_str start--; } *p_cols += (int)(expr_start - start); + if (*start == '\n') { + *p_cols -= 1; + } } /* adjust the start based on the number of newlines encountered before the f-string expression */ @@ -416,7 +419,7 @@ fstring_compile_expr(Parser *p, const char *expr_start, const char *expr_end, NULL, p->arena); p2->starting_lineno = t->lineno + lines; - p2->starting_col_offset = t->col_offset + cols; + p2->starting_col_offset = lines != 0 ? cols : t->col_offset + cols; expr = _PyPegen_run_parser(p2); diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 542e46968ce564c1140e5bf2c19fdcf8e5c26763..6b43d5340301463d9f69823e0659adfd8607a5b9 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -368,6 +368,8 @@ static int test_bpo20891(void) PyThread_free_lock(lock); + Py_Finalize(); + return 0; } diff --git a/Python/Python-ast.c b/Python/Python-ast.c index e52a72d43bcbd84ff37ead7d678b52b0e1becfd8..f485af675ccff7536779794c8c9a4d7463fdeb90 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -1851,6 +1851,8 @@ init_types(struct ast_state *state) "TypeIgnore(int lineno, string tag)"); if (!state->TypeIgnore_type) return 0; + state->recursion_depth = 0; + state->recursion_limit = 0; state->initialized = 1; return 1; } @@ -3610,6 +3612,11 @@ ast2obj_mod(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } + if (++state->recursion_depth > state->recursion_limit) { + PyErr_SetString(PyExc_RecursionError, + "maximum recursion depth exceeded during ast construction"); + return 0; + } switch (o->kind) { case Module_kind: tp = (PyTypeObject *)state->Module_type; @@ -3665,6 +3672,7 @@ ast2obj_mod(struct ast_state *state, void* _o) Py_DECREF(value); break; } + state->recursion_depth--; return result; failed: Py_XDECREF(value); @@ -3681,6 +3689,11 @@ ast2obj_stmt(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } + if (++state->recursion_depth > state->recursion_limit) { + PyErr_SetString(PyExc_RecursionError, + "maximum recursion depth exceeded during ast construction"); + return 0; + } switch (o->kind) { case FunctionDef_kind: tp = (PyTypeObject *)state->FunctionDef_type; @@ -4224,6 +4237,7 @@ ast2obj_stmt(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->end_col_offset, value) < 0) goto failed; Py_DECREF(value); + state->recursion_depth--; return result; failed: Py_XDECREF(value); @@ -4240,6 +4254,11 @@ ast2obj_expr(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } + if (++state->recursion_depth > state->recursion_limit) { + PyErr_SetString(PyExc_RecursionError, + "maximum recursion depth exceeded during ast construction"); + return 0; + } switch (o->kind) { case BoolOp_kind: tp = (PyTypeObject *)state->BoolOp_type; @@ -4701,6 +4720,7 @@ ast2obj_expr(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->end_col_offset, value) < 0) goto failed; Py_DECREF(value); + state->recursion_depth--; return result; failed: Py_XDECREF(value); @@ -4843,6 +4863,11 @@ ast2obj_comprehension(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } + if (++state->recursion_depth > state->recursion_limit) { + PyErr_SetString(PyExc_RecursionError, + "maximum recursion depth exceeded during ast construction"); + return 0; + } tp = (PyTypeObject *)state->comprehension_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) return NULL; @@ -4866,6 +4891,7 @@ ast2obj_comprehension(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->is_async, value) == -1) goto failed; Py_DECREF(value); + state->recursion_depth--; return result; failed: Py_XDECREF(value); @@ -4882,6 +4908,11 @@ ast2obj_excepthandler(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } + if (++state->recursion_depth > state->recursion_limit) { + PyErr_SetString(PyExc_RecursionError, + "maximum recursion depth exceeded during ast construction"); + return 0; + } switch (o->kind) { case ExceptHandler_kind: tp = (PyTypeObject *)state->ExceptHandler_type; @@ -4925,6 +4956,7 @@ ast2obj_excepthandler(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->end_col_offset, value) < 0) goto failed; Py_DECREF(value); + state->recursion_depth--; return result; failed: Py_XDECREF(value); @@ -4941,6 +4973,11 @@ ast2obj_arguments(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } + if (++state->recursion_depth > state->recursion_limit) { + PyErr_SetString(PyExc_RecursionError, + "maximum recursion depth exceeded during ast construction"); + return 0; + } tp = (PyTypeObject *)state->arguments_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) return NULL; @@ -4979,6 +5016,7 @@ ast2obj_arguments(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->defaults, value) == -1) goto failed; Py_DECREF(value); + state->recursion_depth--; return result; failed: Py_XDECREF(value); @@ -4995,6 +5033,11 @@ ast2obj_arg(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } + if (++state->recursion_depth > state->recursion_limit) { + PyErr_SetString(PyExc_RecursionError, + "maximum recursion depth exceeded during ast construction"); + return 0; + } tp = (PyTypeObject *)state->arg_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) return NULL; @@ -5033,6 +5076,7 @@ ast2obj_arg(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->end_col_offset, value) < 0) goto failed; Py_DECREF(value); + state->recursion_depth--; return result; failed: Py_XDECREF(value); @@ -5049,6 +5093,11 @@ ast2obj_keyword(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } + if (++state->recursion_depth > state->recursion_limit) { + PyErr_SetString(PyExc_RecursionError, + "maximum recursion depth exceeded during ast construction"); + return 0; + } tp = (PyTypeObject *)state->keyword_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) return NULL; @@ -5082,6 +5131,7 @@ ast2obj_keyword(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->end_col_offset, value) < 0) goto failed; Py_DECREF(value); + state->recursion_depth--; return result; failed: Py_XDECREF(value); @@ -5098,6 +5148,11 @@ ast2obj_alias(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } + if (++state->recursion_depth > state->recursion_limit) { + PyErr_SetString(PyExc_RecursionError, + "maximum recursion depth exceeded during ast construction"); + return 0; + } tp = (PyTypeObject *)state->alias_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) return NULL; @@ -5131,6 +5186,7 @@ ast2obj_alias(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->end_col_offset, value) < 0) goto failed; Py_DECREF(value); + state->recursion_depth--; return result; failed: Py_XDECREF(value); @@ -5147,6 +5203,11 @@ ast2obj_withitem(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } + if (++state->recursion_depth > state->recursion_limit) { + PyErr_SetString(PyExc_RecursionError, + "maximum recursion depth exceeded during ast construction"); + return 0; + } tp = (PyTypeObject *)state->withitem_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) return NULL; @@ -5160,6 +5221,7 @@ ast2obj_withitem(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->optional_vars, value) == -1) goto failed; Py_DECREF(value); + state->recursion_depth--; return result; failed: Py_XDECREF(value); @@ -5176,6 +5238,11 @@ ast2obj_match_case(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } + if (++state->recursion_depth > state->recursion_limit) { + PyErr_SetString(PyExc_RecursionError, + "maximum recursion depth exceeded during ast construction"); + return 0; + } tp = (PyTypeObject *)state->match_case_type; result = PyType_GenericNew(tp, NULL, NULL); if (!result) return NULL; @@ -5194,6 +5261,7 @@ ast2obj_match_case(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->body, value) == -1) goto failed; Py_DECREF(value); + state->recursion_depth--; return result; failed: Py_XDECREF(value); @@ -5210,6 +5278,11 @@ ast2obj_pattern(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } + if (++state->recursion_depth > state->recursion_limit) { + PyErr_SetString(PyExc_RecursionError, + "maximum recursion depth exceeded during ast construction"); + return 0; + } switch (o->kind) { case MatchValue_kind: tp = (PyTypeObject *)state->MatchValue_type; @@ -5349,6 +5422,7 @@ ast2obj_pattern(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->end_col_offset, value) < 0) goto failed; Py_DECREF(value); + state->recursion_depth--; return result; failed: Py_XDECREF(value); @@ -5365,6 +5439,11 @@ ast2obj_type_ignore(struct ast_state *state, void* _o) if (!o) { Py_RETURN_NONE; } + if (++state->recursion_depth > state->recursion_limit) { + PyErr_SetString(PyExc_RecursionError, + "maximum recursion depth exceeded during ast construction"); + return 0; + } switch (o->kind) { case TypeIgnore_kind: tp = (PyTypeObject *)state->TypeIgnore_type; @@ -5382,6 +5461,7 @@ ast2obj_type_ignore(struct ast_state *state, void* _o) Py_DECREF(value); break; } + state->recursion_depth--; return result; failed: Py_XDECREF(value); @@ -12234,7 +12314,32 @@ PyObject* PyAST_mod2obj(mod_ty t) if (state == NULL) { return NULL; } - return ast2obj_mod(state, t); + + int recursion_limit = Py_GetRecursionLimit(); + int starting_recursion_depth; + /* Be careful here to prevent overflow. */ + int COMPILER_STACK_FRAME_SCALE = 3; + PyThreadState *tstate = _PyThreadState_GET(); + if (!tstate) { + return 0; + } + state->recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? + recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit; + int recursion_depth = tstate->recursion_limit - tstate->recursion_remaining; + starting_recursion_depth = (recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? + recursion_depth * COMPILER_STACK_FRAME_SCALE : recursion_depth; + state->recursion_depth = starting_recursion_depth; + + PyObject *result = ast2obj_mod(state, t); + + /* Check that the recursion depth counting balanced correctly */ + if (result && state->recursion_depth != starting_recursion_depth) { + PyErr_Format(PyExc_SystemError, + "AST constructor recursion depth mismatch (before=%d, after=%d)", + starting_recursion_depth, state->recursion_depth); + return 0; + } + return result; } /* mode is 0 for "exec", 1 for "eval" and 2 for "single" input */ diff --git a/Python/_warnings.c b/Python/_warnings.c index 601dae8fb465584767e69d2955720674d3eed611..1b9e107ea30b1378b5ce09d129ae482c3224ac40 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -1030,28 +1030,31 @@ get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno return source_line; } +/*[clinic input] +warn_explicit as warnings_warn_explicit + + message: object + category: object + filename: unicode + lineno: int + module as mod: object = NULL + registry: object = None + module_globals: object = None + source as sourceobj: object = None + +Issue a warning, or maybe ignore it or raise an exception. +[clinic start generated code]*/ + static PyObject * -warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) +warnings_warn_explicit_impl(PyObject *module, PyObject *message, + PyObject *category, PyObject *filename, + int lineno, PyObject *mod, PyObject *registry, + PyObject *module_globals, PyObject *sourceobj) +/*[clinic end generated code: output=c49c62b15a49a186 input=df6eeb8b45e712f1]*/ { - static char *kwd_list[] = {"message", "category", "filename", "lineno", - "module", "registry", "module_globals", - "source", 0}; - PyObject *message; - PyObject *category; - PyObject *filename; - int lineno; - PyObject *module = NULL; - PyObject *registry = NULL; - PyObject *module_globals = NULL; - PyObject *sourceobj = NULL; PyObject *source_line = NULL; PyObject *returned; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOUi|OOOO:warn_explicit", - kwd_list, &message, &category, &filename, &lineno, &module, - ®istry, &module_globals, &sourceobj)) - return NULL; - PyThreadState *tstate = get_current_tstate(); if (tstate == NULL) { return NULL; @@ -1070,8 +1073,8 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) return NULL; } } - returned = warn_explicit(tstate, category, message, filename, lineno, module, - registry, source_line, sourceobj); + returned = warn_explicit(tstate, category, message, filename, lineno, + mod, registry, source_line, sourceobj); Py_XDECREF(source_line); return returned; } @@ -1331,13 +1334,9 @@ _PyErr_WarnUnawaitedCoroutine(PyObject *coro) } } -PyDoc_STRVAR(warn_explicit_doc, -"Low-level interface to warnings functionality."); - static PyMethodDef warnings_functions[] = { WARNINGS_WARN_METHODDEF - {"warn_explicit", _PyCFunction_CAST(warnings_warn_explicit), - METH_VARARGS | METH_KEYWORDS, warn_explicit_doc}, + WARNINGS_WARN_EXPLICIT_METHODDEF {"_filters_mutated", _PyCFunction_CAST(warnings_filters_mutated), METH_NOARGS, NULL}, /* XXX(brett.cannon): add showwarning? */ diff --git a/Python/ceval.c b/Python/ceval.c index 2a0ce63d435d7c3c5d9bfb52c8b477fd035c4c06..7ad26a70dd18c65280dc31a2fed054c833474c94 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -5631,8 +5631,16 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int assert(oparg); oparg <<= 8; oparg |= _Py_OPARG(*next_instr); + // We might be tracing. To avoid breaking tracing guarantees in + // quickened instructions, always deoptimize the next opcode: opcode = _PyOpcode_Deopt[_Py_OPCODE(*next_instr)]; PRE_DISPATCH_GOTO(); + // CPython hasn't traced the following instruction historically + // (DO_TRACING would clobber our extended oparg anyways), so just + // skip our usual cframe.use_tracing check before dispatch. Also, + // make sure the next instruction isn't a RESUME, since that needs + // to trace properly (and shouldn't have an extended arg anyways): + assert(opcode != RESUME); DISPATCH_GOTO(); } @@ -5653,9 +5661,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int case DO_TRACING: #endif { - if (tstate->tracing == 0 && - INSTR_OFFSET() >= frame->f_code->_co_firsttraceable - ) { + assert(cframe.use_tracing); + assert(tstate->tracing == 0); + if (INSTR_OFFSET() >= frame->f_code->_co_firsttraceable) { int instr_prev = _PyInterpreterFrame_LASTI(frame); frame->prev_instr = next_instr; TRACING_NEXTOPARG(); @@ -6089,20 +6097,6 @@ positional_only_passed_as_keyword(PyThreadState *tstate, PyCodeObject *co, } -/* Exception table parsing code. - * See Objects/exception_table_notes.txt for details. - */ - -static inline unsigned char * -parse_varint(unsigned char *p, int *result) { - int val = p[0] & 63; - while (p[0] & 64) { - p++; - val = (val << 6) | (p[0] & 63); - } - *result = val; - return p+1; -} static inline unsigned char * scan_back_to_entry_start(unsigned char *p) { @@ -6881,12 +6875,15 @@ void PyThreadState_EnterTracing(PyThreadState *tstate) { tstate->tracing++; + tstate->cframe->use_tracing = 0; } void PyThreadState_LeaveTracing(PyThreadState *tstate) { + assert(tstate->tracing > 0 && tstate->cframe->use_tracing == 0); tstate->tracing--; + _PyThreadState_UpdateTracingState(tstate); } static int diff --git a/Python/clinic/_warnings.c.h b/Python/clinic/_warnings.c.h index aa85c2a0d4d920349b908d1f5ca86be23a5b2d8f..926fb32e7c261ed34fc374f9736c867b5e4b4558 100644 --- a/Python/clinic/_warnings.c.h +++ b/Python/clinic/_warnings.c.h @@ -66,4 +66,85 @@ skip_optional_pos: exit: return return_value; } -/*[clinic end generated code: output=0435c68611fa2fe9 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(warnings_warn_explicit__doc__, +"warn_explicit($module, /, message, category, filename, lineno,\n" +" module=<unrepresentable>, registry=None,\n" +" module_globals=None, source=None)\n" +"--\n" +"\n" +"Issue a warning, or maybe ignore it or raise an exception."); + +#define WARNINGS_WARN_EXPLICIT_METHODDEF \ + {"warn_explicit", _PyCFunction_CAST(warnings_warn_explicit), METH_FASTCALL|METH_KEYWORDS, warnings_warn_explicit__doc__}, + +static PyObject * +warnings_warn_explicit_impl(PyObject *module, PyObject *message, + PyObject *category, PyObject *filename, + int lineno, PyObject *mod, PyObject *registry, + PyObject *module_globals, PyObject *sourceobj); + +static PyObject * +warnings_warn_explicit(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"message", "category", "filename", "lineno", "module", "registry", "module_globals", "source", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "warn_explicit", 0}; + PyObject *argsbuf[8]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 4; + PyObject *message; + PyObject *category; + PyObject *filename; + int lineno; + PyObject *mod = NULL; + PyObject *registry = Py_None; + PyObject *module_globals = Py_None; + PyObject *sourceobj = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 8, 0, argsbuf); + if (!args) { + goto exit; + } + message = args[0]; + category = args[1]; + if (!PyUnicode_Check(args[2])) { + _PyArg_BadArgument("warn_explicit", "argument 'filename'", "str", args[2]); + goto exit; + } + if (PyUnicode_READY(args[2]) == -1) { + goto exit; + } + filename = args[2]; + lineno = _PyLong_AsInt(args[3]); + if (lineno == -1 && PyErr_Occurred()) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[4]) { + mod = args[4]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[5]) { + registry = args[5]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[6]) { + module_globals = args[6]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + sourceobj = args[7]; +skip_optional_pos: + return_value = warnings_warn_explicit_impl(module, message, category, filename, lineno, mod, registry, module_globals, sourceobj); + +exit: + return return_value; +} +/*[clinic end generated code: output=596b370838b95386 input=a9049054013a1b77]*/ diff --git a/Python/compile.c b/Python/compile.c index f36a6e85a54c20b4f80d38333865d459b5ffa12a..975efa7e23ecdf380c48fd75f55dfb38cbb0144f 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -85,6 +85,10 @@ (opcode) == SETUP_WITH || \ (opcode) == SETUP_CLEANUP) +/* opcodes that must be last in the basicblock */ +#define IS_TERMINATOR_OPCODE(opcode) \ + (IS_JUMP_OPCODE(opcode) || IS_SCOPE_EXIT_OPCODE(opcode)) + /* opcodes which are not emitted in codegen stage, only by the assembler */ #define IS_ASSEMBLER_OPCODE(opcode) \ ((opcode) == JUMP_FORWARD || \ @@ -207,13 +211,13 @@ write_instr(_Py_CODEUNIT *codestr, struct instr *instruction, int ilen) int caches = _PyOpcode_Caches[opcode]; switch (ilen - caches) { case 4: - *codestr++ = _Py_MAKECODEUNIT(EXTENDED_ARG_QUICK, (oparg >> 24) & 0xFF); + *codestr++ = _Py_MAKECODEUNIT(EXTENDED_ARG, (oparg >> 24) & 0xFF); /* fall through */ case 3: - *codestr++ = _Py_MAKECODEUNIT(EXTENDED_ARG_QUICK, (oparg >> 16) & 0xFF); + *codestr++ = _Py_MAKECODEUNIT(EXTENDED_ARG, (oparg >> 16) & 0xFF); /* fall through */ case 2: - *codestr++ = _Py_MAKECODEUNIT(EXTENDED_ARG_QUICK, (oparg >> 8) & 0xFF); + *codestr++ = _Py_MAKECODEUNIT(EXTENDED_ARG, (oparg >> 8) & 0xFF); /* fall through */ case 1: *codestr++ = _Py_MAKECODEUNIT(opcode, oparg & 0xFF); @@ -262,7 +266,7 @@ typedef struct basicblock_ { static struct instr * -basicblock_last_instr(basicblock *b) { +basicblock_last_instr(const basicblock *b) { if (b->b_iused) { return &b->b_instr[b->b_iused - 1]; } @@ -270,19 +274,19 @@ basicblock_last_instr(basicblock *b) { } static inline int -basicblock_returns(basicblock *b) { +basicblock_returns(const basicblock *b) { struct instr *last = basicblock_last_instr(b); return last && last->i_opcode == RETURN_VALUE; } static inline int -basicblock_exits_scope(basicblock *b) { +basicblock_exits_scope(const basicblock *b) { struct instr *last = basicblock_last_instr(b); return last && IS_SCOPE_EXIT_OPCODE(last->i_opcode); } static inline int -basicblock_nofallthrough(basicblock *b) { +basicblock_nofallthrough(const basicblock *b) { struct instr *last = basicblock_last_instr(b); return (last && (IS_SCOPE_EXIT_OPCODE(last->i_opcode) || @@ -321,6 +325,17 @@ enum { COMPILER_SCOPE_COMPREHENSION, }; +typedef struct cfg_builder_ { + /* The entryblock, at which control flow begins. All blocks of the + CFG are reachable through the b_next links */ + basicblock *cfg_entryblock; + /* Pointer to the most recently allocated block. By following + b_list links, you can reach all allocated blocks. */ + basicblock *block_list; + /* pointer to the block currently being constructed */ + basicblock *curblock; +} cfg_builder; + /* The following items change on entry and exit of code blocks. They must be saved and restored when returning to a block. */ @@ -346,10 +361,8 @@ struct compiler_unit { Py_ssize_t u_argcount; /* number of arguments for block */ Py_ssize_t u_posonlyargcount; /* number of positional only arguments for block */ Py_ssize_t u_kwonlyargcount; /* number of keyword only arguments for block */ - /* Pointer to the most recently allocated block. By following b_list - members, you can reach all early allocated blocks. */ - basicblock *u_blocks; - basicblock *u_curblock; /* pointer to current block */ + + cfg_builder u_cfg_builder; /* The control flow graph */ int u_nfblocks; struct fblockinfo u_fblock[CO_MAXBLOCKS]; @@ -386,6 +399,9 @@ struct compiler { PyArena *c_arena; /* pointer to memory allocation arena */ }; +#define CFG_BUILDER(c) (&((c)->u->u_cfg_builder)) +#define COMPILER_LOC(c) ((c)->u->u_loc) + typedef struct { // A list of strings corresponding to name captures. It is used to track: // - Repeated name assignments in the same pattern. @@ -413,12 +429,9 @@ typedef struct { static int basicblock_next_instr(basicblock *); -static int compiler_enter_scope(struct compiler *, identifier, int, void *, int); +static int cfg_builder_addop_i(cfg_builder *g, int opcode, Py_ssize_t oparg, struct location loc); + static void compiler_free(struct compiler *); -static basicblock *compiler_new_block(struct compiler *); -static int compiler_addop(struct compiler *, int, bool); -static int compiler_addop_i(struct compiler *, int, Py_ssize_t, bool); -static int compiler_addop_j(struct compiler *, int, basicblock *, bool); static int compiler_error(struct compiler *, const char *, ...); static int compiler_warn(struct compiler *, const char *, ...); static int compiler_nameop(struct compiler *, identifier, expr_context_ty); @@ -438,7 +451,6 @@ static int are_all_items_const(asdl_expr_seq *, Py_ssize_t, Py_ssize_t); static int compiler_with(struct compiler *, stmt_ty, int); static int compiler_async_with(struct compiler *, stmt_ty, int); static int compiler_async_for(struct compiler *, stmt_ty); -static int validate_keywords(struct compiler *c, asdl_keyword_seq *keywords); static int compiler_call_simple_kw_helper(struct compiler *c, asdl_keyword_seq *keywords, Py_ssize_t nkwelts); @@ -710,10 +722,9 @@ dictbytype(PyObject *src, int scope_type, int flag, Py_ssize_t offset) } static void -compiler_unit_check(struct compiler_unit *u) +cfg_builder_check(cfg_builder *g) { - basicblock *block; - for (block = u->u_blocks; block != NULL; block = block->b_list) { + for (basicblock *block = g->block_list; block != NULL; block = block->b_list) { assert(!_PyMem_IsPtrFreed(block)); if (block->b_instr != NULL) { assert(block->b_ialloc > 0); @@ -728,19 +739,24 @@ compiler_unit_check(struct compiler_unit *u) } static void -compiler_unit_free(struct compiler_unit *u) +cfg_builder_free(cfg_builder* g) { - basicblock *b, *next; - - compiler_unit_check(u); - b = u->u_blocks; + cfg_builder_check(g); + basicblock *b = g->block_list; while (b != NULL) { - if (b->b_instr) + if (b->b_instr) { PyObject_Free((void *)b->b_instr); - next = b->b_list; + } + basicblock *next = b->b_list; PyObject_Free((void *)b); b = next; } +} + +static void +compiler_unit_free(struct compiler_unit *u) +{ + cfg_builder_free(&u->u_cfg_builder); Py_CLEAR(u->u_ste); Py_CLEAR(u->u_name); Py_CLEAR(u->u_qualname); @@ -828,59 +844,48 @@ compiler_set_qualname(struct compiler *c) Returns NULL on error. */ static basicblock * -new_basicblock() +cfg_builder_new_block(cfg_builder *g) { basicblock *b = (basicblock *)PyObject_Calloc(1, sizeof(basicblock)); if (b == NULL) { PyErr_NoMemory(); return NULL; } + /* Extend the singly linked list of blocks with new block. */ + b->b_list = g->block_list; + g->block_list = b; return b; } static basicblock * -compiler_new_block(struct compiler *c) +cfg_builder_use_next_block(cfg_builder *g, basicblock *block) { - basicblock *b = new_basicblock(); - if (b == NULL) { - return NULL; - } - /* Extend the singly linked list of blocks with new block. */ - struct compiler_unit *u = c->u; - b->b_list = u->u_blocks; - u->u_blocks = b; - return b; + assert(block != NULL); + g->curblock->b_next = block; + g->curblock = block; + return block; } static basicblock * -compiler_use_next_block(struct compiler *c, basicblock *block) +compiler_new_block(struct compiler *c) { - assert(block != NULL); - c->u->u_curblock->b_next = block; - c->u->u_curblock = block; - return block; + return cfg_builder_new_block(CFG_BUILDER(c)); } static basicblock * -basicblock_new_b_list_successor(basicblock *prev) +compiler_use_next_block(struct compiler *c, basicblock *block) { - basicblock *result = new_basicblock(); - if (result == NULL) { - return NULL; - } - result->b_list = prev->b_list; - prev->b_list = result; - return result; + return cfg_builder_use_next_block(CFG_BUILDER(c), block); } static basicblock * -copy_basicblock(basicblock *block) +copy_basicblock(cfg_builder *g, basicblock *block) { /* Cannot copy a block if it has a fallthrough, since * a block can only have one fallthrough predecessor. */ assert(BB_NO_FALLTHROUGH(block)); - basicblock *result = basicblock_new_b_list_successor(block); + basicblock *result = cfg_builder_new_block(g); if (result == NULL) { return NULL; } @@ -1243,34 +1248,13 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) return stack_effect(opcode, oparg, -1); } -static int -is_end_of_basic_block(struct instr *instr) -{ - int opcode = instr->i_opcode; - return IS_JUMP_OPCODE(opcode) || IS_SCOPE_EXIT_OPCODE(opcode); -} - -static int -compiler_use_new_implicit_block_if_needed(struct compiler *c) -{ - basicblock *b = c->u->u_curblock; - if (b->b_iused && is_end_of_basic_block(basicblock_last_instr(b))) { - basicblock *b = compiler_new_block(c); - if (b == NULL) { - return -1; - } - compiler_use_next_block(c, b); - } - return 0; -} - /* Add an opcode with no argument. Returns 0 on failure, 1 on success. */ static int basicblock_addop(basicblock *b, int opcode, int oparg, - basicblock *target, const struct location *loc) + basicblock *target, struct location loc) { assert(IS_WITHIN_OPCODE_RANGE(opcode)); assert(!IS_ASSEMBLER_OPCODE(opcode)); @@ -1289,25 +1273,35 @@ basicblock_addop(basicblock *b, int opcode, int oparg, i->i_opcode = opcode; i->i_oparg = oparg; i->i_target = target; - i->i_loc = loc ? *loc : NO_LOCATION; + i->i_loc = loc; return 1; } static int -compiler_addop(struct compiler *c, int opcode, bool line) +cfg_builder_addop(cfg_builder *g, int opcode, int oparg, basicblock *target, + struct location loc) { - assert(!HAS_ARG(opcode)); - if (compiler_use_new_implicit_block_if_needed(c) < 0) { - return -1; + struct instr *last = basicblock_last_instr(g->curblock); + if (last && IS_TERMINATOR_OPCODE(last->i_opcode)) { + basicblock *b = cfg_builder_new_block(g); + if (b == NULL) { + return -1; + } + cfg_builder_use_next_block(g, b); } + return basicblock_addop(g->curblock, opcode, oparg, target, loc); +} - const struct location *loc = line ? &c->u->u_loc : NULL; - return basicblock_addop(c->u->u_curblock, opcode, 0, NULL, loc); +static int +cfg_builder_addop_noarg(cfg_builder *g, int opcode, struct location loc) +{ + assert(!HAS_ARG(opcode)); + return cfg_builder_addop(g, opcode, 0, NULL, loc); } static Py_ssize_t -compiler_add_o(PyObject *dict, PyObject *o) +dict_add_o(PyObject *dict, PyObject *o) { PyObject *v; Py_ssize_t arg; @@ -1452,7 +1446,7 @@ compiler_add_const(struct compiler *c, PyObject *o) return -1; } - Py_ssize_t arg = compiler_add_o(c->u->u_consts, key); + Py_ssize_t arg = dict_add_o(c->u->u_consts, key); Py_DECREF(key); return arg; } @@ -1463,17 +1457,17 @@ compiler_addop_load_const(struct compiler *c, PyObject *o) Py_ssize_t arg = compiler_add_const(c, o); if (arg < 0) return 0; - return compiler_addop_i(c, LOAD_CONST, arg, true); + return cfg_builder_addop_i(CFG_BUILDER(c), LOAD_CONST, arg, COMPILER_LOC(c)); } static int compiler_addop_o(struct compiler *c, int opcode, PyObject *dict, PyObject *o) { - Py_ssize_t arg = compiler_add_o(dict, o); + Py_ssize_t arg = dict_add_o(dict, o); if (arg < 0) return 0; - return compiler_addop_i(c, opcode, arg, true); + return cfg_builder_addop_i(CFG_BUILDER(c), opcode, arg, COMPILER_LOC(c)); } static int @@ -1485,7 +1479,7 @@ compiler_addop_name(struct compiler *c, int opcode, PyObject *dict, PyObject *mangled = _Py_Mangle(c->u->u_private, o); if (!mangled) return 0; - arg = compiler_add_o(dict, mangled); + arg = dict_add_o(dict, mangled); Py_DECREF(mangled); if (arg < 0) return 0; @@ -1497,18 +1491,15 @@ compiler_addop_name(struct compiler *c, int opcode, PyObject *dict, arg <<= 1; arg |= 1; } - return compiler_addop_i(c, opcode, arg, true); + return cfg_builder_addop_i(CFG_BUILDER(c), opcode, arg, COMPILER_LOC(c)); } /* Add an opcode with an integer argument. Returns 0 on failure, 1 on success. */ static int -compiler_addop_i(struct compiler *c, int opcode, Py_ssize_t oparg, bool line) +cfg_builder_addop_i(cfg_builder *g, int opcode, Py_ssize_t oparg, struct location loc) { - if (compiler_use_new_implicit_block_if_needed(c) < 0) { - return -1; - } /* oparg value is unsigned, but a signed C int is usually used to store it in the C code (like Python/ceval.c). @@ -1518,35 +1509,30 @@ compiler_addop_i(struct compiler *c, int opcode, Py_ssize_t oparg, bool line) EXTENDED_ARG is used for 16, 24, and 32-bit arguments. */ int oparg_ = Py_SAFE_DOWNCAST(oparg, Py_ssize_t, int); - - const struct location *loc = line ? &c->u->u_loc : NULL; - return basicblock_addop(c->u->u_curblock, opcode, oparg_, NULL, loc); + return cfg_builder_addop(g, opcode, oparg_, NULL, loc); } static int -compiler_addop_j(struct compiler *c, int opcode, basicblock *target, bool line) +cfg_builder_addop_j(cfg_builder *g, int opcode, basicblock *target, struct location loc) { - if (compiler_use_new_implicit_block_if_needed(c) < 0) { - return -1; - } - const struct location *loc = line ? &c->u->u_loc : NULL; assert(target != NULL); assert(IS_JUMP_OPCODE(opcode) || IS_BLOCK_PUSH_OPCODE(opcode)); - return basicblock_addop(c->u->u_curblock, opcode, 0, target, loc); + return cfg_builder_addop(g, opcode, 0, target, loc); } + #define ADDOP(C, OP) { \ - if (!compiler_addop((C), (OP), true)) \ + if (!cfg_builder_addop_noarg(CFG_BUILDER(C), (OP), COMPILER_LOC(C))) \ return 0; \ } #define ADDOP_NOLINE(C, OP) { \ - if (!compiler_addop((C), (OP), false)) \ + if (!cfg_builder_addop_noarg(CFG_BUILDER(C), (OP), NO_LOCATION)) \ return 0; \ } #define ADDOP_IN_SCOPE(C, OP) { \ - if (!compiler_addop((C), (OP), true)) { \ + if (!cfg_builder_addop_noarg(CFG_BUILDER(C), (OP), COMPILER_LOC(C))) { \ compiler_exit_scope(c); \ return 0; \ } \ @@ -1585,17 +1571,17 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *target, bool line) } #define ADDOP_I(C, OP, O) { \ - if (!compiler_addop_i((C), (OP), (O), true)) \ + if (!cfg_builder_addop_i(CFG_BUILDER(C), (OP), (O), COMPILER_LOC(C))) \ return 0; \ } #define ADDOP_I_NOLINE(C, OP, O) { \ - if (!compiler_addop_i((C), (OP), (O), false)) \ + if (!cfg_builder_addop_i(CFG_BUILDER(C), (OP), (O), NO_LOCATION)) \ return 0; \ } #define ADDOP_JUMP(C, OP, O) { \ - if (!compiler_addop_j((C), (OP), (O), true)) \ + if (!cfg_builder_addop_j(CFG_BUILDER(C), (OP), (O), COMPILER_LOC(C))) \ return 0; \ } @@ -1603,7 +1589,7 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *target, bool line) * Used for artificial jumps that have no corresponding * token in the source code. */ #define ADDOP_JUMP_NOLINE(C, OP, O) { \ - if (!compiler_addop_j((C), (OP), (O), false)) \ + if (!cfg_builder_addop_j(CFG_BUILDER(C), (OP), (O), NO_LOCATION)) \ return 0; \ } @@ -1720,7 +1706,6 @@ compiler_enter_scope(struct compiler *c, identifier name, return 0; } - u->u_blocks = NULL; u->u_nfblocks = 0; u->u_firstlineno = lineno; u->u_loc = LOCATION(lineno, lineno, 0, 0); @@ -1753,10 +1738,12 @@ compiler_enter_scope(struct compiler *c, identifier name, c->c_nestlevel++; - block = compiler_new_block(c); + cfg_builder *g = CFG_BUILDER(c); + g->block_list = NULL; + block = cfg_builder_new_block(g); if (block == NULL) return 0; - c->u->u_curblock = block; + g->curblock = g->cfg_entryblock = block; if (u->u_scope_type == COMPILER_SCOPE_MODULE) { c->u->u_loc.lineno = 0; @@ -1793,7 +1780,7 @@ compiler_exit_scope(struct compiler *c) _PyErr_WriteUnraisableMsg("on removing the last compiler " "stack item", NULL); } - compiler_unit_check(c->u); + cfg_builder_check(CFG_BUILDER(c)); } else { c->u = NULL; @@ -4242,7 +4229,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) } assert(op); - arg = compiler_add_o(dict, mangled); + arg = dict_add_o(dict, mangled); Py_DECREF(mangled); if (arg < 0) { return 0; @@ -4250,7 +4237,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) if (op == LOAD_GLOBAL) { arg <<= 1; } - return compiler_addop_i(c, op, arg, true); + return cfg_builder_addop_i(CFG_BUILDER(c), op, arg, COMPILER_LOC(c)); } static int @@ -4731,13 +4718,30 @@ is_import_originated(struct compiler *c, expr_ty e) return flags & DEF_IMPORT; } +// If an attribute access spans multiple lines, update the current start +// location to point to the attribute name. static void -update_location_to_match_attr(struct compiler *c, expr_ty meth) +update_start_location_to_match_attr(struct compiler *c, expr_ty attr) { - if (meth->lineno != meth->end_lineno) { - // Make start location match attribute - c->u->u_loc.lineno = meth->end_lineno; - c->u->u_loc.col_offset = meth->end_col_offset - (int)PyUnicode_GetLength(meth->v.Attribute.attr)-1; + assert(attr->kind == Attribute_kind); + struct location *loc = &c->u->u_loc; + if (loc->lineno != attr->end_lineno) { + loc->lineno = attr->end_lineno; + int len = (int)PyUnicode_GET_LENGTH(attr->v.Attribute.attr); + if (len <= attr->end_col_offset) { + loc->col_offset = attr->end_col_offset - len; + } + else { + // GH-94694: Somebody's compiling weird ASTs. Just drop the columns: + loc->col_offset = -1; + loc->end_col_offset = -1; + } + // Make sure the end position still follows the start position, even for + // weird ASTs: + loc->end_lineno = Py_MAX(loc->lineno, loc->end_lineno); + if (loc->lineno == loc->end_lineno) { + loc->end_col_offset = Py_MAX(loc->col_offset, loc->end_col_offset); + } } } @@ -4783,7 +4787,7 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e) /* Alright, we can optimize the code. */ VISIT(c, expr, meth->v.Attribute.value); SET_LOC(c, meth); - update_location_to_match_attr(c, meth); + update_start_location_to_match_attr(c, meth); ADDOP_NAME(c, LOAD_METHOD, meth->v.Attribute.attr, names); VISIT_SEQ(c, expr, e->v.Call.args); @@ -4794,7 +4798,7 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e) }; } SET_LOC(c, e); - update_location_to_match_attr(c, meth); + update_start_location_to_match_attr(c, meth); ADDOP_I(c, CALL, argsl + kwdsl); return 1; } @@ -4852,7 +4856,7 @@ compiler_joined_str(struct compiler *c, expr_ty e) Py_ssize_t value_count = asdl_seq_LEN(e->v.JoinedStr.values); if (value_count > STACK_USE_GUIDELINE) { _Py_DECLARE_STR(empty, ""); - ADDOP_LOAD_CONST_NEW(c, &_Py_STR(empty)); + ADDOP_LOAD_CONST_NEW(c, Py_NewRef(&_Py_STR(empty))); ADDOP_NAME(c, LOAD_METHOD, &_Py_ID(join), names); ADDOP_I(c, BUILD_LIST, 0); for (Py_ssize_t i = 0; i < asdl_seq_LEN(e->v.JoinedStr.values); i++) { @@ -5806,23 +5810,18 @@ compiler_visit_expr1(struct compiler *c, expr_ty e) /* The following exprs can be assignment targets. */ case Attribute_kind: VISIT(c, expr, e->v.Attribute.value); + update_start_location_to_match_attr(c, e); switch (e->v.Attribute.ctx) { case Load: { - int old_lineno = c->u->u_loc.lineno; - c->u->u_loc.lineno = e->end_lineno; ADDOP_NAME(c, LOAD_ATTR, e->v.Attribute.attr, names); - c->u->u_loc.lineno = old_lineno; break; } case Store: if (forbidden_name(c, e->v.Attribute.attr, e->v.Attribute.ctx)) { return 0; } - int old_lineno = c->u->u_loc.lineno; - c->u->u_loc.lineno = e->end_lineno; ADDOP_NAME(c, STORE_ATTR, e->v.Attribute.attr, names); - c->u->u_loc.lineno = old_lineno; break; case Del: ADDOP_NAME(c, DELETE_ATTR, e->v.Attribute.attr, names); @@ -5893,10 +5892,8 @@ compiler_augassign(struct compiler *c, stmt_ty s) case Attribute_kind: VISIT(c, expr, e->v.Attribute.value); ADDOP_I(c, COPY, 1); - int old_lineno = c->u->u_loc.lineno; - c->u->u_loc.lineno = e->end_lineno; + update_start_location_to_match_attr(c, e); ADDOP_NAME(c, LOAD_ATTR, e->v.Attribute.attr, names); - c->u->u_loc.lineno = old_lineno; break; case Subscript_kind: VISIT(c, expr, e->v.Subscript.value); @@ -5936,7 +5933,7 @@ compiler_augassign(struct compiler *c, stmt_ty s) switch (e->kind) { case Attribute_kind: - c->u->u_loc.lineno = e->end_lineno; + update_start_location_to_match_attr(c, e); ADDOP_I(c, SWAP, 2); ADDOP_NAME(c, STORE_ATTR, e->v.Attribute.attr, names); break; @@ -6283,7 +6280,7 @@ emit_and_reset_fail_pop(struct compiler *c, pattern_context *pc) } while (--pc->fail_pop_size) { compiler_use_next_block(c, pc->fail_pop[pc->fail_pop_size]); - if (!compiler_addop(c, POP_TOP, true)) { + if (!cfg_builder_addop_noarg(CFG_BUILDER(c), POP_TOP, COMPILER_LOC(c))) { pc->fail_pop_size = 0; PyObject_Free(pc->fail_pop); pc->fail_pop = NULL; @@ -6717,7 +6714,8 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc) pc->fail_pop = NULL; pc->fail_pop_size = 0; pc->on_top = 0; - if (!compiler_addop_i(c, COPY, 1, true) || !compiler_pattern(c, alt, pc)) { + if (!cfg_builder_addop_i(CFG_BUILDER(c), COPY, 1, COMPILER_LOC(c)) || + !compiler_pattern(c, alt, pc)) { goto error; } // Success! @@ -6780,7 +6778,7 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc) } } assert(control); - if (!compiler_addop_j(c, JUMP, end, true) || + if (!cfg_builder_addop_j(CFG_BUILDER(c), JUMP, end, COMPILER_LOC(c)) || !emit_and_reset_fail_pop(c, pc)) { goto error; @@ -6792,7 +6790,7 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc) // Need to NULL this for the PyObject_Free call in the error block. old_pc.fail_pop = NULL; // No match. Pop the remaining copy of the subject and fail: - if (!compiler_addop(c, POP_TOP, true) || !jump_to_fail_pop(c, pc, JUMP)) { + if (!cfg_builder_addop_noarg(CFG_BUILDER(c), POP_TOP, COMPILER_LOC(c)) || !jump_to_fail_pop(c, pc, JUMP)) { goto error; } compiler_use_next_block(c, end); @@ -7422,7 +7420,8 @@ mark_cold(basicblock *entryblock) { } static int -push_cold_blocks_to_end(basicblock *entryblock, int code_flags) { +push_cold_blocks_to_end(cfg_builder *g, int code_flags) { + basicblock *entryblock = g->cfg_entryblock; if (entryblock->b_next == NULL) { /* single basicblock, no need to reorder */ return 0; @@ -7435,11 +7434,11 @@ push_cold_blocks_to_end(basicblock *entryblock, int code_flags) { /* an explicit jump instead of fallthrough */ for (basicblock *b = entryblock; b != NULL; b = b->b_next) { if (b->b_cold && BB_HAS_FALLTHROUGH(b) && b->b_next && b->b_next->b_warm) { - basicblock *explicit_jump = basicblock_new_b_list_successor(b); + basicblock *explicit_jump = cfg_builder_new_block(g); if (explicit_jump == NULL) { return -1; } - basicblock_addop(explicit_jump, JUMP, 0, b->b_next, &NO_LOCATION); + basicblock_addop(explicit_jump, JUMP, 0, b->b_next, NO_LOCATION); explicit_jump->b_cold = 1; explicit_jump->b_next = b->b_next; @@ -8016,7 +8015,7 @@ consts_dict_keys_inorder(PyObject *dict) while (PyDict_Next(dict, &pos, &k, &v)) { i = PyLong_AS_LONG(v); /* The keys of the dictionary can be tuples wrapping a constant. - * (see compiler_add_o and _PyCode_ConstantKey). In that case + * (see dict_add_o and _PyCode_ConstantKey). In that case * the object we want is always second. */ if (PyTuple_CheckExact(k)) { k = PyTuple_GET_ITEM(k, 1); @@ -8288,7 +8287,7 @@ trim_unused_consts(basicblock *entryblock, PyObject *consts); /* Duplicates exit BBs, so that line numbers can be propagated to them */ static int -duplicate_exits_without_lineno(basicblock *entryblock); +duplicate_exits_without_lineno(cfg_builder *g); static int extend_block(basicblock *bb); @@ -8539,25 +8538,13 @@ assemble(struct compiler *c, int addNone) } /* Make sure every block that falls off the end returns None. */ - if (!basicblock_returns(c->u->u_curblock)) { + if (!basicblock_returns(CFG_BUILDER(c)->curblock)) { UNSET_LOC(c); if (addNone) ADDOP_LOAD_CONST(c, Py_None); ADDOP(c, RETURN_VALUE); } - for (basicblock *b = c->u->u_blocks; b != NULL; b = b->b_list) { - if (normalize_basic_block(b)) { - return NULL; - } - } - - for (basicblock *b = c->u->u_blocks; b != NULL; b = b->b_list) { - if (extend_block(b)) { - return NULL; - } - } - assert(PyDict_GET_SIZE(c->u->u_varnames) < INT_MAX); assert(PyDict_GET_SIZE(c->u->u_cellvars) < INT_MAX); assert(PyDict_GET_SIZE(c->u->u_freevars) < INT_MAX); @@ -8573,17 +8560,18 @@ assemble(struct compiler *c, int addNone) } int nblocks = 0; - basicblock *entryblock = NULL; - for (basicblock *b = c->u->u_blocks; b != NULL; b = b->b_list) { + for (basicblock *b = CFG_BUILDER(c)->block_list; b != NULL; b = b->b_list) { nblocks++; - entryblock = b; } - assert(entryblock != NULL); if ((size_t)nblocks > SIZE_MAX / sizeof(basicblock *)) { PyErr_NoMemory(); goto error; } + cfg_builder *g = CFG_BUILDER(c); + basicblock *entryblock = g->cfg_entryblock; + assert(entryblock != NULL); + /* Set firstlineno if it wasn't explicitly set. */ if (!c->u->u_firstlineno) { if (entryblock->b_instr && entryblock->b_instr->i_loc.lineno) { @@ -8615,12 +8603,12 @@ assemble(struct compiler *c, int addNone) if (optimize_cfg(entryblock, consts, c->c_const_cache)) { goto error; } - if (duplicate_exits_without_lineno(entryblock)) { - return NULL; - } if (trim_unused_consts(entryblock, consts)) { goto error; } + if (duplicate_exits_without_lineno(g)) { + return NULL; + } propagate_line_numbers(entryblock); guarantee_lineno_for_exits(entryblock, c->u->u_firstlineno); @@ -8635,7 +8623,7 @@ assemble(struct compiler *c, int addNone) } convert_exception_handlers_to_nops(entryblock); - if (push_cold_blocks_to_end(entryblock, code_flags) < 0) { + if (push_cold_blocks_to_end(g, code_flags) < 0) { goto error; } @@ -9285,7 +9273,10 @@ clean_basic_block(basicblock *bb) { /* or, if the next instruction has same line number or no line number */ if (src < bb->b_iused - 1) { int next_lineno = bb->b_instr[src+1].i_loc.lineno; - if (next_lineno < 0 || next_lineno == lineno) { + if (next_lineno == lineno) { + continue; + } + if (next_lineno < 0) { bb->b_instr[src+1].i_loc = bb->b_instr[src].i_loc; continue; } @@ -9316,8 +9307,8 @@ clean_basic_block(basicblock *bb) { static int normalize_basic_block(basicblock *bb) { - /* Mark blocks as exit and/or nofallthrough. - Raise SystemError if CFG is malformed. */ + /* Skip over empty blocks. + * Raise SystemError if jump or exit is not last instruction in the block. */ for (int i = 0; i < bb->b_iused; i++) { int opcode = bb->b_instr[i].i_opcode; assert(!IS_ASSEMBLER_OPCODE(opcode)); @@ -9454,8 +9445,7 @@ propagate_line_numbers(basicblock *entryblock) { The consts object should still be in list form to allow new constants to be appended. - All transformations keep the code size the same or smaller. - For those that reduce size, the gaps are initially filled with + Code trasnformations that reduce code size initially fill the gaps with NOPs. Later those NOPs are removed. */ @@ -9463,6 +9453,16 @@ static int optimize_cfg(basicblock *entryblock, PyObject *consts, PyObject *const_cache) { assert(PyDict_CheckExact(const_cache)); + for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + if (normalize_basic_block(b)) { + return -1; + } + } + for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + if (extend_block(b)) { + return -1; + } + } for (basicblock *b = entryblock; b != NULL; b = b->b_next) { if (optimize_basic_block(const_cache, b, consts)) { return -1; @@ -9542,15 +9542,16 @@ is_exit_without_lineno(basicblock *b) { * copy the line number from the sole predecessor block. */ static int -duplicate_exits_without_lineno(basicblock *entryblock) +duplicate_exits_without_lineno(cfg_builder *g) { /* Copy all exit blocks without line number that are targets of a jump. */ + basicblock *entryblock = g->cfg_entryblock; for (basicblock *b = entryblock; b != NULL; b = b->b_next) { if (b->b_iused > 0 && is_jump(&b->b_instr[b->b_iused-1])) { basicblock *target = b->b_instr[b->b_iused-1].i_target; if (is_exit_without_lineno(target) && target->b_predecessors > 1) { - basicblock *new_target = copy_basicblock(target); + basicblock *new_target = copy_basicblock(g, target); if (new_target == NULL) { return -1; } diff --git a/Python/dup2.c b/Python/dup2.c index 7c6bbfce11dbf80dae7fe4c79d4c52839a0c68ad..a1df0492099163982661b996e697c708c0235783 100644 --- a/Python/dup2.c +++ b/Python/dup2.c @@ -11,6 +11,7 @@ * Return fd2 if all went well; return BADEXIT otherwise. */ +#include <errno.h> #include <fcntl.h> #include <unistd.h> @@ -20,12 +21,17 @@ int dup2(int fd1, int fd2) { if (fd1 != fd2) { +#ifdef F_DUPFD if (fcntl(fd1, F_GETFL) < 0) return BADEXIT; if (fcntl(fd2, F_GETFL) >= 0) close(fd2); if (fcntl(fd1, F_DUPFD, fd2) < 0) return BADEXIT; +#else + errno = ENOTSUP; + return BADEXIT; +#endif } return fd2; } diff --git a/Python/errors.c b/Python/errors.c index b6b5d9b046ce851fe1f9673e08a264b1a176cddb..2aa748c60c370478a40ddf60d9bdc943b5db8e58 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -1229,8 +1229,8 @@ _PyErr_InitTypes(PyInterpreterState *interp) } if (UnraisableHookArgsType.tp_name == NULL) { - if (PyStructSequence_InitType2(&UnraisableHookArgsType, - &UnraisableHookArgs_desc) < 0) { + if (_PyStructSequence_InitBuiltin(&UnraisableHookArgsType, + &UnraisableHookArgs_desc) < 0) { return _PyStatus_ERR("failed to initialize UnraisableHookArgs type"); } } diff --git a/Python/fileutils.c b/Python/fileutils.c index 7e5d01f6e63d3bc74aaded8609eabc4c44707615..fb1e5ef9a03026bb7b1e44659be5b79fb9c98104 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -2366,7 +2366,7 @@ _Py_dup(int fd) return -1; } -#else +#elif HAVE_DUP Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH fd = dup(fd); @@ -2383,6 +2383,10 @@ _Py_dup(int fd) _Py_END_SUPPRESS_IPH return -1; } +#else + errno = ENOTSUP; + PyErr_SetFromErrno(PyExc_OSError); + return -1; #endif return fd; } diff --git a/Python/getargs.c b/Python/getargs.c index fb4a5124beab8a6bf429aee9abfed068c25b4236..2efd330ea62d1dfe6ea6b1f8e76b5c287f932b21 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1502,6 +1502,50 @@ _PyArg_VaParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords, return retval; } +static void +error_unexpected_keyword_arg(PyObject *kwargs, PyObject *kwnames, PyObject *kwtuple, const char *fname) +{ + /* make sure there are no extraneous keyword arguments */ + Py_ssize_t j = 0; + while (1) { + PyObject *keyword; + if (kwargs != NULL) { + if (!PyDict_Next(kwargs, &j, &keyword, NULL)) + break; + } + else { + if (j >= PyTuple_GET_SIZE(kwnames)) + break; + keyword = PyTuple_GET_ITEM(kwnames, j); + j++; + } + if (!PyUnicode_Check(keyword)) { + PyErr_SetString(PyExc_TypeError, + "keywords must be strings"); + return; + } + + int match = PySequence_Contains(kwtuple, keyword); + if (match <= 0) { + if (!match) { + PyErr_Format(PyExc_TypeError, + "'%S' is an invalid keyword " + "argument for %.200s%s", + keyword, + (fname == NULL) ? "this function" : fname, + (fname == NULL) ? "" : "()"); + } + return; + } + } + /* Something wrong happened. There are extraneous keyword arguments, + * but we don't know what. And we don't bother. */ + PyErr_Format(PyExc_TypeError, + "invalid keyword argument for %.200s%s", + (fname == NULL) ? "this function" : fname, + (fname == NULL) ? "" : "()"); +} + int PyArg_ValidateKeywordArguments(PyObject *kwargs) { @@ -1790,6 +1834,13 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, return cleanreturn(0, &freelist); } } + /* Something wrong happened. There are extraneous keyword arguments, + * but we don't know what. And we don't bother. */ + PyErr_Format(PyExc_TypeError, + "invalid keyword argument for %.200s%s", + (fname == NULL) ? "this function" : fname, + (fname == NULL) ? "" : "()"); + return cleanreturn(0, &freelist); } return cleanreturn(1, &freelist); @@ -2132,7 +2183,6 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, assert(IS_END_OF_FORMAT(*format) || (*format == '|') || (*format == '$')); if (nkwargs > 0) { - Py_ssize_t j; /* make sure there are no arguments given by name and position */ for (i = pos; i < nargs; i++) { keyword = PyTuple_GET_ITEM(kwtuple, i - pos); @@ -2156,34 +2206,9 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, return cleanreturn(0, &freelist); } } - /* make sure there are no extraneous keyword arguments */ - j = 0; - while (1) { - int match; - if (kwargs != NULL) { - if (!PyDict_Next(kwargs, &j, &keyword, NULL)) - break; - } - else { - if (j >= PyTuple_GET_SIZE(kwnames)) - break; - keyword = PyTuple_GET_ITEM(kwnames, j); - j++; - } - match = PySequence_Contains(kwtuple, keyword); - if (match <= 0) { - if (!match) { - PyErr_Format(PyExc_TypeError, - "'%S' is an invalid keyword " - "argument for %.200s%s", - keyword, - (parser->fname == NULL) ? "this function" : parser->fname, - (parser->fname == NULL) ? "" : "()"); - } - return cleanreturn(0, &freelist); - } - } + error_unexpected_keyword_arg(kwargs, kwnames, kwtuple, parser->fname); + return cleanreturn(0, &freelist); } return cleanreturn(1, &freelist); @@ -2357,7 +2382,6 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs, } if (nkwargs > 0) { - Py_ssize_t j; /* make sure there are no arguments given by name and position */ for (i = posonly; i < nargs; i++) { keyword = PyTuple_GET_ITEM(kwtuple, i - posonly); @@ -2381,34 +2405,9 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs, return NULL; } } - /* make sure there are no extraneous keyword arguments */ - j = 0; - while (1) { - int match; - if (kwargs != NULL) { - if (!PyDict_Next(kwargs, &j, &keyword, NULL)) - break; - } - else { - if (j >= PyTuple_GET_SIZE(kwnames)) - break; - keyword = PyTuple_GET_ITEM(kwnames, j); - j++; - } - match = PySequence_Contains(kwtuple, keyword); - if (match <= 0) { - if (!match) { - PyErr_Format(PyExc_TypeError, - "'%S' is an invalid keyword " - "argument for %.200s%s", - keyword, - (parser->fname == NULL) ? "this function" : parser->fname, - (parser->fname == NULL) ? "" : "()"); - } - return NULL; - } - } + error_unexpected_keyword_arg(kwargs, kwnames, kwtuple, parser->fname); + return NULL; } return buf; @@ -2537,35 +2536,8 @@ _PyArg_UnpackKeywordsWithVararg(PyObject *const *args, Py_ssize_t nargs, } if (nkwargs > 0) { - Py_ssize_t j; - /* make sure there are no extraneous keyword arguments */ - j = 0; - while (1) { - int match; - if (kwargs != NULL) { - if (!PyDict_Next(kwargs, &j, &keyword, NULL)) - break; - } - else { - if (j >= PyTuple_GET_SIZE(kwnames)) - break; - keyword = PyTuple_GET_ITEM(kwnames, j); - j++; - } - - match = PySequence_Contains(kwtuple, keyword); - if (match <= 0) { - if (!match) { - PyErr_Format(PyExc_TypeError, - "'%S' is an invalid keyword " - "argument for %.200s%s", - keyword, - (parser->fname == NULL) ? "this function" : parser->fname, - (parser->fname == NULL) ? "" : "()"); - } - goto exit; - } - } + error_unexpected_keyword_arg(kwargs, kwnames, kwtuple, parser->fname); + goto exit; } return buf; @@ -2641,9 +2613,7 @@ skipitem(const char **p_format, va_list *p_va, int flags) if (*format == '#') { if (p_va != NULL) { if (!(flags & FLAG_SIZE_T)) { - PyErr_SetString(PyExc_SystemError, - "PY_SSIZE_T_CLEAN macro must be defined for '#' formats"); - return NULL; + return "PY_SSIZE_T_CLEAN macro must be defined for '#' formats"; } (void) va_arg(*p_va, Py_ssize_t *); } diff --git a/Python/initconfig.c b/Python/initconfig.c index 355f9869290bbd744e5c9d51638e6e281dfa6826..d29c69345a2bb3f306b0aab6832b7e660b309f91 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -2310,6 +2310,9 @@ config_parse_cmdline(PyConfig *config, PyWideStringList *warnoptions, const PyWideStringList *argv = &config->argv; int print_version = 0; const wchar_t* program = config->program_name; + if (!program && argv->length >= 1) { + program = argv->items[0]; + } _PyOS_ResetGetOpt(); do { diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 65e7f23e963b5fc6f7ecb95492e3311411fa7bd1..11a45800533e0142cb23a5ba14d9cefa4bbeaf5e 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1672,9 +1672,10 @@ finalize_interp_types(PyInterpreterState *interp) _PyLong_FiniTypes(interp); _PyThread_FiniType(interp); _PyErr_FiniTypes(interp); - _PyTypes_Fini(interp); _PyTypes_FiniTypes(interp); + _PyTypes_Fini(interp); + // Call _PyUnicode_ClearInterned() before _PyDict_Fini() since it uses // a dict internally. _PyUnicode_ClearInterned(interp); @@ -1687,6 +1688,9 @@ finalize_interp_types(PyInterpreterState *interp) _PyUnicode_Fini(interp); _PyFloat_Fini(interp); +#ifdef Py_DEBUG + _PyStaticObjects_CheckRefcnt(); +#endif } diff --git a/Python/specialize.c b/Python/specialize.c index 66cae44fa8f3d7f2e708323ade3004643989553d..53b2ae82b9836226f89455605801c5a15a05a35a 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -295,6 +295,9 @@ _PyCode_Quicken(PyCodeObject *code) else { assert(!_PyOpcode_Caches[opcode]); switch (opcode) { + case EXTENDED_ARG: + _Py_SET_OPCODE(instructions[i], EXTENDED_ARG_QUICK); + break; case JUMP_BACKWARD: _Py_SET_OPCODE(instructions[i], JUMP_BACKWARD_QUICK); break; @@ -945,6 +948,10 @@ specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) { _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1); + if (!PyType_CheckExact(owner) || _PyType_Lookup(Py_TYPE(owner), name)) { + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE); + return -1; + } PyObject *descr = NULL; DescriptorClassification kind = 0; kind = analyze_descriptor((PyTypeObject *)owner, name, &descr, 0); @@ -957,12 +964,7 @@ specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr, return 0; #ifdef Py_STATS case ABSENT: - if (_PyType_Lookup(Py_TYPE(owner), name) != NULL) { - SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE); - } - else { - SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR); - } + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR); return -1; #endif default: diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h index 553585a76a394ab2fc6a3e0bc10bddd2636999f1..ff422e72301847ff9cfe6e172c2a3d107ebbe341 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -9,7 +9,6 @@ static const char* _Py_stdlib_module_names[] = { "_asyncio", "_bisect", "_blake2", -"_bootsubprocess", "_bz2", "_codecs", "_codecs_cn", diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 93120071b400fd5ee61a32b5796bc7fb703cedf5..e861d9cbce415c45b24e84fd15ffae7135078c56 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -28,7 +28,7 @@ Data members: #include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR #include "pycore_pymem.h" // _PyMem_SetDefaultAllocator() #include "pycore_pystate.h" // _PyThreadState_GET() -#include "pycore_structseq.h" // _PyStructSequence_InitType() +#include "pycore_structseq.h" // _PyStructSequence_InitBuiltinWithFlags() #include "pycore_tuple.h" // _PyTuple_FromArray() #include "frameobject.h" // PyFrame_FastToLocalsWithError() @@ -1772,10 +1772,6 @@ sys__getframe_impl(PyObject *module, int depth) PyThreadState *tstate = _PyThreadState_GET(); _PyInterpreterFrame *frame = tstate->cframe->current_frame; - if (_PySys_Audit(tstate, "sys._getframe", NULL) < 0) { - return NULL; - } - if (frame != NULL) { while (depth > 0) { frame = frame->previous; @@ -1793,7 +1789,13 @@ sys__getframe_impl(PyObject *module, int depth) "call stack is not deep enough"); return NULL; } - return _Py_XNewRef((PyObject *)_PyFrame_GetFrameObject(frame)); + + PyObject *pyFrame = Py_XNewRef((PyObject *)_PyFrame_GetFrameObject(frame)); + if (pyFrame && _PySys_Audit(tstate, "sys._getframe", "(O)", pyFrame) < 0) { + Py_DECREF(pyFrame); + return NULL; + } + return pyFrame; } /*[clinic input] @@ -2919,7 +2921,7 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict) SET_SYS("int_info", PyLong_GetInfo()); /* initialize hash_info */ if (Hash_InfoType.tp_name == NULL) { - if (PyStructSequence_InitType2(&Hash_InfoType, &hash_info_desc) < 0) { + if (_PyStructSequence_InitBuiltin(&Hash_InfoType, &hash_info_desc) < 0) { goto type_init_failed; } } @@ -2941,14 +2943,18 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict) SET_SYS_FROM_STRING("abiflags", ABIFLAGS); #endif +#define ENSURE_INFO_TYPE(TYPE, DESC) \ + do { \ + if (TYPE.tp_name == NULL) { \ + if (_PyStructSequence_InitBuiltinWithFlags( \ + &TYPE, &DESC, Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { \ + goto type_init_failed; \ + } \ + } \ + } while (0) + /* version_info */ - if (VersionInfoType.tp_name == NULL) { - if (_PyStructSequence_InitType(&VersionInfoType, - &version_info_desc, - Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { - goto type_init_failed; - } - } + ENSURE_INFO_TYPE(VersionInfoType, version_info_desc); version_info = make_version_info(tstate); SET_SYS("version_info", version_info); @@ -2956,27 +2962,18 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict) SET_SYS("implementation", make_impl_info(version_info)); // sys.flags: updated in-place later by _PySys_UpdateConfig() - if (FlagsType.tp_name == 0) { - if (_PyStructSequence_InitType(&FlagsType, &flags_desc, - Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { - goto type_init_failed; - } - } + ENSURE_INFO_TYPE(FlagsType, flags_desc); SET_SYS("flags", make_flags(tstate->interp)); #if defined(MS_WINDOWS) /* getwindowsversion */ - if (WindowsVersionType.tp_name == 0) { - if (_PyStructSequence_InitType(&WindowsVersionType, - &windows_version_desc, - Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { - goto type_init_failed; - } - } + ENSURE_INFO_TYPE(WindowsVersionType, windows_version_desc); SET_SYS_FROM_STRING("_vpath", VPATH); #endif +#undef ENSURE_INFO_TYPE + /* float repr style: 0.03 (short) vs 0.029999999999999999 (legacy) */ #if _PY_SHORT_FLOAT_REPR == 1 SET_SYS_FROM_STRING("float_repr_style", "short"); @@ -2988,7 +2985,7 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict) /* initialize asyncgen_hooks */ if (AsyncGenHooksType.tp_name == NULL) { - if (PyStructSequence_InitType2( + if (_PyStructSequence_InitBuiltin( &AsyncGenHooksType, &asyncgen_hooks_desc) < 0) { goto type_init_failed; } diff --git a/Python/thread.c b/Python/thread.c index 846f02545271cf7e3e12bfa36a58af7d469ca214..e206a69c0507daad7c300c33e77c815719aba258 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -55,8 +55,15 @@ PyThread_init_thread(void) PyThread__init_thread(); } -#if defined(_POSIX_THREADS) -# define PYTHREAD_NAME "pthread" +#if defined(HAVE_PTHREAD_STUBS) +# define PYTHREAD_NAME "pthread-stubs" +# include "thread_pthread_stubs.h" +#elif defined(_POSIX_THREADS) +# if defined(__EMSCRIPTEN__) || !defined(__EMSCRIPTEN_PTHREADS__) +# define PYTHREAD_NAME "pthread-stubs" +# else +# define PYTHREAD_NAME "pthread" +# endif # include "thread_pthread.h" #elif defined(NT_THREADS) # define PYTHREAD_NAME "nt" @@ -155,7 +162,8 @@ PyThread_GetInfo(void) #endif if (ThreadInfoType.tp_name == 0) { - if (PyStructSequence_InitType2(&ThreadInfoType, &threadinfo_desc) < 0) + if (_PyStructSequence_InitBuiltin(&ThreadInfoType, + &threadinfo_desc) < 0) return NULL; } @@ -170,7 +178,9 @@ PyThread_GetInfo(void) } PyStructSequence_SET_ITEM(threadinfo, pos++, value); -#ifdef _POSIX_THREADS +#ifdef HAVE_PTHREAD_STUBS + value = Py_NewRef(Py_None); +#elif defined(_POSIX_THREADS) #ifdef USE_SEMAPHORES value = PyUnicode_FromString("semaphore"); #else @@ -181,8 +191,7 @@ PyThread_GetInfo(void) return NULL; } #else - Py_INCREF(Py_None); - value = Py_None; + value = Py_NewRef(Py_None); #endif PyStructSequence_SET_ITEM(threadinfo, pos++, value); diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index c310d72abd2d58916607b880da514499d0b8ff89..1c5b320813af83dbf803475e2003fa3a6b6f5425 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -7,7 +7,9 @@ #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR) #define destructor xxdestructor #endif -#include <pthread.h> +#ifndef HAVE_PTHREAD_STUBS +# include <pthread.h> +#endif #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR) #undef destructor #endif diff --git a/Python/thread_pthread_stubs.h b/Python/thread_pthread_stubs.h new file mode 100644 index 0000000000000000000000000000000000000000..8b80c0f87e25097b0efde717c8d289f043f635c9 --- /dev/null +++ b/Python/thread_pthread_stubs.h @@ -0,0 +1,185 @@ +#include "cpython/pthread_stubs.h" + +// mutex +int +pthread_mutex_init(pthread_mutex_t *restrict mutex, + const pthread_mutexattr_t *restrict attr) +{ + return 0; +} + +int +pthread_mutex_destroy(pthread_mutex_t *mutex) +{ + return 0; +} + +int +pthread_mutex_trylock(pthread_mutex_t *mutex) +{ + return 0; +} + +int +pthread_mutex_lock(pthread_mutex_t *mutex) +{ + return 0; +} + +int +pthread_mutex_unlock(pthread_mutex_t *mutex) +{ + return 0; +} + +// condition +int +pthread_cond_init(pthread_cond_t *restrict cond, + const pthread_condattr_t *restrict attr) +{ + return 0; +} + +PyAPI_FUNC(int)pthread_cond_destroy(pthread_cond_t *cond) +{ + return 0; +} + +int +pthread_cond_wait(pthread_cond_t *restrict cond, + pthread_mutex_t *restrict mutex) +{ + return 0; +} + +int +pthread_cond_timedwait(pthread_cond_t *restrict cond, + pthread_mutex_t *restrict mutex, + const struct timespec *restrict abstime) +{ + return 0; +} + +int +pthread_cond_signal(pthread_cond_t *cond) +{ + return 0; +} + +int +pthread_condattr_init(pthread_condattr_t *attr) +{ + return 0; +} + +int +pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id) +{ + return 0; +} + +// pthread +int +pthread_create(pthread_t *restrict thread, + const pthread_attr_t *restrict attr, + void *(*start_routine)(void *), + void *restrict arg) +{ + return EAGAIN; +} + +int +pthread_detach(pthread_t thread) +{ + return 0; +} + +PyAPI_FUNC(pthread_t) pthread_self(void) +{ + return 0; +} + +int +pthread_exit(void *retval) +{ + exit(0); +} + +int +pthread_attr_init(pthread_attr_t *attr) +{ + return 0; +} + +int +pthread_attr_setstacksize( + pthread_attr_t *attr, size_t stacksize) +{ + return 0; +} + +int +pthread_attr_destroy(pthread_attr_t *attr) +{ + return 0; +} + +// pthread_key +typedef struct { + bool in_use; + void *value; +} py_tls_entry; + +static py_tls_entry py_tls_entries[PTHREAD_KEYS_MAX] = {0}; + +int +pthread_key_create(pthread_key_t *key, void (*destr_function)(void *)) +{ + if (!key) { + return EINVAL; + } + if (destr_function != NULL) { + Py_FatalError("pthread_key_create destructor is not supported"); + } + for (pthread_key_t idx = 0; idx < PTHREAD_KEYS_MAX; idx++) { + if (!py_tls_entries[idx].in_use) { + py_tls_entries[idx].in_use = true; + *key = idx; + return 0; + } + } + return EAGAIN; +} + +int +pthread_key_delete(pthread_key_t key) +{ + if (key < 0 || key >= PTHREAD_KEYS_MAX || !py_tls_entries[key].in_use) { + return EINVAL; + } + py_tls_entries[key].in_use = false; + py_tls_entries[key].value = NULL; + return 0; +} + + +void * +pthread_getspecific(pthread_key_t key) { + if (key < 0 || key >= PTHREAD_KEYS_MAX || !py_tls_entries[key].in_use) { + return NULL; + } + return py_tls_entries[key].value; +} + +int +pthread_setspecific(pthread_key_t key, const void *value) +{ + if (key < 0 || key >= PTHREAD_KEYS_MAX || !py_tls_entries[key].in_use) { + return EINVAL; + } + py_tls_entries[key].value = (void *)value; + return 0; +} + +// let thread_pthread define the Python API +#include "thread_pthread.h" diff --git a/Python/traceback.c b/Python/traceback.c index 439689b32aea8ab833f72e50eaba700482064ba1..de658b9103180ea0eed5044f8ccdcf6558994067 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -592,7 +592,6 @@ _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent, * Traceback (most recent call last): * File "/home/isidentical/cpython/cpython/t.py", line 10, in <module> * add_values(1, 2, 'x', 3, 4) - * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * File "/home/isidentical/cpython/cpython/t.py", line 2, in add_values * return a + b + c + d + e * ~~~~~~^~~ @@ -736,7 +735,7 @@ print_error_location_carets(PyObject *f, int offset, Py_ssize_t start_offset, Py int special_chars = (left_end_offset != -1 || right_start_offset != -1); const char *str; while (++offset <= end_offset) { - if (offset <= start_offset || offset > end_offset) { + if (offset <= start_offset) { str = " "; } else if (special_chars && left_end_offset < offset && offset <= right_start_offset) { str = secondary; @@ -792,6 +791,7 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen int code_offset = tb->tb_lasti; PyCodeObject* code = frame->f_frame->f_code; + const Py_ssize_t source_line_len = PyUnicode_GET_LENGTH(source_line); int start_line; int end_line; @@ -813,7 +813,7 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen // // ERROR LINE ERROR LINE ERROR LINE ERROR LINE ERROR LINE ERROR LINE ERROR LINE // ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^~~~~~~~~~~~~~~~~~~~ - // | |-> left_end_offset | |-> left_offset + // | |-> left_end_offset | |-> end_offset // |-> start_offset |-> right_start_offset // // In general we will only have (start_offset, end_offset) but we can gather more information @@ -822,6 +822,9 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen // the different ranges (primary_error_char and secondary_error_char). If we cannot obtain the // AST information or we cannot identify special ranges within it, then left_end_offset and // right_end_offset will be set to -1. + // + // To keep the column indicators pertinent, they are not shown when the primary character + // spans the whole line. // Convert the utf-8 byte offset to the actual character offset so we print the right number of carets. assert(source_line); @@ -859,7 +862,7 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen goto done; } - Py_ssize_t i = PyUnicode_GET_LENGTH(source_line); + Py_ssize_t i = source_line_len; while (--i >= 0) { if (!IS_WHITESPACE(source_line_str[i])) { break; @@ -869,6 +872,13 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen end_offset = i + 1; } + // Elide indicators if primary char spans the frame line + Py_ssize_t stripped_line_len = source_line_len - truncation - _TRACEBACK_SOURCE_LINE_INDENT; + bool has_secondary_ranges = (left_end_offset != -1 || right_start_offset != -1); + if (end_offset - start_offset == stripped_line_len && !has_secondary_ranges) { + goto done; + } + if (_Py_WriteIndentedMargin(margin_indent, margin, f) < 0) { err = -1; goto done; diff --git a/Tools/c-analyzer/c_common/tables.py b/Tools/c-analyzer/c_common/tables.py index 130be6beba5f81579a7c169ba999fc28fbda6fb1..fe8e8cf473de4f6aa3f4d28373dfe7b5c5353643 100644 --- a/Tools/c-analyzer/c_common/tables.py +++ b/Tools/c-analyzer/c_common/tables.py @@ -1,3 +1,4 @@ +from collections import namedtuple import csv import re import textwrap @@ -225,7 +226,11 @@ def _normalize_table_file_props(header, sep): def resolve_columns(specs): if isinstance(specs, str): specs = specs.replace(',', ' ').strip().split() - return _resolve_colspecs(specs) + resolved = [] + for raw in specs: + column = ColumnSpec.from_raw(raw) + resolved.append(column) + return resolved def build_table(specs, *, sep=' ', defaultwidth=None): @@ -233,37 +238,145 @@ def build_table(specs, *, sep=' ', defaultwidth=None): return _build_table(columns, sep=sep, defaultwidth=defaultwidth) -_COLSPEC_RE = re.compile(textwrap.dedent(r''' - ^ - (?: - \[ - ( - (?: [^\s\]] [^\]]* )? - [^\s\]] - ) # <label> - ] - )? - ( \w+ ) # <field> - (?: +class ColumnSpec(namedtuple('ColumnSpec', 'field label fmt')): + + REGEX = re.compile(textwrap.dedent(r''' + ^ (?: - : - ( [<^>] ) # <align> - ( \d+ ) # <width1> - ) - | + \[ + ( + (?: [^\s\]] [^\]]* )? + [^\s\]] + ) # <label> + ] + )? + ( [-\w]+ ) # <field> (?: (?: : - ( \d+ ) # <width2> - )? + ( [<^>] ) # <align> + ( \d+ )? # <width1> + ) + | (?: - : - ( .*? ) # <fmt> - )? - ) - )? - $ -'''), re.VERBOSE) + (?: + : + ( \d+ ) # <width2> + )? + (?: + : + ( .*? ) # <fmt> + )? + ) + )? + $ + '''), re.VERBOSE) + + @classmethod + def from_raw(cls, raw): + if not raw: + raise ValueError('missing column spec') + elif isinstance(raw, cls): + return raw + + if isinstance(raw, str): + *values, _ = cls._parse(raw) + else: + *values, _ = cls._normalize(raw) + if values is None: + raise ValueError(f'unsupported column spec {raw!r}') + return cls(*values) + + @classmethod + def parse(cls, specstr): + parsed = cls._parse(specstr) + if not parsed: + return None + *values, _ = parsed + return cls(*values) + + @classmethod + def _parse(cls, specstr): + m = cls.REGEX.match(specstr) + if not m: + return None + (label, field, + align, width1, + width2, fmt, + ) = m.groups() + if not label: + label = field + if fmt: + assert not align and not width1, (specstr,) + _parsed = _parse_fmt(fmt) + if not _parsed: + raise NotImplementedError + elif width2: + width, _ = _parsed + if width != int(width2): + raise NotImplementedError(specstr) + elif width2: + fmt = width2 + width = int(width2) + else: + assert not fmt, (fmt, specstr) + if align: + width = int(width1) if width1 else len(label) + fmt = f'{align}{width}' + else: + width = None + return field, label, fmt, width + + @classmethod + def _normalize(cls, spec): + if len(spec) == 1: + raw, = spec + raise NotImplementedError + return _resolve_column(raw) + + if len(spec) == 4: + label, field, width, fmt = spec + if width: + if not fmt: + fmt = str(width) + elif _parse_fmt(fmt)[0] != width: + raise ValueError(f'width mismatch in {spec}') + elif len(raw) == 3: + label, field, fmt = spec + if not field: + label, field = None, label + elif not isinstance(field, str) or not field.isidentifier(): + # XXX This doesn't seem right... + fmt = f'{field}:{fmt}' if fmt else field + label, field = None, label + elif len(raw) == 2: + label = None + field, fmt = raw + if not field: + field, fmt = fmt, None + elif not field.isidentifier() or fmt.isidentifier(): + label, field = field, fmt + else: + raise NotImplementedError + + fmt = f':{fmt}' if fmt else '' + if label: + return cls._parse(f'[{label}]{field}{fmt}') + else: + return cls._parse(f'{field}{fmt}') + + @property + def width(self): + if not self.fmt: + return None + parsed = _parse_fmt(self.fmt) + if not parsed: + return None + width, _ = parsed + return width + + def resolve_width(self, default=None): + return _resolve_width(self.width, self.fmt, self.label, default) def _parse_fmt(fmt): @@ -272,100 +385,31 @@ def _parse_fmt(fmt): width = fmt[1:] if width.isdigit(): return int(width), align - return None, None + elif fmt.isdigit(): + return int(fmt), '<' + return None -def _parse_colspec(raw): - m = _COLSPEC_RE.match(raw) - if not m: - return None - label, field, align, width1, width2, fmt = m.groups() - if not label: - label = field - if width1: - width = None - fmt = f'{align}{width1}' - elif width2: - width = int(width2) - if fmt: - _width, _ = _parse_fmt(fmt) - if _width == width: - width = None - else: - width = None - return field, label, width, fmt - - -def _normalize_colspec(spec): - if len(spec) == 1: - raw, = spec - return _resolve_column(raw) - - if len(spec) == 4: - label, field, width, fmt = spec - if width: - fmt = f'{width}:{fmt}' if fmt else width - elif len(raw) == 3: - label, field, fmt = spec - if not field: - label, field = None, label - elif not isinstance(field, str) or not field.isidentifier(): - fmt = f'{field}:{fmt}' if fmt else field - label, field = None, label - elif len(raw) == 2: - label = None - field, fmt = raw - if not field: - field, fmt = fmt, None - elif not field.isidentifier() or fmt.isidentifier(): - label, field = field, fmt - else: - raise NotImplementedError - - fmt = f':{fmt}' if fmt else '' - if label: - return _parse_colspec(f'[{label}]{field}{fmt}') - else: - return _parse_colspec(f'{field}{fmt}') - - -def _resolve_colspec(raw): - if isinstance(raw, str): - spec = _parse_colspec(raw) - else: - spec = _normalize_colspec(raw) - if spec is None: - raise ValueError(f'unsupported column spec {raw!r}') - return spec - - -def _resolve_colspecs(columns): - parsed = [] - for raw in columns: - column = _resolve_colspec(raw) - parsed.append(column) - return parsed - - -def _resolve_width(spec, defaultwidth): - _, label, width, fmt = spec +def _resolve_width(width, fmt, label, default): if width: if not isinstance(width, int): raise NotImplementedError return width - elif width and fmt: - width, _ = _parse_fmt(fmt) - if width: - return width - - if not defaultwidth: + elif fmt: + parsed = _parse_fmt(fmt) + if parsed: + width, _ = parsed + if width: + return width + + if not default: return WIDTH - elif not hasattr(defaultwidth, 'get'): - return defaultwidth or WIDTH - - defaultwidths = defaultwidth - defaultwidth = defaultwidths.get(None) or WIDTH - return defaultwidths.get(label) or defaultwidth + elif hasattr(default, 'get'): + defaults = default + default = defaults.get(None) or WIDTH + return defaults.get(label) or default + else: + return default or WIDTH def _build_table(columns, *, sep=' ', defaultwidth=None): @@ -373,16 +417,13 @@ def _build_table(columns, *, sep=' ', defaultwidth=None): div = [] rowfmt = [] for spec in columns: - label, field, _, colfmt = spec - width = _resolve_width(spec, defaultwidth) - if colfmt: - colfmt = f':{colfmt}' - else: - colfmt = f':{width}' + width = spec.resolve_width(defaultwidth) + colfmt = spec.fmt + colfmt = f':{spec.fmt}' if spec.fmt else f':{width}' - header.append(f' {{:^{width}}} '.format(label)) + header.append(f' {{:^{width}}} '.format(spec.label)) div.append('-' * (width + 2)) - rowfmt.append(f' {{{field}{colfmt}}} ') + rowfmt.append(f' {{{spec.field}{colfmt}}} ') return ( sep.join(header), sep.join(div), diff --git a/Tools/c-analyzer/c_parser/preprocessor/__init__.py b/Tools/c-analyzer/c_parser/preprocessor/__init__.py index e38176fee31fac7bee0b3c20681f0a24c1943cff..c154137bf42f0d99609193bf0e36a7c5df78162e 100644 --- a/Tools/c-analyzer/c_parser/preprocessor/__init__.py +++ b/Tools/c-analyzer/c_parser/preprocessor/__init__.py @@ -1,7 +1,9 @@ import contextlib -import distutils.ccompiler import logging +import os import os.path +import re +import sys from c_common.fsutil import match_glob as _match_glob from c_common.tables import parse_table as _parse_table @@ -168,9 +170,17 @@ def handling_errors(ignore_exc=None, *, log_err=None): } +def _get_default_compiler(): + if re.match('cygwin.*', sys.platform) is not None: + return 'unix' + if os.name == 'nt': + return 'msvc' + return 'unix' + + def _get_preprocessor(tool): if tool is True: - tool = distutils.ccompiler.get_default_compiler() + tool = _get_default_compiler() preprocess = _COMPILERS.get(tool) if preprocess is None: raise ValueError(f'unsupported tool {tool}') diff --git a/Tools/c-analyzer/cpython/__main__.py b/Tools/c-analyzer/cpython/__main__.py index be331d50427d53300d52d1fe627678fd7832f6d6..2b9e4233b95ac46a24390aa7fe9384f40ba4a6d8 100644 --- a/Tools/c-analyzer/cpython/__main__.py +++ b/Tools/c-analyzer/cpython/__main__.py @@ -20,7 +20,7 @@ import c_analyzer.__main__ as c_analyzer import c_analyzer as _c_analyzer from c_analyzer.info import UNKNOWN -from . import _analyzer, _capi, _files, _parser, REPO_ROOT +from . import _analyzer, _builtin_types, _capi, _files, _parser, REPO_ROOT logger = logging.getLogger(__name__) @@ -325,6 +325,47 @@ def cmd_capi(filenames=None, *, print(line) +def _cli_builtin_types(parser): + parser.add_argument('--format', dest='fmt', default='table') +# parser.add_argument('--summary', dest='format', +# action='store_const', const='summary') + def process_format(args, *, argv=None): + orig = args.fmt + args.fmt = _builtin_types.resolve_format(args.fmt) + if isinstance(args.fmt, str): + if args.fmt not in _builtin_types._FORMATS: + parser.error(f'unsupported format {orig!r}') + + parser.add_argument('--include-modules', dest='showmodules', + action='store_true') + def process_modules(args, *, argv=None): + pass + + return [ + process_format, + process_modules, + ] + + +def cmd_builtin_types(fmt, *, + showmodules=False, + verbosity=VERBOSITY, + ): + render = _builtin_types.get_renderer(fmt) + types = _builtin_types.iter_builtin_types() + match = _builtin_types.resolve_matcher(showmodules) + if match: + types = (t for t in types if match(t, log=lambda msg: logger.log(1, msg))) + + lines = render( + types, +# verbose=verbosity > VERBOSITY, + ) + print() + for line in lines: + print(line) + + # We do not define any other cmd_*() handlers here, # favoring those defined elsewhere. @@ -354,6 +395,11 @@ def cmd_capi(filenames=None, *, [_cli_capi], cmd_capi, ), + 'builtin-types': ( + 'show the builtin types', + [_cli_builtin_types], + cmd_builtin_types, + ), } diff --git a/Tools/c-analyzer/cpython/_builtin_types.py b/Tools/c-analyzer/cpython/_builtin_types.py new file mode 100644 index 0000000000000000000000000000000000000000..faa0b7a82a8bb4e19a2e91e79706ff4cc890d1dc --- /dev/null +++ b/Tools/c-analyzer/cpython/_builtin_types.py @@ -0,0 +1,365 @@ +from collections import namedtuple +import os.path +import re +import textwrap + +from c_common import tables +from . import REPO_ROOT +from ._files import iter_header_files, iter_filenames + + +CAPI_PREFIX = os.path.join('Include', '') +INTERNAL_PREFIX = os.path.join('Include', 'internal', '') + +REGEX = re.compile(textwrap.dedent(rf''' + (?: + ^ + (?: + (?: + (?: + (?: + (?: + ( static ) # <static> + \s+ + | + ( extern ) # <extern> + \s+ + )? + PyTypeObject \s+ + ) + | + (?: + ( PyAPI_DATA ) # <capi> + \s* [(] \s* PyTypeObject \s* [)] \s* + ) + ) + (\w+) # <name> + \s* + (?: + (?: + ( = \s* {{ ) # <def> + $ + ) + | + ( ; ) # <decl> + ) + ) + | + (?: + # These are specific to Objects/exceptions.c: + (?: + SimpleExtendsException + | + MiddlingExtendsException + | + ComplexExtendsException + ) + \( \w+ \s* , \s* + ( \w+ ) # <excname> + \s* , + ) + ) + ) +'''), re.VERBOSE) + + +def _parse_line(line): + m = re.match(REGEX, line) + if not m: + return None + (static, extern, capi, + name, + def_, decl, + excname, + ) = m.groups() + if def_: + isdecl = False + if extern or capi: + raise NotImplementedError(line) + kind = 'static' if static else None + elif excname: + name = f'_PyExc_{excname}' + isdecl = False + kind = 'static' + else: + isdecl = True + if static: + kind = 'static' + elif extern: + kind = 'extern' + elif capi: + kind = 'capi' + else: + kind = None + return name, isdecl, kind + + +class BuiltinTypeDecl(namedtuple('BuiltinTypeDecl', 'file lno name kind')): + + KINDS = { + 'static', + 'extern', + 'capi', + 'forward', + } + + @classmethod + def from_line(cls, line, filename, lno): + # This is similar to ._capi.CAPIItem.from_line(). + parsed = _parse_line(line) + if not parsed: + return None + name, isdecl, kind = parsed + if not isdecl: + return None + return cls.from_parsed(name, kind, filename, lno) + + @classmethod + def from_parsed(cls, name, kind, filename, lno): + if not kind: + kind = 'forward' + return cls.from_values(filename, lno, name, kind) + + @classmethod + def from_values(cls, filename, lno, name, kind): + if kind not in cls.KINDS: + raise ValueError(f'unsupported kind {kind!r}') + self = cls(filename, lno, name, kind) + if self.kind not in ('extern', 'capi') and self.api: + raise NotImplementedError(self) + elif self.kind == 'capi' and not self.api: + raise NotImplementedError(self) + return self + + @property + def relfile(self): + return self.file[len(REPO_ROOT) + 1:] + + @property + def api(self): + return self.relfile.startswith(CAPI_PREFIX) + + @property + def internal(self): + return self.relfile.startswith(INTERNAL_PREFIX) + + @property + def private(self): + if not self.name.startswith('_'): + return False + return self.api and not self.internal + + @property + def public(self): + if self.kind != 'capi': + return False + return not self.internal and not self.private + + +class BuiltinTypeInfo(namedtuple('BuiltinTypeInfo', 'file lno name static decl')): + + @classmethod + def from_line(cls, line, filename, lno, *, decls=None): + parsed = _parse_line(line) + if not parsed: + return None + name, isdecl, kind = parsed + if isdecl: + return None + return cls.from_parsed(name, kind, filename, lno, decls=decls) + + @classmethod + def from_parsed(cls, name, kind, filename, lno, *, decls=None): + if not kind: + static = False + elif kind == 'static': + static = True + else: + raise NotImplementedError((filename, line, kind)) + decl = decls.get(name) if decls else None + return cls(filename, lno, name, static, decl) + + @property + def relfile(self): + return self.file[len(REPO_ROOT) + 1:] + + @property + def exported(self): + return not self.static + + @property + def api(self): + if not self.decl: + return False + return self.decl.api + + @property + def internal(self): + if not self.decl: + return False + return self.decl.internal + + @property + def private(self): + if not self.decl: + return False + return self.decl.private + + @property + def public(self): + if not self.decl: + return False + return self.decl.public + + @property + def inmodule(self): + return self.relfile.startswith('Modules' + os.path.sep) + + def render_rowvalues(self, kinds): + row = { + 'name': self.name, + **{k: '' for k in kinds}, + 'filename': f'{self.relfile}:{self.lno}', + } + if self.static: + kind = 'static' + else: + if self.internal: + kind = 'internal' + elif self.private: + kind = 'private' + elif self.public: + kind = 'public' + else: + kind = 'global' + row['kind'] = kind + row[kind] = kind + return row + + +def _ensure_decl(decl, decls): + prev = decls.get(decl.name) + if prev: + if decl.kind == 'forward': + return None + if prev.kind != 'forward': + if decl.kind == prev.kind and decl.file == prev.file: + assert decl.lno != prev.lno, (decl, prev) + return None + raise NotImplementedError(f'duplicate {decl} (was {prev}') + decls[decl.name] = decl + + +def iter_builtin_types(filenames=None): + decls = {} + seen = set() + for filename in iter_header_files(): + seen.add(filename) + with open(filename) as infile: + for lno, line in enumerate(infile, 1): + decl = BuiltinTypeDecl.from_line(line, filename, lno) + if not decl: + continue + _ensure_decl(decl, decls) + srcfiles = [] + for filename in iter_filenames(): + if filename.endswith('.c'): + srcfiles.append(filename) + continue + if filename in seen: + continue + with open(filename) as infile: + for lno, line in enumerate(infile, 1): + decl = BuiltinTypeDecl.from_line(line, filename, lno) + if not decl: + continue + _ensure_decl(decl, decls) + + for filename in srcfiles: + with open(filename) as infile: + localdecls = {} + for lno, line in enumerate(infile, 1): + parsed = _parse_line(line) + if not parsed: + continue + name, isdecl, kind = parsed + if isdecl: + decl = BuiltinTypeDecl.from_parsed(name, kind, filename, lno) + if not decl: + raise NotImplementedError((filename, line)) + _ensure_decl(decl, localdecls) + else: + builtin = BuiltinTypeInfo.from_parsed( + name, kind, filename, lno, + decls=decls if name in decls else localdecls) + if not builtin: + raise NotImplementedError((filename, line)) + yield builtin + + +def resolve_matcher(showmodules=False): + def match(info, *, log=None): + if not info.inmodule: + return True + if log is not None: + log(f'ignored {info.name!r}') + return False + return match + + +################################## +# CLI rendering + +def resolve_format(fmt): + if not fmt: + return 'table' + elif isinstance(fmt, str) and fmt in _FORMATS: + return fmt + else: + raise NotImplementedError(fmt) + + +def get_renderer(fmt): + fmt = resolve_format(fmt) + if isinstance(fmt, str): + try: + return _FORMATS[fmt] + except KeyError: + raise ValueError(f'unsupported format {fmt!r}') + else: + raise NotImplementedError(fmt) + + +def render_table(types): + types = sorted(types, key=(lambda t: t.name)) + colspecs = tables.resolve_columns( + 'name:<33 static:^ global:^ internal:^ private:^ public:^ filename:<30') + header, div, rowfmt = tables.build_table(colspecs) + leader = ' ' * sum(c.width+2 for c in colspecs[:3]) + ' ' + yield leader + f'{"API":^29}' + yield leader + '-' * 29 + yield header + yield div + kinds = [c[0] for c in colspecs[1:-1]] + counts = {k: 0 for k in kinds} + base = {k: '' for k in kinds} + for t in types: + row = t.render_rowvalues(kinds) + kind = row['kind'] + yield rowfmt.format(**row) + counts[kind] += 1 + yield '' + yield f'total: {sum(counts.values()):>3}' + for kind in kinds: + yield f' {kind:>10}: {counts[kind]:>3}' + + +def render_repr(types): + for t in types: + yield repr(t) + + +_FORMATS = { + 'table': render_table, + 'repr': render_repr, +} diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index c92f64df1c5de5eff2d5f2e212b2769952e2e2c6..bc9d6aabb0936b9494be67510f7661ce78a03646 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -7,7 +7,7 @@ filename funcname name reason # global objects to fix in core code #----------------------- -# static types +# exported builtin types (C-API) Objects/boolobject.c - PyBool_Type - Objects/bytearrayobject.c - PyByteArrayIter_Type - @@ -18,8 +18,6 @@ Objects/capsule.c - PyCapsule_Type - Objects/cellobject.c - PyCell_Type - Objects/classobject.c - PyInstanceMethod_Type - Objects/classobject.c - PyMethod_Type - -Objects/codeobject.c - _PyLineIterator - -Objects/codeobject.c - _PyPositionsIterator - Objects/codeobject.c - PyCode_Type - Objects/complexobject.c - PyComplex_Type - Objects/descrobject.c - PyClassMethodDescr_Type - @@ -42,16 +40,12 @@ Objects/dictobject.c - PyDictValues_Type - Objects/dictobject.c - PyDict_Type - Objects/enumobject.c - PyEnum_Type - Objects/enumobject.c - PyReversed_Type - -Objects/exceptions.c - _PyExc_BaseExceptionGroup - -Objects/exceptions.c - _PyExc_EncodingWarning - Objects/fileobject.c - PyStdPrinter_Type - -Objects/floatobject.c - FloatInfoType - Objects/floatobject.c - PyFloat_Type - Objects/frameobject.c - PyFrame_Type - Objects/funcobject.c - PyClassMethod_Type - Objects/funcobject.c - PyFunction_Type - Objects/funcobject.c - PyStaticMethod_Type - -Objects/genericaliasobject.c - _Py_GenericAliasIterType - Objects/genericaliasobject.c - Py_GenericAliasType - Objects/genobject.c - PyAsyncGen_Type - Objects/genobject.c - PyCoro_Type - @@ -63,13 +57,10 @@ Objects/genobject.c - _PyCoroWrapper_Type - Objects/interpreteridobject.c - _PyInterpreterID_Type - Objects/iterobject.c - PyCallIter_Type - Objects/iterobject.c - PySeqIter_Type - -Objects/iterobject.c - _PyAnextAwaitable_Type - Objects/listobject.c - PyListIter_Type - Objects/listobject.c - PyListRevIter_Type - Objects/listobject.c - PyList_Type - -Objects/longobject.c - Int_InfoType - Objects/longobject.c - PyLong_Type - -Objects/memoryobject.c - _PyMemoryIter_Type - Objects/memoryobject.c - PyMemoryView_Type - Objects/memoryobject.c - _PyManagedBuffer_Type - Objects/methodobject.c - PyCFunction_Type - @@ -91,7 +82,6 @@ Objects/rangeobject.c - PyRange_Type - Objects/setobject.c - PyFrozenSet_Type - Objects/setobject.c - PySetIter_Type - Objects/setobject.c - PySet_Type - -Objects/setobject.c - _PySetDummy_Type - Objects/sliceobject.c - PyEllipsis_Type - Objects/sliceobject.c - PySlice_Type - Objects/tupleobject.c - PyTupleIter_Type - @@ -99,11 +89,8 @@ Objects/tupleobject.c - PyTuple_Type - Objects/typeobject.c - PyBaseObject_Type - Objects/typeobject.c - PySuper_Type - Objects/typeobject.c - PyType_Type - -Objects/unicodeobject.c - EncodingMapType - Objects/unicodeobject.c - PyUnicodeIter_Type - Objects/unicodeobject.c - PyUnicode_Type - -Objects/unionobject.c - _PyUnion_Type - -Objects/unionobject.c - _Py_UnionType - Objects/weakrefobject.c - _PyWeakref_CallableProxyType - Objects/weakrefobject.c - _PyWeakref_ProxyType - Objects/weakrefobject.c - _PyWeakref_RefType - @@ -113,8 +100,23 @@ Python/bltinmodule.c - PyZip_Type - Python/context.c - PyContextToken_Type - Python/context.c - PyContextVar_Type - Python/context.c - PyContext_Type - +Python/traceback.c - PyTraceBack_Type - + +#----------------------- +# other exported builtin types + +# Not in a .h file: +Objects/codeobject.c - _PyLineIterator - +# Not in a .h file: +Objects/codeobject.c - _PyPositionsIterator - +Objects/genericaliasobject.c - _Py_GenericAliasIterType - +# Not in a .h file: +Objects/iterobject.c - _PyAnextAwaitable_Type - +# Not in a .h file: +Objects/memoryobject.c - _PyMemoryIter_Type - +#Objects/unicodeobject.c - _PyUnicodeASCIIIter_Type - +Objects/unionobject.c - _PyUnion_Type - Python/context.c - _PyContextTokenMissing_Type - -Python/errors.c - UnraisableHookArgsType - Python/hamt.c - _PyHamtItems_Type - Python/hamt.c - _PyHamtKeys_Type - Python/hamt.c - _PyHamtValues_Type - @@ -123,17 +125,32 @@ Python/hamt.c - _PyHamt_BitmapNode_Type - Python/hamt.c - _PyHamt_CollisionNode_Type - Python/hamt.c - _PyHamt_Type - Python/symtable.c - PySTEntry_Type - + +#----------------------- +# private static builtin types + +Objects/setobject.c - _PySetDummy_Type - +Objects/unicodeobject.c - EncodingMapType - +#Objects/unicodeobject.c - PyFieldNameIter_Type - +#Objects/unicodeobject.c - PyFormatterIter_Type - + +#----------------------- +# static builtin structseq + +Objects/floatobject.c - FloatInfoType - +Objects/longobject.c - Int_InfoType - +Python/errors.c - UnraisableHookArgsType - Python/sysmodule.c - AsyncGenHooksType - Python/sysmodule.c - FlagsType - Python/sysmodule.c - Hash_InfoType - Python/sysmodule.c - VersionInfoType - Python/thread.c - ThreadInfoType - -Python/traceback.c - PyTraceBack_Type - #----------------------- # builtin exception types Objects/exceptions.c - _PyExc_BaseException - +Objects/exceptions.c - _PyExc_BaseExceptionGroup - Objects/exceptions.c - _PyExc_UnicodeEncodeError - Objects/exceptions.c - _PyExc_UnicodeDecodeError - Objects/exceptions.c - _PyExc_UnicodeTranslateError - @@ -197,9 +214,11 @@ Objects/exceptions.c - _PyExc_ImportWarning - Objects/exceptions.c - _PyExc_UnicodeWarning - Objects/exceptions.c - _PyExc_BytesWarning - Objects/exceptions.c - _PyExc_ResourceWarning - +Objects/exceptions.c - _PyExc_EncodingWarning - Objects/exceptions.c - PyExc_EnvironmentError - Objects/exceptions.c - PyExc_IOError - Objects/exceptions.c - PyExc_BaseException - +Objects/exceptions.c - PyExc_BaseExceptionGroup - Objects/exceptions.c - PyExc_Exception - Objects/exceptions.c - PyExc_TypeError - Objects/exceptions.c - PyExc_StopAsyncIteration - @@ -263,6 +282,7 @@ Objects/exceptions.c - PyExc_ImportWarning - Objects/exceptions.c - PyExc_UnicodeWarning - Objects/exceptions.c - PyExc_BytesWarning - Objects/exceptions.c - PyExc_ResourceWarning - +Objects/exceptions.c - PyExc_EncodingWarning - #----------------------- # singletons @@ -354,8 +374,6 @@ Objects/unicodeobject.c - static_strings - # other # initialized once -Objects/exceptions.c - PyExc_BaseExceptionGroup - -Objects/exceptions.c - PyExc_EncodingWarning - # XXX This should have been found by the analyzer but wasn't: Python/context.c - _token_missing - # XXX This should have been found by the analyzer but wasn't: diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 0041363c46be2fb97df75ee74085120c74adb02a..36bfc7050507e560262812bbb5c41285a03dddc0 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -3826,17 +3826,6 @@ def render(self, function, data): add_c_return_converter(CReturnConverter, 'object') -class NoneType_return_converter(CReturnConverter): - def render(self, function, data): - self.declare(data) - data.return_conversion.append(''' -if (_return_value != Py_None) { - goto exit; -} -return_value = Py_None; -Py_INCREF(Py_None); -'''.strip()) - class bool_return_converter(CReturnConverter): type = 'int' diff --git a/Tools/scripts/check_extension_modules.py b/Tools/scripts/check_extension_modules.py index b3f43abf637bdcb138823a346eebd7d7fce27d1d..59239c62e2ef347f7efaf4466f423db5c73fb193 100644 --- a/Tools/scripts/check_extension_modules.py +++ b/Tools/scripts/check_extension_modules.py @@ -130,10 +130,11 @@ class ModuleChecker: pybuilddir_txt = "pybuilddir.txt" setup_files = ( - SRC_DIR / "Modules/Setup", + # see end of configure.ac "Modules/Setup.local", - "Modules/Setup.bootstrap", "Modules/Setup.stdlib", + "Modules/Setup.bootstrap", + SRC_DIR / "Modules/Setup", ) def __init__(self, cross_compiling: bool = False, strict: bool = False): @@ -308,12 +309,6 @@ def get_sysconfig_modules(self) -> Iterable[ModuleInfo]: MODBUILT_NAMES: modules in *static* block MODSHARED_NAMES: modules in *shared* block MODDISABLED_NAMES: modules in *disabled* block - - Modules built by setup.py addext() have a MODULE_{modname}_STATE entry, - but are not listed in MODSHARED_NAMES. - - Modules built by old-style setup.py add() have neither a MODULE_{modname} - entry nor an entry in MODSHARED_NAMES. """ moddisabled = set(sysconfig.get_config_var("MODDISABLED_NAMES").split()) if self.cross_compiling: diff --git a/Tools/scripts/deepfreeze.py b/Tools/scripts/deepfreeze.py index f9fd4e36a81baa93200f1e6d6096f0505a82c6ff..62eeafab0848cbcae7e629d24f904843400d2e07 100644 --- a/Tools/scripts/deepfreeze.py +++ b/Tools/scripts/deepfreeze.py @@ -359,7 +359,12 @@ def generate_complex(self, name: str, z: complex) -> str: return f"&{name}.ob_base" def generate_frozenset(self, name: str, fs: FrozenSet[object]) -> str: - ret = self.generate_tuple(name, tuple(sorted(fs))) + try: + fs = sorted(fs) + except TypeError: + # frozen set with incompatible types, fallback to repr() + fs = sorted(fs, key=repr) + ret = self.generate_tuple(name, tuple(fs)) self.write("// TODO: The above tuple should be a frozenset") return ret diff --git a/Tools/scripts/generate_global_objects.py b/Tools/scripts/generate_global_objects.py index 27e3530f38574da354b980b959b8195ebc299776..f3a11f5f7e5969457205672c9d953cef1fecdca8 100644 --- a/Tools/scripts/generate_global_objects.py +++ b/Tools/scripts/generate_global_objects.py @@ -250,6 +250,7 @@ def generate_runtime_init(identifiers, strings): # Generate the file. with open_for_changes(filename, orig) as outfile: + immortal_objects = [] printer = Printer(outfile) printer.write(before) printer.write(START) @@ -259,31 +260,39 @@ def generate_runtime_init(identifiers, strings): with printer.block('.small_ints =', ','): for i in range(-nsmallnegints, nsmallposints): printer.write(f'_PyLong_DIGIT_INIT({i}),') + immortal_objects.append(f'(PyObject *)&_Py_SINGLETON(small_ints)[_PY_NSMALLNEGINTS + {i}]') printer.write('') # Global bytes objects. printer.write('.bytes_empty = _PyBytes_SIMPLE_INIT(0, 0),') + immortal_objects.append(f'(PyObject *)&_Py_SINGLETON(bytes_empty)') with printer.block('.bytes_characters =', ','): for i in range(256): printer.write(f'_PyBytes_CHAR_INIT({i}),') + immortal_objects.append(f'(PyObject *)&_Py_SINGLETON(bytes_characters)[{i}]') printer.write('') # Global strings. with printer.block('.strings =', ','): with printer.block('.literals =', ','): for literal, name in sorted(strings.items(), key=lambda x: x[1]): printer.write(f'INIT_STR({name}, "{literal}"),') + immortal_objects.append(f'(PyObject *)&_Py_STR({name})') with printer.block('.identifiers =', ','): for name in sorted(identifiers): assert name.isidentifier(), name printer.write(f'INIT_ID({name}),') + immortal_objects.append(f'(PyObject *)&_Py_ID({name})') with printer.block('.ascii =', ','): for i in range(128): printer.write(f'_PyASCIIObject_INIT("\\x{i:02x}"),') + immortal_objects.append(f'(PyObject *)&_Py_SINGLETON(strings).ascii[{i}]') with printer.block('.latin1 =', ','): for i in range(128, 256): printer.write(f'_PyUnicode_LATIN1_INIT("\\x{i:02x}"),') + immortal_objects.append(f'(PyObject *)&_Py_SINGLETON(strings).latin1[{i} - 128]') printer.write('') with printer.block('.tuple_empty =', ','): printer.write('.ob_base = _PyVarObject_IMMORTAL_INIT(&PyTuple_Type, 0)') + immortal_objects.append(f'(PyObject *)&_Py_SINGLETON(tuple_empty)') printer.write('') printer.write("static inline void") with printer.block("_PyUnicode_InitStaticStrings(void)"): @@ -293,6 +302,16 @@ def generate_runtime_init(identifiers, strings): # since iter_files() ignores .h files. printer.write(f'string = &_Py_ID({i});') printer.write(f'PyUnicode_InternInPlace(&string);') + printer.write('') + printer.write('#ifdef Py_DEBUG') + printer.write("static inline void") + with printer.block("_PyStaticObjects_CheckRefcnt(void)"): + for i in immortal_objects: + with printer.block(f'if (Py_REFCNT({i}) < _PyObject_IMMORTAL_REFCNT)', ';'): + printer.write(f'_PyObject_Dump({i});') + printer.write(f'Py_FatalError("immortal object has less refcnt than ' + 'expected _PyObject_IMMORTAL_REFCNT");') + printer.write('#endif') printer.write(END) printer.write(after) diff --git a/Tools/scripts/generate_opcode_h.py b/Tools/scripts/generate_opcode_h.py index 1d21af8cac2816fe9db9453386ad12f472d17c3e..9ff264af9cdc2b1f2e4da7fafd39e82a135513ce 100644 --- a/Tools/scripts/generate_opcode_h.py +++ b/Tools/scripts/generate_opcode_h.py @@ -131,7 +131,6 @@ def main(opcode_py, outfile='Include/opcode.h', internaloutfile='Include/interna iobj.write("\nextern const uint8_t _PyOpcode_Caches[256];\n") iobj.write("\nextern const uint8_t _PyOpcode_Deopt[256];\n") - iobj.write("\nextern const uint8_t _PyOpcode_Original[256];\n") iobj.write("\n#ifdef NEED_OPCODE_TABLES\n") write_int_array_from_ops("_PyOpcode_RelativeJump", opcode['hasjrel'], iobj) write_int_array_from_ops("_PyOpcode_Jump", opcode['hasjrel'] + opcode['hasjabs'], iobj) @@ -153,12 +152,6 @@ def main(opcode_py, outfile='Include/opcode.h', internaloutfile='Include/interna for opt, deopt in sorted(deoptcodes.items()): iobj.write(f" [{opt}] = {deopt},\n") iobj.write("};\n") - iobj.write("\nconst uint8_t _PyOpcode_Original[256] = {\n") - for opt, deopt in sorted(deoptcodes.items()): - if opt.startswith("EXTENDED_ARG"): - deopt = "EXTENDED_ARG_QUICK" - iobj.write(f" [{opt}] = {deopt},\n") - iobj.write("};\n") iobj.write("#endif // NEED_OPCODE_TABLES\n") fobj.write("\n") diff --git a/Tools/scripts/generate_stdlib_module_names.py b/Tools/scripts/generate_stdlib_module_names.py index 82f10948b1b95b595513f0685e26575efd8359e4..92100bd06509a5b0c9a691efe81a03ddbd5618a4 100644 --- a/Tools/scripts/generate_stdlib_module_names.py +++ b/Tools/scripts/generate_stdlib_module_names.py @@ -12,7 +12,6 @@ SRC_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) STDLIB_PATH = os.path.join(SRC_DIR, 'Lib') -SETUP_PY = os.path.join(SRC_DIR, 'setup.py') IGNORE = { '__init__', @@ -64,15 +63,6 @@ def list_packages(names): names.add(name) -# Extension modules built by setup.py -def list_setup_extensions(names): - cmd = [sys.executable, SETUP_PY, "-q", "build", "--list-module-names"] - output = subprocess.check_output(cmd) - output = output.decode("utf8") - extensions = output.splitlines() - names |= set(extensions) - - # Built-in and extension modules built by Modules/Setup* # includes Windows and macOS extensions. def list_modules_setup_extensions(names): @@ -103,7 +93,6 @@ def list_frozen(names): def list_modules(): names = set(sys.builtin_module_names) list_modules_setup_extensions(names) - list_setup_extensions(names) list_packages(names) list_python_modules(names) list_frozen(names) diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index fc6b2d0f8becf8281b34879e749faec02a460eee..24ddd2a20913a281f8677cf69f3fcba79c3cd458 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -358,7 +358,7 @@ def recompile_pymods(self): env["LD_RUN_PATH"] = self.lib_dir log.info("Rebuilding Python modules") - cmd = [sys.executable, os.path.join(PYTHONROOT, "setup.py"), "build"] + cmd = ["make", "sharedmods", "checksharedmods"] self._subprocess_call(cmd, env=env) self.check_imports() @@ -472,7 +472,7 @@ def main(): start = datetime.now() if args.steps in {'modules', 'tests'}: - for name in ['setup.py', 'Modules/_ssl.c']: + for name in ['Makefile.pre.in', 'Modules/_ssl.c']: if not os.path.isfile(os.path.join(PYTHONROOT, name)): parser.error( "Must be executed from CPython build dir" diff --git a/Tools/wasm/README.md b/Tools/wasm/README.md index 40f23a396f6711c630275cd92755239ad074d350..6496a29e6ff809f9d01cf4612bb8425dc9f6bfc2 100644 --- a/Tools/wasm/README.md +++ b/Tools/wasm/README.md @@ -23,16 +23,20 @@ ## wasm32-emscripten build Christian Heimes maintains a container image with Emscripten SDK, Python build dependencies, WASI-SDK, wasmtime, and several additional tools. +From within your local CPython repo clone, run one of the following commands: + ``` # Fedora, RHEL, CentOS -podman run --rm -ti -v $(pwd):/python-wasm/cpython:Z quay.io/tiran/cpythonbuild:emsdk3 +podman run --rm -ti -v $(pwd):/python-wasm/cpython:Z -w /python-wasm/cpython quay.io/tiran/cpythonbuild:emsdk3 # other -docker run --rm -ti -v $(pwd):/python-wasm/cpython quay.io/tiran/cpythonbuild:emsdk3 +docker run --rm -ti -v $(pwd):/python-wasm/cpython -w /python-wasm/cpython quay.io/tiran/cpythonbuild:emsdk3 ``` ### Compile a build Python interpreter +From within the container, run the following commands: + ```shell mkdir -p builddir/build pushd builddir/build @@ -65,12 +69,9 @@ ### Cross compile to wasm32-emscripten for browser ``` Serve `python.html` with a local webserver and open the file in a browser. - -```shell -emrun builddir/emscripten-browser/python.html -``` - -or +Python comes with a minimal web server script that sets necessary HTTP +headers like COOP, COEP, and mimetypes. Run the script outside the container +and from the root of the CPython checkout. ```shell ./Tools/wasm/wasm_webserver.py @@ -80,6 +81,7 @@ ### Cross compile to wasm32-emscripten for browser directory structure enables the *C/C++ DevTools Support (DWARF)* to load C and header files with debug builds. + ### Cross compile to wasm32-emscripten for node ```shell @@ -165,7 +167,7 @@ ## Misc - Heap memory and stack size are limited. Recursion or extensive memory consumption can crash Python. - Most stdlib modules with a dependency on external libraries are missing, - e.g. ``ctypes``, ``readline``, ``sqlite3``, ``ssl``, and more. + e.g. ``ctypes``, ``readline``, ``ssl``, and more. - Shared extension modules are not implemented yet. All extension modules are statically linked into the main binary. The experimental configure option ``--enable-wasm-dynamic-linking`` enables dynamic extensions @@ -224,9 +226,27 @@ # .htaccess # WASI (wasm32-wasi) -WASI builds require [WASI SDK](https://github.com/WebAssembly/wasi-sdk) 15.0+ -and currently [wasix](https://github.com/singlestore-labs/wasix) for POSIX -compatibility stubs. +WASI builds require [WASI SDK](https://github.com/WebAssembly/wasi-sdk) 16.0+. + +## Cross-compile to wasm32-wasi + +The script ``wasi-env`` sets necessary compiler and linker flags as well as +``pkg-config`` overrides. The script assumes that WASI-SDK is installed in +``/opt/wasi-sdk`` or ``$WASI_SDK_PATH``. + +```shell +mkdir -p builddir/wasi +pushd builddir/wasi + +CONFIG_SITE=../../Tools/wasm/config.site-wasm32-wasi \ + ../../Tools/wasm/wasi-env ../../configure -C \ + --host=wasm32-unknown-wasi \ + --build=$(../../config.guess) \ + --with-build-python=$(pwd)/../build/python + +make -j$(nproc) +popd +``` ## WASI limitations and issues (WASI SDK 15.0) @@ -372,6 +392,16 @@ ### Install [Emscripten SDK](https://emscripten.org/docs/getting_started/downloa /opt/emsdk/emsdk activate latest ``` +### Optionally: enable ccache for EMSDK + +The ``EM_COMPILER_WRAPPER`` must be set after the EMSDK environment is +sourced. Otherwise the source script removes the environment variable. + +``` +. /opt/emsdk/emsdk_env.sh +EM_COMPILER_WRAPPER=ccache +``` + ### Optionally: pre-build and cache static libraries Emscripten SDK provides static builds of core libraries without PIC @@ -380,12 +410,8 @@ ### Optionally: pre-build and cache static libraries ```shell . /opt/emsdk/emsdk_env.sh -embuilder build --force zlib bzip2 -embuilder build --force --pic \ - zlib bzip2 libc-mt libdlmalloc-mt libsockets-mt \ - libstubs libcompiler_rt libcompiler_rt-mt crtbegin libhtml5 \ - libc++-mt-noexcept libc++abi-mt-noexcept \ - libal libGL-mt libstubs-debug libc-mt-debug +embuilder build zlib bzip2 MINIMAL_PIC +embuilder build --pic zlib bzip2 MINIMAL_PIC ``` ### Install [WASI-SDK](https://github.com/WebAssembly/wasi-sdk) @@ -405,18 +431,18 @@ ### Install [WASI-SDK](https://github.com/WebAssembly/wasi-sdk) ### Install [wasmtime](https://github.com/bytecodealliance/wasmtime) WASI runtime -**NOTE**: wasmtime 0.37 has a bug. Newer versions should be fine again. +wasmtime 0.38 or newer is required. ```shell curl -sSf -L -o ~/install-wasmtime.sh https://wasmtime.dev/install.sh chmod +x ~/install-wasmtime.sh -~/install-wasmtime.sh --version v0.36.0 +~/install-wasmtime.sh --version v0.38.0 ln -srf -t /usr/local/bin/ ~/.wasmtime/bin/wasmtime ``` -### Install [WASIX](https://github.com/singlestore-labs/wasix) -```shell -git clone https://github.com/singlestore-labs/wasix.git ~/wasix -make install -C ~/wasix -``` +### WASI debugging + +* ``wasmtime run -g`` generates debugging symbols for gdb and lldb. +* The environment variable ``RUST_LOG=wasi_common`` enables debug and + trace logging. diff --git a/Tools/wasm/config.site-wasm32-wasi b/Tools/wasm/config.site-wasm32-wasi index f151b7bc5ab0c93aeb7b5561525774a92b8153cc..893a0d132cda591069f3ee6bf2b22f2c93e23f9c 100644 --- a/Tools/wasm/config.site-wasm32-wasi +++ b/Tools/wasm/config.site-wasm32-wasi @@ -32,15 +32,11 @@ ac_cv_func_makedev=no # OSError: [Errno 28] Invalid argument: '.' ac_cv_func_fdopendir=no -# WASIX stubs we don't want to use. -ac_cv_func_kill=no - -# WASI SDK 15.0 does not have chmod. -# Ignore WASIX stubs for now. -ac_cv_func_chmod=no -ac_cv_func_fchmod=no - # WASI sockets are limited to operations on given socket fd and inet sockets. # Disable AF_UNIX and AF_PACKET support, see socketmodule.h. ac_cv_header_sys_un_h=no ac_cv_header_netpacket_packet_h=no + +# disable accept for WASM runtimes without sock_accept +#ac_cv_func_accept=no +#ac_cv_func_accept4=no diff --git a/Tools/wasm/wasi-env b/Tools/wasm/wasi-env new file mode 100755 index 0000000000000000000000000000000000000000..6c2d56e0e5e32b16466cd15a35d30ff5d181cb32 --- /dev/null +++ b/Tools/wasm/wasi-env @@ -0,0 +1,75 @@ +#!/bin/sh +set -e + +# function +usage() { + echo "wasi-env - Run command with WASI-SDK" + echo "" + echo "wasi-env is a helper to set various environment variables to" + echo "run configure and make with WASI-SDK. A WASI-SDK must be either" + echo "installed at /opt/wasi-sdk or the env var 'WASI_SDK_PATH' must" + echo "set to the root of a WASI-SDK." + echo "" + echo "Usage: wasi-env command [...]" + echo "" + echo " -h --help display this help and exit" + echo "" +} + +case $1 in + -h|--help) + usage + exit + ;; +esac + +if test -z "$1"; then + echo "ERROR: command required" >&2 + usage + exit 1 +fi + +WASI_SDK_PATH="${WASI_SDK_PATH:-/opt/wasi-sdk}" +WASI_SYSROOT="${WASI_SDK_PATH}/share/wasi-sysroot" + +if ! test -x "${WASI_SDK_PATH}/bin/clang"; then + echo "Error: ${WASI_SDK_PATH}/bin/clang does not exist." >&2 + exit 2 +fi + +CC="${WASI_SDK_PATH}/bin/clang" +CPP="${WASI_SDK_PATH}/bin/clang-cpp" +CXX="${WASI_SDK_PATH}/bin/clang++" + +# --sysroot is required if WASI-SDK is not installed in /opt/wasi-sdk. +if test "${WASI_SDK_PATH}" != "/opt/wasi-sdk"; then + CC="${CC} --sysroot=${WASI_SYSROOT}" + CPP="${CPP} --sysroot=${WASI_SYSROOT}" + CXX="${CXX} --sysroot=${WASI_SYSROOT}" +fi + +# use ccache if available +if command -v ccache >/dev/null 2>&1; then + CC="ccache ${CC}" + CPP="ccache ${CPP}" + CXX="ccache ${CXX}" +fi + +LDSHARED="${WASI_SDK_PATH}/bin/wasm-ld" +AR="${WASI_SDK_PATH}/bin/llvm-ar" +RANLIB="${WASI_SDK_PATH}/bin/ranlib" + +# instruct pkg-config to use sysroot +PKG_CONFIG_PATH="" +PKG_CONFIG_LIBDIR="${WASI_SYSROOT}/lib/pkgconfig:${WASI_SYSROOT}/share/pkgconfig" +PKG_CONFIG_SYSROOT_DIR="${WASI_SYSROOT}" + +PATH="${WASI_SDK_PATH}/bin:${PATH}" + +export WASI_SDK_PATH WASI_SYSROOT +export CC CPP CXX LDSHARED AR RANLIB +export CFLAGS LDFLAGS +export PKG_CONFIG_PATH PKG_CONFIG_LIBDIR PKG_CONFIG_SYSROOT_DIR +export PATH + +exec "$@" diff --git a/Tools/wasm/wasm_assets.py b/Tools/wasm/wasm_assets.py index a59db9db7cdd2083489c371a211d3b9cfeb42c5d..07450ac928dcd6f9178602f3df5b6cc5a2a5a1e1 100755 --- a/Tools/wasm/wasm_assets.py +++ b/Tools/wasm/wasm_assets.py @@ -165,14 +165,13 @@ def detect_extension_modules(args: argparse.Namespace): loc = {} exec(data, globals(), loc) - for name, value in loc["build_time_vars"].items(): - if value not in {"yes", "missing", "disabled", "n/a"}: + for key, value in loc["build_time_vars"].items(): + if not key.startswith("MODULE_") or not key.endswith("_STATE"): continue - if not name.startswith("MODULE_"): - continue - if name.endswith(("_CFLAGS", "_DEPS", "_LDFLAGS")): - continue - modname = name.removeprefix("MODULE_").lower() + if value not in {"yes", "disabled", "missing", "n/a"}: + raise ValueError(f"Unsupported value '{value}' for {key}") + + modname = key[7:-6].lower() if modname not in modules: modules[modname] = value == "yes" return modules diff --git a/configure b/configure index bffc30a590fbe48511fb7dec57d97157390f40b1..5df9f83290da06337989c3a104be9674b27518a5 100755 --- a/configure +++ b/configure @@ -632,6 +632,8 @@ MODULE__CTYPES_TEST_FALSE MODULE__CTYPES_TEST_TRUE MODULE__XXTESTFUZZ_FALSE MODULE__XXTESTFUZZ_TRUE +MODULE_XXSUBTYPE_FALSE +MODULE_XXSUBTYPE_TRUE MODULE__TESTMULTIPHASE_FALSE MODULE__TESTMULTIPHASE_TRUE MODULE__TESTIMPORTMULTIPLE_FALSE @@ -786,12 +788,10 @@ MODULE_TIME_FALSE MODULE_TIME_TRUE MODULE__IO_FALSE MODULE__IO_TRUE -MODULES_SETUP_STDLIB MODULE_BUILDTYPE TEST_MODULES LIBB2_LIBS LIBB2_CFLAGS -OPENSSL_RPATH OPENSSL_LDFLAGS OPENSSL_LIBS OPENSSL_INCLUDES @@ -852,13 +852,11 @@ LIBSQLITE3_CFLAGS LIBNSL_LIBS LIBNSL_CFLAGS LIBMPDEC_INTERNAL -LIBMPDEC_LDFLAGS LIBMPDEC_CFLAGS MODULE__CTYPES_MALLOC_CLOSURE LIBFFI_LIBS LIBFFI_CFLAGS LIBEXPAT_INTERNAL -LIBEXPAT_LDFLAGS LIBEXPAT_CFLAGS TZPATH LIBUUID_LIBS @@ -3092,6 +3090,10 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + if test "$srcdir" != . -a "$srcdir" != "$(pwd)"; then # If we're building out-of-tree, we need to make sure the following # resources get picked up before their $srcdir counterparts. @@ -6340,7 +6342,11 @@ case $host/$ac_cv_cc_name in #( PY_SUPPORT_TIER=3 ;; #( s390x-*-linux-gnu/gcc) : PY_SUPPORT_TIER=3 ;; #( - x86_64-*-freebsd*/clang) : + wasm32-unknown-emscripten/clang) : + PY_SUPPORT_TIER=3 ;; #( + wasm32-unknown-wasi/clang) : + PY_SUPPORT_TIER=3 ;; #( + x86_64-*-freebsd*/clang) : PY_SUPPORT_TIER=3 ;; #( *) : PY_SUPPORT_TIER=0 @@ -9052,7 +9058,7 @@ for ac_header in \ alloca.h asm/types.h bluetooth.h conio.h crypt.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/memfd.h \ linux/random.h linux/soundcard.h \ - linux/tipc.h linux/wait.h netinet/in.h netpacket/packet.h poll.h process.h pthread.h pty.h \ + linux/tipc.h linux/wait.h netdb.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 \ sys/endian.h sys/epoll.h sys/event.h sys/eventfd.h sys/file.h sys/ioctl.h sys/kern_control.h \ sys/loadavg.h sys/lock.h sys/memfd.h sys/mkdev.h sys/mman.h sys/modem.h sys/param.h sys/poll.h \ @@ -11265,7 +11271,15 @@ fi echo "$LIBUUID_PKG_ERRORS" >&5 - for ac_header in uuid/uuid.h + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + CPPFLAGS="$CPPFLAGS $LIBUUID_CFLAGS" + LDFLAGS="$LDFLAGS $LIBUUID_LIBS" + for ac_header in uuid/uuid.h do : ac_fn_c_check_header_mongrel "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default" if test "x$ac_cv_header_uuid_uuid_h" = xyes; then : @@ -11273,11 +11287,7 @@ if test "x$ac_cv_header_uuid_uuid_h" = xyes; then : #define HAVE_UUID_UUID_H 1 _ACEOF - save_CFLAGS=$CFLAGS -save_CPPFLAGS=$CPPFLAGS -save_LDFLAGS=$LDFLAGS -save_LIBS=$LIBS - + py_check_lib_save_LIBS=$LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5 $as_echo_n "checking for uuid_generate_time in -luuid... " >&6; } if ${ac_cv_lib_uuid_uuid_generate_time+:} false; then : @@ -11318,20 +11328,10 @@ if test "x$ac_cv_lib_uuid_uuid_generate_time" = xyes; then : have_uuid=yes fi +LIBS=$py_check_lib_save_LIBS -CFLAGS=$save_CFLAGS -CPPFLAGS=$save_CPPFLAGS -LDFLAGS=$save_LDFLAGS -LIBS=$save_LIBS - - - save_CFLAGS=$CFLAGS -save_CPPFLAGS=$CPPFLAGS -save_LDFLAGS=$LDFLAGS -save_LIBS=$LIBS - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time_safe in -luuid" >&5 + py_check_lib_save_LIBS=$LIBS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time_safe in -luuid" >&5 $as_echo_n "checking for uuid_generate_time_safe in -luuid... " >&6; } if ${ac_cv_lib_uuid_uuid_generate_time_safe+:} false; then : $as_echo_n "(cached) " >&6 @@ -11368,19 +11368,18 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate_time_safe" >&5 $as_echo "$ac_cv_lib_uuid_uuid_generate_time_safe" >&6; } if test "x$ac_cv_lib_uuid_uuid_generate_time_safe" = xyes; then : - - have_uuid=yes + have_uuid=yes $as_echo "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h fi +LIBS=$py_check_lib_save_LIBS -CFLAGS=$save_CFLAGS -CPPFLAGS=$save_CPPFLAGS -LDFLAGS=$save_LDFLAGS -LIBS=$save_LIBS +fi + +done if test "x$have_uuid" = xyes; then : @@ -11389,9 +11388,11 @@ LIBS=$save_LIBS fi -fi +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS -done @@ -11399,7 +11400,15 @@ elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - for ac_header in uuid/uuid.h + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + CPPFLAGS="$CPPFLAGS $LIBUUID_CFLAGS" + LDFLAGS="$LDFLAGS $LIBUUID_LIBS" + for ac_header in uuid/uuid.h do : ac_fn_c_check_header_mongrel "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default" if test "x$ac_cv_header_uuid_uuid_h" = xyes; then : @@ -11407,11 +11416,7 @@ if test "x$ac_cv_header_uuid_uuid_h" = xyes; then : #define HAVE_UUID_UUID_H 1 _ACEOF - save_CFLAGS=$CFLAGS -save_CPPFLAGS=$CPPFLAGS -save_LDFLAGS=$LDFLAGS -save_LIBS=$LIBS - + py_check_lib_save_LIBS=$LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5 $as_echo_n "checking for uuid_generate_time in -luuid... " >&6; } if ${ac_cv_lib_uuid_uuid_generate_time+:} false; then : @@ -11452,20 +11457,10 @@ if test "x$ac_cv_lib_uuid_uuid_generate_time" = xyes; then : have_uuid=yes fi +LIBS=$py_check_lib_save_LIBS -CFLAGS=$save_CFLAGS -CPPFLAGS=$save_CPPFLAGS -LDFLAGS=$save_LDFLAGS -LIBS=$save_LIBS - - - save_CFLAGS=$CFLAGS -save_CPPFLAGS=$CPPFLAGS -save_LDFLAGS=$LDFLAGS -save_LIBS=$LIBS - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time_safe in -luuid" >&5 + py_check_lib_save_LIBS=$LIBS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time_safe in -luuid" >&5 $as_echo_n "checking for uuid_generate_time_safe in -luuid... " >&6; } if ${ac_cv_lib_uuid_uuid_generate_time_safe+:} false; then : $as_echo_n "(cached) " >&6 @@ -11502,19 +11497,18 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate_time_safe" >&5 $as_echo "$ac_cv_lib_uuid_uuid_generate_time_safe" >&6; } if test "x$ac_cv_lib_uuid_uuid_generate_time_safe" = xyes; then : - - have_uuid=yes + have_uuid=yes $as_echo "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h fi +LIBS=$py_check_lib_save_LIBS -CFLAGS=$save_CFLAGS -CPPFLAGS=$save_CPPFLAGS -LDFLAGS=$save_LDFLAGS -LIBS=$save_LIBS +fi + +done if test "x$have_uuid" = xyes; then : @@ -11523,9 +11517,11 @@ LIBS=$save_LIBS fi -fi +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS -done @@ -12026,7 +12022,6 @@ fi - # Check for use of the system libffi library { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-system-ffi" >&5 $as_echo_n "checking for --with-system-ffi... " >&6; } @@ -12125,15 +12120,17 @@ fi echo "$LIBFFI_PKG_ERRORS" >&5 - ac_fn_c_check_header_mongrel "$LINENO" "ffi.h" "ac_cv_header_ffi_h" "$ac_includes_default" -if test "x$ac_cv_header_ffi_h" = xyes; then : - - save_CFLAGS=$CFLAGS + save_CFLAGS=$CFLAGS save_CPPFLAGS=$CPPFLAGS save_LDFLAGS=$LDFLAGS save_LIBS=$LIBS + CPPFLAGS="$CPPFLAGS $LIBFFI_CFLAGS" + LDFLAGS="$LDFLAGS $LIBFFI_LIBS" + ac_fn_c_check_header_mongrel "$LINENO" "ffi.h" "ac_cv_header_ffi_h" "$ac_includes_default" +if test "x$ac_cv_header_ffi_h" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ffi_call in -lffi" >&5 $as_echo_n "checking for ffi_call in -lffi... " >&6; } if ${ac_cv_lib_ffi_ffi_call+:} false; then : @@ -12173,13 +12170,18 @@ $as_echo "$ac_cv_lib_ffi_ffi_call" >&6; } if test "x$ac_cv_lib_ffi_ffi_call" = xyes; then : have_libffi=yes - LIBFFI_LIBS="-lffi" + LIBFFI_CFLAGS=${LIBFFI_CFLAGS-""} + LIBFFI_LIBS=${LIBFFI_LIBS-"-lffi"} else have_libffi=no fi +fi + + + CFLAGS=$save_CFLAGS CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS @@ -12187,23 +12189,21 @@ LIBS=$save_LIBS -fi - - - elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - ac_fn_c_check_header_mongrel "$LINENO" "ffi.h" "ac_cv_header_ffi_h" "$ac_includes_default" -if test "x$ac_cv_header_ffi_h" = xyes; then : - - save_CFLAGS=$CFLAGS + save_CFLAGS=$CFLAGS save_CPPFLAGS=$CPPFLAGS save_LDFLAGS=$LDFLAGS save_LIBS=$LIBS + CPPFLAGS="$CPPFLAGS $LIBFFI_CFLAGS" + LDFLAGS="$LDFLAGS $LIBFFI_LIBS" + ac_fn_c_check_header_mongrel "$LINENO" "ffi.h" "ac_cv_header_ffi_h" "$ac_includes_default" +if test "x$ac_cv_header_ffi_h" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ffi_call in -lffi" >&5 $as_echo_n "checking for ffi_call in -lffi... " >&6; } if ${ac_cv_lib_ffi_ffi_call+:} false; then : @@ -12243,13 +12243,18 @@ $as_echo "$ac_cv_lib_ffi_ffi_call" >&6; } if test "x$ac_cv_lib_ffi_ffi_call" = xyes; then : have_libffi=yes - LIBFFI_LIBS="-lffi" + LIBFFI_CFLAGS=${LIBFFI_CFLAGS-""} + LIBFFI_LIBS=${LIBFFI_LIBS-"-lffi"} else have_libffi=no fi +fi + + + CFLAGS=$save_CFLAGS CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS @@ -12257,10 +12262,6 @@ LIBS=$save_LIBS -fi - - - else LIBFFI_CFLAGS=$pkg_cv_LIBFFI_CFLAGS LIBFFI_LIBS=$pkg_cv_LIBFFI_LIBS @@ -12525,8 +12526,13 @@ else LIBMPDEC_LDFLAGS="-lm \$(LIBMPDEC_A)" LIBMPDEC_INTERNAL="\$(LIBMPDEC_A)" + if test "x$with_pydebug" = xyes; then : + + as_fn_append LIBMPDEC_CFLAGS " -DTEST_COVERAGE" + fi +fi @@ -12877,7 +12883,7 @@ save_LDFLAGS=$LDFLAGS save_LIBS=$LIBS - CPPFLAGS="$LIBNSL_CFLAGS $CFLAGS" + CPPFLAGS="$CPPFLAGS $LIBNSL_CFLAGS" for ac_header in rpc/rpc.h do : ac_fn_c_check_header_mongrel "$LINENO" "rpc/rpc.h" "ac_cv_header_rpc_rpc_h" "$ac_includes_default" @@ -12909,6 +12915,19 @@ case $ac_sys_system in #( esac + + + if test "$ac_sys_system" = "Emscripten" -a -z "$LIBSQLITE3_CFLAGS" -a -z "$LIBSQLITE3_LIBS"; then : + + LIBSQLITE3_CFLAGS="-sUSE_SQLITE3" + LIBSQLITE3_LIBS="-sUSE_SQLITE3" + +fi + + + + + pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSQLITE3" >&5 $as_echo_n "checking for LIBSQLITE3... " >&6; } @@ -12997,7 +13016,7 @@ save_LDFLAGS=$LDFLAGS save_LIBS=$LIBS - CPPFLAGS="$LIBSQLITE3_CFLAGS $CFLAGS" + CPPFLAGS="$CPPFLAGS $LIBSQLITE3_CFLAGS" LDFLAGS="$LIBSQLITE3_LIBS $LDFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "sqlite3.h" "ac_cv_header_sqlite3_h" "$ac_includes_default" @@ -13943,7 +13962,7 @@ save_LDFLAGS=$LDFLAGS save_LIBS=$LIBS - CPPFLAGS="$TCLTK_CFLAGS $CFLAGS" + CPPFLAGS="$CPPFLAGS $TCLTK_CFLAGS" LIBS="$TCLTK_LIBS $LDFLAGS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -14008,7 +14027,7 @@ save_LDFLAGS=$LDFLAGS save_LIBS=$LIBS - CPPFLAGS="$GDBM_CFLAGS $CFLAGS" + CPPFLAGS="$CPPFLAGS $GDBM_CFLAGS" LDFLAGS="$GDBM_LIBS $LDFLAGS" for ac_header in gdbm.h do : @@ -14729,11 +14748,16 @@ if test "x$ac_cv_lib_cma_pthread_create" = xyes; then : else + case $ac_sys_system in #( + WASI) : + posix_threads=stub ;; #( + *) : as_fn_error $? "could not find pthreads on your system" "$LINENO" 5 + ;; +esac fi - fi fi @@ -14891,6 +14915,13 @@ done fi +if test "x$posix_threads" = xstub; then : + + +$as_echo "#define HAVE_PTHREAD_STUBS 1" >>confdefs.h + + +fi # Check for enable-ipv6 @@ -15530,11 +15561,11 @@ fi # checks for library functions for ac_func in \ accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \ - copy_file_range ctermid dup3 execv explicit_bzero explicit_memset \ + copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \ faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \ fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \ gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \ - getgrnam_r getgrouplist getgroups getitimer getloadavg getlogin \ + getgrnam_r getgrouplist getgroups gethostname getitimer getloadavg getlogin \ getpeername getpgid getpid getppid getpriority _getpty \ getpwent getpwnam_r getpwuid getpwuid_r getresgid getresuid getrusage getsid getspent \ getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \ @@ -16517,6 +16548,19 @@ fi + + + if test "$ac_sys_system" = "Emscripten" -a -z "$ZLIB_CFLAGS" -a -z "$ZLIB_LIBS"; then : + + ZLIB_CFLAGS="-sUSE_ZLIB" + ZLIB_LIBS="-sUSE_ZLIB" + +fi + + + + + pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ZLIB" >&5 $as_echo_n "checking for ZLIB... " >&6; } @@ -16576,7 +16620,15 @@ fi echo "$ZLIB_PKG_ERRORS" >&5 - for ac_header in zlib.h + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + CPPFLAGS="$CPPFLAGS $ZLIB_CFLAGS" + LDFLAGS="$LDFLAGS $ZLIB_LIBS" + for ac_header in zlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = xyes; then : @@ -16584,13 +16636,8 @@ if test "x$ac_cv_header_zlib_h" = xyes; then : #define HAVE_ZLIB_H 1 _ACEOF - save_CFLAGS=$CFLAGS -save_CPPFLAGS=$CPPFLAGS -save_LDFLAGS=$LDFLAGS -save_LIBS=$LIBS - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzread in -lz" >&5 + py_check_lib_save_LIBS=$LIBS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzread in -lz" >&5 $as_echo_n "checking for gzread in -lz... " >&6; } if ${ac_cv_lib_z_gzread+:} false; then : $as_echo_n "(cached) " >&6 @@ -16627,11 +16674,26 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_gzread" >&5 $as_echo "$ac_cv_lib_z_gzread" >&6; } if test "x$ac_cv_lib_z_gzread" = xyes; then : + have_zlib=yes +else + have_zlib=no +fi + +LIBS=$py_check_lib_save_LIBS + + +else + have_zlib=no +fi + +done + + if test "x$have_zlib" = xyes; then : - have_zlib=yes - ZLIB_CFLAGS=${ZLIB_CFLAGS-""} - ZLIB_LIBS=${ZLIB_LIBS-"-lz"} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5 + ZLIB_CFLAGS=${ZLIB_CFLAGS-""} + ZLIB_LIBS=${ZLIB_LIBS-"-lz"} + py_check_lib_save_LIBS=$LIBS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5 $as_echo_n "checking for inflateCopy in -lz... " >&6; } if ${ac_cv_lib_z_inflateCopy+:} false; then : $as_echo_n "(cached) " >&6 @@ -16672,14 +16734,11 @@ if test "x$ac_cv_lib_z_inflateCopy" = xyes; then : fi +LIBS=$py_check_lib_save_LIBS -else - - have_zlib=no fi - CFLAGS=$save_CFLAGS CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS @@ -16687,18 +16746,19 @@ LIBS=$save_LIBS -else - have_zlib=no -fi - -done - - elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - for ac_header in zlib.h + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + CPPFLAGS="$CPPFLAGS $ZLIB_CFLAGS" + LDFLAGS="$LDFLAGS $ZLIB_LIBS" + for ac_header in zlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = xyes; then : @@ -16706,13 +16766,8 @@ if test "x$ac_cv_header_zlib_h" = xyes; then : #define HAVE_ZLIB_H 1 _ACEOF - save_CFLAGS=$CFLAGS -save_CPPFLAGS=$CPPFLAGS -save_LDFLAGS=$LDFLAGS -save_LIBS=$LIBS - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzread in -lz" >&5 + py_check_lib_save_LIBS=$LIBS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzread in -lz" >&5 $as_echo_n "checking for gzread in -lz... " >&6; } if ${ac_cv_lib_z_gzread+:} false; then : $as_echo_n "(cached) " >&6 @@ -16749,11 +16804,26 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_gzread" >&5 $as_echo "$ac_cv_lib_z_gzread" >&6; } if test "x$ac_cv_lib_z_gzread" = xyes; then : + have_zlib=yes +else + have_zlib=no +fi + +LIBS=$py_check_lib_save_LIBS + + +else + have_zlib=no +fi + +done - have_zlib=yes - ZLIB_CFLAGS=${ZLIB_CFLAGS-""} - ZLIB_LIBS=${ZLIB_LIBS-"-lz"} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5 + if test "x$have_zlib" = xyes; then : + + ZLIB_CFLAGS=${ZLIB_CFLAGS-""} + ZLIB_LIBS=${ZLIB_LIBS-"-lz"} + py_check_lib_save_LIBS=$LIBS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5 $as_echo_n "checking for inflateCopy in -lz... " >&6; } if ${ac_cv_lib_z_inflateCopy+:} false; then : $as_echo_n "(cached) " >&6 @@ -16794,14 +16864,11 @@ if test "x$ac_cv_lib_z_inflateCopy" = xyes; then : fi +LIBS=$py_check_lib_save_LIBS -else - - have_zlib=no fi - CFLAGS=$save_CFLAGS CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS @@ -16809,13 +16876,6 @@ LIBS=$save_LIBS -else - have_zlib=no -fi - -done - - else ZLIB_CFLAGS=$pkg_cv_ZLIB_CFLAGS ZLIB_LIBS=$pkg_cv_ZLIB_LIBS @@ -16828,11 +16888,6 @@ $as_echo "yes" >&6; } fi -if test "$have_zlib" = "yes" -a "$ac_sys_system" = "Emscripten" -a "$ZLIB_LIBS" = "-lz"; then - ZLIB_CFLAGS="-sUSE_ZLIB" - ZLIB_LIBS="-sUSE_ZLIB" -fi - if test "x$have_zlib" = xyes; then : BINASCII_CFLAGS="-DUSE_ZLIB_CRC32 $ZLIB_CFLAGS" @@ -16841,6 +16896,19 @@ if test "x$have_zlib" = xyes; then : fi + + + if test "$ac_sys_system" = "Emscripten" -a -z "$BZIP2_CFLAGS" -a -z "$BZIP2_LIBS"; then : + + BZIP2_CFLAGS="-sUSE_BZIP2" + BZIP2_LIBS="-sUSE_BZIP2" + +fi + + + + + pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BZIP2" >&5 $as_echo_n "checking for BZIP2... " >&6; } @@ -16900,7 +16968,15 @@ fi echo "$BZIP2_PKG_ERRORS" >&5 - for ac_header in bzlib.h + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + CPPFLAGS="$CPPFLAGS $BZIP2_CFLAGS" + LDFLAGS="$LDFLAGS $BZIP2_LIBS" + for ac_header in bzlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "bzlib.h" "ac_cv_header_bzlib_h" "$ac_includes_default" if test "x$ac_cv_header_bzlib_h" = xyes; then : @@ -16908,12 +16984,6 @@ if test "x$ac_cv_header_bzlib_h" = xyes; then : #define HAVE_BZLIB_H 1 _ACEOF - save_CFLAGS=$CFLAGS -save_CPPFLAGS=$CPPFLAGS -save_LDFLAGS=$LDFLAGS -save_LIBS=$LIBS - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BZ2_bzCompress in -lbz2" >&5 $as_echo_n "checking for BZ2_bzCompress in -lbz2... " >&6; } if ${ac_cv_lib_bz2_BZ2_bzCompress+:} false; then : @@ -16951,15 +17021,24 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_BZ2_bzCompress" >&5 $as_echo "$ac_cv_lib_bz2_BZ2_bzCompress" >&6; } if test "x$ac_cv_lib_bz2_BZ2_bzCompress" = xyes; then : + have_bzip2=yes +else + have_bzip2=no +fi - have_bzip2=yes - BZIP2_CFLAGS=${BZIP2_CFLAGS-""} - BZIP2_LIBS=${BZIP2_LIBS-"-lbz2"} else have_bzip2=no fi +done + + if test "x$have_bzip2" = xyes; then : + + BZIP2_CFLAGS=${BZIP2_CFLAGS-""} + BZIP2_LIBS=${BZIP2_LIBS-"-lbz2"} + +fi CFLAGS=$save_CFLAGS CPPFLAGS=$save_CPPFLAGS @@ -16968,18 +17047,19 @@ LIBS=$save_LIBS -else - have_bzip2=no -fi - -done - - elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - for ac_header in bzlib.h + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + CPPFLAGS="$CPPFLAGS $BZIP2_CFLAGS" + LDFLAGS="$LDFLAGS $BZIP2_LIBS" + for ac_header in bzlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "bzlib.h" "ac_cv_header_bzlib_h" "$ac_includes_default" if test "x$ac_cv_header_bzlib_h" = xyes; then : @@ -16987,12 +17067,6 @@ if test "x$ac_cv_header_bzlib_h" = xyes; then : #define HAVE_BZLIB_H 1 _ACEOF - save_CFLAGS=$CFLAGS -save_CPPFLAGS=$CPPFLAGS -save_LDFLAGS=$LDFLAGS -save_LIBS=$LIBS - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BZ2_bzCompress in -lbz2" >&5 $as_echo_n "checking for BZ2_bzCompress in -lbz2... " >&6; } if ${ac_cv_lib_bz2_BZ2_bzCompress+:} false; then : @@ -17030,15 +17104,24 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_BZ2_bzCompress" >&5 $as_echo "$ac_cv_lib_bz2_BZ2_bzCompress" >&6; } if test "x$ac_cv_lib_bz2_BZ2_bzCompress" = xyes; then : + have_bzip2=yes +else + have_bzip2=no +fi - have_bzip2=yes - BZIP2_CFLAGS=${BZIP2_CFLAGS-""} - BZIP2_LIBS=${BZIP2_LIBS-"-lbz2"} else have_bzip2=no fi +done + + if test "x$have_bzip2" = xyes; then : + + BZIP2_CFLAGS=${BZIP2_CFLAGS-""} + BZIP2_LIBS=${BZIP2_LIBS-"-lbz2"} + +fi CFLAGS=$save_CFLAGS CPPFLAGS=$save_CPPFLAGS @@ -17047,13 +17130,6 @@ LIBS=$save_LIBS -else - have_bzip2=no -fi - -done - - else BZIP2_CFLAGS=$pkg_cv_BZIP2_CFLAGS BZIP2_LIBS=$pkg_cv_BZIP2_LIBS @@ -17062,12 +17138,6 @@ $as_echo "yes" >&6; } have_bzip2=yes fi -if test "$have_bzip2" = "yes" -a "$ac_sys_system" = "Emscripten" -a "$BZIP2_LIBS" = "-lbz2"; then - BZIP2_CFLAGS="-sUSE_BZIP2" - BZIP2_LIBS="-sUSE_BZIP2" -fi - - pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBLZMA" >&5 @@ -17128,7 +17198,15 @@ fi echo "$LIBLZMA_PKG_ERRORS" >&5 - for ac_header in lzma.h + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + CPPFLAGS="$CPPFLAGS $LIBLZMA_CFLAGS" + LDFLAGS="$LDFLAGS $LIBLZMA_LIBS" + for ac_header in lzma.h do : ac_fn_c_check_header_mongrel "$LINENO" "lzma.h" "ac_cv_header_lzma_h" "$ac_includes_default" if test "x$ac_cv_header_lzma_h" = xyes; then : @@ -17136,12 +17214,89 @@ if test "x$ac_cv_header_lzma_h" = xyes; then : #define HAVE_LZMA_H 1 _ACEOF - save_CFLAGS=$CFLAGS + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lzma_easy_encoder in -llzma" >&5 +$as_echo_n "checking for lzma_easy_encoder in -llzma... " >&6; } +if ${ac_cv_lib_lzma_lzma_easy_encoder+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llzma $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char lzma_easy_encoder (); +int +main () +{ +return lzma_easy_encoder (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lzma_lzma_easy_encoder=yes +else + ac_cv_lib_lzma_lzma_easy_encoder=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzma_lzma_easy_encoder" >&5 +$as_echo "$ac_cv_lib_lzma_lzma_easy_encoder" >&6; } +if test "x$ac_cv_lib_lzma_lzma_easy_encoder" = xyes; then : + have_liblzma=yes +else + have_liblzma=no +fi + + +else + have_liblzma=no +fi + +done + + if test "x$have_liblzma" = xyes; then : + + LIBLZMA_CFLAGS=${LIBLZMA_CFLAGS-""} + LIBLZMA_LIBS=${LIBLZMA_LIBS-"-llzma"} + +fi + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + save_CFLAGS=$CFLAGS save_CPPFLAGS=$CPPFLAGS save_LDFLAGS=$LDFLAGS save_LIBS=$LIBS + CPPFLAGS="$CPPFLAGS $LIBLZMA_CFLAGS" + LDFLAGS="$LDFLAGS $LIBLZMA_LIBS" + for ac_header in lzma.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "lzma.h" "ac_cv_header_lzma_h" "$ac_includes_default" +if test "x$ac_cv_header_lzma_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LZMA_H 1 +_ACEOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lzma_easy_encoder in -llzma" >&5 $as_echo_n "checking for lzma_easy_encoder in -llzma... " >&6; } if ${ac_cv_lib_lzma_lzma_easy_encoder+:} false; then : @@ -17179,15 +17334,24 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzma_lzma_easy_encoder" >&5 $as_echo "$ac_cv_lib_lzma_lzma_easy_encoder" >&6; } if test "x$ac_cv_lib_lzma_lzma_easy_encoder" = xyes; then : + have_liblzma=yes +else + have_liblzma=no +fi - have_liblzma=yes - LIBLZMA_CFLAGS=${LIBLZMA_CFLAGS-""} - LIBLZMA_LIBS=${LIBLZMA_LIBS-"-llzma"} else have_liblzma=no fi +done + + if test "x$have_liblzma" = xyes; then : + + LIBLZMA_CFLAGS=${LIBLZMA_CFLAGS-""} + LIBLZMA_LIBS=${LIBLZMA_LIBS-"-llzma"} + +fi CFLAGS=$save_CFLAGS CPPFLAGS=$save_CPPFLAGS @@ -17197,130 +17361,680 @@ LIBS=$save_LIBS else - have_liblzma=no + LIBLZMA_CFLAGS=$pkg_cv_LIBLZMA_CFLAGS + LIBLZMA_LIBS=$pkg_cv_LIBLZMA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_liblzma=yes +fi + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for hstrerror" >&5 +$as_echo_n "checking for hstrerror... " >&6; } +if ${ac_cv_func_hstrerror+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <netdb.h> +int +main () +{ +void *x=hstrerror + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_hstrerror=yes +else + ac_cv_func_hstrerror=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_hstrerror" >&5 +$as_echo "$ac_cv_func_hstrerror" >&6; } + if test "x$ac_cv_func_hstrerror" = xyes; then : + +$as_echo "#define HAVE_HSTRERROR 1" >>confdefs.h + +fi + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getservbyname" >&5 +$as_echo_n "checking for getservbyname... " >&6; } +if ${ac_cv_func_getservbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <netdb.h> +int +main () +{ +void *x=getservbyname + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_getservbyname=yes +else + ac_cv_func_getservbyname=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getservbyname" >&5 +$as_echo "$ac_cv_func_getservbyname" >&6; } + if test "x$ac_cv_func_getservbyname" = xyes; then : + +$as_echo "#define HAVE_GETSERVBYNAME 1" >>confdefs.h + +fi + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getservbyport" >&5 +$as_echo_n "checking for getservbyport... " >&6; } +if ${ac_cv_func_getservbyport+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <netdb.h> +int +main () +{ +void *x=getservbyport + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_getservbyport=yes +else + ac_cv_func_getservbyport=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getservbyport" >&5 +$as_echo "$ac_cv_func_getservbyport" >&6; } + if test "x$ac_cv_func_getservbyport" = xyes; then : + +$as_echo "#define HAVE_GETSERVBYPORT 1" >>confdefs.h + +fi + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname" >&5 +$as_echo_n "checking for gethostbyname... " >&6; } +if ${ac_cv_func_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <netdb.h> +int +main () +{ +void *x=gethostbyname + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_gethostbyname=yes +else + ac_cv_func_gethostbyname=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_gethostbyname" >&5 +$as_echo "$ac_cv_func_gethostbyname" >&6; } + if test "x$ac_cv_func_gethostbyname" = xyes; then : + +$as_echo "#define HAVE_GETHOSTBYNAME 1" >>confdefs.h + +fi + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyaddr" >&5 +$as_echo_n "checking for gethostbyaddr... " >&6; } +if ${ac_cv_func_gethostbyaddr+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <netdb.h> +int +main () +{ +void *x=gethostbyaddr + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_gethostbyaddr=yes +else + ac_cv_func_gethostbyaddr=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_gethostbyaddr" >&5 +$as_echo "$ac_cv_func_gethostbyaddr" >&6; } + if test "x$ac_cv_func_gethostbyaddr" = xyes; then : + +$as_echo "#define HAVE_GETHOSTBYADDR 1" >>confdefs.h + +fi + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getprotobyname" >&5 +$as_echo_n "checking for getprotobyname... " >&6; } +if ${ac_cv_func_getprotobyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <netdb.h> +int +main () +{ +void *x=getprotobyname + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_getprotobyname=yes +else + ac_cv_func_getprotobyname=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getprotobyname" >&5 +$as_echo "$ac_cv_func_getprotobyname" >&6; } + if test "x$ac_cv_func_getprotobyname" = xyes; then : + +$as_echo "#define HAVE_GETPROTOBYNAME 1" >>confdefs.h + +fi + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_aton" >&5 +$as_echo_n "checking for inet_aton... " >&6; } +if ${ac_cv_func_inet_aton+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +int +main () +{ +void *x=inet_aton + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_inet_aton=yes +else + ac_cv_func_inet_aton=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_inet_aton" >&5 +$as_echo "$ac_cv_func_inet_aton" >&6; } + if test "x$ac_cv_func_inet_aton" = xyes; then : + +$as_echo "#define HAVE_INET_ATON 1" >>confdefs.h + +fi + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa" >&5 +$as_echo_n "checking for inet_ntoa... " >&6; } +if ${ac_cv_func_inet_ntoa+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +int +main () +{ +void *x=inet_ntoa + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_inet_ntoa=yes +else + ac_cv_func_inet_ntoa=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_inet_ntoa" >&5 +$as_echo "$ac_cv_func_inet_ntoa" >&6; } + if test "x$ac_cv_func_inet_ntoa" = xyes; then : + +$as_echo "#define HAVE_INET_NTOA 1" >>confdefs.h + +fi + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_pton" >&5 +$as_echo_n "checking for inet_pton... " >&6; } +if ${ac_cv_func_inet_pton+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +int +main () +{ +void *x=inet_pton + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_inet_pton=yes +else + ac_cv_func_inet_pton=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_inet_pton" >&5 +$as_echo "$ac_cv_func_inet_pton" >&6; } + if test "x$ac_cv_func_inet_pton" = xyes; then : + +$as_echo "#define HAVE_INET_PTON 1" >>confdefs.h + +fi + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpeername" >&5 +$as_echo_n "checking for getpeername... " >&6; } +if ${ac_cv_func_getpeername+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +int +main () +{ +void *x=getpeername + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_getpeername=yes +else + ac_cv_func_getpeername=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getpeername" >&5 +$as_echo "$ac_cv_func_getpeername" >&6; } + if test "x$ac_cv_func_getpeername" = xyes; then : + +$as_echo "#define HAVE_GETPEERNAME 1" >>confdefs.h + +fi + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getsockname" >&5 +$as_echo_n "checking for getsockname... " >&6; } +if ${ac_cv_func_getsockname+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +int +main () +{ +void *x=getsockname + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_getsockname=yes +else + ac_cv_func_getsockname=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getsockname" >&5 +$as_echo "$ac_cv_func_getsockname" >&6; } + if test "x$ac_cv_func_getsockname" = xyes; then : + +$as_echo "#define HAVE_GETSOCKNAME 1" >>confdefs.h + +fi + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for accept" >&5 +$as_echo_n "checking for accept... " >&6; } +if ${ac_cv_func_accept+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +int +main () +{ +void *x=accept + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_accept=yes +else + ac_cv_func_accept=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_accept" >&5 +$as_echo "$ac_cv_func_accept" >&6; } + if test "x$ac_cv_func_accept" = xyes; then : + +$as_echo "#define HAVE_ACCEPT 1" >>confdefs.h + +fi + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bind" >&5 +$as_echo_n "checking for bind... " >&6; } +if ${ac_cv_func_bind+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +int +main () +{ +void *x=bind + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_bind=yes +else + ac_cv_func_bind=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_bind" >&5 +$as_echo "$ac_cv_func_bind" >&6; } + if test "x$ac_cv_func_bind" = xyes; then : + +$as_echo "#define HAVE_BIND 1" >>confdefs.h + +fi + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for connect" >&5 +$as_echo_n "checking for connect... " >&6; } +if ${ac_cv_func_connect+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +int +main () +{ +void *x=connect + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_connect=yes +else + ac_cv_func_connect=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_connect" >&5 +$as_echo "$ac_cv_func_connect" >&6; } + if test "x$ac_cv_func_connect" = xyes; then : -done +$as_echo "#define HAVE_CONNECT 1" >>confdefs.h +fi -elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - for ac_header in lzma.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "lzma.h" "ac_cv_header_lzma_h" "$ac_includes_default" -if test "x$ac_cv_header_lzma_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LZMA_H 1 -_ACEOF - save_CFLAGS=$CFLAGS -save_CPPFLAGS=$CPPFLAGS -save_LDFLAGS=$LDFLAGS -save_LIBS=$LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lzma_easy_encoder in -llzma" >&5 -$as_echo_n "checking for lzma_easy_encoder in -llzma... " >&6; } -if ${ac_cv_lib_lzma_lzma_easy_encoder+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for listen" >&5 +$as_echo_n "checking for listen... " >&6; } +if ${ac_cv_func_listen+:} false; then : $as_echo_n "(cached) " >&6 else - ac_check_lib_save_LIBS=$LIBS -LIBS="-llzma $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char lzma_easy_encoder (); +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + int main () { -return lzma_easy_encoder (); +void *x=listen ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_lzma_lzma_easy_encoder=yes +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_listen=yes else - ac_cv_lib_lzma_lzma_easy_encoder=no + ac_cv_func_listen=no fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzma_lzma_easy_encoder" >&5 -$as_echo "$ac_cv_lib_lzma_lzma_easy_encoder" >&6; } -if test "x$ac_cv_lib_lzma_lzma_easy_encoder" = xyes; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_listen" >&5 +$as_echo "$ac_cv_func_listen" >&6; } + if test "x$ac_cv_func_listen" = xyes; then : - have_liblzma=yes - LIBLZMA_CFLAGS=${LIBLZMA_CFLAGS-""} - LIBLZMA_LIBS=${LIBLZMA_LIBS-"-llzma"} +$as_echo "#define HAVE_LISTEN 1" >>confdefs.h -else - have_liblzma=no fi -CFLAGS=$save_CFLAGS -CPPFLAGS=$save_CPPFLAGS -LDFLAGS=$save_LDFLAGS -LIBS=$save_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for recvfrom" >&5 +$as_echo_n "checking for recvfrom... " >&6; } +if ${ac_cv_func_recvfrom+:} false; then : + $as_echo_n "(cached) " >&6 else - have_liblzma=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +int +main () +{ +void *x=recvfrom + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_recvfrom=yes +else + ac_cv_func_recvfrom=no fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_recvfrom" >&5 +$as_echo "$ac_cv_func_recvfrom" >&6; } + if test "x$ac_cv_func_recvfrom" = xyes; then : +$as_echo "#define HAVE_RECVFROM 1" >>confdefs.h -else - LIBLZMA_CFLAGS=$pkg_cv_LIBLZMA_CFLAGS - LIBLZMA_LIBS=$pkg_cv_LIBLZMA_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - have_liblzma=yes fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for hstrerror" >&5 -$as_echo_n "checking for hstrerror... " >&6; } -if ${ac_cv_func_hstrerror+:} false; then : + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sendto" >&5 +$as_echo_n "checking for sendto... " >&6; } +if ${ac_cv_func_sendto+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include <netdb.h> + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + int main () { -void *x=hstrerror +void *x=sendto ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_func_hstrerror=yes + ac_cv_func_sendto=yes else - ac_cv_func_hstrerror=no + ac_cv_func_sendto=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_hstrerror" >&5 -$as_echo "$ac_cv_func_hstrerror" >&6; } - if test "x$ac_cv_func_hstrerror" = xyes; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_sendto" >&5 +$as_echo "$ac_cv_func_sendto" >&6; } + if test "x$ac_cv_func_sendto" = xyes; then : -$as_echo "#define HAVE_HSTRERROR 1" >>confdefs.h +$as_echo "#define HAVE_SENDTO 1" >>confdefs.h fi @@ -17328,10 +18042,9 @@ fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_aton" >&5 -$as_echo_n "checking for inet_aton... " >&6; } -if ${ac_cv_func_inet_aton+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setsockopt" >&5 +$as_echo_n "checking for setsockopt... " >&6; } +if ${ac_cv_func_setsockopt+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -17345,24 +18058,24 @@ else int main () { -void *x=inet_aton +void *x=setsockopt ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_func_inet_aton=yes + ac_cv_func_setsockopt=yes else - ac_cv_func_inet_aton=no + ac_cv_func_setsockopt=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_inet_aton" >&5 -$as_echo "$ac_cv_func_inet_aton" >&6; } - if test "x$ac_cv_func_inet_aton" = xyes; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_setsockopt" >&5 +$as_echo "$ac_cv_func_setsockopt" >&6; } + if test "x$ac_cv_func_setsockopt" = xyes; then : -$as_echo "#define HAVE_INET_ATON 1" >>confdefs.h +$as_echo "#define HAVE_SETSOCKOPT 1" >>confdefs.h fi @@ -17370,10 +18083,9 @@ fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_pton" >&5 -$as_echo_n "checking for inet_pton... " >&6; } -if ${ac_cv_func_inet_pton+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket" >&5 +$as_echo_n "checking for socket... " >&6; } +if ${ac_cv_func_socket+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -17387,24 +18099,24 @@ else int main () { -void *x=inet_pton +void *x=socket ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_func_inet_pton=yes + ac_cv_func_socket=yes else - ac_cv_func_inet_pton=no + ac_cv_func_socket=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_inet_pton" >&5 -$as_echo "$ac_cv_func_inet_pton" >&6; } - if test "x$ac_cv_func_inet_pton" = xyes; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_socket" >&5 +$as_echo "$ac_cv_func_socket" >&6; } + if test "x$ac_cv_func_socket" = xyes; then : -$as_echo "#define HAVE_INET_PTON 1" >>confdefs.h +$as_echo "#define HAVE_SOCKET 1" >>confdefs.h fi @@ -18036,7 +18748,7 @@ save_LDFLAGS=$LDFLAGS save_LIBS=$LIBS - CPPFLAGS="$LIBCRYPT_CFLAGS $CFLAGS" + CPPFLAGS="$CPPFLAGS $LIBCRYPT_CFLAGS" LIBS="$LIBCRYPT_LIBS $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for crypt or crypt_r" >&5 $as_echo_n "checking for crypt or crypt_r... " >&6; } @@ -20619,7 +21331,15 @@ fi echo "$LIBREADLINE_PKG_ERRORS" >&5 - for ac_header in readline/readline.h + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + CPPFLAGS="$CPPFLAGS $LIBREADLINE_CFLAGS" + LDFLAGS="$LDFLAGS $LIBREADLINE_LIBS" + for ac_header in readline/readline.h do : ac_fn_c_check_header_mongrel "$LINENO" "readline/readline.h" "ac_cv_header_readline_readline_h" "$ac_includes_default" if test "x$ac_cv_header_readline_readline_h" = xyes; then : @@ -20627,12 +21347,6 @@ if test "x$ac_cv_header_readline_readline_h" = xyes; then : #define HAVE_READLINE_READLINE_H 1 _ACEOF - save_CFLAGS=$CFLAGS -save_CPPFLAGS=$CPPFLAGS -save_LDFLAGS=$LDFLAGS -save_LIBS=$LIBS - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5 $as_echo_n "checking for readline in -lreadline... " >&6; } if ${ac_cv_lib_readline_readline+:} false; then : @@ -20676,11 +21390,16 @@ if test "x$ac_cv_lib_readline_readline" = xyes; then : READLINE_LIBS=${LIBREADLINE_LIBS-"-lreadline"} else + with_readline=no +fi - with_readline=no +else + with_readline=no fi +done + CFLAGS=$save_CFLAGS CPPFLAGS=$save_CPPFLAGS @@ -20689,18 +21408,19 @@ LIBS=$save_LIBS -else - with_readline=no -fi - -done - - elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - for ac_header in readline/readline.h + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + CPPFLAGS="$CPPFLAGS $LIBREADLINE_CFLAGS" + LDFLAGS="$LDFLAGS $LIBREADLINE_LIBS" + for ac_header in readline/readline.h do : ac_fn_c_check_header_mongrel "$LINENO" "readline/readline.h" "ac_cv_header_readline_readline_h" "$ac_includes_default" if test "x$ac_cv_header_readline_readline_h" = xyes; then : @@ -20708,12 +21428,6 @@ if test "x$ac_cv_header_readline_readline_h" = xyes; then : #define HAVE_READLINE_READLINE_H 1 _ACEOF - save_CFLAGS=$CFLAGS -save_CPPFLAGS=$CPPFLAGS -save_LDFLAGS=$LDFLAGS -save_LIBS=$LIBS - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5 $as_echo_n "checking for readline in -lreadline... " >&6; } if ${ac_cv_lib_readline_readline+:} false; then : @@ -20757,11 +21471,16 @@ if test "x$ac_cv_lib_readline_readline" = xyes; then : READLINE_LIBS=${LIBREADLINE_LIBS-"-lreadline"} else + with_readline=no +fi - with_readline=no +else + with_readline=no fi +done + CFLAGS=$save_CFLAGS CPPFLAGS=$save_CPPFLAGS @@ -20770,13 +21489,6 @@ LIBS=$save_LIBS -else - with_readline=no -fi - -done - - else LIBREADLINE_CFLAGS=$pkg_cv_LIBREADLINE_CFLAGS LIBREADLINE_LIBS=$pkg_cv_LIBREADLINE_LIBS @@ -20853,7 +21565,15 @@ fi echo "$LIBEDIT_PKG_ERRORS" >&5 - for ac_header in editline/readline.h + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + CPPFLAGS="$CPPFLAGS $LIBEDIT_CFLAGS" + LDFLAGS="$LDFLAGS $LIBEDIT_LIBS" + for ac_header in editline/readline.h do : ac_fn_c_check_header_mongrel "$LINENO" "editline/readline.h" "ac_cv_header_editline_readline_h" "$ac_includes_default" if test "x$ac_cv_header_editline_readline_h" = xyes; then : @@ -20861,12 +21581,6 @@ if test "x$ac_cv_header_editline_readline_h" = xyes; then : #define HAVE_EDITLINE_READLINE_H 1 _ACEOF - save_CFLAGS=$CFLAGS -save_CPPFLAGS=$CPPFLAGS -save_LDFLAGS=$LDFLAGS -save_LIBS=$LIBS - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readline in -ledit" >&5 $as_echo_n "checking for readline in -ledit... " >&6; } if ${ac_cv_lib_edit_readline+:} false; then : @@ -20912,11 +21626,16 @@ if test "x$ac_cv_lib_edit_readline" = xyes; then : READLINE_LIBS=${LIBEDIT_LIBS-"-ledit"} else + with_readline=no +fi - with_readline=no +else + with_readline=no fi +done + CFLAGS=$save_CFLAGS CPPFLAGS=$save_CPPFLAGS @@ -20925,18 +21644,19 @@ LIBS=$save_LIBS -else - with_readline=no -fi - -done - - elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - for ac_header in editline/readline.h + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + CPPFLAGS="$CPPFLAGS $LIBEDIT_CFLAGS" + LDFLAGS="$LDFLAGS $LIBEDIT_LIBS" + for ac_header in editline/readline.h do : ac_fn_c_check_header_mongrel "$LINENO" "editline/readline.h" "ac_cv_header_editline_readline_h" "$ac_includes_default" if test "x$ac_cv_header_editline_readline_h" = xyes; then : @@ -20944,12 +21664,6 @@ if test "x$ac_cv_header_editline_readline_h" = xyes; then : #define HAVE_EDITLINE_READLINE_H 1 _ACEOF - save_CFLAGS=$CFLAGS -save_CPPFLAGS=$CPPFLAGS -save_LDFLAGS=$LDFLAGS -save_LIBS=$LIBS - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readline in -ledit" >&5 $as_echo_n "checking for readline in -ledit... " >&6; } if ${ac_cv_lib_edit_readline+:} false; then : @@ -20995,11 +21709,16 @@ if test "x$ac_cv_lib_edit_readline" = xyes; then : READLINE_LIBS=${LIBEDIT_LIBS-"-ledit"} else + with_readline=no +fi - with_readline=no +else + with_readline=no fi +done + CFLAGS=$save_CFLAGS CPPFLAGS=$save_CPPFLAGS @@ -21008,13 +21727,6 @@ LIBS=$save_LIBS -else - with_readline=no -fi - -done - - else LIBEDIT_CFLAGS=$pkg_cv_LIBEDIT_CFLAGS LIBEDIT_LIBS=$pkg_cv_LIBEDIT_LIBS @@ -21051,7 +21763,7 @@ save_LDFLAGS=$LDFLAGS save_LIBS=$LIBS - CPPFLAGS="$READLINE_CFLAGS $CFLAGS" + CPPFLAGS="$CPPFLAGS $READLINE_CFLAGS" LIBS="$READLINE_LIBS $LIBS" LIBS_SAVE=$LIBS @@ -24024,7 +24736,6 @@ esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OPENSSL_RPATH" >&5 $as_echo "$OPENSSL_RPATH" >&6; } - # This static linking is NOT OFFICIALLY SUPPORTED and not advertised. # Requires static OpenSSL build with position-independent code. Some features # like DSO engines or external OSSL providers don't work. Only tested with GCC @@ -24503,22 +25214,6 @@ case $host_cpu in #( esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for additional Modules/Setup files" >&5 -$as_echo_n "checking for additional Modules/Setup files... " >&6; } -case $ac_sys_system in #( - Emscripten) : - MODULES_SETUP_STDLIB=Modules/Setup.stdlib ;; #( - WASI) : - MODULES_SETUP_STDLIB=Modules/Setup.stdlib ;; #( - *) : - MODULES_SETUP_STDLIB= - ;; -esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MODULES_SETUP_STDLIB" >&5 -$as_echo "$MODULES_SETUP_STDLIB" >&6; } - - - MODULE_BLOCK= @@ -26683,6 +27378,40 @@ fi $as_echo "$py_cv_module__testmultiphase" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module xxsubtype" >&5 +$as_echo_n "checking for stdlib extension module xxsubtype... " >&6; } + if test "$py_cv_module_xxsubtype" != "n/a"; then : + + if test "$TEST_MODULES" = yes; then : + if true; then : + py_cv_module_xxsubtype=yes +else + py_cv_module_xxsubtype=missing +fi +else + py_cv_module_xxsubtype=disabled +fi + +fi + as_fn_append MODULE_BLOCK "MODULE_XXSUBTYPE_STATE=$py_cv_module_xxsubtype$as_nl" + if test "x$py_cv_module_xxsubtype" = xyes; then : + + + + +fi + if test "$py_cv_module_xxsubtype" = yes; then + MODULE_XXSUBTYPE_TRUE= + MODULE_XXSUBTYPE_FALSE='#' +else + MODULE_XXSUBTYPE_TRUE='#' + MODULE_XXSUBTYPE_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module_xxsubtype" >&5 +$as_echo "$py_cv_module_xxsubtype" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _xxtestfuzz" >&5 $as_echo_n "checking for stdlib extension module _xxtestfuzz... " >&6; } if test "$py_cv_module__xxtestfuzz" != "n/a"; then : @@ -27248,6 +27977,10 @@ if test -z "${MODULE__TESTMULTIPHASE_TRUE}" && test -z "${MODULE__TESTMULTIPHASE as_fn_error $? "conditional \"MODULE__TESTMULTIPHASE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE_XXSUBTYPE_TRUE}" && test -z "${MODULE_XXSUBTYPE_FALSE}"; then + as_fn_error $? "conditional \"MODULE_XXSUBTYPE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__XXTESTFUZZ_TRUE}" && test -z "${MODULE__XXTESTFUZZ_FALSE}"; then as_fn_error $? "conditional \"MODULE__XXTESTFUZZ\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -28467,7 +29200,11 @@ fi $as_echo "$as_me: creating Makefile" >&6;} $SHELL $srcdir/Modules/makesetup -c $srcdir/Modules/config.c.in \ -s Modules \ - Modules/Setup.local $MODULES_SETUP_STDLIB Modules/Setup.bootstrap $srcdir/Modules/Setup + Modules/Setup.local Modules/Setup.stdlib Modules/Setup.bootstrap $srcdir/Modules/Setup +if test $? -ne 0; then + as_fn_error $? "makesetup failed" "$LINENO" 5 +fi + mv config.c Modules if test -z "$PKG_CONFIG"; then diff --git a/configure.ac b/configure.ac index f940c9b2ddf001e0c6e028e6666250425c241ca4..38880fcc8cc15b7527775d577f363feef8a46061 100644 --- a/configure.ac +++ b/configure.ac @@ -69,6 +69,28 @@ AC_DEFUN([PY_CHECK_FUNC], AS_VAR_POPDEF([py_define]) ]) +dnl PY_CHECK_LIB(LIBRARY, FUNCTION, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], [OTHER-LIBRARIES]) +dnl Like AC_CHECK_LIB() but does not modify LIBS +AC_DEFUN([PY_CHECK_LIB], +[AS_VAR_COPY([py_check_lib_save_LIBS], [LIBS])] +[AC_CHECK_LIB($1, $2, $3, $4, $5)] +[AS_VAR_COPY([LIBS], [py_check_lib_save_LIBS])] +) + +dnl PY_CHECK_EMSCRIPTEN_PORT(PKG_VAR, [EMPORT_ARGS]) +dnl Use Emscripten port unless user passes ${PKG_VAR}_CFLAGS +dnl or ${PKG_VAR}_LIBS to configure. +AC_DEFUN([PY_CHECK_EMSCRIPTEN_PORT], [ + AS_VAR_PUSHDEF([py_cflags], [$1_CFLAGS]) + AS_VAR_PUSHDEF([py_libs], [$1_LIBS]) + AS_IF([test "$ac_sys_system" = "Emscripten" -a -z "$py_cflags" -a -z "$py_libs"], [ + py_cflags="$2" + py_libs="$2" + ]) + AS_VAR_POPDEF([py_cflags]) + AS_VAR_POPDEF([py_libs]) +]) + AC_SUBST(BASECPPFLAGS) if test "$srcdir" != . -a "$srcdir" != "$(pwd)"; then # If we're building out-of-tree, we need to make sure the following @@ -1119,8 +1141,8 @@ AS_CASE([$host/$ac_cv_cc_name], [armv7l-*-linux-gnueabihf/gcc], [PY_SUPPORT_TIER=3], dnl ARMv7 LE with hardware floats, any vendor, glibc, gcc [powerpc64le-*-linux-gnu/clang], [PY_SUPPORT_TIER=3], dnl Linux on PPC64 little endian, glibc, clang [s390x-*-linux-gnu/gcc], [PY_SUPPORT_TIER=3], dnl Linux on 64bit s390x (big endian), glibc, gcc - dnl [wasm32-unknown-emscripten/clang], [PY_SUPPORT_TIER=3], dnl WebAssembly Emscripten - dnl [wasm32-unknown-wasi/clang], [PY_SUPPORT_TIER=3], dnl WebAssembly System Interface + [wasm32-unknown-emscripten/clang], [PY_SUPPORT_TIER=3], dnl WebAssembly Emscripten + [wasm32-unknown-wasi/clang], [PY_SUPPORT_TIER=3], dnl WebAssembly System Interface [x86_64-*-freebsd*/clang], [PY_SUPPORT_TIER=3], dnl FreeBSD on AMD64 [PY_SUPPORT_TIER=0] ) @@ -2621,7 +2643,7 @@ AC_CHECK_HEADERS([ \ alloca.h asm/types.h bluetooth.h conio.h crypt.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/memfd.h \ linux/random.h linux/soundcard.h \ - linux/tipc.h linux/wait.h netinet/in.h netpacket/packet.h poll.h process.h pthread.h pty.h \ + linux/tipc.h linux/wait.h netdb.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 \ sys/endian.h sys/epoll.h sys/event.h sys/eventfd.h sys/file.h sys/ioctl.h sys/kern_control.h \ sys/loadavg.h sys/lock.h sys/memfd.h sys/mkdev.h sys/mman.h sys/modem.h sys/param.h sys/poll.h \ @@ -3371,12 +3393,12 @@ AS_VAR_IF([have_uuid], [missing], [ AC_DEFINE([HAVE_UUID_H], [1]) AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1]) ], [ - AC_CHECK_HEADERS([uuid/uuid.h], [ - WITH_SAVE_ENV( - [AC_CHECK_LIB([uuid], [uuid_generate_time], [have_uuid=yes]) - ]) - WITH_SAVE_ENV([ - AC_CHECK_LIB([uuid], [uuid_generate_time_safe], [ + WITH_SAVE_ENV([ + CPPFLAGS="$CPPFLAGS $LIBUUID_CFLAGS" + LDFLAGS="$LDFLAGS $LIBUUID_LIBS" + AC_CHECK_HEADERS([uuid/uuid.h], [ + PY_CHECK_LIB([uuid], [uuid_generate_time], [have_uuid=yes]) + PY_CHECK_LIB([uuid], [uuid_generate_time_safe], [ have_uuid=yes AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1]) ]) @@ -3569,7 +3591,6 @@ AS_VAR_IF([with_system_expat], [yes], [ ]) AC_SUBST([LIBEXPAT_CFLAGS]) -AC_SUBST([LIBEXPAT_LDFLAGS]) AC_SUBST([LIBEXPAT_INTERNAL]) # Check for use of the system libffi library @@ -3603,11 +3624,14 @@ dnl detect libffi have_libffi=missing AS_VAR_IF([with_system_ffi], [yes], [ PKG_CHECK_MODULES([LIBFFI], [libffi], [have_libffi=yes], [ - AC_CHECK_HEADER([ffi.h], [ - WITH_SAVE_ENV([ + WITH_SAVE_ENV([ + CPPFLAGS="$CPPFLAGS $LIBFFI_CFLAGS" + LDFLAGS="$LDFLAGS $LIBFFI_LIBS" + AC_CHECK_HEADER([ffi.h], [ AC_CHECK_LIB([ffi], [ffi_call], [ have_libffi=yes - LIBFFI_LIBS="-lffi" + LIBFFI_CFLAGS=${LIBFFI_CFLAGS-""} + LIBFFI_LIBS=${LIBFFI_LIBS-"-lffi"} ], [have_libffi=no]) ]) ]) @@ -3673,10 +3697,14 @@ AS_VAR_IF([with_system_libmpdec], [yes], [ LIBMPDEC_CFLAGS="-I\$(srcdir)/Modules/_decimal/libmpdec" LIBMPDEC_LDFLAGS="-lm \$(LIBMPDEC_A)" LIBMPDEC_INTERNAL="\$(LIBMPDEC_A)" + + dnl Disable forced inlining in debug builds, see GH-94847 + AS_VAR_IF([with_pydebug], [yes], [ + AS_VAR_APPEND([LIBMPDEC_CFLAGS], [" -DTEST_COVERAGE"]) + ]) ]) AC_SUBST([LIBMPDEC_CFLAGS]) -AC_SUBST([LIBMPDEC_LDFLAGS]) AC_SUBST([LIBMPDEC_INTERNAL]) # Check whether _decimal should use a coroutine-local or thread-local context @@ -3770,7 +3798,7 @@ PKG_CHECK_MODULES([LIBNSL], [libnsl], [have_nis=yes], [ AS_VAR_IF([have_nis], [yes], [ WITH_SAVE_ENV([ - CPPFLAGS="$LIBNSL_CFLAGS $CFLAGS" + CPPFLAGS="$CPPFLAGS $LIBNSL_CFLAGS" AC_CHECK_HEADERS([rpc/rpc.h]) ]) ]) @@ -3781,6 +3809,9 @@ AS_CASE([$ac_sys_system], [OSSAUDIODEV_LIBS=""] ) +dnl detect sqlite3 from Emscripten emport +PY_CHECK_EMSCRIPTEN_PORT([LIBSQLITE3], [-sUSE_SQLITE3]) + dnl Check for SQLite library. Use pkg-config if available. PKG_CHECK_MODULES( [LIBSQLITE3], [sqlite3 >= 3.7.15], [], [ @@ -3800,7 +3831,7 @@ AC_DEFUN([PY_CHECK_SQLITE_FUNC], [ WITH_SAVE_ENV([ dnl bpo-45774/GH-29507: The CPP check in AC_CHECK_HEADER can fail on FreeBSD, dnl hence CPPFLAGS instead of CFLAGS. - CPPFLAGS="$LIBSQLITE3_CFLAGS $CFLAGS" + CPPFLAGS="$CPPFLAGS $LIBSQLITE3_CFLAGS" LDFLAGS="$LIBSQLITE3_LIBS $LDFLAGS" AC_CHECK_HEADER([sqlite3.h], [ @@ -3904,7 +3935,7 @@ AS_CASE([$ac_sys_system], ) WITH_SAVE_ENV([ - CPPFLAGS="$TCLTK_CFLAGS $CFLAGS" + CPPFLAGS="$CPPFLAGS $TCLTK_CFLAGS" LIBS="$TCLTK_LIBS $LDFLAGS" AC_LINK_IFELSE([ @@ -3946,7 +3977,7 @@ dnl NOTE: gdbm does not provide a pkgconf file. AC_ARG_VAR([GDBM_CFLAGS], [C compiler flags for gdbm]) AC_ARG_VAR([GDBM_LIBS], [additional linker flags for gdbm]) WITH_SAVE_ENV([ - CPPFLAGS="$GDBM_CFLAGS $CFLAGS" + CPPFLAGS="$CPPFLAGS $GDBM_CFLAGS" LDFLAGS="$GDBM_LIBS $LDFLAGS" AC_CHECK_HEADERS([gdbm.h], [ AC_CHECK_LIB([gdbm], [gdbm_open], [ @@ -4176,9 +4207,11 @@ pthread_create (NULL, NULL, start_routine, NULL)]])],[ posix_threads=yes LIBS="$LIBS -lcma" ],[ - AC_MSG_ERROR([could not find pthreads on your system]) - ]) - ])])])])]) + AS_CASE([$ac_sys_system], + [WASI], [posix_threads=stub], + [AC_MSG_ERROR([could not find pthreads on your system])] + ) + ])])])])])]) AC_CHECK_LIB(mpc, usconfig, [ LIBS="$LIBS -lmpc" @@ -4241,6 +4274,9 @@ if test "$posix_threads" = "yes"; then AC_CHECK_FUNCS(pthread_getcpuclockid) fi +AS_VAR_IF([posix_threads], [stub], [ + AC_DEFINE([HAVE_PTHREAD_STUBS], [1], [Define if platform requires stubbed pthreads support]) +]) # Check for enable-ipv6 AH_TEMPLATE(ENABLE_IPV6, [Define if --enable-ipv6 is specified]) @@ -4622,11 +4658,11 @@ fi # checks for library functions AC_CHECK_FUNCS([ \ accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \ - copy_file_range ctermid dup3 execv explicit_bzero explicit_memset \ + copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \ faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \ fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \ gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \ - getgrnam_r getgrouplist getgroups getitimer getloadavg getlogin \ + getgrnam_r getgrouplist getgroups gethostname getitimer getloadavg getlogin \ getpeername getpgid getpid getppid getpriority _getpty \ getpwent getpwnam_r getpwuid getpwuid_r getresgid getresuid getrusage getsid getspent \ getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \ @@ -4790,81 +4826,98 @@ fi dnl Check for compression libraries AH_TEMPLATE([HAVE_ZLIB_COPY], [Define if the zlib library has inflateCopy]) +dnl detect zlib from Emscripten emport +PY_CHECK_EMSCRIPTEN_PORT([ZLIB], [-sUSE_ZLIB]) + PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.0], [ have_zlib=yes dnl zlib 1.2.0 (2003) added inflateCopy AC_DEFINE([HAVE_ZLIB_COPY], [1]) ], [ - AC_CHECK_HEADERS([zlib.h], [ - WITH_SAVE_ENV([ - AC_CHECK_LIB([z], [gzread], [ - have_zlib=yes - ZLIB_CFLAGS=${ZLIB_CFLAGS-""} - ZLIB_LIBS=${ZLIB_LIBS-"-lz"} - AC_CHECK_LIB([z], [inflateCopy], [AC_DEFINE([HAVE_ZLIB_COPY], [1])]) - ], [ - have_zlib=no - ]) + WITH_SAVE_ENV([ + CPPFLAGS="$CPPFLAGS $ZLIB_CFLAGS" + LDFLAGS="$LDFLAGS $ZLIB_LIBS" + AC_CHECK_HEADERS([zlib.h], [ + PY_CHECK_LIB([z], [gzread], [have_zlib=yes], [have_zlib=no]) + ], [have_zlib=no]) + AS_VAR_IF([have_zlib], [yes], [ + ZLIB_CFLAGS=${ZLIB_CFLAGS-""} + ZLIB_LIBS=${ZLIB_LIBS-"-lz"} + PY_CHECK_LIB([z], [inflateCopy], [AC_DEFINE([HAVE_ZLIB_COPY], [1])]) ]) - ], [have_zlib=no]) + ]) ]) -if test "$have_zlib" = "yes" -a "$ac_sys_system" = "Emscripten" -a "$ZLIB_LIBS" = "-lz"; then - ZLIB_CFLAGS="-sUSE_ZLIB" - ZLIB_LIBS="-sUSE_ZLIB" -fi - dnl binascii can use zlib for optimized crc32. AS_VAR_IF([have_zlib], [yes], [ BINASCII_CFLAGS="-DUSE_ZLIB_CRC32 $ZLIB_CFLAGS" BINASCII_LIBS="$ZLIB_LIBS" ]) +dnl detect bzip2 from Emscripten emport +PY_CHECK_EMSCRIPTEN_PORT([BZIP2], [-sUSE_BZIP2]) + PKG_CHECK_MODULES([BZIP2], [bzip2], [have_bzip2=yes], [ - AC_CHECK_HEADERS([bzlib.h], [ - WITH_SAVE_ENV([ - AC_CHECK_LIB([bz2], [BZ2_bzCompress], [ - have_bzip2=yes - BZIP2_CFLAGS=${BZIP2_CFLAGS-""} - BZIP2_LIBS=${BZIP2_LIBS-"-lbz2"} - ], [have_bzip2=no]) + WITH_SAVE_ENV([ + CPPFLAGS="$CPPFLAGS $BZIP2_CFLAGS" + LDFLAGS="$LDFLAGS $BZIP2_LIBS" + AC_CHECK_HEADERS([bzlib.h], [ + AC_CHECK_LIB([bz2], [BZ2_bzCompress], [have_bzip2=yes], [have_bzip2=no]) + ], [have_bzip2=no]) + AS_VAR_IF([have_bzip2], [yes], [ + BZIP2_CFLAGS=${BZIP2_CFLAGS-""} + BZIP2_LIBS=${BZIP2_LIBS-"-lbz2"} ]) - ], [have_bzip2=no]) + ]) ]) -if test "$have_bzip2" = "yes" -a "$ac_sys_system" = "Emscripten" -a "$BZIP2_LIBS" = "-lbz2"; then - BZIP2_CFLAGS="-sUSE_BZIP2" - BZIP2_LIBS="-sUSE_BZIP2" -fi - - PKG_CHECK_MODULES([LIBLZMA], [liblzma], [have_liblzma=yes], [ - AC_CHECK_HEADERS([lzma.h], [ - WITH_SAVE_ENV([ - AC_CHECK_LIB([lzma], [lzma_easy_encoder], [ - have_liblzma=yes - LIBLZMA_CFLAGS=${LIBLZMA_CFLAGS-""} - LIBLZMA_LIBS=${LIBLZMA_LIBS-"-llzma"} - ], [have_liblzma=no]) + WITH_SAVE_ENV([ + CPPFLAGS="$CPPFLAGS $LIBLZMA_CFLAGS" + LDFLAGS="$LDFLAGS $LIBLZMA_LIBS" + AC_CHECK_HEADERS([lzma.h], [ + AC_CHECK_LIB([lzma], [lzma_easy_encoder], [have_liblzma=yes], [have_liblzma=no]) + ], [have_liblzma=no]) + AS_VAR_IF([have_liblzma], [yes], [ + LIBLZMA_CFLAGS=${LIBLZMA_CFLAGS-""} + LIBLZMA_LIBS=${LIBLZMA_LIBS-"-llzma"} ]) - ], [have_liblzma=no]) + ]) ]) -PY_CHECK_FUNC([hstrerror], [#include <netdb.h>]) +dnl PY_CHECK_NETDB_FUNC(FUNCTION) +AC_DEFUN([PY_CHECK_NETDB_FUNC], [PY_CHECK_FUNC([$1], [#include <netdb.h>])]) -PY_CHECK_FUNC([inet_aton], [ -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -]) +PY_CHECK_NETDB_FUNC([hstrerror]) +dnl not available in WASI yet +PY_CHECK_NETDB_FUNC([getservbyname]) +PY_CHECK_NETDB_FUNC([getservbyport]) +PY_CHECK_NETDB_FUNC([gethostbyname]) +PY_CHECK_NETDB_FUNC([gethostbyaddr]) +PY_CHECK_NETDB_FUNC([getprotobyname]) -PY_CHECK_FUNC([inet_pton], [ +dnl PY_CHECK_SOCKET_FUNC(FUNCTION) +AC_DEFUN([PY_CHECK_SOCKET_FUNC], [PY_CHECK_FUNC([$1], [ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> -]) +])]) + +PY_CHECK_SOCKET_FUNC([inet_aton]) +PY_CHECK_SOCKET_FUNC([inet_ntoa]) +PY_CHECK_SOCKET_FUNC([inet_pton]) +dnl not available in WASI yet +PY_CHECK_SOCKET_FUNC([getpeername]) +PY_CHECK_SOCKET_FUNC([getsockname]) +PY_CHECK_SOCKET_FUNC([accept]) +PY_CHECK_SOCKET_FUNC([bind]) +PY_CHECK_SOCKET_FUNC([connect]) +PY_CHECK_SOCKET_FUNC([listen]) +PY_CHECK_SOCKET_FUNC([recvfrom]) +PY_CHECK_SOCKET_FUNC([sendto]) +PY_CHECK_SOCKET_FUNC([setsockopt]) +PY_CHECK_SOCKET_FUNC([socket]) # On some systems, setgroups is in unistd.h, on others, in grp.h PY_CHECK_FUNC([setgroups], [ @@ -4930,7 +4983,7 @@ PKG_CHECK_MODULES([LIBCRYPT], [libxcrypt >= 3.1.1], [ ]) WITH_SAVE_ENV([ - CPPFLAGS="$LIBCRYPT_CFLAGS $CFLAGS" + CPPFLAGS="$CPPFLAGS $LIBCRYPT_CFLAGS" LIBS="$LIBCRYPT_LIBS $LIBS" AC_CACHE_CHECK([for crypt or crypt_r], [ac_cv_crypt_crypt], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([ @@ -5814,17 +5867,17 @@ AS_VAR_IF([with_readline], [readline], [ READLINE_CFLAGS=$LIBREADLINE_CFLAGS READLINE_LIBS=$LIBREADLINE_LIBS ], [ - AC_CHECK_HEADERS([readline/readline.h], [ - WITH_SAVE_ENV([ + WITH_SAVE_ENV([ + CPPFLAGS="$CPPFLAGS $LIBREADLINE_CFLAGS" + LDFLAGS="$LDFLAGS $LIBREADLINE_LIBS" + AC_CHECK_HEADERS([readline/readline.h], [ AC_CHECK_LIB([readline], [readline], [ LIBREADLINE=readline READLINE_CFLAGS=${LIBREADLINE_CFLAGS-""} READLINE_LIBS=${LIBREADLINE_LIBS-"-lreadline"} - ], [ - with_readline=no - ]) - ]) - ], [with_readline=no]) + ], [with_readline=no]) + ], [with_readline=no]) + ]) ]) ]) @@ -5835,18 +5888,18 @@ AS_VAR_IF([with_readline], [edit], [ READLINE_CFLAGS=$LIBEDIT_CFLAGS READLINE_LIBS=$LIBEDIT_LIBS ], [ - AC_CHECK_HEADERS([editline/readline.h], [ - WITH_SAVE_ENV([ + WITH_SAVE_ENV([ + CPPFLAGS="$CPPFLAGS $LIBEDIT_CFLAGS" + LDFLAGS="$LDFLAGS $LIBEDIT_LIBS" + AC_CHECK_HEADERS([editline/readline.h], [ AC_CHECK_LIB([edit], [readline], [ LIBREADLINE=edit AC_DEFINE([WITH_EDITLINE], [1]) READLINE_CFLAGS=${LIBEDIT_CFLAGS-""} READLINE_LIBS=${LIBEDIT_LIBS-"-ledit"} - ], [ - with_readline=no - ]) - ]) - ], [with_readline=no]) + ], [with_readline=no]) + ], [with_readline=no]) + ]) ]) ]) @@ -5860,7 +5913,7 @@ AS_VAR_IF([with_readline], [no], [ AC_MSG_RESULT([$with_readline (CFLAGS: $READLINE_CFLAGS, LIBS: $READLINE_LIBS)]) WITH_SAVE_ENV([ - CPPFLAGS="$READLINE_CFLAGS $CFLAGS" + CPPFLAGS="$CPPFLAGS $READLINE_CFLAGS" LIBS="$READLINE_LIBS $LIBS" LIBS_SAVE=$LIBS @@ -6736,7 +6789,6 @@ AS_CASE($with_openssl_rpath, ] ) AC_MSG_RESULT($OPENSSL_RPATH) -AC_SUBST([OPENSSL_RPATH]) # This static linking is NOT OFFICIALLY SUPPORTED and not advertised. # Requires static OpenSSL build with position-independent code. Some features @@ -6983,17 +7035,6 @@ AS_CASE([$host_cpu], ) AC_SUBST([MODULE_BUILDTYPE]) -dnl Use Modules/Setup.stdlib as additional provider? -AC_MSG_CHECKING([for additional Modules/Setup files]) -AS_CASE([$ac_sys_system], - [Emscripten], [MODULES_SETUP_STDLIB=Modules/Setup.stdlib], - [WASI], [MODULES_SETUP_STDLIB=Modules/Setup.stdlib], - [MODULES_SETUP_STDLIB=] -) -AC_MSG_RESULT([$MODULES_SETUP_STDLIB]) -AC_SUBST([MODULES_SETUP_STDLIB]) - - dnl _MODULE_BLOCK_ADD([VAR], [VALUE]) dnl internal: adds $1=quote($2) to MODULE_BLOCK AC_DEFUN([_MODULE_BLOCK_ADD], [AS_VAR_APPEND([MODULE_BLOCK], ["$1=_AS_QUOTE([$2])$as_nl"])]) @@ -7198,6 +7239,7 @@ PY_STDLIB_MOD([_testinternalcapi], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testbuffer], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testimportmultiple], [test "$TEST_MODULES" = yes], [test "$ac_cv_func_dlopen" = yes]) PY_STDLIB_MOD([_testmultiphase], [test "$TEST_MODULES" = yes], [test "$ac_cv_func_dlopen" = yes]) +PY_STDLIB_MOD([xxsubtype], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_xxtestfuzz], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_ctypes_test], [test "$TEST_MODULES" = yes], [test "$have_libffi" = yes -a "$ac_cv_func_dlopen" = yes], @@ -7227,7 +7269,11 @@ fi AC_MSG_NOTICE([creating Makefile]) $SHELL $srcdir/Modules/makesetup -c $srcdir/Modules/config.c.in \ -s Modules \ - Modules/Setup.local $MODULES_SETUP_STDLIB Modules/Setup.bootstrap $srcdir/Modules/Setup + Modules/Setup.local Modules/Setup.stdlib Modules/Setup.bootstrap $srcdir/Modules/Setup +if test $? -ne 0; then + AC_MSG_ERROR([makesetup failed]) +fi + mv config.c Modules if test -z "$PKG_CONFIG"; then diff --git a/pyconfig.h.in b/pyconfig.h.in index aa9fc559fa2511cc507b33baa986211e430fdf1d..10e7ad12fa982c2429726b7ed22f3c8f754254b3 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -51,6 +51,9 @@ /* Define if getpgrp() must be called as getpgrp(0). */ #undef GETPGRP_HAVE_ARG +/* Define if you have the 'accept' function. */ +#undef HAVE_ACCEPT + /* Define to 1 if you have the `accept4' function. */ #undef HAVE_ACCEPT4 @@ -81,6 +84,9 @@ /* Define to 1 if you have the `atanh' function. */ #undef HAVE_ATANH +/* Define if you have the 'bind' function. */ +#undef HAVE_BIND + /* Define to 1 if you have the `bind_textdomain_codeset' function. */ #undef HAVE_BIND_TEXTDOMAIN_CODESET @@ -160,6 +166,9 @@ /* Define to 1 if you have the <conio.h> header file. */ #undef HAVE_CONIO_H +/* Define if you have the 'connect' function. */ +#undef HAVE_CONNECT + /* Define to 1 if you have the `copy_file_range' function. */ #undef HAVE_COPY_FILE_RANGE @@ -278,6 +287,9 @@ /* Define to 1 if you have the `dlopen' function. */ #undef HAVE_DLOPEN +/* Define to 1 if you have the `dup' function. */ +#undef HAVE_DUP + /* Define to 1 if you have the `dup2' function. */ #undef HAVE_DUP2 @@ -477,6 +489,9 @@ /* Define to 1 if you have the `getgroups' function. */ #undef HAVE_GETGROUPS +/* Define if you have the 'gethostbyaddr' function. */ +#undef HAVE_GETHOSTBYADDR + /* Define to 1 if you have the `gethostbyname' function. */ #undef HAVE_GETHOSTBYNAME @@ -492,6 +507,9 @@ /* Define this if you have the 6-arg version of gethostbyname_r(). */ #undef HAVE_GETHOSTBYNAME_R_6_ARG +/* Define to 1 if you have the `gethostname' function. */ +#undef HAVE_GETHOSTNAME + /* Define to 1 if you have the `getitimer' function. */ #undef HAVE_GETITIMER @@ -507,7 +525,7 @@ /* Define if you have the 'getpagesize' function. */ #undef HAVE_GETPAGESIZE -/* Define to 1 if you have the `getpeername' function. */ +/* Define if you have the 'getpeername' function. */ #undef HAVE_GETPEERNAME /* Define to 1 if you have the `getpgid' function. */ @@ -525,6 +543,9 @@ /* Define to 1 if you have the `getpriority' function. */ #undef HAVE_GETPRIORITY +/* Define if you have the 'getprotobyname' function. */ +#undef HAVE_GETPROTOBYNAME + /* Define to 1 if you have the `getpwent' function. */ #undef HAVE_GETPWENT @@ -552,9 +573,18 @@ /* Define to 1 if you have the `getrusage' function. */ #undef HAVE_GETRUSAGE +/* Define if you have the 'getservbyname' function. */ +#undef HAVE_GETSERVBYNAME + +/* Define if you have the 'getservbyport' function. */ +#undef HAVE_GETSERVBYPORT + /* Define to 1 if you have the `getsid' function. */ #undef HAVE_GETSID +/* Define if you have the 'getsockname' function. */ +#undef HAVE_GETSOCKNAME + /* Define to 1 if you have the `getspent' function. */ #undef HAVE_GETSPENT @@ -589,6 +619,9 @@ /* Define if you have the 'inet_aton' function. */ #undef HAVE_INET_ATON +/* Define if you have the 'inet_ntoa' function. */ +#undef HAVE_INET_NTOA + /* Define if you have the 'inet_pton' function. */ #undef HAVE_INET_PTON @@ -715,6 +748,9 @@ /* Define to 1 if you have the <linux/wait.h> header file. */ #undef HAVE_LINUX_WAIT_H +/* Define if you have the 'listen' function. */ +#undef HAVE_LISTEN + /* Define to 1 if you have the `lockf' function. */ #undef HAVE_LOCKF @@ -799,6 +835,9 @@ /* Define to 1 if you have the <netcan/can.h> header file. */ #undef HAVE_NETCAN_CAN_H +/* Define to 1 if you have the <netdb.h> header file. */ +#undef HAVE_NETDB_H + /* Define to 1 if you have the <netinet/in.h> header file. */ #undef HAVE_NETINET_IN_H @@ -899,6 +938,9 @@ /* Define to 1 if you have the `pthread_sigmask' function. */ #undef HAVE_PTHREAD_SIGMASK +/* Define if platform requires stubbed pthreads support */ +#undef HAVE_PTHREAD_STUBS + /* Define to 1 if you have the <pty.h> header file. */ #undef HAVE_PTY_H @@ -926,6 +968,9 @@ /* Define to 1 if you have the `realpath' function. */ #undef HAVE_REALPATH +/* Define if you have the 'recvfrom' function. */ +#undef HAVE_RECVFROM + /* Define to 1 if you have the `renameat' function. */ #undef HAVE_RENAMEAT @@ -995,6 +1040,9 @@ /* Define to 1 if you have the `sendfile' function. */ #undef HAVE_SENDFILE +/* Define if you have the 'sendto' function. */ +#undef HAVE_SENDTO + /* Define to 1 if you have the `setegid' function. */ #undef HAVE_SETEGID @@ -1043,6 +1091,9 @@ /* Define to 1 if you have the `setsid' function. */ #undef HAVE_SETSID +/* Define if you have the 'setsockopt' function. */ +#undef HAVE_SETSOCKOPT + /* Define to 1 if you have the `setuid' function. */ #undef HAVE_SETUID @@ -1106,6 +1157,9 @@ /* struct sockaddr_storage (sys/socket.h) */ #undef HAVE_SOCKADDR_STORAGE +/* Define if you have the 'socket' function. */ +#undef HAVE_SOCKET + /* Define if you have the 'socketpair' function. */ #undef HAVE_SOCKETPAIR diff --git a/setup.py b/setup.py deleted file mode 100644 index 7c71ac6ec64141e2d22e3cdea57e3eacfd045016..0000000000000000000000000000000000000000 --- a/setup.py +++ /dev/null @@ -1,1294 +0,0 @@ -# Autodetecting setup.py script for building the Python extensions - -import argparse -import importlib._bootstrap -import importlib.machinery -import importlib.util -import logging -import os -import re -import shlex -import sys -import sysconfig -import warnings -from glob import glob, escape -import _osx_support - - -try: - import subprocess - del subprocess - SUBPROCESS_BOOTSTRAP = False -except ImportError: - # Bootstrap Python: distutils.spawn uses subprocess to build C extensions, - # subprocess requires C extensions built by setup.py like _posixsubprocess. - # - # Use _bootsubprocess which only uses the os module. - # - # It is dropped from sys.modules as soon as all C extension modules - # are built. - import _bootsubprocess - sys.modules['subprocess'] = _bootsubprocess - del _bootsubprocess - SUBPROCESS_BOOTSTRAP = True - - -with warnings.catch_warnings(): - # bpo-41282 (PEP 632) deprecated distutils but setup.py still uses it - warnings.filterwarnings( - "ignore", - "The distutils package is deprecated", - DeprecationWarning - ) - warnings.filterwarnings( - "ignore", - "The distutils.sysconfig module is deprecated, use sysconfig instead", - DeprecationWarning - ) - - from distutils.command.build_ext import build_ext - from distutils.command.install import install - from distutils.command.install_lib import install_lib - from distutils.core import Extension, setup - from distutils.errors import CCompilerError, DistutilsError - from distutils.spawn import find_executable - - -# This global variable is used to hold the list of modules to be disabled. -DISABLED_MODULE_LIST = [] - -# --list-module-names option used by Tools/scripts/generate_module_names.py -LIST_MODULE_NAMES = False - - -logging.basicConfig(format='%(message)s', level=logging.INFO) -log = logging.getLogger('setup') - - -def get_platform(): - # Cross compiling - if "_PYTHON_HOST_PLATFORM" in os.environ: - return os.environ["_PYTHON_HOST_PLATFORM"] - - # Get value of sys.platform - if sys.platform.startswith('osf1'): - return 'osf1' - return sys.platform - - -CROSS_COMPILING = ("_PYTHON_HOST_PLATFORM" in os.environ) -HOST_PLATFORM = get_platform() -MS_WINDOWS = (HOST_PLATFORM == 'win32') -CYGWIN = (HOST_PLATFORM == 'cygwin') -MACOS = (HOST_PLATFORM == 'darwin') -AIX = (HOST_PLATFORM.startswith('aix')) -VXWORKS = ('vxworks' in HOST_PLATFORM) -EMSCRIPTEN = HOST_PLATFORM == 'emscripten-wasm32' -CC = os.environ.get("CC") -if not CC: - CC = sysconfig.get_config_var("CC") - -if EMSCRIPTEN: - # emcc is a Python script from a different Python interpreter. - os.environ.pop("PYTHONPATH", None) - - -SUMMARY = """ -Python is an interpreted, interactive, object-oriented programming -language. It is often compared to Tcl, Perl, Scheme or Java. - -Python combines remarkable power with very clear syntax. It has -modules, classes, exceptions, very high level dynamic data types, and -dynamic typing. There are interfaces to many system calls and -libraries, as well as to various windowing systems (X11, Motif, Tk, -Mac, MFC). New built-in modules are easily written in C or C++. Python -is also usable as an extension language for applications that need a -programmable interface. - -The Python implementation is portable: it runs on many brands of UNIX, -on Windows, DOS, Mac, Amiga... If your favorite system isn't -listed here, it may still be supported, if there's a C compiler for -it. Ask around on comp.lang.python -- or just try compiling Python -yourself. -""" - -CLASSIFIERS = """ -Development Status :: 6 - Mature -License :: OSI Approved :: Python Software Foundation License -Natural Language :: English -Programming Language :: C -Programming Language :: Python -Topic :: Software Development -""" - - -def run_command(cmd): - status = os.system(cmd) - return os.waitstatus_to_exitcode(status) - - -# Set common compiler and linker flags derived from the Makefile, -# reserved for building the interpreter and the stdlib modules. -# See bpo-21121 and bpo-35257 -def set_compiler_flags(compiler_flags, compiler_py_flags_nodist): - flags = sysconfig.get_config_var(compiler_flags) - py_flags_nodist = sysconfig.get_config_var(compiler_py_flags_nodist) - sysconfig.get_config_vars()[compiler_flags] = flags + ' ' + py_flags_nodist - - -def add_dir_to_list(dirlist, dir): - """Add the directory 'dir' to the list 'dirlist' (after any relative - directories) if: - - 1) 'dir' is not already in 'dirlist' - 2) 'dir' actually exists, and is a directory. - """ - if dir is None or not os.path.isdir(dir) or dir in dirlist: - return - for i, path in enumerate(dirlist): - if not os.path.isabs(path): - dirlist.insert(i + 1, dir) - return - dirlist.insert(0, dir) - - -def sysroot_paths(make_vars, subdirs): - """Get the paths of sysroot sub-directories. - - * make_vars: a sequence of names of variables of the Makefile where - sysroot may be set. - * subdirs: a sequence of names of subdirectories used as the location for - headers or libraries. - """ - - dirs = [] - for var_name in make_vars: - var = sysconfig.get_config_var(var_name) - if var is not None: - m = re.search(r'--sysroot=([^"]\S*|"[^"]+")', var) - if m is not None: - sysroot = m.group(1).strip('"') - for subdir in subdirs: - if os.path.isabs(subdir): - subdir = subdir[1:] - path = os.path.join(sysroot, subdir) - if os.path.isdir(path): - dirs.append(path) - break - return dirs - - -MACOS_SDK_ROOT = None -MACOS_SDK_SPECIFIED = None - -def macosx_sdk_root(): - """Return the directory of the current macOS SDK. - - If no SDK was explicitly configured, call the compiler to find which - include files paths are being searched by default. Use '/' if the - compiler is searching /usr/include (meaning system header files are - installed) or use the root of an SDK if that is being searched. - (The SDK may be supplied via Xcode or via the Command Line Tools). - The SDK paths used by Apple-supplied tool chains depend on the - setting of various variables; see the xcrun man page for more info. - Also sets MACOS_SDK_SPECIFIED for use by macosx_sdk_specified(). - """ - global MACOS_SDK_ROOT, MACOS_SDK_SPECIFIED - - # If already called, return cached result. - if MACOS_SDK_ROOT: - return MACOS_SDK_ROOT - - cflags = sysconfig.get_config_var('CFLAGS') - m = re.search(r'-isysroot\s*(\S+)', cflags) - if m is not None: - MACOS_SDK_ROOT = m.group(1) - MACOS_SDK_SPECIFIED = MACOS_SDK_ROOT != '/' - else: - MACOS_SDK_ROOT = _osx_support._default_sysroot( - sysconfig.get_config_var('CC')) - MACOS_SDK_SPECIFIED = False - - return MACOS_SDK_ROOT - - -def is_macosx_sdk_path(path): - """ - Returns True if 'path' can be located in a macOS SDK - """ - return ( (path.startswith('/usr/') and not path.startswith('/usr/local')) - or path.startswith('/System/Library') - or path.startswith('/System/iOSSupport') ) - - -def grep_headers_for(function, headers): - for header in headers: - with open(header, 'r', errors='surrogateescape') as f: - if function in f.read(): - return True - return False - - -def find_file(filename, std_dirs, paths): - """Searches for the directory where a given file is located, - and returns a possibly-empty list of additional directories, or None - if the file couldn't be found at all. - - 'filename' is the name of a file, such as readline.h or libcrypto.a. - 'std_dirs' is the list of standard system directories; if the - file is found in one of them, no additional directives are needed. - 'paths' is a list of additional locations to check; if the file is - found in one of them, the resulting list will contain the directory. - """ - if MACOS: - # Honor the MacOSX SDK setting when one was specified. - # An SDK is a directory with the same structure as a real - # system, but with only header files and libraries. - sysroot = macosx_sdk_root() - - # Check the standard locations - for dir_ in std_dirs: - f = os.path.join(dir_, filename) - - if MACOS and is_macosx_sdk_path(dir_): - f = os.path.join(sysroot, dir_[1:], filename) - - if os.path.exists(f): return [] - - # Check the additional directories - for dir_ in paths: - f = os.path.join(dir_, filename) - - if MACOS and is_macosx_sdk_path(dir_): - f = os.path.join(sysroot, dir_[1:], filename) - - if os.path.exists(f): - return [dir_] - - # Not found anywhere - return None - - -def validate_tzpath(): - base_tzpath = sysconfig.get_config_var('TZPATH') - if not base_tzpath: - return - - tzpaths = base_tzpath.split(os.pathsep) - bad_paths = [tzpath for tzpath in tzpaths if not os.path.isabs(tzpath)] - if bad_paths: - raise ValueError('TZPATH must contain only absolute paths, ' - + f'found:\n{tzpaths!r}\nwith invalid paths:\n' - + f'{bad_paths!r}') - - -def find_module_file(module, dirlist): - """Find a module in a set of possible folders. If it is not found - return the unadorned filename""" - dirs = find_file(module, [], dirlist) - if not dirs: - return module - if len(dirs) > 1: - log.info(f"WARNING: multiple copies of {module} found") - return os.path.abspath(os.path.join(dirs[0], module)) - - -class PyBuildExt(build_ext): - - def __init__(self, dist): - build_ext.__init__(self, dist) - self.srcdir = None - self.lib_dirs = None - self.inc_dirs = None - self.config_h_vars = None - self.failed = [] - self.failed_on_import = [] - self.missing = [] - self.disabled_configure = [] - if '-j' in os.environ.get('MAKEFLAGS', ''): - self.parallel = True - - def add(self, ext): - self.extensions.append(ext) - - def addext(self, ext, *, update_flags=True): - """Add extension with Makefile MODULE_{name} support - """ - if update_flags: - self.update_extension_flags(ext) - - state = sysconfig.get_config_var(f"MODULE_{ext.name.upper()}_STATE") - if state == "yes": - self.extensions.append(ext) - elif state == "disabled": - self.disabled_configure.append(ext.name) - elif state == "missing": - self.missing.append(ext.name) - elif state == "n/a": - # not available on current platform - pass - else: - # not migrated to MODULE_{name}_STATE yet. - self.announce( - f'WARNING: Makefile is missing module variable for "{ext.name}"', - level=2 - ) - self.extensions.append(ext) - - def update_extension_flags(self, ext): - """Update extension flags with module CFLAGS and LDFLAGS - - Reads MODULE_{name}_CFLAGS and _LDFLAGS - - Distutils appends extra args to the compiler arguments. Some flags like - -I must appear earlier, otherwise the pre-processor picks up files - from system include directories. - """ - upper_name = ext.name.upper() - # Parse compiler flags (-I, -D, -U, extra args) - cflags = sysconfig.get_config_var(f"MODULE_{upper_name}_CFLAGS") - if cflags: - for token in shlex.split(cflags): - switch = token[0:2] - value = token[2:] - if switch == '-I': - ext.include_dirs.append(value) - elif switch == '-D': - key, _, val = value.partition("=") - if not val: - val = None - ext.define_macros.append((key, val)) - elif switch == '-U': - ext.undef_macros.append(value) - else: - ext.extra_compile_args.append(token) - - # Parse linker flags (-L, -l, extra objects, extra args) - ldflags = sysconfig.get_config_var(f"MODULE_{upper_name}_LDFLAGS") - if ldflags: - for token in shlex.split(ldflags): - switch = token[0:2] - value = token[2:] - if switch == '-L': - ext.library_dirs.append(value) - elif switch == '-l': - ext.libraries.append(value) - elif ( - token[0] != '-' and - token.endswith(('.a', '.o', '.so', '.sl', '.dylib')) - ): - ext.extra_objects.append(token) - else: - ext.extra_link_args.append(token) - - return ext - - def set_srcdir(self): - self.srcdir = sysconfig.get_config_var('srcdir') - if not self.srcdir: - # Maybe running on Windows but not using CYGWIN? - raise ValueError("No source directory; cannot proceed.") - self.srcdir = os.path.abspath(self.srcdir) - - def remove_disabled(self): - # Remove modules that are present on the disabled list - extensions = [ext for ext in self.extensions - if ext.name not in DISABLED_MODULE_LIST] - self.extensions = extensions - - def update_sources_depends(self): - # Fix up the autodetected modules, prefixing all the source files - # with Modules/. - # Add dependencies from MODULE_{name}_DEPS variable - moddirlist = [ - # files in Modules/ directory - os.path.join(self.srcdir, 'Modules'), - # files relative to build base, e.g. libmpdec.a, libexpat.a - os.getcwd() - ] - - # Python header files - include_dir = escape(sysconfig.get_path('include')) - headers = [sysconfig.get_config_h_filename()] - headers.extend(glob(os.path.join(include_dir, "*.h"))) - headers.extend(glob(os.path.join(include_dir, "cpython", "*.h"))) - headers.extend(glob(os.path.join(include_dir, "internal", "*.h"))) - - for ext in self.extensions: - ext.sources = [ find_module_file(filename, moddirlist) - for filename in ext.sources ] - # Update dependencies from Makefile - makedeps = sysconfig.get_config_var(f"MODULE_{ext.name.upper()}_DEPS") - if makedeps: - # remove backslashes from line break continuations - ext.depends.extend( - dep for dep in makedeps.split() if dep != "\\" - ) - ext.depends = [ - find_module_file(filename, moddirlist) for filename in ext.depends - ] - # re-compile extensions if a header file has been changed - ext.depends.extend(headers) - - def handle_configured_extensions(self): - # The sysconfig variables built by makesetup that list the already - # built modules and the disabled modules as configured by the Setup - # files. - sysconf_built = set(sysconfig.get_config_var('MODBUILT_NAMES').split()) - sysconf_shared = set(sysconfig.get_config_var('MODSHARED_NAMES').split()) - sysconf_dis = set(sysconfig.get_config_var('MODDISABLED_NAMES').split()) - - mods_built = [] - mods_disabled = [] - for ext in self.extensions: - # If a module has already been built or has been disabled in the - # Setup files, don't build it here. - if ext.name in sysconf_built: - mods_built.append(ext) - if ext.name in sysconf_dis: - mods_disabled.append(ext) - - mods_configured = mods_built + mods_disabled - if mods_configured: - self.extensions = [x for x in self.extensions if x not in - mods_configured] - # Remove the shared libraries built by a previous build. - for ext in mods_configured: - # Don't remove shared extensions which have been built - # by Modules/Setup - if ext.name in sysconf_shared: - continue - fullpath = self.get_ext_fullpath(ext.name) - if os.path.lexists(fullpath): - os.unlink(fullpath) - - return mods_built, mods_disabled - - def set_compiler_executables(self): - # When you run "make CC=altcc" or something similar, you really want - # those environment variables passed into the setup.py phase. Here's - # a small set of useful ones. - compiler = os.environ.get('CC') - args = {} - # unfortunately, distutils doesn't let us provide separate C and C++ - # compilers - if compiler is not None: - (ccshared,cflags) = sysconfig.get_config_vars('CCSHARED','CFLAGS') - args['compiler_so'] = compiler + ' ' + ccshared + ' ' + cflags - self.compiler.set_executables(**args) - - def build_extensions(self): - self.set_srcdir() - self.set_compiler_executables() - self.configure_compiler() - self.init_inc_lib_dirs() - - # Detect which modules should be compiled - self.detect_modules() - - if not LIST_MODULE_NAMES: - self.remove_disabled() - - self.update_sources_depends() - mods_built, mods_disabled = self.handle_configured_extensions() - - if LIST_MODULE_NAMES: - for ext in self.extensions: - print(ext.name) - for name in self.missing: - print(name) - return - - build_ext.build_extensions(self) - - if SUBPROCESS_BOOTSTRAP: - # Drop our custom subprocess module: - # use the newly built subprocess module - del sys.modules['subprocess'] - - for ext in self.extensions: - self.check_extension_import(ext) - - self.summary(mods_built, mods_disabled) - - def summary(self, mods_built, mods_disabled): - longest = max([len(e.name) for e in self.extensions], default=0) - if self.failed or self.failed_on_import: - all_failed = self.failed + self.failed_on_import - longest = max(longest, max([len(name) for name in all_failed])) - - def print_three_column(lst): - lst.sort(key=str.lower) - # guarantee zip() doesn't drop anything - while len(lst) % 3: - lst.append("") - for e, f, g in zip(lst[::3], lst[1::3], lst[2::3]): - print("%-*s %-*s %-*s" % (longest, e, longest, f, - longest, g)) - - if self.missing: - print() - print("The necessary bits to build these optional modules were not " - "found:") - print_three_column(self.missing) - print("To find the necessary bits, look in setup.py in" - " detect_modules() for the module's name.") - print() - - if mods_built: - print() - print("The following modules found by detect_modules() in" - " setup.py, have been") - print("built by the Makefile instead, as configured by the" - " Setup files:") - print_three_column([ext.name for ext in mods_built]) - print() - - if mods_disabled: - print() - print("The following modules found by detect_modules() in" - " setup.py have not") - print("been built, they are *disabled* in the Setup files:") - print_three_column([ext.name for ext in mods_disabled]) - print() - - if self.disabled_configure: - print() - print("The following modules found by detect_modules() in" - " setup.py have not") - print("been built, they are *disabled* by configure:") - print_three_column(self.disabled_configure) - print() - - if self.failed: - failed = self.failed[:] - print() - print("Failed to build these modules:") - print_three_column(failed) - print() - - if self.failed_on_import: - failed = self.failed_on_import[:] - print() - print("Following modules built successfully" - " but were removed because they could not be imported:") - print_three_column(failed) - print() - - if any('_ssl' in l - for l in (self.missing, self.failed, self.failed_on_import)): - print() - print("Could not build the ssl module!") - print("Python requires a OpenSSL 1.1.1 or newer") - if sysconfig.get_config_var("OPENSSL_LDFLAGS"): - print("Custom linker flags may require --with-openssl-rpath=auto") - print() - - if os.environ.get("PYTHONSTRICTEXTENSIONBUILD") and ( - self.failed or self.failed_on_import or self.missing - ): - raise RuntimeError("Failed to build some stdlib modules") - - def build_extension(self, ext): - try: - build_ext.build_extension(self, ext) - except (CCompilerError, DistutilsError) as why: - self.announce('WARNING: building of extension "%s" failed: %s' % - (ext.name, why)) - self.failed.append(ext.name) - return - - def check_extension_import(self, ext): - # Don't try to import an extension that has failed to compile - if ext.name in self.failed: - self.announce( - 'WARNING: skipping import check for failed build "%s"' % - ext.name, level=1) - return - - # Workaround for Mac OS X: The Carbon-based modules cannot be - # reliably imported into a command-line Python - if 'Carbon' in ext.extra_link_args: - self.announce( - 'WARNING: skipping import check for Carbon-based "%s"' % - ext.name) - return - - if MACOS and ( - sys.maxsize > 2**32 and '-arch' in ext.extra_link_args): - # Don't bother doing an import check when an extension was - # build with an explicit '-arch' flag on OSX. That's currently - # only used to build 32-bit only extensions in a 4-way - # universal build and loading 32-bit code into a 64-bit - # process will fail. - self.announce( - 'WARNING: skipping import check for "%s"' % - ext.name) - return - - # Workaround for Cygwin: Cygwin currently has fork issues when many - # modules have been imported - if CYGWIN: - self.announce('WARNING: skipping import check for Cygwin-based "%s"' - % ext.name) - return - ext_filename = os.path.join( - self.build_lib, - self.get_ext_filename(self.get_ext_fullname(ext.name))) - - # If the build directory didn't exist when setup.py was - # started, sys.path_importer_cache has a negative result - # cached. Clear that cache before trying to import. - sys.path_importer_cache.clear() - - # Don't try to load extensions for cross builds - if CROSS_COMPILING: - return - - loader = importlib.machinery.ExtensionFileLoader(ext.name, ext_filename) - spec = importlib.util.spec_from_file_location(ext.name, ext_filename, - loader=loader) - try: - importlib._bootstrap._load(spec) - except ImportError as why: - self.failed_on_import.append(ext.name) - self.announce('*** WARNING: renaming "%s" since importing it' - ' failed: %s' % (ext.name, why), level=3) - assert not self.inplace - basename, tail = os.path.splitext(ext_filename) - newname = basename + "_failed" + tail - if os.path.exists(newname): - os.remove(newname) - os.rename(ext_filename, newname) - - except: - exc_type, why, tb = sys.exc_info() - self.announce('*** WARNING: importing extension "%s" ' - 'failed with %s: %s' % (ext.name, exc_type, why), - level=3) - self.failed.append(ext.name) - - def add_multiarch_paths(self): - # Debian/Ubuntu multiarch support. - # https://wiki.ubuntu.com/MultiarchSpec - tmpfile = os.path.join(self.build_temp, 'multiarch') - if not os.path.exists(self.build_temp): - os.makedirs(self.build_temp) - ret = run_command( - '%s -print-multiarch > %s 2> /dev/null' % (CC, tmpfile)) - multiarch_path_component = '' - try: - if ret == 0: - with open(tmpfile) as fp: - multiarch_path_component = fp.readline().strip() - finally: - os.unlink(tmpfile) - - if multiarch_path_component != '': - add_dir_to_list(self.compiler.library_dirs, - '/usr/lib/' + multiarch_path_component) - add_dir_to_list(self.compiler.include_dirs, - '/usr/include/' + multiarch_path_component) - return - - if not find_executable('dpkg-architecture'): - return - opt = '' - if CROSS_COMPILING: - opt = '-t' + sysconfig.get_config_var('HOST_GNU_TYPE') - tmpfile = os.path.join(self.build_temp, 'multiarch') - if not os.path.exists(self.build_temp): - os.makedirs(self.build_temp) - ret = run_command( - 'dpkg-architecture %s -qDEB_HOST_MULTIARCH > %s 2> /dev/null' % - (opt, tmpfile)) - try: - if ret == 0: - with open(tmpfile) as fp: - multiarch_path_component = fp.readline().strip() - add_dir_to_list(self.compiler.library_dirs, - '/usr/lib/' + multiarch_path_component) - add_dir_to_list(self.compiler.include_dirs, - '/usr/include/' + multiarch_path_component) - finally: - os.unlink(tmpfile) - - def add_wrcc_search_dirs(self): - # add library search path by wr-cc, the compiler wrapper - - def convert_mixed_path(path): - # convert path like C:\folder1\folder2/folder3/folder4 - # to msys style /c/folder1/folder2/folder3/folder4 - drive = path[0].lower() - left = path[2:].replace("\\", "/") - return "/" + drive + left - - def add_search_path(line): - # On Windows building machine, VxWorks does - # cross builds under msys2 environment. - pathsep = (";" if sys.platform == "msys" else ":") - for d in line.strip().split("=")[1].split(pathsep): - d = d.strip() - if sys.platform == "msys": - # On Windows building machine, compiler - # returns mixed style path like: - # C:\folder1\folder2/folder3/folder4 - d = convert_mixed_path(d) - d = os.path.normpath(d) - add_dir_to_list(self.compiler.library_dirs, d) - - tmpfile = os.path.join(self.build_temp, 'wrccpaths') - os.makedirs(self.build_temp, exist_ok=True) - try: - ret = run_command('%s --print-search-dirs >%s' % (CC, tmpfile)) - if ret: - return - with open(tmpfile) as fp: - # Parse paths in libraries line. The line is like: - # On Linux, "libraries: = path1:path2:path3" - # On Windows, "libraries: = path1;path2;path3" - for line in fp: - if not line.startswith("libraries"): - continue - add_search_path(line) - finally: - try: - os.unlink(tmpfile) - except OSError: - pass - - def add_cross_compiling_paths(self): - tmpfile = os.path.join(self.build_temp, 'ccpaths') - if not os.path.exists(self.build_temp): - os.makedirs(self.build_temp) - # bpo-38472: With a German locale, GCC returns "gcc-Version 9.1.0 - # (GCC)", whereas it returns "gcc version 9.1.0" with the C locale. - ret = run_command('LC_ALL=C %s -E -v - </dev/null 2>%s 1>/dev/null' % (CC, tmpfile)) - is_gcc = False - is_clang = False - in_incdirs = False - try: - if ret == 0: - with open(tmpfile) as fp: - for line in fp.readlines(): - if line.startswith("gcc version"): - is_gcc = True - elif line.startswith("clang version"): - is_clang = True - elif line.startswith("#include <...>"): - in_incdirs = True - elif line.startswith("End of search list"): - in_incdirs = False - elif (is_gcc or is_clang) and line.startswith("LIBRARY_PATH"): - for d in line.strip().split("=")[1].split(":"): - d = os.path.normpath(d) - if '/gcc/' not in d: - add_dir_to_list(self.compiler.library_dirs, - d) - elif (is_gcc or is_clang) and in_incdirs and '/gcc/' not in line and '/clang/' not in line: - add_dir_to_list(self.compiler.include_dirs, - line.strip()) - finally: - os.unlink(tmpfile) - - if VXWORKS: - self.add_wrcc_search_dirs() - - def add_ldflags_cppflags(self): - # Add paths specified in the environment variables LDFLAGS and - # CPPFLAGS for header and library files. - # We must get the values from the Makefile and not the environment - # directly since an inconsistently reproducible issue comes up where - # the environment variable is not set even though the value were passed - # into configure and stored in the Makefile (issue found on OS X 10.3). - for env_var, arg_name, dir_list in ( - ('LDFLAGS', '-R', self.compiler.runtime_library_dirs), - ('LDFLAGS', '-L', self.compiler.library_dirs), - ('CPPFLAGS', '-I', self.compiler.include_dirs)): - env_val = sysconfig.get_config_var(env_var) - if env_val: - parser = argparse.ArgumentParser() - parser.add_argument(arg_name, dest="dirs", action="append") - - # To prevent argparse from raising an exception about any - # options in env_val that it mistakes for known option, we - # strip out all double dashes and any dashes followed by a - # character that is not for the option we are dealing with. - # - # Please note that order of the regex is important! We must - # strip out double-dashes first so that we don't end up with - # substituting "--Long" to "-Long" and thus lead to "ong" being - # used for a library directory. - env_val = re.sub(r'(^|\s+)-(-|(?!%s))' % arg_name[1], - ' ', env_val) - options, _ = parser.parse_known_args(env_val.split()) - if options.dirs: - for directory in reversed(options.dirs): - add_dir_to_list(dir_list, directory) - - def configure_compiler(self): - # Ensure that /usr/local is always used, but the local build - # directories (i.e. '.' and 'Include') must be first. See issue - # 10520. - if not CROSS_COMPILING: - add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib') - add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') - # only change this for cross builds for 3.3, issues on Mageia - if CROSS_COMPILING: - self.add_cross_compiling_paths() - self.add_multiarch_paths() - self.add_ldflags_cppflags() - - def init_inc_lib_dirs(self): - if (not CROSS_COMPILING and - os.path.normpath(sys.base_prefix) != '/usr' and - not sysconfig.get_config_var('PYTHONFRAMEWORK')): - # OSX note: Don't add LIBDIR and INCLUDEDIR to building a framework - # (PYTHONFRAMEWORK is set) to avoid # linking problems when - # building a framework with different architectures than - # the one that is currently installed (issue #7473) - add_dir_to_list(self.compiler.library_dirs, - sysconfig.get_config_var("LIBDIR")) - add_dir_to_list(self.compiler.include_dirs, - sysconfig.get_config_var("INCLUDEDIR")) - - system_lib_dirs = ['/lib64', '/usr/lib64', '/lib', '/usr/lib'] - system_include_dirs = ['/usr/include'] - # lib_dirs and inc_dirs are used to search for files; - # if a file is found in one of those directories, it can - # be assumed that no additional -I,-L directives are needed. - if not CROSS_COMPILING: - self.lib_dirs = self.compiler.library_dirs + system_lib_dirs - self.inc_dirs = self.compiler.include_dirs + system_include_dirs - else: - # Add the sysroot paths. 'sysroot' is a compiler option used to - # set the logical path of the standard system headers and - # libraries. - self.lib_dirs = (self.compiler.library_dirs + - sysroot_paths(('LDFLAGS', 'CC'), system_lib_dirs)) - self.inc_dirs = (self.compiler.include_dirs + - sysroot_paths(('CPPFLAGS', 'CFLAGS', 'CC'), - system_include_dirs)) - - config_h = sysconfig.get_config_h_filename() - with open(config_h) as file: - self.config_h_vars = sysconfig.parse_config_h(file) - - # OSF/1 and Unixware have some stuff in /usr/ccs/lib (like -ldb) - if HOST_PLATFORM in ['osf1', 'unixware7', 'openunix8']: - self.lib_dirs += ['/usr/ccs/lib'] - - # HP-UX11iv3 keeps files in lib/hpux folders. - if HOST_PLATFORM == 'hp-ux11': - self.lib_dirs += ['/usr/lib/hpux64', '/usr/lib/hpux32'] - - if MACOS: - # This should work on any unixy platform ;-) - # If the user has bothered specifying additional -I and -L flags - # in OPT and LDFLAGS we might as well use them here. - # - # NOTE: using shlex.split would technically be more correct, but - # also gives a bootstrap problem. Let's hope nobody uses - # directories with whitespace in the name to store libraries. - cflags, ldflags = sysconfig.get_config_vars( - 'CFLAGS', 'LDFLAGS') - for item in cflags.split(): - if item.startswith('-I'): - self.inc_dirs.append(item[2:]) - - for item in ldflags.split(): - if item.startswith('-L'): - self.lib_dirs.append(item[2:]) - - def detect_simple_extensions(self): - # - # The following modules are all pretty straightforward, and compile - # on pretty much any POSIXish platform. - # - - # array objects - self.addext(Extension('array', ['arraymodule.c'])) - - # Context Variables - self.addext(Extension('_contextvars', ['_contextvarsmodule.c'])) - - # math library functions, e.g. sin() - self.addext(Extension('math', ['mathmodule.c'])) - - # complex math library functions - self.addext(Extension('cmath', ['cmathmodule.c'])) - - # libm is needed by delta_new() that uses round() and by accum() that - # uses modf(). - self.addext(Extension('_datetime', ['_datetimemodule.c'])) - self.addext(Extension('_zoneinfo', ['_zoneinfo.c'])) - # random number generator implemented in C - self.addext(Extension("_random", ["_randommodule.c"])) - self.addext(Extension("_bisect", ["_bisectmodule.c"])) - self.addext(Extension("_heapq", ["_heapqmodule.c"])) - # C-optimized pickle replacement - self.addext(Extension("_pickle", ["_pickle.c"])) - # _json speedups - self.addext(Extension("_json", ["_json.c"])) - - # profiler (_lsprof is for cProfile.py) - self.addext(Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c'])) - # static Unicode character database - self.addext(Extension('unicodedata', ['unicodedata.c'])) - self.addext(Extension('_opcode', ['_opcode.c'])) - - # asyncio speedups - self.addext(Extension("_asyncio", ["_asynciomodule.c"])) - - self.addext(Extension("_queue", ["_queuemodule.c"])) - self.addext(Extension("_statistics", ["_statisticsmodule.c"])) - self.addext(Extension("_struct", ["_struct.c"])) - self.addext(Extension("_typing", ["_typingmodule.c"])) - - # Modules with some UNIX dependencies -- on by default: - # (If you have a really backward UNIX, select and socket may not be - # supported...) - - # fcntl(2) and ioctl(2) - self.addext(Extension('fcntl', ['fcntlmodule.c'])) - # grp(3) - self.addext(Extension('grp', ['grpmodule.c'])) - - self.addext(Extension('_socket', ['socketmodule.c'])) - self.addext(Extension('spwd', ['spwdmodule.c'])) - - # select(2); not on ancient System V - self.addext(Extension('select', ['selectmodule.c'])) - - # Memory-mapped files (also works on Win32). - self.addext(Extension('mmap', ['mmapmodule.c'])) - - # Lance Ellinghaus's syslog module - # syslog daemon interface - self.addext(Extension('syslog', ['syslogmodule.c'])) - - # Python interface to subinterpreter C-API. - self.addext(Extension('_xxsubinterpreters', ['_xxsubinterpretersmodule.c'])) - - # - # Here ends the simple stuff. From here on, modules need certain - # libraries, are platform-specific, or present other surprises. - # - - # Multimedia modules - # These don't work for 64-bit platforms!!! - # These represent audio samples or images as strings: - # - # Operations on audio samples - # According to #993173, this one should actually work fine on - # 64-bit platforms. - # - # audioop needs libm for floor() in multiple functions. - self.addext(Extension('audioop', ['audioop.c'])) - - # CSV files - self.addext(Extension('_csv', ['_csv.c'])) - - # POSIX subprocess module helper. - self.addext(Extension('_posixsubprocess', ['_posixsubprocess.c'])) - - def detect_test_extensions(self): - # Python C API test module - self.addext(Extension('_testcapi', ['_testcapimodule.c', '_testcapi/vectorcall.c'])) - - # Python Internal C API test module - self.addext(Extension('_testinternalcapi', ['_testinternalcapi.c'])) - - # Python PEP-3118 (buffer protocol) test module - self.addext(Extension('_testbuffer', ['_testbuffer.c'])) - - # Test loading multiple modules from one compiled file (https://bugs.python.org/issue16421) - self.addext(Extension('_testimportmultiple', ['_testimportmultiple.c'])) - - # Test multi-phase extension module init (PEP 489) - self.addext(Extension('_testmultiphase', ['_testmultiphase.c'])) - - # Fuzz tests. - self.addext(Extension( - '_xxtestfuzz', - ['_xxtestfuzz/_xxtestfuzz.c', '_xxtestfuzz/fuzzer.c'] - )) - - def detect_readline_curses(self): - self.addext(Extension('readline', ['readline.c'])) - self.addext(Extension('_curses', ['_cursesmodule.c'])) - self.addext(Extension('_curses_panel', ['_curses_panel.c'])) - - def detect_crypt(self): - self.addext(Extension('_crypt', ['_cryptmodule.c'])) - - def detect_dbm_gdbm(self): - self.addext(Extension('_dbm', ['_dbmmodule.c'])) - # Anthony Baxter's gdbm module. GNU dbm(3) will require -lgdbm: - self.addext(Extension('_gdbm', ['_gdbmmodule.c'])) - - def detect_sqlite(self): - sources = [ - "_sqlite/blob.c", - "_sqlite/connection.c", - "_sqlite/cursor.c", - "_sqlite/microprotocols.c", - "_sqlite/module.c", - "_sqlite/prepare_protocol.c", - "_sqlite/row.c", - "_sqlite/statement.c", - "_sqlite/util.c", - ] - self.addext(Extension("_sqlite3", sources=sources)) - - def detect_platform_specific_exts(self): - # Unix-only modules - # Steen Lumholt's termios module - self.addext(Extension('termios', ['termios.c'])) - # Jeremy Hylton's rlimit interface - self.addext(Extension('resource', ['resource.c'])) - # linux/soundcard.h or sys/soundcard.h - self.addext(Extension('ossaudiodev', ['ossaudiodev.c'])) - - # macOS-only, needs SystemConfiguration and CoreFoundation framework - self.addext(Extension('_scproxy', ['_scproxy.c'])) - - def detect_compress_exts(self): - # Andrew Kuchling's zlib module. - self.addext(Extension('zlib', ['zlibmodule.c'])) - - # Helper module for various ascii-encoders. Uses zlib for an optimized - # crc32 if we have it. Otherwise binascii uses its own. - self.addext(Extension('binascii', ['binascii.c'])) - - # Gustavo Niemeyer's bz2 module. - self.addext(Extension('_bz2', ['_bz2module.c'])) - - # LZMA compression support. - self.addext(Extension('_lzma', ['_lzmamodule.c'])) - - def detect_expat_elementtree(self): - # Interface to the Expat XML parser - # - # Expat was written by James Clark and is now maintained by a group of - # developers on SourceForge; see www.libexpat.org for more information. - # The pyexpat module was written by Paul Prescod after a prototype by - # Jack Jansen. The Expat source is included in Modules/expat/. Usage - # of a system shared libexpat.so is possible with --with-system-expat - # configure option. - # - # More information on Expat can be found at www.libexpat.org. - # - self.addext(Extension('pyexpat', sources=['pyexpat.c'])) - - # Fredrik Lundh's cElementTree module. Note that this also - # uses expat (via the CAPI hook in pyexpat). - self.addext(Extension('_elementtree', sources=['_elementtree.c'])) - - def detect_multibytecodecs(self): - # Hye-Shik Chang's CJKCodecs modules. - self.addext(Extension('_multibytecodec', - ['cjkcodecs/multibytecodec.c'])) - for loc in ('kr', 'jp', 'cn', 'tw', 'hk', 'iso2022'): - self.addext(Extension( - f'_codecs_{loc}', [f'cjkcodecs/_codecs_{loc}.c'] - )) - - def detect_multiprocessing(self): - # Richard Oudkerk's multiprocessing module - multiprocessing_srcs = ['_multiprocessing/multiprocessing.c'] - if ( - sysconfig.get_config_var('HAVE_SEM_OPEN') and not - sysconfig.get_config_var('POSIX_SEMAPHORES_NOT_ENABLED') - ): - multiprocessing_srcs.append('_multiprocessing/semaphore.c') - self.addext(Extension('_multiprocessing', multiprocessing_srcs)) - self.addext(Extension('_posixshmem', ['_multiprocessing/posixshmem.c'])) - - def detect_uuid(self): - # Build the _uuid module if possible - self.addext(Extension('_uuid', ['_uuidmodule.c'])) - - def detect_modules(self): - # remove dummy extension - self.extensions = [] - - # Some C extensions are built by entries in Modules/Setup.bootstrap. - # These are extensions are required to bootstrap the interpreter or - # build process. - self.detect_simple_extensions() - self.detect_test_extensions() - self.detect_readline_curses() - self.detect_crypt() - self.detect_openssl_hashlib() - self.detect_hash_builtins() - self.detect_dbm_gdbm() - self.detect_sqlite() - self.detect_platform_specific_exts() - self.detect_nis() - self.detect_compress_exts() - self.detect_expat_elementtree() - self.detect_multibytecodecs() - self.detect_decimal() - self.detect_ctypes() - self.detect_multiprocessing() - self.detect_tkinter() - self.detect_uuid() - - # Uncomment the next line if you want to play with xxmodule.c -# self.add(Extension('xx', ['xxmodule.c'])) - - self.addext(Extension('xxlimited', ['xxlimited.c'])) - self.addext(Extension('xxlimited_35', ['xxlimited_35.c'])) - - def detect_tkinter(self): - self.addext(Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'])) - - def detect_ctypes(self): - # Thomas Heller's _ctypes module - src = [ - '_ctypes/_ctypes.c', - '_ctypes/callbacks.c', - '_ctypes/callproc.c', - '_ctypes/stgdict.c', - '_ctypes/cfield.c', - ] - malloc_closure = sysconfig.get_config_var( - "MODULE__CTYPES_MALLOC_CLOSURE" - ) - if malloc_closure: - src.append(malloc_closure) - - self.addext(Extension('_ctypes', src)) - self.addext(Extension('_ctypes_test', ['_ctypes/_ctypes_test.c'])) - - def detect_decimal(self): - # Stefan Krah's _decimal module - self.addext( - Extension( - '_decimal', - ['_decimal/_decimal.c'], - # Uncomment for extra functionality: - # define_macros=[('EXTRA_FUNCTIONALITY', 1)] - ) - ) - - def detect_openssl_hashlib(self): - self.addext(Extension('_ssl', ['_ssl.c'])) - self.addext(Extension('_hashlib', ['_hashopenssl.c'])) - - def detect_hash_builtins(self): - # By default we always compile these even when OpenSSL is available - # (issue #14693). It's harmless and the object code is tiny - # (40-50 KiB per module, only loaded when actually used). Modules can - # be disabled via the --with-builtin-hashlib-hashes configure flag. - - self.addext(Extension('_md5', ['md5module.c'])) - self.addext(Extension('_sha1', ['sha1module.c'])) - self.addext(Extension('_sha256', ['sha256module.c'])) - self.addext(Extension('_sha512', ['sha512module.c'])) - self.addext(Extension('_sha3', ['_sha3/sha3module.c'])) - self.addext(Extension('_blake2', - [ - '_blake2/blake2module.c', - '_blake2/blake2b_impl.c', - '_blake2/blake2s_impl.c' - ] - )) - - def detect_nis(self): - self.addext(Extension('nis', ['nismodule.c'])) - - -class PyBuildInstall(install): - # Suppress the warning about installation into the lib_dynload - # directory, which is not in sys.path when running Python during - # installation: - def initialize_options (self): - install.initialize_options(self) - self.warn_dir=0 - - # Customize subcommands to not install an egg-info file for Python - sub_commands = [('install_lib', install.has_lib), - ('install_headers', install.has_headers), - ('install_scripts', install.has_scripts), - ('install_data', install.has_data)] - - -class PyBuildInstallLib(install_lib): - # Do exactly what install_lib does but make sure correct access modes get - # set on installed directories and files. All installed files with get - # mode 644 unless they are a shared library in which case they will get - # mode 755. All installed directories will get mode 755. - - # this is works for EXT_SUFFIX too, which ends with SHLIB_SUFFIX - shlib_suffix = sysconfig.get_config_var("SHLIB_SUFFIX") - - def install(self): - outfiles = install_lib.install(self) - self.set_file_modes(outfiles, 0o644, 0o755) - self.set_dir_modes(self.install_dir, 0o755) - return outfiles - - def set_file_modes(self, files, defaultMode, sharedLibMode): - if not files: return - - for filename in files: - if os.path.islink(filename): continue - mode = defaultMode - if filename.endswith(self.shlib_suffix): mode = sharedLibMode - log.info("changing mode of %s to %o", filename, mode) - if not self.dry_run: os.chmod(filename, mode) - - def set_dir_modes(self, dirname, mode): - for dirpath, dirnames, fnames in os.walk(dirname): - if os.path.islink(dirpath): - continue - log.info("changing mode of %s to %o", dirpath, mode) - if not self.dry_run: os.chmod(dirpath, mode) - - -def main(): - global LIST_MODULE_NAMES - - if "--list-module-names" in sys.argv: - LIST_MODULE_NAMES = True - sys.argv.remove("--list-module-names") - - set_compiler_flags('CFLAGS', 'PY_CFLAGS_NODIST') - set_compiler_flags('LDFLAGS', 'PY_LDFLAGS_NODIST') - - class DummyProcess: - """Hack for parallel build""" - ProcessPoolExecutor = None - - sys.modules['concurrent.futures.process'] = DummyProcess - validate_tzpath() - - # turn off warnings when deprecated modules are imported - import warnings - warnings.filterwarnings("ignore",category=DeprecationWarning) - setup(# PyPI Metadata (PEP 301) - name = "Python", - version = sys.version.split()[0], - url = "https://www.python.org/%d.%d" % sys.version_info[:2], - maintainer = "Guido van Rossum and the Python community", - maintainer_email = "python-dev@python.org", - description = "A high-level object-oriented programming language", - long_description = SUMMARY.strip(), - license = "PSF license", - classifiers = [x for x in CLASSIFIERS.split("\n") if x], - platforms = ["Many"], - - # Build info - cmdclass = {'build_ext': PyBuildExt, - 'install': PyBuildInstall, - 'install_lib': PyBuildInstallLib}, - # A dummy module is defined here, because build_ext won't be - # called unless there's at least one extension module defined. - ext_modules=[Extension('_dummy', ['_dummy.c'])], - ) - -# --install-platlib -if __name__ == '__main__': - main()