Repository: bwhmather/ssort

Issue:
ssort reformats dummy classes (conflict with black 24)
In black v24 a few new rules become stable.
One of them is

> Dummy class and function implementations consisting only of ... are formatted more compactly ([#3796](https://github.com/psf/black/pull/3796))

Most of the dummy bodies adjustment black makes are fine with ssort,
but a dummy class isn't.

Consider this simple file:

```py
class MyException(Exception):
    ...
```

black v24 now re-formats it as:
```py
class MyException(Exception): ...
```

while `ssort` re-formats it back to the original "shape".

I think this is a bug on ssort side.

We have both `ssort` and `black` configured in our pre-commit setup
and now we're unable to use them together.

Hints from issue comments:
@bwhmather: This certainly breaks our "if code is ordered correctly then it won't be changed rule".
@bwhmather: Thank you for reporting.  Have published a fix in 0.12.4.

Solution patch:
diff --git a/src/ssort/_ssort.py b/src/ssort/_ssort.py
index ce3282b..83cfb23 100644
--- a/src/ssort/_ssort.py
+++ b/src/ssort/_ssort.py
@@ -229,7 +229,9 @@ def _statement_binding_sort_key(binding_key):
 
 
 def _statement_text_sorted_class(statement):
-    head_text, statements = split_class(statement)
+    head_text, unsorted_statements = split_class(statement)
+
+    statements = list(unsorted_statements)
 
     # Take a snapshot of any hard dependencies between statements so that we can
     # restore them later.
@@ -317,6 +319,9 @@ def _statement_text_sorted_class(statement):
         sorted_statements, graph=runtime_graph
     )
 
+    if sorted_statements == unsorted_statements:
+        return statement.text
+
     return (
         head_text
         + "\n"


Test patch:
diff --git a/tests/test_ssort.py b/tests/test_ssort.py
index edf562c..87da854 100644
--- a/tests/test_ssort.py
+++ b/tests/test_ssort.py
@@ -678,3 +678,19 @@ def test_ssort_self_positional_only():
     )
     actual = ssort(original)
     assert actual == expected
+
+
+def test_single_line_dummy_function():
+    original = "def fun(): ...\n"
+    expected = "def fun(): ...\n"
+
+    actual = ssort(original)
+    assert actual == expected
+
+
+def test_single_line_dummy_class():
+    original = "class Class: ...\n"
+    expected = "class Class: ...\n"
+
+    actual = ssort(original)
+    assert actual == expected