Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 15 additions & 5 deletions Grammar/python.gram
Original file line number Diff line number Diff line change
Expand Up @@ -225,14 +225,24 @@ import_stmt[stmt_ty](memo):
# -----------------

import_name[stmt_ty]:
| lazy="lazy"? 'import' a=dotted_as_names { _PyAST_Import(a, lazy ? 1 : 0, EXTRA) }
| "lazy" 'import' a=dotted_as_names {
CHECK_VERSION(stmt_ty, 15, "Lazy imports are",
_PyAST_Import(a, 1, EXTRA)) }
| 'import' a=dotted_as_names { _PyAST_Import(a, 0, EXTRA) }

# note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS
import_from[stmt_ty]:
| lazy="lazy"? 'from' a=('.' | '...')* b=dotted_name 'import' c=import_from_targets {
_PyPegen_checked_future_import(p, b->v.Name.id, c, _PyPegen_seq_count_dots(a), lazy, EXTRA) }
| lazy="lazy"? 'from' a=('.' | '...')+ 'import' b=import_from_targets {
_PyAST_ImportFrom(NULL, b, _PyPegen_seq_count_dots(a), lazy ? 1 : 0, EXTRA) }
| lazy="lazy" 'from' a=('.' | '...')* b=dotted_name 'import' c=import_from_targets {
CHECK_VERSION(stmt_ty, 15, "Lazy imports are",
_PyPegen_checked_future_import(p, b->v.Name.id, c, _PyPegen_seq_count_dots(a), lazy, EXTRA)) }
| "lazy" 'from' a=('.' | '...')+ 'import' b=import_from_targets {
CHECK_VERSION(stmt_ty, 15, "Lazy imports are",
_PyAST_ImportFrom(NULL, b, _PyPegen_seq_count_dots(a), 1, EXTRA)) }
| 'from' a=('.' | '...')* b=dotted_name 'import' c=import_from_targets {
_PyPegen_checked_future_import(p, b->v.Name.id, c, _PyPegen_seq_count_dots(a), 0, EXTRA) }
| 'from' a=('.' | '...')+ 'import' b=import_from_targets {
_PyAST_ImportFrom(NULL, b, _PyPegen_seq_count_dots(a), 0, EXTRA) }

import_from_targets[asdl_alias_seq*]:
| '(' a=import_from_as_names [','] ')' { a }
| import_from_as_names !','
Expand Down
13 changes: 13 additions & 0 deletions Lib/test/test_ast/test_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,19 @@ def test_type_params_default_feature_version(self):
with self.assertRaises(SyntaxError):
ast.parse(sample, feature_version=(3, 12))

def test_lazy_imports_feature_version(self):
samples = [
"lazy import os",
"lazy from .. import name",
"lazy from mod import some",
]
for sample in samples:
with self.subTest(sample):
ast.parse(sample)
ast.parse(sample, feature_version=(3, 15))
with self.assertRaises(SyntaxError):
ast.parse(sample, feature_version=(3, 14))

def test_invalid_major_feature_version(self):
with self.assertRaises(ValueError):
ast.parse('pass', feature_version=(2, 7))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix :func:`ast.parse` ability to parse lazy imports with *feature_version*
older than 3.15, now it properly raises :exc:`SyntaxError`.
Loading
Loading