From d312e3e890461b11f6ae131d9dfe4a13ed336ccc Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Wed, 5 Apr 2023 13:02:15 +0100 Subject: [PATCH 1/3] support displaying ast types --- devtools/prettier.py | 9 +++++++++ tests/test_prettier.py | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/devtools/prettier.py b/devtools/prettier.py index 7489d33..b076caa 100644 --- a/devtools/prettier.py +++ b/devtools/prettier.py @@ -1,3 +1,4 @@ +import ast import io import os from collections import OrderedDict @@ -80,6 +81,7 @@ def __init__( (bytearray, self._format_bytearray), (generator_types, self._format_generator), # put these last as the check can be slow + (ast.AST, self._format_ast_expression), (LaxMapping, self._format_dict), (DataClassType, self._format_dataclass), (SQLAlchemyClassType, self._format_sqlalchemy_class), @@ -240,6 +242,13 @@ def _format_bytearray(self, value: 'Any', _: str, indent_current: int, indent_ne lines = self._wrap_lines(bytes(value), indent_new) self._str_lines(lines, indent_current, indent_new) + def _format_ast_expression(self, value: ast.AST, _: str, indent_current: int, indent_new: int) -> None: + s = ast.dump(value, indent=self._indent_step) + lines = s.splitlines(True) + self._stream.write(lines[0]) + for line in lines[1:]: + self._stream.write(indent_current * self._c + line) + def _format_dataclass(self, value: 'Any', _: str, indent_current: int, indent_new: int) -> None: self._format_fields(value, value.__dict__.items(), indent_current, indent_new) diff --git a/tests/test_prettier.py b/tests/test_prettier.py index 364447b..c8aa6af 100644 --- a/tests/test_prettier.py +++ b/tests/test_prettier.py @@ -1,3 +1,4 @@ +import ast import os import string from collections import Counter, OrderedDict, namedtuple @@ -457,3 +458,24 @@ class User(SQLAlchemyBase): " nickname='test',\n" ")" ) + + +def test_ast_expr(): + assert pformat(ast.parse('print(1, 2, round(3))', mode='eval')) == ( + "Expression(" + "\n body=Call(" + "\n func=Name(id='print', ctx=Load())," + "\n args=[" + "\n Constant(value=1)," + "\n Constant(value=2)," + "\n Call(" + "\n func=Name(id='round', ctx=Load())," + "\n args=[" + "\n Constant(value=3)]," + "\n keywords=[])]," + "\n keywords=[]))" + ) + + +def test_ast_module(): + assert pformat(ast.parse('print(1, 2, round(3))')).startswith('Module(\n body=[') From d926e9969fb2c4421948a8e2aafffb63070402d6 Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Wed, 5 Apr 2023 13:06:24 +0100 Subject: [PATCH 2/3] support 3.7 & 3.8 --- devtools/prettier.py | 6 +++++- requirements/testing.in | 4 +++- requirements/testing.txt | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/devtools/prettier.py b/devtools/prettier.py index b076caa..e378030 100644 --- a/devtools/prettier.py +++ b/devtools/prettier.py @@ -243,7 +243,11 @@ def _format_bytearray(self, value: 'Any', _: str, indent_current: int, indent_ne self._str_lines(lines, indent_current, indent_new) def _format_ast_expression(self, value: ast.AST, _: str, indent_current: int, indent_new: int) -> None: - s = ast.dump(value, indent=self._indent_step) + try: + s = ast.dump(value, indent=self._indent_step) + except TypeError: + # no indent before 3.9 + s = ast.dump(value) lines = s.splitlines(True) self._stream.write(lines[0]) for line in lines[1:]: diff --git a/requirements/testing.in b/requirements/testing.in index 7b1ad14..1976d79 100644 --- a/requirements/testing.in +++ b/requirements/testing.in @@ -5,7 +5,9 @@ pytest-mock pytest-pretty # these packages are used in tests so install the latest version pydantic -asyncpg +# no binaries for 3.7 +asyncpg; python_version>='3.8' +# no version is compatible with 3.7 and 3.11 numpy; python_version>='3.8' multidict; python_version>='3.8' sqlalchemy diff --git a/requirements/testing.txt b/requirements/testing.txt index b62eaba..2ce58bf 100644 --- a/requirements/testing.txt +++ b/requirements/testing.txt @@ -4,7 +4,7 @@ # # pip-compile --output-file=requirements/testing.txt --resolver=backtracking requirements/testing.in # -asyncpg==0.27.0 +asyncpg==0.27.0 ; python_version >= "3.8" # via -r requirements/testing.in attrs==22.2.0 # via pytest From b7edd9aaf41fe263792987ee41f80fb7639c977f Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Wed, 5 Apr 2023 13:09:40 +0100 Subject: [PATCH 3/3] skip tests on older python --- tests/test_prettier.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_prettier.py b/tests/test_prettier.py index c8aa6af..6a0247c 100644 --- a/tests/test_prettier.py +++ b/tests/test_prettier.py @@ -1,6 +1,7 @@ import ast import os import string +import sys from collections import Counter, OrderedDict, namedtuple from dataclasses import dataclass from typing import List @@ -460,6 +461,7 @@ class User(SQLAlchemyBase): ) +@pytest.mark.skipif(sys.version_info < (3, 9), reason='no indent on older versions') def test_ast_expr(): assert pformat(ast.parse('print(1, 2, round(3))', mode='eval')) == ( "Expression(" @@ -477,5 +479,6 @@ def test_ast_expr(): ) +@pytest.mark.skipif(sys.version_info < (3, 9), reason='no indent on older versions') def test_ast_module(): assert pformat(ast.parse('print(1, 2, round(3))')).startswith('Module(\n body=[')