resolve conflicts with GH-19611
This commit is contained in:
commit
6d721a0ee1
|
@ -8,18 +8,18 @@ Build Status
|
|||
|
||||
+ `Stable buildbots <http://buildbot.python.org/3.x.stable/>`_
|
||||
|
||||
- 3.9
|
||||
|
||||
+ `Stable buildbots <http://buildbot.python.org/3.9.stable/>`_
|
||||
|
||||
- 3.8
|
||||
|
||||
+ `Stable buildbots <http://buildbot.python.org/3.8.stable/>`_
|
||||
|
||||
- 3.7
|
||||
|
||||
+ `Stable buildbots <http://buildbot.python.org/3.7.stable/>`_
|
||||
|
||||
- 3.6
|
||||
|
||||
+ `Stable buildbots <http://buildbot.python.org/3.6.stable/>`_
|
||||
|
||||
- 2.7
|
||||
|
||||
+ `Stable buildbots <http://buildbot.python.org/2.7.stable/>`_
|
||||
|
||||
|
||||
Thank You
|
||||
---------
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "sphinx-problem-matcher",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.*):(\\d+):\\s+(\\w*):\\s+(.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"severity": 3,
|
||||
"message": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "sphinx-problem-matcher-loose",
|
||||
"pattern": [
|
||||
{
|
||||
"_comment": "A bit of a looser pattern, doesn't look for line numbers, just looks for file names relying on them to start with / and end with .rst",
|
||||
"regexp": "(\/.*\\.rst):\\s+(\\w*):\\s+(.*)$",
|
||||
"file": 1,
|
||||
"severity": 2,
|
||||
"message": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "sphinx-problem-matcher-loose-no-severity",
|
||||
"pattern": [
|
||||
{
|
||||
"_comment": "Looks for file names ending with .rst and line numbers but without severity",
|
||||
"regexp": "^(.*\\.rst):(\\d+):(.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"message": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,33 +1,46 @@
|
|||
name: Tests
|
||||
|
||||
# bpo-40548: "paths-ignore" is not used to skip documentation-only PRs, because
|
||||
# it prevents to mark a job as mandatory. A PR cannot be merged if a job is
|
||||
# mandatory but not scheduled because of "paths-ignore".
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- 3.9
|
||||
- 3.8
|
||||
- 3.7
|
||||
paths-ignore:
|
||||
- 'Doc/**'
|
||||
- 'Misc/**'
|
||||
- '**/*.md'
|
||||
- '**/*.rst'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- 3.9
|
||||
- 3.8
|
||||
- 3.7
|
||||
paths-ignore:
|
||||
- 'Doc/**'
|
||||
- 'Misc/**'
|
||||
- '**/*.md'
|
||||
- '**/*.rst'
|
||||
|
||||
jobs:
|
||||
check_source:
|
||||
name: 'Check for source changes'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
run_tests: ${{ steps.check.outputs.run_tests }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Check for source changes
|
||||
id: check
|
||||
run: |
|
||||
if [ -z "GITHUB_BASE_REF" ]; then
|
||||
echo '::set-output name=run_tests::true'
|
||||
else
|
||||
git fetch origin $GITHUB_BASE_REF --depth=1
|
||||
git diff --name-only origin/$GITHUB_BASE_REF... | grep -qvE '(\.rst$|^Doc|^Misc)' && echo '::set-output name=run_tests::true' || true
|
||||
fi
|
||||
build_win32:
|
||||
name: 'Windows (x86)'
|
||||
runs-on: windows-latest
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build CPython
|
||||
run: .\PCbuild\build.bat -e -p Win32
|
||||
- name: Display build info
|
||||
|
@ -38,8 +51,10 @@ jobs:
|
|||
build_win_amd64:
|
||||
name: 'Windows (x64)'
|
||||
runs-on: windows-latest
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build CPython
|
||||
run: .\PCbuild\build.bat -e -p x64
|
||||
- name: Display build info
|
||||
|
@ -50,8 +65,10 @@ jobs:
|
|||
build_macos:
|
||||
name: 'macOS'
|
||||
runs-on: macos-latest
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Configure CPython
|
||||
run: ./configure --with-pydebug --with-openssl=/usr/local/opt/openssl --prefix=/opt/python-dev
|
||||
- name: Build CPython
|
||||
|
@ -64,10 +81,12 @@ jobs:
|
|||
build_ubuntu:
|
||||
name: 'Ubuntu'
|
||||
runs-on: ubuntu-latest
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
env:
|
||||
OPENSSL_VER: 1.1.1f
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install Dependencies
|
||||
run: sudo ./.github/workflows/posix-deps-apt.sh
|
||||
- name: 'Restore OpenSSL build'
|
||||
|
|
|
@ -4,6 +4,7 @@ on:
|
|||
push:
|
||||
branches:
|
||||
- master
|
||||
- 3.9
|
||||
- 3.8
|
||||
- 3.7
|
||||
paths:
|
||||
|
@ -11,6 +12,7 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- 3.9
|
||||
- 3.8
|
||||
- 3.7
|
||||
paths:
|
||||
|
@ -21,7 +23,7 @@ jobs:
|
|||
name: 'Windows (x86) Installer'
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build CPython installer
|
||||
run: .\Tools\msi\build.bat -x86
|
||||
|
||||
|
@ -29,6 +31,6 @@ jobs:
|
|||
name: 'Windows (x64) Installer'
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build CPython installer
|
||||
run: .\Tools\msi\build.bat -x64
|
||||
|
|
|
@ -4,6 +4,7 @@ on:
|
|||
push:
|
||||
branches:
|
||||
- master
|
||||
- 3.9
|
||||
- 3.8
|
||||
- 3.7
|
||||
paths-ignore:
|
||||
|
@ -12,6 +13,7 @@ on:
|
|||
#pull_request:
|
||||
# branches:
|
||||
# - master
|
||||
# - 3.9
|
||||
# - 3.8
|
||||
# - 3.7
|
||||
# paths-ignore:
|
||||
|
@ -25,7 +27,7 @@ jobs:
|
|||
env:
|
||||
OPENSSL_VER: 1.1.1f
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install Dependencies
|
||||
run: sudo ./.github/workflows/posix-deps-apt.sh
|
||||
- name: 'Restore OpenSSL build'
|
||||
|
@ -48,6 +50,7 @@ jobs:
|
|||
./python -m venv .venv
|
||||
source ./.venv/bin/activate
|
||||
python -m pip install -U coverage
|
||||
python -m pip install -r Misc/requirements-test.txt
|
||||
python -m test.pythoninfo
|
||||
- name: 'Tests with coverage'
|
||||
run: >
|
||||
|
@ -73,7 +76,7 @@ jobs:
|
|||
name: 'Ubuntu (C Coverage)'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install Dependencies
|
||||
run: sudo ./.github/workflows/posix-deps-apt.sh
|
||||
- name: Configure CPython
|
||||
|
|
|
@ -4,6 +4,7 @@ on:
|
|||
#push:
|
||||
# branches:
|
||||
# - master
|
||||
# - 3.9
|
||||
# - 3.8
|
||||
# - 3.7
|
||||
# paths:
|
||||
|
@ -11,6 +12,7 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- 3.9
|
||||
- 3.8
|
||||
- 3.7
|
||||
paths:
|
||||
|
@ -22,7 +24,9 @@ jobs:
|
|||
name: 'Docs'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Register Sphinx problem matcher
|
||||
run: echo "::add-matcher::.github/problem-matchers/sphinx.json"
|
||||
- name: 'Install Dependencies'
|
||||
run: sudo ./.github/workflows/posix-deps-apt.sh && sudo apt-get install wamerican
|
||||
- name: 'Configure CPython'
|
||||
|
@ -32,7 +36,7 @@ jobs:
|
|||
- name: 'Install build dependencies'
|
||||
run: make -C Doc/ PYTHON=../python venv
|
||||
- name: 'Build documentation'
|
||||
run: xvfb-run make -C Doc/ PYTHON=../python SPHINXOPTS="-q -W -j4" doctest suspicious html
|
||||
run: xvfb-run make -C Doc/ PYTHON=../python SPHINXOPTS="-q -W --keep-going -j4" doctest suspicious html
|
||||
- name: 'Upload'
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
|
|
|
@ -87,6 +87,7 @@ matrix:
|
|||
# Need a venv that can parse covered code.
|
||||
- ./python -m venv venv
|
||||
- ./venv/bin/python -m pip install -U coverage
|
||||
- ./venv/bin/python -m pip install -r Misc/requirements-test.txt
|
||||
- ./venv/bin/python -m test.pythoninfo
|
||||
script:
|
||||
# Skip tests that re-run the entire test suite.
|
||||
|
|
|
@ -144,7 +144,7 @@ Vectorcall Support API
|
|||
However, the function ``PyVectorcall_NARGS`` should be used to allow
|
||||
for future extensions.
|
||||
|
||||
This function is not part of the `limited API <stable>`_.
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.8
|
||||
|
||||
|
@ -158,7 +158,7 @@ Vectorcall Support API
|
|||
This is mostly useful to check whether or not *op* supports vectorcall,
|
||||
which can be done by checking ``PyVectorcall_Function(op) != NULL``.
|
||||
|
||||
This function is not part of the `limited API <stable>`_.
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.8
|
||||
|
||||
|
@ -172,7 +172,7 @@ Vectorcall Support API
|
|||
It does not check the :const:`Py_TPFLAGS_HAVE_VECTORCALL` flag
|
||||
and it does not fall back to ``tp_call``.
|
||||
|
||||
This function is not part of the `limited API <stable>`_.
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.8
|
||||
|
||||
|
@ -256,7 +256,7 @@ please see individual documentation for details.
|
|||
Return the result of the call on success, or raise an exception and return
|
||||
*NULL* on failure.
|
||||
|
||||
This function is not part of the `limited API <stable>`_.
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
@ -343,7 +343,7 @@ please see individual documentation for details.
|
|||
Return the result of the call on success, or raise an exception and return
|
||||
*NULL* on failure.
|
||||
|
||||
This function is not part of the `limited API <stable>`_.
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
@ -357,7 +357,7 @@ please see individual documentation for details.
|
|||
Return the result of the call on success, or raise an exception and return
|
||||
*NULL* on failure.
|
||||
|
||||
This function is not part of the `limited API <stable>`_.
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
@ -372,7 +372,7 @@ please see individual documentation for details.
|
|||
Return the result of the call on success, or raise an exception and return
|
||||
*NULL* on failure.
|
||||
|
||||
This function is not part of the `limited API <stable>`_.
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
@ -388,7 +388,7 @@ please see individual documentation for details.
|
|||
already has a dictionary ready to use for the keyword arguments,
|
||||
but not a tuple for the positional arguments.
|
||||
|
||||
This function is not part of the `limited API <stable>`_.
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
@ -410,7 +410,7 @@ please see individual documentation for details.
|
|||
Return the result of the call on success, or raise an exception and return
|
||||
*NULL* on failure.
|
||||
|
||||
This function is not part of the `limited API <stable>`_.
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
|
|
@ -1004,6 +1004,8 @@ Private provisional API:
|
|||
|
||||
* :c:member:`PyConfig._init_main`: if set to 0,
|
||||
:c:func:`Py_InitializeFromConfig` stops at the "Core" initialization phase.
|
||||
* :c:member:`PyConfig._isolated_interpreter`: if non-zero,
|
||||
disallow threads, subprocesses and fork.
|
||||
|
||||
.. c:function:: PyStatus _Py_InitializeMain(void)
|
||||
|
||||
|
|
|
@ -129,9 +129,8 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
|
|||
single: OverflowError (built-in exception)
|
||||
|
||||
Return a C :c:type:`long` representation of *obj*. If *obj* is not an
|
||||
instance of :c:type:`PyLongObject`, first call its :meth:`__index__` or
|
||||
:meth:`__int__` method (if present) to convert it to a
|
||||
:c:type:`PyLongObject`.
|
||||
instance of :c:type:`PyLongObject`, first call its :meth:`__index__` method
|
||||
(if present) to convert it to a :c:type:`PyLongObject`.
|
||||
|
||||
Raise :exc:`OverflowError` if the value of *obj* is out of range for a
|
||||
:c:type:`long`.
|
||||
|
@ -141,16 +140,15 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
|
|||
.. versionchanged:: 3.8
|
||||
Use :meth:`__index__` if available.
|
||||
|
||||
.. deprecated:: 3.8
|
||||
Using :meth:`__int__` is deprecated.
|
||||
.. versionchanged:: 3.10
|
||||
This function will no longer use :meth:`__int__`.
|
||||
|
||||
|
||||
.. c:function:: long PyLong_AsLongAndOverflow(PyObject *obj, int *overflow)
|
||||
|
||||
Return a C :c:type:`long` representation of *obj*. If *obj* is not an
|
||||
instance of :c:type:`PyLongObject`, first call its :meth:`__index__` or
|
||||
:meth:`__int__` method (if present) to convert it to a
|
||||
:c:type:`PyLongObject`.
|
||||
instance of :c:type:`PyLongObject`, first call its :meth:`__index__`
|
||||
method (if present) to convert it to a :c:type:`PyLongObject`.
|
||||
|
||||
If the value of *obj* is greater than :const:`LONG_MAX` or less than
|
||||
:const:`LONG_MIN`, set *\*overflow* to ``1`` or ``-1``, respectively, and
|
||||
|
@ -162,8 +160,8 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
|
|||
.. versionchanged:: 3.8
|
||||
Use :meth:`__index__` if available.
|
||||
|
||||
.. deprecated:: 3.8
|
||||
Using :meth:`__int__` is deprecated.
|
||||
.. versionchanged:: 3.10
|
||||
This function will no longer use :meth:`__int__`.
|
||||
|
||||
|
||||
.. c:function:: long long PyLong_AsLongLong(PyObject *obj)
|
||||
|
@ -172,9 +170,8 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
|
|||
single: OverflowError (built-in exception)
|
||||
|
||||
Return a C :c:type:`long long` representation of *obj*. If *obj* is not an
|
||||
instance of :c:type:`PyLongObject`, first call its :meth:`__index__` or
|
||||
:meth:`__int__` method (if present) to convert it to a
|
||||
:c:type:`PyLongObject`.
|
||||
instance of :c:type:`PyLongObject`, first call its :meth:`__index__` method
|
||||
(if present) to convert it to a :c:type:`PyLongObject`.
|
||||
|
||||
Raise :exc:`OverflowError` if the value of *obj* is out of range for a
|
||||
:c:type:`long long`.
|
||||
|
@ -184,16 +181,15 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
|
|||
.. versionchanged:: 3.8
|
||||
Use :meth:`__index__` if available.
|
||||
|
||||
.. deprecated:: 3.8
|
||||
Using :meth:`__int__` is deprecated.
|
||||
.. versionchanged:: 3.10
|
||||
This function will no longer use :meth:`__int__`.
|
||||
|
||||
|
||||
.. c:function:: long long PyLong_AsLongLongAndOverflow(PyObject *obj, int *overflow)
|
||||
|
||||
Return a C :c:type:`long long` representation of *obj*. If *obj* is not an
|
||||
instance of :c:type:`PyLongObject`, first call its :meth:`__index__` or
|
||||
:meth:`__int__` method (if present) to convert it to a
|
||||
:c:type:`PyLongObject`.
|
||||
instance of :c:type:`PyLongObject`, first call its :meth:`__index__` method
|
||||
(if present) to convert it to a :c:type:`PyLongObject`.
|
||||
|
||||
If the value of *obj* is greater than :const:`LLONG_MAX` or less than
|
||||
:const:`LLONG_MIN`, set *\*overflow* to ``1`` or ``-1``, respectively,
|
||||
|
@ -207,8 +203,8 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
|
|||
.. versionchanged:: 3.8
|
||||
Use :meth:`__index__` if available.
|
||||
|
||||
.. deprecated:: 3.8
|
||||
Using :meth:`__int__` is deprecated.
|
||||
.. versionchanged:: 3.10
|
||||
This function will no longer use :meth:`__int__`.
|
||||
|
||||
|
||||
.. c:function:: Py_ssize_t PyLong_AsSsize_t(PyObject *pylong)
|
||||
|
@ -278,10 +274,9 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
|
|||
|
||||
.. c:function:: unsigned long PyLong_AsUnsignedLongMask(PyObject *obj)
|
||||
|
||||
Return a C :c:type:`unsigned long` representation of *obj*. If *obj*
|
||||
is not an instance of :c:type:`PyLongObject`, first call its
|
||||
:meth:`__index__` or :meth:`__int__` method (if present) to convert
|
||||
it to a :c:type:`PyLongObject`.
|
||||
Return a C :c:type:`unsigned long` representation of *obj*. If *obj* is not
|
||||
an instance of :c:type:`PyLongObject`, first call its :meth:`__index__`
|
||||
method (if present) to convert it to a :c:type:`PyLongObject`.
|
||||
|
||||
If the value of *obj* is out of range for an :c:type:`unsigned long`,
|
||||
return the reduction of that value modulo ``ULONG_MAX + 1``.
|
||||
|
@ -292,16 +287,16 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
|
|||
.. versionchanged:: 3.8
|
||||
Use :meth:`__index__` if available.
|
||||
|
||||
.. deprecated:: 3.8
|
||||
Using :meth:`__int__` is deprecated.
|
||||
.. versionchanged:: 3.10
|
||||
This function will no longer use :meth:`__int__`.
|
||||
|
||||
|
||||
.. c:function:: unsigned long long PyLong_AsUnsignedLongLongMask(PyObject *obj)
|
||||
|
||||
Return a C :c:type:`unsigned long long` representation of *obj*. If *obj*
|
||||
is not an instance of :c:type:`PyLongObject`, first call its
|
||||
:meth:`__index__` or :meth:`__int__` method (if present) to convert
|
||||
it to a :c:type:`PyLongObject`.
|
||||
:meth:`__index__` method (if present) to convert it to a
|
||||
:c:type:`PyLongObject`.
|
||||
|
||||
If the value of *obj* is out of range for an :c:type:`unsigned long long`,
|
||||
return the reduction of that value modulo ``ULLONG_MAX + 1``.
|
||||
|
@ -312,8 +307,8 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
|
|||
.. versionchanged:: 3.8
|
||||
Use :meth:`__index__` if available.
|
||||
|
||||
.. deprecated:: 3.8
|
||||
Using :meth:`__int__` is deprecated.
|
||||
.. versionchanged:: 3.10
|
||||
This function will no longer use :meth:`__int__`.
|
||||
|
||||
|
||||
.. c:function:: double PyLong_AsDouble(PyObject *pylong)
|
||||
|
|
|
@ -256,6 +256,10 @@ Number Protocol
|
|||
Returns the *o* converted to a Python int on success or ``NULL`` with a
|
||||
:exc:`TypeError` exception raised on failure.
|
||||
|
||||
.. versionchanged:: 3.10
|
||||
The result always has exact type :class:`int`. Previously, the result
|
||||
could have been an instance of a subclass of ``int``.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyNumber_ToBase(PyObject *n, int base)
|
||||
|
||||
|
|
|
@ -62,12 +62,15 @@ the definition of all other Python objects.
|
|||
See documentation of :c:type:`PyVarObject` above.
|
||||
|
||||
|
||||
.. c:macro:: Py_TYPE(o)
|
||||
.. c:function:: PyTypeObject* Py_TYPE(const PyObject *o)
|
||||
|
||||
This macro is used to access the :attr:`ob_type` member of a Python object.
|
||||
It expands to::
|
||||
Get the type of the Python object *o*.
|
||||
|
||||
(((PyObject*)(o))->ob_type)
|
||||
Return a borrowed reference.
|
||||
|
||||
.. versionchanged:: 3.10
|
||||
:c:func:`Py_TYPE()` is changed to the inline static function.
|
||||
Use :c:func:`Py_SET_TYPE()` to set an object type.
|
||||
|
||||
|
||||
.. c:function:: int Py_IS_TYPE(PyObject *o, PyTypeObject *type)
|
||||
|
@ -85,13 +88,13 @@ the definition of all other Python objects.
|
|||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
.. c:macro:: Py_REFCNT(o)
|
||||
.. c:function:: Py_ssize_t Py_REFCNT(const PyObject *o)
|
||||
|
||||
This macro is used to access the :attr:`ob_refcnt` member of a Python
|
||||
object.
|
||||
It expands to::
|
||||
Get the reference count of the Python object *o*.
|
||||
|
||||
(((PyObject*)(o))->ob_refcnt)
|
||||
.. versionchanged:: 3.10
|
||||
:c:func:`Py_REFCNT()` is changed to the inline static function.
|
||||
Use :c:func:`Py_SET_REFCNT()` to set an object reference count.
|
||||
|
||||
|
||||
.. c:function:: void Py_SET_REFCNT(PyObject *o, Py_ssize_t refcnt)
|
||||
|
@ -101,12 +104,13 @@ the definition of all other Python objects.
|
|||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
.. c:macro:: Py_SIZE(o)
|
||||
.. c:function:: Py_ssize_t Py_SIZE(const PyVarObject *o)
|
||||
|
||||
This macro is used to access the :attr:`ob_size` member of a Python object.
|
||||
It expands to::
|
||||
Get the size of the Python object *o*.
|
||||
|
||||
(((PyVarObject*)(o))->ob_size)
|
||||
.. versionchanged:: 3.10
|
||||
:c:func:`Py_SIZE()` is changed to the inline static function.
|
||||
Use :c:func:`Py_SET_SIZE()` to set an object size.
|
||||
|
||||
|
||||
.. c:function:: void Py_SET_SIZE(PyVarObject *o, Py_ssize_t size)
|
||||
|
@ -147,23 +151,56 @@ Implementing functions and methods
|
|||
value of the function as exposed in Python. The function must return a new
|
||||
reference.
|
||||
|
||||
The function signature is::
|
||||
|
||||
PyObject *PyCFunction(PyObject *self,
|
||||
PyObject *args);
|
||||
|
||||
.. c:type:: PyCFunctionWithKeywords
|
||||
|
||||
Type of the functions used to implement Python callables in C
|
||||
with signature :const:`METH_VARARGS | METH_KEYWORDS`.
|
||||
The function signature is::
|
||||
|
||||
PyObject *PyCFunctionWithKeywords(PyObject *self,
|
||||
PyObject *args,
|
||||
PyObject *kwargs);
|
||||
|
||||
|
||||
.. c:type:: _PyCFunctionFast
|
||||
|
||||
Type of the functions used to implement Python callables in C
|
||||
with signature :const:`METH_FASTCALL`.
|
||||
The function signature is::
|
||||
|
||||
PyObject *_PyCFunctionFast(PyObject *self,
|
||||
PyObject *const *args,
|
||||
Py_ssize_t nargs);
|
||||
|
||||
.. c:type:: _PyCFunctionFastWithKeywords
|
||||
|
||||
Type of the functions used to implement Python callables in C
|
||||
with signature :const:`METH_FASTCALL | METH_KEYWORDS`.
|
||||
The function signature is::
|
||||
|
||||
PyObject *_PyCFunctionFastWithKeywords(PyObject *self,
|
||||
PyObject *const *args,
|
||||
Py_ssize_t nargs,
|
||||
PyObject *kwnames);
|
||||
|
||||
.. c:type:: PyCMethod
|
||||
|
||||
Type of the functions used to implement Python callables in C
|
||||
with signature :const:`METH_METHOD | METH_FASTCALL | METH_KEYWORDS`.
|
||||
The function signature is::
|
||||
|
||||
PyObject *PyCMethod(PyObject *self,
|
||||
PyTypeObject *defining_class,
|
||||
PyObject *const *args,
|
||||
Py_ssize_t nargs,
|
||||
PyObject *kwnames)
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
.. c:type:: PyMethodDef
|
||||
|
@ -197,9 +234,7 @@ The :attr:`ml_flags` field is a bitfield which can include the following flags.
|
|||
The individual flags indicate either a calling convention or a binding
|
||||
convention.
|
||||
|
||||
There are four basic calling conventions for positional arguments
|
||||
and two of them can be combined with :const:`METH_KEYWORDS` to support
|
||||
also keyword arguments. So there are a total of 6 calling conventions:
|
||||
There are these calling conventions:
|
||||
|
||||
.. data:: METH_VARARGS
|
||||
|
||||
|
@ -250,6 +285,19 @@ also keyword arguments. So there are a total of 6 calling conventions:
|
|||
.. versionadded:: 3.7
|
||||
|
||||
|
||||
.. data:: METH_METHOD | METH_FASTCALL | METH_KEYWORDS
|
||||
|
||||
Extension of :const:`METH_FASTCALL | METH_KEYWORDS` supporting the *defining
|
||||
class*, that is, the class that contains the method in question.
|
||||
The defining class might be a superclass of ``Py_TYPE(self)``.
|
||||
|
||||
The method needs to be of type :c:type:`PyCMethod`, the same as for
|
||||
``METH_FASTCALL | METH_KEYWORDS`` with ``defining_class`` argument added after
|
||||
``self``.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
.. data:: METH_NOARGS
|
||||
|
||||
Methods without parameters don't need to check whether arguments are given if
|
||||
|
@ -380,9 +428,11 @@ Accessing attributes of extension types
|
|||
|
||||
Heap allocated types (created using :c:func:`PyType_FromSpec` or similar),
|
||||
``PyMemberDef`` may contain definitions for the special members
|
||||
``__dictoffset__`` and ``__weaklistoffset__``, corresponding to
|
||||
:c:member:`~PyTypeObject.tp_dictoffset` and
|
||||
:c:member:`~PyTypeObject.tp_weaklistoffset` in type objects.
|
||||
``__dictoffset__``, ``__weaklistoffset__`` and ``__vectorcalloffset__``,
|
||||
corresponding to
|
||||
:c:member:`~PyTypeObject.tp_dictoffset`,
|
||||
:c:member:`~PyTypeObject.tp_weaklistoffset` and
|
||||
:c:member:`~PyTypeObject.tp_vectorcall_offset` in type objects.
|
||||
These must be defined with ``T_PYSSIZET`` and ``READONLY``, for example::
|
||||
|
||||
static PyMemberDef spam_type_members[] = {
|
||||
|
|
|
@ -109,6 +109,30 @@ Type Objects
|
|||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
.. c:function:: PyObject* PyType_GetModule(PyTypeObject *type)
|
||||
|
||||
Return the module object associated with the given type when the type was
|
||||
created using :c:func:`PyType_FromModuleAndSpec`.
|
||||
|
||||
If no module is associated with the given type, sets :py:class:`TypeError`
|
||||
and returns ``NULL``.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
.. c:function:: void* PyType_GetModuleState(PyTypeObject *type)
|
||||
|
||||
Return the state of the module object associated with the given type.
|
||||
This is a shortcut for calling :c:func:`PyModule_GetState()` on the result
|
||||
of :c:func:`PyType_GetModule`.
|
||||
|
||||
If no module is associated with the given type, sets :py:class:`TypeError`
|
||||
and returns ``NULL``.
|
||||
|
||||
If the *type* has an associated module but its state is ``NULL``,
|
||||
returns ``NULL`` without setting an exception.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
Creating Heap-Allocated Types
|
||||
.............................
|
||||
|
@ -116,7 +140,7 @@ Creating Heap-Allocated Types
|
|||
The following functions and structs are used to create
|
||||
:ref:`heap types <heap-types>`.
|
||||
|
||||
.. c:function:: PyObject* PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
|
||||
.. c:function:: PyObject* PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
|
||||
|
||||
Creates and returns a heap type object from the *spec*
|
||||
(:const:`Py_TPFLAGS_HEAPTYPE`).
|
||||
|
@ -127,8 +151,18 @@ The following functions and structs are used to create
|
|||
If *bases* is ``NULL``, the *Py_tp_base* slot is used instead.
|
||||
If that also is ``NULL``, the new type derives from :class:`object`.
|
||||
|
||||
The *module* must be a module object or ``NULL``.
|
||||
If not ``NULL``, the module is associated with the new type and can later be
|
||||
retreived with :c:func:`PyType_GetModule`.
|
||||
|
||||
This function calls :c:func:`PyType_Ready` on the new type.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
.. c:function:: PyObject* PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
|
||||
|
||||
Equivalent to ``PyType_FromModuleAndSpec(NULL, spec, bases)``.
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
.. c:function:: PyObject* PyType_FromSpec(PyType_Spec *spec)
|
||||
|
@ -194,6 +228,7 @@ The following functions and structs are used to create
|
|||
* :c:member:`~PyTypeObject.tp_dictoffset`
|
||||
(see :ref:`PyMemberDef <pymemberdef-offsets>`)
|
||||
* :c:member:`~PyTypeObject.tp_vectorcall_offset`
|
||||
(see :ref:`PyMemberDef <pymemberdef-offsets>`)
|
||||
* :c:member:`~PyBufferProcs.bf_getbuffer`
|
||||
* :c:member:`~PyBufferProcs.bf_releasebuffer`
|
||||
|
||||
|
|
|
@ -1223,11 +1223,25 @@ and :c:type:`PyType_Type` effectively act as defaults.)
|
|||
but the instance has no strong reference to the elements inside it, as they
|
||||
are allowed to be removed even if the instance is still alive).
|
||||
|
||||
|
||||
Note that :c:func:`Py_VISIT` requires the *visit* and *arg* parameters to
|
||||
:c:func:`local_traverse` to have these specific names; don't name them just
|
||||
anything.
|
||||
|
||||
Heap-allocated types (:const:`Py_TPFLAGS_HEAPTYPE`, such as those created
|
||||
with :c:func:`PyType_FromSpec` and similar APIs) hold a reference to their
|
||||
type. Their traversal function must therefore either visit
|
||||
:c:func:`Py_TYPE(self) <Py_TYPE>`, or delegate this responsibility by
|
||||
calling ``tp_traverse`` of another heap-allocated type (such as a
|
||||
heap-allocated superclass).
|
||||
If they do not, the type object may not be garbage-collected.
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
|
||||
Heap-allocated types are expected to visit ``Py_TYPE(self)`` in
|
||||
``tp_traverse``. In earlier versions of Python, due to
|
||||
`bug 40217 <https://bugs.python.org/issue40217>`_, doing this
|
||||
may lead to crashes in subclasses.
|
||||
|
||||
**Inheritance:**
|
||||
|
||||
Group: :const:`Py_TPFLAGS_HAVE_GC`, :attr:`tp_traverse`, :attr:`tp_clear`
|
||||
|
|
|
@ -14,7 +14,8 @@ sys.path.append(os.path.abspath('includes'))
|
|||
# ---------------------
|
||||
|
||||
extensions = ['sphinx.ext.coverage', 'sphinx.ext.doctest',
|
||||
'pyspecific', 'c_annotations', 'escape4chm']
|
||||
'pyspecific', 'c_annotations', 'escape4chm',
|
||||
'asdl_highlight']
|
||||
|
||||
|
||||
doctest_global_setup = '''
|
||||
|
|
|
@ -651,7 +651,7 @@ Why doesn't Python have a "with" statement for attribute assignments?
|
|||
---------------------------------------------------------------------
|
||||
|
||||
Python has a 'with' statement that wraps the execution of a block, calling code
|
||||
on the entrance and exit from the block. Some language have a construct that
|
||||
on the entrance and exit from the block. Some languages have a construct that
|
||||
looks like this::
|
||||
|
||||
with obj:
|
||||
|
|
|
@ -353,7 +353,7 @@ Our program keeps growing in complexity::
|
|||
args = parser.parse_args()
|
||||
answer = args.square**2
|
||||
if args.verbose:
|
||||
print("the square of {} equals {}".format(args.square, answer))
|
||||
print(f"the square of {args.square} equals {answer}")
|
||||
else:
|
||||
print(answer)
|
||||
|
||||
|
@ -387,9 +387,9 @@ multiple verbosity values, and actually get to use them::
|
|||
args = parser.parse_args()
|
||||
answer = args.square**2
|
||||
if args.verbosity == 2:
|
||||
print("the square of {} equals {}".format(args.square, answer))
|
||||
print(f"the square of {args.square} equals {answer}")
|
||||
elif args.verbosity == 1:
|
||||
print("{}^2 == {}".format(args.square, answer))
|
||||
print(f"{args.square}^2 == {answer}")
|
||||
else:
|
||||
print(answer)
|
||||
|
||||
|
@ -421,9 +421,9 @@ Let's fix it by restricting the values the ``--verbosity`` option can accept::
|
|||
args = parser.parse_args()
|
||||
answer = args.square**2
|
||||
if args.verbosity == 2:
|
||||
print("the square of {} equals {}".format(args.square, answer))
|
||||
print(f"the square of {args.square} equals {answer}")
|
||||
elif args.verbosity == 1:
|
||||
print("{}^2 == {}".format(args.square, answer))
|
||||
print(f"{args.square}^2 == {answer}")
|
||||
else:
|
||||
print(answer)
|
||||
|
||||
|
@ -461,9 +461,9 @@ verbosity argument (check the output of ``python --help``)::
|
|||
args = parser.parse_args()
|
||||
answer = args.square**2
|
||||
if args.verbosity == 2:
|
||||
print("the square of {} equals {}".format(args.square, answer))
|
||||
print(f"the square of {args.square} equals {answer}")
|
||||
elif args.verbosity == 1:
|
||||
print("{}^2 == {}".format(args.square, answer))
|
||||
print(f"{args.square}^2 == {answer}")
|
||||
else:
|
||||
print(answer)
|
||||
|
||||
|
@ -529,9 +529,9 @@ Let's fix::
|
|||
|
||||
# bugfix: replace == with >=
|
||||
if args.verbosity >= 2:
|
||||
print("the square of {} equals {}".format(args.square, answer))
|
||||
print(f"the square of {args.square} equals {answer}")
|
||||
elif args.verbosity >= 1:
|
||||
print("{}^2 == {}".format(args.square, answer))
|
||||
print(f"{args.square}^2 == {answer}")
|
||||
else:
|
||||
print(answer)
|
||||
|
||||
|
@ -566,9 +566,9 @@ Let's fix that bug::
|
|||
args = parser.parse_args()
|
||||
answer = args.square**2
|
||||
if args.verbosity >= 2:
|
||||
print("the square of {} equals {}".format(args.square, answer))
|
||||
print(f"the square of {args.square} equals {answer}")
|
||||
elif args.verbosity >= 1:
|
||||
print("{}^2 == {}".format(args.square, answer))
|
||||
print(f"{args.square}^2 == {answer}")
|
||||
else:
|
||||
print(answer)
|
||||
|
||||
|
@ -606,9 +606,9 @@ not just squares::
|
|||
args = parser.parse_args()
|
||||
answer = args.x**args.y
|
||||
if args.verbosity >= 2:
|
||||
print("{} to the power {} equals {}".format(args.x, args.y, answer))
|
||||
print(f"{args.x} to the power {args.y} equals {answer}")
|
||||
elif args.verbosity >= 1:
|
||||
print("{}^{} == {}".format(args.x, args.y, answer))
|
||||
print(f"{args.x}^{args.y} == {answer}")
|
||||
else:
|
||||
print(answer)
|
||||
|
||||
|
@ -645,9 +645,9 @@ to display *more* text instead::
|
|||
args = parser.parse_args()
|
||||
answer = args.x**args.y
|
||||
if args.verbosity >= 2:
|
||||
print("Running '{}'".format(__file__))
|
||||
print(f"Running '{__file__}'")
|
||||
if args.verbosity >= 1:
|
||||
print("{}^{} == ".format(args.x, args.y), end="")
|
||||
print(f"{args.x}^{args.y} == ", end="")
|
||||
print(answer)
|
||||
|
||||
Output:
|
||||
|
@ -688,9 +688,9 @@ which will be the opposite of the ``--verbose`` one::
|
|||
if args.quiet:
|
||||
print(answer)
|
||||
elif args.verbose:
|
||||
print("{} to the power {} equals {}".format(args.x, args.y, answer))
|
||||
print(f"{args.x} to the power {args.y} equals {answer}")
|
||||
else:
|
||||
print("{}^{} == {}".format(args.x, args.y, answer))
|
||||
print(f"{args.x}^{args.y} == {answer}")
|
||||
|
||||
Our program is now simpler, and we've lost some functionality for the sake of
|
||||
demonstration. Anyways, here's the output:
|
||||
|
|
|
@ -319,7 +319,7 @@ inside-out.
|
|||
|
||||
In Python, you use ``socket.setblocking(False)`` to make it non-blocking. In C, it's
|
||||
more complex, (for one thing, you'll need to choose between the BSD flavor
|
||||
``O_NONBLOCK`` and the almost indistinguishable Posix flavor ``O_NDELAY``, which
|
||||
``O_NONBLOCK`` and the almost indistinguishable POSIX flavor ``O_NDELAY``, which
|
||||
is completely different from ``TCP_NODELAY``), but it's the exact same idea. You
|
||||
do this after creating the socket, but before using it. (Actually, if you're
|
||||
nuts, you can switch back and forth.)
|
||||
|
|
|
@ -961,19 +961,6 @@ values are:
|
|||
usage: PROG [-h] foo [foo ...]
|
||||
PROG: error: the following arguments are required: foo
|
||||
|
||||
.. _`argparse.REMAINDER`:
|
||||
|
||||
* ``argparse.REMAINDER``. All the remaining command-line arguments are gathered
|
||||
into a list. This is commonly useful for command line utilities that dispatch
|
||||
to other command line utilities::
|
||||
|
||||
>>> parser = argparse.ArgumentParser(prog='PROG')
|
||||
>>> parser.add_argument('--foo')
|
||||
>>> parser.add_argument('command')
|
||||
>>> parser.add_argument('args', nargs=argparse.REMAINDER)
|
||||
>>> print(parser.parse_args('--foo B cmd --arg1 XX ZZ'.split()))
|
||||
Namespace(args=['--arg1', 'XX', 'ZZ'], command='cmd', foo='B')
|
||||
|
||||
If the ``nargs`` keyword argument is not provided, the number of arguments consumed
|
||||
is determined by the action_. Generally this means a single command-line argument
|
||||
will be consumed and a single item (not a list) will be produced.
|
||||
|
|
|
@ -22,7 +22,7 @@ defined:
|
|||
+-----------+--------------------+-------------------+-----------------------+-------+
|
||||
| ``'B'`` | unsigned char | int | 1 | |
|
||||
+-----------+--------------------+-------------------+-----------------------+-------+
|
||||
| ``'u'`` | Py_UNICODE | Unicode character | 2 | \(1) |
|
||||
| ``'u'`` | wchar_t | Unicode character | 2 | \(1) |
|
||||
+-----------+--------------------+-------------------+-----------------------+-------+
|
||||
| ``'h'`` | signed short | int | 2 | |
|
||||
+-----------+--------------------+-------------------+-----------------------+-------+
|
||||
|
@ -48,15 +48,16 @@ defined:
|
|||
Notes:
|
||||
|
||||
(1)
|
||||
The ``'u'`` type code corresponds to Python's obsolete unicode character
|
||||
(:c:type:`Py_UNICODE` which is :c:type:`wchar_t`). Depending on the
|
||||
platform, it can be 16 bits or 32 bits.
|
||||
It can be 16 bits or 32 bits depending on the platform.
|
||||
|
||||
``'u'`` will be removed together with the rest of the :c:type:`Py_UNICODE`
|
||||
API.
|
||||
.. versionchanged:: 3.9
|
||||
``array('u')`` now uses ``wchar_t`` as C type instead of deprecated
|
||||
``Py_UNICODE``. This change doesn't affect to its behavior because
|
||||
``Py_UNICODE`` is alias of ``wchar_t`` since Python 3.3.
|
||||
|
||||
.. deprecated-removed:: 3.3 4.0
|
||||
|
||||
|
||||
The actual representation of values is determined by the machine architecture
|
||||
(strictly speaking, by the C implementation). The actual size can be accessed
|
||||
through the :attr:`itemsize` attribute.
|
||||
|
|
|
@ -35,7 +35,7 @@ Abstract Grammar
|
|||
The abstract grammar is currently defined as follows:
|
||||
|
||||
.. literalinclude:: ../../Parser/Python.asdl
|
||||
:language: none
|
||||
:language: asdl
|
||||
|
||||
|
||||
Node classes
|
||||
|
|
|
@ -48,6 +48,9 @@ await on multiple things with timeouts.
|
|||
* - :class:`Task`
|
||||
- Task object.
|
||||
|
||||
* - :func:`to_thread`
|
||||
- Asychronously run a function in a separate OS thread.
|
||||
|
||||
* - :func:`run_coroutine_threadsafe`
|
||||
- Schedule a coroutine from another OS thread.
|
||||
|
||||
|
|
|
@ -170,7 +170,7 @@ Future Object
|
|||
Returns the number of callbacks removed, which is typically 1,
|
||||
unless a callback was added more than once.
|
||||
|
||||
.. method:: cancel()
|
||||
.. method:: cancel(msg=None)
|
||||
|
||||
Cancel the Future and schedule callbacks.
|
||||
|
||||
|
@ -178,6 +178,9 @@ Future Object
|
|||
Otherwise, change the Future's state to *cancelled*,
|
||||
schedule the callbacks, and return ``True``.
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
Added the ``msg`` parameter.
|
||||
|
||||
.. method:: exception()
|
||||
|
||||
Return the exception that was set on this Future.
|
||||
|
@ -255,3 +258,6 @@ the Future has a result::
|
|||
- asyncio Future is not compatible with the
|
||||
:func:`concurrent.futures.wait` and
|
||||
:func:`concurrent.futures.as_completed` functions.
|
||||
|
||||
- :meth:`asyncio.Future.cancel` accepts an optional ``msg`` argument,
|
||||
but :func:`concurrent.futures.cancel` does not.
|
||||
|
|
|
@ -95,14 +95,14 @@ Creating Subprocesses
|
|||
See the documentation of :meth:`loop.subprocess_shell` for other
|
||||
parameters.
|
||||
|
||||
.. important::
|
||||
.. important::
|
||||
|
||||
It is the application's responsibility to ensure that all whitespace and
|
||||
special characters are quoted appropriately to avoid `shell injection
|
||||
<https://en.wikipedia.org/wiki/Shell_injection#Shell_injection>`_
|
||||
vulnerabilities. The :func:`shlex.quote` function can be used to properly
|
||||
escape whitespace and special shell characters in strings that are going
|
||||
to be used to construct shell commands.
|
||||
It is the application's responsibility to ensure that all whitespace and
|
||||
special characters are quoted appropriately to avoid `shell injection
|
||||
<https://en.wikipedia.org/wiki/Shell_injection#Shell_injection>`_
|
||||
vulnerabilities. The :func:`shlex.quote` function can be used to properly
|
||||
escape whitespace and special shell characters in strings that are going
|
||||
to be used to construct shell commands.
|
||||
|
||||
.. deprecated-removed:: 3.8 3.10
|
||||
|
||||
|
|
|
@ -453,7 +453,8 @@ Timeouts
|
|||
wrap it in :func:`shield`.
|
||||
|
||||
The function will wait until the future is actually cancelled,
|
||||
so the total wait time may exceed the *timeout*.
|
||||
so the total wait time may exceed the *timeout*. If an exception
|
||||
happens during cancellation, it is propagated.
|
||||
|
||||
If the wait is cancelled, the future *aw* is also cancelled.
|
||||
|
||||
|
@ -498,6 +499,8 @@ Waiting Primitives
|
|||
set concurrently and block until the condition specified
|
||||
by *return_when*.
|
||||
|
||||
The *aws* set must not be empty.
|
||||
|
||||
Returns two sets of Tasks/Futures: ``(done, pending)``.
|
||||
|
||||
Usage::
|
||||
|
@ -573,7 +576,7 @@ Waiting Primitives
|
|||
if task in done:
|
||||
# Everything will work as expected now.
|
||||
|
||||
.. deprecated:: 3.8
|
||||
.. deprecated-removed:: 3.8 3.11
|
||||
|
||||
Passing coroutine objects to ``wait()`` directly is
|
||||
deprecated.
|
||||
|
@ -582,9 +585,9 @@ Waiting Primitives
|
|||
.. function:: as_completed(aws, \*, loop=None, timeout=None)
|
||||
|
||||
Run :ref:`awaitable objects <asyncio-awaitables>` in the *aws*
|
||||
set concurrently. Return an iterator of :class:`Future` objects.
|
||||
Each Future object returned represents the earliest result
|
||||
from the set of the remaining awaitables.
|
||||
set concurrently. Return an iterator of coroutines.
|
||||
Each coroutine returned can be awaited to get the earliest next
|
||||
result from the set of the remaining awaitables.
|
||||
|
||||
Raises :exc:`asyncio.TimeoutError` if the timeout occurs before
|
||||
all Futures are done.
|
||||
|
@ -594,11 +597,71 @@ Waiting Primitives
|
|||
|
||||
Example::
|
||||
|
||||
for f in as_completed(aws):
|
||||
earliest_result = await f
|
||||
for coro in as_completed(aws):
|
||||
earliest_result = await coro
|
||||
# ...
|
||||
|
||||
|
||||
Running in Threads
|
||||
==================
|
||||
|
||||
.. coroutinefunction:: to_thread(func, /, \*args, \*\*kwargs)
|
||||
|
||||
Asynchronously run function *func* in a separate thread.
|
||||
|
||||
Any \*args and \*\*kwargs supplied for this function are directly passed
|
||||
to *func*. Also, the current :class:`contextvars.Context` is propogated,
|
||||
allowing context variables from the event loop thread to be accessed in the
|
||||
separate thread.
|
||||
|
||||
Return an :class:`asyncio.Future` which represents the eventual result of
|
||||
*func*.
|
||||
|
||||
This coroutine function is primarily intended to be used for executing
|
||||
IO-bound functions/methods that would otherwise block the event loop if
|
||||
they were ran in the main thread. For example::
|
||||
|
||||
def blocking_io():
|
||||
print(f"start blocking_io at {time.strftime('%X')}")
|
||||
# Note that time.sleep() can be replaced with any blocking
|
||||
# IO-bound operation, such as file operations.
|
||||
time.sleep(1)
|
||||
print(f"blocking_io complete at {time.strftime('%X')}")
|
||||
|
||||
async def main():
|
||||
print(f"started main at {time.strftime('%X')}")
|
||||
|
||||
await asyncio.gather(
|
||||
asyncio.to_thread(blocking_io),
|
||||
asyncio.sleep(1))
|
||||
|
||||
print(f"finished main at {time.strftime('%X')}")
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
|
||||
# Expected output:
|
||||
#
|
||||
# started main at 19:50:53
|
||||
# start blocking_io at 19:50:53
|
||||
# blocking_io complete at 19:50:54
|
||||
# finished main at 19:50:54
|
||||
|
||||
Directly calling `blocking_io()` in any coroutine would block the event loop
|
||||
for its duration, resulting in an additional 1 second of run time. Instead,
|
||||
by using `asyncio.to_thread()`, we can run it in a separate thread without
|
||||
blocking the event loop.
|
||||
|
||||
.. note::
|
||||
|
||||
Due to the :term:`GIL`, `asyncio.to_thread()` can typically only be used
|
||||
to make IO-bound functions non-blocking. However, for extension modules
|
||||
that release the GIL or alternative Python implementations that don't
|
||||
have one, `asyncio.to_thread()` can also be used for CPU-bound functions.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
Scheduling From Other Threads
|
||||
=============================
|
||||
|
||||
|
@ -721,7 +784,7 @@ Task Object
|
|||
.. deprecated-removed:: 3.8 3.10
|
||||
The *loop* parameter.
|
||||
|
||||
.. method:: cancel()
|
||||
.. method:: cancel(msg=None)
|
||||
|
||||
Request the Task to be cancelled.
|
||||
|
||||
|
@ -736,6 +799,9 @@ Task Object
|
|||
suppressing cancellation completely is not common and is actively
|
||||
discouraged.
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
Added the ``msg`` parameter.
|
||||
|
||||
.. _asyncio_example_task_cancel:
|
||||
|
||||
The following example illustrates how coroutines can intercept
|
||||
|
|
|
@ -56,8 +56,8 @@ build applications which provide an interactive interpreter prompt.
|
|||
|
||||
*source* is the source string; *filename* is the optional filename from which
|
||||
source was read, defaulting to ``'<input>'``; and *symbol* is the optional
|
||||
grammar start symbol, which should be either ``'single'`` (the default) or
|
||||
``'eval'``.
|
||||
grammar start symbol, which should be ``'single'`` (the default), ``'eval'``
|
||||
or ``'exec'``.
|
||||
|
||||
Returns a code object (the same as ``compile(source, filename, symbol)``) if the
|
||||
command is complete and valid; ``None`` if the command is incomplete; raises
|
||||
|
|
|
@ -43,8 +43,9 @@ To do just the former:
|
|||
:exc:`OverflowError` or :exc:`ValueError` if there is an invalid literal.
|
||||
|
||||
The *symbol* argument determines whether *source* is compiled as a statement
|
||||
(``'single'``, the default) or as an :term:`expression` (``'eval'``). Any
|
||||
other value will cause :exc:`ValueError` to be raised.
|
||||
(``'single'``, the default), as a sequence of statements (``'exec'``) or
|
||||
as an :term:`expression` (``'eval'``). Any other value will
|
||||
cause :exc:`ValueError` to be raised.
|
||||
|
||||
.. note::
|
||||
|
||||
|
|
|
@ -290,6 +290,47 @@ For example::
|
|||
>>> sorted(c.elements())
|
||||
['a', 'a', 'a', 'a', 'b', 'b']
|
||||
|
||||
.. method:: isdisjoint(other)
|
||||
|
||||
True if none of the elements in *self* overlap with those in *other*.
|
||||
Negative or missing counts are ignored.
|
||||
Logically equivalent to: ``not (+self) & (+other)``
|
||||
|
||||
.. versionadded:: 3.10
|
||||
|
||||
.. method:: isequal(other)
|
||||
|
||||
Test whether counts agree exactly.
|
||||
Negative or missing counts are treated as zero.
|
||||
|
||||
This method works differently than the inherited :meth:`__eq__` method
|
||||
which treats negative or missing counts as distinct from zero::
|
||||
|
||||
>>> Counter(a=1, b=0).isequal(Counter(a=1))
|
||||
True
|
||||
>>> Counter(a=1, b=0) == Counter(a=1)
|
||||
False
|
||||
|
||||
Logically equivalent to: ``+self == +other``
|
||||
|
||||
.. versionadded:: 3.10
|
||||
|
||||
.. method:: issubset(other)
|
||||
|
||||
True if the counts in *self* are less than or equal to those in *other*.
|
||||
Negative or missing counts are treated as zero.
|
||||
Logically equivalent to: ``not self - (+other)``
|
||||
|
||||
.. versionadded:: 3.10
|
||||
|
||||
.. method:: issuperset(other)
|
||||
|
||||
True if the counts in *self* are greater than or equal to those in *other*.
|
||||
Negative or missing counts are treated as zero.
|
||||
Logically equivalent to: ``not other - (+self)``
|
||||
|
||||
.. versionadded:: 3.10
|
||||
|
||||
.. method:: most_common([n])
|
||||
|
||||
Return a list of the *n* most common elements and their counts from the
|
||||
|
@ -1161,6 +1202,8 @@ variants of :func:`functools.lru_cache`::
|
|||
return value
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if key in self:
|
||||
self.move_to_end(key)
|
||||
super().__setitem__(key, value)
|
||||
if len(self) > self.maxsize:
|
||||
oldest = next(iter(self))
|
||||
|
|
|
@ -113,6 +113,11 @@ compile Python sources.
|
|||
|
||||
Ignore symlinks pointing outside the given directory.
|
||||
|
||||
.. cmdoption:: --hardlink-dupes
|
||||
|
||||
If two ``.pyc`` files with different optimization level have
|
||||
the same content, use hard links to consolidate duplicate files.
|
||||
|
||||
.. versionchanged:: 3.2
|
||||
Added the ``-i``, ``-b`` and ``-h`` options.
|
||||
|
||||
|
@ -125,7 +130,7 @@ compile Python sources.
|
|||
Added the ``--invalidation-mode`` option.
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
Added the ``-s``, ``-p``, ``-e`` options.
|
||||
Added the ``-s``, ``-p``, ``-e`` and ``--hardlink-dupes`` options.
|
||||
Raised the default recursion limit from 10 to
|
||||
:py:func:`sys.getrecursionlimit()`.
|
||||
Added the possibility to specify the ``-o`` option multiple times.
|
||||
|
@ -143,14 +148,14 @@ runtime.
|
|||
Public functions
|
||||
----------------
|
||||
|
||||
.. function:: compile_dir(dir, maxlevels=sys.getrecursionlimit(), ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, workers=1, invalidation_mode=None, \*, stripdir=None, prependdir=None, limit_sl_dest=None)
|
||||
.. function:: compile_dir(dir, maxlevels=sys.getrecursionlimit(), ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, workers=1, invalidation_mode=None, \*, stripdir=None, prependdir=None, limit_sl_dest=None, hardlink_dupes=False)
|
||||
|
||||
Recursively descend the directory tree named by *dir*, compiling all :file:`.py`
|
||||
files along the way. Return a true value if all the files compiled successfully,
|
||||
and a false value otherwise.
|
||||
|
||||
The *maxlevels* parameter is used to limit the depth of the recursion; it
|
||||
defaults to ``10``.
|
||||
defaults to ``sys.getrecursionlimit()``.
|
||||
|
||||
If *ddir* is given, it is prepended to the path to each file being compiled
|
||||
for use in compilation time tracebacks, and is also compiled in to the
|
||||
|
@ -176,7 +181,8 @@ Public functions
|
|||
coexist.
|
||||
|
||||
*optimize* specifies the optimization level for the compiler. It is passed to
|
||||
the built-in :func:`compile` function.
|
||||
the built-in :func:`compile` function. Accepts also a sequence of optimization
|
||||
levels which lead to multiple compilations of one :file:`.py` file in one call.
|
||||
|
||||
The argument *workers* specifies how many workers are used to
|
||||
compile files in parallel. The default is to not use multiple workers.
|
||||
|
@ -193,6 +199,9 @@ Public functions
|
|||
the ``-s``, ``-p`` and ``-e`` options described above.
|
||||
They may be specified as ``str``, ``bytes`` or :py:class:`os.PathLike`.
|
||||
|
||||
If *hardlink_dupes* is true and two ``.pyc`` files with different optimization
|
||||
level have the same content, use hard links to consolidate duplicate files.
|
||||
|
||||
.. versionchanged:: 3.2
|
||||
Added the *legacy* and *optimize* parameter.
|
||||
|
||||
|
@ -219,9 +228,10 @@ Public functions
|
|||
Setting *workers* to 0 now chooses the optimal number of cores.
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
Added *stripdir*, *prependdir* and *limit_sl_dest* arguments.
|
||||
Added *stripdir*, *prependdir*, *limit_sl_dest* and *hardlink_dupes* arguments.
|
||||
Default value of *maxlevels* was changed from ``10`` to ``sys.getrecursionlimit()``
|
||||
|
||||
.. function:: compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, invalidation_mode=None, \*, stripdir=None, prependdir=None, limit_sl_dest=None)
|
||||
.. function:: compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, invalidation_mode=None, \*, stripdir=None, prependdir=None, limit_sl_dest=None, hardlink_dupes=False)
|
||||
|
||||
Compile the file with path *fullname*. Return a true value if the file
|
||||
compiled successfully, and a false value otherwise.
|
||||
|
@ -247,7 +257,8 @@ Public functions
|
|||
coexist.
|
||||
|
||||
*optimize* specifies the optimization level for the compiler. It is passed to
|
||||
the built-in :func:`compile` function.
|
||||
the built-in :func:`compile` function. Accepts also a sequence of optimization
|
||||
levels which lead to multiple compilations of one :file:`.py` file in one call.
|
||||
|
||||
*invalidation_mode* should be a member of the
|
||||
:class:`py_compile.PycInvalidationMode` enum and controls how the generated
|
||||
|
@ -257,6 +268,9 @@ Public functions
|
|||
the ``-s``, ``-p`` and ``-e`` options described above.
|
||||
They may be specified as ``str``, ``bytes`` or :py:class:`os.PathLike`.
|
||||
|
||||
If *hardlink_dupes* is true and two ``.pyc`` files with different optimization
|
||||
level have the same content, use hard links to consolidate duplicate files.
|
||||
|
||||
.. versionadded:: 3.2
|
||||
|
||||
.. versionchanged:: 3.5
|
||||
|
@ -273,7 +287,7 @@ Public functions
|
|||
The *invalidation_mode* parameter's default value is updated to None.
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
Added *stripdir*, *prependdir* and *limit_sl_dest* arguments.
|
||||
Added *stripdir*, *prependdir*, *limit_sl_dest* and *hardlink_dupes* arguments.
|
||||
|
||||
.. function:: compile_path(skip_curdir=True, maxlevels=0, force=False, quiet=0, legacy=False, optimize=-1, invalidation_mode=None)
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ in :pep:`557`.
|
|||
The member variables to use in these generated methods are defined
|
||||
using :pep:`526` type annotations. For example this code::
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
@dataclass
|
||||
class InventoryItem:
|
||||
'''Class for keeping track of an item in inventory.'''
|
||||
|
|
|
@ -20,6 +20,7 @@ The following modules are documented in this chapter:
|
|||
.. toctree::
|
||||
|
||||
datetime.rst
|
||||
zoneinfo.rst
|
||||
calendar.rst
|
||||
collections.rst
|
||||
collections.abc.rst
|
||||
|
|
|
@ -35,7 +35,8 @@ on efficient attribute extraction for output formatting and manipulation.
|
|||
Aware and Naive Objects
|
||||
-----------------------
|
||||
|
||||
Date and time objects may be categorized as "aware" or "naive."
|
||||
Date and time objects may be categorized as "aware" or "naive" depending on
|
||||
whether or not they include timezone information.
|
||||
|
||||
With sufficient knowledge of applicable algorithmic and political time
|
||||
adjustments, such as time zone and daylight saving time information,
|
||||
|
@ -670,7 +671,8 @@ Instance methods:
|
|||
|
||||
.. method:: date.isocalendar()
|
||||
|
||||
Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
|
||||
Return a :term:`named tuple` object with three components: ``year``,
|
||||
``week`` and ``weekday``.
|
||||
|
||||
The ISO calendar is a widely used variant of the Gregorian calendar. [#]_
|
||||
|
||||
|
@ -682,11 +684,14 @@ Instance methods:
|
|||
For example, 2004 begins on a Thursday, so the first week of ISO year 2004
|
||||
begins on Monday, 29 Dec 2003 and ends on Sunday, 4 Jan 2004::
|
||||
|
||||
>>> from datetime import date
|
||||
>>> date(2003, 12, 29).isocalendar()
|
||||
(2004, 1, 1)
|
||||
>>> date(2004, 1, 4).isocalendar()
|
||||
(2004, 1, 7)
|
||||
>>> from datetime import date
|
||||
>>> date(2003, 12, 29).isocalendar()
|
||||
datetime.IsoCalendarDate(year=2004, week=1, weekday=1)
|
||||
>>> date(2004, 1, 4).isocalendar()
|
||||
datetime.IsoCalendarDate(year=2004, week=1, weekday=7)
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
Result changed from a tuple to a :term:`named tuple`.
|
||||
|
||||
.. method:: date.isoformat()
|
||||
|
||||
|
@ -1397,8 +1402,8 @@ Instance methods:
|
|||
|
||||
.. method:: datetime.isocalendar()
|
||||
|
||||
Return a 3-tuple, (ISO year, ISO week number, ISO weekday). The same as
|
||||
``self.date().isocalendar()``.
|
||||
Return a :term:`named tuple` with three components: ``year``, ``week``
|
||||
and ``weekday``. The same as ``self.date().isocalendar()``.
|
||||
|
||||
|
||||
.. method:: datetime.isoformat(sep='T', timespec='auto')
|
||||
|
|
|
@ -421,7 +421,7 @@ The :class:`SequenceMatcher` class has this constructor:
|
|||
is not changed.
|
||||
|
||||
|
||||
.. method:: find_longest_match(alo, ahi, blo, bhi)
|
||||
.. method:: find_longest_match(alo=0, ahi=None, blo=0, bhi=None)
|
||||
|
||||
Find longest matching block in ``a[alo:ahi]`` and ``b[blo:bhi]``.
|
||||
|
||||
|
@ -458,6 +458,9 @@ The :class:`SequenceMatcher` class has this constructor:
|
|||
|
||||
This method returns a :term:`named tuple` ``Match(a, b, size)``.
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
Added default arguments.
|
||||
|
||||
|
||||
.. method:: get_matching_blocks()
|
||||
|
||||
|
|
|
@ -26,6 +26,32 @@ function for the purposes of this module.
|
|||
|
||||
The :mod:`functools` module defines the following functions:
|
||||
|
||||
.. decorator:: cache(user_function)
|
||||
|
||||
Simple lightweight unbounded function cache. Sometimes called
|
||||
`"memoize" <https://en.wikipedia.org/wiki/Memoization>`_.
|
||||
|
||||
Returns the same as ``lru_cache(maxsize=None)``, creating a thin
|
||||
wrapper around a dictionary lookup for the function arguments. Because it
|
||||
never needs to evict old values, this is smaller and faster than
|
||||
:func:`lru_cache()` with a size limit.
|
||||
|
||||
For example::
|
||||
|
||||
@cache
|
||||
def factorial(n):
|
||||
return n * factorial(n-1) if n else 1
|
||||
|
||||
>>> factorial(10) # no previously cached result, makes 11 recursive calls
|
||||
3628800
|
||||
>>> factorial(5) # just looks up cached value result
|
||||
120
|
||||
>>> factorial(12) # makes two new recursive calls, the other 10 are cached
|
||||
479001600
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
.. decorator:: cached_property(func)
|
||||
|
||||
Transform a method of a class into a property whose value is computed once
|
||||
|
@ -107,8 +133,7 @@ The :mod:`functools` module defines the following functions:
|
|||
return sum(sentence.count(vowel) for vowel in 'aeiou')
|
||||
|
||||
If *maxsize* is set to ``None``, the LRU feature is disabled and the cache can
|
||||
grow without bound. The LRU feature performs best when *maxsize* is a
|
||||
power-of-two.
|
||||
grow without bound.
|
||||
|
||||
If *typed* is set to true, function arguments of different types will be
|
||||
cached separately. For example, ``f(3)`` and ``f(3.0)`` will be treated
|
||||
|
@ -133,11 +158,11 @@ The :mod:`functools` module defines the following functions:
|
|||
bypassing the cache, or for rewrapping the function with a different cache.
|
||||
|
||||
An `LRU (least recently used) cache
|
||||
<https://en.wikipedia.org/wiki/Cache_algorithms#Examples>`_ works
|
||||
best when the most recent calls are the best predictors of upcoming calls (for
|
||||
example, the most popular articles on a news server tend to change each day).
|
||||
The cache's size limit assures that the cache does not grow without bound on
|
||||
long-running processes such as web servers.
|
||||
<https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)>`_
|
||||
works best when the most recent calls are the best predictors of upcoming
|
||||
calls (for example, the most popular articles on a news server tend to
|
||||
change each day). The cache's size limit assures that the cache does not
|
||||
grow without bound on long-running processes such as web servers.
|
||||
|
||||
In general, the LRU cache should only be used when you want to reuse
|
||||
previously computed values. Accordingly, it doesn't make sense to cache
|
||||
|
|
|
@ -87,6 +87,8 @@ library that Python uses on your platform. On most platforms the
|
|||
that the hashing algorithm is not used in a security context, e.g. as a
|
||||
non-cryptographic one-way compression function.
|
||||
|
||||
Hashlib now uses SHA3 and SHAKE from OpenSSL 1.1.1 and newer.
|
||||
|
||||
For example, to obtain the digest of the byte string ``b'Nobody inspects the
|
||||
spammish repetition'``::
|
||||
|
||||
|
|
|
@ -114,6 +114,12 @@ A hash object has the following attributes:
|
|||
.. versionadded:: 3.4
|
||||
|
||||
|
||||
.. deprecated:: 3.9
|
||||
|
||||
The undocumented attributes ``HMAC.digest_cons``, ``HMAC.inner``, and
|
||||
``HMAC.outer`` are internal implementation details and will be removed in
|
||||
Python 3.10.
|
||||
|
||||
This module also provides the following helper function:
|
||||
|
||||
.. function:: compare_digest(a, b)
|
||||
|
@ -132,6 +138,11 @@ This module also provides the following helper function:
|
|||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
.. versionchanged:: 3.10
|
||||
|
||||
The function uses OpenSSL's ``CRYPTO_memcmp()`` internally when
|
||||
available.
|
||||
|
||||
|
||||
.. seealso::
|
||||
|
||||
|
|
|
@ -480,6 +480,8 @@ ABC hierarchy::
|
|||
|
||||
.. class:: ResourceReader
|
||||
|
||||
*Superseded by TraversableReader*
|
||||
|
||||
An :term:`abstract base class` to provide the ability to read
|
||||
*resources*.
|
||||
|
||||
|
@ -795,6 +797,28 @@ ABC hierarchy::
|
|||
itself does not end in ``__init__``.
|
||||
|
||||
|
||||
.. class:: Traversable
|
||||
|
||||
An object with a subset of pathlib.Path methods suitable for
|
||||
traversing directories and opening files.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
.. class:: TraversableReader
|
||||
|
||||
An abstract base class for resource readers capable of serving
|
||||
the ``files`` interface. Subclasses ResourceReader and provides
|
||||
concrete implementations of the ResourceReader's abstract
|
||||
methods. Therefore, any loader supplying TraversableReader
|
||||
also supplies ResourceReader.
|
||||
|
||||
Loaders that wish to support resource reading are expected to
|
||||
implement this interface.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
:mod:`importlib.resources` -- Resources
|
||||
---------------------------------------
|
||||
|
||||
|
@ -853,6 +877,19 @@ The following types are defined.
|
|||
|
||||
The following functions are available.
|
||||
|
||||
|
||||
.. function:: files(package)
|
||||
|
||||
Returns an :class:`importlib.resources.abc.Traversable` object
|
||||
representing the resource container for the package (think directory)
|
||||
and its resources (think files). A Traversable may contain other
|
||||
containers (think subdirectories).
|
||||
|
||||
*package* is either a name or a module object which conforms to the
|
||||
``Package`` requirements.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
.. function:: open_binary(package, resource)
|
||||
|
||||
Open for binary reading the *resource* within *package*.
|
||||
|
|
|
@ -473,15 +473,12 @@ Retrieving source code
|
|||
|
||||
Get the documentation string for an object, cleaned up with :func:`cleandoc`.
|
||||
If the documentation string for an object is not provided and the object is
|
||||
a method, a property or a descriptor, retrieve the documentation
|
||||
a class, a method, a property or a descriptor, retrieve the documentation
|
||||
string from the inheritance hierarchy.
|
||||
|
||||
.. versionchanged:: 3.5
|
||||
Documentation strings are now inherited if not overridden.
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
Documentation strings for classes are no longer inherited.
|
||||
|
||||
|
||||
.. function:: getcomments(object)
|
||||
|
||||
|
|
|
@ -132,12 +132,13 @@ High-level Module Interface
|
|||
Opens the provided file with mode ``'rb'``. This function should be used
|
||||
when the intent is to treat the contents as executable code.
|
||||
|
||||
``path`` should be an absolute path.
|
||||
``path`` should be a :class:`str` and an absolute path.
|
||||
|
||||
The behavior of this function may be overridden by an earlier call to the
|
||||
:c:func:`PyFile_SetOpenCodeHook`, however, it should always be considered
|
||||
interchangeable with ``open(path, 'rb')``. Overriding the behavior is
|
||||
intended for additional validation or preprocessing of the file.
|
||||
:c:func:`PyFile_SetOpenCodeHook`. However, assuming that ``path`` is a
|
||||
:class:`str` and an absolute path, ``open_code(path)`` should always behave
|
||||
the same as ``open(path, 'rb')``. Overriding the behavior is intended for
|
||||
additional validation or preprocessing of the file.
|
||||
|
||||
.. versionadded:: 3.8
|
||||
|
||||
|
|
|
@ -81,7 +81,9 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
|
|||
private copy-on-write mapping, so changes to the contents of the mmap
|
||||
object will be private to this process, and :const:`MAP_SHARED` creates a
|
||||
mapping that's shared with all other processes mapping the same areas of
|
||||
the file. The default value is :const:`MAP_SHARED`.
|
||||
the file. The default value is :const:`MAP_SHARED`. Some systems have
|
||||
additional possible flags with the full list specified in
|
||||
:ref:`MAP_* constants <map-constants>`.
|
||||
|
||||
*prot*, if specified, gives the desired memory protection; the two most
|
||||
useful values are :const:`PROT_READ` and :const:`PROT_WRITE`, to specify
|
||||
|
@ -342,3 +344,21 @@ MADV_* Constants
|
|||
Availability: Systems with the madvise() system call.
|
||||
|
||||
.. versionadded:: 3.8
|
||||
|
||||
.. _map-constants:
|
||||
|
||||
MAP_* Constants
|
||||
+++++++++++++++
|
||||
|
||||
.. data:: MAP_SHARED
|
||||
MAP_PRIVATE
|
||||
MAP_DENYWRITE
|
||||
MAP_EXECUTABLE
|
||||
MAP_ANON
|
||||
MAP_ANONYMOUS
|
||||
MAP_POPULATE
|
||||
|
||||
These are the various flags that can be passed to :meth:`mmap.mmap`. Note that some options might not be present on some systems.
|
||||
|
||||
.. versionchanged:: 3.10
|
||||
Added MAP_POPULATE constant.
|
||||
|
|
|
@ -2144,7 +2144,7 @@ with the :class:`Pool` class.
|
|||
or by calling :meth:`close` and :meth:`terminate` manually. Failure to do this
|
||||
can lead to the process hanging on finalization.
|
||||
|
||||
Note that is **not correct** to rely on the garbage colletor to destroy the pool
|
||||
Note that it is **not correct** to rely on the garbage collector to destroy the pool
|
||||
as CPython does not assure that the finalizer of the pool will be called
|
||||
(see :meth:`object.__del__` for more information).
|
||||
|
||||
|
|
|
@ -112,6 +112,10 @@ The mathematical and bitwise operations are the most numerous:
|
|||
|
||||
Return *a* converted to an integer. Equivalent to ``a.__index__()``.
|
||||
|
||||
.. versionchanged:: 3.10
|
||||
The result always has exact type :class:`int`. Previously, the result
|
||||
could have been an instance of a subclass of ``int``.
|
||||
|
||||
|
||||
.. function:: inv(obj)
|
||||
invert(obj)
|
||||
|
|
|
@ -1151,7 +1151,8 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo
|
|||
Combine the functionality of :func:`os.readv` and :func:`os.pread`.
|
||||
|
||||
.. availability:: Linux 2.6.30 and newer, FreeBSD 6.0 and newer,
|
||||
OpenBSD 2.7 and newer. Using flags requires Linux 4.6 or newer.
|
||||
OpenBSD 2.7 and newer, AIX 7.1 and newer. Using flags requires
|
||||
Linux 4.6 or newer.
|
||||
|
||||
.. versionadded:: 3.7
|
||||
|
||||
|
@ -1210,6 +1211,7 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo
|
|||
|
||||
- :data:`RWF_DSYNC`
|
||||
- :data:`RWF_SYNC`
|
||||
- :data:`RWF_APPEND`
|
||||
|
||||
Return the total number of bytes actually written.
|
||||
|
||||
|
@ -1219,15 +1221,16 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo
|
|||
Combine the functionality of :func:`os.writev` and :func:`os.pwrite`.
|
||||
|
||||
.. availability:: Linux 2.6.30 and newer, FreeBSD 6.0 and newer,
|
||||
OpenBSD 2.7 and newer. Using flags requires Linux 4.7 or newer.
|
||||
OpenBSD 2.7 and newer, AIX 7.1 and newer. Using flags requires
|
||||
Linux 4.7 or newer.
|
||||
|
||||
.. versionadded:: 3.7
|
||||
|
||||
|
||||
.. data:: RWF_DSYNC
|
||||
|
||||
Provide a per-write equivalent of the :data:`O_DSYNC` ``open(2)`` flag. This
|
||||
flag effect applies only to the data range written by the system call.
|
||||
Provide a per-write equivalent of the :data:`O_DSYNC` :func:`os.open` flag.
|
||||
This flag effect applies only to the data range written by the system call.
|
||||
|
||||
.. availability:: Linux 4.7 and newer.
|
||||
|
||||
|
@ -1236,14 +1239,28 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo
|
|||
|
||||
.. data:: RWF_SYNC
|
||||
|
||||
Provide a per-write equivalent of the :data:`O_SYNC` ``open(2)`` flag. This
|
||||
flag effect applies only to the data range written by the system call.
|
||||
Provide a per-write equivalent of the :data:`O_SYNC` :func:`os.open` flag.
|
||||
This flag effect applies only to the data range written by the system call.
|
||||
|
||||
.. availability:: Linux 4.7 and newer.
|
||||
|
||||
.. versionadded:: 3.7
|
||||
|
||||
|
||||
.. data:: RWF_APPEND
|
||||
|
||||
Provide a per-write equivalent of the :data:`O_APPEND` :func:`os.open`
|
||||
flag. This flag is meaningful only for :func:`os.pwritev`, and its
|
||||
effect applies only to the data range written by the system call. The
|
||||
*offset* argument does not affect the write operation; the data is always
|
||||
appended to the end of the file. However, if the *offset* argument is
|
||||
``-1``, the current file *offset* is updated.
|
||||
|
||||
.. availability:: Linux 4.16 and newer.
|
||||
|
||||
.. versionadded:: 3.10
|
||||
|
||||
|
||||
.. function:: read(fd, n)
|
||||
|
||||
Read at most *n* bytes from file descriptor *fd*.
|
||||
|
|
|
@ -549,25 +549,24 @@ Pure paths provide the following methods and properties:
|
|||
>>> p.relative_to('/usr')
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
File "pathlib.py", line 940, in relative_to
|
||||
File "pathlib.py", line 941, in relative_to
|
||||
raise ValueError(error_message.format(str(self), str(formatted)))
|
||||
ValueError: '/etc/passwd' does not start with '/usr'
|
||||
ValueError: '/etc/passwd' is not in the subpath of '/usr' OR one path is relative and the other is absolute.
|
||||
>>> p.relative_to('/usr', strict=False)
|
||||
PurePosixPath('../etc/passwd')
|
||||
>>> p.relative_to('foo', strict=False)
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
File "pathlib.py", line 940, in relative_to
|
||||
File "pathlib.py", line 941, in relative_to
|
||||
raise ValueError(error_message.format(str(self), str(formatted)))
|
||||
ValueError: '/etc/passwd' is not related to 'foo'
|
||||
ValueError: '/etc/passwd' is not on the same drive as 'foo' OR one path is relative and the other is absolute.
|
||||
|
||||
If the path doesn't start with *other* and *strict* is ``True``,
|
||||
:exc:`ValueError` is raised. If *strict* is ``False`` and the paths are
|
||||
not both relative or both absolute :exc:`ValueError` is raised (on Windows
|
||||
both paths must reference the same drive as well).
|
||||
If the path doesn't start with *other* and *strict* is ``True``, :exc:`ValueError` is raised. If *strict* is ``False`` and one path is relative and the other is absolute or if they reference different drives :exc:`ValueError` is raised.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
The *strict* parameter was added.
|
||||
NOTE: This function is part of :class:`PurePath` and works with strings. It does not check or access the underlying file structure.
|
||||
|
||||
.. versionadded:: 3.10
|
||||
The *strict* argument (pre-3.10 behavior is strict).
|
||||
|
||||
|
||||
.. method:: PurePath.with_name(name)
|
||||
|
@ -1201,6 +1200,7 @@ os and os.path pathlib
|
|||
:func:`os.path.abspath` :meth:`Path.resolve`
|
||||
:func:`os.chmod` :meth:`Path.chmod`
|
||||
:func:`os.mkdir` :meth:`Path.mkdir`
|
||||
:func:`os.makedirs` :meth:`Path.mkdir`
|
||||
:func:`os.rename` :meth:`Path.rename`
|
||||
:func:`os.replace` :meth:`Path.replace`
|
||||
:func:`os.rmdir` :meth:`Path.rmdir`
|
||||
|
|
|
@ -252,10 +252,10 @@ process more convenient:
|
|||
.. versionchanged:: 3.8
|
||||
The *buffers* argument was added.
|
||||
|
||||
.. function:: loads(bytes_object, \*, fix_imports=True, encoding="ASCII", errors="strict", buffers=None)
|
||||
.. function:: loads(data, /, \*, fix_imports=True, encoding="ASCII", errors="strict", buffers=None)
|
||||
|
||||
Return the reconstituted object hierarchy of the pickled representation
|
||||
*bytes_object* of an object.
|
||||
*data* of an object. *data* must be a :term:`bytes-like object`.
|
||||
|
||||
The protocol version of the pickle is detected automatically, so no
|
||||
protocol argument is needed. Bytes past the pickled representation
|
||||
|
|
|
@ -104,21 +104,16 @@ Bookkeeping functions
|
|||
the time :func:`getstate` was called.
|
||||
|
||||
|
||||
.. function:: getrandbits(k)
|
||||
|
||||
Returns a Python integer with *k* random bits. This method is supplied with
|
||||
the MersenneTwister generator and some other generators may also provide it
|
||||
as an optional part of the API. When available, :meth:`getrandbits` enables
|
||||
:meth:`randrange` to handle arbitrarily large ranges.
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
This method now accepts zero for *k*.
|
||||
|
||||
Functions for bytes
|
||||
-------------------
|
||||
|
||||
.. function:: randbytes(n)
|
||||
|
||||
Generate *n* random bytes.
|
||||
|
||||
This method should not be used for generating security tokens.
|
||||
Use :func:`secrets.token_bytes` instead.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
|
@ -145,6 +140,16 @@ Functions for integers
|
|||
Return a random integer *N* such that ``a <= N <= b``. Alias for
|
||||
``randrange(a, b+1)``.
|
||||
|
||||
.. function:: getrandbits(k)
|
||||
|
||||
Returns a Python integer with *k* random bits. This method is supplied with
|
||||
the MersenneTwister generator and some other generators may also provide it
|
||||
as an optional part of the API. When available, :meth:`getrandbits` enables
|
||||
:meth:`randrange` to handle arbitrarily large ranges.
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
This method now accepts zero for *k*.
|
||||
|
||||
|
||||
Functions for sequences
|
||||
-----------------------
|
||||
|
@ -208,8 +213,11 @@ Functions for sequences
|
|||
generated. For example, a sequence of length 2080 is the largest that
|
||||
can fit within the period of the Mersenne Twister random number generator.
|
||||
|
||||
.. deprecated-removed:: 3.9 3.11
|
||||
The optional parameter *random*.
|
||||
|
||||
.. function:: sample(population, k)
|
||||
|
||||
.. function:: sample(population, k, *, counts=None)
|
||||
|
||||
Return a *k* length list of unique elements chosen from the population sequence
|
||||
or set. Used for random sampling without replacement.
|
||||
|
@ -223,6 +231,11 @@ Functions for sequences
|
|||
Members of the population need not be :term:`hashable` or unique. If the population
|
||||
contains repeats, then each occurrence is a possible selection in the sample.
|
||||
|
||||
Repeated elements can be specified one at a time or with the optional
|
||||
keyword-only *counts* parameter. For example, ``sample(['red', 'blue'],
|
||||
counts=[4, 2], k=5)`` is equivalent to ``sample(['red', 'red', 'red', 'red',
|
||||
'blue', 'blue'], k=5)``.
|
||||
|
||||
To choose a sample from a range of integers, use a :func:`range` object as an
|
||||
argument. This is especially fast and space efficient for sampling from a large
|
||||
population: ``sample(range(10000000), k=60)``.
|
||||
|
@ -230,6 +243,9 @@ Functions for sequences
|
|||
If the sample size is larger than the population size, a :exc:`ValueError`
|
||||
is raised.
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
Added the *counts* parameter.
|
||||
|
||||
.. deprecated:: 3.9
|
||||
In the future, the *population* must be a sequence. Instances of
|
||||
:class:`set` are no longer supported. The set must first be converted
|
||||
|
@ -412,12 +428,11 @@ Simulations::
|
|||
>>> choices(['red', 'black', 'green'], [18, 18, 2], k=6)
|
||||
['red', 'green', 'black', 'black', 'red', 'black']
|
||||
|
||||
>>> # Deal 20 cards without replacement from a deck of 52 playing cards
|
||||
>>> # and determine the proportion of cards with a ten-value
|
||||
>>> # (a ten, jack, queen, or king).
|
||||
>>> deck = collections.Counter(tens=16, low_cards=36)
|
||||
>>> seen = sample(list(deck.elements()), k=20)
|
||||
>>> seen.count('tens') / 20
|
||||
>>> # Deal 20 cards without replacement from a deck
|
||||
>>> # of 52 playing cards, and determine the proportion of cards
|
||||
>>> # with a ten-value: ten, jack, queen, or king.
|
||||
>>> dealt = sample(['tens', 'low cards'], counts=[16, 36], k=20)
|
||||
>>> dealt.count('tens') / 20
|
||||
0.15
|
||||
|
||||
>>> # Estimate the probability of getting 5 or more heads from 7 spins
|
||||
|
@ -479,7 +494,7 @@ Simulation of arrival times and service deliveries for a multiserver queue::
|
|||
|
||||
from heapq import heappush, heappop
|
||||
from random import expovariate, gauss
|
||||
from statistics import mean, median, stdev
|
||||
from statistics import mean, quantiles
|
||||
|
||||
average_arrival_interval = 5.6
|
||||
average_service_time = 15.0
|
||||
|
@ -498,8 +513,8 @@ Simulation of arrival times and service deliveries for a multiserver queue::
|
|||
service_completed = arrival_time + wait + service_duration
|
||||
heappush(servers, service_completed)
|
||||
|
||||
print(f'Mean wait: {mean(waits):.1f}. Stdev wait: {stdev(waits):.1f}.')
|
||||
print(f'Median wait: {median(waits):.1f}. Max wait: {max(waits):.1f}.')
|
||||
print(f'Mean wait: {mean(waits):.1f} Max wait: {max(waits):.1f}')
|
||||
print('Quartiles:', [round(q, 1) for q in quantiles(waits)])
|
||||
|
||||
.. seealso::
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ The module defines the following:
|
|||
.. function:: select(rlist, wlist, xlist[, timeout])
|
||||
|
||||
This is a straightforward interface to the Unix :c:func:`select` system call.
|
||||
The first three arguments are sequences of 'waitable objects': either
|
||||
The first three arguments are iterables of 'waitable objects': either
|
||||
integers representing file descriptors or objects with a parameterless method
|
||||
named :meth:`~io.IOBase.fileno` returning such an integer:
|
||||
|
||||
|
@ -126,7 +126,7 @@ The module defines the following:
|
|||
* *xlist*: wait for an "exceptional condition" (see the manual page for what
|
||||
your system considers such a condition)
|
||||
|
||||
Empty sequences are allowed, but acceptance of three empty sequences is
|
||||
Empty iterables are allowed, but acceptance of three empty iterables is
|
||||
platform-dependent. (It is known to work on Unix but not on Windows.) The
|
||||
optional *timeout* argument specifies a time-out as a floating point number
|
||||
in seconds. When the *timeout* argument is omitted the function blocks until
|
||||
|
@ -141,7 +141,7 @@ The module defines the following:
|
|||
single: socket() (in module socket)
|
||||
single: popen() (in module os)
|
||||
|
||||
Among the acceptable object types in the sequences are Python :term:`file
|
||||
Among the acceptable object types in the iterables are Python :term:`file
|
||||
objects <file object>` (e.g. ``sys.stdin``, or objects returned by
|
||||
:func:`open` or :func:`os.popen`), socket objects returned by
|
||||
:func:`socket.socket`. You may also define a :dfn:`wrapper` class yourself,
|
||||
|
|
|
@ -279,9 +279,10 @@ An :class:`SMTP` instance has the following methods:
|
|||
response for ESMTP option and store them for use by :meth:`has_extn`.
|
||||
Also sets several informational attributes: the message returned by
|
||||
the server is stored as the :attr:`ehlo_resp` attribute, :attr:`does_esmtp`
|
||||
is set to true or false depending on whether the server supports ESMTP, and
|
||||
:attr:`esmtp_features` will be a dictionary containing the names of the
|
||||
SMTP service extensions this server supports, and their parameters (if any).
|
||||
is set to ``True`` or ``False`` depending on whether the server supports
|
||||
ESMTP, and :attr:`esmtp_features` will be a dictionary containing the names
|
||||
of the SMTP service extensions this server supports, and their parameters
|
||||
(if any).
|
||||
|
||||
Unless you wish to use :meth:`has_extn` before sending mail, it should not be
|
||||
necessary to call this method explicitly. It will be implicitly called by
|
||||
|
|
|
@ -118,6 +118,10 @@ created. Socket addresses are represented as follows:
|
|||
- :const:`CAN_ISOTP` protocol require a tuple ``(interface, rx_addr, tx_addr)``
|
||||
where both additional parameters are unsigned long integer that represent a
|
||||
CAN identifier (standard or extended).
|
||||
- :const:`CAN_J1939` protocol require a tuple ``(interface, name, pgn, addr)``
|
||||
where additional parameters are 64-bit unsigned integer representing the
|
||||
ECU name, a 32-bit unsigned integer representing the Parameter Group Number
|
||||
(PGN), and an 8-bit integer representing the address.
|
||||
|
||||
- A string or a tuple ``(id, unit)`` is used for the :const:`SYSPROTO_CONTROL`
|
||||
protocol of the :const:`PF_SYSTEM` family. The string is the name of a
|
||||
|
@ -428,6 +432,15 @@ Constants
|
|||
|
||||
.. versionadded:: 3.7
|
||||
|
||||
.. data:: CAN_J1939
|
||||
|
||||
CAN_J1939, in the CAN protocol family, is the SAE J1939 protocol.
|
||||
J1939 constants, documented in the Linux documentation.
|
||||
|
||||
.. availability:: Linux >= 5.4.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
.. data:: AF_PACKET
|
||||
PF_PACKET
|
||||
|
@ -544,7 +557,8 @@ The following functions all create :ref:`socket objects <socket-objects>`.
|
|||
default), :const:`SOCK_DGRAM`, :const:`SOCK_RAW` or perhaps one of the other
|
||||
``SOCK_`` constants. The protocol number is usually zero and may be omitted
|
||||
or in the case where the address family is :const:`AF_CAN` the protocol
|
||||
should be one of :const:`CAN_RAW`, :const:`CAN_BCM` or :const:`CAN_ISOTP`.
|
||||
should be one of :const:`CAN_RAW`, :const:`CAN_BCM`, :const:`CAN_ISOTP` or
|
||||
:const:`CAN_J1939`.
|
||||
|
||||
If *fileno* is specified, the values for *family*, *type*, and *proto* are
|
||||
auto-detected from the specified file descriptor. Auto-detection can be
|
||||
|
@ -588,6 +602,9 @@ The following functions all create :ref:`socket objects <socket-objects>`.
|
|||
``SOCK_NONBLOCK``, but ``sock.type`` will be set to
|
||||
``socket.SOCK_STREAM``.
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
The CAN_J1939 protocol was added.
|
||||
|
||||
.. function:: socketpair([family[, type[, proto]]])
|
||||
|
||||
Build a pair of connected socket objects using the given address family, socket
|
||||
|
|
|
@ -928,7 +928,7 @@ a class like this::
|
|||
self.x, self.y = x, y
|
||||
|
||||
Now you want to store the point in a single SQLite column. First you'll have to
|
||||
choose one of the supported types first to be used for representing the point.
|
||||
choose one of the supported types to be used for representing the point.
|
||||
Let's just use str and separate the coordinates using a semicolon. Then you need
|
||||
to give your class a method ``__conform__(self, protocol)`` which must return
|
||||
the converted value. The parameter *protocol* will be :class:`PrepareProtocol`.
|
||||
|
|
|
@ -615,7 +615,7 @@ Constants
|
|||
Possible value for :attr:`SSLContext.verify_flags`. In this mode, only the
|
||||
peer cert is checked but none of the intermediate CA certificates. The mode
|
||||
requires a valid CRL that is signed by the peer cert's issuer (its direct
|
||||
ancestor CA). If no proper CRL has has been loaded with
|
||||
ancestor CA). If no proper CRL has been loaded with
|
||||
:attr:`SSLContext.load_verify_locations`, validation will fail.
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
|
|
@ -434,12 +434,10 @@ Notes:
|
|||
Negative shift counts are illegal and cause a :exc:`ValueError` to be raised.
|
||||
|
||||
(2)
|
||||
A left shift by *n* bits is equivalent to multiplication by ``pow(2, n)``
|
||||
without overflow check.
|
||||
A left shift by *n* bits is equivalent to multiplication by ``pow(2, n)``.
|
||||
|
||||
(3)
|
||||
A right shift by *n* bits is equivalent to division by ``pow(2, n)`` without
|
||||
overflow check.
|
||||
A right shift by *n* bits is equivalent to floor division by ``pow(2, n)``.
|
||||
|
||||
(4)
|
||||
Performing these calculations with at least one extra sign extension bit in
|
||||
|
|
|
@ -40,7 +40,7 @@ compatibility with older versions, see the :ref:`call-function-trio` section.
|
|||
.. function:: run(args, *, stdin=None, input=None, stdout=None, stderr=None,\
|
||||
capture_output=False, shell=False, cwd=None, timeout=None, \
|
||||
check=False, encoding=None, errors=None, text=None, env=None, \
|
||||
universal_newlines=None)
|
||||
universal_newlines=None, **other_popen_kwargs)
|
||||
|
||||
Run the command described by *args*. Wait for command to complete, then
|
||||
return a :class:`CompletedProcess` instance.
|
||||
|
@ -791,14 +791,14 @@ Instances of the :class:`Popen` class have the following methods:
|
|||
|
||||
.. method:: Popen.terminate()
|
||||
|
||||
Stop the child. On Posix OSs the method sends SIGTERM to the
|
||||
Stop the child. On POSIX OSs the method sends SIGTERM to the
|
||||
child. On Windows the Win32 API function :c:func:`TerminateProcess` is called
|
||||
to stop the child.
|
||||
|
||||
|
||||
.. method:: Popen.kill()
|
||||
|
||||
Kills the child. On Posix OSs the function sends SIGKILL to the child.
|
||||
Kills the child. On POSIX OSs the function sends SIGKILL to the child.
|
||||
On Windows :meth:`kill` is an alias for :meth:`terminate`.
|
||||
|
||||
|
||||
|
@ -1085,7 +1085,8 @@ Prior to Python 3.5, these three functions comprised the high level API to
|
|||
subprocess. You can now use :func:`run` in many cases, but lots of existing code
|
||||
calls these functions.
|
||||
|
||||
.. function:: call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None)
|
||||
.. function:: call(args, *, stdin=None, stdout=None, stderr=None, \
|
||||
shell=False, cwd=None, timeout=None, **other_popen_kwargs)
|
||||
|
||||
Run the command described by *args*. Wait for command to complete, then
|
||||
return the :attr:`~Popen.returncode` attribute.
|
||||
|
@ -1111,7 +1112,9 @@ calls these functions.
|
|||
.. versionchanged:: 3.3
|
||||
*timeout* was added.
|
||||
|
||||
.. function:: check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None)
|
||||
.. function:: check_call(args, *, stdin=None, stdout=None, stderr=None, \
|
||||
shell=False, cwd=None, timeout=None, \
|
||||
**other_popen_kwargs)
|
||||
|
||||
Run command with arguments. Wait for command to complete. If the return
|
||||
code was zero then return, otherwise raise :exc:`CalledProcessError`. The
|
||||
|
@ -1142,7 +1145,8 @@ calls these functions.
|
|||
|
||||
.. function:: check_output(args, *, stdin=None, stderr=None, shell=False, \
|
||||
cwd=None, encoding=None, errors=None, \
|
||||
universal_newlines=None, timeout=None, text=None)
|
||||
universal_newlines=None, timeout=None, text=None, \
|
||||
**other_popen_kwargs)
|
||||
|
||||
Run command with arguments and return its output.
|
||||
|
||||
|
|
|
@ -74,12 +74,12 @@ places.
|
|||
|
||||
Python currently supports seven schemes:
|
||||
|
||||
- *posix_prefix*: scheme for Posix platforms like Linux or Mac OS X. This is
|
||||
- *posix_prefix*: scheme for POSIX platforms like Linux or Mac OS X. This is
|
||||
the default scheme used when Python or a component is installed.
|
||||
- *posix_home*: scheme for Posix platforms used when a *home* option is used
|
||||
- *posix_home*: scheme for POSIX platforms used when a *home* option is used
|
||||
upon installation. This scheme is used when a component is installed through
|
||||
Distutils with a specific home prefix.
|
||||
- *posix_user*: scheme for Posix platforms used when a component is installed
|
||||
- *posix_user*: scheme for POSIX platforms used when a component is installed
|
||||
through Distutils and the *user* option is used. This scheme defines paths
|
||||
located under the user home directory.
|
||||
- *nt*: scheme for NT platforms like Windows.
|
||||
|
|
|
@ -263,11 +263,6 @@ The :mod:`test.support` module defines the following constants:
|
|||
Set to a non-ASCII name for a temporary file.
|
||||
|
||||
|
||||
.. data:: TESTFN_ENCODING
|
||||
|
||||
Set to :func:`sys.getfilesystemencoding`.
|
||||
|
||||
|
||||
.. data:: TESTFN_UNENCODABLE
|
||||
|
||||
Set to a filename (str type) that should not be able to be encoded by file
|
||||
|
@ -838,18 +833,6 @@ The :mod:`test.support` module defines the following functions:
|
|||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
.. function:: wait_threads_exit(timeout=60.0)
|
||||
|
||||
Context manager to wait until all threads created in the ``with`` statement
|
||||
exit.
|
||||
|
||||
|
||||
.. function:: start_threads(threads, unlock=None)
|
||||
|
||||
Context manager to start *threads*. It attempts to join the threads upon
|
||||
exit.
|
||||
|
||||
|
||||
.. function:: calcobjsize(fmt)
|
||||
|
||||
Return :func:`struct.calcsize` for ``nP{fmt}0n`` or, if ``gettotalrefcount``
|
||||
|
@ -988,11 +971,6 @@ The :mod:`test.support` module defines the following functions:
|
|||
the trace function.
|
||||
|
||||
|
||||
.. decorator:: reap_threads(func)
|
||||
|
||||
Decorator to ensure the threads are cleaned up even if the test fails.
|
||||
|
||||
|
||||
.. decorator:: bigmemtest(size, memuse, dry_run=True)
|
||||
|
||||
Decorator for bigmem tests.
|
||||
|
@ -1110,23 +1088,6 @@ The :mod:`test.support` module defines the following functions:
|
|||
preserve internal cache.
|
||||
|
||||
|
||||
.. function:: threading_setup()
|
||||
|
||||
Return current thread count and copy of dangling threads.
|
||||
|
||||
|
||||
.. function:: threading_cleanup(*original_values)
|
||||
|
||||
Cleanup up threads not specified in *original_values*. Designed to emit
|
||||
a warning if a test leaves running threads in the background.
|
||||
|
||||
|
||||
.. function:: join_thread(thread, timeout=30.0)
|
||||
|
||||
Join a *thread* within *timeout*. Raise an :exc:`AssertionError` if thread
|
||||
is still alive after *timeout* seconds.
|
||||
|
||||
|
||||
.. function:: reap_children()
|
||||
|
||||
Use this at the end of ``test_main`` whenever sub-processes are started.
|
||||
|
@ -1140,39 +1101,6 @@ The :mod:`test.support` module defines the following functions:
|
|||
is raised.
|
||||
|
||||
|
||||
.. function:: catch_threading_exception()
|
||||
|
||||
Context manager catching :class:`threading.Thread` exception using
|
||||
:func:`threading.excepthook`.
|
||||
|
||||
Attributes set when an exception is catched:
|
||||
|
||||
* ``exc_type``
|
||||
* ``exc_value``
|
||||
* ``exc_traceback``
|
||||
* ``thread``
|
||||
|
||||
See :func:`threading.excepthook` documentation.
|
||||
|
||||
These attributes are deleted at the context manager exit.
|
||||
|
||||
Usage::
|
||||
|
||||
with support.catch_threading_exception() as cm:
|
||||
# code spawning a thread which raises an exception
|
||||
...
|
||||
|
||||
# check the thread exception, use cm attributes:
|
||||
# exc_type, exc_value, exc_traceback, thread
|
||||
...
|
||||
|
||||
# exc_type, exc_value, exc_traceback, thread attributes of cm no longer
|
||||
# exists at this point
|
||||
# (to avoid reference cycles)
|
||||
|
||||
.. versionadded:: 3.8
|
||||
|
||||
|
||||
.. function:: catch_unraisable_exception()
|
||||
|
||||
Context manager catching unraisable exception using
|
||||
|
@ -1628,3 +1556,81 @@ The module defines the following class:
|
|||
.. method:: BytecodeTestCase.assertNotInBytecode(x, opname, argval=_UNSPECIFIED)
|
||||
|
||||
Throws :exc:`AssertionError` if *opname* is found.
|
||||
|
||||
|
||||
:mod:`test.support.threading_helper` --- Utilities for threading tests
|
||||
======================================================================
|
||||
|
||||
.. module:: test.support.threading_helper
|
||||
:synopsis: Support for threading tests.
|
||||
|
||||
The :mod:`test.support.threading_helper` module provides support for threading tests.
|
||||
|
||||
.. versionadded:: 3.10
|
||||
|
||||
|
||||
.. function:: join_thread(thread, timeout=None)
|
||||
|
||||
Join a *thread* within *timeout*. Raise an :exc:`AssertionError` if thread
|
||||
is still alive after *timeout* seconds.
|
||||
|
||||
|
||||
.. decorator:: reap_threads(func)
|
||||
|
||||
Decorator to ensure the threads are cleaned up even if the test fails.
|
||||
|
||||
|
||||
.. function:: start_threads(threads, unlock=None)
|
||||
|
||||
Context manager to start *threads*. It attempts to join the threads upon
|
||||
exit.
|
||||
|
||||
|
||||
.. function:: threading_cleanup(*original_values)
|
||||
|
||||
Cleanup up threads not specified in *original_values*. Designed to emit
|
||||
a warning if a test leaves running threads in the background.
|
||||
|
||||
|
||||
.. function:: threading_setup()
|
||||
|
||||
Return current thread count and copy of dangling threads.
|
||||
|
||||
|
||||
.. function:: wait_threads_exit(timeout=None)
|
||||
|
||||
Context manager to wait until all threads created in the ``with`` statement
|
||||
exit.
|
||||
|
||||
|
||||
.. function:: catch_threading_exception()
|
||||
|
||||
Context manager catching :class:`threading.Thread` exception using
|
||||
:func:`threading.excepthook`.
|
||||
|
||||
Attributes set when an exception is catched:
|
||||
|
||||
* ``exc_type``
|
||||
* ``exc_value``
|
||||
* ``exc_traceback``
|
||||
* ``thread``
|
||||
|
||||
See :func:`threading.excepthook` documentation.
|
||||
|
||||
These attributes are deleted at the context manager exit.
|
||||
|
||||
Usage::
|
||||
|
||||
with threading_helper.catch_threading_exception() as cm:
|
||||
# code spawning a thread which raises an exception
|
||||
...
|
||||
|
||||
# check the thread exception, use cm attributes:
|
||||
# exc_type, exc_value, exc_traceback, thread
|
||||
...
|
||||
|
||||
# exc_type, exc_value, exc_traceback, thread attributes of cm no longer
|
||||
# exists at this point
|
||||
# (to avoid reference cycles)
|
||||
|
||||
.. versionadded:: 3.8
|
||||
|
|
|
@ -251,7 +251,8 @@ quotes and using leading spaces. Multiple :option:`-s` options are treated
|
|||
similarly.
|
||||
|
||||
If :option:`-n` is not given, a suitable number of loops is calculated by trying
|
||||
successive powers of 10 until the total time is at least 0.2 seconds.
|
||||
increasing numbers from the sequence 1, 2, 5, 10, 20, 50, ... until the total
|
||||
time is at least 0.2 seconds.
|
||||
|
||||
:func:`default_timer` measurements can be affected by other programs running on
|
||||
the same machine, so the best thing to do when accurate timing is necessary is
|
||||
|
|
|
@ -249,6 +249,47 @@ Example of output of the Python test suite::
|
|||
|
||||
See :meth:`Snapshot.statistics` for more options.
|
||||
|
||||
Record the current and peak size of all traced memory blocks
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following code computes two sums like ``0 + 1 + 2 + ...`` inefficiently, by
|
||||
creating a list of those numbers. This list consumes a lot of memory
|
||||
temporarily. We can use :func:`get_traced_memory` and :func:`reset_peak` to
|
||||
observe the small memory usage after the sum is computed as well as the peak
|
||||
memory usage during the computations::
|
||||
|
||||
import tracemalloc
|
||||
|
||||
tracemalloc.start()
|
||||
|
||||
# Example code: compute a sum with a large temporary list
|
||||
large_sum = sum(list(range(100000)))
|
||||
|
||||
first_size, first_peak = tracemalloc.get_traced_memory()
|
||||
|
||||
tracemalloc.reset_peak()
|
||||
|
||||
# Example code: compute a sum with a small temporary list
|
||||
small_sum = sum(list(range(1000)))
|
||||
|
||||
second_size, second_peak = tracemalloc.get_traced_memory()
|
||||
|
||||
print(f"{first_size=}, {first_peak=}")
|
||||
print(f"{second_size=}, {second_peak=}")
|
||||
|
||||
Output::
|
||||
|
||||
first_size=664, first_peak=3592984
|
||||
second_size=804, second_peak=29704
|
||||
|
||||
Using :func:`reset_peak` ensured we could accurately record the peak during the
|
||||
computation of ``small_sum``, even though it is much smaller than the overall
|
||||
peak size of memory blocks since the :func:`start` call. Without the call to
|
||||
:func:`reset_peak`, ``second_peak`` would still be the peak from the
|
||||
computation ``large_sum`` (that is, equal to ``first_peak``). In this case,
|
||||
both peaks are much higher than the final memory usage, and which suggests we
|
||||
could optimise (by removing the unnecessary call to :class:`list`, and writing
|
||||
``sum(range(...))``).
|
||||
|
||||
API
|
||||
---
|
||||
|
@ -289,6 +330,24 @@ Functions
|
|||
:mod:`tracemalloc` module as a tuple: ``(current: int, peak: int)``.
|
||||
|
||||
|
||||
.. function:: reset_peak()
|
||||
|
||||
Set the peak size of memory blocks traced by the :mod:`tracemalloc` module
|
||||
to the current size.
|
||||
|
||||
Do nothing if the :mod:`tracemalloc` module is not tracing memory
|
||||
allocations.
|
||||
|
||||
This function only modifies the recorded peak size, and does not modify or
|
||||
clear any traces, unlike :func:`clear_traces`. Snapshots taken with
|
||||
:func:`take_snapshot` before a call to :func:`reset_peak` can be
|
||||
meaningfully compared to snapshots taken after the call.
|
||||
|
||||
See also :func:`get_traced_memory`.
|
||||
|
||||
.. versionadded:: 3.10
|
||||
|
||||
|
||||
.. function:: get_tracemalloc_memory()
|
||||
|
||||
Get the memory usage in bytes of the :mod:`tracemalloc` module used to store
|
||||
|
|
|
@ -329,6 +329,12 @@ Standard names are defined for the following types:
|
|||
|
||||
Return a new view of the underlying mapping's values.
|
||||
|
||||
.. describe:: reversed(proxy)
|
||||
|
||||
Return a reverse iterator over the keys of the underlying mapping.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
Additional Utility Classes and Functions
|
||||
----------------------------------------
|
||||
|
@ -349,8 +355,7 @@ Additional Utility Classes and Functions
|
|||
self.__dict__.update(kwargs)
|
||||
|
||||
def __repr__(self):
|
||||
keys = sorted(self.__dict__)
|
||||
items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys)
|
||||
items = (f"{k}={v!r}" for k, v in self.__dict__.items())
|
||||
return "{}({})".format(type(self).__name__, ", ".join(items))
|
||||
|
||||
def __eq__(self, other):
|
||||
|
@ -362,6 +367,9 @@ Additional Utility Classes and Functions
|
|||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
Attribute order in the repr changed from alphabetical to insertion (like
|
||||
``dict``).
|
||||
|
||||
.. function:: DynamicClassAttribute(fget=None, fset=None, fdel=None, doc=None)
|
||||
|
||||
|
@ -373,7 +381,7 @@ Additional Utility Classes and Functions
|
|||
class's __getattr__ method; this is done by raising AttributeError.
|
||||
|
||||
This allows one to have properties active on an instance, and have virtual
|
||||
attributes on the class with the same name (see Enum for an example).
|
||||
attributes on the class with the same name (see :class:`enum.Enum` for an example).
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
|
|
|
@ -1021,9 +1021,9 @@ The module defines the following classes, functions and decorators:
|
|||
``List[ForwardRef("SomeClass")]``. This class should not be instantiated by
|
||||
a user, but may be used by introspection tools.
|
||||
|
||||
.. function:: NewType(typ)
|
||||
.. function:: NewType(name, tp)
|
||||
|
||||
A helper function to indicate a distinct types to a typechecker,
|
||||
A helper function to indicate a distinct type to a typechecker,
|
||||
see :ref:`distinct`. At runtime it returns a function that returns
|
||||
its argument. Usage::
|
||||
|
||||
|
|
|
@ -1235,7 +1235,7 @@ Here is an example of doing a ``PUT`` request using :class:`Request`::
|
|||
|
||||
import urllib.request
|
||||
DATA = b'some data'
|
||||
req = urllib.request.Request(url='http://localhost:8080', data=DATA,method='PUT')
|
||||
req = urllib.request.Request(url='http://localhost:8080', data=DATA, method='PUT')
|
||||
with urllib.request.urlopen(req) as f:
|
||||
pass
|
||||
print(f.status)
|
||||
|
|
|
@ -249,7 +249,8 @@ creation according to their needs, the :class:`EnvBuilder` class.
|
|||
There is also a module-level convenience function:
|
||||
|
||||
.. function:: create(env_dir, system_site_packages=False, clear=False, \
|
||||
symlinks=False, with_pip=False, prompt=None)
|
||||
symlinks=False, with_pip=False, prompt=None, \
|
||||
upgrade_deps=False)
|
||||
|
||||
Create an :class:`EnvBuilder` with the given keyword arguments, and call its
|
||||
:meth:`~EnvBuilder.create` method with the *env_dir* argument.
|
||||
|
@ -262,6 +263,9 @@ There is also a module-level convenience function:
|
|||
.. versionchanged:: 3.6
|
||||
Added the ``prompt`` parameter
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
Added the ``upgrade_deps`` parameter
|
||||
|
||||
An example of extending ``EnvBuilder``
|
||||
--------------------------------------
|
||||
|
||||
|
|
|
@ -0,0 +1,413 @@
|
|||
:mod:`zoneinfo` --- IANA time zone support
|
||||
==========================================
|
||||
|
||||
.. module:: zoneinfo
|
||||
:synopsis: IANA time zone support
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
.. moduleauthor:: Paul Ganssle <paul@ganssle.io>
|
||||
.. sectionauthor:: Paul Ganssle <paul@ganssle.io>
|
||||
|
||||
--------------
|
||||
|
||||
The :mod:`zoneinfo` module provides a concrete time zone implementation to
|
||||
support the IANA time zone database as originally specified in :pep:`615`. By
|
||||
default, :mod:`zoneinfo` uses the system's time zone data if available; if no
|
||||
system time zone data is available, the library will fall back to using the
|
||||
first-party `tzdata`_ package available on PyPI.
|
||||
|
||||
.. seealso::
|
||||
|
||||
Module: :mod:`datetime`
|
||||
Provides the :class:`~datetime.time` and :class:`~datetime.datetime`
|
||||
types with which the :class:`ZoneInfo` class is designed to be used.
|
||||
|
||||
Package `tzdata`_
|
||||
First-party package maintained by the CPython core developers to supply
|
||||
time zone data via PyPI.
|
||||
|
||||
|
||||
Using ``ZoneInfo``
|
||||
------------------
|
||||
|
||||
:class:`ZoneInfo` is a concrete implementation of the :class:`datetime.tzinfo`
|
||||
abstract base class, and is intended to be attached to ``tzinfo``, either via
|
||||
the constructor, the :meth:`datetime.replace <datetime.datetime.replace>`
|
||||
method or :meth:`datetime.astimezone <datetime.datetime.astimezone>`::
|
||||
|
||||
>>> from zoneinfo import ZoneInfo
|
||||
>>> from datetime import datetime, timedelta
|
||||
|
||||
>>> dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles"))
|
||||
>>> print(dt)
|
||||
2020-10-31 12:00:00-07:00
|
||||
|
||||
>>> dt.tzname()
|
||||
'PDT'
|
||||
|
||||
Datetimes constructed in this way are compatible with datetime arithmetic and
|
||||
handle daylight saving time transitions with no further intervention::
|
||||
|
||||
>>> dt_add = dt + timedelta(days=1)
|
||||
|
||||
>>> print(dt_add)
|
||||
2020-11-01 12:00:00-08:00
|
||||
|
||||
>>> dt_add.tzname()
|
||||
'PST'
|
||||
|
||||
These time zones also support the :attr:`~datetime.datetime.fold` attribute
|
||||
introduced in :pep:`495`. During offset transitions which induce ambiguous
|
||||
times (such as a daylight saving time to standard time transition), the offset
|
||||
from *before* the transition is used when ``fold=0``, and the offset *after*
|
||||
the transition is used when ``fold=1``, for example::
|
||||
|
||||
>>> dt = datetime(2020, 11, 1, 1, tzinfo=ZoneInfo("America/Los_Angeles"))
|
||||
>>> print(dt)
|
||||
2020-11-01 01:00:00-07:00
|
||||
|
||||
>>> print(dt.replace(fold=1))
|
||||
2020-11-01 01:00:00-08:00
|
||||
|
||||
When converting from another time zone, the fold will be set to the correct
|
||||
value::
|
||||
|
||||
>>> from datetime import timezone
|
||||
>>> LOS_ANGELES = ZoneInfo("America/Los_Angeles")
|
||||
>>> dt_utc = datetime(2020, 11, 1, 8, tzinfo=timezone.utc)
|
||||
|
||||
>>> # Before the PDT -> PST transition
|
||||
>>> print(dt_utc.astimezone(LOS_ANGELES))
|
||||
2020-11-01 01:00:00-07:00
|
||||
|
||||
>>> # After the PDT -> PST transition
|
||||
>>> print((dt_utc + timedelta(hours=1)).astimezone(LOS_ANGELES))
|
||||
2020-11-01 01:00:00-08:00
|
||||
|
||||
Data sources
|
||||
------------
|
||||
|
||||
The ``zoneinfo`` module does not directly provide time zone data, and instead
|
||||
pulls time zone information from the system time zone database or the
|
||||
first-party PyPI package `tzdata`_, if available. Some systems, including
|
||||
notably Windows systems, do not have an IANA database available, and so for
|
||||
projects targeting cross-platform compatibility that require time zone data, it
|
||||
is recommended to declare a dependency on tzdata. If neither system data nor
|
||||
tzdata are available, all calls to :class:`ZoneInfo` will raise
|
||||
:exc:`ZoneInfoNotFoundError`.
|
||||
|
||||
.. _zoneinfo_data_configuration:
|
||||
|
||||
Configuring the data sources
|
||||
****************************
|
||||
|
||||
When ``ZoneInfo(key)`` is called, the constructor first searches the
|
||||
directories specified in :data:`TZPATH` for a file matching ``key``, and on
|
||||
failure looks for a match in the tzdata package. This behavior can be
|
||||
configured in three ways:
|
||||
|
||||
1. The default :data:`TZPATH` when not otherwise specified can be configured at
|
||||
:ref:`compile time <zoneinfo_data_compile_time_config>`.
|
||||
2. :data:`TZPATH` can be configured using :ref:`an environment variable
|
||||
<zoneinfo_data_environment_var>`.
|
||||
3. At :ref:`runtime <zoneinfo_data_runtime_config>`, the search path can be
|
||||
manipulated using the :func:`reset_tzpath` function.
|
||||
|
||||
.. _zoneinfo_data_compile_time_config:
|
||||
|
||||
Compile-time configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The default :data:`TZPATH` includes several common deployment locations for the
|
||||
time zone database (except on Windows, where there are no "well-known"
|
||||
locations for time zone data). On POSIX systems, downstream distributors and
|
||||
those building Python from source who know where their system
|
||||
time zone data is deployed may change the default time zone path by specifying
|
||||
the compile-time option ``TZPATH`` (or, more likely, the ``configure`` flag
|
||||
``--with-tzpath``), which should be a string delimited by :data:`os.pathsep`.
|
||||
|
||||
On all platforms, the configured value is available as the ``TZPATH`` key in
|
||||
:func:`sysconfig.get_config_var`.
|
||||
|
||||
.. _zoneinfo_data_environment_var:
|
||||
|
||||
Environment configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When initializing :data:`TZPATH` (either at import time or whenever
|
||||
:func:`reset_tzpath` is called with no arguments), the ``zoneinfo`` module will
|
||||
use the environment variable ``PYTHONTZPATH``, if it exists, to set the search
|
||||
path.
|
||||
|
||||
.. envvar:: PYTHONTZPATH
|
||||
|
||||
This is an :data:`os.pathsep`-separated string containing the time zone
|
||||
search path to use. It must consist of only absolute rather than relative
|
||||
paths. Relative components specified in ``PYTHONTZPATH`` will not be used,
|
||||
but otherwise the behavior when a relative path is specified is
|
||||
implementation-defined; CPython will raise :exc:`InvalidTZPathWarning`, but
|
||||
other implementations are free to silently ignore the erroneous component
|
||||
or raise an exception.
|
||||
|
||||
To set the system to ignore the system data and use the tzdata package
|
||||
instead, set ``PYTHONTZPATH=""``.
|
||||
|
||||
.. _zoneinfo_data_runtime_config:
|
||||
|
||||
Runtime configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The TZ search path can also be configured at runtime using the
|
||||
:func:`reset_tzpath` function. This is generally not an advisable operation,
|
||||
though it is reasonable to use it in test functions that require the use of a
|
||||
specific time zone path (or require disabling access to the system time zones).
|
||||
|
||||
|
||||
The ``ZoneInfo`` class
|
||||
----------------------
|
||||
|
||||
.. class:: ZoneInfo(key)
|
||||
|
||||
A concrete :class:`datetime.tzinfo` subclass that represents an IANA time
|
||||
zone specified by the string ``key``. Calls to the primary constructor will
|
||||
always return objects that compare identically; put another way, barring
|
||||
cache invalidation via :meth:`ZoneInfo.clear_cache`, for all values of
|
||||
``key``, the following assertion will always be true:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
a = ZoneInfo(key)
|
||||
b = ZoneInfo(key)
|
||||
assert a is b
|
||||
|
||||
``key`` must be in the form of a relative, normalized POSIX path, with no
|
||||
up-level references. The constructor will raise :exc:`ValueError` if a
|
||||
non-conforming key is passed.
|
||||
|
||||
If no file matching ``key`` is found, the constructor will raise
|
||||
:exc:`ZoneInfoNotFoundError`.
|
||||
|
||||
|
||||
The ``ZoneInfo`` class has two alternate constructors:
|
||||
|
||||
.. classmethod:: ZoneInfo.from_file(fobj, /, key=None)
|
||||
|
||||
Constructs a ``ZoneInfo`` object from a file-like object returning bytes
|
||||
(e.g. a file opened in binary mode or an :class:`io.BytesIO` object).
|
||||
Unlike the primary constructor, this always constructs a new object.
|
||||
|
||||
The ``key`` parameter sets the name of the zone for the purposes of
|
||||
:py:meth:`~object.__str__` and :py:meth:`~object.__repr__`.
|
||||
|
||||
Objects created via this constructor cannot be pickled (see `pickling`_).
|
||||
|
||||
.. classmethod:: ZoneInfo.no_cache(key)
|
||||
|
||||
An alternate constructor that bypasses the constructor's cache. It is
|
||||
identical to the primary constructor, but returns a new object on each
|
||||
call. This is most likely to be useful for testing or demonstration
|
||||
purposes, but it can also be used to create a system with a different cache
|
||||
invalidation strategy.
|
||||
|
||||
Objects created via this constructor will also bypass the cache of a
|
||||
deserializing process when unpickled.
|
||||
|
||||
.. TODO: Add "See `cache_behavior`_" reference when that section is ready.
|
||||
|
||||
.. caution::
|
||||
|
||||
Using this constructor may change the semantics of your datetimes in
|
||||
surprising ways, only use it if you know that you need to.
|
||||
|
||||
The following class methods are also available:
|
||||
|
||||
.. classmethod:: ZoneInfo.clear_cache(*, only_keys=None)
|
||||
|
||||
A method for invalidating the cache on the ``ZoneInfo`` class. If no
|
||||
arguments are passed, all caches are invalidated and the next call to
|
||||
the primary constructor for each key will return a new instance.
|
||||
|
||||
If an iterable of key names is passed to the ``only_keys`` parameter, only
|
||||
the specified keys will be removed from the cache. Keys passed to
|
||||
``only_keys`` but not found in the cache are ignored.
|
||||
|
||||
.. TODO: Add "See `cache_behavior`_" reference when that section is ready.
|
||||
|
||||
.. warning::
|
||||
|
||||
Invoking this function may change the semantics of datetimes using
|
||||
``ZoneInfo`` in surprising ways; this modifies process-wide global state
|
||||
and thus may have wide-ranging effects. Only use it if you know that you
|
||||
need to.
|
||||
|
||||
The class has one attribute:
|
||||
|
||||
.. attribute:: ZoneInfo.key
|
||||
|
||||
This is a read-only :term:`attribute` that returns the value of ``key``
|
||||
passed to the constructor, which should be a lookup key in the IANA time
|
||||
zone database (e.g. ``America/New_York``, ``Europe/Paris`` or
|
||||
``Asia/Tokyo``).
|
||||
|
||||
For zones constructed from file without specifying a ``key`` parameter,
|
||||
this will be set to ``None``.
|
||||
|
||||
.. note::
|
||||
|
||||
Although it is a somewhat common practice to expose these to end users,
|
||||
these values are designed to be primary keys for representing the
|
||||
relevant zones and not necessarily user-facing elements. Projects like
|
||||
CLDR (the Unicode Common Locale Data Repository) can be used to get
|
||||
more user-friendly strings from these keys.
|
||||
|
||||
String representations
|
||||
**********************
|
||||
|
||||
The string representation returned when calling :py:class:`str` on a
|
||||
:class:`ZoneInfo` object defaults to using the :attr:`ZoneInfo.key` attribute (see
|
||||
the note on usage in the attribute documentation)::
|
||||
|
||||
>>> zone = ZoneInfo("Pacific/Kwajalein")
|
||||
>>> str(zone)
|
||||
'Pacific/Kwajalein'
|
||||
|
||||
>>> dt = datetime(2020, 4, 1, 3, 15, tzinfo=zone)
|
||||
>>> f"{dt.isoformat()} [{dt.tzinfo}]"
|
||||
'2020-04-01T03:15:00+12:00 [Pacific/Kwajalein]'
|
||||
|
||||
For objects constructed from a file without specifying a ``key`` parameter,
|
||||
``str`` falls back to calling :func:`repr`. ``ZoneInfo``'s ``repr`` is
|
||||
implementation-defined and not necessarily stable between versions, but it is
|
||||
guaranteed not to be a valid ``ZoneInfo`` key.
|
||||
|
||||
.. _pickling:
|
||||
|
||||
Pickle serialization
|
||||
********************
|
||||
|
||||
Rather than serializing all transition data, ``ZoneInfo`` objects are
|
||||
serialized by key, and ``ZoneInfo`` objects constructed from files (even those
|
||||
with a value for ``key`` specified) cannot be pickled.
|
||||
|
||||
The behavior of a ``ZoneInfo`` file depends on how it was constructed:
|
||||
|
||||
1. ``ZoneInfo(key)``: When constructed with the primary constructor, a
|
||||
``ZoneInfo`` object is serialized by key, and when deserialized, the
|
||||
deserializing process uses the primary and thus it is expected that these
|
||||
are expected to be the same object as other references to the same time
|
||||
zone. For example, if ``europe_berlin_pkl`` is a string containing a pickle
|
||||
constructed from ``ZoneInfo("Europe/Berlin")``, one would expect the
|
||||
following behavior:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a = ZoneInfo("Europe/Berlin")
|
||||
>>> b = pickle.loads(europe_berlin_pkl)
|
||||
>>> a is b
|
||||
True
|
||||
|
||||
2. ``ZoneInfo.no_cache(key)``: When constructed from the cache-bypassing
|
||||
constructor, the ``ZoneInfo`` object is also serialized by key, but when
|
||||
deserialized, the deserializing process uses the cache bypassing
|
||||
constructor. If ``europe_berlin_pkl_nc`` is a string containing a pickle
|
||||
constructed from ``ZoneInfo.no_cache("Europe/Berlin")``, one would expect
|
||||
the following behavior:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a = ZoneInfo("Europe/Berlin")
|
||||
>>> b = pickle.loads(europe_berlin_pkl_nc)
|
||||
>>> a is b
|
||||
False
|
||||
|
||||
3. ``ZoneInfo.from_file(fobj, /, key=None)``: When constructed from a file, the
|
||||
``ZoneInfo`` object raises an exception on pickling. If an end user wants to
|
||||
pickle a ``ZoneInfo`` constructed from a file, it is recommended that they
|
||||
use a wrapper type or a custom serialization function: either serializing by
|
||||
key or storing the contents of the file object and serializing that.
|
||||
|
||||
This method of serialization requires that the time zone data for the required
|
||||
key be available on both the serializing and deserializing side, similar to the
|
||||
way that references to classes and functions are expected to exist in both the
|
||||
serializing and deserializing environments. It also means that no guarantees
|
||||
are made about the consistency of results when unpickling a ``ZoneInfo``
|
||||
pickled in an environment with a different version of the time zone data.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: available_timezones()
|
||||
|
||||
Get a set containing all the valid keys for IANA time zones available
|
||||
anywhere on the time zone path. This is recalculated on every call to the
|
||||
function.
|
||||
|
||||
This function only includes canonical zone names and does not include
|
||||
"special" zones such as those under the ``posix/`` and ``right/``
|
||||
directories, or the ``posixrules`` zone.
|
||||
|
||||
.. caution::
|
||||
|
||||
This function may open a large number of files, as the best way to
|
||||
determine if a file on the time zone path is a valid time zone is to
|
||||
read the "magic string" at the beginning.
|
||||
|
||||
.. note::
|
||||
|
||||
These values are not designed to be exposed to end-users; for user
|
||||
facing elements, applications should use something like CLDR (the
|
||||
Unicode Common Locale Data Repository) to get more user-friendly
|
||||
strings. See also the cautionary note on :attr:`ZoneInfo.key`.
|
||||
|
||||
.. function:: reset_tzpath(to=None)
|
||||
|
||||
Sets or resets the time zone search path (:data:`TZPATH`) for the module.
|
||||
When called with no arguments, :data:`TZPATH` is set to the default value.
|
||||
|
||||
Calling ``reset_tzpath`` will not invalidate the :class:`ZoneInfo` cache,
|
||||
and so calls to the primary ``ZoneInfo`` constructor will only use the new
|
||||
``TZPATH`` in the case of a cache miss.
|
||||
|
||||
The ``to`` parameter must be a :term:`sequence` of strings or
|
||||
:class:`os.PathLike` and not a string, all of which must be absolute paths.
|
||||
:exc:`ValueError` will be raised if something other than an absolute path
|
||||
is passed.
|
||||
|
||||
Globals
|
||||
-------
|
||||
|
||||
.. data:: TZPATH
|
||||
|
||||
A read-only sequence representing the time zone search path -- when
|
||||
constructing a ``ZoneInfo`` from a key, the key is joined to each entry in
|
||||
the ``TZPATH``, and the first file found is used.
|
||||
|
||||
``TZPATH`` may contain only absolute paths, never relative paths,
|
||||
regardless of how it is configured.
|
||||
|
||||
The object that ``zoneinfo.TZPATH`` points to may change in response to a
|
||||
call to :func:`reset_tzpath`, so it is recommended to use
|
||||
``zoneinfo.TZPATH`` rather than importing ``TZPATH`` from ``zoneinfo`` or
|
||||
assigning a long-lived variable to ``zoneinfo.TZPATH``.
|
||||
|
||||
For more information on configuring the time zone search path, see
|
||||
:ref:`zoneinfo_data_configuration`.
|
||||
|
||||
Exceptions and warnings
|
||||
-----------------------
|
||||
|
||||
.. exception:: ZoneInfoNotFoundError
|
||||
|
||||
Raised when construction of a :class:`ZoneInfo` object fails because the
|
||||
specified key could not be found on the system. This is a subclass of
|
||||
:exc:`KeyError`.
|
||||
|
||||
.. exception:: InvalidTZPathWarning
|
||||
|
||||
Raised when :envvar:`PYTHONTZPATH` contains an invalid component that will
|
||||
be filtered out, such as a relative path.
|
||||
|
||||
.. Links and references:
|
||||
|
||||
.. _tzdata: https://pypi.org/project/tzdata/
|
|
@ -325,7 +325,7 @@ of identifiers is based on NFKC.
|
|||
|
||||
A non-normative HTML file listing all valid identifier characters for Unicode
|
||||
4.1 can be found at
|
||||
https://www.dcl.hpi.uni-potsdam.de/home/loewis/table-3131.html.
|
||||
https://www.unicode.org/Public/13.0.0/ucd/DerivedCoreProperties.txt
|
||||
|
||||
|
||||
.. _keywords:
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
import os
|
||||
import sys
|
||||
sys.path.append(os.path.abspath("../Parser/"))
|
||||
|
||||
from pygments.lexer import RegexLexer, bygroups, include, words
|
||||
from pygments.token import (Comment, Generic, Keyword, Name, Operator,
|
||||
Punctuation, Text)
|
||||
|
||||
from asdl import builtin_types
|
||||
from sphinx.highlighting import lexers
|
||||
|
||||
class ASDLLexer(RegexLexer):
|
||||
name = "ASDL"
|
||||
aliases = ["asdl"]
|
||||
filenames = ["*.asdl"]
|
||||
_name = r"([^\W\d]\w*)"
|
||||
_text_ws = r"(\s*)"
|
||||
|
||||
tokens = {
|
||||
"ws": [
|
||||
(r"\n", Text),
|
||||
(r"\s+", Text),
|
||||
(r"--.*?$", Comment.Singleline),
|
||||
],
|
||||
"root": [
|
||||
include("ws"),
|
||||
(
|
||||
r"(module)" + _text_ws + _name,
|
||||
bygroups(Keyword, Text, Name.Tag),
|
||||
),
|
||||
(
|
||||
r"(\w+)(\*\s|\?\s|\s)(\w+)",
|
||||
bygroups(Name.Builtin.Pseudo, Operator, Name),
|
||||
),
|
||||
(words(builtin_types), Name.Builtin),
|
||||
(r"attributes", Name.Builtin),
|
||||
(
|
||||
_name + _text_ws + "(=)",
|
||||
bygroups(Name, Text, Operator),
|
||||
),
|
||||
(_name, Name.Class),
|
||||
(r"\|", Operator),
|
||||
(r"{|}|\(|\)", Punctuation),
|
||||
(r".", Text),
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def setup(app):
|
||||
lexers["asdl"] = ASDLLexer()
|
||||
return {'version': '1.0', 'parallel_read_safe': True}
|
|
@ -10,7 +10,8 @@
|
|||
'(?:release/\\d.\\d[\\x\\d\\.]*)'];
|
||||
|
||||
var all_versions = {
|
||||
'3.9': 'dev (3.9)',
|
||||
'3.10': 'dev (3.10)',
|
||||
'3.9': 'pre (3.9)',
|
||||
'3.8': '3.8',
|
||||
'3.7': '3.7',
|
||||
'3.6': '3.6',
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
<p><a href="{{ pathto('download') }}">{% trans %}Download these documents{% endtrans %}</a></p>
|
||||
<h3>{% trans %}Docs by version{% endtrans %}</h3>
|
||||
<ul>
|
||||
<li><a href="https://docs.python.org/3.9/">{% trans %}Python 3.9 (in development){% endtrans %}</a></li>
|
||||
<li><a href="https://docs.python.org/3.10/">{% trans %}Python 3.10 (in development){% endtrans %}</a></li>
|
||||
<li><a href="https://docs.python.org/3.9/">{% trans %}Python 3.9 (pre-release){% endtrans %}</a></li>
|
||||
<li><a href="https://docs.python.org/3.8/">{% trans %}Python 3.8 (stable){% endtrans %}</a></li>
|
||||
<li><a href="https://docs.python.org/3.7/">{% trans %}Python 3.7 (stable){% endtrans %}</a></li>
|
||||
<li><a href="https://docs.python.org/3.6/">{% trans %}Python 3.6 (security-fixes){% endtrans %}</a></li>
|
||||
|
|
|
@ -70,6 +70,9 @@ Code that modifies a collection while iterating over that same collection can
|
|||
be tricky to get right. Instead, it is usually more straight-forward to loop
|
||||
over a copy of the collection or to create a new collection::
|
||||
|
||||
# Create a sample collection
|
||||
users = {'Hans': 'active', 'Éléonore': 'inactive', '景太郎': 'active'}
|
||||
|
||||
# Strategy: Iterate over a copy
|
||||
for user, status in users.copy().items():
|
||||
if status == 'inactive':
|
||||
|
|
|
@ -613,6 +613,21 @@ direction and then call the :func:`reversed` function. ::
|
|||
To loop over a sequence in sorted order, use the :func:`sorted` function which
|
||||
returns a new sorted list while leaving the source unaltered. ::
|
||||
|
||||
>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
|
||||
>>> for i in sorted(basket):
|
||||
... print(i)
|
||||
...
|
||||
apple
|
||||
apple
|
||||
banana
|
||||
orange
|
||||
orange
|
||||
pear
|
||||
|
||||
Using :func:`set` on a sequence eliminates duplicate elements. The use of
|
||||
:func:`sorted` in combination with :func:`set` over a sequence is an idiomatic
|
||||
way to loop over unique elements of the sequence in sorted order. ::
|
||||
|
||||
>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
|
||||
>>> for f in sorted(set(basket)):
|
||||
... print(f)
|
||||
|
|
|
@ -67,7 +67,7 @@ The rest of the line provides detail based on the type of exception and what
|
|||
caused it.
|
||||
|
||||
The preceding part of the error message shows the context where the exception
|
||||
happened, in the form of a stack traceback. In general it contains a stack
|
||||
occurred, in the form of a stack traceback. In general it contains a stack
|
||||
traceback listing source lines; however, it will not display lines read from
|
||||
standard input.
|
||||
|
||||
|
|
|
@ -172,7 +172,7 @@ Positional and keyword arguments can be arbitrarily combined::
|
|||
If you have a really long format string that you don't want to split up, it
|
||||
would be nice if you could reference the variables to be formatted by name
|
||||
instead of by position. This can be done by simply passing the dict and using
|
||||
square brackets ``'[]'`` to access the keys ::
|
||||
square brackets ``'[]'`` to access the keys. ::
|
||||
|
||||
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
|
||||
>>> print('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; '
|
||||
|
@ -257,10 +257,10 @@ left with zeros. It understands about plus and minus signs::
|
|||
Old string formatting
|
||||
---------------------
|
||||
|
||||
The ``%`` operator can also be used for string formatting. It interprets the
|
||||
left argument much like a :c:func:`sprintf`\ -style format string to be applied
|
||||
to the right argument, and returns the string resulting from this formatting
|
||||
operation. For example::
|
||||
The % operator (modulo) can also be used for string formatting. Given ``'string'
|
||||
% values``, instances of ``%`` in ``string`` are replaced with zero or more
|
||||
elements of ``values``. This operation is commonly known as string
|
||||
interpolation. For example::
|
||||
|
||||
>>> import math
|
||||
>>> print('The value of pi is approximately %5.3f.' % math.pi)
|
||||
|
|
|
@ -10,13 +10,13 @@ Using the Python Interpreter
|
|||
Invoking the Interpreter
|
||||
========================
|
||||
|
||||
The Python interpreter is usually installed as :file:`/usr/local/bin/python3.9`
|
||||
The Python interpreter is usually installed as :file:`/usr/local/bin/python3.10`
|
||||
on those machines where it is available; putting :file:`/usr/local/bin` in your
|
||||
Unix shell's search path makes it possible to start it by typing the command:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
python3.9
|
||||
python3.10
|
||||
|
||||
to the shell. [#]_ Since the choice of the directory where the interpreter lives
|
||||
is an installation option, other places are possible; check with your local
|
||||
|
@ -24,7 +24,7 @@ Python guru or system administrator. (E.g., :file:`/usr/local/python` is a
|
|||
popular alternative location.)
|
||||
|
||||
On Windows machines where you have installed Python from the :ref:`Microsoft Store
|
||||
<windows-store>`, the :file:`python3.9` command will be available. If you have
|
||||
<windows-store>`, the :file:`python3.10` command will be available. If you have
|
||||
the :ref:`py.exe launcher <launcher>` installed, you can use the :file:`py`
|
||||
command. See :ref:`setting-envvars` for other ways to launch Python.
|
||||
|
||||
|
@ -97,8 +97,8 @@ before printing the first prompt:
|
|||
|
||||
.. code-block:: shell-session
|
||||
|
||||
$ python3.9
|
||||
Python 3.9 (default, June 4 2019, 09:25:04)
|
||||
$ python3.10
|
||||
Python 3.10 (default, June 4 2019, 09:25:04)
|
||||
[GCC 4.8.2] on linux
|
||||
Type "help", "copyright", "credits" or "license" for more information.
|
||||
>>>
|
||||
|
|
|
@ -15,7 +15,7 @@ operating system::
|
|||
|
||||
>>> import os
|
||||
>>> os.getcwd() # Return the current working directory
|
||||
'C:\\Python39'
|
||||
'C:\\Python310'
|
||||
>>> os.chdir('/server/accesslogs') # Change current working directory
|
||||
>>> os.system('mkdir today') # Run the command mkdir in the system shell
|
||||
0
|
||||
|
|
|
@ -278,7 +278,7 @@ applications include caching objects that are expensive to create::
|
|||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
d['primary'] # entry was automatically removed
|
||||
File "C:/python39/lib/weakref.py", line 46, in __getitem__
|
||||
File "C:/python310/lib/weakref.py", line 46, in __getitem__
|
||||
o = self.data[key]()
|
||||
KeyError: 'primary'
|
||||
|
||||
|
|
|
@ -27,9 +27,8 @@ What you get after installing is a number of things:
|
|||
|
||||
* A :file:`Python 3.9` folder in your :file:`Applications` folder. In here
|
||||
you find IDLE, the development environment that is a standard part of official
|
||||
Python distributions; PythonLauncher, which handles double-clicking Python
|
||||
scripts from the Finder; and the "Build Applet" tool, which allows you to
|
||||
package Python scripts as standalone applications on your system.
|
||||
Python distributions; and PythonLauncher, which handles double-clicking Python
|
||||
scripts from the Finder.
|
||||
|
||||
* A framework :file:`/Library/Frameworks/Python.framework`, which includes the
|
||||
Python executable and libraries. The installer adds this location to your shell
|
||||
|
@ -159,11 +158,6 @@ https://riverbankcomputing.com/software/pyqt/intro.
|
|||
Distributing Python Applications on the Mac
|
||||
===========================================
|
||||
|
||||
The "Build Applet" tool that is placed in the MacPython 3.6 folder is fine for
|
||||
packaging small Python scripts on your own machine to run as a standard Mac
|
||||
application. This tool, however, is not robust enough to distribute Python
|
||||
applications to other users.
|
||||
|
||||
The standard tool for deploying standalone Python applications on the Mac is
|
||||
:program:`py2app`. More information on installing and using py2app can be found
|
||||
at http://undefined.org/python/#py2app.
|
||||
|
|
|
@ -91,7 +91,7 @@ The command, if run with ``-h``, will show the available options::
|
|||
PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||
|
||||
See `About Execution Policies
|
||||
<ttps:/go.microsoft.com/fwlink/?LinkID=135170>`_
|
||||
<https://go.microsoft.com/fwlink/?LinkID=135170>`_
|
||||
for more information.
|
||||
|
||||
The created ``pyvenv.cfg`` file also includes the
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
****************************
|
||||
What's New In Python 3.10
|
||||
****************************
|
||||
|
||||
:Release: |release|
|
||||
:Date: |today|
|
||||
|
||||
.. Rules for maintenance:
|
||||
|
||||
* Anyone can add text to this document. Do not spend very much time
|
||||
on the wording of your changes, because your text will probably
|
||||
get rewritten to some degree.
|
||||
|
||||
* The maintainer will go through Misc/NEWS periodically and add
|
||||
changes; it's therefore more important to add your changes to
|
||||
Misc/NEWS than to this file.
|
||||
|
||||
* This is not a complete list of every single change; completeness
|
||||
is the purpose of Misc/NEWS. Some changes I consider too small
|
||||
or esoteric to include. If such a change is added to the text,
|
||||
I'll just remove it. (This is another reason you shouldn't spend
|
||||
too much time on writing your addition.)
|
||||
|
||||
* If you want to draw your new text to the attention of the
|
||||
maintainer, add 'XXX' to the beginning of the paragraph or
|
||||
section.
|
||||
|
||||
* It's OK to just add a fragmentary note about a change. For
|
||||
example: "XXX Describe the transmogrify() function added to the
|
||||
socket module." The maintainer will research the change and
|
||||
write the necessary text.
|
||||
|
||||
* You can comment out your additions if you like, but it's not
|
||||
necessary (especially when a final release is some months away).
|
||||
|
||||
* Credit the author of a patch or bugfix. Just the name is
|
||||
sufficient; the e-mail address isn't necessary.
|
||||
|
||||
* It's helpful to add the bug/patch number as a comment:
|
||||
|
||||
XXX Describe the transmogrify() function added to the socket
|
||||
module.
|
||||
(Contributed by P.Y. Developer in :issue:`12345`.)
|
||||
|
||||
This saves the maintainer the effort of going through the Mercurial log
|
||||
when researching a change.
|
||||
|
||||
This article explains the new features in Python 3.10, compared to 3.9.
|
||||
|
||||
For full details, see the :ref:`changelog <changelog>`.
|
||||
|
||||
.. note::
|
||||
|
||||
Prerelease users should be aware that this document is currently in draft
|
||||
form. It will be updated substantially as Python 3.10 moves towards release,
|
||||
so it's worth checking back even after reading earlier versions.
|
||||
|
||||
|
||||
Summary -- Release highlights
|
||||
=============================
|
||||
|
||||
.. This section singles out the most important changes in Python 3.10.
|
||||
Brevity is key.
|
||||
|
||||
|
||||
.. PEP-sized items next.
|
||||
|
||||
|
||||
|
||||
New Features
|
||||
============
|
||||
|
||||
|
||||
|
||||
Other Language Changes
|
||||
======================
|
||||
|
||||
* Builtin and extension functions that take integer arguments no longer accept
|
||||
:class:`~decimal.Decimal`\ s, :class:`~fractions.Fraction`\ s and other
|
||||
objects that can be converted to integers only with a loss (e.g. that have
|
||||
the :meth:`~object.__int__` method but do not have the
|
||||
:meth:`~object.__index__` method).
|
||||
(Contributed by Serhiy Storchaka in :issue:`37999`.)
|
||||
|
||||
|
||||
New Modules
|
||||
===========
|
||||
|
||||
* None yet.
|
||||
|
||||
|
||||
Improved Modules
|
||||
================
|
||||
|
||||
tracemalloc
|
||||
-----------
|
||||
|
||||
Added :func:`tracemalloc.reset_peak` to set the peak size of traced memory
|
||||
blocks to the current size, to measure the peak of specific pieces of code.
|
||||
(Contributed by Huon Wilson in :issue:`40630`.)
|
||||
|
||||
Optimizations
|
||||
=============
|
||||
|
||||
|
||||
Deprecated
|
||||
==========
|
||||
|
||||
|
||||
Removed
|
||||
=======
|
||||
|
||||
|
||||
Porting to Python 3.10
|
||||
======================
|
||||
|
||||
This section lists previously described changes and other bugfixes
|
||||
that may require changes to your code.
|
||||
|
||||
|
||||
|
||||
Build Changes
|
||||
=============
|
||||
|
||||
|
||||
C API Changes
|
||||
=============
|
||||
|
||||
New Features
|
||||
------------
|
||||
|
||||
The result of :c:func:`PyNumber_Index` now always has exact type :class:`int`.
|
||||
Previously, the result could have been an instance of a subclass of ``int``.
|
||||
(Contributed by Serhiy Storchaka in :issue:`40792`.)
|
||||
|
||||
|
||||
Porting to Python 3.10
|
||||
----------------------
|
||||
|
||||
* Since :c:func:`Py_TYPE()` is changed to the inline static function,
|
||||
``Py_TYPE(obj) = new_type`` must be replaced with ``Py_SET_TYPE(obj, new_type)``:
|
||||
see :c:func:`Py_SET_TYPE()` (available since Python 3.9).
|
||||
(Contributed by Dong-hee Na in :issue:`39573`.)
|
||||
|
||||
* Since :c:func:`Py_REFCNT()` is changed to the inline static function,
|
||||
``Py_REFCNT(obj) = new_refcnt`` must be replaced with ``Py_SET_REFCNT(obj, new_refcnt)``:
|
||||
see :c:func:`Py_SET_REFCNT()` (available since Python 3.9).
|
||||
(Contributed by Victor Stinner in :issue:`39573`.)
|
||||
|
||||
* Since :c:func:`Py_SIZE()` is changed to the inline static function,
|
||||
``Py_SIZE(obj) = new_size`` must be replaced with ``Py_SET_SIZE(obj, new_size)``:
|
||||
see :c:func:`Py_SET_SIZE()` (available since Python 3.9).
|
||||
(Contributed by Victor Stinner in :issue:`39573`.)
|
||||
|
||||
Removed
|
||||
-------
|
|
@ -428,8 +428,8 @@ Other Language Changes
|
|||
lastname, *members = family.split()
|
||||
return lastname.upper(), *members
|
||||
|
||||
>>> parse('simpsons homer marge bart lisa sally')
|
||||
('SIMPSONS', 'homer', 'marge', 'bart', 'lisa', 'sally')
|
||||
>>> parse('simpsons homer marge bart lisa maggie')
|
||||
('SIMPSONS', 'homer', 'marge', 'bart', 'lisa', 'maggie')
|
||||
|
||||
(Contributed by David Cuthbert and Jordan Chapman in :issue:`32117`.)
|
||||
|
||||
|
@ -1692,7 +1692,7 @@ Deprecated
|
|||
:meth:`~gettext.NullTranslations.set_output_charset`, and the *codeset*
|
||||
parameter of functions :func:`~gettext.translation` and
|
||||
:func:`~gettext.install` are also deprecated, since they are only used for
|
||||
for the ``l*gettext()`` functions.
|
||||
the ``l*gettext()`` functions.
|
||||
(Contributed by Serhiy Storchaka in :issue:`33710`.)
|
||||
|
||||
* The :meth:`~threading.Thread.isAlive()` method of :class:`threading.Thread`
|
||||
|
|
|
@ -113,7 +113,7 @@ PEP 616: New removeprefix() and removesuffix() string methods
|
|||
to easily remove an unneeded prefix or a suffix from a string. Corresponding
|
||||
``bytes``, ``bytearray``, and ``collections.UserString`` methods have also been
|
||||
added. See :pep:`616` for a full description. (Contributed by Dennis Sweeney in
|
||||
:issue:`18939`.)
|
||||
:issue:`39939`.)
|
||||
|
||||
PEP 585: Builtin Generic Types
|
||||
------------------------------
|
||||
|
@ -205,7 +205,44 @@ Other Language Changes
|
|||
New Modules
|
||||
===========
|
||||
|
||||
* None yet.
|
||||
zoneinfo
|
||||
--------
|
||||
|
||||
The :mod:`zoneinfo` module brings support for the IANA time zone database to
|
||||
the standard library. It adds :class:`zoneinfo.ZoneInfo`, a concrete
|
||||
:class:`datetime.tzinfo` implementation backed by the system's time zone data.
|
||||
|
||||
Example::
|
||||
|
||||
>>> from zoneinfo import ZoneInfo
|
||||
>>> from datetime import datetime, timedelta
|
||||
|
||||
>>> # Daylight saving time
|
||||
>>> dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles"))
|
||||
>>> print(dt)
|
||||
2020-10-31 12:00:00-07:00
|
||||
>>> dt.tzname()
|
||||
'PDT'
|
||||
|
||||
>>> # Standard time
|
||||
>>> dt += timedelta(days=7)
|
||||
>>> print(dt)
|
||||
2020-11-07 12:00:00-08:00
|
||||
>>> print(dt.tzname())
|
||||
PST
|
||||
|
||||
|
||||
As a fall-back source of data for platforms that don't ship the IANA database,
|
||||
the |tzdata|_ module was released as a first-party package -- distributed via
|
||||
PyPI and maintained by the CPython core team.
|
||||
|
||||
.. |tzdata| replace:: ``tzdata``
|
||||
.. _tzdata: https://pypi.org/project/tzdata/
|
||||
|
||||
.. seealso::
|
||||
|
||||
:pep:`615` -- Support for the IANA Time Zone Database in the Standard Library
|
||||
PEP written and implemented by Paul Ganssle
|
||||
|
||||
|
||||
Improved Modules
|
||||
|
@ -245,6 +282,22 @@ that schedules a shutdown for the default executor that waits on the
|
|||
Added :class:`asyncio.PidfdChildWatcher`, a Linux-specific child watcher
|
||||
implementation that polls process file descriptors. (:issue:`38692`)
|
||||
|
||||
Added a new :term:`coroutine` :func:`asyncio.to_thread`. It is mainly used for
|
||||
running IO-bound functions in a separate thread to avoid blocking the event
|
||||
loop, and essentially works as a high-level version of
|
||||
:meth:`~asyncio.loop.run_in_executor` that can directly take keyword arguments.
|
||||
(Contributed by Kyle Stanley and Yury Selivanov in :issue:`32309`.)
|
||||
|
||||
compileall
|
||||
----------
|
||||
|
||||
Added new possibility to use hardlinks for duplicated ``.pyc`` files: *hardlink_dupes* parameter and --hardlink-dupes command line option.
|
||||
(Contributed by Lumír 'Frenzy' Balhar in :issue:`40495`.)
|
||||
|
||||
Added new options for path manipulation in resulting ``.pyc`` files: *stripdir*, *prependdir*, *limit_sl_dest* parameters and -s, -p, -e command line options.
|
||||
Added the possibility to specify the option for an optimization level multiple times.
|
||||
(Contributed by Lumír 'Frenzy' Balhar in :issue:`38112`.)
|
||||
|
||||
concurrent.futures
|
||||
------------------
|
||||
|
||||
|
@ -271,6 +324,20 @@ Add :func:`curses.get_escdelay`, :func:`curses.set_escdelay`,
|
|||
:func:`curses.get_tabsize`, and :func:`curses.set_tabsize` functions.
|
||||
(Contributed by Anthony Sottile in :issue:`38312`.)
|
||||
|
||||
datetime
|
||||
--------
|
||||
The :meth:`~datetime.date.isocalendar()` of :class:`datetime.date`
|
||||
and :meth:`~datetime.datetime.isocalendar()` of :class:`datetime.datetime`
|
||||
methods now returns a :func:`~collections.namedtuple` instead of a :class:`tuple`.
|
||||
(Contributed by Dong-hee Na in :issue:`24416`.)
|
||||
|
||||
distutils
|
||||
---------
|
||||
|
||||
The :command:`upload` command now creates SHA2-256 and Blake2b-256 hash
|
||||
digests. It skips MD5 on platforms that block MD5 digest.
|
||||
(Contributed by Christian Heimes in :issue:`40698`.)
|
||||
|
||||
fcntl
|
||||
-----
|
||||
|
||||
|
@ -304,6 +371,15 @@ Added a new function :func:`gc.is_finalized` to check if an object has been
|
|||
finalized by the garbage collector. (Contributed by Pablo Galindo in
|
||||
:issue:`39322`.)
|
||||
|
||||
hashlib
|
||||
-------
|
||||
|
||||
Builtin hash modules can now be disabled with
|
||||
``./configure --without-builtin-hashlib-hashes`` or selectively enabled with
|
||||
e.g. ``./configure --with-builtin-hashlib-hashes=sha3,blake2`` to force use
|
||||
of OpenSSL based implementation.
|
||||
(Contributed by Christian Heimes in :issue:`40479`)
|
||||
|
||||
http
|
||||
----
|
||||
|
||||
|
@ -461,6 +537,17 @@ The :mod:`socket` module now exports the :data:`~socket.CAN_RAW_JOIN_FILTERS`
|
|||
constant on Linux 4.1 and greater.
|
||||
(Contributed by Stefan Tatschner and Zackery Spytz in :issue:`25780`.)
|
||||
|
||||
The socket module now supports the :data:`~socket.CAN_J1939` protocol on
|
||||
platforms that support it. (Contributed by Karl Ding in :issue:`40291`.)
|
||||
|
||||
time
|
||||
----
|
||||
|
||||
On AIX, :func:`~time.thread_time` is now implemented with ``thread_cputime()``
|
||||
which has nanosecond resolution, rather than
|
||||
``clock_gettime(CLOCK_THREAD_CPUTIME_ID)`` which has a resolution of 10 ms.
|
||||
(Contributed by Batuhan Taskaya in :issue:`40192`)
|
||||
|
||||
sys
|
||||
---
|
||||
|
||||
|
@ -471,6 +558,10 @@ most platforms. On Fedora and SuSE, it is equal to ``"lib64"`` on 64-bit
|
|||
platforms.
|
||||
(Contributed by Jan Matějek, Matěj Cepl, Charalampos Stratakis and Victor Stinner in :issue:`1294959`.)
|
||||
|
||||
Previously, :attr:`sys.stderr` was block-buffered when non-interactive. Now
|
||||
``stderr`` defaults to always being line-buffered.
|
||||
(Contributed by Jendrik Seipp in :issue:`13601`.)
|
||||
|
||||
|
||||
typing
|
||||
------
|
||||
|
@ -514,7 +605,7 @@ Optimizations
|
|||
|
||||
sums = [s for s in [0] for x in data for s in [s + x]]
|
||||
|
||||
Unlike to the ``:=`` operator this idiom does not leak a variable to the
|
||||
Unlike the ``:=`` operator this idiom does not leak a variable to the
|
||||
outer scope.
|
||||
|
||||
(Contributed by Serhiy Storchaka in :issue:`32856`.)
|
||||
|
@ -533,6 +624,61 @@ Optimizations
|
|||
(Contributed by Ed Maste, Conrad Meyer, Kyle Evans, Kubilay Kocak and Victor
|
||||
Stinner in :issue:`38061`.)
|
||||
|
||||
Here's a summary of performance improvements from Python 3.4 through Python 3.9:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
Python version 3.4 3.5 3.6 3.7 3.8 3.9
|
||||
-------------- --- --- --- --- --- ---
|
||||
|
||||
Variable and attribute read access:
|
||||
read_local 7.1 7.1 5.4 5.1 3.9 4.0
|
||||
read_nonlocal 7.1 8.1 5.8 5.4 4.4 4.8
|
||||
read_global 15.5 19.0 14.3 13.6 7.6 7.7
|
||||
read_builtin 21.1 21.6 18.5 19.0 7.5 7.7
|
||||
read_classvar_from_class 25.6 26.5 20.7 19.5 18.4 18.6
|
||||
read_classvar_from_instance 22.8 23.5 18.8 17.1 16.4 20.1
|
||||
read_instancevar 32.4 33.1 28.0 26.3 25.4 27.7
|
||||
read_instancevar_slots 27.8 31.3 20.8 20.8 20.2 24.5
|
||||
read_namedtuple 73.8 57.5 45.0 46.8 18.4 23.2
|
||||
read_boundmethod 37.6 37.9 29.6 26.9 27.7 45.9
|
||||
|
||||
Variable and attribute write access:
|
||||
write_local 8.7 9.3 5.5 5.3 4.3 4.2
|
||||
write_nonlocal 10.5 11.1 5.6 5.5 4.7 4.9
|
||||
write_global 19.7 21.2 18.0 18.0 15.8 17.2
|
||||
write_classvar 92.9 96.0 104.6 102.1 39.2 43.2
|
||||
write_instancevar 44.6 45.8 40.0 38.9 35.5 40.7
|
||||
write_instancevar_slots 35.6 36.1 27.3 26.6 25.7 27.7
|
||||
|
||||
Data structure read access:
|
||||
read_list 24.2 24.5 20.8 20.8 19.0 21.1
|
||||
read_deque 24.7 25.5 20.2 20.6 19.8 21.6
|
||||
read_dict 24.3 25.7 22.3 23.0 21.0 22.5
|
||||
read_strdict 22.6 24.3 19.5 21.2 18.9 21.6
|
||||
|
||||
Data structure write access:
|
||||
write_list 27.1 28.5 22.5 21.6 20.0 21.6
|
||||
write_deque 28.7 30.1 22.7 21.8 23.5 23.2
|
||||
write_dict 31.4 33.3 29.3 29.2 24.7 27.8
|
||||
write_strdict 28.4 29.9 27.5 25.2 23.1 29.8
|
||||
|
||||
Stack (or queue) operations:
|
||||
list_append_pop 93.4 112.7 75.4 74.2 50.8 53.9
|
||||
deque_append_pop 43.5 57.0 49.4 49.2 42.5 45.5
|
||||
deque_append_popleft 43.7 57.3 49.7 49.7 42.8 45.5
|
||||
|
||||
Timing loop:
|
||||
loop_overhead 0.5 0.6 0.4 0.3 0.3 0.3
|
||||
|
||||
These results were generated from the variable access benchmark script at:
|
||||
``Tools/scripts/var_access_benchmark.py``. The benchmark script displays timings
|
||||
in nanoseconds. The benchmarks were measured on an
|
||||
`Intel® Core™ i7-4960HQ processor
|
||||
<https://ark.intel.com/content/www/us/en/ark/products/76088/intel-core-i7-4960hq-processor-6m-cache-up-to-3-80-ghz.html>`_
|
||||
running the macOS 64-bit builds found at
|
||||
`python.org <https://www.python.org/downloads/mac-osx/>`_.
|
||||
|
||||
|
||||
Deprecated
|
||||
==========
|
||||
|
@ -608,6 +754,16 @@ Deprecated
|
|||
* Passing ``None`` as the first argument to the :func:`shlex.split` function
|
||||
has been deprecated. (Contributed by Zackery Spytz in :issue:`33262`.)
|
||||
|
||||
* The :mod:`lib2to3` module now emits a :exc:`PendingDeprecationWarning`.
|
||||
Python 3.9 switched to a PEG parser (see :pep:`617`), and Python 3.10 may
|
||||
include new language syntax that is not parsable by lib2to3's LL(1) parser.
|
||||
The ``lib2to3`` module may be removed from the standard library in a future
|
||||
Python version. Consider third-party alternatives such as `LibCST`_ or
|
||||
`parso`_.
|
||||
(Contributed by Carl Meyer in :issue:`40360`.)
|
||||
|
||||
.. _LibCST: https://libcst.readthedocs.io/
|
||||
.. _parso: https://parso.readthedocs.io/
|
||||
|
||||
Removed
|
||||
=======
|
||||
|
@ -673,9 +829,6 @@ Removed
|
|||
removed, standard :class:`bytes` objects are always used instead.
|
||||
(Contributed by Jon Janzen in :issue:`36409`.)
|
||||
|
||||
* The C function ``PyThreadState_DeleteCurrent()`` has been removed. It was not documented.
|
||||
(Contributed by Joannah Nanjekye in :issue:`37878`.)
|
||||
|
||||
* The C function ``PyGen_NeedsFinalizing`` has been removed. It was not
|
||||
documented, tested, or used anywhere within CPython after the implementation
|
||||
of :pep:`442`. Patch by Joannah Nanjekye.
|
||||
|
@ -712,7 +865,7 @@ Removed
|
|||
(Contributed by Victor Stinner in :issue:`39489`.)
|
||||
|
||||
* The ``_field_types`` attribute of the :class:`typing.NamedTuple` class
|
||||
has been removed. It was deprecated deprecated since Python 3.8. Use
|
||||
has been removed. It was deprecated since Python 3.8. Use
|
||||
the ``__annotations__`` attribute instead.
|
||||
(Contributed by Serhiy Storchaka in :issue:`40182`.)
|
||||
|
||||
|
@ -761,11 +914,6 @@ Changes in the Python API
|
|||
:class:`ftplib.FTP_TLS` as a keyword-only parameter, and the default encoding
|
||||
is changed from Latin-1 to UTF-8 to follow :rfc:`2640`.
|
||||
|
||||
* :func:`inspect.getdoc` no longer returns docstring inherited from the type
|
||||
of the object or from parent class if it is a class if it is not defined
|
||||
in the object itself.
|
||||
(Contributed by Serhiy Storchaka in :issue:`40257`.)
|
||||
|
||||
* :meth:`asyncio.loop.shutdown_default_executor` has been added to
|
||||
:class:`~asyncio.AbstractEventLoop`, meaning alternative event loops that
|
||||
inherit from it should have this method defined.
|
||||
|
@ -776,6 +924,61 @@ Changes in the Python API
|
|||
``PyCF_ALLOW_TOP_LEVEL_AWAIT`` was clashing with ``CO_FUTURE_DIVISION``.
|
||||
(Contributed by Batuhan Taskaya in :issue:`39562`)
|
||||
|
||||
* ``array('u')`` now uses ``wchar_t`` as C type instead of ``Py_UNICODE``.
|
||||
This change doesn't affect to its behavior because ``Py_UNICODE`` is alias
|
||||
of ``wchar_t`` since Python 3.3.
|
||||
(Contributed by Inada Naoki in :issue:`34538`.)
|
||||
|
||||
|
||||
Changes in the C API
|
||||
--------------------
|
||||
|
||||
* Instances of heap-allocated types (such as those created with
|
||||
:c:func:`PyType_FromSpec` and similar APIs) hold a reference to their type
|
||||
object since Python 3.8. As indicated in the "Changes in the C API" of Python
|
||||
3.8, for the vast majority of cases, there should be no side effect but for
|
||||
types that have a custom :c:member:`~PyTypeObject.tp_traverse` function,
|
||||
ensure that all custom ``tp_traverse`` functions of heap-allocated types
|
||||
visit the object's type.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
int
|
||||
foo_traverse(foo_struct *self, visitproc visit, void *arg) {
|
||||
// Rest of the traverse function
|
||||
#if PY_VERSION_HEX >= 0x03090000
|
||||
// This was not needed before Python 3.9 (Python issue 35810 and 40217)
|
||||
Py_VISIT(Py_TYPE(self));
|
||||
#endif
|
||||
}
|
||||
|
||||
If your traverse function delegates to ``tp_traverse`` of its base class
|
||||
(or another type), ensure that ``Py_TYPE(self)`` is visited only once.
|
||||
Note that only heap types are expected to visit the type in ``tp_traverse``.
|
||||
|
||||
For example, if your ``tp_traverse`` function includes:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
base->tp_traverse(self, visit, arg)
|
||||
|
||||
then add:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#if PY_VERSION_HEX >= 0x03090000
|
||||
// This was not needed before Python 3.9 (Python issue 35810 and 40217)
|
||||
if (base->tp_flags & Py_TPFLAGS_HEAPTYPE) {
|
||||
// a heap type's tp_traverse already visited Py_TYPE(self)
|
||||
} else {
|
||||
Py_VISIT(Py_TYPE(self));
|
||||
}
|
||||
#else
|
||||
|
||||
(See :issue:`35810` and :issue:`40217` for more information.)
|
||||
|
||||
CPython bytecode changes
|
||||
------------------------
|
||||
|
||||
|
@ -902,6 +1105,8 @@ Removed
|
|||
|
||||
* Exclude the following functions from the limited C API:
|
||||
|
||||
* ``PyThreadState_DeleteCurrent()``
|
||||
(Contributed by Joannah Nanjekye in :issue:`37878`.)
|
||||
* ``_Py_CheckRecursionLimit``
|
||||
* ``_Py_NewReference()``
|
||||
* ``_Py_ForgetReference()``
|
||||
|
@ -948,3 +1153,6 @@ Removed
|
|||
* ``PyTuple_ClearFreeList()``
|
||||
* ``PyUnicode_ClearFreeList()``: the Unicode free list has been removed in
|
||||
Python 3.3.
|
||||
|
||||
* Remove ``_PyUnicode_ClearStaticStrings()`` function.
|
||||
(Contributed by Victor Stinner in :issue:`39465`.)
|
||||
|
|
|
@ -11,6 +11,7 @@ anyone wishing to stay up-to-date after a new release.
|
|||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
3.10.rst
|
||||
3.9.rst
|
||||
3.8.rst
|
||||
3.7.rst
|
||||
|
|
|
@ -17,6 +17,8 @@ _PyPegen_parse(Parser *p)
|
|||
result = interactive_rule(p);
|
||||
} else if (p->start_rule == Py_eval_input) {
|
||||
result = eval_rule(p);
|
||||
} else if (p->start_rule == Py_func_type_input) {
|
||||
result = func_type_rule(p);
|
||||
} else if (p->start_rule == Py_fstring_input) {
|
||||
result = fstring_rule(p);
|
||||
}
|
||||
|
@ -26,11 +28,24 @@ _PyPegen_parse(Parser *p)
|
|||
|
||||
// The end
|
||||
'''
|
||||
file[mod_ty]: a=[statements] ENDMARKER { Module(a, NULL, p->arena) }
|
||||
file[mod_ty]: a=[statements] ENDMARKER { _PyPegen_make_module(p, a) }
|
||||
interactive[mod_ty]: a=statement_newline { Interactive(a, p->arena) }
|
||||
eval[mod_ty]: a=expressions NEWLINE* ENDMARKER { Expression(a, p->arena) }
|
||||
func_type[mod_ty]: '(' a=[type_expressions] ')' '->' b=expression NEWLINE* ENDMARKER { FunctionType(a, b, p->arena) }
|
||||
fstring[expr_ty]: star_expressions
|
||||
|
||||
# type_expressions allow */** but ignore them
|
||||
type_expressions[asdl_seq*]:
|
||||
| a=','.expression+ ',' '*' b=expression ',' '**' c=expression {
|
||||
_PyPegen_seq_append_to_end(p, CHECK(_PyPegen_seq_append_to_end(p, a, b)), c) }
|
||||
| a=','.expression+ ',' '*' b=expression { _PyPegen_seq_append_to_end(p, a, b) }
|
||||
| a=','.expression+ ',' '**' b=expression { _PyPegen_seq_append_to_end(p, a, b) }
|
||||
| '*' a=expression ',' '**' b=expression {
|
||||
_PyPegen_seq_append_to_end(p, CHECK(_PyPegen_singleton_seq(p, a)), b) }
|
||||
| '*' a=expression { _PyPegen_singleton_seq(p, a) }
|
||||
| '**' a=expression { _PyPegen_singleton_seq(p, a) }
|
||||
| ','.expression+
|
||||
|
||||
statements[asdl_seq*]: a=statement+ { _PyPegen_seq_flatten(p, a) }
|
||||
statement[asdl_seq*]: a=compound_stmt { _PyPegen_singleton_seq(p, a) } | simple_stmt
|
||||
statement_newline[asdl_seq*]:
|
||||
|
@ -67,32 +82,36 @@ compound_stmt[stmt_ty]:
|
|||
| &'while' while_stmt
|
||||
|
||||
# NOTE: annotated_rhs may start with 'yield'; yield_expr must start with 'yield'
|
||||
assignment:
|
||||
assignment[stmt_ty]:
|
||||
| a=NAME ':' b=expression c=['=' d=annotated_rhs { d }] {
|
||||
_Py_AnnAssign(CHECK(_PyPegen_set_expr_context(p, a, Store)), b, c, 1, EXTRA) }
|
||||
| a=('(' b=inside_paren_ann_assign_target ')' { b }
|
||||
| ann_assign_subscript_attribute_target) ':' b=expression c=['=' d=annotated_rhs { d }] {
|
||||
_Py_AnnAssign(a, b, c, 0, EXTRA)}
|
||||
| a=(z=star_targets '=' { z })+ b=(yield_expr | star_expressions) {
|
||||
_Py_Assign(a, b, NULL, EXTRA) }
|
||||
| a=target b=augassign c=(yield_expr | star_expressions) {
|
||||
CHECK_VERSION(
|
||||
6,
|
||||
"Variable annotation syntax is",
|
||||
_Py_AnnAssign(CHECK(_PyPegen_set_expr_context(p, a, Store)), b, c, 1, EXTRA)
|
||||
) }
|
||||
| a=('(' b=single_target ')' { b }
|
||||
| single_subscript_attribute_target) ':' b=expression c=['=' d=annotated_rhs { d }] {
|
||||
CHECK_VERSION(6, "Variable annotations syntax is", _Py_AnnAssign(a, b, c, 0, EXTRA)) }
|
||||
| a=(z=star_targets '=' { z })+ b=(yield_expr | star_expressions) tc=[TYPE_COMMENT] {
|
||||
_Py_Assign(a, b, NEW_TYPE_COMMENT(p, tc), EXTRA) }
|
||||
| a=single_target b=augassign c=(yield_expr | star_expressions) {
|
||||
_Py_AugAssign(a, b->kind, c, EXTRA) }
|
||||
| invalid_assignment
|
||||
|
||||
augassign[AugOperator*]:
|
||||
| '+=' {_PyPegen_augoperator(p, Add)}
|
||||
| '-=' {_PyPegen_augoperator(p, Sub)}
|
||||
| '*=' {_PyPegen_augoperator(p, Mult)}
|
||||
| '@=' {_PyPegen_augoperator(p, MatMult)}
|
||||
| '/=' {_PyPegen_augoperator(p, Div)}
|
||||
| '%=' {_PyPegen_augoperator(p, Mod)}
|
||||
| '&=' {_PyPegen_augoperator(p, BitAnd)}
|
||||
| '|=' {_PyPegen_augoperator(p, BitOr)}
|
||||
| '^=' {_PyPegen_augoperator(p, BitXor)}
|
||||
| '<<=' {_PyPegen_augoperator(p, LShift)}
|
||||
| '>>=' {_PyPegen_augoperator(p, RShift)}
|
||||
| '**=' {_PyPegen_augoperator(p, Pow)}
|
||||
| '//=' {_PyPegen_augoperator(p, FloorDiv)}
|
||||
| '+=' { _PyPegen_augoperator(p, Add) }
|
||||
| '-=' { _PyPegen_augoperator(p, Sub) }
|
||||
| '*=' { _PyPegen_augoperator(p, Mult) }
|
||||
| '@=' { CHECK_VERSION(5, "The '@' operator is", _PyPegen_augoperator(p, MatMult)) }
|
||||
| '/=' { _PyPegen_augoperator(p, Div) }
|
||||
| '%=' { _PyPegen_augoperator(p, Mod) }
|
||||
| '&=' { _PyPegen_augoperator(p, BitAnd) }
|
||||
| '|=' { _PyPegen_augoperator(p, BitOr) }
|
||||
| '^=' { _PyPegen_augoperator(p, BitXor) }
|
||||
| '<<=' { _PyPegen_augoperator(p, LShift) }
|
||||
| '>>=' { _PyPegen_augoperator(p, RShift) }
|
||||
| '**=' { _PyPegen_augoperator(p, Pow) }
|
||||
| '//=' { _PyPegen_augoperator(p, FloorDiv) }
|
||||
|
||||
global_stmt[stmt_ty]: 'global' a=','.NAME+ {
|
||||
_Py_Global(CHECK(_PyPegen_map_names_to_ids(p, a)), EXTRA) }
|
||||
|
@ -115,8 +134,9 @@ import_from[stmt_ty]:
|
|||
_Py_ImportFrom(NULL, b, _PyPegen_seq_count_dots(a), EXTRA) }
|
||||
import_from_targets[asdl_seq*]:
|
||||
| '(' a=import_from_as_names [','] ')' { a }
|
||||
| import_from_as_names
|
||||
| import_from_as_names !','
|
||||
| '*' { _PyPegen_singleton_seq(p, CHECK(_PyPegen_alias_for_star(p))) }
|
||||
| invalid_import_from_targets
|
||||
import_from_as_names[asdl_seq*]:
|
||||
| a=','.import_from_as_name+ { a }
|
||||
import_from_as_name[alias_ty]:
|
||||
|
@ -145,14 +165,20 @@ while_stmt[stmt_ty]:
|
|||
| 'while' a=named_expression ':' b=block c=[else_block] { _Py_While(a, b, c, EXTRA) }
|
||||
|
||||
for_stmt[stmt_ty]:
|
||||
| is_async=[ASYNC] 'for' t=star_targets 'in' ex=star_expressions ':' b=block el=[else_block] {
|
||||
(is_async ? _Py_AsyncFor : _Py_For)(t, ex, b, el, NULL, EXTRA) }
|
||||
| 'for' t=star_targets 'in' ex=star_expressions ':' tc=[TYPE_COMMENT] b=block el=[else_block] {
|
||||
_Py_For(t, ex, b, el, NEW_TYPE_COMMENT(p, tc), EXTRA) }
|
||||
| ASYNC 'for' t=star_targets 'in' ex=star_expressions ':' tc=[TYPE_COMMENT] b=block el=[else_block] {
|
||||
CHECK_VERSION(5, "Async for loops are", _Py_AsyncFor(t, ex, b, el, NEW_TYPE_COMMENT(p, tc), EXTRA)) }
|
||||
|
||||
with_stmt[stmt_ty]:
|
||||
| is_async=[ASYNC] 'with' '(' a=','.with_item+ ')' ':' b=block {
|
||||
(is_async ? _Py_AsyncWith : _Py_With)(a, b, NULL, EXTRA) }
|
||||
| is_async=[ASYNC] 'with' a=','.with_item+ ':' b=block {
|
||||
(is_async ? _Py_AsyncWith : _Py_With)(a, b, NULL, EXTRA) }
|
||||
| 'with' '(' a=','.with_item+ ','? ')' ':' b=block {
|
||||
_Py_With(a, b, NULL, EXTRA) }
|
||||
| 'with' a=','.with_item+ ':' tc=[TYPE_COMMENT] b=block {
|
||||
_Py_With(a, b, NEW_TYPE_COMMENT(p, tc), EXTRA) }
|
||||
| ASYNC 'with' '(' a=','.with_item+ ','? ')' ':' b=block {
|
||||
CHECK_VERSION(5, "Async with statements are", _Py_AsyncWith(a, b, NULL, EXTRA)) }
|
||||
| ASYNC 'with' a=','.with_item+ ':' tc=[TYPE_COMMENT] b=block {
|
||||
CHECK_VERSION(5, "Async with statements are", _Py_AsyncWith(a, b, NEW_TYPE_COMMENT(p, tc), EXTRA)) }
|
||||
with_item[withitem_ty]:
|
||||
| e=expression o=['as' t=target { t }] { _Py_withitem(e, o, p->arena) }
|
||||
|
||||
|
@ -160,7 +186,7 @@ try_stmt[stmt_ty]:
|
|||
| 'try' ':' b=block f=finally_block { _Py_Try(b, NULL, NULL, f, EXTRA) }
|
||||
| 'try' ':' b=block ex=except_block+ el=[else_block] f=[finally_block] { _Py_Try(b, ex, el, f, EXTRA) }
|
||||
except_block[excepthandler_ty]:
|
||||
| 'except' e=expression t=['as' z=target { z }] ':' b=block {
|
||||
| 'except' e=expression t=['as' z=NAME { z }] ':' b=block {
|
||||
_Py_ExceptHandler(e, (t) ? ((expr_ty) t)->v.Name.id : NULL, b, EXTRA) }
|
||||
| 'except' ':' b=block { _Py_ExceptHandler(NULL, NULL, b, EXTRA) }
|
||||
finally_block[asdl_seq*]: 'finally' ':' a=block { a }
|
||||
|
@ -177,43 +203,82 @@ function_def[stmt_ty]:
|
|||
| function_def_raw
|
||||
|
||||
function_def_raw[stmt_ty]:
|
||||
| is_async=[ASYNC] 'def' n=NAME '(' params=[params] ')' a=['->' z=annotation { z }] ':' b=block {
|
||||
(is_async ? _Py_AsyncFunctionDef : _Py_FunctionDef)(n->v.Name.id,
|
||||
(params) ? params : CHECK(_PyPegen_empty_arguments(p)),
|
||||
b, NULL, a, NULL, EXTRA) }
|
||||
| 'def' n=NAME '(' params=[params] ')' a=['->' z=expression { z }] ':' tc=[func_type_comment] b=block {
|
||||
_Py_FunctionDef(n->v.Name.id,
|
||||
(params) ? params : CHECK(_PyPegen_empty_arguments(p)),
|
||||
b, NULL, a, NEW_TYPE_COMMENT(p, tc), EXTRA) }
|
||||
| ASYNC 'def' n=NAME '(' params=[params] ')' a=['->' z=expression { z }] ':' tc=[func_type_comment] b=block {
|
||||
CHECK_VERSION(
|
||||
5,
|
||||
"Async functions are",
|
||||
_Py_AsyncFunctionDef(n->v.Name.id,
|
||||
(params) ? params : CHECK(_PyPegen_empty_arguments(p)),
|
||||
b, NULL, a, NEW_TYPE_COMMENT(p, tc), EXTRA)
|
||||
) }
|
||||
func_type_comment[Token*]:
|
||||
| NEWLINE t=TYPE_COMMENT &(NEWLINE INDENT) { t } # Must be followed by indented block
|
||||
| invalid_double_type_comments
|
||||
| TYPE_COMMENT
|
||||
|
||||
params[arguments_ty]:
|
||||
| invalid_parameters
|
||||
| parameters
|
||||
|
||||
parameters[arguments_ty]:
|
||||
| a=slash_without_default b=[',' x=plain_names { x }] c=[',' y=names_with_default { y }] d=[',' z=[star_etc] { z }] {
|
||||
| a=slash_no_default b=param_no_default* c=param_with_default* d=[star_etc] {
|
||||
_PyPegen_make_arguments(p, a, NULL, b, c, d) }
|
||||
| a=slash_with_default b=[',' y=names_with_default { y }] c=[',' z=[star_etc] { z }] {
|
||||
| a=slash_with_default b=param_with_default* c=[star_etc] {
|
||||
_PyPegen_make_arguments(p, NULL, a, NULL, b, c) }
|
||||
| a=plain_names b=[',' y=names_with_default { y }] c=[',' z=[star_etc] { z }] {
|
||||
| a=param_no_default+ b=param_with_default* c=[star_etc] {
|
||||
_PyPegen_make_arguments(p, NULL, NULL, a, b, c) }
|
||||
| a=names_with_default b=[',' z=[star_etc] { z }] { _PyPegen_make_arguments(p, NULL, NULL, NULL, a, b)}
|
||||
| a=param_with_default+ b=[star_etc] { _PyPegen_make_arguments(p, NULL, NULL, NULL, a, b)}
|
||||
| a=star_etc { _PyPegen_make_arguments(p, NULL, NULL, NULL, NULL, a) }
|
||||
slash_without_default[asdl_seq*]: a=plain_names ',' '/' { a }
|
||||
slash_with_default[SlashWithDefault*]: a=[n=plain_names ',' { n }] b=names_with_default ',' '/' {
|
||||
_PyPegen_slash_with_default(p, a, b) }
|
||||
|
||||
# Some duplication here because we can't write (',' | &')'),
|
||||
# which is because we don't support empty alternatives (yet).
|
||||
#
|
||||
slash_no_default[asdl_seq*]:
|
||||
| a=param_no_default+ '/' ',' { a }
|
||||
| a=param_no_default+ '/' &')' { a }
|
||||
slash_with_default[SlashWithDefault*]:
|
||||
| a=param_no_default* b=param_with_default+ '/' ',' { _PyPegen_slash_with_default(p, a, b) }
|
||||
| a=param_no_default* b=param_with_default+ '/' &')' { _PyPegen_slash_with_default(p, a, b) }
|
||||
|
||||
star_etc[StarEtc*]:
|
||||
| '*' a=plain_name b=name_with_optional_default* c=[',' d=kwds { d }] [','] {
|
||||
| '*' a=param_no_default b=param_maybe_default* c=[kwds] {
|
||||
_PyPegen_star_etc(p, a, b, c) }
|
||||
| '*' b=name_with_optional_default+ c=[',' d=kwds { d }] [','] {
|
||||
| '*' ',' b=param_maybe_default+ c=[kwds] {
|
||||
_PyPegen_star_etc(p, NULL, b, c) }
|
||||
| a=kwds [','] { _PyPegen_star_etc(p, NULL, NULL, a) }
|
||||
name_with_optional_default[NameDefaultPair*]:
|
||||
| ',' a=plain_name b=['=' e=expression { e }] { _PyPegen_name_default_pair(p, a, b) }
|
||||
names_with_default[asdl_seq*]: a=','.name_with_default+ { a }
|
||||
name_with_default[NameDefaultPair*]:
|
||||
| n=plain_name '=' e=expression { _PyPegen_name_default_pair(p, n, e) }
|
||||
plain_names[asdl_seq*] (memo): a=','.(plain_name !'=')+ { a }
|
||||
plain_name[arg_ty]:
|
||||
| a=NAME b=[':' z=annotation { z }] { _Py_arg(a->v.Name.id, b, NULL, EXTRA) }
|
||||
kwds[arg_ty]:
|
||||
| '**' a=plain_name { a }
|
||||
annotation[expr_ty]: expression
|
||||
| a=kwds { _PyPegen_star_etc(p, NULL, NULL, a) }
|
||||
| invalid_star_etc
|
||||
|
||||
kwds[arg_ty]: '**' a=param_no_default { a }
|
||||
|
||||
# One parameter. This *includes* a following comma and type comment.
|
||||
#
|
||||
# There are three styles:
|
||||
# - No default
|
||||
# - With default
|
||||
# - Maybe with default
|
||||
#
|
||||
# There are two alternative forms of each, to deal with type comments:
|
||||
# - Ends in a comma followed by an optional type comment
|
||||
# - No comma, optional type comment, must be followed by close paren
|
||||
# The latter form is for a final parameter without trailing comma.
|
||||
#
|
||||
param_no_default[arg_ty]:
|
||||
| a=param ',' tc=TYPE_COMMENT? { _PyPegen_add_type_comment_to_arg(p, a, tc) }
|
||||
| a=param tc=TYPE_COMMENT? &')' { _PyPegen_add_type_comment_to_arg(p, a, tc) }
|
||||
param_with_default[NameDefaultPair*]:
|
||||
| a=param c=default ',' tc=TYPE_COMMENT? { _PyPegen_name_default_pair(p, a, c, tc) }
|
||||
| a=param c=default tc=TYPE_COMMENT? &')' { _PyPegen_name_default_pair(p, a, c, tc) }
|
||||
param_maybe_default[NameDefaultPair*]:
|
||||
| a=param c=default? ',' tc=TYPE_COMMENT? { _PyPegen_name_default_pair(p, a, c, tc) }
|
||||
| a=param c=default? tc=TYPE_COMMENT? &')' { _PyPegen_name_default_pair(p, a, c, tc) }
|
||||
param[arg_ty]: a=NAME b=annotation? { _Py_arg(a->v.Name.id, b, NULL, EXTRA) }
|
||||
|
||||
annotation[expr_ty]: ':' a=expression { a }
|
||||
default[expr_ty]: '=' a=expression { a }
|
||||
|
||||
decorators[asdl_seq*]: a=('@' f=named_expression NEWLINE { f })+ { a }
|
||||
|
||||
|
@ -265,32 +330,48 @@ expression[expr_ty] (memo):
|
|||
|
||||
lambdef[expr_ty]:
|
||||
| 'lambda' a=[lambda_parameters] ':' b=expression { _Py_Lambda((a) ? a : CHECK(_PyPegen_empty_arguments(p)), b, EXTRA) }
|
||||
|
||||
# lambda_parameters etc. duplicates parameters but without annotations
|
||||
# or type comments, and if there's no comma after a parameter, we expect
|
||||
# a colon, not a close parenthesis. (For more, see parameters above.)
|
||||
#
|
||||
lambda_parameters[arguments_ty]:
|
||||
| a=lambda_slash_without_default b=[',' x=lambda_plain_names { x }] c=[',' y=lambda_names_with_default { y }] d=[',' z=[lambda_star_etc] { z }] {
|
||||
| a=lambda_slash_no_default b=lambda_param_no_default* c=lambda_param_with_default* d=[lambda_star_etc] {
|
||||
_PyPegen_make_arguments(p, a, NULL, b, c, d) }
|
||||
| a=lambda_slash_with_default b=[',' y=lambda_names_with_default { y }] c=[',' z=[lambda_star_etc] { z }] {
|
||||
| a=lambda_slash_with_default b=lambda_param_with_default* c=[lambda_star_etc] {
|
||||
_PyPegen_make_arguments(p, NULL, a, NULL, b, c) }
|
||||
| a=lambda_plain_names b=[',' y=lambda_names_with_default { y }] c=[',' z=[lambda_star_etc] { z }] {
|
||||
| a=lambda_param_no_default+ b=lambda_param_with_default* c=[lambda_star_etc] {
|
||||
_PyPegen_make_arguments(p, NULL, NULL, a, b, c) }
|
||||
| a=lambda_names_with_default b=[',' z=[lambda_star_etc] { z }] { _PyPegen_make_arguments(p, NULL, NULL, NULL, a, b)}
|
||||
| a=lambda_param_with_default+ b=[lambda_star_etc] { _PyPegen_make_arguments(p, NULL, NULL, NULL, a, b)}
|
||||
| a=lambda_star_etc { _PyPegen_make_arguments(p, NULL, NULL, NULL, NULL, a) }
|
||||
lambda_slash_without_default[asdl_seq*]: a=lambda_plain_names ',' '/' { a }
|
||||
lambda_slash_with_default[SlashWithDefault*]: a=[n=lambda_plain_names ',' { n }] b=lambda_names_with_default ',' '/' {
|
||||
_PyPegen_slash_with_default(p, a, b) }
|
||||
|
||||
lambda_slash_no_default[asdl_seq*]:
|
||||
| a=lambda_param_no_default+ '/' ',' { a }
|
||||
| a=lambda_param_no_default+ '/' &':' { a }
|
||||
lambda_slash_with_default[SlashWithDefault*]:
|
||||
| a=lambda_param_no_default* b=lambda_param_with_default+ '/' ',' { _PyPegen_slash_with_default(p, a, b) }
|
||||
| a=lambda_param_no_default* b=lambda_param_with_default+ '/' &':' { _PyPegen_slash_with_default(p, a, b) }
|
||||
|
||||
lambda_star_etc[StarEtc*]:
|
||||
| '*' a=lambda_plain_name b=lambda_name_with_optional_default* c=[',' d=lambda_kwds { d }] [','] {
|
||||
| '*' a=lambda_param_no_default b=lambda_param_maybe_default* c=[lambda_kwds] {
|
||||
_PyPegen_star_etc(p, a, b, c) }
|
||||
| '*' b=lambda_name_with_optional_default+ c=[',' d=lambda_kwds { d }] [','] {
|
||||
| '*' ',' b=lambda_param_maybe_default+ c=[lambda_kwds] {
|
||||
_PyPegen_star_etc(p, NULL, b, c) }
|
||||
| a=lambda_kwds [','] { _PyPegen_star_etc(p, NULL, NULL, a) }
|
||||
lambda_name_with_optional_default[NameDefaultPair*]:
|
||||
| ',' a=lambda_plain_name b=['=' e=expression { e }] { _PyPegen_name_default_pair(p, a, b) }
|
||||
lambda_names_with_default[asdl_seq*]: a=','.lambda_name_with_default+ { a }
|
||||
lambda_name_with_default[NameDefaultPair*]:
|
||||
| n=lambda_plain_name '=' e=expression { _PyPegen_name_default_pair(p, n, e) }
|
||||
lambda_plain_names[asdl_seq*]: a=','.(lambda_plain_name !'=')+ { a }
|
||||
lambda_plain_name[arg_ty]: a=NAME { _Py_arg(a->v.Name.id, NULL, NULL, EXTRA) }
|
||||
lambda_kwds[arg_ty]: '**' a=lambda_plain_name { a }
|
||||
| a=lambda_kwds { _PyPegen_star_etc(p, NULL, NULL, a) }
|
||||
| invalid_lambda_star_etc
|
||||
|
||||
lambda_kwds[arg_ty]: '**' a=lambda_param_no_default { a }
|
||||
|
||||
lambda_param_no_default[arg_ty]:
|
||||
| a=lambda_param ',' { a }
|
||||
| a=lambda_param &':' { a }
|
||||
lambda_param_with_default[NameDefaultPair*]:
|
||||
| a=lambda_param c=default ',' { _PyPegen_name_default_pair(p, a, c, NULL) }
|
||||
| a=lambda_param c=default &':' { _PyPegen_name_default_pair(p, a, c, NULL) }
|
||||
lambda_param_maybe_default[NameDefaultPair*]:
|
||||
| a=lambda_param c=default? ',' { _PyPegen_name_default_pair(p, a, c, NULL) }
|
||||
| a=lambda_param c=default? &':' { _PyPegen_name_default_pair(p, a, c, NULL) }
|
||||
lambda_param[arg_ty]: a=NAME { _Py_arg(a->v.Name.id, NULL, NULL, EXTRA) }
|
||||
|
||||
disjunction[expr_ty] (memo):
|
||||
| a=conjunction b=('or' c=conjunction { c })+ { _Py_BoolOp(
|
||||
|
@ -357,7 +438,7 @@ term[expr_ty]:
|
|||
| a=term '/' b=factor { _Py_BinOp(a, Div, b, EXTRA) }
|
||||
| a=term '//' b=factor { _Py_BinOp(a, FloorDiv, b, EXTRA) }
|
||||
| a=term '%' b=factor { _Py_BinOp(a, Mod, b, EXTRA) }
|
||||
| a=term '@' b=factor { _Py_BinOp(a, MatMult, b, EXTRA) }
|
||||
| a=term '@' b=factor { CHECK_VERSION(5, "The '@' operator is", _Py_BinOp(a, MatMult, b, EXTRA)) }
|
||||
| factor
|
||||
factor[expr_ty] (memo):
|
||||
| '+' a=factor { _Py_UnaryOp(UAdd, a, EXTRA) }
|
||||
|
@ -368,7 +449,7 @@ power[expr_ty]:
|
|||
| a=await_primary '**' b=factor { _Py_BinOp(a, Pow, b, EXTRA) }
|
||||
| await_primary
|
||||
await_primary[expr_ty] (memo):
|
||||
| AWAIT a=primary { _Py_Await(a, EXTRA) }
|
||||
| AWAIT a=primary { CHECK_VERSION(5, "Await expressions are", _Py_Await(a, EXTRA)) }
|
||||
| primary
|
||||
primary[expr_ty]:
|
||||
| a=primary '.' b=NAME { _Py_Attribute(a, b->v.Name.id, Load, EXTRA) }
|
||||
|
@ -418,17 +499,23 @@ setcomp[expr_ty]:
|
|||
| '{' a=expression b=for_if_clauses '}' { _Py_SetComp(a, b, EXTRA) }
|
||||
| invalid_comprehension
|
||||
dict[expr_ty]:
|
||||
| '{' a=[kvpairs] '}' { _Py_Dict(CHECK(_PyPegen_get_keys(p, a)),
|
||||
CHECK(_PyPegen_get_values(p, a)), EXTRA) }
|
||||
| '{' a=[double_starred_kvpairs] '}' {
|
||||
_Py_Dict(CHECK(_PyPegen_get_keys(p, a)), CHECK(_PyPegen_get_values(p, a)), EXTRA) }
|
||||
dictcomp[expr_ty]:
|
||||
| '{' a=kvpair b=for_if_clauses '}' { _Py_DictComp(a->key, a->value, b, EXTRA) }
|
||||
kvpairs[asdl_seq*]: a=','.kvpair+ [','] { a }
|
||||
kvpair[KeyValuePair*]:
|
||||
| invalid_dict_comprehension
|
||||
double_starred_kvpairs[asdl_seq*]: a=','.double_starred_kvpair+ [','] { a }
|
||||
double_starred_kvpair[KeyValuePair*]:
|
||||
| '**' a=bitwise_or { _PyPegen_key_value_pair(p, NULL, a) }
|
||||
| a=expression ':' b=expression { _PyPegen_key_value_pair(p, a, b) }
|
||||
| kvpair
|
||||
kvpair[KeyValuePair*]: a=expression ':' b=expression { _PyPegen_key_value_pair(p, a, b) }
|
||||
for_if_clauses[asdl_seq*]:
|
||||
| a=(y=[ASYNC] 'for' a=star_targets 'in' b=disjunction c=('if' z=disjunction { z })*
|
||||
{ _Py_comprehension(a, b, c, y != NULL, p->arena) })+ { a }
|
||||
| for_if_clause+
|
||||
for_if_clause[comprehension_ty]:
|
||||
| ASYNC 'for' a=star_targets 'in' b=disjunction c=('if' z=disjunction { z })* {
|
||||
CHECK_VERSION(6, "Async comprehensions are", _Py_comprehension(a, b, c, 1, p->arena)) }
|
||||
| 'for' a=star_targets 'in' b=disjunction c=('if' z=disjunction { z })* {
|
||||
_Py_comprehension(a, b, c, 0, p->arena) }
|
||||
|
||||
yield_expr[expr_ty]:
|
||||
| 'yield' 'from' a=expression { _Py_YieldFrom(a, EXTRA) }
|
||||
|
@ -464,10 +551,12 @@ kwarg_or_starred[KeywordOrStarred*]:
|
|||
| a=NAME '=' b=expression {
|
||||
_PyPegen_keyword_or_starred(p, CHECK(_Py_keyword(a->v.Name.id, b, EXTRA)), 1) }
|
||||
| a=starred_expression { _PyPegen_keyword_or_starred(p, a, 0) }
|
||||
| invalid_kwarg
|
||||
kwarg_or_double_starred[KeywordOrStarred*]:
|
||||
| a=NAME '=' b=expression {
|
||||
_PyPegen_keyword_or_starred(p, CHECK(_Py_keyword(a->v.Name.id, b, EXTRA)), 1) }
|
||||
| '**' a=expression { _PyPegen_keyword_or_starred(p, CHECK(_Py_keyword(NULL, a, EXTRA)), 1) }
|
||||
| invalid_kwarg
|
||||
|
||||
# NOTE: star_targets may contain *bitwise_or, targets may not.
|
||||
star_targets[expr_ty]:
|
||||
|
@ -487,25 +576,28 @@ star_atom[expr_ty]:
|
|||
| '(' a=[star_targets_seq] ')' { _Py_Tuple(a, Store, EXTRA) }
|
||||
| '[' a=[star_targets_seq] ']' { _Py_List(a, Store, EXTRA) }
|
||||
|
||||
inside_paren_ann_assign_target[expr_ty]:
|
||||
| ann_assign_subscript_attribute_target
|
||||
single_target[expr_ty]:
|
||||
| single_subscript_attribute_target
|
||||
| a=NAME { _PyPegen_set_expr_context(p, a, Store) }
|
||||
| '(' a=inside_paren_ann_assign_target ')' { a }
|
||||
|
||||
ann_assign_subscript_attribute_target[expr_ty]:
|
||||
| '(' a=single_target ')' { a }
|
||||
single_subscript_attribute_target[expr_ty]:
|
||||
| a=t_primary '.' b=NAME !t_lookahead { _Py_Attribute(a, b->v.Name.id, Store, EXTRA) }
|
||||
| a=t_primary '[' b=slices ']' !t_lookahead { _Py_Subscript(a, b, Store, EXTRA) }
|
||||
|
||||
del_targets[asdl_seq*]: a=','.del_target+ [','] { a }
|
||||
# The lookaheads to del_target_end ensure that we don't match expressions where a prefix of the
|
||||
# expression matches our rule, thereby letting these cases fall through to invalid_del_target.
|
||||
del_target[expr_ty] (memo):
|
||||
| a=t_primary '.' b=NAME !t_lookahead { _Py_Attribute(a, b->v.Name.id, Del, EXTRA) }
|
||||
| a=t_primary '[' b=slices ']' !t_lookahead { _Py_Subscript(a, b, Del, EXTRA) }
|
||||
| a=t_primary '.' b=NAME &del_target_end { _Py_Attribute(a, b->v.Name.id, Del, EXTRA) }
|
||||
| a=t_primary '[' b=slices ']' &del_target_end { _Py_Subscript(a, b, Del, EXTRA) }
|
||||
| del_t_atom
|
||||
del_t_atom[expr_ty]:
|
||||
| a=NAME { _PyPegen_set_expr_context(p, a, Del) }
|
||||
| a=NAME &del_target_end { _PyPegen_set_expr_context(p, a, Del) }
|
||||
| '(' a=del_target ')' { _PyPegen_set_expr_context(p, a, Del) }
|
||||
| '(' a=[del_targets] ')' { _Py_Tuple(a, Del, EXTRA) }
|
||||
| '[' a=[del_targets] ']' { _Py_List(a, Del, EXTRA) }
|
||||
| invalid_del_target
|
||||
del_target_end: ')' | ']' | ',' | ';' | NEWLINE
|
||||
|
||||
targets[asdl_seq*]: a=','.target+ [','] { a }
|
||||
target[expr_ty] (memo):
|
||||
|
@ -533,24 +625,60 @@ t_atom[expr_ty]:
|
|||
# From here on, there are rules for invalid syntax with specialised error messages
|
||||
incorrect_arguments:
|
||||
| args ',' '*' { RAISE_SYNTAX_ERROR("iterable argument unpacking follows keyword argument unpacking") }
|
||||
| expression for_if_clauses ',' [args | expression for_if_clauses] {
|
||||
RAISE_SYNTAX_ERROR("Generator expression must be parenthesized") }
|
||||
| a=expression for_if_clauses ',' [args | expression for_if_clauses] {
|
||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "Generator expression must be parenthesized") }
|
||||
| a=args for_if_clauses { _PyPegen_nonparen_genexp_in_call(p, a) }
|
||||
| args ',' a=expression for_if_clauses {
|
||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "Generator expression must be parenthesized") }
|
||||
| a=args ',' args { _PyPegen_arguments_parsing_error(p, a) }
|
||||
invalid_kwarg:
|
||||
| a=expression '=' {
|
||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
|
||||
a, "expression cannot contain assignment, perhaps you meant \"==\"?") }
|
||||
invalid_named_expression:
|
||||
| a=expression ':=' expression {
|
||||
RAISE_SYNTAX_ERROR("cannot use assignment expressions with %s", _PyPegen_get_expr_name(a)) }
|
||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
|
||||
a, "cannot use assignment expressions with %s", _PyPegen_get_expr_name(a)) }
|
||||
invalid_assignment:
|
||||
| list ':' { RAISE_SYNTAX_ERROR("only single target (not list) can be annotated") }
|
||||
| tuple ':' { RAISE_SYNTAX_ERROR("only single target (not tuple) can be annotated") }
|
||||
| expression ':' expression ['=' annotated_rhs] {
|
||||
RAISE_SYNTAX_ERROR("illegal target for annotation") }
|
||||
| a=expression ('=' | augassign) (yield_expr | star_expressions) {
|
||||
RAISE_SYNTAX_ERROR("cannot assign to %s", _PyPegen_get_expr_name(a)) }
|
||||
| a=list ':' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "only single target (not list) can be annotated") }
|
||||
| a=tuple ':' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "only single target (not tuple) can be annotated") }
|
||||
| a=star_named_expression ',' star_named_expressions* ':' {
|
||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "only single target (not tuple) can be annotated") }
|
||||
| a=expression ':' expression ['=' annotated_rhs] {
|
||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "illegal target for annotation") }
|
||||
| a=star_expressions '=' (yield_expr | star_expressions) {
|
||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
|
||||
_PyPegen_get_invalid_target(a),
|
||||
"cannot assign to %s", _PyPegen_get_expr_name(_PyPegen_get_invalid_target(a))) }
|
||||
| a=star_expressions augassign (yield_expr | star_expressions) {
|
||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
|
||||
a,
|
||||
"'%s' is an illegal expression for augmented assignment",
|
||||
_PyPegen_get_expr_name(a)
|
||||
)}
|
||||
|
||||
invalid_block:
|
||||
| NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block") }
|
||||
invalid_comprehension:
|
||||
| ('[' | '(' | '{') '*' expression for_if_clauses {
|
||||
RAISE_SYNTAX_ERROR("iterable unpacking cannot be used in comprehension") }
|
||||
| ('[' | '(' | '{') a=starred_expression for_if_clauses {
|
||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "iterable unpacking cannot be used in comprehension") }
|
||||
invalid_dict_comprehension:
|
||||
| '{' a='**' bitwise_or for_if_clauses '}' {
|
||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "dict unpacking cannot be used in dict comprehension") }
|
||||
invalid_parameters:
|
||||
| [plain_names ','] (slash_with_default | names_with_default) ',' plain_names {
|
||||
| param_no_default* (slash_with_default | param_with_default+) param_no_default {
|
||||
RAISE_SYNTAX_ERROR("non-default argument follows default argument") }
|
||||
invalid_star_etc:
|
||||
| '*' (')' | ',' (')' | '**')) { RAISE_SYNTAX_ERROR("named arguments must follow bare *") }
|
||||
| '*' ',' TYPE_COMMENT { RAISE_SYNTAX_ERROR("bare * has associated type comment") }
|
||||
invalid_lambda_star_etc:
|
||||
| '*' (':' | ',' (':' | '**')) { RAISE_SYNTAX_ERROR("named arguments must follow bare *") }
|
||||
invalid_double_type_comments:
|
||||
| TYPE_COMMENT NEWLINE TYPE_COMMENT NEWLINE INDENT {
|
||||
RAISE_SYNTAX_ERROR("Cannot have two type comments on def") }
|
||||
invalid_del_target:
|
||||
| a=star_expression &del_target_end {
|
||||
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "cannot delete %s", _PyPegen_get_expr_name(a)) }
|
||||
invalid_import_from_targets:
|
||||
| import_from_as_names ',' {
|
||||
RAISE_SYNTAX_ERROR("trailing comma not allowed without surrounding parentheses") }
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
|
||||
typedef PyObject * identifier;
|
||||
typedef PyObject * string;
|
||||
typedef PyObject * bytes;
|
||||
typedef PyObject * object;
|
||||
typedef PyObject * singleton;
|
||||
typedef PyObject * constant;
|
||||
|
||||
/* It would be nice if the code generated by asdl_c.py was completely
|
||||
|
|
|
@ -379,6 +379,9 @@ PyAPI_FUNC(void) _Py_add_one_to_index_C(int nd, Py_ssize_t *index,
|
|||
/* Convert Python int to Py_ssize_t. Do nothing if the argument is None. */
|
||||
PyAPI_FUNC(int) _Py_convert_optional_to_ssize_t(PyObject *, void *);
|
||||
|
||||
/* Same as PyNumber_Index but can return an instance of a subclass of int. */
|
||||
PyAPI_FUNC(PyObject *) _PyNumber_Index(PyObject *o);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -409,6 +409,10 @@ typedef struct {
|
|||
|
||||
/* If equal to 0, stop Python initialization before the "main" phase */
|
||||
int _init_main;
|
||||
|
||||
/* If non-zero, disallow threads, subprocesses, and fork.
|
||||
Default: 0. */
|
||||
int _isolated_interpreter;
|
||||
} PyConfig;
|
||||
|
||||
PyAPI_FUNC(void) PyConfig_InitPythonConfig(PyConfig *config);
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef Py_CPYTHON_METHODOBJECT_H
|
||||
# error "this header file must not be included directly"
|
||||
#endif
|
||||
|
||||
PyAPI_DATA(PyTypeObject) PyCMethod_Type;
|
||||
|
||||
#define PyCMethod_CheckExact(op) Py_IS_TYPE(op, &PyCMethod_Type)
|
||||
#define PyCMethod_Check(op) PyObject_TypeCheck(op, &PyCMethod_Type)
|
||||
|
||||
/* Macros for direct access to these values. Type checks are *not*
|
||||
done, so use with care. */
|
||||
#define PyCFunction_GET_FUNCTION(func) \
|
||||
(((PyCFunctionObject *)func) -> m_ml -> ml_meth)
|
||||
#define PyCFunction_GET_SELF(func) \
|
||||
(((PyCFunctionObject *)func) -> m_ml -> ml_flags & METH_STATIC ? \
|
||||
NULL : ((PyCFunctionObject *)func) -> m_self)
|
||||
#define PyCFunction_GET_FLAGS(func) \
|
||||
(((PyCFunctionObject *)func) -> m_ml -> ml_flags)
|
||||
#define PyCFunction_GET_CLASS(func) \
|
||||
(((PyCFunctionObject *)func) -> m_ml -> ml_flags & METH_METHOD ? \
|
||||
((PyCMethodObject *)func) -> mm_class : NULL)
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
PyMethodDef *m_ml; /* Description of the C function to call */
|
||||
PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */
|
||||
PyObject *m_module; /* The __module__ attribute, can be anything */
|
||||
PyObject *m_weakreflist; /* List of weak references */
|
||||
vectorcallfunc vectorcall;
|
||||
} PyCFunctionObject;
|
||||
|
||||
typedef struct {
|
||||
PyCFunctionObject func;
|
||||
PyTypeObject *mm_class; /* Class that defines this method */
|
||||
} PyCMethodObject;
|
|
@ -36,7 +36,7 @@ PyAPI_FUNC(Py_ssize_t) _Py_GetRefTotal(void);
|
|||
|
||||
PyId_foo is a static variable, either on block level or file level. On first
|
||||
usage, the string "foo" is interned, and the structures are linked. On interpreter
|
||||
shutdown, all strings are released (through _PyUnicode_ClearStaticStrings).
|
||||
shutdown, all strings are released.
|
||||
|
||||
Alternatively, _Py_static_string allows choosing the variable name.
|
||||
_PyUnicode_FromId returns a borrowed reference to the interned string.
|
||||
|
@ -289,6 +289,7 @@ typedef struct _heaptypeobject {
|
|||
PyBufferProcs as_buffer;
|
||||
PyObject *ht_name, *ht_slots, *ht_qualname;
|
||||
struct _dictkeysobject *ht_cached_keys;
|
||||
PyObject *ht_module;
|
||||
/* here are optional user slots, followed by the members. */
|
||||
} PyHeapTypeObject;
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ typedef PyOSErrorObject PyWindowsErrorObject;
|
|||
/* Error handling definitions */
|
||||
|
||||
PyAPI_FUNC(void) _PyErr_SetKeyError(PyObject *);
|
||||
_PyErr_StackItem *_PyErr_GetTopmostException(PyThreadState *tstate);
|
||||
PyAPI_FUNC(_PyErr_StackItem*) _PyErr_GetTopmostException(PyThreadState *tstate);
|
||||
PyAPI_FUNC(void) _PyErr_GetExcInfo(PyThreadState *, PyObject **, PyObject **, PyObject **);
|
||||
|
||||
/* Context manipulation (PEP 3134) */
|
||||
|
|
|
@ -65,6 +65,8 @@ PyAPI_FUNC(int) _Py_CoerceLegacyLocale(int warn);
|
|||
PyAPI_FUNC(int) _Py_LegacyLocaleDetected(int warn);
|
||||
PyAPI_FUNC(char *) _Py_SetLocaleFromEnv(int category);
|
||||
|
||||
PyAPI_FUNC(PyThreadState *) _Py_NewInterpreter(int isolated_subinterpreter);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1215,13 +1215,13 @@ Py_DEPRECATED(3.3) PyAPI_FUNC(Py_UNICODE*) PyUnicode_AsUnicodeCopy(
|
|||
|
||||
/* Return an interned Unicode object for an Identifier; may fail if there is no memory.*/
|
||||
PyAPI_FUNC(PyObject*) _PyUnicode_FromId(_Py_Identifier*);
|
||||
/* Clear all static strings. */
|
||||
PyAPI_FUNC(void) _PyUnicode_ClearStaticStrings(void);
|
||||
|
||||
/* Fast equality check when the inputs are known to be exact unicode types
|
||||
and where the hash values are equal (i.e. a very probable match) */
|
||||
PyAPI_FUNC(int) _PyUnicode_EQ(PyObject *, PyObject *);
|
||||
|
||||
PyAPI_FUNC(Py_ssize_t) _PyUnicode_ScanIdentifier(PyObject *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -29,9 +29,7 @@ extern "C" {
|
|||
#define E_EOFS 23 /* EOF in triple-quoted string */
|
||||
#define E_EOLS 24 /* EOL in single-quoted string */
|
||||
#define E_LINECONT 25 /* Unexpected characters after a line continuation */
|
||||
#define E_IDENTIFIER 26 /* Invalid characters in identifier */
|
||||
#define E_BADSINGLE 27 /* Ill-formed single statement input */
|
||||
#define E_BADPREFIX 28 /* Bad string prefixes */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -11,25 +11,34 @@ extern "C" {
|
|||
#include "Python.h"
|
||||
#include "Python-ast.h"
|
||||
|
||||
PyAPI_FUNC(mod_ty) PyPegen_ASTFromFile(const char *filename, int mode, PyCompilerFlags*, PyArena *arena);
|
||||
PyAPI_FUNC(mod_ty) PyPegen_ASTFromString(const char *str, int mode, PyCompilerFlags *flags,
|
||||
PyArena *arena);
|
||||
PyAPI_FUNC(mod_ty) PyPegen_ASTFromStringObject(const char *str, PyObject* filename, int mode,
|
||||
PyCompilerFlags *flags, PyArena *arena);
|
||||
PyAPI_FUNC(mod_ty) PyPegen_ASTFromFileObject(FILE *fp, PyObject *filename_ob,
|
||||
int mode, const char *enc, const char *ps1,
|
||||
const char *ps2, PyCompilerFlags *flags,
|
||||
int *errcode, PyArena *arena);
|
||||
PyAPI_FUNC(PyCodeObject *) PyPegen_CodeObjectFromFile(const char *filename, int mode, PyCompilerFlags *flags);
|
||||
PyAPI_FUNC(PyCodeObject *) PyPegen_CodeObjectFromString(const char *str, int mode,
|
||||
PyCompilerFlags *flags);
|
||||
PyAPI_FUNC(PyCodeObject *) PyPegen_CodeObjectFromFileObject(FILE *, PyObject *filename_ob,
|
||||
int mode,
|
||||
const char *ps1,
|
||||
const char *ps2,
|
||||
PyCompilerFlags *flags,
|
||||
const char *enc,
|
||||
int *errcode);
|
||||
PyAPI_FUNC(mod_ty) PyPegen_ASTFromString(
|
||||
const char *str,
|
||||
const char *filename,
|
||||
int mode,
|
||||
PyCompilerFlags *flags,
|
||||
PyArena *arena);
|
||||
PyAPI_FUNC(mod_ty) PyPegen_ASTFromStringObject(
|
||||
const char *str,
|
||||
PyObject* filename,
|
||||
int mode,
|
||||
PyCompilerFlags *flags,
|
||||
PyArena *arena);
|
||||
PyAPI_FUNC(mod_ty) PyPegen_ASTFromFileObject(
|
||||
FILE *fp,
|
||||
PyObject *filename_ob,
|
||||
int mode,
|
||||
const char *enc,
|
||||
const char *ps1,
|
||||
const char *ps2,
|
||||
PyCompilerFlags *flags,
|
||||
int *errcode,
|
||||
PyArena *arena);
|
||||
PyAPI_FUNC(mod_ty) PyPegen_ASTFromFilename(
|
||||
const char *filename,
|
||||
int mode,
|
||||
PyCompilerFlags *flags,
|
||||
PyArena *arena);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -50,7 +50,11 @@ extern PyObject *_PyEval_EvalCode(
|
|||
PyObject *kwdefs, PyObject *closure,
|
||||
PyObject *name, PyObject *qualname);
|
||||
|
||||
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
|
||||
extern int _PyEval_ThreadsInitialized(PyInterpreterState *interp);
|
||||
#else
|
||||
extern int _PyEval_ThreadsInitialized(struct pyruntimestate *runtime);
|
||||
#endif
|
||||
extern PyStatus _PyEval_InitGIL(PyThreadState *tstate);
|
||||
extern void _PyEval_FiniGIL(PyThreadState *tstate);
|
||||
|
||||
|
@ -65,12 +69,12 @@ PyAPI_DATA(int) _Py_CheckRecursionLimit;
|
|||
/* With USE_STACKCHECK macro defined, trigger stack checks in
|
||||
_Py_CheckRecursiveCall() on every 64th call to Py_EnterRecursiveCall. */
|
||||
static inline int _Py_MakeRecCheck(PyThreadState *tstate) {
|
||||
return (++tstate->recursion_depth > _Py_CheckRecursionLimit
|
||||
return (++tstate->recursion_depth > tstate->interp->ceval.recursion_limit
|
||||
|| ++tstate->stackcheck_counter > 64);
|
||||
}
|
||||
#else
|
||||
static inline int _Py_MakeRecCheck(PyThreadState *tstate) {
|
||||
return (++tstate->recursion_depth > _Py_CheckRecursionLimit);
|
||||
return (++tstate->recursion_depth > tstate->interp->ceval.recursion_limit);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -90,20 +94,22 @@ static inline int _Py_EnterRecursiveCall_inline(const char *where) {
|
|||
|
||||
#define Py_EnterRecursiveCall(where) _Py_EnterRecursiveCall_inline(where)
|
||||
|
||||
|
||||
/* Compute the "lower-water mark" for a recursion limit. When
|
||||
* Py_LeaveRecursiveCall() is called with a recursion depth below this mark,
|
||||
* the overflowed flag is reset to 0. */
|
||||
#define _Py_RecursionLimitLowerWaterMark(limit) \
|
||||
(((limit) > 200) \
|
||||
? ((limit) - 50) \
|
||||
: (3 * ((limit) >> 2)))
|
||||
|
||||
#define _Py_MakeEndRecCheck(x) \
|
||||
(--(x) < _Py_RecursionLimitLowerWaterMark(_Py_CheckRecursionLimit))
|
||||
static inline int _Py_RecursionLimitLowerWaterMark(int limit) {
|
||||
if (limit > 200) {
|
||||
return (limit - 50);
|
||||
}
|
||||
else {
|
||||
return (3 * (limit >> 2));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _Py_LeaveRecursiveCall(PyThreadState *tstate) {
|
||||
if (_Py_MakeEndRecCheck(tstate->recursion_depth)) {
|
||||
tstate->recursion_depth--;
|
||||
int limit = tstate->interp->ceval.recursion_limit;
|
||||
if (tstate->recursion_depth < _Py_RecursionLimitLowerWaterMark(limit)) {
|
||||
tstate->overflowed = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
#ifndef Py_INTERNAL_HASHTABLE_H
|
||||
#define Py_INTERNAL_HASHTABLE_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
/* Single linked list */
|
||||
|
||||
typedef struct _Py_slist_item_s {
|
||||
struct _Py_slist_item_s *next;
|
||||
} _Py_slist_item_t;
|
||||
|
||||
typedef struct {
|
||||
_Py_slist_item_t *head;
|
||||
} _Py_slist_t;
|
||||
|
||||
#define _Py_SLIST_ITEM_NEXT(ITEM) (((_Py_slist_item_t *)ITEM)->next)
|
||||
|
||||
#define _Py_SLIST_HEAD(SLIST) (((_Py_slist_t *)SLIST)->head)
|
||||
|
||||
|
||||
/* _Py_hashtable: table entry */
|
||||
|
||||
typedef struct {
|
||||
/* used by _Py_hashtable_t.buckets to link entries */
|
||||
_Py_slist_item_t _Py_slist_item;
|
||||
|
||||
Py_uhash_t key_hash;
|
||||
void *key;
|
||||
void *value;
|
||||
} _Py_hashtable_entry_t;
|
||||
|
||||
|
||||
/* _Py_hashtable: prototypes */
|
||||
|
||||
/* Forward declaration */
|
||||
struct _Py_hashtable_t;
|
||||
typedef struct _Py_hashtable_t _Py_hashtable_t;
|
||||
|
||||
typedef Py_uhash_t (*_Py_hashtable_hash_func) (const void *key);
|
||||
typedef int (*_Py_hashtable_compare_func) (const void *key1, const void *key2);
|
||||
typedef void (*_Py_hashtable_destroy_func) (void *key);
|
||||
typedef _Py_hashtable_entry_t* (*_Py_hashtable_get_entry_func)(_Py_hashtable_t *ht,
|
||||
const void *key);
|
||||
|
||||
typedef struct {
|
||||
// Allocate a memory block
|
||||
void* (*malloc) (size_t size);
|
||||
|
||||
// Release a memory block
|
||||
void (*free) (void *ptr);
|
||||
} _Py_hashtable_allocator_t;
|
||||
|
||||
|
||||
/* _Py_hashtable: table */
|
||||
struct _Py_hashtable_t {
|
||||
size_t nentries; // Total number of entries in the table
|
||||
size_t nbuckets;
|
||||
_Py_slist_t *buckets;
|
||||
|
||||
_Py_hashtable_get_entry_func get_entry_func;
|
||||
_Py_hashtable_hash_func hash_func;
|
||||
_Py_hashtable_compare_func compare_func;
|
||||
_Py_hashtable_destroy_func key_destroy_func;
|
||||
_Py_hashtable_destroy_func value_destroy_func;
|
||||
_Py_hashtable_allocator_t alloc;
|
||||
};
|
||||
|
||||
/* Hash a pointer (void*) */
|
||||
PyAPI_FUNC(Py_uhash_t) _Py_hashtable_hash_ptr(const void *key);
|
||||
|
||||
/* Comparison using memcmp() */
|
||||
PyAPI_FUNC(int) _Py_hashtable_compare_direct(
|
||||
const void *key1,
|
||||
const void *key2);
|
||||
|
||||
PyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_new(
|
||||
_Py_hashtable_hash_func hash_func,
|
||||
_Py_hashtable_compare_func compare_func);
|
||||
|
||||
PyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_new_full(
|
||||
_Py_hashtable_hash_func hash_func,
|
||||
_Py_hashtable_compare_func compare_func,
|
||||
_Py_hashtable_destroy_func key_destroy_func,
|
||||
_Py_hashtable_destroy_func value_destroy_func,
|
||||
_Py_hashtable_allocator_t *allocator);
|
||||
|
||||
PyAPI_FUNC(void) _Py_hashtable_destroy(_Py_hashtable_t *ht);
|
||||
|
||||
PyAPI_FUNC(void) _Py_hashtable_clear(_Py_hashtable_t *ht);
|
||||
|
||||
typedef int (*_Py_hashtable_foreach_func) (_Py_hashtable_t *ht,
|
||||
const void *key, const void *value,
|
||||
void *user_data);
|
||||
|
||||
/* Call func() on each entry of the hashtable.
|
||||
Iteration stops if func() result is non-zero, in this case it's the result
|
||||
of the call. Otherwise, the function returns 0. */
|
||||
PyAPI_FUNC(int) _Py_hashtable_foreach(
|
||||
_Py_hashtable_t *ht,
|
||||
_Py_hashtable_foreach_func func,
|
||||
void *user_data);
|
||||
|
||||
PyAPI_FUNC(size_t) _Py_hashtable_size(const _Py_hashtable_t *ht);
|
||||
|
||||
/* Add a new entry to the hash. The key must not be present in the hash table.
|
||||
Return 0 on success, -1 on memory error. */
|
||||
PyAPI_FUNC(int) _Py_hashtable_set(
|
||||
_Py_hashtable_t *ht,
|
||||
const void *key,
|
||||
void *value);
|
||||
|
||||
|
||||
/* Get an entry.
|
||||
Return NULL if the key does not exist. */
|
||||
static inline _Py_hashtable_entry_t *
|
||||
_Py_hashtable_get_entry(_Py_hashtable_t *ht, const void *key)
|
||||
{
|
||||
return ht->get_entry_func(ht, key);
|
||||
}
|
||||
|
||||
|
||||
/* Get value from an entry.
|
||||
Return NULL if the entry is not found.
|
||||
|
||||
Use _Py_hashtable_get_entry() to distinguish entry value equal to NULL
|
||||
and entry not found. */
|
||||
PyAPI_FUNC(void*) _Py_hashtable_get(_Py_hashtable_t *ht, const void *key);
|
||||
|
||||
|
||||
/* Remove a key and its associated value without calling key and value destroy
|
||||
functions.
|
||||
|
||||
Return the removed value if the key was found.
|
||||
Return NULL if the key was not found. */
|
||||
PyAPI_FUNC(void*) _Py_hashtable_steal(
|
||||
_Py_hashtable_t *ht,
|
||||
const void *key);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_HASHTABLE_H */
|
|
@ -33,6 +33,7 @@ struct _pending_calls {
|
|||
};
|
||||
|
||||
struct _ceval_state {
|
||||
int recursion_limit;
|
||||
/* Records whether tracing is on for any thread. Counts the number
|
||||
of threads for which tstate->c_tracefunc is non-NULL, so if the
|
||||
value is 0, we know we don't have to check this thread's
|
||||
|
@ -42,7 +43,25 @@ struct _ceval_state {
|
|||
/* This single variable consolidates all requests to break out of
|
||||
the fast path in the eval loop. */
|
||||
_Py_atomic_int eval_breaker;
|
||||
/* Request for dropping the GIL */
|
||||
_Py_atomic_int gil_drop_request;
|
||||
struct _pending_calls pending;
|
||||
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
|
||||
struct _gil_runtime_state gil;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* fs_codec.encoding is initialized to NULL.
|
||||
Later, it is set to a non-NULL string by _PyUnicode_InitEncodings(). */
|
||||
struct _Py_unicode_fs_codec {
|
||||
char *encoding; // Filesystem encoding (encoded to UTF-8)
|
||||
int utf8; // encoding=="utf-8"?
|
||||
char *errors; // Filesystem errors (encoded to UTF-8)
|
||||
_Py_error_handler error_handler;
|
||||
};
|
||||
|
||||
struct _Py_unicode_state {
|
||||
struct _Py_unicode_fs_codec fs_codec;
|
||||
};
|
||||
|
||||
|
||||
|
@ -91,14 +110,7 @@ struct _is {
|
|||
PyObject *codec_error_registry;
|
||||
int codecs_initialized;
|
||||
|
||||
/* fs_codec.encoding is initialized to NULL.
|
||||
Later, it is set to a non-NULL string by _PyUnicode_InitEncodings(). */
|
||||
struct {
|
||||
char *encoding; /* Filesystem encoding (encoded to UTF-8) */
|
||||
int utf8; /* encoding=="utf-8"? */
|
||||
char *errors; /* Filesystem errors (encoded to UTF-8) */
|
||||
_Py_error_handler error_handler;
|
||||
} fs_codec;
|
||||
struct _Py_unicode_state unicode;
|
||||
|
||||
PyConfig config;
|
||||
#ifdef HAVE_DLOPEN
|
||||
|
|
|
@ -14,6 +14,20 @@ static inline PyObject* _PyErr_Occurred(PyThreadState *tstate)
|
|||
return tstate->curexc_type;
|
||||
}
|
||||
|
||||
static inline void _PyErr_ClearExcState(_PyErr_StackItem *exc_state)
|
||||
{
|
||||
PyObject *t, *v, *tb;
|
||||
t = exc_state->exc_type;
|
||||
v = exc_state->exc_value;
|
||||
tb = exc_state->exc_traceback;
|
||||
exc_state->exc_type = NULL;
|
||||
exc_state->exc_value = NULL;
|
||||
exc_state->exc_traceback = NULL;
|
||||
Py_XDECREF(t);
|
||||
Py_XDECREF(v);
|
||||
Py_XDECREF(tb);
|
||||
}
|
||||
|
||||
|
||||
PyAPI_FUNC(void) _PyErr_Fetch(
|
||||
PyThreadState *tstate,
|
||||
|
@ -36,6 +50,9 @@ PyAPI_FUNC(void) _PyErr_SetObject(
|
|||
PyObject *type,
|
||||
PyObject *value);
|
||||
|
||||
PyAPI_FUNC(void) _PyErr_ChainStackItem(
|
||||
_PyErr_StackItem *exc_info);
|
||||
|
||||
PyAPI_FUNC(void) _PyErr_Clear(PyThreadState *tstate);
|
||||
|
||||
PyAPI_FUNC(void) _PyErr_SetNone(PyThreadState *tstate, PyObject *exception);
|
||||
|
|
|
@ -88,17 +88,12 @@ struct _PyTraceMalloc_Config {
|
|||
/* limit of the number of frames in a traceback, 1 by default.
|
||||
Variable protected by the GIL. */
|
||||
int max_nframe;
|
||||
|
||||
/* use domain in trace key?
|
||||
Variable protected by the GIL. */
|
||||
int use_domain;
|
||||
};
|
||||
|
||||
#define _PyTraceMalloc_Config_INIT \
|
||||
{.initialized = TRACEMALLOC_NOT_INITIALIZED, \
|
||||
.tracing = 0, \
|
||||
.max_nframe = 1, \
|
||||
.use_domain = 0}
|
||||
.max_nframe = 1}
|
||||
|
||||
PyAPI_DATA(struct _PyTraceMalloc_Config) _Py_tracemalloc_config;
|
||||
|
||||
|
|
|
@ -49,8 +49,18 @@ _Py_ThreadCanHandlePendingCalls(void)
|
|||
/* Variable and macro for in-line access to current thread
|
||||
and interpreter state */
|
||||
|
||||
static inline PyThreadState* _PyRuntimeState_GetThreadState(_PyRuntimeState *runtime) {
|
||||
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
|
||||
PyAPI_FUNC(PyThreadState*) _PyThreadState_GetTSS(void);
|
||||
#endif
|
||||
|
||||
static inline PyThreadState*
|
||||
_PyRuntimeState_GetThreadState(_PyRuntimeState *runtime)
|
||||
{
|
||||
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
|
||||
return _PyThreadState_GetTSS();
|
||||
#else
|
||||
return (PyThreadState*)_Py_atomic_load_relaxed(&runtime->gilstate.tstate_current);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Get the current Python thread state.
|
||||
|
@ -62,8 +72,14 @@ static inline PyThreadState* _PyRuntimeState_GetThreadState(_PyRuntimeState *run
|
|||
The caller must hold the GIL.
|
||||
|
||||
See also PyThreadState_Get() and PyThreadState_GET(). */
|
||||
static inline PyThreadState *_PyThreadState_GET(void) {
|
||||
static inline PyThreadState*
|
||||
_PyThreadState_GET(void)
|
||||
{
|
||||
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
|
||||
return _PyThreadState_GetTSS();
|
||||
#else
|
||||
return _PyRuntimeState_GetThreadState(&_PyRuntime);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Redefine PyThreadState_GET() as an alias to _PyThreadState_GET() */
|
||||
|
|
|
@ -14,12 +14,14 @@ extern "C" {
|
|||
/* ceval state */
|
||||
|
||||
struct _ceval_runtime_state {
|
||||
int recursion_limit;
|
||||
/* Request for dropping the GIL */
|
||||
_Py_atomic_int gil_drop_request;
|
||||
/* Request for checking signals. */
|
||||
/* Request for checking signals. It is shared by all interpreters (see
|
||||
bpo-40513). Any thread of any interpreter can receive a signal, but only
|
||||
the main thread of the main interpreter can handle signals: see
|
||||
_Py_ThreadCanHandleSignals(). */
|
||||
_Py_atomic_int signals_pending;
|
||||
#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
|
||||
struct _gil_runtime_state gil;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* GIL state */
|
||||
|
|
|
@ -173,23 +173,6 @@ PyAPI_FUNC(int) _PyLong_AsByteArray(PyLongObject* v,
|
|||
unsigned char* bytes, size_t n,
|
||||
int little_endian, int is_signed);
|
||||
|
||||
/* _PyLong_FromNbInt: Convert the given object to a PyLongObject
|
||||
using the nb_int slot, if available. Raise TypeError if either the
|
||||
nb_int slot is not available or the result of the call to nb_int
|
||||
returns something not of type int.
|
||||
*/
|
||||
PyAPI_FUNC(PyObject *) _PyLong_FromNbInt(PyObject *);
|
||||
|
||||
/* Convert the given object to a PyLongObject using the nb_index or
|
||||
nb_int slots, if available (the latter is deprecated).
|
||||
Raise TypeError if either nb_index and nb_int slots are not
|
||||
available or the result of the call to nb_index or nb_int
|
||||
returns something not of type int.
|
||||
Should be replaced with PyNumber_Index after the end of the
|
||||
deprecation period.
|
||||
*/
|
||||
PyAPI_FUNC(PyObject *) _PyLong_FromNbIndexOrNbInt(PyObject *);
|
||||
|
||||
/* _PyLong_Format: Convert the long to a string object with given base,
|
||||
appending a base prefix of 0[box] if base is 2, 8 or 16. */
|
||||
PyAPI_FUNC(PyObject *) _PyLong_Format(PyObject *obj, int base);
|
||||
|
|
|
@ -13,7 +13,8 @@ extern "C" {
|
|||
|
||||
PyAPI_DATA(PyTypeObject) PyCFunction_Type;
|
||||
|
||||
#define PyCFunction_Check(op) Py_IS_TYPE(op, &PyCFunction_Type)
|
||||
#define PyCFunction_CheckExact(op) Py_IS_TYPE(op, &PyCFunction_Type)
|
||||
#define PyCFunction_Check(op) PyObject_TypeCheck(op, &PyCFunction_Type)
|
||||
|
||||
typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
|
||||
typedef PyObject *(*_PyCFunctionFast) (PyObject *, PyObject *const *, Py_ssize_t);
|
||||
|
@ -22,21 +23,13 @@ typedef PyObject *(*PyCFunctionWithKeywords)(PyObject *, PyObject *,
|
|||
typedef PyObject *(*_PyCFunctionFastWithKeywords) (PyObject *,
|
||||
PyObject *const *, Py_ssize_t,
|
||||
PyObject *);
|
||||
typedef PyObject *(*PyCMethod)(PyObject *, PyTypeObject *, PyObject *const *,
|
||||
size_t, PyObject *);
|
||||
|
||||
PyAPI_FUNC(PyCFunction) PyCFunction_GetFunction(PyObject *);
|
||||
PyAPI_FUNC(PyObject *) PyCFunction_GetSelf(PyObject *);
|
||||
PyAPI_FUNC(int) PyCFunction_GetFlags(PyObject *);
|
||||
|
||||
/* Macros for direct access to these values. Type checks are *not*
|
||||
done, so use with care. */
|
||||
#ifndef Py_LIMITED_API
|
||||
#define PyCFunction_GET_FUNCTION(func) \
|
||||
(((PyCFunctionObject *)func) -> m_ml -> ml_meth)
|
||||
#define PyCFunction_GET_SELF(func) \
|
||||
(((PyCFunctionObject *)func) -> m_ml -> ml_flags & METH_STATIC ? \
|
||||
NULL : ((PyCFunctionObject *)func) -> m_self)
|
||||
#define PyCFunction_GET_FLAGS(func) \
|
||||
(((PyCFunctionObject *)func) -> m_ml -> ml_flags)
|
||||
#endif
|
||||
Py_DEPRECATED(3.9) PyAPI_FUNC(PyObject *) PyCFunction_Call(PyObject *, PyObject *, PyObject *);
|
||||
|
||||
struct PyMethodDef {
|
||||
|
@ -52,6 +45,13 @@ typedef struct PyMethodDef PyMethodDef;
|
|||
PyAPI_FUNC(PyObject *) PyCFunction_NewEx(PyMethodDef *, PyObject *,
|
||||
PyObject *);
|
||||
|
||||
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03090000
|
||||
#define PyCFunction_NewEx(ML, SELF, MOD) PyCMethod_New((ML), (SELF), (MOD), NULL)
|
||||
PyAPI_FUNC(PyObject *) PyCMethod_New(PyMethodDef *, PyObject *,
|
||||
PyObject *, PyTypeObject *);
|
||||
#endif
|
||||
|
||||
|
||||
/* Flag passed to newmethodobject */
|
||||
/* #define METH_OLDARGS 0x0000 -- unsupported now */
|
||||
#define METH_VARARGS 0x0001
|
||||
|
@ -84,15 +84,24 @@ PyAPI_FUNC(PyObject *) PyCFunction_NewEx(PyMethodDef *, PyObject *,
|
|||
#define METH_STACKLESS 0x0000
|
||||
#endif
|
||||
|
||||
/* METH_METHOD means the function stores an
|
||||
* additional reference to the class that defines it;
|
||||
* both self and class are passed to it.
|
||||
* It uses PyCMethodObject instead of PyCFunctionObject.
|
||||
* May not be combined with METH_NOARGS, METH_O, METH_CLASS or METH_STATIC.
|
||||
*/
|
||||
|
||||
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03090000
|
||||
#define METH_METHOD 0x0200
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef Py_LIMITED_API
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
PyMethodDef *m_ml; /* Description of the C function to call */
|
||||
PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */
|
||||
PyObject *m_module; /* The __module__ attribute, can be anything */
|
||||
PyObject *m_weakreflist; /* List of weak references */
|
||||
vectorcallfunc vectorcall;
|
||||
} PyCFunctionObject;
|
||||
|
||||
#define Py_CPYTHON_METHODOBJECT_H
|
||||
#include "cpython/methodobject.h"
|
||||
#undef Py_CPYTHON_METHODOBJECT_H
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -119,26 +119,45 @@ typedef struct {
|
|||
|
||||
/* Cast argument to PyVarObject* type. */
|
||||
#define _PyVarObject_CAST(op) ((PyVarObject*)(op))
|
||||
#define _PyVarObject_CAST_CONST(op) ((const PyVarObject*)(op))
|
||||
|
||||
|
||||
static inline Py_ssize_t _Py_REFCNT(const PyObject *ob) {
|
||||
return ob->ob_refcnt;
|
||||
}
|
||||
#define Py_REFCNT(ob) _Py_REFCNT(_PyObject_CAST_CONST(ob))
|
||||
|
||||
|
||||
static inline Py_ssize_t _Py_SIZE(const PyVarObject *ob) {
|
||||
return ob->ob_size;
|
||||
}
|
||||
#define Py_SIZE(ob) _Py_SIZE(_PyVarObject_CAST_CONST(ob))
|
||||
|
||||
|
||||
static inline PyTypeObject* _Py_TYPE(const PyObject *ob) {
|
||||
return ob->ob_type;
|
||||
}
|
||||
#define Py_TYPE(ob) _Py_TYPE(_PyObject_CAST_CONST(ob))
|
||||
|
||||
#define Py_REFCNT(ob) (_PyObject_CAST(ob)->ob_refcnt)
|
||||
#define Py_TYPE(ob) (_PyObject_CAST(ob)->ob_type)
|
||||
#define Py_SIZE(ob) (_PyVarObject_CAST(ob)->ob_size)
|
||||
|
||||
static inline int _Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) {
|
||||
return ob->ob_type == type;
|
||||
}
|
||||
#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST_CONST(ob), type)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) {
|
||||
ob->ob_size = size;
|
||||
}
|
||||
|
@ -213,6 +232,11 @@ PyAPI_FUNC(PyObject*) PyType_FromSpecWithBases(PyType_Spec*, PyObject*);
|
|||
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03040000
|
||||
PyAPI_FUNC(void*) PyType_GetSlot(PyTypeObject*, int);
|
||||
#endif
|
||||
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03090000
|
||||
PyAPI_FUNC(PyObject*) PyType_FromModuleAndSpec(PyObject *, PyType_Spec *, PyObject *);
|
||||
PyAPI_FUNC(PyObject *) PyType_GetModule(struct _typeobject *);
|
||||
PyAPI_FUNC(void *) PyType_GetModuleState(struct _typeobject *);
|
||||
#endif
|
||||
|
||||
/* Generic type check */
|
||||
PyAPI_FUNC(int) PyType_IsSubtype(PyTypeObject *, PyTypeObject *);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue