Hello community, here is the log from the commit of package python-autopep8 for openSUSE:Factory checked in at 2018-10-18 15:37:27 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-autopep8 (Old) and /work/SRC/openSUSE:Factory/.python-autopep8.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-autopep8" Thu Oct 18 15:37:27 2018 rev:13 rq:642684 version:1.4.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-autopep8/python-autopep8.changes 2018-09-04 22:56:19.993034338 +0200 +++ /work/SRC/openSUSE:Factory/.python-autopep8.new/python-autopep8.changes 2018-10-18 15:37:50.746194414 +0200 @@ -1,0 +2,36 @@ +Wed Oct 17 15:34:05 UTC 2018 - Arun Persaud <[email protected]> + +- specfile: + * update requirement of pycodestyle to >= 2.4 + +- update to version 1.4.1: + * update description for --exit-code option + * add unit test for --exit-code option + * fix fail test + * use --exit-code option value + * add --exit-code option + * format .rst + * update readme + * fallback, use .pep8 config + * update requirement, pycodestyle 2.4.0 and higher version + * refactoring + * not change import statement to top of file when duplicate import + * pycodestyle & autopep8 + * enable reading the settings from '.flake8' file + * change default config path + * change: return exit-code 1 when exists diff output + * work around exception for #403 + * fix w503 with into comments (for #411) + * handling exception with case of line comment + * remove debug print + * unit test for w503 and w504 fixed methods + * implementation W504 fixed method. + * W50x are set to DEFAULT_IGNORE + * update test suite data for e72x test + * add test for get_module_imports_on_top_of_file + * improve e402 fixed method + * update test suite output + * update method list + * add E402 fixed method and test + +------------------------------------------------------------------- Old: ---- autopep8-1.4.tar.gz New: ---- autopep8-1.4.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-autopep8.spec ++++++ --- /var/tmp/diff_new_pack.qVSzDB/_old 2018-10-18 15:37:51.394193673 +0200 +++ /var/tmp/diff_new_pack.qVSzDB/_new 2018-10-18 15:37:51.398193669 +0200 @@ -12,23 +12,23 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# Please submit bugfixes or comments via https://bugs.opensuse.org/ # %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-autopep8 -Version: 1.4 +Version: 1.4.1 Release: 0 Summary: Automatic generated to pep8 checked code License: MIT Group: Development/Languages/Python URL: https://github.com/hhatto/autopep8 Source: https://files.pythonhosted.org/packages/source/a/autopep8/autopep8-%{version}.tar.gz -BuildRequires: %{python_module pycodestyle >= 2.3} +BuildRequires: %{python_module pycodestyle >= 2.4} BuildRequires: %{python_module setuptools} BuildRequires: python-rpm-macros -Requires: python-pycodestyle +Requires: python-pycodestyle >= 2.4 Requires: python-setuptools Requires(post): update-alternatives Requires(postun): update-alternatives ++++++ autopep8-1.4.tar.gz -> autopep8-1.4.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autopep8-1.4/PKG-INFO new/autopep8-1.4.1/PKG-INFO --- old/autopep8-1.4/PKG-INFO 2018-09-01 18:03:14.000000000 +0200 +++ new/autopep8-1.4.1/PKG-INFO 2018-10-17 16:00:25.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: autopep8 -Version: 1.4 +Version: 1.4.1 Summary: A tool that automatically formats Python code to conform to the PEP 8 style guide Home-page: https://github.com/hhatto/autopep8 Author: Hideo Hattori @@ -138,7 +138,7 @@ [--ignore-local-config] [-r] [-j n] [-p n] [-a] [--experimental] [--exclude globs] [--list-fixes] [--ignore errors] [--select errors] [--max-line-length n] - [--line-range line line] [--hang-closing] + [--line-range line line] [--hang-closing] [--exit-code] [files [files ...]] Automatically formats Python code to conform to the PEP 8 style guide. @@ -175,7 +175,7 @@ separated globs --list-fixes list codes for fixes; used by --ignore and --select --ignore errors do not fix these errors/warnings (default: - E226,E24,W503) + E226,E24,W50,W690) --select errors fix only these errors/warnings (e.g. E4,W) --max-line-length n set maximum allowed line length (default: 79) --line-range line line, --range line line @@ -183,6 +183,10 @@ line numbers (e.g. 1 99); line numbers are indexed at 1 --hang-closing hang-closing option passed to pycodestyle + --exit-code change to behavior of exit code. default behavior of + return value, 0 is no differences, 1 is error exit. + return 2 when add this option. 2 is exists + differences. Features @@ -191,7 +195,7 @@ autopep8 fixes the following issues_ reported by pycodestyle_:: E101 - Reindent all lines. - E11 - Fix indentation. (not include E112 and E113) + E11 - Fix indentation. E121 - Fix indentation to be a multiple of four. E122 - Add absent indentation for hanging indentation. E123 - Align closing bracket to match opening bracket. @@ -200,10 +204,14 @@ E126 - Fix over-indented hanging indentation. E127 - Fix visual indentation. E128 - Fix visual indentation. + E129 - Fix visual indentation. + E131 - Fix hanging indent for unaligned continuation line. + E133 - Fix missing indentation for closing bracket. E20 - Remove extraneous whitespace. E211 - Remove extraneous whitespace. E22 - Fix extraneous whitespace around keywords. E224 - Remove extraneous whitespace around operator. + E225 - Fix missing whitespace around operator. E226 - Fix missing whitespace around arithmetic operator. E227 - Fix missing whitespace around bitwise/shift operator. E228 - Fix missing whitespace around modulo operator. @@ -214,29 +222,38 @@ E252 - Missing whitespace around parameter equals. E26 - Fix spacing after comment hash for inline comments. E265 - Fix spacing after comment hash for block comments. + E266 - Fix too many leading '#' for block comments. E27 - Fix extraneous whitespace around keywords. E301 - Add missing blank line. E302 - Add missing 2 blank lines. E303 - Remove extra blank lines. E304 - Remove blank line following function decorator. - E306 - Expected 1 blank line before a nested definition + E305 - Expected 2 blank lines after end of function or class. + E306 - Expected 1 blank line before a nested definition. E401 - Put imports on separate lines. + E402 - Fix module level import not at top of file E501 - Try to make lines fit within --max-line-length characters. E502 - Remove extraneous escape of newline. E701 - Put colon-separated compound statement on separate lines. E70 - Put semicolon-separated compound statement on separate lines. E711 - Fix comparison with None. E712 - Fix comparison with boolean. + E713 - Use 'not in' for test for membership. + E714 - Use 'is not' test for object identity. E721 - Use "isinstance()" instead of comparing types directly. E722 - Fix bare except. + E731 - Use a def when use do not assign a lambda expression. W291 - Remove trailing whitespace. W292 - Add a single newline at the end of the file. W293 - Remove trailing whitespace on blank line. W391 - Remove trailing blank lines. + W503 - Fix line break before binary operator. + W504 - Fix line break after binary operator. W601 - Use "in" rather than "has_key()". W602 - Fix deprecated form of raising exception. W603 - Use "!=" instead of "<>" W604 - Use "repr()" instead of backticks. + W605 - Fix invalid escape sequence 'x'. W690 - Fix various deprecated code (via lib2to3). autopep8 also fixes some issues not found by pycodestyle_. @@ -324,13 +341,33 @@ 'print( 123 )\n' + Configuration + ============= + + By default, if ``$HOME/.config/.pycodestyle`` (``~\.pycodestyle`` in Windows + environment) exists, it will be used as global configuration file. It can + specify the configuration file with the ``--global-config`` option. + + Also, if ``setup.cfg``, ``tox.ini``, ``.pep8`` and ``.flake8`` files exist + in the directory where the target file exists, it will be used as the + configuration file. + + ``pep8``, ``pycodestyle``, and ``flake8`` can be used as a section. + + configuration file example:: + + [pycodestyle] + max_line_length = 120 + ignore = E501 + + Testing ======= Test cases are in ``test/test_autopep8.py``. They can be run directly via ``python test/test_autopep8.py`` or via tox_. The latter is useful for testing against multiple Python interpreters. (We currently test against - CPython versions 2.7, 3.4, 3.5 and 3.6. We also test against PyPy.) + CPython versions 2.7, 3.4, 3.5, 3.6 and 3.7. We also test against PyPy.) .. _`tox`: https://pypi.org/project/tox/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autopep8-1.4/README.rst new/autopep8-1.4.1/README.rst --- old/autopep8-1.4/README.rst 2018-09-01 17:05:18.000000000 +0200 +++ new/autopep8-1.4.1/README.rst 2018-10-15 15:05:07.000000000 +0200 @@ -130,7 +130,7 @@ [--ignore-local-config] [-r] [-j n] [-p n] [-a] [--experimental] [--exclude globs] [--list-fixes] [--ignore errors] [--select errors] [--max-line-length n] - [--line-range line line] [--hang-closing] + [--line-range line line] [--hang-closing] [--exit-code] [files [files ...]] Automatically formats Python code to conform to the PEP 8 style guide. @@ -167,7 +167,7 @@ separated globs --list-fixes list codes for fixes; used by --ignore and --select --ignore errors do not fix these errors/warnings (default: - E226,E24,W503) + E226,E24,W50,W690) --select errors fix only these errors/warnings (e.g. E4,W) --max-line-length n set maximum allowed line length (default: 79) --line-range line line, --range line line @@ -175,6 +175,10 @@ line numbers (e.g. 1 99); line numbers are indexed at 1 --hang-closing hang-closing option passed to pycodestyle + --exit-code change to behavior of exit code. default behavior of + return value, 0 is no differences, 1 is error exit. + return 2 when add this option. 2 is exists + differences. Features @@ -183,7 +187,7 @@ autopep8 fixes the following issues_ reported by pycodestyle_:: E101 - Reindent all lines. - E11 - Fix indentation. (not include E112 and E113) + E11 - Fix indentation. E121 - Fix indentation to be a multiple of four. E122 - Add absent indentation for hanging indentation. E123 - Align closing bracket to match opening bracket. @@ -192,10 +196,14 @@ E126 - Fix over-indented hanging indentation. E127 - Fix visual indentation. E128 - Fix visual indentation. + E129 - Fix visual indentation. + E131 - Fix hanging indent for unaligned continuation line. + E133 - Fix missing indentation for closing bracket. E20 - Remove extraneous whitespace. E211 - Remove extraneous whitespace. E22 - Fix extraneous whitespace around keywords. E224 - Remove extraneous whitespace around operator. + E225 - Fix missing whitespace around operator. E226 - Fix missing whitespace around arithmetic operator. E227 - Fix missing whitespace around bitwise/shift operator. E228 - Fix missing whitespace around modulo operator. @@ -206,29 +214,38 @@ E252 - Missing whitespace around parameter equals. E26 - Fix spacing after comment hash for inline comments. E265 - Fix spacing after comment hash for block comments. + E266 - Fix too many leading '#' for block comments. E27 - Fix extraneous whitespace around keywords. E301 - Add missing blank line. E302 - Add missing 2 blank lines. E303 - Remove extra blank lines. E304 - Remove blank line following function decorator. - E306 - Expected 1 blank line before a nested definition + E305 - Expected 2 blank lines after end of function or class. + E306 - Expected 1 blank line before a nested definition. E401 - Put imports on separate lines. + E402 - Fix module level import not at top of file E501 - Try to make lines fit within --max-line-length characters. E502 - Remove extraneous escape of newline. E701 - Put colon-separated compound statement on separate lines. E70 - Put semicolon-separated compound statement on separate lines. E711 - Fix comparison with None. E712 - Fix comparison with boolean. + E713 - Use 'not in' for test for membership. + E714 - Use 'is not' test for object identity. E721 - Use "isinstance()" instead of comparing types directly. E722 - Fix bare except. + E731 - Use a def when use do not assign a lambda expression. W291 - Remove trailing whitespace. W292 - Add a single newline at the end of the file. W293 - Remove trailing whitespace on blank line. W391 - Remove trailing blank lines. + W503 - Fix line break before binary operator. + W504 - Fix line break after binary operator. W601 - Use "in" rather than "has_key()". W602 - Fix deprecated form of raising exception. W603 - Use "!=" instead of "<>" W604 - Use "repr()" instead of backticks. + W605 - Fix invalid escape sequence 'x'. W690 - Fix various deprecated code (via lib2to3). autopep8 also fixes some issues not found by pycodestyle_. @@ -316,13 +333,33 @@ 'print( 123 )\n' +Configuration +============= + +By default, if ``$HOME/.config/.pycodestyle`` (``~\.pycodestyle`` in Windows +environment) exists, it will be used as global configuration file. It can +specify the configuration file with the ``--global-config`` option. + +Also, if ``setup.cfg``, ``tox.ini``, ``.pep8`` and ``.flake8`` files exist +in the directory where the target file exists, it will be used as the +configuration file. + +``pep8``, ``pycodestyle``, and ``flake8`` can be used as a section. + +configuration file example:: + + [pycodestyle] + max_line_length = 120 + ignore = E501 + + Testing ======= Test cases are in ``test/test_autopep8.py``. They can be run directly via ``python test/test_autopep8.py`` or via tox_. The latter is useful for testing against multiple Python interpreters. (We currently test against -CPython versions 2.7, 3.4, 3.5 and 3.6. We also test against PyPy.) +CPython versions 2.7, 3.4, 3.5, 3.6 and 3.7. We also test against PyPy.) .. _`tox`: https://pypi.org/project/tox/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autopep8-1.4/autopep8.egg-info/PKG-INFO new/autopep8-1.4.1/autopep8.egg-info/PKG-INFO --- old/autopep8-1.4/autopep8.egg-info/PKG-INFO 2018-09-01 18:03:14.000000000 +0200 +++ new/autopep8-1.4.1/autopep8.egg-info/PKG-INFO 2018-10-17 16:00:25.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: autopep8 -Version: 1.4 +Version: 1.4.1 Summary: A tool that automatically formats Python code to conform to the PEP 8 style guide Home-page: https://github.com/hhatto/autopep8 Author: Hideo Hattori @@ -138,7 +138,7 @@ [--ignore-local-config] [-r] [-j n] [-p n] [-a] [--experimental] [--exclude globs] [--list-fixes] [--ignore errors] [--select errors] [--max-line-length n] - [--line-range line line] [--hang-closing] + [--line-range line line] [--hang-closing] [--exit-code] [files [files ...]] Automatically formats Python code to conform to the PEP 8 style guide. @@ -175,7 +175,7 @@ separated globs --list-fixes list codes for fixes; used by --ignore and --select --ignore errors do not fix these errors/warnings (default: - E226,E24,W503) + E226,E24,W50,W690) --select errors fix only these errors/warnings (e.g. E4,W) --max-line-length n set maximum allowed line length (default: 79) --line-range line line, --range line line @@ -183,6 +183,10 @@ line numbers (e.g. 1 99); line numbers are indexed at 1 --hang-closing hang-closing option passed to pycodestyle + --exit-code change to behavior of exit code. default behavior of + return value, 0 is no differences, 1 is error exit. + return 2 when add this option. 2 is exists + differences. Features @@ -191,7 +195,7 @@ autopep8 fixes the following issues_ reported by pycodestyle_:: E101 - Reindent all lines. - E11 - Fix indentation. (not include E112 and E113) + E11 - Fix indentation. E121 - Fix indentation to be a multiple of four. E122 - Add absent indentation for hanging indentation. E123 - Align closing bracket to match opening bracket. @@ -200,10 +204,14 @@ E126 - Fix over-indented hanging indentation. E127 - Fix visual indentation. E128 - Fix visual indentation. + E129 - Fix visual indentation. + E131 - Fix hanging indent for unaligned continuation line. + E133 - Fix missing indentation for closing bracket. E20 - Remove extraneous whitespace. E211 - Remove extraneous whitespace. E22 - Fix extraneous whitespace around keywords. E224 - Remove extraneous whitespace around operator. + E225 - Fix missing whitespace around operator. E226 - Fix missing whitespace around arithmetic operator. E227 - Fix missing whitespace around bitwise/shift operator. E228 - Fix missing whitespace around modulo operator. @@ -214,29 +222,38 @@ E252 - Missing whitespace around parameter equals. E26 - Fix spacing after comment hash for inline comments. E265 - Fix spacing after comment hash for block comments. + E266 - Fix too many leading '#' for block comments. E27 - Fix extraneous whitespace around keywords. E301 - Add missing blank line. E302 - Add missing 2 blank lines. E303 - Remove extra blank lines. E304 - Remove blank line following function decorator. - E306 - Expected 1 blank line before a nested definition + E305 - Expected 2 blank lines after end of function or class. + E306 - Expected 1 blank line before a nested definition. E401 - Put imports on separate lines. + E402 - Fix module level import not at top of file E501 - Try to make lines fit within --max-line-length characters. E502 - Remove extraneous escape of newline. E701 - Put colon-separated compound statement on separate lines. E70 - Put semicolon-separated compound statement on separate lines. E711 - Fix comparison with None. E712 - Fix comparison with boolean. + E713 - Use 'not in' for test for membership. + E714 - Use 'is not' test for object identity. E721 - Use "isinstance()" instead of comparing types directly. E722 - Fix bare except. + E731 - Use a def when use do not assign a lambda expression. W291 - Remove trailing whitespace. W292 - Add a single newline at the end of the file. W293 - Remove trailing whitespace on blank line. W391 - Remove trailing blank lines. + W503 - Fix line break before binary operator. + W504 - Fix line break after binary operator. W601 - Use "in" rather than "has_key()". W602 - Fix deprecated form of raising exception. W603 - Use "!=" instead of "<>" W604 - Use "repr()" instead of backticks. + W605 - Fix invalid escape sequence 'x'. W690 - Fix various deprecated code (via lib2to3). autopep8 also fixes some issues not found by pycodestyle_. @@ -324,13 +341,33 @@ 'print( 123 )\n' + Configuration + ============= + + By default, if ``$HOME/.config/.pycodestyle`` (``~\.pycodestyle`` in Windows + environment) exists, it will be used as global configuration file. It can + specify the configuration file with the ``--global-config`` option. + + Also, if ``setup.cfg``, ``tox.ini``, ``.pep8`` and ``.flake8`` files exist + in the directory where the target file exists, it will be used as the + configuration file. + + ``pep8``, ``pycodestyle``, and ``flake8`` can be used as a section. + + configuration file example:: + + [pycodestyle] + max_line_length = 120 + ignore = E501 + + Testing ======= Test cases are in ``test/test_autopep8.py``. They can be run directly via ``python test/test_autopep8.py`` or via tox_. The latter is useful for testing against multiple Python interpreters. (We currently test against - CPython versions 2.7, 3.4, 3.5 and 3.6. We also test against PyPy.) + CPython versions 2.7, 3.4, 3.5, 3.6 and 3.7. We also test against PyPy.) .. _`tox`: https://pypi.org/project/tox/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autopep8-1.4/autopep8.egg-info/requires.txt new/autopep8-1.4.1/autopep8.egg-info/requires.txt --- old/autopep8-1.4/autopep8.egg-info/requires.txt 2018-09-01 18:03:14.000000000 +0200 +++ new/autopep8-1.4.1/autopep8.egg-info/requires.txt 2018-10-17 16:00:25.000000000 +0200 @@ -1 +1 @@ -pycodestyle>=2.3 +pycodestyle>=2.4.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autopep8-1.4/autopep8.py new/autopep8-1.4.1/autopep8.py --- old/autopep8-1.4/autopep8.py 2018-09-01 18:00:55.000000000 +0200 +++ new/autopep8-1.4.1/autopep8.py 2018-10-17 15:58:22.000000000 +0200 @@ -67,7 +67,7 @@ unicode = str -__version__ = '1.4' +__version__ = '1.4.1' CR = '\r' @@ -82,6 +82,9 @@ BARE_EXCEPT_REGEX = re.compile(r'except\s*:') STARTSWITH_DEF_REGEX = re.compile(r'^(async\s+def|def)\s.*\):') +EXIT_CODE_OK = 0 +EXIT_CODE_ERROR = 1 +EXIT_CODE_EXISTS_DIFF = 2 # For generating line shortening candidates. SHORTEN_OPERATOR_GROUPS = frozenset([ @@ -94,7 +97,7 @@ ]) -DEFAULT_IGNORE = 'E226,E24,W503,W690' # TODO: use pycodestyle.DEFAULT_IGNORE +DEFAULT_IGNORE = 'E226,E24,W50,W690' # TODO: use pycodestyle.DEFAULT_IGNORE DEFAULT_INDENT_SIZE = 4 SELECTED_GLOBAL_FIXED_METHOD_CODES = ['W602', ] @@ -122,11 +125,18 @@ if sys.platform == 'win32': # pragma: no cover - DEFAULT_CONFIG = os.path.expanduser(r'~\.pep8') + DEFAULT_CONFIG = os.path.expanduser(r'~\.pycodestyle') else: DEFAULT_CONFIG = os.path.join(os.getenv('XDG_CONFIG_HOME') or - os.path.expanduser('~/.config'), 'pep8') -PROJECT_CONFIG = ('setup.cfg', 'tox.ini', '.pep8') + os.path.expanduser('~/.config'), + 'pycodestyle') +# fallback, use .pep8 +if not os.path.exists(DEFAULT_CONFIG): # pragma: no cover + if sys.platform == 'win32': + DEFAULT_CONFIG = os.path.expanduser(r'~\.pep8') + else: + DEFAULT_CONFIG = os.path.join(os.path.expanduser('~/.config'), 'pep8') +PROJECT_CONFIG = ('setup.cfg', 'tox.ini', '.pep8', '.flake8') MAX_PYTHON_FILE_DETECTION_BYTES = 1024 @@ -411,14 +421,14 @@ - e261,e262 - e271,e272,e273,e274 - e301,e302,e303,e304,e305,e306 - - e401 + - e401,e402 - e502 - e701,e702,e703,e704 - e711,e712,e713,e714 - e722 - e731 - w291 - - w503 + - w503,504 """ @@ -435,6 +445,14 @@ self.options = options self.indent_word = _get_indentword(''.join(self.source)) + # collect imports line + self.imports = {} + for i, line in enumerate(self.source): + if (line.find("import ") == 0 or line.find("from ") == 0) and \ + line not in self.imports: + # collect only import statements that first appeared + self.imports[line] = i + self.long_line_ignore_cache = ( set() if long_line_ignore_cache is None else long_line_ignore_cache) @@ -852,6 +870,15 @@ indentation + 'import ' + target[offset:].lstrip('\t ,')) self.source[line_index] = fixed + def fix_e402(self, result): + (line_index, offset, target) = get_index_offset_contents(result, + self.source) + if not (target in self.imports and self.imports[target] != line_index): + mod_offset = get_module_imports_on_top_of_file(self.source, + line_index) + self.source[mod_offset] = target + self.source[mod_offset] + self.source[line_index] = '' + def fix_long_line_logically(self, result, logical): """Try to make lines fit within --max-line-length characters.""" if ( @@ -1190,12 +1217,16 @@ return # find comment comment_index = 0 + comment_only_linenum = 0 for i in range(5): # NOTE: try to parse code in 5 times if (line_index - i) < 0: break from_index = line_index - i - 1 to_index = line_index + 1 + if self.source[from_index].lstrip()[0] == '#': + comment_only_linenum += 1 + continue try: ts = generate_tokens("".join(self.source[from_index:to_index])) except (SyntaxError, tokenize.TokenError): @@ -1210,34 +1241,91 @@ tts = ts[newline_index[-3]:] else: tts = ts - old = [] + old = None for t in tts: - if tokenize.COMMENT == t[0] and old: + if tokenize.COMMENT == t[0] and old and old[0] != tokenize.NL: comment_index = old[3][1] break old = t break i = target.index(one_string_token) + fix_target_line = line_index - 1 - comment_only_linenum self.source[line_index] = '{}{}'.format( target[:i], target[i + len(one_string_token):].lstrip()) - nl = find_newline(self.source[line_index - 1:line_index]) - before_line = self.source[line_index - 1] + nl = find_newline(self.source[fix_target_line:line_index]) + before_line = self.source[fix_target_line] bl = before_line.index(nl) if comment_index: - self.source[line_index - 1] = '{} {} {}'.format( + self.source[fix_target_line] = '{} {} {}'.format( before_line[:comment_index], one_string_token, before_line[comment_index + 1:]) else: - self.source[line_index - 1] = '{} {}{}'.format( + self.source[fix_target_line] = '{} {}{}'.format( before_line[:bl], one_string_token, before_line[bl:]) + def fix_w504(self, result): + (line_index, _, target) = get_index_offset_contents(result, + self.source) + # NOTE: is not collect pointed out in pycodestyle==2.4.0 + comment_index = 0 + operator_position = None # (start_position, end_position) + for i in range(1, 6): + to_index = line_index + i + try: + ts = generate_tokens("".join(self.source[line_index:to_index])) + except (SyntaxError, tokenize.TokenError): + continue + newline_count = 0 + newline_index = [] + for index, t in enumerate(ts): + if t[0] == tokenize.OP: + if t[2][0] == 1 and t[3][0] == 1: + operator_position = (t[2][1], t[3][1]) + elif t[0] in (tokenize.NEWLINE, tokenize.NL): + newline_index.append(index) + newline_count += 1 + if newline_count > 2: + tts = ts[:newline_index[-3]] + else: + tts = ts + old = [] + for t in tts: + if tokenize.COMMENT == t[0] and old: + comment_index = old[3][1] + break + old = t + break + if not operator_position: + return + target_operator = target[operator_position[0]:operator_position[1]] + if comment_index: + self.source[line_index] = '{}{}'.format( + target[:operator_position[0]].rstrip(), + target[comment_index:]) + else: + self.source[line_index] = '{}{}{}'.format( + target[:operator_position[0]].rstrip(), + target[operator_position[1]:].lstrip(), + target[operator_position[1]:]) + next_line = self.source[line_index + 1] + next_line_indent = 0 + m = re.match(r'\s*', next_line) + if m: + next_line_indent = m.span()[1] + self.source[line_index + 1] = '{}{} {}'.format( + next_line[:next_line_indent], target_operator, + next_line[next_line_indent:]) + def fix_w605(self, result): (line_index, _, target) = get_index_offset_contents(result, self.source) - tokens = list(generate_tokens(target)) + try: + tokens = list(generate_tokens(target)) + except (SyntaxError, tokenize.TokenError): + return for (pos, _msg) in get_w605_position(tokens): self.source[line_index] = '{}r{}'.format( - target[:pos], target[pos:]) + target[:pos], target[pos:]) def get_w605_position(tokens): @@ -1274,6 +1362,42 @@ pos = string.find('\\', pos + 1) +def get_module_imports_on_top_of_file(source, import_line_index): + """return import or from keyword position + + example: + > 0: import sys + 1: import os + 2: + 3: def function(): + """ + def is_string_literal(line): + if line[0] in 'uUbB': + line = line[1:] + if line and line[0] in 'rR': + line = line[1:] + return line and (line[0] == '"' or line[0] == "'") + allowed_try_keywords = ('try', 'except', 'else', 'finally') + for cnt, line in enumerate(source): + if not line.rstrip(): + continue + elif line.startswith('#'): + continue + if line.startswith('import ') or line.startswith('from '): + if cnt == import_line_index: + continue + return cnt + elif pycodestyle.DUNDER_REGEX.match(line): + continue + elif any(line.startswith(kw) for kw in allowed_try_keywords): + continue + elif is_string_literal(line): + return cnt + else: + return cnt + return 0 + + def get_index_offset_contents(result, source): """Return (line_index, column_offset, line_contents).""" line_index = result['line'] - 1 @@ -1736,7 +1860,7 @@ second_indent = indentation if (first.rstrip().endswith('(') and - source[end_offset:].lstrip().startswith(')')): + source[end_offset:].lstrip().startswith(')')): pass elif first.rstrip().endswith('('): second_indent += indent_word @@ -3014,11 +3138,11 @@ continue if aggressive <= 1: - if issue_id.startswith(('e712', 'e713', 'e714', 'w5')): + if issue_id.startswith(('e712', 'e713', 'e714')): continue if aggressive <= 2: - if issue_id.startswith(('e704', 'w5')): + if issue_id.startswith(('e704')): continue if r['line'] in commented_out_code_line_numbers: @@ -3281,18 +3405,22 @@ if output: output.write(diff) output.flush() - else: - return diff + return diff elif options.in_place: fp = open_with_encoding(filename, encoding=encoding, mode='w') fp.write(fixed_source) fp.close() + original = "".join(original_source).splitlines() + fixed = fixed_source.splitlines() + if original != fixed: + return fixed_source + else: + return '' else: if output: output.write(fixed_source) output.flush() - else: - return fixed_source + return fixed_source def global_fixes(): @@ -3444,6 +3572,11 @@ type=int, help=argparse.SUPPRESS) parser.add_argument('--hang-closing', action='store_true', help='hang-closing option passed to pycodestyle') + parser.add_argument('--exit-code', action='store_true', + help='change to behavior of exit code.' + ' default behavior of return value, 0 is no ' + 'differences, 1 is error exit. return 2 when' + ' add this option. 2 is exists differences.') parser.add_argument('files', nargs='*', help="files to format or '-' for standard in") @@ -3500,7 +3633,7 @@ elif not args.select: if args.aggressive: # Enable everything by default if aggressive. - args.select = {'E', 'W'} + args.select = {'E', 'W1', 'W2', 'W3', 'W6'} else: args.ignore = _split_comma_separated(DEFAULT_IGNORE) @@ -3883,7 +4016,7 @@ if parameters[1].verbose: print('[file:{}]'.format(parameters[0]), file=sys.stderr) try: - fix_file(*parameters) + return fix_file(*parameters) except IOError as error: print(unicode(error), file=sys.stderr) @@ -3894,15 +4027,26 @@ Optionally fix files recursively. """ + results = [] filenames = find_files(filenames, options.recursive, options.exclude) if options.jobs > 1: import multiprocessing pool = multiprocessing.Pool(options.jobs) - pool.map(_fix_file, - [(name, options) for name in filenames]) + ret = pool.map(_fix_file, [(name, options) for name in filenames]) + results.extend(filter(lambda x: x is not None, ret)) else: for name in filenames: - _fix_file((name, options, output)) + ret = _fix_file((name, options, output)) + if ret is None: + continue + if options.diff or options.in_place: + if ret != '': + results.append(ret) + else: + original_source = readlines_from_file(name) + if "".join(original_source).splitlines() != ret.splitlines(): + results.append(ret) + return results def is_python_file(filename): @@ -3972,7 +4116,7 @@ for code, description in sorted(supported_fixes()): print('{code} - {description}'.format( code=code, description=description)) - return 0 + return EXIT_CODE_OK if args.files == ['-']: assert not args.in_place @@ -3990,9 +4134,11 @@ assert len(args.files) == 1 assert not args.recursive - fix_multiple_files(args.files, args, sys.stdout) + ret = fix_multiple_files(args.files, args, sys.stdout) + if args.exit_code and len(ret) > 0: + return EXIT_CODE_EXISTS_DIFF except KeyboardInterrupt: - return 1 # pragma: no cover + return EXIT_CODE_ERROR # pragma: no cover class CachedTokenizer(object): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autopep8-1.4/setup.py new/autopep8-1.4.1/setup.py --- old/autopep8-1.4/setup.py 2018-09-01 18:00:07.000000000 +0200 +++ new/autopep8-1.4.1/setup.py 2018-10-15 15:05:07.000000000 +0200 @@ -10,7 +10,7 @@ INSTALL_REQUIRES = ( - ['pycodestyle >= 2.3'] + ['pycodestyle >= 2.4.0'] ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autopep8-1.4/test/test_autopep8.py new/autopep8-1.4.1/test/test_autopep8.py --- old/autopep8-1.4/test/test_autopep8.py 2018-09-01 17:05:18.000000000 +0200 +++ new/autopep8-1.4.1/test/test_autopep8.py 2018-10-15 15:05:07.000000000 +0200 @@ -35,7 +35,7 @@ sys.path.insert(0, ROOT_DIR) import autopep8 - +from autopep8 import get_module_imports_on_top_of_file FAKE_CONFIGURATION = os.path.join(ROOT_DIR, 'test', 'fake_configuration') FAKE_PYCODESTYLE_CONFIGURATION = os.path.join( @@ -1561,8 +1561,12 @@ """ fixed = """\ def extractBlocks(self): - addLine = (self.matchMultiple(linesIncludePatterns, line) and - not self.matchMultiple(linesExcludePatterns, line)) or emptyLine + addLine = ( + self.matchMultiple( + linesIncludePatterns, + line) and not self.matchMultiple( + linesExcludePatterns, + line)) or emptyLine """ with autopep8_context(line, options=['-aaa']) as result: self.assertEqual(fixed, result) @@ -2400,6 +2404,18 @@ with autopep8_context(line, options=['--select=E401']) as result: self.assertEqual(fixed, result) + def test_e402(self): + line = 'a = 1\nimport os\n' + fixed = 'import os\na = 1\n' + with autopep8_context(line) as result: + self.assertEqual(fixed, result) + + def test_e402_duplicate_module(self): + line = 'a = 1\nimport os\nprint(os)\nimport os\n' + fixed = 'import os\na = 1\nprint(os)\n' + with autopep8_context(line) as result: + self.assertEqual(fixed, result) + def test_e501_basic(self): line = """\ @@ -4266,7 +4282,7 @@ def test_w503(self): line = '(width == 0\n + height == 0)\n' fixed = '(width == 0 +\n height == 0)\n' - with autopep8_context(line, options=['-aaa']) as result: + with autopep8_context(line, options=['--select=W503']) as result: self.assertEqual(fixed, result) def test_w503_skip_default(self): @@ -4277,13 +4293,13 @@ def test_w503_and_or(self): line = '(width == 0\n and height == 0\n or name == "")\n' fixed = '(width == 0 and\n height == 0 or\n name == "")\n' - with autopep8_context(line, options=['-aaa']) as result: + with autopep8_context(line, options=['--select=W503']) as result: self.assertEqual(fixed, result) def test_w503_with_comment(self): line = '(width == 0 # this is comment\n + height == 0)\n' fixed = '(width == 0 + # this is comment\n height == 0)\n' - with autopep8_context(line, options=['-aaa']) as result: + with autopep8_context(line, options=['--select=W503']) as result: self.assertEqual(fixed, result) def test_w503_with_comment_double(self): @@ -4301,7 +4317,7 @@ 333333333333 # C3 ) """ - with autopep8_context(line, options=['-aaa']) as result: + with autopep8_context(line, options=['--select=W503']) as result: self.assertEqual(fixed, result) def test_w503_over_5lines(self): @@ -4327,7 +4343,32 @@ 7 # 7 ) """ - with autopep8_context(line, options=['-aaa']) as result: + with autopep8_context(line, options=['--select=W503']) as result: + self.assertEqual(fixed, result) + + def test_w503_with_line_comment(self): + line = '(width == 0\n # this is comment\n + height == 0)\n' + fixed = '(width == 0 +\n # this is comment\n height == 0)\n' + with autopep8_context(line, options=['--select=W503', '--ignore=E']) as result: + self.assertEqual(fixed, result) + + def test_w503_with_line_comments(self): + line = '(width == 0\n # this is comment\n # comment2\n + height == 0)\n' + fixed = '(width == 0 +\n # this is comment\n # comment2\n height == 0)\n' + with autopep8_context(line, options=['--select=W503', '--ignore=E']) as result: + self.assertEqual(fixed, result) + + def test_w504(self): + line = '(width == 0 +\n height == 0)\n' + fixed = '(width == 0\n + height == 0)\n' + with autopep8_context(line, options=['--select=W504', '--ignore=E']) as result: + self.assertEqual(fixed, result) + + @unittest.skip('TODO') + def test_w504_with_line_comment(self): + line = '(width == 0 +\n # this is comment\n height == 0)\n' + fixed = '(width == 0\n # this is comment\n + height == 0)\n' + with autopep8_context(line, options=['--select=W504', '--ignore=E']) as result: self.assertEqual(fixed, result) def test_w601(self): @@ -4682,6 +4723,45 @@ self.assertEqual(line, result) +class UtilityFunctionTests(unittest.TestCase): + + def test_get_module_imports(self): + line = """\ +import os +import sys + +if True: + print(1) +""" + target_line_index = 8 + result = get_module_imports_on_top_of_file(line.splitlines(), + target_line_index) + self.assertEqual(result, 0) + + def test_get_module_imports_case_of_autopep8(self): + line = """\ +#!/usr/bin/python + +# comment +# comment + +'''this module ... + +this module ... +''' + +import os +import sys + +if True: + print(1) +""" + target_line_index = 11 + result = get_module_imports_on_top_of_file(line.splitlines(), + target_line_index) + self.assertEqual(result, 5) + + class CommandLineTests(unittest.TestCase): maxDiff = None @@ -4689,12 +4769,27 @@ def test_diff(self): line = "'abc' \n" fixed = "-'abc' \n+'abc'\n" - with autopep8_subprocess(line, ['--diff']) as result: + with autopep8_subprocess(line, ['--diff']) as (result, retcode): self.assertEqual(fixed, '\n'.join(result.split('\n')[3:])) + self.assertEqual(retcode, autopep8.EXIT_CODE_OK) + + def test_diff_with_exit_code_option(self): + line = "'abc' \n" + fixed = "-'abc' \n+'abc'\n" + with autopep8_subprocess(line, ['--diff', '--exit-code']) as (result, retcode): + self.assertEqual(fixed, '\n'.join(result.split('\n')[3:])) + self.assertEqual(retcode, autopep8.EXIT_CODE_EXISTS_DIFF) + + def test_non_diff_with_exit_code_option(self): + line = "'abc'\n" + with autopep8_subprocess(line, ['--diff', '--exit-code']) as (result, retcode): + self.assertEqual('', '\n'.join(result.split('\n')[3:])) + self.assertEqual(retcode, autopep8.EXIT_CODE_OK) def test_diff_with_empty_file(self): - with autopep8_subprocess('', ['--diff']) as result: + with autopep8_subprocess('', ['--diff']) as (result, retcode): self.assertEqual('\n'.join(result.split('\n')[3:]), '') + self.assertEqual(retcode, autopep8.EXIT_CODE_OK) def test_diff_with_nonexistent_file(self): p = Popen(list(AUTOPEP8_CMD_TUPLE) + ['--diff', 'non_existent_file'], @@ -4711,19 +4806,22 @@ def test_pep8_passes(self): line = "'abc' \n" fixed = "'abc'\n" - with autopep8_subprocess(line, ['--pep8-passes', '0']) as result: + with autopep8_subprocess(line, ['--pep8-passes', '0']) as (result, retcode): self.assertEqual(fixed, result) + self.assertEqual(retcode, autopep8.EXIT_CODE_OK) def test_pep8_ignore(self): line = "'abc' \n" - with autopep8_subprocess(line, ['--ignore=E,W']) as result: + with autopep8_subprocess(line, ['--ignore=E,W']) as (result, retcode): self.assertEqual(line, result) + self.assertEqual(retcode, autopep8.EXIT_CODE_OK) def test_pep8_ignore_should_handle_trailing_comma_gracefully(self): line = "'abc' \n" fixed = "'abc'\n" - with autopep8_subprocess(line, ['--ignore=,']) as result: + with autopep8_subprocess(line, ['--ignore=,']) as (result, retcode): self.assertEqual(fixed, result) + self.assertEqual(retcode, autopep8.EXIT_CODE_OK) def test_help(self): p = Popen(list(AUTOPEP8_CMD_TUPLE) + ['-h'], @@ -4757,6 +4855,20 @@ with open(filename) as f: self.assertEqual(fixed, f.read()) + self.assertEqual(p.returncode, autopep8.EXIT_CODE_OK) + + def test_in_place_with_exit_code_option(self): + line = "'abc' \n" + fixed = "'abc'\n" + + with temporary_file_context(line) as filename: + p = Popen(list(AUTOPEP8_CMD_TUPLE) + [filename, + '--in-place', + '--exit-code']) + p.wait() + with open(filename) as f: + self.assertEqual(fixed, f.read()) + self.assertEqual(p.returncode, autopep8.EXIT_CODE_EXISTS_DIFF) def test_parallel_jobs(self): line = "'abc' \n" @@ -4914,8 +5026,9 @@ self.assertTrue(len(result)) def test_list_fixes(self): - with autopep8_subprocess('', options=['--list-fixes']) as result: + with autopep8_subprocess('', options=['--list-fixes']) as (result, retcode): self.assertIn('E121', result) + self.assertEqual(retcode, autopep8.EXIT_CODE_OK) def test_fixpep8_class_constructor(self): line = 'print 1\nprint 2\n' @@ -6347,7 +6460,7 @@ with temporary_file_context(line) as filename: p = Popen(list(AUTOPEP8_CMD_TUPLE) + [filename] + options, stdout=PIPE) - yield p.communicate()[0].decode('utf-8') + yield (p.communicate()[0].decode('utf-8'), p.returncode) @contextlib.contextmanager
