diff options
-rw-r--r-- | Doc/c-api/concrete.rst | 1 | ||||
-rw-r--r-- | Doc/c-api/coro.rst | 34 | ||||
-rw-r--r-- | Doc/c-api/gen.rst | 20 | ||||
-rw-r--r-- | Doc/data/refcounts.dat | 6 | ||||
-rw-r--r-- | Doc/glossary.rst | 25 | ||||
-rw-r--r-- | Doc/library/dis.rst | 8 | ||||
-rw-r--r-- | Doc/library/inspect.rst | 57 | ||||
-rw-r--r-- | Doc/library/sys.rst | 5 | ||||
-rw-r--r-- | Doc/library/types.rst | 8 | ||||
-rw-r--r-- | Doc/reference/compound_stmts.rst | 21 | ||||
-rw-r--r-- | Doc/whatsnew/3.5.rst | 11 | ||||
-rw-r--r-- | Include/genobject.h | 59 | ||||
-rw-r--r-- | Include/opcode.h | 1 | ||||
-rw-r--r-- | Lib/_collections_abc.py | 27 | ||||
-rw-r--r-- | Lib/asyncio/coroutines.py | 48 | ||||
-rw-r--r-- | Lib/importlib/_bootstrap_external.py | 3 | ||||
-rw-r--r-- | Lib/inspect.py | 50 | ||||
-rw-r--r-- | Lib/opcode.py | 1 | ||||
-rw-r--r-- | Lib/test/test_coroutines.py | 160 | ||||
-rw-r--r-- | Lib/test/test_inspect.py | 71 | ||||
-rw-r--r-- | Lib/test/test_types.py | 54 | ||||
-rw-r--r-- | Lib/types.py | 85 | ||||
-rw-r--r-- | Misc/NEWS | 9 | ||||
-rw-r--r-- | Objects/genobject.c | 325 | ||||
-rw-r--r-- | Objects/object.c | 6 | ||||
-rw-r--r-- | Python/ceval.c | 79 | ||||
-rw-r--r-- | Python/compile.c | 10 | ||||
-rw-r--r-- | Python/importlib_external.h | 208 | ||||
-rw-r--r-- | Python/opcode_targets.h | 2 |
29 files changed, 1015 insertions, 379 deletions
diff --git a/Doc/c-api/concrete.rst b/Doc/c-api/concrete.rst index 2d56386..47dab81 100644 --- a/Doc/c-api/concrete.rst +++ b/Doc/c-api/concrete.rst @@ -112,5 +112,6 @@ Other Objects weakref.rst capsule.rst gen.rst + coro.rst datetime.rst diff --git a/Doc/c-api/coro.rst b/Doc/c-api/coro.rst new file mode 100644 index 0000000..2fe50b5 --- /dev/null +++ b/Doc/c-api/coro.rst @@ -0,0 +1,34 @@ +.. highlightlang:: c + +.. _coro-objects: + +Coroutine Objects +----------------- + +.. versionadded:: 3.5 + +Coroutine objects are what functions declared with an ``async`` keyword +return. + + +.. c:type:: PyCoroObject + + The C structure used for coroutine objects. + + +.. c:var:: PyTypeObject PyCoro_Type + + The type object corresponding to coroutine objects. + + +.. c:function:: int PyCoro_CheckExact(PyObject *ob) + + Return true if *ob*'s type is *PyCoro_Type*; *ob* must not be *NULL*. + + +.. c:function:: PyObject* PyCoro_New(PyFrameObject *frame, PyObject *name, PyObject *qualname) + + Create and return a new coroutine object based on the *frame* object, + with ``__name__`` and ``__qualname__`` set to *name* and *qualname*. + A reference to *frame* is stolen by this function. The *frame* argument + must not be *NULL*. diff --git a/Doc/c-api/gen.rst b/Doc/c-api/gen.rst index 33cd27a..3ab073b 100644 --- a/Doc/c-api/gen.rst +++ b/Doc/c-api/gen.rst @@ -7,7 +7,7 @@ Generator Objects Generator objects are what Python uses to implement generator iterators. They are normally created by iterating over a function that yields values, rather -than explicitly calling :c:func:`PyGen_New`. +than explicitly calling :c:func:`PyGen_New` or :c:func:`PyGen_NewWithQualName`. .. c:type:: PyGenObject @@ -20,19 +20,25 @@ than explicitly calling :c:func:`PyGen_New`. The type object corresponding to generator objects -.. c:function:: int PyGen_Check(ob) +.. c:function:: int PyGen_Check(PyObject *ob) Return true if *ob* is a generator object; *ob* must not be *NULL*. -.. c:function:: int PyGen_CheckExact(ob) +.. c:function:: int PyGen_CheckExact(PyObject *ob) - Return true if *ob*'s type is *PyGen_Type* is a generator object; *ob* must not - be *NULL*. + Return true if *ob*'s type is *PyGen_Type*; *ob* must not be *NULL*. .. c:function:: PyObject* PyGen_New(PyFrameObject *frame) - Create and return a new generator object based on the *frame* object. A - reference to *frame* is stolen by this function. The parameter must not be + Create and return a new generator object based on the *frame* object. + A reference to *frame* is stolen by this function. The argument must not be *NULL*. + +.. c:function:: PyObject* PyGen_NewWithQualName(PyFrameObject *frame, PyObject *name, PyObject *qualname) + + Create and return a new generator object based on the *frame* object, + with ``__name__`` and ``__qualname__`` set to *name* and *qualname*. + A reference to *frame* is stolen by this function. The *frame* argument + must not be *NULL*. diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index d1c24e5..e388195 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -491,6 +491,12 @@ PyFunction_SetDefaults:PyObject*:defaults:+1: PyGen_New:PyObject*::+1: PyGen_New:PyFrameObject*:frame:0: +PyGen_NewWithQualName:PyObject*::+1: +PyGen_NewWithQualName:PyFrameObject*:frame:0: + +PyCoro_New:PyObject*::+1: +PyCoro_New:PyFrameObject*:frame:0: + Py_InitModule:PyObject*::0: Py_InitModule:const char*:name:: Py_InitModule:PyMethodDef[]:methods:: diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 3b7975b..bdbb272 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -333,14 +333,23 @@ Glossary .. index:: single: generator generator - A function which returns an iterator. It looks like a normal function - except that it contains :keyword:`yield` statements for producing a series - of values usable in a for-loop or that can be retrieved one at a time with - the :func:`next` function. Each :keyword:`yield` temporarily suspends - processing, remembering the location execution state (including local - variables and pending try-statements). When the generator resumes, it - picks-up where it left-off (in contrast to functions which start fresh on - every invocation). + A function which returns a :term:`generator iterator`. It looks like a + normal function except that it contains :keyword:`yield` expressions + for producing a series of values usable in a for-loop or that can be + retrieved one at a time with the :func:`next` function. + + Usually refers to a generator function, but may refer to a + *generator iterator* in some contexts. In cases where the intended + meaning isn't clear, using the full terms avoids ambiguity. + + generator iterator + An object created by a :term:`generator` function. + + Each :keyword:`yield` temporarily suspends processing, remembering the + location execution state (including local variables and pending + try-statements). When the *generator iterator* resumes, it picks-up where + it left-off (in contrast to functions which start fresh on every + invocation). .. index:: single: generator expression diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 2e938ab..836c4c1 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -346,6 +346,14 @@ result back on the stack. Implements ``TOS = iter(TOS)``. +.. opcode:: GET_YIELD_FROM_ITER + + If ``TOS`` is a :term:`generator iterator` or :term:`coroutine` object + it is left as is. Otherwise, implements ``TOS = iter(TOS)``. + + .. versionadded:: 3.5 + + **Binary operations** Binary operations remove the top of the stack (TOS) and the second top-most diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 98b7cb7..d4ebffd 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -178,6 +178,16 @@ attributes: +-----------+-----------------+---------------------------+ | | gi_code | code | +-----------+-----------------+---------------------------+ +| coroutine | __name__ | name | ++-----------+-----------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------+-----------------+---------------------------+ +| | cr_frame | frame | ++-----------+-----------------+---------------------------+ +| | cr_running | is the coroutine running? | ++-----------+-----------------+---------------------------+ +| | cr_code | code | ++-----------+-----------------+---------------------------+ | builtin | __doc__ | documentation string | +-----------+-----------------+---------------------------+ | | __name__ | original name of this | @@ -279,29 +289,16 @@ attributes: .. function:: iscoroutinefunction(object) - Return true if the object is a :term:`coroutine function`. - - Coroutine functions are defined with an ``async def`` syntax, - or are generators decorated with :func:`types.coroutine` - or :func:`asyncio.coroutine`. - - The function will return false for plain Python generator - functions. + Return true if the object is a :term:`coroutine function` + (a function defined with an :keyword:`async def` syntax). .. versionadded:: 3.5 .. function:: iscoroutine(object) - Return true if the object is a :term:`coroutine`. - - Coroutines are results of calls of coroutine functions or - generator functions decorated with :func:`types.coroutine` - or :func:`asyncio.coroutine`. - - The function will return false for plain python generators. - - See also :class:`collections.abc.Coroutine`. + Return true if the object is a :term:`coroutine` created by an + :keyword:`async def` function. .. versionadded:: 3.5 @@ -1116,8 +1113,8 @@ code execution:: pass -Current State of a Generator ----------------------------- +Current State of Generators and Coroutines +------------------------------------------ When implementing coroutine schedulers and for other advanced uses of generators, it is useful to determine whether a generator is currently @@ -1137,6 +1134,21 @@ generator to be determined easily. .. versionadded:: 3.2 +.. function:: getcoroutinestate(coroutine) + + Get current state of a coroutine object. The function is intended to be + used with coroutine objects created by :keyword:`async def` functions, but + will accept any coroutine-like object that has ``cr_running`` and + ``cr_frame`` attributes. + + Possible states are: + * CORO_CREATED: Waiting to start execution. + * CORO_RUNNING: Currently being executed by the interpreter. + * CORO_SUSPENDED: Currently suspended at an await expression. + * CORO_CLOSED: Execution has completed. + + .. versionadded:: 3.5 + The current internal state of the generator can also be queried. This is mostly useful for testing purposes, to ensure that internal state is being updated as expected: @@ -1161,6 +1173,13 @@ updated as expected: .. versionadded:: 3.3 +.. function:: getcoroutinelocals(coroutine) + + This function is analogous to :func:`~inspect.getgeneratorlocals`, but + works for coroutine objects created by :keyword:`async def` functions. + + .. versionadded:: 3.5 + .. _inspect-module-cli: diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 9d62835..144c986 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -1075,7 +1075,10 @@ always available. .. function:: set_coroutine_wrapper(wrapper) - Allows to intercept creation of :term:`coroutine` objects. + Allows intercepting creation of :term:`coroutine` objects (only ones that + are created by an :keyword:`async def` function; generators decorated with + :func:`types.coroutine` or :func:`asyncio.coroutine` will not be + intercepted). *wrapper* must be either: diff --git a/Doc/library/types.rst b/Doc/library/types.rst index 3fb0c9c..d7b14e7 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -90,6 +90,14 @@ Standard names are defined for the following types: generator function. +.. data:: CoroutineType + + The type of :term:`coroutine` objects, produced by calling a + function defined with an :keyword:`async def` statement. + + .. versionadded:: 3.5 + + .. data:: CodeType .. index:: builtin: compile diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index 58b6d71..c73e886 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -666,6 +666,15 @@ can be used to create instance variables with different implementation details. Coroutines ========== +.. index:: + statement: async def + statement: async for + statement: async with + keyword: async + keyword: await + +.. versionadded:: 3.5 + .. _`async def`: Coroutine function definition @@ -683,7 +692,11 @@ even if they do not contain ``await`` or ``async`` keywords. It is a :exc:`SyntaxError` to use :keyword:`yield` expressions in coroutines. -.. versionadded:: 3.5 +An example of a coroutine function:: + + async def func(param1, param2): + do_stuff() + await some_coroutine() .. _`async for`: @@ -725,7 +738,8 @@ Is semantically equivalent to:: See also :meth:`__aiter__` and :meth:`__anext__` for details. -.. versionadded:: 3.5 +It is a :exc:`SyntaxError` to use ``async for`` statement outside of an +:keyword:`async def` function. .. _`async with`: @@ -762,7 +776,8 @@ Is semantically equivalent to:: See also :meth:`__aenter__` and :meth:`__aexit__` for details. -.. versionadded:: 3.5 +It is a :exc:`SyntaxError` to use ``async with`` statement outside of an +:keyword:`async def` function. .. seealso:: diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst index 6b9fd02..b0d5efe 100644 --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -531,6 +531,9 @@ inspect and :func:`~inspect.isawaitable` functions. (Contributed by Yury Selivanov in :issue:`24017`.) +* New :func:`~inspect.getcoroutinelocals` and :func:`~inspect.getcoroutinestate` + functions. (Contributed by Yury Selivanov in :issue:`24400`.) + ipaddress --------- @@ -734,6 +737,9 @@ types * New :func:`~types.coroutine` function. (Contributed by Yury Selivanov in :issue:`24017`.) +* New :class:`~types.CoroutineType`. (Contributed by Yury Selivanov + in :issue:`24400`.) + urllib ------ @@ -1101,6 +1107,7 @@ Changes in the C API the :attr:`__module__` attribute. Would be an AttributeError in future. (:issue:`20204`) -* As part of PEP 492 implementation, ``tp_reserved`` slot of +* As part of :pep:`492` implementation, ``tp_reserved`` slot of :c:type:`PyTypeObject` was replaced with a - :c:member:`PyTypeObject.tp_as_async` slot. + :c:member:`PyTypeObject.tp_as_async` slot. Refer to :ref:`coro-objects` for + new types, structures and functions. diff --git a/Include/genobject.h b/Include/genobject.h index ee0b130..4c71861 100644 --- a/Include/genobject.h +++ b/Include/genobject.h @@ -10,27 +10,26 @@ extern "C" { struct _frame; /* Avoid including frameobject.h */ +/* _PyGenObject_HEAD defines the initial segment of generator + and coroutine objects. */ +#define _PyGenObject_HEAD(prefix) \ + PyObject_HEAD \ + /* Note: gi_frame can be NULL if the generator is "finished" */ \ + struct _frame *prefix##_frame; \ + /* True if generator is being executed. */ \ + char prefix##_running; \ + /* The code object backing the generator */ \ + PyObject *prefix##_code; \ + /* List of weak reference. */ \ + PyObject *prefix##_weakreflist; \ + /* Name of the generator. */ \ + PyObject *prefix##_name; \ + /* Qualified name of the generator. */ \ + PyObject *prefix##_qualname; + typedef struct { - PyObject_HEAD /* The gi_ prefix is intended to remind of generator-iterator. */ - - /* Note: gi_frame can be NULL if the generator is "finished" */ - struct _frame *gi_frame; - - /* True if generator is being executed. */ - char gi_running; - - /* The code object backing the generator */ - PyObject *gi_code; - - /* List of weak reference. */ - PyObject *gi_weakreflist; - - /* Name of the generator. */ - PyObject *gi_name; - - /* Qualified name of the generator. */ - PyObject *gi_qualname; + _PyGenObject_HEAD(gi) } PyGenObject; PyAPI_DATA(PyTypeObject) PyGen_Type; @@ -38,12 +37,6 @@ PyAPI_DATA(PyTypeObject) PyGen_Type; #define PyGen_Check(op) PyObject_TypeCheck(op, &PyGen_Type) #define PyGen_CheckExact(op) (Py_TYPE(op) == &PyGen_Type) -#define PyGen_CheckCoroutineExact(op) (PyGen_CheckExact(op) && \ - (((PyCodeObject*) \ - ((PyGenObject*)op)->gi_code) \ - ->co_flags & (CO_ITERABLE_COROUTINE | \ - CO_COROUTINE))) - PyAPI_FUNC(PyObject *) PyGen_New(struct _frame *); PyAPI_FUNC(PyObject *) PyGen_NewWithQualName(struct _frame *, PyObject *name, PyObject *qualname); @@ -52,7 +45,21 @@ PyAPI_FUNC(int) _PyGen_FetchStopIterationValue(PyObject **); PyObject *_PyGen_Send(PyGenObject *, PyObject *); PyAPI_FUNC(void) _PyGen_Finalize(PyObject *self); -PyObject *_PyGen_GetAwaitableIter(PyObject *o); +#ifndef Py_LIMITED_API +typedef struct { + _PyGenObject_HEAD(cr) +} PyCoroObject; + +PyAPI_DATA(PyTypeObject) PyCoro_Type; +PyAPI_DATA(PyTypeObject) _PyCoroWrapper_Type; + +#define PyCoro_CheckExact(op) (Py_TYPE(op) == &PyCoro_Type) +PyObject *_PyCoro_GetAwaitableIter(PyObject *o); +PyAPI_FUNC(PyObject *) PyCoro_New(struct _frame *, + PyObject *name, PyObject *qualname); +#endif + +#undef _PyGenObject_HEAD #ifdef __cplusplus } diff --git a/Include/opcode.h b/Include/opcode.h index ca59338..3f917fb 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -45,6 +45,7 @@ extern "C" { #define BINARY_OR 66 #define INPLACE_POWER 67 #define GET_ITER 68 +#define GET_YIELD_FROM_ITER 69 #define PRINT_EXPR 70 #define LOAD_BUILD_CLASS 71 #define YIELD_FROM 72 diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py index a02b219..ba6a9b8 100644 --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -52,6 +52,12 @@ dict_items = type({}.items()) ## misc ## mappingproxy = type(type.__dict__) generator = type((lambda: (yield))()) +## coroutine ## +async def _coro(): pass +_coro = _coro() +coroutine = type(_coro) +_coro.close() # Prevent ResourceWarning +del _coro ### ONE-TRICK PONIES ### @@ -78,17 +84,15 @@ class Hashable(metaclass=ABCMeta): class _AwaitableMeta(ABCMeta): def __instancecheck__(cls, instance): - # 0x80 = CO_COROUTINE - # 0x100 = CO_ITERABLE_COROUTINE - # We don't want to import 'inspect' module, as - # a dependency for 'collections.abc'. - CO_COROUTINES = 0x80 | 0x100 - - if (isinstance(instance, generator) and - instance.gi_code.co_flags & CO_COROUTINES): - + # This hook is needed because we can't add + # '__await__' method to generator objects, and + # we can't register GeneratorType on Awaitable. + # NB: 0x100 = CO_ITERABLE_COROUTINE + # (We don't want to import 'inspect' module, as + # a dependency for 'collections.abc') + if (instance.__class__ is generator and + instance.gi_code.co_flags & 0x100): return True - return super().__instancecheck__(instance) @@ -159,6 +163,9 @@ class Coroutine(Awaitable): return NotImplemented +Coroutine.register(coroutine) + + class AsyncIterable(metaclass=ABCMeta): __slots__ = () diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py index edb6806..4fc46a5 100644 --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -34,30 +34,20 @@ _DEBUG = (not sys.flags.ignore_environment try: - types.coroutine + _types_coroutine = types.coroutine except AttributeError: - native_coroutine_support = False -else: - native_coroutine_support = True + _types_coroutine = None try: - _iscoroutinefunction = inspect.iscoroutinefunction + _inspect_iscoroutinefunction = inspect.iscoroutinefunction except AttributeError: - _iscoroutinefunction = lambda func: False + _inspect_iscoroutinefunction = lambda func: False try: - inspect.CO_COROUTINE -except AttributeError: - _is_native_coro_code = lambda code: False -else: - _is_native_coro_code = lambda code: (code.co_flags & - inspect.CO_COROUTINE) - -try: - from collections.abc import Coroutine as CoroutineABC, \ - Awaitable as AwaitableABC + from collections.abc import Coroutine as _CoroutineABC, \ + Awaitable as _AwaitableABC except ImportError: - CoroutineABC = AwaitableABC = None + _CoroutineABC = _AwaitableABC = None # Check for CPython issue #21209 @@ -89,10 +79,7 @@ def debug_wrapper(gen): # We only wrap here coroutines defined via 'async def' syntax. # Generator-based coroutines are wrapped in @coroutine # decorator. - if _is_native_coro_code(gen.gi_code): - return CoroWrapper(gen, None) - else: - return gen + return CoroWrapper(gen, None) class CoroWrapper: @@ -177,8 +164,7 @@ def coroutine(func): If the coroutine is not yielded from before it is destroyed, an error message is logged. """ - is_coroutine = _iscoroutinefunction(func) - if is_coroutine and _is_native_coro_code(func.__code__): + if _inspect_iscoroutinefunction(func): # In Python 3.5 that's all we need to do for coroutines # defiend with "async def". # Wrapping in CoroWrapper will happen via @@ -193,7 +179,7 @@ def coroutine(func): res = func(*args, **kw) if isinstance(res, futures.Future) or inspect.isgenerator(res): res = yield from res - elif AwaitableABC is not None: + elif _AwaitableABC is not None: # If 'func' returns an Awaitable (new in 3.5) we # want to run it. try: @@ -201,15 +187,15 @@ def coroutine(func): except AttributeError: pass else: - if isinstance(res, AwaitableABC): + if isinstance(res, _AwaitableABC): res = yield from await_meth() return res if not _DEBUG: - if native_coroutine_support: - wrapper = types.coroutine(coro) - else: + if _types_coroutine is None: wrapper = coro + else: + wrapper = _types_coroutine(coro) else: @functools.wraps(func) def wrapper(*args, **kwds): @@ -231,12 +217,12 @@ def coroutine(func): def iscoroutinefunction(func): """Return True if func is a decorated coroutine function.""" return (getattr(func, '_is_coroutine', False) or - _iscoroutinefunction(func)) + _inspect_iscoroutinefunction(func)) _COROUTINE_TYPES = (types.GeneratorType, CoroWrapper) -if CoroutineABC is not None: - _COROUTINE_TYPES += (CoroutineABC,) +if _CoroutineABC is not None: + _COROUTINE_TYPES += (_CoroutineABC,) def iscoroutine(obj): diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index b3c10b9..3508ce9 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -222,12 +222,13 @@ _code_type = type(_write_atomic.__code__) # Python 3.5a0 3320 (matrix multiplication operator) # Python 3.5b1 3330 (PEP 448: Additional Unpacking Generalizations) # Python 3.5b2 3340 (fix dictionary display evaluation order #11205) +# Python 3.5b2 3350 (add GET_YIELD_FROM_ITER opcode #24400) # # MAGIC must change whenever the bytecode emitted by the compiler may no # longer be understood by older implementations of the eval loop (usually # due to the addition of new opcodes). -MAGIC_NUMBER = (3340).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3350).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Lib/inspect.py b/Lib/inspect.py index 25ddd26..6285a6c 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -175,8 +175,7 @@ def isgeneratorfunction(object): See help(isfunction) for attributes listing.""" return bool((isfunction(object) or ismethod(object)) and - object.__code__.co_flags & CO_GENERATOR and - not object.__code__.co_flags & CO_COROUTINE) + object.__code__.co_flags & CO_GENERATOR) def iscoroutinefunction(object): """Return true if the object is a coroutine function. @@ -185,8 +184,7 @@ def iscoroutinefunction(object): or generators decorated with "types.coroutine". """ return bool((isfunction(object) or ismethod(object)) and - object.__code__.co_flags & (CO_ITERABLE_COROUTINE | - CO_COROUTINE)) + object.__code__.co_flags & CO_COROUTINE) def isawaitable(object): """Return true if the object can be used in "await" expression.""" @@ -207,12 +205,11 @@ def isgenerator(object): send resumes the generator and "sends" a value that becomes the result of the current yield-expression throw used to raise an exception inside the generator""" - return (isinstance(object, types.GeneratorType) and - not object.gi_code.co_flags & CO_COROUTINE) + return isinstance(object, types.GeneratorType) def iscoroutine(object): """Return true if the object is a coroutine.""" - return isinstance(object, collections.abc.Coroutine) + return isinstance(object, types.CoroutineType) def istraceback(object): """Return true if the object is a traceback. @@ -1598,6 +1595,45 @@ def getgeneratorlocals(generator): else: return {} + +# ------------------------------------------------ coroutine introspection + +CORO_CREATED = 'CORO_CREATED' +CORO_RUNNING = 'CORO_RUNNING' +CORO_SUSPENDED = 'CORO_SUSPENDED' +CORO_CLOSED = 'CORO_CLOSED' + +def getcoroutinestate(coroutine): + """Get current state of a coroutine object. + + Possible states are: + CORO_CREATED: Waiting to start execution. + CORO_RUNNING: Currently being executed by the interpreter. + CORO_SUSPENDED: Currently suspended at an await expression. + CORO_CLOSED: Execution has completed. + """ + if coroutine.cr_running: + return CORO_RUNNING + if coroutine.cr_frame is None: + return CORO_CLOSED + if coroutine.cr_frame.f_lasti == -1: + return CORO_CREATED + return CORO_SUSPENDED + + +def getcoroutinelocals(coroutine): + """ + Get the mapping of coroutine local variables to their current values. + + A dict is returned, with the keys the local variable names and values the + bound values.""" + frame = getattr(coroutine, "cr_frame", None) + if frame is not None: + return frame.f_locals + else: + return {} + + ############################################################################### ### Function Signature Object (PEP 362) ############################################################################### diff --git a/Lib/opcode.py b/Lib/opcode.py index c7b3443..4c826a7 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -103,6 +103,7 @@ def_op('BINARY_XOR', 65) def_op('BINARY_OR', 66) def_op('INPLACE_POWER', 67) def_op('GET_ITER', 68) +def_op('GET_YIELD_FROM_ITER', 69) def_op('PRINT_EXPR', 70) def_op('LOAD_BUILD_CLASS', 71) diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py index e3a3304..8d2b1a3 100644 --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -24,7 +24,7 @@ class AsyncYield: def run_async(coro): - assert coro.__class__ is types.GeneratorType + assert coro.__class__ in {types.GeneratorType, types.CoroutineType} buffer = [] result = None @@ -37,6 +37,25 @@ def run_async(coro): return buffer, result +def run_async__await__(coro): + assert coro.__class__ is types.CoroutineType + aw = coro.__await__() + buffer = [] + result = None + i = 0 + while True: + try: + if i % 2: + buffer.append(next(aw)) + else: + buffer.append(aw.send(None)) + i += 1 + except StopIteration as ex: + result = ex.args[0] if ex.args else None + break + return buffer, result + + @contextlib.contextmanager def silence_coro_gc(): with warnings.catch_warnings(): @@ -121,22 +140,24 @@ class CoroutineTest(unittest.TestCase): return 10 f = foo() - self.assertIsInstance(f, types.GeneratorType) - self.assertTrue(bool(foo.__code__.co_flags & 0x80)) - self.assertTrue(bool(foo.__code__.co_flags & 0x20)) - self.assertTrue(bool(f.gi_code.co_flags & 0x80)) - self.assertTrue(bool(f.gi_code.co_flags & 0x20)) + self.assertIsInstance(f, types.CoroutineType) + self.assertTrue(bool(foo.__code__.co_flags & inspect.CO_COROUTINE)) + self.assertFalse(bool(foo.__code__.co_flags & inspect.CO_GENERATOR)) + self.assertTrue(bool(f.cr_code.co_flags & inspect.CO_COROUTINE)) + self.assertFalse(bool(f.cr_code.co_flags & inspect.CO_GENERATOR)) self.assertEqual(run_async(f), ([], 10)) + self.assertEqual(run_async__await__(foo()), ([], 10)) + def bar(): pass - self.assertFalse(bool(bar.__code__.co_flags & 0x80)) + self.assertFalse(bool(bar.__code__.co_flags & inspect.CO_COROUTINE)) def test_func_2(self): async def foo(): raise StopIteration with self.assertRaisesRegex( - RuntimeError, "generator raised StopIteration"): + RuntimeError, "coroutine raised StopIteration"): run_async(foo()) @@ -152,7 +173,7 @@ class CoroutineTest(unittest.TestCase): raise StopIteration check = lambda: self.assertRaisesRegex( - TypeError, "coroutine-objects do not support iteration") + TypeError, "'coroutine' object is not iterable") with check(): list(foo()) @@ -166,9 +187,6 @@ class CoroutineTest(unittest.TestCase): with check(): iter(foo()) - with check(): - next(foo()) - with silence_coro_gc(), check(): for i in foo(): pass @@ -185,7 +203,7 @@ class CoroutineTest(unittest.TestCase): await bar() check = lambda: self.assertRaisesRegex( - TypeError, "coroutine-objects do not support iteration") + TypeError, "'coroutine' object is not iterable") with check(): for el in foo(): pass @@ -221,7 +239,7 @@ class CoroutineTest(unittest.TestCase): with silence_coro_gc(), self.assertRaisesRegex( TypeError, - "cannot 'yield from' a coroutine object from a generator"): + "cannot 'yield from' a coroutine object in a non-coroutine generator"): list(foo()) @@ -244,6 +262,98 @@ class CoroutineTest(unittest.TestCase): foo() support.gc_collect() + def test_func_10(self): + N = 0 + + @types.coroutine + def gen(): + nonlocal N + try: + a = yield + yield (a ** 2) + except ZeroDivisionError: + N += 100 + raise + finally: + N += 1 + + async def foo(): + await gen() + + coro = foo() + aw = coro.__await__() + self.assertIs(aw, iter(aw)) + next(aw) + self.assertEqual(aw.send(10), 100) + + self.assertEqual(N, 0) + aw.close() + self.assertEqual(N, 1) + + coro = foo() + aw = coro.__await__() + next(aw) + with self.assertRaises(ZeroDivisionError): + aw.throw(ZeroDivisionError, None, None) + self.assertEqual(N, 102) + + def test_func_11(self): + async def func(): pass + coro = func() + # Test that PyCoro_Type and _PyCoroWrapper_Type types were properly + # initialized + self.assertIn('__await__', dir(coro)) + self.assertIn('__iter__', dir(coro.__await__())) + self.assertIn('coroutine_wrapper', repr(coro.__await__())) + coro.close() # avoid RuntimeWarning + + def test_func_12(self): + async def g(): + i = me.send(None) + await foo + me = g() + with self.assertRaisesRegex(ValueError, + "coroutine already executing"): + me.send(None) + + def test_func_13(self): + async def g(): + pass + with self.assertRaisesRegex( + TypeError, + "can't send non-None value to a just-started coroutine"): + + g().send('spam') + + def test_func_14(self): + @types.coroutine + def gen(): + yield + async def coro(): + try: + await gen() + except GeneratorExit: + await gen() + c = coro() + c.send(None) + with self.assertRaisesRegex(RuntimeError, + "coroutine ignored GeneratorExit"): + c.close() + + def test_corotype_1(self): + ct = types.CoroutineType + self.assertIn('into coroutine', ct.send.__doc__) + self.assertIn('inside coroutine', ct.close.__doc__) + self.assertIn('in coroutine', ct.throw.__doc__) + self.assertIn('of the coroutine', ct.__dict__['__name__'].__doc__) + self.assertIn('of the coroutine', ct.__dict__['__qualname__'].__doc__) + self.assertEqual(ct.__name__, 'coroutine') + + async def f(): pass + c = f() + self.assertIn('coroutine object', repr(c)) + c.close() + def test_await_1(self): async def foo(): @@ -262,6 +372,7 @@ class CoroutineTest(unittest.TestCase): await AsyncYieldFrom([1, 2, 3]) self.assertEqual(run_async(foo()), ([1, 2, 3], None)) + self.assertEqual(run_async__await__(foo()), ([1, 2, 3], None)) def test_await_4(self): async def bar(): @@ -1015,6 +1126,27 @@ class SysSetCoroWrapperTest(unittest.TestCase): finally: sys.set_coroutine_wrapper(None) + def test_set_wrapper_4(self): + @types.coroutine + def foo(): + return 'spam' + + wrapped = None + def wrap(gen): + nonlocal wrapped + wrapped = gen + return gen + + sys.set_coroutine_wrapper(wrap) + try: + foo() + self.assertIs( + wrapped, None, + "generator-based coroutine was wrapped via " + "sys.set_coroutine_wrapper") + finally: + sys.set_coroutine_wrapper(None) + class CAPITest(unittest.TestCase): diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 4695da8..39fa484 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -141,9 +141,9 @@ class TestPredicates(IsTestBase): gen_coro = gen_coroutine_function_example(1) coro = coroutine_function_example(1) - self.assertTrue( + self.assertFalse( inspect.iscoroutinefunction(gen_coroutine_function_example)) - self.assertTrue(inspect.iscoroutine(gen_coro)) + self.assertFalse(inspect.iscoroutine(gen_coro)) self.assertTrue( inspect.isgeneratorfunction(gen_coroutine_function_example)) @@ -1737,6 +1737,70 @@ class TestGetGeneratorState(unittest.TestCase): self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3)) +class TestGetCoroutineState(unittest.TestCase): + + def setUp(self): + @types.coroutine + def number_coroutine(): + for number in range(5): + yield number + async def coroutine(): + await number_coroutine() + self.coroutine = coroutine() + + def tearDown(self): + self.coroutine.close() + + def _coroutinestate(self): + return inspect.getcoroutinestate(self.coroutine) + + def test_created(self): + self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED) + + def test_suspended(self): + self.coroutine.send(None) + self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED) + + def test_closed_after_exhaustion(self): + while True: + try: + self.coroutine.send(None) + except StopIteration: + break + + self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED) + + def test_closed_after_immediate_exception(self): + with self.assertRaises(RuntimeError): + self.coroutine.throw(RuntimeError) + self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED) + + def test_easy_debugging(self): + # repr() and str() of a coroutine state should contain the state name + names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split() + for name in names: + state = getattr(inspect, name) + self.assertIn(name, repr(state)) + self.assertIn(name, str(state)) + + def test_getcoroutinelocals(self): + @types.coroutine + def gencoro(): + yield + + gencoro = gencoro() + async def func(a=None): + b = 'spam' + await gencoro + + coro = func() + self.assertEqual(inspect.getcoroutinelocals(coro), + {'a': None, 'gencoro': gencoro}) + coro.send(None) + self.assertEqual(inspect.getcoroutinelocals(coro), + {'a': None, 'gencoro': gencoro, 'b': 'spam'}) + + class MySignature(inspect.Signature): # Top-level to make it picklable; # used in test_signature_object_pickle @@ -3494,7 +3558,8 @@ def test_main(): TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject, TestBoundArguments, TestSignaturePrivateHelpers, TestSignatureDefinitions, - TestGetClosureVars, TestUnwrap, TestMain, TestReload + TestGetClosureVars, TestUnwrap, TestMain, TestReload, + TestGetCoroutineState ) if __name__ == "__main__": diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 17ec645..5b971d1 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1205,10 +1205,28 @@ class CoroutineTests(unittest.TestCase): def test_wrong_func(self): @types.coroutine def foo(): - pass - with self.assertRaisesRegex(TypeError, - 'callable wrapped .* non-coroutine'): - foo() + return 'spam' + self.assertEqual(foo(), 'spam') + + def test_async_def(self): + # Test that types.coroutine passes 'async def' coroutines + # without modification + + async def foo(): pass + foo_code = foo.__code__ + foo_flags = foo.__code__.co_flags + decorated_foo = types.coroutine(foo) + self.assertIs(foo, decorated_foo) + self.assertEqual(foo.__code__.co_flags, foo_flags) + self.assertIs(decorated_foo.__code__, foo_code) + + foo_coro = foo() + @types.coroutine + def bar(): return foo_coro + coro = bar() + self.assertIs(foo_coro, coro) + self.assertEqual(coro.cr_code.co_flags, foo_flags) + coro.close() def test_duck_coro(self): class CoroLike: @@ -1221,6 +1239,23 @@ class CoroutineTests(unittest.TestCase): @types.coroutine def foo(): return coro + self.assertIs(foo(), coro) + self.assertIs(foo().__await__(), coro) + + def test_duck_corogen(self): + class CoroGenLike: + def send(self): pass + def throw(self): pass + def close(self): pass + def __await__(self): return self + def __iter__(self): return self + def __next__(self): pass + + coro = CoroGenLike() + @types.coroutine + def foo(): + return coro + self.assertIs(foo(), coro) self.assertIs(foo().__await__(), coro) def test_duck_gen(self): @@ -1236,7 +1271,7 @@ class CoroutineTests(unittest.TestCase): def foo(): return gen self.assertIs(foo().__await__(), gen) - + self.assertTrue(isinstance(foo(), collections.abc.Coroutine)) with self.assertRaises(AttributeError): foo().gi_code @@ -1251,6 +1286,7 @@ class CoroutineTests(unittest.TestCase): 'gi_running', 'gi_frame'): self.assertIs(getattr(foo(), name), getattr(gen, name)) + self.assertIs(foo().cr_code, gen.gi_code) def test_genfunc(self): def gen(): @@ -1259,7 +1295,13 @@ class CoroutineTests(unittest.TestCase): self.assertFalse(isinstance(gen(), collections.abc.Coroutine)) self.assertFalse(isinstance(gen(), collections.abc.Awaitable)) - self.assertIs(types.coroutine(gen), gen) + gen_code = gen.__code__ + decorated_gen = types.coroutine(gen) + self.assertIs(decorated_gen, gen) + self.assertIsNot(decorated_gen.__code__, gen_code) + + decorated_gen2 = types.coroutine(decorated_gen) + self.assertIs(decorated_gen2.__code__, decorated_gen.__code__) self.assertTrue(gen.__code__.co_flags & inspect.CO_ITERABLE_COROUTINE) self.assertFalse(gen.__code__.co_flags & inspect.CO_COROUTINE) diff --git a/Lib/types.py b/Lib/types.py index 0a87c2f..dc1b040 100644 --- a/Lib/types.py +++ b/Lib/types.py @@ -19,6 +19,11 @@ def _g(): yield 1 GeneratorType = type(_g()) +async def _c(): pass +_c = _c() +CoroutineType = type(_c) +_c.close() # Prevent ResourceWarning + class _C: def _m(self): pass MethodType = type(_C()._m) @@ -40,7 +45,7 @@ except TypeError: GetSetDescriptorType = type(FunctionType.__code__) MemberDescriptorType = type(FunctionType.__globals__) -del sys, _f, _g, _C, # Not for export +del sys, _f, _g, _C, _c, # Not for export # Provide a PEP 3115 compliant mechanism for class creation @@ -164,29 +169,33 @@ import collections.abc as _collections_abc def coroutine(func): """Convert regular generator function to a coroutine.""" - # We don't want to import 'dis' or 'inspect' just for - # these constants. - CO_GENERATOR = 0x20 - CO_ITERABLE_COROUTINE = 0x100 - if not callable(func): raise TypeError('types.coroutine() expects a callable') - if (isinstance(func, FunctionType) and - isinstance(getattr(func, '__code__', None), CodeType) and - (func.__code__.co_flags & CO_GENERATOR)): - - # TODO: Implement this in C. - co = func.__code__ - func.__code__ = CodeType( - co.co_argcount, co.co_kwonlyargcount, co.co_nlocals, - co.co_stacksize, - co.co_flags | CO_ITERABLE_COROUTINE, - co.co_code, - co.co_consts, co.co_names, co.co_varnames, co.co_filename, - co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, - co.co_cellvars) - return func + if (func.__class__ is FunctionType and + getattr(func, '__code__', None).__class__ is CodeType): + + co_flags = func.__code__.co_flags + + # Check if 'func' is a coroutine function. + # (0x180 == CO_COROUTINE | CO_ITERABLE_COROUTINE) + if co_flags & 0x180: + return func + + # Check if 'func' is a generator function. + # (0x20 == CO_GENERATOR) + if co_flags & 0x20: + # TODO: Implement this in C. + co = func.__code__ + func.__code__ = CodeType( + co.co_argcount, co.co_kwonlyargcount, co.co_nlocals, + co.co_stacksize, + co.co_flags | 0x100, # 0x100 == CO_ITERABLE_COROUTINE + co.co_code, + co.co_consts, co.co_names, co.co_varnames, co.co_filename, + co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, + co.co_cellvars) + return func # The following code is primarily to support functions that # return generator-like objects (for instance generators @@ -195,11 +204,14 @@ def coroutine(func): class GeneratorWrapper: def __init__(self, gen): self.__wrapped__ = gen - self.send = gen.send - self.throw = gen.throw - self.close = gen.close self.__name__ = getattr(gen, '__name__', None) self.__qualname__ = getattr(gen, '__qualname__', None) + def send(self, val): + return self.__wrapped__.send(val) + def throw(self, *args): + return self.__wrapped__.throw(*args) + def close(self): + return self.__wrapped__.close() @property def gi_code(self): return self.__wrapped__.gi_code @@ -209,24 +221,31 @@ def coroutine(func): @property def gi_running(self): return self.__wrapped__.gi_running + cr_code = gi_code + cr_frame = gi_frame + cr_running = gi_running def __next__(self): return next(self.__wrapped__) def __iter__(self): return self.__wrapped__ - __await__ = __iter__ + def __await__(self): + return self.__wrapped__ @_functools.wraps(func) def wrapped(*args, **kwargs): coro = func(*args, **kwargs) - if coro.__class__ is GeneratorType: + if coro.__class__ is CoroutineType: + # 'coro' is a native coroutine object. + return coro + if (coro.__class__ is GeneratorType or + (isinstance(coro, _collections_abc.Generator) and + not isinstance(coro, _collections_abc.Coroutine))): + # 'coro' is either a pure Python generator iterator, or it + # implements collections.abc.Generator (and does not implement + # collections.abc.Coroutine). return GeneratorWrapper(coro) - # slow checks - if not isinstance(coro, _collections_abc.Coroutine): - if isinstance(coro, _collections_abc.Generator): - return GeneratorWrapper(coro) - raise TypeError( - 'callable wrapped with types.coroutine() returned ' - 'non-coroutine: {!r}'.format(coro)) + # 'coro' is either an instance of collections.abc.Coroutine or + # some other object -- pass it through. return coro return wrapped @@ -12,6 +12,15 @@ Core and Builtins - Issue #24345: Add Py_tp_finalize slot for the stable ABI. +- Issue #24400: Introduce a distinct type for PEP 492 coroutines; add + types.CoroutineType, inspect.getcoroutinestate, inspect.getcoroutinelocals; + coroutines no longer use CO_GENERATOR flag; sys.set_coroutine_wrapper + works only for 'async def' coroutines; inspect.iscoroutine no longer + uses collections.abc.Coroutine, it's intended to test for pure 'async def' + coroutines only; add new opcode: GET_YIELD_FROM_ITER; fix generators wrapper + used in types.coroutine to be instance of collections.abc.Generator. + + Library ------- diff --git a/Objects/genobject.c b/Objects/genobject.c index 5d3b66c..40340b4 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -27,8 +27,7 @@ _PyGen_Finalize(PyObject *self) /* If `gen` is a coroutine, and if it was never awaited on, issue a RuntimeWarning. */ if (gen->gi_code != NULL - && ((PyCodeObject *)gen->gi_code)->co_flags & (CO_COROUTINE - | CO_ITERABLE_COROUTINE) + && ((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE && gen->gi_frame != NULL && gen->gi_frame->f_lasti == -1 && !PyErr_Occurred() @@ -86,8 +85,10 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc) PyObject *result; if (gen->gi_running) { - PyErr_SetString(PyExc_ValueError, - "generator already executing"); + char *msg = "generator already executing"; + if (PyCoro_CheckExact(gen)) + msg = "coroutine already executing"; + PyErr_SetString(PyExc_ValueError, msg); return NULL; } if (f == NULL || f->f_stacktop == NULL) { @@ -99,9 +100,12 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc) if (f->f_lasti == -1) { if (arg && arg != Py_None) { - PyErr_SetString(PyExc_TypeError, - "can't send non-None value to a " - "just-started generator"); + char *msg = "can't send non-None value to a " + "just-started generator"; + if (PyCoro_CheckExact(gen)) + msg = "can't send non-None value to a " + "just-started coroutine"; + PyErr_SetString(PyExc_TypeError, msg); return NULL; } } else { @@ -151,14 +155,16 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc) (CO_FUTURE_GENERATOR_STOP | CO_COROUTINE | CO_ITERABLE_COROUTINE)) { PyObject *exc, *val, *val2, *tb; + char *msg = "generator raised StopIteration"; + if (PyCoro_CheckExact(gen)) + msg = "coroutine raised StopIteration"; PyErr_Fetch(&exc, &val, &tb); PyErr_NormalizeException(&exc, &val, &tb); if (tb != NULL) PyException_SetTraceback(val, tb); Py_DECREF(exc); Py_XDECREF(tb); - PyErr_SetString(PyExc_RuntimeError, - "generator raised StopIteration"); + PyErr_SetString(PyExc_RuntimeError, msg); PyErr_Fetch(&exc, &val2, &tb); PyErr_NormalizeException(&exc, &val2, &tb); Py_INCREF(val); @@ -288,9 +294,11 @@ gen_close(PyGenObject *gen, PyObject *args) PyErr_SetNone(PyExc_GeneratorExit); retval = gen_send_ex(gen, Py_None, 1); if (retval) { + char *msg = "generator ignored GeneratorExit"; + if (PyCoro_CheckExact(gen)) + msg = "coroutine ignored GeneratorExit"; Py_DECREF(retval); - PyErr_SetString(PyExc_RuntimeError, - "generator ignored GeneratorExit"); + PyErr_SetString(PyExc_RuntimeError, msg); return NULL; } if (PyErr_ExceptionMatches(PyExc_StopIteration) @@ -432,12 +440,6 @@ failed_throw: static PyObject * gen_iternext(PyGenObject *gen) { - if (((PyCodeObject*)gen->gi_code)->co_flags & CO_COROUTINE) { - PyErr_SetString(PyExc_TypeError, - "coroutine-objects do not support iteration"); - return NULL; - } - return gen_send_ex(gen, NULL, 0); } @@ -494,14 +496,8 @@ _PyGen_FetchStopIterationValue(PyObject **pvalue) { static PyObject * gen_repr(PyGenObject *gen) { - if (PyGen_CheckCoroutineExact(gen)) { - return PyUnicode_FromFormat("<coroutine object %S at %p>", - gen->gi_qualname, gen); - } - else { - return PyUnicode_FromFormat("<generator object %S at %p>", - gen->gi_qualname, gen); - } + return PyUnicode_FromFormat("<generator object %S at %p>", + gen->gi_qualname, gen); } static PyObject * @@ -537,19 +533,6 @@ gen_get_qualname(PyGenObject *op) return op->gi_qualname; } -static PyObject * -gen_get_iter(PyGenObject *gen) -{ - if (((PyCodeObject*)gen->gi_code)->co_flags & CO_COROUTINE) { - PyErr_SetString(PyExc_TypeError, - "coroutine-objects do not support iteration"); - return NULL; - } - - Py_INCREF(gen); - return (PyObject *)gen; -} - static int gen_set_qualname(PyGenObject *op, PyObject *value) { @@ -619,7 +602,7 @@ PyTypeObject PyGen_Type = { 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(PyGenObject, gi_weakreflist), /* tp_weaklistoffset */ - (getiterfunc)gen_get_iter, /* tp_iter */ + PyObject_SelfIter, /* tp_iter */ (iternextfunc)gen_iternext, /* tp_iternext */ gen_methods, /* tp_methods */ gen_memberlist, /* tp_members */ @@ -645,10 +628,11 @@ PyTypeObject PyGen_Type = { _PyGen_Finalize, /* tp_finalize */ }; -PyObject * -PyGen_NewWithQualName(PyFrameObject *f, PyObject *name, PyObject *qualname) +static PyObject * +gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f, + PyObject *name, PyObject *qualname) { - PyGenObject *gen = PyObject_GC_New(PyGenObject, &PyGen_Type); + PyGenObject *gen = PyObject_GC_New(PyGenObject, type); if (gen == NULL) { Py_DECREF(f); return NULL; @@ -674,9 +658,15 @@ PyGen_NewWithQualName(PyFrameObject *f, PyObject *name, PyObject *qualname) } PyObject * +PyGen_NewWithQualName(PyFrameObject *f, PyObject *name, PyObject *qualname) +{ + return gen_new_with_qualname(&PyGen_Type, f, name, qualname); +} + +PyObject * PyGen_New(PyFrameObject *f) { - return PyGen_NewWithQualName(f, NULL, NULL); + return gen_new_with_qualname(&PyGen_Type, f, NULL, NULL); } int @@ -697,6 +687,25 @@ PyGen_NeedsFinalizing(PyGenObject *gen) return 0; } +/* Coroutine Object */ + +typedef struct { + PyObject_HEAD + PyCoroObject *cw_coroutine; +} PyCoroWrapper; + +static int +gen_is_coroutine(PyObject *o) +{ + if (PyGen_CheckExact(o)) { + PyCodeObject *code = (PyCodeObject *)((PyGenObject*)o)->gi_code; + if (code->co_flags & CO_ITERABLE_COROUTINE) { + return 1; + } + } + return 0; +} + /* * This helper function returns an awaitable for `o`: * - `o` if `o` is a coroutine-object; @@ -706,13 +715,13 @@ PyGen_NeedsFinalizing(PyGenObject *gen) * an awaitable and returns NULL. */ PyObject * -_PyGen_GetAwaitableIter(PyObject *o) +_PyCoro_GetAwaitableIter(PyObject *o) { unaryfunc getter = NULL; PyTypeObject *ot; - if (PyGen_CheckCoroutineExact(o)) { - /* Fast path. It's a central function for 'await'. */ + if (PyCoro_CheckExact(o) || gen_is_coroutine(o)) { + /* 'o' is a coroutine. */ Py_INCREF(o); return o; } @@ -724,22 +733,19 @@ _PyGen_GetAwaitableIter(PyObject *o) if (getter != NULL) { PyObject *res = (*getter)(o); if (res != NULL) { - if (!PyIter_Check(res)) { + if (PyCoro_CheckExact(res) || gen_is_coroutine(res)) { + /* __await__ must return an *iterator*, not + a coroutine or another awaitable (see PEP 492) */ + PyErr_SetString(PyExc_TypeError, + "__await__() returned a coroutine"); + Py_CLEAR(res); + } else if (!PyIter_Check(res)) { PyErr_Format(PyExc_TypeError, "__await__() returned non-iterator " "of type '%.100s'", Py_TYPE(res)->tp_name); Py_CLEAR(res); } - else { - if (PyGen_CheckCoroutineExact(res)) { - /* __await__ must return an *iterator*, not - a coroutine or another awaitable (see PEP 492) */ - PyErr_SetString(PyExc_TypeError, - "__await__() returned a coroutine"); - Py_CLEAR(res); - } - } } return res; } @@ -747,6 +753,211 @@ _PyGen_GetAwaitableIter(PyObject *o) PyErr_Format(PyExc_TypeError, "object %.100s can't be used in 'await' expression", ot->tp_name); - return NULL; } + +static PyObject * +coro_repr(PyCoroObject *coro) +{ + return PyUnicode_FromFormat("<coroutine object %S at %p>", + coro->cr_qualname, coro); +} + +static PyObject * +coro_await(PyCoroObject *coro) +{ + PyCoroWrapper *cw = PyObject_GC_New(PyCoroWrapper, &_PyCoroWrapper_Type); + if (cw == NULL) { + return NULL; + } + Py_INCREF(coro); + cw->cw_coroutine = coro; + _PyObject_GC_TRACK(cw); + return (PyObject *)cw; +} + +static PyGetSetDef coro_getsetlist[] = { + {"__name__", (getter)gen_get_name, (setter)gen_set_name, + PyDoc_STR("name of the coroutine")}, + {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname, + PyDoc_STR("qualified name of the coroutine")}, + {NULL} /* Sentinel */ +}; + +static PyMemberDef coro_memberlist[] = { + {"cr_frame", T_OBJECT, offsetof(PyCoroObject, cr_frame), READONLY}, + {"cr_running", T_BOOL, offsetof(PyCoroObject, cr_running), READONLY}, + {"cr_code", T_OBJECT, offsetof(PyCoroObject, cr_code), READONLY}, + {NULL} /* Sentinel */ +}; + +PyDoc_STRVAR(coro_send_doc, +"send(arg) -> send 'arg' into coroutine,\n\ +return next yielded value or raise StopIteration."); + +PyDoc_STRVAR(coro_throw_doc, +"throw(typ[,val[,tb]]) -> raise exception in coroutine,\n\ +return next yielded value or raise StopIteration."); + +PyDoc_STRVAR(coro_close_doc, +"close() -> raise GeneratorExit inside coroutine."); + +static PyMethodDef coro_methods[] = { + {"send",(PyCFunction)_PyGen_Send, METH_O, coro_send_doc}, + {"throw",(PyCFunction)gen_throw, METH_VARARGS, coro_throw_doc}, + {"close",(PyCFunction)gen_close, METH_NOARGS, coro_close_doc}, + {NULL, NULL} /* Sentinel */ +}; + +static PyAsyncMethods coro_as_async = { + (unaryfunc)coro_await, /* am_await */ + 0, /* am_aiter */ + 0 /* am_anext */ +}; + +PyTypeObject PyCoro_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "coroutine", /* tp_name */ + sizeof(PyCoroObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)gen_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + &coro_as_async, /* tp_as_async */ + (reprfunc)coro_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */ + 0, /* tp_doc */ + (traverseproc)gen_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + offsetof(PyCoroObject, cr_weakreflist), /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + coro_methods, /* tp_methods */ + coro_memberlist, /* tp_members */ + coro_getsetlist, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ + 0, /* tp_del */ + 0, /* tp_version_tag */ + _PyGen_Finalize, /* tp_finalize */ +}; + +static void +coro_wrapper_dealloc(PyCoroWrapper *cw) +{ + _PyObject_GC_UNTRACK((PyObject *)cw); + Py_CLEAR(cw->cw_coroutine); + PyObject_GC_Del(cw); +} + +static PyObject * +coro_wrapper_iternext(PyCoroWrapper *cw) +{ + return gen_send_ex((PyGenObject *)cw->cw_coroutine, NULL, 0); +} + +static PyObject * +coro_wrapper_send(PyCoroWrapper *cw, PyObject *arg) +{ + return gen_send_ex((PyGenObject *)cw->cw_coroutine, arg, 0); +} + +static PyObject * +coro_wrapper_throw(PyCoroWrapper *cw, PyObject *args) +{ + return gen_throw((PyGenObject *)cw->cw_coroutine, args); +} + +static PyObject * +coro_wrapper_close(PyCoroWrapper *cw, PyObject *args) +{ + return gen_close((PyGenObject *)cw->cw_coroutine, args); +} + +static int +coro_wrapper_traverse(PyCoroWrapper *cw, visitproc visit, void *arg) +{ + Py_VISIT((PyObject *)cw->cw_coroutine); + return 0; +} + +static PyMethodDef coro_wrapper_methods[] = { + {"send",(PyCFunction)coro_wrapper_send, METH_O, send_doc}, + {"throw",(PyCFunction)coro_wrapper_throw, METH_VARARGS, throw_doc}, + {"close",(PyCFunction)coro_wrapper_close, METH_NOARGS, close_doc}, + {NULL, NULL} /* Sentinel */ +}; + +PyTypeObject _PyCoroWrapper_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "coroutine_wrapper", + sizeof(PyCoroWrapper), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)coro_wrapper_dealloc, /* destructor tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_as_async */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ + "A wrapper object implementing __await__ for coroutines.", + (traverseproc)coro_wrapper_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)coro_wrapper_iternext, /* tp_iternext */ + coro_wrapper_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + PyObject_Del, /* tp_free */ +}; + +PyObject * +PyCoro_New(PyFrameObject *f, PyObject *name, PyObject *qualname) +{ + return gen_new_with_qualname(&PyCoro_Type, f, name, qualname); +} diff --git a/Objects/object.c b/Objects/object.c index be12be5..11b7bff 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1726,6 +1726,12 @@ _Py_ReadyTypes(void) if (PyType_Ready(&PySeqIter_Type) < 0) Py_FatalError("Can't initialize sequence iterator type"); + + if (PyType_Ready(&PyCoro_Type) < 0) + Py_FatalError("Can't initialize coroutine type"); + + if (PyType_Ready(&_PyCoroWrapper_Type) < 0) + Py_FatalError("Can't initialize coroutine wrapper type"); } diff --git a/Python/ceval.c b/Python/ceval.c index e127a73..12df0fe 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1191,7 +1191,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) f->f_stacktop = NULL; /* remains NULL unless yield suspends frame */ f->f_executing = 1; - if (co->co_flags & CO_GENERATOR) { + if (co->co_flags & (CO_GENERATOR | CO_COROUTINE)) { if (!throwflag && f->f_exc_type != NULL && f->f_exc_type != Py_None) { /* We were in an except handler when we left, restore the exception state which was put aside @@ -1955,7 +1955,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) goto error; } - awaitable = _PyGen_GetAwaitableIter(iter); + awaitable = _PyCoro_GetAwaitableIter(iter); if (awaitable == NULL) { SET_TOP(NULL); PyErr_Format( @@ -1998,7 +1998,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) goto error; } - awaitable = _PyGen_GetAwaitableIter(next_iter); + awaitable = _PyCoro_GetAwaitableIter(next_iter); if (awaitable == NULL) { PyErr_Format( PyExc_TypeError, @@ -2017,7 +2017,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(GET_AWAITABLE) { PyObject *iterable = TOP(); - PyObject *iter = _PyGen_GetAwaitableIter(iterable); + PyObject *iter = _PyCoro_GetAwaitableIter(iterable); Py_DECREF(iterable); @@ -2034,25 +2034,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) PyObject *v = POP(); PyObject *reciever = TOP(); int err; - if (PyGen_CheckExact(reciever)) { - if ( - (((PyCodeObject*) \ - ((PyGenObject*)reciever)->gi_code)->co_flags & - CO_COROUTINE) - && !(co->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) - { - /* If we're yielding-from a coroutine object from a regular - generator object - raise an error. */ - - Py_CLEAR(v); - Py_CLEAR(reciever); - SET_TOP(NULL); - - PyErr_SetString(PyExc_TypeError, - "cannot 'yield from' a coroutine object " - "from a generator"); - goto error; - } + if (PyGen_CheckExact(reciever) || PyCoro_CheckExact(reciever)) { retval = _PyGen_Send((PyGenObject *)reciever, v); } else { _Py_IDENTIFIER(send); @@ -2929,19 +2911,33 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(GET_ITER) { /* before: [obj]; after [getiter(obj)] */ PyObject *iterable = TOP(); - PyObject *iter; - /* If we have a generator object on top -- keep it there, - it's already an iterator. - - This is needed to allow use of 'async def' coroutines - in 'yield from' expression from generator-based coroutines - (decorated with types.coroutine()). + PyObject *iter = PyObject_GetIter(iterable); + Py_DECREF(iterable); + SET_TOP(iter); + if (iter == NULL) + goto error; + PREDICT(FOR_ITER); + DISPATCH(); + } - 'yield from' is compiled to GET_ITER..YIELD_FROM combination, - but since coroutines raise TypeError in their 'tp_iter' we - need a way for them to "pass through" the GET_ITER. - */ - if (!PyGen_CheckExact(iterable)) { + TARGET(GET_YIELD_FROM_ITER) { + /* before: [obj]; after [getiter(obj)] */ + PyObject *iterable = TOP(); + PyObject *iter; + if (PyCoro_CheckExact(iterable)) { + /* `iterable` is a coroutine */ + if (!(co->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { + /* and it is used in a 'yield from' expression of a + regular generator. */ + Py_DECREF(iterable); + SET_TOP(NULL); + PyErr_SetString(PyExc_TypeError, + "cannot 'yield from' a coroutine object " + "in a non-coroutine generator"); + goto error; + } + } + else if (!PyGen_CheckExact(iterable)) { /* `iterable` is not a generator. */ iter = PyObject_GetIter(iterable); Py_DECREF(iterable); @@ -2949,7 +2945,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) if (iter == NULL) goto error; } - PREDICT(FOR_ITER); DISPATCH(); } @@ -3517,7 +3512,7 @@ fast_block_end: assert((retval != NULL) ^ (PyErr_Occurred() != NULL)); fast_yield: - if (co->co_flags & CO_GENERATOR) { + if (co->co_flags & (CO_GENERATOR | CO_COROUTINE)) { /* The purpose of this block is to put aside the generator's exception state and restore that of the calling frame. If the current @@ -3919,10 +3914,10 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals, freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o; } - if (co->co_flags & CO_GENERATOR) { + if (co->co_flags & (CO_GENERATOR | CO_COROUTINE)) { PyObject *gen; PyObject *coro_wrapper = tstate->coroutine_wrapper; - int is_coro = co->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE); + int is_coro = co->co_flags & CO_COROUTINE; if (is_coro && tstate->in_coroutine_wrapper) { assert(coro_wrapper != NULL); @@ -3942,7 +3937,11 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals, /* Create a new generator that owns the ready to run frame * and return that as the value. */ - gen = PyGen_NewWithQualName(f, name, qualname); + if (is_coro) { + gen = PyCoro_New(f, name, qualname); + } else { + gen = PyGen_NewWithQualName(f, name, qualname); + } if (gen == NULL) return NULL; diff --git a/Python/compile.c b/Python/compile.c index cbc23aa..1977c3a 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1064,6 +1064,8 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) return 0; case GET_ANEXT: return 1; + case GET_YIELD_FROM_ITER: + return 0; default: return PY_INVALID_STACK_EFFECT; } @@ -1751,12 +1753,8 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async) Py_DECREF(qualname); Py_DECREF(co); - if (is_async) { + if (is_async) co->co_flags |= CO_COROUTINE; - /* An async function is always a generator, even - if there is no 'yield' expressions in it. */ - co->co_flags |= CO_GENERATOR; - } /* decorators */ for (i = 0; i < asdl_seq_LEN(decos); i++) { @@ -3850,7 +3848,7 @@ compiler_visit_expr(struct compiler *c, expr_ty e) return compiler_error(c, "'yield from' inside async function"); VISIT(c, expr, e->v.YieldFrom.value); - ADDOP(c, GET_ITER); + ADDOP(c, GET_YIELD_FROM_ITER); ADDOP_O(c, LOAD_CONST, Py_None, consts); ADDOP(c, YIELD_FROM); break; diff --git a/Python/importlib_external.h b/Python/importlib_external.h index edf342b..aea434c 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -259,7 +259,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,114,5,0,0,0,218,13,95,119,114,105,116,101,95, 97,116,111,109,105,99,99,0,0,0,115,26,0,0,0,0, 5,24,1,9,1,33,1,3,3,21,1,20,1,20,1,13, - 1,3,1,17,1,13,1,5,1,114,55,0,0,0,105,12, + 1,3,1,17,1,13,1,5,1,114,55,0,0,0,105,22, 13,0,0,233,2,0,0,0,114,13,0,0,0,115,2,0, 0,0,13,10,90,11,95,95,112,121,99,97,99,104,101,95, 95,122,4,111,112,116,45,122,3,46,112,121,122,4,46,112, @@ -369,7 +369,7 @@ const unsigned char _Py_M__importlib_external[] = { 116,97,103,90,15,97,108,109,111,115,116,95,102,105,108,101, 110,97,109,101,114,4,0,0,0,114,4,0,0,0,114,5, 0,0,0,218,17,99,97,99,104,101,95,102,114,111,109,95, - 115,111,117,114,99,101,242,0,0,0,115,46,0,0,0,0, + 115,111,117,114,99,101,243,0,0,0,115,46,0,0,0,0, 18,12,1,9,1,7,1,12,1,6,1,12,1,18,1,18, 1,24,1,12,1,12,1,12,1,36,1,12,1,18,1,9, 2,12,1,12,1,12,1,12,1,21,1,21,1,114,79,0, @@ -448,7 +448,7 @@ const unsigned char _Py_M__importlib_external[] = { 95,108,101,118,101,108,90,13,98,97,115,101,95,102,105,108, 101,110,97,109,101,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,17,115,111,117,114,99,101,95,102,114,111, - 109,95,99,97,99,104,101,30,1,0,0,115,44,0,0,0, + 109,95,99,97,99,104,101,31,1,0,0,115,44,0,0,0, 0,9,18,1,12,1,18,1,18,1,12,1,9,1,15,1, 15,1,12,1,9,1,15,1,12,1,22,1,15,1,9,1, 12,1,22,1,12,1,9,1,12,1,19,1,114,85,0,0, @@ -486,7 +486,7 @@ const unsigned char _Py_M__importlib_external[] = { 115,105,111,110,218,11,115,111,117,114,99,101,95,112,97,116, 104,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, 218,15,95,103,101,116,95,115,111,117,114,99,101,102,105,108, - 101,63,1,0,0,115,20,0,0,0,0,7,18,1,4,1, + 101,64,1,0,0,115,20,0,0,0,0,7,18,1,4,1, 24,1,35,1,4,1,3,1,16,1,19,1,21,1,114,91, 0,0,0,99,1,0,0,0,0,0,0,0,1,0,0,0, 11,0,0,0,67,0,0,0,115,92,0,0,0,124,0,0, @@ -500,7 +500,7 @@ const unsigned char _Py_M__importlib_external[] = { 84,0,0,0,114,79,0,0,0,114,66,0,0,0,114,74, 0,0,0,41,1,218,8,102,105,108,101,110,97,109,101,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,11, - 95,103,101,116,95,99,97,99,104,101,100,82,1,0,0,115, + 95,103,101,116,95,99,97,99,104,101,100,83,1,0,0,115, 16,0,0,0,0,1,21,1,3,1,14,1,13,1,8,1, 21,1,4,2,114,95,0,0,0,99,1,0,0,0,0,0, 0,0,2,0,0,0,11,0,0,0,67,0,0,0,115,60, @@ -515,7 +515,7 @@ const unsigned char _Py_M__importlib_external[] = { 41,3,114,39,0,0,0,114,41,0,0,0,114,40,0,0, 0,41,2,114,35,0,0,0,114,42,0,0,0,114,4,0, 0,0,114,4,0,0,0,114,5,0,0,0,218,10,95,99, - 97,108,99,95,109,111,100,101,94,1,0,0,115,12,0,0, + 97,108,99,95,109,111,100,101,95,1,0,0,115,12,0,0, 0,0,2,3,1,19,1,13,1,11,3,10,1,114,97,0, 0,0,218,9,118,101,114,98,111,115,105,116,121,114,29,0, 0,0,99,1,0,0,0,1,0,0,0,3,0,0,0,4, @@ -536,7 +536,7 @@ const unsigned char _Py_M__importlib_external[] = { 218,6,115,116,100,101,114,114,41,3,114,75,0,0,0,114, 98,0,0,0,218,4,97,114,103,115,114,4,0,0,0,114, 4,0,0,0,114,5,0,0,0,218,16,95,118,101,114,98, - 111,115,101,95,109,101,115,115,97,103,101,106,1,0,0,115, + 111,115,101,95,109,101,115,115,97,103,101,107,1,0,0,115, 8,0,0,0,0,2,18,1,15,1,10,1,114,105,0,0, 0,99,1,0,0,0,0,0,0,0,3,0,0,0,11,0, 0,0,3,0,0,0,115,84,0,0,0,100,1,0,135,0, @@ -576,7 +576,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,90,6,107,119,97,114,103,115,41,1,218,6,109,101, 116,104,111,100,114,4,0,0,0,114,5,0,0,0,218,19, 95,99,104,101,99,107,95,110,97,109,101,95,119,114,97,112, - 112,101,114,122,1,0,0,115,12,0,0,0,0,1,12,1, + 112,101,114,123,1,0,0,115,12,0,0,0,0,1,12,1, 12,1,15,1,6,1,25,1,122,40,95,99,104,101,99,107, 95,110,97,109,101,46,60,108,111,99,97,108,115,62,46,95, 99,104,101,99,107,95,110,97,109,101,95,119,114,97,112,112, @@ -595,7 +595,7 @@ const unsigned char _Py_M__importlib_external[] = { 116,97,116,116,114,218,8,95,95,100,105,99,116,95,95,218, 6,117,112,100,97,116,101,41,3,90,3,110,101,119,90,3, 111,108,100,114,52,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,218,5,95,119,114,97,112,133,1, + 0,0,114,5,0,0,0,218,5,95,119,114,97,112,134,1, 0,0,115,8,0,0,0,0,1,25,1,15,1,29,1,122, 26,95,99,104,101,99,107,95,110,97,109,101,46,60,108,111, 99,97,108,115,62,46,95,119,114,97,112,41,3,218,10,95, @@ -603,7 +603,7 @@ const unsigned char _Py_M__importlib_external[] = { 78,97,109,101,69,114,114,111,114,41,3,114,109,0,0,0, 114,110,0,0,0,114,120,0,0,0,114,4,0,0,0,41, 1,114,109,0,0,0,114,5,0,0,0,218,11,95,99,104, - 101,99,107,95,110,97,109,101,114,1,0,0,115,14,0,0, + 101,99,107,95,110,97,109,101,115,1,0,0,115,14,0,0, 0,0,8,21,7,3,1,13,1,13,2,17,5,13,1,114, 123,0,0,0,99,2,0,0,0,0,0,0,0,5,0,0, 0,4,0,0,0,67,0,0,0,115,84,0,0,0,124,0, @@ -633,7 +633,7 @@ const unsigned char _Py_M__importlib_external[] = { 218,8,112,111,114,116,105,111,110,115,218,3,109,115,103,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,17, 95,102,105,110,100,95,109,111,100,117,108,101,95,115,104,105, - 109,142,1,0,0,115,10,0,0,0,0,10,21,1,24,1, + 109,143,1,0,0,115,10,0,0,0,0,10,21,1,24,1, 6,1,29,1,114,130,0,0,0,99,4,0,0,0,0,0, 0,0,11,0,0,0,19,0,0,0,67,0,0,0,115,228, 1,0,0,105,0,0,125,4,0,124,2,0,100,1,0,107, @@ -717,7 +717,7 @@ const unsigned char _Py_M__importlib_external[] = { 109,101,218,11,115,111,117,114,99,101,95,115,105,122,101,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,25, 95,118,97,108,105,100,97,116,101,95,98,121,116,101,99,111, - 100,101,95,104,101,97,100,101,114,159,1,0,0,115,76,0, + 100,101,95,104,101,97,100,101,114,160,1,0,0,115,76,0, 0,0,0,11,6,1,12,1,13,3,6,1,12,1,10,1, 16,1,16,1,16,1,12,1,18,1,10,1,18,1,18,1, 15,1,10,1,15,1,18,1,15,1,10,1,12,1,12,1, @@ -748,7 +748,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,106,0,0,0,114,89,0,0,0,114,90,0,0,0,218, 4,99,111,100,101,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,17,95,99,111,109,112,105,108,101,95,98, - 121,116,101,99,111,100,101,214,1,0,0,115,16,0,0,0, + 121,116,101,99,111,100,101,215,1,0,0,115,16,0,0,0, 0,2,15,1,15,1,13,1,12,1,16,1,4,2,18,1, 114,147,0,0,0,114,59,0,0,0,99,3,0,0,0,0, 0,0,0,4,0,0,0,3,0,0,0,67,0,0,0,115, @@ -768,7 +768,7 @@ const unsigned char _Py_M__importlib_external[] = { 4,114,146,0,0,0,114,133,0,0,0,114,140,0,0,0, 114,53,0,0,0,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,17,95,99,111,100,101,95,116,111,95,98, - 121,116,101,99,111,100,101,226,1,0,0,115,10,0,0,0, + 121,116,101,99,111,100,101,227,1,0,0,115,10,0,0,0, 0,3,12,1,19,1,19,1,22,1,114,150,0,0,0,99, 1,0,0,0,0,0,0,0,5,0,0,0,4,0,0,0, 67,0,0,0,115,89,0,0,0,100,1,0,100,2,0,108, @@ -797,7 +797,7 @@ const unsigned char _Py_M__importlib_external[] = { 100,105,110,103,90,15,110,101,119,108,105,110,101,95,100,101, 99,111,100,101,114,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,13,100,101,99,111,100,101,95,115,111,117, - 114,99,101,236,1,0,0,115,10,0,0,0,0,5,12,1, + 114,99,101,237,1,0,0,115,10,0,0,0,0,5,12,1, 18,1,15,1,18,1,114,155,0,0,0,114,127,0,0,0, 218,26,115,117,98,109,111,100,117,108,101,95,115,101,97,114, 99,104,95,108,111,99,97,116,105,111,110,115,99,2,0,0, @@ -862,7 +862,7 @@ const unsigned char _Py_M__importlib_external[] = { 159,0,0,0,90,7,100,105,114,110,97,109,101,114,4,0, 0,0,114,4,0,0,0,114,5,0,0,0,218,23,115,112, 101,99,95,102,114,111,109,95,102,105,108,101,95,108,111,99, - 97,116,105,111,110,253,1,0,0,115,60,0,0,0,0,12, + 97,116,105,111,110,254,1,0,0,115,60,0,0,0,0,12, 12,4,6,1,15,2,3,1,19,1,13,1,5,8,24,1, 9,3,12,1,22,1,21,1,15,1,9,1,5,2,4,3, 12,2,15,1,3,1,19,1,13,1,5,2,6,1,12,2, @@ -902,7 +902,7 @@ const unsigned char _Py_M__importlib_external[] = { 79,67,65,76,95,77,65,67,72,73,78,69,41,2,218,3, 99,108,115,218,3,107,101,121,114,4,0,0,0,114,4,0, 0,0,114,5,0,0,0,218,14,95,111,112,101,110,95,114, - 101,103,105,115,116,114,121,75,2,0,0,115,8,0,0,0, + 101,103,105,115,116,114,121,76,2,0,0,115,8,0,0,0, 0,2,3,1,23,1,13,1,122,36,87,105,110,100,111,119, 115,82,101,103,105,115,116,114,121,70,105,110,100,101,114,46, 95,111,112,101,110,95,114,101,103,105,115,116,114,121,99,2, @@ -929,7 +929,7 @@ const unsigned char _Py_M__importlib_external[] = { 171,0,0,0,90,4,104,107,101,121,218,8,102,105,108,101, 112,97,116,104,114,4,0,0,0,114,4,0,0,0,114,5, 0,0,0,218,16,95,115,101,97,114,99,104,95,114,101,103, - 105,115,116,114,121,82,2,0,0,115,22,0,0,0,0,2, + 105,115,116,114,121,83,2,0,0,115,22,0,0,0,0,2, 9,1,12,2,9,1,15,1,22,1,3,1,18,1,29,1, 13,1,9,1,122,38,87,105,110,100,111,119,115,82,101,103, 105,115,116,114,121,70,105,110,100,101,114,46,95,115,101,97, @@ -953,7 +953,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,35,0,0,0,218,6,116,97,114,103,101,116,114,177,0, 0,0,114,127,0,0,0,114,166,0,0,0,114,164,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,9,102,105,110,100,95,115,112,101,99,97,2,0,0,115, + 218,9,102,105,110,100,95,115,112,101,99,98,2,0,0,115, 26,0,0,0,0,2,15,1,12,1,4,1,3,1,14,1, 13,1,9,1,22,1,21,1,9,1,15,1,9,1,122,31, 87,105,110,100,111,119,115,82,101,103,105,115,116,114,121,70, @@ -973,7 +973,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,41,4,114,170,0,0,0,114,126,0,0,0,114, 35,0,0,0,114,164,0,0,0,114,4,0,0,0,114,4, 0,0,0,114,5,0,0,0,218,11,102,105,110,100,95,109, - 111,100,117,108,101,113,2,0,0,115,8,0,0,0,0,7, + 111,100,117,108,101,114,2,0,0,115,8,0,0,0,0,7, 18,1,12,1,7,2,122,33,87,105,110,100,111,119,115,82, 101,103,105,115,116,114,121,70,105,110,100,101,114,46,102,105, 110,100,95,109,111,100,117,108,101,41,12,114,112,0,0,0, @@ -982,7 +982,7 @@ const unsigned char _Py_M__importlib_external[] = { 99,108,97,115,115,109,101,116,104,111,100,114,172,0,0,0, 114,178,0,0,0,114,181,0,0,0,114,182,0,0,0,114, 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,168,0,0,0,63,2,0,0,115,20,0,0, + 0,0,0,114,168,0,0,0,64,2,0,0,115,20,0,0, 0,12,2,6,3,6,3,6,2,6,2,18,7,18,15,3, 1,21,15,3,1,114,168,0,0,0,99,0,0,0,0,0, 0,0,0,0,0,0,0,2,0,0,0,64,0,0,0,115, @@ -1020,7 +1020,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,114,94,0,0,0,90,13,102,105,108,101,110,97, 109,101,95,98,97,115,101,90,9,116,97,105,108,95,110,97, 109,101,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,159,0,0,0,132,2,0,0,115,8,0,0,0,0, + 0,114,159,0,0,0,133,2,0,0,115,8,0,0,0,0, 3,25,1,22,1,19,1,122,24,95,76,111,97,100,101,114, 66,97,115,105,99,115,46,105,115,95,112,97,99,107,97,103, 101,99,2,0,0,0,0,0,0,0,2,0,0,0,1,0, @@ -1030,7 +1030,7 @@ const unsigned char _Py_M__importlib_external[] = { 117,108,101,32,99,114,101,97,116,105,111,110,46,78,114,4, 0,0,0,41,2,114,108,0,0,0,114,164,0,0,0,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,13, - 99,114,101,97,116,101,95,109,111,100,117,108,101,140,2,0, + 99,114,101,97,116,101,95,109,111,100,117,108,101,141,2,0, 0,115,0,0,0,0,122,27,95,76,111,97,100,101,114,66, 97,115,105,99,115,46,99,114,101,97,116,101,95,109,111,100, 117,108,101,99,2,0,0,0,0,0,0,0,3,0,0,0, @@ -1052,7 +1052,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,41,3,114,108,0,0,0,218,6,109,111,100,117,108,101, 114,146,0,0,0,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,11,101,120,101,99,95,109,111,100,117,108, - 101,143,2,0,0,115,10,0,0,0,0,2,18,1,12,1, + 101,144,2,0,0,115,10,0,0,0,0,2,18,1,12,1, 9,1,15,1,122,25,95,76,111,97,100,101,114,66,97,115, 105,99,115,46,101,120,101,99,95,109,111,100,117,108,101,99, 2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, @@ -1061,14 +1061,14 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,218,17,95,108,111,97,100,95,109,111,100,117,108, 101,95,115,104,105,109,41,2,114,108,0,0,0,114,126,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,218,11,108,111,97,100,95,109,111,100,117,108,101,151,2, + 0,218,11,108,111,97,100,95,109,111,100,117,108,101,152,2, 0,0,115,2,0,0,0,0,1,122,25,95,76,111,97,100, 101,114,66,97,115,105,99,115,46,108,111,97,100,95,109,111, 100,117,108,101,78,41,8,114,112,0,0,0,114,111,0,0, 0,114,113,0,0,0,114,114,0,0,0,114,159,0,0,0, 114,186,0,0,0,114,191,0,0,0,114,193,0,0,0,114, 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,184,0,0,0,127,2,0,0,115,10,0,0, + 0,0,0,114,184,0,0,0,128,2,0,0,115,10,0,0, 0,12,3,6,2,12,8,12,3,12,8,114,184,0,0,0, 99,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, 0,64,0,0,0,115,106,0,0,0,101,0,0,90,1,0, @@ -1096,7 +1096,7 @@ const unsigned char _Py_M__importlib_external[] = { 1,218,7,73,79,69,114,114,111,114,41,2,114,108,0,0, 0,114,35,0,0,0,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,10,112,97,116,104,95,109,116,105,109, - 101,157,2,0,0,115,2,0,0,0,0,6,122,23,83,111, + 101,158,2,0,0,115,2,0,0,0,0,6,122,23,83,111, 117,114,99,101,76,111,97,100,101,114,46,112,97,116,104,95, 109,116,105,109,101,99,2,0,0,0,0,0,0,0,2,0, 0,0,3,0,0,0,67,0,0,0,115,19,0,0,0,100, @@ -1131,7 +1131,7 @@ const unsigned char _Py_M__importlib_external[] = { 32,32,32,114,133,0,0,0,41,1,114,196,0,0,0,41, 2,114,108,0,0,0,114,35,0,0,0,114,4,0,0,0, 114,4,0,0,0,114,5,0,0,0,218,10,112,97,116,104, - 95,115,116,97,116,115,165,2,0,0,115,2,0,0,0,0, + 95,115,116,97,116,115,166,2,0,0,115,2,0,0,0,0, 11,122,23,83,111,117,114,99,101,76,111,97,100,101,114,46, 112,97,116,104,95,115,116,97,116,115,99,4,0,0,0,0, 0,0,0,4,0,0,0,3,0,0,0,67,0,0,0,115, @@ -1155,7 +1155,7 @@ const unsigned char _Py_M__importlib_external[] = { 90,0,0,0,90,10,99,97,99,104,101,95,112,97,116,104, 114,53,0,0,0,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,15,95,99,97,99,104,101,95,98,121,116, - 101,99,111,100,101,178,2,0,0,115,2,0,0,0,0,8, + 101,99,111,100,101,179,2,0,0,115,2,0,0,0,0,8, 122,28,83,111,117,114,99,101,76,111,97,100,101,114,46,95, 99,97,99,104,101,95,98,121,116,101,99,111,100,101,99,3, 0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,67, @@ -1172,7 +1172,7 @@ const unsigned char _Py_M__importlib_external[] = { 32,32,32,32,32,32,78,114,4,0,0,0,41,3,114,108, 0,0,0,114,35,0,0,0,114,53,0,0,0,114,4,0, 0,0,114,4,0,0,0,114,5,0,0,0,114,198,0,0, - 0,188,2,0,0,115,0,0,0,0,122,21,83,111,117,114, + 0,189,2,0,0,115,0,0,0,0,122,21,83,111,117,114, 99,101,76,111,97,100,101,114,46,115,101,116,95,100,97,116, 97,99,2,0,0,0,0,0,0,0,5,0,0,0,16,0, 0,0,67,0,0,0,115,105,0,0,0,124,0,0,106,0, @@ -1194,7 +1194,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,114,126,0,0,0,114,35,0,0,0,114,153,0,0, 0,218,3,101,120,99,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,10,103,101,116,95,115,111,117,114,99, - 101,195,2,0,0,115,14,0,0,0,0,2,15,1,3,1, + 101,196,2,0,0,115,14,0,0,0,0,2,15,1,3,1, 19,1,18,1,9,1,31,1,122,23,83,111,117,114,99,101, 76,111,97,100,101,114,46,103,101,116,95,115,111,117,114,99, 101,218,9,95,111,112,116,105,109,105,122,101,114,29,0,0, @@ -1216,7 +1216,7 @@ const unsigned char _Py_M__importlib_external[] = { 101,41,4,114,108,0,0,0,114,53,0,0,0,114,35,0, 0,0,114,203,0,0,0,114,4,0,0,0,114,4,0,0, 0,114,5,0,0,0,218,14,115,111,117,114,99,101,95,116, - 111,95,99,111,100,101,205,2,0,0,115,4,0,0,0,0, + 111,95,99,111,100,101,206,2,0,0,115,4,0,0,0,0, 5,21,1,122,27,83,111,117,114,99,101,76,111,97,100,101, 114,46,115,111,117,114,99,101,95,116,111,95,99,111,100,101, 99,2,0,0,0,0,0,0,0,10,0,0,0,43,0,0, @@ -1277,7 +1277,7 @@ const unsigned char _Py_M__importlib_external[] = { 98,121,116,101,115,95,100,97,116,97,114,153,0,0,0,90, 11,99,111,100,101,95,111,98,106,101,99,116,114,4,0,0, 0,114,4,0,0,0,114,5,0,0,0,114,187,0,0,0, - 213,2,0,0,115,78,0,0,0,0,7,15,1,6,1,3, + 214,2,0,0,115,78,0,0,0,0,7,15,1,6,1,3, 1,16,1,13,1,11,2,3,1,19,1,13,1,5,2,16, 1,3,1,19,1,13,1,5,2,3,1,9,1,12,1,13, 1,19,1,5,2,9,1,7,1,15,1,6,1,7,1,15, @@ -1289,7 +1289,7 @@ const unsigned char _Py_M__importlib_external[] = { 199,0,0,0,114,198,0,0,0,114,202,0,0,0,114,206, 0,0,0,114,187,0,0,0,114,4,0,0,0,114,4,0, 0,0,114,4,0,0,0,114,5,0,0,0,114,194,0,0, - 0,155,2,0,0,115,14,0,0,0,12,2,12,8,12,13, + 0,156,2,0,0,115,14,0,0,0,12,2,12,8,12,13, 12,10,12,7,12,10,18,8,114,194,0,0,0,99,0,0, 0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0, 0,0,115,112,0,0,0,101,0,0,90,1,0,100,0,0, @@ -1317,7 +1317,7 @@ const unsigned char _Py_M__importlib_external[] = { 32,32,32,32,32,32,102,105,110,100,101,114,46,78,41,2, 114,106,0,0,0,114,35,0,0,0,41,3,114,108,0,0, 0,114,126,0,0,0,114,35,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,185,0,0,0,14, + 114,4,0,0,0,114,5,0,0,0,114,185,0,0,0,15, 3,0,0,115,4,0,0,0,0,3,9,1,122,19,70,105, 108,101,76,111,97,100,101,114,46,95,95,105,110,105,116,95, 95,99,2,0,0,0,0,0,0,0,2,0,0,0,2,0, @@ -1327,7 +1327,7 @@ const unsigned char _Py_M__importlib_external[] = { 41,2,218,9,95,95,99,108,97,115,115,95,95,114,118,0, 0,0,41,2,114,108,0,0,0,218,5,111,116,104,101,114, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218, - 6,95,95,101,113,95,95,20,3,0,0,115,4,0,0,0, + 6,95,95,101,113,95,95,21,3,0,0,115,4,0,0,0, 0,1,18,1,122,17,70,105,108,101,76,111,97,100,101,114, 46,95,95,101,113,95,95,99,1,0,0,0,0,0,0,0, 1,0,0,0,3,0,0,0,67,0,0,0,115,26,0,0, @@ -1336,7 +1336,7 @@ const unsigned char _Py_M__importlib_external[] = { 218,4,104,97,115,104,114,106,0,0,0,114,35,0,0,0, 41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0, 0,114,5,0,0,0,218,8,95,95,104,97,115,104,95,95, - 24,3,0,0,115,2,0,0,0,0,1,122,19,70,105,108, + 25,3,0,0,115,2,0,0,0,0,1,122,19,70,105,108, 101,76,111,97,100,101,114,46,95,95,104,97,115,104,95,95, 99,2,0,0,0,0,0,0,0,2,0,0,0,3,0,0, 0,3,0,0,0,115,22,0,0,0,116,0,0,116,1,0, @@ -1350,7 +1350,7 @@ const unsigned char _Py_M__importlib_external[] = { 32,32,32,32,32,32,32,32,41,3,218,5,115,117,112,101, 114,114,210,0,0,0,114,193,0,0,0,41,2,114,108,0, 0,0,114,126,0,0,0,41,1,114,211,0,0,0,114,4, - 0,0,0,114,5,0,0,0,114,193,0,0,0,27,3,0, + 0,0,0,114,5,0,0,0,114,193,0,0,0,28,3,0, 0,115,2,0,0,0,0,10,122,22,70,105,108,101,76,111, 97,100,101,114,46,108,111,97,100,95,109,111,100,117,108,101, 99,2,0,0,0,0,0,0,0,2,0,0,0,1,0,0, @@ -1361,7 +1361,7 @@ const unsigned char _Py_M__importlib_external[] = { 32,98,121,32,116,104,101,32,102,105,110,100,101,114,46,41, 1,114,35,0,0,0,41,2,114,108,0,0,0,114,126,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,157,0,0,0,39,3,0,0,115,2,0,0,0,0, + 0,114,157,0,0,0,40,3,0,0,115,2,0,0,0,0, 3,122,23,70,105,108,101,76,111,97,100,101,114,46,103,101, 116,95,102,105,108,101,110,97,109,101,99,2,0,0,0,0, 0,0,0,3,0,0,0,9,0,0,0,67,0,0,0,115, @@ -1374,14 +1374,14 @@ const unsigned char _Py_M__importlib_external[] = { 49,0,0,0,114,50,0,0,0,90,4,114,101,97,100,41, 3,114,108,0,0,0,114,35,0,0,0,114,54,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 200,0,0,0,44,3,0,0,115,4,0,0,0,0,2,21, + 200,0,0,0,45,3,0,0,115,4,0,0,0,0,2,21, 1,122,19,70,105,108,101,76,111,97,100,101,114,46,103,101, 116,95,100,97,116,97,41,11,114,112,0,0,0,114,111,0, 0,0,114,113,0,0,0,114,114,0,0,0,114,185,0,0, 0,114,213,0,0,0,114,215,0,0,0,114,123,0,0,0, 114,193,0,0,0,114,157,0,0,0,114,200,0,0,0,114, 4,0,0,0,114,4,0,0,0,41,1,114,211,0,0,0, - 114,5,0,0,0,114,210,0,0,0,9,3,0,0,115,14, + 114,5,0,0,0,114,210,0,0,0,10,3,0,0,115,14, 0,0,0,12,3,6,2,12,6,12,4,12,3,24,12,18, 5,114,210,0,0,0,99,0,0,0,0,0,0,0,0,0, 0,0,0,4,0,0,0,64,0,0,0,115,64,0,0,0, @@ -1404,7 +1404,7 @@ const unsigned char _Py_M__importlib_external[] = { 3,114,39,0,0,0,218,8,115,116,95,109,116,105,109,101, 90,7,115,116,95,115,105,122,101,41,3,114,108,0,0,0, 114,35,0,0,0,114,208,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,197,0,0,0,54,3, + 4,0,0,0,114,5,0,0,0,114,197,0,0,0,55,3, 0,0,115,4,0,0,0,0,2,12,1,122,27,83,111,117, 114,99,101,70,105,108,101,76,111,97,100,101,114,46,112,97, 116,104,95,115,116,97,116,115,99,4,0,0,0,0,0,0, @@ -1415,7 +1415,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,97,0,0,0,114,198,0,0,0,41,5,114,108,0,0, 0,114,90,0,0,0,114,89,0,0,0,114,53,0,0,0, 114,42,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,199,0,0,0,59,3,0,0,115,4,0, + 5,0,0,0,114,199,0,0,0,60,3,0,0,115,4,0, 0,0,0,2,12,1,122,32,83,111,117,114,99,101,70,105, 108,101,76,111,97,100,101,114,46,95,99,97,99,104,101,95, 98,121,116,101,99,111,100,101,114,220,0,0,0,105,182,1, @@ -1453,7 +1453,7 @@ const unsigned char _Py_M__importlib_external[] = { 53,0,0,0,114,220,0,0,0,218,6,112,97,114,101,110, 116,114,94,0,0,0,114,27,0,0,0,114,23,0,0,0, 114,201,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,198,0,0,0,64,3,0,0,115,38,0, + 5,0,0,0,114,198,0,0,0,65,3,0,0,115,38,0, 0,0,0,2,18,1,6,2,22,1,18,1,17,2,19,1, 15,1,3,1,17,1,13,2,7,1,18,3,16,1,27,1, 3,1,16,1,17,1,18,2,122,25,83,111,117,114,99,101, @@ -1462,7 +1462,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,113,0,0,0,114,114,0,0,0,114,197,0,0,0,114, 199,0,0,0,114,198,0,0,0,114,4,0,0,0,114,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,114,218,0, - 0,0,50,3,0,0,115,8,0,0,0,12,2,6,2,12, + 0,0,51,3,0,0,115,8,0,0,0,12,2,6,2,12, 5,12,5,114,218,0,0,0,99,0,0,0,0,0,0,0, 0,0,0,0,0,2,0,0,0,64,0,0,0,115,46,0, 0,0,101,0,0,90,1,0,100,0,0,90,2,0,100,1, @@ -1484,7 +1484,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,147,0,0,0,41,5,114,108,0,0,0,114,126,0,0, 0,114,35,0,0,0,114,53,0,0,0,114,209,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 187,0,0,0,97,3,0,0,115,8,0,0,0,0,1,15, + 187,0,0,0,98,3,0,0,115,8,0,0,0,0,1,15, 1,15,1,24,1,122,29,83,111,117,114,99,101,108,101,115, 115,70,105,108,101,76,111,97,100,101,114,46,103,101,116,95, 99,111,100,101,99,2,0,0,0,0,0,0,0,2,0,0, @@ -1494,13 +1494,13 @@ const unsigned char _Py_M__importlib_external[] = { 32,115,111,117,114,99,101,32,99,111,100,101,46,78,114,4, 0,0,0,41,2,114,108,0,0,0,114,126,0,0,0,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,202, - 0,0,0,103,3,0,0,115,2,0,0,0,0,2,122,31, + 0,0,0,104,3,0,0,115,2,0,0,0,0,2,122,31, 83,111,117,114,99,101,108,101,115,115,70,105,108,101,76,111, 97,100,101,114,46,103,101,116,95,115,111,117,114,99,101,78, 41,6,114,112,0,0,0,114,111,0,0,0,114,113,0,0, 0,114,114,0,0,0,114,187,0,0,0,114,202,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,223,0,0,0,93,3,0,0,115,6,0, + 5,0,0,0,114,223,0,0,0,94,3,0,0,115,6,0, 0,0,12,2,6,2,12,6,114,223,0,0,0,99,0,0, 0,0,0,0,0,0,0,0,0,0,3,0,0,0,64,0, 0,0,115,136,0,0,0,101,0,0,90,1,0,100,0,0, @@ -1525,7 +1525,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,100,0,0,83,41,1,78,41,2,114,106,0,0,0,114, 35,0,0,0,41,3,114,108,0,0,0,114,106,0,0,0, 114,35,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,185,0,0,0,120,3,0,0,115,4,0, + 5,0,0,0,114,185,0,0,0,121,3,0,0,115,4,0, 0,0,0,1,9,1,122,28,69,120,116,101,110,115,105,111, 110,70,105,108,101,76,111,97,100,101,114,46,95,95,105,110, 105,116,95,95,99,2,0,0,0,0,0,0,0,2,0,0, @@ -1534,7 +1534,7 @@ const unsigned char _Py_M__importlib_external[] = { 124,0,0,106,1,0,124,1,0,106,1,0,107,2,0,83, 41,1,78,41,2,114,211,0,0,0,114,118,0,0,0,41, 2,114,108,0,0,0,114,212,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,213,0,0,0,124, + 114,4,0,0,0,114,5,0,0,0,114,213,0,0,0,125, 3,0,0,115,4,0,0,0,0,1,18,1,122,26,69,120, 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, 114,46,95,95,101,113,95,95,99,1,0,0,0,0,0,0, @@ -1543,7 +1543,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,124,0,0,106,2,0,131,1,0,65,83,41,1,78,41, 3,114,214,0,0,0,114,106,0,0,0,114,35,0,0,0, 41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,114,215,0,0,0,128,3,0,0,115, + 0,114,5,0,0,0,114,215,0,0,0,129,3,0,0,115, 2,0,0,0,0,1,122,28,69,120,116,101,110,115,105,111, 110,70,105,108,101,76,111,97,100,101,114,46,95,95,104,97, 115,104,95,95,99,2,0,0,0,0,0,0,0,3,0,0, @@ -1561,7 +1561,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,105,0,0,0,114,106,0,0,0,114,35,0,0,0,41, 3,114,108,0,0,0,114,164,0,0,0,114,190,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 186,0,0,0,131,3,0,0,115,10,0,0,0,0,2,6, + 186,0,0,0,132,3,0,0,115,10,0,0,0,0,2,6, 1,15,1,6,1,16,1,122,33,69,120,116,101,110,115,105, 111,110,70,105,108,101,76,111,97,100,101,114,46,99,114,101, 97,116,101,95,109,111,100,117,108,101,99,2,0,0,0,0, @@ -1578,7 +1578,7 @@ const unsigned char _Py_M__importlib_external[] = { 12,101,120,101,99,95,100,121,110,97,109,105,99,114,105,0, 0,0,114,106,0,0,0,114,35,0,0,0,41,2,114,108, 0,0,0,114,190,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,191,0,0,0,139,3,0,0, + 0,0,114,5,0,0,0,114,191,0,0,0,140,3,0,0, 115,6,0,0,0,0,2,19,1,6,1,122,31,69,120,116, 101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114, 46,101,120,101,99,95,109,111,100,117,108,101,99,2,0,0, @@ -1597,7 +1597,7 @@ const unsigned char _Py_M__importlib_external[] = { 78,114,4,0,0,0,41,2,114,22,0,0,0,218,6,115, 117,102,102,105,120,41,1,218,9,102,105,108,101,95,110,97, 109,101,114,4,0,0,0,114,5,0,0,0,250,9,60,103, - 101,110,101,120,112,114,62,148,3,0,0,115,2,0,0,0, + 101,110,101,120,112,114,62,149,3,0,0,115,2,0,0,0, 6,1,122,49,69,120,116,101,110,115,105,111,110,70,105,108, 101,76,111,97,100,101,114,46,105,115,95,112,97,99,107,97, 103,101,46,60,108,111,99,97,108,115,62,46,60,103,101,110, @@ -1605,7 +1605,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,218,3,97,110,121,218,18,69,88,84,69,78,83,73,79, 78,95,83,85,70,70,73,88,69,83,41,2,114,108,0,0, 0,114,126,0,0,0,114,4,0,0,0,41,1,114,226,0, - 0,0,114,5,0,0,0,114,159,0,0,0,145,3,0,0, + 0,0,114,5,0,0,0,114,159,0,0,0,146,3,0,0, 115,6,0,0,0,0,2,19,1,18,1,122,30,69,120,116, 101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114, 46,105,115,95,112,97,99,107,97,103,101,99,2,0,0,0, @@ -1617,7 +1617,7 @@ const unsigned char _Py_M__importlib_external[] = { 99,111,100,101,32,111,98,106,101,99,116,46,78,114,4,0, 0,0,41,2,114,108,0,0,0,114,126,0,0,0,114,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,114,187,0, - 0,0,151,3,0,0,115,2,0,0,0,0,2,122,28,69, + 0,0,152,3,0,0,115,2,0,0,0,0,2,122,28,69, 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, 101,114,46,103,101,116,95,99,111,100,101,99,2,0,0,0, 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, @@ -1627,7 +1627,7 @@ const unsigned char _Py_M__importlib_external[] = { 118,101,32,110,111,32,115,111,117,114,99,101,32,99,111,100, 101,46,78,114,4,0,0,0,41,2,114,108,0,0,0,114, 126,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,202,0,0,0,155,3,0,0,115,2,0,0, + 0,0,0,114,202,0,0,0,156,3,0,0,115,2,0,0, 0,0,2,122,30,69,120,116,101,110,115,105,111,110,70,105, 108,101,76,111,97,100,101,114,46,103,101,116,95,115,111,117, 114,99,101,99,2,0,0,0,0,0,0,0,2,0,0,0, @@ -1638,7 +1638,7 @@ const unsigned char _Py_M__importlib_external[] = { 117,110,100,32,98,121,32,116,104,101,32,102,105,110,100,101, 114,46,41,1,114,35,0,0,0,41,2,114,108,0,0,0, 114,126,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,157,0,0,0,159,3,0,0,115,2,0, + 5,0,0,0,114,157,0,0,0,160,3,0,0,115,2,0, 0,0,0,3,122,32,69,120,116,101,110,115,105,111,110,70, 105,108,101,76,111,97,100,101,114,46,103,101,116,95,102,105, 108,101,110,97,109,101,78,41,14,114,112,0,0,0,114,111, @@ -1647,7 +1647,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,114,191,0,0,0,114,159,0,0,0,114,187,0,0,0, 114,202,0,0,0,114,123,0,0,0,114,157,0,0,0,114, 4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,224,0,0,0,112,3,0,0,115,20,0,0, + 0,0,0,114,224,0,0,0,113,3,0,0,115,20,0,0, 0,12,6,6,2,12,4,12,4,12,3,12,8,12,6,12, 6,12,4,12,4,114,224,0,0,0,99,0,0,0,0,0, 0,0,0,0,0,0,0,2,0,0,0,64,0,0,0,115, @@ -1691,7 +1691,7 @@ const unsigned char _Py_M__importlib_external[] = { 95,112,97,116,104,95,102,105,110,100,101,114,41,4,114,108, 0,0,0,114,106,0,0,0,114,35,0,0,0,218,11,112, 97,116,104,95,102,105,110,100,101,114,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,185,0,0,0,172,3, + 4,0,0,0,114,5,0,0,0,114,185,0,0,0,173,3, 0,0,115,8,0,0,0,0,1,9,1,9,1,21,1,122, 23,95,78,97,109,101,115,112,97,99,101,80,97,116,104,46, 95,95,105,110,105,116,95,95,99,1,0,0,0,0,0,0, @@ -1710,7 +1710,7 @@ const unsigned char _Py_M__importlib_external[] = { 41,4,114,108,0,0,0,114,222,0,0,0,218,3,100,111, 116,90,2,109,101,114,4,0,0,0,114,4,0,0,0,114, 5,0,0,0,218,23,95,102,105,110,100,95,112,97,114,101, - 110,116,95,112,97,116,104,95,110,97,109,101,115,178,3,0, + 110,116,95,112,97,116,104,95,110,97,109,101,115,179,3,0, 0,115,8,0,0,0,0,2,27,1,12,2,4,3,122,38, 95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,95, 102,105,110,100,95,112,97,114,101,110,116,95,112,97,116,104, @@ -1724,7 +1724,7 @@ const unsigned char _Py_M__importlib_external[] = { 110,116,95,109,111,100,117,108,101,95,110,97,109,101,90,14, 112,97,116,104,95,97,116,116,114,95,110,97,109,101,114,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,114,233,0, - 0,0,188,3,0,0,115,4,0,0,0,0,1,18,1,122, + 0,0,189,3,0,0,115,4,0,0,0,0,1,18,1,122, 31,95,78,97,109,101,115,112,97,99,101,80,97,116,104,46, 95,103,101,116,95,112,97,114,101,110,116,95,112,97,116,104, 99,1,0,0,0,0,0,0,0,3,0,0,0,3,0,0, @@ -1742,7 +1742,7 @@ const unsigned char _Py_M__importlib_external[] = { 108,0,0,0,90,11,112,97,114,101,110,116,95,112,97,116, 104,114,164,0,0,0,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,12,95,114,101,99,97,108,99,117,108, - 97,116,101,192,3,0,0,115,16,0,0,0,0,2,18,1, + 97,116,101,193,3,0,0,115,16,0,0,0,0,2,18,1, 15,1,21,3,27,1,9,1,12,1,9,1,122,27,95,78, 97,109,101,115,112,97,99,101,80,97,116,104,46,95,114,101, 99,97,108,99,117,108,97,116,101,99,1,0,0,0,0,0, @@ -1751,14 +1751,14 @@ const unsigned char _Py_M__importlib_external[] = { 1,0,83,41,1,78,41,2,218,4,105,116,101,114,114,240, 0,0,0,41,1,114,108,0,0,0,114,4,0,0,0,114, 4,0,0,0,114,5,0,0,0,218,8,95,95,105,116,101, - 114,95,95,205,3,0,0,115,2,0,0,0,0,1,122,23, + 114,95,95,206,3,0,0,115,2,0,0,0,0,1,122,23, 95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,95, 95,105,116,101,114,95,95,99,1,0,0,0,0,0,0,0, 1,0,0,0,2,0,0,0,67,0,0,0,115,16,0,0, 0,116,0,0,124,0,0,106,1,0,131,0,0,131,1,0, 83,41,1,78,41,2,114,31,0,0,0,114,240,0,0,0, 41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,5,0,0,0,218,7,95,95,108,101,110,95,95,208, + 0,114,5,0,0,0,218,7,95,95,108,101,110,95,95,209, 3,0,0,115,2,0,0,0,0,1,122,22,95,78,97,109, 101,115,112,97,99,101,80,97,116,104,46,95,95,108,101,110, 95,95,99,1,0,0,0,0,0,0,0,1,0,0,0,2, @@ -1768,7 +1768,7 @@ const unsigned char _Py_M__importlib_external[] = { 123,33,114,125,41,41,2,114,47,0,0,0,114,232,0,0, 0,41,1,114,108,0,0,0,114,4,0,0,0,114,4,0, 0,0,114,5,0,0,0,218,8,95,95,114,101,112,114,95, - 95,211,3,0,0,115,2,0,0,0,0,1,122,23,95,78, + 95,212,3,0,0,115,2,0,0,0,0,1,122,23,95,78, 97,109,101,115,112,97,99,101,80,97,116,104,46,95,95,114, 101,112,114,95,95,99,2,0,0,0,0,0,0,0,2,0, 0,0,2,0,0,0,67,0,0,0,115,16,0,0,0,124, @@ -1776,7 +1776,7 @@ const unsigned char _Py_M__importlib_external[] = { 1,78,41,1,114,240,0,0,0,41,2,114,108,0,0,0, 218,4,105,116,101,109,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,12,95,95,99,111,110,116,97,105,110, - 115,95,95,214,3,0,0,115,2,0,0,0,0,1,122,27, + 115,95,95,215,3,0,0,115,2,0,0,0,0,1,122,27, 95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,95, 95,99,111,110,116,97,105,110,115,95,95,99,2,0,0,0, 0,0,0,0,2,0,0,0,2,0,0,0,67,0,0,0, @@ -1784,7 +1784,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,131,1,0,1,100,0,0,83,41,1,78,41,2,114,232, 0,0,0,114,163,0,0,0,41,2,114,108,0,0,0,114, 245,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,163,0,0,0,217,3,0,0,115,2,0,0, + 0,0,0,114,163,0,0,0,218,3,0,0,115,2,0,0, 0,0,1,122,21,95,78,97,109,101,115,112,97,99,101,80, 97,116,104,46,97,112,112,101,110,100,78,41,13,114,112,0, 0,0,114,111,0,0,0,114,113,0,0,0,114,114,0,0, @@ -1792,7 +1792,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,240,0,0,0,114,242,0,0,0,114,243,0,0,0,114, 244,0,0,0,114,246,0,0,0,114,163,0,0,0,114,4, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,230,0,0,0,165,3,0,0,115,20,0,0,0, + 0,0,114,230,0,0,0,166,3,0,0,115,20,0,0,0, 12,5,6,2,12,6,12,10,12,4,12,13,12,3,12,3, 12,3,12,3,114,230,0,0,0,99,0,0,0,0,0,0, 0,0,0,0,0,0,3,0,0,0,64,0,0,0,115,118, @@ -1811,7 +1811,7 @@ const unsigned char _Py_M__importlib_external[] = { 41,1,78,41,2,114,230,0,0,0,114,232,0,0,0,41, 4,114,108,0,0,0,114,106,0,0,0,114,35,0,0,0, 114,236,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,185,0,0,0,223,3,0,0,115,2,0, + 5,0,0,0,114,185,0,0,0,224,3,0,0,115,2,0, 0,0,0,1,122,25,95,78,97,109,101,115,112,97,99,101, 76,111,97,100,101,114,46,95,95,105,110,105,116,95,95,99, 2,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0, @@ -1828,14 +1828,14 @@ const unsigned char _Py_M__importlib_external[] = { 110,97,109,101,115,112,97,99,101,41,62,41,2,114,47,0, 0,0,114,112,0,0,0,41,2,114,170,0,0,0,114,190, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,218,11,109,111,100,117,108,101,95,114,101,112,114,226, + 0,0,218,11,109,111,100,117,108,101,95,114,101,112,114,227, 3,0,0,115,2,0,0,0,0,7,122,28,95,78,97,109, 101,115,112,97,99,101,76,111,97,100,101,114,46,109,111,100, 117,108,101,95,114,101,112,114,99,2,0,0,0,0,0,0, 0,2,0,0,0,1,0,0,0,67,0,0,0,115,4,0, 0,0,100,1,0,83,41,2,78,84,114,4,0,0,0,41, 2,114,108,0,0,0,114,126,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,159,0,0,0,235, + 114,4,0,0,0,114,5,0,0,0,114,159,0,0,0,236, 3,0,0,115,2,0,0,0,0,1,122,27,95,78,97,109, 101,115,112,97,99,101,76,111,97,100,101,114,46,105,115,95, 112,97,99,107,97,103,101,99,2,0,0,0,0,0,0,0, @@ -1843,7 +1843,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,100,1,0,83,41,2,78,114,30,0,0,0,114,4,0, 0,0,41,2,114,108,0,0,0,114,126,0,0,0,114,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,114,202,0, - 0,0,238,3,0,0,115,2,0,0,0,0,1,122,27,95, + 0,0,239,3,0,0,115,2,0,0,0,0,1,122,27,95, 78,97,109,101,115,112,97,99,101,76,111,97,100,101,114,46, 103,101,116,95,115,111,117,114,99,101,99,2,0,0,0,0, 0,0,0,2,0,0,0,6,0,0,0,67,0,0,0,115, @@ -1852,7 +1852,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,122,8,60,115,116,114,105,110,103,62,114,189,0,0, 0,114,204,0,0,0,84,41,1,114,205,0,0,0,41,2, 114,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,187,0,0,0,241,3, + 4,0,0,0,114,5,0,0,0,114,187,0,0,0,242,3, 0,0,115,2,0,0,0,0,1,122,25,95,78,97,109,101, 115,112,97,99,101,76,111,97,100,101,114,46,103,101,116,95, 99,111,100,101,99,2,0,0,0,0,0,0,0,2,0,0, @@ -1862,14 +1862,14 @@ const unsigned char _Py_M__importlib_external[] = { 109,111,100,117,108,101,32,99,114,101,97,116,105,111,110,46, 78,114,4,0,0,0,41,2,114,108,0,0,0,114,164,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,186,0,0,0,244,3,0,0,115,0,0,0,0,122, + 0,114,186,0,0,0,245,3,0,0,115,0,0,0,0,122, 30,95,78,97,109,101,115,112,97,99,101,76,111,97,100,101, 114,46,99,114,101,97,116,101,95,109,111,100,117,108,101,99, 2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, 67,0,0,0,115,4,0,0,0,100,0,0,83,41,1,78, 114,4,0,0,0,41,2,114,108,0,0,0,114,190,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 114,191,0,0,0,247,3,0,0,115,2,0,0,0,0,1, + 114,191,0,0,0,248,3,0,0,115,2,0,0,0,0,1, 122,28,95,78,97,109,101,115,112,97,99,101,76,111,97,100, 101,114,46,101,120,101,99,95,109,111,100,117,108,101,99,2, 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, @@ -1887,7 +1887,7 @@ const unsigned char _Py_M__importlib_external[] = { 104,32,123,33,114,125,41,4,114,105,0,0,0,114,232,0, 0,0,114,121,0,0,0,114,192,0,0,0,41,2,114,108, 0,0,0,114,126,0,0,0,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,193,0,0,0,250,3,0,0, + 0,0,114,5,0,0,0,114,193,0,0,0,251,3,0,0, 115,4,0,0,0,0,7,16,1,122,28,95,78,97,109,101, 115,112,97,99,101,76,111,97,100,101,114,46,108,111,97,100, 95,109,111,100,117,108,101,78,41,12,114,112,0,0,0,114, @@ -1895,7 +1895,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,114,248,0,0,0,114,159,0,0,0,114,202,0, 0,0,114,187,0,0,0,114,186,0,0,0,114,191,0,0, 0,114,193,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,5,0,0,0,114,247,0,0,0,222, + 114,4,0,0,0,114,5,0,0,0,114,247,0,0,0,223, 3,0,0,115,16,0,0,0,12,1,12,3,18,9,12,3, 12,3,12,3,12,3,12,3,114,247,0,0,0,99,0,0, 0,0,0,0,0,0,0,0,0,0,5,0,0,0,64,0, @@ -1933,7 +1933,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,95,99,97,99,104,101,218,6,118,97,108,117,101,115,114, 115,0,0,0,114,250,0,0,0,41,2,114,170,0,0,0, 218,6,102,105,110,100,101,114,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,250,0,0,0,11,4,0,0, + 0,0,114,5,0,0,0,114,250,0,0,0,12,4,0,0, 115,6,0,0,0,0,4,22,1,15,1,122,28,80,97,116, 104,70,105,110,100,101,114,46,105,110,118,97,108,105,100,97, 116,101,95,99,97,99,104,101,115,99,2,0,0,0,0,0, @@ -1959,7 +1959,7 @@ const unsigned char _Py_M__importlib_external[] = { 107,0,0,0,41,3,114,170,0,0,0,114,35,0,0,0, 90,4,104,111,111,107,114,4,0,0,0,114,4,0,0,0, 114,5,0,0,0,218,11,95,112,97,116,104,95,104,111,111, - 107,115,19,4,0,0,115,16,0,0,0,0,7,25,1,16, + 107,115,20,4,0,0,115,16,0,0,0,0,7,25,1,16, 1,16,1,3,1,14,1,13,1,12,2,122,22,80,97,116, 104,70,105,110,100,101,114,46,95,112,97,116,104,95,104,111, 111,107,115,99,2,0,0,0,0,0,0,0,3,0,0,0, @@ -1991,7 +1991,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,114,255,0,0,0,41,3,114,170,0,0,0,114,35, 0,0,0,114,253,0,0,0,114,4,0,0,0,114,4,0, 0,0,114,5,0,0,0,218,20,95,112,97,116,104,95,105, - 109,112,111,114,116,101,114,95,99,97,99,104,101,36,4,0, + 109,112,111,114,116,101,114,95,99,97,99,104,101,37,4,0, 0,115,22,0,0,0,0,8,12,1,3,1,16,1,13,3, 9,1,3,1,17,1,13,1,15,1,18,1,122,31,80,97, 116,104,70,105,110,100,101,114,46,95,112,97,116,104,95,105, @@ -2011,7 +2011,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,114,126,0,0,0,114,253,0,0,0,114,127,0,0, 0,114,128,0,0,0,114,164,0,0,0,114,4,0,0,0, 114,4,0,0,0,114,5,0,0,0,218,16,95,108,101,103, - 97,99,121,95,103,101,116,95,115,112,101,99,58,4,0,0, + 97,99,121,95,103,101,116,95,115,112,101,99,59,4,0,0, 115,18,0,0,0,0,4,15,1,24,2,15,1,6,1,12, 1,16,1,18,1,9,1,122,27,80,97,116,104,70,105,110, 100,101,114,46,95,108,101,103,97,99,121,95,103,101,116,95, @@ -2047,7 +2047,7 @@ const unsigned char _Py_M__importlib_external[] = { 101,115,112,97,99,101,95,112,97,116,104,90,5,101,110,116, 114,121,114,253,0,0,0,114,164,0,0,0,114,128,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, - 218,9,95,103,101,116,95,115,112,101,99,73,4,0,0,115, + 218,9,95,103,101,116,95,115,112,101,99,74,4,0,0,115, 40,0,0,0,0,5,6,1,13,1,21,1,3,1,15,1, 12,1,15,1,21,2,18,1,12,1,3,1,15,1,4,1, 9,1,12,1,12,5,17,2,18,1,9,1,122,20,80,97, @@ -2075,7 +2075,7 @@ const unsigned char _Py_M__importlib_external[] = { 6,114,170,0,0,0,114,126,0,0,0,114,35,0,0,0, 114,180,0,0,0,114,164,0,0,0,114,4,1,0,0,114, 4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,181, - 0,0,0,105,4,0,0,115,26,0,0,0,0,4,12,1, + 0,0,0,106,4,0,0,115,26,0,0,0,0,4,12,1, 9,1,21,1,12,1,4,1,15,1,9,1,6,3,9,1, 24,1,4,2,7,2,122,20,80,97,116,104,70,105,110,100, 101,114,46,102,105,110,100,95,115,112,101,99,99,3,0,0, @@ -2097,7 +2097,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,181,0,0,0,114,127,0,0,0,41,4,114,170,0,0, 0,114,126,0,0,0,114,35,0,0,0,114,164,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 182,0,0,0,127,4,0,0,115,8,0,0,0,0,8,18, + 182,0,0,0,128,4,0,0,115,8,0,0,0,0,8,18, 1,12,1,4,1,122,22,80,97,116,104,70,105,110,100,101, 114,46,102,105,110,100,95,109,111,100,117,108,101,41,12,114, 112,0,0,0,114,111,0,0,0,114,113,0,0,0,114,114, @@ -2105,7 +2105,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,114,1,1,0,0,114,2,1,0,0,114,5,1,0, 0,114,181,0,0,0,114,182,0,0,0,114,4,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 249,0,0,0,7,4,0,0,115,22,0,0,0,12,2,6, + 249,0,0,0,8,4,0,0,115,22,0,0,0,12,2,6, 2,18,8,18,17,18,22,18,15,3,1,18,31,3,1,21, 21,3,1,114,249,0,0,0,99,0,0,0,0,0,0,0, 0,0,0,0,0,3,0,0,0,64,0,0,0,115,133,0, @@ -2154,7 +2154,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,86,1,113,3,0,100,0,0,83,41,1,78,114,4,0, 0,0,41,2,114,22,0,0,0,114,225,0,0,0,41,1, 114,127,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 227,0,0,0,156,4,0,0,115,2,0,0,0,6,0,122, + 227,0,0,0,157,4,0,0,115,2,0,0,0,6,0,122, 38,70,105,108,101,70,105,110,100,101,114,46,95,95,105,110, 105,116,95,95,46,60,108,111,99,97,108,115,62,46,60,103, 101,110,101,120,112,114,62,114,58,0,0,0,114,29,0,0, @@ -2167,7 +2167,7 @@ const unsigned char _Py_M__importlib_external[] = { 111,97,100,101,114,95,100,101,116,97,105,108,115,90,7,108, 111,97,100,101,114,115,114,166,0,0,0,114,4,0,0,0, 41,1,114,127,0,0,0,114,5,0,0,0,114,185,0,0, - 0,150,4,0,0,115,16,0,0,0,0,4,6,1,19,1, + 0,151,4,0,0,115,16,0,0,0,0,4,6,1,19,1, 36,1,9,2,15,1,9,1,12,1,122,19,70,105,108,101, 70,105,110,100,101,114,46,95,95,105,110,105,116,95,95,99, 1,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0, @@ -2177,7 +2177,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,121,32,109,116,105,109,101,46,114,29,0,0,0,78,114, 87,0,0,0,41,1,114,8,1,0,0,41,1,114,108,0, 0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0, - 0,114,250,0,0,0,164,4,0,0,115,2,0,0,0,0, + 0,114,250,0,0,0,165,4,0,0,115,2,0,0,0,0, 2,122,28,70,105,108,101,70,105,110,100,101,114,46,105,110, 118,97,108,105,100,97,116,101,95,99,97,99,104,101,115,99, 2,0,0,0,0,0,0,0,3,0,0,0,2,0,0,0, @@ -2201,7 +2201,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,181,0,0,0,114,127,0,0,0,114,156,0,0,0,41, 3,114,108,0,0,0,114,126,0,0,0,114,164,0,0,0, 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114, - 124,0,0,0,170,4,0,0,115,8,0,0,0,0,7,15, + 124,0,0,0,171,4,0,0,115,8,0,0,0,0,7,15, 1,12,1,10,1,122,22,70,105,108,101,70,105,110,100,101, 114,46,102,105,110,100,95,108,111,97,100,101,114,99,6,0, 0,0,0,0,0,0,7,0,0,0,7,0,0,0,67,0, @@ -2212,7 +2212,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,41,7,114,108,0,0,0,114,165,0,0,0,114, 126,0,0,0,114,35,0,0,0,90,4,115,109,115,108,114, 180,0,0,0,114,127,0,0,0,114,4,0,0,0,114,4, - 0,0,0,114,5,0,0,0,114,5,1,0,0,182,4,0, + 0,0,0,114,5,0,0,0,114,5,1,0,0,183,4,0, 0,115,6,0,0,0,0,1,15,1,18,1,122,20,70,105, 108,101,70,105,110,100,101,114,46,95,103,101,116,95,115,112, 101,99,78,99,3,0,0,0,0,0,0,0,14,0,0,0, @@ -2276,7 +2276,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,114,165,0,0,0,90,13,105,110,105,116,95,102,105,108, 101,110,97,109,101,90,9,102,117,108,108,95,112,97,116,104, 114,164,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 5,0,0,0,114,181,0,0,0,187,4,0,0,115,68,0, + 5,0,0,0,114,181,0,0,0,188,4,0,0,115,68,0, 0,0,0,3,6,1,19,1,3,1,34,1,13,1,11,1, 15,1,10,1,9,2,9,1,9,1,15,2,9,1,6,2, 12,1,18,1,22,1,10,1,15,1,12,1,32,4,12,2, @@ -2313,7 +2313,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,4,0,0,0,41,1,114,88,0,0,0,41,2,114,22, 0,0,0,90,2,102,110,114,4,0,0,0,114,4,0,0, 0,114,5,0,0,0,250,9,60,115,101,116,99,111,109,112, - 62,5,5,0,0,115,2,0,0,0,9,0,122,41,70,105, + 62,6,5,0,0,115,2,0,0,0,9,0,122,41,70,105, 108,101,70,105,110,100,101,114,46,95,102,105,108,108,95,99, 97,99,104,101,46,60,108,111,99,97,108,115,62,46,60,115, 101,116,99,111,109,112,62,78,41,18,114,35,0,0,0,114, @@ -2330,7 +2330,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,245,0,0,0,114,106,0,0,0,114,237,0,0,0,114, 225,0,0,0,90,8,110,101,119,95,110,97,109,101,114,4, 0,0,0,114,4,0,0,0,114,5,0,0,0,114,13,1, - 0,0,232,4,0,0,115,34,0,0,0,0,2,9,1,3, + 0,0,233,4,0,0,115,34,0,0,0,0,2,9,1,3, 1,31,1,22,3,11,3,18,1,18,7,9,1,13,1,24, 1,6,1,27,2,6,1,17,1,9,1,18,1,122,22,70, 105,108,101,70,105,110,100,101,114,46,95,102,105,108,108,95, @@ -2369,14 +2369,14 @@ const unsigned char _Py_M__importlib_external[] = { 0,41,2,114,170,0,0,0,114,12,1,0,0,114,4,0, 0,0,114,5,0,0,0,218,24,112,97,116,104,95,104,111, 111,107,95,102,111,114,95,70,105,108,101,70,105,110,100,101, - 114,17,5,0,0,115,6,0,0,0,0,2,12,1,18,1, + 114,18,5,0,0,115,6,0,0,0,0,2,12,1,18,1, 122,54,70,105,108,101,70,105,110,100,101,114,46,112,97,116, 104,95,104,111,111,107,46,60,108,111,99,97,108,115,62,46, 112,97,116,104,95,104,111,111,107,95,102,111,114,95,70,105, 108,101,70,105,110,100,101,114,114,4,0,0,0,41,3,114, 170,0,0,0,114,12,1,0,0,114,18,1,0,0,114,4, 0,0,0,41,2,114,170,0,0,0,114,12,1,0,0,114, - 5,0,0,0,218,9,112,97,116,104,95,104,111,111,107,7, + 5,0,0,0,218,9,112,97,116,104,95,104,111,111,107,8, 5,0,0,115,4,0,0,0,0,10,21,6,122,20,70,105, 108,101,70,105,110,100,101,114,46,112,97,116,104,95,104,111, 111,107,99,1,0,0,0,0,0,0,0,1,0,0,0,2, @@ -2385,7 +2385,7 @@ const unsigned char _Py_M__importlib_external[] = { 16,70,105,108,101,70,105,110,100,101,114,40,123,33,114,125, 41,41,2,114,47,0,0,0,114,35,0,0,0,41,1,114, 108,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5, - 0,0,0,114,244,0,0,0,25,5,0,0,115,2,0,0, + 0,0,0,114,244,0,0,0,26,5,0,0,115,2,0,0, 0,0,1,122,19,70,105,108,101,70,105,110,100,101,114,46, 95,95,114,101,112,114,95,95,41,15,114,112,0,0,0,114, 111,0,0,0,114,113,0,0,0,114,114,0,0,0,114,185, @@ -2393,7 +2393,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,114,124,0,0,0,114,5,1,0,0,114,181,0,0, 0,114,13,1,0,0,114,183,0,0,0,114,19,1,0,0, 114,244,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,5,0,0,0,114,6,1,0,0,141,4, + 4,0,0,0,114,5,0,0,0,114,6,1,0,0,142,4, 0,0,115,20,0,0,0,12,7,6,2,12,14,12,4,6, 2,12,12,12,5,15,45,12,31,18,18,114,6,1,0,0, 99,4,0,0,0,0,0,0,0,6,0,0,0,11,0,0, @@ -2420,7 +2420,7 @@ const unsigned char _Py_M__importlib_external[] = { 97,116,104,110,97,109,101,114,127,0,0,0,114,164,0,0, 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0, 218,14,95,102,105,120,95,117,112,95,109,111,100,117,108,101, - 31,5,0,0,115,34,0,0,0,0,2,15,1,15,1,6, + 32,5,0,0,115,34,0,0,0,0,2,15,1,15,1,6, 1,6,1,12,1,12,1,18,2,15,1,6,1,21,1,3, 1,10,1,10,1,10,1,14,1,13,2,114,24,1,0,0, 99,0,0,0,0,0,0,0,0,3,0,0,0,3,0,0, @@ -2440,7 +2440,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,114,74,0,0,0,41,3,90,10,101,120,116,101, 110,115,105,111,110,115,90,6,115,111,117,114,99,101,90,8, 98,121,116,101,99,111,100,101,114,4,0,0,0,114,4,0, - 0,0,114,5,0,0,0,114,161,0,0,0,54,5,0,0, + 0,0,114,5,0,0,0,114,161,0,0,0,55,5,0,0, 115,8,0,0,0,0,5,18,1,12,1,12,1,114,161,0, 0,0,99,1,0,0,0,0,0,0,0,12,0,0,0,12, 0,0,0,67,0,0,0,115,70,2,0,0,124,0,0,97, @@ -2502,7 +2502,7 @@ const unsigned char _Py_M__importlib_external[] = { 1,113,3,0,100,1,0,83,41,2,114,29,0,0,0,78, 41,1,114,31,0,0,0,41,2,114,22,0,0,0,114,77, 0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0, - 0,0,114,227,0,0,0,90,5,0,0,115,2,0,0,0, + 0,0,114,227,0,0,0,91,5,0,0,115,2,0,0,0, 6,0,122,25,95,115,101,116,117,112,46,60,108,111,99,97, 108,115,62,46,60,103,101,110,101,120,112,114,62,114,59,0, 0,0,122,30,105,109,112,111,114,116,108,105,98,32,114,101, @@ -2532,7 +2532,7 @@ const unsigned char _Py_M__importlib_external[] = { 95,109,111,100,117,108,101,90,14,119,101,97,107,114,101,102, 95,109,111,100,117,108,101,90,13,119,105,110,114,101,103,95, 109,111,100,117,108,101,114,4,0,0,0,114,4,0,0,0, - 114,5,0,0,0,218,6,95,115,101,116,117,112,65,5,0, + 114,5,0,0,0,218,6,95,115,101,116,117,112,66,5,0, 0,115,82,0,0,0,0,8,6,1,9,1,9,3,13,1, 13,1,15,1,18,2,13,1,20,3,33,1,19,2,31,1, 10,1,15,1,13,1,4,2,3,1,15,1,5,1,13,1, @@ -2558,7 +2558,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,114,249,0,0,0,114,218,0,0,0,41,2,114,32, 1,0,0,90,17,115,117,112,112,111,114,116,101,100,95,108, 111,97,100,101,114,115,114,4,0,0,0,114,4,0,0,0, - 114,5,0,0,0,218,8,95,105,110,115,116,97,108,108,133, + 114,5,0,0,0,218,8,95,105,110,115,116,97,108,108,134, 5,0,0,115,16,0,0,0,0,2,10,1,9,1,28,1, 15,1,16,1,16,4,9,1,114,35,1,0,0,41,3,122, 3,119,105,110,114,1,0,0,0,114,2,0,0,0,41,57, @@ -2588,7 +2588,7 @@ const unsigned char _Py_M__importlib_external[] = { 5,0,0,0,218,8,60,109,111,100,117,108,101,62,8,0, 0,0,115,100,0,0,0,6,17,6,3,12,12,12,5,12, 5,12,6,12,12,12,10,12,9,12,5,12,7,15,22,15, - 109,22,1,18,2,6,1,6,2,9,2,9,2,10,2,21, + 110,22,1,18,2,6,1,6,2,9,2,9,2,10,2,21, 44,12,33,12,19,12,12,12,12,18,8,12,28,12,17,21, 55,21,12,18,10,12,14,9,3,12,1,15,65,19,64,19, 28,22,110,19,41,25,43,25,16,6,3,25,53,19,57,19, diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index ed2a135..19259e1 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -68,7 +68,7 @@ static void *opcode_targets[256] = { &&TARGET_BINARY_OR, &&TARGET_INPLACE_POWER, &&TARGET_GET_ITER, - &&_unknown_opcode, + &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, &&TARGET_LOAD_BUILD_CLASS, &&TARGET_YIELD_FROM, |