Skip to content

Commit f8cb8a1

Browse files
committed
Issue #27985: Implement PEP 526 -- Syntax for Variable Annotations.
Patch by Ivan Levkivskyi.
1 parent 09ad178 commit f8cb8a1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+3116
-1182
lines changed

Doc/glossary.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,18 @@ Glossary
964964
``'\r'``. See :pep:`278` and :pep:`3116`, as well as
965965
:func:`bytes.splitlines` for an additional use.
966966

967+
variable annotation
968+
A type metadata value associated with a module global variable or
969+
a class attribute. Its syntax is explained in section :ref:`annassign`.
970+
Annotations are stored in the :attr:`__annotations__` special
971+
attribute of a class or module object and can be accessed using
972+
:func:`typing.get_type_hints`.
973+
974+
Python itself does not assign any particular meaning to variable
975+
annotations. They are intended to be interpreted by third-party libraries
976+
or type checking tools. See :pep:`526`, :pep:`484` which describe
977+
some of their potential uses.
978+
967979
virtual environment
968980
A cooperatively isolated runtime environment that allows Python users
969981
and applications to install and upgrade Python distribution packages

Doc/library/dis.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,12 @@ iterations of the loop.
607607

608608
.. versionadded:: 3.3
609609

610+
.. opcode:: SETUP_ANNOTATIONS
611+
612+
Checks whether ``__annotations__`` is defined in ``locals()``, if not it is
613+
set up to an empty ``dict``. This opcode is only emmitted if a class
614+
or module body contains :term:`variable annotations <variable annotation>`
615+
statically.
610616

611617
.. opcode:: IMPORT_STAR
612618

@@ -890,6 +896,11 @@ All of the following opcodes use their arguments.
890896
Deletes local ``co_varnames[var_num]``.
891897

892898

899+
.. opcode:: STORE_ANNOTATION (namei)
900+
901+
Stores TOS as ``locals()['__annotations__'][co_names[namei]] = TOS``.
902+
903+
893904
.. opcode:: LOAD_CLOSURE (i)
894905

895906
Pushes a reference to the cell contained in slot *i* of the cell and free

Doc/reference/datamodel.rst

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -686,33 +686,36 @@ Modules
686686
Attribute assignment updates the module's namespace dictionary, e.g.,
687687
``m.x = 1`` is equivalent to ``m.__dict__["x"] = 1``.
688688

689-
.. index:: single: __dict__ (module attribute)
690-
691-
Special read-only attribute: :attr:`~object.__dict__` is the module's namespace as a
692-
dictionary object.
693-
694-
.. impl-detail::
695-
696-
Because of the way CPython clears module dictionaries, the module
697-
dictionary will be cleared when the module falls out of scope even if the
698-
dictionary still has live references. To avoid this, copy the dictionary
699-
or keep the module around while using its dictionary directly.
700-
701689
.. index::
702690
single: __name__ (module attribute)
703691
single: __doc__ (module attribute)
704692
single: __file__ (module attribute)
693+
single: __annotations__ (module attribute)
705694
pair: module; namespace
706695

707696
Predefined (writable) attributes: :attr:`__name__` is the module's name;
708697
:attr:`__doc__` is the module's documentation string, or ``None`` if
709-
unavailable; :attr:`__file__` is the pathname of the file from which the
698+
unavailable; :attr:`__annotations__` (optional) is a dictionary containing
699+
:term:`variable annotations <variable annotation>` collected during module
700+
body execution; :attr:`__file__` is the pathname of the file from which the
710701
module was loaded, if it was loaded from a file. The :attr:`__file__`
711702
attribute may be missing for certain types of modules, such as C modules
712703
that are statically linked into the interpreter; for extension modules
713704
loaded dynamically from a shared library, it is the pathname of the shared
714705
library file.
715706

