Repository: psf/black

Issue:
Cache does not get wiped when `--skip-magic-trailing-comma` changes
**Describe the bug** The cache is still used after you change a configuration option.

**To Reproduce** Steps to reproduce the behavior:

1. Format some code with Black
2. Change some formatting flag (e.g., add `skip-magic-trailing-comma = true` to your pyproject.toml)
3. Run Black on your code again and see that nothing changes
4. Figure out where Black stores the cache and `rm -rf` it
5. Run Black on your code again and see that it changes formatting

**Does this bug also happen on master?** Yes

This is because `FileMode.get_cache_key` doesn't include this flag.



Discussion:

Resolving patch:
diff --git a/src/black/__init__.py b/src/black/__init__.py
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -273,9 +273,9 @@ class Mode:
     target_versions: Set[TargetVersion] = field(default_factory=set)
     line_length: int = DEFAULT_LINE_LENGTH
     string_normalization: bool = True
+    is_pyi: bool = False
     magic_trailing_comma: bool = True
     experimental_string_processing: bool = False
-    is_pyi: bool = False
 
     def get_cache_key(self) -> str:
         if self.target_versions:
@@ -290,6 +290,8 @@ def get_cache_key(self) -> str:
             str(self.line_length),
             str(int(self.string_normalization)),
             str(int(self.is_pyi)),
+            str(int(self.magic_trailing_comma)),
+            str(int(self.experimental_string_processing)),
         ]
         return ".".join(parts)
 


Test patch:
diff --git a/tests/test_black.py b/tests/test_black.py
--- a/tests/test_black.py
+++ b/tests/test_black.py
@@ -379,11 +379,12 @@ 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")
-        actual = fs(source)
+        mode = black.Mode(experimental_string_processing=True)
+        actual = fs(source, mode=mode)
         self.assertFormatEqual(expected, actual)
         black.assert_equivalent(source, actual)
-        black.assert_stable(source, actual, DEFAULT_MODE)
-        mode = replace(DEFAULT_MODE, string_normalization=False)
+        black.assert_stable(source, actual, mode)
+        mode = replace(mode, string_normalization=False)
         not_normalized = fs(source, mode=mode)
         self.assertFormatEqual(source.replace("\\\n", ""), not_normalized)
         black.assert_equivalent(source, not_normalized)
diff --git a/tests/test_format.py b/tests/test_format.py
--- a/tests/test_format.py
+++ b/tests/test_format.py
@@ -16,7 +16,6 @@
 SIMPLE_CASES = [
     "beginning_backslash",
     "bracketmatch",
-    "cantfit",
     "class_blank_parentheses",
     "class_methods_new_line",
     "collections",
@@ -26,7 +25,6 @@
     "comments4",
     "comments5",
     "comments6",
-    "comments7",
     "comments_non_breaking_space",
     "comment_after_escaped_newline",
     "composition",
@@ -48,11 +46,7 @@
     "function2",
     "function_trailing_comma",
     "import_spacing",
-    "long_strings",
-    "long_strings__edge_case",
-    "long_strings__regression",
     "numeric_literals_py2",
-    "percent_precedence",
     "python2",
     "python2_unicode_literals",
     "remove_parens",
@@ -62,6 +56,15 @@
     "tupleassign",
 ]
 
+EXPERIMENTAL_STRING_PROCESSING_CASES = [
+    "cantfit",
+    "comments7",
+    "long_strings",
+    "long_strings__edge_case",
+    "long_strings__regression",
+    "percent_precedence",
+]
+
 
 SOURCES = [
     "tests/test_black.py",
@@ -86,19 +89,23 @@ class TestSimpleFormat(BlackBaseTestCase):
     @parameterized.expand(SIMPLE_CASES)
     @patch("black.dump_to_file", dump_to_stderr)
     def test_simple_format(self, filename: str) -> None:
-        source, expected = read_data(filename)
-        actual = fs(source)
-        self.assertFormatEqual(expected, actual)
-        black.assert_equivalent(source, actual)
-        black.assert_stable(source, actual, DEFAULT_MODE)
+        self.check_file(filename, DEFAULT_MODE)
+
+    @parameterized.expand(EXPERIMENTAL_STRING_PROCESSING_CASES)
+    @patch("black.dump_to_file", dump_to_stderr)
+    def test_experimental_format(self, filename: str) -> None:
+        self.check_file(filename, black.Mode(experimental_string_processing=True))
 
     @parameterized.expand(SOURCES)
     @patch("black.dump_to_file", dump_to_stderr)
     def test_source_is_formatted(self, filename: str) -> None:
         path = THIS_DIR.parent / filename
-        source, expected = read_data(str(path), data=False)
-        actual = fs(source, mode=DEFAULT_MODE)
+        self.check_file(str(path), DEFAULT_MODE, data=False)
+        self.assertFalse(ff(path))
+
+    def check_file(self, filename: str, mode: black.Mode, *, data: bool = True) -> None:
+        source, expected = read_data(filename, data=data)
+        actual = fs(source, mode=mode)
         self.assertFormatEqual(expected, actual)
         black.assert_equivalent(source, actual)
-        black.assert_stable(source, actual, DEFAULT_MODE)
-        self.assertFalse(ff(path))
+        black.assert_stable(source, actual, mode)
diff --git a/tests/util.py b/tests/util.py
--- a/tests/util.py
+++ b/tests/util.py
@@ -12,7 +12,7 @@
 DETERMINISTIC_HEADER = "[Deterministic header]"
 
 
-DEFAULT_MODE = black.FileMode(experimental_string_processing=True)
+DEFAULT_MODE = black.Mode()
 ff = partial(black.format_file_in_place, mode=DEFAULT_MODE, fast=True)
 fs = partial(black.format_str, mode=DEFAULT_MODE)