From 466c4dec28499202e46b8224279f265a2dabf9d8 Mon Sep 17 00:00:00 2001 From: Lorenz Neureuter Date: Sun, 21 Dec 2025 11:08:42 -0500 Subject: [PATCH] Remove typed-ast --- Pipfile | 1 - black.py | 43 ++++++++++++++++---------------------- setup.py | 1 - tests/data/expression.diff | 2 +- tests/data/expression.py | 4 ++-- tests/test_black.py | 20 +++++++++++++++--- 6 files changed, 38 insertions(+), 33 deletions(-) diff --git a/Pipfile b/Pipfile index 3784810e5a0..71d5d7f5ac9 100644 --- a/Pipfile +++ b/Pipfile @@ -11,7 +11,6 @@ appdirs = "*" toml = ">=0.9.4" black = {path = ".",extras = ["d"],editable = true} aiohttp-cors = "*" -typed-ast = "==1.4.0" regex = ">=2019.8" pathspec = ">=0.6" diff --git a/black.py b/black.py index f783a95c0fc..925b052a592 100644 --- a/black.py +++ b/black.py @@ -42,7 +42,6 @@ from attr import dataclass, evolve, Factory import click import toml -from typed_ast import ast3, ast27 from pathspec import PathSpec # lib2to3 fork @@ -3667,36 +3666,33 @@ def __str__(self) -> str: return ", ".join(report) + "." -def parse_ast(src: str) -> Union[ast.AST, ast3.AST, ast27.AST]: +def parse_ast(src: str) -> ast.AST: filename = "" if sys.version_info >= (3, 8): # TODO: support Python 4+ ;) for minor_version in range(sys.version_info[1], 4, -1): try: - return ast.parse(src, filename, feature_version=(3, minor_version)) - except SyntaxError: - continue - else: - for feature_version in (7, 6): - try: - return ast3.parse(src, filename, feature_version=feature_version) + return ast.parse( + src, + filename, + feature_version=(3, minor_version), + type_comments=True, + ) except SyntaxError: continue - return ast27.parse(src) + return ast.parse(src, filename) -def _fixup_ast_constants( - node: Union[ast.AST, ast3.AST, ast27.AST] -) -> Union[ast.AST, ast3.AST, ast27.AST]: +def _fixup_ast_constants(node: ast.AST) -> ast.AST: """Map ast nodes deprecated in 3.8 to Constant.""" - if isinstance(node, (ast.Str, ast3.Str, ast27.Str, ast.Bytes, ast3.Bytes)): + if isinstance(node, (ast.Str, ast.Bytes)): return ast.Constant(value=node.s) - if isinstance(node, (ast.Num, ast3.Num, ast27.Num)): + if isinstance(node, ast.Num): return ast.Constant(value=node.n) - if isinstance(node, (ast.NameConstant, ast3.NameConstant)): + if isinstance(node, ast.NameConstant): return ast.Constant(value=node.value) return node @@ -3705,7 +3701,7 @@ def _fixup_ast_constants( def assert_equivalent(src: str, dst: str) -> None: """Raise AssertionError if `src` and `dst` aren't equivalent.""" - def _v(node: Union[ast.AST, ast3.AST, ast27.AST], depth: int = 0) -> Iterator[str]: + def _v(node: ast.AST, depth: int = 0) -> Iterator[str]: """Simple visitor generating strings to compare ASTs by content.""" node = _fixup_ast_constants(node) @@ -3714,10 +3710,7 @@ def _v(node: Union[ast.AST, ast3.AST, ast27.AST], depth: int = 0) -> Iterator[st for field in sorted(node._fields): # TypeIgnore has only one field 'lineno' which breaks this comparison - type_ignore_classes = (ast3.TypeIgnore, ast27.TypeIgnore) - if sys.version_info >= (3, 8): - type_ignore_classes += (ast.TypeIgnore,) - if isinstance(node, type_ignore_classes): + if isinstance(node, ast.TypeIgnore): break try: @@ -3733,16 +3726,16 @@ def _v(node: Union[ast.AST, ast3.AST, ast27.AST], depth: int = 0) -> Iterator[st # parentheses and they change the AST. if ( field == "targets" - and isinstance(node, (ast.Delete, ast3.Delete, ast27.Delete)) - and isinstance(item, (ast.Tuple, ast3.Tuple, ast27.Tuple)) + and isinstance(node, ast.Delete) + and isinstance(item, ast.Tuple) ): for item in item.elts: yield from _v(item, depth + 2) - elif isinstance(item, (ast.AST, ast3.AST, ast27.AST)): + elif isinstance(item, ast.AST): yield from _v(item, depth + 2) - elif isinstance(value, (ast.AST, ast3.AST, ast27.AST)): + elif isinstance(value, ast.AST): yield from _v(value, depth + 2) else: diff --git a/setup.py b/setup.py index 614a8d6051e..55689545811 100644 --- a/setup.py +++ b/setup.py @@ -39,7 +39,6 @@ def get_long_description() -> str: "attrs>=18.1.0", "appdirs", "toml>=0.9.4", - "typed-ast>=1.4.0", "regex", "pathspec>=0.6, <1", ], diff --git a/tests/data/expression.diff b/tests/data/expression.diff index 629e1012f87..dfb159bc781 100644 --- a/tests/data/expression.diff +++ b/tests/data/expression.diff @@ -179,7 +179,7 @@ -((i ** 2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))) +((i ** 2) for i, _ in ((1, "a"), (2, "b"), (3, "c"))) (((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3)) - (*starred) + (*starred,) -{"id": "1","type": "type","started_at": now(),"ended_at": now() + timedelta(days=10),"priority": 1,"import_session_id": 1,**kwargs} +{ + "id": "1", diff --git a/tests/data/expression.py b/tests/data/expression.py index 3bcf52b54c4..6a04db8b1c4 100644 --- a/tests/data/expression.py +++ b/tests/data/expression.py @@ -146,7 +146,7 @@ ((i ** 2) for i in (1, 2, 3)) ((i ** 2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))) (((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3)) -(*starred) +(*starred,) {"id": "1","type": "type","started_at": now(),"ended_at": now() + timedelta(days=10),"priority": 1,"import_session_id": 1,**kwargs} a = (1,) b = 1, @@ -431,7 +431,7 @@ async def f(): ((i ** 2) for i in (1, 2, 3)) ((i ** 2) for i, _ in ((1, "a"), (2, "b"), (3, "c"))) (((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3)) -(*starred) +(*starred,) { "id": "1", "type": "type", diff --git a/tests/test_black.py b/tests/test_black.py index 93f853bae4f..2e0f13aa951 100644 --- a/tests/test_black.py +++ b/tests/test_black.py @@ -26,6 +26,14 @@ from aiohttp import web except ImportError: has_blackd_deps = False + + class AioHTTPTestCase: + pass + + def unittest_run_loop(func: Any) -> Any: + return func + + else: has_blackd_deps = True @@ -535,6 +543,7 @@ def test_numeric_literals_py2(self) -> None: self.assertFormatEqual(expected, actual) black.assert_stable(source, actual, black.FileMode()) + @unittest.skip("skip python2") @patch("black.dump_to_file", dump_to_stderr) def test_python2(self) -> None: source, expected = read_data("python2") @@ -543,6 +552,7 @@ def test_python2(self) -> None: black.assert_equivalent(source, actual) black.assert_stable(source, actual, black.FileMode()) + @unittest.skip("skip python2") @patch("black.dump_to_file", dump_to_stderr) def test_python2_print_function(self) -> None: source, expected = read_data("python2_print_function") @@ -552,6 +562,7 @@ def test_python2_print_function(self) -> None: black.assert_equivalent(source, actual) black.assert_stable(source, actual, mode) + @unittest.skip("skip python2") @patch("black.dump_to_file", dump_to_stderr) def test_python2_unicode_literals(self) -> None: source, expected = read_data("python2_unicode_literals") @@ -1571,7 +1582,7 @@ def test_symlink_out_of_root_directory(self) -> None: def test_shhh_click(self) -> None: try: from click import _unicodefun # type: ignore - except ModuleNotFoundError: + except ImportError: self.skipTest("Incompatible Click version") if not hasattr(_unicodefun, "_verify_python3_env"): self.skipTest("Incompatible Click version") @@ -1615,8 +1626,11 @@ def test_blackd_main(self) -> None: class BlackDTestCase(AioHTTPTestCase): - async def get_application(self) -> web.Application: - return blackd.make_app() + + if has_blackd_deps: + + async def get_application(self) -> web.Application: + return blackd.make_app() # TODO: remove these decorators once the below is released # https://github.com/aio-libs/aiohttp/pull/3727