File pythoncapi-compat-vendored.obscpio of Package python-gobject

07070100000000000041ED00000000000000000000000266CC467200000000000000000000000000000000000000000000002300000000pythoncapi-compat-vendored/.github07070100000001000041ED00000000000000000000000266CC467200000000000000000000000000000000000000000000002D00000000pythoncapi-compat-vendored/.github/workflows07070100000002000081A400000000000000000000000166CC467200000BBC000000000000000000000000000000000000003700000000pythoncapi-compat-vendored/.github/workflows/build.ymlname: Build

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        # Available OS Images:
        # https://github.com/actions/runner-images/#available-images
        #
        # Allow Python pre-releases:
        # https://github.com/actions/setup-python/blob/main/docs/advanced-usage.md#allow-pre-releases
        # See "allow-prereleases: true" below.
        os: [ubuntu-latest]
        python:
          # Python versions (CPython):
          # https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json
          - "3.7"
          - "3.8"
          - "3.9"
          - "3.10"
          - "3.11"
          - "3.12"
          # CPython 3.13 final is scheduled for October 2024:
          # https://peps.python.org/pep-0719/
          - "3.13"

          # PyPy versions:
          # - https://github.com/actions/setup-python/blob/main/docs/advanced-usage.md
          # - https://downloads.python.org/pypy/
          # - Only versions listed in this JSON are supported:
          #   https://downloads.python.org/pypy/versions.json
          - "pypy2.7"
          - "pypy3.6"
          - "pypy3.7"
          - "pypy3.8"
          - "pypy3.9"
          - "pypy3.10"

          # Old PyPy versions
          # See https://foss.heptapod.net/pypy/pypy/-/issues/3991
          - "pypy2.7-v7.3.2"
          - "pypy3.6-v7.3.2"
          - "pypy3.7-v7.3.2"

        include:
          # Windows: test old and new Python
          - os: windows-latest
            python: 3.6
          - os: windows-latest
            python: 3.12

          # macOS: test only new Python
          - os: macos-latest
            python: 3.12

          # Ubuntu: test deadsnakes Python versions which are not supported by
          # GHA python-versions.
          - os: ubuntu-20.04
            python: 3.6

    steps:
        # https://github.com/actions/checkout
      - uses: actions/checkout@v4
      - name: Setup Python
        # https://github.com/actions/setup-python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python }}
          allow-prereleases: true
      - name: Install setuptools
        run: python -m pip install setuptools
      - name: Display the Python version
        run: python -VV
      - name: Run tests
        run: python runtests.py --current --verbose

  test_python27:
    # Get Python 2.7 from Ubuntu 22.04.
    #
    # Python 2.7 was removed from GHA setup-python in June 2023:
    # https://github.com/actions/setup-python/issues/672
    name: 'Test Python 2.7'
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v4
      - name: Install Python 2.7
        run: |
          sudo apt-get update
          sudo apt-get -yq install python2.7 python2.7-dev
      - name: Display the Python version
        run: python2.7 -VV
      - name: Run tests
        run: python2.7 runtests.py --current --verbose
07070100000003000081A400000000000000000000000166CC46720000002F000000000000000000000000000000000000002600000000pythoncapi-compat-vendored/.gitignorebuild
*.swp
tests/build/
*.py[cod]
__pycache__
07070100000004000081A400000000000000000000000166CC4672000000DA000000000000000000000000000000000000002D00000000pythoncapi-compat-vendored/.readthedocs.yaml# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

version: 2

build:
  os: ubuntu-22.04
  tools:
    python: "3.12"

sphinx:
   configuration: docs/conf.py
07070100000005000081A400000000000000000000000166CC467200000275000000000000000000000000000000000000002E00000000pythoncapi-compat-vendored/CODE_OF_CONDUCT.md# Code of Conduct

Please note that all interactions on
[Python Software Foundation](https://www.python.org/psf-landing/)-supported
infrastructure is [covered](https://www.python.org/psf/records/board/minutes/2014-01-06/#management-of-the-psfs-web-properties)
by the [PSF Code of Conduct](https://www.python.org/psf/codeofconduct/),
which includes all the infrastructure used in the development of Python itself
(e.g. mailing lists, issue trackers, GitHub, etc.).

In general, this means that everyone is expected to be **open**, **considerate**, and
**respectful** of others no matter what their position is within the project.
07070100000006000081A400000000000000000000000166CC4672000002B2000000000000000000000000000000000000002300000000pythoncapi-compat-vendored/COPYINGBSD Zero Clause License

Copyright Contributors to the pythoncapi_compat project.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
07070100000007000081A400000000000000000000000166CC4672000006A1000000000000000000000000000000000000002600000000pythoncapi-compat-vendored/README.rst++++++++++++++++++++++++++
Python C API compatibility
++++++++++++++++++++++++++

.. image:: https://github.com/python/pythoncapi-compat/actions/workflows/build.yml/badge.svg
   :alt: Build status of pythoncapi-compat on GitHub Actions
   :target: https://github.com/python/pythoncapi-compat/actions

The ``pythoncapi-compat`` project can be used to write a C or C++ extension
supporting a wide range of Python versions with a single code base.  It is made
of the ``pythoncapi_compat.h`` header file and the ``upgrade_pythoncapi.py``
script.

``upgrade_pythoncapi.py`` requires Python 3.6 or newer.

See the `documentation at ReadTheDocs
<https://pythoncapi-compat.readthedocs.io/en/latest/>`_
for more details.

Getting started
===============

To upgrade a specific file::

    python3 upgrade_pythoncapi.py module.c

To upgrade all C/C++ files in a directory::

    python3 upgrade_pythoncapi.py src/

Select operations
-----------------

To only replace ``op->ob_type`` with ``Py_TYPE(op)``, select the ``Py_TYPE``
operation with::

    python3 upgrade_pythoncapi.py -o Py_TYPE module.c

Or the opposite, to apply all operations but leave ``op->ob_type`` unchanged,
deselect the ``Py_TYPE`` operation with::

    python3 upgrade_pythoncapi.py -o all,-Py_TYPE module.c

Download pythoncapi_compat.h
----------------------------

If you want to ``pythoncapi_compat.h`` to your code base, use the
``upgrade_pythoncapi.py`` tool to fetch it::

    python3 upgrade_pythoncapi.py --download PATH


This project is distributed under the `Zero Clause BSD (0BSD) license
<https://opensource.org/licenses/0BSD>`_ and is covered by the `PSF Code of
Conduct <https://www.python.org/psf/codeofconduct/>`_.
07070100000008000041ED00000000000000000000000266CC467200000000000000000000000000000000000000000000002000000000pythoncapi-compat-vendored/docs07070100000009000081A400000000000000000000000166CC467200000279000000000000000000000000000000000000002900000000pythoncapi-compat-vendored/docs/Makefile# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS    ?=
SPHINXBUILD   ?= sphinx-build
SOURCEDIR     = .
BUILDDIR      = build

# Put it first so that "make" without argument is like "make help".
help:
	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
0707010000000A000081A400000000000000000000000166CC467200005115000000000000000000000000000000000000002800000000pythoncapi-compat-vendored/docs/api.rst+++++++++++++++++++++++
pythoncapi_compat.h API
+++++++++++++++++++++++

The ``pythoncapi_compat.h`` header file provides implementations of recent
functions for old Python versions.

Supported Python versions:

* Python 3.6 - 3.14
* PyPy 2.7 and PyPy 3.6 - 3.10

Python 2.7 and Python 3.4 are no longer officially supported since GitHub
Actions doesn't support them anymore: only best effort support is provided.

C++03 and C++11 are supported on Python 3.6 and newer.

A C11 subset (without optional features) is required, like ``static inline``
functions: see `PEP 7 <https://www.python.org/dev/peps/pep-0007/>`_. ISO C90
is partially supported for Python 2.7.

Some functions related to frame objects and ``PyThreadState`` are not available
on PyPy.

Latest version of the header file:
`pythoncapi_compat.h <https://raw.githubusercontent.com/python/pythoncapi-compat/master/pythoncapi_compat.h>`_.


Python 3.14
-----------

.. c:function:: int PyLong_GetSign(PyObject *obj, int *sign)

   See `PyLong_GetSign() documentation <https://docs.python.org/dev/c-api/long.html#c.PyLong_GetSign>`__.

Python 3.13
-----------

.. c:function:: int PyDict_GetItemRef(PyObject *p, PyObject *key, PyObject **result)

   See `PyDict_GetItemRef() documentation <https://docs.python.org/dev/c-api/dict.html#c.PyDict_GetItemRef>`__.

.. c:function:: int PyDict_GetItemStringRef(PyObject *p, const char *key, PyObject **result)

   See `PyDict_GetItemStringRef() documentation <https://docs.python.org/dev/c-api/dict.html#c.PyDict_GetItemStringRef>`__.

.. c:function:: PyObject* PyImport_AddModuleRef(const char *name)

   See `PyImport_AddModuleRef() documentation <https://docs.python.org/dev/c-api/import.html#c.PyImport_AddModuleRef>`__.

.. c:function:: int PyObject_GetOptionalAttr(PyObject *obj, PyObject *attr_name, PyObject **result)

   See `PyObject_GetOptionalAttr() documentation <https://docs.python.org/dev/c-api/object.html#c.PyObject_GetOptionalAttr>`__.

.. c:function:: int PyObject_GetOptionalAttrString(PyObject *obj, const char *attr_name, PyObject **result)

   See `PyObject_GetOptionalAttrString() documentation <https://docs.python.org/dev/c-api/object.html#c.PyObject_GetOptionalAttrString>`__.

.. c:function:: int PyObject_HasAttrWithError(PyObject *obj, PyObject *attr_name)

   See `PyObject_HasAttrWithError() documentation <https://docs.python.org/dev/c-api/object.html#c.PyObject_HasAttrWithError>`__.

.. c:function:: int PyObject_HasAttrStringWithError(PyObject *obj, const char *attr_name)

   See `PyObject_HasAttrStringWithError() documentation <https://docs.python.org/dev/c-api/object.html#c.PyObject_HasAttrStringWithError>`__.

.. c:function:: int PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result)

   See `PyMapping_GetOptionalItem() documentation <https://docs.python.org/dev/c-api/mapping.html#c.PyMapping_GetOptionalItem>`__.

.. c:function:: int PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result)

   See `PyMapping_GetOptionalItemString() documentation <https://docs.python.org/dev/c-api/mapping.html#c.PyMapping_GetOptionalItemString>`__.

.. c:function:: int PyMapping_HasKeyWithError(PyObject *obj, PyObject *key)

   See `PyMapping_HasKeyWithError() documentation <https://docs.python.org/dev/c-api/mapping.html#c.PyMapping_HasKeyWithError>`__.

.. c:function:: int PyMapping_HasKeyStringWithError(PyObject *obj, const char *key)

   See `PyMapping_HasKeyStringWithError() documentation <https://docs.python.org/dev/c-api/mapping.html#c.PyMapping_HasKeyStringWithError>`__.

.. c:function:: int PyModule_Add(PyObject *module, const char *name, PyObject *value)

   See `PyModule_Add() documentation <https://docs.python.org/dev/c-api/module.html#c.PyModule_Add>`__.

.. c:function:: int PyWeakref_GetRef(PyObject *ref, PyObject **pobj)

   See `PyWeakref_GetRef() documentation <https://docs.python.org/dev/c-api/weakref.html#c.PyWeakref_GetRef>`__.

.. c:function:: int Py_IsFinalizing()

   Return non-zero if the Python interpreter is shutting down, return 0
   otherwise.

   Availability: Python 3.3 and newer, PyPy 7.3 and newer.

   See `Py_IsFinalizing() documentation <https://docs.python.org/dev/c-api/init.html#c.Py_IsFinalizing>`__.

.. c:function:: int PyDict_ContainsString(PyObject *p, const char *key)

   See `PyDict_ContainsString() documentation <https://docs.python.org/dev/c-api/dict.html#c.PyDict_ContainsString>`__.

.. c:function:: int PyLong_AsInt(PyObject *obj)

   See `PyLong_AsInt() documentation <https://docs.python.org/dev/c-api/long.html#c.PyLong_AsInt>`__.

.. c:function:: int PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg)

   See `PyObject_VisitManagedDict() documentation <https://docs.python.org/dev/c-api/object.html#c.PyObject_VisitManagedDict>`__.

.. c:function:: void PyObject_ClearManagedDict(PyObject *obj)

   See `PyObject_ClearManagedDict() documentation <https://docs.python.org/dev/c-api/object.html#c.PyObject_ClearManagedDict>`__.

.. c:function:: PyThreadState* PyThreadState_GetUnchecked(void)

   See `PyThreadState_GetUnchecked() documentation <https://docs.python.org/dev/c-api/init.html#c.PyThreadState_GetUnchecked>`__.

   Available on Python 3.5.2 and newer.

.. c:function:: int PyUnicode_EqualToUTF8(PyObject *unicode, const char *str)

   See `PyUnicode_EqualToUTF8() documentation <https://docs.python.org/dev/c-api/unicode.html#c.PyUnicode_EqualToUTF8>`__.

.. c:function:: int PyUnicode_EqualToUTF8AndSize(PyObject *unicode, const char *str, Py_ssize_t size)

   See `PyUnicode_EqualToUTF8AndSize() documentation <https://docs.python.org/dev/c-api/unicode.html#c.PyUnicode_EqualToUTF8AndSize>`__.

.. c:function:: int PyList_Extend(PyObject *list, PyObject *iterable)

   See `PyList_Extend() documentation <https://docs.python.org/dev/c-api/list.html#c.PyList_Extend>`__.

.. c:function:: int PyList_Clear(PyObject *list)

   See `PyList_Clear() documentation <https://docs.python.org/dev/c-api/list.html#c.PyList_Clear>`__.

.. c:function:: int PyDict_Pop(PyObject *dict, PyObject *key, PyObject **result)

   See `PyDict_Pop() documentation <https://docs.python.org/dev/c-api/dict.html#c.PyDict_Pop>`__.

.. c:function:: int PyDict_PopString(PyObject *dict, const char *key, PyObject **result)

   See `PyDict_PopString() documentation <https://docs.python.org/dev/c-api/dict.html#c.PyDict_PopString>`__.

.. c:function:: Py_hash_t Py_HashPointer(const void *ptr)

   See `Py_HashPointer() documentation <https://docs.python.org/dev/c-api/hash.html#c.Py_HashPointer>`__.

.. c:type:: PyTime_t

   A timestamp or duration in nanoseconds, represented as a signed 64-bit
   integer.

.. c:var:: PyTime_t PyTime_MIN

   Minimum value of :c:type:`PyTime_t`.

.. c:var:: PyTime_t PyTime_MAX

   Maximum value of :c:type:`PyTime_t`.

.. c:function:: double PyTime_AsSecondsDouble(PyTime_t t)

   See `PyTime_AsSecondsDouble() documentation <https://docs.python.org/dev/c-api/time.html#c.PyTime_AsSecondsDouble>`__.

.. c:function:: int PyTime_Monotonic(PyTime_t *result)

   See `PyTime_Monotonic() documentation <https://docs.python.org/dev/c-api/time.html#c.PyTime_Monotonic>`__.

.. c:function:: int PyTime_Time(PyTime_t *result)

   See `PyTime_Time() documentation <https://docs.python.org/dev/c-api/time.html#c.PyTime_Time>`__.

.. c:function:: int PyTime_PerfCounter(PyTime_t *result)

   See `PyTime_PerfCounter() documentation <https://docs.python.org/dev/c-api/time.html#c.PyTime_PerfCounter>`__.

.. c:function:: PyObject* PyList_GetItemRef(PyObject *op, Py_ssize_t index)

   See `PyList_GetItemRef() documentation <https://docs.python.org/dev/c-api/list.html#c.PyList_GetItemRef>`__.

.. c:function:: int PyDict_SetDefaultRef(PyObject *d, PyObject *key, PyObject *default_value, PyObject **result)

   See `PyDict_SetDefaultRef() documentation <https://docs.python.org/dev/c-api/dict.html#c.PyDict_SetDefaultRef>`__.


Not supported:

* ``PyErr_FormatUnraisable()``.
* ``PyLong_AsNativeBytes()``
* ``PyLong_FromNativeBytes()``
* ``PyLong_FromUnsignedNativeBytes()``
* ``PyObject_GenericHash()``.
* ``PySys_Audit()``.
* ``PySys_AuditTuple()``.
* ``PyType_GetFullyQualifiedName()``
* ``PyType_GetModuleName()``

Python 3.12
-----------

.. c:function:: PyObject* PyFrame_GetVar(PyFrameObject *frame, PyObject *name)

   See `PyFrame_GetVar() documentation <https://docs.python.org/dev/c-api/frame.html#c.PyFrame_GetVar>`__.

   Not available on PyPy.

.. c:function:: PyObject* PyFrame_GetVarString(PyFrameObject *frame, const char *name)

   See `PyFrame_GetVarString() documentation <https://docs.python.org/dev/c-api/frame.html#c.PyFrame_GetVarString>`__.

   Not available on PyPy.

.. c:function:: PyObject* Py_GetConstant(unsigned int constant_id)

   See `Py_GetConstant() documentation <https://docs.python.org/dev/c-api/object.html#c.Py_GetConstant>`__.

.. c:function:: PyObject* Py_GetConstantBorrowed(unsigned int constant_id)

   See `Py_GetConstantBorrowed() documentation <https://docs.python.org/dev/c-api/object.html#c.Py_GetConstantBorrowed>`__.


Not supported:

* ``PyDict_AddWatcher()``, ``PyDict_Watch()``.
* ``PyCode_AddWatcher()``, ``PyCode_ClearWatcher()``.
* ``PyErr_GetRaisedException()``, ``PyErr_SetRaisedException()``.
* ``_PyErr_ChainExceptions1()``.
* ``PyErr_DisplayException()``.
* ``_Py_IsImmortal()``.
* ``Py_NewInterpreterFromConfig()``.
* ``PyException_GetArgs()``, ``PyException_SetArgs()``.
* ``PyEval_SetProfileAllThreads()``, ``PyEval_SetTraceAllThreads()``.
* ``PyFunction_SetVectorcall()``.
* ``PyType_FromMetaclass()``: implementation too big to be backported.
* ``PyVectorcall_Call()``.

Python 3.11
-----------

.. c:function:: PyObject* PyCode_GetCellvars(PyCodeObject *code)

   See `PyCode_GetCellvars() documentation <https://docs.python.org/dev/c-api/code.html#c.PyCode_GetCellvars>`__.

   Not available on PyPy.

.. c:function:: PyObject* PyCode_GetCode(PyCodeObject *code)

   See `PyCode_GetCode() documentation <https://docs.python.org/dev/c-api/code.html#c.PyCode_GetCode>`__.

   Not available on PyPy.

.. c:function:: PyObject* PyCode_GetFreevars(PyCodeObject *code)

   See `PyCode_GetFreevars() documentation <https://docs.python.org/dev/c-api/code.html#c.PyCode_GetFreevars>`__.

   Not available on PyPy.

.. c:function:: PyObject* PyCode_GetVarnames(PyCodeObject *code)

   See `PyCode_GetVarnames() documentation <https://docs.python.org/dev/c-api/code.html#c.PyCode_GetVarnames>`__.

   Not available on PyPy.

.. c:function:: PyObject* PyFrame_GetBuiltins(PyFrameObject *frame)

   See `PyFrame_GetBuiltins() documentation <https://docs.python.org/dev/c-api/frame.html#c.PyFrame_GetBuiltins>`__.

   Not available on PyPy.

.. c:function:: PyObject* PyFrame_GetGlobals(PyFrameObject *frame)

   See `PyFrame_GetGlobals() documentation <https://docs.python.org/dev/c-api/frame.html#c.PyFrame_GetGlobals>`__.

   Not available on PyPy.

.. c:function:: int PyFrame_GetLasti(PyFrameObject *frame)

   See `PyFrame_GetLasti() documentation <https://docs.python.org/dev/c-api/frame.html#c.PyFrame_GetLasti>`__.

   Not available on PyPy.

.. c:function:: PyObject* PyFrame_GetLocals(PyFrameObject *frame)

   See `PyFrame_GetLocals() documentation <https://docs.python.org/dev/c-api/frame.html#c.PyFrame_GetLocals>`__.

   Not available on PyPy.

.. c:function:: void PyThreadState_EnterTracing(PyThreadState *tstate)

   See `PyThreadState_EnterTracing() documentation <https://docs.python.org/dev/c-api/init.html#c.PyThreadState_EnterTracing>`__.

   Not available on PyPy.

.. c:function:: void PyThreadState_LeaveTracing(PyThreadState *tstate)

   See `PyThreadState_LeaveTracing() documentation <https://docs.python.org/dev/c-api/init.html#c.PyThreadState_LeaveTracing>`__.

   Not available on PyPy

.. c:function:: int PyFloat_Pack2(double x, unsigned char *p, int le)

   Pack a C double as the IEEE 754 binary16 half-precision format.

   Availability: Python 3.6 and newer. Not available on PyPy

.. c:function:: int PyFloat_Pack4(double x, unsigned char *p, int le)

   Pack a C double as the IEEE 754 binary32 single precision format.

   Not available on PyPy

.. c:function:: int PyFloat_Pack8(double x, unsigned char *p, int le)

   Pack a C double as the IEEE 754 binary64 double precision format.

   Not available on PyPy

.. c:function:: double PyFloat_Unpack2(const unsigned char *p, int le)

   Unpack the IEEE 754 binary16 half-precision format as a C double.

   Availability: Python 3.6 and newer. Not available on PyPy

.. c:function:: double PyFloat_Unpack4(const unsigned char *p, int le)

   Unpack the IEEE 754 binary32 single precision format as a C double.

   Not available on PyPy

.. c:function:: double PyFloat_Unpack8(const unsigned char *p, int le)

   Unpack the IEEE 754 binary64 double precision format as a C double.

   Not available on PyPy

Not supported:

* ``PyType_GetModuleByDef()``.
* ``PyType_GetName()``.
* ``PyType_GetQualName()``.
* ``Py_Version`` constant.
* ``PyErr_GetHandledException()``, ``PyErr_SetHandledException()``.
* ``PyFrame_GetGenerator()``.

Python 3.10
-----------

.. c:function:: PyObject* Py_NewRef(PyObject *obj)

   See `Py_NewRef() documentation <https://docs.python.org/dev/c-api/refcounting.html#c.Py_NewRef>`__.

.. c:function:: PyObject* Py_XNewRef(PyObject *obj)

   See `Py_XNewRef() documentation <https://docs.python.org/dev/c-api/refcounting.html#c.Py_XNewRef>`__.

.. c:function:: int Py_Is(PyObject *x, PyObject *y)

   See `Py_Is() documentation <https://docs.python.org/dev/c-api/structures.html#c.Py_Is>`__.

.. c:function:: int Py_IsNone(PyObject *x)

   See `Py_IsNone() documentation <https://docs.python.org/dev/c-api/structures.html#c.Py_IsNone>`__.

.. c:function:: int Py_IsTrue(PyObject *x)

   See `Py_IsTrue() documentation <https://docs.python.org/dev/c-api/structures.html#c.Py_IsTrue>`__.

.. c:function:: int Py_IsFalse(PyObject *x)

   See `Py_IsFalse() documentation <https://docs.python.org/dev/c-api/structures.html#c.Py_IsFalse>`__.

.. c:function:: int PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value)

   See `PyModule_AddObjectRef() documentation <https://docs.python.org/dev/c-api/module.html#c.PyModule_AddObjectRef>`__.

Not supported:

* ``PyCodec_Unregister()``.
* ``PyDateTime_DATE_GET_TZINFO()``, ``PyDateTime_TIME_GET_TZINFO()``.
* ``PyErr_SetInterruptEx()``.
* ``PyGC_Enable()``, ``PyGC_Disable()`` and ``PyGC_IsEnabled()``.
* ``PyIter_Send()``.
* ``PySet_CheckExact()``.
* ``Py_TPFLAGS_DISALLOW_INSTANTIATION`` constant.
* ``Py_TPFLAGS_IMMUTABLETYPE`` constant.

Python 3.9
----------

PyObject
^^^^^^^^

.. c:function:: void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt)

   See `Py_SET_REFCNT() documentation <https://docs.python.org/dev/c-api/structures.html#c.Py_SET_REFCNT>`__.

.. c:function:: void Py_SET_TYPE(PyObject *ob, PyTypeObject *type)

   See `Py_SET_TYPE() documentation <https://docs.python.org/dev/c-api/structures.html#c.Py_SET_TYPE>`__.

.. c:function:: void Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size)

   See `Py_SET_SIZE() documentation <https://docs.python.org/dev/c-api/structures.html#c.Py_SET_SIZE>`__.

.. c:function:: int Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type)

   See `Py_IS_TYPE() documentation <https://docs.python.org/dev/c-api/structures.html#c.Py_IS_TYPE>`__.

.. c:function:: PyObject* PyObject_CallNoArgs(PyObject *func)

   See `PyObject_CallNoArgs() documentation <https://docs.python.org/dev/c-api/call.html#c.PyObject_CallNoArgs>`__.

.. c:function:: PyObject* PyObject_CallOneArg(PyObject *func, PyObject *arg)

   See `PyObject_CallOneArg() documentation <https://docs.python.org/dev/c-api/call.html#c.PyObject_CallOneArg>`__.

.. c:function:: PyObject* PyObject_Vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)

   See `PyObject_Vectorcall() documentation <https://docs.python.org/dev/c-api/call.html#c.PyObject_Vectorcall>`__.

.. c:function:: Py_ssize_t PyVectorcall_NARGS(size_t nargsf)

   See `PyVectorcall_NARGS() documentation <https://docs.python.org/dev/c-api/call.html#c.PyVectorcall_NARGS>`__.

.. c:macro:: PY_VECTORCALL_ARGUMENTS_OFFSET

   See `PY_VECTORCALL_ARGUMENTS_OFFSET documentation <https://docs.python.org/dev/c-api/call.html#PY_VECTORCALL_ARGUMENTS_OFFSET>`__.

Not supported:

* ``PyVectorcall_CallMethod()``.
* ``PyType_FromModuleAndSpec()``



PyFrameObject
^^^^^^^^^^^^^

.. c:function:: PyCodeObject* PyFrame_GetCode(PyFrameObject *frame)

   See `PyFrame_GetCode() documentation <https://docs.python.org/dev/c-api/reflection.html#c.PyFrame_GetCode>`__.

.. c:function:: PyFrameObject* PyFrame_GetBack(PyFrameObject *frame)

   See `PyFrame_GetBack() documentation <https://docs.python.org/dev/c-api/reflection.html#c.PyFrame_GetBack>`__.

   Not available on PyPy


PyThreadState
^^^^^^^^^^^^^

.. c:function:: PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate)

   See `PyThreadState_GetFrame() documentation <https://docs.python.org/dev/c-api/init.html#c.PyThreadState_GetFrame>`__.

   Not available on PyPy

.. c:function:: PyInterpreterState* PyThreadState_GetInterpreter(PyThreadState *tstate)

   See `PyThreadState_GetInterpreter() documentation <https://docs.python.org/dev/c-api/init.html#c.PyThreadState_GetInterpreter>`__.

.. c:function:: uint64_t PyThreadState_GetID(PyThreadState *tstate)

   See `PyThreadState_GetID() documentation <https://docs.python.org/dev/c-api/init.html#c.PyThreadState_GetID>`__.

   Availability: Python 3.7. Not available on PyPy.

PyInterpreterState
^^^^^^^^^^^^^^^^^^

.. c:function:: PyInterpreterState* PyInterpreterState_Get(void)

   See `PyInterpreterState_Get() documentation <https://docs.python.org/dev/c-api/init.html#c.PyInterpreterState_Get>`__.


GC protocol
^^^^^^^^^^^

.. c:function:: int PyObject_GC_IsTracked(PyObject* obj)

   See `PyObject_GC_IsTracked() documentation <https://docs.python.org/dev/c-api/gcsupport.html#c.PyObject_GC_IsTracked>`__.

   Not available on PyPy.

.. c:function:: int PyObject_GC_IsFinalized(PyObject *obj)

   See `PyObject_GC_IsFinalized() documentation <https://docs.python.org/dev/c-api/gcsupport.html#c.PyObject_GC_IsFinalized>`__.

   Availability: Python 3.4. Not available on PyPy.

Module helper
^^^^^^^^^^^^^

.. c:function:: int PyModule_AddType(PyObject *module, PyTypeObject *type)

   See `PyModule_AddType() documentation <https://docs.python.org/dev/c-api/module.html#c.PyModule_AddType>`__.

Python 3.8
----------

Not supported:

* ``PyCode_NewWithPosOnlyArgs()``.

Python 3.7
----------

Not supported:

