diff --git a/.isort.cfg b/.isort.cfg new file mode 100644 index 0000000..8ee9a98 --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,6 @@ +[settings] +line_length=100 +multi_line_output=4 +use_parentheses=true +known_standard_library=Bastion,CGIHTTPServer,DocXMLRPCServer,HTMLParser,MimeWriter,SimpleHTTPServer,UserDict,UserList,UserString,aifc,antigravity,ast,audiodev,bdb,binhex,cgi,chunk,code,codeop,colorsys,cookielib,copy_reg,dummy_thread,dummy_threading,formatter,fpformat,ftplib,genericpath,htmlentitydefs,htmllib,httplib,ihooks,imghdr,imputil,keyword,macpath,macurl2path,mailcap,markupbase,md5,mimetools,mimetypes,mimify,modulefinder,multifile,mutex,netrc,new,nntplib,ntpath,nturl2path,numbers,opcode,os2emxpath,pickletools,popen2,poplib,posixfile,posixpath,pty,py_compile,quopri,repr,rexec,rfc822,runpy,sets,sgmllib,sha,sndhdr,sre,sre_compile,sre_constants,sre_parse,ssl,stat,statvfs,stringold,stringprep,sunau,sunaudio,symbol,symtable,telnetlib,this,toaiff,token,tokenize,tty,types,user,uu,wave,xdrlib,xmllib +known_third_party=six,six.moves,sip diff --git a/esss_fix_format/cli.py b/esss_fix_format/cli.py index eadc7e8..281b9b5 100644 --- a/esss_fix_format/cli.py +++ b/esss_fix_format/cli.py @@ -6,40 +6,6 @@ import click - -# This is a complete list of all modules in our stdlib which are not already known to isort -# This is a workaround for https://github.com/timothycrosley/isort/issues/464 -all_stdlib_modules = ["Bastion", "CGIHTTPServer", "DocXMLRPCServer", "HTMLParser", "MimeWriter", - "SimpleHTTPServer", "UserDict", "UserList", "UserString", "aifc", - "antigravity", "ast", - "audiodev", "bdb", "binhex", "cgi", "chunk", "code", "codeop", "colorsys", - "cookielib", "copy_reg", "email", - "dummy_thread", "dummy_threading", "formatter", "fpformat", "ftplib", - "genericpath", - "htmlentitydefs", "htmllib", "httplib", "ihooks", "imghdr", "imputil", - "keyword", "macpath", "macurl2path", - "mailcap", "markupbase", "md5", "mimetools", "mimetypes", "mimify", - "modulefinder", "multifile", "mutex", - "netrc", "new", "nntplib", "ntpath", "nturl2path", "numbers", "opcode", - "os2emxpath", "pickletools", "popen2", "poplib", "posixfile", "posixpath", - "pty", - "py_compile", "quopri", "repr", "rexec", "rfc822", "runpy", "sets", "sgmllib", - "sha", "sndhdr", "sre", - "sre_compile", "sre_constants", "sre_parse", "ssl", "stat", "statvfs", - "stringold", - "stringprep", "sunau", "sunaudio", "symbol", "symtable", "telnetlib", "this", - "toaiff", "token", - "tokenize", "tty", "types", "user", "uu", "wave", "xdrlib", "xmllib"] - -ISORT_CONFIG = { - 'line_length': 100, - 'multi_line_output': 4, # 4-vert-grid - 'use_parentheses': True, - # This is a workaround for https://github.com/timothycrosley/isort/issues/464 - 'known_standard_library': all_stdlib_modules, - 'known_third_party': ["six", "six.moves", "sip"], -} - PATTERNS = { '*.py', '*.cpp', @@ -74,7 +40,7 @@ def should_format(filename): help='use modified files from git') def main(files_or_directories, check, stdin, commit): """Fixes and checks formatting according to ESSS standards.""" - import isort + import isort.settings if stdin: files = [x.strip() for x in click.get_text_stream('stdin').readlines()] elif commit: @@ -119,7 +85,18 @@ def main(files_or_directories, check, stdin, commit): extension = os.path.normcase(os.path.splitext(filename)[1]) if extension == '.py': - sorter = isort.SortImports(file_contents=new_contents, **ISORT_CONFIG) + settings_path = os.path.dirname(filename) + settings_loaded = isort.settings.from_path(settings_path) + if settings_loaded['line_length'] < 80: + # The default isort configuration has 79 chars, so, if the passed + # does not have more than that, complain that .isort.cfg is not configured. + msg = ': ERROR .isort.cfg not available in repository (or line_length config < 80).' + error_msg = click.format_filename(filename) + msg + click.secho(error_msg, fg='red') + errors.append(error_msg) + + + sorter = isort.SortImports(file_contents=new_contents, settings_path=settings_path) # strangely, if the entire file is skipped by an "isort:skip_file" # instruction in the docstring, SortImports doesn't even contain an # "output" attribute diff --git a/tests/test_esss_fix_format.py b/tests/test_esss_fix_format.py index dd67d5d..625026f 100644 --- a/tests/test_esss_fix_format.py +++ b/tests/test_esss_fix_format.py @@ -13,9 +13,16 @@ from esss_fix_format import cli +@pytest.fixture +def sort_cfg_to_tmpdir(tmpdir): + import shutil + shutil.copyfile( + os.path.join(os.path.dirname(__file__), '..', '.isort.cfg'), + str(tmpdir.join('.isort.cfg'))) + @pytest.fixture -def input_file(tmpdir): +def input_file(tmpdir, sort_cfg_to_tmpdir): # imports out-of-order included in example so isort detects as necessary to change source = textwrap.dedent( '''\ @@ -34,6 +41,7 @@ def input_file(tmpdir): ) filename = tmpdir.join('test.py') filename.write(source) + return filename @@ -106,7 +114,7 @@ def test_fix_whitespace(input_file): assert obtained == expected -def test_imports(tmpdir): +def test_imports(tmpdir, sort_cfg_to_tmpdir): source = textwrap.dedent('''\ import pytest import sys @@ -146,7 +154,7 @@ def test_unknown_extension(input_file): output.fnmatch_lines(str(new_filename) + ': Unknown file type') -def test_filename_without_wildcard(tmpdir): +def test_filename_without_wildcard(tmpdir, sort_cfg_to_tmpdir): filename = tmpdir.join('CMakeLists.txt') filename.write('\t#\n') output = run([str(filename)], expected_exit=0) @@ -176,7 +184,7 @@ def check_output(cmd, *args, **kwargs): ] -def test_input_invalid_codec(tmpdir): +def test_input_invalid_codec(tmpdir, sort_cfg_to_tmpdir): """Display error summary when we fail to open a file""" filename = tmpdir.join('test.py') filename.write(u'hello world'.encode('UTF-16'), 'wb') @@ -186,14 +194,14 @@ def test_input_invalid_codec(tmpdir): output.fnmatch_lines(str(filename) + ': ERROR (Unicode*') -def test_empty_file(tmpdir): +def test_empty_file(tmpdir, sort_cfg_to_tmpdir): """Ensure files with a single empty line do not raise an error""" filename = tmpdir.join('test.py') filename.write(u'\r\n', 'w') run([str(filename)], expected_exit=0) -def test_skip_entire_file(tmpdir): +def test_skip_entire_file(tmpdir, sort_cfg_to_tmpdir): """Check that a module-level isort:skip_file correctly skips that file""" source = textwrap.dedent('''\ """ @@ -208,7 +216,7 @@ def test_skip_entire_file(tmpdir): assert filename.read() == source -def test_isort_bug_with_comment_headers(tmpdir): +def test_isort_bug_with_comment_headers(tmpdir, sort_cfg_to_tmpdir): source = textwrap.dedent("""\ ''' See README.md for usage. @@ -231,7 +239,7 @@ def Ask(question, answers): check_valid_file(filename) -def test_missing_builtins(tmpdir): +def test_missing_builtins(tmpdir, sort_cfg_to_tmpdir): source = textwrap.dedent("""\ import thirdparty import os @@ -253,7 +261,7 @@ def test_missing_builtins(tmpdir): """) -def test_force_parentheses(tmpdir): +def test_force_parentheses(tmpdir, sort_cfg_to_tmpdir): source = ( 'from shutil import copyfileobj, copyfile, copymode, copystat,\\\n' ' copymode, ignore_patterns, copytree, rmtree, move' @@ -270,6 +278,12 @@ def test_force_parentheses(tmpdir): ) assert obtained == expected +def test_no_isort_cfg(tmpdir): + filename = tmpdir.join('test.py') + filename.write('import os', 'w') + output = run([str(filename)], expected_exit=1) + output.fnmatch_lines(r'*ERROR .isort.cfg not available in repository (or line_length config < 80).') + def run(args, expected_exit): from _pytest.pytester import LineMatcher