Skip to content

Commit

Permalink
Extract the inner _v method to decrease complexity
Browse files Browse the repository at this point in the history
This reduces the cyclomatic complexity to a level that makes flake8 happy.
  • Loading branch information
Alex Vandiver committed Oct 15, 2019
1 parent 982d92d commit b96f9ca
Showing 1 changed file with 52 additions and 49 deletions.
101 changes: 52 additions & 49 deletions black.py
Original file line number Diff line number Diff line change
Expand Up @@ -3653,62 +3653,65 @@ def _fixup_ast_constants(
return node


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]:
"""Simple visitor generating strings to compare ASTs by content."""
def _stringify_ast(
node: Union[ast.AST, ast3.AST, ast27.AST], depth: int = 0
) -> Iterator[str]:
"""Simple visitor generating strings to compare ASTs by content."""

node = _fixup_ast_constants(node)
node = _fixup_ast_constants(node)

yield f"{' ' * depth}{node.__class__.__name__}("
yield f"{' ' * depth}{node.__class__.__name__}("

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):
break
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):
break

try:
value = getattr(node, field)
except AttributeError:
continue
try:
value = getattr(node, field)
except AttributeError:
continue

yield f"{' ' * (depth+1)}{field}="

if isinstance(value, list):
for item in value:
# Ignore nested tuples within del statements, because we may insert
# 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))
):
for item in item.elts:
yield from _v(item, depth + 2)
elif isinstance(item, (ast.AST, ast3.AST, ast27.AST)):
yield from _v(item, depth + 2)

elif isinstance(value, (ast.AST, ast3.AST, ast27.AST)):
yield from _v(value, depth + 2)
yield f"{' ' * (depth+1)}{field}="

else:
# Constant strings may be indented across newlines, if they are
# docstrings; fold spaces after newlines when comparing
if isinstance(value, list):
for item in value:
# Ignore nested tuples within del statements, because we may insert
# parentheses and they change the AST.
if (
isinstance(node, ast.Constant)
and field == "value"
and isinstance(value, str)
field == "targets"
and isinstance(node, (ast.Delete, ast3.Delete, ast27.Delete))
and isinstance(item, (ast.Tuple, ast3.Tuple, ast27.Tuple))
):
normalized = re.sub(r"\n[ \t]+", "\n ", value)
else:
normalized = value
yield f"{' ' * (depth+2)}{normalized!r}, # {value.__class__.__name__}"
for item in item.elts:
yield from _stringify_ast(item, depth + 2)
elif isinstance(item, (ast.AST, ast3.AST, ast27.AST)):
yield from _stringify_ast(item, depth + 2)

yield f"{' ' * depth}) # /{node.__class__.__name__}"
elif isinstance(value, (ast.AST, ast3.AST, ast27.AST)):
yield from _stringify_ast(value, depth + 2)

else:
# Constant strings may be indented across newlines, if they are
# docstrings; fold spaces after newlines when comparing
if (
isinstance(node, ast.Constant)
and field == "value"
and isinstance(value, str)
):
normalized = re.sub(r"\n[ \t]+", "\n ", value)
else:
normalized = value
yield f"{' ' * (depth+2)}{normalized!r}, # {value.__class__.__name__}"

yield f"{' ' * depth}) # /{node.__class__.__name__}"


def assert_equivalent(src: str, dst: str) -> None:
"""Raise AssertionError if `src` and `dst` aren't equivalent."""

try:
src_ast = parse_ast(src)
Expand All @@ -3728,8 +3731,8 @@ def _v(node: Union[ast.AST, ast3.AST, ast27.AST], depth: int = 0) -> Iterator[st
f"This invalid output might be helpful: {log}"
) from None

src_ast_str = "\n".join(_v(src_ast))
dst_ast_str = "\n".join(_v(dst_ast))
src_ast_str = "\n".join(_stringify_ast(src_ast))
dst_ast_str = "\n".join(_stringify_ast(dst_ast))
if src_ast_str != dst_ast_str:
log = dump_to_file(diff(src_ast_str, dst_ast_str, "src", "dst"))
raise AssertionError(
Expand Down

0 comments on commit b96f9ca

Please sign in to comment.