* ``PyImport_GetModule()``.
* ``PyInterpreterState_GetID()``.
* ``PySlice_Unpack()``, ``PySlice_AdjustIndices()``.
* ``PyTimeZone_FromOffset()``, ``PyTimeZone_FromOffsetAndName()``.
* ``Py_RETURN_RICHCOMPARE()``.
* ``Py_UNREACHABLE`` macro.

Python 3.6
----------

Not supported:

* ``PyErr_ResourceWarning()``.
* ``PyErr_SetImportErrorSubclass()``.
* ``PyOS_FSPath()``.
* ``Py_FinalizeEx()``.

Python 3.5.2
------------

.. c:macro:: Py_SETREF(op, op2)

.. c:macro:: Py_XSETREF(op, op2)

Not supported:

* ``PyCodec_NameReplaceErrors()``.
* ``PyErr_FormatV()``.
* ``PyExc_RecursionError``.
* ``PyModule_FromDefAndSpec()``, ``PyModule_FromDefAndSpec2()``,
  and ``PyModule_ExecDef()``.
* ``PyNumber_MatrixMultiply()`` and ``PyNumber_InPlaceMatrixMultiply()``.

Python 3.4
----------

.. c:macro:: Py_UNUSED(name)

   See `Py_UNUSED() documentation <https://docs.python.org/dev/c-api/intro.html#c.Py_UNUSED>`__.

Python 3.2
----------

Not supported:

* ``Py_VA_COPY``.
* ``PySys_SetArgvEx()``.
* ``PyLong_AsLongLongAndOverflow()``.
* ``PyErr_NewExceptionWithDoc()``.

Python 3.1
----------

Not supported:

* ``PyOS_string_to_double()``.
* ``PyCapsule`` API.

Borrow variant
--------------

To ease migration of C extensions to the new C API, a variant is provided
to return borrowed references rather than strong references.

These functions are only available in ``pythoncapi_compat.h`` and are not
part of the Python C API.

.. c:function:: PyObject* _Py_StealRef(PyObject *ob)

   Similar to ``Py_DECREF(ob); return ob;``.

.. c:function:: PyObject* _Py_XStealRef(PyObject *ob)

   Similar to ``Py_XDECREF(ob); return ob;``.

.. c:function:: PyFrameObject* _PyThreadState_GetFrameBorrow(PyThreadState *tstate)

   :c:func:`PyThreadState_GetFrame` variant. Not available on PyPy.

.. c:function:: PyCodeObject* _PyFrame_GetCodeBorrow(PyFrameObject *frame)

   :c:func:`PyFrame_GetCode` variant.

.. c:function:: PyFrameObject* _PyFrame_GetBackBorrow(PyFrameObject *frame)

   :c:func:`PyFrame_GetBack` variant Not available on PyPy.

For example, ``tstate->frame`` can be replaced with
``_PyThreadState_GetFrameBorrow(tstate)`` to avoid accessing directly
``PyThreadState.frame`` member.
0707010000000B000081A400000000000000000000000166CC4672000010F2000000000000000000000000000000000000002E00000000pythoncapi-compat-vendored/docs/changelog.rstChangelog
=========

* 2024-07-18: Add functions:

  * ``PyUnicodeWriter_Create()``
  * ``PyUnicodeWriter_Discard()``
  * ``PyUnicodeWriter_Finish()``
  * ``PyUnicodeWriter_WriteChar()``
  * ``PyUnicodeWriter_WriteUTF8()``
  * ``PyUnicodeWriter_WriteStr()``
  * ``PyUnicodeWriter_WriteRepr()``
  * ``PyUnicodeWriter_WriteSubstring()``
  * ``PyUnicodeWriter_WriteWideChar()``
  * ``PyUnicodeWriter_Format()``

* 2024-06-03: Add ``PyLong_GetSign()``.
* 2024-04-23: Drop Python 3.5 support. It cannot be tested anymore (pip fails).
* 2024-04-02: Add ``PyDict_SetDefaultRef()`` function.
* 2024-03-29: Add ``PyList_GetItemRef()`` function.
* 2024-03-21: Add functions:

  * ``Py_GetConstant()``
  * ``Py_GetConstantBorrowed()``

* 2024-03-09: Add hash constants:

  * ``PyHASH_BITS``
  * ``PyHASH_IMAG``
  * ``PyHASH_INF``
  * ``PyHASH_MODULUS``

* 2024-02-20: Add PyTime API:

  * ``PyTime_t`` type
  * ``PyTime_MIN`` and ``PyTime_MAX`` constants
  * ``PyTime_AsSecondsDouble()``
  * ``PyTime_Monotonic()``
  * ``PyTime_PerfCounter()``
  * ``PyTime_Time()``

* 2023-12-15: Add function ``Py_HashPointer()``.
* 2023-11-14: Add functions:

  * ``PyDict_Pop()``
  * ``PyDict_PopString()``

* 2023-11-13: Add functions:

  * ``PyList_Extend()``
  * ``PyList_Clear()``

* 2023-10-04: Add functions:

  * ``PyUnicode_EqualToUTF8()``
  * ``PyUnicode_EqualToUTF8AndSize()``

* 2023-10-03: Add functions:

  * ``PyObject_VisitManagedDict()``
  * ``PyObject_ClearManagedDict()``
  * ``PyThreadState_GetUnchecked()``

* 2023-09-29: Add functions:

  * ``PyMapping_HasKeyWithError()``
  * ``PyMapping_HasKeyStringWithError()``
  * ``PyObject_HasAttrWithError()``
  * ``PyObject_HasAttrStringWithError()``

* 2023-08-25: Add ``PyDict_ContainsString()`` and ``PyLong_AsInt()`` functions.
* 2023-08-21: Remove support for Python 2.7, Python 3.4 and older.
* 2023-08-16: Add ``Py_IsFinalizing()`` function.
* 2023-07-21: Add ``PyDict_GetItemRef()`` function.
* 2023-07-18: Add ``PyModule_Add()`` function.
* 2023-07-12: Add functions:

  * ``PyObject_GetOptionalAttr()``
  * ``PyObject_GetOptionalAttrString()``
  * ``PyMapping_GetOptionalItem()``
  * ``PyMapping_GetOptionalItemString()``

* 2023-07-05: Add ``PyObject_Vectorcall()`` function.
* 2023-06-21: Add ``PyWeakref_GetRef()`` function.
* 2023-06-20: Add ``PyImport_AddModuleRef()`` function.
* 2022-11-15: Add experimental operations to the ``upgrade_pythoncapi.py``
  script: ``Py_NewRef``, ``Py_CLEAR`` and ``Py_SETREF``.
* 2022-11-09: Fix ``Py_SETREF()`` and ``Py_XSETREF()`` macros
  for `gh-98724 <https://github.com/python/cpython/issues/98724>`_.
* 2022-11-04: Add ``PyFrame_GetVar()`` and ``PyFrame_GetVarString()``
  functions.
* 2022-08-04: Add ``PyCode_GetVarnames()``, ``PyCode_GetFreevars()``
  and ``PyCode_GetCellvars()`` functions.
* 2022-06-14: Fix compatibility with C++ older than C++11.
* 2022-05-03: Add ``PyCode_GetCode()`` function.
* 2022-04-26: Rename the project from ``pythoncapi_compat`` to
  ``pythoncapi-compat``: replace the underscore separator with a dash.
* 2022-04-08: Add functions ``PyFrame_GetLocals()``, ``PyFrame_GetGlobals()``
  ``PyFrame_GetBuiltins()``, and ``PyFrame_GetLasti()``.
* 2022-03-12: Add functions ``PyFloat_Pack2()``, ``PyFloat_Pack4()``,
  ``PyFloat_Pack8()``, ``PyFloat_Unpack2()``, ``PyFloat_Unpack4()`` and
  ``PyFloat_Unpack8()``.
* 2022-03-03: The project moved to https://github.com/python/pythoncapi-compat
* 2022-02-11: The project license changes from the MIT license to the Zero
  Clause BSD (0BSD) license. Projects copying ``pythoncapi_compat.h`` no longer
  have to include the MIT license and the copyright notice.
* 2022-02-08: Add documentation.
* 2022-02-09: ``pythoncapi_compat.h`` now supports C++ on Python 3.6 and newer:
  use ``nullptr`` and ``reinterpret_cast<type>`` cast on C++, and use ``NULL``
  and ``(type)`` cast on C.
* 2021-10-15: Add ``PyThreadState_EnterTracing()`` and
  ``PyThreadState_LeaveTracing()``.
* 2021-04-09: Add ``Py_Is()``, ``Py_IsNone()``, ``Py_IsTrue()``,
  ``Py_IsFalse()`` functions.
* 2021-04-01:

  * Add ``Py_SETREF()``, ``Py_XSETREF()`` and ``Py_UNUSED()``.
  * Add PyPy support.

* 2021-01-27: Fix compatibility with Visual Studio 2008 for Python 2.7.
* 2020-11-30: Creation of the ``upgrade_pythoncapi.py`` script.
* 2020-06-04: Creation of the ``pythoncapi_compat.h`` header file.

0707010000000C000081A400000000000000000000000166CC46720000075B000000000000000000000000000000000000002800000000pythoncapi-compat-vendored/docs/conf.py# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))


# -- Project information -----------------------------------------------------

project = 'pythoncapi_compat'
copyright = '2022, Victor Stinner'
author = 'Victor Stinner'
language = "en"


# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['templates']

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']


# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
#
html_theme = 'default'

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['static']
0707010000000D000081A400000000000000000000000166CC467200000323000000000000000000000000000000000000002A00000000pythoncapi-compat-vendored/docs/index.rst++++++++++++++++++++++++++
Python C API compatibility
++++++++++++++++++++++++++

The ``pythoncapi-compat`` project can be used to write a C or C++ extension
supporting a wide range of Python versions with a single code base.  It is made
of the ``pythoncapi_compat.h`` header file and the ``upgrade_pythoncapi.py``
script.

* Homepage: `GitHub pythoncapi-compat project
  <https://github.com/python/pythoncapi-compat>`_.
* `Documentation
  <https://pythoncapi-compat.readthedocs.io/en/latest/>`_

Documentation:

.. toctree::
   :maxdepth: 2

   upgrade
   api
   users
   tests
   changelog
   links

This project is distributed under the `Zero Clause BSD (0BSD) license
<https://opensource.org/licenses/0BSD>`_ and is covered by the `PSF Code of
Conduct <https://www.python.org/psf/codeofconduct/>`_.
0707010000000E000081A400000000000000000000000166CC467200000501000000000000000000000000000000000000002A00000000pythoncapi-compat-vendored/docs/links.rstLinks
=====

* `Python/C API Reference Manual <https://docs.python.org/dev/c-api/>`_
* `HPy: a better API for Python
  <https://hpy.readthedocs.io/>`_
* `Cython: C-extensions for Python
  <https://cython.org/>`_
* `Old 2to3c project <https://github.com/davidmalcolm/2to3c>`_ by David Malcolm
  which uses `Coccinelle <https://coccinelle.gitlabpages.inria.fr/website/>`_
  to ease migration of C extensions from Python 2 to Python 3. See
  also `2to3c: an implementation of Python's 2to3 for C code
  <https://dmalcolm.livejournal.com/3935.html>`_ article (2009).
* PEPs related to the C API:

  * `PEP 620 -- Hide implementation details from the C API
    <https://www.python.org/dev/peps/pep-0620/>`_
  * `PEP 670 -- Convert macros to functions in the Python C API
    <https://www.python.org/dev/peps/pep-0670/>`_
  * `PEP 674 -- Disallow using macros as l-values
    <https://www.python.org/dev/peps/pep-0674/>`_

* Make structures opaque

  * `bpo-39573: PyObject <https://bugs.python.org/issue39573>`_
  * `bpo-40170: PyTypeObject <https://bugs.python.org/issue40170>`_
  * `bpo-39947: PyThreadState <https://bugs.python.org/issue39947>`_
  * `bpo-40421: PyFrameObject <https://bugs.python.org/issue40421>`_
  * `bpo-47241: PyCodeObject <https://bugs.python.org/issue47241>`_
0707010000000F000081A400000000000000000000000166CC46720000031F000000000000000000000000000000000000002900000000pythoncapi-compat-vendored/docs/make.bat@ECHO OFF

pushd %~dp0

REM Command file for Sphinx documentation

if "%SPHINXBUILD%" == "" (
	set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=build

if "%1" == "" goto help

%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
	echo.
	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
	echo.installed, then set the SPHINXBUILD environment variable to point
	echo.to the full path of the 'sphinx-build' executable. Alternatively you
	echo.may add the Sphinx directory to PATH.
	echo.
	echo.If you don't have Sphinx installed, grab it from
	echo.https://www.sphinx-doc.org/
	exit /b 1
)

%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end

:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%

:end
popd
07070100000010000081A400000000000000000000000166CC467200000145000000000000000000000000000000000000002A00000000pythoncapi-compat-vendored/docs/tests.rstRun tests
=========

To run pythoncapi-compat tests, type::

    python3 runtests.py

To only test the current Python version, use the ``-c`` or the ``--current``
option::

    python3 runtests.py --current

Verbose mode (``-v``, ``--verbose``)::

    python3 runtests.py --verbose

See tests in the ``tests/`` subdirectory.
07070100000011000081A400000000000000000000000166CC4672000011CB000000000000000000000000000000000000002C00000000pythoncapi-compat-vendored/docs/upgrade.rst++++++++++++++++++++++++++++
upgrade_pythoncapi.py script
++++++++++++++++++++++++++++

``upgrade_pythoncapi.py`` requires Python 3.6 or newer.

Usage
=====

Run the with no arguments to display command line options and list available
operations::

    python3 upgrade_pythoncapi.py

Select files and directories
----------------------------

To upgrade ``module.c`` file, type::

    python3 upgrade_pythoncapi.py module.c

To upgrade all C and C++ files (``.c``, ``.h``, ``.cc``, ``.cpp``, ``.cxx`` and
``.hpp`` files) in the ``directory/`` directory, type::

    python3 upgrade_pythoncapi.py directory/

Multiple filenames an directories can be specified on the command line.

Files are modified in-place! If a file is modified, a copy of the original file
is created with the ``.old`` suffix.

Select operations
-----------------

To only replace ``op->ob_type`` with ``Py_TYPE(op)``, select the ``Py_TYPE``
operation with::

    python3 upgrade_pythoncapi.py -o Py_TYPE module.c

Or the opposite, to apply all operations but leave ``op->ob_type`` unchanged,
deselect the ``Py_TYPE`` operation with::

    python3 upgrade_pythoncapi.py -o all,-Py_TYPE module.c

Download pythoncapi_compat.h
----------------------------

Most ``upgrade_pythoncapi.py`` operations add ``#include
"pythoncapi_compat.h"``. You may have to download the ``pythoncapi_compat.h``
header file to your project. It can be downloaded with::

    python3 upgrade_pythoncapi.py --download PATH


Upgrade Operations
==================

``upgrade_pythoncapi.py`` implements the following operations:

Py_TYPE
-------

* Replace ``op->ob_type`` with ``Py_TYPE(op)``.

Py_SIZE
-------

* Replace ``op->ob_size`` with ``Py_SIZE(op)``.

Py_REFCNT
---------

* Replace ``op->ob_refcnt`` with ``Py_REFCNT(op)``.

Py_SET_TYPE
-----------

* Replace ``obj->ob_type = type;`` with ``Py_SET_TYPE(obj, type);``.
* Replace ``Py_TYPE(obj) = type;`` with ``Py_SET_TYPE(obj, type);``.

Py_SET_SIZE
-----------

* Replace ``obj->ob_size = size;`` with ``Py_SET_SIZE(obj, size);``.
* Replace ``Py_SIZE(obj) = size;`` with ``Py_SET_SIZE(obj, size);``.

Py_SET_REFCNT
-------------

* Replace ``obj->ob_refcnt = refcnt;`` with ``Py_SET_REFCNT(obj, refcnt);``.
* Replace ``Py_REFCNT(obj) = refcnt;`` with ``Py_SET_REFCNT(obj, refcnt);``.

Py_Is
-----

* Replace ``x == Py_None`` with ``Py_IsNone(x)``.
* Replace ``x == Py_True`` with ``Py_IsTrue(x)``.
* Replace ``x == Py_False`` with ``Py_IsFalse(x)``.
* Replace ``x != Py_None`` with ``!Py_IsNone(x)``.
* Replace ``x != Py_True`` with ``!Py_IsTrue(x)``.
* Replace ``x != Py_False`` with ``!Py_IsFalse(x)``.

PyObject_NEW
------------

* Replace ``PyObject_NEW(...)`` with ``PyObject_New(...)``.
* Replace ``PyObject_NEW_VAR(...)`` with ``PyObject_NewVar(...)``.

PyMem_MALLOC
------------

* Replace ``PyMem_MALLOC(n)`` with ``PyMem_Malloc(n)``.
* Replace ``PyMem_REALLOC(ptr, n)`` with ``PyMem_Realloc(ptr, n)``.
* Replace ``PyMem_FREE(ptr)``, ``PyMem_DEL(ptr)`` and ``PyMem_Del(ptr)`` .
  with ``PyMem_Free(n)``.

PyObject_MALLOC
---------------

* Replace ``PyObject_MALLOC(n)`` with ``PyObject_Malloc(n)``.
* Replace ``PyObject_REALLOC(ptr, n)`` with ``PyObject_Realloc(ptr, n)``.
* Replace ``PyObject_FREE(ptr)``, ``PyObject_DEL(ptr)``
  and ``PyObject_Del(ptr)`` .  with ``PyObject_Free(n)``.

PyFrame_GetBack
---------------

* Replace ``frame->f_back`` with ``_PyFrame_GetBackBorrow(frame)``.

PyFrame_GetCode
---------------

* Replace ``frame->f_code`` with ``_PyFrame_GetCodeBorrow(frame)``.

PyThreadState_GetInterpreter
----------------------------

* Replace ``tstate->interp`` with ``PyThreadState_GetInterpreter(tstate)``.

PyThreadState_GetFrame
----------------------

* Replace ``tstate->frame`` with ``_PyThreadState_GetFrameBorrow(tstate)``.

Experimental operations
-----------------------

The following operations are experimental (ex: can introduce compiler warnings)
and so not included in the ``all`` group, they have to be selected explicitly.
Example: ``-o all,Py_SETREF``.

Experimental operations:

* ``Py_NewRef``:

  * Replace ``Py_INCREF(res); return res;`` with ``return Py_NewRef(res);``
  * Replace ``x = y; Py_INCREF(x);`` with ``x = Py_NewRef(y);``
  * Replace ``x = y; Py_INCREF(y);`` with ``x = Py_NewRef(y);``
  * Replace ``Py_INCREF(y); x = y;`` with ``x = Py_NewRef(y);``

* ``Py_CLEAR``:

  * Replace ``Py_XDECREF(var); var = NULL;`` with ``Py_CLEAR(var);``

* ``Py_SETREF``:

  * Replace ``Py_DECREF(x); x = y;`` with ``Py_SETREF(x, y);``
  * Replace ``Py_XDECREF(x); x = y;`` with ``Py_XSETREF(x, y);``
07070100000012000081A400000000000000000000000166CC467200000DFD000000000000000000000000000000000000002A00000000pythoncapi-compat-vendored/docs/users.rst+++++++++++++++++++++++
pythoncapi-compat users
+++++++++++++++++++++++

Examples of projects using pythoncapi_compat.h
==============================================

* `bitarray <https://github.com/ilanschnell/bitarray/>`_:
  ``bitarray/_bitarray.c`` uses ``Py_SET_SIZE()``
  (`pythoncapi_compat.h copy
  <https://github.com/ilanschnell/bitarray/blob/master/bitarray/pythoncapi_compat.h>`__)
* `datatable <https://github.com/h2oai/datatable>`_
  (`commit <https://github.com/h2oai/datatable/commit/02f13114828ed4567e4410f5bac579895e20355a>`__)
* `guppy3 <https://github.com/zhuyifei1999/guppy3/>`_
  (`commit
  <https://github.com/zhuyifei1999/guppy3/commit/4cb9fcb5d75327544a6875b6caabfdffb70a7e29>`__)
* `immutables <https://github.com/MagicStack/immutables/>`_:
  ``immutables/_map.c`` uses ``Py_SET_SIZE()``
  (`pythoncapi_compat.h copy
  <https://github.com/MagicStack/immutables/blob/master/immutables/pythoncapi_compat.h>`__)
* `Mercurial (hg) <https://www.mercurial-scm.org/>`_ uses ``Py_SET_TYPE()``
  (`commit
  <https://www.mercurial-scm.org/repo/hg/rev/e92ca942ddca>`__,
  `pythoncapi_compat.h copy
  <https://www.mercurial-scm.org/repo/hg/file/tip/mercurial/pythoncapi_compat.h>`__)
* `mypy <https://github.com/python/mypy>`_
  (mypyc,
  `commit <https://github.com/python/mypy/commit/2b7e2df923f7e4a3a199915b3c8563f45bc69dfa>`__)
* `numpy <https://numpy.org/>`_:
  `pythoncapi-compat Git submodule
  <https://github.com/numpy/numpy/blob/main/.gitmodules>`_
* `pybluez <https://github.com/pybluez/pybluez>`_
  (`commit <https://github.com/pybluez/pybluez/commit/5096047f90a1f6a74ceb250aef6243e144170f92>`__)
* `python-snappy <https://github.com/andrix/python-snappy/>`_
  (`commit <https://github.com/andrix/python-snappy/commit/1a539d71d5b1ceaf9a2291f21f686cf53a46d707>`__)
* `python-zstandard <https://github.com/indygreg/python-zstandard/>`_
  uses ``Py_SET_TYPE()`` and ``Py_SET_SIZE()``
  (`commit <https://github.com/indygreg/python-zstandard/commit/e5a3baf61b65f3075f250f504ddad9f8612bfedf>`__):
  Mercurial extension.
* `python-zstd <https://github.com/sergey-dryabzhinsky/python-zstd/>`_
  (`commit <https://github.com/sergey-dryabzhinsky/python-zstd/commit/8aa6d7a4b250e1f0a4e27b4107c39dc516c87f96>`__)
* `hollerith <https://github.com/pyansys/hollerith/>`_
  ``src/writer.c`` uses ``PyObject_CallOneArg() and other Python 3.9 apis``
  (`pythoncapi_compat.h copy
  <https://github.com/pyansys/hollerith/blob/main/src/pythoncapi_compat.h>`__)
* `PyTorch <https://github.com/pytorch/pytorch/>`_ (`pythoncapi_compat.h copy
  <https://github.com/pytorch/pytorch/blob/main/torch/csrc/utils/pythoncapi_compat.h>`__)


Projects not using pythoncapi_compat.h
======================================

Projects not using ``pythoncapi_compat.h``:

* numpy has its own compatibility layer, ``npy_pycompat.h`` and
  ``npy_3kcompat.h`` header files. It supports more C compilers than
  pythoncapi_compat.h: it supports ``__STRICT_ANSI__`` (ISO C90) for example.
  Rejected `PR 18713: MAINT: Use pythoncapi_compat.h in npy_3kcompat.h
  <https://github.com/numpy/numpy/pull/18713>`_ (when it was rejected, numpy
  still had code for compatibility with Python 2.7).
* Cython doesn't use pythoncapi_compat.h:
  `see Cython issue #3934
  <https://github.com/cython/cython/issues/3934>`_.
  For example, `ModuleSetupCode.c
  <https://github.com/cython/cython/blob/0.29.x/Cython/Utility/ModuleSetupCode.c>`_
  provides functions like ``__Pyx_SET_REFCNT()``.

Project with a strict contributor agreement:

* `zodbpickle
  <https://github.com/zopefoundation/zodbpickle/pull/64>`_
07070100000013000081A400000000000000000000000166CC467200009FAF000000000000000000000000000000000000002F00000000pythoncapi-compat-vendored/pythoncapi_compat.h// Header file providing new C API functions to old Python versions.
//
// File distributed under the Zero Clause BSD (0BSD) license.
// Copyright Contributors to the pythoncapi_compat project.
//
// Homepage:
// https://github.com/python/pythoncapi_compat
//
// Latest version:
// https://raw.githubusercontent.com/python/pythoncapi_compat/master/pythoncapi_compat.h
//
// SPDX-License-Identifier: 0BSD

#ifndef PYTHONCAPI_COMPAT
#define PYTHONCAPI_COMPAT

#ifdef __cplusplus
extern "C" {
#endif

#include <Python.h>

// Python 3.11.0b4 added PyFrame_Back() to Python.h
#if PY_VERSION_HEX < 0x030b00B4 && !defined(PYPY_VERSION)
#  include "frameobject.h"        // PyFrameObject, PyFrame_GetBack()
#endif


#ifndef _Py_CAST
#  define _Py_CAST(type, expr) ((type)(expr))
#endif

// Static inline functions should use _Py_NULL rather than using directly NULL
// to prevent C++ compiler warnings. On C23 and newer and on C++11 and newer,
// _Py_NULL is defined as nullptr.
#if (defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L) \
        || (defined(__cplusplus) && __cplusplus >= 201103)
#  define _Py_NULL nullptr
#else
#  define _Py_NULL NULL
#endif

// Cast argument to PyObject* type.
#ifndef _PyObject_CAST
#  define _PyObject_CAST(op) _Py_CAST(PyObject*, op)
#endif


// bpo-42262 added Py_NewRef() to Python 3.10.0a3
#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_NewRef)
static inline PyObject* _Py_NewRef(PyObject *obj)
{
    Py_INCREF(obj);
    return obj;
}
#define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj))
#endif


// bpo-42262 added Py_XNewRef() to Python 3.10.0a3
#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_XNewRef)
static inline PyObject* _Py_XNewRef(PyObject *obj)
{
    Py_XINCREF(obj);
    return obj;
}
#define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj))
#endif


// bpo-39573 added Py_SET_REFCNT() to Python 3.9.0a4
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_REFCNT)
static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt)
{
    ob->ob_refcnt = refcnt;
}
#define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT(_PyObject_CAST(ob), refcnt)
#endif


// Py_SETREF() and Py_XSETREF() were added to Python 3.5.2.
// It is excluded from the limited C API.
#if (PY_VERSION_HEX < 0x03050200 && !defined(Py_SETREF)) && !defined(Py_LIMITED_API)
#define Py_SETREF(dst, src)                                     \
    do {                                                        \
        PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \
        PyObject *_tmp_dst = (*_tmp_dst_ptr);                   \
        *_tmp_dst_ptr = _PyObject_CAST(src);                    \
        Py_DECREF(_tmp_dst);                                    \
    } while (0)

#define Py_XSETREF(dst, src)                                    \
    do {                                                        \
        PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \
        PyObject *_tmp_dst = (*_tmp_dst_ptr);                   \
        *_tmp_dst_ptr = _PyObject_CAST(src);                    \
        Py_XDECREF(_tmp_dst);                                   \
    } while (0)
#endif


// bpo-43753 added Py_Is(), Py_IsNone(), Py_IsTrue() and Py_IsFalse()
// to Python 3.10.0b1.
#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_Is)
#  define Py_Is(x, y) ((x) == (y))
#endif
#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_IsNone)
#  define Py_IsNone(x) Py_Is(x, Py_None)
#endif
#if (PY_VERSION_HEX < 0x030A00B1 || defined(PYPY_VERSION)) && !defined(Py_IsTrue)
#  define Py_IsTrue(x) Py_Is(x, Py_True)
#endif
#if (PY_VERSION_HEX < 0x030A00B1 || defined(PYPY_VERSION)) && !defined(Py_IsFalse)
#  define Py_IsFalse(x) Py_Is(x, Py_False)
#endif


// bpo-39573 added Py_SET_TYPE() to Python 3.9.0a4
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE)
static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type)
{
    ob->ob_type = type;
}
#define Py_SET_TYPE(ob, type) _Py_SET_TYPE(_PyObject_CAST(ob), type)
#endif


// bpo-39573 added Py_SET_SIZE() to Python 3.9.0a4
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE)
static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size)
{
    ob->ob_size = size;
}
#define Py_SET_SIZE(ob, size) _Py_SET_SIZE((PyVarObject*)(ob), size)
#endif


// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1
#if PY_VERSION_HEX < 0x030900B1 || defined(PYPY_VERSION)
static inline PyCodeObject* PyFrame_GetCode(PyFrameObject *frame)
{
    assert(frame != _Py_NULL);
    assert(frame->f_code != _Py_NULL);
    return _Py_CAST(PyCodeObject*, Py_NewRef(frame->f_code));
}
#endif

static inline PyCodeObject* _PyFrame_GetCodeBorrow(PyFrameObject *frame)
{
    PyCodeObject *code = PyFrame_GetCode(frame);
    Py_DECREF(code);
    return code;
}


