From 365a83982cbe6e9776f5962de2290cd7cc96d927 Mon Sep 17 00:00:00 2001 From: felix-hilden Date: Fri, 21 Jan 2022 00:30:32 +0200 Subject: [PATCH 1/5] Deprecate ESP and move the functionality under --preview (#2756) --- CHANGES.md | 5 ++++- docs/faq.md | 2 +- docs/the_black_code_style/current_style.md | 10 --------- docs/the_black_code_style/future_style.md | 19 +++++++++-------- src/black/__init__.py | 5 +---- src/black/linegen.py | 7 +++---- src/black/mode.py | 19 ++++++++++++++++- tests/test_black.py | 7 ++++++- tests/test_format.py | 24 ++++++++-------------- 9 files changed, 53 insertions(+), 45 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 4b9ceae81dc..c3e2a3350d3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -30,6 +30,8 @@ - Fix handling of standalone `match()` or `case()` when there is a trailing newline or a comment inside of the parentheses. (#2760) - Black now normalizes string prefix order (#2297) +- Deprecate `--experimental-string-processing` and move the functionality under + `--preview` (#2789) ### Packaging @@ -38,7 +40,8 @@ ### Preview style -- Introduce the `--preview` flag with no style changes (#2752) +- Introduce the `--preview` flag (#2752) +- Add `--experimental-string-processing` to the preview style (#2789) ### Integrations diff --git a/docs/faq.md b/docs/faq.md index c7d5ec33ad9..94a978d826f 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -33,7 +33,7 @@ still proposed on the issue tracker. See Starting in 2022, the formatting output will be stable for the releases made in the same year (other than unintentional bugs). It is possible to opt-in to the latest formatting -styles, using the `--future` flag. +styles, using the `--preview` flag. ## Why is my file not formatted? diff --git a/docs/the_black_code_style/current_style.md b/docs/the_black_code_style/current_style.md index 11fe2c8cceb..41ff3a38695 100644 --- a/docs/the_black_code_style/current_style.md +++ b/docs/the_black_code_style/current_style.md @@ -260,16 +260,6 @@ If you are adopting _Black_ in a large project with pre-existing string conventi you can pass `--skip-string-normalization` on the command line. This is meant as an adoption helper, avoid using this for new projects. -(labels/experimental-string)= - -As an experimental option (can be enabled by `--experimental-string-processing`), -_Black_ splits long strings (using parentheses where appropriate) and merges short ones. -When split, parts of f-strings that don't need formatting are converted to plain -strings. User-made splits are respected when they do not exceed the line length limit. -Line continuation backslashes are converted into parenthesized strings. Unnecessary -parentheses are stripped. Because the functionality is experimental, feedback and issue -reports are highly encouraged! - _Black_ also processes docstrings. Firstly the indentation of docstrings is corrected for both quotations and the text within, although relative indentation in the text is preserved. Superfluous trailing whitespace on each line and unnecessary new lines at the diff --git a/docs/the_black_code_style/future_style.md b/docs/the_black_code_style/future_style.md index 70ffeefc76a..2ec2c0333a5 100644 --- a/docs/the_black_code_style/future_style.md +++ b/docs/the_black_code_style/future_style.md @@ -34,15 +34,18 @@ with \ Although when the target version is Python 3.9 or higher, _Black_ will use parentheses instead since they're allowed in Python 3.9 and higher. -## Improved string processing - -Currently, _Black_ does not split long strings to fit the line length limit. Currently, -there is [an experimental option](labels/experimental-string) to enable splitting -strings. We plan to enable this option by default once it is fully stable. This is -tracked in [this issue](https://github.com/psf/black/issues/2188). - ## Preview style Experimental, potentially disruptive style changes are gathered under the `--preview` CLI flag. At the end of each year, these changes may be adopted into the default style, -as described in [The Black Code Style](./index.rst). +as described in [The Black Code Style](./index.rst). Because the functionality is +experimental, feedback and issue reports are highly encouraged! + +### Improved string processing + +_Black_ will split long string literals and merge short ones. Parentheses are used where +appropriate. When split, parts of f-strings that don't need formatting are converted to +plain strings. User-made splits are respected when they do not exceed the line length +limit. Line continuation backslashes are converted into parenthesized strings. +Unnecessary parentheses are stripped. The stability and status of this feature is +tracked in [this issue](https://github.com/psf/black/issues/2188). diff --git a/src/black/__init__.py b/src/black/__init__.py index 405a01082e7..67c272e3cc9 100644 --- a/src/black/__init__.py +++ b/src/black/__init__.py @@ -241,10 +241,7 @@ def validate_regex( "--experimental-string-processing", is_flag=True, hidden=True, - help=( - "Experimental option that performs more normalization on string literals." - " Currently disabled because it leads to some crashes." - ), + help="(DEPRECATED and now included in --preview) Normalize string literals.", ) @click.option( "--preview", diff --git a/src/black/linegen.py b/src/black/linegen.py index 6008c773f94..9ee42aaaf72 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -23,8 +23,7 @@ from black.strings import normalize_string_prefix, normalize_string_quotes from black.trans import Transformer, CannotTransform, StringMerger from black.trans import StringSplitter, StringParenWrapper, StringParenStripper -from black.mode import Mode -from black.mode import Feature +from black.mode import Mode, Feature, Preview from blib2to3.pytree import Node, Leaf from blib2to3.pgen2 import token @@ -338,7 +337,7 @@ def transform_line( and not (line.inside_brackets and line.contains_standalone_comments()) ): # Only apply basic string preprocessing, since lines shouldn't be split here. - if mode.experimental_string_processing: + if Preview.string_processing in mode: transformers = [string_merge, string_paren_strip] else: transformers = [] @@ -381,7 +380,7 @@ def _rhs( # via type ... https://github.com/mypyc/mypyc/issues/884 rhs = type("rhs", (), {"__call__": _rhs})() - if mode.experimental_string_processing: + if Preview.string_processing in mode: if line.inside_brackets: transformers = [ string_merge, diff --git a/src/black/mode.py b/src/black/mode.py index c8c2bd4eb26..d8ede37c369 100644 --- a/src/black/mode.py +++ b/src/black/mode.py @@ -7,9 +7,10 @@ import sys from dataclasses import dataclass, field -from enum import Enum +from enum import Enum, auto from operator import attrgetter from typing import Dict, Set +from warnings import warn if sys.version_info < (3, 8): from typing_extensions import Final @@ -124,6 +125,12 @@ def supports_feature(target_versions: Set[TargetVersion], feature: Feature) -> b class Preview(Enum): """Individual preview style features.""" + string_processing = auto + + +class Deprecated(UserWarning): + """Visible deprecation warning.""" + @dataclass class Mode: @@ -136,6 +143,14 @@ class Mode: experimental_string_processing: bool = False preview: bool = False + def __post_init__(self) -> None: + if self.experimental_string_processing: + warn( + "`experimental string processing` has been included in `preview`" + " and deprecated. Use `preview` instead.", + Deprecated, + ) + def __contains__(self, feature: Preview) -> bool: """ Provide `Preview.FEATURE in Mode` syntax that mirrors the ``preview`` flag. @@ -143,6 +158,8 @@ def __contains__(self, feature: Preview) -> bool: The argument is not checked and features are not differentiated. They only exist to make development easier by clarifying intent. """ + if feature == Preview.string_processing: + return self.preview or self.experimental_string_processing return self.preview def get_cache_key(self) -> str: diff --git a/tests/test_black.py b/tests/test_black.py index 202fe23ddcd..19cff23cb89 100644 --- a/tests/test_black.py +++ b/tests/test_black.py @@ -150,6 +150,11 @@ def test_empty_ff(self) -> None: os.unlink(tmp_file) self.assertFormatEqual(expected, actual) + def test_experimental_string_processing_warns(self) -> None: + self.assertWarns( + black.mode.Deprecated, black.Mode, experimental_string_processing=True + ) + def test_piping(self) -> None: source, expected = read_data("src/black/__init__", data=False) result = BlackRunner().invoke( @@ -342,7 +347,7 @@ def test_detect_pos_only_arguments(self) -> None: @patch("black.dump_to_file", dump_to_stderr) def test_string_quotes(self) -> None: source, expected = read_data("string_quotes") - mode = black.Mode(experimental_string_processing=True) + mode = black.Mode(preview=True) assert_format(source, expected, mode) mode = replace(mode, string_normalization=False) not_normalized = fs(source, mode=mode) diff --git a/tests/test_format.py b/tests/test_format.py index 00cd07f36f7..40f225c9554 100644 --- a/tests/test_format.py +++ b/tests/test_format.py @@ -55,15 +55,6 @@ "tupleassign", ] -EXPERIMENTAL_STRING_PROCESSING_CASES: List[str] = [ - "cantfit", - "comments7", - "long_strings", - "long_strings__edge_case", - "long_strings__regression", - "percent_precedence", -] - PY310_CASES: List[str] = [ "pattern_matching_simple", "pattern_matching_complex", @@ -73,7 +64,15 @@ "parenthesized_context_managers", ] -PREVIEW_CASES: List[str] = [] +PREVIEW_CASES: List[str] = [ + # string processing + "cantfit", + "comments7", + "long_strings", + "long_strings__edge_case", + "long_strings__regression", + "percent_precedence", +] SOURCES: List[str] = [ "src/black/__init__.py", @@ -136,11 +135,6 @@ def test_simple_format(filename: str) -> None: check_file(filename, DEFAULT_MODE) -@pytest.mark.parametrize("filename", EXPERIMENTAL_STRING_PROCESSING_CASES) -def test_experimental_format(filename: str) -> None: - check_file(filename, black.Mode(experimental_string_processing=True)) - - @pytest.mark.parametrize("filename", PREVIEW_CASES) def test_preview_format(filename: str) -> None: check_file(filename, black.Mode(preview=True)) From 782b2fd37f0780c0f8f054e4b71724f3264a9b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Hild=C3=A9n?= Date: Fri, 21 Jan 2022 00:48:51 +0200 Subject: [PATCH 2/5] Whoops not *that* auto Co-authored-by: Jelle Zijlstra --- src/black/mode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/black/mode.py b/src/black/mode.py index d8ede37c369..bf7ddb4b9ad 100644 --- a/src/black/mode.py +++ b/src/black/mode.py @@ -125,7 +125,7 @@ def supports_feature(target_versions: Set[TargetVersion], feature: Feature) -> b class Preview(Enum): """Individual preview style features.""" - string_processing = auto + string_processing = auto() class Deprecated(UserWarning): From e8deed497f82d55e13fc6cd5d52af07ccfeae269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Hild=C3=A9n?= Date: Fri, 21 Jan 2022 00:49:51 +0200 Subject: [PATCH 3/5] Enum comparison using identity Co-authored-by: Jelle Zijlstra --- src/black/mode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/black/mode.py b/src/black/mode.py index bf7ddb4b9ad..7e1f05b3111 100644 --- a/src/black/mode.py +++ b/src/black/mode.py @@ -158,7 +158,7 @@ def __contains__(self, feature: Preview) -> bool: The argument is not checked and features are not differentiated. They only exist to make development easier by clarifying intent. """ - if feature == Preview.string_processing: + if feature is Preview.string_processing: return self.preview or self.experimental_string_processing return self.preview From 79a994275cbf370b4e27e25066353d9019ad4eb4 Mon Sep 17 00:00:00 2001 From: felix-hilden Date: Fri, 21 Jan 2022 00:55:17 +0200 Subject: [PATCH 4/5] Mention --preview in style doc --- docs/the_black_code_style/current_style.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/the_black_code_style/current_style.md b/docs/the_black_code_style/current_style.md index 41ff3a38695..1d1e42e75c8 100644 --- a/docs/the_black_code_style/current_style.md +++ b/docs/the_black_code_style/current_style.md @@ -10,6 +10,10 @@ with `# fmt: off` and end with `# fmt: on`, or lines that ends with `# fmt: skip [YAPF](https://github.com/google/yapf)'s block comments to the same effect, as a courtesy for straddling code. +The rest of this document describes the current formatting style. If you're interested +in trying out where the style is heading, see [future style](./future_style.md) and try +running `black --preview`. + ### How _Black_ wraps lines _Black_ ignores previous formatting and applies uniform horizontal and vertical From 7ebdcd8ed0e5cf5f5909c44fda5fb3b0c4d94150 Mon Sep 17 00:00:00 2001 From: felix-hilden Date: Fri, 21 Jan 2022 01:14:21 +0200 Subject: [PATCH 5/5] Dummy preview feature for mypy --- src/black/mode.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/black/mode.py b/src/black/mode.py index 7e1f05b3111..b6d1a1fbbef 100644 --- a/src/black/mode.py +++ b/src/black/mode.py @@ -126,6 +126,7 @@ class Preview(Enum): """Individual preview style features.""" string_processing = auto() + hug_simple_powers = auto() class Deprecated(UserWarning):