Issue #27985: Implement PEP 526 -- Syntax for Variable Annotations.

Patch by Ivan Levkivskyi.
This commit is contained in:
Yury Selivanov 2016-09-08 20:50:03 -07:00
parent 09ad17810c
commit f8cb8a16a3
45 changed files with 3242 additions and 1308 deletions

View file

@ -964,6 +964,18 @@ Glossary
``'\r'``. See :pep:`278` and :pep:`3116`, as well as
:func:`bytes.splitlines` for an additional use.
variable annotation
A type metadata value associated with a module global variable or
a class attribute. Its syntax is explained in section :ref:`annassign`.
Annotations are stored in the :attr:`__annotations__` special
attribute of a class or module object and can be accessed using
:func:`typing.get_type_hints`.
Python itself does not assign any particular meaning to variable
annotations. They are intended to be interpreted by third-party libraries
or type checking tools. See :pep:`526`, :pep:`484` which describe
some of their potential uses.
virtual environment
A cooperatively isolated runtime environment that allows Python users
and applications to install and upgrade Python distribution packages

View file

@ -607,6 +607,12 @@ iterations of the loop.
.. versionadded:: 3.3
.. opcode:: SETUP_ANNOTATIONS
Checks whether ``__annotations__`` is defined in ``locals()``, if not it is
set up to an empty ``dict``. This opcode is only emmitted if a class
or module body contains :term:`variable annotations <variable annotation>`
statically.
.. opcode:: IMPORT_STAR
@ -890,6 +896,11 @@ All of the following opcodes use their arguments.
Deletes local ``co_varnames[var_num]``.
.. opcode:: STORE_ANNOTATION (namei)
Stores TOS as ``locals()['__annotations__'][co_names[namei]] = TOS``.
.. opcode:: LOAD_CLOSURE (i)
Pushes a reference to the cell contained in slot *i* of the cell and free

View file

@ -686,10 +686,28 @@ Modules
Attribute assignment updates the module's namespace dictionary, e.g.,
``m.x = 1`` is equivalent to ``m.__dict__["x"] = 1``.
.. index::
single: __name__ (module attribute)
single: __doc__ (module attribute)
single: __file__ (module attribute)
single: __annotations__ (module attribute)
pair: module; namespace
Predefined (writable) attributes: :attr:`__name__` is the module's name;
:attr:`__doc__` is the module's documentation string, or ``None`` if
unavailable; :attr:`__annotations__` (optional) is a dictionary containing
:term:`variable annotations <variable annotation>` collected during module
body execution; :attr:`__file__` is the pathname of the file from which the
module was loaded, if it was loaded from a file. The :attr:`__file__`
attribute may be missing for certain types of modules, such as C modules
that are statically linked into the interpreter; for extension modules
loaded dynamically from a shared library, it is the pathname of the shared
library file.
.. index:: single: __dict__ (module attribute)
Special read-only attribute: :attr:`~object.__dict__` is the module's namespace as a
dictionary object.
Special read-only attribute: :attr:`~object.__dict__` is the module's
namespace as a dictionary object.
.. impl-detail::
@ -698,21 +716,6 @@ Modules
dictionary still has live references. To avoid this, copy the dictionary
or keep the module around while using its dictionary directly.
.. index::
single: __name__ (module attribute)
single: __doc__ (module attribute)
single: __file__ (module attribute)
pair: module; namespace
Predefined (writable) attributes: :attr:`__name__` is the module's name;
:attr:`__doc__` is the module's documentation string, or ``None`` if
unavailable; :attr:`__file__` is the pathname of the file from which the
module was loaded, if it was loaded from a file. The :attr:`__file__`
attribute may be missing for certain types of modules, such as C modules
that are statically linked into the interpreter; for extension modules
loaded dynamically from a shared library, it is the pathname of the shared
library file.
Custom classes
Custom class types are typically created by class definitions (see section
:ref:`class`). A class has a namespace implemented by a dictionary object.
@ -761,13 +764,17 @@ Custom classes
single: __dict__ (class attribute)
single: __bases__ (class attribute)
single: __doc__ (class attribute)
single: __annotations__ (class attribute)
Special attributes: :attr:`~definition.__name__` is the class name; :attr:`__module__` is
the module name in which the class was defined; :attr:`~object.__dict__` is the
dictionary containing the class's namespace; :attr:`~class.__bases__` is a
tuple (possibly empty or a singleton) containing the base classes, in the
order of their occurrence in the base class list; :attr:`__doc__` is the
class's documentation string, or None if undefined.
class's documentation string, or None if undefined;
:attr:`__annotations__` (optional) is a dictionary containing
:term:`variable annotations <variable annotation>` collected during
class body execution.
Class instances
.. index::

View file

@ -16,6 +16,7 @@ simple statements is:
: | `assert_stmt`
: | `assignment_stmt`
: | `augmented_assignment_stmt`
: | `annotated_assignment_stmt`
: | `pass_stmt`
: | `del_stmt`
: | `return_stmt`
@ -312,6 +313,49 @@ For targets which are attribute references, the same :ref:`caveat about class
and instance attributes <attr-target-note>` applies as for regular assignments.
.. _annassign:
Annotated assignment statements
-------------------------------
.. index::
pair: annotated; assignment
single: statement; assignment, annotated
Annotation assignment is the combination, in a single statement,
of a variable or attribute annotation and an optional assignment statement:
.. productionlist::
annotated_assignment_stmt: `augtarget` ":" `expression` ["=" `expression`]
The difference from normal :ref:`assignment` is that only single target and
only single right hand side value is allowed.
For simple names as assignment targets, if in class or module scope,
the annotations are evaluated and stored in a special class or module
attribute :attr:`__annotations__`
that is a dictionary mapping from variable names to evaluated annotations.
This attribute is writable and is automatically created at the start
of class or module body execution, if annotations are found statically.
For expressions as assignment targets, the annotations are evaluated if
in class or module scope, but not stored.
If a name is annotated in a function scope, then this name is local for
that scope. Annotations are never evaluated and stored in function scopes.
If the right hand side is present, an annotated
assignment performs the actual assignment before evaluating annotations
(where applicable). If the right hand side is not present for an expression
target, then the interpreter evaluates the target except for the last
:meth:`__setitem__` or :meth:`__setattr__` call.
.. seealso::
:pep:`526` - Variable and attribute annotation syntax
:pep:`484` - Type hints
.. _assert:
The :keyword:`assert` statement

View file

@ -45,12 +45,13 @@ stmt: simple_stmt | compound_stmt
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
import_stmt | global_stmt | nonlocal_stmt | assert_stmt)
expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) |
expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) |
('=' (yield_expr|testlist_star_expr))*)
annassign: ':' test ['=' test]
testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
'<<=' | '>>=' | '**=' | '//=')
# For normal assignments, additional restrictions enforced by the interpreter
# For normal and annotated assignments, additional restrictions enforced by the interpreter
del_stmt: 'del' exprlist
pass_stmt: 'pass'
flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt

View file

@ -65,11 +65,12 @@ struct _mod {
enum _stmt_kind {FunctionDef_kind=1, AsyncFunctionDef_kind=2, ClassDef_kind=3,
Return_kind=4, Delete_kind=5, Assign_kind=6,
AugAssign_kind=7, For_kind=8, AsyncFor_kind=9, While_kind=10,
If_kind=11, With_kind=12, AsyncWith_kind=13, Raise_kind=14,
Try_kind=15, Assert_kind=16, Import_kind=17,
ImportFrom_kind=18, Global_kind=19, Nonlocal_kind=20,
Expr_kind=21, Pass_kind=22, Break_kind=23, Continue_kind=24};
AugAssign_kind=7, AnnAssign_kind=8, For_kind=9,
AsyncFor_kind=10, While_kind=11, If_kind=12, With_kind=13,
AsyncWith_kind=14, Raise_kind=15, Try_kind=16,
Assert_kind=17, Import_kind=18, ImportFrom_kind=19,
Global_kind=20, Nonlocal_kind=21, Expr_kind=22, Pass_kind=23,
Break_kind=24, Continue_kind=25};
struct _stmt {
enum _stmt_kind kind;
union {
@ -116,6 +117,13 @@ struct _stmt {
expr_ty value;
} AugAssign;
struct {
expr_ty target;
expr_ty annotation;
expr_ty value;
int simple;
} AnnAssign;
struct {
expr_ty target;
expr_ty iter;
@ -461,6 +469,9 @@ stmt_ty _Py_Assign(asdl_seq * targets, expr_ty value, int lineno, int
#define AugAssign(a0, a1, a2, a3, a4, a5) _Py_AugAssign(a0, a1, a2, a3, a4, a5)
stmt_ty _Py_AugAssign(expr_ty target, operator_ty op, expr_ty value, int
lineno, int col_offset, PyArena *arena);
#define AnnAssign(a0, a1, a2, a3, a4, a5, a6) _Py_AnnAssign(a0, a1, a2, a3, a4, a5, a6)
stmt_ty _Py_AnnAssign(expr_ty target, expr_ty annotation, expr_ty value, int
simple, int lineno, int col_offset, PyArena *arena);
#define For(a0, a1, a2, a3, a4, a5, a6) _Py_For(a0, a1, a2, a3, a4, a5, a6)
stmt_ty _Py_For(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq *
orelse, int lineno, int col_offset, PyArena *arena);

View file

@ -17,71 +17,72 @@
#define simple_stmt 270
#define small_stmt 271
#define expr_stmt 272
#define testlist_star_expr 273
#define augassign 274
#define del_stmt 275
#define pass_stmt 276
#define flow_stmt 277
#define break_stmt 278
#define continue_stmt 279
#define return_stmt 280
#define yield_stmt 281
#define raise_stmt 282
#define import_stmt 283
#define import_name 284
#define import_from 285
#define import_as_name 286
#define dotted_as_name 287
#define import_as_names 288
#define dotted_as_names 289
#define dotted_name 290
#define global_stmt 291
#define nonlocal_stmt 292
#define assert_stmt 293
#define compound_stmt 294
#define async_stmt 295
#define if_stmt 296
#define while_stmt 297
#define for_stmt 298
#define try_stmt 299
#define with_stmt 300
#define with_item 301
#define except_clause 302
#define suite 303
#define test 304
#define test_nocond 305
#define lambdef 306
#define lambdef_nocond 307
#define or_test 308
#define and_test 309
#define not_test 310
#define comparison 311
#define comp_op 312
#define star_expr 313
#define expr 314
#define xor_expr 315
#define and_expr 316
#define shift_expr 317
#define arith_expr 318
#define term 319
#define factor 320
#define power 321
#define atom_expr 322
#define atom 323
#define testlist_comp 324
#define trailer 325
#define subscriptlist 326
#define subscript 327
#define sliceop 328
#define exprlist 329
#define testlist 330
#define dictorsetmaker 331
#define classdef 332
#define arglist 333
#define argument 334
#define comp_iter 335
#define comp_for 336
#define comp_if 337
#define encoding_decl 338
#define yield_expr 339
#define yield_arg 340
#define annassign 273
#define testlist_star_expr 274
#define augassign 275
#define del_stmt 276
#define pass_stmt 277
#define flow_stmt 278
#define break_stmt 279
#define continue_stmt 280
#define return_stmt 281
#define yield_stmt 282
#define raise_stmt 283
#define import_stmt 284
#define import_name 285
#define import_from 286
#define import_as_name 287
#define dotted_as_name 288
#define import_as_names 289
#define dotted_as_names 290
#define dotted_name 291
#define global_stmt 292
#define nonlocal_stmt 293
#define assert_stmt 294
#define compound_stmt 295
#define async_stmt 296
#define if_stmt 297
#define while_stmt 298
#define for_stmt 299
#define try_stmt 300
#define with_stmt 301
#define with_item 302
#define except_clause 303
#define suite 304
#define test 305
#define test_nocond 306
#define lambdef 307
#define lambdef_nocond 308
#define or_test 309
#define and_test 310
#define not_test 311
#define comparison 312
#define comp_op 313
#define star_expr 314
#define expr 315
#define xor_expr 316
#define and_expr 317
#define shift_expr 318
#define arith_expr 319
#define term 320
#define factor 321
#define power 322
#define atom_expr 323
#define atom 324
#define testlist_comp 325
#define trailer 326
#define subscriptlist 327
#define subscript 328
#define sliceop 329
#define exprlist 330
#define testlist 331
#define dictorsetmaker 332
#define classdef 333
#define arglist 334
#define argument 335
#define comp_iter 336
#define comp_for 337
#define comp_if 338
#define encoding_decl 339
#define yield_expr 340
#define yield_arg 341

View file

@ -60,6 +60,7 @@ extern "C" {
#define WITH_CLEANUP_FINISH 82
#define RETURN_VALUE 83
#define IMPORT_STAR 84
#define SETUP_ANNOTATIONS 85
#define YIELD_VALUE 86
#define POP_BLOCK 87
#define END_FINALLY 88
@ -98,6 +99,7 @@ extern "C" {
#define LOAD_FAST 124
#define STORE_FAST 125
#define DELETE_FAST 126
#define STORE_ANNOTATION 127
#define RAISE_VARARGS 130
#define CALL_FUNCTION 131
#define MAKE_FUNCTION 132

View file

@ -91,6 +91,7 @@ PyAPI_FUNC(void) PySymtable_Free(struct symtable *);
#define DEF_FREE 2<<4 /* name used but not defined in nested block */
#define DEF_FREE_CLASS 2<<5 /* free variable from class's method */
#define DEF_IMPORT 2<<6 /* assignment occurred via import */
#define DEF_ANNOT 2<<7 /* this name is annotated */
#define DEF_BOUND (DEF_LOCAL | DEF_PARAM | DEF_IMPORT)

View file

@ -234,6 +234,8 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.6a1 3372 (MAKE_FUNCTION simplification, remove MAKE_CLOSURE
# #27095)
# Python 3.6b1 3373 (add BUILD_STRING opcode #27078)
# Python 3.6b1 3375 (add SETUP_ANNOTATIONS and STORE_ANNOTATION opcodes
# #27985)
#
# MAGIC must change whenever the bytecode emitted by the compiler may no
# longer be understood by older implementations of the eval loop (usually
@ -242,7 +244,7 @@ def _write_atomic(path, data, mode=0o666):
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.
MAGIC_NUMBER = (3373).to_bytes(2, 'little') + b'\r\n'
MAGIC_NUMBER = (3375).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
_PYCACHE = '__pycache__'

View file

@ -54,12 +54,13 @@ stmt: simple_stmt | compound_stmt
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
small_stmt: (expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt |
import_stmt | global_stmt | exec_stmt | assert_stmt)
expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) |
expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) |
('=' (yield_expr|testlist_star_expr))*)
annassign: ':' test ['=' test]
testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
'<<=' | '>>=' | '**=' | '//=')
# For normal assignments, additional restrictions enforced by the interpreter
# For normal and annotated assignments, additional restrictions enforced by the interpreter
print_stmt: 'print' ( [ test (',' test)* [','] ] |
'>>' test [ (',' test)+ [','] ] )
del_stmt: 'del' exprlist

View file

@ -237,6 +237,36 @@ def test_8(self):
self.validate(s)
# Adapted from Python 3's Lib/test/test_grammar.py:GrammarTests.test_var_annot
class TestFunctionAnnotations(GrammarTest):
def test_1(self):
self.validate("var1: int = 5")
def test_2(self):
self.validate("var2: [int, str]")
def test_3(self):
self.validate("def f():\n"
" st: str = 'Hello'\n"
" a.b: int = (1, 2)\n"
" return st\n")
def test_4(self):
self.validate("def fbad():\n"
" x: int\n"
" print(x)\n")
def test_5(self):
self.validate("class C:\n"
" x: int\n"
" s: str = 'attr'\n"
" z = 2\n"
" def __init__(self, x):\n"
" self.x: int = x\n")
def test_6(self):
self.validate("lst: List[int] = []")
class TestExcept(GrammarTest):
def test_new(self):
s = """

View file

@ -119,7 +119,7 @@ def jabs_op(name, op):
def_op('RETURN_VALUE', 83)
def_op('IMPORT_STAR', 84)
def_op('SETUP_ANNOTATIONS', 85)
def_op('YIELD_VALUE', 86)
def_op('POP_BLOCK', 87)
def_op('END_FINALLY', 88)
@ -169,6 +169,7 @@ def jabs_op(name, op):
haslocal.append(125)
def_op('DELETE_FAST', 126) # Local variable number
haslocal.append(126)
name_op('STORE_ANNOTATION', 127) # Index in name list
def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3)
def_op('CALL_FUNCTION', 131) # #args + (#kwargs << 8)

View file

@ -27,74 +27,75 @@
simple_stmt = 270
small_stmt = 271
expr_stmt = 272
testlist_star_expr = 273
augassign = 274
del_stmt = 275
pass_stmt = 276
flow_stmt = 277
break_stmt = 278
continue_stmt = 279
return_stmt = 280
yield_stmt = 281
raise_stmt = 282
import_stmt = 283
import_name = 284
import_from = 285
import_as_name = 286
dotted_as_name = 287
import_as_names = 288
dotted_as_names = 289
dotted_name = 290
global_stmt = 291
nonlocal_stmt = 292
assert_stmt = 293
compound_stmt = 294
async_stmt = 295
if_stmt = 296
while_stmt = 297
for_stmt = 298
try_stmt = 299
with_stmt = 300
with_item = 301
except_clause = 302
suite = 303
test = 304
test_nocond = 305
lambdef = 306
lambdef_nocond = 307
or_test = 308
and_test = 309
not_test = 310
comparison = 311
comp_op = 312
star_expr = 313
expr = 314
xor_expr = 315
and_expr = 316
shift_expr = 317
arith_expr = 318
term = 319
factor = 320
power = 321
atom_expr = 322
atom = 323
testlist_comp = 324
trailer = 325
subscriptlist = 326
subscript = 327
sliceop = 328
exprlist = 329
testlist = 330
dictorsetmaker = 331
classdef = 332
arglist = 333
argument = 334
comp_iter = 335
comp_for = 336
comp_if = 337
encoding_decl = 338
yield_expr = 339
yield_arg = 340
annassign = 273
testlist_star_expr = 274
augassign = 275
del_stmt = 276
pass_stmt = 277
flow_stmt = 278
break_stmt = 279
continue_stmt = 280
return_stmt = 281
yield_stmt = 282
raise_stmt = 283
import_stmt = 284
import_name = 285
import_from = 286
import_as_name = 287
dotted_as_name = 288
import_as_names = 289
dotted_as_names = 290
dotted_name = 291
global_stmt = 292
nonlocal_stmt = 293
assert_stmt = 294
compound_stmt = 295
async_stmt = 296
if_stmt = 297
while_stmt = 298
for_stmt = 299
try_stmt = 300
with_stmt = 301
with_item = 302
except_clause = 303
suite = 304
test = 305
test_nocond = 306
lambdef = 307
lambdef_nocond = 308
or_test = 309
and_test = 310
not_test = 311
comparison = 312
comp_op = 313
star_expr = 314
expr = 315
xor_expr = 316
and_expr = 317
shift_expr = 318
arith_expr = 319
term = 320
factor = 321
power = 322
atom_expr = 323
atom = 324
testlist_comp = 325
trailer = 326
subscriptlist = 327
subscript = 328
sliceop = 329
exprlist = 330
testlist = 331
dictorsetmaker = 332
classdef = 333
arglist = 334
argument = 335
comp_iter = 336
comp_for = 337
comp_if = 338
encoding_decl = 339
yield_expr = 340
yield_arg = 341
#--end constants--
sym_name = {}

View file

@ -2,7 +2,7 @@
import _symtable
from _symtable import (USE, DEF_GLOBAL, DEF_LOCAL, DEF_PARAM,
DEF_IMPORT, DEF_BOUND, SCOPE_OFF, SCOPE_MASK, FREE,
DEF_IMPORT, DEF_BOUND, DEF_ANNOT, SCOPE_OFF, SCOPE_MASK, FREE,
LOCAL, GLOBAL_IMPLICIT, GLOBAL_EXPLICIT, CELL)
import weakref
@ -190,6 +190,9 @@ def is_declared_global(self):
def is_local(self):
return bool(self.__flags & DEF_BOUND)
def is_annotated(self):
return bool(self.__flags & DEF_ANNOT)
def is_free(self):
return bool(self.__scope == FREE)

53
Lib/test/ann_module.py Normal file
View file

@ -0,0 +1,53 @@
"""
The module for testing variable annotations.
Empty lines above are for good reason (testing for correct line numbers)
"""
from typing import Optional
__annotations__[1] = 2
class C:
x = 5; y: Optional['C'] = None
from typing import Tuple
x: int = 5; y: str = x; f: Tuple[int, int]
class M(type):
__annotations__['123'] = 123
o: type = object
(pars): bool = True
class D(C):
j: str = 'hi'; k: str= 'bye'
from types import new_class
h_class = new_class('H', (C,))
j_class = new_class('J')
class F():
z: int = 5
def __init__(self, x):
pass
class Y(F):
def __init__(self):
super(F, self).__init__(123)
class Meta(type):
def __new__(meta, name, bases, namespace):
return super().__new__(meta, name, bases, namespace)
class S(metaclass = Meta):
x: str = 'something'
y: str = 'something else'
def foo(x: int = 10):
def bar(y: List[str]):
x: str = 'yes'
bar()

36
Lib/test/ann_module2.py Normal file
View file

@ -0,0 +1,36 @@
"""
Some correct syntax for variable annotation here.
More examples are in test_grammar and test_parser.
"""
from typing import no_type_check, ClassVar
i: int = 1
j: int
x: float = i/10
def f():
class C: ...
return C()
f().new_attr: object = object()
class C:
def __init__(self, x: int) -> None:
self.x = x
c = C(5)
c.new_attr: int = 10
__annotations__ = {}
@no_type_check
class NTC:
def meth(self, param: complex) -> None:
...
class CV:
var: ClassVar['CV']
CV.var = CV()

18
Lib/test/ann_module3.py Normal file
View file

@ -0,0 +1,18 @@
"""
Correct syntax for variable annotation that should fail at runtime
in a certain manner. More examples are in test_grammar and test_parser.
"""
def f_bad_ann():
__annotations__[1] = 2
class C_OK:
def __init__(self, x: int) -> None:
self.x: no_such_name = x # This one is OK as proposed by Guido
class D_bad_ann:
def __init__(self, x: int) -> None:
sfel.y: int = 0
def g_bad_ann():
no_such_name.attr: int = 0

View file

@ -12,7 +12,7 @@ def __init__():
pass
class B(object):
NO_MEANING = "eggs"
NO_MEANING: str = "eggs"
pass
class C(object):

View file

@ -38,6 +38,8 @@ def check_all(self, modname):
modname, e.__class__.__name__, e))
if "__builtins__" in names:
del names["__builtins__"]
if '__annotations__' in names:
del names['__annotations__']
keys = set(names)
all_list = sys.modules[modname].__all__
all_set = set(all_list)

View file

@ -207,6 +207,38 @@ def bug1333982(x=[]):
10 RETURN_VALUE
"""
annot_stmt_str = """\
x: int = 1
y: fun(1)
lst[fun(0)]: int = 1
"""
# leading newline is for a reason (tests lineno)
dis_annot_stmt_str = """\
2 0 SETUP_ANNOTATIONS
2 LOAD_CONST 0 (1)
4 STORE_NAME 0 (x)
6 LOAD_NAME 1 (int)
8 STORE_ANNOTATION 0 (x)
3 10 LOAD_NAME 2 (fun)
12 LOAD_CONST 0 (1)
14 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
16 STORE_ANNOTATION 3 (y)
4 18 LOAD_CONST 0 (1)
20 LOAD_NAME 4 (lst)
22 LOAD_NAME 2 (fun)
24 LOAD_CONST 1 (0)
26 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
28 STORE_SUBSCR
30 LOAD_NAME 1 (int)
32 POP_TOP
34 LOAD_CONST 2 (None)
36 RETURN_VALUE
"""
compound_stmt_str = """\
x = 0
while 1:
@ -345,6 +377,7 @@ def func(count):
def test_disassemble_str(self):
self.do_disassembly_test(expr_str, dis_expr_str)
self.do_disassembly_test(simple_stmt_str, dis_simple_stmt_str)
self.do_disassembly_test(annot_stmt_str, dis_annot_stmt_str)
self.do_disassembly_test(compound_stmt_str, dis_compound_stmt_str)
def test_disassemble_bytes(self):

View file

@ -8,6 +8,14 @@
# testing import *
from sys import *
# different import patterns to check that __annotations__ does not interfere
# with import machinery
import test.ann_module as ann_module
import typing
from collections import ChainMap
from test import ann_module2
import test
class TokenTests(unittest.TestCase):
@ -139,6 +147,19 @@ def test_eof_error(self):
compile(s, "<test>", "exec")
self.assertIn("unexpected EOF", str(cm.exception))
var_annot_global: int # a global annotated is necessary for test_var_annot
# custom namespace for testing __annotations__
class CNS:
def __init__(self):
self._dct = {}
def __setitem__(self, item, value):
self._dct[item.lower()] = value
def __getitem__(self, item):
return self._dct[item]
class GrammarTests(unittest.TestCase):
# single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
@ -154,6 +175,163 @@ def test_eval_input(self):
# testlist ENDMARKER
x = eval('1, 0 or 1')
def test_var_annot_basics(self):
# all these should be allowed
var1: int = 5
var2: [int, str]
my_lst = [42]
def one():
return 1
int.new_attr: int
[list][0]: type
my_lst[one()-1]: int = 5
self.assertEqual(my_lst, [5])
def test_var_annot_syntax_errors(self):
# parser pass
check_syntax_error(self, "def f: int")
check_syntax_error(self, "x: int: str")
check_syntax_error(self, "def f():\n"
" nonlocal x: int\n")
# AST pass
check_syntax_error(self, "[x, 0]: int\n")
check_syntax_error(self, "f(): int\n")
check_syntax_error(self, "(x,): int")
check_syntax_error(self, "def f():\n"
" (x, y): int = (1, 2)\n")
# symtable pass
check_syntax_error(self, "def f():\n"
" x: int\n"
" global x\n")
check_syntax_error(self, "def f():\n"
" global x\n"
" x: int\n")
def test_var_annot_basic_semantics(self):
# execution order
with self.assertRaises(ZeroDivisionError):
no_name[does_not_exist]: no_name_again = 1/0
with self.assertRaises(NameError):
no_name[does_not_exist]: 1/0 = 0
global var_annot_global
# function semantics
def f():
st: str = "Hello"
a.b: int = (1, 2)
return st
self.assertEqual(f.__annotations__, {})
def f_OK():
x: 1/0
f_OK()
def fbad():
x: int
print(x)
with self.assertRaises(UnboundLocalError):
fbad()
def f2bad():
(no_such_global): int
print(no_such_global)
try:
f2bad()
except Exception as e:
self.assertIs(type(e), NameError)
# class semantics
class C:
x: int
s: str = "attr"
z = 2
def __init__(self, x):
self.x: int = x
self.assertEqual(C.__annotations__, {'x': int, 's': str})
with self.assertRaises(NameError):
class CBad:
no_such_name_defined.attr: int = 0
with self.assertRaises(NameError):
class Cbad2(C):
x: int
x.y: list = []
def test_var_annot_metaclass_semantics(self):
class CMeta(type):
@classmethod
def __prepare__(metacls, name, bases, **kwds):
return {'__annotations__': CNS()}
class CC(metaclass=CMeta):
XX: 'ANNOT'
self.assertEqual(CC.__annotations__['xx'], 'ANNOT')
def test_var_annot_module_semantics(self):
with self.assertRaises(AttributeError):
print(test.__annotations__)
self.assertEqual(ann_module.__annotations__,
{1: 2, 'x': int, 'y': str, 'f': typing.Tuple[int, int]})
self.assertEqual(ann_module.M.__annotations__,
{'123': 123, 'o': type})
self.assertEqual(ann_module2.__annotations__, {})
self.assertEqual(typing.get_type_hints(ann_module2.CV,
ann_module2.__dict__),
ChainMap({'var': typing.ClassVar[ann_module2.CV]}, {}))
def test_var_annot_in_module(self):
# check that functions fail the same way when executed
# outside of module where they were defined
from test.ann_module3 import f_bad_ann, g_bad_ann, D_bad_ann
with self.assertRaises(NameError):
f_bad_ann()
with self.assertRaises(NameError):
g_bad_ann()
with self.assertRaises(NameError):
D_bad_ann(5)
def test_var_annot_simple_exec(self):
gns = {}; lns= {}
exec("'docstring'\n"
"__annotations__[1] = 2\n"
"x: int = 5\n", gns, lns)
self.assertEqual(lns["__annotations__"], {1: 2, 'x': int})
with self.assertRaises(KeyError):
gns['__annotations__']
def test_var_annot_custom_maps(self):
# tests with custom locals() and __annotations__
ns = {'__annotations__': CNS()}
exec('X: int; Z: str = "Z"; (w): complex = 1j', ns)
self.assertEqual(ns['__annotations__']['x'], int)
self.assertEqual(ns['__annotations__']['z'], str)
with self.assertRaises(KeyError):
ns['__annotations__']['w']
nonloc_ns = {}
class CNS2:
def __init__(self):
self._dct = {}
def __setitem__(self, item, value):
nonlocal nonloc_ns
self._dct[item] = value
nonloc_ns[item] = value
def __getitem__(self, item):
return self._dct[item]
exec('x: int = 1', {}, CNS2())
self.assertEqual(nonloc_ns['__annotations__']['x'], int)
def test_var_annot_refleak(self):
# complex case: custom locals plus custom __annotations__
# this was causing refleak
cns = CNS()
nonloc_ns = {'__annotations__': cns}
class CNS2:
def __init__(self):
self._dct = {'__annotations__': cns}
def __setitem__(self, item, value):
nonlocal nonloc_ns
self._dct[item] = value
nonloc_ns[item] = value
def __getitem__(self, item):
return self._dct[item]
exec('X: str', {}, CNS2())
self.assertEqual(nonloc_ns['__annotations__']['x'], str)
def test_funcdef(self):
### [decorators] 'def' NAME parameters ['->' test] ':' suite
### decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE

View file

@ -1,6 +1,7 @@
# Python test set -- part 2, opcodes
import unittest
from test import ann_module
class OpcodeTest(unittest.TestCase):
@ -20,6 +21,32 @@ def test_try_inside_for_loop(self):
if n != 90:
self.fail('try inside for')
def test_setup_annotations_line(self):
# check that SETUP_ANNOTATIONS does not create spurious line numbers
try:
with open(ann_module.__file__) as f:
txt = f.read()
co = compile(txt, ann_module.__file__, 'exec')
self.assertEqual(co.co_firstlineno, 6)
except OSError:
pass
def test_no_annotations_if_not_needed(self):
class C: pass
with self.assertRaises(AttributeError):
C.__annotations__
def test_use_existing_annotations(self):
ns = {'__annotations__': {1: 2}}
exec('x: int', ns)
self.assertEqual(ns['__annotations__'], {'x': int, 1: 2})
def test_do_not_recreate_annotations(self):
class C:
del __annotations__
with self.assertRaises(NameError):
x: int
def test_raise_class_exceptions(self):
class AClass(Exception): pass

View file

@ -138,6 +138,45 @@ def test_simple_assignments(self):
self.check_suite("a = b")
self.check_suite("a = b = c = d = e")
def test_var_annot(self):
self.check_suite("x: int = 5")
self.check_suite("y: List[T] = []; z: [list] = fun()")
self.check_suite("x: tuple = (1, 2)")
self.check_suite("d[f()]: int = 42")
self.check_suite("f(d[x]): str = 'abc'")
self.check_suite("x.y.z.w: complex = 42j")
self.check_suite("x: int")
self.check_suite("def f():\n"
" x: str\n"
" y: int = 5\n")
self.check_suite("class C:\n"
" x: str\n"
" y: int = 5\n")
self.check_suite("class C:\n"
" def __init__(self, x: int) -> None:\n"
" self.x: int = x\n")
# double check for nonsense
with self.assertRaises(SyntaxError):
exec("2+2: int", {}, {})
with self.assertRaises(SyntaxError):
exec("[]: int = 5", {}, {})
with self.assertRaises(SyntaxError):
exec("x, *y, z: int = range(5)", {}, {})
with self.assertRaises(SyntaxError):
exec("t: tuple = 1, 2", {}, {})
with self.assertRaises(SyntaxError):
exec("u = v: int", {}, {})
with self.assertRaises(SyntaxError):
exec("False: int", {}, {})
with self.assertRaises(SyntaxError):
exec("x.False: int", {}, {})
with self.assertRaises(SyntaxError):
exec("x.y,: int", {}, {})
with self.assertRaises(SyntaxError):
exec("[0]: int", {}, {})
with self.assertRaises(SyntaxError):
exec("f(): int", {}, {})
def test_simple_augmented_assignments(self):
self.check_suite("a += b")
self.check_suite("a -= b")

View file

@ -83,6 +83,8 @@ class B(builtins.object)
| Data and other attributes defined here:
|\x20\x20
| NO_MEANING = 'eggs'
|\x20\x20
| __annotations__ = {'NO_MEANING': <class 'str'>}
\x20\x20\x20\x20
class C(builtins.object)
| Methods defined here:
@ -195,6 +197,8 @@ class C(builtins.object)
Data and other attributes defined here:<br>
<dl><dt><strong>NO_MEANING</strong> = 'eggs'</dl>
<dl><dt><strong>__annotations__</strong> = {'NO_MEANING': &lt;class 'str'&gt;}</dl>
</td></tr></table> <p>
<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ffc8d8">

View file

@ -133,6 +133,17 @@ def test_assigned(self):
self.assertTrue(self.Mine.lookup("a_method").is_assigned())
self.assertFalse(self.internal.lookup("x").is_assigned())
def test_annotated(self):
st1 = symtable.symtable('def f():\n x: int\n', 'test', 'exec')
st2 = st1.get_children()[0]
self.assertTrue(st2.lookup('x').is_local())
self.assertTrue(st2.lookup('x').is_annotated())
self.assertFalse(st2.lookup('x').is_global())
st3 = symtable.symtable('def f():\n x = 1\n', 'test', 'exec')
st4 = st3.get_children()[0]
self.assertTrue(st4.lookup('x').is_local())
self.assertFalse(st4.lookup('x').is_annotated())
def test_imported(self):
self.assertTrue(self.top.lookup("sys").is_imported())

View file

@ -0,0 +1,260 @@
"""Tests for the com2ann.py script in the Tools/parser directory."""
import unittest
import test.support
import os
import re
from test.test_tools import basepath, toolsdir, skip_if_missing
skip_if_missing()
parser_path = os.path.join(toolsdir, "parser")
with test.support.DirsOnSysPath(parser_path):
from com2ann import *
class BaseTestCase(unittest.TestCase):
def check(self, code, expected, n=False, e=False):
self.assertEqual(com2ann(code,
drop_None=n, drop_Ellipsis=e, silent=True),
expected)
class SimpleTestCase(BaseTestCase):
# Tests for basic conversions
def test_basics(self):
self.check("z = 5", "z = 5")
self.check("z: int = 5", "z: int = 5")
self.check("z = 5 # type: int", "z: int = 5")
self.check("z = 5 # type: int # comment",
"z: int = 5 # comment")
def test_type_ignore(self):
self.check("foobar = foobaz() #type: ignore",
"foobar = foobaz() #type: ignore")
self.check("a = 42 #type: ignore #comment",
"a = 42 #type: ignore #comment")
def test_complete_tuple(self):
self.check("t = 1, 2, 3 # type: Tuple[int, ...]",
"t: Tuple[int, ...] = (1, 2, 3)")
self.check("t = 1, # type: Tuple[int]",
"t: Tuple[int] = (1,)")
self.check("t = (1, 2, 3) # type: Tuple[int, ...]",
"t: Tuple[int, ...] = (1, 2, 3)")
def test_drop_None(self):
self.check("x = None # type: int",
"x: int", True)
self.check("x = None # type: int # another",
"x: int # another", True)
self.check("x = None # type: int # None",
"x: int # None", True)
def test_drop_Ellipsis(self):
self.check("x = ... # type: int",
"x: int", False, True)
self.check("x = ... # type: int # another",
"x: int # another", False, True)
self.check("x = ... # type: int # ...",
"x: int # ...", False, True)
def test_newline(self):
self.check("z = 5 # type: int\r\n", "z: int = 5\r\n")
self.check("z = 5 # type: int # comment\x85",
"z: int = 5 # comment\x85")
def test_wrong(self):
self.check("#type : str", "#type : str")
self.check("x==y #type: bool", "x==y #type: bool")
def test_pattern(self):
for line in ["#type: int", " # type: str[:] # com"]:
self.assertTrue(re.search(TYPE_COM, line))
for line in ["", "#", "# comment", "#type", "type int:"]:
self.assertFalse(re.search(TYPE_COM, line))
class BigTestCase(BaseTestCase):
# Tests for really crazy formatting, to be sure
# that script works reasonably in extreme situations
def test_crazy(self):
self.maxDiff = None
self.check(crazy_code, big_result, False, False)
self.check(crazy_code, big_result_ne, True, True)
crazy_code = """\
# -*- coding: utf-8 -*- # this should not be spoiled
'''
Docstring here
'''
import testmod
x = 5 #type : int # this one is OK
ttt \\
= \\
1.0, \\
2.0, \\
3.0, #type: Tuple[float, float, float]
with foo(x==1) as f: #type: str
print(f)
for i, j in my_inter(x=1): # type: ignore
i + j # type: int # what about this
x = y = z = 1 # type: int
x, y, z = [], [], [] # type: (List[int], List[int], List[str])
class C:
l[f(x
=1)] = [
1,
2,
] # type: List[int]
(C.x[1]) = \\
42 == 5# type: bool
lst[...] = \\
((\\
...)) # type: int # comment ..
y = ... # type: int # comment ...
z = ...
#type: int
#DONE placement of annotation after target rather than before =
TD.x[1] \\
= 0 == 5# type: bool
TD.y[1] =5 == 5# type: bool # one more here
F[G(x == y,
# hm...
z)]\\
= None # type: OMG[int] # comment: None
x = None#type:int #comment : None"""
big_result = """\
# -*- coding: utf-8 -*- # this should not be spoiled
'''
Docstring here
'''
import testmod
x: int = 5 # this one is OK
ttt: Tuple[float, float, float] \\
= \\
(1.0, \\
2.0, \\
3.0,)
with foo(x==1) as f: #type: str
print(f)
for i, j in my_inter(x=1): # type: ignore
i + j # type: int # what about this
x = y = z = 1 # type: int
x, y, z = [], [], [] # type: (List[int], List[int], List[str])
class C:
l[f(x
=1)]: List[int] = [
1,
2,
]
(C.x[1]): bool = \\
42 == 5
lst[...]: int = \\
((\\
...)) # comment ..
y: int = ... # comment ...
z = ...
#type: int
#DONE placement of annotation after target rather than before =
TD.x[1]: bool \\
= 0 == 5
TD.y[1]: bool =5 == 5 # one more here
F[G(x == y,
# hm...
z)]: OMG[int]\\
= None # comment: None
x: int = None #comment : None"""
big_result_ne = """\
# -*- coding: utf-8 -*- # this should not be spoiled
'''
Docstring here
'''
import testmod
x: int = 5 # this one is OK
ttt: Tuple[float, float, float] \\
= \\
(1.0, \\
2.0, \\
3.0,)
with foo(x==1) as f: #type: str
print(f)
for i, j in my_inter(x=1): # type: ignore
i + j # type: int # what about this
x = y = z = 1 # type: int
x, y, z = [], [], [] # type: (List[int], List[int], List[str])
class C:
l[f(x
=1)]: List[int] = [
1,
2,
]
(C.x[1]): bool = \\
42 == 5
lst[...]: int \\
\\
# comment ..
y: int # comment ...
z = ...
#type: int
#DONE placement of annotation after target rather than before =
TD.x[1]: bool \\
= 0 == 5
TD.y[1]: bool =5 == 5 # one more here
F[G(x == y,
# hm...
z)]: OMG[int]\\
# comment: None
x: int #comment : None"""
if __name__ == '__main__':
unittest.main()

View file

@ -4,14 +4,16 @@
import re
import sys
from unittest import TestCase, main, skipUnless, SkipTest
from collections import ChainMap
from test import ann_module, ann_module2, ann_module3
from typing import Any
from typing import TypeVar, AnyStr
from typing import T, KT, VT # Not in __all__.
from typing import Union, Optional
from typing import Tuple
from typing import Tuple, List
from typing import Callable
from typing import Generic
from typing import Generic, ClassVar
from typing import cast
from typing import get_type_hints
from typing import no_type_check, no_type_check_decorator
@ -827,6 +829,43 @@ class D(C):
with self.assertRaises(Exception):
D[T]
class ClassVarTests(BaseTestCase):
def test_basics(self):
with self.assertRaises(TypeError):
ClassVar[1]
with self.assertRaises(TypeError):
ClassVar[int, str]
with self.assertRaises(TypeError):
ClassVar[int][str]
def test_repr(self):
self.assertEqual(repr(ClassVar), 'typing.ClassVar')
cv = ClassVar[int]
self.assertEqual(repr(cv), 'typing.ClassVar[int]')
cv = ClassVar[Employee]
self.assertEqual(repr(cv), 'typing.ClassVar[%s.Employee]' % __name__)
def test_cannot_subclass(self):
with self.assertRaises(TypeError):
class C(type(ClassVar)):
pass
with self.assertRaises(TypeError):
class C(type(ClassVar[int])):
pass
def test_cannot_init(self):
with self.assertRaises(TypeError):
type(ClassVar)()
with self.assertRaises(TypeError):
type(ClassVar[Optional[int]])()
def test_no_isinstance(self):
with self.assertRaises(TypeError):
isinstance(1, ClassVar[int])
with self.assertRaises(TypeError):
issubclass(int, ClassVar)
class VarianceTests(BaseTestCase):
@ -930,6 +969,46 @@ def add_right(self, node: 'Node[T]' = None):
right_hints = get_type_hints(t.add_right, globals(), locals())
self.assertEqual(right_hints['node'], Optional[Node[T]])
def test_get_type_hints(self):
gth = get_type_hints
self.assertEqual(gth(ann_module), {'x': int, 'y': str})
self.assertEqual(gth(ann_module.C, ann_module.__dict__),
ChainMap({'y': Optional[ann_module.C]}, {}))
self.assertEqual(gth(ann_module2), {})
self.assertEqual(gth(ann_module3), {})
self.assertEqual(repr(gth(ann_module.j_class)), 'ChainMap({}, {})')
self.assertEqual(gth(ann_module.M), ChainMap({'123': 123, 'o': type},
{}, {}))
self.assertEqual(gth(ann_module.D),
ChainMap({'j': str, 'k': str,
'y': Optional[ann_module.C]}, {}))
self.assertEqual(gth(ann_module.Y), ChainMap({'z': int}, {}))
self.assertEqual(gth(ann_module.h_class),
ChainMap({}, {'y': Optional[ann_module.C]}, {}))
self.assertEqual(gth(ann_module.S), ChainMap({'x': str, 'y': str},
{}))
self.assertEqual(gth(ann_module.foo), {'x': int})
def testf(x, y): ...
testf.__annotations__['x'] = 'int'
self.assertEqual(gth(testf), {'x': int})
self.assertEqual(gth(ann_module2.NTC.meth), {})
# interactions with ClassVar
class B:
x: ClassVar[Optional['B']] = None
y: int
class C(B):
z: ClassVar['C'] = B()
class G(Generic[T]):
lst: ClassVar[List[T]] = []
self.assertEqual(gth(B, locals()),
ChainMap({'y': int, 'x': ClassVar[Optional[B]]}, {}))
self.assertEqual(gth(C, locals()),
ChainMap({'z': ClassVar[C]},
{'y': int, 'x': ClassVar[Optional[B]]}, {}))
self.assertEqual(gth(G), ChainMap({'lst': ClassVar[List[T]]},{},{}))
def test_forwardref_instance_type_error(self):
fr = typing._ForwardRef('int')
with self.assertRaises(TypeError):

View file

@ -6,6 +6,7 @@
import re as stdlib_re # Avoid confusion with the re we export.
import sys
import types
try:
import collections.abc as collections_abc
except ImportError:
@ -17,6 +18,7 @@
# Super-special typing primitives.
'Any',
'Callable',
'ClassVar',
'Generic',
'Optional',
'Tuple',
@ -270,7 +272,7 @@ def __subclasscheck__(self, cls):
def _get_type_vars(types, tvars):
for t in types:
if isinstance(t, TypingMeta):
if isinstance(t, TypingMeta) or isinstance(t, _ClassVar):
t._get_type_vars(tvars)
@ -281,7 +283,7 @@ def _type_vars(types):
def _eval_type(t, globalns, localns):
if isinstance(t, TypingMeta):
if isinstance(t, TypingMeta) or isinstance(t, _ClassVar):
return t._eval_type(globalns, localns)
else:
return t
@ -1114,6 +1116,67 @@ def __new__(cls, *args, **kwds):
return obj
class _ClassVar(metaclass=TypingMeta, _root=True):
"""Special type construct to mark class variables.
An annotation wrapped in ClassVar indicates that a given
attribute is intended to be used as a class variable and
should not be set on instances of that class. Usage::
class Starship:
stats: ClassVar[Dict[str, int]] = {} # class variable
damage: int = 10 # instance variable
ClassVar accepts only types and cannot be further subscribed.
Note that ClassVar is not a class itself, and should not
be used with isinstance() or issubclass().
"""
def __init__(self, tp=None, _root=False):
cls = type(self)
if _root:
self.__type__ = tp
else:
raise TypeError('Cannot initialize {}'.format(cls.__name__[1:]))
def __getitem__(self, item):
cls = type(self)
if self.__type__ is None:
return cls(_type_check(item,
'{} accepts only types.'.format(cls.__name__[1:])),
_root=True)
raise TypeError('{} cannot be further subscripted'
.format(cls.__name__[1:]))
def _eval_type(self, globalns, localns):
return type(self)(_eval_type(self.__type__, globalns, localns),
_root=True)
def _get_type_vars(self, tvars):
if self.__type__:
_get_type_vars(self.__type__, tvars)
def __repr__(self):
cls = type(self)
if not self.__type__:
return '{}.{}'.format(cls.__module__, cls.__name__[1:])
return '{}.{}[{}]'.format(cls.__module__, cls.__name__[1:],
_type_repr(self.__type__))
def __hash__(self):
return hash((type(self).__name__, self.__type__))
def __eq__(self, other):
if not isinstance(other, _ClassVar):
return NotImplemented
if self.__type__ is not None:
return self.__type__ == other.__type__
return self is other
ClassVar = _ClassVar(_root=True)
def cast(typ, val):
"""Cast a value to a type.
@ -1142,12 +1205,20 @@ def _get_defaults(func):
def get_type_hints(obj, globalns=None, localns=None):
"""Return type hints for a function or method object.
"""Return type hints for an object.
This is often the same as obj.__annotations__, but it handles
forward references encoded as string literals, and if necessary
adds Optional[t] if a default value equal to None is set.
The argument may be a module, class, method, or function. The annotations
are returned as a dictionary, or in the case of a class, a ChainMap of
dictionaries.
TypeError is raised if the argument is not of a type that can contain
annotations, and an empty dictionary is returned if no annotations are
present.
BEWARE -- the behavior of globalns and localns is counterintuitive
(unless you are familiar with how eval() and exec() work). The
search order is locals first, then globals.
@ -1162,6 +1233,7 @@ def get_type_hints(obj, globalns=None, localns=None):
- If two dict arguments are passed, they specify globals and
locals, respectively.
"""
if getattr(obj, '__no_type_check__', None):
return {}
if globalns is None:
@ -1170,16 +1242,62 @@ def get_type_hints(obj, globalns=None, localns=None):
localns = globalns
elif localns is None:
localns = globalns
defaults = _get_defaults(obj)
hints = dict(obj.__annotations__)
for name, value in hints.items():
if isinstance(value, str):
value = _ForwardRef(value)
value = _eval_type(value, globalns, localns)
if name in defaults and defaults[name] is None:
value = Optional[value]
hints[name] = value
return hints
if (isinstance(obj, types.FunctionType) or
isinstance(obj, types.BuiltinFunctionType) or
isinstance(obj, types.MethodType)):
defaults = _get_defaults(obj)
hints = obj.__annotations__
for name, value in hints.items():
if value is None:
value = type(None)
if isinstance(value, str):
value = _ForwardRef(value)
value = _eval_type(value, globalns, localns)
if name in defaults and defaults[name] is None:
value = Optional[value]
hints[name] = value
return hints
if isinstance(obj, types.ModuleType):
try:
hints = obj.__annotations__
except AttributeError:
return {}
# we keep only those annotations that can be accessed on module
members = obj.__dict__
hints = {name: value for name, value in hints.items()
if name in members}
for name, value in hints.items():
if value is None:
value = type(None)
if isinstance(value, str):
value = _ForwardRef(value)
value = _eval_type(value, globalns, localns)
hints[name] = value
return hints
if isinstance(object, type):
cmap = None
for base in reversed(obj.__mro__):
new_map = collections.ChainMap if cmap is None else cmap.new_child
try:
hints = base.__dict__['__annotations__']
except KeyError:
cmap = new_map()
else:
for name, value in hints.items():
if value is None:
value = type(None)
if isinstance(value, str):
value = _ForwardRef(value)
value = _eval_type(value, globalns, localns)
hints[name] = value
cmap = new_map(hints)
return cmap
raise TypeError('{!r} is not a module, class, method, '
'or function.'.format(obj))
def no_type_check(arg):
@ -1300,6 +1418,8 @@ def _get_protocol_attrs(self):
else:
if (not attr.startswith('_abc_') and
attr != '__abstractmethods__' and
attr != '__annotations__' and
attr != '__weakref__' and
attr != '_is_protocol' and
attr != '__dict__' and
attr != '__args__' and

View file

@ -468,6 +468,7 @@ Jason Fried
Robin Friedrich
Bradley Froehle
Ivan Frohne
Ivan Levkivskyi
Matthias Fuchs
Jim Fulton
Tadayoshi Funaba

View file

@ -100,6 +100,9 @@ Core and Builtins
In a brand new thread, raise a RuntimeError since there is no active
exception to reraise. Patch written by Xiang Zhang.
- Issue #27985: Implement PEP 526 -- Syntax for Variable Annotations.
Patch by Ivan Levkivskyi.
Library
-------

View file

@ -79,6 +79,7 @@ PyInit__symtable(void)
PyModule_AddIntMacro(m, DEF_FREE_CLASS);
PyModule_AddIntMacro(m, DEF_IMPORT);
PyModule_AddIntMacro(m, DEF_BOUND);
PyModule_AddIntMacro(m, DEF_ANNOT);
PyModule_AddIntConstant(m, "TYPE_FUNCTION", FunctionBlock);
PyModule_AddIntConstant(m, "TYPE_CLASS", ClassBlock);

View file

@ -1089,7 +1089,7 @@ static PYC_MAGIC magic_values[] = {
{ 3190, 3230, L"3.3" },
{ 3250, 3310, L"3.4" },
{ 3320, 3351, L"3.5" },
{ 3360, 3373, L"3.6" },
{ 3360, 3375, L"3.6" },
{ 0 }
};

View file

@ -28,6 +28,8 @@ module Python
| Delete(expr* targets)
| Assign(expr* targets, expr value)
| AugAssign(expr target, operator op, expr value)
-- 'simple' indicates that we annotate simple name without parens
| AnnAssign(expr target, expr annotation, expr? value, int simple)
-- use 'orelse' because else is a keyword in target languages
| For(expr target, expr iter, stmt* body, stmt* orelse)

View file

@ -86,6 +86,15 @@ static char *AugAssign_fields[]={
"op",
"value",
};
static PyTypeObject *AnnAssign_type;
_Py_IDENTIFIER(annotation);
_Py_IDENTIFIER(simple);
static char *AnnAssign_fields[]={
"target",
"annotation",
"value",
"simple",
};
static PyTypeObject *For_type;
_Py_IDENTIFIER(iter);
_Py_IDENTIFIER(orelse);
@ -466,7 +475,6 @@ static char *arg_attributes[] = {
"col_offset",
};
_Py_IDENTIFIER(arg);
_Py_IDENTIFIER(annotation);
static char *arg_fields[]={
"arg",
"annotation",
@ -873,6 +881,8 @@ static int init_types(void)
if (!Assign_type) return 0;
AugAssign_type = make_type("AugAssign", stmt_type, AugAssign_fields, 3);
if (!AugAssign_type) return 0;
AnnAssign_type = make_type("AnnAssign", stmt_type, AnnAssign_fields, 4);
if (!AnnAssign_type) return 0;
For_type = make_type("For", stmt_type, For_fields, 4);
if (!For_type) return 0;
AsyncFor_type = make_type("AsyncFor", stmt_type, AsyncFor_fields, 4);
@ -1406,6 +1416,34 @@ AugAssign(expr_ty target, operator_ty op, expr_ty value, int lineno, int
return p;
}
stmt_ty
AnnAssign(expr_ty target, expr_ty annotation, expr_ty value, int simple, int
lineno, int col_offset, PyArena *arena)
{
stmt_ty p;
if (!target) {
PyErr_SetString(PyExc_ValueError,
"field target is required for AnnAssign");
return NULL;
}
if (!annotation) {
PyErr_SetString(PyExc_ValueError,
"field annotation is required for AnnAssign");
return NULL;
}
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
if (!p)
return NULL;
p->kind = AnnAssign_kind;
p->v.AnnAssign.target = target;
p->v.AnnAssign.annotation = annotation;
p->v.AnnAssign.value = value;
p->v.AnnAssign.simple = simple;
p->lineno = lineno;
p->col_offset = col_offset;
return p;
}
stmt_ty
For(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * orelse, int
lineno, int col_offset, PyArena *arena)
@ -2740,6 +2778,30 @@ ast2obj_stmt(void* _o)
goto failed;
Py_DECREF(value);
break;
case AnnAssign_kind:
result = PyType_GenericNew(AnnAssign_type, NULL, NULL);
if (!result) goto failed;
value = ast2obj_expr(o->v.AnnAssign.target);
if (!value) goto failed;
if (_PyObject_SetAttrId(result, &PyId_target, value) == -1)
goto failed;
Py_DECREF(value);
value = ast2obj_expr(o->v.AnnAssign.annotation);
if (!value) goto failed;
if (_PyObject_SetAttrId(result, &PyId_annotation, value) == -1)
goto failed;
Py_DECREF(value);
value = ast2obj_expr(o->v.AnnAssign.value);
if (!value) goto failed;
if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
goto failed;
Py_DECREF(value);
value = ast2obj_int(o->v.AnnAssign.simple);
if (!value) goto failed;
if (_PyObject_SetAttrId(result, &PyId_simple, value) == -1)
goto failed;
Py_DECREF(value);
break;
case For_kind:
result = PyType_GenericNew(For_type, NULL, NULL);
if (!result) goto failed;
@ -4535,6 +4597,64 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
if (*out == NULL) goto failed;
return 0;
}
isinstance = PyObject_IsInstance(obj, (PyObject*)AnnAssign_type);
if (isinstance == -1) {
return 1;
}
if (isinstance) {
expr_ty target;
expr_ty annotation;
expr_ty value;
int simple;
if (_PyObject_HasAttrId(obj, &PyId_target)) {
int res;
tmp = _PyObject_GetAttrId(obj, &PyId_target);
if (tmp == NULL) goto failed;
res = obj2ast_expr(tmp, &target, arena);
if (res != 0) goto failed;
Py_CLEAR(tmp);
} else {
PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from AnnAssign");
return 1;
}
if (_PyObject_HasAttrId(obj, &PyId_annotation)) {
int res;
tmp = _PyObject_GetAttrId(obj, &PyId_annotation);
if (tmp == NULL) goto failed;
res = obj2ast_expr(tmp, &annotation, arena);
if (res != 0) goto failed;
Py_CLEAR(tmp);
} else {
PyErr_SetString(PyExc_TypeError, "required field \"annotation\" missing from AnnAssign");
return 1;
}
if (exists_not_none(obj, &PyId_value)) {
int res;
tmp = _PyObject_GetAttrId(obj, &PyId_value);
if (tmp == NULL) goto failed;
res = obj2ast_expr(tmp, &value, arena);
if (res != 0) goto failed;
Py_CLEAR(tmp);
} else {
value = NULL;
}
if (_PyObject_HasAttrId(obj, &PyId_simple)) {
int res;
tmp = _PyObject_GetAttrId(obj, &PyId_simple);
if (tmp == NULL) goto failed;
res = obj2ast_int(tmp, &simple, arena);
if (res != 0) goto failed;
Py_CLEAR(tmp);
} else {
PyErr_SetString(PyExc_TypeError, "required field \"simple\" missing from AnnAssign");
return 1;
}
*out = AnnAssign(target, annotation, value, simple, lineno, col_offset,
arena);
if (*out == NULL) goto failed;
return 0;
}
isinstance = PyObject_IsInstance(obj, (PyObject*)For_type);
if (isinstance == -1) {
return 1;
@ -7517,6 +7637,8 @@ PyInit__ast(void)
NULL;
if (PyDict_SetItemString(d, "AugAssign", (PyObject*)AugAssign_type) < 0)
return NULL;
if (PyDict_SetItemString(d, "AnnAssign", (PyObject*)AnnAssign_type) < 0)
return NULL;
if (PyDict_SetItemString(d, "For", (PyObject*)For_type) < 0) return NULL;
if (PyDict_SetItemString(d, "AsyncFor", (PyObject*)AsyncFor_type) < 0)
return NULL;

View file

@ -397,6 +397,17 @@ validate_stmt(stmt_ty stmt)
case AugAssign_kind:
return validate_expr(stmt->v.AugAssign.target, Store) &&
validate_expr(stmt->v.AugAssign.value, Load);
case AnnAssign_kind:
if (stmt->v.AnnAssign.target->kind != Name_kind &&
stmt->v.AnnAssign.simple) {
PyErr_SetString(PyExc_TypeError,
"AnnAssign with simple non-Name target");
return 0;
}
return validate_expr(stmt->v.AnnAssign.target, Store) &&
(!stmt->v.AnnAssign.value ||
validate_expr(stmt->v.AnnAssign.value, Load)) &&
validate_expr(stmt->v.AnnAssign.annotation, Load);
case For_kind:
return validate_expr(stmt->v.For.target, Store) &&
validate_expr(stmt->v.For.iter, Load) &&
@ -2847,8 +2858,9 @@ static stmt_ty
ast_for_expr_stmt(struct compiling *c, const node *n)
{
REQ(n, expr_stmt);
/* expr_stmt: testlist_star_expr (augassign (yield_expr|testlist)
| ('=' (yield_expr|testlist))*)
/* expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) |
('=' (yield_expr|testlist_star_expr))*)
annassign: ':' test ['=' test]
testlist_star_expr: (test|star_expr) (',' test|star_expr)* [',']
augassign: '+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^='
| '<<=' | '>>=' | '**=' | '//='
@ -2900,6 +2912,76 @@ ast_for_expr_stmt(struct compiling *c, const node *n)
return AugAssign(expr1, newoperator, expr2, LINENO(n), n->n_col_offset, c->c_arena);
}
else if (TYPE(CHILD(n, 1)) == annassign) {
expr_ty expr1, expr2, expr3;
node *ch = CHILD(n, 0);
node *deep, *ann = CHILD(n, 1);
int simple = 1;
/* we keep track of parens to qualify (x) as expression not name */
deep = ch;
while (NCH(deep) == 1) {
deep = CHILD(deep, 0);
}
if (NCH(deep) > 0 && TYPE(CHILD(deep, 0)) == LPAR) {
simple = 0;
}
expr1 = ast_for_testlist(c, ch);
if (!expr1) {
return NULL;
}
switch (expr1->kind) {
case Name_kind:
if (forbidden_name(c, expr1->v.Name.id, n, 0)) {
return NULL;
}
expr1->v.Name.ctx = Store;
break;
case Attribute_kind:
if (forbidden_name(c, expr1->v.Attribute.attr, n, 1)) {
return NULL;
}
expr1->v.Attribute.ctx = Store;
break;
case Subscript_kind:
expr1->v.Subscript.ctx = Store;
break;
case List_kind:
ast_error(c, ch,
"only single target (not list) can be annotated");
return NULL;
case Tuple_kind:
ast_error(c, ch,
"only single target (not tuple) can be annotated");
return NULL;
default:
ast_error(c, ch,
"illegal target for annotation");
return NULL;
}
if (expr1->kind != Name_kind) {
simple = 0;
}
ch = CHILD(ann, 1);
expr2 = ast_for_expr(c, ch);
if (!expr2) {
return NULL;
}
if (NCH(ann) == 2) {
return AnnAssign(expr1, expr2, NULL, simple,
LINENO(n), n->n_col_offset, c->c_arena);
}
else {
ch = CHILD(ann, 3);
expr3 = ast_for_expr(c, ch);
if (!expr3) {
return NULL;
}
return AnnAssign(expr1, expr2, expr3, simple,
LINENO(n), n->n_col_offset, c->c_arena);
}
}
else {
int i;
asdl_seq *targets;

View file

@ -1873,6 +1873,62 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
DISPATCH();
}
TARGET(STORE_ANNOTATION) {
_Py_IDENTIFIER(__annotations__);
PyObject *ann_dict;
PyObject *ann = POP();
PyObject *name = GETITEM(names, oparg);
int err;
if (f->f_locals == NULL) {
PyErr_Format(PyExc_SystemError,
"no locals found when storing annotation");
Py_DECREF(ann);
goto error;
}
/* first try to get __annotations__ from locals... */
if (PyDict_CheckExact(f->f_locals)) {
ann_dict = _PyDict_GetItemId(f->f_locals,
&PyId___annotations__);
if (ann_dict == NULL) {
PyErr_SetString(PyExc_NameError,
"__annotations__ not found");
Py_DECREF(ann);
goto error;
}
Py_INCREF(ann_dict);
}
else {
PyObject *ann_str = _PyUnicode_FromId(&PyId___annotations__);
if (ann_str == NULL) {
Py_DECREF(ann);
goto error;
}
ann_dict = PyObject_GetItem(f->f_locals, ann_str);
if (ann_dict == NULL) {
if (PyErr_ExceptionMatches(PyExc_KeyError)) {
PyErr_SetString(PyExc_NameError,
"__annotations__ not found");
}
Py_DECREF(ann);
goto error;
}
}
/* ...if succeeded, __annotations__[name] = ann */
if (PyDict_CheckExact(ann_dict)) {
err = PyDict_SetItem(ann_dict, name, ann);
}
else {
err = PyObject_SetItem(ann_dict, name, ann);
}
Py_DECREF(ann_dict);
if (err != 0) {
Py_DECREF(ann);
goto error;
}
Py_DECREF(ann);
DISPATCH();
}
TARGET(DELETE_SUBSCR) {
PyObject *sub = TOP();
PyObject *container = SECOND();
@ -2680,6 +2736,62 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
DISPATCH();
}
TARGET(SETUP_ANNOTATIONS) {
_Py_IDENTIFIER(__annotations__);
int err;
PyObject *ann_dict;
if (f->f_locals == NULL) {
PyErr_Format(PyExc_SystemError,
"no locals found when setting up annotations");
goto error;
}
/* check if __annotations__ in locals()... */
if (PyDict_CheckExact(f->f_locals)) {
ann_dict = _PyDict_GetItemId(f->f_locals,
&PyId___annotations__);
if (ann_dict == NULL) {
/* ...if not, create a new one */
ann_dict = PyDict_New();
if (ann_dict == NULL) {
goto error;
}
err = _PyDict_SetItemId(f->f_locals,
&PyId___annotations__, ann_dict);
Py_DECREF(ann_dict);
if (err != 0) {
goto error;
}
}
}
else {
/* do the same if locals() is not a dict */
PyObject *ann_str = _PyUnicode_FromId(&PyId___annotations__);
if (ann_str == NULL) {
break;
}
ann_dict = PyObject_GetItem(f->f_locals, ann_str);
if (ann_dict == NULL) {
if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
goto error;
}
PyErr_Clear();
ann_dict = PyDict_New();
if (ann_dict == NULL) {
goto error;
}
err = PyObject_SetItem(f->f_locals, ann_str, ann_dict);
Py_DECREF(ann_dict);
if (err != 0) {
goto error;
}
}
else {
Py_DECREF(ann_dict);
}
}
DISPATCH();
}
TARGET(BUILD_CONST_KEY_MAP) {
Py_ssize_t i;
PyObject *map;

View file

@ -179,6 +179,7 @@ static int compiler_visit_stmt(struct compiler *, stmt_ty);
static int compiler_visit_keyword(struct compiler *, keyword_ty);
static int compiler_visit_expr(struct compiler *, expr_ty);
static int compiler_augassign(struct compiler *, stmt_ty);
static int compiler_annassign(struct compiler *, stmt_ty);
static int compiler_visit_slice(struct compiler *, slice_ty,
expr_context_ty);
@ -933,6 +934,8 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
return -1;
case IMPORT_STAR:
return -1;
case SETUP_ANNOTATIONS:
return 0;
case YIELD_VALUE:
return 0;
case YIELD_FROM:
@ -1020,6 +1023,8 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
return -1;
case DELETE_FAST:
return 0;
case STORE_ANNOTATION:
return -1;
case RAISE_VARARGS:
return -oparg;
@ -1358,7 +1363,65 @@ get_const_value(expr_ty e)
}
}
/* Compile a sequence of statements, checking for a docstring. */
/* Search if variable annotations are present statically in a block. */
static int
find_ann(asdl_seq *stmts)
{
int i, j, res = 0;
stmt_ty st;
for (i = 0; i < asdl_seq_LEN(stmts); i++) {
st = (stmt_ty)asdl_seq_GET(stmts, i);
switch (st->kind) {
case AnnAssign_kind:
return 1;
case For_kind:
res = find_ann(st->v.For.body) ||
find_ann(st->v.For.orelse);
break;
case AsyncFor_kind:
res = find_ann(st->v.AsyncFor.body) ||
find_ann(st->v.AsyncFor.orelse);
break;
case While_kind:
res = find_ann(st->v.While.body) ||
find_ann(st->v.While.orelse);
break;
case If_kind:
res = find_ann(st->v.If.body) ||
find_ann(st->v.If.orelse);
break;
case With_kind:
res = find_ann(st->v.With.body);
break;
case AsyncWith_kind:
res = find_ann(st->v.AsyncWith.body);
break;
case Try_kind:
for (j = 0; j < asdl_seq_LEN(st->v.Try.handlers); j++) {
excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET(
st->v.Try.handlers, j);
if (find_ann(handler->v.ExceptHandler.body)) {
return 1;
}
}
res = find_ann(st->v.Try.body) ||
find_ann(st->v.Try.finalbody) ||
find_ann(st->v.Try.orelse);
break;
default:
res = 0;
}
if (res) {
break;
}
}
return res;
}
/* Compile a sequence of statements, checking for a docstring
and for annotations. */
static int
compiler_body(struct compiler *c, asdl_seq *stmts)
@ -1366,6 +1429,19 @@ compiler_body(struct compiler *c, asdl_seq *stmts)
int i = 0;
stmt_ty st;
/* Set current line number to the line number of first statement.
This way line number for SETUP_ANNOTATIONS will always
coincide with the line number of first "real" statement in module.
If body is empy, then lineno will be set later in assemble. */
if (c->u->u_scope_type == COMPILER_SCOPE_MODULE &&
!c->u->u_lineno && asdl_seq_LEN(stmts)) {
st = (stmt_ty)asdl_seq_GET(stmts, 0);
c->u->u_lineno = st->lineno;
}
/* Every annotated class and module should have __annotations__. */
if (find_ann(stmts)) {
ADDOP(c, SETUP_ANNOTATIONS);
}
if (!asdl_seq_LEN(stmts))
return 1;
st = (stmt_ty)asdl_seq_GET(stmts, 0);
@ -1403,6 +1479,9 @@ compiler_mod(struct compiler *c, mod_ty mod)
}
break;
case Interactive_kind:
if (find_ann(mod->v.Interactive.body)) {
ADDOP(c, SETUP_ANNOTATIONS);
}
c->c_interactive = 1;
VISIT_SEQ_IN_SCOPE(c, stmt,
mod->v.Interactive.body);
@ -2743,6 +2822,8 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
break;
case AugAssign_kind:
return compiler_augassign(c, s);
case AnnAssign_kind:
return compiler_annassign(c, s);
case For_kind:
return compiler_for(c, s);
case While_kind:
@ -4222,6 +4303,138 @@ compiler_augassign(struct compiler *c, stmt_ty s)
return 1;
}
static int
check_ann_expr(struct compiler *c, expr_ty e)
{
VISIT(c, expr, e);
ADDOP(c, POP_TOP);
return 1;
}
static int
check_annotation(struct compiler *c, stmt_ty s)
{
/* Annotations are only evaluated in a module or class. */
if (c->u->u_scope_type == COMPILER_SCOPE_MODULE ||
c->u->u_scope_type == COMPILER_SCOPE_CLASS) {
return check_ann_expr(c, s->v.AnnAssign.annotation);
}
return 1;
}
static int
check_ann_slice(struct compiler *c, slice_ty sl)
{
switch(sl->kind) {
case Index_kind:
return check_ann_expr(c, sl->v.Index.value);
case Slice_kind:
if (sl->v.Slice.lower && !check_ann_expr(c, sl->v.Slice.lower)) {
return 0;
}
if (sl->v.Slice.upper && !check_ann_expr(c, sl->v.Slice.upper)) {
return 0;
}
if (sl->v.Slice.step && !check_ann_expr(c, sl->v.Slice.step)) {
return 0;
}
break;
default:
PyErr_SetString(PyExc_SystemError,
"unexpected slice kind");
return 0;
}
return 1;
}
static int
check_ann_subscr(struct compiler *c, slice_ty sl)
{
/* We check that everything in a subscript is defined at runtime. */
Py_ssize_t i, n;
switch (sl->kind) {
case Index_kind:
case Slice_kind:
if (!check_ann_slice(c, sl)) {
return 0;
}
break;
case ExtSlice_kind:
n = asdl_seq_LEN(sl->v.ExtSlice.dims);
for (i = 0; i < n; i++) {
slice_ty subsl = (slice_ty)asdl_seq_GET(sl->v.ExtSlice.dims, i);
switch (subsl->kind) {
case Index_kind:
case Slice_kind:
if (!check_ann_slice(c, subsl)) {
return 0;
}
break;
case ExtSlice_kind:
default:
PyErr_SetString(PyExc_SystemError,
"extended slice invalid in nested slice");
return 0;
}
}
break;
default:
PyErr_Format(PyExc_SystemError,
"invalid subscript kind %d", sl->kind);
return 0;
}
return 1;
}
static int
compiler_annassign(struct compiler *c, stmt_ty s)
{
expr_ty targ = s->v.AnnAssign.target;
assert(s->kind == AnnAssign_kind);
/* We perform the actual assignment first. */
if (s->v.AnnAssign.value) {
VISIT(c, expr, s->v.AnnAssign.value);
VISIT(c, expr, targ);
}
switch (targ->kind) {
case Name_kind:
/* If we have a simple name in a module or class, store annotation. */
if (s->v.AnnAssign.simple &&
(c->u->u_scope_type == COMPILER_SCOPE_MODULE ||
c->u->u_scope_type == COMPILER_SCOPE_CLASS)) {
VISIT(c, expr, s->v.AnnAssign.annotation);
ADDOP_O(c, STORE_ANNOTATION, targ->v.Name.id, names)
}
break;
case Attribute_kind:
if (!s->v.AnnAssign.value &&
!check_ann_expr(c, targ->v.Attribute.value)) {
return 0;
}
break;
case Subscript_kind:
if (!s->v.AnnAssign.value &&
(!check_ann_expr(c, targ->v.Subscript.value) ||
!check_ann_subscr(c, targ->v.Subscript.slice))) {
return 0;
}
break;
default:
PyErr_Format(PyExc_SystemError,
"invalid node type (%d) for annotated assignment",
targ->kind);
return 0;
}
/* Annotation is evaluated last. */
if (!s->v.AnnAssign.simple && !check_annotation(c, s)) {
return 0;
}
return 1;
}
static int
compiler_push_fblock(struct compiler *c, enum fblocktype t, basicblock *b)
{

File diff suppressed because it is too large Load diff

View file

@ -242,7 +242,7 @@ const unsigned char _Py_M__importlib_external[] = {
101,95,97,116,111,109,105,99,106,0,0,0,115,26,0,0,
0,0,5,16,1,6,1,26,1,2,3,14,1,20,1,16,
1,14,1,2,1,14,1,14,1,6,1,114,58,0,0,0,
105,45,13,0,0,233,2,0,0,0,114,15,0,0,0,115,
105,47,13,0,0,233,2,0,0,0,114,15,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,121,99,78,41,1,218,12,111,112,116,105,109,105,122,
@ -346,7 +346,7 @@ const unsigned char _Py_M__importlib_external[] = {
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,6,0,0,
0,218,17,99,97,99,104,101,95,102,114,111,109,95,115,111,
117,114,99,101,1,1,0,0,115,48,0,0,0,0,18,8,
117,114,99,101,3,1,0,0,115,48,0,0,0,0,18,8,
1,6,1,6,1,8,1,4,1,8,1,12,1,10,1,12,
1,16,1,8,1,8,1,8,1,24,1,8,1,12,1,6,
2,8,1,8,1,8,1,8,1,14,1,14,1,114,83,0,
@ -420,7 +420,7 @@ const unsigned char _Py_M__importlib_external[] = {
112,116,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,6,0,0,0,218,17,115,111,117,114,99,101,95,102,
114,111,109,95,99,97,99,104,101,46,1,0,0,115,46,0,
114,111,109,95,99,97,99,104,101,48,1,0,0,115,46,0,
0,0,0,9,12,1,8,1,10,1,12,1,12,1,8,1,
6,1,10,1,10,1,8,1,6,1,10,1,8,1,16,1,
10,1,6,1,8,1,16,1,8,1,6,1,8,1,14,1,
@ -456,7 +456,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,6,0,0,0,
218,15,95,103,101,116,95,115,111,117,114,99,101,102,105,108,
101,80,1,0,0,115,20,0,0,0,0,7,12,1,4,1,
101,82,1,0,0,115,20,0,0,0,0,7,12,1,4,1,
16,1,26,1,4,1,2,1,12,1,18,1,18,1,114,95,
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,74,0,0,0,124,0,106,
@ -469,7 +469,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,114,83,0,0,0,114,70,0,0,0,114,78,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,6,0,0,0,218,11,95,103,
101,116,95,99,97,99,104,101,100,99,1,0,0,115,16,0,
101,116,95,99,97,99,104,101,100,101,1,0,0,115,16,0,
0,0,0,1,14,1,2,1,8,1,14,1,8,1,14,1,
6,2,114,99,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,52,0,0,
@ -483,7 +483,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,233,128,0,0,0,41,3,114,41,0,0,0,114,43,0,
0,0,114,42,0,0,0,41,2,114,37,0,0,0,114,44,
0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,
0,0,218,10,95,99,97,108,99,95,109,111,100,101,111,1,
0,0,218,10,95,99,97,108,99,95,109,111,100,101,113,1,
0,0,115,12,0,0,0,0,2,2,1,14,1,14,1,10,
3,8,1,114,101,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,68,0,
@ -521,7 +521,7 @@ const unsigned char _Py_M__importlib_external[] = {
115,90,6,107,119,97,114,103,115,41,1,218,6,109,101,116,
104,111,100,114,4,0,0,0,114,6,0,0,0,218,19,95,
99,104,101,99,107,95,110,97,109,101,95,119,114,97,112,112,
101,114,131,1,0,0,115,12,0,0,0,0,1,8,1,8,
101,114,133,1,0,0,115,12,0,0,0,0,1,8,1,8,
1,10,1,4,1,20,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,101,
@ -541,7 +541,7 @@ const unsigned char _Py_M__importlib_external[] = {
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,55,0,0,0,114,4,0,0,0,114,4,0,0,0,
114,6,0,0,0,218,5,95,119,114,97,112,142,1,0,0,
114,6,0,0,0,218,5,95,119,114,97,112,144,1,0,0,
115,8,0,0,0,0,1,10,1,10,1,22,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,1,78,41,3,218,10,
@ -549,7 +549,7 @@ const unsigned char _Py_M__importlib_external[] = {
9,78,97,109,101,69,114,114,111,114,41,3,114,106,0,0,
0,114,107,0,0,0,114,117,0,0,0,114,4,0,0,0,
41,1,114,106,0,0,0,114,6,0,0,0,218,11,95,99,
104,101,99,107,95,110,97,109,101,123,1,0,0,115,14,0,
104,101,99,107,95,110,97,109,101,125,1,0,0,115,14,0,
0,0,0,8,14,7,2,1,10,1,14,2,14,5,10,1,
114,120,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,60,0,0,0,124,
@ -577,7 +577,7 @@ const unsigned char _Py_M__importlib_external[] = {
101,218,6,108,111,97,100,101,114,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,6,0,0,0,218,17,95,102,105,110,100,95,109,
111,100,117,108,101,95,115,104,105,109,151,1,0,0,115,10,
111,100,117,108,101,95,115,104,105,109,153,1,0,0,115,10,
0,0,0,0,10,14,1,16,1,4,1,22,1,114,127,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,128,1,0,0,105,0,125,4,
@ -657,7 +657,7 @@ const unsigned char _Py_M__importlib_external[] = {
111,117,114,99,101,95,115,105,122,101,114,4,0,0,0,114,
4,0,0,0,114,6,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,168,1,0,0,115,76,0,0,0,0,11,4,
97,100,101,114,170,1,0,0,115,76,0,0,0,0,11,4,
1,8,1,10,3,4,1,8,1,8,1,12,1,12,1,12,
1,8,1,12,1,12,1,12,1,12,1,10,1,12,1,10,
1,12,1,10,1,12,1,8,1,10,1,2,1,16,1,14,
@ -686,7 +686,7 @@ const unsigned char _Py_M__importlib_external[] = {
5,114,56,0,0,0,114,102,0,0,0,114,93,0,0,0,
114,94,0,0,0,218,4,99,111,100,101,114,4,0,0,0,
114,4,0,0,0,114,6,0,0,0,218,17,95,99,111,109,
112,105,108,101,95,98,121,116,101,99,111,100,101,223,1,0,
112,105,108,101,95,98,121,116,101,99,111,100,101,225,1,0,
0,115,16,0,0,0,0,2,10,1,10,1,12,1,8,1,
12,1,6,2,12,1,114,145,0,0,0,114,62,0,0,0,
99,3,0,0,0,0,0,0,0,4,0,0,0,3,0,0,
@ -705,7 +705,7 @@ const unsigned char _Py_M__importlib_external[] = {
115,41,4,114,144,0,0,0,114,130,0,0,0,114,138,0,
0,0,114,56,0,0,0,114,4,0,0,0,114,4,0,0,
0,114,6,0,0,0,218,17,95,99,111,100,101,95,116,111,
95,98,121,116,101,99,111,100,101,235,1,0,0,115,10,0,
95,98,121,116,101,99,111,100,101,237,1,0,0,115,10,0,
0,0,0,3,8,1,14,1,14,1,16,1,114,148,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,62,0,0,0,100,1,100,2,108,
@ -732,7 +732,7 @@ const unsigned char _Py_M__importlib_external[] = {
101,218,8,101,110,99,111,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,6,0,0,0,218,13,100,101,99,
111,100,101,95,115,111,117,114,99,101,245,1,0,0,115,10,
111,100,101,95,115,111,117,114,99,101,247,1,0,0,115,10,
0,0,0,0,5,8,1,12,1,10,1,12,1,114,153,0,
0,0,41,2,114,124,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,
@ -794,7 +794,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,90,7,100,105,114,110,97,109,101,114,4,0,0,0,
114,4,0,0,0,114,6,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,6,2,0,0,115,62,0,0,0,0,12,8,4,
105,111,110,8,2,0,0,115,62,0,0,0,0,12,8,4,
4,1,10,2,2,1,14,1,14,1,8,2,10,8,18,1,
6,3,8,1,16,1,14,1,10,1,6,1,6,2,4,3,
8,2,10,1,2,1,14,1,14,1,6,2,4,1,8,2,
@ -830,7 +830,7 @@ const unsigned char _Py_M__importlib_external[] = {
72,75,69,89,95,76,79,67,65,76,95,77,65,67,72,73,
78,69,41,2,218,3,99,108,115,114,5,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,6,0,0,0,218,14,95,
111,112,101,110,95,114,101,103,105,115,116,114,121,86,2,0,
111,112,101,110,95,114,101,103,105,115,116,114,121,88,2,0,
0,115,8,0,0,0,0,2,2,1,14,1,14,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,
@ -856,7 +856,7 @@ const unsigned char _Py_M__importlib_external[] = {
114,121,95,107,101,121,114,5,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,6,0,0,0,218,16,95,115,101,97,
114,99,104,95,114,101,103,105,115,116,114,121,93,2,0,0,
114,99,104,95,114,101,103,105,115,116,114,121,95,2,0,0,
115,22,0,0,0,0,2,6,1,8,2,6,1,10,1,22,
1,2,1,12,1,26,1,14,1,6,1,122,38,87,105,110,
100,111,119,115,82,101,103,105,115,116,114,121,70,105,110,100,
@ -878,7 +878,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,0,114,37,0,0,0,218,6,116,97,114,103,101,116,
114,174,0,0,0,114,124,0,0,0,114,164,0,0,0,114,
162,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,
0,0,0,218,9,102,105,110,100,95,115,112,101,99,108,2,
0,0,0,218,9,102,105,110,100,95,115,112,101,99,110,2,
0,0,115,26,0,0,0,0,2,10,1,8,1,4,1,2,
1,12,1,14,1,6,1,16,1,14,1,6,1,10,1,8,
1,122,31,87,105,110,100,111,119,115,82,101,103,105,115,116,
@ -897,7 +897,7 @@ const unsigned char _Py_M__importlib_external[] = {
78,41,2,114,178,0,0,0,114,124,0,0,0,41,4,114,
168,0,0,0,114,123,0,0,0,114,37,0,0,0,114,162,
0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,
0,0,218,11,102,105,110,100,95,109,111,100,117,108,101,124,
0,0,218,11,102,105,110,100,95,109,111,100,117,108,101,126,
2,0,0,115,8,0,0,0,0,7,12,1,8,1,8,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,
@ -907,7 +907,7 @@ const unsigned char _Py_M__importlib_external[] = {
11,99,108,97,115,115,109,101,116,104,111,100,114,169,0,0,
0,114,175,0,0,0,114,178,0,0,0,114,179,0,0,0,
114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
6,0,0,0,114,166,0,0,0,74,2,0,0,115,20,0,
6,0,0,0,114,166,0,0,0,76,2,0,0,115,20,0,
0,0,8,2,4,3,4,3,4,2,4,2,12,7,12,15,
2,1,12,15,2,1,114,166,0,0,0,99,0,0,0,0,
0,0,0,0,0,0,0,0,2,0,0,0,64,0,0,0,
@ -942,7 +942,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,114,123,0,0,0,114,98,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,
6,0,0,0,114,157,0,0,0,143,2,0,0,115,8,0,
6,0,0,0,114,157,0,0,0,145,2,0,0,115,8,0,
0,0,0,3,18,1,16,1,14,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,
@ -953,7 +953,7 @@ const unsigned char _Py_M__importlib_external[] = {
78,114,4,0,0,0,41,2,114,104,0,0,0,114,162,0,
0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,
0,218,13,99,114,101,97,116,101,95,109,111,100,117,108,101,
151,2,0,0,115,0,0,0,0,122,27,95,76,111,97,100,
153,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,4,0,0,0,67,0,0,0,115,56,0,0,0,
@ -972,7 +972,7 @@ const unsigned char _Py_M__importlib_external[] = {
100,218,4,101,120,101,99,114,115,0,0,0,41,3,114,104,
0,0,0,218,6,109,111,100,117,108,101,114,144,0,0,0,
114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,218,
11,101,120,101,99,95,109,111,100,117,108,101,154,2,0,0,
11,101,120,101,99,95,109,111,100,117,108,101,156,2,0,0,
115,10,0,0,0,0,2,12,1,8,1,6,1,10,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,
@ -984,13 +984,13 @@ const unsigned char _Py_M__importlib_external[] = {
117,108,101,95,115,104,105,109,41,2,114,104,0,0,0,114,
123,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,
0,0,0,218,11,108,111,97,100,95,109,111,100,117,108,101,
162,2,0,0,115,2,0,0,0,0,2,122,25,95,76,111,
164,2,0,0,115,2,0,0,0,0,2,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,109,0,0,0,114,108,
0,0,0,114,110,0,0,0,114,111,0,0,0,114,157,0,
0,0,114,183,0,0,0,114,188,0,0,0,114,190,0,0,
0,114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,
114,6,0,0,0,114,181,0,0,0,138,2,0,0,115,10,
114,6,0,0,0,114,181,0,0,0,140,2,0,0,115,10,
0,0,0,8,3,4,2,8,8,8,3,8,8,114,181,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,74,0,0,0,101,0,90,1,
@ -1016,7 +1016,7 @@ const unsigned char _Py_M__importlib_external[] = {
1,218,7,73,79,69,114,114,111,114,41,2,114,104,0,0,
0,114,37,0,0,0,114,4,0,0,0,114,4,0,0,0,
114,6,0,0,0,218,10,112,97,116,104,95,109,116,105,109,
101,169,2,0,0,115,2,0,0,0,0,6,122,23,83,111,
101,171,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,14,0,0,0,100,
@ -1051,7 +1051,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,0,41,1,114,193,0,0,0,41,2,114,104,0,0,
0,114,37,0,0,0,114,4,0,0,0,114,4,0,0,0,
114,6,0,0,0,218,10,112,97,116,104,95,115,116,97,116,
115,177,2,0,0,115,2,0,0,0,0,11,122,23,83,111,
115,179,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,12,0,0,0,124,
@ -1074,7 +1074,7 @@ const unsigned char _Py_M__importlib_external[] = {
4,114,104,0,0,0,114,94,0,0,0,90,10,99,97,99,
104,101,95,112,97,116,104,114,56,0,0,0,114,4,0,0,
0,114,4,0,0,0,114,6,0,0,0,218,15,95,99,97,
99,104,101,95,98,121,116,101,99,111,100,101,190,2,0,0,
99,104,101,95,98,121,116,101,99,111,100,101,192,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,
@ -1091,7 +1091,7 @@ const unsigned char _Py_M__importlib_external[] = {
108,101,115,46,10,32,32,32,32,32,32,32,32,78,114,4,
0,0,0,41,3,114,104,0,0,0,114,37,0,0,0,114,
56,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,
0,0,0,114,195,0,0,0,200,2,0,0,115,0,0,0,
0,0,0,114,195,0,0,0,202,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,84,0,
@ -1112,7 +1112,7 @@ const unsigned char _Py_M__importlib_external[] = {
104,0,0,0,114,123,0,0,0,114,37,0,0,0,114,151,
0,0,0,218,3,101,120,99,114,4,0,0,0,114,4,0,
0,0,114,6,0,0,0,218,10,103,101,116,95,115,111,117,
114,99,101,207,2,0,0,115,14,0,0,0,0,2,10,1,
114,99,101,209,2,0,0,115,14,0,0,0,0,2,10,1,
2,1,14,1,16,1,6,1,28,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,114,31,0,0,0,41,1,218,9,95,111,112,116,
@ -1134,7 +1134,7 @@ const unsigned char _Py_M__importlib_external[] = {
104,0,0,0,114,56,0,0,0,114,37,0,0,0,114,200,
0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,
0,0,218,14,115,111,117,114,99,101,95,116,111,95,99,111,
100,101,217,2,0,0,115,4,0,0,0,0,5,14,1,122,
100,101,219,2,0,0,115,4,0,0,0,0,5,14,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,0,67,0,0,
@ -1190,7 +1190,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,218,2,115,116,114,56,0,0,0,218,10,98,121,116,
101,115,95,100,97,116,97,114,151,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,6,0,0,0,114,184,0,0,0,225,2,0,
0,0,0,114,6,0,0,0,114,184,0,0,0,227,2,0,
0,115,78,0,0,0,0,7,10,1,4,1,2,1,12,1,
14,1,10,2,2,1,14,1,14,1,6,2,12,1,2,1,
14,1,14,1,6,2,2,1,6,1,8,1,12,1,18,1,
@ -1202,7 +1202,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,114,193,0,0,0,114,194,0,0,0,114,196,0,0,
0,114,195,0,0,0,114,199,0,0,0,114,203,0,0,0,
114,184,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
4,0,0,0,114,6,0,0,0,114,191,0,0,0,167,2,
4,0,0,0,114,6,0,0,0,114,191,0,0,0,169,2,
0,0,115,14,0,0,0,8,2,8,8,8,13,8,10,8,
7,8,10,14,8,114,191,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,
@ -1229,7 +1229,7 @@ const unsigned char _Py_M__importlib_external[] = {
78,41,2,114,102,0,0,0,114,37,0,0,0,41,3,114,
104,0,0,0,114,123,0,0,0,114,37,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,6,0,0,0,114,182,0,
0,0,26,3,0,0,115,4,0,0,0,0,3,6,1,122,
0,0,28,3,0,0,115,4,0,0,0,0,3,6,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,0,0,67,0,0,0,115,24,0,0,0,124,0,
@ -1238,7 +1238,7 @@ const unsigned char _Py_M__importlib_external[] = {
108,97,115,115,95,95,114,115,0,0,0,41,2,114,104,0,
0,0,218,5,111,116,104,101,114,114,4,0,0,0,114,4,
0,0,0,114,6,0,0,0,218,6,95,95,101,113,95,95,
32,3,0,0,115,4,0,0,0,0,1,12,1,122,17,70,
34,3,0,0,115,4,0,0,0,0,1,12,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,20,0,0,0,116,0,124,0,106,1,
@ -1246,7 +1246,7 @@ const unsigned char _Py_M__importlib_external[] = {
78,41,3,218,4,104,97,115,104,114,102,0,0,0,114,37,
0,0,0,41,1,114,104,0,0,0,114,4,0,0,0,114,
4,0,0,0,114,6,0,0,0,218,8,95,95,104,97,115,
104,95,95,36,3,0,0,115,2,0,0,0,0,1,122,19,
104,95,95,38,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,16,0,0,0,116,0,116,
@ -1260,7 +1260,7 @@ const unsigned char _Py_M__importlib_external[] = {
32,32,32,32,32,41,3,218,5,115,117,112,101,114,114,207,
0,0,0,114,190,0,0,0,41,2,114,104,0,0,0,114,
123,0,0,0,41,1,114,208,0,0,0,114,4,0,0,0,
114,6,0,0,0,114,190,0,0,0,39,3,0,0,115,2,
114,6,0,0,0,114,190,0,0,0,41,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,0,67,0,
@ -1271,7 +1271,7 @@ const unsigned char _Py_M__importlib_external[] = {
116,104,101,32,102,105,110,100,101,114,46,41,1,114,37,0,
0,0,41,2,114,104,0,0,0,114,123,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,6,0,0,0,114,155,0,
0,0,51,3,0,0,115,2,0,0,0,0,3,122,23,70,
0,0,53,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,32,0,0,0,
@ -1283,14 +1283,14 @@ const unsigned char _Py_M__importlib_external[] = {
3,114,52,0,0,0,114,53,0,0,0,90,4,114,101,97,
100,41,3,114,104,0,0,0,114,37,0,0,0,114,57,0,
0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,
0,114,197,0,0,0,56,3,0,0,115,4,0,0,0,0,
0,114,197,0,0,0,58,3,0,0,115,4,0,0,0,0,
2,14,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,109,0,0,0,114,
108,0,0,0,114,110,0,0,0,114,111,0,0,0,114,182,
0,0,0,114,210,0,0,0,114,212,0,0,0,114,120,0,
0,0,114,190,0,0,0,114,155,0,0,0,114,197,0,0,
0,114,4,0,0,0,114,4,0,0,0,41,1,114,208,0,
0,0,114,6,0,0,0,114,207,0,0,0,21,3,0,0,
0,0,114,6,0,0,0,114,207,0,0,0,23,3,0,0,
115,14,0,0,0,8,3,4,2,8,6,8,4,8,3,16,
12,12,5,114,207,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,46,0,
@ -1312,7 +1312,7 @@ const unsigned char _Py_M__importlib_external[] = {
8,115,116,95,109,116,105,109,101,90,7,115,116,95,115,105,
122,101,41,3,114,104,0,0,0,114,37,0,0,0,114,205,
0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,
0,0,114,194,0,0,0,66,3,0,0,115,4,0,0,0,
0,0,114,194,0,0,0,68,3,0,0,115,4,0,0,0,
0,2,8,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,0,5,0,0,0,5,0,
@ -1322,7 +1322,7 @@ const unsigned char _Py_M__importlib_external[] = {
2,114,101,0,0,0,114,195,0,0,0,41,5,114,104,0,
0,0,114,94,0,0,0,114,93,0,0,0,114,56,0,0,
0,114,44,0,0,0,114,4,0,0,0,114,4,0,0,0,
114,6,0,0,0,114,196,0,0,0,71,3,0,0,115,4,
114,6,0,0,0,114,196,0,0,0,73,3,0,0,115,4,
0,0,0,0,2,8,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,105,182,1,0,0,41,1,
@ -1357,7 +1357,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,114,217,0,0,0,218,6,112,97,114,101,110,116,114,98,
0,0,0,114,29,0,0,0,114,25,0,0,0,114,198,0,
0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,
0,114,195,0,0,0,76,3,0,0,115,42,0,0,0,0,
0,114,195,0,0,0,78,3,0,0,115,42,0,0,0,0,
2,12,1,4,2,16,1,12,1,14,2,14,1,10,1,2,
1,14,1,14,2,6,1,16,3,6,1,8,1,20,1,2,
1,12,1,16,1,16,2,8,1,122,25,83,111,117,114,99,
@ -1366,7 +1366,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,114,110,0,0,0,114,111,0,0,0,114,194,0,0,0,
114,196,0,0,0,114,195,0,0,0,114,4,0,0,0,114,
4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,215,
0,0,0,62,3,0,0,115,8,0,0,0,8,2,4,2,
0,0,0,64,3,0,0,115,8,0,0,0,8,2,4,2,
8,5,8,5,114,215,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,32,
0,0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,
@ -1386,7 +1386,7 @@ const unsigned char _Py_M__importlib_external[] = {
145,0,0,0,41,5,114,104,0,0,0,114,123,0,0,0,
114,37,0,0,0,114,56,0,0,0,114,206,0,0,0,114,
4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,184,
0,0,0,111,3,0,0,115,8,0,0,0,0,1,10,1,
0,0,0,113,3,0,0,115,8,0,0,0,0,1,10,1,
10,1,18,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,0,
@ -1396,13 +1396,13 @@ const unsigned char _Py_M__importlib_external[] = {
115,111,117,114,99,101,32,99,111,100,101,46,78,114,4,0,
0,0,41,2,114,104,0,0,0,114,123,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,6,0,0,0,114,199,0,
0,0,117,3,0,0,115,2,0,0,0,0,2,122,31,83,
0,0,119,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,109,0,0,0,114,108,0,0,0,114,110,0,0,0,
114,111,0,0,0,114,184,0,0,0,114,199,0,0,0,114,
4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,
0,0,0,114,220,0,0,0,107,3,0,0,115,6,0,0,
0,0,0,114,220,0,0,0,109,3,0,0,115,6,0,0,
0,8,2,4,2,8,6,114,220,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,92,0,0,0,101,0,90,1,100,0,90,2,100,1,
@ -1424,7 +1424,7 @@ const unsigned char _Py_M__importlib_external[] = {
83,0,41,1,78,41,2,114,102,0,0,0,114,37,0,0,
0,41,3,114,104,0,0,0,114,102,0,0,0,114,37,0,
0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,
0,114,182,0,0,0,134,3,0,0,115,4,0,0,0,0,
0,114,182,0,0,0,136,3,0,0,115,4,0,0,0,0,
1,6,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,0,2,0,
@ -1433,7 +1433,7 @@ const unsigned char _Py_M__importlib_external[] = {
2,83,0,41,1,78,41,2,114,208,0,0,0,114,115,0,
0,0,41,2,114,104,0,0,0,114,209,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,6,0,0,0,114,210,0,
0,0,138,3,0,0,115,4,0,0,0,0,1,12,1,122,
0,0,140,3,0,0,115,4,0,0,0,0,1,12,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,0,1,0,0,0,3,0,0,0,67,0,0,0,
@ -1441,7 +1441,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,106,2,131,1,65,0,83,0,41,1,78,41,3,114,211,
0,0,0,114,102,0,0,0,114,37,0,0,0,41,1,114,
104,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,
0,0,0,114,212,0,0,0,142,3,0,0,115,2,0,0,
0,0,0,114,212,0,0,0,144,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,0,4,0,
@ -1458,7 +1458,7 @@ const unsigned char _Py_M__importlib_external[] = {
105,99,114,133,0,0,0,114,102,0,0,0,114,37,0,0,
0,41,3,114,104,0,0,0,114,162,0,0,0,114,187,0,
0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,
0,114,183,0,0,0,145,3,0,0,115,10,0,0,0,0,
0,114,183,0,0,0,147,3,0,0,115,10,0,0,0,0,
2,4,1,10,1,6,1,12,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,
@ -1475,7 +1475,7 @@ const unsigned char _Py_M__importlib_external[] = {
121,110,97,109,105,99,114,133,0,0,0,114,102,0,0,0,
114,37,0,0,0,41,2,114,104,0,0,0,114,187,0,0,
0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,
114,188,0,0,0,153,3,0,0,115,6,0,0,0,0,2,
114,188,0,0,0,155,3,0,0,115,6,0,0,0,0,2,
14,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,0,0,0,0,0,2,0,
@ -1492,7 +1492,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,41,2,114,182,0,0,0,78,114,4,0,0,0,41,2,
114,24,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,
6,0,0,0,250,9,60,103,101,110,101,120,112,114,62,162,
6,0,0,0,250,9,60,103,101,110,101,120,112,114,62,164,
3,0,0,115,2,0,0,0,4,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,
@ -1501,7 +1501,7 @@ const unsigned char _Py_M__importlib_external[] = {
69,88,84,69,78,83,73,79,78,95,83,85,70,70,73,88,
69,83,41,2,114,104,0,0,0,114,123,0,0,0,114,4,
0,0,0,41,1,114,223,0,0,0,114,6,0,0,0,114,
157,0,0,0,159,3,0,0,115,6,0,0,0,0,2,14,
157,0,0,0,161,3,0,0,115,6,0,0,0,0,2,14,
1,12,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,0,0,0,0,2,0,0,0,
@ -1512,7 +1512,7 @@ const unsigned char _Py_M__importlib_external[] = {
114,101,97,116,101,32,97,32,99,111,100,101,32,111,98,106,
101,99,116,46,78,114,4,0,0,0,41,2,114,104,0,0,
0,114,123,0,0,0,114,4,0,0,0,114,4,0,0,0,
114,6,0,0,0,114,184,0,0,0,165,3,0,0,115,2,
114,6,0,0,0,114,184,0,0,0,167,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,
@ -1523,7 +1523,7 @@ const unsigned char _Py_M__importlib_external[] = {
117,114,99,101,32,99,111,100,101,46,78,114,4,0,0,0,
41,2,114,104,0,0,0,114,123,0,0,0,114,4,0,0,
0,114,4,0,0,0,114,6,0,0,0,114,199,0,0,0,
169,3,0,0,115,2,0,0,0,0,2,122,30,69,120,116,
171,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,1,0,0,0,67,0,0,0,
@ -1534,7 +1534,7 @@ const unsigned char _Py_M__importlib_external[] = {
101,32,102,105,110,100,101,114,46,41,1,114,37,0,0,0,
41,2,114,104,0,0,0,114,123,0,0,0,114,4,0,0,
0,114,4,0,0,0,114,6,0,0,0,114,155,0,0,0,
173,3,0,0,115,2,0,0,0,0,3,122,32,69,120,116,
175,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,109,0,0,0,114,108,0,0,0,114,110,0,0,0,114,
@ -1542,7 +1542,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,0,114,183,0,0,0,114,188,0,0,0,114,157,0,
0,0,114,184,0,0,0,114,199,0,0,0,114,120,0,0,
0,114,155,0,0,0,114,4,0,0,0,114,4,0,0,0,
114,4,0,0,0,114,6,0,0,0,114,221,0,0,0,126,
114,4,0,0,0,114,6,0,0,0,114,221,0,0,0,128,
3,0,0,115,20,0,0,0,8,6,4,2,8,4,8,4,
8,3,8,8,8,6,8,6,8,4,8,4,114,221,0,0,
0,99,0,0,0,0,0,0,0,0,0,0,0,0,2,0,
@ -1584,7 +1584,7 @@ const unsigned char _Py_M__importlib_external[] = {
114,41,4,114,104,0,0,0,114,102,0,0,0,114,37,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,6,0,0,0,114,182,
0,0,0,186,3,0,0,115,8,0,0,0,0,1,6,1,
0,0,0,188,3,0,0,115,8,0,0,0,0,1,6,1,
6,1,14,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,0,4,0,0,0,3,0,0,0,67,0,
@ -1602,7 +1602,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,218,3,100,111,116,90,2,109,101,114,4,0,0,0,
114,4,0,0,0,114,6,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,192,3,0,0,115,8,0,0,0,0,2,18,1,
109,101,115,194,3,0,0,115,8,0,0,0,0,2,18,1,
8,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,95,110,97,109,101,115,99,1,0,0,
@ -1614,7 +1614,7 @@ const unsigned char _Py_M__importlib_external[] = {
3,114,104,0,0,0,90,18,112,97,114,101,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,6,0,0,0,114,230,0,0,0,202,3,
4,0,0,0,114,6,0,0,0,114,230,0,0,0,204,3,
0,0,115,4,0,0,0,0,1,12,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,
@ -1630,7 +1630,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,0,41,3,114,104,0,0,0,90,11,112,97,114,101,
110,116,95,112,97,116,104,114,162,0,0,0,114,4,0,0,
0,114,4,0,0,0,114,6,0,0,0,218,12,95,114,101,
99,97,108,99,117,108,97,116,101,206,3,0,0,115,16,0,
99,97,108,99,117,108,97,116,101,208,3,0,0,115,16,0,
0,0,0,2,12,1,10,1,14,3,18,1,6,1,8,1,
6,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,
@ -1639,7 +1639,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,131,1,83,0,41,1,78,41,2,218,4,105,116,101,114,
114,237,0,0,0,41,1,114,104,0,0,0,114,4,0,0,
0,114,4,0,0,0,114,6,0,0,0,218,8,95,95,105,
116,101,114,95,95,219,3,0,0,115,2,0,0,0,0,1,
116,101,114,95,95,221,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,3,0,0,0,0,0,
0,0,3,0,0,0,3,0,0,0,67,0,0,0,115,14,
@ -1647,7 +1647,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,41,1,78,41,1,114,229,0,0,0,41,3,114,104,0,
0,0,218,5,105,110,100,101,120,114,37,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,6,0,0,0,218,11,95,
95,115,101,116,105,116,101,109,95,95,222,3,0,0,115,2,
95,115,101,116,105,116,101,109,95,95,224,3,0,0,115,2,
0,0,0,0,1,122,26,95,78,97,109,101,115,112,97,99,
101,80,97,116,104,46,95,95,115,101,116,105,116,101,109,95,
95,99,1,0,0,0,0,0,0,0,1,0,0,0,2,0,
@ -1655,7 +1655,7 @@ const unsigned char _Py_M__importlib_external[] = {
1,131,0,131,1,83,0,41,1,78,41,2,114,33,0,0,
0,114,237,0,0,0,41,1,114,104,0,0,0,114,4,0,
0,0,114,4,0,0,0,114,6,0,0,0,218,7,95,95,
108,101,110,95,95,225,3,0,0,115,2,0,0,0,0,1,
108,101,110,95,95,227,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,0,0,0,67,0,0,0,115,12,0,
@ -1664,7 +1664,7 @@ const unsigned char _Py_M__importlib_external[] = {
104,40,123,33,114,125,41,41,2,114,50,0,0,0,114,229,
0,0,0,41,1,114,104,0,0,0,114,4,0,0,0,114,
4,0,0,0,114,6,0,0,0,218,8,95,95,114,101,112,
114,95,95,228,3,0,0,115,2,0,0,0,0,1,122,23,
114,95,95,230,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,12,0,0,
@ -1672,7 +1672,7 @@ const unsigned char _Py_M__importlib_external[] = {
41,1,114,237,0,0,0,41,2,114,104,0,0,0,218,4,
105,116,101,109,114,4,0,0,0,114,4,0,0,0,114,6,
0,0,0,218,12,95,95,99,111,110,116,97,105,110,115,95,
95,231,3,0,0,115,2,0,0,0,0,1,122,27,95,78,
95,233,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,115,16,
@ -1680,7 +1680,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,83,0,41,1,78,41,2,114,229,0,0,0,114,161,0,
0,0,41,2,114,104,0,0,0,114,244,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,6,0,0,0,114,161,0,
0,0,234,3,0,0,115,2,0,0,0,0,1,122,21,95,
0,0,236,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,14,114,109,0,0,0,114,108,0,0,
0,114,110,0,0,0,114,111,0,0,0,114,182,0,0,0,
@ -1688,7 +1688,7 @@ const unsigned char _Py_M__importlib_external[] = {
239,0,0,0,114,241,0,0,0,114,242,0,0,0,114,243,
0,0,0,114,245,0,0,0,114,161,0,0,0,114,4,0,
0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,
0,114,227,0,0,0,179,3,0,0,115,22,0,0,0,8,
0,114,227,0,0,0,181,3,0,0,115,22,0,0,0,8,
5,4,2,8,6,8,10,8,4,8,13,8,3,8,3,8,
3,8,3,8,3,114,227,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,
@ -1704,7 +1704,7 @@ const unsigned char _Py_M__importlib_external[] = {
100,0,83,0,41,1,78,41,2,114,227,0,0,0,114,229,
0,0,0,41,4,114,104,0,0,0,114,102,0,0,0,114,
37,0,0,0,114,233,0,0,0,114,4,0,0,0,114,4,
0,0,0,114,6,0,0,0,114,182,0,0,0,240,3,0,
0,0,0,114,6,0,0,0,114,182,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,95,95,105,110,105,
116,95,95,99,2,0,0,0,0,0,0,0,2,0,0,0,
@ -1721,14 +1721,14 @@ const unsigned char _Py_M__importlib_external[] = {
110,97,109,101,115,112,97,99,101,41,62,41,2,114,50,0,
0,0,114,109,0,0,0,41,2,114,168,0,0,0,114,187,
0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,
0,0,218,11,109,111,100,117,108,101,95,114,101,112,114,243,
0,0,218,11,109,111,100,117,108,101,95,114,101,112,114,245,
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,83,0,41,2,78,84,114,4,0,0,0,41,
2,114,104,0,0,0,114,123,0,0,0,114,4,0,0,0,
114,4,0,0,0,114,6,0,0,0,114,157,0,0,0,252,
114,4,0,0,0,114,6,0,0,0,114,157,0,0,0,254,
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,
@ -1736,7 +1736,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,100,1,83,0,41,2,78,114,32,0,0,0,114,4,0,
0,0,41,2,114,104,0,0,0,114,123,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,6,0,0,0,114,199,0,
0,0,255,3,0,0,115,2,0,0,0,0,1,122,27,95,
0,0,1,4,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,
@ -1745,7 +1745,7 @@ const unsigned char _Py_M__importlib_external[] = {
60,115,116,114,105,110,103,62,114,186,0,0,0,114,201,0,
0,0,84,41,1,114,202,0,0,0,41,2,114,104,0,0,
0,114,123,0,0,0,114,4,0,0,0,114,4,0,0,0,
114,6,0,0,0,114,184,0,0,0,2,4,0,0,115,2,
114,6,0,0,0,114,184,0,0,0,4,4,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,0,1,0,0,
@ -1755,14 +1755,14 @@ const unsigned char _Py_M__importlib_external[] = {
108,101,32,99,114,101,97,116,105,111,110,46,78,114,4,0,
0,0,41,2,114,104,0,0,0,114,162,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,6,0,0,0,114,183,0,
0,0,5,4,0,0,115,0,0,0,0,122,30,95,78,97,
0,0,7,4,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,83,0,41,1,78,114,4,0,0,
0,41,2,114,104,0,0,0,114,187,0,0,0,114,4,0,
0,0,114,4,0,0,0,114,6,0,0,0,114,188,0,0,
0,8,4,0,0,115,2,0,0,0,0,1,122,28,95,78,
0,10,4,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,0,0,0,115,
@ -1780,7 +1780,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,0,114,133,0,0,0,114,229,0,0,0,114,189,0,
0,0,41,2,114,104,0,0,0,114,123,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,6,0,0,0,114,190,0,
0,0,11,4,0,0,115,6,0,0,0,0,7,6,1,8,
0,0,13,4,0,0,115,6,0,0,0,0,7,6,1,8,
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,109,0,0,0,114,108,0,0,0,114,110,0,0,
@ -1788,7 +1788,7 @@ const unsigned char _Py_M__importlib_external[] = {
114,157,0,0,0,114,199,0,0,0,114,184,0,0,0,114,
183,0,0,0,114,188,0,0,0,114,190,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,
0,0,114,246,0,0,0,239,3,0,0,115,16,0,0,0,
0,0,114,246,0,0,0,241,3,0,0,115,16,0,0,0,
8,1,8,3,12,9,8,3,8,3,8,3,8,3,8,3,
114,246,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,
@ -1822,7 +1822,7 @@ const unsigned char _Py_M__importlib_external[] = {
108,117,101,115,114,112,0,0,0,114,249,0,0,0,41,2,
114,168,0,0,0,218,6,102,105,110,100,101,114,114,4,0,
0,0,114,4,0,0,0,114,6,0,0,0,114,249,0,0,
0,29,4,0,0,115,6,0,0,0,0,4,16,1,10,1,
0,31,4,0,0,115,6,0,0,0,0,4,16,1,10,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,0,0,3,0,0,0,12,0,0,0,67,
@ -1841,7 +1841,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,114,64,0,0,0,114,122,0,0,0,114,103,0,0,
0,41,3,114,168,0,0,0,114,37,0,0,0,90,4,104,
111,111,107,114,4,0,0,0,114,4,0,0,0,114,6,0,
0,0,218,11,95,112,97,116,104,95,104,111,111,107,115,37,
0,0,218,11,95,112,97,116,104,95,104,111,111,107,115,39,
4,0,0,115,16,0,0,0,0,3,18,1,12,1,12,1,
2,1,8,1,14,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,
@ -1873,7 +1873,7 @@ const unsigned char _Py_M__importlib_external[] = {
3,114,168,0,0,0,114,37,0,0,0,114,252,0,0,0,
114,4,0,0,0,114,4,0,0,0,114,6,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,50,4,0,0,115,22,0,0,0,0,8,
99,97,99,104,101,52,4,0,0,115,22,0,0,0,0,8,
8,1,2,1,12,1,14,3,6,1,2,1,14,1,14,1,
10,1,16,1,122,31,80,97,116,104,70,105,110,100,101,114,
46,95,112,97,116,104,95,105,109,112,111,114,116,101,114,95,
@ -1890,7 +1890,7 @@ const unsigned char _Py_M__importlib_external[] = {
114,168,0,0,0,114,123,0,0,0,114,252,0,0,0,114,
124,0,0,0,114,125,0,0,0,114,162,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,6,0,0,0,218,16,95,
108,101,103,97,99,121,95,103,101,116,95,115,112,101,99,72,
108,101,103,97,99,121,95,103,101,116,95,115,112,101,99,74,
4,0,0,115,18,0,0,0,0,4,10,1,16,2,10,1,
4,1,8,1,12,1,12,1,6,1,122,27,80,97,116,104,
70,105,110,100,101,114,46,95,108,101,103,97,99,121,95,103,
@ -1922,7 +1922,7 @@ const unsigned char _Py_M__importlib_external[] = {
95,112,97,116,104,90,5,101,110,116,114,121,114,252,0,0,
0,114,162,0,0,0,114,125,0,0,0,114,4,0,0,0,
114,4,0,0,0,114,6,0,0,0,218,9,95,103,101,116,
95,115,112,101,99,87,4,0,0,115,40,0,0,0,0,5,
95,115,112,101,99,89,4,0,0,115,40,0,0,0,0,5,
4,1,10,1,14,1,2,1,10,1,8,1,10,1,14,2,
12,1,8,1,2,1,10,1,4,1,6,1,8,1,8,5,
14,2,12,1,6,1,122,20,80,97,116,104,70,105,110,100,
@ -1950,7 +1950,7 @@ const unsigned char _Py_M__importlib_external[] = {
41,6,114,168,0,0,0,114,123,0,0,0,114,37,0,0,
0,114,177,0,0,0,114,162,0,0,0,114,3,1,0,0,
114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,
178,0,0,0,119,4,0,0,115,26,0,0,0,0,6,8,
178,0,0,0,121,4,0,0,115,26,0,0,0,0,6,8,
1,6,1,14,1,8,1,6,1,10,1,6,1,4,3,6,
1,16,1,6,2,6,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,
@ -1971,7 +1971,7 @@ const unsigned char _Py_M__importlib_external[] = {
32,32,32,78,41,2,114,178,0,0,0,114,124,0,0,0,
41,4,114,168,0,0,0,114,123,0,0,0,114,37,0,0,
0,114,162,0,0,0,114,4,0,0,0,114,4,0,0,0,
114,6,0,0,0,114,179,0,0,0,143,4,0,0,115,8,
114,6,0,0,0,114,179,0,0,0,145,4,0,0,115,8,
0,0,0,0,8,12,1,8,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,1,78,41,2,78,78,41,1,78,41,12,114,
@ -1980,7 +1980,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,114,0,1,0,0,114,1,1,0,0,114,4,1,0,
0,114,178,0,0,0,114,179,0,0,0,114,4,0,0,0,
114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,
248,0,0,0,25,4,0,0,115,22,0,0,0,8,2,4,
248,0,0,0,27,4,0,0,115,22,0,0,0,8,2,4,
2,12,8,12,13,12,22,12,15,2,1,12,31,2,1,12,
23,2,1,114,248,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,90,0,
@ -2024,7 +2024,7 @@ const unsigned char _Py_M__importlib_external[] = {
1,0,113,2,100,0,83,0,41,1,78,114,4,0,0,0,
41,2,114,24,0,0,0,114,222,0,0,0,41,1,114,124,
0,0,0,114,4,0,0,0,114,6,0,0,0,114,224,0,
0,0,172,4,0,0,115,2,0,0,0,4,0,122,38,70,
0,0,174,4,0,0,115,2,0,0,0,4,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,61,0,0,0,114,31,0,0,0,78,
@ -2036,7 +2036,7 @@ const unsigned char _Py_M__importlib_external[] = {
5,114,104,0,0,0,114,37,0,0,0,218,14,108,111,97,
100,101,114,95,100,101,116,97,105,108,115,90,7,108,111,97,
100,101,114,115,114,164,0,0,0,114,4,0,0,0,41,1,
114,124,0,0,0,114,6,0,0,0,114,182,0,0,0,166,
114,124,0,0,0,114,6,0,0,0,114,182,0,0,0,168,
4,0,0,115,16,0,0,0,0,4,4,1,14,1,28,1,
6,2,10,1,6,1,8,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,
@ -2047,7 +2047,7 @@ const unsigned char _Py_M__importlib_external[] = {
105,109,101,46,114,31,0,0,0,78,114,91,0,0,0,41,
1,114,7,1,0,0,41,1,114,104,0,0,0,114,4,0,
0,0,114,4,0,0,0,114,6,0,0,0,114,249,0,0,
0,180,4,0,0,115,2,0,0,0,0,2,122,28,70,105,
0,182,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,67,0,0,0,115,
@ -2069,7 +2069,7 @@ const unsigned char _Py_M__importlib_external[] = {
32,32,32,32,32,32,32,78,41,3,114,178,0,0,0,114,
124,0,0,0,114,154,0,0,0,41,3,114,104,0,0,0,
114,123,0,0,0,114,162,0,0,0,114,4,0,0,0,114,
4,0,0,0,114,6,0,0,0,114,121,0,0,0,186,4,
4,0,0,0,114,6,0,0,0,114,121,0,0,0,188,4,
0,0,115,8,0,0,0,0,7,10,1,8,1,8,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,
@ -2080,7 +2080,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,0,41,7,114,104,0,0,0,114,163,0,0,0,114,
123,0,0,0,114,37,0,0,0,90,4,115,109,115,108,114,
177,0,0,0,114,124,0,0,0,114,4,0,0,0,114,4,
0,0,0,114,6,0,0,0,114,4,1,0,0,198,4,0,
0,0,0,114,6,0,0,0,114,4,1,0,0,200,4,0,
0,115,6,0,0,0,0,1,10,1,12,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,
@ -2135,7 +2135,7 @@ const unsigned char _Py_M__importlib_external[] = {
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,162,0,
0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,
0,114,178,0,0,0,203,4,0,0,115,70,0,0,0,0,
0,114,178,0,0,0,205,4,0,0,115,70,0,0,0,0,
5,4,1,14,1,2,1,24,1,14,1,10,1,10,1,8,
1,6,2,6,1,6,1,10,2,6,1,4,2,8,1,12,
1,16,1,8,1,10,1,8,1,24,4,8,2,16,1,16,
@ -2166,7 +2166,7 @@ const unsigned char _Py_M__importlib_external[] = {
125,1,124,1,106,0,131,0,146,2,113,4,83,0,114,4,
0,0,0,41,1,114,92,0,0,0,41,2,114,24,0,0,
0,90,2,102,110,114,4,0,0,0,114,4,0,0,0,114,
6,0,0,0,250,9,60,115,101,116,99,111,109,112,62,24,
6,0,0,0,250,9,60,115,101,116,99,111,109,112,62,26,
5,0,0,115,2,0,0,0,6,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,
@ -2184,7 +2184,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,0,114,102,0,0,0,114,234,0,0,0,114,222,0,
0,0,90,8,110,101,119,95,110,97,109,101,114,4,0,0,
0,114,4,0,0,0,114,6,0,0,0,114,12,1,0,0,
251,4,0,0,115,34,0,0,0,0,2,6,1,2,1,22,
253,4,0,0,115,34,0,0,0,0,2,6,1,2,1,22,
1,20,3,10,3,12,1,12,7,6,1,10,1,16,1,4,
1,18,2,4,1,14,1,6,1,12,1,122,22,70,105,108,
101,70,105,110,100,101,114,46,95,102,105,108,108,95,99,97,
@ -2221,7 +2221,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,114,103,0,0,0,41,1,114,37,0,0,0,41,2,114,
168,0,0,0,114,11,1,0,0,114,4,0,0,0,114,6,
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,36,5,0,
111,114,95,70,105,108,101,70,105,110,100,101,114,38,5,0,
0,115,6,0,0,0,0,2,8,1,14,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,
@ -2229,7 +2229,7 @@ const unsigned char _Py_M__importlib_external[] = {
110,100,101,114,114,4,0,0,0,41,3,114,168,0,0,0,
114,11,1,0,0,114,17,1,0,0,114,4,0,0,0,41,
2,114,168,0,0,0,114,11,1,0,0,114,6,0,0,0,
218,9,112,97,116,104,95,104,111,111,107,26,5,0,0,115,
218,9,112,97,116,104,95,104,111,111,107,28,5,0,0,115,
4,0,0,0,0,10,14,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,0,0,0,67,
@ -2238,7 +2238,7 @@ const unsigned char _Py_M__importlib_external[] = {
100,101,114,40,123,33,114,125,41,41,2,114,50,0,0,0,
114,37,0,0,0,41,1,114,104,0,0,0,114,4,0,0,
0,114,4,0,0,0,114,6,0,0,0,114,243,0,0,0,
44,5,0,0,115,2,0,0,0,0,1,122,19,70,105,108,
46,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,1,78,41,15,114,109,0,0,0,114,108,0,0,0,114,
110,0,0,0,114,111,0,0,0,114,182,0,0,0,114,249,
@ -2246,7 +2246,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,114,4,1,0,0,114,178,0,0,0,114,12,1,0,
0,114,180,0,0,0,114,18,1,0,0,114,243,0,0,0,
114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
6,0,0,0,114,5,1,0,0,157,4,0,0,115,20,0,
6,0,0,0,114,5,1,0,0,159,4,0,0,115,20,0,
0,0,8,7,4,2,8,14,8,4,4,2,8,12,8,5,
10,48,8,31,12,18,114,5,1,0,0,99,4,0,0,0,
0,0,0,0,6,0,0,0,11,0,0,0,67,0,0,0,
@ -2269,7 +2269,7 @@ const unsigned char _Py_M__importlib_external[] = {
112,97,116,104,110,97,109,101,90,9,99,112,97,116,104,110,
97,109,101,114,124,0,0,0,114,162,0,0,0,114,4,0,
0,0,114,4,0,0,0,114,6,0,0,0,218,14,95,102,
105,120,95,117,112,95,109,111,100,117,108,101,50,5,0,0,
105,120,95,117,112,95,109,111,100,117,108,101,52,5,0,0,
115,34,0,0,0,0,2,10,1,10,1,4,1,4,1,8,
1,8,1,12,2,10,1,4,1,16,1,2,1,8,1,8,
1,8,1,12,1,14,2,114,23,1,0,0,99,0,0,0,
@ -2289,7 +2289,7 @@ const unsigned char _Py_M__importlib_external[] = {
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,6,0,
0,0,114,159,0,0,0,73,5,0,0,115,8,0,0,0,
0,0,114,159,0,0,0,75,5,0,0,115,8,0,0,0,
0,5,12,1,8,1,8,1,114,159,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,188,1,0,0,124,0,97,0,116,0,106,1,97,
@ -2342,7 +2342,7 @@ const unsigned char _Py_M__importlib_external[] = {
83,0,41,2,114,31,0,0,0,78,41,1,114,33,0,0,
0,41,2,114,24,0,0,0,114,81,0,0,0,114,4,0,
0,0,114,4,0,0,0,114,6,0,0,0,114,224,0,0,
0,109,5,0,0,115,2,0,0,0,4,0,122,25,95,115,
0,111,5,0,0,115,2,0,0,0,4,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,62,0,0,0,122,30,105,109,
112,111,114,116,108,105,98,32,114,101,113,117,105,114,101,115,
@ -2372,7 +2372,7 @@ const unsigned char _Py_M__importlib_external[] = {
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,6,0,0,0,218,
6,95,115,101,116,117,112,84,5,0,0,115,82,0,0,0,
6,95,115,101,116,117,112,86,5,0,0,115,82,0,0,0,
0,8,4,1,6,1,6,3,10,1,10,1,10,1,12,2,
10,1,16,3,22,1,14,2,22,1,8,1,10,1,10,1,
4,2,2,1,10,1,6,1,14,1,12,2,8,1,12,1,
@ -2396,7 +2396,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,114,215,0,0,0,41,2,114,31,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,6,0,0,0,218,
8,95,105,110,115,116,97,108,108,152,5,0,0,115,16,0,
8,95,105,110,115,116,97,108,108,154,5,0,0,115,16,0,
0,0,0,2,8,1,6,1,20,1,10,1,12,1,12,4,
6,1,114,34,1,0,0,41,1,122,3,119,105,110,41,2,
114,1,0,0,0,114,2,0,0,0,41,1,114,49,0,0,
@ -2430,7 +2430,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,0,114,4,0,0,0,114,6,0,0,0,218,8,60,
109,111,100,117,108,101,62,8,0,0,0,115,108,0,0,0,
4,16,4,1,4,1,2,1,6,3,8,17,8,5,8,5,
8,6,8,12,8,10,8,9,8,5,8,7,10,22,10,117,
8,6,8,12,8,10,8,9,8,5,8,7,10,22,10,119,
16,1,12,2,4,1,4,2,6,2,6,2,8,2,16,45,
8,34,8,19,8,12,8,12,8,28,8,17,10,55,10,12,
10,10,8,14,6,3,4,1,14,67,14,64,14,29,16,110,

View file

@ -84,7 +84,7 @@ static void *opcode_targets[256] = {
&&TARGET_WITH_CLEANUP_FINISH,
&&TARGET_RETURN_VALUE,
&&TARGET_IMPORT_STAR,
&&_unknown_opcode,
&&TARGET_SETUP_ANNOTATIONS,
&&TARGET_YIELD_VALUE,
&&TARGET_POP_BLOCK,
&&TARGET_END_FINALLY,
@ -126,7 +126,7 @@ static void *opcode_targets[256] = {
&&TARGET_LOAD_FAST,
&&TARGET_STORE_FAST,
&&TARGET_DELETE_FAST,
&&_unknown_opcode,
&&TARGET_STORE_ANNOTATION,
&&_unknown_opcode,
&&_unknown_opcode,
&&TARGET_RAISE_VARARGS,

View file

@ -937,11 +937,17 @@ Py_GetPythonHome(void)
static void
initmain(PyInterpreterState *interp)
{
PyObject *m, *d, *loader;
PyObject *m, *d, *loader, *ann_dict;
m = PyImport_AddModule("__main__");
if (m == NULL)
Py_FatalError("can't create __main__ module");
d = PyModule_GetDict(m);
ann_dict = PyDict_New();
if ((ann_dict == NULL) ||
(PyDict_SetItemString(d, "__annotations__", ann_dict) < 0)) {
Py_FatalError("Failed to initialize __main__.__annotations__");
}
Py_DECREF(ann_dict);
if (PyDict_GetItemString(d, "__builtins__") == NULL) {
PyObject *bimod = PyImport_ImportModule("builtins");
if (bimod == NULL) {

View file

@ -1201,6 +1201,44 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
VISIT_SEQ(st, expr, s->v.Assign.targets);
VISIT(st, expr, s->v.Assign.value);
break;
case AnnAssign_kind:
if (s->v.AnnAssign.target->kind == Name_kind) {
expr_ty e_name = s->v.AnnAssign.target;
long cur = symtable_lookup(st, e_name->v.Name.id);
if (cur < 0) {
VISIT_QUIT(st, 0);
}
if ((cur & (DEF_GLOBAL | DEF_NONLOCAL))
&& s->v.AnnAssign.simple) {
PyErr_Format(PyExc_SyntaxError,
"annotated name '%U' can't be %s",
e_name->v.Name.id,
cur & DEF_GLOBAL ? "global" : "nonlocal");
PyErr_SyntaxLocationObject(st->st_filename,
s->lineno,
s->col_offset);
VISIT_QUIT(st, 0);
}
if (s->v.AnnAssign.simple &&
!symtable_add_def(st, e_name->v.Name.id,
DEF_ANNOT | DEF_LOCAL)) {
VISIT_QUIT(st, 0);
}
else {
if (s->v.AnnAssign.value
&& !symtable_add_def(st, e_name->v.Name.id, DEF_LOCAL)) {
VISIT_QUIT(st, 0);
}
}
}
else {
VISIT(st, expr, s->v.AnnAssign.target);
}
VISIT(st, expr, s->v.AnnAssign.annotation);
if (s->v.AnnAssign.value) {
VISIT(st, expr, s->v.AnnAssign.value);
}
break;
case AugAssign_kind:
VISIT(st, expr, s->v.AugAssign.target);
VISIT(st, expr, s->v.AugAssign.value);
@ -1258,6 +1296,15 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
long cur = symtable_lookup(st, name);
if (cur < 0)
VISIT_QUIT(st, 0);
if (cur & DEF_ANNOT) {
PyErr_Format(PyExc_SyntaxError,
"annotated name '%U' can't be global",
name);
PyErr_SyntaxLocationObject(st->st_filename,
s->lineno,
s->col_offset);
VISIT_QUIT(st, 0);
}
if (cur & (DEF_LOCAL | USE)) {
char buf[256];
char *c_name = _PyUnicode_AsString(name);
@ -1289,6 +1336,15 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
long cur = symtable_lookup(st, name);
if (cur < 0)
VISIT_QUIT(st, 0);
if (cur & DEF_ANNOT) {
PyErr_Format(PyExc_SyntaxError,
"annotated name '%U' can't be nonlocal",
name);
PyErr_SyntaxLocationObject(st->st_filename,
s->lineno,
s->col_offset);
VISIT_QUIT(st, 0);
}
if (cur & (DEF_LOCAL | USE)) {
char buf[256];
char *c_name = _PyUnicode_AsString(name);

308
Tools/parser/com2ann.py Normal file
View file

@ -0,0 +1,308 @@
"""Helper module to tranlate 3.5 type comments to 3.6 variable annotations."""
import re
import os
import ast
import argparse
import tokenize
from collections import defaultdict
from textwrap import dedent
from io import BytesIO
__all__ = ['com2ann', 'TYPE_COM']
TYPE_COM = re.compile('\s*#\s*type\s*:.*$', flags=re.DOTALL)
TRAIL_OR_COM = re.compile('\s*$|\s*#.*$', flags=re.DOTALL)
class _Data:
"""Internal class describing global data on file."""
def __init__(self, lines, tokens):
self.lines = lines
self.tokens = tokens
ttab = defaultdict(list) # maps line number to token numbers
for i, tok in enumerate(tokens):
ttab[tok.start[0]].append(i)
self.ttab = ttab
self.success = [] # list of lines where type comments where processed
self.fail = [] # list of lines where type comments where rejected
def skip_blank(d, lno):
while d.lines[lno].strip() == '':
lno += 1
return lno
def find_start(d, lcom):
"""Find first char of the assignment target."""
i = d.ttab[lcom + 1][-2] # index of type comment token in tokens list
while ((d.tokens[i].exact_type != tokenize.NEWLINE) and
(d.tokens[i].exact_type != tokenize.ENCODING)):
i -= 1
lno = d.tokens[i].start[0]
return skip_blank(d, lno)
def check_target(stmt):
if len(stmt.body):
assign = stmt.body[0]
else:
return False
if isinstance(assign, ast.Assign) and len(assign.targets) == 1:
targ = assign.targets[0]
else:
return False
if (isinstance(targ, ast.Name) or isinstance(targ, ast.Attribute)
or isinstance(targ, ast.Subscript)):
return True
return False
def find_eq(d, lstart):
"""Find equal sign starting from lstart taking care about d[f(x=1)] = 5."""
col = pars = 0
lno = lstart
while d.lines[lno][col] != '=' or pars != 0:
ch = d.lines[lno][col]
if ch in '([{':
pars += 1
elif ch in ')]}':
pars -= 1
if ch == '#' or col == len(d.lines[lno])-1:
lno = skip_blank(d, lno+1)
col = 0
else:
col += 1
return lno, col
def find_val(d, poseq):
"""Find position of first char of assignment value starting from poseq."""
lno, col = poseq
while (d.lines[lno][col].isspace() or d.lines[lno][col] in '=\\'):
if col == len(d.lines[lno])-1:
lno += 1
col = 0
else:
col += 1
return lno, col
def find_targ(d, poseq):
"""Find position of last char of target (annotation goes here)."""
lno, col = poseq
while (d.lines[lno][col].isspace() or d.lines[lno][col] in '=\\'):
if col == 0:
lno -= 1
col = len(d.lines[lno])-1
else:
col -= 1
return lno, col+1
def trim(new_lines, string, ltarg, poseq, lcom, ccom):
"""Remove None or Ellipsis from assignment value.
Also remove parens if one has (None), (...) etc.
string -- 'None' or '...'
ltarg -- line where last char of target is located
poseq -- position of equal sign
lcom, ccom -- position of type comment
"""
nopars = lambda s: s.replace('(', '').replace(')', '')
leq, ceq = poseq
end = ccom if leq == lcom else len(new_lines[leq])
subline = new_lines[leq][:ceq]
if leq == ltarg:
subline = subline.rstrip()
new_lines[leq] = subline + (new_lines[leq][end:] if leq == lcom
else new_lines[leq][ceq+1:end])
for lno in range(leq+1,lcom):
new_lines[lno] = nopars(new_lines[lno])
if lcom != leq:
subline = nopars(new_lines[lcom][:ccom]).replace(string, '')
if (not subline.isspace()):
subline = subline.rstrip()
new_lines[lcom] = subline + new_lines[lcom][ccom:]
def _com2ann(d, drop_None, drop_Ellipsis):
new_lines = d.lines[:]
for lcom, line in enumerate(d.lines):
match = re.search(TYPE_COM, line)
if match:
# strip " # type : annotation \n" -> "annotation \n"
tp = match.group().lstrip()[1:].lstrip()[4:].lstrip()[1:].lstrip()
submatch = re.search(TRAIL_OR_COM, tp)
subcom = ''
if submatch and submatch.group():
subcom = submatch.group()
tp = tp[:submatch.start()]
if tp == 'ignore':
continue
ccom = match.start()
if not any(d.tokens[i].exact_type == tokenize.COMMENT
for i in d.ttab[lcom + 1]):
d.fail.append(lcom)
continue # type comment inside string
lstart = find_start(d, lcom)
stmt_str = dedent(''.join(d.lines[lstart:lcom+1]))
try:
stmt = ast.parse(stmt_str)
except SyntaxError:
d.fail.append(lcom)
continue # for or with statements
if not check_target(stmt):
d.fail.append(lcom)
continue
d.success.append(lcom)
val = stmt.body[0].value
# writing output now
poseq = find_eq(d, lstart)
lval, cval = find_val(d, poseq)
ltarg, ctarg = find_targ(d, poseq)
op_par = ''
cl_par = ''
if isinstance(val, ast.Tuple):
if d.lines[lval][cval] != '(':
op_par = '('
cl_par = ')'
# write the comment first
new_lines[lcom] = d.lines[lcom][:ccom].rstrip() + cl_par + subcom
ccom = len(d.lines[lcom][:ccom].rstrip())
string = False
if isinstance(val, ast.Tuple):
# t = 1, 2 -> t = (1, 2); only latter is allowed with annotation
free_place = int(new_lines[lval][cval-2:cval] == ' ')
new_lines[lval] = (new_lines[lval][:cval-free_place] +
op_par + new_lines[lval][cval:])
elif isinstance(val, ast.Ellipsis) and drop_Ellipsis:
string = '...'
elif (isinstance(val, ast.NameConstant) and
val.value is None and drop_None):
string = 'None'
if string:
trim(new_lines, string, ltarg, poseq, lcom, ccom)
# finally write an annotation
new_lines[ltarg] = (new_lines[ltarg][:ctarg] +
': ' + tp + new_lines[ltarg][ctarg:])
return ''.join(new_lines)
def com2ann(code, *, drop_None=False, drop_Ellipsis=False, silent=False):
"""Translate type comments to type annotations in code.
Take code as string and return this string where::
variable = value # type: annotation # real comment
is translated to::
variable: annotation = value # real comment
For unsupported syntax cases, the type comments are
left intact. If drop_None is True or if drop_Ellipsis
is True translate correcpondingly::
variable = None # type: annotation
variable = ... # type: annotation
into::
variable: annotation
The tool tries to preserve code formatting as much as
possible, but an exact translation is not guarateed.
A summary of translated comments id printed by default.
"""
try:
ast.parse(code) # we want to work only with file without syntax errors
except SyntaxError:
return None
lines = code.splitlines(keepends=True)
rl = BytesIO(code.encode('utf-8')).readline
tokens = list(tokenize.tokenize(rl))
data = _Data(lines, tokens)
new_code = _com2ann(data, drop_None, drop_Ellipsis)
if not silent:
if data.success:
print('Comments translated on lines:',
', '.join(str(lno+1) for lno in data.success))
if data.fail:
print('Comments rejected on lines:',
', '.join(str(lno+1) for lno in data.fail))
if not data.success and not data.fail:
print('No type comments found')
return new_code
def translate_file(infile, outfile, dnone, dell, silent):
try:
descr = tokenize.open(infile)
except SyntaxError:
print("Cannot open", infile)
return
with descr as f:
code = f.read()
enc = f.encoding
if not silent:
print('File:', infile)
new_code = com2ann(code, drop_None=dnone,
drop_Ellipsis=dell,
silent=silent)
if new_code is None:
print("SyntaxError in", infile)
return
with open(outfile, 'wb') as f:
f.write((new_code).encode(enc))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("-o", "--outfile",
help="output file, will be overwritten if exists,\n"
"defaults to input file")
parser.add_argument("infile",
help="input file or directory for translation, must\n"
"contain no syntax errors, for directory\n"
"the outfile is ignored and translation is\n"
"made in place")
parser.add_argument("-s", "--silent",
help="Do not print summary for line numbers of\n"
"translated and rejected comments",
action="store_true")
parser.add_argument("-n", "--drop-none",
help="drop any None as assignment value during\n"
"translation if it is annotated by a type coment",
action="store_true")
parser.add_argument("-e", "--drop-ellipsis",
help="drop any Ellipsis (...) as assignment value during\n"
"translation if it is annotated by a type coment",
action="store_true")
args = parser.parse_args()
if args.outfile is None:
args.outfile = args.infile
if os.path.isfile(args.infile):
translate_file(args.infile, args.outfile,
args.drop_none, args.drop_ellipsis, args.silent)
else:
for root, dirs, files in os.walk(args.infile):
for afile in files:
_, ext = os.path.splitext(afile)
if ext == '.py' or ext == '.pyi':
fname = os.path.join(root, afile)
translate_file(fname, fname,
args.drop_none, args.drop_ellipsis,
args.silent)

View file

@ -104,6 +104,19 @@ def _AugAssign(self, t):
self.write(" "+self.binop[t.op.__class__.__name__]+"= ")
self.dispatch(t.value)
def _AnnAssign(self, t):
self.fill()
if not t.simple and isinstance(t.target, ast.Name):
self.write('(')
self.dispatch(t.target)
if not t.simple and isinstance(t.target, ast.Name):
self.write(')')
self.write(": ")
self.dispatch(t.annotation)
if t.value:
self.write(" = ")
self.dispatch(t.value)
def _Return(self, t):
self.fill("return")
if t.value: