-
Notifications
You must be signed in to change notification settings - Fork 234
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
style: isort #519
style: isort #519
Conversation
Second commit is completely generated so this can easily be rebased, no rush. |
This might be the first time I more or less agree with Black :-o Two things that're ugly, IMO:
I'll come back complaining when Black starts correcting me when I'm sure I'm right ;-) |
https://pycqa.github.io/isort/ What is wrong with grouping imports? |
Sorting imports and many of the decisions in Black are not about beauty, but are about reducing merge conflicts. Sorted imports would have removed 1 of 6 merge conflicts when I rebased #511, Black would have removed at least 2 more with function arguments. My work would have been cut in half.
PS: TLDR; 3 doesn't bother me that much, I'd rather consistency. But it might even be controllable. |
You could put pytest first: https://pycqa.github.io/isort/#custom-sections-and-ordering :) |
from . import test_projects | ||
import pytest | ||
|
||
from . import test_projects, utils |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is slightly confusing, actually, the thing after a from x import
ideally shouldn't be a module; if you have an __init__.py
and it contains a test_projects
or utils
object, you'll get that instead of the module. But it's a bit special for .
imports, since you are required to use from
with a relative import.
I believe you are guaranteed to have the test directory as the first on the path in PyTest, so this could be just import test_projects
, etc? Also, we could from .test_projects import new_c_project
, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of the exiting ones are written this way, so I'd probably leave it for now, and eventually rewrite them properly (see test_0_basic.py
, for example).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I first wanted to suggest import .test_projects
, but apparently that only works in the from ... import ...
construct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the thing after a
from x import
ideally shouldn't be a module
Not sure I agree, e.g. from numpy import linalg
from django import models
from tensorflow import keras
... also I'd rather rely on the __init__.py
file being empty than rely on the value of sys.path
. I expect tools like mypy or language servers to be able to read the code better without relying on a sys.path
set by pytest too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from numpy import linalg
is an often used shortcut for import numpy.linalg as linalg
, but it is confusing - a reader can't tell if linalg is a package or an object. We are stuck with it, but I wish the language wasn't ambiguous. Ideally, relative imports probably should import objects, from .test_projects import new_c_project
.
Relative imports also don't work if you don't execute it as a package; python test_before_all.py
will fail. (ImportError: attempted relative import with no known parent package
) (PyTest handles this correctly).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure it matters, from a users' point of view.
If you try to rewrite it, you have to either run it interactively or look up the source. For example:
from a import b
b.c()
# May or may not be written as
from a.b import c
c()
And, if you need to look up the source, is there an a/b.py
or an a/__init__.py
file with a b in it, or is it a file? (I often teach Python, this sort of thing can be a pain point...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use relative imports a lot, but they have downsides, especially for new users who do not know how to set up a proper environment. They have to be in a loaded package; it's not only "in the same directory". So python x.py
inside a package fails if there are relative imports in x
; I think python outer/x.py
fails too (I could be wrong). If you stick a if __name__ == "__main__"
in it for standalone runs or tests, it fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also use absolute imports a lot...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do know someone who will not do any import except import a.b.c
, and always uses fully qualified names. That's it. No shortening. It drive me crazy seeing numpy.stuff
sometimes. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW (given we're on this tangent anyway?), I tend to not like from module import thing
either. Often, module.thing
is not so much longer to write, should be auto-completed, and we're not trying to save bytes in code anyway? But yes, numpy
to np
just becomes a habit, after a while :-)
util, | ||
windows, | ||
) | ||
from cibuildwheel import linux, macos, util, windows |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is irritating, it didn't respect Black's magic comma.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it doesn't. Sad. For things like typing I add the comma because I know they are likely to change. (Not true of this case, of course, but might be useful elsewhere, especially with typing).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is irritating, it didn't respect Black's magic comma.
What did you mean? Black put ,
only at the end of the multiline import. When the import is a single line then black does not put a comma on the end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, that would be nice, if we could teach it. And once again (I'm surprised) I would agree with Black that the comma there is a pretty good indicator to say that this is a changing list.
Yeah, don't pay too much attention to my grumbling. These are just the things that I'm used to, so not even sure whether this was |
After finish the discussion here the simplest thing will be created the next PR which starts from the current master and has copied isort configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
from . import test_projects | ||
import pytest | ||
|
||
from . import test_projects, utils |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the thing after a
from x import
ideally shouldn't be a module
Not sure I agree, e.g. from numpy import linalg
from django import models
from tensorflow import keras
... also I'd rather rely on the __init__.py
file being empty than rely on the value of sys.path
. I expect tools like mypy or language servers to be able to read the code better without relying on a sys.path
set by pytest too.
To put @Czaki's recommendation into code; if you are working on a branch: git checkout master -- .pre-commit-config.yaml setup.cfg
pre-commit run -a
git add -u
git commit -m "style: pre-commit run -a" Then you can squash on master if you want. Or |
Also, for simplicity, I'll rebase and merge instead of squash and merge. Maybe we could even eventually add a |
Permissions error on Windows Travis can be ignored, I think. |
I restarted that build, but indeed. Go ahead if you want to merge :-) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Unless @joerick still wants to fix the from . import x, y
, but you already got an approval there, so I'm not holding up this PR on that!)
There already was a |
Actually, even easier, just rebase, delete the merge conflict lines, and then run |
This actually can do full Black-style includes, I like it. :) Discussed in #518.
This is Black-style, which I like - short includes are bundled onto one line, longer ones are one-per line. You can get merge conflicts for the short includes, but hopefully they are not changed often? And matching changes are okay.
Sticking configs in setup.cfg instead of pyproject.toml because mypy and flake8 don't support that yet. (Flake8 may never :( )