Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-docformatter for openSUSE:Factory checked in at 2021-05-20 19:25:17 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-docformatter (Old) and /work/SRC/openSUSE:Factory/.python-docformatter.new.2988 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-docformatter" Thu May 20 19:25:17 2021 rev:8 rq:894546 version:1.4 Changes: -------- --- /work/SRC/openSUSE:Factory/python-docformatter/python-docformatter.changes 2020-05-28 09:17:59.529058972 +0200 +++ /work/SRC/openSUSE:Factory/.python-docformatter.new.2988/python-docformatter.changes 2021-05-20 19:25:45.293771576 +0200 @@ -1,0 +2,9 @@ +Thu May 20 07:18:31 UTC 2021 - pgaj...@suse.com + +- version update to 1.4 + * Add --docstring-length flag + * Not add period for summary formatted as title + * Added command line exclude option +- use %pytest macro + +------------------------------------------------------------------- Old: ---- docformatter-1.3.1.tar.gz New: ---- docformatter-1.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-docformatter.spec ++++++ --- /var/tmp/diff_new_pack.nv7Xxb/_old 2021-05-20 19:25:45.749769706 +0200 +++ /var/tmp/diff_new_pack.nv7Xxb/_new 2021-05-20 19:25:45.749769706 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-docformatter # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-docformatter -Version: 1.3.1 +Version: 1.4 Release: 0 Summary: Utility to re-format docstrings per PEP 257 License: MIT @@ -31,9 +31,13 @@ Requires: python-setuptools Requires: python-untokenize Requires(post): update-alternatives -Requires(postun): update-alternatives +Requires(postun):update-alternatives BuildArch: noarch # SECTION test requirements +%if %{suse_version} <= 1500 +BuildRequires: python2-mock +%endif +BuildRequires: %{python_module pytest} BuildRequires: %{python_module untokenize} # /SECTION %python_subpackages @@ -71,7 +75,7 @@ %python_expand %fdupes %{buildroot}%{$python_sitelib} %check -%python_exec setup.py test +%pytest %post %python_install_alternative docformatter ++++++ docformatter-1.3.1.tar.gz -> docformatter-1.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docformatter-1.3.1/MANIFEST.in new/docformatter-1.4/MANIFEST.in --- old/docformatter-1.3.1/MANIFEST.in 2018-06-14 15:54:54.000000000 +0200 +++ new/docformatter-1.4/MANIFEST.in 2020-12-27 18:50:40.000000000 +0100 @@ -3,6 +3,7 @@ include MANIFEST.in include README.rst include test_docformatter.py +recursive-include images *.png exclude .pre-commit-hooks.yaml exclude .travis.yml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docformatter-1.3.1/PKG-INFO new/docformatter-1.4/PKG-INFO --- old/docformatter-1.3.1/PKG-INFO 2019-11-10 17:22:49.000000000 +0100 +++ new/docformatter-1.4/PKG-INFO 2020-12-27 19:11:01.456480700 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: docformatter -Version: 1.3.1 +Version: 1.4 Summary: Formats docstrings to follow PEP 257. Home-page: https://github.com/myint/docformatter Author: Steven Myint @@ -155,6 +155,8 @@ -i, --in-place make changes to files instead of printing diffs -c, --check only check and report incorrectly formatted files -r, --recursive drill down directories recursively + -e, --exclude exclude directories and files by names + --wrap-summaries length wrap long summary lines at this length; set to 0 to disable wrapping (default: 79) @@ -195,6 +197,39 @@ even these instances to get wrapped use ``--force-wrap``. + Integration + =========== + + Git Hook + -------- + + *docformatter* is configured for `pre-commit`_ and can be set up as a hook with the following ``.pre-commit-config.yaml`` configuration: + + .. _`pre-commit`: https://pre-commit.com/ + + .. code-block:: yaml + + - repo: https://github.com/myint/docformatter + rev: v1.3.1 + hooks: + - id: docformatter + args: [--in-place] + + You will need to install ``pre-commit`` and run ``pre-commit install``. + + You may alternatively use ``args: [--check]`` if you prefer the commit to fail instead of letting *docformatter* format docstrings automatically. + + PyCharm + ------- + + *docformatter* can be configured as a PyCharm file watcher to automatically format docstrings on saving python files. + + Head over to ``Preferences > Tools > File Watchers``, click the ``+`` icon and configure *docformatter* as shown below: + + .. image:: /images/pycharm-file-watcher-configurations.png + :alt: PyCharm file watcher configurations + + Issues ====== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docformatter-1.3.1/README.rst new/docformatter-1.4/README.rst --- old/docformatter-1.3.1/README.rst 2019-05-24 19:17:04.000000000 +0200 +++ new/docformatter-1.4/README.rst 2020-12-27 18:37:29.000000000 +0100 @@ -147,6 +147,8 @@ -i, --in-place make changes to files instead of printing diffs -c, --check only check and report incorrectly formatted files -r, --recursive drill down directories recursively + -e, --exclude exclude directories and files by names + --wrap-summaries length wrap long summary lines at this length; set to 0 to disable wrapping (default: 79) @@ -187,6 +189,39 @@ even these instances to get wrapped use ``--force-wrap``. +Integration +=========== + +Git Hook +-------- + +*docformatter* is configured for `pre-commit`_ and can be set up as a hook with the following ``.pre-commit-config.yaml`` configuration: + +.. _`pre-commit`: https://pre-commit.com/ + +.. code-block:: yaml + + - repo: https://github.com/myint/docformatter + rev: v1.3.1 + hooks: + - id: docformatter + args: [--in-place] + +You will need to install ``pre-commit`` and run ``pre-commit install``. + +You may alternatively use ``args: [--check]`` if you prefer the commit to fail instead of letting *docformatter* format docstrings automatically. + +PyCharm +------- + +*docformatter* can be configured as a PyCharm file watcher to automatically format docstrings on saving python files. + +Head over to ``Preferences > Tools > File Watchers``, click the ``+`` icon and configure *docformatter* as shown below: + +.. image:: /images/pycharm-file-watcher-configurations.png + :alt: PyCharm file watcher configurations + + Issues ====== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docformatter-1.3.1/docformatter.egg-info/PKG-INFO new/docformatter-1.4/docformatter.egg-info/PKG-INFO --- old/docformatter-1.3.1/docformatter.egg-info/PKG-INFO 2019-11-10 17:22:49.000000000 +0100 +++ new/docformatter-1.4/docformatter.egg-info/PKG-INFO 2020-12-27 19:11:01.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: docformatter -Version: 1.3.1 +Version: 1.4 Summary: Formats docstrings to follow PEP 257. Home-page: https://github.com/myint/docformatter Author: Steven Myint @@ -155,6 +155,8 @@ -i, --in-place make changes to files instead of printing diffs -c, --check only check and report incorrectly formatted files -r, --recursive drill down directories recursively + -e, --exclude exclude directories and files by names + --wrap-summaries length wrap long summary lines at this length; set to 0 to disable wrapping (default: 79) @@ -195,6 +197,39 @@ even these instances to get wrapped use ``--force-wrap``. + Integration + =========== + + Git Hook + -------- + + *docformatter* is configured for `pre-commit`_ and can be set up as a hook with the following ``.pre-commit-config.yaml`` configuration: + + .. _`pre-commit`: https://pre-commit.com/ + + .. code-block:: yaml + + - repo: https://github.com/myint/docformatter + rev: v1.3.1 + hooks: + - id: docformatter + args: [--in-place] + + You will need to install ``pre-commit`` and run ``pre-commit install``. + + You may alternatively use ``args: [--check]`` if you prefer the commit to fail instead of letting *docformatter* format docstrings automatically. + + PyCharm + ------- + + *docformatter* can be configured as a PyCharm file watcher to automatically format docstrings on saving python files. + + Head over to ``Preferences > Tools > File Watchers``, click the ``+`` icon and configure *docformatter* as shown below: + + .. image:: /images/pycharm-file-watcher-configurations.png + :alt: PyCharm file watcher configurations + + Issues ====== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docformatter-1.3.1/docformatter.egg-info/SOURCES.txt new/docformatter-1.4/docformatter.egg-info/SOURCES.txt --- old/docformatter-1.3.1/docformatter.egg-info/SOURCES.txt 2019-11-10 17:22:49.000000000 +0100 +++ new/docformatter-1.4/docformatter.egg-info/SOURCES.txt 2020-12-27 19:11:01.000000000 +0100 @@ -10,4 +10,5 @@ docformatter.egg-info/dependency_links.txt docformatter.egg-info/entry_points.txt docformatter.egg-info/requires.txt -docformatter.egg-info/top_level.txt \ No newline at end of file +docformatter.egg-info/top_level.txt +images/pycharm-file-watcher-configurations.png \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docformatter-1.3.1/docformatter.py new/docformatter-1.4/docformatter.py --- old/docformatter-1.3.1/docformatter.py 2019-11-10 17:20:52.000000000 +0100 +++ new/docformatter-1.4/docformatter.py 2020-12-27 19:02:32.000000000 +0100 @@ -38,11 +38,11 @@ import sys import textwrap import tokenize - +import sysconfig import untokenize -__version__ = '1.3.1' +__version__ = '1.4' try: @@ -57,6 +57,8 @@ LF = '\n' CRLF = '\r\n' +_PYTHON_LIBS = set(sysconfig.get_paths().values()) + class FormatResult(object): """Possible exit codes.""" @@ -83,6 +85,24 @@ return source +def has_correct_length(length_range, start, end): + """Return True if docstring's length is in range.""" + if length_range is None: + return True + min_length, max_length = length_range + + docstring_length = end + 1 - start + return min_length <= docstring_length <= max_length + + +def is_in_range(line_range, start, end): + """Return True if start/end is in line_range.""" + if line_range is None: + return True + return any(line_range[0] <= line_no <= line_range[1] + for line_no in range(start, end + 1)) + + def _format_code(source, summary_wrap_length=79, description_wrap_length=72, @@ -90,7 +110,8 @@ make_summary_multi_line=False, post_description_blank=False, force_wrap=False, - line_range=None): + line_range=None, + length_range=None): """Return source code with docstrings formatted.""" if not source: return source @@ -98,12 +119,8 @@ if line_range is not None: assert line_range[0] > 0 and line_range[1] > 0 - def in_range(start, end): - """Return True if start/end is in line_range.""" - if line_range is None: - return True - return any(line_range[0] <= line_no <= line_range[1] - for line_no in range(start, end + 1)) + if length_range is not None: + assert length_range[0] > 0 and length_range[1] > 0 modified_tokens = [] @@ -123,7 +140,8 @@ token_string.startswith(('"', "'")) and (previous_token_type == tokenize.INDENT or only_comments_so_far) and - in_range(start[0], end[0]) + is_in_range(line_range, start[0], end[0]) and + has_correct_length(length_range, start[0], end[0]) ): if only_comments_so_far: indentation = '' @@ -448,7 +466,11 @@ summary = re.sub(r'\s*\n\s*', ' ', summary.rstrip()) # Add period at end of sentence - if summary and (summary[-1].isalnum() or summary[-1] in ['"', "'"]): + if ( + summary and + (summary[-1].isalnum() or summary[-1] in ['"', "'"]) and + (not summary.startswith('#')) + ): summary += '.' return summary @@ -609,6 +631,8 @@ 'files') parser.add_argument('-r', '--recursive', action='store_true', help='drill down directories recursively') + parser.add_argument('-e', '--exclude', nargs='*', + help='exclude directories and files by names') parser.add_argument('--wrap-summaries', default=79, type=int, metavar='length', help='wrap long summary lines at this length; ' @@ -637,6 +661,11 @@ default=None, type=int, nargs=2, help='apply docformatter to docstrings between these ' 'lines; line numbers are indexed at 1') + parser.add_argument('--docstring-length', metavar='length', + dest='length_range', + default=None, type=int, nargs=2, + help='apply docformatter to docstrings of given ' + 'length') parser.add_argument('--version', action='version', version='%(prog)s ' + __version__) parser.add_argument('files', nargs='+', @@ -651,6 +680,13 @@ parser.error('First value of --range should be less than or equal ' 'to the second') + if args.length_range: + if args.length_range[0] <= 0: + parser.error('--docstring-length must be positive numbers') + if args.length_range[0] > args.length_range[1]: + parser.error('First value of --docstring-length should be less ' + 'than or equal to the second') + if '-' in args.files: _format_standard_in(args, parser=parser, @@ -692,12 +728,13 @@ return locale.getpreferredencoding() or sys.getdefaultencoding() -def find_py_files(sources, recursive): +def find_py_files(sources, recursive, exclude=None): """Find Python source files. Parameters - sources: iterable with paths as strings. - recursive: drill down directories if True. + - exclude: string based on which directories and files are excluded. Return: yields paths to found files. """ @@ -705,12 +742,29 @@ """Return True if file 'name' isn't .hidden.""" return not name.startswith('.') + def is_excluded(name, exclude): + """Return True if file 'name' is excluded.""" + if not exclude: + return False + for e in exclude: + if re.search(re.escape(str(e)), name, re.IGNORECASE): + return True + return False + for name in sorted(sources): if recursive and os.path.isdir(name): for root, dirs, children in os.walk(unicode(name)): - dirs[:] = sorted(filter(not_hidden, dirs)) - for filename in sorted(filter(not_hidden, children)): - if filename.endswith('.py'): + dirs[:] = [d for d in dirs if not_hidden( + d) and not is_excluded(d, _PYTHON_LIBS)] + dirs[:] = sorted( + [d for d in dirs if not is_excluded(d, exclude)]) + files = sorted([f for f in children if not_hidden( + f) and not is_excluded(f, exclude)]) + for filename in files: + if ( + filename.endswith('.py') and + not is_excluded(root, exclude) + ): yield os.path.join(root, filename) else: yield name @@ -722,7 +776,9 @@ Return: one of the FormatResult codes. """ outcomes = collections.Counter() - for filename in find_py_files(set(args.files), args.recursive): + for filename in find_py_files(set(args.files), + args.recursive, + args.exclude): try: result = format_file(filename, args=args, standard_out=standard_out) Binary files old/docformatter-1.3.1/images/pycharm-file-watcher-configurations.png and new/docformatter-1.4/images/pycharm-file-watcher-configurations.png differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docformatter-1.3.1/setup.py new/docformatter-1.4/setup.py --- old/docformatter-1.3.1/setup.py 2019-02-09 19:45:13.000000000 +0100 +++ new/docformatter-1.4/setup.py 2020-12-27 19:02:32.000000000 +0100 @@ -38,4 +38,5 @@ entry_points={ 'console_scripts': ['docformatter = docformatter:main']}, install_requires=['untokenize'], + tests_require=['mock;python_version<"3.3"'], test_suite='test_docformatter') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docformatter-1.3.1/test_docformatter.py new/docformatter-1.4/test_docformatter.py --- old/docformatter-1.3.1/test_docformatter.py 2019-11-10 17:18:08.000000000 +0100 +++ new/docformatter-1.4/test_docformatter.py 2020-12-27 19:02:32.000000000 +0100 @@ -18,6 +18,11 @@ import tempfile import unittest +if sys.version_info >= (3, 3): + from unittest.mock import patch +else: + from mock import patch + import docformatter @@ -42,6 +47,22 @@ class TestUnits(unittest.TestCase): + def test_is_in_range(self): + self.assertTrue(docformatter.is_in_range(None, 1, 9)) + self.assertTrue(docformatter.is_in_range([1, 4], 3, 5)) + self.assertTrue(docformatter.is_in_range([1, 4], 4, 10)) + self.assertTrue(docformatter.is_in_range([2, 10], 1, 2)) + self.assertFalse(docformatter.is_in_range([1, 1], 2, 9)) + self.assertFalse(docformatter.is_in_range([10, 20], 1, 9)) + + def test_has_correct_length(self): + self.assertTrue(docformatter.has_correct_length(None, 1, 9)) + self.assertTrue(docformatter.has_correct_length([1, 3], 3, 5)) + self.assertTrue(docformatter.has_correct_length([1, 1], 1, 1)) + self.assertTrue(docformatter.has_correct_length([1, 10], 5, 10)) + self.assertFalse(docformatter.has_correct_length([1, 1], 2, 9)) + self.assertFalse(docformatter.has_correct_length([10, 20], 2, 9)) + def test_strip_docstring(self): self.assertEqual( 'Hello.', @@ -454,6 +475,30 @@ """ Badly indented docstring""" pass''', line_range=[1, 2])) + def test_format_code_docstring_length(self): + self.assertEqual('''\ +def f(x): + """This is a docstring. + + + That should be on less lines + """ + pass +def g(x): + """Badly indented docstring.""" + pass''', + docformatter.format_code('''\ +def f(x): + """This is a docstring. + + + That should be on less lines + """ + pass +def g(x): + """ Badly indented docstring""" + pass''', length_range=[1, 1])) + def test_format_code_with_module_docstring(self): self.assertEqual( '''\ @@ -1013,6 +1058,12 @@ self.assertEqual( summary, docformatter.normalize_summary(summary)) + + def test_normalize_summary_formatted_as_title(self): + summary = '# This is a title' + self.assertEqual( + summary, + docformatter.normalize_summary(summary)) def test_detect_encoding_with_bad_encoding(self): with temporary_file('# -*- coding: blah -*-\n') as filename: @@ -1182,6 +1233,43 @@ """This one-line docstring will be multi-line"""\ ''', make_summary_multi_line=True)) + def test_exclude(self): + sources = {"/root"} + patch_data = [ + ("/root", ['folder_one', 'folder_two'], []), + ("/root/folder_one", ['folder_three'], ["one.py"]), + ("/root/folder_one/folder_three", [], ["three.py"]), + ("/root/folder_two", [], ["two.py"]), + ] + with patch("os.walk", return_value=patch_data), patch("os.path.isdir", return_value=True): + test_exclude_one = list(docformatter.find_py_files(sources, True, ["folder_one"])) + self.assertEqual(test_exclude_one, ['/root/folder_two/two.py']) + test_exclude_two = list(docformatter.find_py_files(sources, True, ["folder_two"])) + self.assertEqual(test_exclude_two, ['/root/folder_one/one.py', '/root/folder_one/folder_three/three.py']) + test_exclude_three = list(docformatter.find_py_files(sources, True, ["folder_three"])) + self.assertEqual(test_exclude_three, ['/root/folder_one/one.py', '/root/folder_two/two.py']) + test_exclude_py = list(docformatter.find_py_files(sources, True, ".py")) + self.assertFalse(test_exclude_py) + test_exclude_two_and_three = list(docformatter.find_py_files(sources, True, ["folder_two", "folder_three"])) + self.assertEqual(test_exclude_two_and_three, ['/root/folder_one/one.py']) + test_exclude_files = list(docformatter.find_py_files(sources, True, ["one.py", "two.py"])) + self.assertEqual(test_exclude_files, ['/root/folder_one/folder_three/three.py']) + + def test_exclude_nothing(self): + sources = {"/root"} + patch_data = [ + ("/root", ['folder_one', 'folder_two'], []), + ("/root/folder_one", ['folder_three'], ["one.py"]), + ("/root/folder_one/folder_three", [], ["three.py"]), + ("/root/folder_two", [], ["two.py"]), + ] + with patch("os.walk", return_value=patch_data), patch("os.path.isdir", return_value=True): + test_exclude_nothing = list(docformatter.find_py_files(sources, True, [])) + self.assertEqual(test_exclude_nothing, ['/root/folder_one/one.py', '/root/folder_one/folder_three/three.py', + '/root/folder_two/two.py']) + test_exclude_nothing = list(docformatter.find_py_files(sources, True)) + self.assertEqual(test_exclude_nothing, ['/root/folder_one/one.py', '/root/folder_one/folder_three/three.py', + '/root/folder_two/two.py']) class TestSystem(unittest.TestCase):