Skip to content
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

Support isort5 #92

Merged
merged 7 commits into from
Aug 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 22 additions & 10 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
dist: xenial
language: python
matrix:
- python: '2.7'
- python: '3.5'
- python: '3.6'
- python: '3.7'
- python: '3.8'
- python: 'pypy'
- python: 'pypy3'
python:
- '2.7'
- '3.5'
- '3.6'
- '3.7'
- '3.8'
- 'pypy'
- 'pypy3'
env:
- ISORT_VER="4"
- ISORT_VER="5"
jobs:
exclude:
- python: "2.7"
env: ISORT_VER="5"
- python: "3.5"
env: ISORT_VER="5"
- python: "pypy"
env: ISORT_VER="5"
cache: pip
install:
- if [[ $ISORT_VER == "4" ]]; then pip install 'isort < 5'; fi
- pip install .[test]
script:
- flake8 *.py
- pytest run_tests.py
- pytest -v
after_success:
- pip install -q -r requirements-cov.txt
- pytest run_tests.py --cov flake8_isort --cov-report term-missing
- pytest -v --cov flake8_isort --cov-report term-missing
- coveralls
4 changes: 2 additions & 2 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
Changelog
=========

3.0.2 (unreleased)
4.0.0 (unreleased)
------------------

- Nothing changed yet.
- support isort >= 5 [bnavigator, pkolbus]


3.0.1 (2020-07-08)
Expand Down
114 changes: 108 additions & 6 deletions flake8_isort.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
# -*- coding: utf-8 -*-
from difflib import Differ
from isort import SortImports
from testfixtures import OutputCapture

import isort

__version__ = '3.0.2.dev0'

if hasattr(isort, 'api'): # isort 5
from contextlib import redirect_stdout
from difflib import unified_diff
from io import StringIO
from pathlib import Path

class Flake8Isort(object):
import warnings
else:
from difflib import Differ
from testfixtures import OutputCapture

__version__ = '4.0.0.dev0'


class Flake8IsortBase(object):
name = 'flake8_isort'
version = __version__
isort_unsorted = (
Expand Down Expand Up @@ -49,13 +59,17 @@ def parse_options(cls, options):
cls.stdin_display_name = options.stdin_display_name
cls.show_traceback = options.isort_show_traceback


class Flake8Isort4(Flake8IsortBase):
"""class for isort <5"""

def run(self):
if self.filename is not self.stdin_display_name:
file_path = self.filename
else:
file_path = None
with OutputCapture() as buffer:
sort_result = SortImports(
sort_result = isort.SortImports(
file_path=file_path,
file_contents=''.join(self.lines),
check=True,
Expand Down Expand Up @@ -168,3 +182,91 @@ def _fixup_sortimports_wrapped(sort_imports):
for new_idx, new_line in enumerate(
sort_imports.out_lines.pop(idx).splitlines()):
sort_imports.out_lines.insert(idx + new_idx, new_line)


class Flake8Isort5(Flake8IsortBase):
"""class for isort >=5"""

def run(self):
if self.filename is not self.stdin_display_name:
file_path = Path(self.filename)
isort_config = isort.settings.Config(
settings_path=file_path.parent)
else:
file_path = None
isort_config = isort.settings.Config(
settings_path=Path.cwd())
input_string = ''.join(self.lines)
traceback = ''
isort_changed = False
input_stream = StringIO(input_string)
output_stream = StringIO()
isort_stdout = StringIO()
try:
with redirect_stdout(isort_stdout):
isort_changed = isort.api.sort_stream(
input_stream=input_stream,
output_stream=output_stream,
config=isort_config,
file_path=file_path)
except isort.exceptions.FileSkipped:
pass
except isort.exceptions.ISortError as e:
warnings.warn(e)
if isort_changed:
outlines = output_stream.getvalue()
diff_delta = "".join(unified_diff(
input_string.splitlines(keepends=True),
outlines.splitlines(keepends=True),
fromfile="{}:before".format(self.filename),
tofile="{}:after".format(self.filename)))
traceback = (isort_stdout.getvalue() + "\n" + diff_delta)
for line_num, message in self.isort_linenum_msg(diff_delta):
if self.show_traceback:
message += traceback
yield line_num, 0, message, type(self)

def isort_linenum_msg(self, udiff):
"""Parse unified diff for changes and generate messages

Args
----
udiff : unified diff delta

Yields
------
tuple: A tuple of the specific isort line number and message.
"""
line_num = 0
additions = []
moves = []
for line in udiff.splitlines():
if line.startswith('@@', 0, 2):
line_num = int(line[4:].split(' ')[0].split(',')[0])
continue
elif not line_num: # skip lines before first hunk
continue
if line.startswith(' ', 0, 1):
line_num += 1 # Ignore unchanged lines but increment line_num.
elif line.startswith('-', 0, 1):
if line.strip() == '-':
yield line_num, self.isort_blank_unexp
line_num += 1
else:
moves.append(line[1:])
yield line_num, self.isort_unsorted
line_num += 1
elif line.startswith('+', 0, 1):
if line.strip() == '+':
# Include newline additions but do not increment line_num.
yield line_num, self.isort_blank_req
else:
additions.append((line_num, line))

# return all additions that did not move
for line_num, line in additions:
if not line[1:] in moves:
yield line_num, self.isort_add_unexp


Flake8Isort = Flake8Isort5 if hasattr(isort, 'api') else Flake8Isort4
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 💯

Loading