[3.13] gh-124960: Fixed `barry_as_FLUFL` future flag does not work in new REPL (#124999) (#125475)

gh-124960: Fixed `barry_as_FLUFL` future flag does not work in new REPL (#124999)

Co-authored-by: Wulian <xiguawulian@gmail.com>
Co-authored-by: Nice Zombies <nineteendo19d0@gmail.com>
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
(cherry picked from commit 6a08a753b7)
This commit is contained in:
Nice Zombies 2024-10-14 20:00:45 +02:00 committed by GitHub
parent cbcdf34a4b
commit d54dbd62cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 40 additions and 5 deletions

View File

@ -174,7 +174,13 @@ def _excepthook(self, typ, value, tb):
def runsource(self, source, filename="<input>", symbol="single"): def runsource(self, source, filename="<input>", symbol="single"):
try: try:
tree = ast.parse(source) tree = self.compile.compiler(
source,
filename,
"exec",
ast.PyCF_ONLY_AST,
incomplete_input=False,
)
except (SyntaxError, OverflowError, ValueError): except (SyntaxError, OverflowError, ValueError):
self.showsyntaxerror(filename, source=source) self.showsyntaxerror(filename, source=source)
return False return False
@ -185,7 +191,7 @@ def runsource(self, source, filename="<input>", symbol="single"):
the_symbol = symbol if stmt is last_stmt else "exec" the_symbol = symbol if stmt is last_stmt else "exec"
item = wrapper([stmt]) item = wrapper([stmt])
try: try:
code = self.compile.compiler(item, filename, the_symbol, dont_inherit=True) code = self.compile.compiler(item, filename, the_symbol)
except SyntaxError as e: except SyntaxError as e:
if e.args[0] == "'await' outside function": if e.args[0] == "'await' outside function":
python = os.path.basename(sys.executable) python = os.path.basename(sys.executable)

View File

@ -44,6 +44,7 @@
# Caveat emptor: These flags are undocumented on purpose and depending # Caveat emptor: These flags are undocumented on purpose and depending
# on their effect outside the standard library is **unsupported**. # on their effect outside the standard library is **unsupported**.
PyCF_DONT_IMPLY_DEDENT = 0x200 PyCF_DONT_IMPLY_DEDENT = 0x200
PyCF_ONLY_AST = 0x400
PyCF_ALLOW_INCOMPLETE_INPUT = 0x4000 PyCF_ALLOW_INCOMPLETE_INPUT = 0x4000
def _maybe_compile(compiler, source, filename, symbol): def _maybe_compile(compiler, source, filename, symbol):
@ -109,12 +110,14 @@ class Compile:
def __init__(self): def __init__(self):
self.flags = PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT self.flags = PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT
def __call__(self, source, filename, symbol, **kwargs): def __call__(self, source, filename, symbol, flags=0, **kwargs):
flags = self.flags flags |= self.flags
if kwargs.get('incomplete_input', True) is False: if kwargs.get('incomplete_input', True) is False:
flags &= ~PyCF_DONT_IMPLY_DEDENT flags &= ~PyCF_DONT_IMPLY_DEDENT
flags &= ~PyCF_ALLOW_INCOMPLETE_INPUT flags &= ~PyCF_ALLOW_INCOMPLETE_INPUT
codeob = compile(source, filename, symbol, flags, True) codeob = compile(source, filename, symbol, flags, True)
if flags & PyCF_ONLY_AST:
return codeob # this is an ast.Module in this case
for feature in _features: for feature in _features:
if codeob.co_flags & feature.compiler_flag: if codeob.co_flags & feature.compiler_flag:
self.flags |= feature.compiler_flag self.flags |= feature.compiler_flag

View File

@ -119,13 +119,38 @@ def test_runsource_shows_syntax_error_for_failed_compilation(self):
def test_no_active_future(self): def test_no_active_future(self):
console = InteractiveColoredConsole() console = InteractiveColoredConsole()
source = "x: int = 1; print(__annotations__)" source = dedent("""\
x: int = 1
print(__annotations__)
""")
f = io.StringIO() f = io.StringIO()
with contextlib.redirect_stdout(f): with contextlib.redirect_stdout(f):
result = console.runsource(source) result = console.runsource(source)
self.assertFalse(result) self.assertFalse(result)
self.assertEqual(f.getvalue(), "{'x': <class 'int'>}\n") self.assertEqual(f.getvalue(), "{'x': <class 'int'>}\n")
def test_future_annotations(self):
console = InteractiveColoredConsole()
source = dedent("""\
from __future__ import annotations
def g(x: int): ...
print(g.__annotations__)
""")
f = io.StringIO()
with contextlib.redirect_stdout(f):
result = console.runsource(source)
self.assertFalse(result)
self.assertEqual(f.getvalue(), "{'x': 'int'}\n")
def test_future_barry_as_flufl(self):
console = InteractiveColoredConsole()
f = io.StringIO()
with contextlib.redirect_stdout(f):
result = console.runsource("from __future__ import barry_as_FLUFL\n")
result = console.runsource("""print("black" <> 'blue')\n""")
self.assertFalse(result)
self.assertEqual(f.getvalue(), "True\n")
class TestMoreLines(unittest.TestCase): class TestMoreLines(unittest.TestCase):
def test_invalid_syntax_single_line(self): def test_invalid_syntax_single_line(self):

View File

@ -0,0 +1 @@
Fix support for the ``barry_as_FLUFL`` future flag in the new REPL.