// bpo-40421 added PyFrame_GetBack() to Python 3.9.0b1
#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION)
static inline PyFrameObject* PyFrame_GetBack(PyFrameObject *frame)
{
    assert(frame != _Py_NULL);
    return _Py_CAST(PyFrameObject*, Py_XNewRef(frame->f_back));
}
#endif

#if !defined(PYPY_VERSION)
static inline PyFrameObject* _PyFrame_GetBackBorrow(PyFrameObject *frame)
{
    PyFrameObject *back = PyFrame_GetBack(frame);
    Py_XDECREF(back);
    return back;
}
#endif


// bpo-40421 added PyFrame_GetLocals() to Python 3.11.0a7
#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
static inline PyObject* PyFrame_GetLocals(PyFrameObject *frame)
{
#if PY_VERSION_HEX >= 0x030400B1
    if (PyFrame_FastToLocalsWithError(frame) < 0) {
        return NULL;
    }
#else
    PyFrame_FastToLocals(frame);
#endif
    return Py_NewRef(frame->f_locals);
}
#endif


// bpo-40421 added PyFrame_GetGlobals() to Python 3.11.0a7
#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
static inline PyObject* PyFrame_GetGlobals(PyFrameObject *frame)
{
    return Py_NewRef(frame->f_globals);
}
#endif


// bpo-40421 added PyFrame_GetBuiltins() to Python 3.11.0a7
#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
static inline PyObject* PyFrame_GetBuiltins(PyFrameObject *frame)
{
    return Py_NewRef(frame->f_builtins);
}
#endif


// bpo-40421 added PyFrame_GetLasti() to Python 3.11.0b1
#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION)
static inline int PyFrame_GetLasti(PyFrameObject *frame)
{
#if PY_VERSION_HEX >= 0x030A00A7
    // bpo-27129: Since Python 3.10.0a7, f_lasti is an instruction offset,
    // not a bytes offset anymore. Python uses 16-bit "wordcode" (2 bytes)
    // instructions.
    if (frame->f_lasti < 0) {
        return -1;
    }
    return frame->f_lasti * 2;
#else
    return frame->f_lasti;
#endif
}
#endif


// gh-91248 added PyFrame_GetVar() to Python 3.12.0a2
#if PY_VERSION_HEX < 0x030C00A2 && !defined(PYPY_VERSION)
static inline PyObject* PyFrame_GetVar(PyFrameObject *frame, PyObject *name)
{
    PyObject *locals, *value;

    locals = PyFrame_GetLocals(frame);
    if (locals == NULL) {
        return NULL;
    }
#if PY_VERSION_HEX >= 0x03000000
    value = PyDict_GetItemWithError(locals, name);
#else
    value = _PyDict_GetItemWithError(locals, name);
#endif
    Py_DECREF(locals);

    if (value == NULL) {
        if (PyErr_Occurred()) {
            return NULL;
        }
#if PY_VERSION_HEX >= 0x03000000
        PyErr_Format(PyExc_NameError, "variable %R does not exist", name);
#else
        PyErr_SetString(PyExc_NameError, "variable does not exist");
#endif
        return NULL;
    }
    return Py_NewRef(value);
}
#endif


// gh-91248 added PyFrame_GetVarString() to Python 3.12.0a2
#if PY_VERSION_HEX < 0x030C00A2 && !defined(PYPY_VERSION)
static inline PyObject*
PyFrame_GetVarString(PyFrameObject *frame, const char *name)
{
    PyObject *name_obj, *value;
#if PY_VERSION_HEX >= 0x03000000
    name_obj = PyUnicode_FromString(name);
#else
    name_obj = PyString_FromString(name);
#endif
    if (name_obj == NULL) {
        return NULL;
    }
    value = PyFrame_GetVar(frame, name_obj);
    Py_DECREF(name_obj);
    return value;
}
#endif


// bpo-39947 added PyThreadState_GetInterpreter() to Python 3.9.0a5
#if PY_VERSION_HEX < 0x030900A5 || defined(PYPY_VERSION)
static inline PyInterpreterState *
PyThreadState_GetInterpreter(PyThreadState *tstate)
{
    assert(tstate != _Py_NULL);
    return tstate->interp;
}
#endif


// bpo-40429 added PyThreadState_GetFrame() to Python 3.9.0b1
#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION)
static inline PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate)
{
    assert(tstate != _Py_NULL);
    return _Py_CAST(PyFrameObject *, Py_XNewRef(tstate->frame));
}
#endif

#if !defined(PYPY_VERSION)
static inline PyFrameObject*
_PyThreadState_GetFrameBorrow(PyThreadState *tstate)
{
    PyFrameObject *frame = PyThreadState_GetFrame(tstate);
    Py_XDECREF(frame);
    return frame;
}
#endif


// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a5
#if PY_VERSION_HEX < 0x030900A5 || defined(PYPY_VERSION)
static inline PyInterpreterState* PyInterpreterState_Get(void)
{
    PyThreadState *tstate;
    PyInterpreterState *interp;

    tstate = PyThreadState_GET();
    if (tstate == _Py_NULL) {
        Py_FatalError("GIL released (tstate is NULL)");
    }
    interp = tstate->interp;
    if (interp == _Py_NULL) {
        Py_FatalError("no current interpreter");
    }
    return interp;
}
#endif


// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a6
#if 0x030700A1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION)
static inline uint64_t PyThreadState_GetID(PyThreadState *tstate)
{
    assert(tstate != _Py_NULL);
    return tstate->id;
}
#endif

// bpo-43760 added PyThreadState_EnterTracing() to Python 3.11.0a2
#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION)
static inline void PyThreadState_EnterTracing(PyThreadState *tstate)
{
    tstate->tracing++;
#if PY_VERSION_HEX >= 0x030A00A1
    tstate->cframe->use_tracing = 0;
#else
    tstate->use_tracing = 0;
#endif
}
#endif

// bpo-43760 added PyThreadState_LeaveTracing() to Python 3.11.0a2
#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION)
static inline void PyThreadState_LeaveTracing(PyThreadState *tstate)
{
    int use_tracing = (tstate->c_tracefunc != _Py_NULL
                       || tstate->c_profilefunc != _Py_NULL);
    tstate->tracing--;
#if PY_VERSION_HEX >= 0x030A00A1
    tstate->cframe->use_tracing = use_tracing;
#else
    tstate->use_tracing = use_tracing;
#endif
}
#endif


// bpo-37194 added PyObject_CallNoArgs() to Python 3.9.0a1
// PyObject_CallNoArgs() added to PyPy 3.9.16-v7.3.11
#if !defined(PyObject_CallNoArgs) && PY_VERSION_HEX < 0x030900A1
static inline PyObject* PyObject_CallNoArgs(PyObject *func)
{
    return PyObject_CallFunctionObjArgs(func, NULL);
}
#endif


// bpo-39245 made PyObject_CallOneArg() public (previously called
// _PyObject_CallOneArg) in Python 3.9.0a4
// PyObject_CallOneArg() added to PyPy 3.9.16-v7.3.11
#if !defined(PyObject_CallOneArg) && PY_VERSION_HEX < 0x030900A4
static inline PyObject* PyObject_CallOneArg(PyObject *func, PyObject *arg)
{
    return PyObject_CallFunctionObjArgs(func, arg, NULL);
}
#endif


// bpo-1635741 added PyModule_AddObjectRef() to Python 3.10.0a3
#if PY_VERSION_HEX < 0x030A00A3
static inline int
PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value)
{
    int res;

    if (!value && !PyErr_Occurred()) {
        // PyModule_AddObject() raises TypeError in this case
        PyErr_SetString(PyExc_SystemError,
                        "PyModule_AddObjectRef() must be called "
                        "with an exception raised if value is NULL");
        return -1;
    }

    Py_XINCREF(value);
    res = PyModule_AddObject(module, name, value);
    if (res < 0) {
        Py_XDECREF(value);
    }
    return res;
}
#endif


// bpo-40024 added PyModule_AddType() to Python 3.9.0a5
#if PY_VERSION_HEX < 0x030900A5
static inline int PyModule_AddType(PyObject *module, PyTypeObject *type)
{
    const char *name, *dot;

    if (PyType_Ready(type) < 0) {
        return -1;
    }

    // inline _PyType_Name()
    name = type->tp_name;
    assert(name != _Py_NULL);
    dot = strrchr(name, '.');
    if (dot != _Py_NULL) {
        name = dot + 1;
    }

    return PyModule_AddObjectRef(module, name, _PyObject_CAST(type));
}
#endif


// bpo-40241 added PyObject_GC_IsTracked() to Python 3.9.0a6.
// bpo-4688 added _PyObject_GC_IS_TRACKED() to Python 2.7.0a2.
#if PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION)
static inline int PyObject_GC_IsTracked(PyObject* obj)
{
    return (PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj));
}
#endif

// bpo-40241 added PyObject_GC_IsFinalized() to Python 3.9.0a6.
// bpo-18112 added _PyGCHead_FINALIZED() to Python 3.4.0 final.
#if PY_VERSION_HEX < 0x030900A6 && PY_VERSION_HEX >= 0x030400F0 && !defined(PYPY_VERSION)
static inline int PyObject_GC_IsFinalized(PyObject *obj)
{
    PyGC_Head *gc = _Py_CAST(PyGC_Head*, obj) - 1;
    return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(gc));
}
#endif


// bpo-39573 added Py_IS_TYPE() to Python 3.9.0a4
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE)
static inline int _Py_IS_TYPE(PyObject *ob, PyTypeObject *type) {
    return Py_TYPE(ob) == type;
}
#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST(ob), type)
#endif


// bpo-46906 added PyFloat_Pack2() and PyFloat_Unpack2() to Python 3.11a7.
// bpo-11734 added _PyFloat_Pack2() and _PyFloat_Unpack2() to Python 3.6.0b1.
// Python 3.11a2 moved _PyFloat_Pack2() and _PyFloat_Unpack2() to the internal
// C API: Python 3.11a2-3.11a6 versions are not supported.
#if 0x030600B1 <= PY_VERSION_HEX && PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION)
static inline int PyFloat_Pack2(double x, char *p, int le)
{ return _PyFloat_Pack2(x, (unsigned char*)p, le); }

static inline double PyFloat_Unpack2(const char *p, int le)
{ return _PyFloat_Unpack2((const unsigned char *)p, le); }
#endif


// bpo-46906 added PyFloat_Pack4(), PyFloat_Pack8(), PyFloat_Unpack4() and
// PyFloat_Unpack8() to Python 3.11a7.
// Python 3.11a2 moved _PyFloat_Pack4(), _PyFloat_Pack8(), _PyFloat_Unpack4()
// and _PyFloat_Unpack8() to the internal C API: Python 3.11a2-3.11a6 versions
// are not supported.
#if PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION)
static inline int PyFloat_Pack4(double x, char *p, int le)
{ return _PyFloat_Pack4(x, (unsigned char*)p, le); }

static inline int PyFloat_Pack8(double x, char *p, int le)
{ return _PyFloat_Pack8(x, (unsigned char*)p, le); }

static inline double PyFloat_Unpack4(const char *p, int le)
{ return _PyFloat_Unpack4((const unsigned char *)p, le); }

static inline double PyFloat_Unpack8(const char *p, int le)
{ return _PyFloat_Unpack8((const unsigned char *)p, le); }
#endif


// gh-92154 added PyCode_GetCode() to Python 3.11.0b1
#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION)
static inline PyObject* PyCode_GetCode(PyCodeObject *code)
{
    return Py_NewRef(code->co_code);
}
#endif


// gh-95008 added PyCode_GetVarnames() to Python 3.11.0rc1
#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
static inline PyObject* PyCode_GetVarnames(PyCodeObject *code)
{
    return Py_NewRef(code->co_varnames);
}
#endif

// gh-95008 added PyCode_GetFreevars() to Python 3.11.0rc1
#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
static inline PyObject* PyCode_GetFreevars(PyCodeObject *code)
{
    return Py_NewRef(code->co_freevars);
}
#endif

// gh-95008 added PyCode_GetCellvars() to Python 3.11.0rc1
#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
static inline PyObject* PyCode_GetCellvars(PyCodeObject *code)
{
    return Py_NewRef(code->co_cellvars);
}
#endif


// Py_UNUSED() was added to Python 3.4.0b2.
#if PY_VERSION_HEX < 0x030400B2 && !defined(Py_UNUSED)
#  if defined(__GNUC__) || defined(__clang__)
#    define Py_UNUSED(name) _unused_ ## name __attribute__((unused))
#  else
#    define Py_UNUSED(name) _unused_ ## name
#  endif
#endif


// gh-105922 added PyImport_AddModuleRef() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A0
static inline PyObject* PyImport_AddModuleRef(const char *name)
{
    return Py_XNewRef(PyImport_AddModule(name));
}
#endif


// gh-105927 added PyWeakref_GetRef() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D0000
static inline int PyWeakref_GetRef(PyObject *ref, PyObject **pobj)
{
    PyObject *obj;
    if (ref != NULL && !PyWeakref_Check(ref)) {
        *pobj = NULL;
        PyErr_SetString(PyExc_TypeError, "expected a weakref");
        return -1;
    }
    obj = PyWeakref_GetObject(ref);
    if (obj == NULL) {
        // SystemError if ref is NULL
        *pobj = NULL;
        return -1;
    }
    if (obj == Py_None) {
        *pobj = NULL;
        return 0;
    }
    *pobj = Py_NewRef(obj);
    return (*pobj != NULL);
}
#endif


// bpo-36974 added PY_VECTORCALL_ARGUMENTS_OFFSET to Python 3.8b1
#ifndef PY_VECTORCALL_ARGUMENTS_OFFSET
#  define PY_VECTORCALL_ARGUMENTS_OFFSET (_Py_CAST(size_t, 1) << (8 * sizeof(size_t) - 1))
#endif

// bpo-36974 added PyVectorcall_NARGS() to Python 3.8b1
#if PY_VERSION_HEX < 0x030800B1
static inline Py_ssize_t PyVectorcall_NARGS(size_t n)
{
    return n & ~PY_VECTORCALL_ARGUMENTS_OFFSET;
}
#endif


// gh-105922 added PyObject_Vectorcall() to Python 3.9.0a4
#if PY_VERSION_HEX < 0x030900A4
static inline PyObject*
PyObject_Vectorcall(PyObject *callable, PyObject *const *args,
                     size_t nargsf, PyObject *kwnames)
{
#if PY_VERSION_HEX >= 0x030800B1 && !defined(PYPY_VERSION)
    // bpo-36974 added _PyObject_Vectorcall() to Python 3.8.0b1
    return _PyObject_Vectorcall(callable, args, nargsf, kwnames);
#else
    PyObject *posargs = NULL, *kwargs = NULL;
    PyObject *res;
    Py_ssize_t nposargs, nkwargs, i;

    if (nargsf != 0 && args == NULL) {
        PyErr_BadInternalCall();
        goto error;
    }
    if (kwnames != NULL && !PyTuple_Check(kwnames)) {
        PyErr_BadInternalCall();
        goto error;
    }

    nposargs = (Py_ssize_t)PyVectorcall_NARGS(nargsf);
    if (kwnames) {
        nkwargs = PyTuple_GET_SIZE(kwnames);
    }
    else {
        nkwargs = 0;
    }

    posargs = PyTuple_New(nposargs);
    if (posargs == NULL) {
        goto error;
    }
    if (nposargs) {
        for (i=0; i < nposargs; i++) {
            PyTuple_SET_ITEM(posargs, i, Py_NewRef(*args));
            args++;
        }
    }

    if (nkwargs) {
        kwargs = PyDict_New();
        if (kwargs == NULL) {
            goto error;
        }

        for (i = 0; i < nkwargs; i++) {
            PyObject *key = PyTuple_GET_ITEM(kwnames, i);
            PyObject *value = *args;
            args++;
            if (PyDict_SetItem(kwargs, key, value) < 0) {
                goto error;
            }
        }
    }
    else {
        kwargs = NULL;
    }

    res = PyObject_Call(callable, posargs, kwargs);
    Py_DECREF(posargs);
    Py_XDECREF(kwargs);
    return res;

error:
    Py_DECREF(posargs);
    Py_XDECREF(kwargs);
    return NULL;
#endif
}
#endif


// gh-106521 added PyObject_GetOptionalAttr() and
// PyObject_GetOptionalAttrString() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int
PyObject_GetOptionalAttr(PyObject *obj, PyObject *attr_name, PyObject **result)
{
    // bpo-32571 added _PyObject_LookupAttr() to Python 3.7.0b1
#if PY_VERSION_HEX >= 0x030700B1 && !defined(PYPY_VERSION)
    return _PyObject_LookupAttr(obj, attr_name, result);
#else
    *result = PyObject_GetAttr(obj, attr_name);
    if (*result != NULL) {
        return 1;
    }
    if (!PyErr_Occurred()) {
        return 0;
    }
    if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
        PyErr_Clear();
        return 0;
    }
    return -1;
#endif
}

static inline int
PyObject_GetOptionalAttrString(PyObject *obj, const char *attr_name, PyObject **result)
{
    PyObject *name_obj;
    int rc;
#if PY_VERSION_HEX >= 0x03000000
    name_obj = PyUnicode_FromString(attr_name);
#else
    name_obj = PyString_FromString(attr_name);
#endif
    if (name_obj == NULL) {
        *result = NULL;
        return -1;
    }
    rc = PyObject_GetOptionalAttr(obj, name_obj, result);
    Py_DECREF(name_obj);
    return rc;
}
#endif


// gh-106307 added PyObject_GetOptionalAttr() and
// PyMapping_GetOptionalItemString() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int
PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result)
{
    *result = PyObject_GetItem(obj, key);
    if (*result) {
        return 1;
    }
    if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
        return -1;
    }
    PyErr_Clear();
    return 0;
}

static inline int
PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result)
{
    PyObject *key_obj;
    int rc;
#if PY_VERSION_HEX >= 0x03000000
    key_obj = PyUnicode_FromString(key);
#else
    key_obj = PyString_FromString(key);
#endif
    if (key_obj == NULL) {
        *result = NULL;
        return -1;
    }
    rc = PyMapping_GetOptionalItem(obj, key_obj, result);
    Py_DECREF(key_obj);
    return rc;
}
#endif

// gh-108511 added PyMapping_HasKeyWithError() and
// PyMapping_HasKeyStringWithError() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int
PyMapping_HasKeyWithError(PyObject *obj, PyObject *key)
{
    PyObject *res;
    int rc = PyMapping_GetOptionalItem(obj, key, &res);
    Py_XDECREF(res);
    return rc;
}

static inline int
PyMapping_HasKeyStringWithError(PyObject *obj, const char *key)
{
    PyObject *res;
    int rc = PyMapping_GetOptionalItemString(obj, key, &res);
    Py_XDECREF(res);
    return rc;
}
#endif


// gh-108511 added PyObject_HasAttrWithError() and
// PyObject_HasAttrStringWithError() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int
PyObject_HasAttrWithError(PyObject *obj, PyObject *attr)
{
    PyObject *res;
    int rc = PyObject_GetOptionalAttr(obj, attr, &res);
    Py_XDECREF(res);
    return rc;
}

static inline int
PyObject_HasAttrStringWithError(PyObject *obj, const char *attr)
{
    PyObject *res;
    int rc = PyObject_GetOptionalAttrString(obj, attr, &res);
    Py_XDECREF(res);
    return rc;
}
#endif


// gh-106004 added PyDict_GetItemRef() and PyDict_GetItemStringRef()
// to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int
PyDict_GetItemRef(PyObject *mp, PyObject *key, PyObject **result)
{
#if PY_VERSION_HEX >= 0x03000000
    PyObject *item = PyDict_GetItemWithError(mp, key);
#else
    PyObject *item = _PyDict_GetItemWithError(mp, key);
#endif
    if (item != NULL) {
        *result = Py_NewRef(item);
        return 1;  // found
    }
    if (!PyErr_Occurred()) {
        *result = NULL;
        return 0;  // not found
    }
    *result = NULL;
    return -1;
}

static inline int
PyDict_GetItemStringRef(PyObject *mp, const char *key, PyObject **result)
{
    int res;
#if PY_VERSION_HEX >= 0x03000000
    PyObject *key_obj = PyUnicode_FromString(key);
#else
    PyObject *key_obj = PyString_FromString(key);
#endif
    if (key_obj == NULL) {
        *result = NULL;
        return -1;
    }
    res = PyDict_GetItemRef(mp, key_obj, result);
    Py_DECREF(key_obj);
    return res;
}
#endif


// gh-106307 added PyModule_Add() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int
PyModule_Add(PyObject *mod, const char *name, PyObject *value)
{
    int res = PyModule_AddObjectRef(mod, name, value);
    Py_XDECREF(value);
    return res;
}
#endif


// gh-108014 added Py_IsFinalizing() to Python 3.13.0a1
// bpo-1856 added _Py_Finalizing to Python 3.2.1b1.
// _Py_IsFinalizing() was added to PyPy 7.3.0.
#if (0x030201B1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030D00A1) \
        && (!defined(PYPY_VERSION_NUM) || PYPY_VERSION_NUM >= 0x7030000)
static inline int Py_IsFinalizing(void)
{
#if PY_VERSION_HEX >= 0x030700A1
    // _Py_IsFinalizing() was added to Python 3.7.0a1.
    return _Py_IsFinalizing();
#else
    return (_Py_Finalizing != NULL);
#endif
}
#endif


// gh-108323 added PyDict_ContainsString() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int PyDict_ContainsString(PyObject *op, const char *key)
{
    PyObject *key_obj = PyUnicode_FromString(key);
    if (key_obj == NULL) {
        return -1;
    }
    int res = PyDict_Contains(op, key_obj);
    Py_DECREF(key_obj);
    return res;
}
#endif


// gh-108445 added PyLong_AsInt() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int PyLong_AsInt(PyObject *obj)
{
#ifdef PYPY_VERSION
    long value = PyLong_AsLong(obj);
    if (value == -1 && PyErr_Occurred()) {
        return -1;
    }
    if (value < (long)INT_MIN || (long)INT_MAX < value) {
        PyErr_SetString(PyExc_OverflowError,
                        "Python int too large to convert to C int");
        return -1;
    }
    return (int)value;
#else
    return _PyLong_AsInt(obj);
#endif
}
#endif


// gh-107073 added PyObject_VisitManagedDict() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int
PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg)
{
    PyObject **dict = _PyObject_GetDictPtr(obj);
    if (*dict == NULL) {
        return -1;
    }
    Py_VISIT(*dict);
    return 0;
}

static inline void
PyObject_ClearManagedDict(PyObject *obj)
{
    PyObject **dict = _PyObject_GetDictPtr(obj);
    if (*dict == NULL) {
        return;
    }
    Py_CLEAR(*dict);
}
#endif

// gh-108867 added PyThreadState_GetUnchecked() to Python 3.13.0a1
// Python 3.5.2 added _PyThreadState_UncheckedGet().
#if PY_VERSION_HEX >= 0x03050200 && PY_VERSION_HEX < 0x030D00A1
static inline PyThreadState*
PyThreadState_GetUnchecked(void)
{
    return _PyThreadState_UncheckedGet();
}
#endif

// gh-110289 added PyUnicode_EqualToUTF8() and PyUnicode_EqualToUTF8AndSize()
// to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int
PyUnicode_EqualToUTF8AndSize(PyObject *unicode, const char *str, Py_ssize_t str_len)
{
    Py_ssize_t len;
    const void *utf8;
    PyObject *exc_type, *exc_value, *exc_tb;
    int res;

    // API cannot report errors so save/restore the exception
    PyErr_Fetch(&exc_type, &exc_value, &exc_tb);

    // Python 3.3.0a1 added PyUnicode_AsUTF8AndSize()
#if PY_VERSION_HEX >= 0x030300A1
    if (PyUnicode_IS_ASCII(unicode)) {
        utf8 = PyUnicode_DATA(unicode);
        len = PyUnicode_GET_LENGTH(unicode);
    }
    else {
        utf8 = PyUnicode_AsUTF8AndSize(unicode, &len);
        if (utf8 == NULL) {
            // Memory allocation failure. The API cannot report error,
            // so ignore the exception and return 0.
            res = 0;
            goto done;
        }
    }

    if (len != str_len) {
        res = 0;
        goto done;
    }
    res = (memcmp(utf8, str, (size_t)len) == 0);
#else
    PyObject *bytes = PyUnicode_AsUTF8String(unicode);
    if (bytes == NULL) {
        // Memory allocation failure. The API cannot report error,
        // so ignore the exception and return 0.
        res = 0;
        goto done;
    }

#if PY_VERSION_HEX >= 0x03000000
    len = PyBytes_GET_SIZE(bytes);
    utf8 = PyBytes_AS_STRING(bytes);
#else
    len = PyString_GET_SIZE(bytes);
    utf8 = PyString_AS_STRING(bytes);
#endif
    if (len != str_len) {
        Py_DECREF(bytes);
        res = 0;
        goto done;
    }

    res = (memcmp(utf8, str, (size_t)len) == 0);
    Py_DECREF(bytes);
#endif

done:
    PyErr_Restore(exc_type, exc_value, exc_tb);
    return res;
}

static inline int
PyUnicode_EqualToUTF8(PyObject *unicode, const char *str)
{
    return PyUnicode_EqualToUTF8AndSize(unicode, str, (Py_ssize_t)strlen(str));
}
#endif


// gh-111138 added PyList_Extend() and PyList_Clear() to Python 3.13.0a2
#if PY_VERSION_HEX < 0x030D00A2
static inline int
PyList_Extend(PyObject *list, PyObject *iterable)
{
    return PyList_SetSlice(list, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, iterable);
}

static inline int
PyList_Clear(PyObject *list)
{
    return PyList_SetSlice(list, 0, PY_SSIZE_T_MAX, NULL);
}
#endif

// gh-111262 added PyDict_Pop() and PyDict_PopString() to Python 3.13.0a2
#if PY_VERSION_HEX < 0x030D00A2
static inline int
PyDict_Pop(PyObject *dict, PyObject *key, PyObject **result)
{
    PyObject *value;

    if (!PyDict_Check(dict)) {
        PyErr_BadInternalCall();
        if (result) {
            *result = NULL;
        }
        return -1;
    }

    // bpo-16991 added _PyDict_Pop() to Python 3.5.0b2.
    // Python 3.6.0b3 changed _PyDict_Pop() first argument type to PyObject*.
    // Python 3.13.0a1 removed _PyDict_Pop().
#if defined(PYPY_VERSION) || PY_VERSION_HEX < 0x030500b2 || PY_VERSION_HEX >= 0x030D0000
    value = PyObject_CallMethod(dict, "pop", "O", key);
#elif PY_VERSION_HEX < 0x030600b3
    value = _PyDict_Pop(_Py_CAST(PyDictObject*, dict), key, NULL);
#else
    value = _PyDict_Pop(dict, key, NULL);
#endif
    if (value == NULL) {
        if (result) {
            *result = NULL;
        }
        if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_KeyError)) {
            return -1;
        }
        PyErr_Clear();
        return 0;
    }
    if (result) {
        *result = value;
    }
    else {
        Py_DECREF(value);
    }
    return 1;
}

static inline int
PyDict_PopString(PyObject *dict, const char *key, PyObject **result)
{
    PyObject *key_obj = PyUnicode_FromString(key);
    if (key_obj == NULL) {
        if (result != NULL) {
            *result = NULL;
        }
        return -1;
    }

    int res = PyDict_Pop(dict, key_obj, result);
    Py_DECREF(key_obj);
    return res;
}
#endif


#if PY_VERSION_HEX < 0x030200A4
// Python 3.2.0a4 added Py_hash_t type
typedef Py_ssize_t Py_hash_t;
#endif


// gh-111545 added Py_HashPointer() to Python 3.13.0a3
#if PY_VERSION_HEX < 0x030D00A3
static inline Py_hash_t Py_HashPointer(const void *ptr)
{
#if PY_VERSION_HEX >= 0x030900A4 && !defined(PYPY_VERSION)
    return _Py_HashPointer(ptr);
#else
    return _Py_HashPointer(_Py_CAST(void*, ptr));
#endif
}
#endif


// Python 3.13a4 added a PyTime API.
// Use the private API added to Python 3.5.
#if PY_VERSION_HEX < 0x030D00A4 && PY_VERSION_HEX  >= 0x03050000
typedef _PyTime_t PyTime_t;
#define PyTime_MIN _PyTime_MIN
#define PyTime_MAX _PyTime_MAX

static inline double PyTime_AsSecondsDouble(PyTime_t t)
{ return _PyTime_AsSecondsDouble(t); }

static inline int PyTime_Monotonic(PyTime_t *result)
{ return _PyTime_GetMonotonicClockWithInfo(result, NULL); }

static inline int PyTime_Time(PyTime_t *result)
{ return _PyTime_GetSystemClockWithInfo(result, NULL); }

static inline int PyTime_PerfCounter(PyTime_t *result)
{
#if PY_VERSION_HEX >= 0x03070000 && !defined(PYPY_VERSION)
    return _PyTime_GetPerfCounterWithInfo(result, NULL);
#elif PY_VERSION_HEX >= 0x03070000
    // Call time.perf_counter_ns() and convert Python int object to PyTime_t.
    // Cache time.perf_counter_ns() function for best performance.
    static PyObject *func = NULL;
    if (func == NULL) {
        PyObject *mod = PyImport_ImportModule("time");
        if (mod == NULL) {
            return -1;
        }

        func = PyObject_GetAttrString(mod, "perf_counter_ns");
        Py_DECREF(mod);
        if (func == NULL) {
            return -1;
        }
    }

    PyObject *res = PyObject_CallNoArgs(func);
    if (res == NULL) {
        return -1;
    }
    long long value = PyLong_AsLongLong(res);
    Py_DECREF(res);

    if (value == -1 && PyErr_Occurred()) {
        return -1;
    }

    Py_BUILD_ASSERT(sizeof(value) >= sizeof(PyTime_t));
    *result = (PyTime_t)value;
    return 0;
#else
    // Call time.perf_counter() and convert C double to PyTime_t.
    // Cache time.perf_counter() function for best performance.
    static PyObject *func = NULL;
    if (func == NULL) {
        PyObject *mod = PyImport_ImportModule("time");
        if (mod == NULL) {
            return -1;
        }

        func = PyObject_GetAttrString(mod, "perf_counter");
        Py_DECREF(mod);
        if (func == NULL) {
            return -1;
        }
    }

    PyObject *res = PyObject_CallNoArgs(func);
    if (res == NULL) {
        return -1;
    }
    double d = PyFloat_AsDouble(res);
    Py_DECREF(res);

    if (d == -1.0 && PyErr_Occurred()) {
        return -1;
    }

    // Avoid floor() to avoid having to link to libm
    *result = (PyTime_t)(d * 1e9);
    return 0;
#endif
}

#endif

// gh-111389 added hash constants to Python 3.13.0a5. These constants were
// added first as private macros to Python 3.4.0b1 and PyPy 7.3.9.
#if (!defined(PyHASH_BITS) \
     && ((!defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x030400B1) \
         || (defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x03070000 \
             && PYPY_VERSION_NUM >= 0x07090000)))
#  define PyHASH_BITS _PyHASH_BITS
#  define PyHASH_MODULUS _PyHASH_MODULUS
#  define PyHASH_INF _PyHASH_INF
#  define PyHASH_IMAG _PyHASH_IMAG
#endif


// gh-111545 added Py_GetConstant() and Py_GetConstantBorrowed()
// to Python 3.13.0a6
#if PY_VERSION_HEX < 0x030D00A6 && !defined(Py_CONSTANT_NONE)

#define Py_CONSTANT_NONE 0
#define Py_CONSTANT_FALSE 1
#define Py_CONSTANT_TRUE 2
#define Py_CONSTANT_ELLIPSIS 3
#define Py_CONSTANT_NOT_IMPLEMENTED 4
#define Py_CONSTANT_ZERO 5
#define Py_CONSTANT_ONE 6
#define Py_CONSTANT_EMPTY_STR 7
#define Py_CONSTANT_EMPTY_BYTES 8
#define Py_CONSTANT_EMPTY_TUPLE 9

static inline PyObject* Py_GetConstant(unsigned int constant_id)
{
    static PyObject* constants[Py_CONSTANT_EMPTY_TUPLE + 1] = {NULL};

    if (constants[Py_CONSTANT_NONE] == NULL) {
        constants[Py_CONSTANT_NONE] = Py_None;
        constants[Py_CONSTANT_FALSE] = Py_False;
        constants[Py_CONSTANT_TRUE] = Py_True;
        constants[Py_CONSTANT_ELLIPSIS] = Py_Ellipsis;
        constants[Py_CONSTANT_NOT_IMPLEMENTED] = Py_NotImplemented;

        constants[Py_CONSTANT_ZERO] = PyLong_FromLong(0);
        if (constants[Py_CONSTANT_ZERO] == NULL) {
            goto fatal_error;
        }

        constants[Py_CONSTANT_ONE] = PyLong_FromLong(1);
        if (constants[Py_CONSTANT_ONE] == NULL) {
            goto fatal_error;
        }

        constants[Py_CONSTANT_EMPTY_STR] = PyUnicode_FromStringAndSize("", 0);
        if (constants[Py_CONSTANT_EMPTY_STR] == NULL) {
            goto fatal_error;
        }

        constants[Py_CONSTANT_EMPTY_BYTES] = PyBytes_FromStringAndSize("", 0);
        if (constants[Py_CONSTANT_EMPTY_BYTES] == NULL) {
            goto fatal_error;
        }

        constants[Py_CONSTANT_EMPTY_TUPLE] = PyTuple_New(0);
        if (constants[Py_CONSTANT_EMPTY_TUPLE] == NULL) {
            goto fatal_error;
        }
        // goto dance to avoid compiler warnings about Py_FatalError()
        goto init_done;

fatal_error:
        // This case should never happen
        Py_FatalError("Py_GetConstant() failed to get constants");
    }

init_done:
    if (constant_id <= Py_CONSTANT_EMPTY_TUPLE) {
        return Py_NewRef(constants[constant_id]);
    }
    else {
        PyErr_BadInternalCall();
        return NULL;
    }
}

static inline PyObject* Py_GetConstantBorrowed(unsigned int constant_id)
{
    PyObject *obj = Py_GetConstant(constant_id);
    Py_XDECREF(obj);
    return obj;
}
#endif


// gh-114329 added PyList_GetItemRef() to Python 3.13.0a4
#if PY_VERSION_HEX < 0x030D00A4
static inline PyObject *
PyList_GetItemRef(PyObject *op, Py_ssize_t index)
{
    PyObject *item = PyList_GetItem(op, index);
    Py_XINCREF(item);
    return item;
}
#endif


// gh-114329 added PyList_GetItemRef() to Python 3.13.0a4
#if PY_VERSION_HEX < 0x030D00A4
static inline int
PyDict_SetDefaultRef(PyObject *d, PyObject *key, PyObject *default_value,
                     PyObject **result)
{
    PyObject *value;
    if (PyDict_GetItemRef(d, key, &value) < 0) {
        // get error
        if (result) {
            *result = NULL;
        }
        return -1;
    }
    if (value != NULL) {
        // present
        if (result) {
            *result = value;
        }
        else {
            Py_DECREF(value);
        }
        return 1;
    }

    // missing: set the item
    if (PyDict_SetItem(d, key, default_value) < 0) {
        // set error
        if (result) {
            *result = NULL;
        }
        return -1;
    }
    if (result) {
        *result = Py_NewRef(default_value);
    }
    return 0;
}
#endif

#if PY_VERSION_HEX < 0x030D00B3
#  define Py_BEGIN_CRITICAL_SECTION(op) {
#  define Py_END_CRITICAL_SECTION() }
#  define Py_BEGIN_CRITICAL_SECTION2(a, b) {
#  define Py_END_CRITICAL_SECTION2() }
#endif

#if PY_VERSION_HEX < 0x030E0000 && PY_VERSION_HEX >= 0x03060000 && !defined(PYPY_VERSION)
typedef struct PyUnicodeWriter PyUnicodeWriter;

static inline void PyUnicodeWriter_Discard(PyUnicodeWriter *writer)
{
    _PyUnicodeWriter_Dealloc((_PyUnicodeWriter*)writer);
    PyMem_Free(writer);
}

static inline PyUnicodeWriter* PyUnicodeWriter_Create(Py_ssize_t length)
{
    if (length < 0) {
        PyErr_SetString(PyExc_ValueError,
                        "length must be positive");
        return NULL;
    }

    const size_t size = sizeof(_PyUnicodeWriter);
    PyUnicodeWriter *pub_writer = (PyUnicodeWriter *)PyMem_Malloc(size);
    if (pub_writer == _Py_NULL) {
        PyErr_NoMemory();
        return _Py_NULL;
    }
    _PyUnicodeWriter *writer = (_PyUnicodeWriter *)pub_writer;

    _PyUnicodeWriter_Init(writer);
    if (_PyUnicodeWriter_Prepare(writer, length, 127) < 0) {
        PyUnicodeWriter_Discard(pub_writer);
        return NULL;
    }
    writer->overallocate = 1;
    return pub_writer;
}

static inline PyObject* PyUnicodeWriter_Finish(PyUnicodeWriter *writer)
{
    PyObject *str = _PyUnicodeWriter_Finish((_PyUnicodeWriter*)writer);
    assert(((_PyUnicodeWriter*)writer)->buffer == NULL);
    PyMem_Free(writer);
    return str;
}

static inline int
PyUnicodeWriter_WriteChar(PyUnicodeWriter *writer, Py_UCS4 ch)
{
    if (ch > 0x10ffff) {
        PyErr_SetString(PyExc_ValueError,
                        "character must be in range(0x110000)");
        return -1;
    }

    return _PyUnicodeWriter_WriteChar((_PyUnicodeWriter*)writer, ch);
}

static inline int
PyUnicodeWriter_WriteStr(PyUnicodeWriter *writer, PyObject *obj)
{
    PyObject *str = PyObject_Str(obj);
    if (str == NULL) {
        return -1;
    }

    int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str);
    Py_DECREF(str);
    return res;
}

static inline int
PyUnicodeWriter_WriteRepr(PyUnicodeWriter *writer, PyObject *obj)
{
    PyObject *str = PyObject_Repr(obj);
    if (str == NULL) {
        return -1;
    }

    int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str);
    Py_DECREF(str);
    return res;
}

static inline int
PyUnicodeWriter_WriteUTF8(PyUnicodeWriter *writer,
                          const char *str, Py_ssize_t size)
{
    if (size < 0) {
        size = (Py_ssize_t)strlen(str);
    }

    PyObject *str_obj = PyUnicode_FromStringAndSize(str, size);
    if (str_obj == _Py_NULL) {
        return -1;
    }

    int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str_obj);
    Py_DECREF(str_obj);
    return res;
}

static inline int
PyUnicodeWriter_WriteWideChar(PyUnicodeWriter *writer,
                              const wchar_t *str, Py_ssize_t size)
{
    if (size < 0) {
        size = (Py_ssize_t)wcslen(str);
    }

    PyObject *str_obj = PyUnicode_FromWideChar(str, size);
    if (str_obj == _Py_NULL) {
        return -1;
    }

    int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str_obj);
    Py_DECREF(str_obj);
    return res;
}

static inline int
PyUnicodeWriter_WriteSubstring(PyUnicodeWriter *writer, PyObject *str,
                               Py_ssize_t start, Py_ssize_t end)
{
    if (!PyUnicode_Check(str)) {
        PyErr_Format(PyExc_TypeError, "expect str, not %T", str);
        return -1;
    }
    if (start < 0 || start > end) {
        PyErr_Format(PyExc_ValueError, "invalid start argument");
        return -1;
    }
    if (end > PyUnicode_GET_LENGTH(str)) {
        PyErr_Format(PyExc_ValueError, "invalid end argument");
        return -1;
    }

    return _PyUnicodeWriter_WriteSubstring((_PyUnicodeWriter*)writer, str,
                                           start, end);
}

static inline int
PyUnicodeWriter_Format(PyUnicodeWriter *writer, const char *format, ...)
{
    va_list vargs;
    va_start(vargs, format);
    PyObject *str = PyUnicode_FromFormatV(format, vargs);
    va_end(vargs);
    if (str == _Py_NULL) {
        return -1;
    }

    int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str);
    Py_DECREF(str);
    return res;
}
#endif  // PY_VERSION_HEX < 0x030E0000

// gh-116560 added PyLong_GetSign() to Python 3.14.0a0
#if PY_VERSION_HEX < 0x030E00A0
static inline int PyLong_GetSign(PyObject *obj, int *sign)
{
    if (!PyLong_Check(obj)) {
        PyErr_Format(PyExc_TypeError, "expect int, got %s", Py_TYPE(obj)->tp_name);
        return -1;
    }

    *sign = _PyLong_Sign(obj);
    return 0;
}
#endif


#ifdef __cplusplus
}
#endif
#endif  // PYTHONCAPI_COMPAT
07070100000014000081ED00000000000000000000000166CC467200000B61000000000000000000000000000000000000002700000000pythoncapi-compat-vendored/runtests.py#!/usr/bin/python3 -u
"""
Run the test suite on multiple Python versions.

Usage::

    python3 runtests.py
    python3 runtests.py --verbose
    python3 runtests.py --current --verbose
"""
from __future__ import absolute_import
from __future__ import print_function
import argparse
import os.path
import shutil
import subprocess
import sys
try:
    from shutil import which
except ImportError:
    # Python 2
    from distutils.spawn import find_executable as which


from tests.utils import run_command


TEST_DIR = os.path.join(os.path.dirname(__file__), 'tests')
TEST_COMPAT = os.path.join(TEST_DIR, "test_pythoncapi_compat.py")
TEST_UPGRADE = os.path.join(TEST_DIR, "test_upgrade_pythoncapi.py")

PYTHONS = (
    # CPython
    "python3-debug",
    "python3",
    "python2.7",
    "python3.6",
    "python3.7",
    "python3.8",
    "python3.9",
    "python3.10",
    "python3.11",
    "python3.12",
    "python3.13",

    # PyPy
    "pypy",
    "pypy2",
    "pypy2.7",
    "pypy3",
    "pypy3.6",
    "pypy3.7",
    "pypy3.8",
    "pypy3.9",
    "pypy3.10",
)


def run_tests_exe(executable, verbose, tested):
    tested_key = os.path.realpath(executable)
    if tested_key in tested:
        return

    # Don't use realpath() for the executed command to support virtual
    # environments
    cmd = [executable, TEST_COMPAT]
    if verbose:
        cmd.append('-v')
    run_command(cmd)
    tested.add(tested_key)


def run_tests(python, verbose, tested):
    executable = which(python)
    if not executable:
        print("Ignore missing Python executable: %s" % python)
        return
    run_tests_exe(executable, verbose, tested)


def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('-v', '--verbose', action="store_true",
                        help='Verbose mode')
    parser.add_argument('-c', '--current', action="store_true",
                        help="Only test the current Python executable "
                             "(don't test multiple Python versions)")
    return parser.parse_args()


def main():
    args = parse_args()

    path = os.path.join(TEST_DIR, 'build')
    if os.path.exists(path):
        shutil.rmtree(path)

    # upgrade_pythoncapi.py requires Python 3.6 or newer
    if sys.version_info >= (3, 6):
        print("Run %s" % TEST_UPGRADE)
        cmd = [sys.executable, TEST_UPGRADE]
        if args.verbose:
            cmd.append('-v')
        run_command(cmd)
    else:
        print("Don't test upgrade_pythoncapi.py: it requires Python 3.6")
    print()

    tested = set()
    if not args.current:
        for python in PYTHONS:
            run_tests(python, args.verbose, tested)
        run_tests_exe(sys.executable, args.verbose, tested)

        print()
        print("Tested: %s Python executables" % len(tested))
    else:
        run_tests_exe(sys.executable, args.verbose, tested)


if __name__ == "__main__":
    main()
07070100000015000041ED00000000000000000000000266CC467200000000000000000000000000000000000000000000002100000000pythoncapi-compat-vendored/tests07070100000016000081A400000000000000000000000166CC467200000000000000000000000000000000000000000000002D00000000pythoncapi-compat-vendored/tests/__init__.py07070100000017000081ED00000000000000000000000166CC467200000C6C000000000000000000000000000000000000002A00000000pythoncapi-compat-vendored/tests/setup.py#!/usr/bin/env python3
import os.path
import shlex
import sys
try:
    from setuptools import setup, Extension
except ImportError:
    from distutils.core import setup, Extension
try:
    from distutils import sysconfig
except ImportError:
    import sysconfig


# C++ is only supported on Python 3.6 and newer
TEST_CPP = (sys.version_info >= (3, 6))

SRC_DIR = os.path.normpath(os.path.join(os.path.dirname(__file__), '..'))

# Windows uses MSVC compiler
MSVC = (os.name == "nt")

# C compiler flags for GCC and clang
COMMON_FLAGS = [
    # Treat warnings as error
    '-Werror',
    # Enable all warnings
    '-Wall', '-Wextra',
    # Extra warnings
    '-Wconversion',
    # /usr/lib64/pypy3.7/include/pyport.h:68:20: error: redefinition of typedef
    # 'Py_hash_t' is a C11 feature
    "-Wno-typedef-redefinition",
]
CFLAGS = COMMON_FLAGS + [
    # Use C99 for pythoncapi_compat.c which initializes PyModuleDef with a
    # mixture of designated and non-designated initializers
    '-std=c99',
]
CPPFLAGS = list(COMMON_FLAGS)
# FIXME: _Py_CAST() emits C++ compilers on Python 3.12.
# See: https://github.com/python/cpython/issues/94731
if 0:
    CPPFLAGS.extend((
        '-Wold-style-cast',
        '-Wzero-as-null-pointer-constant',
    ))


def main():
    # gh-105776: When "gcc -std=11" is used as the C++ compiler, -std=c11
    # option emits a C++ compiler warning. Remove "-std11" option from the
    # CC command.
    cmd = (sysconfig.get_config_var('CC') or '')
    if cmd:
        cmd = shlex.split(cmd)
        cmd = [arg for arg in cmd if not arg.startswith('-std=')]
        if (sys.version_info >= (3, 8)):
            cmd = shlex.join(cmd)
        elif (sys.version_info >= (3, 3)):
            cmd = ' '.join(shlex.quote(arg) for arg in cmd)
        else:
            # Python 2.7
            import pipes
            cmd = ' '.join(pipes.quote(arg) for arg in cmd)
        # CC env var overrides sysconfig CC variable in setuptools
        os.environ['CC'] = cmd

    cflags = ['-I' + SRC_DIR]
    cppflags = list(cflags)
    if not MSVC:
        cflags.extend(CFLAGS)
        cppflags.extend(CPPFLAGS)

    # C extension
    c_ext = Extension(
        'test_pythoncapi_compat_cext',
        sources=['test_pythoncapi_compat_cext.c'],
        extra_compile_args=cflags)
    extensions = [c_ext]

    if TEST_CPP:
        # C++ extension

        # MSVC has /std flag but doesn't support /std:c++11
        if not MSVC:
            versions = [
                ('test_pythoncapi_compat_cpp03ext', '-std=c++03'),
                ('test_pythoncapi_compat_cpp11ext', '-std=c++11'),
            ]
        else:
            versions = [('test_pythoncapi_compat_cppext', None)]
        for name, flag in versions:
            flags = list(cppflags)
            if flag is not None:
                flags.append(flag)
            cpp_ext = Extension(
                name,
                sources=['test_pythoncapi_compat_cppext.cpp'],
                extra_compile_args=flags,
                language='c++')
            extensions.append(cpp_ext)

    setup(name="test_pythoncapi_compat",
          ext_modules=extensions)


if __name__ == "__main__":
    main()
07070100000018000081A400000000000000000000000166CC4672000013A8000000000000000000000000000000000000003B00000000pythoncapi-compat-vendored/tests/test_pythoncapi_compat.py#!/usr/bin/python3
"""
Run the test suite.

Usage::

    python3 run_tests.py
    python3 run_tests.py -v # verbose mode
"""
from __future__ import absolute_import
from __future__ import print_function
import gc
import os.path
import shutil
import subprocess
import sys
try:
    import faulthandler
except ImportError:
    # Python 2
    faulthandler = None

# test.utils
from utils import run_command, command_stdout


TESTS = [
    ("test_pythoncapi_compat_cext", "C"),
    ("test_pythoncapi_compat_cppext", "C++"),
    ("test_pythoncapi_compat_cpp03ext", "C++03"),
    ("test_pythoncapi_compat_cpp11ext", "C++11"),
]

VERBOSE = False


def display_title(title):
    if not VERBOSE:
        return

    ver = sys.version_info
    title = "Python %s.%s: %s" % (ver.major, ver.minor, title)

    print(title)
    print("=" * len(title))
    print()
    sys.stdout.flush()


def build_ext():
    display_title("Build test extensions")
    if os.path.exists("build"):
        shutil.rmtree("build")
    cmd = [sys.executable, "setup.py", "build"]
    if VERBOSE:
        run_command(cmd)
        print()
    else:
        exitcode, stdout = command_stdout(cmd, stderr=subprocess.STDOUT)
        if exitcode:
            print(stdout.rstrip())
            sys.exit(exitcode)


def import_tests(module_name):
    pythonpath = None
    for name in os.listdir("build"):
        if name.startswith('lib.'):
            pythonpath = os.path.join("build", name)

    if not pythonpath:
        raise Exception("Failed to find the build directory")
    sys.path.append(pythonpath)

    return __import__(module_name)


def _run_tests(tests, verbose):
    for name, test_func in tests:
        if verbose:
            print("%s()" % name)
            sys.stdout.flush()
        test_func()


_HAS_CLEAR_TYPE_CACHE = hasattr(sys, '_clear_type_cache')

def _refleak_cleanup():
    if _HAS_CLEAR_TYPE_CACHE:
        sys._clear_type_cache()
    gc.collect()


def _check_refleak(test_func, verbose):
    nrun = 6
    for i in range(1, nrun + 1):
        if verbose:
            if i > 1:
                print()
            print("Run %s/%s:" % (i, nrun))
            sys.stdout.flush()

        init_refcnt = sys.gettotalrefcount()
        test_func()
        _refleak_cleanup()
        diff = sys.gettotalrefcount() - init_refcnt

        if i > 3 and diff:
            raise AssertionError("refcnt leak, diff: %s" % diff)


def python_version():
    ver = sys.version_info
    build = 'debug' if hasattr(sys, 'gettotalrefcount') else 'release'
    if hasattr(sys, 'implementation'):
        python_impl = sys.implementation.name
        if python_impl == 'cpython':
            python_impl = 'CPython'
        elif python_impl == 'pypy':
            python_impl = 'PyPy'
    else:
        if "PyPy" in sys.version:
            python_impl = "PyPy"
        else:
            python_impl = 'Python'
    return "%s %s.%s (%s build)" % (python_impl, ver.major, ver.minor, build)


def run_tests(module_name, lang):
    title = "Test %s (%s)" % (module_name, lang)
    display_title(title)

    try:
        testmod = import_tests(module_name)
    except ImportError:
        # The C extension must always be available
        if lang == "C":
            raise

        if VERBOSE:
            print("%s: skip %s, missing %s extension"
                  % (python_version(), lang, module_name))
            print()
        return

    if VERBOSE:
        empty_line = False
        for attr in ('__cplusplus', 'PY_VERSION', 'PY_VERSION_HEX',
                     'PYPY_VERSION', 'PYPY_VERSION_NUM'):
            try:
                value = getattr(testmod, attr)
            except AttributeError:
                pass
            else:
                if attr in ("PY_VERSION_HEX", "PYPY_VERSION_NUM"):
                    value = "0x%x" % value
                print("%s: %s" % (attr, value))
                empty_line = True

        if empty_line:
            print()

    check_refleak = hasattr(sys, 'gettotalrefcount')

    tests = [(name, getattr(testmod, name))
             for name in dir(testmod)
             if name.startswith("test")]

    def test_func():
        _run_tests(tests, VERBOSE)

    if check_refleak:
        _check_refleak(test_func, VERBOSE)
    else:
        test_func()

    if VERBOSE:
        print()

    msg = "%s %s tests succeeded!" % (len(tests), lang)
    msg = "%s: %s" % (python_version(), msg)
    if check_refleak:
        msg = "%s (no reference leak detected)" % msg
    print(msg)


def main():
    global VERBOSE
    VERBOSE = ("-v" in sys.argv[1:] or "--verbose" in sys.argv[1:])

    if (3, 13) <= sys.version_info <= (3, 13, 0, 'alpha', 4):
        print("SKIP Python 3.13 alpha 1..4: not supported!")
        return

    if faulthandler is not None:
        faulthandler.enable()

    src_dir = os.path.dirname(__file__)
    if src_dir:
        os.chdir(src_dir)

    build_ext()

    for module_name, lang in TESTS:
        run_tests(module_name, lang)


if __name__ == "__main__":
    main()
07070100000019000081A400000000000000000000000166CC46720000D1DF000000000000000000000000000000000000003F00000000pythoncapi-compat-vendored/tests/test_pythoncapi_compat_cext.c// Always enable assertions
#undef NDEBUG

#include "pythoncapi_compat.h"

#ifdef NDEBUG
#  error "assertions must be enabled"
#endif

#ifdef Py_LIMITED_API
#  error "Py_LIMITED_API is not supported"
#endif

#if PY_VERSION_HEX >= 0x03000000
#  define PYTHON3 1
#endif

#if defined(_MSC_VER) && defined(__cplusplus)
#  define MODULE_NAME test_pythoncapi_compat_cppext
#elif defined(__cplusplus) && __cplusplus >= 201103
#  define MODULE_NAME test_pythoncapi_compat_cpp11ext
#elif defined(__cplusplus)
#  define MODULE_NAME test_pythoncapi_compat_cpp03ext
#else
#  define MODULE_NAME test_pythoncapi_compat_cext
#endif

#define _STR(NAME) #NAME
#define STR(NAME) _STR(NAME)
#define _CONCAT(a, b) a ## b
#define CONCAT(a, b) _CONCAT(a, b)

#define MODULE_NAME_STR STR(MODULE_NAME)

// Ignore reference count checks on PyPy
#ifndef PYPY_VERSION
#  define CHECK_REFCNT
#endif

// CPython 3.12 beta 1 implements immortal objects (PEP 683)
#if 0x030C00B1 <= PY_VERSION_HEX && !defined(PYPY_VERSION)
   // Don't check reference count of Python 3.12 immortal objects (ex: bool
   // and str types)
#  define IMMORTAL_OBJS
#endif

#ifdef CHECK_REFCNT
#  define ASSERT_REFCNT(expr) assert(expr)
#else
#  define ASSERT_REFCNT(expr)
#endif

// Marker to check that pointer value was set
static const char uninitialized[] = "uninitialized";
#define UNINITIALIZED_OBJ ((PyObject *)uninitialized)
#define UNINITIALIZED_INT 0x83ff979


static PyObject*
create_string(const char *str)
{
    PyObject *obj;
#ifdef PYTHON3
    obj = PyUnicode_FromString(str);
#else
    obj = PyString_FromString(str);
#endif
    assert(obj != _Py_NULL);
    return obj;
}


static PyObject *
test_object(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
{
    PyObject *obj = PyList_New(0);
    if (obj == _Py_NULL) {
        return _Py_NULL;
    }
    Py_ssize_t refcnt = Py_REFCNT(obj);

    // Py_NewRef()
    PyObject *ref = Py_NewRef(obj);
    assert(ref == obj);
    assert(Py_REFCNT(obj) == (refcnt + 1));
    Py_DECREF(ref);

    // Py_XNewRef()
    PyObject *xref = Py_XNewRef(obj);
    assert(xref == obj);
    assert(Py_REFCNT(obj) == (refcnt + 1));
    Py_DECREF(xref);

    assert(Py_XNewRef(_Py_NULL) == _Py_NULL);

    // Py_SETREF()
    PyObject *setref = Py_NewRef(obj);
    PyObject *none = Py_None;
    assert(Py_REFCNT(obj) == (refcnt + 1));

    Py_SETREF(setref, none);
    assert(setref == none);
    assert(Py_REFCNT(obj) == refcnt);
    Py_INCREF(setref);

    Py_SETREF(setref, _Py_NULL);
    assert(setref == _Py_NULL);

    // Py_XSETREF()
    PyObject *xsetref = _Py_NULL;

    Py_INCREF(obj);
    assert(Py_REFCNT(obj) == (refcnt + 1));
    Py_XSETREF(xsetref, obj);
    assert(xsetref == obj);

    Py_XSETREF(xsetref, _Py_NULL);
    assert(Py_REFCNT(obj) == refcnt);
    assert(xsetref == _Py_NULL);

    // Py_SET_REFCNT
    Py_SET_REFCNT(obj, Py_REFCNT(obj));
    // Py_SET_TYPE
    Py_SET_TYPE(obj, Py_TYPE(obj));
    // Py_SET_SIZE
    Py_SET_SIZE(obj, Py_SIZE(obj));
    // Py_IS_TYPE()
    int is_type = Py_IS_TYPE(obj, Py_TYPE(obj));
    assert(is_type);

    assert(Py_REFCNT(obj) == refcnt);
    Py_DECREF(obj);
    Py_RETURN_NONE;
}


static PyObject *
test_py_is(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
{
    PyObject *o_none = Py_None;
    PyObject *o_true = Py_True;
    PyObject *o_false = Py_False;
    PyObject *obj = PyList_New(0);
    if (obj == _Py_NULL) {
        return _Py_NULL;
    }

    /* test Py_Is() */
    assert(Py_Is(obj, obj));
    assert(!Py_Is(obj, o_none));

    /* test Py_IsNone() */
    assert(Py_IsNone(o_none));
    assert(!Py_IsNone(obj));

    /* test Py_IsTrue() */
    assert(Py_IsTrue(o_true));
    assert(!Py_IsTrue(o_false));
    assert(!Py_IsTrue(obj));

    /* testPy_IsFalse() */
    assert(Py_IsFalse(o_false));
    assert(!Py_IsFalse(o_true));
    assert(!Py_IsFalse(obj));

    Py_DECREF(obj);
    Py_RETURN_NONE;
}


#ifndef PYPY_VERSION
static void
test_frame_getvar(PyFrameObject *frame)
{
    // Make the assumption that test_frame_getvar() is only called by
    // _run_tests() of test_pythoncapi_compat.py and so that the "name"
    // variable exists.

    // test PyFrame_GetVar() and PyFrame_GetVarString()
    PyObject *attr = PyUnicode_FromString("name");
    assert(attr != _Py_NULL);
    PyObject *name1 = PyFrame_GetVar(frame, attr);
    Py_DECREF(attr);
    assert(name1 != _Py_NULL);
    Py_DECREF(name1);

    PyObject *name2 = PyFrame_GetVarString(frame, "name");
    assert(name2 != _Py_NULL);
    Py_DECREF(name2);

    // test PyFrame_GetVar() and PyFrame_GetVarString() NameError
    PyObject *attr3 = PyUnicode_FromString("dontexist");
    assert(attr3 != _Py_NULL);
    PyObject *name3 = PyFrame_GetVar(frame, attr3);
    Py_DECREF(attr3);
    assert(name3 == _Py_NULL);
    assert(PyErr_ExceptionMatches(PyExc_NameError));
    PyErr_Clear();

    PyObject *name4 = PyFrame_GetVarString(frame, "dontexist");
    assert(name4 == _Py_NULL);
    assert(PyErr_ExceptionMatches(PyExc_NameError));
    PyErr_Clear();
}


static PyObject *
test_frame(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
{
    PyThreadState *tstate = PyThreadState_Get();

    // test PyThreadState_GetFrame()
    PyFrameObject *frame = PyThreadState_GetFrame(tstate);
    if (frame == _Py_NULL) {
        PyErr_SetString(PyExc_AssertionError, "PyThreadState_GetFrame failed");
        return _Py_NULL;
    }

    // test _PyThreadState_GetFrameBorrow()
    Py_ssize_t frame_refcnt = Py_REFCNT(frame);
    PyFrameObject *frame2 = _PyThreadState_GetFrameBorrow(tstate);
    assert(frame2 == frame);
    assert(Py_REFCNT(frame) == frame_refcnt);

    // test PyFrame_GetCode()
    PyCodeObject *code = PyFrame_GetCode(frame);
    assert(code != _Py_NULL);
    assert(PyCode_Check(code));

    // test _PyFrame_GetCodeBorrow()
    Py_ssize_t code_refcnt = Py_REFCNT(code);
    PyCodeObject *code2 = _PyFrame_GetCodeBorrow(frame);
    assert(code2 == code);
    assert(Py_REFCNT(code) == code_refcnt);
    Py_DECREF(code);

    // PyFrame_GetBack()
    PyFrameObject* back = PyFrame_GetBack(frame);
    if (back != _Py_NULL) {
        assert(PyFrame_Check(back));
    }

    // test _PyFrame_GetBackBorrow()
    if (back != _Py_NULL) {
        Py_ssize_t back_refcnt = Py_REFCNT(back);
        PyFrameObject *back2 = _PyFrame_GetBackBorrow(frame);
        assert(back2 == back);
        assert(Py_REFCNT(back) == back_refcnt);
    }
    else {
        PyFrameObject *back2 = _PyFrame_GetBackBorrow(frame);
        assert(back2 == back);
    }
    Py_XDECREF(back);

    // test PyFrame_GetLocals()
    PyObject *locals = PyFrame_GetLocals(frame);
    assert(locals != _Py_NULL);
    // Python 3.13 creates a local proxy
#if PY_VERSION_HEX < 0x030D0000
    assert(PyDict_Check(locals));
#endif

    // test PyFrame_GetGlobals()
    PyObject *globals = PyFrame_GetGlobals(frame);
    assert(globals != _Py_NULL);
    assert(PyDict_Check(globals));

    // test PyFrame_GetBuiltins()
    PyObject *builtins = PyFrame_GetBuiltins(frame);
    assert(builtins != _Py_NULL);
    assert(PyDict_Check(builtins));

    assert(locals != globals);
    assert(globals != builtins);
    assert(builtins != locals);

    Py_DECREF(locals);
    Py_DECREF(globals);
    Py_DECREF(builtins);

    // test PyFrame_GetLasti()
    int lasti = PyFrame_GetLasti(frame);
    assert(lasti >= 0);

    // test PyFrame_GetVar() and PyFrame_GetVarString()
    test_frame_getvar(frame);

    // done
    Py_DECREF(frame);
    Py_RETURN_NONE;
}
#endif


static PyObject *
test_thread_state(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
{
    PyThreadState *tstate = PyThreadState_Get();

    // test PyThreadState_GetInterpreter()
    PyInterpreterState *interp = PyThreadState_GetInterpreter(tstate);
    assert(interp != _Py_NULL);

#ifndef PYPY_VERSION
    // test PyThreadState_GetFrame()
    PyFrameObject *frame = PyThreadState_GetFrame(tstate);
    if (frame != _Py_NULL) {
        assert(PyFrame_Check(frame));
    }
    Py_XDECREF(frame);
#endif

#if 0x030700A1 <= PY_VERSION_HEX && !defined(PYPY_VERSION)
    uint64_t id = PyThreadState_GetID(tstate);
    assert(id > 0);
#endif

#ifndef PYPY_VERSION
    // PyThreadState_EnterTracing(), PyThreadState_LeaveTracing()
    PyThreadState_EnterTracing(tstate);
    PyThreadState_LeaveTracing(tstate);
#endif

#if PY_VERSION_HEX >= 0x03050200
    // PyThreadState_GetUnchecked()
    assert(PyThreadState_GetUnchecked() == tstate);
#endif

    Py_RETURN_NONE;
}


static PyObject *
test_interpreter(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
{
    // test PyInterpreterState_Get()
    PyInterpreterState *interp = PyInterpreterState_Get();
    assert(interp != _Py_NULL);
    PyThreadState *tstate = PyThreadState_Get();
    PyInterpreterState *interp2 = PyThreadState_GetInterpreter(tstate);
    assert(interp == interp2);

#if 0x030300A1 <= PY_VERSION_HEX && (!defined(PYPY_VERSION_NUM) || PYPY_VERSION_NUM >= 0x7030000)
    // test Py_IsFinalizing()
    assert(Py_IsFinalizing() == 0);
#endif

    Py_RETURN_NONE;
}


static PyObject *
test_calls(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
{
    PyObject *func = _Py_CAST(PyObject*, &PyUnicode_Type);

    // test PyObject_CallNoArgs(): str() returns ''
    PyObject *res = PyObject_CallNoArgs(func);
    if (res == _Py_NULL) {
        return _Py_NULL;
    }
    assert(PyUnicode_Check(res));
    Py_DECREF(res);

    // test PyObject_CallOneArg(): str(1) returns '1'
    PyObject *arg = PyLong_FromLong(1);
    if (arg == _Py_NULL) {
        return _Py_NULL;
    }
    res = PyObject_CallOneArg(func, arg);
    Py_DECREF(arg);
    if (res == _Py_NULL) {
        return _Py_NULL;
    }
    assert(PyUnicode_Check(res));
    Py_DECREF(res);

    Py_RETURN_NONE;
}


static PyObject *
test_gc(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
{
    PyObject *tuple = PyTuple_New(1);
    Py_INCREF(Py_None);
    PyTuple_SET_ITEM(tuple, 0, Py_None);

#if !defined(PYPY_VERSION)
    // test PyObject_GC_IsTracked()
    int tracked = PyObject_GC_IsTracked(tuple);
    assert(tracked);
#endif

#if PY_VERSION_HEX >= 0x030400F0 && !defined(PYPY_VERSION)
    // test PyObject_GC_IsFinalized()
    int finalized = PyObject_GC_IsFinalized(tuple);
    assert(!finalized);
#endif

    Py_DECREF(tuple);
    Py_RETURN_NONE;
}


static int
check_module_attr(PyObject *module, const char *name, PyObject *expected)
{
    PyObject *attr = PyObject_GetAttrString(module, name);
    if (attr == _Py_NULL) {
        return -1;
    }
    assert(attr == expected);
    Py_DECREF(attr);

    if (PyObject_DelAttrString(module, name) < 0) {
        return -1;
    }
    return 0;
}


// test PyModule_AddType()
static int
test_module_add_type(PyObject *module)
{
    PyTypeObject *type = &PyUnicode_Type;
#ifdef PYTHON3
    const char *type_name = "str";
#else
    const char *type_name = "unicode";
#endif
#ifdef CHECK_REFCNT
    Py_ssize_t refcnt = Py_REFCNT(type);
#endif

    if (PyModule_AddType(module, type) < 0) {
        return -1;
    }
#ifndef IMMORTAL_OBJS
    ASSERT_REFCNT(Py_REFCNT(type) == refcnt + 1);
#endif

    if (check_module_attr(module, type_name, _Py_CAST(PyObject*, type)) < 0) {
        return -1;
    }
    ASSERT_REFCNT(Py_REFCNT(type) == refcnt);
    return 0;
}


// test PyModule_AddObjectRef()
static int
test_module_addobjectref(PyObject *module)
{
    const char *name = "test_module_addobjectref";
    PyObject *obj = PyUnicode_FromString(name);
    assert(obj != _Py_NULL);
#ifdef CHECK_REFCNT
    Py_ssize_t refcnt = Py_REFCNT(obj);
#endif

    if (PyModule_AddObjectRef(module, name, obj) < 0) {
        ASSERT_REFCNT(Py_REFCNT(obj) == refcnt);
        Py_DECREF(obj);
        return -1;
    }
    ASSERT_REFCNT(Py_REFCNT(obj) == refcnt + 1);

    if (check_module_attr(module, name, obj) < 0) {
        Py_DECREF(obj);
        return -1;
    }
    ASSERT_REFCNT(Py_REFCNT(obj) == refcnt);

    // PyModule_AddObjectRef() with value=NULL must not crash
    assert(!PyErr_Occurred());
    int res = PyModule_AddObjectRef(module, name, _Py_NULL);
    assert(res < 0);
    assert(PyErr_ExceptionMatches(PyExc_SystemError));
    PyErr_Clear();

    Py_DECREF(obj);
    return 0;
}


// test PyModule_Add()
static int
test_module_add(PyObject *module)
{
    const char *name = "test_module_add";
    PyObject *obj = PyUnicode_FromString(name);
    assert(obj != _Py_NULL);
#ifdef CHECK_REFCNT
    Py_ssize_t refcnt = Py_REFCNT(obj);
#endif

    if (PyModule_Add(module, name, Py_NewRef(obj)) < 0) {
        ASSERT_REFCNT(Py_REFCNT(obj) == refcnt);
        Py_DECREF(obj);
        return -1;
    }
    ASSERT_REFCNT(Py_REFCNT(obj) == refcnt + 1);

    if (check_module_attr(module, name, obj) < 0) {
        Py_DECREF(obj);
        return -1;
    }
    ASSERT_REFCNT(Py_REFCNT(obj) == refcnt);

    // PyModule_Add() with value=NULL must not crash
    assert(!PyErr_Occurred());
    int res = PyModule_Add(module, name, _Py_NULL);
    assert(res < 0);
    assert(PyErr_ExceptionMatches(PyExc_SystemError));
    PyErr_Clear();

    Py_DECREF(obj);
    return 0;
}


static PyObject *
test_module(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
{
    PyObject *module = PyImport_ImportModule("sys");
    if (module == _Py_NULL) {
        return _Py_NULL;
    }
    assert(PyModule_Check(module));

    if (test_module_add_type(module) < 0) {
        goto error;
    }
    if (test_module_addobjectref(module) < 0) {
        goto error;
    }
    if (test_module_add(module) < 0) {
        goto error;
    }

    Py_DECREF(module);
    Py_RETURN_NONE;

error:
    Py_DECREF(module);
    return _Py_NULL;
}


#if (PY_VERSION_HEX <= 0x030B00A1 || 0x030B00A7 <= PY_VERSION_HEX) && !defined(PYPY_VERSION)
static PyObject *
test_float_pack(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
{
    const int big_endian = 0;
    const int little_endian = 1;
    char data[8];
    const double d = 1.5;

#if PY_VERSION_HEX >= 0x030600B1
#  define HAVE_FLOAT_PACK2
#endif

    // Test Pack (big endian)
#ifdef HAVE_FLOAT_PACK2
    assert(PyFloat_Pack2(d, data, big_endian) == 0);
    assert(memcmp(data, ">\x00", 2) == 0);
#endif

    assert(PyFloat_Pack4(d, data, big_endian) == 0);
    assert(memcmp(data, "?\xc0\x00\x00", 2) == 0);

    assert(PyFloat_Pack8(d, data, big_endian) == 0);
    assert(memcmp(data, "?\xf8\x00\x00\x00\x00\x00\x00", 2) == 0);

    // Test Pack (little endian)
#ifdef HAVE_FLOAT_PACK2
    assert(PyFloat_Pack2(d, data, little_endian) == 0);
    assert(memcmp(data, "\x00>", 2) == 0);
#endif

    assert(PyFloat_Pack4(d, data, little_endian) == 0);
    assert(memcmp(data, "\x00\x00\xc0?", 2) == 0);

    assert(PyFloat_Pack8(d, data, little_endian) == 0);
    assert(memcmp(data, "\x00\x00\x00\x00\x00\x00\xf8?", 2) == 0);

    // Test Unpack (big endian)
#ifdef HAVE_FLOAT_PACK2
    assert(PyFloat_Unpack2(">\x00", big_endian) == d);
#endif
    assert(PyFloat_Unpack4("?\xc0\x00\x00", big_endian) == d);
    assert(PyFloat_Unpack8("?\xf8\x00\x00\x00\x00\x00\x00", big_endian) == d);

    // Test Unpack (little endian)
#ifdef HAVE_FLOAT_PACK2
    assert(PyFloat_Unpack2("\x00>", little_endian) == d);
#endif
    assert(PyFloat_Unpack4("\x00\x00\xc0?", little_endian) == d);
    assert(PyFloat_Unpack8("\x00\x00\x00\x00\x00\x00\xf8?", little_endian) == d);

    Py_RETURN_NONE;
}
#endif


#if !defined(PYPY_VERSION)
static PyObject *
test_code(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
{
    PyThreadState *tstate = PyThreadState_Get();
    PyFrameObject *frame = PyThreadState_GetFrame(tstate);
    if (frame == _Py_NULL) {
        PyErr_SetString(PyExc_AssertionError, "PyThreadState_GetFrame failed");
        return _Py_NULL;
    }
    PyCodeObject *code = PyFrame_GetCode(frame);

    // PyCode_GetCode()
    {
        PyObject *co_code = PyCode_GetCode(code);
        assert(co_code != _Py_NULL);
        assert(PyBytes_Check(co_code));
        Py_DECREF(co_code);
    }

    // PyCode_GetVarnames
    {
        PyObject *co_varnames = PyCode_GetVarnames(code);
        assert(co_varnames != _Py_NULL);
        assert(PyTuple_CheckExact(co_varnames));
        assert(PyTuple_GET_SIZE(co_varnames) != 0);
        Py_DECREF(co_varnames);
    }

    // PyCode_GetCellvars
    {
        PyObject *co_cellvars = PyCode_GetCellvars(code);
        assert(co_cellvars != _Py_NULL);
        assert(PyTuple_CheckExact(co_cellvars));
        assert(PyTuple_GET_SIZE(co_cellvars) == 0);
        Py_DECREF(co_cellvars);
    }

    // PyCode_GetFreevars
    {
        PyObject *co_freevars = PyCode_GetFreevars(code);
        assert(co_freevars != _Py_NULL);
        assert(PyTuple_CheckExact(co_freevars));
        assert(PyTuple_GET_SIZE(co_freevars) == 0);
        Py_DECREF(co_freevars);
    }

    Py_DECREF(code);
    Py_DECREF(frame);
    Py_RETURN_NONE;
}
#endif


#ifdef __cplusplus
// Class to test operator casting an object to PyObject*
class StrongRef
{
public:
    StrongRef(PyObject *obj) : m_obj(obj) {
        Py_INCREF(this->m_obj);
    }

    ~StrongRef() {
        Py_DECREF(this->m_obj);
    }

    // Cast to PyObject*: get a borrowed reference
    inline operator PyObject*() const { return this->m_obj; }

private:
    PyObject *m_obj;  // Strong reference
};
#endif


static PyObject *
test_api_casts(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
    PyObject *obj = Py_BuildValue("(ii)", 1, 2);
    if (obj == _Py_NULL) {
        return _Py_NULL;
    }
    Py_ssize_t refcnt = Py_REFCNT(obj);
    assert(refcnt >= 1);

    // gh-92138: For backward compatibility, functions of Python C API accepts
    // "const PyObject*". Check that using it does not emit C++ compiler
    // warnings.
    const PyObject *const_obj = obj;
    Py_INCREF(const_obj);
    Py_DECREF(const_obj);
    PyTypeObject *type = Py_TYPE(const_obj);
    assert(Py_REFCNT(const_obj) == refcnt);
    assert(type == &PyTuple_Type);
    assert(PyTuple_GET_SIZE(const_obj) == 2);
    PyObject *one = PyTuple_GET_ITEM(const_obj, 0);
    assert(PyLong_AsLong(one) == 1);

#ifdef __cplusplus
    // gh-92898: StrongRef doesn't inherit from PyObject but has an operator to
    // cast to PyObject*.
    StrongRef strong_ref(obj);
    assert(Py_TYPE(strong_ref) == &PyTuple_Type);
    assert(Py_REFCNT(strong_ref) == (refcnt + 1));
    Py_INCREF(strong_ref);
    Py_DECREF(strong_ref);
#endif

    // gh-93442: Pass 0 as NULL for PyObject*
    Py_XINCREF(0);
    Py_XDECREF(0);
#if _cplusplus >= 201103
    // Test nullptr passed as PyObject*
    Py_XINCREF(nullptr);
    Py_XDECREF(nullptr);
#endif

    Py_DECREF(obj);
    Py_RETURN_NONE;
}


static PyObject *
test_import(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
    PyObject *mod = PyImport_ImportModule("sys");
    if (mod == _Py_NULL) {
        return _Py_NULL;
    }
    Py_ssize_t refcnt = Py_REFCNT(mod);

    // test PyImport_AddModuleRef()
    PyObject *mod2 = PyImport_AddModuleRef("sys");
    if (mod2 == _Py_NULL) {
        return _Py_NULL;
    }
    assert(PyModule_Check(mod2));
    assert(Py_REFCNT(mod) == (refcnt + 1));

    Py_DECREF(mod2);
    Py_DECREF(mod);

    Py_RETURN_NONE;
}


static void
gc_collect(void)
{
#if defined(PYPY_VERSION)
    PyObject *mod = PyImport_ImportModule("gc");
    assert(mod != _Py_NULL);

    PyObject *res = PyObject_CallMethod(mod, "collect", _Py_NULL);
    Py_DECREF(mod);
    assert(res != _Py_NULL);
    Py_DECREF(res);
#else
    PyGC_Collect();
#endif
}


static PyObject *
func_varargs(PyObject *Py_UNUSED(module), PyObject *args, PyObject *kwargs)
{
    if (kwargs != _Py_NULL) {
        return PyTuple_Pack(2, args, kwargs);
    }
    else {
        return PyTuple_Pack(1, args);
    }
}


static void
check_int(PyObject *obj, int value)
{
#ifdef PYTHON3
    assert(PyLong_Check(obj));
    assert(PyLong_AsLong(obj) == value);
#else
    assert(PyInt_Check(obj));
    assert(PyInt_AsLong(obj) == value);
#endif
}


static PyObject *
test_weakref(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
    // Create a new heap type, create an instance of this type, and delete the
    // type. This object supports weak references.
    PyObject *new_type = PyObject_CallFunction((PyObject*)&PyType_Type,
                                               "s(){}", "TypeName");
    if (new_type == _Py_NULL) {
        return _Py_NULL;
    }
    PyObject *obj = PyObject_CallNoArgs(new_type);
    Py_DECREF(new_type);
    if (obj == _Py_NULL) {
        return _Py_NULL;
    }
    Py_ssize_t refcnt = Py_REFCNT(obj);

    // create a weak reference
    PyObject *weakref = PyWeakref_NewRef(obj, _Py_NULL);
    if (weakref == _Py_NULL) {
        return _Py_NULL;
    }

    // test PyWeakref_GetRef(), reference is alive
    PyObject *ref = UNINITIALIZED_OBJ;
    assert(PyWeakref_GetRef(weakref, &ref) == 1);
    assert(ref == obj);
    assert(Py_REFCNT(obj) == (refcnt + 1));
    Py_DECREF(ref);

    // delete the referenced object: clear the weakref
    Py_DECREF(obj);
    gc_collect();

    // test PyWeakref_GetRef(), reference is dead
    ref = Py_True;
    assert(PyWeakref_GetRef(weakref, &ref) == 0);
    assert(ref == _Py_NULL);

    // test PyWeakref_GetRef(), invalid type
    PyObject *invalid_weakref = Py_None;
    assert(!PyErr_Occurred());
    ref = Py_True;
    assert(PyWeakref_GetRef(invalid_weakref, &ref) == -1);
    assert(PyErr_ExceptionMatches(PyExc_TypeError));
    assert(ref == _Py_NULL);
    PyErr_Clear();

#ifndef PYPY_VERSION
    // test PyWeakref_GetRef(NULL)
    ref = Py_True;
    assert(PyWeakref_GetRef(_Py_NULL, &ref) == -1);
    assert(PyErr_ExceptionMatches(PyExc_SystemError));
    assert(ref == _Py_NULL);
    PyErr_Clear();
#endif

    Py_DECREF(weakref);
    Py_RETURN_NONE;
}


static void
test_vectorcall_noargs(PyObject *func_varargs)
{
    PyObject *res = PyObject_Vectorcall(func_varargs, _Py_NULL, 0, _Py_NULL);
    assert(res != _Py_NULL);

    assert(PyTuple_Check(res));
    assert(PyTuple_GET_SIZE(res) == 1);
    PyObject *posargs = PyTuple_GET_ITEM(res, 0);

    assert(PyTuple_Check(posargs));
    assert(PyTuple_GET_SIZE(posargs) == 0);

    Py_DECREF(res);
}


static void
test_vectorcall_args(PyObject *func_varargs)
{
    PyObject *args_tuple = Py_BuildValue("ii", 1, 2);
    assert(args_tuple != _Py_NULL);
    size_t nargs = (size_t)PyTuple_GET_SIZE(args_tuple);
    PyObject **args = &PyTuple_GET_ITEM(args_tuple, 0);

    PyObject *res = PyObject_Vectorcall(func_varargs, args, nargs, _Py_NULL);
    Py_DECREF(args_tuple);
    assert(res != _Py_NULL);

    assert(PyTuple_Check(res));
    assert(PyTuple_GET_SIZE(res) == 1);
    PyObject *posargs = PyTuple_GET_ITEM(res, 0);

    assert(PyTuple_Check(posargs));
    assert(PyTuple_GET_SIZE(posargs) == 2);
    check_int(PyTuple_GET_ITEM(posargs, 0), 1);
    check_int(PyTuple_GET_ITEM(posargs, 1), 2);

    Py_DECREF(res);
}


static void
test_vectorcall_args_offset(PyObject *func_varargs)
{
    // args contains 3 values, but only pass 2 last values
    PyObject *args_tuple = Py_BuildValue("iii", 1, 2, 3);
    assert(args_tuple != _Py_NULL);
    size_t nargs = 2 | PY_VECTORCALL_ARGUMENTS_OFFSET;
    PyObject **args = &PyTuple_GET_ITEM(args_tuple, 1);
    PyObject *arg0 = PyTuple_GET_ITEM(args_tuple, 0);

    PyObject *res = PyObject_Vectorcall(func_varargs, args, nargs, _Py_NULL);
    assert(PyTuple_GET_ITEM(args_tuple, 0) == arg0);
    Py_DECREF(args_tuple);
    assert(res != _Py_NULL);

    assert(PyTuple_Check(res));
    assert(PyTuple_GET_SIZE(res) == 1);
    PyObject *posargs = PyTuple_GET_ITEM(res, 0);

    assert(PyTuple_Check(posargs));
    assert(PyTuple_GET_SIZE(posargs) == 2);
    check_int(PyTuple_GET_ITEM(posargs, 0), 2);
    check_int(PyTuple_GET_ITEM(posargs, 1), 3);

    Py_DECREF(res);
}


static void
test_vectorcall_args_kwnames(PyObject *func_varargs)
{
    PyObject *args_tuple = Py_BuildValue("iiiii", 1, 2, 3, 4, 5);
    assert(args_tuple != _Py_NULL);
    PyObject **args = &PyTuple_GET_ITEM(args_tuple, 0);

#ifdef PYTHON3
    PyObject *key1 = PyUnicode_FromString("key1");
    PyObject *key2 = PyUnicode_FromString("key2");
#else
    PyObject *key1 = PyString_FromString("key1");
    PyObject *key2 = PyString_FromString("key2");
#endif
    assert(key1 != _Py_NULL);
    assert(key2 != _Py_NULL);
    PyObject *kwnames = PyTuple_Pack(2, key1, key2);
    assert(kwnames != _Py_NULL);
    size_t nargs = (size_t)(PyTuple_GET_SIZE(args_tuple) - PyTuple_GET_SIZE(kwnames));

    PyObject *res = PyObject_Vectorcall(func_varargs, args, nargs, kwnames);
    Py_DECREF(args_tuple);
    Py_DECREF(kwnames);
    assert(res != _Py_NULL);

    assert(PyTuple_Check(res));
    assert(PyTuple_GET_SIZE(res) == 2);
    PyObject *posargs = PyTuple_GET_ITEM(res, 0);
    PyObject *kwargs = PyTuple_GET_ITEM(res, 1);

    assert(PyTuple_Check(posargs));
    assert(PyTuple_GET_SIZE(posargs) == 3);
    check_int(PyTuple_GET_ITEM(posargs, 0), 1);
    check_int(PyTuple_GET_ITEM(posargs, 1), 2);
    check_int(PyTuple_GET_ITEM(posargs, 2), 3);

    assert(PyDict_Check(kwargs));
    assert(PyDict_Size(kwargs) == 2);

    Py_ssize_t pos = 0;
    PyObject *key, *value;
    while (PyDict_Next(kwargs, &pos, &key, &value)) {
#ifdef PYTHON3
        assert(PyUnicode_Check(key));
#else
        assert(PyString_Check(key));
#endif
        if (PyObject_RichCompareBool(key, key1, Py_EQ)) {
            check_int(value, 4);
        }
        else {
            assert(PyObject_RichCompareBool(key, key2, Py_EQ));
            check_int(value, 5);
        }
    }

    Py_DECREF(res);
    Py_DECREF(key1);
    Py_DECREF(key2);
}


static PyObject *
test_vectorcall(PyObject *module, PyObject *Py_UNUSED(args))
{
#ifndef PYTHON3
    module = PyImport_ImportModule(MODULE_NAME_STR);
    assert(module != _Py_NULL);
#endif
    PyObject *func_varargs = PyObject_GetAttrString(module, "func_varargs");
#ifndef PYTHON3
    Py_DECREF(module);
#endif
    if (func_varargs == _Py_NULL) {
        return _Py_NULL;
    }

    // test PyObject_Vectorcall()
    test_vectorcall_noargs(func_varargs);
    test_vectorcall_args(func_varargs);
    test_vectorcall_args_offset(func_varargs);
    test_vectorcall_args_kwnames(func_varargs);

    Py_DECREF(func_varargs);
    Py_RETURN_NONE;
}


static PyObject *
test_getattr(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
    assert(!PyErr_Occurred());

    PyObject *obj = PyImport_ImportModule("sys");
    if (obj == _Py_NULL) {
        return _Py_NULL;
    }

    PyObject *attr_name = create_string("version");
    PyObject *missing_attr = create_string("nonexistant_attr_name");

    // test PyObject_GetOptionalAttr(): attribute exists
    PyObject *value;
    value = UNINITIALIZED_OBJ;
    assert(PyObject_GetOptionalAttr(obj, attr_name, &value) == 1);
    assert(value != _Py_NULL);
    Py_DECREF(value);

    // test PyObject_HasAttrWithError(): attribute exists
    assert(PyObject_HasAttrWithError(obj, attr_name) == 1);

    // test PyObject_GetOptionalAttrString(): attribute exists
    value = UNINITIALIZED_OBJ;
    assert(PyObject_GetOptionalAttrString(obj, "version", &value) == 1);
    assert(!PyErr_Occurred());
    assert(value != _Py_NULL);
    Py_DECREF(value);

    // test PyObject_HasAttrStringWithError(): attribute exists
    assert(PyObject_HasAttrStringWithError(obj, "version") == 1);
    assert(!PyErr_Occurred());

    // test PyObject_GetOptionalAttr(): attribute doesn't exist
    value = UNINITIALIZED_OBJ;
    assert(PyObject_GetOptionalAttr(obj, missing_attr, &value) == 0);
    assert(!PyErr_Occurred());
    assert(value == _Py_NULL);

    // test PyObject_HasAttrWithError(): attribute doesn't exist
    assert(PyObject_HasAttrWithError(obj, missing_attr) == 0);
    assert(!PyErr_Occurred());

    // test PyObject_GetOptionalAttrString(): attribute doesn't exist
    value = UNINITIALIZED_OBJ;
    assert(PyObject_GetOptionalAttrString(obj, "nonexistant_attr_name", &value) == 0);
    assert(!PyErr_Occurred());
    assert(value == _Py_NULL);

    // test PyObject_HasAttrStringWithError(): attribute doesn't exist
    assert(PyObject_HasAttrStringWithError(obj, "nonexistant_attr_name") == 0);
    assert(!PyErr_Occurred());

    Py_DECREF(attr_name);
    Py_DECREF(missing_attr);
    Py_DECREF(obj);
    Py_RETURN_NONE;
}


static PyObject *
test_getitem(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
    assert(!PyErr_Occurred());

    PyObject *value = Py_BuildValue("s", "value");
    assert(value != _Py_NULL);
    PyObject *obj = Py_BuildValue("{sO}", "key", value);
    assert(obj != _Py_NULL);
    PyObject *present_key, *missing_key;
    PyObject *item;

    present_key = create_string("key");
    missing_key = create_string("dontexist");

    // test PyMapping_GetOptionalItem(): key is present
    item = UNINITIALIZED_OBJ;
    assert(PyMapping_GetOptionalItem(obj, present_key, &item) == 1);
    assert(item == value);
    Py_DECREF(item);
    assert(!PyErr_Occurred());

    // test PyMapping_HasKeyWithError(): key is present
    assert(PyMapping_HasKeyWithError(obj, present_key) == 1);
    assert(!PyErr_Occurred());

    // test PyMapping_GetOptionalItemString(): key is present
    item = UNINITIALIZED_OBJ;
    assert(PyMapping_GetOptionalItemString(obj, "key", &item) == 1);
    assert(item == value);
    Py_DECREF(item);

    // test PyMapping_HasKeyStringWithError(): key is present
    assert(PyMapping_HasKeyStringWithError(obj, "key") == 1);
    assert(!PyErr_Occurred());

    // test PyMapping_GetOptionalItem(): missing key
    item = UNINITIALIZED_OBJ;
    assert(PyMapping_GetOptionalItem(obj, missing_key, &item) == 0);
    assert(item == _Py_NULL);
    assert(!PyErr_Occurred());

    // test PyMapping_HasKeyWithError(): missing key
    assert(PyMapping_HasKeyWithError(obj, missing_key) == 0);
    assert(!PyErr_Occurred());

    // test PyMapping_GetOptionalItemString(): missing key
    item = UNINITIALIZED_OBJ;
    assert(PyMapping_GetOptionalItemString(obj, "dontexist", &item) == 0);
    assert(item == _Py_NULL);

    // test PyMapping_HasKeyStringWithError(): missing key
    assert(PyMapping_HasKeyStringWithError(obj, "dontexist") == 0);
    assert(!PyErr_Occurred());

    Py_DECREF(obj);
    Py_DECREF(value);
    Py_DECREF(present_key);
    Py_DECREF(missing_key);
    Py_RETURN_NONE;
}


static PyObject *
test_dict_api(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
    assert(!PyErr_Occurred());

    PyObject *dict = NULL, *key = NULL, *missing_key = NULL, *value = NULL;
    PyObject *invalid_key = NULL;
    PyObject *invalid_dict = NULL;
    PyObject *get_value = NULL;
    int res;

    // test PyDict_New()
    dict = PyDict_New();
    if (dict == NULL) {
        goto error;
    }

    key = PyUnicode_FromString("key");
    if (key == NULL) {
        goto error;
    }
    invalid_dict = key;  // borrowed reference

    missing_key = PyUnicode_FromString("missing_key");
    if (missing_key == NULL) {
        goto error;
    }

    invalid_key = PyList_New(0);  // not hashable key
    if (invalid_key == NULL) {
        goto error;
    }

    value = PyUnicode_FromString("value");
    if (value == NULL) {
        goto error;
    }

    res = PyDict_SetItemString(dict, "key", value);
    if (res < 0) {
        goto error;
    }
    assert(res == 0);

    // test PyDict_Contains()
    assert(PyDict_Contains(dict, key) == 1);
    assert(PyDict_Contains(dict, missing_key) == 0);

    // test PyDict_ContainsString()
    assert(PyDict_ContainsString(dict, "key") == 1);
    assert(PyDict_ContainsString(dict, "missing_key") == 0);
    assert(PyDict_ContainsString(dict, "\xff") == -1);
    assert(PyErr_ExceptionMatches(PyExc_UnicodeDecodeError));
    PyErr_Clear();

    // test PyDict_GetItemRef(), key is present
    get_value = UNINITIALIZED_OBJ;
    assert(PyDict_GetItemRef(dict, key, &get_value) == 1);
    assert(get_value == value);
    Py_DECREF(get_value);

    // test PyDict_GetItemStringRef(), key is present
    get_value = UNINITIALIZED_OBJ;
    assert(PyDict_GetItemStringRef(dict, "key", &get_value) == 1);
    assert(get_value == value);
    Py_DECREF(get_value);

    // test PyDict_GetItemRef(), missing key
    get_value = UNINITIALIZED_OBJ;
    assert(PyDict_GetItemRef(dict, missing_key, &get_value) == 0);
    assert(!PyErr_Occurred());
    assert(get_value == NULL);

    // test PyDict_GetItemStringRef(), missing key
    get_value = UNINITIALIZED_OBJ;
    assert(PyDict_GetItemStringRef(dict, "missing_key", &get_value) == 0);
    assert(!PyErr_Occurred());
    assert(get_value == NULL);

    // test PyDict_GetItemRef(), invalid dict
    get_value = UNINITIALIZED_OBJ;
    assert(PyDict_GetItemRef(invalid_dict, key, &get_value) == -1);
    assert(PyErr_ExceptionMatches(PyExc_SystemError));
    PyErr_Clear();
    assert(get_value == NULL);

    // test PyDict_GetItemStringRef(), invalid dict
    get_value = UNINITIALIZED_OBJ;
    assert(PyDict_GetItemStringRef(invalid_dict, "key", &get_value) == -1);
    assert(PyErr_ExceptionMatches(PyExc_SystemError));
    PyErr_Clear();
    assert(get_value == NULL);

    // test PyDict_GetItemRef(), invalid key
    get_value = UNINITIALIZED_OBJ;
    assert(PyDict_GetItemRef(dict, invalid_key, &get_value) == -1);
    assert(PyErr_ExceptionMatches(PyExc_TypeError));
    PyErr_Clear();
    assert(get_value == NULL);

    Py_DECREF(dict);
    Py_DECREF(key);
    Py_DECREF(missing_key);
    Py_DECREF(value);
    Py_DECREF(invalid_key);

    Py_RETURN_NONE;

error:
    Py_XDECREF(dict);
    Py_XDECREF(key);
    Py_XDECREF(missing_key);
    Py_XDECREF(value);
    Py_XDECREF(invalid_key);
    return NULL;
}


static PyObject *
test_dict_pop(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
    PyObject *dict = PyDict_New();
    if (dict == NULL) {
        return NULL;
    }

    PyObject *key = PyUnicode_FromString("key");
    assert(key != NULL);
    PyObject *value = PyUnicode_FromString("abc");
    assert(value != NULL);

    // test PyDict_Pop(), get the removed value, key is present
    assert(PyDict_SetItem(dict, key, value) == 0);
    PyObject *removed = UNINITIALIZED_OBJ;
    assert(PyDict_Pop(dict, key, &removed) == 1);
    assert(removed == value);
    Py_DECREF(removed);

    // test PyDict_Pop(), ignore the removed value, key is present
    assert(PyDict_SetItem(dict, key, value) == 0);
    assert(PyDict_Pop(dict, key, NULL) == 1);

    // test PyDict_Pop(), key is missing
    removed = UNINITIALIZED_OBJ;
    assert(PyDict_Pop(dict, key, &removed) == 0);
    assert(removed == NULL);
    assert(PyDict_Pop(dict, key, NULL) == 0);

    // test PyDict_PopString(), get the removed value, key is present
    assert(PyDict_SetItem(dict, key, value) == 0);
    removed = UNINITIALIZED_OBJ;
    assert(PyDict_PopString(dict, "key", &removed) == 1);
    assert(removed == value);
    Py_DECREF(removed);

    // test PyDict_PopString(), ignore the removed value, key is present
    assert(PyDict_SetItem(dict, key, value) == 0);
    assert(PyDict_PopString(dict, "key", NULL) == 1);

    // test PyDict_PopString(), key is missing
    removed = UNINITIALIZED_OBJ;
    assert(PyDict_PopString(dict, "key", &removed) == 0);
    assert(removed == NULL);
    assert(PyDict_PopString(dict, "key", NULL) == 0);

    // dict error
    removed = UNINITIALIZED_OBJ;
    assert(PyDict_Pop(key, key, &removed) == -1);
    assert(removed == NULL);
    assert(PyErr_ExceptionMatches(PyExc_SystemError));
    PyErr_Clear();

    assert(PyDict_Pop(key, key, NULL) == -1);
    assert(PyErr_ExceptionMatches(PyExc_SystemError));
    PyErr_Clear();

    removed = UNINITIALIZED_OBJ;
    assert(PyDict_PopString(key, "key", &removed) == -1);
    assert(removed == NULL);
    assert(PyErr_ExceptionMatches(PyExc_SystemError));
    PyErr_Clear();

    assert(PyDict_PopString(key, "key", NULL) == -1);
    assert(PyErr_ExceptionMatches(PyExc_SystemError));
    PyErr_Clear();

    // exit
    Py_DECREF(dict);
    Py_DECREF(key);
    Py_DECREF(value);
    Py_RETURN_NONE;
}


static PyObject *
test_dict_setdefault(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
    PyObject *dict = PyDict_New();
    if (dict == NULL) {
        return NULL;
    }
    PyObject *key = PyUnicode_FromString("key");
    assert(key != NULL);
    PyObject *value = PyUnicode_FromString("abc");
    assert(value != NULL);
    PyObject *invalid_key = PyList_New(0);  // not hashable key
    assert(invalid_key != NULL);

    // insert item
    PyObject *result = UNINITIALIZED_OBJ;
    assert(PyDict_SetDefaultRef(dict, key, value, &result) == 0);
    assert(result == value);
    Py_DECREF(result);

    // item already present
    result = UNINITIALIZED_OBJ;
    assert(PyDict_SetDefaultRef(dict, key, value, &result) == 1);
    assert(result == value);
    Py_DECREF(result);

    // error: invalid key
    assert(!PyErr_Occurred());
    result = UNINITIALIZED_OBJ;
    assert(PyDict_SetDefaultRef(dict, invalid_key, value, &result) == -1);
    assert(result == NULL);
    assert(PyErr_Occurred());
    PyErr_Clear();

    // insert item with NULL result
    assert(PyDict_Pop(dict, key, NULL) == 1);
    assert(PyDict_SetDefaultRef(dict, key, value, NULL) == 0);

    // item already present with NULL result
    assert(PyDict_SetDefaultRef(dict, key, value, NULL) == 1);

    // error: invalid key with NULL result
    assert(!PyErr_Occurred());
    assert(PyDict_SetDefaultRef(dict, invalid_key, value, NULL) == -1);
    assert(PyErr_Occurred());
    PyErr_Clear();

    // exit
    Py_DECREF(dict);
    Py_DECREF(key);
    Py_DECREF(value);
    Py_DECREF(invalid_key);
    Py_RETURN_NONE;
}


static PyObject *
test_long_api(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
    // test PyLong_AsInt()
    assert(!PyErr_Occurred());
    PyObject *obj = PyLong_FromLong(123);
    if (obj == NULL) {
        return NULL;
    }
    int value = PyLong_AsInt(obj);
    assert(value == 123);
    assert(!PyErr_Occurred());
    Py_DECREF(obj);

    // test PyLong_AsInt() with overflow
    PyObject *obj2 = PyLong_FromLongLong((long long)INT_MAX + 1);
    if (obj2 == NULL) {
        return NULL;
    }
    value = PyLong_AsInt(obj2);
    assert(value == -1);
    assert(PyErr_ExceptionMatches(PyExc_OverflowError));
    PyErr_Clear();
    Py_DECREF(obj2);

    // test PyLong_GetSign()
    int sign = UNINITIALIZED_INT;
    assert(PyLong_GetSign(obj, &sign) == 0);
    assert(sign == 1);

    Py_RETURN_NONE;
}


// --- HeapCTypeWithManagedDict --------------------------------------------

// Py_TPFLAGS_MANAGED_DICT was added to Python 3.11.0a3
#if PY_VERSION_HEX >= 0x030B00A3
#  define TEST_MANAGED_DICT

typedef struct {
    PyObject_HEAD
} HeapCTypeObject;

static int
heapmanaged_traverse(PyObject *self, visitproc visit, void *arg)
{
    Py_VISIT(Py_TYPE(self));
    return PyObject_VisitManagedDict(self, visit, arg);
}

static int
heapmanaged_clear(PyObject *self)
{
    PyObject_ClearManagedDict(self);
    return 0;
}

static void
heapmanaged_dealloc(HeapCTypeObject *self)
{
    PyTypeObject *tp = Py_TYPE(self);
    PyObject_ClearManagedDict((PyObject *)self);
    PyObject_GC_UnTrack(self);
    PyObject_GC_Del(self);
    Py_DECREF(tp);
}

static PyType_Slot HeapCTypeWithManagedDict_slots[] = {
    {Py_tp_traverse, _Py_CAST(void*, heapmanaged_traverse)},
    {Py_tp_clear, _Py_CAST(void*, heapmanaged_clear)},
    {Py_tp_dealloc, _Py_CAST(void*, heapmanaged_dealloc)},
    {0, 0},
};

static PyType_Spec HeapCTypeWithManagedDict_spec = {
    "test_pythoncapi_compat.HeapCTypeWithManagedDict",
    sizeof(PyObject),
    0,
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_MANAGED_DICT,
    HeapCTypeWithManagedDict_slots
};

static PyObject *
test_managed_dict(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
    PyObject *type = PyType_FromSpec(&HeapCTypeWithManagedDict_spec);
    if (type == NULL) {
        return NULL;
    }

    PyObject *obj = PyObject_CallNoArgs(type);
    if (obj == NULL) {
        Py_DECREF(type);
        return NULL;
    }

    // call heapmanaged_traverse()
    PyGC_Collect();

    // call heapmanaged_clear()
    Py_DECREF(obj);
    PyGC_Collect();

    Py_DECREF(type);
    // Just in case!
    PyGC_Collect();

    Py_RETURN_NONE;
}
#endif  // PY_VERSION_HEX >= 0x030B00A3


static PyObject *
test_unicode(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
    PyObject *abc = PyUnicode_FromString("abc");
    if (abc == NULL) {
        return NULL;
    }

    PyObject *abc0def = PyUnicode_FromStringAndSize("abc\0def", 7);
    if (abc0def == NULL) {
        Py_DECREF(abc);
        return NULL;
    }

    // PyUnicode_EqualToUTF8() and PyUnicode_EqualToUTF8AndSize() can be called
    // with an exception raised and they must not clear the current exception.
    PyErr_NoMemory();

    assert(PyUnicode_EqualToUTF8AndSize(abc, "abc", 3) == 1);
    assert(PyUnicode_EqualToUTF8AndSize(abc, "Python", 6) == 0);
    assert(PyUnicode_EqualToUTF8AndSize(abc0def, "abc\0def", 7) == 1);

    assert(PyUnicode_EqualToUTF8(abc, "abc") == 1);
    assert(PyUnicode_EqualToUTF8(abc, "Python") == 0);
    assert(PyUnicode_EqualToUTF8(abc0def, "abc\0def") == 0);

    assert(PyErr_ExceptionMatches(PyExc_MemoryError));
    PyErr_Clear();

    Py_DECREF(abc);
    Py_DECREF(abc0def);
    Py_RETURN_NONE;
}


static PyObject *
test_list(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
    PyObject *list = PyList_New(0);
    if (list == NULL) {
        return NULL;
    }

    // test PyList_Extend()
    {
        PyObject *abc = PyUnicode_FromString("abc");
        if (abc == NULL) {
            Py_DECREF(list);
            return NULL;
        }

        assert(PyList_Extend(list, abc) == 0);
        Py_DECREF(abc);
        assert(PyList_GET_SIZE(list) == 3);
    }

    // test PyList_GetItemRef()
    PyObject *item = PyList_GetItemRef(list, 1);
    assert(item != NULL);
    assert(item == PyList_GetItem(list, 1));
    Py_DECREF(item);

    // test PyList_Clear()
    assert(PyList_Clear(list) == 0);
    assert(PyList_GET_SIZE(list) == 0);

    Py_DECREF(list);
    Py_RETURN_NONE;
}


static PyObject *
test_hash(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
    void *ptr0 = NULL;
    assert(Py_HashPointer(ptr0) == 0);

#ifndef PYPY_VERSION
#if SIZEOF_VOID_P == 8
    void *ptr1 = (void*)(uintptr_t)0xABCDEF1234567890;
    assert(Py_HashPointer(ptr1) == (uintptr_t)0x0ABCDEF123456789);
#else
    void *ptr1 = (void*)(uintptr_t)0xDEADCAFE;
    assert(Py_HashPointer(ptr1) == (uintptr_t)0xEDEADCAF);
#endif
#else
    // PyPy
#if SIZEOF_VOID_P == 8
    void *ptr1 = (void*)(uintptr_t)0xABCDEF1234567890;
#else
    void *ptr1 = (void*)(uintptr_t)0xDEADCAFE;
#endif
    assert(Py_HashPointer(ptr1) == (Py_hash_t)ptr1);
#endif

#if ((!defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x030400B1) \
     || (defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x03070000 \
         && PYPY_VERSION_NUM >= 0x07090000))
    // Just check that constants are available
    size_t bits = PyHASH_BITS;
    assert(bits >= 8);
    size_t mod = PyHASH_MODULUS;
    assert(mod >= 7);
    size_t inf = PyHASH_INF;
    assert(inf != 0);
    size_t imag = PyHASH_IMAG;
    assert(imag != 0);
#endif

    Py_RETURN_NONE;
}


#if PY_VERSION_HEX  >= 0x03050000
#define TEST_PYTIME

static PyObject *
test_time(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
    PyTime_t t;
#define UNINITIALIZED_TIME ((PyTime_t)-483884113929936179)

    t = UNINITIALIZED_TIME;
    assert(PyTime_Time(&t) == 0);
    assert(t != UNINITIALIZED_TIME);

    t = UNINITIALIZED_TIME;
    assert(PyTime_Monotonic(&t) == 0);
    assert(t != UNINITIALIZED_TIME);

    // Test multiple times since an implementation uses a cache
    for (int i=0; i < 5; i++) {
        t = UNINITIALIZED_TIME;
        assert(PyTime_PerfCounter(&t) == 0);
        assert(t != UNINITIALIZED_TIME);
    }

    assert(PyTime_AsSecondsDouble(1) == 1e-9);
    assert(PyTime_AsSecondsDouble(1500 * 1000 * 1000) == 1.5);
    assert(PyTime_AsSecondsDouble(-500 * 1000 * 1000) == -0.5);

    Py_RETURN_NONE;
}
#endif


static void
check_get_constant(PyObject* (*get_constant)(unsigned int), int borrowed)
{
#define CLEAR(var) if (!borrowed) { Py_DECREF(var); }

    PyObject *obj, *expected;

    // Py_CONSTANT_NONE
    obj = get_constant(Py_CONSTANT_NONE);
    assert(obj == Py_None);
    CLEAR(obj);

    // Py_CONSTANT_FALSE
    obj = get_constant(Py_CONSTANT_FALSE);
    assert(obj = Py_False);
    CLEAR(obj);

    // Py_CONSTANT_TRUE
    obj = get_constant(Py_CONSTANT_TRUE);
    assert(obj == Py_True);
    CLEAR(obj);

    // Py_CONSTANT_ELLIPSIS
    obj = get_constant(Py_CONSTANT_ELLIPSIS);
    assert(obj == Py_Ellipsis);
    CLEAR(obj);

    // Py_CONSTANT_NOT_IMPLEMENTED
    obj = get_constant(Py_CONSTANT_NOT_IMPLEMENTED);
    assert(obj == Py_NotImplemented);
    CLEAR(obj);

    // Py_CONSTANT_ZERO
    obj = get_constant(Py_CONSTANT_ZERO);
    expected = PyLong_FromLong(0);
    assert(expected != NULL);
    assert(Py_TYPE(obj) == &PyLong_Type);
    assert(PyObject_RichCompareBool(obj, expected, Py_EQ) == 1);
    CLEAR(obj);
    Py_DECREF(expected);

    // Py_CONSTANT_ONE
    obj = get_constant(Py_CONSTANT_ONE);
    expected = PyLong_FromLong(1);
    assert(expected != NULL);
    assert(Py_TYPE(obj) == &PyLong_Type);
    assert(PyObject_RichCompareBool(obj, expected, Py_EQ) == 1);
    CLEAR(obj);
    Py_DECREF(expected);

    // Py_CONSTANT_EMPTY_STR
    obj = get_constant(Py_CONSTANT_EMPTY_STR);
    assert(Py_TYPE(obj) == &PyUnicode_Type);
#if PY_VERSION_HEX >= 0x03030000
    assert(PyUnicode_GetLength(obj) == 0);
#else
    assert(PyUnicode_GetSize(obj) == 0);
#endif
    CLEAR(obj);

    // Py_CONSTANT_EMPTY_BYTES
    obj = get_constant(Py_CONSTANT_EMPTY_BYTES);
    assert(Py_TYPE(obj) == &PyBytes_Type);
    assert(PyBytes_Size(obj) == 0);
    CLEAR(obj);

    // Py_CONSTANT_EMPTY_TUPLE
    obj = get_constant(Py_CONSTANT_EMPTY_TUPLE);
    assert(Py_TYPE(obj) == &PyTuple_Type);
    assert(PyTuple_Size(obj) == 0);
    CLEAR(obj);

#undef CLEAR
}


static PyObject *
test_get_constant(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
    check_get_constant(Py_GetConstant, 0);
    check_get_constant(Py_GetConstantBorrowed, 1);
    Py_RETURN_NONE;
}


#if PY_VERSION_HEX < 0x030E0000 && PY_VERSION_HEX >= 0x03060000 && !defined(PYPY_VERSION)
#define TEST_UNICODEWRITER 1

static PyObject *
test_unicodewriter(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
{
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
    if (writer == NULL) {
        return NULL;
    }
    int ret;

    // test PyUnicodeWriter_WriteStr()
    PyObject *str = PyUnicode_FromString("var");
    if (str == NULL) {
        goto error;
    }
    ret = PyUnicodeWriter_WriteStr(writer, str);
    Py_CLEAR(str);
    if (ret < 0) {
        goto error;
    }

    // test PyUnicodeWriter_WriteChar()
    if (PyUnicodeWriter_WriteChar(writer, '=') < 0) {
        goto error;
    }

    // test PyUnicodeWriter_WriteSubstring()
    str = PyUnicode_FromString("[long]");
    if (str == NULL) {
        goto error;
    }
    ret = PyUnicodeWriter_WriteSubstring(writer, str, 1, 5);
    Py_CLEAR(str);
    if (ret < 0) {
        goto error;
    }

    // test PyUnicodeWriter_WriteUTF8()
    if (PyUnicodeWriter_WriteUTF8(writer, " valu\xC3\xA9", -1) < 0) {
        goto error;
    }
    if (PyUnicodeWriter_WriteChar(writer, ' ') < 0) {
        goto error;
    }

    // test PyUnicodeWriter_WriteRepr()
    str = PyUnicode_FromString("repr");
    if (str == NULL) {
        goto error;
    }
    if (PyUnicodeWriter_WriteRepr(writer, str) < 0) {
        goto error;
    }
    Py_CLEAR(str);

    {
        PyObject *result = PyUnicodeWriter_Finish(writer);
        if (result == NULL) {
            return NULL;
        }
        assert(PyUnicode_EqualToUTF8(result, "var=long valu\xC3\xA9 'repr'"));
        Py_DECREF(result);
    }

    Py_RETURN_NONE;

error:
    PyUnicodeWriter_Discard(writer);
    return NULL;
}


static PyObject *
test_unicodewriter_widechar(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
{
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
    if (writer == NULL) {
        return NULL;
    }

    // test PyUnicodeWriter_WriteWideChar()
    int ret = PyUnicodeWriter_WriteWideChar(writer, L"euro=\u20AC", -1);
    if (ret < 0) {
        goto error;
    }

    {
        PyObject *result = PyUnicodeWriter_Finish(writer);
        if (result == NULL) {
            return NULL;
        }
        assert(PyUnicode_EqualToUTF8(result, "euro=\xe2\x82\xac"));
        Py_DECREF(result);
    }

    Py_RETURN_NONE;

error:
    PyUnicodeWriter_Discard(writer);
    return NULL;
}


static PyObject *
test_unicodewriter_format(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
{
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
    if (writer == NULL) {
        return NULL;
    }

    // test PyUnicodeWriter_Format()
    if (PyUnicodeWriter_Format(writer, "%s %i", "Hello", 123) < 0) {
        goto error;
    }

    // test PyUnicodeWriter_WriteChar()
    if (PyUnicodeWriter_WriteChar(writer, '.') < 0) {
        goto error;
    }

    {
        PyObject *result = PyUnicodeWriter_Finish(writer);
        if (result == NULL) {
            return NULL;
        }
        assert(PyUnicode_EqualToUTF8(result, "Hello 123."));
        Py_DECREF(result);
    }

    Py_RETURN_NONE;

error:
    PyUnicodeWriter_Discard(writer);
    return NULL;
}
#endif


static struct PyMethodDef methods[] = {
    {"test_object", test_object, METH_NOARGS, _Py_NULL},
    {"test_py_is", test_py_is, METH_NOARGS, _Py_NULL},
#ifndef PYPY_VERSION
    {"test_frame", test_frame, METH_NOARGS, _Py_NULL},
#endif
    {"test_thread_state", test_thread_state, METH_NOARGS, _Py_NULL},
    {"test_interpreter", test_interpreter, METH_NOARGS, _Py_NULL},
    {"test_calls", test_calls, METH_NOARGS, _Py_NULL},
    {"test_gc", test_gc, METH_NOARGS, _Py_NULL},
    {"test_module", test_module, METH_NOARGS, _Py_NULL},
#if (PY_VERSION_HEX <= 0x030B00A1 || 0x030B00A7 <= PY_VERSION_HEX) && !defined(PYPY_VERSION)
    {"test_float_pack", test_float_pack, METH_NOARGS, _Py_NULL},
#endif
#ifndef PYPY_VERSION
    {"test_code", test_code, METH_NOARGS, _Py_NULL},
#endif
    {"test_api_casts", test_api_casts, METH_NOARGS, _Py_NULL},
    {"test_import", test_import, METH_NOARGS, _Py_NULL},
    {"test_weakref", test_weakref, METH_NOARGS, _Py_NULL},
    {"func_varargs", (PyCFunction)(void*)func_varargs, METH_VARARGS | METH_KEYWORDS, _Py_NULL},
    {"test_vectorcall", test_vectorcall, METH_NOARGS, _Py_NULL},
    {"test_getattr", test_getattr, METH_NOARGS, _Py_NULL},
    {"test_getitem", test_getitem, METH_NOARGS, _Py_NULL},
    {"test_dict_api", test_dict_api, METH_NOARGS, _Py_NULL},
    {"test_dict_pop", test_dict_pop, METH_NOARGS, _Py_NULL},
    {"test_dict_setdefault", test_dict_setdefault, METH_NOARGS, _Py_NULL},
    {"test_long_api", test_long_api, METH_NOARGS, _Py_NULL},
#ifdef TEST_MANAGED_DICT
    {"test_managed_dict", test_managed_dict, METH_NOARGS, _Py_NULL},
#endif
    {"test_unicode", test_unicode, METH_NOARGS, _Py_NULL},
    {"test_list", test_list, METH_NOARGS, _Py_NULL},
    {"test_hash", test_hash, METH_NOARGS, _Py_NULL},
#ifdef TEST_PYTIME
    {"test_time", test_time, METH_NOARGS, _Py_NULL},
#endif
    {"test_get_constant", test_get_constant, METH_NOARGS, _Py_NULL},
#ifdef TEST_UNICODEWRITER
    {"test_unicodewriter", test_unicodewriter, METH_NOARGS, _Py_NULL},
    {"test_unicodewriter_widechar", test_unicodewriter_widechar, METH_NOARGS, _Py_NULL},
    {"test_unicodewriter_format", test_unicodewriter_format, METH_NOARGS, _Py_NULL},
#endif
    {_Py_NULL, _Py_NULL, 0, _Py_NULL}
};


static int
module_exec(PyObject *module)
{
#ifdef __cplusplus
    if (PyModule_AddIntMacro(module, __cplusplus)) {
        return -1;
    }
#endif
    if (PyModule_AddStringMacro(module, PY_VERSION)) {
        return -1;
    }
    if (PyModule_AddIntMacro(module, PY_VERSION_HEX)) {
        return -1;
    }
#ifdef PYPY_VERSION
    if (PyModule_AddStringMacro(module, PYPY_VERSION)) {
        return -1;
    }
#endif
#ifdef PYPY_VERSION_NUM
    if (PyModule_AddIntMacro(module, PYPY_VERSION_NUM)) {
        return -1;
    }
#endif
    return 0;
}


#if PY_VERSION_HEX >= 0x03050000
static PyModuleDef_Slot module_slots[] = {
    {Py_mod_exec, _Py_CAST(void*, module_exec)},
    {0, _Py_NULL}
};
#endif


#ifdef PYTHON3
static struct PyModuleDef module_def = {
    PyModuleDef_HEAD_INIT,
    MODULE_NAME_STR,     // m_name
    _Py_NULL,            // m_doc
    0,                   // m_size
    methods,             // m_methods
#if PY_VERSION_HEX >= 0x03050000
    module_slots,        // m_slots
#else
    _Py_NULL,            // m_reload
#endif
    _Py_NULL,            // m_traverse
    _Py_NULL,            // m_clear
    _Py_NULL,            // m_free
};


#define INIT_FUNC CONCAT(PyInit_, MODULE_NAME)

#if PY_VERSION_HEX >= 0x03050000
PyMODINIT_FUNC
INIT_FUNC(void)
{
    return PyModuleDef_Init(&module_def);
}
#else
// Python 3.4
PyMODINIT_FUNC
INIT_FUNC(void)
{
    PyObject *module = PyModule_Create(&module_def);
    if (module == _Py_NULL) {
        return _Py_NULL;
    }
    if (module_exec(module) < 0) {
        Py_DECREF(module);
        return _Py_NULL;
    }
    return module;
}
#endif

#else
// Python 2

#define INIT_FUNC CONCAT(init, MODULE_NAME)

PyMODINIT_FUNC
INIT_FUNC(void)
{
    PyObject *module;
    module = Py_InitModule4(MODULE_NAME_STR,
                            methods,
                            _Py_NULL,
                            _Py_NULL,
                            PYTHON_API_VERSION);
    if (module == _Py_NULL) {
        return;
    }

    if (module_exec(module) < 0) {
        return;
    }
}
#endif
0707010000001A000081A400000000000000000000000166CC4672000000BA000000000000000000000000000000000000004300000000pythoncapi-compat-vendored/tests/test_pythoncapi_compat_cppext.cpp// C++ flavor of the C extension.
// Reuse the whole C source code using an #include, but the file has ".cpp"
// extension to use a C++ builder.
#include "test_pythoncapi_compat_cext.c"
0707010000001B000081A400000000000000000000000166CC467200006B50000000000000000000000000000000000000003C00000000pythoncapi-compat-vendored/tests/test_upgrade_pythoncapi.py#!/usr/bin/env python3
import io
import os
import sys
import tempfile
import textwrap
import unittest

# Get upgrade_pythoncapi.py of the parent directory
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
import upgrade_pythoncapi   # noqa


def operations(disable=None):
    if isinstance(disable, str):
        disable = (disable,)
    elif not disable:
        disable = ()
    operations = ["all"]
    for op in upgrade_pythoncapi.EXCLUDE_FROM_ALL:
        if op.NAME in disable:
            continue
        operations.append(op.NAME)
    for name in disable:
        operations.append(f'-{name}')
    operations = ','.join(operations)
    return operations


def patch(source, no_compat=False, disable=None):
    args = ['script', 'mod.c', '-o', operations(disable=disable)]
    if no_compat:
        args.append('--no-compat')

    patcher = upgrade_pythoncapi.Patcher(args)
    return patcher.patch(source)


def reformat(source):
    return textwrap.dedent(source).strip()


class Tests(unittest.TestCase):
    maxDiff = 80 * 30

    def _test_patch_file(self, tmp_dir):
        # test Patcher.patcher()
        source = """
            PyTypeObject*
            test_type(PyObject *obj, PyTypeObject *type)
            {
                Py_TYPE(obj) = type;
                return Py_TYPE(obj);
            }
        """
        expected = """
            #include "pythoncapi_compat.h"

            PyTypeObject*
            test_type(PyObject *obj, PyTypeObject *type)
            {
                Py_SET_TYPE(obj, type);
                return Py_TYPE(obj);
            }
        """
        source = reformat(source)
        expected = reformat(expected)

        filename = tempfile.mktemp(suffix='.c', dir=tmp_dir)
        old_filename = filename + ".old"
        try:
            with open(filename, "w", encoding="utf-8") as fp:
                fp.write(source)

            old_stderr = sys.stderr
            old_argv = list(sys.argv)
            try:
                # redirect stderr
                sys.stderr = io.StringIO()

                if tmp_dir is not None:
                    arg = tmp_dir
                else:
                    arg = filename
                sys.argv = ['script', arg]
                try:
                    upgrade_pythoncapi.Patcher().main()
                except SystemExit as exc:
                    self.assertEqual(exc.code, 0)
                else:
                    self.fail("SystemExit not raised")
            finally:
                sys.stderr = old_stderr
                sys.argv = old_argv

            with open(filename, encoding="utf-8") as fp:
                new_contents = fp.read()

            with open(old_filename, encoding="utf-8") as fp:
                old_contents = fp.read()
        finally:
            try:
                os.unlink(filename)
            except FileNotFoundError:
                pass
            try:
                os.unlink(old_filename)
            except FileNotFoundError:
                pass

        self.assertEqual(new_contents, expected)
        self.assertEqual(old_contents, source)

    def test_patch_file(self):
        self._test_patch_file(None)

    def test_patch_directory(self):
        with tempfile.TemporaryDirectory() as tmp_dir:
            self._test_patch_file(tmp_dir)

    def check_replace(self, source, expected, **kwargs):
        source = reformat(source)
        expected = reformat(expected)
        self.assertEqual(patch(source, **kwargs), expected)

    def check_dont_replace(self, source, disable=None):
        source = reformat(source)
        self.assertEqual(patch(source, disable=disable), source)

    def test_expr_regex(self):
        # Test EXPR_REGEX
        self.check_replace("a->b->ob_type", "Py_TYPE(a->b)")
        self.check_replace("a.b->ob_type", "Py_TYPE(a.b)")
        self.check_replace("array[2]->ob_type", "Py_TYPE(array[2])")

        # Don't match function calls
        self.check_dont_replace("func()->ob_type")

    def test_pythoncapi_compat(self):
        # If pythoncapi_compat.h is included, avoid compatibility includes
        # and macros.
        #
        # Otherise, Py_SET_TYPE() requires a macro and PyFrame_GetBack()
        # requires 2 macros and an include.
        HEADERS = (
            '<pythoncapi_compat.h>',
            '"pythoncapi_compat.h"',
        )
        for header in HEADERS:
            # There is no empty line between the include and the function
            # on purpose.
            self.check_replace("""
                #include %s
                void test_set_type(PyObject *obj, PyTypeObject *type)
                {
                    Py_TYPE(obj) = type;
                }
                PyFrameObject* frame_back_borrowed(PyFrameObject *frame)
                {
                    return frame->f_back;
                }
            """ % header, """
                #include %s
                void test_set_type(PyObject *obj, PyTypeObject *type)
                {
                    Py_SET_TYPE(obj, type);
                }
                PyFrameObject* frame_back_borrowed(PyFrameObject *frame)
                {
                    return _PyFrame_GetBackBorrow(frame);
                }
            """ % header)

    def test_py_type(self):
        source = """
            PyTypeObject* get_type(PyObject *obj)
            { return obj->ob_type; }
        """
        expected = """
            PyTypeObject* get_type(PyObject *obj)
            { return Py_TYPE(obj); }
        """
        self.check_replace(source, expected)

    def test_py_size(self):
        source = """
            Py_ssize_t get_size(PyVarObject *obj)
            { return obj->ob_size; }
        """
        expected = """
            Py_ssize_t get_size(PyVarObject *obj)
            { return Py_SIZE(obj); }
        """
        self.check_replace(source, expected)

    def test_py_refcnt(self):
        source = """
            Py_ssize_t get_refcnt(PyObject *obj)
            { return obj->ob_refcnt; }
        """
        expected = """
            Py_ssize_t get_refcnt(PyObject *obj)
            { return Py_REFCNT(obj); }
        """
        self.check_replace(source, expected)

    def test_py_set_type(self):
        source = """
            void test_type(PyObject *obj, PyTypeObject *type)
            {
                obj->ob_type = type;
                Py_TYPE(obj) = type;
            }
        """
        expected = """
            #include "pythoncapi_compat.h"

            void test_type(PyObject *obj, PyTypeObject *type)
            {
                Py_SET_TYPE(obj, type);
                Py_SET_TYPE(obj, type);
            }
        """
        self.check_replace(source, expected)

        self.check_dont_replace("""
            PyTypeObject* get_type(PyObject *obj, PyTypeObject *check_type)
            {
                assert(Py_TYPE(args) == check_type);
                return Py_TYPE(obj);
            }
        """)

    def test_py_set_size(self):
        source = """\
            void test_size(PyVarObject *obj)
            {
                obj->ob_size = 3;
                Py_SIZE(obj) = 4;
            }
        """
        expected = """\
            #include "pythoncapi_compat.h"

            void test_size(PyVarObject *obj)
            {
                Py_SET_SIZE(obj, 3);
                Py_SET_SIZE(obj, 4);
            }
        """
        self.check_replace(source, expected)

        self.check_dont_replace("""
            Py_ssize_t
            get_size(PyObject *obj)
            {
                assert(Py_SIZE(args) == 1);
                return Py_SIZE(obj);
            }
        """)

    def test_py_set_refcnt(self):
        source = """\
            void set_refcnt(PyObject *obj)
            {
                obj->ob_refcnt = 1;
                Py_REFCNT(obj) = 2;
            }
        """
        expected = """\
            #include "pythoncapi_compat.h"

            void set_refcnt(PyObject *obj)
            {
                Py_SET_REFCNT(obj, 1);
                Py_SET_REFCNT(obj, 2);
            }
        """
        self.check_replace(source, expected)

        self.check_dont_replace("""
            Py_ssize_t
            get_refcnt(PyObject *obj)
            {
                assert(Py_REFCNT(args) == 1);
                return Py_REFCNT(obj);
            }
        """)

    def test_pyobject_new(self):
        source = """\
            capsule = PyObject_NEW(PyCapsule, &PyCapsule_Type);
            pattern = PyObject_NEW_VAR(PatternObject, Pattern_Type, n);
        """
        expected = """\
            capsule = PyObject_New(PyCapsule, &PyCapsule_Type);
            pattern = PyObject_NewVar(PatternObject, Pattern_Type, n);
        """
        self.check_replace(source, expected)

        self.check_dont_replace("""
            func = PyObject_NEW;
            capsule2 = PyObject_NEW2(PyCapsule, &PyCapsule_Type);

            func2 = PyObject_NEW_VAR;
            pattern2 = PyObject_NEW_VAR2(PatternObject, Pattern_Type, n);
        """)

    def test_pymem_malloc(self):
        source = """\
            void *ptr = PyMem_MALLOC(10);
            ptr = PyMem_REALLOC(ptr, 20);
            PyMem_FREE(ptr);
            PyMem_DEL(ptr);
            PyMem_Del(ptr);
        """
        expected = """\
            void *ptr = PyMem_Malloc(10);
            ptr = PyMem_Realloc(ptr, 20);
            PyMem_Free(ptr);
            PyMem_Free(ptr);
            PyMem_Free(ptr);
        """
        self.check_replace(source, expected)

    def test_pyobject_malloc(self):
        source = """\
            void *ptr = PyObject_MALLOC(10);
            ptr = PyObject_REALLOC(ptr, 20);
            PyObject_FREE(ptr);
            PyObject_DEL(ptr);
            PyObject_Del(ptr);
        """
        expected = """\
            void *ptr = PyObject_Malloc(10);
            ptr = PyObject_Realloc(ptr, 20);
            PyObject_Free(ptr);
            PyObject_Free(ptr);
            PyObject_Free(ptr);
        """
        self.check_replace(source, expected)

    def test_pyframe_getback(self):
        source = """\
            PyFrameObject* frame_back_borrowed(PyFrameObject *frame)
            {
                return frame->f_back;
            }
        """
        expected = """\
            #include "pythoncapi_compat.h"

            PyFrameObject* frame_back_borrowed(PyFrameObject *frame)
            {
                return _PyFrame_GetBackBorrow(frame);
            }
        """
        self.check_replace(source, expected)

    def test_pyframe_getcode(self):
        self.check_replace("""\
            PyCodeObject* frame_code_borrowed(PyFrameObject *frame)
            {
                return frame->f_code;
            }
        """, """\
            #include "pythoncapi_compat.h"

            PyCodeObject* frame_code_borrowed(PyFrameObject *frame)
            {
                return _PyFrame_GetCodeBorrow(frame);
            }
        """)

    def test_get_member_regex(self):
        # Use PyFrame_GetCode() to test get_member_regex()
        self.check_dont_replace("""
            void frame_set_code(PyFrameObject *frame, PyCodeObject *code)
            {
                frame->f_code = code;
            }

            void frame_clear_code(PyFrameObject *frame)
            {
                Py_CLEAR(frame->f_code);
            }
        """)

    def test_pythreadstate_getinterpreter(self):
        self.check_replace("""
            PyInterpreterState* get_interp(PyThreadState *tstate)
            { return tstate->interp; }
        """, """
            #include "pythoncapi_compat.h"

            PyInterpreterState* get_interp(PyThreadState *tstate)
            { return PyThreadState_GetInterpreter(tstate); }
        """)

    def test_pythreadstate_getframe(self):
        self.check_replace("""
            PyFrameObject* get_frame(PyThreadState *tstate)
            { return tstate->frame; }
        """, """
            #include "pythoncapi_compat.h"

            PyFrameObject* get_frame(PyThreadState *tstate)
            { return _PyThreadState_GetFrameBorrow(tstate); }
        """)

    def test_py_newref_return(self):
        self.check_replace("""
            PyObject* new_ref(PyObject *obj) {
                Py_INCREF(obj);
                return obj;
            }

            PyObject* same_line(PyObject *obj) {
                Py_INCREF(obj); return obj;
            }

            PyObject* new_xref(PyObject *obj) {
                Py_XINCREF(obj);
                return obj;
            }

            PyObject* cast(PyLongObject *obj) {
                Py_XINCREF(obj);
                return (PyObject *)obj;
            }
        """, """
            #include "pythoncapi_compat.h"

            PyObject* new_ref(PyObject *obj) {
                return Py_NewRef(obj);
            }

            PyObject* same_line(PyObject *obj) {
                return Py_NewRef(obj);
            }

            PyObject* new_xref(PyObject *obj) {
                return Py_XNewRef(obj);
            }

            PyObject* cast(PyLongObject *obj) {
                return Py_XNewRef(obj);
            }
        """)

    def test_py_newref(self):
        # INCREF, assign
        self.check_replace("""
            void set_attr(MyStruct *obj, PyObject *value, int test)
            {
                // 1
                Py_INCREF(value);
                obj->attr = value;
                // 2
                obj->attr = value;
                Py_INCREF(value);
                // 3
                obj->attr = value;
                Py_INCREF(obj->attr);
            }
        """, """
            #include "pythoncapi_compat.h"

            void set_attr(MyStruct *obj, PyObject *value, int test)
            {
                // 1
                obj->attr = Py_NewRef(value);
                // 2
                obj->attr = Py_NewRef(value);
                // 3
                obj->attr = Py_NewRef(value);
            }
        """)

        # Same line
        self.check_replace("""
            void set_attr(MyStruct *obj, PyObject *value, int test)
            {
                // same line 1
                obj->attr = value; Py_INCREF(value);
                // same line 2
                if (test) { obj->attr = value; Py_INCREF(obj->attr); }
                // same line 3
                if (test) { Py_INCREF(value); obj->attr = value; }
            }
        """, """
            #include "pythoncapi_compat.h"

            void set_attr(MyStruct *obj, PyObject *value, int test)
            {
                // same line 1
                obj->attr = Py_NewRef(value);
                // same line 2
                if (test) { obj->attr = Py_NewRef(value); }
                // same line 3
                if (test) { obj->attr = Py_NewRef(value); }
            }
        """)

        # Cast
        self.check_replace("""
            void set_attr(MyStruct *obj, PyObject *value, int test)
            {
                // cast 1
                Py_INCREF(value);
                obj->attr = (PyObject*)value;
                // cast 2
                obj->attr = (PyObject*)value;
                Py_INCREF(value);

                // assign var, incref
                PyCodeObject *code_obj = (PyCodeObject *)code;
                Py_INCREF(code_obj);
                // assign var, incref
                PyCodeObject* code_obj = (PyCodeObject *)code;
                Py_INCREF(code);
                // assign var, xincref
                PyCodeObject * code_obj = (PyCodeObject *)code;
                Py_XINCREF(code_obj);

                // incref, assign var
                Py_INCREF(code);
                PyCodeObject* code_obj = (PyCodeObject *)code;
                // xincref, assign var
                Py_XINCREF(code);
                PyCodeObject *code_obj = (PyCodeObject *)code;
            }
        """, """
            #include "pythoncapi_compat.h"

            void set_attr(MyStruct *obj, PyObject *value, int test)
            {
                // cast 1
                obj->attr = Py_NewRef(value);
                // cast 2
                obj->attr = Py_NewRef(value);

                // assign var, incref
                PyCodeObject *code_obj = (PyCodeObject *)Py_NewRef(code);
                // assign var, incref
                PyCodeObject* code_obj = (PyCodeObject *)Py_NewRef(code);
                // assign var, xincref
                PyCodeObject * code_obj = (PyCodeObject *)Py_XNewRef(code);

                // incref, assign var
                PyCodeObject* code_obj = (PyCodeObject *)Py_NewRef(code);
                // xincref, assign var
                PyCodeObject *code_obj = (PyCodeObject *)Py_XNewRef(code);
            }
        """)

        # Py_XINCREF
        self.check_replace("""
            void set_xattr(MyStruct *obj, PyObject *value)
            {
                // 1
                Py_XINCREF(value);
                obj->attr = value;
                // 2
                obj->attr = value;
                Py_XINCREF(value);
                // 3
                obj->attr = value;
                Py_XINCREF(obj->attr);
            }
        """, """
            #include "pythoncapi_compat.h"

            void set_xattr(MyStruct *obj, PyObject *value)
            {
                // 1
                obj->attr = Py_XNewRef(value);
                // 2
                obj->attr = Py_XNewRef(value);
                // 3
                obj->attr = Py_XNewRef(value);
            }
        """)

        # the first Py_INCREF should be replaced before the second one,
        # otherwise the first Py_INCREF is not replaced.
        self.check_replace("""
            void set(void)
            {
                PyObject *x, *y;
                Py_INCREF(Py_None);
                x = Py_None;
                Py_INCREF(Py_None);
                x = Py_None;
                Py_DECREF(x);
                Py_DECREF(y);
            }
        """, """
            #include "pythoncapi_compat.h"

            void set(void)
            {
                PyObject *x, *y;
                x = Py_NewRef(Py_None);
                x = Py_NewRef(Py_None);
                Py_DECREF(x);
                Py_DECREF(y);
            }
        """)

        # Indentation matters for conditional code
        self.check_dont_replace("""
            void test1(int test)
            {
                PyObject *res;
                if (test)
                    res = Py_True;
                else
                    res = Py_False;
                Py_INCREF(res);

                Py_DECREF(res);
            }

            int test2(struct datetime* result, PyObject *tzinfo)
            {
                int res = 0;
                if (test)
                 res = 1;
                else
                 Py_INCREF(tzinfo);
                result->tzinfo = tzinfo;
                return res;
            }
        """)

    def test_py_clear(self):
        self.check_replace("""
            void clear(int test)
            {
                PyObject *obj;

                // two lines
                Py_XDECREF(obj);
                obj = NULL;

                // inside if
                if (test) { Py_XDECREF(obj); obj = NULL; }
            }
        """, """
            void clear(int test)
            {
                PyObject *obj;

                // two lines
                Py_CLEAR(obj);

                // inside if
                if (test) { Py_CLEAR(obj); }
            }
        """)

        # Don't replace Py_DECREF()
        self.check_dont_replace("""
            void dont_clear(void)
            {
                PyObject *obj;
                Py_DECREF(obj);
                obj = NULL;
            }
        """, disable="Py_SETREF")

    def test_py_setref(self):
        self.check_replace("""
            void set(PyObject **obj, PyObject *t)
            {
                // DECREF
                Py_DECREF(*obj);
                *obj = t;

                // XDECREF
                Py_XDECREF(*obj);
                *obj = t;

                // DECREF, INCREF
                Py_DECREF(*obj);
                Py_INCREF(t);
                *obj = t;
            }
        """, """
            #include "pythoncapi_compat.h"

            void set(PyObject **obj, PyObject *t)
            {
                // DECREF
                Py_SETREF(*obj, t);

                // XDECREF
                Py_XSETREF(*obj, t);

                // DECREF, INCREF
                Py_SETREF(*obj, Py_NewRef(t));
            }
        """)

        self.check_replace("""
            void set(PyObject **obj, PyObject *value)
            {
                // 1
                PyObject *old = *obj;
                *obj = value;
                Py_DECREF(old);
                // 2
                PyObject *old = *obj;
                *obj = Py_XNewRef(value);
                Py_DECREF(old);
                // 3
                PyObject *old = *obj;
                *obj = value;
                Py_XDECREF(old);
                // 4
                PyObject *old = *obj;
                *obj = Py_NewRef(value);
                Py_XDECREF(old);
            }
        """, """
            #include "pythoncapi_compat.h"

            void set(PyObject **obj, PyObject *value)
            {
                // 1
                Py_SETREF(*obj, value);
                // 2
                Py_SETREF(*obj, Py_XNewRef(value));
                // 3
                Py_XSETREF(*obj, value);
                // 4
                Py_XSETREF(*obj, Py_NewRef(value));
            }
        """)

        # INCREF, DECREF, assign
        self.check_replace("""
            void set(void)
            {
                // 1
                Py_INCREF(value);
                Py_DECREF(obj);
                obj = value;
                // 2
                Py_INCREF(value);
                Py_XDECREF(obj);
                obj = value;
                // 3
                Py_XINCREF(value);
                Py_DECREF(obj);
                obj = value;
                // 4
                Py_XINCREF(value);
                Py_XDECREF(obj);
                obj = value;
            }
        """, """
            #include "pythoncapi_compat.h"

            void set(void)
            {
                // 1
                Py_SETREF(obj, Py_NewRef(value));
                // 2
                Py_XSETREF(obj, Py_NewRef(value));
                // 3
                Py_SETREF(obj, Py_XNewRef(value));
                // 4
                Py_XSETREF(obj, Py_XNewRef(value));
            }
        """)

        # old variable
        self.check_replace("""
            void set(PyObject **obj, PyObject *value)
            {
                // 1
                PyObject *old_next = (PyObject*)self->tb_next;
                self->tb_next = (PyTracebackObject *)Py_XNewRef(new_next);
                Py_XDECREF(old_next);
                // 2
                old_next = (PyObject*)self->tb_next;
                self->tb_next = (PyTracebackObject *)Py_XNewRef(new_next);
                Py_XDECREF(old_next);
            }
        """, """
            #include "pythoncapi_compat.h"

            void set(PyObject **obj, PyObject *value)
            {
                // 1
                Py_XSETREF(self->tb_next, (PyTracebackObject *)Py_XNewRef(new_next));
                // 2
                Py_XSETREF(self->tb_next, (PyTracebackObject *)Py_XNewRef(new_next));
            }
        """)

        # Py_CLEAR
        self.check_replace("""
            void set(PyObject **obj, PyObject *value)
            {
                // 1
                Py_CLEAR(self->tb_next);
                self->tb_next = value;
                // 2
                Py_INCREF(value);
                Py_CLEAR(self->tb_next);
                self->tb_next = value;
                // 3
                Py_XINCREF(value);
                Py_CLEAR(self->tb_next);
                self->tb_next = value;
            }
        """, """
            #include "pythoncapi_compat.h"

            void set(PyObject **obj, PyObject *value)
            {
                // 1
                Py_XSETREF(self->tb_next, value);
                // 2
                Py_XSETREF(self->tb_next, Py_NewRef(value));
                // 3
                Py_XSETREF(self->tb_next, Py_XNewRef(value));
            }
        """)

    def test_py_is(self):
        self.check_replace("""
            void test_py_is(PyObject *x)
            {
                if (x == Py_None) {
                    return 1;
                }
                if (x == Py_True) {
                    return 2;
                }
                if (x == Py_False) {
                    return 3;
                }
                return 0;
            }

            void test_py_is_not(PyObject *x)
            {
                if (x != Py_None) {
                    return 1;
                }
                if (x != Py_True) {
                    return 2;
                }
                if (x != Py_False) {
                    return 3;
                }
                return 0;
            }
        """, """
            #include "pythoncapi_compat.h"

            void test_py_is(PyObject *x)
            {
                if (Py_IsNone(x)) {
                    return 1;
                }
                if (Py_IsTrue(x)) {
                    return 2;
                }
                if (Py_IsFalse(x)) {
                    return 3;
                }
                return 0;
            }

            void test_py_is_not(PyObject *x)
            {
                if (!Py_IsNone(x)) {
                    return 1;
                }
                if (!Py_IsTrue(x)) {
                    return 2;
                }
                if (!Py_IsFalse(x)) {
                    return 3;
                }
                return 0;
            }
        """)

        self.check_replace("""
            void test_expr(struct MyStruct *obj, PyObject **obj2)
            {
                if (obj->attr1 == Py_None) {
                    return 1;
                }
                if (obj->attr2.name == Py_None) {
                    return 1;
                }
                if (*obj2 == Py_None) {
                    return 1;
                }
                return 0;
            }
        """, """
            #include "pythoncapi_compat.h"

            void test_expr(struct MyStruct *obj, PyObject **obj2)
            {
                if (Py_IsNone(obj->attr1)) {
                    return 1;
                }
                if (Py_IsNone(obj->attr2.name)) {
                    return 1;
                }
                if (Py_IsNone(*obj2)) {
                    return 1;
                }
                return 0;
            }
        """)


    def test_no_compat(self):
        # Don't add "#include "pythoncapi_compat.h"
        source = """
            void test_type(PyObject *obj, PyTypeObject *type)
            {
                obj->ob_type = type;
            }
        """
        expected = """
            void test_type(PyObject *obj, PyTypeObject *type)
            {
                Py_SET_TYPE(obj, type);
            }
        """
        self.check_replace(source, expected, no_compat=True)

if __name__ == "__main__":
    unittest.main()
0707010000001C000081A400000000000000000000000166CC4672000003A8000000000000000000000000000000000000002A00000000pythoncapi-compat-vendored/tests/utils.pyimport subprocess
import sys


PYTHON3 = (sys.version_info >= (3,))


def run_command(cmd, **kw):
    if hasattr(subprocess, 'run'):
        proc = subprocess.run(cmd, **kw)
    else:
        kw['shell'] = False
        proc = subprocess.Popen(cmd, **kw)
        try:
            proc.wait()
        except:
            proc.kill()
            proc.wait()
            raise

    exitcode = proc.returncode
    if exitcode:
        sys.exit(exitcode)


def command_stdout(cmd, **kw):
    kw['stdout'] = subprocess.PIPE
    kw['universal_newlines'] = True
    if hasattr(subprocess, 'run'):
        proc = subprocess.run(cmd, **kw)
        return (proc.returncode, proc.stdout)
    else:
        kw['shell'] = False
        proc = subprocess.Popen(cmd, **kw)
        try:
            stdout = proc.communicate()[0]
        except:
            proc.kill()
            proc.wait()
            raise
        return (proc.returncode, stdout)
0707010000001D000081ED00000000000000000000000166CC4672000063F0000000000000000000000000000000000000003100000000pythoncapi-compat-vendored/upgrade_pythoncapi.py#!/usr/bin/env python3
import argparse
import os
import re
import urllib.request
import sys


MIN_PYTHON = (2, 7)


PYTHONCAPI_COMPAT_URL = ('https://raw.githubusercontent.com/python/'
                         'pythoncapi_compat/master/pythoncapi_compat.h')
PYTHONCAPI_COMPAT_H = 'pythoncapi_compat.h'
INCLUDE_PYTHONCAPI_COMPAT = f'#include "{PYTHONCAPI_COMPAT_H}"'
INCLUDE_PYTHONCAPI_COMPAT2 = f'#include <{PYTHONCAPI_COMPAT_H}>'

C_FILE_EXT = (
    # C language
    ".c", ".h",
    # C++ language
    ".cc", ".cpp", ".cxx", ".hpp",
)
IGNORE_DIRS = (".git", ".tox")


# Match spaces but not newline characters.
# Similar to \s but exclude newline characters and only look for ASCII spaces
SPACE_REGEX = r'[ \t\f\v]'
# Match the end of a line: newline characters of a single line
NEWLINE_REGEX = r'(?:\n|\r|\r\n)'
# Match the indentation at the beginning of a line
INDENTATION_REGEX = fr'^{SPACE_REGEX}*'


# Match a C identifier: 'identifier', 'var_3', 'NameCamelCase', '_var'
# Use \b to only match a full word: match "a_b", but not just "b" in "a_b".
ID_REGEX = r'\b[a-zA-Z_][a-zA-Z0-9_]*\b'
# Match 'array[3]'
SUBEXPR_REGEX = fr'{ID_REGEX}(?:\[[^]]+\])*'
# Match a C expression like "frame", "frame.attr", "obj->attr" or "*obj".
# Don't match functions calls like "func()".
EXPR_REGEX = (fr"\*?"  # "*" prefix
              fr"{SUBEXPR_REGEX}"  # "var"
              fr"(?:(?:->|\.){SUBEXPR_REGEX})*")  # "->attr" or ".attr"

# # Match 'PyObject *var' and 'struct MyStruct* var'
TYPE_PTR_REGEX = fr'{ID_REGEX} *\*'

# Match '(PyObject*)' and nothing
OPT_CAST_REGEX = fr'(?:\({TYPE_PTR_REGEX} *\){SPACE_REGEX}*)?'


def same_indentation(group):
    # the regex must have re.MULTILINE flag
    return fr'{SPACE_REGEX}*(?:{NEWLINE_REGEX}{group})?'


def get_member_regex_str(member):
    # Match "var->member".
    return fr'\b({EXPR_REGEX}) *-> *{member}\b'


def get_member_regex(member):
    # Match "var->member" (get).
    # Don't match "var->member = value" (set).
    # Don't match "Py_CLEAR(var->member)".
    # Only "Py_CLEAR(" exact string is excluded.
    regex = (r'(?<!Py_CLEAR\()'
             + get_member_regex_str(member)
             + r'(?!\s*=\s*)')
    return re.compile(regex)


def assign_regex_str(var, expr):
    # Match "var = expr;".
    return fr'{var} *= *{expr}\s*;'


def set_member_regex(member):
    # Match "var->member = expr;".
    regex = assign_regex_str(get_member_regex_str(member), r'([^=].*)')
    return re.compile(regex)


def call_assign_regex(name):
    # Match "Py_TYPE(expr) = expr;".
    # Don't match "assert(Py_TYPE(expr) == expr);".
    # Tolerate spaces
    regex = fr'{name} *\( *(.+) *\) *= *([^=].*) *;'
    return re.compile(regex)


def is_c_filename(filename):
    return filename.endswith(C_FILE_EXT)


class Operation:
    NAME = "<name>"
    REPLACE = ()
    NEED_PYTHONCAPI_COMPAT = False

    def __init__(self, patcher):
        self.patcher = patcher

    def patch(self, content):
        old_content = content
        for regex, replace in self.REPLACE:
            content = regex.sub(replace, content)
        if content != old_content and self.NEED_PYTHONCAPI_COMPAT:
            content = self.patcher.add_pythoncapi_compat(content)
        return content


class Py_TYPE(Operation):
    NAME = "Py_TYPE"
    REPLACE = (
        (get_member_regex('ob_type'), r'Py_TYPE(\1)'),
    )
    # Py_TYPE() was added to Python 2.6.


class Py_SIZE(Operation):
    NAME = "Py_SIZE"
    REPLACE = (
        (get_member_regex('ob_size'), r'Py_SIZE(\1)'),
    )
    # Py_SIZE() was added to Python 2.6.


class Py_REFCNT(Operation):
    NAME = "Py_REFCNT"
    REPLACE = (
        (get_member_regex('ob_refcnt'), r'Py_REFCNT(\1)'),
    )
    # Py_REFCNT() was added to Python 2.6.


class Py_SET_TYPE(Operation):
    NAME = "Py_SET_TYPE"
    REPLACE = (
        (call_assign_regex('Py_TYPE'), r'Py_SET_TYPE(\1, \2);'),
        (set_member_regex('ob_type'), r'Py_SET_TYPE(\1, \2);'),
    )
    # Need Py_SET_TYPE(): new in Python 3.9.
    NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 9))


class Py_SET_SIZE(Operation):
    NAME = "Py_SET_SIZE"
    REPLACE = (
        (call_assign_regex('Py_SIZE'), r'Py_SET_SIZE(\1, \2);'),
        (set_member_regex('ob_size'), r'Py_SET_SIZE(\1, \2);'),
    )
    # Need Py_SET_SIZE(): new in Python 3.9.
    NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 9))


class Py_SET_REFCNT(Operation):
    NAME = "Py_SET_REFCNT"
    REPLACE = (
        (call_assign_regex('Py_REFCNT'), r'Py_SET_REFCNT(\1, \2);'),
        (set_member_regex('ob_refcnt'), r'Py_SET_REFCNT(\1, \2);'),
    )
    # Need Py_SET_REFCNT(): new in Python 3.9.
    NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 9))


class PyObject_NEW(Operation):
    NAME = "PyObject_NEW"
    # In Python 3.9, the PyObject_NEW() macro becomes an alias to the
    # PyObject_New() macro, and the PyObject_NEW_VAR() macro becomes an alias
    # to the PyObject_NewVar() macro.
    REPLACE = (
        (re.compile(r"\bPyObject_NEW\b( *\()"), r'PyObject_New\1'),
        (re.compile(r"\bPyObject_NEW_VAR\b( *\()"), r'PyObject_NewVar\1'),
    )


class PyMem_MALLOC(Operation):
    NAME = "PyMem_MALLOC"
    # In Python 3.9, the PyObject_NEW() macro becomes an alias to the
    # PyObject_New() macro, and the PyObject_NEW_VAR() macro becomes an alias
    # to the PyObject_NewVar() macro.

    REPLACE = (
        (re.compile(r"\bPyMem_MALLOC\b( *\()"), r'PyMem_Malloc\1'),
        (re.compile(r"\bPyMem_REALLOC\b( *\()"), r'PyMem_Realloc\1'),
        (re.compile(r"\bPyMem_FREE\b( *\()"), r'PyMem_Free\1'),
        (re.compile(r"\bPyMem_Del\b( *\()"), r'PyMem_Free\1'),
        (re.compile(r"\bPyMem_DEL\b( *\()"), r'PyMem_Free\1'),
    )


class PyObject_MALLOC(Operation):
    NAME = "PyObject_MALLOC"
    # In Python 3.9, the PyObject_NEW() macro becomes an alias to the
    # PyObject_New() macro, and the PyObject_NEW_VAR() macro becomes an alias
    # to the PyObject_NewVar() macro.

    REPLACE = (
        (re.compile(r"\bPyObject_MALLOC\b( *\()"), r'PyObject_Malloc\1'),
        (re.compile(r"\bPyObject_REALLOC\b( *\()"), r'PyObject_Realloc\1'),
        (re.compile(r"\bPyObject_FREE\b( *\()"), r'PyObject_Free\1'),
        (re.compile(r"\bPyObject_Del\b( *\()"), r'PyObject_Free\1'),
        (re.compile(r"\bPyObject_DEL\b( *\()"), r'PyObject_Free\1'),
    )


class PyFrame_GetBack(Operation):
    NAME = "PyFrame_GetBack"
    REPLACE = (
        (get_member_regex('f_back'), r'_PyFrame_GetBackBorrow(\1)'),
    )
    # Need _PyFrame_GetBackBorrow() (PyFrame_GetBack() is new in Python 3.9)
    NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 9))


class PyFrame_GetCode(Operation):
    NAME = "PyFrame_GetCode"

    REPLACE = (
        (get_member_regex('f_code'), r'_PyFrame_GetCodeBorrow(\1)'),
    )
    # Need _PyFrame_GetCodeBorrow() (PyFrame_GetCode() is new in Python 3.9)
    NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 9))


class PyThreadState_GetInterpreter(Operation):
    NAME = "PyThreadState_GetInterpreter"
    REPLACE = (
        (get_member_regex('interp'), r'PyThreadState_GetInterpreter(\1)'),
    )
    # Need PyThreadState_GetInterpreter() (new in Python 3.9)
    NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 9))


class PyThreadState_GetFrame(Operation):
    NAME = "PyThreadState_GetFrame"
    REPLACE = (
        (get_member_regex('frame'), r'_PyThreadState_GetFrameBorrow(\1)'),
    )
    # Need _PyThreadState_GetFrameBorrow()
    # (PyThreadState_GetFrame() is new in Python 3.9)
    NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 9))


class Py_NewRef(Operation):
    NAME = "Py_NewRef"
    REPLACE = (
        # "Py_INCREF(x); return x;" => "return Py_NewRef(x);"
        # "Py_XINCREF(x); return x;" => "return Py_XNewRef(x);"
        # The two statements must be at the same indentation, otherwise the
        # regex does not match.
        (re.compile(fr'({INDENTATION_REGEX})'
                    + fr'Py_(X?)INCREF\(({EXPR_REGEX})\)\s*;'
                    + same_indentation(r'\1')
                    + fr'return {OPT_CAST_REGEX}\3;',
                    re.MULTILINE),
         r'\1return Py_\2NewRef(\3);'),

        # Same regex than the previous one,
        # but the two statements are on the same line.
        (re.compile(fr'Py_(X?)INCREF\(({EXPR_REGEX})\)\s*;'
                    + fr'{SPACE_REGEX}*'
                    + fr'return {OPT_CAST_REGEX}\2;',
                    re.MULTILINE),
         r'return Py_\1NewRef(\2);'),

        # "Py_INCREF(x); y = x;" must be replaced before
        # "y = x; Py_INCREF(y);", to not miss consecutive
        # "Py_INCREF; assign; Py_INCREF; assign; ..." (see unit tests).

        # "Py_INCREF(x); y = x;" => "y = Py_NewRef(x)"
        # "Py_XINCREF(x); y = x;" => "y = Py_XNewRef(x)"
        # The two statements must have the same indentation, otherwise the
        # regex does not match.
        (re.compile(fr'({INDENTATION_REGEX})'
                    + fr'Py_(X?)INCREF\(({EXPR_REGEX})\);'
                    + same_indentation(r'\1')
                    + assign_regex_str(fr'({EXPR_REGEX})',
                                       fr'{OPT_CAST_REGEX}\3'),
                    re.MULTILINE),
         r'\1\4 = Py_\2NewRef(\3);'),

        # Same regex than the previous one,
        # but the two statements are on the same line.
        (re.compile(fr'Py_(X?)INCREF\(({EXPR_REGEX})\);'
                    + fr'{SPACE_REGEX}*'
                    + assign_regex_str(fr'({EXPR_REGEX})',
                                       fr'{OPT_CAST_REGEX}\2')),
         r'\3 = Py_\1NewRef(\2);'),

        # "y = x; Py_INCREF(x);" => "y = Py_NewRef(x);"
        # "y = x; Py_INCREF(y);" => "y = Py_NewRef(x);"
        # "y = x; Py_XINCREF(x);" => "y = Py_XNewRef(x);"
        # "y = x; Py_XINCREF(y);" => "y = Py_XNewRef(x);"
        # "y = (PyObject*)x; Py_XINCREF(y);" => "y = Py_XNewRef(x);"
        # The two statements must have the same indentation, otherwise the
        # regex does not match.
        (re.compile(fr'({INDENTATION_REGEX})'
                    + assign_regex_str(fr'({EXPR_REGEX})',
                                       fr'{OPT_CAST_REGEX}({EXPR_REGEX})')
                    + same_indentation(r'\1')
                    + r'Py_(X?)INCREF\((?:\2|\3)\);',
                    re.MULTILINE),
         r'\1\2 = Py_\4NewRef(\3);'),

        # Same regex than the previous one,
        # but the two statements are on the same line.
        (re.compile(assign_regex_str(fr'({EXPR_REGEX})',
                                     fr'{OPT_CAST_REGEX}({EXPR_REGEX})')
                    + fr'{SPACE_REGEX}*'
                    + r'Py_(X?)INCREF\((?:\1|\2)\);'),
         r'\1 = Py_\3NewRef(\2);'),

        # "PyObject *var = x; Py_INCREF(x);" => "PyObject *var = Py_NewRef(x);"
        # The two statements must have the same indentation, otherwise the
        # regex does not match.
        (re.compile(fr'({INDENTATION_REGEX})'
                      # "type* var = expr;"
                    + assign_regex_str(fr'({TYPE_PTR_REGEX} *)({EXPR_REGEX})',
                                       fr'({OPT_CAST_REGEX})({EXPR_REGEX})')
                    + same_indentation(r'\1')
                      # "Py_INCREF(var);"
                    + r'Py_(X?)INCREF\((?:\3|\5)\);',
                    re.MULTILINE),
         r'\1\2\3 = \4Py_\6NewRef(\5);'),

        # "Py_INCREF(x); PyObject *var = x;" => "PyObject *var = Py_NewRef(x);"
        # The two statements must have the same indentation, otherwise the
        # regex does not match.
        (re.compile(fr'({INDENTATION_REGEX})'
                      # "Py_INCREF(var);"
                    + fr'Py_(X?)INCREF\(({EXPR_REGEX})\);'
                    + same_indentation(r'\1')
                      # "type* var = expr;"
                    + assign_regex_str(fr'({TYPE_PTR_REGEX} *{EXPR_REGEX})',
                                       fr'({OPT_CAST_REGEX})\3'),
                    re.MULTILINE),
         r'\1\4 = \5Py_\2NewRef(\3);'),
    )
    # Need Py_NewRef(): new in Python 3.10
    NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 10))


