toml = ">=0.9.4"
black = {path = ".",extras = ["d"],editable = true}
aiohttp-cors = "*"
+typed-ast = ">=1.3.1"
[dev-packages]
pre-commit = "*"
from attr import dataclass, evolve, Factory
import click
import toml
+from typed_ast import ast3, ast27
# lib2to3 fork
from blib2to3.pytree import Node, Leaf, type_repr
return ", ".join(report) + "."
+def parse_ast(src: str) -> Union[ast3.AST, ast27.AST]:
+ try:
+ return ast3.parse(src)
+ except SyntaxError:
+ return ast27.parse(src)
+
+
def assert_equivalent(src: str, dst: str) -> None:
"""Raise AssertionError if `src` and `dst` aren't equivalent."""
- import ast
import traceback
- def _v(node: ast.AST, depth: int = 0) -> Iterator[str]:
+ def _v(node: Union[ast3.AST, ast27.AST], depth: int = 0) -> Iterator[str]:
"""Simple visitor generating strings to compare ASTs by content."""
yield f"{' ' * depth}{node.__class__.__name__}("
for field in sorted(node._fields):
+ # TypeIgnore has only one field 'lineno' which breaks this comparison
+ if isinstance(node, (ast3.TypeIgnore, ast27.TypeIgnore)):
+ break
+
+ # Ignore str kind which is case sensitive / and ignores unicode_literals
+ if isinstance(node, (ast3.Str, ast27.Str, ast3.Bytes)) and field == "kind":
+ continue
+
try:
value = getattr(node, field)
except AttributeError:
# parentheses and they change the AST.
if (
field == "targets"
- and isinstance(node, ast.Delete)
- and isinstance(item, ast.Tuple)
+ and isinstance(node, (ast3.Delete, ast27.Delete))
+ and isinstance(item, (ast3.Tuple, ast27.Tuple))
):
for item in item.elts:
yield from _v(item, depth + 2)
- elif isinstance(item, ast.AST):
+ elif isinstance(item, (ast3.AST, ast27.AST)):
yield from _v(item, depth + 2)
- elif isinstance(value, ast.AST):
+ elif isinstance(value, (ast3.AST, ast27.AST)):
yield from _v(value, depth + 2)
else:
yield f"{' ' * depth}) # /{node.__class__.__name__}"
try:
- src_ast = ast.parse(src)
+ src_ast = parse_ast(src)
except Exception as exc:
major, minor = sys.version_info[:2]
raise AssertionError(
)
try:
- dst_ast = ast.parse(dst)
+ dst_ast = parse_ast(dst)
except Exception as exc:
log = dump_to_file("".join(traceback.format_tb(exc.__traceback__)), dst)
raise AssertionError(
package_data={"blib2to3": ["*.txt"]},
python_requires=">=3.6",
zip_safe=False,
- install_requires=["click>=6.5", "attrs>=18.1.0", "appdirs", "toml>=0.9.4"],
+ install_requires=[
+ "click>=6.5",
+ "attrs>=18.1.0",
+ "appdirs",
+ "toml>=0.9.4",
+ "typed-ast>=1.3.1",
+ ],
extras_require={"d": ["aiohttp>=3.3.2", "aiohttp-cors"]},
test_suite="tests.test_black",
classifiers=[
an_element_with_a_long_value = calls() or more_calls() and more() # type: bool
tup = (
- another_element, # type: int
- another_really_really_long_element_with_a_unnecessarily_long_name_to_describe_what_it_does_enterprise_style, # type: int
+ another_element,
+ another_really_really_long_element_with_a_unnecessarily_long_name_to_describe_what_it_does_enterprise_style,
) # type: Tuple[int, int]
a = (
0.0456,
0.0789,
a[-1], # type: ignore
- )
\ No newline at end of file
+ )
import asyncio
import logging
from concurrent.futures import ThreadPoolExecutor
-from contextlib import contextmanager, redirect_stderr
+from contextlib import contextmanager
from functools import partial, wraps
from io import BytesIO, TextIOWrapper
import os
source, expected = read_data("python2")
actual = fs(source)
self.assertFormatEqual(expected, actual)
- # black.assert_equivalent(source, actual)
+ black.assert_equivalent(source, actual)
black.assert_stable(source, actual, black.FileMode())
@patch("black.dump_to_file", dump_to_stderr)
mode = black.FileMode(target_versions={TargetVersion.PY27})
actual = fs(source, mode=mode)
self.assertFormatEqual(expected, actual)
+ black.assert_equivalent(source, actual)
black.assert_stable(source, actual, mode)
@patch("black.dump_to_file", dump_to_stderr)
source, expected = read_data("python2_unicode_literals")
actual = fs(source)
self.assertFormatEqual(expected, actual)
+ black.assert_equivalent(source, actual)
black.assert_stable(source, actual, black.FileMode())
@patch("black.dump_to_file", dump_to_stderr)
await check("3.4", 204)
await check("py3.4", 204)
- @unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
- @async_test
- async def test_blackd_fast(self) -> None:
- with open(os.devnull, "w") as dn, redirect_stderr(dn):
- app = blackd.make_app()
- async with TestClient(TestServer(app)) as client:
- response = await client.post("/", data=b"ur'hello'")
- self.assertEqual(response.status, 500)
- self.assertIn("failed to parse source file", await response.text())
- response = await client.post(
- "/", data=b"ur'hello'", headers={blackd.FAST_OR_SAFE_HEADER: "fast"}
- )
- self.assertEqual(response.status, 200)
-
@unittest.skipUnless(has_blackd_deps, "blackd's dependencies are not installed")
@async_test
async def test_blackd_line_length(self) -> None: