From f1a2f92bba7f1b8e4407e89d71a18fd1d6c61a91 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Fri, 27 Sep 2024 13:41:29 -0700 Subject: [PATCH] Include --unstable in cache key (#4466) Fixes #4465 --- CHANGES.md | 4 ++++ src/black/mode.py | 1 + tests/test_black.py | 32 +++++++++++++++++++++++++++++++- tests/test_blackd.py | 6 ++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 11e491e1c65..97e8645e3ea 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -30,6 +30,10 @@ - Fix type annotation spacing between * and more complex type variable tuple (i.e. `def fn(*args: *tuple[*Ts, T]) -> None: pass`) (#4440) +### Caching + +- Fix bug where the cache was shared between runs with and without `--unstable` (#4466) + ### Configuration diff --git a/src/black/mode.py b/src/black/mode.py index 452be963686..02fe1de24db 100644 --- a/src/black/mode.py +++ b/src/black/mode.py @@ -290,6 +290,7 @@ def get_cache_key(self) -> str: str(int(self.skip_source_first_line)), str(int(self.magic_trailing_comma)), str(int(self.preview)), + str(int(self.unstable)), features_and_magics, ] return ".".join(parts) diff --git a/tests/test_black.py b/tests/test_black.py index d283ea62de4..c448c602713 100644 --- a/tests/test_black.py +++ b/tests/test_black.py @@ -12,7 +12,7 @@ import types from concurrent.futures import ThreadPoolExecutor from contextlib import contextmanager, redirect_stderr -from dataclasses import replace +from dataclasses import fields, replace from io import BytesIO from pathlib import Path, WindowsPath from platform import system @@ -2347,6 +2347,36 @@ def test_read_cache_line_lengths(self) -> None: two = black.Cache.read(short_mode) assert two.is_changed(path) + def test_cache_key(self) -> None: + # Test that all members of the mode enum affect the cache key. + for field in fields(Mode): + values: List[Any] + if field.name == "target_versions": + values = [ + {TargetVersion.PY312}, + {TargetVersion.PY313}, + ] + elif field.name == "python_cell_magics": + values = [{"magic1"}, {"magic2"}] + elif field.name == "enabled_features": + # If you are looking to remove one of these features, just + # replace it with any other feature. + values = [ + {Preview.docstring_check_for_newline}, + {Preview.hex_codes_in_unicode_sequences}, + ] + elif field.type is bool: + values = [True, False] + elif field.type is int: + values = [1, 2] + else: + raise AssertionError( + f"Unhandled field type: {field.type} for field {field.name}" + ) + modes = [replace(DEFAULT_MODE, **{field.name: value}) for value in values] + keys = [mode.get_cache_key() for mode in modes] + assert len(set(keys)) == len(modes) + def assert_collected_sources( src: Sequence[Union[str, Path]], diff --git a/tests/test_blackd.py b/tests/test_blackd.py index 3a9851a8b93..bef5eaec4f9 100644 --- a/tests/test_blackd.py +++ b/tests/test_blackd.py @@ -1,3 +1,4 @@ +import gc import re from unittest.mock import patch @@ -17,6 +18,11 @@ @pytest.mark.blackd class BlackDTestCase(AioHTTPTestCase): + def tearDown(self) -> None: + # Work around https://github.com/python/cpython/issues/124706 + gc.collect() + super().tearDown() + def test_blackd_main(self) -> None: with patch("blackd.web.run_app"): result = CliRunner().invoke(blackd.main, [])