class Py_CLEAR(Operation):
    NAME = "Py_CLEAR"
    REPLACE = (
        # "Py_XDECREF(x); x = NULL;" => "Py_CLEAR(x)";
        # The two statements must have the same indentation, otherwise the
        # regex does not match.
        (re.compile(fr'({INDENTATION_REGEX})'
                    + fr'Py_XDECREF\(({EXPR_REGEX})\) *;'
                    + same_indentation(r'\1')
                    + assign_regex_str(r'\2', r'NULL'),
                    re.MULTILINE),
         r'\1Py_CLEAR(\2);'),

        # "Py_XDECREF(x); x = NULL;" => "Py_CLEAR(x)";
        (re.compile(fr'Py_XDECREF\(({EXPR_REGEX})\) *;'
                    + fr'{SPACE_REGEX}*'
                    + assign_regex_str(r'\1', r'NULL')),
         r'Py_CLEAR(\1);'),
    )


SETREF_VALUE = fr'{OPT_CAST_REGEX}(?:{EXPR_REGEX}|Py_X?NewRef\({EXPR_REGEX}\))'


class Py_SETREF(Operation):
    NAME = "Py_SETREF"
    REPLACE = (
        # "Py_INCREF(y); Py_CLEAR(x); x = y;" => "Py_XSETREF(x, y)";
        # Statements must have the same indentation, otherwise the regex does
        # not match.
        (re.compile(fr'({INDENTATION_REGEX})'
                    + fr'Py_(X?)INCREF\(({EXPR_REGEX})\) *;'
                    + same_indentation(r'\1')
                    + fr'Py_CLEAR\(({EXPR_REGEX})\) *;'
                    + same_indentation(r'\1')
                    + assign_regex_str(r'\4', r'\3'),
                    re.MULTILINE),
         r'\1Py_XSETREF(\4, Py_\2NewRef(\3));'),

        # "Py_CLEAR(x); x = y;" => "Py_XSETREF(x, y)";
        # Statements must have the same indentation, otherwise the regex does
        # not match.
        (re.compile(fr'({INDENTATION_REGEX})'
                    + fr'Py_CLEAR\(({EXPR_REGEX})\) *;'
                    + same_indentation(r'\1')
                    + assign_regex_str(r'\2',
                                       fr'({SETREF_VALUE})'),
                    re.MULTILINE),
         r'\1Py_XSETREF(\2, \3);'),

        # "Py_INCREF(y); Py_DECREF(x); x = y;" => "Py_SETREF(x, y)";
        # Statements must have the same indentation, otherwise the regex does
        # not match.
        (re.compile(fr'({INDENTATION_REGEX})'
                    + fr'Py_(X?)INCREF\(({EXPR_REGEX})\) *;'
                    + same_indentation(r'\1')
                    + fr'Py_(X?)DECREF\(({EXPR_REGEX})\) *;'
                    + same_indentation(r'\1')
                    + assign_regex_str(r'\5', r'\3'),
                    re.MULTILINE),
         r'\1Py_\4SETREF(\5, Py_\2NewRef(\3));'),

        # "Py_DECREF(x); x = y;" => "Py_SETREF(x, y)";
        # "Py_DECREF(x); x = Py_NewRef(y);" => "Py_SETREF(x, Py_NewRef(y))";
        # Statements must have the same indentation, otherwise the regex does
        # not match.
        (re.compile(fr'({INDENTATION_REGEX})'
                    + fr'Py_(X?)DECREF\(({EXPR_REGEX})\) *;'
                    + same_indentation(r'\1')
                    + assign_regex_str(r'\3',
                                       fr'({SETREF_VALUE})'),
                    re.MULTILINE),
         r'\1Py_\2SETREF(\3, \4);'),

        # "old = var; var = new; Py_DECREF(old);" => "Py_SETREF(var, new);"
        # "PyObject *old = var; var = new; Py_DECREF(old);" => "Py_SETREF(var, new);"
        # Statements must have the same indentation, otherwise the regex does
        # not match.
        (re.compile(fr'({INDENTATION_REGEX})'
                    + fr'(?:{ID_REGEX} *\* *)?({ID_REGEX}) *= *{OPT_CAST_REGEX}({EXPR_REGEX}) *;'
                    + same_indentation(r'\1')
                    + assign_regex_str(r'\3',
                                       fr'({SETREF_VALUE})')
                    + same_indentation(r'\1')
                    + fr'Py_(X?)DECREF\(\2\) *;',
                    re.MULTILINE),
         r'\1Py_\5SETREF(\3, \4);'),
    )
    # Need Py_NewRef(): new in Python 3.5
    NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 5))


class Py_Is(Operation):
    NAME = "Py_Is"

    def replace2(regs):
        x = regs.group(1)
        y = regs.group(2)
        if y == 'NULL':
            return regs.group(0)
        return f'{x} = _Py_StealRef({y});'

    REPLACE = []
    expr = fr'({EXPR_REGEX})'
    for name in ('None', 'True', 'False'):
        REPLACE.extend((
            (re.compile(fr'{expr} == Py_{name}\b'),
             fr'Py_Is{name}(\1)'),
            (re.compile(fr'{expr} != Py_{name}\b'),
             fr'!Py_Is{name}(\1)'),
        ))

    # Need Py_IsNone(), Py_IsTrue(), Py_IsFalse(): new in Python 3.10
    NEED_PYTHONCAPI_COMPAT = (MIN_PYTHON < (3, 10))


OPERATIONS = (
    Py_SET_TYPE,
    Py_SET_SIZE,
    Py_SET_REFCNT,
    # Py_SET_xxx must be run before Py_xxx
    Py_TYPE,
    Py_SIZE,
    Py_REFCNT,

    Py_Is,

    PyObject_NEW,
    PyMem_MALLOC,
    PyObject_MALLOC,

    PyFrame_GetBack,
    PyFrame_GetCode,

    PyThreadState_GetInterpreter,
    PyThreadState_GetFrame,

    # Code style: excluded from "all"
    Py_NewRef,
    Py_CLEAR,
    Py_SETREF,
)

EXCLUDE_FROM_ALL = (
    Py_NewRef,
    Py_CLEAR,
    Py_SETREF,
)


def all_operations():
    return set(operation_class.NAME for operation_class in OPERATIONS
               if operation_class not in EXCLUDE_FROM_ALL)


class Patcher:
    def __init__(self, args=None):
        self.exitcode = 0
        self.pythoncapi_compat_added = 0
        self.want_pythoncapi_compat = False
        self.operations = None
        self.applied_operations = set()

        # Set temporariliy by patch()
        self._has_pythoncapi_compat = None
        self._applied_operations = None

        self._parse_options(args)

    def log(self, msg=''):
        print(msg, file=sys.stderr, flush=True)

    def warning(self, msg):
        self.log(f"WARNING: {msg}")

    def _get_operations(self, parser):
        args_names = self.args.operations.split(',')

        wanted = set()
        for name in args_names:
            name = name.strip()
            if not name:
                continue

            if name == "all":
                wanted |= all_operations()
            elif name.startswith("-"):
                name = name[1:]
                wanted.discard(name)
            else:
                wanted.add(name)

        operations = []
        for operation_class in OPERATIONS:
            name = operation_class.NAME
            if name not in wanted:
                continue
            wanted.discard(name)
            operation = operation_class(self)
            operations.append(operation)

        if wanted:
            print(f"invalid operations: {','.join(wanted)}")
            print()
            self.usage(parser)
            sys.exit(1)

        return operations

    def add_line(self, content, line):
        line = line + '\n'
        # FIXME: tolerate trailing spaces
        if line not in content:
            # FIXME: add macro after the first header comment
            # FIXME: add macro after includes
            # FIXME: add macro after: #define PY_SSIZE_T_CLEAN
            return line + '\n' + content
        else:
            return content

    def add_pythoncapi_compat(self, content):
        if self._has_pythoncapi_compat:
            return content
        content = self.add_line(content, INCLUDE_PYTHONCAPI_COMPAT)
        self._has_pythoncapi_compat = True
        self.pythoncapi_compat_added += 1
        return content

    def _patch(self, content):
        try:
            has = (self.args.no_compat
                   or INCLUDE_PYTHONCAPI_COMPAT in content
                   or INCLUDE_PYTHONCAPI_COMPAT2 in content)
            self._has_pythoncapi_compat = has
            self._applied_operations = []
            for operation in self.operations:
                new_content = operation.patch(content)
                if new_content != content:
                    self._applied_operations.append(operation.NAME)
                content = new_content
            applied_operations = self._applied_operations
        finally:
            self._has_pythoncapi_compat = None
            self._applied_operations = None
        return (content, applied_operations)

    def patch(self, content):
        return self._patch(content)[0]

    def patch_file(self, filename):
        if os.path.basename(filename) == PYTHONCAPI_COMPAT_H:
            self.log(f"Skip {filename}")
            return

        encoding = "utf-8"
        errors = "surrogateescape"

        with open(filename, encoding=encoding, errors=errors) as fp:
            old_contents = fp.read()

        new_contents, operations = self._patch(old_contents)

        if self.args.to_stdout:
            print(new_contents, end="")
            return (new_contents != old_contents)

        # Don't rewrite if the filename for in-place replacement,
        # to avoid changing the file modification time.
        if new_contents == old_contents:
            return False

        if not self.args.no_backup:
            old_filename = filename + ".old"
            # If old_filename already exists, replace it
            os.replace(filename, old_filename)

        with open(filename, "w", encoding=encoding, errors=errors) as fp:
            fp.write(new_contents)

        self.applied_operations |= set(operations)
        operations = ', '.join(operations)
        self.log(f"Patched file: {filename} ({operations})")
        return True

    def _walk_dir(self, path):
        empty = True

        for dirpath, dirnames, filenames in os.walk(path):
            # Don't walk into .tox
            for ignore_name in IGNORE_DIRS:
                try:
                    dirnames.remove(ignore_name)
                except ValueError:
                    pass
            for filename in filenames:
                if is_c_filename(filename):
                    yield os.path.join(dirpath, filename)
                    empty = False

        if empty:
            self.warning(f"Directory {path} doesn't contain any C file")
            self.exitcode = 1

    def walk(self, paths):
        for path in paths:
            if os.path.isdir(path):
                for filename in self._walk_dir(path):
                    yield filename
            elif os.path.exists(path):
                yield path
            else:
                self.warning(f"Path {path} does not exist")
                self.exitcode = 1

    def get_latest_header(self, base_dir):
        target = os.path.join(base_dir, PYTHONCAPI_COMPAT_H)
        self.log(f"Download the file from {PYTHONCAPI_COMPAT_URL} to {target}.")
        urllib.request.urlretrieve(PYTHONCAPI_COMPAT_URL, target)

    @staticmethod
    def usage(parser):
        parser.print_help()
        print()
        print("Operations:")
        print()
        for operation in sorted(OPERATIONS,
                                key=lambda operation: operation.NAME.lower()):
            print(f"- {operation.NAME}")
        print()
        print("If a directory is passed, search for .c and .h files "
              "in subdirectories.")

    def _parse_dir_path(self, path):
        if os.path.isdir(path):
            return path
        else:
            raise argparse.ArgumentTypeError(f"{path} is not a valid path")

    def _parse_options(self, args):
        parser = argparse.ArgumentParser(
            description="Upgrade C extension modules to newer Python C API")
        parser.add_argument(
            '-o', '--operations', action="store",
            default="all",
            help='Space separated list of operation names to apply')
        parser.add_argument(
            '-q', '--quiet', action="store_true",
            help='Quiet mode')
        parser.add_argument(
            '-c', '--to-stdout', action="store_true",
            help='Write output into stdout instead of modifying files '
                 'in-place (imply quiet mode)')
        parser.add_argument(
            '-B', '--no-backup', action="store_true",
            help="Don't create .old backup files")
        parser.add_argument(
            '-C', '--no-compat', action="store_true",
            help=f"Don't add: {INCLUDE_PYTHONCAPI_COMPAT}")
        parser.add_argument(
            '-d', '--download', metavar='PATH',
            help=f'Download latest pythoncapi_compat.h file to designated PATH',
            type=self._parse_dir_path)
        parser.add_argument(
            metavar='file_or_directory', dest="paths", nargs='*')

        args = parser.parse_args(args)
        if not args.paths and not args.download:
            self.usage(parser)
            sys.exit(1)

        if args.to_stdout:
            args.quiet = True

        self.args = args
        self.operations = self._get_operations(parser)

    def main(self):
        if self.args.paths:
            for filename in self.walk(self.args.paths):
                self.patch_file(filename)

        if self.applied_operations:
            nops = len(self.applied_operations)
            ops = ', '.join(sorted(self.applied_operations))
            self.log()
            self.log(f"Applied operations ({nops}): {ops}")

        if self.args.download:
            path = self.args.download
            self.get_latest_header(path)

        if self.pythoncapi_compat_added and not self.args.quiet:
            self.log()
            self.log(f"{INCLUDE_PYTHONCAPI_COMPAT} added: you may have "
                     f"to copy {PYTHONCAPI_COMPAT_H} to your project")
            self.log("Run 'python upgrade_pythoncapi.py --download <target_path>'")

        sys.exit(self.exitcode)


if __name__ == "__main__":
    Patcher().main()
07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!411 blocks
openSUSE Build Service is sponsored by