hatch icon indicating copy to clipboard operation
hatch copied to clipboard

`hatch fmt` leads to unresolvable `ruff` setting conflict with `from __future__ import annotations`

Open warsaw opened this issue 1 year ago • 18 comments

Let's start with this branch: https://gitlab.com/warsaw/public/-/tree/hatch-fmt

Specifically, the src/public/public.py file starts with these lines:

# https://docs.astral.sh/ruff/rules/future-rewritable-type-annotation/
from __future__ import annotations

import sys

from typing import Any, TYPE_CHECKING, overload

Running hatch fmt check gives me this error:

$ hatch fmt --check
src/public/public.py:2:1: I001 [*] Import block is un-sorted or un-formatted
Found 1 error.
[*] 1 fixable with the `--fix` option.

and would make this change:

$ hatch fmt --diff
--- src/public/public.py
+++ src/public/public.py
@@ -1,9 +1,10 @@
 # https://docs.astral.sh/ruff/rules/future-rewritable-type-annotation/
-from __future__ import annotations
-
 import sys
 
-from typing import Any, TYPE_CHECKING, overload
+from typing import TYPE_CHECKING, Any, overload
+
+from __future__ import annotations
+
 
 if TYPE_CHECKING:
     from .types import ModuleAware

Would fix 1 error.

Let's let hatch fix it:

$ hatch fmt
src/public/public.py:6:1: F404 `from __future__` imports must occur at the beginning of the file
Found 2 errors (1 fixed, 1 remaining).
$ git diff
git diff
diff --git a/src/public/public.py b/src/public/public.py
index b31fd19..d731a41 100644
--- a/src/public/public.py
+++ b/src/public/public.py
@@ -1,9 +1,10 @@
 # https://docs.astral.sh/ruff/rules/future-rewritable-type-annotation/
-from __future__ import annotations
-
 import sys
 
-from typing import Any, TYPE_CHECKING, overload
+from typing import TYPE_CHECKING, Any, overload
+
+from __future__ import annotations
+
 
 if TYPE_CHECKING:
     from .types import ModuleAware

Uh oh! The I001 and F404 can't be resolved without ignoring one or the other. Since __future__ imports should go at the top, it's probably better to ignore the I001 but such a blanket ignore could hide other import sorting issues.

warsaw avatar May 03 '24 01:05 warsaw

The solution would be to run just the formatter first via -f

ofek avatar May 03 '24 01:05 ofek

Hmm, running hatch fmt -f turns all my single quotes to double quotes!

warsaw avatar May 03 '24 01:05 warsaw

You would have to add configuration for that, see the config file in this repo

ofek avatar May 03 '24 01:05 ofek

Ah, so hatch fmt -f doesn't use the same defaults as hatch fmt?

warsaw avatar May 03 '24 01:05 warsaw

No it does but what's happening is that the linter comes first followed by the formatter and you're encountering an error in the former so the only way is to run the other one separately. This is a known issue where everything is not yet cohesive which is why they have a plan to only have a single command, and also the reason I have implemented this as a single command in preparation for that future.

ofek avatar May 03 '24 01:05 ofek

I see! Thanks. Let me continue to play around with it.

warsaw avatar May 03 '24 02:05 warsaw

I still have to add the noqa: I001 to the from __future__ import annotations line, but I'm going to chalk this up to ruff's problem, not hatch's.

https://gitlab.com/warsaw/public/-/blob/hatch-fmt/src/public/public.py#L3

warsaw avatar May 03 '24 02:05 warsaw

I'm confused, why is it trying to move the import somewhere other than the top?

ofek avatar May 03 '24 02:05 ofek

I'm confused, why is it trying to move the import somewhere other than the top?

Great question! I'm confused why it wants to do that too.

warsaw avatar May 03 '24 15:05 warsaw

Fixed?

ofek avatar May 04 '24 16:05 ofek

Nope, even with ruff 0.4.3.

warsaw avatar May 04 '24 16:05 warsaw

You provide a minimal reproducible example file and open up an issue over there?

ofek avatar May 04 '24 16:05 ofek

So, you don't think it's a hatch fmt problem specifically?

warsaw avatar May 04 '24 19:05 warsaw

If you can provide a very small file to reproduce we could test by just enabling that single offending rule.

ofek avatar May 04 '24 19:05 ofek

I don't know if this is reproducible outside the repository, but the file triggering the problem is public.py.

Another way to reproduce it is:

$ git clone https://gitlab.com/warsaw/public.git
$ cd public
# Edit src/public/public.py to remove the noqa comment from the future import line
$ hatch fmt --check src
src/public/public.py:7:1: I001 [*] Import block is un-sorted or un-formatted
Found 1 error.
[*] 1 fixable with the `--fix` option.
$ hatch fmt src
src/public/public.py:11:1: F404 `from __future__` imports must occur at the beginning of the file
Found 2 errors (1 fixed, 1 remaining).
$ git diff
diff --git a/src/public/public.py b/src/public/public.py
index 96bd404..bbe8d7f 100644
--- a/src/public/public.py
+++ b/src/public/public.py
@@ -4,11 +4,12 @@
 # and linter will be in conflict between I001 and F404 (which wants to move
 # this import to below `import sys`.  Ruff's unified linter and formatter
 # will hopefully resolve this: https://github.com/astral-sh/ruff/issues/8232
-from __future__ import annotations  # noqa: I001
-
 import sys
 
-from typing import Any, TYPE_CHECKING, overload
+from typing import TYPE_CHECKING, Any, overload
+
+from __future__ import annotations
+
 
 if TYPE_CHECKING:
     from .types import ModuleAware

warsaw avatar May 04 '24 19:05 warsaw

Disable Hatch static analysis config: https://hatch.pypa.io/latest/config/internal/static-analysis/#no-config

ofek avatar May 04 '24 20:05 ofek

Sorry, are you saying that this is not a bug in hatch, or it is caused by the ruff lint/formatter problem? One thing that I think would help to debug further is to be able to print the commands hatch is running with higher verbosity in hatch fmt, but I believe you're fixing that already.

warsaw avatar May 06 '24 15:05 warsaw

I'm not precisely sure what caused the issue but I thought that you weren't extending when in fact you seem to be doing so. I wonder what happens when you try the persistent config approach.

ofek avatar May 06 '24 16:05 ofek