Skip to content

Commit

Permalink
[3.12] gh-104799: PEP 695 backward compatibility for ast.unparse (GH-…
Browse files Browse the repository at this point in the history
…105846) (#105862)

(cherry picked from commit 957a974)

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
  • Loading branch information
miss-islington and JelleZijlstra committed Jun 16, 2023
1 parent e6982c5 commit 5ca707d
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 3 deletions.
6 changes: 4 additions & 2 deletions Lib/ast.py
Expand Up @@ -1051,7 +1051,8 @@ def visit_ClassDef(self, node):
self.fill("@")
self.traverse(deco)
self.fill("class " + node.name)
self._type_params_helper(node.type_params)
if hasattr(node, "type_params"):
self._type_params_helper(node.type_params)
with self.delimit_if("(", ")", condition = node.bases or node.keywords):
comma = False
for e in node.bases:
Expand Down Expand Up @@ -1083,7 +1084,8 @@ def _function_helper(self, node, fill_suffix):
self.traverse(deco)
def_str = fill_suffix + " " + node.name
self.fill(def_str)
self._type_params_helper(node.type_params)
if hasattr(node, "type_params"):
self._type_params_helper(node.type_params)
with self.delimit("(", ")"):
self.traverse(node.args)
if node.returns:
Expand Down
74 changes: 73 additions & 1 deletion Lib/test/test_unparse.py
@@ -1,4 +1,4 @@
"""Tests for the unparse.py script in the Tools/parser directory."""
"""Tests for ast.unparse."""

import unittest
import test.support
Expand Down Expand Up @@ -625,6 +625,78 @@ def test_star_expr_assign_target_multiple(self):
self.check_src_roundtrip("a, b = [c, d] = e, f = g")


class ManualASTCreationTestCase(unittest.TestCase):
"""Test that AST nodes created without a type_params field unparse correctly."""

def test_class(self):
node = ast.ClassDef(name="X", bases=[], keywords=[], body=[ast.Pass()], decorator_list=[])
ast.fix_missing_locations(node)
self.assertEqual(ast.unparse(node), "class X:\n pass")

def test_class_with_type_params(self):
node = ast.ClassDef(name="X", bases=[], keywords=[], body=[ast.Pass()], decorator_list=[],
type_params=[ast.TypeVar("T")])
ast.fix_missing_locations(node)
self.assertEqual(ast.unparse(node), "class X[T]:\n pass")

def test_function(self):
node = ast.FunctionDef(
name="f",
args=ast.arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]),
body=[ast.Pass()],
decorator_list=[],
returns=None,
)
ast.fix_missing_locations(node)
self.assertEqual(ast.unparse(node), "def f():\n pass")

def test_function_with_type_params(self):
node = ast.FunctionDef(
name="f",
args=ast.arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]),
body=[ast.Pass()],
decorator_list=[],
returns=None,
type_params=[ast.TypeVar("T")],
)
ast.fix_missing_locations(node)
self.assertEqual(ast.unparse(node), "def f[T]():\n pass")

def test_function_with_type_params_and_bound(self):
node = ast.FunctionDef(
name="f",
args=ast.arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]),
body=[ast.Pass()],
decorator_list=[],
returns=None,
type_params=[ast.TypeVar("T", bound=ast.Name("int"))],
)
ast.fix_missing_locations(node)
self.assertEqual(ast.unparse(node), "def f[T: int]():\n pass")

def test_async_function(self):
node = ast.AsyncFunctionDef(
name="f",
args=ast.arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]),
body=[ast.Pass()],
decorator_list=[],
returns=None,
)
ast.fix_missing_locations(node)
self.assertEqual(ast.unparse(node), "async def f():\n pass")

def test_async_function_with_type_params(self):
node = ast.AsyncFunctionDef(
name="f",
args=ast.arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]),
body=[ast.Pass()],
decorator_list=[],
returns=None,
type_params=[ast.TypeVar("T")],
)
ast.fix_missing_locations(node)
self.assertEqual(ast.unparse(node), "async def f[T]():\n pass")


class DirectoryTestCase(ASTTestCase):
"""Test roundtrip behaviour on all files in Lib and Lib/test."""
Expand Down
@@ -0,0 +1,3 @@
Enable :func:`ast.unparse` to unparse function and class definitions created
without the new ``type_params`` field from :pep:`695`. Patch by Jelle
Zijlstra.

0 comments on commit 5ca707d

Please sign in to comment.