pycqa / isort Goto Github PK
View Code? Open in Web Editor NEWA Python utility / library to sort imports.
Home Page: https://pycqa.github.io/isort/
License: MIT License
A Python utility / library to sort imports.
Home Page: https://pycqa.github.io/isort/
License: MIT License
Sometimes you have a submodule in which you want to sort the imports in a seperate group. For example see https://github.com/django/django/blob/master/django/contrib/admin/views/main.py
Could you add a way to configure isort for that case?
For example by adding a 'subpackage' option to the config file.
The process of compiling code into pyc files and checking for syntax errors could be used after and potentially before isort is ran to verify isort does not introduce any errors. If isort does introduce an error, a message would be displayed to the user, and the file would stay at the state it was before isort was ran, with the isort output never being written to the filesystem.
There many situations when some imports should not be put at the top, lest it will introduce circularity. These include projects such as Flask apps with HTTP handlers split between separate modules:
# __init__.py
from flask import Flask
app = Flask('myapp')
import myapp.handlers
# handlers.py
from myapp import app
@app.route('index')
def index():
return "Hello world"
In this example, moving import myapp.handlers
to the top will cause circular import error because of app
symbol.
We can of course exclude the whole file, but this may be suboptimal. I suggest introducing a directive that allows for more fine-grained skipping, for example:
import myapp.handlers # isort:skip
On most of the projects I work on, everything is namespaced so it's really easy to say --known-first-party=<base namespace>
. Unfortunately for lazy people, everything unknown is assumed to be first-party so I have to build a long list of known third-party packages. It'd be really nice if there was a way to simply have isort treat everything not in stdlib or the first-party list as third-party so I would only need to populate the exceptions.
isort creates import lines with multiple spaces like this:
from my_package import Mod0, Mod1, \
Mod2, fun1
flake8 will complain about them:
myfile:13:44: E271 multiple spaces after keyword
from my_package import mod0, mod1, \
^
Avoid extraneous whitespace around keywords.
When I remove the duplicate space and run isort again, it reappears.
For example, in my own project. Before:
import socket
import struct
from parsley import makeProtocol, stack
from twisted.internet import protocol, defer, interfaces
from twisted.python import failure
from zope.interface import implements
import txsocksx.constants as c, txsocksx.errors as e
from txsocksx import grammar
After:
import socket
import struct
import txsocksx.constants as c
from parsley import makeProtocol, stack
from twisted.internet import defer, interfaces, protocol
from twisted.python import failure
from txsocksx import grammar
from zope.interface import implements
import c as e
import e
It would be nice to have a configurable option to allow multiple "from a import b" lines, instead of forcing them all to be on a single line, e.g. to allow
from a import b
from a import c
instead of
from a import b, c
PEP 8 says that the latter is "OK", but it seems to be phrased as an exception to the basic idea of "Imports should usually be on separate lines"
It looks like when isort is run on multiple times on a file with an .isortrc like this:
[settings]
import_heading_stdlib=Standard Library
import_heading_thirdparty=Third Party
import_heading_localfolder=Local
I'll get a file which looks like this:
# Standard Library
# Standard Library
# Standard Library
import heapq
# Local
from . import util
from .node import nullrev
# Local
# Local
I expect you need a check to see if the comment is already there.
This is useful for integrating with existing IDEs (esp. Emacs)
isort caused a syntax error:
--- a/foo/foo/foo_foo/tests/foo_v0/test_jobs.py
+++ b/foo/foo/foo_foo/tests/foo_v0/test_jobs.py
@@ -6,9 +6,10 @@ from django.test.client import RequestFactory
from mock import patch
from model_mommy import mommy
-from ... import models, sproqet_api as sproq_api
-from ... fields.sproqet import SproqetCollection
-from ..utils import fake_spork_client, http_status_codes as status
+from ... import sproqet_api as sproq_api
+from ... import fields.sproqet, models, SproqetCollection
+from ..utils import http_status_codes as status
+from ..utils import fake_spork_client
from ..utils.misc import SporkPatcherTestCaseMixin
from .utils.constants import job_clone_uri_name, job_detail_uri_name
It would be nice if I could configure my jnekins box to "UNSTABLE" the build if imports are in the wrong order. For this, isort should leave the files alone and print out error messages for each bad line.
Along with this feature the ability to add:
from django import foo # isort: disable
would be nice
Following the changes for allowing order_by_type
(thanks for that by the way)
I get the following diff
@@ -27,13 +27,13 @@
# might be a little less Pythonic. See os.system() calls for more
# details.
+import StringIO
import glob
import os
import shutil
-import StringIO
import tempfile
import time
-from subprocess import Popen, PIPE, STDOUT
+from subprocess import PIPE, Popen, STDOUT
join = os.path.join
Two issues seem to be present
from subprocess import PIPE, STDOUT, Popen
Before:
import socket
import struct
from parsley import makeProtocol, stack
from twisted.internet import protocol, defer, interfaces
from twisted.python import failure
from zope.interface import implements
import txsocksx.constants as c, txsocksx.errors as e
from txsocksx import grammar
After:
import socket
import struct
import txsocksx.constants as c
import txsocksx.errors as e
from parsley import makeProtocol, stack
from twisted.internet import defer, interfaces, protocol
from twisted.python import failure
from txsocksx import grammar
from zope.interface import implements
import c
import e
This is better than before, but still somehow ends up with import c
and import e
.
(TL;DR: I think comments should be ignored when determining what the "next" thing in a file is after imports)
pep8
is happy with the following file:
import sys
# This is a comment
def foo():
pass
Running isort
on it removes one of the newlines between the import and the comment, which makes pep8
unhappy.
The lines_after_imports
setting lets us work-around this (which is good 👍), but it means that we always end up with two spaces, even in the cases where pep8
would be happy with only 1.
For example, pep8
is happy with the single space in this case:
import sys
# This is a comment
wibble = 'bar'
P.S. Thanks for all your hard work making a great tool!
The following diff is from our code.
I'd expect the current line to remain unchanged. Instead isort breaks this in two but then also sorts it in an order that doesn't seem to follow any logical sort order. Both parse and rich_parse should sort after general. I'd expect this to sort on parse anyway and not on rich_parse.
from translate.misc.multistring import multistring
from translate.storage import base, factory
-from translate.storage.placeables import general, parse as rich_parse
+from translate.storage.placeables import parse as rich_parse
+from translate.storage.placeables import general
Traceback (most recent call last):
File "/usr/share/apps/kate/plugins/pate/kate/init.py", line 306, in call
return self.f()
File "/home/zaufi/.kde4/share/apps/kate/pate/kate_plugin.py", line 59, in add_imports
document.setText(SortImports(file_contents=document.text(), add_imports=text.split(";")).output)
File "/usr/lib64/python3.3/site-packages/isort/isort.py", line 91, in init
self._parse()
File "/usr/lib64/python3.3/site-packages/isort/isort.py", line 316, in _parse
self.as_map[imports[index -1]] = imports[index + 1]
IndexError: list index out of range
I have a file in my code base that looks like this:
"""Module docstring"""
class MyClass(object):
pass
I try to run this:
isort -a "from __future__ import print_function"
Afterwards the file looks like this:
"""Module docstring"""
class MyClass(object):
pass
from __future__ import print_function
Since __future__
imports need to be at the top of the file, this is invalid syntax.
I'd like to be able to print the diff so that I can see what isort
is trying to do before actually writing to the file system. An option like --diff
would be fine. Though I kind of like the default behavior of 2to3
, which does the safe thing by default by only writing to the file system if the user tells it to. Otherwise it just prints a diff.
after any action (add
or remove
, not talking about sort
) it would be nice to have a cursor at the original position.
It would be nice to have a new mode, mixing the grid with the hanging indent.
Something like this:
from third_party import (
lib1, lib2, lib3,
lib4, lib5, lib6)
It would help to save lines and fits well with long from module paths.
$ isort *
Traceback (most recent call last):
File "/usr/local/bin/isort", line 30, in
SortImports(file_name, **arguments)
File "/usr/local/lib/python2.7/dist-packages/isort/isort.py", line 82, in init
self._parse()
File "/usr/local/lib/python2.7/dist-packages/isort/isort.py", line 273, in _parse
self.imports[module_placment][import_type].setdefualt(from_import, set()).update(imports)
AttributeError: 'dict' object has no attribute 'setdefualt'
When I use line breaks in my imports, like this:
from my_lib.my_package.test.level_1.level_2.level_3.level_4.level_5.\
my_module import my_function
isort drops everything after the \
:
-from my_lib.my_package.test.level_1.level_2.level_3.level_4.level_5.\
- my_module import my_function
+from my_lib.my_package.test.level_1.level_2.level_3.level_4.level_5. import my_function
This of course breaks the code and is obviously not intended. isort should detect the line break, strip the indentation whitespace on the second line, concatenate the import into one and hande that as usual.
Note that there is a .
character before the import
keyword, which is always invalid syntax.
Also note that the import line isort adds is longer than allowed. I am not sure if this can be fixed together or in a different issue.
In our project we decided to break the cluster of imports from a module such that they are grouped not just alphabetically bust by type.
So:
from module import CONSTANT, Class, function
Instead of:
from module import Class, CONSTANT, function
We find the visual order much easier to parse.
Relating to #38, this would make it even easier to use with M-|
in emacs.
Many tools do this by accepting the special file name -
as meaning stdin. This can also imply -d
$subj will be added after every call to this plugin.
to reproduce, just press Ctrl+[
for a few seconds: watch how vertical scrollbar is getting grow...
same for add
and remove
import...
The check feature gives a wrong output, if there are newlines in the insert line of the input file.
For example:
from lib import (
some_object,
some_other_object)
Here is a test for this problem.
from mock import patch
def test_check_newline_in_imports():
test_input = "from lib1 import (\n sub1, sub2\n sub3)"
SortImports.file_path = '' # Add file_path to Class
with patch('__builtin__.print') as mock_print:
SortImports(file_path=False, file_contents=test_input, check=True)
assert 'SUCCESS' in mock_print.call_args[0][0]
For example, in this project's isort.py. Before:
from __future__ import absolute_import, division, print_function, unicode_literals
import copy
import os
from pies import *
from sys import path as PYTHONPATH
from . import settings
After:
from __future__ import absolute_, division, print_function, unicode_literals
import copy
import os
from sys import path as PYTHONPATH
from pies import *
from . import settings
Note the absolute_
.
Sometimes it is useful to comment imports, e.g. to clarify renames:
from a import f as f_small # more space efficient implementation
from b import f as f_quick # more time efficient implementation
Currently isort removes such inline comments:
from a import f as f_small
from b import f as f_quick
isort should reorder and reformat inline comments properly.
It seems like the tool always writes the result into the current directory, which is pretty unexpected. I think you should provide an --inplace option or fail explicitly if you don't know where to save the result.
Currently for the unsuspecting newcomer it seems that the tool does nothing when run on a different path.
pep8 can use the setup.cfg file for project-level config: http://pep8.readthedocs.org/en/latest/intro.html#configuration
What do you think about using that instead of / in addition to the .isort.cfg file to reduce the proliferation of dotfiles inside projects?
It should be possible to test python projects by running,
python setup.py test in their project directory.
A cool tool for this is:
https://nose.readthedocs.org/en/latest/setuptools_integration.html
It would be great to run these tests on py2-3 on travis-ci
from __future__ import unicode_literals
import datetime
from random import randint
from django.core.urlresolvers import reverse
from django.utils.six.moves import xrange
from rest_framework.viewsets import ViewSet
becomes:
from __future__ import unicode_literals
import datetime
from random import randint
from django.core.urlresolvers import reverse
from rest_framework.viewsets import ViewSet
from django.utils.six.moves import xrange
Here's two more or less identical python scripts, one of which contains UTF-8 encoded characters:
$ cat test1.py
# -*- coding: utf-8 -*-
"""abc"""
$ cat test2.py
# -*- coding: utf-8 -*-
"""æøå"""
$ python test1.py && echo ok
ok
$ python test2.py && echo ok
ok
$ isort test1.py && echo ok
ok
$ isort test2.py && echo ok
Traceback (most recent call last):
File "/usr/local/bin/isort", line 43, in <module>
SortImports(file_name, **arguments)
File "/usr/local/lib/python2.7/dist-packages/isort/isort.py", line 73, in __init__
self.in_lines = file_contents.split("\n")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 27: ordinal not in range(128)
$
Boom!
Setting anything to False
in the .isort.cfg
does not work.
The following .isort.cfg
[settings]
balanced_wrapping=False
length_sort=False
order_by_type=False
is equivalent to
[settings]
balanced_wrapping=True
length_sort=True
order_by_type=True
or even
[settings]
balanced_wrapping=does_not_matter
length_sort=irrelevant
order_by_type
As a workaround, I commented out all settings I wanted to be False
, since that is currently the default for all of them:
[settings]
# balanced_wrapping=False
# length_sort=False
# order_by_type=False
argparse, configparser, and ordereddict really should not be installed on Python 2.7. At best this is unnecessary. At worst it is clobbering things.
Ideally, isort should keep record of what areas of a file changed. The Kate plugin should then use this data to update the text for only these areas (instead of replacing the entire document text).
When I run (the current 2.6.1 from PyPI) isort using the command line options like this:
$ isort --multi_line=2 src/**/*.py
my imports get formatted like this:
from third_party import lib1, lib2, lib3, \
lib4, lib5, lib6
When I try to use the config file to configure indent permanently like this:
$ cat .isort.cfg
[settings]
# [...]
indent=' '
my source gets polluted with quotation marks like this:
from third_party import lib1, lib2, lib3, \
' 'lib4, lib5, lib6
Seems like the string from the configuration file gets copied without removing the quotation marks.
I get this altered sort order. I think thread should be a standard library...
@@ -28,10 +28,10 @@ import os.path
import re
import stat
import sys
-import thread
from UserDict import UserDict
from sqlite3 import dbapi2
+import thread
from translate import __version__ as toolkitversion
from translate.lang.common import Common
from translate.misc.multistring import multistring
Then I force it using
known_standard_library=thread
And now the diff is this
@@ -24,14 +24,14 @@
"""
import logging
-import os.path
import re
import stat
-import sys
import thread
from UserDict import UserDict
from sqlite3 import dbapi2
+import os.path
+import sys
from translate import __version__ as toolkitversion
from translate.lang.common import Common
from translate.misc.multistring import multistring
i.e. a lot of standard libraries have been moved to incorrect sections.
While PEP8 is unclear about how many lines after the import block it does say this:
"Separate top-level function and class definitions with two blank lines."
So in our code we add two lines after imports to closely match our high level double line breaks.
This probably isn't what other people do so being able to set the blank line following an import block would be a good option
Input:
import os
"""
Let us
import foo
okay?
"""
Corrupted output:
import os
import foo
"""
Let us
okay?
"""
Hi,
I have written a package to use isort with Emacs - py-isort.el: https://github.com/paetzke/py-isort.el. Maybe you can mention it in the Readme.
Greetings
Friedrich
When sorting, adding, or removing imports using the isort Kate plugin the current selected text becomes un-selected unexpectedly.
I didn't do a pull request adding the vim plugin to your repo, because in the vim world we use some plugin managers that install plugins directly from git repos, and the repos must have the vim plugin structure on the root folder. That would require that I put the vim plugin code on the root of your repo, which would be ugly. So I created the plugin on its own repo, here:
https://github.com/fisadev/vim-isort
Can you point to it on the readme?
input
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from model.parser import LogParser
from utils.scribec import send as scribesend
output
import os
import sys
from model.parser import LogParser
from utils.scribec import send as scribesend
looks like sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
is gone.
I don't think the fix for #67 is quite right.
import os
'\
import foo'
is still parsed incorrectly. isort
ends up garbling the syntax into
import os
import foo'
'\
I would recommend using Python tokenizer and blacklisting those lines that are within strings. I think that would be easier than coming up with a custom Python parser.
isort currently collapses spaces separating inline comments from import statements into one space.
When I write this:
import a # useful library
isort removes one of the spaces:
diff [...]
-import a # useful library
+import a # useful library
According to pep8, [i]nline comments should be separated by at least two spaces from the statement.
I think, isort should keep double spaces if they exist, to keep code adhering to pep8 valid. Perhaps isort should also introduce double spaces, if there is only one, to make the resulting code adhere to pep8.
I had one weird import in my code that got ignored by isort:
from pkg \
import stuff, other_suff \
more_stuff
Sorry if this is fixed already - I only tested with pypi release.
I'm working on a project with some funky paths config, which means the project I'm working on is discovered as a thirdy-party lib rather than first-party code.
It would be nice to have a config file ala .pep8
or setup.cfg
that can be checked into git.
Hi,
Thanks for this great project, I use it via vim and it works very well for me.
I have a little suggestion concerning the __future__
statement. isort formats it like this:
from __future__ import (absolute_import, division, print_function,
unicode_literals)
I would like to see print_function
in the next line:
from __future__ import (absolute_import, division,
print_function, unicode_literals)
It looks more balanced :) It's not a big thing, I know.
Best,
Laszlo
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.