Thanks to visit codestin.com
Credit goes to github.com

Skip to content

gh-125331: Allow the parser to activate future imports on the fly #125482

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 10 commits into from
Feb 14, 2025
Merged
2 changes: 1 addition & 1 deletion Grammar/python.gram
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ import_name[stmt_ty]: 'import' a=dotted_as_names { _PyAST_Import(a, EXTRA) }
# note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS
import_from[stmt_ty]:
| 'from' a=('.' | '...')* b=dotted_name 'import' c=import_from_targets {
_PyAST_ImportFrom(b->v.Name.id, c, _PyPegen_seq_count_dots(a), EXTRA) }
_PyPegen_checked_future_import(p, b->v.Name.id, c, _PyPegen_seq_count_dots(a), EXTRA) }
| 'from' a=('.' | '...')+ 'import' b=import_from_targets {
_PyAST_ImportFrom(NULL, b, _PyPegen_seq_count_dots(a), EXTRA) }
import_from_targets[asdl_alias_seq*]:
Expand Down
26 changes: 26 additions & 0 deletions Lib/test/test_flufl.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,32 @@ def test_guido_as_bdfl(self):
# parser reports the start of the token
self.assertEqual(cm.exception.offset, 3)

def test_barry_as_bdfl_look_ma_with_no_compiler_flags(self):
# Check that the future import is handled by the parser
# even if the compiler flags are not passed.
code = "from __future__ import barry_as_FLUFL;2 {0} 3"
compile(code.format('<>'), '<BDFL test>', 'exec')
with self.assertRaises(SyntaxError) as cm:
compile(code.format('!='), '<FLUFL test>', 'exec')
self.assertRegex(str(cm.exception), "with Barry as BDFL, use '<>' instead of '!='")
self.assertIn('2 != 3', cm.exception.text)
self.assertEqual(cm.exception.filename, '<FLUFL test>')
self.assertEqual(cm.exception.lineno, 1)
self.assertEqual(cm.exception.offset, len(code) - 4)

def test_barry_as_bdfl_relative_import(self):
code = "from .__future__ import barry_as_FLUFL;2 {0} 3"
compile(code.format('!='), '<FLUFL test>', 'exec')
with self.assertRaises(SyntaxError) as cm:
compile(code.format('<>'), '<BDFL test>', 'exec')
self.assertRegex(str(cm.exception), "<BDFL test>")
self.assertIn('2 <> 3', cm.exception.text)
self.assertEqual(cm.exception.filename, '<BDFL test>')
self.assertEqual(cm.exception.lineno, 1)
self.assertEqual(cm.exception.offset, len(code) - 4)




if __name__ == '__main__':
unittest.main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
``from __future__ import barry_as_FLUFL`` now works in more contexts,
including when it is used in files, with the ``-c`` flag, and in the REPL
when there are multiple statements on the same line. Previously, it worked
only on subsequent lines in the REPL, and when the appropriate flags were
passed directly to :func:`compile`. Patch by Pablo Galindo.
15 changes: 15 additions & 0 deletions Parser/action_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -1694,3 +1694,18 @@ _PyPegen_concatenate_strings(Parser *p, asdl_expr_seq *strings,
assert(current_pos == n_elements);
return _PyAST_JoinedStr(values, lineno, col_offset, end_lineno, end_col_offset, p->arena);
}

stmt_ty
_PyPegen_checked_future_import(Parser *p, identifier module, asdl_alias_seq * names, int level,
int lineno, int col_offset, int end_lineno, int end_col_offset,
PyArena *arena) {
if (level == 0 && PyUnicode_CompareWithASCIIString(module, "__future__") == 0) {
for (Py_ssize_t i = 0; i < asdl_seq_LEN(names); i++) {
alias_ty alias = asdl_seq_GET(names, i);
if (PyUnicode_CompareWithASCIIString(alias->name, "barry_as_FLUFL") == 0) {
p->flags |= PyPARSE_BARRY_AS_BDFL;
}
}
}
return _PyAST_ImportFrom(module, names, level, lineno, col_offset, end_lineno, end_col_offset, arena);
}
2 changes: 1 addition & 1 deletion Parser/parser.c

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

2 changes: 2 additions & 0 deletions Parser/pegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,8 @@ mod_ty _PyPegen_make_module(Parser *, asdl_stmt_seq *);
void *_PyPegen_arguments_parsing_error(Parser *, expr_ty);
expr_ty _PyPegen_get_last_comprehension_item(comprehension_ty comprehension);
void *_PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args, asdl_comprehension_seq *comprehensions);
stmt_ty _PyPegen_checked_future_import(Parser *p, identifier module, asdl_alias_seq *,
int , int, int , int , int , PyArena *);

// Parser API

Expand Down
Loading