Skip to content

bpo-35766: Merge typed_ast back into CPython #11645

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 49 commits into from
Jan 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
77de614
Add TYPE_IGNORE and TYPE_COMMENT without regenerating anything
gvanrossum Jan 19, 2019
8e0fd8a
Regenerated files (make regen-token)
gvanrossum Jan 19, 2019
cb93ba5
Tentative parsetok.c changes to handle TYPE_IGNORE
gvanrossum Jan 19, 2019
232f2b6
Unconditionally recognize type comments in tokenizer.c
gvanrossum Jan 19, 2019
c80197e
Changes to Grammar without regenerating anything
gvanrossum Jan 19, 2019
b440842
Regenerated files (make regen-grammar)
gvanrossum Jan 19, 2019
9db5e34
Add type_comment fields to various asdl classes without regenerating …
gvanrossum Jan 19, 2019
6cc5a55
Regenerated files (make regen-ast)
gvanrossum Jan 19, 2019
e7f207d
Make ast.c compile by adding NULL for all type_comment arguments
gvanrossum Jan 19, 2019
8b426b9
Make recognition of type comments conditional on a flag (off by default)
gvanrossum Jan 19, 2019
72e4f4d
Define flags to turn on parsing type comments
gvanrossum Jan 19, 2019
3d19dbb
Support passing type ignores to Module object
gvanrossum Jan 19, 2019
d273d67
Support TYPE_COMMENT in ast.c for all nodes that need it
gvanrossum Jan 22, 2019
830d63a
Regenerate Lib/symbol.py
gvanrossum Jan 22, 2019
71aecd5
Make growable_int_array functions static
gvanrossum Jan 22, 2019
53ceee6
News blurb (thank you blurb-it)
blurb-it[bot] Jan 22, 2019
6ddca66
Fix test_ast.py
gvanrossum Jan 22, 2019
36c212b
Fix test_asdl_parser.py
gvanrossum Jan 22, 2019
d2091ed
Hacky way to get tests to pass
gvanrossum Jan 23, 2019
6d1f1de
Regen Lib/symbol.py (again)
gvanrossum Jan 23, 2019
567f341
Fix assert in ast_for_suite() -- n can be a func_body_suite too now
gvanrossum Jan 23, 2019
5d36558
A better hack for IndentationError
gvanrossum Jan 23, 2019
7e78552
Merge remote-tracking branch 'origin/master' into ast-type-comments
gvanrossum Jan 25, 2019
308df83
Move func_body_suite towards the end of Grammar to stabilize symbol n…
gvanrossum Jan 25, 2019
110c42a
Fix test_parser.py in a hacky way
gvanrossum Jan 25, 2019
46dfac5
Export PyCF_TYPE_COMMENTS and add an interface for it to ast.parse()
gvanrossum Jan 25, 2019
8c527b7
Add some tests for type comments
gvanrossum Jan 25, 2019
cb301f7
Add some negative tests
gvanrossum Jan 28, 2019
d57aeab
Add checks that no type comments are returned without type_comments=True
gvanrossum Jan 28, 2019
30ea39e
Add 'as a' to with-statement with type comment
gvanrossum Jan 28, 2019
cef9f31
Don't allow type comments on expression statements
gvanrossum Jan 28, 2019
1667b8c
Add guards to some '== TYPE_COMMENT' checks, hopefully fixing a crash
gvanrossum Jan 28, 2019
895a012
Support compile(source, filename, 'func_type', PyCF_ONLY_AST)
gvanrossum Jan 28, 2019
ac485cd
Fix test_func_type_input()
gvanrossum Jan 28, 2019
8935005
Document type_comments=True and mode='func_type' for ast.parse()
gvanrossum Jan 28, 2019
4687be4
Document token.TYPE_COMMENT
gvanrossum Jan 28, 2019
783224d
Fix the asdl_c.py code generator to support mode='func_type'
gvanrossum Jan 28, 2019
50a921a
Reject function def with two signature type comments
gvanrossum Jan 28, 2019
d0adc22
Add a test with a non-ASCII name in a type comment
gvanrossum Jan 28, 2019
98ee20a
Add comment clarifying the func_body_suite switcheroo
gvanrossum Jan 28, 2019
4abedd3
Check for errors from _Py_asdl_seq_new()
gvanrossum Jan 28, 2019
551f2a6
Check for NULL from NEW_TYPE_COMMENT()
gvanrossum Jan 28, 2019
b68270c
Fix markup bug
gvanrossum Jan 28, 2019
dcf86e8
Brace block in parsetok.c
gvanrossum Jan 30, 2019
87812ad
Brace a block and fix indentation of another block
gvanrossum Jan 30, 2019
5633403
Brace block, update grammar comment, fix indents of many ast_error calls
gvanrossum Jan 30, 2019
2062e27
Merge branch 'master' into new-ast-type-comments
gvanrossum Jan 30, 2019
03310fc
Merge remote-tracking branch 'origin/master' into ast-type-comments
gvanrossum Jan 30, 2019
229874c
Break up long comment to trigger Appveyor build
gvanrossum Jan 30, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion Doc/library/ast.rst
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,33 @@ The abstract grammar is currently defined as follows:
Apart from the node classes, the :mod:`ast` module defines these utility functions
and classes for traversing abstract syntax trees:

.. function:: parse(source, filename='<unknown>', mode='exec')
.. function:: parse(source, filename='<unknown>', mode='exec', *, type_comments=False)

Parse the source into an AST node. Equivalent to ``compile(source,
filename, mode, ast.PyCF_ONLY_AST)``.

If ``type_comments=True`` is given, the parser is modified to check
and return type comments as specified by :pep:`484` and :pep:`526`.
This is equivalent to adding :data:`ast.PyCF_TYPE_COMMENTS` to the
flags passed to :func:`compile()`. This will report syntax errors
for misplaced type comments. Without this flag, type comments will
be ignored, and the ``type_comment`` field on selected AST nodes
will always be ``None``. In addition, the locations of ``# type:
ignore`` comments will be returned as the ``type_ignores``
attribute of :class:`Module` (otherwise it is always an empty list).

In addition, if ``mode`` is ``'func_type'``, the input syntax is
modified to correspond to :pep:`484` "signature type comments",
e.g. ``(str, int) -> List[str]``.

.. warning::
It is possible to crash the Python interpreter with a
sufficiently large/complex string due to stack depth limitations
in Python's AST compiler.

.. versionchanged:: 3.8
Added ``type_comments=True`` and ``mode='func_type'``.


.. function:: literal_eval(node_or_string)

Expand Down
4 changes: 4 additions & 0 deletions Doc/library/token-list.inc

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions Doc/library/token.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ the :mod:`tokenize` module.
always be an ``ENCODING`` token.


.. data:: TYPE_COMMENT

Token value indicating that a type comment was recognized. Such
tokens are only produced when :func:`ast.parse()` is invoked with
``type_comments=True``.


.. versionchanged:: 3.5
Added :data:`AWAIT` and :data:`ASYNC` tokens.

Expand All @@ -78,3 +85,6 @@ the :mod:`tokenize` module.
.. versionchanged:: 3.7
Removed :data:`AWAIT` and :data:`ASYNC` tokens. "async" and "await" are
now tokenized as :data:`NAME` tokens.

.. versionchanged:: 3.8
Added :data:`TYPE_COMMENT`.
31 changes: 22 additions & 9 deletions Grammar/Grammar
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
# single_input is a single interactive statement;
# file_input is a module or sequence of commands read from an input file;
# eval_input is the input for the eval() functions.
# func_type_input is a PEP 484 Python 2 function type comment
# NB: compound_stmt in single_input is followed by extra NEWLINE!
# NB: due to the way TYPE_COMMENT is tokenized it will always be followed by a NEWLINE
single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
file_input: (NEWLINE | stmt)* ENDMARKER
eval_input: testlist NEWLINE* ENDMARKER
Expand All @@ -17,14 +19,14 @@ decorators: decorator+
decorated: decorators (classdef | funcdef | async_funcdef)

async_funcdef: 'async' funcdef
funcdef: 'def' NAME parameters ['->' test] ':' suite
funcdef: 'def' NAME parameters ['->' test] ':' [TYPE_COMMENT] func_body_suite
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently this doesn't give an error, and the type comment recorded is the one on the same line:

def f():  # type: () -> int
    # type: () -> str
    pass

I think this should cause a SyntaxError (not here, but in ast.c).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, will do.


parameters: '(' [typedargslist] ')'
typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' [
'*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]]
| '**' tfpdef [',']]]
| '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]]
| '**' tfpdef [','])
typedargslist: (tfpdef ['=' test] (',' [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' [TYPE_COMMENT] [
'*' [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' [TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]])
| '**' tfpdef [','] [TYPE_COMMENT]]])
| '*' [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' [TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]])
| '**' tfpdef [','] [TYPE_COMMENT])
tfpdef: NAME [':' test]
varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [
'*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]]
Expand All @@ -39,7 +41,7 @@ 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 (annassign | augassign (yield_expr|testlist) |
('=' (yield_expr|testlist_star_expr))*)
[('=' (yield_expr|testlist_star_expr))+ [TYPE_COMMENT]] )
annassign: ':' test ['=' (yield_expr|testlist)]
testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
Expand Down Expand Up @@ -71,13 +73,13 @@ compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef
async_stmt: 'async' (funcdef | with_stmt | for_stmt)
if_stmt: 'if' namedexpr_test ':' suite ('elif' namedexpr_test ':' suite)* ['else' ':' suite]
while_stmt: 'while' test ':' suite ['else' ':' suite]
for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
for_stmt: 'for' exprlist 'in' testlist ':' [TYPE_COMMENT] suite ['else' ':' suite]
try_stmt: ('try' ':' suite
((except_clause ':' suite)+
['else' ':' suite]
['finally' ':' suite] |
'finally' ':' suite))
with_stmt: 'with' with_item (',' with_item)* ':' suite
with_stmt: 'with' with_item (',' with_item)* ':' [TYPE_COMMENT] suite
with_item: test ['as' expr]
# NB compile.c makes sure that the default except clause is last
except_clause: 'except' [test ['as' NAME]]
Expand Down Expand Up @@ -150,3 +152,14 @@ encoding_decl: NAME

yield_expr: 'yield' [yield_arg]
yield_arg: 'from' test | testlist_star_expr

# the TYPE_COMMENT in suites is only parsed for funcdefs,
# but can't go elsewhere due to ambiguity
func_body_suite: simple_stmt | NEWLINE [TYPE_COMMENT NEWLINE] INDENT stmt+ DEDENT

func_type_input: func_type NEWLINE* ENDMARKER
func_type: '(' [typelist] ')' '->' test
# typelist is a modified typedargslist (see above)
typelist: (test (',' test)* [','
['*' [test] (',' test)* [',' '**' test] | '**' test]]
| '*' [test] (',' test)* [',' '**' test] | '**' test)
2 changes: 2 additions & 0 deletions Grammar/Tokens
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ ELLIPSIS '...'
COLONEQUAL ':='

OP
TYPE_IGNORE
TYPE_COMMENT
ERRORTOKEN

# These aren't used by the C tokenizer but are needed for tokenize.py
Expand Down
94 changes: 64 additions & 30 deletions Include/Python-ast.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Include/compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ PyAPI_FUNC(PyCodeObject *) PyNode_Compile(struct _node *, const char *);
#define PyCF_DONT_IMPLY_DEDENT 0x0200
#define PyCF_ONLY_AST 0x0400
#define PyCF_IGNORE_COOKIE 0x0800
#define PyCF_TYPE_COMMENTS 0x1000

#ifndef Py_LIMITED_API
typedef struct {
Expand Down Expand Up @@ -85,10 +86,10 @@ PyAPI_FUNC(int) _PyAST_Optimize(struct _mod *, PyArena *arena, int optimize);

#endif /* !Py_LIMITED_API */

/* These definitions must match corresponding definitions in graminit.h.
There's code in compile.c that checks that they are the same. */
/* These definitions must match corresponding definitions in graminit.h. */
#define Py_single_input 256
#define Py_file_input 257
#define Py_eval_input 258
#define Py_func_type_input 345

#endif /* !Py_COMPILE_H */
4 changes: 4 additions & 0 deletions Include/graminit.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading