https://github.com/python/cpython/commit/6a08a753b702ac63c9b6ac58dd204d1fe9662e9d
commit: 6a08a753b702ac63c9b6ac58dd204d1fe9662e9d
branch: main
author: Wulian <[email protected]>
committer: ambv <[email protected]>
date: 2024-10-14T15:53:50+02:00
summary:

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

Co-authored-by: Nice Zombies <[email protected]>
Co-authored-by: Ɓukasz Langa <[email protected]>

files:
A Misc/NEWS.d/next/Library/2024-10-05-15-49-53.gh-issue-124960.Bol9hT.rst
M Lib/_pyrepl/console.py
M Lib/codeop.py
M Lib/test/test_pyrepl/test_interact.py

diff --git a/Lib/_pyrepl/console.py b/Lib/_pyrepl/console.py
index 3e72a56807f6fb..03266c4dfc2dd8 100644
--- a/Lib/_pyrepl/console.py
+++ b/Lib/_pyrepl/console.py
@@ -174,7 +174,13 @@ def _excepthook(self, typ, value, tb):
 
     def runsource(self, source, filename="<input>", symbol="single"):
         try:
-            tree = ast.parse(source)
+            tree = self.compile.compiler(
+                source,
+                filename,
+                "exec",
+                ast.PyCF_ONLY_AST,
+                incomplete_input=False,
+            )
         except (SyntaxError, OverflowError, ValueError):
             self.showsyntaxerror(filename, source=source)
             return False
@@ -185,7 +191,7 @@ def runsource(self, source, filename="<input>", 
symbol="single"):
             the_symbol = symbol if stmt is last_stmt else "exec"
             item = wrapper([stmt])
             try:
-                code = self.compile.compiler(item, filename, the_symbol, 
dont_inherit=True)
+                code = self.compile.compiler(item, filename, the_symbol)
             except SyntaxError as e:
                 if e.args[0] == "'await' outside function":
                     python = os.path.basename(sys.executable)
diff --git a/Lib/codeop.py b/Lib/codeop.py
index a0276b52d484e3..adf000ba29f88c 100644
--- a/Lib/codeop.py
+++ b/Lib/codeop.py
@@ -44,6 +44,7 @@
 # Caveat emptor: These flags are undocumented on purpose and depending
 # on their effect outside the standard library is **unsupported**.
 PyCF_DONT_IMPLY_DEDENT = 0x200
+PyCF_ONLY_AST = 0x400
 PyCF_ALLOW_INCOMPLETE_INPUT = 0x4000
 
 def _maybe_compile(compiler, source, filename, symbol):
@@ -109,12 +110,14 @@ class Compile:
     def __init__(self):
         self.flags = PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT
 
-    def __call__(self, source, filename, symbol, **kwargs):
-        flags = self.flags
+    def __call__(self, source, filename, symbol, flags=0, **kwargs):
+        flags |= self.flags
         if kwargs.get('incomplete_input', True) is False:
             flags &= ~PyCF_DONT_IMPLY_DEDENT
             flags &= ~PyCF_ALLOW_INCOMPLETE_INPUT
         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:
             if codeob.co_flags & feature.compiler_flag:
                 self.flags |= feature.compiler_flag
diff --git a/Lib/test/test_pyrepl/test_interact.py 
b/Lib/test/test_pyrepl/test_interact.py
index b7adaffbac0e22..0c6df4e5dae869 100644
--- a/Lib/test/test_pyrepl/test_interact.py
+++ b/Lib/test/test_pyrepl/test_interact.py
@@ -119,13 +119,38 @@ def 
test_runsource_shows_syntax_error_for_failed_compilation(self):
 
     def test_no_active_future(self):
         console = InteractiveColoredConsole()
-        source = "x: int = 1; print(__annotate__(1))"
+        source = dedent("""\
+        x: int = 1
+        print(__annotate__(1))
+        """)
         f = io.StringIO()
         with contextlib.redirect_stdout(f):
             result = console.runsource(source)
         self.assertFalse(result)
         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):
     def test_invalid_syntax_single_line(self):
diff --git 
a/Misc/NEWS.d/next/Library/2024-10-05-15-49-53.gh-issue-124960.Bol9hT.rst 
b/Misc/NEWS.d/next/Library/2024-10-05-15-49-53.gh-issue-124960.Bol9hT.rst
new file mode 100644
index 00000000000000..332d6bb54d80c7
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-10-05-15-49-53.gh-issue-124960.Bol9hT.rst
@@ -0,0 +1 @@
+Fix support for the ``barry_as_FLUFL`` future flag in the new REPL.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to