Open alexmojaki opened 7 months ago
It preserves currently the black formatting (https://15r10nk.github.io/inline-snapshot/#code-generation point 5).
I think the problem is that it does not detect that your code is formatted with "black style". black and ruff should format the code in the similar 99% like way.
Maybe your files are part of this 1%, or there are some black or ruff options which are responsible for the different formatting.
Maybe this info helps you.
The other option for me would be to preform the same check and formatting with ruff, which I do with black.
$ cat /home/alex/.config/JetBrains/PyCharm2023.3/scratches/scratch_1906.py
from inline_snapshot import snapshot
def test_example():
foo = [dict.fromkeys(range(6), 'abcdefghijkl') for _ in range(2)]
assert foo == snapshot(0)
$ pytest --inline-snapshot=fix /home/alex/.config/JetBrains/PyCharm2023.3/scratches/scratch_1906.py
=============================================================================== test session starts ===============================================================================
platform linux -- Python 3.12.1, pytest-7.4.3, pluggy-1.3.0
rootdir: /home/alex
plugins: xdist-3.5.0, anyio-4.2.0, base-url-2.0.0, hypothesis-6.92.2, logfire-0.22.0, playwright-0.4.3, devtools-0.12.2, inline-snapshot-0.7.0, django-4.8.0, timeout-2.2.0, requests-mock-1.11.0, pretty-1.2.0
collected 1 item
../../.config/JetBrains/PyCharm2023.3/scratches/scratch_1906.py . [100%]
================================================================================= inline snapshot =================================================================================
fixed 1 snapshots
Results (0.15s):
1 passed
$ cat /home/alex/.config/JetBrains/PyCharm2023.3/scratches/scratch_1906.py
from inline_snapshot import snapshot
def test_example():
foo = [dict.fromkeys(range(6), 'abcdefghijkl') for _ in range(2)]
assert foo == snapshot([
{
0: "abcdefghijkl",
1: "abcdefghijkl",
2: "abcdefghijkl",
3: "abcdefghijkl",
4: "abcdefghijkl",
5: "abcdefghijkl",
},
{
0: "abcdefghijkl",
1: "abcdefghijkl",
2: "abcdefghijkl",
3: "abcdefghijkl",
4: "abcdefghijkl",
5: "abcdefghijkl",
},
])
$ black /home/alex/.config/JetBrains/PyCharm2023.3/scratches/scratch_1906.py
reformatted /home/alex/.config/JetBrains/PyCharm2023.3/scratches/scratch_1906.py
All done! ✨ 🍰 ✨
1 file reformatted.
$ cat /home/alex/.config/JetBrains/PyCharm2023.3/scratches/scratch_1906.py
from inline_snapshot import snapshot
def test_example():
foo = [dict.fromkeys(range(6), "abcdefghijkl") for _ in range(2)]
assert foo == snapshot(
[
{
0: "abcdefghijkl",
1: "abcdefghijkl",
2: "abcdefghijkl",
3: "abcdefghijkl",
4: "abcdefghijkl",
5: "abcdefghijkl",
},
{
0: "abcdefghijkl",
1: "abcdefghijkl",
2: "abcdefghijkl",
3: "abcdefghijkl",
4: "abcdefghijkl",
5: "abcdefghijkl",
},
]
)
$ ruff format /home/alex/.config/JetBrains/PyCharm2023.3/scratches/scratch_1906.py
1 file reformatted
$ cat /home/alex/.config/JetBrains/PyCharm2023.3/scratches/scratch_1906.py
from inline_snapshot import snapshot
def test_example():
foo = [dict.fromkeys(range(6), 'abcdefghijkl') for _ in range(2)]
assert foo == snapshot(
[
{
0: 'abcdefghijkl',
1: 'abcdefghijkl',
2: 'abcdefghijkl',
3: 'abcdefghijkl',
4: 'abcdefghijkl',
5: 'abcdefghijkl',
},
{
0: 'abcdefghijkl',
1: 'abcdefghijkl',
2: 'abcdefghijkl',
3: 'abcdefghijkl',
4: 'abcdefghijkl',
5: 'abcdefghijkl',
},
]
)
The problem is that ruff formats differently than black in your case (double/single quotes).
inline-snapshot looks at the source before it changes anything and thinks "this is not formatted with black". It re-formats only the snapshots with black (this causes the double quotes in your snapshots) and skips the reformatting of the whole file.
I think you have
[tool.ruff.format]
quote-style = "single"
in your config.
I will think about a way to handle the formatting better. Maybe a enforce-format="black|ruff"
option, maybe integrating ruff in the same way I integrated black.
What would you prefer?
OK, I see now how this happens:
def test_example():
foo = [dict.fromkeys(range(6), 'abcdefghijkl') for _ in range(2)]
assert foo == snapshot([
{
0: "abcdefghijkl",
1: "abcdefghijkl",
2: "abcdefghijkl",
3: "abcdefghijkl",
4: "abcdefghijkl",
5: "abcdefghijkl",
},
{
0: "abcdefghijkl",
1: "abcdefghijkl",
2: "abcdefghijkl",
3: "abcdefghijkl",
4: "abcdefghijkl",
5: "abcdefghijkl",
},
])
as a result of only formatting the snapshot. I do think that could be improved so that the result is still nice for people who are not using any kind of formatter. Specifically, I think you should black/ruff-format the snapshot call node (not just the contents) and then indent that by the amount of indentation in the containin statement (4 spaces in this case).
I will think about a way to handle the formatting better. Maybe a
enforce-format="black|ruff"
option, maybe integrating ruff in the same way I integrated black.What would you prefer?
I'm not sure I understand the difference between the two options. If both are integrated, there will probably need to be a config option to pick one. You could maybe default to using the one that seems closest to the file's current formatting. If it's a tie, I would suggest choosing ruff just because it's faster.
Formating source ranges is not supported by black https://github.com/psf/black/issues/134#issuecomment-381726788
I can fix the indentation and make it look acceptable if you are not using black for your whole file. But the indentation affects the formatting and this solution will probably never be perfect.
Detecting if a file is formatted and preserving this formatting is easier. This is what inline-snapshot currently does with black.
You can format your example with black before you fix your snapshot. Inline-snapshot will format the whole file after the fix and preserve the formatting.
I think I can implement the same behavior for ruff formatted files.
To be clear, for the case of formatting just the snapshot, I'm only talking about it for the sake of interest and because I imagine you'd like it to work better for users not using black/ruff. I'm happy with just formatting the whole file with ruff.
I'm not suggesting formatting source ranges. I'm saying instead of using black to format [{...}]
, format snapshot([{...}])
, and then indent that.
BTW, it would be nice to use inline-snapshot completely without Black since it pulls in several the dependencies.
Wouldn't it be reasonable to tell users that whatever code formatter they use, it should be installed for this to work? Would probably require a major bump, but then again it's "just" a test dependency so no service should go down because of that. Maybe add inline-snapshots[black]
and inline-snapshots[ruff]
, too.
@hynek, you propose to ship inline-snapshot without a default formatter, if I understand you correct.
The problem is that repr()
has no line length limit or formatting. It generates just an very long string when you pass it some large dict/list values. This is not the best experience for the developer.
But it might be a good idea to provide only a inline-snapshots[ruff]
option which depends not on black.
Yeah, I personally would be fine with Black being the default, but not being auto-installed. And that I’m able to overwrite the default in tool.inline-snapshot.formatter
or something like that.
Every time I fix snapshots, I immediately have to press a few more keys to reformat with ruff. It'd be lovely if it was already formatted 'correctly'.