Introduce DebugVisitor.show() + tests
This commit is contained in:
parent
c98a6f134f
commit
7e1c5b2ba6
9
black.py
9
black.py
@ -320,6 +320,15 @@ def visit_default(self, node: LN) -> Iterator[T]:
|
||||
out(f' {node.prefix!r}', fg='green', bold=False, nl=False)
|
||||
out(f' {node.value!r}', fg='blue', bold=False)
|
||||
|
||||
@classmethod
|
||||
def show(cls, code: str) -> None:
|
||||
"""Pretty-prints a given string of `code`.
|
||||
|
||||
Convenience method for debugging.
|
||||
"""
|
||||
v: DebugVisitor[None] = DebugVisitor()
|
||||
list(v.visit(lib2to3_parse(code)))
|
||||
|
||||
|
||||
KEYWORDS = set(keyword.kwlist)
|
||||
WHITESPACE = {token.DEDENT, token.INDENT, token.NEWLINE}
|
||||
|
804
tests/debug_visitor.out
Normal file
804
tests/debug_visitor.out
Normal file
@ -0,0 +1,804 @@
|
||||
file_input
|
||||
decorated
|
||||
decorator
|
||||
AT
|
||||
'@'
|
||||
NAME
|
||||
'dataclass'
|
||||
NEWLINE
|
||||
'\n'
|
||||
/decorator
|
||||
classdef
|
||||
NAME
|
||||
'class'
|
||||
NAME
|
||||
' '
|
||||
'DebugVisitor'
|
||||
LPAR
|
||||
'('
|
||||
power
|
||||
NAME
|
||||
'Visitor'
|
||||
trailer
|
||||
LSQB
|
||||
'['
|
||||
NAME
|
||||
'T'
|
||||
RSQB
|
||||
']'
|
||||
/trailer
|
||||
/power
|
||||
RPAR
|
||||
')'
|
||||
COLON
|
||||
':'
|
||||
suite
|
||||
NEWLINE
|
||||
'\n'
|
||||
INDENT
|
||||
' '
|
||||
simple_stmt
|
||||
expr_stmt
|
||||
NAME
|
||||
'tree_depth'
|
||||
annassign
|
||||
COLON
|
||||
':'
|
||||
NAME
|
||||
' '
|
||||
'int'
|
||||
EQUAL
|
||||
' '
|
||||
'='
|
||||
NUMBER
|
||||
' '
|
||||
'0'
|
||||
/annassign
|
||||
/expr_stmt
|
||||
NEWLINE
|
||||
'\n'
|
||||
/simple_stmt
|
||||
funcdef
|
||||
NAME
|
||||
'\n '
|
||||
'def'
|
||||
NAME
|
||||
' '
|
||||
'visit_default'
|
||||
parameters
|
||||
LPAR
|
||||
'('
|
||||
typedargslist
|
||||
NAME
|
||||
'self'
|
||||
COMMA
|
||||
','
|
||||
tname
|
||||
NAME
|
||||
' '
|
||||
'node'
|
||||
COLON
|
||||
':'
|
||||
NAME
|
||||
' '
|
||||
'LN'
|
||||
/tname
|
||||
/typedargslist
|
||||
RPAR
|
||||
')'
|
||||
/parameters
|
||||
RARROW
|
||||
' '
|
||||
'->'
|
||||
power
|
||||
NAME
|
||||
' '
|
||||
'Iterator'
|
||||
trailer
|
||||
LSQB
|
||||
'['
|
||||
NAME
|
||||
'T'
|
||||
RSQB
|
||||
']'
|
||||
/trailer
|
||||
/power
|
||||
COLON
|
||||
':'
|
||||
suite
|
||||
NEWLINE
|
||||
'\n'
|
||||
INDENT
|
||||
' '
|
||||
simple_stmt
|
||||
expr_stmt
|
||||
NAME
|
||||
'indent'
|
||||
EQUAL
|
||||
' '
|
||||
'='
|
||||
term
|
||||
STRING
|
||||
' '
|
||||
"' '"
|
||||
STAR
|
||||
' '
|
||||
'*'
|
||||
atom
|
||||
LPAR
|
||||
' '
|
||||
'('
|
||||
term
|
||||
NUMBER
|
||||
'2'
|
||||
STAR
|
||||
' '
|
||||
'*'
|
||||
power
|
||||
NAME
|
||||
' '
|
||||
'self'
|
||||
trailer
|
||||
DOT
|
||||
'.'
|
||||
NAME
|
||||
'tree_depth'
|
||||
/trailer
|
||||
/power
|
||||
/term
|
||||
RPAR
|
||||
')'
|
||||
/atom
|
||||
/term
|
||||
/expr_stmt
|
||||
NEWLINE
|
||||
'\n'
|
||||
/simple_stmt
|
||||
if_stmt
|
||||
NAME
|
||||
' '
|
||||
'if'
|
||||
power
|
||||
NAME
|
||||
' '
|
||||
'isinstance'
|
||||
trailer
|
||||
LPAR
|
||||
'('
|
||||
arglist
|
||||
NAME
|
||||
'node'
|
||||
COMMA
|
||||
','
|
||||
NAME
|
||||
' '
|
||||
'Node'
|
||||
/arglist
|
||||
RPAR
|
||||
')'
|
||||
/trailer
|
||||
/power
|
||||
COLON
|
||||
':'
|
||||
suite
|
||||
NEWLINE
|
||||
'\n'
|
||||
INDENT
|
||||
' '
|
||||
simple_stmt
|
||||
expr_stmt
|
||||
NAME
|
||||
'_type'
|
||||
EQUAL
|
||||
' '
|
||||
'='
|
||||
power
|
||||
NAME
|
||||
' '
|
||||
'type_repr'
|
||||
trailer
|
||||
LPAR
|
||||
'('
|
||||
power
|
||||
NAME
|
||||
'node'
|
||||
trailer
|
||||
DOT
|
||||
'.'
|
||||
NAME
|
||||
'type'
|
||||
/trailer
|
||||
/power
|
||||
RPAR
|
||||
')'
|
||||
/trailer
|
||||
/power
|
||||
/expr_stmt
|
||||
NEWLINE
|
||||
'\n'
|
||||
/simple_stmt
|
||||
simple_stmt
|
||||
power
|
||||
NAME
|
||||
' '
|
||||
'out'
|
||||
trailer
|
||||
LPAR
|
||||
'('
|
||||
arglist
|
||||
STRING
|
||||
"f'{indent}{_type}'"
|
||||
COMMA
|
||||
','
|
||||
argument
|
||||
NAME
|
||||
' '
|
||||
'fg'
|
||||
EQUAL
|
||||
'='
|
||||
STRING
|
||||
"'yellow'"
|
||||
/argument
|
||||
/arglist
|
||||
RPAR
|
||||
')'
|
||||
/trailer
|
||||
/power
|
||||
NEWLINE
|
||||
'\n'
|
||||
/simple_stmt
|
||||
simple_stmt
|
||||
expr_stmt
|
||||
power
|
||||
NAME
|
||||
' '
|
||||
'self'
|
||||
trailer
|
||||
DOT
|
||||
'.'
|
||||
NAME
|
||||
'tree_depth'
|
||||
/trailer
|
||||
/power
|
||||
PLUSEQUAL
|
||||
' '
|
||||
'+='
|
||||
NUMBER
|
||||
' '
|
||||
'1'
|
||||
/expr_stmt
|
||||
NEWLINE
|
||||
'\n'
|
||||
/simple_stmt
|
||||
for_stmt
|
||||
NAME
|
||||
' '
|
||||
'for'
|
||||
NAME
|
||||
' '
|
||||
'child'
|
||||
NAME
|
||||
' '
|
||||
'in'
|
||||
power
|
||||
NAME
|
||||
' '
|
||||
'node'
|
||||
trailer
|
||||
DOT
|
||||
'.'
|
||||
NAME
|
||||
'children'
|
||||
/trailer
|
||||
/power
|
||||
COLON
|
||||
':'
|
||||
suite
|
||||
NEWLINE
|
||||
'\n'
|
||||
INDENT
|
||||
' '
|
||||
simple_stmt
|
||||
yield_expr
|
||||
NAME
|
||||
'yield'
|
||||
yield_arg
|
||||
NAME
|
||||
' '
|
||||
'from'
|
||||
power
|
||||
NAME
|
||||
' '
|
||||
'self'
|
||||
trailer
|
||||
DOT
|
||||
'.'
|
||||
NAME
|
||||
'visit'
|
||||
/trailer
|
||||
trailer
|
||||
LPAR
|
||||
'('
|
||||
NAME
|
||||
'child'
|
||||
RPAR
|
||||
')'
|
||||
/trailer
|
||||
/power
|
||||
/yield_arg
|
||||
/yield_expr
|
||||
NEWLINE
|
||||
'\n'
|
||||
/simple_stmt
|
||||
DEDENT
|
||||
''
|
||||
/suite
|
||||
/for_stmt
|
||||
simple_stmt
|
||||
expr_stmt
|
||||
power
|
||||
NAME
|
||||
'\n '
|
||||
'self'
|
||||
trailer
|
||||
DOT
|
||||
'.'
|
||||
NAME
|
||||
'tree_depth'
|
||||
/trailer
|
||||
/power
|
||||
MINEQUAL
|
||||
' '
|
||||
'-='
|
||||
NUMBER
|
||||
' '
|
||||
'1'
|
||||
/expr_stmt
|
||||
NEWLINE
|
||||
'\n'
|
||||
/simple_stmt
|
||||
simple_stmt
|
||||
power
|
||||
NAME
|
||||
' '
|
||||
'out'
|
||||
trailer
|
||||
LPAR
|
||||
'('
|
||||
arglist
|
||||
STRING
|
||||
"f'{indent}/{_type}'"
|
||||
COMMA
|
||||
','
|
||||
argument
|
||||
NAME
|
||||
' '
|
||||
'fg'
|
||||
EQUAL
|
||||
'='
|
||||
STRING
|
||||
"'yellow'"
|
||||
/argument
|
||||
COMMA
|
||||
','
|
||||
argument
|
||||
NAME
|
||||
' '
|
||||
'bold'
|
||||
EQUAL
|
||||
'='
|
||||
NAME
|
||||
'False'
|
||||
/argument
|
||||
/arglist
|
||||
RPAR
|
||||
')'
|
||||
/trailer
|
||||
/power
|
||||
NEWLINE
|
||||
'\n'
|
||||
/simple_stmt
|
||||
DEDENT
|
||||
''
|
||||
/suite
|
||||
NAME
|
||||
' '
|
||||
'else'
|
||||
COLON
|
||||
':'
|
||||
suite
|
||||
NEWLINE
|
||||
'\n'
|
||||
INDENT
|
||||
' '
|
||||
simple_stmt
|
||||
expr_stmt
|
||||
NAME
|
||||
'_type'
|
||||
EQUAL
|
||||
' '
|
||||
'='
|
||||
power
|
||||
NAME
|
||||
' '
|
||||
'token'
|
||||
trailer
|
||||
DOT
|
||||
'.'
|
||||
NAME
|
||||
'tok_name'
|
||||
/trailer
|
||||
trailer
|
||||
DOT
|
||||
'.'
|
||||
NAME
|
||||
'get'
|
||||
/trailer
|
||||
trailer
|
||||
LPAR
|
||||
'('
|
||||
arglist
|
||||
power
|
||||
NAME
|
||||
'node'
|
||||
trailer
|
||||
DOT
|
||||
'.'
|
||||
NAME
|
||||
'type'
|
||||
/trailer
|
||||
/power
|
||||
COMMA
|
||||
','
|
||||
power
|
||||
NAME
|
||||
' '
|
||||
'str'
|
||||
trailer
|
||||
LPAR
|
||||
'('
|
||||
power
|
||||
NAME
|
||||
'node'
|
||||
trailer
|
||||
DOT
|
||||
'.'
|
||||
NAME
|
||||
'type'
|
||||
/trailer
|
||||
/power
|
||||
RPAR
|
||||
')'
|
||||
/trailer
|
||||
/power
|
||||
/arglist
|
||||
RPAR
|
||||
')'
|
||||
/trailer
|
||||
/power
|
||||
/expr_stmt
|
||||
NEWLINE
|
||||
'\n'
|
||||
/simple_stmt
|
||||
simple_stmt
|
||||
power
|
||||
NAME
|
||||
' '
|
||||
'out'
|
||||
trailer
|
||||
LPAR
|
||||
'('
|
||||
arglist
|
||||
STRING
|
||||
"f'{indent}{_type}'"
|
||||
COMMA
|
||||
','
|
||||
argument
|
||||
NAME
|
||||
' '
|
||||
'fg'
|
||||
EQUAL
|
||||
'='
|
||||
STRING
|
||||
"'blue'"
|
||||
/argument
|
||||
COMMA
|
||||
','
|
||||
argument
|
||||
NAME
|
||||
' '
|
||||
'nl'
|
||||
EQUAL
|
||||
'='
|
||||
NAME
|
||||
'False'
|
||||
/argument
|
||||
/arglist
|
||||
RPAR
|
||||
')'
|
||||
/trailer
|
||||
/power
|
||||
NEWLINE
|
||||
'\n'
|
||||
/simple_stmt
|
||||
if_stmt
|
||||
NAME
|
||||
' '
|
||||
'if'
|
||||
power
|
||||
NAME
|
||||
' '
|
||||
'node'
|
||||
trailer
|
||||
DOT
|
||||
'.'
|
||||
NAME
|
||||
'prefix'
|
||||
/trailer
|
||||
/power
|
||||
COLON
|
||||
':'
|
||||
suite
|
||||
NEWLINE
|
||||
'\n'
|
||||
INDENT
|
||||
' '
|
||||
simple_stmt
|
||||
power
|
||||
NAME
|
||||
" # We don't have to handle prefixes for `Node` objects since\n # that delegates to the first child anyway.\n"
|
||||
'out'
|
||||
trailer
|
||||
LPAR
|
||||
'('
|
||||
arglist
|
||||
STRING
|
||||
"f' {node.prefix!r}'"
|
||||
COMMA
|
||||
','
|
||||
argument
|
||||
NAME
|
||||
' '
|
||||
'fg'
|
||||
EQUAL
|
||||
'='
|
||||
STRING
|
||||
"'green'"
|
||||
/argument
|
||||
COMMA
|
||||
','
|
||||
argument
|
||||
NAME
|
||||
' '
|
||||
'bold'
|
||||
EQUAL
|
||||
'='
|
||||
NAME
|
||||
'False'
|
||||
/argument
|
||||
COMMA
|
||||
','
|
||||
argument
|
||||
NAME
|
||||
' '
|
||||
'nl'
|
||||
EQUAL
|
||||
'='
|
||||
NAME
|
||||
'False'
|
||||
/argument
|
||||
/arglist
|
||||
RPAR
|
||||
')'
|
||||
/trailer
|
||||
/power
|
||||
NEWLINE
|
||||
'\n'
|
||||
/simple_stmt
|
||||
DEDENT
|
||||
''
|
||||
/suite
|
||||
/if_stmt
|
||||
simple_stmt
|
||||
power
|
||||
NAME
|
||||
' '
|
||||
'out'
|
||||
trailer
|
||||
LPAR
|
||||
'('
|
||||
arglist
|
||||
STRING
|
||||
"f' {node.value!r}'"
|
||||
COMMA
|
||||
','
|
||||
argument
|
||||
NAME
|
||||
' '
|
||||
'fg'
|
||||
EQUAL
|
||||
'='
|
||||
STRING
|
||||
"'blue'"
|
||||
/argument
|
||||
COMMA
|
||||
','
|
||||
argument
|
||||
NAME
|
||||
' '
|
||||
'bold'
|
||||
EQUAL
|
||||
'='
|
||||
NAME
|
||||
'False'
|
||||
/argument
|
||||
/arglist
|
||||
RPAR
|
||||
')'
|
||||
/trailer
|
||||
/power
|
||||
NEWLINE
|
||||
'\n'
|
||||
/simple_stmt
|
||||
DEDENT
|
||||
''
|
||||
/suite
|
||||
/if_stmt
|
||||
DEDENT
|
||||
''
|
||||
/suite
|
||||
/funcdef
|
||||
decorated
|
||||
decorator
|
||||
AT
|
||||
'\n '
|
||||
'@'
|
||||
NAME
|
||||
'classmethod'
|
||||
NEWLINE
|
||||
'\n'
|
||||
/decorator
|
||||
funcdef
|
||||
NAME
|
||||
' '
|
||||
'def'
|
||||
NAME
|
||||
' '
|
||||
'show'
|
||||
parameters
|
||||
LPAR
|
||||
'('
|
||||
typedargslist
|
||||
NAME
|
||||
'cls'
|
||||
COMMA
|
||||
','
|
||||
tname
|
||||
NAME
|
||||
' '
|
||||
'code'
|
||||
COLON
|
||||
':'
|
||||
NAME
|
||||
' '
|
||||
'str'
|
||||
/tname
|
||||
/typedargslist
|
||||
RPAR
|
||||
')'
|
||||
/parameters
|
||||
RARROW
|
||||
' '
|
||||
'->'
|
||||
NAME
|
||||
' '
|
||||
'None'
|
||||
COLON
|
||||
':'
|
||||
suite
|
||||
NEWLINE
|
||||
'\n'
|
||||
INDENT
|
||||
' '
|
||||
simple_stmt
|
||||
STRING
|
||||
'"""Pretty-prints a given string of `code`.\n\n Convenience method for debugging.\n """'
|
||||
NEWLINE
|
||||
'\n'
|
||||
/simple_stmt
|
||||
simple_stmt
|
||||
expr_stmt
|
||||
NAME
|
||||
' '
|
||||
'v'
|
||||
annassign
|
||||
COLON
|
||||
':'
|
||||
power
|
||||
NAME
|
||||
' '
|
||||
'DebugVisitor'
|
||||
trailer
|
||||
LSQB
|
||||
'['
|
||||
NAME
|
||||
'None'
|
||||
RSQB
|
||||
']'
|
||||
/trailer
|
||||
/power
|
||||
EQUAL
|
||||
' '
|
||||
'='
|
||||
power
|
||||
NAME
|
||||
' '
|
||||
'DebugVisitor'
|
||||
trailer
|
||||
LPAR
|
||||
'('
|
||||
RPAR
|
||||
')'
|
||||
/trailer
|
||||
/power
|
||||
/annassign
|
||||
/expr_stmt
|
||||
NEWLINE
|
||||
'\n'
|
||||
/simple_stmt
|
||||
simple_stmt
|
||||
power
|
||||
NAME
|
||||
' '
|
||||
'list'
|
||||
trailer
|
||||
LPAR
|
||||
'('
|
||||
power
|
||||
NAME
|
||||
'v'
|
||||
trailer
|
||||
DOT
|
||||
'.'
|
||||
NAME
|
||||
'visit'
|
||||
/trailer
|
||||
trailer
|
||||
LPAR
|
||||
'('
|
||||
power
|
||||
NAME
|
||||
'lib2to3_parse'
|
||||
trailer
|
||||
LPAR
|
||||
'('
|
||||
NAME
|
||||
'code'
|
||||
RPAR
|
||||
')'
|
||||
/trailer
|
||||
/power
|
||||
RPAR
|
||||
')'
|
||||
/trailer
|
||||
/power
|
||||
RPAR
|
||||
')'
|
||||
/trailer
|
||||
/power
|
||||
NEWLINE
|
||||
'\n'
|
||||
/simple_stmt
|
||||
DEDENT
|
||||
''
|
||||
/suite
|
||||
/funcdef
|
||||
/decorated
|
||||
DEDENT
|
||||
''
|
||||
/suite
|
||||
/classdef
|
||||
/decorated
|
||||
ENDMARKER
|
||||
''
|
||||
/file_input
|
32
tests/debug_visitor.py
Normal file
32
tests/debug_visitor.py
Normal file
@ -0,0 +1,32 @@
|
||||
@dataclass
|
||||
class DebugVisitor(Visitor[T]):
|
||||
tree_depth: int = 0
|
||||
|
||||
def visit_default(self, node: LN) -> Iterator[T]:
|
||||
indent = ' ' * (2 * self.tree_depth)
|
||||
if isinstance(node, Node):
|
||||
_type = type_repr(node.type)
|
||||
out(f'{indent}{_type}', fg='yellow')
|
||||
self.tree_depth += 1
|
||||
for child in node.children:
|
||||
yield from self.visit(child)
|
||||
|
||||
self.tree_depth -= 1
|
||||
out(f'{indent}/{_type}', fg='yellow', bold=False)
|
||||
else:
|
||||
_type = token.tok_name.get(node.type, str(node.type))
|
||||
out(f'{indent}{_type}', fg='blue', nl=False)
|
||||
if node.prefix:
|
||||
# We don't have to handle prefixes for `Node` objects since
|
||||
# that delegates to the first child anyway.
|
||||
out(f' {node.prefix!r}', fg='green', bold=False, nl=False)
|
||||
out(f' {node.value!r}', fg='blue', bold=False)
|
||||
|
||||
@classmethod
|
||||
def show(cls, code: str) -> None:
|
||||
"""Pretty-prints a given string of `code`.
|
||||
|
||||
Convenience method for debugging.
|
||||
"""
|
||||
v: DebugVisitor[None] = DebugVisitor()
|
||||
list(v.visit(lib2to3_parse(code)))
|
@ -25,7 +25,7 @@ def dump_to_stderr(*output: str) -> str:
|
||||
|
||||
def read_data(name: str) -> Tuple[str, str]:
|
||||
"""read_data('test_name') -> 'input', 'output'"""
|
||||
if not name.endswith('.py'):
|
||||
if not name.endswith(('.py', '.out')):
|
||||
name += '.py'
|
||||
_input: List[str] = []
|
||||
_output: List[str] = []
|
||||
@ -282,6 +282,30 @@ def test_is_python36(self) -> None:
|
||||
node = black.lib2to3_parse(expected)
|
||||
self.assertFalse(black.is_python36(node))
|
||||
|
||||
def test_debug_visitor(self) -> None:
|
||||
source, _ = read_data('debug_visitor.py')
|
||||
expected, _ = read_data('debug_visitor.out')
|
||||
out_lines = []
|
||||
err_lines = []
|
||||
|
||||
def out(msg: str, **kwargs: Any) -> None:
|
||||
out_lines.append(msg)
|
||||
|
||||
def err(msg: str, **kwargs: Any) -> None:
|
||||
err_lines.append(msg)
|
||||
|
||||
with patch("black.out", out), patch("black.err", err):
|
||||
black.DebugVisitor.show(source)
|
||||
actual = '\n'.join(out_lines) + '\n'
|
||||
log_name = ''
|
||||
if expected != actual:
|
||||
log_name = black.dump_to_file(*out_lines)
|
||||
self.assertEqual(
|
||||
expected,
|
||||
actual,
|
||||
f"AST print out is different. Actual version dumped to {log_name}",
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
Reference in New Issue
Block a user