Skip to content

Commit

Permalink
Check stability for both preview and non-preview styles (#3423)
Browse files Browse the repository at this point in the history
And fix parens-related test failures this found.

Co-authored-by: Richard Si <63936253+ichard26@users.noreply.github.com>
  • Loading branch information
JelleZijlstra and ichard26 committed Dec 17, 2022
1 parent c0089ef commit 159984a
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Expand Up @@ -17,6 +17,8 @@
<!-- Changes that affect Black's preview style -->

- Fix a crash in preview style with assert + parenthesized string (#3415)
- Fix crashes in preview style with walrus operators used in function return annotations
and except clauses (#3423)
- Do not put the closing quotes in a docstring on a separate line, even if the line is
too long (#3430)
- Long values in dict literals are now wrapped in parentheses; correspondingly
Expand Down
2 changes: 2 additions & 0 deletions src/black/linegen.py
Expand Up @@ -1268,6 +1268,8 @@ def maybe_make_parens_invisible_in_atom(
syms.expr_stmt,
syms.assert_stmt,
syms.return_stmt,
syms.except_clause,
syms.funcdef,
# these ones aren't useful to end users, but they do please fuzzers
syms.for_stmt,
syms.del_stmt,
Expand Down
2 changes: 1 addition & 1 deletion tests/data/py_310/pattern_matching_extras.py
Expand Up @@ -114,6 +114,6 @@ def func(match: case, case: match) -> case:

match bar1:
case Foo(
normal=x, perhaps=[list, {an: d, dict: 1.0}] as y, otherwise=something, q=t as u
normal=x, perhaps=[list, {"x": d, "y": 1.0}] as y, otherwise=something, q=t as u
):
pass
54 changes: 52 additions & 2 deletions tests/util.py
Expand Up @@ -2,6 +2,7 @@
import sys
import unittest
from contextlib import contextmanager
from dataclasses import replace
from functools import partial
from pathlib import Path
from typing import Any, Iterator, List, Optional, Tuple
Expand Down Expand Up @@ -56,6 +57,10 @@ def _assert_format_equal(expected: str, actual: str) -> None:
assert actual == expected


class FormatFailure(Exception):
"""Used to wrap failures when assert_format() runs in an extra mode."""


def assert_format(
source: str,
expected: str,
Expand All @@ -70,12 +75,57 @@ def assert_format(
safety guards so they don't just crash with a SyntaxError. Please note this is
separate from TargetVerson Mode configuration.
"""
_assert_format_inner(
source, expected, mode, fast=fast, minimum_version=minimum_version
)

# For both preview and non-preview tests, ensure that Black doesn't crash on
# this code, but don't pass "expected" because the precise output may differ.
try:
_assert_format_inner(
source,
None,
replace(mode, preview=not mode.preview),
fast=fast,
minimum_version=minimum_version,
)
except Exception as e:
text = "non-preview" if mode.preview else "preview"
raise FormatFailure(
f"Black crashed formatting this case in {text} mode."
) from e
# Similarly, setting line length to 1 is a good way to catch
# stability bugs. But only in non-preview mode because preview mode
# currently has a lot of line length 1 bugs.
try:
_assert_format_inner(
source,
None,
replace(mode, preview=False, line_length=1),
fast=fast,
minimum_version=minimum_version,
)
except Exception as e:
raise FormatFailure(
"Black crashed formatting this case with line-length set to 1."
) from e


def _assert_format_inner(
source: str,
expected: Optional[str] = None,
mode: black.Mode = DEFAULT_MODE,
*,
fast: bool = False,
minimum_version: Optional[Tuple[int, int]] = None,
) -> None:
actual = black.format_str(source, mode=mode)
_assert_format_equal(expected, actual)
if expected is not None:
_assert_format_equal(expected, actual)
# It's not useful to run safety checks if we're expecting no changes anyway. The
# assertion right above will raise if reality does actually make changes. This just
# avoids wasted CPU cycles.
if not fast and source != expected:
if not fast and source != actual:
# Unfortunately the AST equivalence check relies on the built-in ast module
# being able to parse the code being formatted. This doesn't always work out
# when checking modern code on older versions.
Expand Down

0 comments on commit 159984a

Please sign in to comment.