Merge branch 'master' into feat/dataclass-init-args
This commit is contained in:
commit
4e90401d12
|
@ -31,7 +31,7 @@ jobs:
|
||||||
buildVersionToDownload: specific
|
buildVersionToDownload: specific
|
||||||
buildId: $(BuildToPublish)
|
buildId: $(BuildToPublish)
|
||||||
|
|
||||||
- powershell: gci pythonarm*.nupkg | %{ Write-Host "Not publishing: $($_.Name)"; gi $_ } | del
|
- powershell: 'gci pythonarm*.nupkg | %{ Write-Host "Not publishing: $($_.Name)"; gi $_ } | del'
|
||||||
displayName: 'Prevent publishing ARM/ARM64 packages'
|
displayName: 'Prevent publishing ARM/ARM64 packages'
|
||||||
workingDirectory: '$(Build.BinariesDirectory)\nuget'
|
workingDirectory: '$(Build.BinariesDirectory)\nuget'
|
||||||
condition: and(succeeded(), not(variables['PublishArmPackages']))
|
condition: and(succeeded(), not(variables['PublishArmPackages']))
|
||||||
|
|
|
@ -39,7 +39,7 @@ jobs:
|
||||||
artifactName: embed
|
artifactName: embed
|
||||||
downloadPath: $(Build.BinariesDirectory)
|
downloadPath: $(Build.BinariesDirectory)
|
||||||
|
|
||||||
- powershell: gci *embed-arm*.zip | %{ Write-Host "Not publishing: $($_.Name)"; gi $_ } | del
|
- powershell: 'gci *embed-arm*.zip | %{ Write-Host "Not publishing: $($_.Name)"; gi $_ } | del'
|
||||||
displayName: 'Prevent publishing ARM/ARM64 packages'
|
displayName: 'Prevent publishing ARM/ARM64 packages'
|
||||||
workingDirectory: '$(Build.BinariesDirectory)\embed'
|
workingDirectory: '$(Build.BinariesDirectory)\embed'
|
||||||
condition: and(succeeded(), not(variables['PublishArmPackages']))
|
condition: and(succeeded(), not(variables['PublishArmPackages']))
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
**/*context* @1st1
|
**/*context* @1st1
|
||||||
**/*genobject* @1st1
|
**/*genobject* @1st1
|
||||||
**/*hamt* @1st1
|
**/*hamt* @1st1
|
||||||
|
Objects/set* @rhettinger
|
||||||
Objects/dict* @methane
|
Objects/dict* @methane
|
||||||
|
|
||||||
# Hashing
|
# Hashing
|
||||||
|
@ -93,6 +94,7 @@ Include/pytime.h @pganssle @abalkin
|
||||||
/Tools/msi/ @python/windows-team
|
/Tools/msi/ @python/windows-team
|
||||||
/Tools/nuget/ @python/windows-team
|
/Tools/nuget/ @python/windows-team
|
||||||
|
|
||||||
|
# Misc
|
||||||
**/*itertools* @rhettinger
|
**/*itertools* @rhettinger
|
||||||
**/*collections* @rhettinger
|
**/*collections* @rhettinger
|
||||||
**/*random* @rhettinger
|
**/*random* @rhettinger
|
||||||
|
@ -108,6 +110,15 @@ Include/pytime.h @pganssle @abalkin
|
||||||
|
|
||||||
**/*typing* @gvanrossum @ilevkivskyi
|
**/*typing* @gvanrossum @ilevkivskyi
|
||||||
|
|
||||||
|
**/*asyncore @giampaolo
|
||||||
|
**/*asynchat @giampaolo
|
||||||
|
**/*ftplib @giampaolo
|
||||||
|
**/*shutil @giampaolo
|
||||||
|
|
||||||
|
**/*enum* @ethanfurman
|
||||||
|
**/*cgi* @ethanfurman
|
||||||
|
**/*tarfile* @ethanfurman
|
||||||
|
|
||||||
# macOS
|
# macOS
|
||||||
/Mac/ @python/macos-team
|
/Mac/ @python/macos-team
|
||||||
**/*osx_support* @python/macos-team
|
**/*osx_support* @python/macos-team
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
*.iml
|
*.iml
|
||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
*.so*
|
*.so
|
||||||
|
*.so.*
|
||||||
*.dylib
|
*.dylib
|
||||||
*.dll
|
*.dll
|
||||||
*.orig
|
*.orig
|
||||||
|
|
|
@ -195,8 +195,8 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
|
||||||
:meth:`__int__` method (if present) to convert it to a
|
:meth:`__int__` method (if present) to convert it to a
|
||||||
:c:type:`PyLongObject`.
|
:c:type:`PyLongObject`.
|
||||||
|
|
||||||
If the value of *obj* is greater than :const:`PY_LLONG_MAX` or less than
|
If the value of *obj* is greater than :const:`LLONG_MAX` or less than
|
||||||
:const:`PY_LLONG_MIN`, set *\*overflow* to ``1`` or ``-1``, respectively,
|
:const:`LLONG_MIN`, set *\*overflow* to ``1`` or ``-1``, respectively,
|
||||||
and return ``-1``; otherwise, set *\*overflow* to ``0``. If any other
|
and return ``-1``; otherwise, set *\*overflow* to ``0``. If any other
|
||||||
exception occurs set *\*overflow* to ``0`` and return ``-1`` as usual.
|
exception occurs set *\*overflow* to ``0`` and return ``-1`` as usual.
|
||||||
|
|
||||||
|
@ -304,7 +304,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
|
||||||
it to a :c:type:`PyLongObject`.
|
it to a :c:type:`PyLongObject`.
|
||||||
|
|
||||||
If the value of *obj* is out of range for an :c:type:`unsigned long long`,
|
If the value of *obj* is out of range for an :c:type:`unsigned long long`,
|
||||||
return the reduction of that value modulo ``PY_ULLONG_MAX + 1``.
|
return the reduction of that value modulo ``ULLONG_MAX + 1``.
|
||||||
|
|
||||||
Returns ``(unsigned long long)-1`` on error. Use :c:func:`PyErr_Occurred`
|
Returns ``(unsigned long long)-1`` on error. Use :c:func:`PyErr_Occurred`
|
||||||
to disambiguate.
|
to disambiguate.
|
||||||
|
|
|
@ -309,7 +309,7 @@ accessible to C code. They all work with the current interpreter thread's
|
||||||
|
|
||||||
.. c:function:: int PySys_Audit(const char *event, const char *format, ...)
|
.. c:function:: int PySys_Audit(const char *event, const char *format, ...)
|
||||||
|
|
||||||
Raises an auditing event with any active hooks. Returns zero for success
|
Raise an auditing event with any active hooks. Return zero for success
|
||||||
and non-zero with an exception set on failure.
|
and non-zero with an exception set on failure.
|
||||||
|
|
||||||
If any hooks have been added, *format* and other arguments will be used
|
If any hooks have been added, *format* and other arguments will be used
|
||||||
|
@ -320,18 +320,31 @@ accessible to C code. They all work with the current interpreter thread's
|
||||||
arguments to this function will be consumed, using it may cause reference
|
arguments to this function will be consumed, using it may cause reference
|
||||||
leaks.)
|
leaks.)
|
||||||
|
|
||||||
|
Note that ``#`` format characters should always be treated as
|
||||||
|
``Py_ssize_t``, regardless of whether ``PY_SSIZE_T_CLEAN`` was defined.
|
||||||
|
|
||||||
:func:`sys.audit` performs the same function from Python code.
|
:func:`sys.audit` performs the same function from Python code.
|
||||||
|
|
||||||
.. versionadded:: 3.8
|
.. versionadded:: 3.8
|
||||||
|
|
||||||
|
.. versionchanged:: 3.8.2
|
||||||
|
|
||||||
|
Require ``Py_ssize_t`` for ``#`` format characters. Previously, an
|
||||||
|
unavoidable deprecation warning was raised.
|
||||||
|
|
||||||
|
|
||||||
.. c:function:: int PySys_AddAuditHook(Py_AuditHookFunction hook, void *userData)
|
.. c:function:: int PySys_AddAuditHook(Py_AuditHookFunction hook, void *userData)
|
||||||
|
|
||||||
Adds to the collection of active auditing hooks. Returns zero for success
|
Append the callable *hook* to the list of active auditing hooks.
|
||||||
and non-zero on failure. If the runtime has been initialized, also sets an
|
Return zero for success
|
||||||
|
and non-zero on failure. If the runtime has been initialized, also set an
|
||||||
error on failure. Hooks added through this API are called for all
|
error on failure. Hooks added through this API are called for all
|
||||||
interpreters created by the runtime.
|
interpreters created by the runtime.
|
||||||
|
|
||||||
|
The *userData* pointer is passed into the hook function. Since hook
|
||||||
|
functions may be called from different runtimes, this pointer should not
|
||||||
|
refer directly to Python state.
|
||||||
|
|
||||||
This function is safe to call before :c:func:`Py_Initialize`. When called
|
This function is safe to call before :c:func:`Py_Initialize`. When called
|
||||||
after runtime initialization, existing audit hooks are notified and may
|
after runtime initialization, existing audit hooks are notified and may
|
||||||
silently abort the operation by raising an error subclassed from
|
silently abort the operation by raising an error subclassed from
|
||||||
|
@ -342,14 +355,10 @@ accessible to C code. They all work with the current interpreter thread's
|
||||||
:c:type:`PyTupleObject`. The hook function is always called with the GIL
|
:c:type:`PyTupleObject`. The hook function is always called with the GIL
|
||||||
held by the Python interpreter that raised the event.
|
held by the Python interpreter that raised the event.
|
||||||
|
|
||||||
The *userData* pointer is passed into the hook function. Since hook
|
See :pep:`578` for a detailed description of auditing. Functions in the
|
||||||
functions may be called from different runtimes, this pointer should not
|
runtime and standard library that raise events are listed in the
|
||||||
refer directly to Python state.
|
:ref:`audit events table <audit-events>`.
|
||||||
|
Details are in each function's documentation.
|
||||||
See :pep:`578` for a detailed description of auditing. Functions in the
|
|
||||||
runtime and standard library that raise events include the details in each
|
|
||||||
function's documentation and listed in the :ref:`audit events table
|
|
||||||
<audit-events>`.
|
|
||||||
|
|
||||||
.. audit-event:: sys.addaudithook "" c.PySys_AddAuditHook
|
.. audit-event:: sys.addaudithook "" c.PySys_AddAuditHook
|
||||||
|
|
||||||
|
|
|
@ -955,7 +955,7 @@ and :c:type:`PyType_Type` effectively act as defaults.)
|
||||||
|
|
||||||
The signature is the same as for :c:func:`PyObject_SetAttr`::
|
The signature is the same as for :c:func:`PyObject_SetAttr`::
|
||||||
|
|
||||||
PyObject *tp_setattro(PyObject *self, PyObject *attr, PyObject *value);
|
int tp_setattro(PyObject *self, PyObject *attr, PyObject *value);
|
||||||
|
|
||||||
In addition, setting *value* to ``NULL`` to delete an attribute must be
|
In addition, setting *value* to ``NULL`` to delete an attribute must be
|
||||||
supported. It is usually convenient to set this field to
|
supported. It is usually convenient to set this field to
|
||||||
|
|
|
@ -197,11 +197,6 @@ access internal read-only data of Unicode objects:
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
|
||||||
.. c:function:: int PyUnicode_ClearFreeList()
|
|
||||||
|
|
||||||
Clear the free list. Return the total number of freed items.
|
|
||||||
|
|
||||||
|
|
||||||
.. c:function:: Py_ssize_t PyUnicode_GET_SIZE(PyObject *o)
|
.. c:function:: Py_ssize_t PyUnicode_GET_SIZE(PyObject *o)
|
||||||
|
|
||||||
Return the size of the deprecated :c:type:`Py_UNICODE` representation, in
|
Return the size of the deprecated :c:type:`Py_UNICODE` representation, in
|
||||||
|
|
|
@ -3045,8 +3045,6 @@ Py_XINCREF:PyObject*:o:+1:if o is not NULL
|
||||||
|
|
||||||
_PyImport_Fini:void:::
|
_PyImport_Fini:void:::
|
||||||
|
|
||||||
_PyImport_Init:void:::
|
|
||||||
|
|
||||||
_PyObject_New:PyObject*::+1:
|
_PyObject_New:PyObject*::+1:
|
||||||
_PyObject_New:PyTypeObject*:type:0:
|
_PyObject_New:PyTypeObject*:type:0:
|
||||||
|
|
||||||
|
|
|
@ -1545,7 +1545,7 @@ Python's own build procedures.
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
.. module:: distutils.text_file
|
.. module:: distutils.text_file
|
||||||
:synopsis: provides the TextFile class, a simple interface to text files
|
:synopsis: Provides the TextFile class, a simple interface to text files
|
||||||
|
|
||||||
|
|
||||||
This module provides the :class:`TextFile` class, which gives an interface to
|
This module provides the :class:`TextFile` class, which gives an interface to
|
||||||
|
@ -1684,7 +1684,7 @@ lines, and joining lines with backslashes.
|
||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
.. module:: distutils.version
|
.. module:: distutils.version
|
||||||
:synopsis: implements classes that represent module version numbers.
|
:synopsis: Implements classes that represent module version numbers.
|
||||||
|
|
||||||
|
|
||||||
.. % todo
|
.. % todo
|
||||||
|
@ -1699,7 +1699,7 @@ lines, and joining lines with backslashes.
|
||||||
===================================================================
|
===================================================================
|
||||||
|
|
||||||
.. module:: distutils.cmd
|
.. module:: distutils.cmd
|
||||||
:synopsis: This module provides the abstract base class Command. This class
|
:synopsis: Provides the abstract base class :class:`~distutils.cmd.Command`. This class
|
||||||
is subclassed by the modules in the distutils.command subpackage.
|
is subclassed by the modules in the distutils.command subpackage.
|
||||||
|
|
||||||
|
|
||||||
|
@ -1792,7 +1792,7 @@ Subclasses of :class:`Command` must define the following methods.
|
||||||
==========================================================
|
==========================================================
|
||||||
|
|
||||||
.. module:: distutils.command
|
.. module:: distutils.command
|
||||||
:synopsis: This subpackage contains one module for each standard Distutils command.
|
:synopsis: Contains one module for each standard Distutils command.
|
||||||
|
|
||||||
|
|
||||||
.. % \subsubsection{Individual Distutils commands}
|
.. % \subsubsection{Individual Distutils commands}
|
||||||
|
@ -2039,7 +2039,7 @@ This is described in more detail in :pep:`301`.
|
||||||
===================================================================
|
===================================================================
|
||||||
|
|
||||||
.. module:: distutils.command.check
|
.. module:: distutils.command.check
|
||||||
:synopsis: Check the metadata of a package
|
:synopsis: Check the meta-data of a package
|
||||||
|
|
||||||
|
|
||||||
The ``check`` command performs some tests on the meta-data of a package.
|
The ``check`` command performs some tests on the meta-data of a package.
|
||||||
|
|
|
@ -456,7 +456,7 @@ and off individually. They are described here in more detail.
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
.. module:: lib2to3
|
.. module:: lib2to3
|
||||||
:synopsis: the 2to3 library
|
:synopsis: The 2to3 library
|
||||||
|
|
||||||
.. moduleauthor:: Guido van Rossum
|
.. moduleauthor:: Guido van Rossum
|
||||||
.. moduleauthor:: Collin Winter
|
.. moduleauthor:: Collin Winter
|
||||||
|
|
|
@ -169,11 +169,6 @@ The following data items and methods are also supported:
|
||||||
a.append(x)`` except that if there is a type error, the array is unchanged.
|
a.append(x)`` except that if there is a type error, the array is unchanged.
|
||||||
|
|
||||||
|
|
||||||
.. method:: array.fromstring()
|
|
||||||
|
|
||||||
Deprecated alias for :meth:`frombytes`.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: array.fromunicode(s)
|
.. method:: array.fromunicode(s)
|
||||||
|
|
||||||
Extends this array with data from the given unicode string. The array must
|
Extends this array with data from the given unicode string. The array must
|
||||||
|
@ -231,11 +226,6 @@ The following data items and methods are also supported:
|
||||||
Convert the array to an ordinary list with the same items.
|
Convert the array to an ordinary list with the same items.
|
||||||
|
|
||||||
|
|
||||||
.. method:: array.tostring()
|
|
||||||
|
|
||||||
Deprecated alias for :meth:`tobytes`.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: array.tounicode()
|
.. method:: array.tounicode()
|
||||||
|
|
||||||
Convert the array to a unicode string. The array must be a type ``'u'`` array;
|
Convert the array to a unicode string. The array must be a type ``'u'`` array;
|
||||||
|
|
|
@ -161,6 +161,19 @@ and classes for traversing abstract syntax trees:
|
||||||
Added ``type_comments``, ``mode='func_type'`` and ``feature_version``.
|
Added ``type_comments``, ``mode='func_type'`` and ``feature_version``.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: unparse(ast_obj)
|
||||||
|
|
||||||
|
Unparse an :class:`ast.AST` object and generate a string with code
|
||||||
|
that would produce an equivalent :class:`ast.AST` object if parsed
|
||||||
|
back with :func:`ast.parse`.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
The produced code string will not necesarily be equal to the original
|
||||||
|
code that generated the :class:`ast.AST` object.
|
||||||
|
|
||||||
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
|
|
||||||
.. function:: literal_eval(node_or_string)
|
.. function:: literal_eval(node_or_string)
|
||||||
|
|
||||||
Safely evaluate an expression node or a string containing a Python literal or
|
Safely evaluate an expression node or a string containing a Python literal or
|
||||||
|
|
|
@ -473,6 +473,21 @@ Opening network connections
|
||||||
reuse_address=None, reuse_port=None, \
|
reuse_address=None, reuse_port=None, \
|
||||||
allow_broadcast=None, sock=None)
|
allow_broadcast=None, sock=None)
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
The parameter *reuse_address* is no longer supported, as using
|
||||||
|
:py:data:`~sockets.SO_REUSEADDR` poses a significant security concern for
|
||||||
|
UDP. Explicitly passing ``reuse_address=True`` will raise an exception.
|
||||||
|
|
||||||
|
When multiple processes with differing UIDs assign sockets to an
|
||||||
|
indentical UDP socket address with ``SO_REUSEADDR``, incoming packets can
|
||||||
|
become randomly distributed among the sockets.
|
||||||
|
|
||||||
|
For supported platforms, *reuse_port* can be used as a replacement for
|
||||||
|
similar functionality. With *reuse_port*,
|
||||||
|
:py:data:`~sockets.SO_REUSEPORT` is used instead, which specifically
|
||||||
|
prevents processes with differing UIDs from assigning sockets to the same
|
||||||
|
socket address.
|
||||||
|
|
||||||
Create a datagram connection.
|
Create a datagram connection.
|
||||||
|
|
||||||
The socket family can be either :py:data:`~socket.AF_INET`,
|
The socket family can be either :py:data:`~socket.AF_INET`,
|
||||||
|
@ -501,11 +516,6 @@ Opening network connections
|
||||||
resolution. If given, these should all be integers from the
|
resolution. If given, these should all be integers from the
|
||||||
corresponding :mod:`socket` module constants.
|
corresponding :mod:`socket` module constants.
|
||||||
|
|
||||||
* *reuse_address* tells the kernel to reuse a local socket in
|
|
||||||
``TIME_WAIT`` state, without waiting for its natural timeout to
|
|
||||||
expire. If not specified will automatically be set to ``True`` on
|
|
||||||
Unix.
|
|
||||||
|
|
||||||
* *reuse_port* tells the kernel to allow this endpoint to be bound to the
|
* *reuse_port* tells the kernel to allow this endpoint to be bound to the
|
||||||
same port as other existing endpoints are bound to, so long as they all
|
same port as other existing endpoints are bound to, so long as they all
|
||||||
set this flag when being created. This option is not supported on Windows
|
set this flag when being created. This option is not supported on Windows
|
||||||
|
@ -527,6 +537,10 @@ Opening network connections
|
||||||
The *family*, *proto*, *flags*, *reuse_address*, *reuse_port,
|
The *family*, *proto*, *flags*, *reuse_address*, *reuse_port,
|
||||||
*allow_broadcast*, and *sock* parameters were added.
|
*allow_broadcast*, and *sock* parameters were added.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.8.1
|
||||||
|
The *reuse_address* parameter is no longer supported due to security
|
||||||
|
concerns.
|
||||||
|
|
||||||
.. versionchanged:: 3.8
|
.. versionchanged:: 3.8
|
||||||
Added support for Windows.
|
Added support for Windows.
|
||||||
|
|
||||||
|
|
|
@ -588,9 +588,6 @@ Buffered Streaming Protocols
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
.. versionadded:: 3.7
|
.. versionadded:: 3.7
|
||||||
**Important:** this has been added to asyncio in Python 3.7
|
|
||||||
*on a provisional basis*! This is as an experimental API that
|
|
||||||
might be changed or removed completely in Python 3.8.
|
|
||||||
|
|
||||||
Buffered Protocols can be used with any event loop method
|
Buffered Protocols can be used with any event loop method
|
||||||
that supports `Streaming Protocols`_.
|
that supports `Streaming Protocols`_.
|
||||||
|
|
|
@ -7,7 +7,7 @@ Audit events table
|
||||||
|
|
||||||
This table contains all events raised by :func:`sys.audit` or
|
This table contains all events raised by :func:`sys.audit` or
|
||||||
:c:func:`PySys_Audit` calls throughout the CPython runtime and the
|
:c:func:`PySys_Audit` calls throughout the CPython runtime and the
|
||||||
standard library.
|
standard library. These calls were added in 3.8.0 or later.
|
||||||
|
|
||||||
See :func:`sys.addaudithook` and :c:func:`PySys_AddAuditHook` for
|
See :func:`sys.addaudithook` and :c:func:`PySys_AddAuditHook` for
|
||||||
information on handling these events.
|
information on handling these events.
|
||||||
|
|
|
@ -881,7 +881,7 @@ Other constructors, all class methods:
|
||||||
Because naive ``datetime`` objects are treated by many ``datetime`` methods
|
Because naive ``datetime`` objects are treated by many ``datetime`` methods
|
||||||
as local times, it is preferred to use aware datetimes to represent times
|
as local times, it is preferred to use aware datetimes to represent times
|
||||||
in UTC. As such, the recommended way to create an object representing the
|
in UTC. As such, the recommended way to create an object representing the
|
||||||
current time in UTC by calling ``datetime.now(timezone.utc)``.
|
current time in UTC is by calling ``datetime.now(timezone.utc)``.
|
||||||
|
|
||||||
|
|
||||||
.. classmethod:: datetime.fromtimestamp(timestamp, tz=None)
|
.. classmethod:: datetime.fromtimestamp(timestamp, tz=None)
|
||||||
|
@ -942,7 +942,7 @@ Other constructors, all class methods:
|
||||||
Because naive ``datetime`` objects are treated by many ``datetime`` methods
|
Because naive ``datetime`` objects are treated by many ``datetime`` methods
|
||||||
as local times, it is preferred to use aware datetimes to represent times
|
as local times, it is preferred to use aware datetimes to represent times
|
||||||
in UTC. As such, the recommended way to create an object representing a
|
in UTC. As such, the recommended way to create an object representing a
|
||||||
specific timestamp in UTC by calling
|
specific timestamp in UTC is by calling
|
||||||
``datetime.fromtimestamp(timestamp, tz=timezone.utc)``.
|
``datetime.fromtimestamp(timestamp, tz=timezone.utc)``.
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
|
@ -2362,7 +2362,7 @@ requires, and these work on all platforms with a standard C implementation.
|
||||||
| | string if the object is | +063415, | |
|
| | string if the object is | +063415, | |
|
||||||
| | naive). | -030712.345216 | |
|
| | naive). | -030712.345216 | |
|
||||||
+-----------+--------------------------------+------------------------+-------+
|
+-----------+--------------------------------+------------------------+-------+
|
||||||
| ``%Z`` | Time zone name (empty string | (empty), UTC, EST, CST | |
|
| ``%Z`` | Time zone name (empty string | (empty), UTC, GMT | \(6) |
|
||||||
| | if the object is naive). | | |
|
| | if the object is naive). | | |
|
||||||
+-----------+--------------------------------+------------------------+-------+
|
+-----------+--------------------------------+------------------------+-------+
|
||||||
| ``%j`` | Day of the year as a | 001, 002, ..., 366 | \(9) |
|
| ``%j`` | Day of the year as a | 001, 002, ..., 366 | \(9) |
|
||||||
|
@ -2533,9 +2533,18 @@ Notes:
|
||||||
In addition, providing ``'Z'`` is identical to ``'+00:00'``.
|
In addition, providing ``'Z'`` is identical to ``'+00:00'``.
|
||||||
|
|
||||||
``%Z``
|
``%Z``
|
||||||
If :meth:`tzname` returns ``None``, ``%Z`` is replaced by an empty
|
In :meth:`strftime`, ``%Z`` is replaced by an empty string if
|
||||||
string. Otherwise ``%Z`` is replaced by the returned value, which must
|
:meth:`tzname` returns ``None``; otherwise ``%Z`` is replaced by the
|
||||||
be a string.
|
returned value, which must be a string.
|
||||||
|
|
||||||
|
:meth:`strptime` only accepts certain values for ``%Z``:
|
||||||
|
|
||||||
|
1. any value in ``time.tzname`` for your machine's locale
|
||||||
|
2. the hard-coded values ``UTC`` and ``GMT``
|
||||||
|
|
||||||
|
So someone living in Japan may have ``JST``, ``UTC``, and ``GMT`` as
|
||||||
|
valid values, but probably not ``EST``. It will raise ``ValueError`` for
|
||||||
|
invalid values.
|
||||||
|
|
||||||
.. versionchanged:: 3.2
|
.. versionchanged:: 3.2
|
||||||
When the ``%z`` directive is provided to the :meth:`strptime` method, an
|
When the ``%z`` directive is provided to the :meth:`strptime` method, an
|
||||||
|
|
|
@ -706,50 +706,21 @@ iterations of the loop.
|
||||||
popped values are used to restore the exception state.
|
popped values are used to restore the exception state.
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: POP_FINALLY (preserve_tos)
|
.. opcode:: RERAISE
|
||||||
|
|
||||||
Cleans up the value stack and the block stack. If *preserve_tos* is not
|
Re-raises the exception currently on top of the stack.
|
||||||
``0`` TOS first is popped from the stack and pushed on the stack after
|
|
||||||
performing other stack operations:
|
|
||||||
|
|
||||||
* If TOS is ``NULL`` or an integer (pushed by :opcode:`BEGIN_FINALLY`
|
.. versionadded:: 3.9
|
||||||
or :opcode:`CALL_FINALLY`) it is popped from the stack.
|
|
||||||
* If TOS is an exception type (pushed when an exception has been raised)
|
|
||||||
6 values are popped from the stack, the last three popped values are
|
|
||||||
used to restore the exception state. An exception handler block is
|
|
||||||
removed from the block stack.
|
|
||||||
|
|
||||||
It is similar to :opcode:`END_FINALLY`, but doesn't change the bytecode
|
|
||||||
counter nor raise an exception. Used for implementing :keyword:`break`,
|
|
||||||
:keyword:`continue` and :keyword:`return` in the :keyword:`finally` block.
|
|
||||||
|
|
||||||
.. versionadded:: 3.8
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: BEGIN_FINALLY
|
.. opcode:: WITH_EXCEPT_START
|
||||||
|
|
||||||
Pushes ``NULL`` onto the stack for using it in :opcode:`END_FINALLY`,
|
Calls the function in position 7 on the stack with the top three
|
||||||
:opcode:`POP_FINALLY`, :opcode:`WITH_CLEANUP_START` and
|
items on the stack as arguments.
|
||||||
:opcode:`WITH_CLEANUP_FINISH`. Starts the :keyword:`finally` block.
|
Used to implement the call ``context_manager.__exit__(*exc_info())`` when an exception
|
||||||
|
has occurred in a :keyword:`with` statement.
|
||||||
|
|
||||||
.. versionadded:: 3.8
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: END_FINALLY
|
|
||||||
|
|
||||||
Terminates a :keyword:`finally` clause. The interpreter recalls whether the
|
|
||||||
exception has to be re-raised or execution has to be continued depending on
|
|
||||||
the value of TOS.
|
|
||||||
|
|
||||||
* If TOS is ``NULL`` (pushed by :opcode:`BEGIN_FINALLY`) continue from
|
|
||||||
the next instruction. TOS is popped.
|
|
||||||
* If TOS is an integer (pushed by :opcode:`CALL_FINALLY`), sets the
|
|
||||||
bytecode counter to TOS. TOS is popped.
|
|
||||||
* If TOS is an exception type (pushed when an exception has been raised)
|
|
||||||
6 values are popped from the stack, the first three popped values are
|
|
||||||
used to re-raise the exception and the last three popped values are used
|
|
||||||
to restore the exception state. An exception handler block is removed
|
|
||||||
from the block stack.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: LOAD_ASSERTION_ERROR
|
.. opcode:: LOAD_ASSERTION_ERROR
|
||||||
|
@ -780,35 +751,6 @@ iterations of the loop.
|
||||||
.. versionadded:: 3.2
|
.. versionadded:: 3.2
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: WITH_CLEANUP_START
|
|
||||||
|
|
||||||
Starts cleaning up the stack when a :keyword:`with` statement block exits.
|
|
||||||
|
|
||||||
At the top of the stack are either ``NULL`` (pushed by
|
|
||||||
:opcode:`BEGIN_FINALLY`) or 6 values pushed if an exception has been
|
|
||||||
raised in the with block. Below is the context manager's
|
|
||||||
:meth:`~object.__exit__` or :meth:`~object.__aexit__` bound method.
|
|
||||||
|
|
||||||
If TOS is ``NULL``, calls ``SECOND(None, None, None)``,
|
|
||||||
removes the function from the stack, leaving TOS, and pushes ``None``
|
|
||||||
to the stack. Otherwise calls ``SEVENTH(TOP, SECOND, THIRD)``,
|
|
||||||
shifts the bottom 3 values of the stack down, replaces the empty spot
|
|
||||||
with ``NULL`` and pushes TOS. Finally pushes the result of the call.
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: WITH_CLEANUP_FINISH
|
|
||||||
|
|
||||||
Finishes cleaning up the stack when a :keyword:`with` statement block exits.
|
|
||||||
|
|
||||||
TOS is result of ``__exit__()`` or ``__aexit__()`` function call pushed
|
|
||||||
by :opcode:`WITH_CLEANUP_START`. SECOND is ``None`` or an exception type
|
|
||||||
(pushed when an exception has been raised).
|
|
||||||
|
|
||||||
Pops two values from the stack. If SECOND is not None and TOS is true
|
|
||||||
unwinds the EXCEPT_HANDLER block which was created when the exception
|
|
||||||
was caught and pushes ``NULL`` to the stack.
|
|
||||||
|
|
||||||
|
|
||||||
All of the following opcodes use their arguments.
|
All of the following opcodes use their arguments.
|
||||||
|
|
||||||
.. opcode:: STORE_NAME (namei)
|
.. opcode:: STORE_NAME (namei)
|
||||||
|
@ -1060,15 +1002,6 @@ All of the following opcodes use their arguments.
|
||||||
stack. *delta* points to the finally block or the first except block.
|
stack. *delta* points to the finally block or the first except block.
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: CALL_FINALLY (delta)
|
|
||||||
|
|
||||||
Pushes the address of the next instruction onto the stack and increments
|
|
||||||
bytecode counter by *delta*. Used for calling the finally block as a
|
|
||||||
"subroutine".
|
|
||||||
|
|
||||||
.. versionadded:: 3.8
|
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: LOAD_FAST (var_num)
|
.. opcode:: LOAD_FAST (var_num)
|
||||||
|
|
||||||
Pushes a reference to the local ``co_varnames[var_num]`` onto the stack.
|
Pushes a reference to the local ``co_varnames[var_num]`` onto the stack.
|
||||||
|
|
|
@ -199,7 +199,8 @@ Format Paragraph
|
||||||
Strip trailing whitespace
|
Strip trailing whitespace
|
||||||
Remove trailing space and other whitespace characters after the last
|
Remove trailing space and other whitespace characters after the last
|
||||||
non-whitespace character of a line by applying str.rstrip to each line,
|
non-whitespace character of a line by applying str.rstrip to each line,
|
||||||
including lines within multiline strings.
|
including lines within multiline strings. Except for Shell windows,
|
||||||
|
remove extra newlines at the end of the file.
|
||||||
|
|
||||||
.. index::
|
.. index::
|
||||||
single: Run script
|
single: Run script
|
||||||
|
|
|
@ -732,12 +732,24 @@ Command line options
|
||||||
|
|
||||||
.. versionadded:: 3.5
|
.. versionadded:: 3.5
|
||||||
|
|
||||||
|
.. cmdoption:: --no-ensure-ascii
|
||||||
|
|
||||||
|
Disable escaping of non-ascii characters, see :func:`json.dumps` for more information.
|
||||||
|
|
||||||
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
.. cmdoption:: --json-lines
|
.. cmdoption:: --json-lines
|
||||||
|
|
||||||
Parse every input line as separate JSON object.
|
Parse every input line as separate JSON object.
|
||||||
|
|
||||||
.. versionadded:: 3.8
|
.. versionadded:: 3.8
|
||||||
|
|
||||||
|
.. cmdoption:: --indent, --tab, --no-indent, --compact
|
||||||
|
|
||||||
|
Mutually exclusive options for whitespace control
|
||||||
|
|
||||||
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
.. cmdoption:: -h, --help
|
.. cmdoption:: -h, --help
|
||||||
|
|
||||||
Show the help message.
|
Show the help message.
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
================================================
|
================================================
|
||||||
|
|
||||||
.. module:: linecache
|
.. module:: linecache
|
||||||
:synopsis: This module provides random access to individual lines from text files.
|
:synopsis: Provides random access to individual lines from text files.
|
||||||
|
|
||||||
.. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
|
.. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
|
||||||
|
|
||||||
|
|
|
@ -2169,7 +2169,8 @@ with the :class:`Pool` class.
|
||||||
.. method:: map(func, iterable[, chunksize])
|
.. method:: map(func, iterable[, chunksize])
|
||||||
|
|
||||||
A parallel equivalent of the :func:`map` built-in function (it supports only
|
A parallel equivalent of the :func:`map` built-in function (it supports only
|
||||||
one *iterable* argument though). It blocks until the result is ready.
|
one *iterable* argument though, for multiple iterables see :meth:`starmap`).
|
||||||
|
It blocks until the result is ready.
|
||||||
|
|
||||||
This method chops the iterable into a number of chunks which it submits to
|
This method chops the iterable into a number of chunks which it submits to
|
||||||
the process pool as separate tasks. The (approximate) size of these
|
the process pool as separate tasks. The (approximate) size of these
|
||||||
|
|
|
@ -165,8 +165,9 @@ Functions for sequences
|
||||||
|
|
||||||
The *weights* or *cum_weights* can use any numeric type that interoperates
|
The *weights* or *cum_weights* can use any numeric type that interoperates
|
||||||
with the :class:`float` values returned by :func:`random` (that includes
|
with the :class:`float` values returned by :func:`random` (that includes
|
||||||
integers, floats, and fractions but excludes decimals). Weights are
|
integers, floats, and fractions but excludes decimals). Behavior is
|
||||||
assumed to be non-negative.
|
undefined if any weight is negative. A :exc:`ValueError` is raised if all
|
||||||
|
weights are zero.
|
||||||
|
|
||||||
For a given seed, the :func:`choices` function with equal weighting
|
For a given seed, the :func:`choices` function with equal weighting
|
||||||
typically produces a different sequence than repeated calls to
|
typically produces a different sequence than repeated calls to
|
||||||
|
@ -177,6 +178,9 @@ Functions for sequences
|
||||||
|
|
||||||
.. versionadded:: 3.6
|
.. versionadded:: 3.6
|
||||||
|
|
||||||
|
.. versionchanged:: 3.9
|
||||||
|
Raises a :exc:`ValueError` if all weights are zero.
|
||||||
|
|
||||||
|
|
||||||
.. function:: shuffle(x[, random])
|
.. function:: shuffle(x[, random])
|
||||||
|
|
||||||
|
|
|
@ -1411,9 +1411,9 @@ to sockets.
|
||||||
fds = array.array("i") # Array of ints
|
fds = array.array("i") # Array of ints
|
||||||
msg, ancdata, flags, addr = sock.recvmsg(msglen, socket.CMSG_LEN(maxfds * fds.itemsize))
|
msg, ancdata, flags, addr = sock.recvmsg(msglen, socket.CMSG_LEN(maxfds * fds.itemsize))
|
||||||
for cmsg_level, cmsg_type, cmsg_data in ancdata:
|
for cmsg_level, cmsg_type, cmsg_data in ancdata:
|
||||||
if (cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS):
|
if cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS:
|
||||||
# Append data, ignoring any truncated integers at the end.
|
# Append data, ignoring any truncated integers at the end.
|
||||||
fds.fromstring(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)])
|
fds.frombytes(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)])
|
||||||
return msg, list(fds)
|
return msg, list(fds)
|
||||||
|
|
||||||
.. availability:: most Unix platforms, possibly others.
|
.. availability:: most Unix platforms, possibly others.
|
||||||
|
|
|
@ -1256,6 +1256,9 @@ SSL sockets also have the following additional methods and attributes:
|
||||||
The returned dictionary includes additional X509v3 extension items
|
The returned dictionary includes additional X509v3 extension items
|
||||||
such as ``crlDistributionPoints``, ``caIssuers`` and ``OCSP`` URIs.
|
such as ``crlDistributionPoints``, ``caIssuers`` and ``OCSP`` URIs.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.9
|
||||||
|
IPv6 address strings no longer have a trailing new line.
|
||||||
|
|
||||||
.. method:: SSLSocket.cipher()
|
.. method:: SSLSocket.cipher()
|
||||||
|
|
||||||
Returns a three-value tuple containing the name of the cipher being used, the
|
Returns a three-value tuple containing the name of the cipher being used, the
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
=======================================================
|
=======================================================
|
||||||
|
|
||||||
.. module:: statistics
|
.. module:: statistics
|
||||||
:synopsis: mathematical statistics functions
|
:synopsis: Mathematical statistics functions
|
||||||
|
|
||||||
.. moduleauthor:: Steven D'Aprano <steve+python@pearwood.info>
|
.. moduleauthor:: Steven D'Aprano <steve+python@pearwood.info>
|
||||||
.. sectionauthor:: Steven D'Aprano <steve+python@pearwood.info>
|
.. sectionauthor:: Steven D'Aprano <steve+python@pearwood.info>
|
||||||
|
|
|
@ -25,7 +25,7 @@ always available.
|
||||||
|
|
||||||
.. function:: addaudithook(hook)
|
.. function:: addaudithook(hook)
|
||||||
|
|
||||||
Adds the callable *hook* to the collection of active auditing hooks for the
|
Append the callable *hook* to the list of active auditing hooks for the
|
||||||
current interpreter.
|
current interpreter.
|
||||||
|
|
||||||
When an auditing event is raised through the :func:`sys.audit` function, each
|
When an auditing event is raised through the :func:`sys.audit` function, each
|
||||||
|
@ -35,14 +35,19 @@ always available.
|
||||||
|
|
||||||
.. audit-event:: sys.addaudithook "" sys.addaudithook
|
.. audit-event:: sys.addaudithook "" sys.addaudithook
|
||||||
|
|
||||||
Raises a auditing event ``sys.addaudithook`` with no arguments. If any
|
Raise an auditing event ``sys.addaudithook`` with no arguments. If any
|
||||||
existing hooks raise an exception derived from :class:`Exception`, the
|
existing hooks raise an exception derived from :class:`RuntimeError`, the
|
||||||
new hook will not be added and the exception suppressed. As a result,
|
new hook will not be added and the exception suppressed. As a result,
|
||||||
callers cannot assume that their hook has been added unless they control
|
callers cannot assume that their hook has been added unless they control
|
||||||
all existing hooks.
|
all existing hooks.
|
||||||
|
|
||||||
.. versionadded:: 3.8
|
.. versionadded:: 3.8
|
||||||
|
|
||||||
|
.. versionchanged:: 3.8.1
|
||||||
|
|
||||||
|
Exceptions derived from :class:`Exception` but not :class:`RuntimeError`
|
||||||
|
are no longer suppressed.
|
||||||
|
|
||||||
.. impl-detail::
|
.. impl-detail::
|
||||||
|
|
||||||
When tracing is enabled (see :func:`settrace`), Python hooks are only
|
When tracing is enabled (see :func:`settrace`), Python hooks are only
|
||||||
|
@ -74,7 +79,7 @@ always available.
|
||||||
|
|
||||||
.. index:: single: auditing
|
.. index:: single: auditing
|
||||||
|
|
||||||
Raises an auditing event with any active hooks. The event name is a string
|
Raise an auditing event with any active hooks. The event name is a string
|
||||||
identifying the event and its associated schema, which is the number and
|
identifying the event and its associated schema, which is the number and
|
||||||
types of arguments. The schema for a given event is considered public and
|
types of arguments. The schema for a given event is considered public and
|
||||||
stable API and should not be modified between releases.
|
stable API and should not be modified between releases.
|
||||||
|
@ -308,6 +313,15 @@ always available.
|
||||||
before the program exits. The handling of such top-level exceptions can be
|
before the program exits. The handling of such top-level exceptions can be
|
||||||
customized by assigning another three-argument function to ``sys.excepthook``.
|
customized by assigning another three-argument function to ``sys.excepthook``.
|
||||||
|
|
||||||
|
.. audit-event:: sys.excepthook hook,type,value,traceback sys.excepthook
|
||||||
|
|
||||||
|
Raise an auditing event ``sys.excepthook`` with arguments ``hook``,
|
||||||
|
``type``, ``value``, ``traceback`` when an uncaught exception occurs.
|
||||||
|
If no hook has been set, ``hook`` may be ``None``. If any hook raises
|
||||||
|
an exception derived from :class:`RuntimeError` the call to the hook will
|
||||||
|
be suppressed. Otherwise, the audit hook exception will be reported as
|
||||||
|
unraisable and ``sys.excepthook`` will be called.
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
||||||
The :func:`sys.unraisablehook` function handles unraisable exceptions
|
The :func:`sys.unraisablehook` function handles unraisable exceptions
|
||||||
|
@ -1540,6 +1554,13 @@ always available.
|
||||||
|
|
||||||
See also :func:`excepthook` which handles uncaught exceptions.
|
See also :func:`excepthook` which handles uncaught exceptions.
|
||||||
|
|
||||||
|
.. audit-event:: sys.unraisablehook hook,unraisable sys.unraisablehook
|
||||||
|
|
||||||
|
Raise an auditing event ``sys.unraisablehook`` with arguments
|
||||||
|
``hook``, ``unraisable`` when an exception that cannot be handled occurs.
|
||||||
|
The ``unraisable`` object is the same as what will be passed to the hook.
|
||||||
|
If no hook has been set, ``hook`` may be ``None``.
|
||||||
|
|
||||||
.. versionadded:: 3.8
|
.. versionadded:: 3.8
|
||||||
|
|
||||||
.. data:: version
|
.. data:: version
|
||||||
|
|
|
@ -105,8 +105,8 @@ The module defines the following user-callable items:
|
||||||
causes the file to roll over to an on-disk file regardless of its size.
|
causes the file to roll over to an on-disk file regardless of its size.
|
||||||
|
|
||||||
The returned object is a file-like object whose :attr:`_file` attribute
|
The returned object is a file-like object whose :attr:`_file` attribute
|
||||||
is either an :class:`io.BytesIO` or :class:`io.StringIO` object (depending on
|
is either an :class:`io.BytesIO` or :class:`io.TextIOWrapper` object
|
||||||
whether binary or text *mode* was specified) or a true file
|
(depending on whether binary or text *mode* was specified) or a true file
|
||||||
object, depending on whether :func:`rollover` has been called. This
|
object, depending on whether :func:`rollover` has been called. This
|
||||||
file-like object can be used in a :keyword:`with` statement, just like
|
file-like object can be used in a :keyword:`with` statement, just like
|
||||||
a normal file.
|
a normal file.
|
||||||
|
|
|
@ -686,13 +686,6 @@ The :mod:`test.support` module defines the following functions:
|
||||||
``sys.stdout`` if it's not set.
|
``sys.stdout`` if it's not set.
|
||||||
|
|
||||||
|
|
||||||
.. function:: strip_python_strerr(stderr)
|
|
||||||
|
|
||||||
Strip the *stderr* of a Python process from potential debug output
|
|
||||||
emitted by the interpreter. This will typically be run on the result of
|
|
||||||
:meth:`subprocess.Popen.communicate`.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: args_from_interpreter_flags()
|
.. function:: args_from_interpreter_flags()
|
||||||
|
|
||||||
Return a list of command line arguments reproducing the current settings
|
Return a list of command line arguments reproducing the current settings
|
||||||
|
@ -1499,6 +1492,9 @@ script execution tests.
|
||||||
in a subprocess. The values can include ``__isolated``, ``__cleanenv``,
|
in a subprocess. The values can include ``__isolated``, ``__cleanenv``,
|
||||||
``__cwd``, and ``TERM``.
|
``__cwd``, and ``TERM``.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.9
|
||||||
|
The function no longer strips whitespaces from *stderr*.
|
||||||
|
|
||||||
|
|
||||||
.. function:: assert_python_ok(*args, **env_vars)
|
.. function:: assert_python_ok(*args, **env_vars)
|
||||||
|
|
||||||
|
@ -1512,6 +1508,9 @@ script execution tests.
|
||||||
Python is started in isolated mode (command line option ``-I``),
|
Python is started in isolated mode (command line option ``-I``),
|
||||||
except if the ``__isolated`` keyword is set to ``False``.
|
except if the ``__isolated`` keyword is set to ``False``.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.9
|
||||||
|
The function no longer strips whitespaces from *stderr*.
|
||||||
|
|
||||||
|
|
||||||
.. function:: assert_python_failure(*args, **env_vars)
|
.. function:: assert_python_failure(*args, **env_vars)
|
||||||
|
|
||||||
|
@ -1521,6 +1520,9 @@ script execution tests.
|
||||||
|
|
||||||
See :func:`assert_python_ok` for more options.
|
See :func:`assert_python_ok` for more options.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.9
|
||||||
|
The function no longer strips whitespaces from *stderr*.
|
||||||
|
|
||||||
|
|
||||||
.. function:: spawn_python(*args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kw)
|
.. function:: spawn_python(*args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kw)
|
||||||
|
|
||||||
|
|
|
@ -496,6 +496,10 @@ All methods are executed atomically.
|
||||||
|
|
||||||
There is no return value.
|
There is no return value.
|
||||||
|
|
||||||
|
.. method:: locked()
|
||||||
|
Return true if the lock is acquired.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _rlock-objects:
|
.. _rlock-objects:
|
||||||
|
|
||||||
|
|
|
@ -42,17 +42,12 @@ An explanation of some terminology and conventions is in order.
|
||||||
library; for 32-bit systems, it is typically in 2038.
|
library; for 32-bit systems, it is typically in 2038.
|
||||||
|
|
||||||
.. index::
|
.. index::
|
||||||
single: Year 2000
|
single: 2-digit years
|
||||||
single: Y2K
|
|
||||||
|
|
||||||
.. _time-y2kissues:
|
* Function :func:`strptime` can parse 2-digit years when given ``%y`` format
|
||||||
|
code. When 2-digit years are parsed, they are converted according to the POSIX
|
||||||
* **Year 2000 (Y2K) issues**: Python depends on the platform's C library, which
|
and ISO C standards: values 69--99 are mapped to 1969--1999, and values 0--68
|
||||||
generally doesn't have year 2000 issues, since all dates and times are
|
are mapped to 2000--2068.
|
||||||
represented internally as seconds since the epoch. Function :func:`strptime`
|
|
||||||
can parse 2-digit years when given ``%y`` format code. When 2-digit years are
|
|
||||||
parsed, they are converted according to the POSIX and ISO C standards: values
|
|
||||||
69--99 are mapped to 1969--1999, and values 0--68 are mapped to 2000--2068.
|
|
||||||
|
|
||||||
.. index::
|
.. index::
|
||||||
single: UTC
|
single: UTC
|
||||||
|
|
|
@ -132,7 +132,7 @@ creation according to their needs, the :class:`EnvBuilder` class.
|
||||||
.. versionadded:: 3.6
|
.. versionadded:: 3.6
|
||||||
Added the ``prompt`` parameter
|
Added the ``prompt`` parameter
|
||||||
|
|
||||||
.. versionadded:: 3.8
|
.. versionadded:: 3.9
|
||||||
Added the ``upgrade_deps`` parameter
|
Added the ``upgrade_deps`` parameter
|
||||||
|
|
||||||
Creators of third-party virtual environment tools will be free to use the
|
Creators of third-party virtual environment tools will be free to use the
|
||||||
|
@ -197,7 +197,7 @@ creation according to their needs, the :class:`EnvBuilder` class.
|
||||||
``setuptools``) in the environment. This is done by shelling out to the
|
``setuptools``) in the environment. This is done by shelling out to the
|
||||||
``pip`` executable in the environment.
|
``pip`` executable in the environment.
|
||||||
|
|
||||||
.. versionadded:: 3.8
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
.. method:: post_setup(context)
|
.. method:: post_setup(context)
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,8 @@ This module offers the following functions:
|
||||||
The return value is the handle of the opened key. If the function fails, an
|
The return value is the handle of the opened key. If the function fails, an
|
||||||
:exc:`OSError` exception is raised.
|
:exc:`OSError` exception is raised.
|
||||||
|
|
||||||
|
.. audit-event:: winreg.ConnectRegistry computer_name,key winreg.ConnectRegistry
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
See :ref:`above <exception-changed>`.
|
See :ref:`above <exception-changed>`.
|
||||||
|
|
||||||
|
@ -75,6 +77,10 @@ This module offers the following functions:
|
||||||
The return value is the handle of the opened key. If the function fails, an
|
The return value is the handle of the opened key. If the function fails, an
|
||||||
:exc:`OSError` exception is raised.
|
:exc:`OSError` exception is raised.
|
||||||
|
|
||||||
|
.. audit-event:: winreg.CreateKey key,sub_key,access winreg.CreateKey
|
||||||
|
|
||||||
|
.. audit-event:: winreg.OpenKey/result key winreg.CreateKey
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
See :ref:`above <exception-changed>`.
|
See :ref:`above <exception-changed>`.
|
||||||
|
|
||||||
|
@ -103,6 +109,10 @@ This module offers the following functions:
|
||||||
The return value is the handle of the opened key. If the function fails, an
|
The return value is the handle of the opened key. If the function fails, an
|
||||||
:exc:`OSError` exception is raised.
|
:exc:`OSError` exception is raised.
|
||||||
|
|
||||||
|
.. audit-event:: winreg.CreateKey key,sub_key,access winreg.CreateKeyEx
|
||||||
|
|
||||||
|
.. audit-event:: winreg.OpenKey/result key winreg.CreateKeyEx
|
||||||
|
|
||||||
.. versionadded:: 3.2
|
.. versionadded:: 3.2
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
|
@ -124,6 +134,8 @@ This module offers the following functions:
|
||||||
If the method succeeds, the entire key, including all of its values, is removed.
|
If the method succeeds, the entire key, including all of its values, is removed.
|
||||||
If the method fails, an :exc:`OSError` exception is raised.
|
If the method fails, an :exc:`OSError` exception is raised.
|
||||||
|
|
||||||
|
.. audit-event:: winreg.DeleteKey key,sub_key,access winreg.DeleteKey
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
See :ref:`above <exception-changed>`.
|
See :ref:`above <exception-changed>`.
|
||||||
|
|
||||||
|
@ -158,6 +170,8 @@ This module offers the following functions:
|
||||||
|
|
||||||
On unsupported Windows versions, :exc:`NotImplementedError` is raised.
|
On unsupported Windows versions, :exc:`NotImplementedError` is raised.
|
||||||
|
|
||||||
|
.. audit-event:: winreg.DeleteKey key,sub_key,access winreg.DeleteKeyEx
|
||||||
|
|
||||||
.. versionadded:: 3.2
|
.. versionadded:: 3.2
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
|
@ -173,6 +187,8 @@ This module offers the following functions:
|
||||||
|
|
||||||
*value* is a string that identifies the value to remove.
|
*value* is a string that identifies the value to remove.
|
||||||
|
|
||||||
|
.. audit-event:: winreg.DeleteValue key,value winreg.DeleteValue
|
||||||
|
|
||||||
|
|
||||||
.. function:: EnumKey(key, index)
|
.. function:: EnumKey(key, index)
|
||||||
|
|
||||||
|
@ -187,6 +203,8 @@ This module offers the following functions:
|
||||||
typically called repeatedly until an :exc:`OSError` exception is
|
typically called repeatedly until an :exc:`OSError` exception is
|
||||||
raised, indicating, no more values are available.
|
raised, indicating, no more values are available.
|
||||||
|
|
||||||
|
.. audit-event:: winreg.EnumKey key,index winreg.EnumKey
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
See :ref:`above <exception-changed>`.
|
See :ref:`above <exception-changed>`.
|
||||||
|
|
||||||
|
@ -220,6 +238,8 @@ This module offers the following functions:
|
||||||
| | :meth:`SetValueEx`) |
|
| | :meth:`SetValueEx`) |
|
||||||
+-------+--------------------------------------------+
|
+-------+--------------------------------------------+
|
||||||
|
|
||||||
|
.. audit-event:: winreg.EnumValue key,index winreg.EnumValue
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
See :ref:`above <exception-changed>`.
|
See :ref:`above <exception-changed>`.
|
||||||
|
|
||||||
|
@ -235,6 +255,8 @@ This module offers the following functions:
|
||||||
>>> ExpandEnvironmentStrings('%windir%')
|
>>> ExpandEnvironmentStrings('%windir%')
|
||||||
'C:\\Windows'
|
'C:\\Windows'
|
||||||
|
|
||||||
|
.. audit-event:: winreg.ExpandEnvironmentStrings str winreg.ExpandEnvironmentStrings
|
||||||
|
|
||||||
|
|
||||||
.. function:: FlushKey(key)
|
.. function:: FlushKey(key)
|
||||||
|
|
||||||
|
@ -279,6 +301,8 @@ This module offers the following functions:
|
||||||
If *key* is a handle returned by :func:`ConnectRegistry`, then the path
|
If *key* is a handle returned by :func:`ConnectRegistry`, then the path
|
||||||
specified in *file_name* is relative to the remote computer.
|
specified in *file_name* is relative to the remote computer.
|
||||||
|
|
||||||
|
.. audit-event:: winreg.LoadKey key,sub_key,file_name winreg.LoadKey
|
||||||
|
|
||||||
|
|
||||||
.. function:: OpenKey(key, sub_key, reserved=0, access=KEY_READ)
|
.. function:: OpenKey(key, sub_key, reserved=0, access=KEY_READ)
|
||||||
OpenKeyEx(key, sub_key, reserved=0, access=KEY_READ)
|
OpenKeyEx(key, sub_key, reserved=0, access=KEY_READ)
|
||||||
|
@ -300,6 +324,10 @@ This module offers the following functions:
|
||||||
|
|
||||||
If the function fails, :exc:`OSError` is raised.
|
If the function fails, :exc:`OSError` is raised.
|
||||||
|
|
||||||
|
.. audit-event:: winreg.OpenKey key,sub_key,access winreg.OpenKey
|
||||||
|
|
||||||
|
.. audit-event:: winreg.OpenKey/result key winreg.OpenKey
|
||||||
|
|
||||||
.. versionchanged:: 3.2
|
.. versionchanged:: 3.2
|
||||||
Allow the use of named arguments.
|
Allow the use of named arguments.
|
||||||
|
|
||||||
|
@ -330,6 +358,8 @@ This module offers the following functions:
|
||||||
| | nanoseconds since Jan 1, 1601. |
|
| | nanoseconds since Jan 1, 1601. |
|
||||||
+-------+---------------------------------------------+
|
+-------+---------------------------------------------+
|
||||||
|
|
||||||
|
.. audit-event:: winreg.QueryInfoKey key winreg.QueryInfoKey
|
||||||
|
|
||||||
|
|
||||||
.. function:: QueryValue(key, sub_key)
|
.. function:: QueryValue(key, sub_key)
|
||||||
|
|
||||||
|
@ -347,6 +377,8 @@ This module offers the following functions:
|
||||||
underlying API call doesn't return the type, so always use
|
underlying API call doesn't return the type, so always use
|
||||||
:func:`QueryValueEx` if possible.
|
:func:`QueryValueEx` if possible.
|
||||||
|
|
||||||
|
.. audit-event:: winreg.QueryValue key,sub_key,value_name winreg.QueryValue
|
||||||
|
|
||||||
|
|
||||||
.. function:: QueryValueEx(key, value_name)
|
.. function:: QueryValueEx(key, value_name)
|
||||||
|
|
||||||
|
@ -370,6 +402,8 @@ This module offers the following functions:
|
||||||
| | :meth:`SetValueEx`) |
|
| | :meth:`SetValueEx`) |
|
||||||
+-------+-----------------------------------------+
|
+-------+-----------------------------------------+
|
||||||
|
|
||||||
|
.. audit-event:: winreg.QueryValue key,sub_key,value_name winreg.QueryValueEx
|
||||||
|
|
||||||
|
|
||||||
.. function:: SaveKey(key, file_name)
|
.. function:: SaveKey(key, file_name)
|
||||||
|
|
||||||
|
@ -393,6 +427,8 @@ This module offers the following functions:
|
||||||
|
|
||||||
This function passes ``NULL`` for *security_attributes* to the API.
|
This function passes ``NULL`` for *security_attributes* to the API.
|
||||||
|
|
||||||
|
.. audit-event:: winreg.SaveKey key,file_name winreg.SaveKey
|
||||||
|
|
||||||
|
|
||||||
.. function:: SetValue(key, sub_key, type, value)
|
.. function:: SetValue(key, sub_key, type, value)
|
||||||
|
|
||||||
|
@ -419,6 +455,8 @@ This module offers the following functions:
|
||||||
The key identified by the *key* parameter must have been opened with
|
The key identified by the *key* parameter must have been opened with
|
||||||
:const:`KEY_SET_VALUE` access.
|
:const:`KEY_SET_VALUE` access.
|
||||||
|
|
||||||
|
.. audit-event:: winreg.SetValue key,sub_key,type,value winreg.SetValue
|
||||||
|
|
||||||
|
|
||||||
.. function:: SetValueEx(key, value_name, reserved, type, value)
|
.. function:: SetValueEx(key, value_name, reserved, type, value)
|
||||||
|
|
||||||
|
@ -447,6 +485,8 @@ This module offers the following functions:
|
||||||
bytes) should be stored as files with the filenames stored in the configuration
|
bytes) should be stored as files with the filenames stored in the configuration
|
||||||
registry. This helps the registry perform efficiently.
|
registry. This helps the registry perform efficiently.
|
||||||
|
|
||||||
|
.. audit-event:: winreg.SetValue key,sub_key,type,value winreg.SetValueEx
|
||||||
|
|
||||||
|
|
||||||
.. function:: DisableReflectionKey(key)
|
.. function:: DisableReflectionKey(key)
|
||||||
|
|
||||||
|
@ -463,6 +503,8 @@ This module offers the following functions:
|
||||||
effect. Disabling reflection for a key does not affect reflection of any
|
effect. Disabling reflection for a key does not affect reflection of any
|
||||||
subkeys.
|
subkeys.
|
||||||
|
|
||||||
|
.. audit-event:: winreg.DisableReflectionKey key winreg.DisableReflectionKey
|
||||||
|
|
||||||
|
|
||||||
.. function:: EnableReflectionKey(key)
|
.. function:: EnableReflectionKey(key)
|
||||||
|
|
||||||
|
@ -476,6 +518,8 @@ This module offers the following functions:
|
||||||
|
|
||||||
Restoring reflection for a key does not affect reflection of any subkeys.
|
Restoring reflection for a key does not affect reflection of any subkeys.
|
||||||
|
|
||||||
|
.. audit-event:: winreg.EnableReflectionKey key winreg.EnableReflectionKey
|
||||||
|
|
||||||
|
|
||||||
.. function:: QueryReflectionKey(key)
|
.. function:: QueryReflectionKey(key)
|
||||||
|
|
||||||
|
@ -489,6 +533,8 @@ This module offers the following functions:
|
||||||
Will generally raise :exc:`NotImplementedError` if executed on a 32-bit
|
Will generally raise :exc:`NotImplementedError` if executed on a 32-bit
|
||||||
operating system.
|
operating system.
|
||||||
|
|
||||||
|
.. audit-event:: winreg.QueryReflectionKey key winreg.QueryReflectionKey
|
||||||
|
|
||||||
|
|
||||||
.. _constants:
|
.. _constants:
|
||||||
|
|
||||||
|
@ -741,6 +787,9 @@ integer handle, and also disconnect the Windows handle from the handle object.
|
||||||
handle is not closed. You would call this function when you need the
|
handle is not closed. You would call this function when you need the
|
||||||
underlying Win32 handle to exist beyond the lifetime of the handle object.
|
underlying Win32 handle to exist beyond the lifetime of the handle object.
|
||||||
|
|
||||||
|
.. audit-event:: winreg.PyHKEY.Detach key winreg.PyHKEY.Detach
|
||||||
|
|
||||||
|
|
||||||
.. method:: PyHKEY.__enter__()
|
.. method:: PyHKEY.__enter__()
|
||||||
PyHKEY.__exit__(\*exc_info)
|
PyHKEY.__exit__(\*exc_info)
|
||||||
|
|
||||||
|
|
|
@ -494,7 +494,7 @@ Path objects are traversable using the ``/`` operator.
|
||||||
Invoke :meth:`ZipFile.open` on the current path. Accepts
|
Invoke :meth:`ZipFile.open` on the current path. Accepts
|
||||||
the same arguments as :meth:`ZipFile.open`.
|
the same arguments as :meth:`ZipFile.open`.
|
||||||
|
|
||||||
.. method:: Path.listdir()
|
.. method:: Path.iterdir()
|
||||||
|
|
||||||
Enumerate the children of the current directory.
|
Enumerate the children of the current directory.
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
=====================================================
|
=====================================================
|
||||||
|
|
||||||
.. module:: zipimport
|
.. module:: zipimport
|
||||||
:synopsis: support for importing Python modules from ZIP archives.
|
:synopsis: Support for importing Python modules from ZIP archives.
|
||||||
|
|
||||||
.. moduleauthor:: Just van Rossum <just@letterror.com>
|
.. moduleauthor:: Just van Rossum <just@letterror.com>
|
||||||
|
|
||||||
|
|
|
@ -1655,8 +1655,22 @@ class' :attr:`~object.__dict__`.
|
||||||
Called at the time the owning class *owner* is created. The
|
Called at the time the owning class *owner* is created. The
|
||||||
descriptor has been assigned to *name*.
|
descriptor has been assigned to *name*.
|
||||||
|
|
||||||
.. versionadded:: 3.6
|
.. note::
|
||||||
|
|
||||||
|
:meth:`__set_name__` is only called implicitly as part of the
|
||||||
|
:class:`type` constructor, so it will need to be called explicitly with
|
||||||
|
the appropriate parameters when a descriptor is added to a class after
|
||||||
|
initial creation::
|
||||||
|
|
||||||
|
class A:
|
||||||
|
pass
|
||||||
|
descr = custom_descriptor()
|
||||||
|
A.attr = descr
|
||||||
|
descr.__set_name__(A, 'attr')
|
||||||
|
|
||||||
|
See :ref:`class-object-creation` for more details.
|
||||||
|
|
||||||
|
.. versionadded:: 3.6
|
||||||
|
|
||||||
The attribute :attr:`__objclass__` is interpreted by the :mod:`inspect` module
|
The attribute :attr:`__objclass__` is interpreted by the :mod:`inspect` module
|
||||||
as specifying the class where this object was defined (setting this
|
as specifying the class where this object was defined (setting this
|
||||||
|
|
|
@ -201,7 +201,7 @@ library/readline,,:bind,"python:bind ^I rl_complete"
|
||||||
library/smtplib,,:port,method must support that as well as a regular host:port
|
library/smtplib,,:port,method must support that as well as a regular host:port
|
||||||
library/socket,,::,'5aef:2b::8'
|
library/socket,,::,'5aef:2b::8'
|
||||||
library/socket,,:can,"return (can_id, can_dlc, data[:can_dlc])"
|
library/socket,,:can,"return (can_id, can_dlc, data[:can_dlc])"
|
||||||
library/socket,,:len,fds.fromstring(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)])
|
library/socket,,:len,fds.frombytes(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)])
|
||||||
library/sqlite3,,:age,"cur.execute(""select * from people where name_last=:who and age=:age"", {""who"": who, ""age"": age})"
|
library/sqlite3,,:age,"cur.execute(""select * from people where name_last=:who and age=:age"", {""who"": who, ""age"": age})"
|
||||||
library/sqlite3,,:memory,
|
library/sqlite3,,:memory,
|
||||||
library/sqlite3,,:who,"cur.execute(""select * from people where name_last=:who and age=:age"", {""who"": who, ""age"": age})"
|
library/sqlite3,,:who,"cur.execute(""select * from people where name_last=:who and age=:age"", {""who"": who, ""age"": age})"
|
||||||
|
|
|
|
@ -104,7 +104,7 @@ directory containing the virtual environment):
|
||||||
+=============+=================+=========================================+
|
+=============+=================+=========================================+
|
||||||
| POSIX | bash/zsh | $ source <venv>/bin/activate |
|
| POSIX | bash/zsh | $ source <venv>/bin/activate |
|
||||||
+-------------+-----------------+-----------------------------------------+
|
+-------------+-----------------+-----------------------------------------+
|
||||||
| | fish | $ . <venv>/bin/activate.fish |
|
| | fish | $ source <venv>/bin/activate.fish |
|
||||||
+-------------+-----------------+-----------------------------------------+
|
+-------------+-----------------+-----------------------------------------+
|
||||||
| | csh/tcsh | $ source <venv>/bin/activate.csh |
|
| | csh/tcsh | $ source <venv>/bin/activate.csh |
|
||||||
+-------------+-----------------+-----------------------------------------+
|
+-------------+-----------------+-----------------------------------------+
|
||||||
|
|
|
@ -121,6 +121,11 @@ Added the *indent* option to :func:`~ast.dump` which allows it to produce a
|
||||||
multiline indented output.
|
multiline indented output.
|
||||||
(Contributed by Serhiy Storchaka in :issue:`37995`.)
|
(Contributed by Serhiy Storchaka in :issue:`37995`.)
|
||||||
|
|
||||||
|
Added :func:`ast.unparse` as a function in the :mod:`ast` module that can
|
||||||
|
be used to unparse an :class:`ast.AST` object and produce a string with code
|
||||||
|
that would produce an equivalent :class:`ast.AST` object when parsed.
|
||||||
|
(Contributed by Pablo Galindo and Batuhan Taskaya in :issue:`38870`.)
|
||||||
|
|
||||||
asyncio
|
asyncio
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
@ -179,8 +184,8 @@ case), and one used ``__VENV_NAME__`` instead.
|
||||||
pathlib
|
pathlib
|
||||||
-------
|
-------
|
||||||
|
|
||||||
Added :meth:`~pathlib.Path.readlink()` which acts similar to
|
Added :meth:`pathlib.Path.readlink()` which acts similarly to
|
||||||
:func:`~os.readlink`.
|
:func:`os.readlink`.
|
||||||
(Contributed by Girts Folkmanis in :issue:`30618`)
|
(Contributed by Girts Folkmanis in :issue:`30618`)
|
||||||
|
|
||||||
pprint
|
pprint
|
||||||
|
@ -235,6 +240,10 @@ Build and C API Changes
|
||||||
functions: the free lists of bound method objects have been removed.
|
functions: the free lists of bound method objects have been removed.
|
||||||
(Contributed by Inada Naoki and Victor Stinner in :issue:`37340`.)
|
(Contributed by Inada Naoki and Victor Stinner in :issue:`37340`.)
|
||||||
|
|
||||||
|
* Remove ``PyUnicode_ClearFreeList()`` function: the Unicode free list has been
|
||||||
|
removed in Python 3.3.
|
||||||
|
(Contributed by Victor Stinner in :issue:`38896`.)
|
||||||
|
|
||||||
|
|
||||||
Deprecated
|
Deprecated
|
||||||
==========
|
==========
|
||||||
|
@ -270,6 +279,11 @@ Deprecated
|
||||||
Removed
|
Removed
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
* :class:`array.array`: ``tostring()`` and ``fromstring()`` methods have been
|
||||||
|
removed. They were aliases to ``tobytes()`` and ``frombytes()``, deprecated
|
||||||
|
since Python 3.2.
|
||||||
|
(Contributed by Victor Stinner in :issue:`38916`.)
|
||||||
|
|
||||||
* The abstract base classes in :mod:`collections.abc` no longer are
|
* The abstract base classes in :mod:`collections.abc` no longer are
|
||||||
exposed in the regular :mod:`collections` module. This will help
|
exposed in the regular :mod:`collections` module. This will help
|
||||||
create a clearer distinction between the concrete classes and the abstract
|
create a clearer distinction between the concrete classes and the abstract
|
||||||
|
|
|
@ -147,7 +147,6 @@ struct _ts {
|
||||||
The caller must hold the GIL.*/
|
The caller must hold the GIL.*/
|
||||||
PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_Get(void);
|
PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_Get(void);
|
||||||
|
|
||||||
PyAPI_FUNC(int) _PyState_AddModule(PyObject*, struct PyModuleDef*);
|
|
||||||
PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *);
|
PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *);
|
||||||
|
|
||||||
/* Similar to PyThreadState_Get(), but don't issue a fatal error
|
/* Similar to PyThreadState_Get(), but don't issue a fatal error
|
||||||
|
|
|
@ -40,11 +40,9 @@ extern PyObject * _PyBuiltin_Init(PyThreadState *tstate);
|
||||||
extern PyStatus _PySys_Create(
|
extern PyStatus _PySys_Create(
|
||||||
PyThreadState *tstate,
|
PyThreadState *tstate,
|
||||||
PyObject **sysmod_p);
|
PyObject **sysmod_p);
|
||||||
extern PyStatus _PySys_SetPreliminaryStderr(PyObject *sysdict);
|
|
||||||
extern PyStatus _PySys_ReadPreinitWarnOptions(PyWideStringList *options);
|
extern PyStatus _PySys_ReadPreinitWarnOptions(PyWideStringList *options);
|
||||||
extern PyStatus _PySys_ReadPreinitXOptions(PyConfig *config);
|
extern PyStatus _PySys_ReadPreinitXOptions(PyConfig *config);
|
||||||
extern int _PySys_InitMain(PyThreadState *tstate);
|
extern int _PySys_InitMain(PyThreadState *tstate);
|
||||||
extern PyStatus _PyImport_Init(PyThreadState *tstate);
|
|
||||||
extern PyStatus _PyExc_Init(void);
|
extern PyStatus _PyExc_Init(void);
|
||||||
extern PyStatus _PyErr_Init(void);
|
extern PyStatus _PyErr_Init(void);
|
||||||
extern PyStatus _PyBuiltins_AddExceptions(PyObject * bltinmod);
|
extern PyStatus _PyBuiltins_AddExceptions(PyObject * bltinmod);
|
||||||
|
@ -77,7 +75,7 @@ extern void _PyImport_Fini2(void);
|
||||||
extern void _PyGC_Fini(PyThreadState *tstate);
|
extern void _PyGC_Fini(PyThreadState *tstate);
|
||||||
extern void _PyType_Fini(void);
|
extern void _PyType_Fini(void);
|
||||||
extern void _Py_HashRandomization_Fini(void);
|
extern void _Py_HashRandomization_Fini(void);
|
||||||
extern void _PyUnicode_Fini(void);
|
extern void _PyUnicode_Fini(PyThreadState *tstate);
|
||||||
extern void _PyLong_Fini(void);
|
extern void _PyLong_Fini(void);
|
||||||
extern void _PyFaulthandler_Fini(void);
|
extern void _PyFaulthandler_Fini(void);
|
||||||
extern void _PyHash_Fini(void);
|
extern void _PyHash_Fini(void);
|
||||||
|
|
|
@ -324,6 +324,12 @@ extern void _PyInterpreterState_ClearModules(PyInterpreterState *interp);
|
||||||
|
|
||||||
PyAPI_FUNC(void) _PyGILState_Reinit(_PyRuntimeState *runtime);
|
PyAPI_FUNC(void) _PyGILState_Reinit(_PyRuntimeState *runtime);
|
||||||
|
|
||||||
|
|
||||||
|
PyAPI_FUNC(int) _PyState_AddModule(
|
||||||
|
PyThreadState *tstate,
|
||||||
|
PyObject* module,
|
||||||
|
struct PyModuleDef* def);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,10 +30,11 @@ extern "C" {
|
||||||
#define BINARY_TRUE_DIVIDE 27
|
#define BINARY_TRUE_DIVIDE 27
|
||||||
#define INPLACE_FLOOR_DIVIDE 28
|
#define INPLACE_FLOOR_DIVIDE 28
|
||||||
#define INPLACE_TRUE_DIVIDE 29
|
#define INPLACE_TRUE_DIVIDE 29
|
||||||
|
#define RERAISE 48
|
||||||
|
#define WITH_EXCEPT_START 49
|
||||||
#define GET_AITER 50
|
#define GET_AITER 50
|
||||||
#define GET_ANEXT 51
|
#define GET_ANEXT 51
|
||||||
#define BEFORE_ASYNC_WITH 52
|
#define BEFORE_ASYNC_WITH 52
|
||||||
#define BEGIN_FINALLY 53
|
|
||||||
#define END_ASYNC_FOR 54
|
#define END_ASYNC_FOR 54
|
||||||
#define INPLACE_ADD 55
|
#define INPLACE_ADD 55
|
||||||
#define INPLACE_SUBTRACT 56
|
#define INPLACE_SUBTRACT 56
|
||||||
|
@ -59,14 +60,11 @@ extern "C" {
|
||||||
#define INPLACE_AND 77
|
#define INPLACE_AND 77
|
||||||
#define INPLACE_XOR 78
|
#define INPLACE_XOR 78
|
||||||
#define INPLACE_OR 79
|
#define INPLACE_OR 79
|
||||||
#define WITH_CLEANUP_START 81
|
|
||||||
#define WITH_CLEANUP_FINISH 82
|
|
||||||
#define RETURN_VALUE 83
|
#define RETURN_VALUE 83
|
||||||
#define IMPORT_STAR 84
|
#define IMPORT_STAR 84
|
||||||
#define SETUP_ANNOTATIONS 85
|
#define SETUP_ANNOTATIONS 85
|
||||||
#define YIELD_VALUE 86
|
#define YIELD_VALUE 86
|
||||||
#define POP_BLOCK 87
|
#define POP_BLOCK 87
|
||||||
#define END_FINALLY 88
|
|
||||||
#define POP_EXCEPT 89
|
#define POP_EXCEPT 89
|
||||||
#define HAVE_ARGUMENT 90
|
#define HAVE_ARGUMENT 90
|
||||||
#define STORE_NAME 90
|
#define STORE_NAME 90
|
||||||
|
@ -127,8 +125,6 @@ extern "C" {
|
||||||
#define BUILD_TUPLE_UNPACK_WITH_CALL 158
|
#define BUILD_TUPLE_UNPACK_WITH_CALL 158
|
||||||
#define LOAD_METHOD 160
|
#define LOAD_METHOD 160
|
||||||
#define CALL_METHOD 161
|
#define CALL_METHOD 161
|
||||||
#define CALL_FINALLY 162
|
|
||||||
#define POP_FINALLY 163
|
|
||||||
|
|
||||||
/* EXCEPT_HANDLER is a special, implicit block type which is created when
|
/* EXCEPT_HANDLER is a special, implicit block type which is created when
|
||||||
entering an except handler. It is not an opcode but we define it here
|
entering an except handler. It is not an opcode but we define it here
|
||||||
|
|
|
@ -51,16 +51,16 @@ PyAPI_FUNC(int) PyThread_acquire_lock(PyThread_type_lock, int);
|
||||||
#if defined(_POSIX_THREADS)
|
#if defined(_POSIX_THREADS)
|
||||||
/* PyThread_acquire_lock_timed() uses _PyTime_FromNanoseconds(us * 1000),
|
/* PyThread_acquire_lock_timed() uses _PyTime_FromNanoseconds(us * 1000),
|
||||||
convert microseconds to nanoseconds. */
|
convert microseconds to nanoseconds. */
|
||||||
# define PY_TIMEOUT_MAX (PY_LLONG_MAX / 1000)
|
# define PY_TIMEOUT_MAX (LLONG_MAX / 1000)
|
||||||
#elif defined (NT_THREADS)
|
#elif defined (NT_THREADS)
|
||||||
/* In the NT API, the timeout is a DWORD and is expressed in milliseconds */
|
/* In the NT API, the timeout is a DWORD and is expressed in milliseconds */
|
||||||
# if 0xFFFFFFFFLL * 1000 < PY_LLONG_MAX
|
# if 0xFFFFFFFFLL * 1000 < LLONG_MAX
|
||||||
# define PY_TIMEOUT_MAX (0xFFFFFFFFLL * 1000)
|
# define PY_TIMEOUT_MAX (0xFFFFFFFFLL * 1000)
|
||||||
# else
|
# else
|
||||||
# define PY_TIMEOUT_MAX PY_LLONG_MAX
|
# define PY_TIMEOUT_MAX LLONG_MAX
|
||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
# define PY_TIMEOUT_MAX PY_LLONG_MAX
|
# define PY_TIMEOUT_MAX LLONG_MAX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -328,17 +328,6 @@ PyAPI_FUNC(wchar_t*) PyUnicode_AsWideCharString(
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject*) PyUnicode_FromOrdinal(int ordinal);
|
PyAPI_FUNC(PyObject*) PyUnicode_FromOrdinal(int ordinal);
|
||||||
|
|
||||||
/* --- Free-list management ----------------------------------------------- */
|
|
||||||
|
|
||||||
/* Clear the free list used by the Unicode implementation.
|
|
||||||
|
|
||||||
This can be used to release memory used for objects on the free
|
|
||||||
list back to the Python memory allocator.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
PyAPI_FUNC(int) PyUnicode_ClearFreeList(void);
|
|
||||||
|
|
||||||
/* === Builtin Codecs =====================================================
|
/* === Builtin Codecs =====================================================
|
||||||
|
|
||||||
Many of these APIs take two arguments encoding and errors. These
|
Many of these APIs take two arguments encoding and errors. These
|
||||||
|
|
|
@ -87,7 +87,6 @@ __all__ = [
|
||||||
|
|
||||||
import os as _os
|
import os as _os
|
||||||
import re as _re
|
import re as _re
|
||||||
import shutil as _shutil
|
|
||||||
import sys as _sys
|
import sys as _sys
|
||||||
|
|
||||||
from gettext import gettext as _, ngettext
|
from gettext import gettext as _, ngettext
|
||||||
|
@ -167,7 +166,8 @@ class HelpFormatter(object):
|
||||||
|
|
||||||
# default setting for width
|
# default setting for width
|
||||||
if width is None:
|
if width is None:
|
||||||
width = _shutil.get_terminal_size().columns
|
import shutil
|
||||||
|
width = shutil.get_terminal_size().columns
|
||||||
width -= 2
|
width -= 2
|
||||||
|
|
||||||
self._prog = prog
|
self._prog = prog
|
||||||
|
@ -264,7 +264,7 @@ class HelpFormatter(object):
|
||||||
invocations.append(get_invocation(subaction))
|
invocations.append(get_invocation(subaction))
|
||||||
|
|
||||||
# update the maximum item length
|
# update the maximum item length
|
||||||
invocation_length = max([len(s) for s in invocations])
|
invocation_length = max(map(len, invocations))
|
||||||
action_length = invocation_length + self._current_indent
|
action_length = invocation_length + self._current_indent
|
||||||
self._action_max_length = max(self._action_max_length,
|
self._action_max_length = max(self._action_max_length,
|
||||||
action_length)
|
action_length)
|
||||||
|
|
699
Lib/ast.py
699
Lib/ast.py
|
@ -24,6 +24,7 @@
|
||||||
:copyright: Copyright 2008 by Armin Ronacher.
|
:copyright: Copyright 2008 by Armin Ronacher.
|
||||||
:license: Python License.
|
:license: Python License.
|
||||||
"""
|
"""
|
||||||
|
import sys
|
||||||
from _ast import *
|
from _ast import *
|
||||||
|
|
||||||
|
|
||||||
|
@ -551,6 +552,704 @@ _const_node_type_names = {
|
||||||
type(...): 'Ellipsis',
|
type(...): 'Ellipsis',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Large float and imaginary literals get turned into infinities in the AST.
|
||||||
|
# We unparse those infinities to INFSTR.
|
||||||
|
_INFSTR = "1e" + repr(sys.float_info.max_10_exp + 1)
|
||||||
|
|
||||||
|
class _Unparser(NodeVisitor):
|
||||||
|
"""Methods in this class recursively traverse an AST and
|
||||||
|
output source code for the abstract syntax; original formatting
|
||||||
|
is disregarded."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._source = []
|
||||||
|
self._buffer = []
|
||||||
|
self._indent = 0
|
||||||
|
|
||||||
|
def interleave(self, inter, f, seq):
|
||||||
|
"""Call f on each item in seq, calling inter() in between."""
|
||||||
|
seq = iter(seq)
|
||||||
|
try:
|
||||||
|
f(next(seq))
|
||||||
|
except StopIteration:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
for x in seq:
|
||||||
|
inter()
|
||||||
|
f(x)
|
||||||
|
|
||||||
|
def fill(self, text=""):
|
||||||
|
"""Indent a piece of text and append it, according to the current
|
||||||
|
indentation level"""
|
||||||
|
self.write("\n" + " " * self._indent + text)
|
||||||
|
|
||||||
|
def write(self, text):
|
||||||
|
"""Append a piece of text"""
|
||||||
|
self._source.append(text)
|
||||||
|
|
||||||
|
def buffer_writer(self, text):
|
||||||
|
self._buffer.append(text)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def buffer(self):
|
||||||
|
value = "".join(self._buffer)
|
||||||
|
self._buffer.clear()
|
||||||
|
return value
|
||||||
|
|
||||||
|
class _Block:
|
||||||
|
"""A context manager for preparing the source for blocks. It adds
|
||||||
|
the character':', increases the indentation on enter and decreases
|
||||||
|
the indentation on exit."""
|
||||||
|
def __init__(self, unparser):
|
||||||
|
self.unparser = unparser
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self.unparser.write(":")
|
||||||
|
self.unparser._indent += 1
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_value, traceback):
|
||||||
|
self.unparser._indent -= 1
|
||||||
|
|
||||||
|
def block(self):
|
||||||
|
return self._Block(self)
|
||||||
|
|
||||||
|
def traverse(self, node):
|
||||||
|
if isinstance(node, list):
|
||||||
|
for item in node:
|
||||||
|
self.traverse(item)
|
||||||
|
else:
|
||||||
|
super().visit(node)
|
||||||
|
|
||||||
|
def visit(self, node):
|
||||||
|
"""Outputs a source code string that, if converted back to an ast
|
||||||
|
(using ast.parse) will generate an AST equivalent to *node*"""
|
||||||
|
self._source = []
|
||||||
|
self.traverse(node)
|
||||||
|
return "".join(self._source)
|
||||||
|
|
||||||
|
def visit_Module(self, node):
|
||||||
|
for subnode in node.body:
|
||||||
|
self.traverse(subnode)
|
||||||
|
|
||||||
|
def visit_Expr(self, node):
|
||||||
|
self.fill()
|
||||||
|
self.traverse(node.value)
|
||||||
|
|
||||||
|
def visit_NamedExpr(self, node):
|
||||||
|
self.write("(")
|
||||||
|
self.traverse(node.target)
|
||||||
|
self.write(" := ")
|
||||||
|
self.traverse(node.value)
|
||||||
|
self.write(")")
|
||||||
|
|
||||||
|
def visit_Import(self, node):
|
||||||
|
self.fill("import ")
|
||||||
|
self.interleave(lambda: self.write(", "), self.traverse, node.names)
|
||||||
|
|
||||||
|
def visit_ImportFrom(self, node):
|
||||||
|
self.fill("from ")
|
||||||
|
self.write("." * node.level)
|
||||||
|
if node.module:
|
||||||
|
self.write(node.module)
|
||||||
|
self.write(" import ")
|
||||||
|
self.interleave(lambda: self.write(", "), self.traverse, node.names)
|
||||||
|
|
||||||
|
def visit_Assign(self, node):
|
||||||
|
self.fill()
|
||||||
|
for target in node.targets:
|
||||||
|
self.traverse(target)
|
||||||
|
self.write(" = ")
|
||||||
|
self.traverse(node.value)
|
||||||
|
|
||||||
|
def visit_AugAssign(self, node):
|
||||||
|
self.fill()
|
||||||
|
self.traverse(node.target)
|
||||||
|
self.write(" " + self.binop[node.op.__class__.__name__] + "= ")
|
||||||
|
self.traverse(node.value)
|
||||||
|
|
||||||
|
def visit_AnnAssign(self, node):
|
||||||
|
self.fill()
|
||||||
|
if not node.simple and isinstance(node.target, Name):
|
||||||
|
self.write("(")
|
||||||
|
self.traverse(node.target)
|
||||||
|
if not node.simple and isinstance(node.target, Name):
|
||||||
|
self.write(")")
|
||||||
|
self.write(": ")
|
||||||
|
self.traverse(node.annotation)
|
||||||
|
if node.value:
|
||||||
|
self.write(" = ")
|
||||||
|
self.traverse(node.value)
|
||||||
|
|
||||||
|
def visit_Return(self, node):
|
||||||
|
self.fill("return")
|
||||||
|
if node.value:
|
||||||
|
self.write(" ")
|
||||||
|
self.traverse(node.value)
|
||||||
|
|
||||||
|
def visit_Pass(self, node):
|
||||||
|
self.fill("pass")
|
||||||
|
|
||||||
|
def visit_Break(self, node):
|
||||||
|
self.fill("break")
|
||||||
|
|
||||||
|
def visit_Continue(self, node):
|
||||||
|
self.fill("continue")
|
||||||
|
|
||||||
|
def visit_Delete(self, node):
|
||||||
|
self.fill("del ")
|
||||||
|
self.interleave(lambda: self.write(", "), self.traverse, node.targets)
|
||||||
|
|
||||||
|
def visit_Assert(self, node):
|
||||||
|
self.fill("assert ")
|
||||||
|
self.traverse(node.test)
|
||||||
|
if node.msg:
|
||||||
|
self.write(", ")
|
||||||
|
self.traverse(node.msg)
|
||||||
|
|
||||||
|
def visit_Global(self, node):
|
||||||
|
self.fill("global ")
|
||||||
|
self.interleave(lambda: self.write(", "), self.write, node.names)
|
||||||
|
|
||||||
|
def visit_Nonlocal(self, node):
|
||||||
|
self.fill("nonlocal ")
|
||||||
|
self.interleave(lambda: self.write(", "), self.write, node.names)
|
||||||
|
|
||||||
|
def visit_Await(self, node):
|
||||||
|
self.write("(")
|
||||||
|
self.write("await")
|
||||||
|
if node.value:
|
||||||
|
self.write(" ")
|
||||||
|
self.traverse(node.value)
|
||||||
|
self.write(")")
|
||||||
|
|
||||||
|
def visit_Yield(self, node):
|
||||||
|
self.write("(")
|
||||||
|
self.write("yield")
|
||||||
|
if node.value:
|
||||||
|
self.write(" ")
|
||||||
|
self.traverse(node.value)
|
||||||
|
self.write(")")
|
||||||
|
|
||||||
|
def visit_YieldFrom(self, node):
|
||||||
|
self.write("(")
|
||||||
|
self.write("yield from")
|
||||||
|
if node.value:
|
||||||
|
self.write(" ")
|
||||||
|
self.traverse(node.value)
|
||||||
|
self.write(")")
|
||||||
|
|
||||||
|
def visit_Raise(self, node):
|
||||||
|
self.fill("raise")
|
||||||
|
if not node.exc:
|
||||||
|
if node.cause:
|
||||||
|
raise ValueError(f"Node can't use cause without an exception.")
|
||||||
|
return
|
||||||
|
self.write(" ")
|
||||||
|
self.traverse(node.exc)
|
||||||
|
if node.cause:
|
||||||
|
self.write(" from ")
|
||||||
|
self.traverse(node.cause)
|
||||||
|
|
||||||
|
def visit_Try(self, node):
|
||||||
|
self.fill("try")
|
||||||
|
with self.block():
|
||||||
|
self.traverse(node.body)
|
||||||
|
for ex in node.handlers:
|
||||||
|
self.traverse(ex)
|
||||||
|
if node.orelse:
|
||||||
|
self.fill("else")
|
||||||
|
with self.block():
|
||||||
|
self.traverse(node.orelse)
|
||||||
|
if node.finalbody:
|
||||||
|
self.fill("finally")
|
||||||
|
with self.block():
|
||||||
|
self.traverse(node.finalbody)
|
||||||
|
|
||||||
|
def visit_ExceptHandler(self, node):
|
||||||
|
self.fill("except")
|
||||||
|
if node.type:
|
||||||
|
self.write(" ")
|
||||||
|
self.traverse(node.type)
|
||||||
|
if node.name:
|
||||||
|
self.write(" as ")
|
||||||
|
self.write(node.name)
|
||||||
|
with self.block():
|
||||||
|
self.traverse(node.body)
|
||||||
|
|
||||||
|
def visit_ClassDef(self, node):
|
||||||
|
self.write("\n")
|
||||||
|
for deco in node.decorator_list:
|
||||||
|
self.fill("@")
|
||||||
|
self.traverse(deco)
|
||||||
|
self.fill("class " + node.name)
|
||||||
|
self.write("(")
|
||||||
|
comma = False
|
||||||
|
for e in node.bases:
|
||||||
|
if comma:
|
||||||
|
self.write(", ")
|
||||||
|
else:
|
||||||
|
comma = True
|
||||||
|
self.traverse(e)
|
||||||
|
for e in node.keywords:
|
||||||
|
if comma:
|
||||||
|
self.write(", ")
|
||||||
|
else:
|
||||||
|
comma = True
|
||||||
|
self.traverse(e)
|
||||||
|
self.write(")")
|
||||||
|
|
||||||
|
with self.block():
|
||||||
|
self.traverse(node.body)
|
||||||
|
|
||||||
|
def visit_FunctionDef(self, node):
|
||||||
|
self.__FunctionDef_helper(node, "def")
|
||||||
|
|
||||||
|
def visit_AsyncFunctionDef(self, node):
|
||||||
|
self.__FunctionDef_helper(node, "async def")
|
||||||
|
|
||||||
|
def __FunctionDef_helper(self, node, fill_suffix):
|
||||||
|
self.write("\n")
|
||||||
|
for deco in node.decorator_list:
|
||||||
|
self.fill("@")
|
||||||
|
self.traverse(deco)
|
||||||
|
def_str = fill_suffix + " " + node.name + "("
|
||||||
|
self.fill(def_str)
|
||||||
|
self.traverse(node.args)
|
||||||
|
self.write(")")
|
||||||
|
if node.returns:
|
||||||
|
self.write(" -> ")
|
||||||
|
self.traverse(node.returns)
|
||||||
|
with self.block():
|
||||||
|
self.traverse(node.body)
|
||||||
|
|
||||||
|
def visit_For(self, node):
|
||||||
|
self.__For_helper("for ", node)
|
||||||
|
|
||||||
|
def visit_AsyncFor(self, node):
|
||||||
|
self.__For_helper("async for ", node)
|
||||||
|
|
||||||
|
def __For_helper(self, fill, node):
|
||||||
|
self.fill(fill)
|
||||||
|
self.traverse(node.target)
|
||||||
|
self.write(" in ")
|
||||||
|
self.traverse(node.iter)
|
||||||
|
with self.block():
|
||||||
|
self.traverse(node.body)
|
||||||
|
if node.orelse:
|
||||||
|
self.fill("else")
|
||||||
|
with self.block():
|
||||||
|
self.traverse(node.orelse)
|
||||||
|
|
||||||
|
def visit_If(self, node):
|
||||||
|
self.fill("if ")
|
||||||
|
self.traverse(node.test)
|
||||||
|
with self.block():
|
||||||
|
self.traverse(node.body)
|
||||||
|
# collapse nested ifs into equivalent elifs.
|
||||||
|
while node.orelse and len(node.orelse) == 1 and isinstance(node.orelse[0], If):
|
||||||
|
node = node.orelse[0]
|
||||||
|
self.fill("elif ")
|
||||||
|
self.traverse(node.test)
|
||||||
|
with self.block():
|
||||||
|
self.traverse(node.body)
|
||||||
|
# final else
|
||||||
|
if node.orelse:
|
||||||
|
self.fill("else")
|
||||||
|
with self.block():
|
||||||
|
self.traverse(node.orelse)
|
||||||
|
|
||||||
|
def visit_While(self, node):
|
||||||
|
self.fill("while ")
|
||||||
|
self.traverse(node.test)
|
||||||
|
with self.block():
|
||||||
|
self.traverse(node.body)
|
||||||
|
if node.orelse:
|
||||||
|
self.fill("else")
|
||||||
|
with self.block():
|
||||||
|
self.traverse(node.orelse)
|
||||||
|
|
||||||
|
def visit_With(self, node):
|
||||||
|
self.fill("with ")
|
||||||
|
self.interleave(lambda: self.write(", "), self.traverse, node.items)
|
||||||
|
with self.block():
|
||||||
|
self.traverse(node.body)
|
||||||
|
|
||||||
|
def visit_AsyncWith(self, node):
|
||||||
|
self.fill("async with ")
|
||||||
|
self.interleave(lambda: self.write(", "), self.traverse, node.items)
|
||||||
|
with self.block():
|
||||||
|
self.traverse(node.body)
|
||||||
|
|
||||||
|
def visit_JoinedStr(self, node):
|
||||||
|
self.write("f")
|
||||||
|
self._fstring_JoinedStr(node, self.buffer_writer)
|
||||||
|
self.write(repr(self.buffer))
|
||||||
|
|
||||||
|
def visit_FormattedValue(self, node):
|
||||||
|
self.write("f")
|
||||||
|
self._fstring_FormattedValue(node, self.buffer_writer)
|
||||||
|
self.write(repr(self.buffer))
|
||||||
|
|
||||||
|
def _fstring_JoinedStr(self, node, write):
|
||||||
|
for value in node.values:
|
||||||
|
meth = getattr(self, "_fstring_" + type(value).__name__)
|
||||||
|
meth(value, write)
|
||||||
|
|
||||||
|
def _fstring_Constant(self, node, write):
|
||||||
|
if not isinstance(node.value, str):
|
||||||
|
raise ValueError("Constants inside JoinedStr should be a string.")
|
||||||
|
value = node.value.replace("{", "{{").replace("}", "}}")
|
||||||
|
write(value)
|
||||||
|
|
||||||
|
def _fstring_FormattedValue(self, node, write):
|
||||||
|
write("{")
|
||||||
|
expr = type(self)().visit(node.value).rstrip("\n")
|
||||||
|
if expr.startswith("{"):
|
||||||
|
write(" ") # Separate pair of opening brackets as "{ {"
|
||||||
|
write(expr)
|
||||||
|
if node.conversion != -1:
|
||||||
|
conversion = chr(node.conversion)
|
||||||
|
if conversion not in "sra":
|
||||||
|
raise ValueError("Unknown f-string conversion.")
|
||||||
|
write(f"!{conversion}")
|
||||||
|
if node.format_spec:
|
||||||
|
write(":")
|
||||||
|
meth = getattr(self, "_fstring_" + type(node.format_spec).__name__)
|
||||||
|
meth(node.format_spec, write)
|
||||||
|
write("}")
|
||||||
|
|
||||||
|
def visit_Name(self, node):
|
||||||
|
self.write(node.id)
|
||||||
|
|
||||||
|
def _write_constant(self, value):
|
||||||
|
if isinstance(value, (float, complex)):
|
||||||
|
# Substitute overflowing decimal literal for AST infinities.
|
||||||
|
self.write(repr(value).replace("inf", _INFSTR))
|
||||||
|
else:
|
||||||
|
self.write(repr(value))
|
||||||
|
|
||||||
|
def visit_Constant(self, node):
|
||||||
|
value = node.value
|
||||||
|
if isinstance(value, tuple):
|
||||||
|
self.write("(")
|
||||||
|
if len(value) == 1:
|
||||||
|
self._write_constant(value[0])
|
||||||
|
self.write(",")
|
||||||
|
else:
|
||||||
|
self.interleave(lambda: self.write(", "), self._write_constant, value)
|
||||||
|
self.write(")")
|
||||||
|
elif value is ...:
|
||||||
|
self.write("...")
|
||||||
|
else:
|
||||||
|
if node.kind == "u":
|
||||||
|
self.write("u")
|
||||||
|
self._write_constant(node.value)
|
||||||
|
|
||||||
|
def visit_List(self, node):
|
||||||
|
self.write("[")
|
||||||
|
self.interleave(lambda: self.write(", "), self.traverse, node.elts)
|
||||||
|
self.write("]")
|
||||||
|
|
||||||
|
def visit_ListComp(self, node):
|
||||||
|
self.write("[")
|
||||||
|
self.traverse(node.elt)
|
||||||
|
for gen in node.generators:
|
||||||
|
self.traverse(gen)
|
||||||
|
self.write("]")
|
||||||
|
|
||||||
|
def visit_GeneratorExp(self, node):
|
||||||
|
self.write("(")
|
||||||
|
self.traverse(node.elt)
|
||||||
|
for gen in node.generators:
|
||||||
|
self.traverse(gen)
|
||||||
|
self.write(")")
|
||||||
|
|
||||||
|
def visit_SetComp(self, node):
|
||||||
|
self.write("{")
|
||||||
|
self.traverse(node.elt)
|
||||||
|
for gen in node.generators:
|
||||||
|
self.traverse(gen)
|
||||||
|
self.write("}")
|
||||||
|
|
||||||
|
def visit_DictComp(self, node):
|
||||||
|
self.write("{")
|
||||||
|
self.traverse(node.key)
|
||||||
|
self.write(": ")
|
||||||
|
self.traverse(node.value)
|
||||||
|
for gen in node.generators:
|
||||||
|
self.traverse(gen)
|
||||||
|
self.write("}")
|
||||||
|
|
||||||
|
def visit_comprehension(self, node):
|
||||||
|
if node.is_async:
|
||||||
|
self.write(" async for ")
|
||||||
|
else:
|
||||||
|
self.write(" for ")
|
||||||
|
self.traverse(node.target)
|
||||||
|
self.write(" in ")
|
||||||
|
self.traverse(node.iter)
|
||||||
|
for if_clause in node.ifs:
|
||||||
|
self.write(" if ")
|
||||||
|
self.traverse(if_clause)
|
||||||
|
|
||||||
|
def visit_IfExp(self, node):
|
||||||
|
self.write("(")
|
||||||
|
self.traverse(node.body)
|
||||||
|
self.write(" if ")
|
||||||
|
self.traverse(node.test)
|
||||||
|
self.write(" else ")
|
||||||
|
self.traverse(node.orelse)
|
||||||
|
self.write(")")
|
||||||
|
|
||||||
|
def visit_Set(self, node):
|
||||||
|
if not node.elts:
|
||||||
|
raise ValueError("Set node should has at least one item")
|
||||||
|
self.write("{")
|
||||||
|
self.interleave(lambda: self.write(", "), self.traverse, node.elts)
|
||||||
|
self.write("}")
|
||||||
|
|
||||||
|
def visit_Dict(self, node):
|
||||||
|
self.write("{")
|
||||||
|
|
||||||
|
def write_key_value_pair(k, v):
|
||||||
|
self.traverse(k)
|
||||||
|
self.write(": ")
|
||||||
|
self.traverse(v)
|
||||||
|
|
||||||
|
def write_item(item):
|
||||||
|
k, v = item
|
||||||
|
if k is None:
|
||||||
|
# for dictionary unpacking operator in dicts {**{'y': 2}}
|
||||||
|
# see PEP 448 for details
|
||||||
|
self.write("**")
|
||||||
|
self.traverse(v)
|
||||||
|
else:
|
||||||
|
write_key_value_pair(k, v)
|
||||||
|
|
||||||
|
self.interleave(
|
||||||
|
lambda: self.write(", "), write_item, zip(node.keys, node.values)
|
||||||
|
)
|
||||||
|
self.write("}")
|
||||||
|
|
||||||
|
def visit_Tuple(self, node):
|
||||||
|
self.write("(")
|
||||||
|
if len(node.elts) == 1:
|
||||||
|
elt = node.elts[0]
|
||||||
|
self.traverse(elt)
|
||||||
|
self.write(",")
|
||||||
|
else:
|
||||||
|
self.interleave(lambda: self.write(", "), self.traverse, node.elts)
|
||||||
|
self.write(")")
|
||||||
|
|
||||||
|
unop = {"Invert": "~", "Not": "not", "UAdd": "+", "USub": "-"}
|
||||||
|
|
||||||
|
def visit_UnaryOp(self, node):
|
||||||
|
self.write("(")
|
||||||
|
self.write(self.unop[node.op.__class__.__name__])
|
||||||
|
self.write(" ")
|
||||||
|
self.traverse(node.operand)
|
||||||
|
self.write(")")
|
||||||
|
|
||||||
|
binop = {
|
||||||
|
"Add": "+",
|
||||||
|
"Sub": "-",
|
||||||
|
"Mult": "*",
|
||||||
|
"MatMult": "@",
|
||||||
|
"Div": "/",
|
||||||
|
"Mod": "%",
|
||||||
|
"LShift": "<<",
|
||||||
|
"RShift": ">>",
|
||||||
|
"BitOr": "|",
|
||||||
|
"BitXor": "^",
|
||||||
|
"BitAnd": "&",
|
||||||
|
"FloorDiv": "//",
|
||||||
|
"Pow": "**",
|
||||||
|
}
|
||||||
|
|
||||||
|
def visit_BinOp(self, node):
|
||||||
|
self.write("(")
|
||||||
|
self.traverse(node.left)
|
||||||
|
self.write(" " + self.binop[node.op.__class__.__name__] + " ")
|
||||||
|
self.traverse(node.right)
|
||||||
|
self.write(")")
|
||||||
|
|
||||||
|
cmpops = {
|
||||||
|
"Eq": "==",
|
||||||
|
"NotEq": "!=",
|
||||||
|
"Lt": "<",
|
||||||
|
"LtE": "<=",
|
||||||
|
"Gt": ">",
|
||||||
|
"GtE": ">=",
|
||||||
|
"Is": "is",
|
||||||
|
"IsNot": "is not",
|
||||||
|
"In": "in",
|
||||||
|
"NotIn": "not in",
|
||||||
|
}
|
||||||
|
|
||||||
|
def visit_Compare(self, node):
|
||||||
|
self.write("(")
|
||||||
|
self.traverse(node.left)
|
||||||
|
for o, e in zip(node.ops, node.comparators):
|
||||||
|
self.write(" " + self.cmpops[o.__class__.__name__] + " ")
|
||||||
|
self.traverse(e)
|
||||||
|
self.write(")")
|
||||||
|
|
||||||
|
boolops = {And: "and", Or: "or"}
|
||||||
|
|
||||||
|
def visit_BoolOp(self, node):
|
||||||
|
self.write("(")
|
||||||
|
s = " %s " % self.boolops[node.op.__class__]
|
||||||
|
self.interleave(lambda: self.write(s), self.traverse, node.values)
|
||||||
|
self.write(")")
|
||||||
|
|
||||||
|
def visit_Attribute(self, node):
|
||||||
|
self.traverse(node.value)
|
||||||
|
# Special case: 3.__abs__() is a syntax error, so if node.value
|
||||||
|
# is an integer literal then we need to either parenthesize
|
||||||
|
# it or add an extra space to get 3 .__abs__().
|
||||||
|
if isinstance(node.value, Constant) and isinstance(node.value.value, int):
|
||||||
|
self.write(" ")
|
||||||
|
self.write(".")
|
||||||
|
self.write(node.attr)
|
||||||
|
|
||||||
|
def visit_Call(self, node):
|
||||||
|
self.traverse(node.func)
|
||||||
|
self.write("(")
|
||||||
|
comma = False
|
||||||
|
for e in node.args:
|
||||||
|
if comma:
|
||||||
|
self.write(", ")
|
||||||
|
else:
|
||||||
|
comma = True
|
||||||
|
self.traverse(e)
|
||||||
|
for e in node.keywords:
|
||||||
|
if comma:
|
||||||
|
self.write(", ")
|
||||||
|
else:
|
||||||
|
comma = True
|
||||||
|
self.traverse(e)
|
||||||
|
self.write(")")
|
||||||
|
|
||||||
|
def visit_Subscript(self, node):
|
||||||
|
self.traverse(node.value)
|
||||||
|
self.write("[")
|
||||||
|
self.traverse(node.slice)
|
||||||
|
self.write("]")
|
||||||
|
|
||||||
|
def visit_Starred(self, node):
|
||||||
|
self.write("*")
|
||||||
|
self.traverse(node.value)
|
||||||
|
|
||||||
|
def visit_Ellipsis(self, node):
|
||||||
|
self.write("...")
|
||||||
|
|
||||||
|
def visit_Index(self, node):
|
||||||
|
self.traverse(node.value)
|
||||||
|
|
||||||
|
def visit_Slice(self, node):
|
||||||
|
if node.lower:
|
||||||
|
self.traverse(node.lower)
|
||||||
|
self.write(":")
|
||||||
|
if node.upper:
|
||||||
|
self.traverse(node.upper)
|
||||||
|
if node.step:
|
||||||
|
self.write(":")
|
||||||
|
self.traverse(node.step)
|
||||||
|
|
||||||
|
def visit_ExtSlice(self, node):
|
||||||
|
self.interleave(lambda: self.write(", "), self.traverse, node.dims)
|
||||||
|
|
||||||
|
def visit_arg(self, node):
|
||||||
|
self.write(node.arg)
|
||||||
|
if node.annotation:
|
||||||
|
self.write(": ")
|
||||||
|
self.traverse(node.annotation)
|
||||||
|
|
||||||
|
def visit_arguments(self, node):
|
||||||
|
first = True
|
||||||
|
# normal arguments
|
||||||
|
all_args = node.posonlyargs + node.args
|
||||||
|
defaults = [None] * (len(all_args) - len(node.defaults)) + node.defaults
|
||||||
|
for index, elements in enumerate(zip(all_args, defaults), 1):
|
||||||
|
a, d = elements
|
||||||
|
if first:
|
||||||
|
first = False
|
||||||
|
else:
|
||||||
|
self.write(", ")
|
||||||
|
self.traverse(a)
|
||||||
|
if d:
|
||||||
|
self.write("=")
|
||||||
|
self.traverse(d)
|
||||||
|
if index == len(node.posonlyargs):
|
||||||
|
self.write(", /")
|
||||||
|
|
||||||
|
# varargs, or bare '*' if no varargs but keyword-only arguments present
|
||||||
|
if node.vararg or node.kwonlyargs:
|
||||||
|
if first:
|
||||||
|
first = False
|
||||||
|
else:
|
||||||
|
self.write(", ")
|
||||||
|
self.write("*")
|
||||||
|
if node.vararg:
|
||||||
|
self.write(node.vararg.arg)
|
||||||
|
if node.vararg.annotation:
|
||||||
|
self.write(": ")
|
||||||
|
self.traverse(node.vararg.annotation)
|
||||||
|
|
||||||
|
# keyword-only arguments
|
||||||
|
if node.kwonlyargs:
|
||||||
|
for a, d in zip(node.kwonlyargs, node.kw_defaults):
|
||||||
|
if first:
|
||||||
|
first = False
|
||||||
|
else:
|
||||||
|
self.write(", ")
|
||||||
|
self.traverse(a),
|
||||||
|
if d:
|
||||||
|
self.write("=")
|
||||||
|
self.traverse(d)
|
||||||
|
|
||||||
|
# kwargs
|
||||||
|
if node.kwarg:
|
||||||
|
if first:
|
||||||
|
first = False
|
||||||
|
else:
|
||||||
|
self.write(", ")
|
||||||
|
self.write("**" + node.kwarg.arg)
|
||||||
|
if node.kwarg.annotation:
|
||||||
|
self.write(": ")
|
||||||
|
self.traverse(node.kwarg.annotation)
|
||||||
|
|
||||||
|
def visit_keyword(self, node):
|
||||||
|
if node.arg is None:
|
||||||
|
self.write("**")
|
||||||
|
else:
|
||||||
|
self.write(node.arg)
|
||||||
|
self.write("=")
|
||||||
|
self.traverse(node.value)
|
||||||
|
|
||||||
|
def visit_Lambda(self, node):
|
||||||
|
self.write("(")
|
||||||
|
self.write("lambda ")
|
||||||
|
self.traverse(node.args)
|
||||||
|
self.write(": ")
|
||||||
|
self.traverse(node.body)
|
||||||
|
self.write(")")
|
||||||
|
|
||||||
|
def visit_alias(self, node):
|
||||||
|
self.write(node.name)
|
||||||
|
if node.asname:
|
||||||
|
self.write(" as " + node.asname)
|
||||||
|
|
||||||
|
def visit_withitem(self, node):
|
||||||
|
self.traverse(node.context_expr)
|
||||||
|
if node.optional_vars:
|
||||||
|
self.write(" as ")
|
||||||
|
self.traverse(node.optional_vars)
|
||||||
|
|
||||||
|
def unparse(ast_obj):
|
||||||
|
unparser = _Unparser()
|
||||||
|
return unparser.visit(ast_obj)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
import argparse
|
import argparse
|
||||||
|
|
|
@ -66,6 +66,10 @@ _HAS_IPv6 = hasattr(socket, 'AF_INET6')
|
||||||
# Maximum timeout passed to select to avoid OS limitations
|
# Maximum timeout passed to select to avoid OS limitations
|
||||||
MAXIMUM_SELECT_TIMEOUT = 24 * 3600
|
MAXIMUM_SELECT_TIMEOUT = 24 * 3600
|
||||||
|
|
||||||
|
# Used for deprecation and removal of `loop.create_datagram_endpoint()`'s
|
||||||
|
# *reuse_address* parameter
|
||||||
|
_unset = object()
|
||||||
|
|
||||||
|
|
||||||
def _format_handle(handle):
|
def _format_handle(handle):
|
||||||
cb = handle._callback
|
cb = handle._callback
|
||||||
|
@ -1230,7 +1234,7 @@ class BaseEventLoop(events.AbstractEventLoop):
|
||||||
async def create_datagram_endpoint(self, protocol_factory,
|
async def create_datagram_endpoint(self, protocol_factory,
|
||||||
local_addr=None, remote_addr=None, *,
|
local_addr=None, remote_addr=None, *,
|
||||||
family=0, proto=0, flags=0,
|
family=0, proto=0, flags=0,
|
||||||
reuse_address=None, reuse_port=None,
|
reuse_address=_unset, reuse_port=None,
|
||||||
allow_broadcast=None, sock=None):
|
allow_broadcast=None, sock=None):
|
||||||
"""Create datagram connection."""
|
"""Create datagram connection."""
|
||||||
if sock is not None:
|
if sock is not None:
|
||||||
|
@ -1239,7 +1243,7 @@ class BaseEventLoop(events.AbstractEventLoop):
|
||||||
f'A UDP Socket was expected, got {sock!r}')
|
f'A UDP Socket was expected, got {sock!r}')
|
||||||
if (local_addr or remote_addr or
|
if (local_addr or remote_addr or
|
||||||
family or proto or flags or
|
family or proto or flags or
|
||||||
reuse_address or reuse_port or allow_broadcast):
|
reuse_port or allow_broadcast):
|
||||||
# show the problematic kwargs in exception msg
|
# show the problematic kwargs in exception msg
|
||||||
opts = dict(local_addr=local_addr, remote_addr=remote_addr,
|
opts = dict(local_addr=local_addr, remote_addr=remote_addr,
|
||||||
family=family, proto=proto, flags=flags,
|
family=family, proto=proto, flags=flags,
|
||||||
|
@ -1306,8 +1310,18 @@ class BaseEventLoop(events.AbstractEventLoop):
|
||||||
|
|
||||||
exceptions = []
|
exceptions = []
|
||||||
|
|
||||||
if reuse_address is None:
|
# bpo-37228
|
||||||
reuse_address = os.name == 'posix' and sys.platform != 'cygwin'
|
if reuse_address is not _unset:
|
||||||
|
if reuse_address:
|
||||||
|
raise ValueError("Passing `reuse_address=True` is no "
|
||||||
|
"longer supported, as the usage of "
|
||||||
|
"SO_REUSEPORT in UDP poses a significant "
|
||||||
|
"security concern.")
|
||||||
|
else:
|
||||||
|
warnings.warn("The *reuse_address* parameter has been "
|
||||||
|
"deprecated as of 3.5.10 and is scheduled "
|
||||||
|
"for removal in 3.11.", DeprecationWarning,
|
||||||
|
stacklevel=2)
|
||||||
|
|
||||||
for ((family, proto),
|
for ((family, proto),
|
||||||
(local_address, remote_address)) in addr_pairs_info:
|
(local_address, remote_address)) in addr_pairs_info:
|
||||||
|
@ -1316,9 +1330,6 @@ class BaseEventLoop(events.AbstractEventLoop):
|
||||||
try:
|
try:
|
||||||
sock = socket.socket(
|
sock = socket.socket(
|
||||||
family=family, type=socket.SOCK_DGRAM, proto=proto)
|
family=family, type=socket.SOCK_DGRAM, proto=proto)
|
||||||
if reuse_address:
|
|
||||||
sock.setsockopt(
|
|
||||||
socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
||||||
if reuse_port:
|
if reuse_port:
|
||||||
_set_reuseport(sock)
|
_set_reuseport(sock)
|
||||||
if allow_broadcast:
|
if allow_broadcast:
|
||||||
|
|
|
@ -636,7 +636,7 @@ class BaseDefaultEventLoopPolicy(AbstractEventLoopPolicy):
|
||||||
"""
|
"""
|
||||||
if (self._local._loop is None and
|
if (self._local._loop is None and
|
||||||
not self._local._set_called and
|
not self._local._set_called and
|
||||||
isinstance(threading.current_thread(), threading._MainThread)):
|
threading.current_thread() is threading.main_thread()):
|
||||||
self.set_event_loop(self.new_event_loop())
|
self.set_event_loop(self.new_event_loop())
|
||||||
|
|
||||||
if self._local._loop is None:
|
if self._local._loop is None:
|
||||||
|
|
|
@ -103,6 +103,9 @@ class Future:
|
||||||
context['source_traceback'] = self._source_traceback
|
context['source_traceback'] = self._source_traceback
|
||||||
self._loop.call_exception_handler(context)
|
self._loop.call_exception_handler(context)
|
||||||
|
|
||||||
|
def __class_getitem__(cls, type):
|
||||||
|
return cls
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _log_traceback(self):
|
def _log_traceback(self):
|
||||||
return self.__log_traceback
|
return self.__log_traceback
|
||||||
|
|
|
@ -76,6 +76,9 @@ class Queue:
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f'<{type(self).__name__} {self._format()}>'
|
return f'<{type(self).__name__} {self._format()}>'
|
||||||
|
|
||||||
|
def __class_getitem__(cls, type):
|
||||||
|
return cls
|
||||||
|
|
||||||
def _format(self):
|
def _format(self):
|
||||||
result = f'maxsize={self._maxsize!r}'
|
result = f'maxsize={self._maxsize!r}'
|
||||||
if getattr(self, '_queue', None):
|
if getattr(self, '_queue', None):
|
||||||
|
|
|
@ -40,6 +40,11 @@ def _test_selector_event(selector, fd, event):
|
||||||
return bool(key.events & event)
|
return bool(key.events & event)
|
||||||
|
|
||||||
|
|
||||||
|
def _check_ssl_socket(sock):
|
||||||
|
if ssl is not None and isinstance(sock, ssl.SSLSocket):
|
||||||
|
raise TypeError("Socket cannot be of type SSLSocket")
|
||||||
|
|
||||||
|
|
||||||
class BaseSelectorEventLoop(base_events.BaseEventLoop):
|
class BaseSelectorEventLoop(base_events.BaseEventLoop):
|
||||||
"""Selector event loop.
|
"""Selector event loop.
|
||||||
|
|
||||||
|
@ -348,6 +353,7 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop):
|
||||||
The maximum amount of data to be received at once is specified by
|
The maximum amount of data to be received at once is specified by
|
||||||
nbytes.
|
nbytes.
|
||||||
"""
|
"""
|
||||||
|
_check_ssl_socket(sock)
|
||||||
if self._debug and sock.gettimeout() != 0:
|
if self._debug and sock.gettimeout() != 0:
|
||||||
raise ValueError("the socket must be non-blocking")
|
raise ValueError("the socket must be non-blocking")
|
||||||
try:
|
try:
|
||||||
|
@ -386,6 +392,7 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop):
|
||||||
The received data is written into *buf* (a writable buffer).
|
The received data is written into *buf* (a writable buffer).
|
||||||
The return value is the number of bytes written.
|
The return value is the number of bytes written.
|
||||||
"""
|
"""
|
||||||
|
_check_ssl_socket(sock)
|
||||||
if self._debug and sock.gettimeout() != 0:
|
if self._debug and sock.gettimeout() != 0:
|
||||||
raise ValueError("the socket must be non-blocking")
|
raise ValueError("the socket must be non-blocking")
|
||||||
try:
|
try:
|
||||||
|
@ -425,6 +432,7 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop):
|
||||||
raised, and there is no way to determine how much data, if any, was
|
raised, and there is no way to determine how much data, if any, was
|
||||||
successfully processed by the receiving end of the connection.
|
successfully processed by the receiving end of the connection.
|
||||||
"""
|
"""
|
||||||
|
_check_ssl_socket(sock)
|
||||||
if self._debug and sock.gettimeout() != 0:
|
if self._debug and sock.gettimeout() != 0:
|
||||||
raise ValueError("the socket must be non-blocking")
|
raise ValueError("the socket must be non-blocking")
|
||||||
try:
|
try:
|
||||||
|
@ -472,6 +480,7 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop):
|
||||||
|
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
"""
|
"""
|
||||||
|
_check_ssl_socket(sock)
|
||||||
if self._debug and sock.gettimeout() != 0:
|
if self._debug and sock.gettimeout() != 0:
|
||||||
raise ValueError("the socket must be non-blocking")
|
raise ValueError("the socket must be non-blocking")
|
||||||
|
|
||||||
|
@ -533,6 +542,7 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop):
|
||||||
object usable to send and receive data on the connection, and address
|
object usable to send and receive data on the connection, and address
|
||||||
is the address bound to the socket on the other end of the connection.
|
is the address bound to the socket on the other end of the connection.
|
||||||
"""
|
"""
|
||||||
|
_check_ssl_socket(sock)
|
||||||
if self._debug and sock.gettimeout() != 0:
|
if self._debug and sock.gettimeout() != 0:
|
||||||
raise ValueError("the socket must be non-blocking")
|
raise ValueError("the socket must be non-blocking")
|
||||||
fut = self.create_future()
|
fut = self.create_future()
|
||||||
|
|
|
@ -214,8 +214,7 @@ class StreamReaderProtocol(FlowControlMixin, protocols.Protocol):
|
||||||
def __init__(self, stream_reader, client_connected_cb=None, loop=None):
|
def __init__(self, stream_reader, client_connected_cb=None, loop=None):
|
||||||
super().__init__(loop=loop)
|
super().__init__(loop=loop)
|
||||||
if stream_reader is not None:
|
if stream_reader is not None:
|
||||||
self._stream_reader_wr = weakref.ref(stream_reader,
|
self._stream_reader_wr = weakref.ref(stream_reader)
|
||||||
self._on_reader_gc)
|
|
||||||
self._source_traceback = stream_reader._source_traceback
|
self._source_traceback = stream_reader._source_traceback
|
||||||
else:
|
else:
|
||||||
self._stream_reader_wr = None
|
self._stream_reader_wr = None
|
||||||
|
@ -231,22 +230,6 @@ class StreamReaderProtocol(FlowControlMixin, protocols.Protocol):
|
||||||
self._over_ssl = False
|
self._over_ssl = False
|
||||||
self._closed = self._loop.create_future()
|
self._closed = self._loop.create_future()
|
||||||
|
|
||||||
def _on_reader_gc(self, wr):
|
|
||||||
transport = self._transport
|
|
||||||
if transport is not None:
|
|
||||||
# connection_made was called
|
|
||||||
context = {
|
|
||||||
'message': ('An open stream object is being garbage '
|
|
||||||
'collected; call "stream.close()" explicitly.')
|
|
||||||
}
|
|
||||||
if self._source_traceback:
|
|
||||||
context['source_traceback'] = self._source_traceback
|
|
||||||
self._loop.call_exception_handler(context)
|
|
||||||
transport.abort()
|
|
||||||
else:
|
|
||||||
self._reject_connection = True
|
|
||||||
self._stream_reader_wr = None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _stream_reader(self):
|
def _stream_reader(self):
|
||||||
if self._stream_reader_wr is None:
|
if self._stream_reader_wr is None:
|
||||||
|
|
|
@ -175,6 +175,9 @@ class Task(futures._PyFuture): # Inherit Python Task implementation
|
||||||
self._loop.call_exception_handler(context)
|
self._loop.call_exception_handler(context)
|
||||||
super().__del__()
|
super().__del__()
|
||||||
|
|
||||||
|
def __class_getitem__(cls, type):
|
||||||
|
return cls
|
||||||
|
|
||||||
def _repr_info(self):
|
def _repr_info(self):
|
||||||
return base_tasks._task_repr_info(self)
|
return base_tasks._task_repr_info(self)
|
||||||
|
|
||||||
|
|
|
@ -930,9 +930,20 @@ class PidfdChildWatcher(AbstractChildWatcher):
|
||||||
def _do_wait(self, pid):
|
def _do_wait(self, pid):
|
||||||
pidfd, callback, args = self._callbacks.pop(pid)
|
pidfd, callback, args = self._callbacks.pop(pid)
|
||||||
self._loop._remove_reader(pidfd)
|
self._loop._remove_reader(pidfd)
|
||||||
_, status = os.waitpid(pid, 0)
|
try:
|
||||||
|
_, status = os.waitpid(pid, 0)
|
||||||
|
except ChildProcessError:
|
||||||
|
# The child process is already reaped
|
||||||
|
# (may happen if waitpid() is called elsewhere).
|
||||||
|
returncode = 255
|
||||||
|
logger.warning(
|
||||||
|
"child process pid %d exit status already read: "
|
||||||
|
" will report returncode 255",
|
||||||
|
pid)
|
||||||
|
else:
|
||||||
|
returncode = _compute_returncode(status)
|
||||||
|
|
||||||
os.close(pidfd)
|
os.close(pidfd)
|
||||||
returncode = _compute_returncode(status)
|
|
||||||
callback(pid, returncode, *args)
|
callback(pid, returncode, *args)
|
||||||
|
|
||||||
def remove_child_handler(self, pid):
|
def remove_child_handler(self, pid):
|
||||||
|
@ -1406,8 +1417,7 @@ class _UnixDefaultEventLoopPolicy(events.BaseDefaultEventLoopPolicy):
|
||||||
with events._lock:
|
with events._lock:
|
||||||
if self._watcher is None: # pragma: no branch
|
if self._watcher is None: # pragma: no branch
|
||||||
self._watcher = ThreadedChildWatcher()
|
self._watcher = ThreadedChildWatcher()
|
||||||
if isinstance(threading.current_thread(),
|
if threading.current_thread() is threading.main_thread():
|
||||||
threading._MainThread):
|
|
||||||
self._watcher.attach_loop(self._local._loop)
|
self._watcher.attach_loop(self._local._loop)
|
||||||
|
|
||||||
def set_event_loop(self, loop):
|
def set_event_loop(self, loop):
|
||||||
|
@ -1421,7 +1431,7 @@ class _UnixDefaultEventLoopPolicy(events.BaseDefaultEventLoopPolicy):
|
||||||
super().set_event_loop(loop)
|
super().set_event_loop(loop)
|
||||||
|
|
||||||
if (self._watcher is not None and
|
if (self._watcher is not None and
|
||||||
isinstance(threading.current_thread(), threading._MainThread)):
|
threading.current_thread() is threading.main_thread()):
|
||||||
self._watcher.attach_loop(loop)
|
self._watcher.attach_loop(loop)
|
||||||
|
|
||||||
def get_child_watcher(self):
|
def get_child_watcher(self):
|
||||||
|
|
|
@ -93,10 +93,13 @@ def _maybe_compile(compiler, source, filename, symbol):
|
||||||
except SyntaxError as e:
|
except SyntaxError as e:
|
||||||
err2 = e
|
err2 = e
|
||||||
|
|
||||||
if code:
|
try:
|
||||||
return code
|
if code:
|
||||||
if not code1 and repr(err1) == repr(err2):
|
return code
|
||||||
raise err1
|
if not code1 and repr(err1) == repr(err2):
|
||||||
|
raise err1
|
||||||
|
finally:
|
||||||
|
err1 = err2 = None
|
||||||
|
|
||||||
def _compile(source, filename, symbol):
|
def _compile(source, filename, symbol):
|
||||||
return compile(source, filename, symbol, PyCF_DONT_IMPLY_DEDENT)
|
return compile(source, filename, symbol, PyCF_DONT_IMPLY_DEDENT)
|
||||||
|
|
|
@ -149,6 +149,8 @@ def framework_find(fn, executable_path=None, env=None):
|
||||||
return dyld_find(fn, executable_path=executable_path, env=env)
|
return dyld_find(fn, executable_path=executable_path, env=env)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise error
|
raise error
|
||||||
|
finally:
|
||||||
|
error = None
|
||||||
|
|
||||||
def test_dyld_find():
|
def test_dyld_find():
|
||||||
env = {}
|
env = {}
|
||||||
|
|
|
@ -378,23 +378,24 @@ def _create_fn(name, args, body, *, globals=None, locals=None,
|
||||||
# worries about external callers.
|
# worries about external callers.
|
||||||
if locals is None:
|
if locals is None:
|
||||||
locals = {}
|
locals = {}
|
||||||
# __builtins__ may be the "builtins" module or
|
if 'BUILTINS' not in locals:
|
||||||
# the value of its "__dict__",
|
locals['BUILTINS'] = builtins
|
||||||
# so make sure "__builtins__" is the module.
|
|
||||||
if globals is not None and '__builtins__' not in globals:
|
|
||||||
globals['__builtins__'] = builtins
|
|
||||||
return_annotation = ''
|
return_annotation = ''
|
||||||
if return_type is not MISSING:
|
if return_type is not MISSING:
|
||||||
locals['_return_type'] = return_type
|
locals['_return_type'] = return_type
|
||||||
return_annotation = '->_return_type'
|
return_annotation = '->_return_type'
|
||||||
args = ','.join(args)
|
args = ','.join(args)
|
||||||
body = '\n'.join(f' {b}' for b in body)
|
body = '\n'.join(f' {b}' for b in body)
|
||||||
|
|
||||||
# Compute the text of the entire function.
|
# Compute the text of the entire function.
|
||||||
txt = f'def {name}({args}){return_annotation}:\n{body}'
|
txt = f' def {name}({args}){return_annotation}:\n{body}'
|
||||||
|
|
||||||
exec(txt, globals, locals)
|
local_vars = ', '.join(locals.keys())
|
||||||
return locals[name]
|
txt = f"def __create_fn__({local_vars}):\n{txt}\n return {name}"
|
||||||
|
|
||||||
|
ns = {}
|
||||||
|
exec(txt, globals, ns)
|
||||||
|
return ns['__create_fn__'](**locals)
|
||||||
|
|
||||||
|
|
||||||
def _field_assign(frozen, name, value, self_name):
|
def _field_assign(frozen, name, value, self_name):
|
||||||
|
@ -405,7 +406,7 @@ def _field_assign(frozen, name, value, self_name):
|
||||||
# self_name is what "self" is called in this function: don't
|
# self_name is what "self" is called in this function: don't
|
||||||
# hard-code "self", since that might be a field name.
|
# hard-code "self", since that might be a field name.
|
||||||
if frozen:
|
if frozen:
|
||||||
return f'__builtins__.object.__setattr__({self_name},{name!r},{value})'
|
return f'BUILTINS.object.__setattr__({self_name},{name!r},{value})'
|
||||||
return f'{self_name}.{name}={value}'
|
return f'{self_name}.{name}={value}'
|
||||||
|
|
||||||
|
|
||||||
|
@ -482,15 +483,18 @@ def _init_param(f):
|
||||||
return f'{f.name}:_type_{f.name}{default}'
|
return f'{f.name}:_type_{f.name}{default}'
|
||||||
|
|
||||||
|
|
||||||
def _init_fn(fields, frozen, has_post_init, self_name):
|
def _init_fn(fields, frozen, has_post_init, self_name, globals):
|
||||||
# fields contains both real fields and InitVar pseudo-fields.
|
# fields contains both real fields and InitVar pseudo-fields.
|
||||||
|
|
||||||
globals = {'MISSING': MISSING,
|
locals = {f'_type_{f.name}': f.type for f in fields}
|
||||||
'_HAS_DEFAULT_FACTORY': _HAS_DEFAULT_FACTORY}
|
locals.update({
|
||||||
|
'MISSING': MISSING,
|
||||||
|
'_HAS_DEFAULT_FACTORY': _HAS_DEFAULT_FACTORY,
|
||||||
|
})
|
||||||
|
|
||||||
body_lines = []
|
body_lines = []
|
||||||
for f in fields:
|
for f in fields:
|
||||||
line = _field_init(f, frozen, globals, self_name)
|
line = _field_init(f, frozen, locals, self_name)
|
||||||
# line is None means that this field doesn't require
|
# line is None means that this field doesn't require
|
||||||
# initialization (it's a pseudo-field). Just skip it.
|
# initialization (it's a pseudo-field). Just skip it.
|
||||||
if line:
|
if line:
|
||||||
|
@ -520,7 +524,6 @@ def _init_fn(fields, frozen, has_post_init, self_name):
|
||||||
args.append("*")
|
args.append("*")
|
||||||
args.append(_init_param(f))
|
args.append(_init_param(f))
|
||||||
|
|
||||||
locals = {f'_type_{f.name}': f.type for f in fields}
|
|
||||||
return _create_fn('__init__',
|
return _create_fn('__init__',
|
||||||
args,
|
args,
|
||||||
body_lines,
|
body_lines,
|
||||||
|
@ -529,20 +532,19 @@ def _init_fn(fields, frozen, has_post_init, self_name):
|
||||||
return_type=None)
|
return_type=None)
|
||||||
|
|
||||||
|
|
||||||
def _repr_fn(fields):
|
def _repr_fn(fields, globals):
|
||||||
fn = _create_fn('__repr__',
|
fn = _create_fn('__repr__',
|
||||||
('self',),
|
('self',),
|
||||||
['return self.__class__.__qualname__ + f"(' +
|
['return self.__class__.__qualname__ + f"(' +
|
||||||
', '.join([f"{f.name}={{self.{f.name}!r}}"
|
', '.join([f"{f.name}={{self.{f.name}!r}}"
|
||||||
for f in fields]) +
|
for f in fields]) +
|
||||||
')"'])
|
')"'],
|
||||||
|
globals=globals)
|
||||||
return _recursive_repr(fn)
|
return _recursive_repr(fn)
|
||||||
|
|
||||||
|
|
||||||
def _frozen_get_del_attr(cls, fields):
|
def _frozen_get_del_attr(cls, fields, globals):
|
||||||
# XXX: globals is modified on the first call to _create_fn, then
|
locals = {'cls': cls,
|
||||||
# the modified version is used in the second call. Is this okay?
|
|
||||||
globals = {'cls': cls,
|
|
||||||
'FrozenInstanceError': FrozenInstanceError}
|
'FrozenInstanceError': FrozenInstanceError}
|
||||||
if fields:
|
if fields:
|
||||||
fields_str = '(' + ','.join(repr(f.name) for f in fields) + ',)'
|
fields_str = '(' + ','.join(repr(f.name) for f in fields) + ',)'
|
||||||
|
@ -554,17 +556,19 @@ def _frozen_get_del_attr(cls, fields):
|
||||||
(f'if type(self) is cls or name in {fields_str}:',
|
(f'if type(self) is cls or name in {fields_str}:',
|
||||||
' raise FrozenInstanceError(f"cannot assign to field {name!r}")',
|
' raise FrozenInstanceError(f"cannot assign to field {name!r}")',
|
||||||
f'super(cls, self).__setattr__(name, value)'),
|
f'super(cls, self).__setattr__(name, value)'),
|
||||||
|
locals=locals,
|
||||||
globals=globals),
|
globals=globals),
|
||||||
_create_fn('__delattr__',
|
_create_fn('__delattr__',
|
||||||
('self', 'name'),
|
('self', 'name'),
|
||||||
(f'if type(self) is cls or name in {fields_str}:',
|
(f'if type(self) is cls or name in {fields_str}:',
|
||||||
' raise FrozenInstanceError(f"cannot delete field {name!r}")',
|
' raise FrozenInstanceError(f"cannot delete field {name!r}")',
|
||||||
f'super(cls, self).__delattr__(name)'),
|
f'super(cls, self).__delattr__(name)'),
|
||||||
|
locals=locals,
|
||||||
globals=globals),
|
globals=globals),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _cmp_fn(name, op, self_tuple, other_tuple):
|
def _cmp_fn(name, op, self_tuple, other_tuple, globals):
|
||||||
# Create a comparison function. If the fields in the object are
|
# Create a comparison function. If the fields in the object are
|
||||||
# named 'x' and 'y', then self_tuple is the string
|
# named 'x' and 'y', then self_tuple is the string
|
||||||
# '(self.x,self.y)' and other_tuple is the string
|
# '(self.x,self.y)' and other_tuple is the string
|
||||||
|
@ -574,14 +578,16 @@ def _cmp_fn(name, op, self_tuple, other_tuple):
|
||||||
('self', 'other'),
|
('self', 'other'),
|
||||||
[ 'if other.__class__ is self.__class__:',
|
[ 'if other.__class__ is self.__class__:',
|
||||||
f' return {self_tuple}{op}{other_tuple}',
|
f' return {self_tuple}{op}{other_tuple}',
|
||||||
'return NotImplemented'])
|
'return NotImplemented'],
|
||||||
|
globals=globals)
|
||||||
|
|
||||||
|
|
||||||
def _hash_fn(fields):
|
def _hash_fn(fields, globals):
|
||||||
self_tuple = _tuple_str('self', fields)
|
self_tuple = _tuple_str('self', fields)
|
||||||
return _create_fn('__hash__',
|
return _create_fn('__hash__',
|
||||||
('self',),
|
('self',),
|
||||||
[f'return hash({self_tuple})'])
|
[f'return hash({self_tuple})'],
|
||||||
|
globals=globals)
|
||||||
|
|
||||||
|
|
||||||
def _is_classvar(a_type, typing):
|
def _is_classvar(a_type, typing):
|
||||||
|
@ -754,14 +760,14 @@ def _set_new_attribute(cls, name, value):
|
||||||
# take. The common case is to do nothing, so instead of providing a
|
# take. The common case is to do nothing, so instead of providing a
|
||||||
# function that is a no-op, use None to signify that.
|
# function that is a no-op, use None to signify that.
|
||||||
|
|
||||||
def _hash_set_none(cls, fields):
|
def _hash_set_none(cls, fields, globals):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _hash_add(cls, fields):
|
def _hash_add(cls, fields, globals):
|
||||||
flds = [f for f in fields if (f.compare if f.hash is None else f.hash)]
|
flds = [f for f in fields if (f.compare if f.hash is None else f.hash)]
|
||||||
return _hash_fn(flds)
|
return _hash_fn(flds, globals)
|
||||||
|
|
||||||
def _hash_exception(cls, fields):
|
def _hash_exception(cls, fields, globals):
|
||||||
# Raise an exception.
|
# Raise an exception.
|
||||||
raise TypeError(f'Cannot overwrite attribute __hash__ '
|
raise TypeError(f'Cannot overwrite attribute __hash__ '
|
||||||
f'in class {cls.__name__}')
|
f'in class {cls.__name__}')
|
||||||
|
@ -803,6 +809,16 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
|
||||||
# is defined by the base class, which is found first.
|
# is defined by the base class, which is found first.
|
||||||
fields = {}
|
fields = {}
|
||||||
|
|
||||||
|
if cls.__module__ in sys.modules:
|
||||||
|
globals = sys.modules[cls.__module__].__dict__
|
||||||
|
else:
|
||||||
|
# Theoretically this can happen if someone writes
|
||||||
|
# a custom string to cls.__module__. In which case
|
||||||
|
# such dataclass won't be fully introspectable
|
||||||
|
# (w.r.t. typing.get_type_hints) but will still function
|
||||||
|
# correctly.
|
||||||
|
globals = {}
|
||||||
|
|
||||||
setattr(cls, _PARAMS, _DataclassParams(init, repr, eq, order,
|
setattr(cls, _PARAMS, _DataclassParams(init, repr, eq, order,
|
||||||
unsafe_hash, frozen))
|
unsafe_hash, frozen))
|
||||||
|
|
||||||
|
@ -912,6 +928,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
|
||||||
# if possible.
|
# if possible.
|
||||||
'__dataclass_self__' if 'self' in fields
|
'__dataclass_self__' if 'self' in fields
|
||||||
else 'self',
|
else 'self',
|
||||||
|
globals,
|
||||||
))
|
))
|
||||||
|
|
||||||
# Get the fields as a list, and include only real fields. This is
|
# Get the fields as a list, and include only real fields. This is
|
||||||
|
@ -920,7 +937,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
|
||||||
|
|
||||||
if repr:
|
if repr:
|
||||||
flds = [f for f in field_list if f.repr]
|
flds = [f for f in field_list if f.repr]
|
||||||
_set_new_attribute(cls, '__repr__', _repr_fn(flds))
|
_set_new_attribute(cls, '__repr__', _repr_fn(flds, globals))
|
||||||
|
|
||||||
if eq:
|
if eq:
|
||||||
# Create _eq__ method. There's no need for a __ne__ method,
|
# Create _eq__ method. There's no need for a __ne__ method,
|
||||||
|
@ -930,7 +947,8 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
|
||||||
other_tuple = _tuple_str('other', flds)
|
other_tuple = _tuple_str('other', flds)
|
||||||
_set_new_attribute(cls, '__eq__',
|
_set_new_attribute(cls, '__eq__',
|
||||||
_cmp_fn('__eq__', '==',
|
_cmp_fn('__eq__', '==',
|
||||||
self_tuple, other_tuple))
|
self_tuple, other_tuple,
|
||||||
|
globals=globals))
|
||||||
|
|
||||||
if order:
|
if order:
|
||||||
# Create and set the ordering methods.
|
# Create and set the ordering methods.
|
||||||
|
@ -943,13 +961,14 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
|
||||||
('__ge__', '>='),
|
('__ge__', '>='),
|
||||||
]:
|
]:
|
||||||
if _set_new_attribute(cls, name,
|
if _set_new_attribute(cls, name,
|
||||||
_cmp_fn(name, op, self_tuple, other_tuple)):
|
_cmp_fn(name, op, self_tuple, other_tuple,
|
||||||
|
globals=globals)):
|
||||||
raise TypeError(f'Cannot overwrite attribute {name} '
|
raise TypeError(f'Cannot overwrite attribute {name} '
|
||||||
f'in class {cls.__name__}. Consider using '
|
f'in class {cls.__name__}. Consider using '
|
||||||
'functools.total_ordering')
|
'functools.total_ordering')
|
||||||
|
|
||||||
if frozen:
|
if frozen:
|
||||||
for fn in _frozen_get_del_attr(cls, field_list):
|
for fn in _frozen_get_del_attr(cls, field_list, globals):
|
||||||
if _set_new_attribute(cls, fn.__name__, fn):
|
if _set_new_attribute(cls, fn.__name__, fn):
|
||||||
raise TypeError(f'Cannot overwrite attribute {fn.__name__} '
|
raise TypeError(f'Cannot overwrite attribute {fn.__name__} '
|
||||||
f'in class {cls.__name__}')
|
f'in class {cls.__name__}')
|
||||||
|
@ -962,7 +981,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
|
||||||
if hash_action:
|
if hash_action:
|
||||||
# No need to call _set_new_attribute here, since by the time
|
# No need to call _set_new_attribute here, since by the time
|
||||||
# we're here the overwriting is unconditional.
|
# we're here the overwriting is unconditional.
|
||||||
cls.__hash__ = hash_action(cls, field_list)
|
cls.__hash__ = hash_action(cls, field_list, globals)
|
||||||
|
|
||||||
if not getattr(cls, '__doc__'):
|
if not getattr(cls, '__doc__'):
|
||||||
# Create a class doc-string.
|
# Create a class doc-string.
|
||||||
|
|
|
@ -850,10 +850,15 @@ class MsgID(TokenList):
|
||||||
# message-id tokens may not be folded.
|
# message-id tokens may not be folded.
|
||||||
return str(self) + policy.linesep
|
return str(self) + policy.linesep
|
||||||
|
|
||||||
|
|
||||||
class MessageID(MsgID):
|
class MessageID(MsgID):
|
||||||
token_type = 'message-id'
|
token_type = 'message-id'
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidMessageID(MessageID):
|
||||||
|
token_type = 'invalid-message-id'
|
||||||
|
|
||||||
|
|
||||||
class Header(TokenList):
|
class Header(TokenList):
|
||||||
token_type = 'header'
|
token_type = 'header'
|
||||||
|
|
||||||
|
@ -2042,7 +2047,7 @@ def get_msg_id(value):
|
||||||
no-fold-literal = "[" *dtext "]"
|
no-fold-literal = "[" *dtext "]"
|
||||||
"""
|
"""
|
||||||
msg_id = MsgID()
|
msg_id = MsgID()
|
||||||
if value[0] in CFWS_LEADER:
|
if value and value[0] in CFWS_LEADER:
|
||||||
token, value = get_cfws(value)
|
token, value = get_cfws(value)
|
||||||
msg_id.append(token)
|
msg_id.append(token)
|
||||||
if not value or value[0] != '<':
|
if not value or value[0] != '<':
|
||||||
|
@ -2110,10 +2115,18 @@ def parse_message_id(value):
|
||||||
message_id = MessageID()
|
message_id = MessageID()
|
||||||
try:
|
try:
|
||||||
token, value = get_msg_id(value)
|
token, value = get_msg_id(value)
|
||||||
except errors.HeaderParseError:
|
message_id.append(token)
|
||||||
message_id.defects.append(errors.InvalidHeaderDefect(
|
except errors.HeaderParseError as ex:
|
||||||
"Expected msg-id but found {!r}".format(value)))
|
token = get_unstructured(value)
|
||||||
message_id.append(token)
|
message_id = InvalidMessageID(token)
|
||||||
|
message_id.defects.append(
|
||||||
|
errors.InvalidHeaderDefect("Invalid msg-id: {!r}".format(ex)))
|
||||||
|
else:
|
||||||
|
# Value after parsing a valid msg_id should be None.
|
||||||
|
if value:
|
||||||
|
message_id.defects.append(errors.InvalidHeaderDefect(
|
||||||
|
"Unexpected {!r}".format(value)))
|
||||||
|
|
||||||
return message_id
|
return message_id
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -20,6 +20,10 @@ def uu_encode(input, errors='strict', filename='<data>', mode=0o666):
|
||||||
read = infile.read
|
read = infile.read
|
||||||
write = outfile.write
|
write = outfile.write
|
||||||
|
|
||||||
|
# Remove newline chars from filename
|
||||||
|
filename = filename.replace('\n','\\n')
|
||||||
|
filename = filename.replace('\r','\\r')
|
||||||
|
|
||||||
# Encode
|
# Encode
|
||||||
write(('begin %o %s\n' % (mode & 0o777, filename)).encode('ascii'))
|
write(('begin %o %s\n' % (mode & 0o777, filename)).encode('ascii'))
|
||||||
chunk = read(45)
|
chunk = read(45)
|
||||||
|
|
33
Lib/enum.py
33
Lib/enum.py
|
@ -861,28 +861,20 @@ def _decompose(flag, value):
|
||||||
# _decompose is only called if the value is not named
|
# _decompose is only called if the value is not named
|
||||||
not_covered = value
|
not_covered = value
|
||||||
negative = value < 0
|
negative = value < 0
|
||||||
# issue29167: wrap accesses to _value2member_map_ in a list to avoid race
|
|
||||||
# conditions between iterating over it and having more pseudo-
|
|
||||||
# members added to it
|
|
||||||
if negative:
|
|
||||||
# only check for named flags
|
|
||||||
flags_to_check = [
|
|
||||||
(m, v)
|
|
||||||
for v, m in list(flag._value2member_map_.items())
|
|
||||||
if m.name is not None
|
|
||||||
]
|
|
||||||
else:
|
|
||||||
# check for named flags and powers-of-two flags
|
|
||||||
flags_to_check = [
|
|
||||||
(m, v)
|
|
||||||
for v, m in list(flag._value2member_map_.items())
|
|
||||||
if m.name is not None or _power_of_two(v)
|
|
||||||
]
|
|
||||||
members = []
|
members = []
|
||||||
for member, member_value in flags_to_check:
|
for member in flag:
|
||||||
|
member_value = member.value
|
||||||
if member_value and member_value & value == member_value:
|
if member_value and member_value & value == member_value:
|
||||||
members.append(member)
|
members.append(member)
|
||||||
not_covered &= ~member_value
|
not_covered &= ~member_value
|
||||||
|
if not negative:
|
||||||
|
tmp = not_covered
|
||||||
|
while tmp:
|
||||||
|
flag_value = 2 ** _high_bit(tmp)
|
||||||
|
if flag_value in flag._value2member_map_:
|
||||||
|
members.append(flag._value2member_map_[flag_value])
|
||||||
|
not_covered &= ~flag_value
|
||||||
|
tmp &= ~flag_value
|
||||||
if not members and value in flag._value2member_map_:
|
if not members and value in flag._value2member_map_:
|
||||||
members.append(flag._value2member_map_[value])
|
members.append(flag._value2member_map_[value])
|
||||||
members.sort(key=lambda m: m._value_, reverse=True)
|
members.sort(key=lambda m: m._value_, reverse=True)
|
||||||
|
@ -890,8 +882,3 @@ def _decompose(flag, value):
|
||||||
# we have the breakdown, don't need the value member itself
|
# we have the breakdown, don't need the value member itself
|
||||||
members.pop(0)
|
members.pop(0)
|
||||||
return members, not_covered
|
return members, not_covered
|
||||||
|
|
||||||
def _power_of_two(value):
|
|
||||||
if value < 1:
|
|
||||||
return False
|
|
||||||
return value == 2 ** _high_bit(value)
|
|
||||||
|
|
|
@ -214,10 +214,14 @@ LOOSE_HTTP_DATE_RE = re.compile(
|
||||||
(?::(\d\d))? # optional seconds
|
(?::(\d\d))? # optional seconds
|
||||||
)? # optional clock
|
)? # optional clock
|
||||||
\s*
|
\s*
|
||||||
([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+)? # timezone
|
(?:
|
||||||
|
([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+) # timezone
|
||||||
\s*
|
\s*
|
||||||
(?:\(\w+\))? # ASCII representation of timezone in parens.
|
)?
|
||||||
\s*$""", re.X | re.ASCII)
|
(?:
|
||||||
|
\(\w+\) # ASCII representation of timezone in parens.
|
||||||
|
\s*
|
||||||
|
)?$""", re.X | re.ASCII)
|
||||||
def http2time(text):
|
def http2time(text):
|
||||||
"""Returns time in seconds since epoch of time represented by a string.
|
"""Returns time in seconds since epoch of time represented by a string.
|
||||||
|
|
||||||
|
@ -287,9 +291,11 @@ ISO_DATE_RE = re.compile(
|
||||||
(?::?(\d\d(?:\.\d*)?))? # optional seconds (and fractional)
|
(?::?(\d\d(?:\.\d*)?))? # optional seconds (and fractional)
|
||||||
)? # optional clock
|
)? # optional clock
|
||||||
\s*
|
\s*
|
||||||
([-+]?\d\d?:?(:?\d\d)?
|
(?:
|
||||||
|Z|z)? # timezone (Z is "zero meridian", i.e. GMT)
|
([-+]?\d\d?:?(:?\d\d)?
|
||||||
\s*$""", re.X | re. ASCII)
|
|Z|z) # timezone (Z is "zero meridian", i.e. GMT)
|
||||||
|
\s*
|
||||||
|
)?$""", re.X | re. ASCII)
|
||||||
def iso2time(text):
|
def iso2time(text):
|
||||||
"""
|
"""
|
||||||
As for http2time, but parses the ISO 8601 formats:
|
As for http2time, but parses the ISO 8601 formats:
|
||||||
|
|
|
@ -1014,8 +1014,10 @@ class CGIHTTPRequestHandler(SimpleHTTPRequestHandler):
|
||||||
"""
|
"""
|
||||||
collapsed_path = _url_collapse_path(self.path)
|
collapsed_path = _url_collapse_path(self.path)
|
||||||
dir_sep = collapsed_path.find('/', 1)
|
dir_sep = collapsed_path.find('/', 1)
|
||||||
head, tail = collapsed_path[:dir_sep], collapsed_path[dir_sep+1:]
|
while dir_sep > 0 and not collapsed_path[:dir_sep] in self.cgi_directories:
|
||||||
if head in self.cgi_directories:
|
dir_sep = collapsed_path.find('/', dir_sep+1)
|
||||||
|
if dir_sep > 0:
|
||||||
|
head, tail = collapsed_path[:dir_sep], collapsed_path[dir_sep+1:]
|
||||||
self.cgi_info = head, tail
|
self.cgi_info = head, tail
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -3,6 +3,15 @@ Released on 2020-10-05?
|
||||||
======================================
|
======================================
|
||||||
|
|
||||||
|
|
||||||
|
bpo-38943: Fix autocomplete windows not always appearing on some
|
||||||
|
systems. Patch by Johnny Najera.
|
||||||
|
|
||||||
|
bpo-38944: Excape key now closes IDLE completion windows. Patch by
|
||||||
|
Johnny Najera.
|
||||||
|
|
||||||
|
bpo-38862: 'Strip Trailing Whitespace' on the Format menu removes extra
|
||||||
|
newlines at the end of non-shell files.
|
||||||
|
|
||||||
bpo-38636: Fix IDLE Format menu tab toggle and file indent width. These
|
bpo-38636: Fix IDLE Format menu tab toggle and file indent width. These
|
||||||
functions (default shortcuts Alt-T and Alt-U) were mistakenly disabled
|
functions (default shortcuts Alt-T and Alt-U) were mistakenly disabled
|
||||||
in 3.7.5 and 3.8.0.
|
in 3.7.5 and 3.8.0.
|
||||||
|
|
|
@ -17,7 +17,7 @@ KEYPRESS_VIRTUAL_EVENT_NAME = "<<autocompletewindow-keypress>>"
|
||||||
# before the default specific IDLE function
|
# before the default specific IDLE function
|
||||||
KEYPRESS_SEQUENCES = ("<Key>", "<Key-BackSpace>", "<Key-Return>", "<Key-Tab>",
|
KEYPRESS_SEQUENCES = ("<Key>", "<Key-BackSpace>", "<Key-Return>", "<Key-Tab>",
|
||||||
"<Key-Up>", "<Key-Down>", "<Key-Home>", "<Key-End>",
|
"<Key-Up>", "<Key-Down>", "<Key-Home>", "<Key-End>",
|
||||||
"<Key-Prior>", "<Key-Next>")
|
"<Key-Prior>", "<Key-Next>", "<Key-Escape>")
|
||||||
KEYRELEASE_VIRTUAL_EVENT_NAME = "<<autocompletewindow-keyrelease>>"
|
KEYRELEASE_VIRTUAL_EVENT_NAME = "<<autocompletewindow-keyrelease>>"
|
||||||
KEYRELEASE_SEQUENCE = "<KeyRelease>"
|
KEYRELEASE_SEQUENCE = "<KeyRelease>"
|
||||||
LISTUPDATE_SEQUENCE = "<B1-ButtonRelease>"
|
LISTUPDATE_SEQUENCE = "<B1-ButtonRelease>"
|
||||||
|
@ -257,6 +257,7 @@ class AutoCompleteWindow:
|
||||||
# place acw above current line
|
# place acw above current line
|
||||||
new_y -= acw_height
|
new_y -= acw_height
|
||||||
acw.wm_geometry("+%d+%d" % (new_x, new_y))
|
acw.wm_geometry("+%d+%d" % (new_x, new_y))
|
||||||
|
acw.update_idletasks()
|
||||||
|
|
||||||
if platform.system().startswith('Windows'):
|
if platform.system().startswith('Windows'):
|
||||||
# See issue 15786. When on Windows platform, Tk will misbehave
|
# See issue 15786. When on Windows platform, Tk will misbehave
|
||||||
|
|
|
@ -408,6 +408,16 @@ class Rstrip: # 'Strip Trailing Whitespace" on "Format" menu.
|
||||||
if cut < raw:
|
if cut < raw:
|
||||||
text.delete('%i.%i' % (cur, cut), '%i.end' % cur)
|
text.delete('%i.%i' % (cur, cut), '%i.end' % cur)
|
||||||
|
|
||||||
|
if (text.get('end-2c') == '\n' # File ends with at least 1 newline;
|
||||||
|
and not hasattr(self.editwin, 'interp')): # & is not Shell.
|
||||||
|
# Delete extra user endlines.
|
||||||
|
while (text.index('end-1c') > '1.0' # Stop if file empty.
|
||||||
|
and text.get('end-3c') == '\n'):
|
||||||
|
text.delete('end-3c')
|
||||||
|
# Because tk indexes are slice indexes and never raise,
|
||||||
|
# a file with only newlines will be emptied.
|
||||||
|
# patchcheck.py does the same.
|
||||||
|
|
||||||
undo.undo_block_stop()
|
undo.undo_block_stop()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>IDLE — Python 3.9.0a0 documentation</title>
|
<title>IDLE — Python 3.9.0a1 documentation</title>
|
||||||
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
|
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
|
||||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||||
|
|
||||||
|
@ -17,14 +17,14 @@
|
||||||
<script type="text/javascript" src="../_static/sidebar.js"></script>
|
<script type="text/javascript" src="../_static/sidebar.js"></script>
|
||||||
|
|
||||||
<link rel="search" type="application/opensearchdescription+xml"
|
<link rel="search" type="application/opensearchdescription+xml"
|
||||||
title="Search within Python 3.9.0a0 documentation"
|
title="Search within Python 3.9.0a1 documentation"
|
||||||
href="../_static/opensearch.xml"/>
|
href="../_static/opensearch.xml"/>
|
||||||
<link rel="author" title="About these documents" href="../about.html" />
|
<link rel="author" title="About these documents" href="../about.html" />
|
||||||
<link rel="index" title="Index" href="../genindex.html" />
|
<link rel="index" title="Index" href="../genindex.html" />
|
||||||
<link rel="search" title="Search" href="../search.html" />
|
<link rel="search" title="Search" href="../search.html" />
|
||||||
<link rel="copyright" title="Copyright" href="../copyright.html" />
|
<link rel="copyright" title="Copyright" href="../copyright.html" />
|
||||||
<link rel="next" title="Other Graphical User Interface Packages" href="othergui.html" />
|
<link rel="next" title="Other Graphical User Interface Packages" href="othergui.html" />
|
||||||
<link rel="prev" title="tkinter.scrolledtext — Scrolled Text Widget" href="tkinter.scrolledtext.html" />
|
<link rel="prev" title="tkinter.tix — Extension widgets for Tk" href="tkinter.tix.html" />
|
||||||
<link rel="canonical" href="https://docs.python.org/3/library/idle.html" />
|
<link rel="canonical" href="https://docs.python.org/3/library/idle.html" />
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@
|
||||||
<a href="othergui.html" title="Other Graphical User Interface Packages"
|
<a href="othergui.html" title="Other Graphical User Interface Packages"
|
||||||
accesskey="N">next</a> |</li>
|
accesskey="N">next</a> |</li>
|
||||||
<li class="right" >
|
<li class="right" >
|
||||||
<a href="tkinter.scrolledtext.html" title="tkinter.scrolledtext — Scrolled Text Widget"
|
<a href="tkinter.tix.html" title="tkinter.tix — Extension widgets for Tk"
|
||||||
accesskey="P">previous</a> |</li>
|
accesskey="P">previous</a> |</li>
|
||||||
|
|
||||||
<li><img src="../_static/py.png" alt=""
|
<li><img src="../_static/py.png" alt=""
|
||||||
|
@ -71,7 +71,7 @@
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="../index.html">3.9.0a0 Documentation</a> »
|
<a href="../index.html">3.9.0a1 Documentation</a> »
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li>
|
<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li>
|
||||||
|
@ -240,7 +240,8 @@ paragraph will be formatted to less than N columns, where N defaults to 72.</p>
|
||||||
</dd>
|
</dd>
|
||||||
<dt>Strip trailing whitespace</dt><dd><p>Remove trailing space and other whitespace characters after the last
|
<dt>Strip trailing whitespace</dt><dd><p>Remove trailing space and other whitespace characters after the last
|
||||||
non-whitespace character of a line by applying str.rstrip to each line,
|
non-whitespace character of a line by applying str.rstrip to each line,
|
||||||
including lines within multiline strings.</p>
|
including lines within multiline strings. Except for Shell windows,
|
||||||
|
remove extra newlines at the end of the file.</p>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
@ -886,8 +887,8 @@ also used for testing.</p>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h4>Previous topic</h4>
|
<h4>Previous topic</h4>
|
||||||
<p class="topless"><a href="tkinter.scrolledtext.html"
|
<p class="topless"><a href="tkinter.tix.html"
|
||||||
title="previous chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">tkinter.scrolledtext</span></code> — Scrolled Text Widget</a></p>
|
title="previous chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">tkinter.tix</span></code> — Extension widgets for Tk</a></p>
|
||||||
<h4>Next topic</h4>
|
<h4>Next topic</h4>
|
||||||
<p class="topless"><a href="othergui.html"
|
<p class="topless"><a href="othergui.html"
|
||||||
title="next chapter">Other Graphical User Interface Packages</a></p>
|
title="next chapter">Other Graphical User Interface Packages</a></p>
|
||||||
|
@ -919,7 +920,7 @@ also used for testing.</p>
|
||||||
<a href="othergui.html" title="Other Graphical User Interface Packages"
|
<a href="othergui.html" title="Other Graphical User Interface Packages"
|
||||||
>next</a> |</li>
|
>next</a> |</li>
|
||||||
<li class="right" >
|
<li class="right" >
|
||||||
<a href="tkinter.scrolledtext.html" title="tkinter.scrolledtext — Scrolled Text Widget"
|
<a href="tkinter.tix.html" title="tkinter.tix — Extension widgets for Tk"
|
||||||
>previous</a> |</li>
|
>previous</a> |</li>
|
||||||
|
|
||||||
<li><img src="../_static/py.png" alt=""
|
<li><img src="../_static/py.png" alt=""
|
||||||
|
@ -928,7 +929,7 @@ also used for testing.</p>
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="../index.html">3.9.0a0 Documentation</a> »
|
<a href="../index.html">3.9.0a1 Documentation</a> »
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li>
|
<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li>
|
||||||
|
@ -959,11 +960,11 @@ also used for testing.</p>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
Last updated on Sep 01, 2019.
|
Last updated on Nov 24, 2019.
|
||||||
<a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
|
<a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 2.1.2.
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 2.1.1.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -40,8 +40,9 @@ class Func:
|
||||||
class Editor:
|
class Editor:
|
||||||
'''Minimally imitate editor.EditorWindow class.
|
'''Minimally imitate editor.EditorWindow class.
|
||||||
'''
|
'''
|
||||||
def __init__(self, flist=None, filename=None, key=None, root=None):
|
def __init__(self, flist=None, filename=None, key=None, root=None,
|
||||||
self.text = Text()
|
text=None): # Allow real Text with mock Editor.
|
||||||
|
self.text = text or Text()
|
||||||
self.undo = UndoDelegator()
|
self.undo = UndoDelegator()
|
||||||
|
|
||||||
def get_selection_indices(self):
|
def get_selection_indices(self):
|
||||||
|
|
|
@ -611,37 +611,33 @@ class IndentsTest(unittest.TestCase):
|
||||||
|
|
||||||
class RstripTest(unittest.TestCase):
|
class RstripTest(unittest.TestCase):
|
||||||
|
|
||||||
def test_rstrip_line(self):
|
@classmethod
|
||||||
editor = MockEditor()
|
def setUpClass(cls):
|
||||||
text = editor.text
|
requires('gui')
|
||||||
do_rstrip = ft.Rstrip(editor).do_rstrip
|
cls.root = Tk()
|
||||||
eq = self.assertEqual
|
cls.root.withdraw()
|
||||||
|
cls.text = Text(cls.root)
|
||||||
|
cls.editor = MockEditor(text=cls.text)
|
||||||
|
cls.do_rstrip = ft.Rstrip(cls.editor).do_rstrip
|
||||||
|
|
||||||
do_rstrip()
|
@classmethod
|
||||||
eq(text.get('1.0', 'insert'), '')
|
def tearDownClass(cls):
|
||||||
text.insert('1.0', ' ')
|
del cls.text, cls.do_rstrip, cls.editor
|
||||||
do_rstrip()
|
cls.root.update_idletasks()
|
||||||
eq(text.get('1.0', 'insert'), '')
|
cls.root.destroy()
|
||||||
text.insert('1.0', ' \n')
|
del cls.root
|
||||||
do_rstrip()
|
|
||||||
eq(text.get('1.0', 'insert'), '\n')
|
|
||||||
|
|
||||||
def test_rstrip_multiple(self):
|
def tearDown(self):
|
||||||
editor = MockEditor()
|
self.text.delete('1.0', 'end-1c')
|
||||||
# Comment above, uncomment 3 below to test with real Editor & Text.
|
|
||||||
#from idlelib.editor import EditorWindow as Editor
|
|
||||||
#from tkinter import Tk
|
|
||||||
#editor = Editor(root=Tk())
|
|
||||||
text = editor.text
|
|
||||||
do_rstrip = ft.Rstrip(editor).do_rstrip
|
|
||||||
|
|
||||||
|
def test_rstrip_lines(self):
|
||||||
original = (
|
original = (
|
||||||
"Line with an ending tab \n"
|
"Line with an ending tab \n"
|
||||||
"Line ending in 5 spaces \n"
|
"Line ending in 5 spaces \n"
|
||||||
"Linewithnospaces\n"
|
"Linewithnospaces\n"
|
||||||
" indented line\n"
|
" indented line\n"
|
||||||
" indented line with trailing space \n"
|
" indented line with trailing space \n"
|
||||||
" ")
|
" \n")
|
||||||
stripped = (
|
stripped = (
|
||||||
"Line with an ending tab\n"
|
"Line with an ending tab\n"
|
||||||
"Line ending in 5 spaces\n"
|
"Line ending in 5 spaces\n"
|
||||||
|
@ -649,9 +645,23 @@ class RstripTest(unittest.TestCase):
|
||||||
" indented line\n"
|
" indented line\n"
|
||||||
" indented line with trailing space\n")
|
" indented line with trailing space\n")
|
||||||
|
|
||||||
text.insert('1.0', original)
|
self.text.insert('1.0', original)
|
||||||
do_rstrip()
|
self.do_rstrip()
|
||||||
self.assertEqual(text.get('1.0', 'insert'), stripped)
|
self.assertEqual(self.text.get('1.0', 'insert'), stripped)
|
||||||
|
|
||||||
|
def test_rstrip_end(self):
|
||||||
|
text = self.text
|
||||||
|
for code in ('', '\n', '\n\n\n'):
|
||||||
|
with self.subTest(code=code):
|
||||||
|
text.insert('1.0', code)
|
||||||
|
self.do_rstrip()
|
||||||
|
self.assertEqual(text.get('1.0','end-1c'), '')
|
||||||
|
for code in ('a\n', 'a\n\n', 'a\n\n\n'):
|
||||||
|
with self.subTest(code=code):
|
||||||
|
text.delete('1.0', 'end-1c')
|
||||||
|
text.insert('1.0', code)
|
||||||
|
self.do_rstrip()
|
||||||
|
self.assertEqual(text.get('1.0','end-1c'), 'a\n')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -272,6 +272,8 @@ _code_type = type(_write_atomic.__code__)
|
||||||
# only args in ast.arguments #37593)
|
# only args in ast.arguments #37593)
|
||||||
# Python 3.8b4 3413 (Fix "break" and "continue" in "finally" #37830)
|
# Python 3.8b4 3413 (Fix "break" and "continue" in "finally" #37830)
|
||||||
# Python 3.9a0 3420 (add LOAD_ASSERTION_ERROR #34880)
|
# Python 3.9a0 3420 (add LOAD_ASSERTION_ERROR #34880)
|
||||||
|
# Python 3.9a0 3421 (simplified bytecode for with blocks #32949)
|
||||||
|
# Python 3.9a0 3422 (remove BEGIN_FINALLY, END_FINALLY, CALL_FINALLY, POP_FINALLY bytecodes #33387)
|
||||||
#
|
#
|
||||||
# MAGIC must change whenever the bytecode emitted by the compiler may no
|
# MAGIC must change whenever the bytecode emitted by the compiler may no
|
||||||
# longer be understood by older implementations of the eval loop (usually
|
# longer be understood by older implementations of the eval loop (usually
|
||||||
|
@ -280,7 +282,7 @@ _code_type = type(_write_atomic.__code__)
|
||||||
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
|
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
|
||||||
# in PC/launcher.c must also be updated.
|
# in PC/launcher.c must also be updated.
|
||||||
|
|
||||||
MAGIC_NUMBER = (3420).to_bytes(2, 'little') + b'\r\n'
|
MAGIC_NUMBER = (3422).to_bytes(2, 'little') + b'\r\n'
|
||||||
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
|
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
|
||||||
|
|
||||||
_PYCACHE = '__pycache__'
|
_PYCACHE = '__pycache__'
|
||||||
|
|
|
@ -1136,7 +1136,6 @@ def getfullargspec(func):
|
||||||
varkw = None
|
varkw = None
|
||||||
posonlyargs = []
|
posonlyargs = []
|
||||||
kwonlyargs = []
|
kwonlyargs = []
|
||||||
defaults = ()
|
|
||||||
annotations = {}
|
annotations = {}
|
||||||
defaults = ()
|
defaults = ()
|
||||||
kwdefaults = {}
|
kwdefaults = {}
|
||||||
|
|
|
@ -20,30 +20,52 @@ def main():
|
||||||
description = ('A simple command line interface for json module '
|
description = ('A simple command line interface for json module '
|
||||||
'to validate and pretty-print JSON objects.')
|
'to validate and pretty-print JSON objects.')
|
||||||
parser = argparse.ArgumentParser(prog=prog, description=description)
|
parser = argparse.ArgumentParser(prog=prog, description=description)
|
||||||
parser.add_argument('infile', nargs='?', type=argparse.FileType(),
|
parser.add_argument('infile', nargs='?',
|
||||||
|
type=argparse.FileType(encoding="utf-8"),
|
||||||
help='a JSON file to be validated or pretty-printed',
|
help='a JSON file to be validated or pretty-printed',
|
||||||
default=sys.stdin)
|
default=sys.stdin)
|
||||||
parser.add_argument('outfile', nargs='?', type=argparse.FileType('w'),
|
parser.add_argument('outfile', nargs='?',
|
||||||
|
type=argparse.FileType('w', encoding="utf-8"),
|
||||||
help='write the output of infile to outfile',
|
help='write the output of infile to outfile',
|
||||||
default=sys.stdout)
|
default=sys.stdout)
|
||||||
parser.add_argument('--sort-keys', action='store_true', default=False,
|
parser.add_argument('--sort-keys', action='store_true', default=False,
|
||||||
help='sort the output of dictionaries alphabetically by key')
|
help='sort the output of dictionaries alphabetically by key')
|
||||||
|
parser.add_argument('--no-ensure-ascii', dest='ensure_ascii', action='store_false',
|
||||||
|
help='disable escaping of non-ASCII characters')
|
||||||
parser.add_argument('--json-lines', action='store_true', default=False,
|
parser.add_argument('--json-lines', action='store_true', default=False,
|
||||||
help='parse input using the jsonlines format')
|
help='parse input using the JSON Lines format. '
|
||||||
|
'Use with --no-indent or --compact to produce valid JSON Lines output.')
|
||||||
|
group = parser.add_mutually_exclusive_group()
|
||||||
|
group.add_argument('--indent', default=4, type=int,
|
||||||
|
help='separate items with newlines and use this number '
|
||||||
|
'of spaces for indentation')
|
||||||
|
group.add_argument('--tab', action='store_const', dest='indent',
|
||||||
|
const='\t', help='separate items with newlines and use '
|
||||||
|
'tabs for indentation')
|
||||||
|
group.add_argument('--no-indent', action='store_const', dest='indent',
|
||||||
|
const=None,
|
||||||
|
help='separate items with spaces rather than newlines')
|
||||||
|
group.add_argument('--compact', action='store_true',
|
||||||
|
help='suppress all whitespace separation (most compact)')
|
||||||
options = parser.parse_args()
|
options = parser.parse_args()
|
||||||
|
|
||||||
infile = options.infile
|
dump_args = {
|
||||||
outfile = options.outfile
|
'sort_keys': options.sort_keys,
|
||||||
sort_keys = options.sort_keys
|
'indent': options.indent,
|
||||||
json_lines = options.json_lines
|
'ensure_ascii': options.ensure_ascii,
|
||||||
with infile, outfile:
|
}
|
||||||
|
if options.compact:
|
||||||
|
dump_args['indent'] = None
|
||||||
|
dump_args['separators'] = ',', ':'
|
||||||
|
|
||||||
|
with options.infile as infile, options.outfile as outfile:
|
||||||
try:
|
try:
|
||||||
if json_lines:
|
if options.json_lines:
|
||||||
objs = (json.loads(line) for line in infile)
|
objs = (json.loads(line) for line in infile)
|
||||||
else:
|
else:
|
||||||
objs = (json.load(infile), )
|
objs = (json.load(infile), )
|
||||||
for obj in objs:
|
for obj in objs:
|
||||||
json.dump(obj, outfile, sort_keys=sort_keys, indent=4)
|
json.dump(obj, outfile, **dump_args)
|
||||||
outfile.write('\n')
|
outfile.write('\n')
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise SystemExit(e)
|
raise SystemExit(e)
|
||||||
|
|
|
@ -84,10 +84,12 @@ def_op('BINARY_TRUE_DIVIDE', 27)
|
||||||
def_op('INPLACE_FLOOR_DIVIDE', 28)
|
def_op('INPLACE_FLOOR_DIVIDE', 28)
|
||||||
def_op('INPLACE_TRUE_DIVIDE', 29)
|
def_op('INPLACE_TRUE_DIVIDE', 29)
|
||||||
|
|
||||||
|
def_op('RERAISE', 48)
|
||||||
|
def_op('WITH_EXCEPT_START', 49)
|
||||||
def_op('GET_AITER', 50)
|
def_op('GET_AITER', 50)
|
||||||
def_op('GET_ANEXT', 51)
|
def_op('GET_ANEXT', 51)
|
||||||
def_op('BEFORE_ASYNC_WITH', 52)
|
def_op('BEFORE_ASYNC_WITH', 52)
|
||||||
def_op('BEGIN_FINALLY', 53)
|
|
||||||
def_op('END_ASYNC_FOR', 54)
|
def_op('END_ASYNC_FOR', 54)
|
||||||
def_op('INPLACE_ADD', 55)
|
def_op('INPLACE_ADD', 55)
|
||||||
def_op('INPLACE_SUBTRACT', 56)
|
def_op('INPLACE_SUBTRACT', 56)
|
||||||
|
@ -115,14 +117,13 @@ def_op('INPLACE_RSHIFT', 76)
|
||||||
def_op('INPLACE_AND', 77)
|
def_op('INPLACE_AND', 77)
|
||||||
def_op('INPLACE_XOR', 78)
|
def_op('INPLACE_XOR', 78)
|
||||||
def_op('INPLACE_OR', 79)
|
def_op('INPLACE_OR', 79)
|
||||||
def_op('WITH_CLEANUP_START', 81)
|
|
||||||
def_op('WITH_CLEANUP_FINISH', 82)
|
|
||||||
def_op('RETURN_VALUE', 83)
|
def_op('RETURN_VALUE', 83)
|
||||||
def_op('IMPORT_STAR', 84)
|
def_op('IMPORT_STAR', 84)
|
||||||
def_op('SETUP_ANNOTATIONS', 85)
|
def_op('SETUP_ANNOTATIONS', 85)
|
||||||
def_op('YIELD_VALUE', 86)
|
def_op('YIELD_VALUE', 86)
|
||||||
def_op('POP_BLOCK', 87)
|
def_op('POP_BLOCK', 87)
|
||||||
def_op('END_FINALLY', 88)
|
|
||||||
def_op('POP_EXCEPT', 89)
|
def_op('POP_EXCEPT', 89)
|
||||||
|
|
||||||
HAVE_ARGUMENT = 90 # Opcodes from here have an argument:
|
HAVE_ARGUMENT = 90 # Opcodes from here have an argument:
|
||||||
|
@ -210,7 +211,5 @@ def_op('BUILD_TUPLE_UNPACK_WITH_CALL', 158)
|
||||||
|
|
||||||
name_op('LOAD_METHOD', 160)
|
name_op('LOAD_METHOD', 160)
|
||||||
def_op('CALL_METHOD', 161)
|
def_op('CALL_METHOD', 161)
|
||||||
jrel_op('CALL_FINALLY', 162)
|
|
||||||
def_op('POP_FINALLY', 163)
|
|
||||||
|
|
||||||
del def_op, name_op, jrel_op, jabs_op
|
del def_op, name_op, jrel_op, jabs_op
|
||||||
|
|
|
@ -1072,6 +1072,9 @@ class PathLike(abc.ABC):
|
||||||
def __subclasshook__(cls, subclass):
|
def __subclasshook__(cls, subclass):
|
||||||
return hasattr(subclass, '__fspath__')
|
return hasattr(subclass, '__fspath__')
|
||||||
|
|
||||||
|
def __class_getitem__(cls, type):
|
||||||
|
return cls
|
||||||
|
|
||||||
|
|
||||||
if name == 'nt':
|
if name == 'nt':
|
||||||
class _AddedDllDirectory:
|
class _AddedDllDirectory:
|
||||||
|
|
|
@ -777,6 +777,9 @@ class PurePath(object):
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
return self._cparts >= other._cparts
|
return self._cparts >= other._cparts
|
||||||
|
|
||||||
|
def __class_getitem__(cls, type):
|
||||||
|
return cls
|
||||||
|
|
||||||
drive = property(attrgetter('_drv'),
|
drive = property(attrgetter('_drv'),
|
||||||
doc="""The drive prefix (letter or UNC path), if any.""")
|
doc="""The drive prefix (letter or UNC path), if any.""")
|
||||||
|
|
||||||
|
|
|
@ -1604,17 +1604,29 @@ class _Unpickler:
|
||||||
|
|
||||||
def load_get(self):
|
def load_get(self):
|
||||||
i = int(self.readline()[:-1])
|
i = int(self.readline()[:-1])
|
||||||
self.append(self.memo[i])
|
try:
|
||||||
|
self.append(self.memo[i])
|
||||||
|
except KeyError:
|
||||||
|
msg = f'Memo value not found at index {i}'
|
||||||
|
raise UnpicklingError(msg) from None
|
||||||
dispatch[GET[0]] = load_get
|
dispatch[GET[0]] = load_get
|
||||||
|
|
||||||
def load_binget(self):
|
def load_binget(self):
|
||||||
i = self.read(1)[0]
|
i = self.read(1)[0]
|
||||||
self.append(self.memo[i])
|
try:
|
||||||
|
self.append(self.memo[i])
|
||||||
|
except KeyError as exc:
|
||||||
|
msg = f'Memo value not found at index {i}'
|
||||||
|
raise UnpicklingError(msg) from None
|
||||||
dispatch[BINGET[0]] = load_binget
|
dispatch[BINGET[0]] = load_binget
|
||||||
|
|
||||||
def load_long_binget(self):
|
def load_long_binget(self):
|
||||||
i, = unpack('<I', self.read(4))
|
i, = unpack('<I', self.read(4))
|
||||||
self.append(self.memo[i])
|
try:
|
||||||
|
self.append(self.memo[i])
|
||||||
|
except KeyError as exc:
|
||||||
|
msg = f'Memo value not found at index {i}'
|
||||||
|
raise UnpicklingError(msg) from None
|
||||||
dispatch[LONG_BINGET[0]] = load_long_binget
|
dispatch[LONG_BINGET[0]] = load_long_binget
|
||||||
|
|
||||||
def load_put(self):
|
def load_put(self):
|
||||||
|
|
|
@ -413,8 +413,10 @@ class Random(_random.Random):
|
||||||
raise TypeError('Cannot specify both weights and cumulative weights')
|
raise TypeError('Cannot specify both weights and cumulative weights')
|
||||||
if len(cum_weights) != n:
|
if len(cum_weights) != n:
|
||||||
raise ValueError('The number of weights does not match the population')
|
raise ValueError('The number of weights does not match the population')
|
||||||
bisect = _bisect
|
|
||||||
total = cum_weights[-1] + 0.0 # convert to float
|
total = cum_weights[-1] + 0.0 # convert to float
|
||||||
|
if total <= 0.0:
|
||||||
|
raise ValueError('Total of weights must be greater than zero')
|
||||||
|
bisect = _bisect
|
||||||
hi = n - 1
|
hi = n - 1
|
||||||
return [population[bisect(cum_weights, random() * total, 0, hi)]
|
return [population[bisect(cum_weights, random() * total, 0, hi)]
|
||||||
for i in _repeat(None, k)]
|
for i in _repeat(None, k)]
|
||||||
|
|
|
@ -442,7 +442,7 @@ def ignore_patterns(*patterns):
|
||||||
def _copytree(entries, src, dst, symlinks, ignore, copy_function,
|
def _copytree(entries, src, dst, symlinks, ignore, copy_function,
|
||||||
ignore_dangling_symlinks, dirs_exist_ok=False):
|
ignore_dangling_symlinks, dirs_exist_ok=False):
|
||||||
if ignore is not None:
|
if ignore is not None:
|
||||||
ignored_names = ignore(src, set(os.listdir(src)))
|
ignored_names = ignore(src, {x.name for x in entries})
|
||||||
else:
|
else:
|
||||||
ignored_names = set()
|
ignored_names = set()
|
||||||
|
|
||||||
|
@ -543,11 +543,12 @@ def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
|
||||||
|
|
||||||
"""
|
"""
|
||||||
sys.audit("shutil.copytree", src, dst)
|
sys.audit("shutil.copytree", src, dst)
|
||||||
with os.scandir(src) as entries:
|
with os.scandir(src) as itr:
|
||||||
return _copytree(entries=entries, src=src, dst=dst, symlinks=symlinks,
|
entries = list(itr)
|
||||||
ignore=ignore, copy_function=copy_function,
|
return _copytree(entries=entries, src=src, dst=dst, symlinks=symlinks,
|
||||||
ignore_dangling_symlinks=ignore_dangling_symlinks,
|
ignore=ignore, copy_function=copy_function,
|
||||||
dirs_exist_ok=dirs_exist_ok)
|
ignore_dangling_symlinks=ignore_dangling_symlinks,
|
||||||
|
dirs_exist_ok=dirs_exist_ok)
|
||||||
|
|
||||||
if hasattr(os.stat_result, 'st_file_attributes'):
|
if hasattr(os.stat_result, 'st_file_attributes'):
|
||||||
# Special handling for directory junctions to make them behave like
|
# Special handling for directory junctions to make them behave like
|
||||||
|
|
|
@ -839,7 +839,11 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
|
||||||
sock.close()
|
sock.close()
|
||||||
|
|
||||||
if err is not None:
|
if err is not None:
|
||||||
raise err
|
try:
|
||||||
|
raise err
|
||||||
|
finally:
|
||||||
|
# Break explicitly a reference cycle
|
||||||
|
err = None
|
||||||
else:
|
else:
|
||||||
raise error("getaddrinfo returns an empty list")
|
raise error("getaddrinfo returns an empty list")
|
||||||
|
|
||||||
|
|
|
@ -633,10 +633,9 @@ class SpooledTemporaryFile:
|
||||||
if 'b' in mode:
|
if 'b' in mode:
|
||||||
self._file = _io.BytesIO()
|
self._file = _io.BytesIO()
|
||||||
else:
|
else:
|
||||||
# Setting newline="\n" avoids newline translation;
|
self._file = _io.TextIOWrapper(_io.BytesIO(),
|
||||||
# this is important because otherwise on Windows we'd
|
encoding=encoding, errors=errors,
|
||||||
# get double newline translation upon rollover().
|
newline=newline)
|
||||||
self._file = _io.StringIO(newline="\n")
|
|
||||||
self._max_size = max_size
|
self._max_size = max_size
|
||||||
self._rolled = False
|
self._rolled = False
|
||||||
self._TemporaryFileArgs = {'mode': mode, 'buffering': buffering,
|
self._TemporaryFileArgs = {'mode': mode, 'buffering': buffering,
|
||||||
|
@ -656,8 +655,12 @@ class SpooledTemporaryFile:
|
||||||
newfile = self._file = TemporaryFile(**self._TemporaryFileArgs)
|
newfile = self._file = TemporaryFile(**self._TemporaryFileArgs)
|
||||||
del self._TemporaryFileArgs
|
del self._TemporaryFileArgs
|
||||||
|
|
||||||
newfile.write(file.getvalue())
|
pos = file.tell()
|
||||||
newfile.seek(file.tell(), 0)
|
if hasattr(newfile, 'buffer'):
|
||||||
|
newfile.buffer.write(file.detach().getvalue())
|
||||||
|
else:
|
||||||
|
newfile.write(file.getvalue())
|
||||||
|
newfile.seek(pos, 0)
|
||||||
|
|
||||||
self._rolled = True
|
self._rolled = True
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ Empty lines above are for good reason (testing for correct line numbers)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
__annotations__[1] = 2
|
__annotations__[1] = 2
|
||||||
|
|
||||||
|
@ -51,3 +52,9 @@ def foo(x: int = 10):
|
||||||
def bar(y: List[str]):
|
def bar(y: List[str]):
|
||||||
x: str = 'yes'
|
x: str = 'yes'
|
||||||
bar()
|
bar()
|
||||||
|
|
||||||
|
def dec(func):
|
||||||
|
@wraps(func)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
return wrapper
|
||||||
|
|
|
@ -263,13 +263,73 @@ def test_cantrace():
|
||||||
|
|
||||||
def test_mmap():
|
def test_mmap():
|
||||||
import mmap
|
import mmap
|
||||||
|
|
||||||
with TestHook() as hook:
|
with TestHook() as hook:
|
||||||
mmap.mmap(-1, 8)
|
mmap.mmap(-1, 8)
|
||||||
assertEqual(hook.seen[0][1][:2], (-1, 8))
|
assertEqual(hook.seen[0][1][:2], (-1, 8))
|
||||||
|
|
||||||
|
|
||||||
|
def test_excepthook():
|
||||||
|
def excepthook(exc_type, exc_value, exc_tb):
|
||||||
|
if exc_type is not RuntimeError:
|
||||||
|
sys.__excepthook__(exc_type, exc_value, exc_tb)
|
||||||
|
|
||||||
|
def hook(event, args):
|
||||||
|
if event == "sys.excepthook":
|
||||||
|
if not isinstance(args[2], args[1]):
|
||||||
|
raise TypeError(f"Expected isinstance({args[2]!r}, " f"{args[1]!r})")
|
||||||
|
if args[0] != excepthook:
|
||||||
|
raise ValueError(f"Expected {args[0]} == {excepthook}")
|
||||||
|
print(event, repr(args[2]))
|
||||||
|
|
||||||
|
sys.addaudithook(hook)
|
||||||
|
sys.excepthook = excepthook
|
||||||
|
raise RuntimeError("fatal-error")
|
||||||
|
|
||||||
|
|
||||||
|
def test_unraisablehook():
|
||||||
|
from _testcapi import write_unraisable_exc
|
||||||
|
|
||||||
|
def unraisablehook(hookargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def hook(event, args):
|
||||||
|
if event == "sys.unraisablehook":
|
||||||
|
if args[0] != unraisablehook:
|
||||||
|
raise ValueError(f"Expected {args[0]} == {unraisablehook}")
|
||||||
|
print(event, repr(args[1].exc_value), args[1].err_msg)
|
||||||
|
|
||||||
|
sys.addaudithook(hook)
|
||||||
|
sys.unraisablehook = unraisablehook
|
||||||
|
write_unraisable_exc(RuntimeError("nonfatal-error"), "for audit hook test", None)
|
||||||
|
|
||||||
|
|
||||||
|
def test_winreg():
|
||||||
|
from winreg import OpenKey, EnumKey, CloseKey, HKEY_LOCAL_MACHINE
|
||||||
|
|
||||||
|
def hook(event, args):
|
||||||
|
if not event.startswith("winreg."):
|
||||||
|
return
|
||||||
|
print(event, *args)
|
||||||
|
|
||||||
|
sys.addaudithook(hook)
|
||||||
|
|
||||||
|
k = OpenKey(HKEY_LOCAL_MACHINE, "Software")
|
||||||
|
EnumKey(k, 0)
|
||||||
|
try:
|
||||||
|
EnumKey(k, 10000)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Expected EnumKey(HKLM, 10000) to fail")
|
||||||
|
|
||||||
|
kv = k.Detach()
|
||||||
|
CloseKey(kv)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
from test.libregrtest.setup import suppress_msvcrt_asserts
|
from test.libregrtest.setup import suppress_msvcrt_asserts
|
||||||
|
|
||||||
suppress_msvcrt_asserts(False)
|
suppress_msvcrt_asserts(False)
|
||||||
|
|
||||||
test = sys.argv[1]
|
test = sys.argv[1]
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import dataclasses
|
||||||
|
|
||||||
|
|
||||||
|
class Foo:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
|
class Bar:
|
||||||
|
foo: Foo
|
|
@ -1019,7 +1019,9 @@ class AbstractUnpickleTests(unittest.TestCase):
|
||||||
self.assertEqual(self.loads(dumped), '\u20ac\x00')
|
self.assertEqual(self.loads(dumped), '\u20ac\x00')
|
||||||
|
|
||||||
def test_misc_get(self):
|
def test_misc_get(self):
|
||||||
self.check_unpickling_error(KeyError, b'g0\np0')
|
self.check_unpickling_error(pickle.UnpicklingError, b'g0\np0')
|
||||||
|
self.check_unpickling_error(pickle.UnpicklingError, b'jens:')
|
||||||
|
self.check_unpickling_error(pickle.UnpicklingError, b'hens:')
|
||||||
self.assert_is_copy([(100,), (100,)],
|
self.assert_is_copy([(100,), (100,)],
|
||||||
self.loads(b'((Kdtp0\nh\x00l.))'))
|
self.loads(b'((Kdtp0\nh\x00l.))'))
|
||||||
|
|
||||||
|
|
|
@ -2512,16 +2512,6 @@ def swap_item(obj, item, new_val):
|
||||||
if item in obj:
|
if item in obj:
|
||||||
del obj[item]
|
del obj[item]
|
||||||
|
|
||||||
def strip_python_stderr(stderr):
|
|
||||||
"""Strip the stderr of a Python process from potential debug output
|
|
||||||
emitted by the interpreter.
|
|
||||||
|
|
||||||
This will typically be run on the result of the communicate() method
|
|
||||||
of a subprocess.Popen object.
|
|
||||||
"""
|
|
||||||
stderr = re.sub(br"\[\d+ refs, \d+ blocks\]\r?\n?", b"", stderr).strip()
|
|
||||||
return stderr
|
|
||||||
|
|
||||||
requires_type_collecting = unittest.skipIf(hasattr(sys, 'getcounts'),
|
requires_type_collecting = unittest.skipIf(hasattr(sys, 'getcounts'),
|
||||||
'types are immortal if COUNT_ALLOCS is defined')
|
'types are immortal if COUNT_ALLOCS is defined')
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import py_compile
|
||||||
import zipfile
|
import zipfile
|
||||||
|
|
||||||
from importlib.util import source_from_cache
|
from importlib.util import source_from_cache
|
||||||
from test.support import make_legacy_pyc, strip_python_stderr
|
from test.support import make_legacy_pyc
|
||||||
|
|
||||||
|
|
||||||
# Cached result of the expensive test performed in the function below.
|
# Cached result of the expensive test performed in the function below.
|
||||||
|
@ -134,7 +134,6 @@ def run_python_until_end(*args, **env_vars):
|
||||||
proc.kill()
|
proc.kill()
|
||||||
subprocess._cleanup()
|
subprocess._cleanup()
|
||||||
rc = proc.returncode
|
rc = proc.returncode
|
||||||
err = strip_python_stderr(err)
|
|
||||||
return _PythonRunResult(rc, out, err), cmd_line
|
return _PythonRunResult(rc, out, err), cmd_line
|
||||||
|
|
||||||
def _assert_python(expected_success, /, *args, **env_vars):
|
def _assert_python(expected_success, /, *args, **env_vars):
|
||||||
|
|
|
@ -30,7 +30,7 @@ def setUpModule():
|
||||||
global candidate_locales
|
global candidate_locales
|
||||||
# Issue #13441: Skip some locales (e.g. cs_CZ and hu_HU) on Solaris to
|
# Issue #13441: Skip some locales (e.g. cs_CZ and hu_HU) on Solaris to
|
||||||
# workaround a mbstowcs() bug. For example, on Solaris, the hu_HU locale uses
|
# workaround a mbstowcs() bug. For example, on Solaris, the hu_HU locale uses
|
||||||
# the locale encoding ISO-8859-2, the thousauds separator is b'\xA0' and it is
|
# the locale encoding ISO-8859-2, the thousands separator is b'\xA0' and it is
|
||||||
# decoded as U+30000020 (an invalid character) by mbstowcs().
|
# decoded as U+30000020 (an invalid character) by mbstowcs().
|
||||||
if sys.platform == 'sunos5':
|
if sys.platform == 'sunos5':
|
||||||
old_locale = locale.setlocale(locale.LC_ALL)
|
old_locale = locale.setlocale(locale.LC_ALL)
|
||||||
|
|
|
@ -426,26 +426,6 @@ class BaseTest:
|
||||||
b.fromlist(a.tolist())
|
b.fromlist(a.tolist())
|
||||||
self.assertEqual(a, b)
|
self.assertEqual(a, b)
|
||||||
|
|
||||||
def test_tofromstring(self):
|
|
||||||
# Warnings not raised when arguments are incorrect as Argument Clinic
|
|
||||||
# handles that before the warning can be raised.
|
|
||||||
nb_warnings = 2
|
|
||||||
with warnings.catch_warnings(record=True) as r:
|
|
||||||
warnings.filterwarnings("always",
|
|
||||||
message=r"(to|from)string\(\) is deprecated",
|
|
||||||
category=DeprecationWarning)
|
|
||||||
a = array.array(self.typecode, 2*self.example)
|
|
||||||
b = array.array(self.typecode)
|
|
||||||
self.assertRaises(TypeError, a.tostring, 42)
|
|
||||||
self.assertRaises(TypeError, b.fromstring)
|
|
||||||
self.assertRaises(TypeError, b.fromstring, 42)
|
|
||||||
b.fromstring(a.tostring())
|
|
||||||
self.assertEqual(a, b)
|
|
||||||
if a.itemsize>1:
|
|
||||||
self.assertRaises(ValueError, b.fromstring, "x")
|
|
||||||
nb_warnings += 1
|
|
||||||
self.assertEqual(len(r), nb_warnings)
|
|
||||||
|
|
||||||
def test_tofrombytes(self):
|
def test_tofrombytes(self):
|
||||||
a = array.array(self.typecode, 2*self.example)
|
a = array.array(self.typecode, 2*self.example)
|
||||||
b = array.array(self.typecode)
|
b = array.array(self.typecode)
|
||||||
|
|
|
@ -1738,10 +1738,6 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase):
|
||||||
MyDatagramProto, flags=1, sock=FakeSock())
|
MyDatagramProto, flags=1, sock=FakeSock())
|
||||||
self.assertRaises(ValueError, self.loop.run_until_complete, fut)
|
self.assertRaises(ValueError, self.loop.run_until_complete, fut)
|
||||||
|
|
||||||
fut = self.loop.create_datagram_endpoint(
|
|
||||||
MyDatagramProto, reuse_address=True, sock=FakeSock())
|
|
||||||
self.assertRaises(ValueError, self.loop.run_until_complete, fut)
|
|
||||||
|
|
||||||
fut = self.loop.create_datagram_endpoint(
|
fut = self.loop.create_datagram_endpoint(
|
||||||
MyDatagramProto, reuse_port=True, sock=FakeSock())
|
MyDatagramProto, reuse_port=True, sock=FakeSock())
|
||||||
self.assertRaises(ValueError, self.loop.run_until_complete, fut)
|
self.assertRaises(ValueError, self.loop.run_until_complete, fut)
|
||||||
|
@ -1752,7 +1748,6 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase):
|
||||||
|
|
||||||
def test_create_datagram_endpoint_sockopts(self):
|
def test_create_datagram_endpoint_sockopts(self):
|
||||||
# Socket options should not be applied unless asked for.
|
# Socket options should not be applied unless asked for.
|
||||||
# SO_REUSEADDR defaults to on for UNIX.
|
|
||||||
# SO_REUSEPORT is not available on all platforms.
|
# SO_REUSEPORT is not available on all platforms.
|
||||||
|
|
||||||
coro = self.loop.create_datagram_endpoint(
|
coro = self.loop.create_datagram_endpoint(
|
||||||
|
@ -1761,18 +1756,8 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase):
|
||||||
transport, protocol = self.loop.run_until_complete(coro)
|
transport, protocol = self.loop.run_until_complete(coro)
|
||||||
sock = transport.get_extra_info('socket')
|
sock = transport.get_extra_info('socket')
|
||||||
|
|
||||||
reuse_address_default_on = (
|
|
||||||
os.name == 'posix' and sys.platform != 'cygwin')
|
|
||||||
reuseport_supported = hasattr(socket, 'SO_REUSEPORT')
|
reuseport_supported = hasattr(socket, 'SO_REUSEPORT')
|
||||||
|
|
||||||
if reuse_address_default_on:
|
|
||||||
self.assertTrue(
|
|
||||||
sock.getsockopt(
|
|
||||||
socket.SOL_SOCKET, socket.SO_REUSEADDR))
|
|
||||||
else:
|
|
||||||
self.assertFalse(
|
|
||||||
sock.getsockopt(
|
|
||||||
socket.SOL_SOCKET, socket.SO_REUSEADDR))
|
|
||||||
if reuseport_supported:
|
if reuseport_supported:
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
sock.getsockopt(
|
sock.getsockopt(
|
||||||
|
@ -1788,13 +1773,12 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase):
|
||||||
coro = self.loop.create_datagram_endpoint(
|
coro = self.loop.create_datagram_endpoint(
|
||||||
lambda: MyDatagramProto(create_future=True, loop=self.loop),
|
lambda: MyDatagramProto(create_future=True, loop=self.loop),
|
||||||
local_addr=('127.0.0.1', 0),
|
local_addr=('127.0.0.1', 0),
|
||||||
reuse_address=True,
|
|
||||||
reuse_port=reuseport_supported,
|
reuse_port=reuseport_supported,
|
||||||
allow_broadcast=True)
|
allow_broadcast=True)
|
||||||
transport, protocol = self.loop.run_until_complete(coro)
|
transport, protocol = self.loop.run_until_complete(coro)
|
||||||
sock = transport.get_extra_info('socket')
|
sock = transport.get_extra_info('socket')
|
||||||
|
|
||||||
self.assertTrue(
|
self.assertFalse(
|
||||||
sock.getsockopt(
|
sock.getsockopt(
|
||||||
socket.SOL_SOCKET, socket.SO_REUSEADDR))
|
socket.SOL_SOCKET, socket.SO_REUSEADDR))
|
||||||
if reuseport_supported:
|
if reuseport_supported:
|
||||||
|
@ -1809,6 +1793,29 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase):
|
||||||
self.loop.run_until_complete(protocol.done)
|
self.loop.run_until_complete(protocol.done)
|
||||||
self.assertEqual('CLOSED', protocol.state)
|
self.assertEqual('CLOSED', protocol.state)
|
||||||
|
|
||||||
|
def test_create_datagram_endpoint_reuse_address_error(self):
|
||||||
|
# bpo-37228: Ensure that explicit passing of `reuse_address=True`
|
||||||
|
# raises an error, as it is not safe to use SO_REUSEADDR when using UDP
|
||||||
|
|
||||||
|
coro = self.loop.create_datagram_endpoint(
|
||||||
|
lambda: MyDatagramProto(create_future=True, loop=self.loop),
|
||||||
|
local_addr=('127.0.0.1', 0),
|
||||||
|
reuse_address=True)
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
self.loop.run_until_complete(coro)
|
||||||
|
|
||||||
|
def test_create_datagram_endpoint_reuse_address_warning(self):
|
||||||
|
# bpo-37228: Deprecate *reuse_address* parameter
|
||||||
|
|
||||||
|
coro = self.loop.create_datagram_endpoint(
|
||||||
|
lambda: MyDatagramProto(create_future=True, loop=self.loop),
|
||||||
|
local_addr=('127.0.0.1', 0),
|
||||||
|
reuse_address=False)
|
||||||
|
|
||||||
|
with self.assertWarns(DeprecationWarning):
|
||||||
|
self.loop.run_until_complete(coro)
|
||||||
|
|
||||||
@patch_socket
|
@patch_socket
|
||||||
def test_create_datagram_endpoint_nosoreuseport(self, m_socket):
|
def test_create_datagram_endpoint_nosoreuseport(self, m_socket):
|
||||||
del m_socket.SO_REUSEPORT
|
del m_socket.SO_REUSEPORT
|
||||||
|
|
|
@ -924,59 +924,6 @@ os.close(fd)
|
||||||
wr.close()
|
wr.close()
|
||||||
self.loop.run_until_complete(wr.wait_closed())
|
self.loop.run_until_complete(wr.wait_closed())
|
||||||
|
|
||||||
def test_del_stream_before_sock_closing(self):
|
|
||||||
messages = []
|
|
||||||
self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx))
|
|
||||||
|
|
||||||
with test_utils.run_test_server() as httpd:
|
|
||||||
with self.assertWarns(DeprecationWarning):
|
|
||||||
rd, wr = self.loop.run_until_complete(
|
|
||||||
asyncio.open_connection(*httpd.address, loop=self.loop))
|
|
||||||
sock = wr.get_extra_info('socket')
|
|
||||||
self.assertNotEqual(sock.fileno(), -1)
|
|
||||||
|
|
||||||
wr.write(b'GET / HTTP/1.0\r\n\r\n')
|
|
||||||
f = rd.readline()
|
|
||||||
data = self.loop.run_until_complete(f)
|
|
||||||
self.assertEqual(data, b'HTTP/1.0 200 OK\r\n')
|
|
||||||
|
|
||||||
# drop refs to reader/writer
|
|
||||||
del rd
|
|
||||||
del wr
|
|
||||||
gc.collect()
|
|
||||||
# make a chance to close the socket
|
|
||||||
test_utils.run_briefly(self.loop)
|
|
||||||
|
|
||||||
self.assertEqual(1, len(messages))
|
|
||||||
self.assertEqual(sock.fileno(), -1)
|
|
||||||
|
|
||||||
self.assertEqual(1, len(messages))
|
|
||||||
self.assertEqual('An open stream object is being garbage '
|
|
||||||
'collected; call "stream.close()" explicitly.',
|
|
||||||
messages[0]['message'])
|
|
||||||
|
|
||||||
def test_del_stream_before_connection_made(self):
|
|
||||||
messages = []
|
|
||||||
self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx))
|
|
||||||
|
|
||||||
with test_utils.run_test_server() as httpd:
|
|
||||||
rd = asyncio.StreamReader(loop=self.loop)
|
|
||||||
pr = asyncio.StreamReaderProtocol(rd, loop=self.loop)
|
|
||||||
del rd
|
|
||||||
gc.collect()
|
|
||||||
tr, _ = self.loop.run_until_complete(
|
|
||||||
self.loop.create_connection(
|
|
||||||
lambda: pr, *httpd.address))
|
|
||||||
|
|
||||||
sock = tr.get_extra_info('socket')
|
|
||||||
self.assertEqual(sock.fileno(), -1)
|
|
||||||
|
|
||||||
self.assertEqual(1, len(messages))
|
|
||||||
self.assertEqual('An open stream was garbage collected prior to '
|
|
||||||
'establishing network connection; '
|
|
||||||
'call "stream.close()" explicitly.',
|
|
||||||
messages[0]['message'])
|
|
||||||
|
|
||||||
def test_async_writer_api(self):
|
def test_async_writer_api(self):
|
||||||
async def inner(httpd):
|
async def inner(httpd):
|
||||||
rd, wr = await asyncio.open_connection(*httpd.address)
|
rd, wr = await asyncio.open_connection(*httpd.address)
|
||||||
|
|
|
@ -24,7 +24,23 @@ class AuditTest(unittest.TestCase):
|
||||||
sys.stdout.writelines(p.stdout)
|
sys.stdout.writelines(p.stdout)
|
||||||
sys.stderr.writelines(p.stderr)
|
sys.stderr.writelines(p.stderr)
|
||||||
if p.returncode:
|
if p.returncode:
|
||||||
self.fail(''.join(p.stderr))
|
self.fail("".join(p.stderr))
|
||||||
|
|
||||||
|
def run_python(self, *args):
|
||||||
|
events = []
|
||||||
|
with subprocess.Popen(
|
||||||
|
[sys.executable, "-X utf8", AUDIT_TESTS_PY, *args],
|
||||||
|
encoding="utf-8",
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
) as p:
|
||||||
|
p.wait()
|
||||||
|
sys.stderr.writelines(p.stderr)
|
||||||
|
return (
|
||||||
|
p.returncode,
|
||||||
|
[line.strip().partition(" ") for line in p.stdout],
|
||||||
|
"".join(p.stderr),
|
||||||
|
)
|
||||||
|
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
self.do_test("test_basic")
|
self.do_test("test_basic")
|
||||||
|
@ -36,19 +52,11 @@ class AuditTest(unittest.TestCase):
|
||||||
self.do_test("test_block_add_hook_baseexception")
|
self.do_test("test_block_add_hook_baseexception")
|
||||||
|
|
||||||
def test_finalize_hooks(self):
|
def test_finalize_hooks(self):
|
||||||
events = []
|
returncode, events, stderr = self.run_python("test_finalize_hooks")
|
||||||
with subprocess.Popen(
|
if stderr:
|
||||||
[sys.executable, "-X utf8", AUDIT_TESTS_PY, "test_finalize_hooks"],
|
print(stderr, file=sys.stderr)
|
||||||
encoding="utf-8",
|
if returncode:
|
||||||
stdout=subprocess.PIPE,
|
self.fail(stderr)
|
||||||
stderr=subprocess.PIPE,
|
|
||||||
) as p:
|
|
||||||
p.wait()
|
|
||||||
for line in p.stdout:
|
|
||||||
events.append(line.strip().partition(" "))
|
|
||||||
sys.stderr.writelines(p.stderr)
|
|
||||||
if p.returncode:
|
|
||||||
self.fail(''.join(p.stderr))
|
|
||||||
|
|
||||||
firstId = events[0][2]
|
firstId = events[0][2]
|
||||||
self.assertSequenceEqual(
|
self.assertSequenceEqual(
|
||||||
|
@ -76,6 +84,40 @@ class AuditTest(unittest.TestCase):
|
||||||
def test_mmap(self):
|
def test_mmap(self):
|
||||||
self.do_test("test_mmap")
|
self.do_test("test_mmap")
|
||||||
|
|
||||||
|
def test_excepthook(self):
|
||||||
|
returncode, events, stderr = self.run_python("test_excepthook")
|
||||||
|
if not returncode:
|
||||||
|
self.fail(f"Expected fatal exception\n{stderr}")
|
||||||
|
|
||||||
|
self.assertSequenceEqual(
|
||||||
|
[("sys.excepthook", " ", "RuntimeError('fatal-error')")], events
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_unraisablehook(self):
|
||||||
|
returncode, events, stderr = self.run_python("test_unraisablehook")
|
||||||
|
if returncode:
|
||||||
|
self.fail(stderr)
|
||||||
|
|
||||||
|
self.assertEqual(events[0][0], "sys.unraisablehook")
|
||||||
|
self.assertEqual(
|
||||||
|
events[0][2],
|
||||||
|
"RuntimeError('nonfatal-error') Exception ignored for audit hook test",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_winreg(self):
|
||||||
|
support.import_module("winreg")
|
||||||
|
returncode, events, stderr = self.run_python("test_winreg")
|
||||||
|
if returncode:
|
||||||
|
self.fail(stderr)
|
||||||
|
|
||||||
|
self.assertEqual(events[0][0], "winreg.OpenKey")
|
||||||
|
self.assertEqual(events[1][0], "winreg.OpenKey/result")
|
||||||
|
expected = events[1][2]
|
||||||
|
self.assertTrue(expected)
|
||||||
|
self.assertSequenceEqual(["winreg.EnumKey", " ", f"{expected} 0"], events[2])
|
||||||
|
self.assertSequenceEqual(["winreg.EnumKey", " ", f"{expected} 10000"], events[3])
|
||||||
|
self.assertSequenceEqual(["winreg.PyHKEY.Detach", " ", expected], events[4])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -351,9 +351,11 @@ class CAPITest(unittest.TestCase):
|
||||||
for i in range(1000):
|
for i in range(1000):
|
||||||
L = MyList((L,))
|
L = MyList((L,))
|
||||||
|
|
||||||
|
@support.requires_resource('cpu')
|
||||||
def test_trashcan_python_class1(self):
|
def test_trashcan_python_class1(self):
|
||||||
self.do_test_trashcan_python_class(list)
|
self.do_test_trashcan_python_class(list)
|
||||||
|
|
||||||
|
@support.requires_resource('cpu')
|
||||||
def test_trashcan_python_class2(self):
|
def test_trashcan_python_class2(self):
|
||||||
from _testcapi import MyList
|
from _testcapi import MyList
|
||||||
self.do_test_trashcan_python_class(MyList)
|
self.do_test_trashcan_python_class(MyList)
|
||||||
|
|
|
@ -332,10 +332,10 @@ class CmdLineTest(unittest.TestCase):
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
self.assertEqual(b'1\r\n2\r\n', out)
|
self.assertEqual(b'1\r\n2\r\n', out)
|
||||||
self.assertEqual(b'3\r\n4', err)
|
self.assertEqual(b'3\r\n4\r\n', err)
|
||||||
else:
|
else:
|
||||||
self.assertEqual(b'1\n2\n', out)
|
self.assertEqual(b'1\n2\n', out)
|
||||||
self.assertEqual(b'3\n4', err)
|
self.assertEqual(b'3\n4\n', err)
|
||||||
|
|
||||||
def test_unmached_quote(self):
|
def test_unmached_quote(self):
|
||||||
# Issue #10206: python program starting with unmatched quote
|
# Issue #10206: python program starting with unmatched quote
|
||||||
|
@ -391,7 +391,7 @@ class CmdLineTest(unittest.TestCase):
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
preexec_fn=preexec)
|
preexec_fn=preexec)
|
||||||
out, err = p.communicate()
|
out, err = p.communicate()
|
||||||
self.assertEqual(support.strip_python_stderr(err), b'')
|
self.assertEqual(err, b'')
|
||||||
self.assertEqual(p.returncode, 42)
|
self.assertEqual(p.returncode, 42)
|
||||||
|
|
||||||
def test_no_stdin(self):
|
def test_no_stdin(self):
|
||||||
|
|
|
@ -223,12 +223,13 @@ class CmdLineTest(unittest.TestCase):
|
||||||
|
|
||||||
def test_script_abspath(self):
|
def test_script_abspath(self):
|
||||||
# pass the script using the relative path, expect the absolute path
|
# pass the script using the relative path, expect the absolute path
|
||||||
# in __file__ and sys.argv[0]
|
# in __file__
|
||||||
with support.temp_cwd() as script_dir:
|
with support.temp_cwd() as script_dir:
|
||||||
self.assertTrue(os.path.isabs(script_dir), script_dir)
|
self.assertTrue(os.path.isabs(script_dir), script_dir)
|
||||||
|
|
||||||
script_name = _make_test_script(script_dir, 'script')
|
script_name = _make_test_script(script_dir, 'script')
|
||||||
self._check_script(os.path.basename(script_name), script_name, script_name,
|
relative_name = os.path.basename(script_name)
|
||||||
|
self._check_script(relative_name, script_name, relative_name,
|
||||||
script_dir, None,
|
script_dir, None,
|
||||||
importlib.machinery.SourceFileLoader)
|
importlib.machinery.SourceFileLoader)
|
||||||
|
|
||||||
|
@ -535,7 +536,7 @@ class CmdLineTest(unittest.TestCase):
|
||||||
script_name = _make_test_script(script_dir, 'script', script)
|
script_name = _make_test_script(script_dir, 'script', script)
|
||||||
exitcode, stdout, stderr = assert_python_failure(script_name)
|
exitcode, stdout, stderr = assert_python_failure(script_name)
|
||||||
text = stderr.decode('ascii').split('\n')
|
text = stderr.decode('ascii').split('\n')
|
||||||
self.assertEqual(len(text), 4)
|
self.assertEqual(len(text), 5)
|
||||||
self.assertTrue(text[0].startswith('Traceback'))
|
self.assertTrue(text[0].startswith('Traceback'))
|
||||||
self.assertTrue(text[1].startswith(' File '))
|
self.assertTrue(text[1].startswith(' File '))
|
||||||
self.assertTrue(text[3].startswith('NameError'))
|
self.assertTrue(text[3].startswith('NameError'))
|
||||||
|
@ -579,7 +580,7 @@ class CmdLineTest(unittest.TestCase):
|
||||||
script_name = _make_test_script(script_dir, 'script', script)
|
script_name = _make_test_script(script_dir, 'script', script)
|
||||||
exitcode, stdout, stderr = assert_python_failure(script_name)
|
exitcode, stdout, stderr = assert_python_failure(script_name)
|
||||||
text = stderr.decode('ascii')
|
text = stderr.decode('ascii')
|
||||||
self.assertEqual(text, "some text")
|
self.assertEqual(text.rstrip(), "some text")
|
||||||
|
|
||||||
def test_syntaxerror_unindented_caret_position(self):
|
def test_syntaxerror_unindented_caret_position(self):
|
||||||
script = "1 + 1 = 2\n"
|
script = "1 + 1 = 2\n"
|
||||||
|
|
|
@ -38,9 +38,6 @@ class ContextTest(unittest.TestCase):
|
||||||
|
|
||||||
self.assertNotEqual(hash(c), hash('aaa'))
|
self.assertNotEqual(hash(c), hash('aaa'))
|
||||||
|
|
||||||
def test_context_var_new_2(self):
|
|
||||||
self.assertIsNone(contextvars.ContextVar[int])
|
|
||||||
|
|
||||||
@isolated_context
|
@isolated_context
|
||||||
def test_context_var_repr_1(self):
|
def test_context_var_repr_1(self):
|
||||||
c = contextvars.ContextVar('a')
|
c = contextvars.ContextVar('a')
|
||||||
|
@ -361,6 +358,10 @@ class ContextTest(unittest.TestCase):
|
||||||
tp.shutdown()
|
tp.shutdown()
|
||||||
self.assertEqual(results, list(range(10)))
|
self.assertEqual(results, list(range(10)))
|
||||||
|
|
||||||
|
def test_contextvar_getitem(self):
|
||||||
|
clss = contextvars.ContextVar
|
||||||
|
self.assertEqual(clss[str], clss)
|
||||||
|
|
||||||
|
|
||||||
# HAMT Tests
|
# HAMT Tests
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import builtins
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import Mock
|
from unittest.mock import Mock
|
||||||
from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional
|
from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional
|
||||||
|
from typing import get_type_hints
|
||||||
from collections import deque, OrderedDict, namedtuple
|
from collections import deque, OrderedDict, namedtuple
|
||||||
from functools import total_ordering
|
from functools import total_ordering
|
||||||
|
|
||||||
|
@ -2983,6 +2984,17 @@ class TestStringAnnotations(unittest.TestCase):
|
||||||
# won't exist on the instance.
|
# won't exist on the instance.
|
||||||
self.assertNotIn('not_iv4', c.__dict__)
|
self.assertNotIn('not_iv4', c.__dict__)
|
||||||
|
|
||||||
|
def test_text_annotations(self):
|
||||||
|
from test import dataclass_textanno
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
get_type_hints(dataclass_textanno.Bar),
|
||||||
|
{'foo': dataclass_textanno.Foo})
|
||||||
|
self.assertEqual(
|
||||||
|
get_type_hints(dataclass_textanno.Bar.__init__),
|
||||||
|
{'foo': dataclass_textanno.Foo,
|
||||||
|
'return': type(None)})
|
||||||
|
|
||||||
|
|
||||||
class TestMakeDataclass(unittest.TestCase):
|
class TestMakeDataclass(unittest.TestCase):
|
||||||
def test_simple(self):
|
def test_simple(self):
|
||||||
|
|
|
@ -278,32 +278,34 @@ dis_traceback = """\
|
||||||
--> 6 BINARY_TRUE_DIVIDE
|
--> 6 BINARY_TRUE_DIVIDE
|
||||||
8 POP_TOP
|
8 POP_TOP
|
||||||
10 POP_BLOCK
|
10 POP_BLOCK
|
||||||
12 JUMP_FORWARD 40 (to 54)
|
12 JUMP_FORWARD 44 (to 58)
|
||||||
|
|
||||||
%3d >> 14 DUP_TOP
|
%3d >> 14 DUP_TOP
|
||||||
16 LOAD_GLOBAL 0 (Exception)
|
16 LOAD_GLOBAL 0 (Exception)
|
||||||
18 COMPARE_OP 10 (exception match)
|
18 COMPARE_OP 10 (exception match)
|
||||||
20 POP_JUMP_IF_FALSE 52
|
20 POP_JUMP_IF_FALSE 56
|
||||||
22 POP_TOP
|
22 POP_TOP
|
||||||
24 STORE_FAST 0 (e)
|
24 STORE_FAST 0 (e)
|
||||||
26 POP_TOP
|
26 POP_TOP
|
||||||
28 SETUP_FINALLY 10 (to 40)
|
28 SETUP_FINALLY 18 (to 48)
|
||||||
|
|
||||||
%3d 30 LOAD_FAST 0 (e)
|
%3d 30 LOAD_FAST 0 (e)
|
||||||
32 LOAD_ATTR 1 (__traceback__)
|
32 LOAD_ATTR 1 (__traceback__)
|
||||||
34 STORE_FAST 1 (tb)
|
34 STORE_FAST 1 (tb)
|
||||||
36 POP_BLOCK
|
36 POP_BLOCK
|
||||||
38 BEGIN_FINALLY
|
38 POP_EXCEPT
|
||||||
>> 40 LOAD_CONST 0 (None)
|
40 LOAD_CONST 0 (None)
|
||||||
42 STORE_FAST 0 (e)
|
42 STORE_FAST 0 (e)
|
||||||
44 DELETE_FAST 0 (e)
|
44 DELETE_FAST 0 (e)
|
||||||
46 END_FINALLY
|
46 JUMP_FORWARD 10 (to 58)
|
||||||
48 POP_EXCEPT
|
>> 48 LOAD_CONST 0 (None)
|
||||||
50 JUMP_FORWARD 2 (to 54)
|
50 STORE_FAST 0 (e)
|
||||||
>> 52 END_FINALLY
|
52 DELETE_FAST 0 (e)
|
||||||
|
54 RERAISE
|
||||||
|
>> 56 RERAISE
|
||||||
|
|
||||||
%3d >> 54 LOAD_FAST 1 (tb)
|
%3d >> 58 LOAD_FAST 1 (tb)
|
||||||
56 RETURN_VALUE
|
60 RETURN_VALUE
|
||||||
""" % (TRACEBACK_CODE.co_firstlineno + 1,
|
""" % (TRACEBACK_CODE.co_firstlineno + 1,
|
||||||
TRACEBACK_CODE.co_firstlineno + 2,
|
TRACEBACK_CODE.co_firstlineno + 2,
|
||||||
TRACEBACK_CODE.co_firstlineno + 3,
|
TRACEBACK_CODE.co_firstlineno + 3,
|
||||||
|
@ -752,7 +754,7 @@ Argument count: 0
|
||||||
Positional-only arguments: 0
|
Positional-only arguments: 0
|
||||||
Kw-only arguments: 0
|
Kw-only arguments: 0
|
||||||
Number of locals: 2
|
Number of locals: 2
|
||||||
Stack size: 10
|
Stack size: 9
|
||||||
Flags: OPTIMIZED, NEWLOCALS, NOFREE, COROUTINE
|
Flags: OPTIMIZED, NEWLOCALS, NOFREE, COROUTINE
|
||||||
Constants:
|
Constants:
|
||||||
0: None
|
0: None
|
||||||
|
@ -977,10 +979,10 @@ expected_opinfo_jumpy = [
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=96, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=96, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=98, starts_line=None, is_jump_target=False),
|
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=98, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=100, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=100, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='SETUP_FINALLY', opcode=122, arg=70, argval=174, argrepr='to 174', offset=102, starts_line=20, is_jump_target=True),
|
Instruction(opname='SETUP_FINALLY', opcode=122, arg=98, argval=202, argrepr='to 202', offset=102, starts_line=20, is_jump_target=True),
|
||||||
Instruction(opname='SETUP_FINALLY', opcode=122, arg=12, argval=118, argrepr='to 118', offset=104, starts_line=None, is_jump_target=False),
|
Instruction(opname='SETUP_FINALLY', opcode=122, arg=12, argval=118, argrepr='to 118', offset=104, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=106, starts_line=21, is_jump_target=False),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=106, starts_line=21, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval=0, argrepr='0', offset=108, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=108, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=110, starts_line=None, is_jump_target=False),
|
Instruction(opname='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=110, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=112, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=112, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=114, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=114, starts_line=None, is_jump_target=False),
|
||||||
|
@ -993,33 +995,47 @@ expected_opinfo_jumpy = [
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=128, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=128, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=130, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=130, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=132, starts_line=23, is_jump_target=False),
|
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=132, starts_line=23, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=134, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=134, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=136, starts_line=None, is_jump_target=False),
|
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=136, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=138, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=138, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=140, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=140, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='JUMP_FORWARD', opcode=110, arg=26, argval=170, argrepr='to 170', offset=142, starts_line=None, is_jump_target=False),
|
Instruction(opname='JUMP_FORWARD', opcode=110, arg=46, argval=190, argrepr='to 190', offset=142, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=True),
|
Instruction(opname='RERAISE', opcode=48, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=True),
|
||||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=146, starts_line=25, is_jump_target=True),
|
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=146, starts_line=25, is_jump_target=True),
|
||||||
Instruction(opname='SETUP_WITH', opcode=143, arg=14, argval=164, argrepr='to 164', offset=148, starts_line=None, is_jump_target=False),
|
Instruction(opname='SETUP_WITH', opcode=143, arg=24, argval=174, argrepr='to 174', offset=148, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=150, starts_line=None, is_jump_target=False),
|
Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=150, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=152, starts_line=26, is_jump_target=False),
|
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=152, starts_line=26, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval='Never reach this', argrepr="'Never reach this'", offset=154, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=154, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=156, starts_line=None, is_jump_target=False),
|
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=156, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=158, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=158, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=160, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=160, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='BEGIN_FINALLY', opcode=53, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=162, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='WITH_CLEANUP_START', opcode=81, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=True),
|
Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='WITH_CLEANUP_FINISH', opcode=82, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False),
|
Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=168, starts_line=None, is_jump_target=False),
|
Instruction(opname='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=168, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=True),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='BEGIN_FINALLY', opcode=53, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False),
|
Instruction(opname='JUMP_FORWARD', opcode=110, arg=16, argval=190, argrepr='to 190', offset=172, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=174, starts_line=28, is_jump_target=True),
|
Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=174, starts_line=None, is_jump_target=True),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=176, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=180, argval=180, argrepr='', offset=176, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=178, starts_line=None, is_jump_target=False),
|
Instruction(opname='RERAISE', opcode=48, arg=None, argval=None, argrepr='', offset=178, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=True),
|
||||||
Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=184, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=184, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False),
|
||||||
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False),
|
||||||
|
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=190, starts_line=None, is_jump_target=True),
|
||||||
|
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=192, starts_line=28, is_jump_target=False),
|
||||||
|
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=194, starts_line=None, is_jump_target=False),
|
||||||
|
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=196, starts_line=None, is_jump_target=False),
|
||||||
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=198, starts_line=None, is_jump_target=False),
|
||||||
|
Instruction(opname='JUMP_FORWARD', opcode=110, arg=10, argval=212, argrepr='to 212', offset=200, starts_line=None, is_jump_target=False),
|
||||||
|
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=202, starts_line=None, is_jump_target=True),
|
||||||
|
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=204, starts_line=None, is_jump_target=False),
|
||||||
|
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=206, starts_line=None, is_jump_target=False),
|
||||||
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=208, starts_line=None, is_jump_target=False),
|
||||||
|
Instruction(opname='RERAISE', opcode=48, arg=None, argval=None, argrepr='', offset=210, starts_line=None, is_jump_target=False),
|
||||||
|
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=212, starts_line=None, is_jump_target=True),
|
||||||
|
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=214, starts_line=None, is_jump_target=False)
|
||||||
]
|
]
|
||||||
|
|
||||||
# One last piece of inspect fodder to check the default line number handling
|
# One last piece of inspect fodder to check the default line number handling
|
||||||
|
@ -1032,6 +1048,10 @@ expected_opinfo_simple = [
|
||||||
|
|
||||||
class InstructionTests(BytecodeTestCase):
|
class InstructionTests(BytecodeTestCase):
|
||||||
|
|
||||||
|
def __init__(self, *args):
|
||||||
|
super().__init__(*args)
|
||||||
|
self.maxDiff = None
|
||||||
|
|
||||||
def test_default_first_line(self):
|
def test_default_first_line(self):
|
||||||
actual = dis.get_instructions(simple)
|
actual = dis.get_instructions(simple)
|
||||||
self.assertEqual(list(actual), expected_opinfo_simple)
|
self.assertEqual(list(actual), expected_opinfo_simple)
|
||||||
|
@ -1063,6 +1083,7 @@ class InstructionTests(BytecodeTestCase):
|
||||||
# get_instructions has its own tests above, so can rely on it to validate
|
# get_instructions has its own tests above, so can rely on it to validate
|
||||||
# the object oriented API
|
# the object oriented API
|
||||||
class BytecodeTests(unittest.TestCase):
|
class BytecodeTests(unittest.TestCase):
|
||||||
|
|
||||||
def test_instantiation(self):
|
def test_instantiation(self):
|
||||||
# Test with function, method, code string and code object
|
# Test with function, method, code string and code object
|
||||||
for obj in [_f, _C(1).__init__, "a=1", _f.__code__]:
|
for obj in [_f, _C(1).__init__, "a=1", _f.__code__]:
|
||||||
|
|
|
@ -2583,6 +2583,11 @@ class TestParser(TestParserMixin, TestEmailBase):
|
||||||
|
|
||||||
# get_msg_id
|
# get_msg_id
|
||||||
|
|
||||||
|
def test_get_msg_id_empty(self):
|
||||||
|
# bpo-38708: Test that HeaderParseError is raised and not IndexError.
|
||||||
|
with self.assertRaises(errors.HeaderParseError):
|
||||||
|
parser.get_msg_id('')
|
||||||
|
|
||||||
def test_get_msg_id_valid(self):
|
def test_get_msg_id_valid(self):
|
||||||
msg_id = self._test_get_x(
|
msg_id = self._test_get_x(
|
||||||
parser.get_msg_id,
|
parser.get_msg_id,
|
||||||
|
@ -2638,6 +2643,46 @@ class TestParser(TestParserMixin, TestEmailBase):
|
||||||
)
|
)
|
||||||
self.assertEqual(msg_id.token_type, 'msg-id')
|
self.assertEqual(msg_id.token_type, 'msg-id')
|
||||||
|
|
||||||
|
def test_get_msg_id_invalid_expected_msg_id_not_found(self):
|
||||||
|
text = "935-XPB-567:0:45327:9:90305:17843586-40@example.com"
|
||||||
|
msg_id = parser.parse_message_id(text)
|
||||||
|
self.assertDefectsEqual(
|
||||||
|
msg_id.all_defects,
|
||||||
|
[errors.InvalidHeaderDefect])
|
||||||
|
|
||||||
|
def test_parse_invalid_message_id(self):
|
||||||
|
message_id = self._test_parse_x(
|
||||||
|
parser.parse_message_id,
|
||||||
|
"935-XPB-567:0:45327:9:90305:17843586-40@example.com",
|
||||||
|
"935-XPB-567:0:45327:9:90305:17843586-40@example.com",
|
||||||
|
"935-XPB-567:0:45327:9:90305:17843586-40@example.com",
|
||||||
|
[errors.InvalidHeaderDefect],
|
||||||
|
)
|
||||||
|
self.assertEqual(message_id.token_type, 'invalid-message-id')
|
||||||
|
|
||||||
|
def test_parse_valid_message_id(self):
|
||||||
|
message_id = self._test_parse_x(
|
||||||
|
parser.parse_message_id,
|
||||||
|
"<aperson@somedomain>",
|
||||||
|
"<aperson@somedomain>",
|
||||||
|
"<aperson@somedomain>",
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
self.assertEqual(message_id.token_type, 'message-id')
|
||||||
|
|
||||||
|
def test_parse_message_id_with_remaining(self):
|
||||||
|
message_id = self._test_parse_x(
|
||||||
|
parser.parse_message_id,
|
||||||
|
"<validmessageid@example>thensomething",
|
||||||
|
"<validmessageid@example>",
|
||||||
|
"<validmessageid@example>",
|
||||||
|
[errors.InvalidHeaderDefect],
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
self.assertEqual(message_id.token_type, 'message-id')
|
||||||
|
self.assertEqual(str(message_id.all_defects[0]),
|
||||||
|
"Unexpected 'thensomething'")
|
||||||
|
|
||||||
def test_get_msg_id_no_angle_start(self):
|
def test_get_msg_id_no_angle_start(self):
|
||||||
with self.assertRaises(errors.HeaderParseError):
|
with self.assertRaises(errors.HeaderParseError):
|
||||||
parser.get_msg_id("msgwithnoankle")
|
parser.get_msg_id("msgwithnoankle")
|
||||||
|
@ -2654,6 +2699,7 @@ class TestParser(TestParserMixin, TestEmailBase):
|
||||||
self.assertEqual(msg_id.token_type, 'msg-id')
|
self.assertEqual(msg_id.token_type, 'msg-id')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@parameterize
|
@parameterize
|
||||||
class Test_parse_mime_parameters(TestParserMixin, TestEmailBase):
|
class Test_parse_mime_parameters(TestParserMixin, TestEmailBase):
|
||||||
|
|
||||||
|
|
|
@ -858,10 +858,9 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
preconfig = {
|
preconfig = {
|
||||||
'allocator': PYMEM_ALLOCATOR_DEBUG,
|
'allocator': PYMEM_ALLOCATOR_DEBUG,
|
||||||
}
|
}
|
||||||
script_abspath = os.path.abspath('script.py')
|
|
||||||
config = {
|
config = {
|
||||||
'argv': [script_abspath],
|
'argv': ['script.py'],
|
||||||
'run_filename': script_abspath,
|
'run_filename': os.path.abspath('script.py'),
|
||||||
'dev_mode': 1,
|
'dev_mode': 1,
|
||||||
'faulthandler': 1,
|
'faulthandler': 1,
|
||||||
'warnoptions': ['default'],
|
'warnoptions': ['default'],
|
||||||
|
|
|
@ -71,9 +71,8 @@ class FaultHandlerTests(unittest.TestCase):
|
||||||
with support.SuppressCrashReport():
|
with support.SuppressCrashReport():
|
||||||
process = script_helper.spawn_python('-c', code, pass_fds=pass_fds)
|
process = script_helper.spawn_python('-c', code, pass_fds=pass_fds)
|
||||||
with process:
|
with process:
|
||||||
stdout, stderr = process.communicate()
|
output, stderr = process.communicate()
|
||||||
exitcode = process.wait()
|
exitcode = process.wait()
|
||||||
output = support.strip_python_stderr(stdout)
|
|
||||||
output = output.decode('ascii', 'backslashreplace')
|
output = output.decode('ascii', 'backslashreplace')
|
||||||
if filename:
|
if filename:
|
||||||
self.assertEqual(output, '')
|
self.assertEqual(output, '')
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue