Merge branch 'master' into feat/dataclass-init-args

This commit is contained in:
Laurie O 2019-12-10 10:48:47 +10:00
commit 4e90401d12
236 changed files with 7758 additions and 6651 deletions

View File

@ -31,7 +31,7 @@ jobs:
buildVersionToDownload: specific
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'
workingDirectory: '$(Build.BinariesDirectory)\nuget'
condition: and(succeeded(), not(variables['PublishArmPackages']))

View File

@ -39,7 +39,7 @@ jobs:
artifactName: embed
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'
workingDirectory: '$(Build.BinariesDirectory)\embed'
condition: and(succeeded(), not(variables['PublishArmPackages']))

11
.github/CODEOWNERS vendored
View File

@ -11,6 +11,7 @@
**/*context* @1st1
**/*genobject* @1st1
**/*hamt* @1st1
Objects/set* @rhettinger
Objects/dict* @methane
# Hashing
@ -93,6 +94,7 @@ Include/pytime.h @pganssle @abalkin
/Tools/msi/ @python/windows-team
/Tools/nuget/ @python/windows-team
# Misc
**/*itertools* @rhettinger
**/*collections* @rhettinger
**/*random* @rhettinger
@ -108,6 +110,15 @@ Include/pytime.h @pganssle @abalkin
**/*typing* @gvanrossum @ilevkivskyi
**/*asyncore @giampaolo
**/*asynchat @giampaolo
**/*ftplib @giampaolo
**/*shutil @giampaolo
**/*enum* @ethanfurman
**/*cgi* @ethanfurman
**/*tarfile* @ethanfurman
# macOS
/Mac/ @python/macos-team
**/*osx_support* @python/macos-team

3
.gitignore vendored
View File

@ -6,7 +6,8 @@
*.iml
*.o
*.a
*.so*
*.so
*.so.*
*.dylib
*.dll
*.orig

View File

@ -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
:c:type:`PyLongObject`.
If the value of *obj* is greater than :const:`PY_LLONG_MAX` or less than
:const:`PY_LLONG_MIN`, set *\*overflow* to ``1`` or ``-1``, respectively,
If the value of *obj* is greater than :const:`LLONG_MAX` or less than
:const:`LLONG_MIN`, set *\*overflow* to ``1`` or ``-1``, respectively,
and return ``-1``; otherwise, set *\*overflow* to ``0``. If any other
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`.
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`
to disambiguate.

View File

@ -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, ...)
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.
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
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.
.. 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)
Adds to the collection of active auditing hooks. Returns zero for success
and non-zero on failure. If the runtime has been initialized, also sets an
Append the callable *hook* to the list of active auditing hooks.
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
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
after runtime initialization, existing audit hooks are notified and may
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
held by the Python interpreter that raised the event.
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.
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>`.
runtime and standard library that raise events are listed in the
:ref:`audit events table <audit-events>`.
Details are in each function's documentation.
.. audit-event:: sys.addaudithook "" c.PySys_AddAuditHook

View File

@ -955,7 +955,7 @@ and :c:type:`PyType_Type` effectively act as defaults.)
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
supported. It is usually convenient to set this field to

View File

@ -197,11 +197,6 @@ access internal read-only data of Unicode objects:
.. 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)
Return the size of the deprecated :c:type:`Py_UNICODE` representation, in

View File

@ -3045,8 +3045,6 @@ Py_XINCREF:PyObject*:o:+1:if o is not NULL
_PyImport_Fini:void:::
_PyImport_Init:void:::
_PyObject_New:PyObject*::+1:
_PyObject_New:PyTypeObject*:type:0:

View File

@ -1545,7 +1545,7 @@ Python's own build procedures.
=================================================
.. 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
@ -1684,7 +1684,7 @@ lines, and joining lines with backslashes.
===================================================
.. module:: distutils.version
:synopsis: implements classes that represent module version numbers.
:synopsis: Implements classes that represent module version numbers.
.. % todo
@ -1699,7 +1699,7 @@ lines, and joining lines with backslashes.
===================================================================
.. 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.
@ -1792,7 +1792,7 @@ Subclasses of :class:`Command` must define the following methods.
==========================================================
.. 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}
@ -2039,7 +2039,7 @@ This is described in more detail in :pep:`301`.
===================================================================
.. 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.

View File

@ -456,7 +456,7 @@ and off individually. They are described here in more detail.
-------------------------------
.. module:: lib2to3
:synopsis: the 2to3 library
:synopsis: The 2to3 library
.. moduleauthor:: Guido van Rossum
.. moduleauthor:: Collin Winter

View File

@ -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.
.. method:: array.fromstring()
Deprecated alias for :meth:`frombytes`.
.. method:: array.fromunicode(s)
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.
.. method:: array.tostring()
Deprecated alias for :meth:`tobytes`.
.. method:: array.tounicode()
Convert the array to a unicode string. The array must be a type ``'u'`` array;

View File

@ -161,6 +161,19 @@ and classes for traversing abstract syntax trees:
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)
Safely evaluate an expression node or a string containing a Python literal or

View File

@ -473,6 +473,21 @@ Opening network connections
reuse_address=None, reuse_port=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.
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
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
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
@ -527,6 +537,10 @@ Opening network connections
The *family*, *proto*, *flags*, *reuse_address*, *reuse_port,
*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
Added support for Windows.

View File

@ -588,9 +588,6 @@ Buffered Streaming Protocols
----------------------------
.. 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
that supports `Streaming Protocols`_.

View File

@ -7,7 +7,7 @@ Audit events table
This table contains all events raised by :func:`sys.audit` or
: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
information on handling these events.

View File

@ -881,7 +881,7 @@ Other constructors, all class methods:
Because naive ``datetime`` objects are treated by many ``datetime`` methods
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
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)
@ -942,7 +942,7 @@ Other constructors, all class methods:
Because naive ``datetime`` objects are treated by many ``datetime`` methods
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
specific timestamp in UTC by calling
specific timestamp in UTC is by calling
``datetime.fromtimestamp(timestamp, tz=timezone.utc)``.
.. 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, | |
| | 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). | | |
+-----------+--------------------------------+------------------------+-------+
| ``%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'``.
``%Z``
If :meth:`tzname` returns ``None``, ``%Z`` is replaced by an empty
string. Otherwise ``%Z`` is replaced by the returned value, which must
be a string.
In :meth:`strftime`, ``%Z`` is replaced by an empty string if
:meth:`tzname` returns ``None``; otherwise ``%Z`` is replaced by the
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
When the ``%z`` directive is provided to the :meth:`strptime` method, an

View File

@ -706,50 +706,21 @@ iterations of the loop.
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
``0`` TOS first is popped from the stack and pushed on the stack after
performing other stack operations:
Re-raises the exception currently on top of the stack.
* If TOS is ``NULL`` or an integer (pushed by :opcode:`BEGIN_FINALLY`
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
.. versionadded:: 3.9
.. opcode:: BEGIN_FINALLY
.. opcode:: WITH_EXCEPT_START
Pushes ``NULL`` onto the stack for using it in :opcode:`END_FINALLY`,
:opcode:`POP_FINALLY`, :opcode:`WITH_CLEANUP_START` and
:opcode:`WITH_CLEANUP_FINISH`. Starts the :keyword:`finally` block.
Calls the function in position 7 on the stack with the top three
items on the stack as arguments.
Used to implement the call ``context_manager.__exit__(*exc_info())`` when an exception
has occurred in a :keyword:`with` statement.
.. versionadded:: 3.8
.. 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.
.. versionadded:: 3.9
.. opcode:: LOAD_ASSERTION_ERROR
@ -780,35 +751,6 @@ iterations of the loop.
.. 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.
.. 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.
.. 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)
Pushes a reference to the local ``co_varnames[var_num]`` onto the stack.

View File

@ -199,7 +199,8 @@ Format Paragraph
Strip trailing whitespace
Remove trailing space and other whitespace characters after the last
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::
single: Run script

View File

@ -732,12 +732,24 @@ Command line options
.. 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
Parse every input line as separate JSON object.
.. versionadded:: 3.8
.. cmdoption:: --indent, --tab, --no-indent, --compact
Mutually exclusive options for whitespace control
.. versionadded:: 3.9
.. cmdoption:: -h, --help
Show the help message.

View File

@ -2,7 +2,7 @@
================================================
.. 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>

View File

@ -2169,7 +2169,8 @@ with the :class:`Pool` class.
.. method:: map(func, iterable[, chunksize])
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
the process pool as separate tasks. The (approximate) size of these

View File

@ -165,8 +165,9 @@ Functions for sequences
The *weights* or *cum_weights* can use any numeric type that interoperates
with the :class:`float` values returned by :func:`random` (that includes
integers, floats, and fractions but excludes decimals). Weights are
assumed to be non-negative.
integers, floats, and fractions but excludes decimals). Behavior is
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
typically produces a different sequence than repeated calls to
@ -177,6 +178,9 @@ Functions for sequences
.. versionadded:: 3.6
.. versionchanged:: 3.9
Raises a :exc:`ValueError` if all weights are zero.
.. function:: shuffle(x[, random])

View File

@ -1411,9 +1411,9 @@ to sockets.
fds = array.array("i") # Array of ints
msg, ancdata, flags, addr = sock.recvmsg(msglen, socket.CMSG_LEN(maxfds * fds.itemsize))
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.
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)
.. availability:: most Unix platforms, possibly others.

View File

@ -1256,6 +1256,9 @@ SSL sockets also have the following additional methods and attributes:
The returned dictionary includes additional X509v3 extension items
such as ``crlDistributionPoints``, ``caIssuers`` and ``OCSP`` URIs.
.. versionchanged:: 3.9
IPv6 address strings no longer have a trailing new line.
.. method:: SSLSocket.cipher()
Returns a three-value tuple containing the name of the cipher being used, the

View File

@ -2,7 +2,7 @@
=======================================================
.. module:: statistics
:synopsis: mathematical statistics functions
:synopsis: Mathematical statistics functions
.. moduleauthor:: Steven D'Aprano <steve+python@pearwood.info>
.. sectionauthor:: Steven D'Aprano <steve+python@pearwood.info>

View File

@ -25,7 +25,7 @@ always available.
.. 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.
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
Raises a auditing event ``sys.addaudithook`` with no arguments. If any
existing hooks raise an exception derived from :class:`Exception`, the
Raise an auditing event ``sys.addaudithook`` with no arguments. If any
existing hooks raise an exception derived from :class:`RuntimeError`, the
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
all existing hooks.
.. versionadded:: 3.8
.. versionchanged:: 3.8.1
Exceptions derived from :class:`Exception` but not :class:`RuntimeError`
are no longer suppressed.
.. impl-detail::
When tracing is enabled (see :func:`settrace`), Python hooks are only
@ -74,7 +79,7 @@ always available.
.. 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
types of arguments. The schema for a given event is considered public and
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
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::
The :func:`sys.unraisablehook` function handles unraisable exceptions
@ -1540,6 +1554,13 @@ always available.
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
.. data:: version

View File

@ -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.
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
whether binary or text *mode* was specified) or a true file
is either an :class:`io.BytesIO` or :class:`io.TextIOWrapper` object
(depending on whether binary or text *mode* was specified) or a true file
object, depending on whether :func:`rollover` has been called. This
file-like object can be used in a :keyword:`with` statement, just like
a normal file.

View File

@ -686,13 +686,6 @@ The :mod:`test.support` module defines the following functions:
``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()
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``,
``__cwd``, and ``TERM``.
.. versionchanged:: 3.9
The function no longer strips whitespaces from *stderr*.
.. function:: assert_python_ok(*args, **env_vars)
@ -1512,6 +1508,9 @@ script execution tests.
Python is started in isolated mode (command line option ``-I``),
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)
@ -1521,6 +1520,9 @@ script execution tests.
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)

View File

@ -496,6 +496,10 @@ All methods are executed atomically.
There is no return value.
.. method:: locked()
Return true if the lock is acquired.
.. _rlock-objects:

View File

@ -42,17 +42,12 @@ An explanation of some terminology and conventions is in order.
library; for 32-bit systems, it is typically in 2038.
.. index::
single: Year 2000
single: Y2K
single: 2-digit years
.. _time-y2kissues:
* **Year 2000 (Y2K) issues**: Python depends on the platform's C library, which
generally doesn't have year 2000 issues, since all dates and times are
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.
* 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::
single: UTC

View File

@ -132,7 +132,7 @@ creation according to their needs, the :class:`EnvBuilder` class.
.. versionadded:: 3.6
Added the ``prompt`` parameter
.. versionadded:: 3.8
.. versionadded:: 3.9
Added the ``upgrade_deps`` parameter
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
``pip`` executable in the environment.
.. versionadded:: 3.8
.. versionadded:: 3.9
.. method:: post_setup(context)

View File

@ -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
:exc:`OSError` exception is raised.
.. audit-event:: winreg.ConnectRegistry computer_name,key winreg.ConnectRegistry
.. versionchanged:: 3.3
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
: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
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
: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
.. 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 fails, an :exc:`OSError` exception is raised.
.. audit-event:: winreg.DeleteKey key,sub_key,access winreg.DeleteKey
.. versionchanged:: 3.3
See :ref:`above <exception-changed>`.
@ -158,6 +170,8 @@ This module offers the following functions:
On unsupported Windows versions, :exc:`NotImplementedError` is raised.
.. audit-event:: winreg.DeleteKey key,sub_key,access winreg.DeleteKeyEx
.. versionadded:: 3.2
.. versionchanged:: 3.3
@ -173,6 +187,8 @@ This module offers the following functions:
*value* is a string that identifies the value to remove.
.. audit-event:: winreg.DeleteValue key,value winreg.DeleteValue
.. function:: EnumKey(key, index)
@ -187,6 +203,8 @@ This module offers the following functions:
typically called repeatedly until an :exc:`OSError` exception is
raised, indicating, no more values are available.
.. audit-event:: winreg.EnumKey key,index winreg.EnumKey
.. versionchanged:: 3.3
See :ref:`above <exception-changed>`.
@ -220,6 +238,8 @@ This module offers the following functions:
| | :meth:`SetValueEx`) |
+-------+--------------------------------------------+
.. audit-event:: winreg.EnumValue key,index winreg.EnumValue
.. versionchanged:: 3.3
See :ref:`above <exception-changed>`.
@ -235,6 +255,8 @@ This module offers the following functions:
>>> ExpandEnvironmentStrings('%windir%')
'C:\\Windows'
.. audit-event:: winreg.ExpandEnvironmentStrings str winreg.ExpandEnvironmentStrings
.. 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
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)
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.
.. audit-event:: winreg.OpenKey key,sub_key,access winreg.OpenKey
.. audit-event:: winreg.OpenKey/result key winreg.OpenKey
.. versionchanged:: 3.2
Allow the use of named arguments.
@ -330,6 +358,8 @@ This module offers the following functions:
| | nanoseconds since Jan 1, 1601. |
+-------+---------------------------------------------+
.. audit-event:: winreg.QueryInfoKey key winreg.QueryInfoKey
.. 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
:func:`QueryValueEx` if possible.
.. audit-event:: winreg.QueryValue key,sub_key,value_name winreg.QueryValue
.. function:: QueryValueEx(key, value_name)
@ -370,6 +402,8 @@ This module offers the following functions:
| | :meth:`SetValueEx`) |
+-------+-----------------------------------------+
.. audit-event:: winreg.QueryValue key,sub_key,value_name winreg.QueryValueEx
.. 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.
.. audit-event:: winreg.SaveKey key,file_name winreg.SaveKey
.. 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
:const:`KEY_SET_VALUE` access.
.. audit-event:: winreg.SetValue key,sub_key,type,value winreg.SetValue
.. 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
registry. This helps the registry perform efficiently.
.. audit-event:: winreg.SetValue key,sub_key,type,value winreg.SetValueEx
.. 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
subkeys.
.. audit-event:: winreg.DisableReflectionKey key winreg.DisableReflectionKey
.. 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.
.. audit-event:: winreg.EnableReflectionKey key winreg.EnableReflectionKey
.. function:: QueryReflectionKey(key)
@ -489,6 +533,8 @@ This module offers the following functions:
Will generally raise :exc:`NotImplementedError` if executed on a 32-bit
operating system.
.. audit-event:: winreg.QueryReflectionKey key winreg.QueryReflectionKey
.. _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
underlying Win32 handle to exist beyond the lifetime of the handle object.
.. audit-event:: winreg.PyHKEY.Detach key winreg.PyHKEY.Detach
.. method:: PyHKEY.__enter__()
PyHKEY.__exit__(\*exc_info)

View File

@ -494,7 +494,7 @@ Path objects are traversable using the ``/`` operator.
Invoke :meth:`ZipFile.open` on the current path. Accepts
the same arguments as :meth:`ZipFile.open`.
.. method:: Path.listdir()
.. method:: Path.iterdir()
Enumerate the children of the current directory.

View File

@ -2,7 +2,7 @@
=====================================================
.. 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>

View File

@ -1655,8 +1655,22 @@ class' :attr:`~object.__dict__`.
Called at the time the owning class *owner* is created. The
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
as specifying the class where this object was defined (setting this

View File

@ -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/socket,,::,'5aef:2b::8'
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,,:memory,
library/sqlite3,,:who,"cur.execute(""select * from people where name_last=:who and age=:age"", {""who"": who, ""age"": age})"

1 c-api/arg :ref PyArg_ParseTuple(args, "O|O:ref", &object, &callback)
201 library/smtplib :port method must support that as well as a regular host:port
202 library/socket :: '5aef:2b::8'
203 library/socket :can return (can_id, can_dlc, data[:can_dlc])
204 library/socket :len fds.fromstring(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) fds.frombytes(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)])
205 library/sqlite3 :age cur.execute("select * from people where name_last=:who and age=:age", {"who": who, "age": age})
206 library/sqlite3 :memory
207 library/sqlite3 :who cur.execute("select * from people where name_last=:who and age=:age", {"who": who, "age": age})

View File

@ -104,7 +104,7 @@ directory containing the virtual environment):
+=============+=================+=========================================+
| 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 |
+-------------+-----------------+-----------------------------------------+

View File

@ -121,6 +121,11 @@ Added the *indent* option to :func:`~ast.dump` which allows it to produce a
multiline indented output.
(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
-------
@ -179,8 +184,8 @@ case), and one used ``__VENV_NAME__`` instead.
pathlib
-------
Added :meth:`~pathlib.Path.readlink()` which acts similar to
:func:`~os.readlink`.
Added :meth:`pathlib.Path.readlink()` which acts similarly to
:func:`os.readlink`.
(Contributed by Girts Folkmanis in :issue:`30618`)
pprint
@ -235,6 +240,10 @@ Build and C API Changes
functions: the free lists of bound method objects have been removed.
(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
==========
@ -270,6 +279,11 @@ Deprecated
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
exposed in the regular :mod:`collections` module. This will help
create a clearer distinction between the concrete classes and the abstract

View File

@ -147,7 +147,6 @@ struct _ts {
The caller must hold the GIL.*/
PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_Get(void);
PyAPI_FUNC(int) _PyState_AddModule(PyObject*, struct PyModuleDef*);
PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *);
/* Similar to PyThreadState_Get(), but don't issue a fatal error

View File

@ -40,11 +40,9 @@ extern PyObject * _PyBuiltin_Init(PyThreadState *tstate);
extern PyStatus _PySys_Create(
PyThreadState *tstate,
PyObject **sysmod_p);
extern PyStatus _PySys_SetPreliminaryStderr(PyObject *sysdict);
extern PyStatus _PySys_ReadPreinitWarnOptions(PyWideStringList *options);
extern PyStatus _PySys_ReadPreinitXOptions(PyConfig *config);
extern int _PySys_InitMain(PyThreadState *tstate);
extern PyStatus _PyImport_Init(PyThreadState *tstate);
extern PyStatus _PyExc_Init(void);
extern PyStatus _PyErr_Init(void);
extern PyStatus _PyBuiltins_AddExceptions(PyObject * bltinmod);
@ -77,7 +75,7 @@ extern void _PyImport_Fini2(void);
extern void _PyGC_Fini(PyThreadState *tstate);
extern void _PyType_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 _PyFaulthandler_Fini(void);
extern void _PyHash_Fini(void);

View File

@ -324,6 +324,12 @@ extern void _PyInterpreterState_ClearModules(PyInterpreterState *interp);
PyAPI_FUNC(void) _PyGILState_Reinit(_PyRuntimeState *runtime);
PyAPI_FUNC(int) _PyState_AddModule(
PyThreadState *tstate,
PyObject* module,
struct PyModuleDef* def);
#ifdef __cplusplus
}
#endif

8
Include/opcode.h generated
View File

@ -30,10 +30,11 @@ extern "C" {
#define BINARY_TRUE_DIVIDE 27
#define INPLACE_FLOOR_DIVIDE 28
#define INPLACE_TRUE_DIVIDE 29
#define RERAISE 48
#define WITH_EXCEPT_START 49
#define GET_AITER 50
#define GET_ANEXT 51
#define BEFORE_ASYNC_WITH 52
#define BEGIN_FINALLY 53
#define END_ASYNC_FOR 54
#define INPLACE_ADD 55
#define INPLACE_SUBTRACT 56
@ -59,14 +60,11 @@ extern "C" {
#define INPLACE_AND 77
#define INPLACE_XOR 78
#define INPLACE_OR 79
#define WITH_CLEANUP_START 81
#define WITH_CLEANUP_FINISH 82
#define RETURN_VALUE 83
#define IMPORT_STAR 84
#define SETUP_ANNOTATIONS 85
#define YIELD_VALUE 86
#define POP_BLOCK 87
#define END_FINALLY 88
#define POP_EXCEPT 89
#define HAVE_ARGUMENT 90
#define STORE_NAME 90
@ -127,8 +125,6 @@ extern "C" {
#define BUILD_TUPLE_UNPACK_WITH_CALL 158
#define LOAD_METHOD 160
#define CALL_METHOD 161
#define CALL_FINALLY 162
#define POP_FINALLY 163
/* 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

View File

@ -51,16 +51,16 @@ PyAPI_FUNC(int) PyThread_acquire_lock(PyThread_type_lock, int);
#if defined(_POSIX_THREADS)
/* PyThread_acquire_lock_timed() uses _PyTime_FromNanoseconds(us * 1000),
convert microseconds to nanoseconds. */
# define PY_TIMEOUT_MAX (PY_LLONG_MAX / 1000)
# define PY_TIMEOUT_MAX (LLONG_MAX / 1000)
#elif defined (NT_THREADS)
/* 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)
# else
# define PY_TIMEOUT_MAX PY_LLONG_MAX
# define PY_TIMEOUT_MAX LLONG_MAX
# endif
#else
# define PY_TIMEOUT_MAX PY_LLONG_MAX
# define PY_TIMEOUT_MAX LLONG_MAX
#endif

View File

@ -328,17 +328,6 @@ PyAPI_FUNC(wchar_t*) PyUnicode_AsWideCharString(
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 =====================================================
Many of these APIs take two arguments encoding and errors. These

View File

@ -87,7 +87,6 @@ __all__ = [
import os as _os
import re as _re
import shutil as _shutil
import sys as _sys
from gettext import gettext as _, ngettext
@ -167,7 +166,8 @@ class HelpFormatter(object):
# default setting for width
if width is None:
width = _shutil.get_terminal_size().columns
import shutil
width = shutil.get_terminal_size().columns
width -= 2
self._prog = prog
@ -264,7 +264,7 @@ class HelpFormatter(object):
invocations.append(get_invocation(subaction))
# 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
self._action_max_length = max(self._action_max_length,
action_length)

View File

@ -24,6 +24,7 @@
:copyright: Copyright 2008 by Armin Ronacher.
:license: Python License.
"""
import sys
from _ast import *
@ -551,6 +552,704 @@ _const_node_type_names = {
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():
import argparse

View File

@ -66,6 +66,10 @@ _HAS_IPv6 = hasattr(socket, 'AF_INET6')
# Maximum timeout passed to select to avoid OS limitations
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):
cb = handle._callback
@ -1230,7 +1234,7 @@ class BaseEventLoop(events.AbstractEventLoop):
async def create_datagram_endpoint(self, protocol_factory,
local_addr=None, remote_addr=None, *,
family=0, proto=0, flags=0,
reuse_address=None, reuse_port=None,
reuse_address=_unset, reuse_port=None,
allow_broadcast=None, sock=None):
"""Create datagram connection."""
if sock is not None:
@ -1239,7 +1243,7 @@ class BaseEventLoop(events.AbstractEventLoop):
f'A UDP Socket was expected, got {sock!r}')
if (local_addr or remote_addr 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
opts = dict(local_addr=local_addr, remote_addr=remote_addr,
family=family, proto=proto, flags=flags,
@ -1306,8 +1310,18 @@ class BaseEventLoop(events.AbstractEventLoop):
exceptions = []
if reuse_address is None:
reuse_address = os.name == 'posix' and sys.platform != 'cygwin'
# bpo-37228
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),
(local_address, remote_address)) in addr_pairs_info:
@ -1316,9 +1330,6 @@ class BaseEventLoop(events.AbstractEventLoop):
try:
sock = socket.socket(
family=family, type=socket.SOCK_DGRAM, proto=proto)
if reuse_address:
sock.setsockopt(
socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if reuse_port:
_set_reuseport(sock)
if allow_broadcast:

View File

@ -636,7 +636,7 @@ class BaseDefaultEventLoopPolicy(AbstractEventLoopPolicy):
"""
if (self._local._loop is None 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())
if self._local._loop is None:

View File

@ -103,6 +103,9 @@ class Future:
context['source_traceback'] = self._source_traceback
self._loop.call_exception_handler(context)
def __class_getitem__(cls, type):
return cls
@property
def _log_traceback(self):
return self.__log_traceback

View File

@ -76,6 +76,9 @@ class Queue:
def __str__(self):
return f'<{type(self).__name__} {self._format()}>'
def __class_getitem__(cls, type):
return cls
def _format(self):
result = f'maxsize={self._maxsize!r}'
if getattr(self, '_queue', None):

View File

@ -40,6 +40,11 @@ def _test_selector_event(selector, fd, 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):
"""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
nbytes.
"""
_check_ssl_socket(sock)
if self._debug and sock.gettimeout() != 0:
raise ValueError("the socket must be non-blocking")
try:
@ -386,6 +392,7 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop):
The received data is written into *buf* (a writable buffer).
The return value is the number of bytes written.
"""
_check_ssl_socket(sock)
if self._debug and sock.gettimeout() != 0:
raise ValueError("the socket must be non-blocking")
try:
@ -425,6 +432,7 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop):
raised, and there is no way to determine how much data, if any, was
successfully processed by the receiving end of the connection.
"""
_check_ssl_socket(sock)
if self._debug and sock.gettimeout() != 0:
raise ValueError("the socket must be non-blocking")
try:
@ -472,6 +480,7 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop):
This method is a coroutine.
"""
_check_ssl_socket(sock)
if self._debug and sock.gettimeout() != 0:
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
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:
raise ValueError("the socket must be non-blocking")
fut = self.create_future()

View File

@ -214,8 +214,7 @@ class StreamReaderProtocol(FlowControlMixin, protocols.Protocol):
def __init__(self, stream_reader, client_connected_cb=None, loop=None):
super().__init__(loop=loop)
if stream_reader is not None:
self._stream_reader_wr = weakref.ref(stream_reader,
self._on_reader_gc)
self._stream_reader_wr = weakref.ref(stream_reader)
self._source_traceback = stream_reader._source_traceback
else:
self._stream_reader_wr = None
@ -231,22 +230,6 @@ class StreamReaderProtocol(FlowControlMixin, protocols.Protocol):
self._over_ssl = False
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
def _stream_reader(self):
if self._stream_reader_wr is None:

View File

@ -175,6 +175,9 @@ class Task(futures._PyFuture): # Inherit Python Task implementation
self._loop.call_exception_handler(context)
super().__del__()
def __class_getitem__(cls, type):
return cls
def _repr_info(self):
return base_tasks._task_repr_info(self)

View File

@ -930,9 +930,20 @@ class PidfdChildWatcher(AbstractChildWatcher):
def _do_wait(self, pid):
pidfd, callback, args = self._callbacks.pop(pid)
self._loop._remove_reader(pidfd)
try:
_, status = os.waitpid(pid, 0)
os.close(pidfd)
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)
callback(pid, returncode, *args)
def remove_child_handler(self, pid):
@ -1406,8 +1417,7 @@ class _UnixDefaultEventLoopPolicy(events.BaseDefaultEventLoopPolicy):
with events._lock:
if self._watcher is None: # pragma: no branch
self._watcher = ThreadedChildWatcher()
if isinstance(threading.current_thread(),
threading._MainThread):
if threading.current_thread() is threading.main_thread():
self._watcher.attach_loop(self._local._loop)
def set_event_loop(self, loop):
@ -1421,7 +1431,7 @@ class _UnixDefaultEventLoopPolicy(events.BaseDefaultEventLoopPolicy):
super().set_event_loop(loop)
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)
def get_child_watcher(self):

View File

@ -93,10 +93,13 @@ def _maybe_compile(compiler, source, filename, symbol):
except SyntaxError as e:
err2 = e
try:
if code:
return code
if not code1 and repr(err1) == repr(err2):
raise err1
finally:
err1 = err2 = None
def _compile(source, filename, symbol):
return compile(source, filename, symbol, PyCF_DONT_IMPLY_DEDENT)

View File

@ -149,6 +149,8 @@ def framework_find(fn, executable_path=None, env=None):
return dyld_find(fn, executable_path=executable_path, env=env)
except ValueError:
raise error
finally:
error = None
def test_dyld_find():
env = {}

View File

@ -378,11 +378,8 @@ def _create_fn(name, args, body, *, globals=None, locals=None,
# worries about external callers.
if locals is None:
locals = {}
# __builtins__ may be the "builtins" module or
# the value of its "__dict__",
# so make sure "__builtins__" is the module.
if globals is not None and '__builtins__' not in globals:
globals['__builtins__'] = builtins
if 'BUILTINS' not in locals:
locals['BUILTINS'] = builtins
return_annotation = ''
if return_type is not MISSING:
locals['_return_type'] = return_type
@ -391,10 +388,14 @@ def _create_fn(name, args, body, *, globals=None, locals=None,
body = '\n'.join(f' {b}' for b in body)
# 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)
return locals[name]
local_vars = ', '.join(locals.keys())
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):
@ -405,7 +406,7 @@ def _field_assign(frozen, name, value, self_name):
# self_name is what "self" is called in this function: don't
# hard-code "self", since that might be a field name.
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}'
@ -482,15 +483,18 @@ def _init_param(f):
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.
globals = {'MISSING': MISSING,
'_HAS_DEFAULT_FACTORY': _HAS_DEFAULT_FACTORY}
locals = {f'_type_{f.name}': f.type for f in fields}
locals.update({
'MISSING': MISSING,
'_HAS_DEFAULT_FACTORY': _HAS_DEFAULT_FACTORY,
})
body_lines = []
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
# initialization (it's a pseudo-field). Just skip it.
if line:
@ -520,7 +524,6 @@ def _init_fn(fields, frozen, has_post_init, self_name):
args.append("*")
args.append(_init_param(f))
locals = {f'_type_{f.name}': f.type for f in fields}
return _create_fn('__init__',
args,
body_lines,
@ -529,20 +532,19 @@ def _init_fn(fields, frozen, has_post_init, self_name):
return_type=None)
def _repr_fn(fields):
def _repr_fn(fields, globals):
fn = _create_fn('__repr__',
('self',),
['return self.__class__.__qualname__ + f"(' +
', '.join([f"{f.name}={{self.{f.name}!r}}"
for f in fields]) +
')"'])
')"'],
globals=globals)
return _recursive_repr(fn)
def _frozen_get_del_attr(cls, fields):
# XXX: globals is modified on the first call to _create_fn, then
# the modified version is used in the second call. Is this okay?
globals = {'cls': cls,
def _frozen_get_del_attr(cls, fields, globals):
locals = {'cls': cls,
'FrozenInstanceError': FrozenInstanceError}
if 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}:',
' raise FrozenInstanceError(f"cannot assign to field {name!r}")',
f'super(cls, self).__setattr__(name, value)'),
locals=locals,
globals=globals),
_create_fn('__delattr__',
('self', 'name'),
(f'if type(self) is cls or name in {fields_str}:',
' raise FrozenInstanceError(f"cannot delete field {name!r}")',
f'super(cls, self).__delattr__(name)'),
locals=locals,
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
# named 'x' and 'y', then self_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'),
[ 'if other.__class__ is self.__class__:',
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)
return _create_fn('__hash__',
('self',),
[f'return hash({self_tuple})'])
[f'return hash({self_tuple})'],
globals=globals)
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
# 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
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)]
return _hash_fn(flds)
return _hash_fn(flds, globals)
def _hash_exception(cls, fields):
def _hash_exception(cls, fields, globals):
# Raise an exception.
raise TypeError(f'Cannot overwrite attribute __hash__ '
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.
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,
unsafe_hash, frozen))
@ -912,6 +928,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
# if possible.
'__dataclass_self__' if 'self' in fields
else 'self',
globals,
))
# 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:
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:
# 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)
_set_new_attribute(cls, '__eq__',
_cmp_fn('__eq__', '==',
self_tuple, other_tuple))
self_tuple, other_tuple,
globals=globals))
if order:
# Create and set the ordering methods.
@ -943,13 +961,14 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
('__ge__', '>='),
]:
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} '
f'in class {cls.__name__}. Consider using '
'functools.total_ordering')
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):
raise TypeError(f'Cannot overwrite attribute {fn.__name__} '
f'in class {cls.__name__}')
@ -962,7 +981,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
if hash_action:
# No need to call _set_new_attribute here, since by the time
# 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__'):
# Create a class doc-string.

View File

@ -850,10 +850,15 @@ class MsgID(TokenList):
# message-id tokens may not be folded.
return str(self) + policy.linesep
class MessageID(MsgID):
token_type = 'message-id'
class InvalidMessageID(MessageID):
token_type = 'invalid-message-id'
class Header(TokenList):
token_type = 'header'
@ -2042,7 +2047,7 @@ def get_msg_id(value):
no-fold-literal = "[" *dtext "]"
"""
msg_id = MsgID()
if value[0] in CFWS_LEADER:
if value and value[0] in CFWS_LEADER:
token, value = get_cfws(value)
msg_id.append(token)
if not value or value[0] != '<':
@ -2110,10 +2115,18 @@ def parse_message_id(value):
message_id = MessageID()
try:
token, value = get_msg_id(value)
except errors.HeaderParseError:
message_id.defects.append(errors.InvalidHeaderDefect(
"Expected msg-id but found {!r}".format(value)))
message_id.append(token)
except errors.HeaderParseError as ex:
token = get_unstructured(value)
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
#

View File

@ -20,6 +20,10 @@ def uu_encode(input, errors='strict', filename='<data>', mode=0o666):
read = infile.read
write = outfile.write
# Remove newline chars from filename
filename = filename.replace('\n','\\n')
filename = filename.replace('\r','\\r')
# Encode
write(('begin %o %s\n' % (mode & 0o777, filename)).encode('ascii'))
chunk = read(45)

View File

@ -861,28 +861,20 @@ def _decompose(flag, value):
# _decompose is only called if the value is not named
not_covered = value
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 = []
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:
members.append(member)
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_:
members.append(flag._value2member_map_[value])
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
members.pop(0)
return members, not_covered
def _power_of_two(value):
if value < 1:
return False
return value == 2 ** _high_bit(value)

View File

@ -214,10 +214,14 @@ LOOSE_HTTP_DATE_RE = re.compile(
(?::(\d\d))? # optional seconds
)? # optional clock
\s*
([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+)? # timezone
(?:
([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+) # timezone
\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):
"""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)
)? # optional clock
\s*
(?:
([-+]?\d\d?:?(:?\d\d)?
|Z|z)? # timezone (Z is "zero meridian", i.e. GMT)
\s*$""", re.X | re. ASCII)
|Z|z) # timezone (Z is "zero meridian", i.e. GMT)
\s*
)?$""", re.X | re. ASCII)
def iso2time(text):
"""
As for http2time, but parses the ISO 8601 formats:

View File

@ -1014,8 +1014,10 @@ class CGIHTTPRequestHandler(SimpleHTTPRequestHandler):
"""
collapsed_path = _url_collapse_path(self.path)
dir_sep = collapsed_path.find('/', 1)
while dir_sep > 0 and not collapsed_path[:dir_sep] 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:]
if head in self.cgi_directories:
self.cgi_info = head, tail
return True
return False

View File

@ -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
functions (default shortcuts Alt-T and Alt-U) were mistakenly disabled
in 3.7.5 and 3.8.0.

View File

@ -17,7 +17,7 @@ KEYPRESS_VIRTUAL_EVENT_NAME = "<<autocompletewindow-keypress>>"
# before the default specific IDLE function
KEYPRESS_SEQUENCES = ("<Key>", "<Key-BackSpace>", "<Key-Return>", "<Key-Tab>",
"<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_SEQUENCE = "<KeyRelease>"
LISTUPDATE_SEQUENCE = "<B1-ButtonRelease>"
@ -257,6 +257,7 @@ class AutoCompleteWindow:
# place acw above current line
new_y -= acw_height
acw.wm_geometry("+%d+%d" % (new_x, new_y))
acw.update_idletasks()
if platform.system().startswith('Windows'):
# See issue 15786. When on Windows platform, Tk will misbehave

View File

@ -408,6 +408,16 @@ class Rstrip: # 'Strip Trailing Whitespace" on "Format" menu.
if cut < raw:
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()

View File

@ -4,7 +4,7 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>IDLE &#8212; Python 3.9.0a0 documentation</title>
<title>IDLE &#8212; Python 3.9.0a1 documentation</title>
<link rel="stylesheet" href="../_static/pydoctheme.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>
<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"/>
<link rel="author" title="About these documents" href="../about.html" />
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="copyright" title="Copyright" href="../copyright.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" />
@ -62,7 +62,7 @@
<a href="othergui.html" title="Other Graphical User Interface Packages"
accesskey="N">next</a> |</li>
<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>
<li><img src="../_static/py.png" alt=""
@ -71,7 +71,7 @@
<li>
<a href="../index.html">3.9.0a0 Documentation</a> &#187;
<a href="../index.html">3.9.0a1 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> &#187;</li>
@ -240,7 +240,8 @@ paragraph will be formatted to less than N columns, where N defaults to 72.</p>
</dd>
<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,
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>
</dl>
</div>
@ -886,8 +887,8 @@ also used for testing.</p>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="tkinter.scrolledtext.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>
<p class="topless"><a href="tkinter.tix.html"
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>
<p class="topless"><a href="othergui.html"
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"
>next</a> |</li>
<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>
<li><img src="../_static/py.png" alt=""
@ -928,7 +929,7 @@ also used for testing.</p>
<li>
<a href="../index.html">3.9.0a0 Documentation</a> &#187;
<a href="../index.html">3.9.0a1 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> &#187;</li>
@ -959,11 +960,11 @@ also used for testing.</p>
<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>?
<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>
</body>

View File

@ -40,8 +40,9 @@ class Func:
class Editor:
'''Minimally imitate editor.EditorWindow class.
'''
def __init__(self, flist=None, filename=None, key=None, root=None):
self.text = Text()
def __init__(self, flist=None, filename=None, key=None, root=None,
text=None): # Allow real Text with mock Editor.
self.text = text or Text()
self.undo = UndoDelegator()
def get_selection_indices(self):

View File

@ -611,37 +611,33 @@ class IndentsTest(unittest.TestCase):
class RstripTest(unittest.TestCase):
def test_rstrip_line(self):
editor = MockEditor()
text = editor.text
do_rstrip = ft.Rstrip(editor).do_rstrip
eq = self.assertEqual
@classmethod
def setUpClass(cls):
requires('gui')
cls.root = Tk()
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()
eq(text.get('1.0', 'insert'), '')
text.insert('1.0', ' ')
do_rstrip()
eq(text.get('1.0', 'insert'), '')
text.insert('1.0', ' \n')
do_rstrip()
eq(text.get('1.0', 'insert'), '\n')
@classmethod
def tearDownClass(cls):
del cls.text, cls.do_rstrip, cls.editor
cls.root.update_idletasks()
cls.root.destroy()
del cls.root
def test_rstrip_multiple(self):
editor = MockEditor()
# 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 tearDown(self):
self.text.delete('1.0', 'end-1c')
def test_rstrip_lines(self):
original = (
"Line with an ending tab \n"
"Line ending in 5 spaces \n"
"Linewithnospaces\n"
" indented line\n"
" indented line with trailing space \n"
" ")
" \n")
stripped = (
"Line with an ending tab\n"
"Line ending in 5 spaces\n"
@ -649,9 +645,23 @@ class RstripTest(unittest.TestCase):
" indented line\n"
" indented line with trailing space\n")
text.insert('1.0', original)
do_rstrip()
self.assertEqual(text.get('1.0', 'insert'), stripped)
self.text.insert('1.0', original)
self.do_rstrip()
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__':

View File

@ -272,6 +272,8 @@ _code_type = type(_write_atomic.__code__)
# only args in ast.arguments #37593)
# Python 3.8b4 3413 (Fix "break" and "continue" in "finally" #37830)
# 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
# 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
# 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
_PYCACHE = '__pycache__'

View File

@ -1136,7 +1136,6 @@ def getfullargspec(func):
varkw = None
posonlyargs = []
kwonlyargs = []
defaults = ()
annotations = {}
defaults = ()
kwdefaults = {}

View File

@ -20,30 +20,52 @@ def main():
description = ('A simple command line interface for json module '
'to validate and pretty-print JSON objects.')
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',
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',
default=sys.stdout)
parser.add_argument('--sort-keys', action='store_true', default=False,
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,
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()
infile = options.infile
outfile = options.outfile
sort_keys = options.sort_keys
json_lines = options.json_lines
with infile, outfile:
dump_args = {
'sort_keys': options.sort_keys,
'indent': options.indent,
'ensure_ascii': options.ensure_ascii,
}
if options.compact:
dump_args['indent'] = None
dump_args['separators'] = ',', ':'
with options.infile as infile, options.outfile as outfile:
try:
if json_lines:
if options.json_lines:
objs = (json.loads(line) for line in infile)
else:
objs = (json.load(infile), )
for obj in objs:
json.dump(obj, outfile, sort_keys=sort_keys, indent=4)
json.dump(obj, outfile, **dump_args)
outfile.write('\n')
except ValueError as e:
raise SystemExit(e)

View File

@ -84,10 +84,12 @@ def_op('BINARY_TRUE_DIVIDE', 27)
def_op('INPLACE_FLOOR_DIVIDE', 28)
def_op('INPLACE_TRUE_DIVIDE', 29)
def_op('RERAISE', 48)
def_op('WITH_EXCEPT_START', 49)
def_op('GET_AITER', 50)
def_op('GET_ANEXT', 51)
def_op('BEFORE_ASYNC_WITH', 52)
def_op('BEGIN_FINALLY', 53)
def_op('END_ASYNC_FOR', 54)
def_op('INPLACE_ADD', 55)
def_op('INPLACE_SUBTRACT', 56)
@ -115,14 +117,13 @@ def_op('INPLACE_RSHIFT', 76)
def_op('INPLACE_AND', 77)
def_op('INPLACE_XOR', 78)
def_op('INPLACE_OR', 79)
def_op('WITH_CLEANUP_START', 81)
def_op('WITH_CLEANUP_FINISH', 82)
def_op('RETURN_VALUE', 83)
def_op('IMPORT_STAR', 84)
def_op('SETUP_ANNOTATIONS', 85)
def_op('YIELD_VALUE', 86)
def_op('POP_BLOCK', 87)
def_op('END_FINALLY', 88)
def_op('POP_EXCEPT', 89)
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)
def_op('CALL_METHOD', 161)
jrel_op('CALL_FINALLY', 162)
def_op('POP_FINALLY', 163)
del def_op, name_op, jrel_op, jabs_op

View File

@ -1072,6 +1072,9 @@ class PathLike(abc.ABC):
def __subclasshook__(cls, subclass):
return hasattr(subclass, '__fspath__')
def __class_getitem__(cls, type):
return cls
if name == 'nt':
class _AddedDllDirectory:

View File

@ -777,6 +777,9 @@ class PurePath(object):
return NotImplemented
return self._cparts >= other._cparts
def __class_getitem__(cls, type):
return cls
drive = property(attrgetter('_drv'),
doc="""The drive prefix (letter or UNC path), if any.""")

View File

@ -1604,17 +1604,29 @@ class _Unpickler:
def load_get(self):
i = int(self.readline()[:-1])
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
def load_binget(self):
i = self.read(1)[0]
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
def load_long_binget(self):
i, = unpack('<I', self.read(4))
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
def load_put(self):

View File

@ -413,8 +413,10 @@ class Random(_random.Random):
raise TypeError('Cannot specify both weights and cumulative weights')
if len(cum_weights) != n:
raise ValueError('The number of weights does not match the population')
bisect = _bisect
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
return [population[bisect(cum_weights, random() * total, 0, hi)]
for i in _repeat(None, k)]

View File

@ -442,7 +442,7 @@ def ignore_patterns(*patterns):
def _copytree(entries, src, dst, symlinks, ignore, copy_function,
ignore_dangling_symlinks, dirs_exist_ok=False):
if ignore is not None:
ignored_names = ignore(src, set(os.listdir(src)))
ignored_names = ignore(src, {x.name for x in entries})
else:
ignored_names = set()
@ -543,7 +543,8 @@ def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
"""
sys.audit("shutil.copytree", src, dst)
with os.scandir(src) as entries:
with os.scandir(src) as itr:
entries = list(itr)
return _copytree(entries=entries, src=src, dst=dst, symlinks=symlinks,
ignore=ignore, copy_function=copy_function,
ignore_dangling_symlinks=ignore_dangling_symlinks,

View File

@ -839,7 +839,11 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
sock.close()
if err is not None:
try:
raise err
finally:
# Break explicitly a reference cycle
err = None
else:
raise error("getaddrinfo returns an empty list")

View File

@ -633,10 +633,9 @@ class SpooledTemporaryFile:
if 'b' in mode:
self._file = _io.BytesIO()
else:
# Setting newline="\n" avoids newline translation;
# this is important because otherwise on Windows we'd
# get double newline translation upon rollover().
self._file = _io.StringIO(newline="\n")
self._file = _io.TextIOWrapper(_io.BytesIO(),
encoding=encoding, errors=errors,
newline=newline)
self._max_size = max_size
self._rolled = False
self._TemporaryFileArgs = {'mode': mode, 'buffering': buffering,
@ -656,8 +655,12 @@ class SpooledTemporaryFile:
newfile = self._file = TemporaryFile(**self._TemporaryFileArgs)
del self._TemporaryFileArgs
pos = file.tell()
if hasattr(newfile, 'buffer'):
newfile.buffer.write(file.detach().getvalue())
else:
newfile.write(file.getvalue())
newfile.seek(file.tell(), 0)
newfile.seek(pos, 0)
self._rolled = True

View File

@ -6,6 +6,7 @@ Empty lines above are for good reason (testing for correct line numbers)
"""
from typing import Optional
from functools import wraps
__annotations__[1] = 2
@ -51,3 +52,9 @@ def foo(x: int = 10):
def bar(y: List[str]):
x: str = 'yes'
bar()
def dec(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper

View File

@ -263,13 +263,73 @@ def test_cantrace():
def test_mmap():
import mmap
with TestHook() as hook:
mmap.mmap(-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__":
from test.libregrtest.setup import suppress_msvcrt_asserts
suppress_msvcrt_asserts(False)
test = sys.argv[1]

View File

@ -0,0 +1,12 @@
from __future__ import annotations
import dataclasses
class Foo:
pass
@dataclasses.dataclass
class Bar:
foo: Foo

View File

@ -1019,7 +1019,9 @@ class AbstractUnpickleTests(unittest.TestCase):
self.assertEqual(self.loads(dumped), '\u20ac\x00')
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.loads(b'((Kdtp0\nh\x00l.))'))

View File

@ -2512,16 +2512,6 @@ def swap_item(obj, item, new_val):
if item in obj:
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'),
'types are immortal if COUNT_ALLOCS is defined')

View File

@ -11,7 +11,7 @@ import py_compile
import zipfile
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.
@ -134,7 +134,6 @@ def run_python_until_end(*args, **env_vars):
proc.kill()
subprocess._cleanup()
rc = proc.returncode
err = strip_python_stderr(err)
return _PythonRunResult(rc, out, err), cmd_line
def _assert_python(expected_success, /, *args, **env_vars):

View File

@ -30,7 +30,7 @@ def setUpModule():
global candidate_locales
# 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
# 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().
if sys.platform == 'sunos5':
old_locale = locale.setlocale(locale.LC_ALL)

View File

@ -426,26 +426,6 @@ class BaseTest:
b.fromlist(a.tolist())
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):
a = array.array(self.typecode, 2*self.example)
b = array.array(self.typecode)

View File

@ -1738,10 +1738,6 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase):
MyDatagramProto, flags=1, sock=FakeSock())
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(
MyDatagramProto, reuse_port=True, sock=FakeSock())
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):
# Socket options should not be applied unless asked for.
# SO_REUSEADDR defaults to on for UNIX.
# SO_REUSEPORT is not available on all platforms.
coro = self.loop.create_datagram_endpoint(
@ -1761,18 +1756,8 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase):
transport, protocol = self.loop.run_until_complete(coro)
sock = transport.get_extra_info('socket')
reuse_address_default_on = (
os.name == 'posix' and sys.platform != 'cygwin')
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:
self.assertFalse(
sock.getsockopt(
@ -1788,13 +1773,12 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase):
coro = self.loop.create_datagram_endpoint(
lambda: MyDatagramProto(create_future=True, loop=self.loop),
local_addr=('127.0.0.1', 0),
reuse_address=True,
reuse_port=reuseport_supported,
allow_broadcast=True)
transport, protocol = self.loop.run_until_complete(coro)
sock = transport.get_extra_info('socket')
self.assertTrue(
self.assertFalse(
sock.getsockopt(
socket.SOL_SOCKET, socket.SO_REUSEADDR))
if reuseport_supported:
@ -1809,6 +1793,29 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase):
self.loop.run_until_complete(protocol.done)
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
def test_create_datagram_endpoint_nosoreuseport(self, m_socket):
del m_socket.SO_REUSEPORT

View File

@ -924,59 +924,6 @@ os.close(fd)
wr.close()
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):
async def inner(httpd):
rd, wr = await asyncio.open_connection(*httpd.address)

View File

@ -24,7 +24,23 @@ class AuditTest(unittest.TestCase):
sys.stdout.writelines(p.stdout)
sys.stderr.writelines(p.stderr)
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):
self.do_test("test_basic")
@ -36,19 +52,11 @@ class AuditTest(unittest.TestCase):
self.do_test("test_block_add_hook_baseexception")
def test_finalize_hooks(self):
events = []
with subprocess.Popen(
[sys.executable, "-X utf8", AUDIT_TESTS_PY, "test_finalize_hooks"],
encoding="utf-8",
stdout=subprocess.PIPE,
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))
returncode, events, stderr = self.run_python("test_finalize_hooks")
if stderr:
print(stderr, file=sys.stderr)
if returncode:
self.fail(stderr)
firstId = events[0][2]
self.assertSequenceEqual(
@ -76,6 +84,40 @@ class AuditTest(unittest.TestCase):
def test_mmap(self):
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__":
unittest.main()

View File

@ -351,9 +351,11 @@ class CAPITest(unittest.TestCase):
for i in range(1000):
L = MyList((L,))
@support.requires_resource('cpu')
def test_trashcan_python_class1(self):
self.do_test_trashcan_python_class(list)
@support.requires_resource('cpu')
def test_trashcan_python_class2(self):
from _testcapi import MyList
self.do_test_trashcan_python_class(MyList)

View File

@ -332,10 +332,10 @@ class CmdLineTest(unittest.TestCase):
if sys.platform == 'win32':
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:
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):
# Issue #10206: python program starting with unmatched quote
@ -391,7 +391,7 @@ class CmdLineTest(unittest.TestCase):
stderr=subprocess.PIPE,
preexec_fn=preexec)
out, err = p.communicate()
self.assertEqual(support.strip_python_stderr(err), b'')
self.assertEqual(err, b'')
self.assertEqual(p.returncode, 42)
def test_no_stdin(self):

View File

@ -223,12 +223,13 @@ class CmdLineTest(unittest.TestCase):
def test_script_abspath(self):
# 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:
self.assertTrue(os.path.isabs(script_dir), script_dir)
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,
importlib.machinery.SourceFileLoader)
@ -535,7 +536,7 @@ class CmdLineTest(unittest.TestCase):
script_name = _make_test_script(script_dir, 'script', script)
exitcode, stdout, stderr = assert_python_failure(script_name)
text = stderr.decode('ascii').split('\n')
self.assertEqual(len(text), 4)
self.assertEqual(len(text), 5)
self.assertTrue(text[0].startswith('Traceback'))
self.assertTrue(text[1].startswith(' File '))
self.assertTrue(text[3].startswith('NameError'))
@ -579,7 +580,7 @@ class CmdLineTest(unittest.TestCase):
script_name = _make_test_script(script_dir, 'script', script)
exitcode, stdout, stderr = assert_python_failure(script_name)
text = stderr.decode('ascii')
self.assertEqual(text, "some text")
self.assertEqual(text.rstrip(), "some text")
def test_syntaxerror_unindented_caret_position(self):
script = "1 + 1 = 2\n"

View File

@ -38,9 +38,6 @@ class ContextTest(unittest.TestCase):
self.assertNotEqual(hash(c), hash('aaa'))
def test_context_var_new_2(self):
self.assertIsNone(contextvars.ContextVar[int])
@isolated_context
def test_context_var_repr_1(self):
c = contextvars.ContextVar('a')
@ -361,6 +358,10 @@ class ContextTest(unittest.TestCase):
tp.shutdown()
self.assertEqual(results, list(range(10)))
def test_contextvar_getitem(self):
clss = contextvars.ContextVar
self.assertEqual(clss[str], clss)
# HAMT Tests

View File

@ -10,6 +10,7 @@ import builtins
import unittest
from unittest.mock import Mock
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 functools import total_ordering
@ -2983,6 +2984,17 @@ class TestStringAnnotations(unittest.TestCase):
# won't exist on the instance.
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):
def test_simple(self):

View File

@ -278,32 +278,34 @@ dis_traceback = """\
--> 6 BINARY_TRUE_DIVIDE
8 POP_TOP
10 POP_BLOCK
12 JUMP_FORWARD 40 (to 54)
12 JUMP_FORWARD 44 (to 58)
%3d >> 14 DUP_TOP
16 LOAD_GLOBAL 0 (Exception)
18 COMPARE_OP 10 (exception match)
20 POP_JUMP_IF_FALSE 52
20 POP_JUMP_IF_FALSE 56
22 POP_TOP
24 STORE_FAST 0 (e)
26 POP_TOP
28 SETUP_FINALLY 10 (to 40)
28 SETUP_FINALLY 18 (to 48)
%3d 30 LOAD_FAST 0 (e)
32 LOAD_ATTR 1 (__traceback__)
34 STORE_FAST 1 (tb)
36 POP_BLOCK
38 BEGIN_FINALLY
>> 40 LOAD_CONST 0 (None)
38 POP_EXCEPT
40 LOAD_CONST 0 (None)
42 STORE_FAST 0 (e)
44 DELETE_FAST 0 (e)
46 END_FINALLY
48 POP_EXCEPT
50 JUMP_FORWARD 2 (to 54)
>> 52 END_FINALLY
46 JUMP_FORWARD 10 (to 58)
>> 48 LOAD_CONST 0 (None)
50 STORE_FAST 0 (e)
52 DELETE_FAST 0 (e)
54 RERAISE
>> 56 RERAISE
%3d >> 54 LOAD_FAST 1 (tb)
56 RETURN_VALUE
%3d >> 58 LOAD_FAST 1 (tb)
60 RETURN_VALUE
""" % (TRACEBACK_CODE.co_firstlineno + 1,
TRACEBACK_CODE.co_firstlineno + 2,
TRACEBACK_CODE.co_firstlineno + 3,
@ -752,7 +754,7 @@ Argument count: 0
Positional-only arguments: 0
Kw-only arguments: 0
Number of locals: 2
Stack size: 10
Stack size: 9
Flags: OPTIMIZED, NEWLOCALS, NOFREE, COROUTINE
Constants:
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='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='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='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='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),
@ -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=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_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='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='JUMP_FORWARD', opcode=110, arg=26, argval=170, argrepr='to 170', 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='JUMP_FORWARD', opcode=110, arg=46, argval=190, argrepr='to 190', offset=142, starts_line=None, is_jump_target=False),
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='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='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='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='BEGIN_FINALLY', opcode=53, arg=None, argval=None, argrepr='', 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='WITH_CLEANUP_FINISH', opcode=82, 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='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=True),
Instruction(opname='BEGIN_FINALLY', opcode=53, arg=None, argval=None, argrepr='', 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='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='CALL_FUNCTION', opcode=131, arg=1, argval=1, 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='END_FINALLY', opcode=88, 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='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=186, 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='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=164, 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='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=168, starts_line=None, is_jump_target=False),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=170, 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='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=174, starts_line=None, is_jump_target=True),
Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=180, argval=180, argrepr='', offset=176, 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=True),
Instruction(opname='POP_TOP', opcode=1, 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=184, 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
@ -1032,6 +1048,10 @@ expected_opinfo_simple = [
class InstructionTests(BytecodeTestCase):
def __init__(self, *args):
super().__init__(*args)
self.maxDiff = None
def test_default_first_line(self):
actual = dis.get_instructions(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
# the object oriented API
class BytecodeTests(unittest.TestCase):
def test_instantiation(self):
# Test with function, method, code string and code object
for obj in [_f, _C(1).__init__, "a=1", _f.__code__]:

View File

@ -2583,6 +2583,11 @@ class TestParser(TestParserMixin, TestEmailBase):
# 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):
msg_id = self._test_get_x(
parser.get_msg_id,
@ -2638,6 +2643,46 @@ class TestParser(TestParserMixin, TestEmailBase):
)
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):
with self.assertRaises(errors.HeaderParseError):
parser.get_msg_id("msgwithnoankle")
@ -2654,6 +2699,7 @@ class TestParser(TestParserMixin, TestEmailBase):
self.assertEqual(msg_id.token_type, 'msg-id')
@parameterize
class Test_parse_mime_parameters(TestParserMixin, TestEmailBase):

View File

@ -858,10 +858,9 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
preconfig = {
'allocator': PYMEM_ALLOCATOR_DEBUG,
}
script_abspath = os.path.abspath('script.py')
config = {
'argv': [script_abspath],
'run_filename': script_abspath,
'argv': ['script.py'],
'run_filename': os.path.abspath('script.py'),
'dev_mode': 1,
'faulthandler': 1,
'warnoptions': ['default'],

View File

@ -71,9 +71,8 @@ class FaultHandlerTests(unittest.TestCase):
with support.SuppressCrashReport():
process = script_helper.spawn_python('-c', code, pass_fds=pass_fds)
with process:
stdout, stderr = process.communicate()
output, stderr = process.communicate()
exitcode = process.wait()
output = support.strip_python_stderr(stdout)
output = output.decode('ascii', 'backslashreplace')
if filename:
self.assertEqual(output, '')

Some files were not shown because too many files have changed in this diff Show More