707+
.. index:: single: __dict__ (module attribute)
708+
709+
Special read-only attribute: :attr:`~object.__dict__` is the module's
710+
namespace as a dictionary object.
711+
712+
.. impl-detail::
713+
714+
Because of the way CPython clears module dictionaries, the module
715+
dictionary will be cleared when the module falls out of scope even if the
716+
dictionary still has live references. To avoid this, copy the dictionary
717+
or keep the module around while using its dictionary directly.
718+
716719
Custom classes
717720
Custom class types are typically created by class definitions (see section
718721
:ref:`class`). A class has a namespace implemented by a dictionary object.
@@ -761,13 +764,17 @@ Custom classes
761764
single: __dict__ (class attribute)
762765
single: __bases__ (class attribute)
763766
single: __doc__ (class attribute)
767+
single: __annotations__ (class attribute)
764768

765769
Special attributes: :attr:`~definition.__name__` is the class name; :attr:`__module__` is
766770
the module name in which the class was defined; :attr:`~object.__dict__` is the
767771
dictionary containing the class's namespace; :attr:`~class.__bases__` is a
768772
tuple (possibly empty or a singleton) containing the base classes, in the
769773
order of their occurrence in the base class list; :attr:`__doc__` is the
770-
class's documentation string, or None if undefined.
774+
class's documentation string, or None if undefined;
775+
:attr:`__annotations__` (optional) is a dictionary containing
776+
:term:`variable annotations <variable annotation>` collected during
777+
class body execution.
771778

772779
Class instances
773780
.. index::

Doc/reference/simple_stmts.rst

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ simple statements is:
1616
: | `assert_stmt`
1717
: | `assignment_stmt`
1818
: | `augmented_assignment_stmt`
19+
: | `annotated_assignment_stmt`
1920
: | `pass_stmt`
2021
: | `del_stmt`
2122
: | `return_stmt`
@@ -312,6 +313,49 @@ For targets which are attribute references, the same :ref:`caveat about class
312313
and instance attributes <attr-target-note>` applies as for regular assignments.
313314

314315

316+
.. _annassign:
317+
318+
Annotated assignment statements
319+
-------------------------------
320+
321+
.. index::
322+
pair: annotated; assignment
323+
single: statement; assignment, annotated
324+
325+
Annotation assignment is the combination, in a single statement,
326+
of a variable or attribute annotation and an optional assignment statement:
327+
328+
.. productionlist::
329+
annotated_assignment_stmt: `augtarget` ":" `expression` ["=" `expression`]
330+
331+
The difference from normal :ref:`assignment` is that only single target and
332+
only single right hand side value is allowed.
333+
334+
For simple names as assignment targets, if in class or module scope,
335+
the annotations are evaluated and stored in a special class or module
336+
attribute :attr:`__annotations__`
337+
that is a dictionary mapping from variable names to evaluated annotations.
338+
This attribute is writable and is automatically created at the start
339+
of class or module body execution, if annotations are found statically.
340+
341+
For expressions as assignment targets, the annotations are evaluated if
342+
in class or module scope, but not stored.
343+
344+
If a name is annotated in a function scope, then this name is local for
345+
that scope. Annotations are never evaluated and stored in function scopes.
346+
347+
If the right hand side is present, an annotated
348+
assignment performs the actual assignment before evaluating annotations
349+
(where applicable). If the right hand side is not present for an expression
350+
target, then the interpreter evaluates the target except for the last
351+
:meth:`__setitem__` or :meth:`__setattr__` call.
352+
353+
.. seealso::
354+
355+
:pep:`526` - Variable and attribute annotation syntax
356+
:pep:`484` - Type hints
357+
358+
315359
.. _assert:
316360

317361
The :keyword:`assert` statement

Grammar/Grammar

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,13 @@ stmt: simple_stmt | compound_stmt
4545
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
4646
small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
4747
import_stmt | global_stmt | nonlocal_stmt | assert_stmt)
48-
expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) |
48+
expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) |
4949
('=' (yield_expr|testlist_star_expr))*)
50+
annassign: ':' test ['=' test]
5051
testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
5152
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
5253
'<<=' | '>>=' | '**=' | '//=')
53-
# For normal assignments, additional restrictions enforced by the interpreter
54+
# For normal and annotated assignments, additional restrictions enforced by the interpreter
5455
del_stmt: 'del' exprlist
5556
pass_stmt: 'pass'
5657
flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt

Include/Python-ast.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,12 @@ struct _mod {
6565

6666
enum _stmt_kind {FunctionDef_kind=1, AsyncFunctionDef_kind=2, ClassDef_kind=3,
6767
Return_kind=4, Delete_kind=5, Assign_kind=6,
68-
AugAssign_kind=7, For_kind=8, AsyncFor_kind=9, While_kind=10,
69-
If_kind=11, With_kind=12, AsyncWith_kind=13, Raise_kind=14,
70-
Try_kind=15, Assert_kind=16, Import_kind=17,
71-
ImportFrom_kind=18, Global_kind=19, Nonlocal_kind=20,
72-
Expr_kind=21, Pass_kind=22, Break_kind=23, Continue_kind=24};
68+
AugAssign_kind=7, AnnAssign_kind=8, For_kind=9,
69+
AsyncFor_kind=10, While_kind=11, If_kind=12, With_kind=13,
70+
AsyncWith_kind=14, Raise_kind=15, Try_kind=16,
71+
Assert_kind=17, Import_kind=18, ImportFrom_kind=19,
72+
Global_kind=20, Nonlocal_kind=21, Expr_kind=22, Pass_kind=23,
73+
Break_kind=24, Continue_kind=25};
7374
struct _stmt {
7475
enum _stmt_kind kind;
7576
union {
@@ -116,6 +117,13 @@ struct _stmt {
116117
expr_ty value;
117118
} AugAssign;
118119

120+
struct {
121+
expr_ty target;
122+
expr_ty annotation;
123+
expr_ty value;
124+
int simple;
125+
} AnnAssign;
126+
119127
struct {
120128
expr_ty target;
121129
expr_ty iter;
@@ -461,6 +469,9 @@ stmt_ty _Py_Assign(asdl_seq * targets, expr_ty value, int lineno, int
461469
#define AugAssign(a0, a1, a2, a3, a4, a5) _Py_AugAssign(a0, a1, a2, a3, a4, a5)
462470
stmt_ty _Py_AugAssign(expr_ty target, operator_ty op, expr_ty value, int
463471
lineno, int col_offset, PyArena *arena);
472+
#define AnnAssign(a0, a1, a2, a3, a4, a5, a6) _Py_AnnAssign(a0, a1, a2, a3, a4, a5, a6)
473+
stmt_ty _Py_AnnAssign(expr_ty target, expr_ty annotation, expr_ty value, int
474+
simple, int lineno, int col_offset, PyArena *arena);
464475
#define For(a0, a1, a2, a3, a4, a5, a6) _Py_For(a0, a1, a2, a3, a4, a5, a6)
465476
stmt_ty _Py_For(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq *
466477
orelse, int lineno, int col_offset, PyArena *arena);

Include/graminit.h

Lines changed: 69 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -17,71 +17,72 @@
1717
#define simple_stmt 270
1818
#define small_stmt 271
1919
#define expr_stmt 272
20-
#define testlist_star_expr 273
21-
#define augassign 274
22-
#define del_stmt 275
23-
#define pass_stmt 276
24-
#define flow_stmt 277
25-
#define break_stmt 278
26-
#define continue_stmt 279
27-
#define return_stmt 280
28-
#define yield_stmt 281
29-
#define raise_stmt 282
30-
#define import_stmt 283
31-
#define import_name 284
32-
#define import_from 285
33-
#define import_as_name 286
34-
#define dotted_as_name 287
35-
#define import_as_names 288
36-
#define dotted_as_names 289
37-
#define dotted_name 290
38-
#define global_stmt 291
39-
#define nonlocal_stmt 292
40-
#define assert_stmt 293
41-
#define compound_stmt 294
42-
#define async_stmt 295
43-
#define if_stmt 296
44-
#define while_stmt 297
45-
#define for_stmt 298
46-
#define try_stmt 299
47-
#define with_stmt 300
48-
#define with_item 301
49-
#define except_clause 302
50-
#define suite 303
51-
#define test 304
52-
#define test_nocond 305
53-
#define lambdef 306
54-
#define lambdef_nocond 307
55-
#define or_test 308
56-
#define and_test 309
57-
#define not_test 310
58-
#define comparison 311
59-
#define comp_op 312
60-
#define star_expr 313
61-
#define expr 314
62-
#define xor_expr 315
63-
#define and_expr 316
64-
#define shift_expr 317
65-
#define arith_expr 318
66-
#define term 319
67-
#define factor 320
68-
#define power 321
69-
#define atom_expr 322
70-
#define atom 323
71-
#define testlist_comp 324
72-
#define trailer 325
73-
#define subscriptlist 326
74-
#define subscript 327
75-
#define sliceop 328
76-
#define exprlist 329
77-
#define testlist 330
78-
#define dictorsetmaker 331
79-
#define classdef 332
80-
#define arglist 333
81-
#define argument 334
82-
#define comp_iter 335
83-
#define comp_for 336
84-
#define comp_if 337
85-
#define encoding_decl 338
86-
#define yield_expr 339
87-
#define yield_arg 340
20+
#define annassign 273
21+
#define testlist_star_expr 274
22+
#define augassign 275
23+
#define del_stmt 276
24+
#define pass_stmt 277
25+
#define flow_stmt 278
26+
#define break_stmt 279
27+
#define continue_stmt 280
28+
#define return_stmt 281
29+
#define yield_stmt 282
30+
#define raise_stmt 283
31+
#define import_stmt 284
32+
#define import_name 285
33+
#define import_from 286
34+
#define import_as_name 287
35+
#define dotted_as_name 288
36+
#define import_as_names 289
37+
#define dotted_as_names 290
38+
#define dotted_name 291
39+
#define global_stmt 292
40+
#define nonlocal_stmt 293
41+
#define assert_stmt 294
42+
#define compound_stmt 295
43+
#define async_stmt 296
44+
#define if_stmt 297
45+
#define while_stmt 298
46+
#define for_stmt 299
47+
#define try_stmt 300
48+
#define with_stmt 301
49+
#define with_item 302
50+
#define except_clause 303
51+
#define suite 304
52+
#define test 305
53+
#define test_nocond 306
54+
#define lambdef 307
55+
#define lambdef_nocond 308
56+
#define or_test 309
57+
#define and_test 310
58+
#define not_test 311
59+
#define comparison 312
60+
#define comp_op 313
61+
#define star_expr 314
62+
#define expr 315
63+
#define xor_expr 316
64+
#define and_expr 317
65+
#define shift_expr 318
66+
#define arith_expr 319
67+
#define term 320
68+
#define factor 321
69+
#define power 322
70+
#define atom_expr 323
71+
#define atom 324
72+
#define testlist_comp 325
73+
#define trailer 326
74+
#define subscriptlist 327
75+
#define subscript 328
76+
#define sliceop 329
77+
#define exprlist 330
78+
#define testlist 331
79+
#define dictorsetmaker 332
80+
#define classdef 333
81+
#define arglist 334
82+
#define argument 335
83+
#define comp_iter 336
84+
#define comp_for 337
85+
#define comp_if 338
86+
#define encoding_decl 339
87+
#define yield_expr 340
88+
#define yield_arg 341

Include/opcode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ extern "C" {
6060
#define WITH_CLEANUP_FINISH 82
6161
#define RETURN_VALUE 83
6262
#define IMPORT_STAR 84
63+
#define SETUP_ANNOTATIONS 85
6364
#define YIELD_VALUE 86
6465
#define POP_BLOCK 87
6566
#define END_FINALLY 88
@@ -98,6 +99,7 @@ extern "C" {
9899
#define LOAD_FAST 124
99100
#define STORE_FAST 125
100101
#define DELETE_FAST 126
102+
#define STORE_ANNOTATION 127
101103
#define RAISE_VARARGS 130
102104
#define CALL_FUNCTION 131
103105
#define MAKE_FUNCTION 132

Include/symtable.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ PyAPI_FUNC(void) PySymtable_Free(struct symtable *);
9191
#define DEF_FREE 2<<4 /* name used but not defined in nested block */
9292
#define DEF_FREE_CLASS 2<<5 /* free variable from class's method */
9393
#define DEF_IMPORT 2<<6 /* assignment occurred via import */
94+
#define DEF_ANNOT 2<<7 /* this name is annotated */
9495

9596
#define DEF_BOUND (DEF_LOCAL | DEF_PARAM | DEF_IMPORT)
9697

0 commit comments

Comments
 (0)