From 9a58911ea760b996b88355b6b18420b88b5a0ea9 Mon Sep 17 00:00:00 2001 From: Hynek Schlawack Date: Mon, 11 Apr 2022 15:43:12 +0200 Subject: [PATCH] Add black & isort to pre-commit Use the default 88 columns from Black while allowing for 99 columns for longer (doc)strings. --- .pre-commit-config.yaml | 15 ++- admin/canonicalize_version.py | 2 +- admin/check_tag_version_match.py | 1 + bin/towncrier | 5 +- docs/conf.py | 61 ++++++------- pyproject.toml | 5 + setup.py | 4 +- src/towncrier/__init__.py | 1 + src/towncrier/__main__.py | 1 + src/towncrier/_builder.py | 8 +- src/towncrier/_git.py | 3 +- src/towncrier/_project.py | 6 +- src/towncrier/_settings/__init__.py | 1 + src/towncrier/_settings/fragment_types.py | 9 +- src/towncrier/_settings/load.py | 13 +-- src/towncrier/_shell.py | 3 +- src/towncrier/_version.py | 1 + src/towncrier/build.py | 31 ++++--- src/towncrier/check.py | 10 +- src/towncrier/create.py | 13 ++- src/towncrier/test/test_build.py | 106 +++++++++++++--------- src/towncrier/test/test_builder.py | 4 +- src/towncrier/test/test_check.py | 35 ++++--- src/towncrier/test/test_create.py | 13 ++- src/towncrier/test/test_format.py | 4 +- src/towncrier/test/test_project.py | 5 +- src/towncrier/test/test_settings.py | 53 +++++++++-- src/towncrier/test/test_write.py | 19 ++-- tox.ini | 1 + 29 files changed, 264 insertions(+), 169 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cc1ca28d..22a34b58 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,12 +3,23 @@ ci: autoupdate_schedule: monthly repos: + - repo: https://github.com/psf/black + rev: 22.3.0 + hooks: + - id: black + - repo: https://github.com/asottile/pyupgrade - rev: v2.31.1 + rev: v2.32.0 hooks: - id: pyupgrade args: [--py37-plus] + - repo: https://github.com/PyCQA/isort + rev: 5.10.1 + hooks: + - id: isort + additional_dependencies: [toml] + - repo: https://github.com/PyCQA/flake8 rev: 4.0.1 hooks: @@ -16,7 +27,7 @@ repos: language_version: python3.10 - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.1.0 + rev: v4.2.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer diff --git a/admin/canonicalize_version.py b/admin/canonicalize_version.py index 7d80717f..671b8c23 100644 --- a/admin/canonicalize_version.py +++ b/admin/canonicalize_version.py @@ -12,7 +12,7 @@ def cli(version): release_candidate = None if parsed_version.pre is not None: - if parsed_version.pre[0] == 'rc': + if parsed_version.pre[0] == "rc": release_candidate = parsed_version.pre[1] incremental_version = incremental.Version( diff --git a/admin/check_tag_version_match.py b/admin/check_tag_version_match.py index 9fabd4da..f340e040 100644 --- a/admin/check_tag_version_match.py +++ b/admin/check_tag_version_match.py @@ -11,6 +11,7 @@ import pep517.meta + TAG_PREFIX = "refs/tags/" if len(sys.argv) < 2: diff --git a/bin/towncrier b/bin/towncrier index f76f7186..a5604922 100755 --- a/bin/towncrier +++ b/bin/towncrier @@ -1,11 +1,14 @@ #! /usr/bin/env python3 # flake8: noqa -import sys import os.path +import sys + srcdir = os.path.join(os.path.dirname(__file__), "..", "src") sys.path.insert(0, srcdir) import towncrier + + towncrier._main() diff --git a/docs/conf.py b/docs/conf.py index 855dbd0f..072bd313 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -32,30 +32,30 @@ extensions = [] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ".rst" # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = 'Towncrier' -copyright = '2017, Amber Brown' -author = 'Amber Brown' +project = "Towncrier" +copyright = "2017, Amber Brown" +author = "Amber Brown" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '17.08' +version = "17.08" # The full version, including alpha/beta/rc tags. -release = '17.08' +release = "17.08" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -67,10 +67,10 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False @@ -81,7 +81,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +html_theme = "alabaster" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the @@ -92,7 +92,7 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # Custom sidebar templates, must be a dictionary that maps document names # to template names. @@ -100,12 +100,12 @@ # This is required for the alabaster theme # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars html_sidebars = { - '**': [ - 'about.html', - 'navigation.html', - 'relations.html', # needs 'show_related': True theme option to display - 'searchbox.html', - 'donate.html', + "**": [ + "about.html", + "navigation.html", + "relations.html", # needs 'show_related': True theme option to display + "searchbox.html", + "donate.html", ] } @@ -113,7 +113,7 @@ # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. -htmlhelp_basename = 'Towncrierdoc' +htmlhelp_basename = "Towncrierdoc" # -- Options for LaTeX output --------------------------------------------- @@ -122,15 +122,12 @@ # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. # # 'preamble': '', - # Latex figure (float) alignment # # 'figure_align': 'htbp', @@ -140,8 +137,7 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'Towncrier.tex', 'Towncrier Documentation', - 'Amber Brown', 'manual'), + (master_doc, "Towncrier.tex", "Towncrier Documentation", "Amber Brown", "manual"), ] @@ -149,10 +145,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'towncrier', 'Towncrier Documentation', - [author], 1) -] +man_pages = [(master_doc, "towncrier", "Towncrier Documentation", [author], 1)] # -- Options for Texinfo output ------------------------------------------- @@ -161,7 +154,13 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'Towncrier', 'Towncrier Documentation', - author, 'Towncrier', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "Towncrier", + "Towncrier Documentation", + author, + "Towncrier", + "One line description of project.", + "Miscellaneous", + ), ] diff --git a/pyproject.toml b/pyproject.toml index 23be09a0..9f13d8db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,6 +54,11 @@ exclude = ''' ) ''' + +[tool.isort] +profile = "attrs" + + [build-system] requires = [ "setuptools ~= 44.1.1", diff --git a/setup.py b/setup.py index d648b45a..cdaf2ed3 100644 --- a/setup.py +++ b/setup.py @@ -1,12 +1,12 @@ #!/usr/bin/env python -from setuptools import setup, find_packages - # If incremental is not present then setuptools just silently uses v0.0.0 so # let's import it and fail instead. import incremental # noqa +from setuptools import find_packages, setup + setup( name="towncrier", diff --git a/src/towncrier/__init__.py b/src/towncrier/__init__.py index 78db5995..ba09c39a 100644 --- a/src/towncrier/__init__.py +++ b/src/towncrier/__init__.py @@ -7,4 +7,5 @@ from ._version import __version__ + __all__ = ["__version__"] diff --git a/src/towncrier/__main__.py b/src/towncrier/__main__.py index a404fa89..e7257122 100644 --- a/src/towncrier/__main__.py +++ b/src/towncrier/__main__.py @@ -1,3 +1,4 @@ from towncrier._shell import cli + cli() diff --git a/src/towncrier/_builder.py b/src/towncrier/_builder.py index 3295b9cb..42c3bb00 100644 --- a/src/towncrier/_builder.py +++ b/src/towncrier/_builder.py @@ -47,12 +47,12 @@ def parse_newfragment_basename(basename, definitions): # NOTE: This allows news fragment names like fix-1.2.3.feature or # something-cool.feature.ext for projects that don't use ticket # numbers in news fragment names. - ticket = strip_if_integer_string(parts[i-1]) + ticket = strip_if_integer_string(parts[i - 1]) counter = 0 # Use the following part as the counter if it exists and is a valid # digit. - if len(parts) > (i + 1) and parts[i+1].isdigit(): - counter = int(parts[i+1]) + if len(parts) > (i + 1) and parts[i + 1].isdigit(): + counter = int(parts[i + 1]) return ticket, category, counter else: # No valid category found. @@ -92,7 +92,7 @@ def find_fragments(base_directory, sections, fragment_directory, definitions): files = os.listdir(section_dir) except FileNotFoundError as e: message = "Failed to list the news fragment files.\n{}".format( - ''.join(traceback.format_exception_only(type(e), e)), + "".join(traceback.format_exception_only(type(e), e)), ) raise ConfigError(message) diff --git a/src/towncrier/_git.py b/src/towncrier/_git.py index 2ff7d56b..744efcdd 100644 --- a/src/towncrier/_git.py +++ b/src/towncrier/_git.py @@ -1,9 +1,10 @@ # Copyright (c) Amber Brown, 2015 # See LICENSE for details. +import os + from subprocess import call -import os import click diff --git a/src/towncrier/_project.py b/src/towncrier/_project.py index e9568fc1..c5e4676f 100644 --- a/src/towncrier/_project.py +++ b/src/towncrier/_project.py @@ -54,9 +54,9 @@ def get_version(package_dir, package): return ".".join(map(str, version)).strip() raise Exception( - "I only know how to look at a __version__ that is a str, " - "an Increment Version, or a tuple. If you can't provide " - "that, use the --version argument and specify one." + "I only know how to look at a __version__ that is a str, " + "an Increment Version, or a tuple. If you can't provide " + "that, use the --version argument and specify one." ) diff --git a/src/towncrier/_settings/__init__.py b/src/towncrier/_settings/__init__.py index f0cda51d..6cbe32a2 100644 --- a/src/towncrier/_settings/__init__.py +++ b/src/towncrier/_settings/__init__.py @@ -2,6 +2,7 @@ from towncrier._settings import load + load_config = load.load_config ConfigError = load.ConfigError load_config_from_options = load.load_config_from_options diff --git a/src/towncrier/_settings/fragment_types.py b/src/towncrier/_settings/fragment_types.py index 3262b4ac..434b6475 100644 --- a/src/towncrier/_settings/fragment_types.py +++ b/src/towncrier/_settings/fragment_types.py @@ -25,7 +25,7 @@ def factory(cls, config): return new @abc.abstractmethod - def load(self,): + def load(self): """Load fragment types.""" @@ -42,7 +42,7 @@ class DefaultFragmentTypesLoader(BaseFragmentTypesLoader): ] ) - def load(self,): + def load(self): """Load default types.""" return self._default_types @@ -64,7 +64,7 @@ class ArrayFragmentTypesLoader(BaseFragmentTypesLoader): """ - def load(self,): + def load(self): """Load types from toml array of mappings.""" types = clt.OrderedDict() @@ -104,12 +104,13 @@ class TableFragmentTypesLoader(BaseFragmentTypesLoader): # The content will be shown. """ + def __init__(self, config): """Initialize.""" self.config = config self.fragment_options = config.get("fragment", {}) - def load(self,): + def load(self): """Load types from nested mapping.""" fragment_types = self.fragment_options.keys() fragment_types = sorted(fragment_types) diff --git a/src/towncrier/_settings/load.py b/src/towncrier/_settings/load.py index 2562e9be..f4335af8 100644 --- a/src/towncrier/_settings/load.py +++ b/src/towncrier/_settings/load.py @@ -2,11 +2,12 @@ # See LICENSE for details. import os -import pkg_resources +from collections import OrderedDict + +import pkg_resources import tomli -from collections import OrderedDict from .._settings import fragment_types as ft @@ -38,9 +39,7 @@ def load_config_from_options(directory, config): config = load_config_from_file(os.path.dirname(config), config) if config is None: - raise ConfigError( - f"No configuration file found.\nLooked in: {base_directory}" - ) + raise ConfigError(f"No configuration file found.\nLooked in: {base_directory}") return base_directory, config @@ -79,9 +78,7 @@ def parse_toml(base_path, config): sections[x.get("name", "")] = x["path"] else: sections[""] = "" - fragment_types_loader = ft.BaseFragmentTypesLoader.factory( - config - ) + fragment_types_loader = ft.BaseFragmentTypesLoader.factory(config) types = fragment_types_loader.load() wrap = config.get("wrap", False) diff --git a/src/towncrier/_shell.py b/src/towncrier/_shell.py index e7f10f69..f550003f 100644 --- a/src/towncrier/_shell.py +++ b/src/towncrier/_shell.py @@ -6,12 +6,13 @@ """ import click + from click_default_group import DefaultGroup +from ._version import __version__ from .build import _main as _build_cmd from .check import _main as _check_cmd from .create import _main as _create_cmd -from ._version import __version__ @click.group(cls=DefaultGroup, default="build", default_if_no_args=True) diff --git a/src/towncrier/_version.py b/src/towncrier/_version.py index 595cc4a8..11115e27 100644 --- a/src/towncrier/_version.py +++ b/src/towncrier/_version.py @@ -7,5 +7,6 @@ from incremental import Version + __version__ = Version("towncrier", 21, 9, 1, dev=0) __all__ = ["__version__"] diff --git a/src/towncrier/build.py b/src/towncrier/build.py index b85804ce..1f7aab66 100644 --- a/src/towncrier/build.py +++ b/src/towncrier/build.py @@ -7,16 +7,17 @@ import os -import click import sys from datetime import date -from ._settings import load_config_from_options, ConfigError -from ._builder import find_fragments, split_fragments, render_fragments -from ._project import get_version, get_project_name -from ._writer import append_to_newsfile +import click + +from ._builder import find_fragments, render_fragments, split_fragments from ._git import remove_files, stage_newsfile +from ._project import get_project_name, get_version +from ._settings import ConfigError, load_config_from_options +from ._writer import append_to_newsfile def _get_date(): @@ -114,19 +115,21 @@ def __main( ) if project_version is None: - project_version = config.get('version') + project_version = config.get("version") if project_version is None: project_version = get_version( os.path.join(base_directory, config["package_dir"]), config["package"] ).strip() if project_name is None: - project_name = config.get('name') + project_name = config.get("name") if not project_name: package = config.get("package") if package: project_name = get_project_name( - os.path.abspath(os.path.join(base_directory, config["package_dir"])), + os.path.abspath( + os.path.join(base_directory, config["package_dir"]) + ), package, ) else: @@ -168,11 +171,13 @@ def __main( ) if render_title_separately: - content = "\n".join([ - top_line, - config["underlines"][0] * len(top_line), - rendered, - ]) + content = "\n".join( + [ + top_line, + config["underlines"][0] * len(top_line), + rendered, + ] + ) else: content = rendered diff --git a/src/towncrier/check.py b/src/towncrier/check.py index aaa71336..0c0d5b0a 100644 --- a/src/towncrier/check.py +++ b/src/towncrier/check.py @@ -5,12 +5,12 @@ import os import sys -import click +from subprocess import STDOUT, CalledProcessError, check_output -from subprocess import CalledProcessError, check_output, STDOUT +import click -from ._settings import load_config_from_options from ._builder import find_fragments +from ._settings import load_config_from_options def _run(args, **kwargs): @@ -49,7 +49,9 @@ def __main(comparewith, directory, config): raise if not files_changed: - click.echo(f"On {comparewith} branch, or no diffs, so no newsfragment required.") + click.echo( + f"On {comparewith} branch, or no diffs, so no newsfragment required." + ) sys.exit(0) files = { diff --git a/src/towncrier/create.py b/src/towncrier/create.py index 82f47de6..616bad3f 100644 --- a/src/towncrier/create.py +++ b/src/towncrier/create.py @@ -7,6 +7,7 @@ import os + import click from ._settings import load_config_from_options @@ -22,10 +23,11 @@ help="Open an editor for writing the newsfragment content.", ) # TODO: default should be true @click.option( - "-c", "--content", + "-c", + "--content", type=str, default="Add your info here", - help="Sets the content of the new fragment." + help="Sets the content of the new fragment.", ) @click.argument("filename") def _main(ctx, directory, config, filename, edit, content): @@ -87,13 +89,10 @@ def _get_news_content_from_user(message): initial_content = ( "# Please write your news content. When finished, save the file.\n" "# In order to abort, exit without saving.\n" - "# Lines starting with \"#\" are ignored.\n" + '# Lines starting with "#" are ignored.\n' ) if message is not None: - initial_content += ( - "\n" - "{message}\n".format(message=message) - ) + initial_content += "\n" "{message}\n".format(message=message) content = click.edit(initial_content) if content is None: return None diff --git a/src/towncrier/test/test_build.py b/src/towncrier/test/test_build.py index 5562a2f7..bed40131 100644 --- a/src/towncrier/test/test_build.py +++ b/src/towncrier/test/test_build.py @@ -2,14 +2,15 @@ # See LICENSE for details. import os + from subprocess import call from textwrap import dedent -from twisted.trial.unittest import TestCase from click.testing import CliRunner +from twisted.trial.unittest import TestCase -from ..build import _main from .._shell import cli +from ..build import _main def setup_simple_project(): @@ -387,9 +388,7 @@ def test_version_in_config(self): with open("newsfragments/123.feature", "w") as f: f.write("Adds levitation") - result = runner.invoke( - _main, ["--date", "01-01-2001", "--draft"] - ) + result = runner.invoke(_main, ["--date", "01-01-2001", "--draft"]) self.assertEqual(0, result.exit_code, result.output) self.assertEqual( @@ -565,7 +564,7 @@ def test_singlefile_errors_and_explains_cleanly(self): self.assertEqual(1, result.exit_code) self.assertEqual( - '`singlefile` is not a valid option. Did you mean `single_file`?\n', + "`singlefile` is not a valid option. Did you mean `single_file`?\n", result.output, ) @@ -631,30 +630,19 @@ def test_bullet_points_false(self): with runner.isolated_filesystem(): with open("pyproject.toml", "w") as f: f.write( - '[tool.towncrier]\n' + "[tool.towncrier]\n" 'template="towncrier:single-file-no-bullets"\n' - 'all_bullets=false' + "all_bullets=false" ) os.mkdir("newsfragments") with open("newsfragments/123.feature", "w") as f: - f.write( - "wow!\n" - "~~~~\n" - "\n" - "No indentation at all." - ) + f.write("wow!\n" "~~~~\n" "\n" "No indentation at all.") with open("newsfragments/124.bugfix", "w") as f: - f.write( - "#. Numbered bullet list." - ) + f.write("#. Numbered bullet list.") with open("newsfragments/125.removal", "w") as f: - f.write( - "- Hyphen based bullet list." - ) + f.write("- Hyphen based bullet list.") with open("newsfragments/126.doc", "w") as f: - f.write( - "* Asterisk based bullet list." - ) + f.write("* Asterisk based bullet list.") result = runner.invoke( _main, @@ -719,11 +707,15 @@ def test_title_format_custom(self): with runner.isolated_filesystem(): with open("pyproject.toml", "w") as f: - f.write(dedent("""\ + f.write( + dedent( + """\ [tool.towncrier] package = "foo" title_format = "[{project_date}] CUSTOM RELEASE for {name} version {version}" - """)) + """ + ) + ) os.mkdir("foo") os.mkdir("foo/newsfragments") with open("foo/newsfragments/123.feature", "w") as f: @@ -745,7 +737,8 @@ def test_title_format_custom(self): ], ) - expected_output = dedent("""\ + expected_output = dedent( + """\ Loading template... Finding news fragments... Rendering news fragments... @@ -761,7 +754,8 @@ def test_title_format_custom(self): - Adds levitation (#123) - Extends levitation (#124) - """) + """ + ) self.assertEqual(0, result.exit_code) self.assertEqual(expected_output, result.output) @@ -775,16 +769,22 @@ def test_title_format_false(self): with runner.isolated_filesystem(): with open("pyproject.toml", "w") as f: - f.write(dedent("""\ + f.write( + dedent( + """\ [tool.towncrier] package = "foo" title_format = false template = "template.rst" - """)) + """ + ) + ) os.mkdir("foo") os.mkdir("foo/newsfragments") with open("template.rst", "w") as f: - f.write(dedent("""\ + f.write( + dedent( + """\ Here's a hardcoded title added by the template ============================================== {% for section in sections %} @@ -797,7 +797,9 @@ def test_title_format_false(self): {% endfor %} {% endfor %} {% endfor %} - """)) + """ + ) + ) result = runner.invoke( _main, @@ -812,7 +814,8 @@ def test_title_format_false(self): ], ) - expected_output = dedent("""\ + expected_output = dedent( + """\ Loading template... Finding news fragments... Rendering news fragments... @@ -822,7 +825,8 @@ def test_title_format_false(self): Here's a hardcoded title added by the template ============================================== - """) + """ + ) self.assertEqual(0, result.exit_code) self.assertEqual(expected_output, result.output) @@ -837,10 +841,14 @@ def test_start_string(self): with runner.isolated_filesystem(): with open("pyproject.toml", "w") as f: - f.write(dedent("""\ + f.write( + dedent( + """\ [tool.towncrier] start_string="Release notes start marker" - """)) + """ + ) + ) os.mkdir("newsfragments") with open("newsfragments/123.feature", "w") as f: f.write("Adds levitation") @@ -865,7 +873,8 @@ def test_start_string(self): with open("NEWS.rst") as f: output = f.read() - expected_output = dedent("""\ + expected_output = dedent( + """\ a line another @@ -880,7 +889,8 @@ def test_start_string(self): - Adds levitation (#123) - """) + """ + ) self.assertEqual(expected_output, output) @@ -892,7 +902,9 @@ def test_with_topline_and_template_and_draft(self): with runner.isolated_filesystem(): with open("pyproject.toml", "w") as f: - f.write(dedent("""\ + f.write( + dedent( + """\ [tool.towncrier] title_format = "{version} - {project_date}" template = "template.rst" @@ -901,12 +913,16 @@ def test_with_topline_and_template_and_draft(self): directory = "feature" name = "" showcontent = true - """)) + """ + ) + ) os.mkdir("newsfragments") with open("newsfragments/123.feature", "w") as f: f.write("Adds levitation") with open("template.rst", "w") as f: - f.write(dedent("""\ + f.write( + dedent( + """\ {% for section in sections %} {% set underline = "-" %} {% for category, val in definitions.items() if category in sections[section] %} @@ -917,7 +933,9 @@ def test_with_topline_and_template_and_draft(self): {% endfor %} {% endfor %} {% endfor %} - """)) + """ + ) + ) result = runner.invoke( _main, @@ -929,7 +947,8 @@ def test_with_topline_and_template_and_draft(self): ], ) - expected_output = dedent("""\ + expected_output = dedent( + """\ Loading template... Finding news fragments... Rendering news fragments... @@ -941,7 +960,8 @@ def test_with_topline_and_template_and_draft(self): - Adds levitation - """) + """ + ) self.assertEqual(0, result.exit_code, result.output) self.assertEqual(expected_output, result.output) diff --git a/src/towncrier/test/test_builder.py b/src/towncrier/test/test_builder.py index 7f48a2e9..62630af0 100644 --- a/src/towncrier/test/test_builder.py +++ b/src/towncrier/test/test_builder.py @@ -73,11 +73,11 @@ def test_strip(self): """ self.assertEqual( parse_newfragment_basename(" 007.feature", ["feature"]), - ("7", "feature", 0) + ("7", "feature", 0), ) def test_strip_with_counter(self): self.assertEqual( parse_newfragment_basename(" 007.feature.3", ["feature"]), - ("7", "feature", 3) + ("7", "feature", 3), ) diff --git a/src/towncrier/test/test_check.py b/src/towncrier/test/test_check.py index 06fa9df8..fabc3e7c 100644 --- a/src/towncrier/test/test_check.py +++ b/src/towncrier/test/test_check.py @@ -5,9 +5,10 @@ import os.path import sys -from twisted.trial.unittest import TestCase +from subprocess import PIPE, Popen, call + from click.testing import CliRunner -from subprocess import call, Popen, PIPE +from twisted.trial.unittest import TestCase from towncrier.check import _main as towncrier_check @@ -18,10 +19,7 @@ def create_project(pyproject_path="pyproject.toml", main_branch="main"): news-fragment and then switch to a new in-work branch. """ with open(pyproject_path, "w") as f: - f.write( - "[tool.towncrier]\n" - 'package = "foo"\n' - ) + f.write("[tool.towncrier]\n" 'package = "foo"\n') os.mkdir("foo") with open("foo/__init__.py", "w") as f: f.write('__version__ = "1.2.3"\n') @@ -56,7 +54,7 @@ def write(path, contents): f.write(contents) -def initial_commit(branch='main'): +def initial_commit(branch="main"): """ Create a git repo, configure it and make an initial commit @@ -116,7 +114,8 @@ def _test_no_changes_made(self, pyproject_path, invoke): self.assertEqual(0, result.exit_code, result.output) self.assertEqual( - "On master branch, or no diffs, so no newsfragment required.\n", result.output + "On master branch, or no diffs, so no newsfragment required.\n", + result.output, ) def test_fragment_exists(self): @@ -186,7 +185,7 @@ def test_none_stdout_encoding_works(self): call(["git", "commit", "-m", "add a newsfragment"]) proc = Popen( - [sys.executable, '-m', 'towncrier.check', "--compare-with", "master"], + [sys.executable, "-m", "towncrier.check", "--compare-with", "master"], stdout=PIPE, stderr=PIPE, ) @@ -208,13 +207,13 @@ def test_first_release(self): # Arrange create_project() # Before any release, the NEWS file might no exist. - self.assertNotIn('NEWS.rst', os.listdir('.')) + self.assertNotIn("NEWS.rst", os.listdir(".")) call(["towncrier", "build", "--yes", "--version", "1.0"]) commit("Prepare a release") # When missing, # the news file is automatically created with a new release. - self.assertIn('NEWS.rst', os.listdir('.')) + self.assertIn("NEWS.rst", os.listdir(".")) # Act result = runner.invoke(towncrier_check, ["--compare-with", "main"]) @@ -238,10 +237,10 @@ def test_release_branch(self): # Do a first release without any checks. # And merge the release branch back into the main branch. - call(["towncrier", "build", "--yes", "--version", "1.0"]) + call(["towncrier", "build", "--yes", "--version", "1.0"]) commit("First release") # The news file is now created. - self.assertIn('NEWS.rst', os.listdir('.')) + self.assertIn("NEWS.rst", os.listdir(".")) call(["git", "checkout", "main"]) call(["git", "merge", "otherbranch", "-m", "Sync release in main branch."]) @@ -251,7 +250,15 @@ def test_release_branch(self): write("foo/newsfragments/456.feature", "Foo the bar") commit("A feature in the second release.") call(["git", "checkout", "main"]) - call(["git", "merge", "new-feature-branch", "-m", "Merge new-feature-branch."]) + call( + [ + "git", + "merge", + "new-feature-branch", + "-m", + "Merge new-feature-branch.", + ] + ) # We now have the new release branch. call(["git", "checkout", "-b", "next-release"]) diff --git a/src/towncrier/test/test_create.py b/src/towncrier/test/test_create.py index efa5b35a..39ae3bf6 100644 --- a/src/towncrier/test/test_create.py +++ b/src/towncrier/test/test_create.py @@ -2,12 +2,12 @@ # See LICENSE for details. import os + from textwrap import dedent from unittest import mock -from twisted.trial.unittest import TestCase - from click.testing import CliRunner +from twisted.trial.unittest import TestCase from ..create import _main @@ -36,7 +36,7 @@ class TestCli(TestCase): maxDiff = None def _test_success( - self, content=None, config=None, mkdir=True, additional_args=None + self, content=None, config=None, mkdir=True, additional_args=None ): runner = CliRunner() @@ -74,7 +74,7 @@ def test_edit_without_comments(self): mock_edit.assert_called_once_with( "# Please write your news content. When finished, save the file.\n" "# In order to abort, exit without saving.\n" - "# Lines starting with \"#\" are ignored.\n" + '# Lines starting with "#" are ignored.\n' "\n" "Add your info here\n" ) @@ -120,13 +120,12 @@ def test_message_and_edit(self): with mock.patch("click.edit") as mock_edit: mock_edit.return_value = "".join(edit_content) self._test_success( - content=edit_content, - additional_args=["-c", content_line, "--edit"] + content=edit_content, additional_args=["-c", content_line, "--edit"] ) mock_edit.assert_called_once_with( "# Please write your news content. When finished, save the file.\n" "# In order to abort, exit without saving.\n" - "# Lines starting with \"#\" are ignored.\n" + '# Lines starting with "#" are ignored.\n' "\n" "{content_line}\n".format(content_line=content_line) ) diff --git a/src/towncrier/test/test_format.py b/src/towncrier/test/test_format.py index 1324b216..bdf6f387 100644 --- a/src/towncrier/test/test_format.py +++ b/src/towncrier/test/test_format.py @@ -2,12 +2,12 @@ # See LICENSE for details. +from collections import OrderedDict + import pkg_resources from twisted.trial.unittest import TestCase -from collections import OrderedDict - from .._builder import render_fragments, split_fragments diff --git a/src/towncrier/test/test_project.py b/src/towncrier/test/test_project.py index 5a7ff8b9..6c9b4657 100644 --- a/src/towncrier/test/test_project.py +++ b/src/towncrier/test/test_project.py @@ -3,6 +3,7 @@ import os import sys + from subprocess import check_output from twisted.trial.unittest import TestCase @@ -107,11 +108,11 @@ def test_dash_m(self): try: os.chdir(new_dir) with open("pyproject.toml", "w") as f: - f.write('[tool.towncrier]\n' 'directory = "news"\n') + f.write("[tool.towncrier]\n" 'directory = "news"\n') os.makedirs("news") out = check_output([sys.executable, "-m", "towncrier", "--help"]) self.assertIn(b"[OPTIONS] COMMAND [ARGS]...", out) - self.assertRegex(out, br".*--help\s+Show this message and exit.") + self.assertRegex(out, rb".*--help\s+Show this message and exit.") finally: os.chdir(orig_dir) diff --git a/src/towncrier/test/test_settings.py b/src/towncrier/test/test_settings.py index 7cfd9003..48a5826d 100644 --- a/src/towncrier/test/test_settings.py +++ b/src/towncrier/test/test_settings.py @@ -3,12 +3,13 @@ import collections as clt import os -from textwrap import dedent import textwrap +from textwrap import dedent + from twisted.trial.unittest import TestCase -from .._settings import load_config, ConfigError +from .._settings import ConfigError, load_config class TomlSettingsTests(TestCase): @@ -226,11 +227,25 @@ def test_custom_types_as_tables_array_deprecated(self): """ toml_content = textwrap.dedent(toml_content) expected = [ - ("foo", {"name": "Foo", "showcontent": False, }), - ("spam", {"name": "Spam", "showcontent": True, },), + ( + "foo", + { + "name": "Foo", + "showcontent": False, + }, + ), + ( + "spam", + { + "name": "Spam", + "showcontent": True, + }, + ), ] expected = clt.OrderedDict(expected) - config = self.load_config_from_string(toml_content, ) + config = self.load_config_from_string( + toml_content, + ) actual = config["types"] self.assertDictEqual(expected, actual) @@ -253,13 +268,33 @@ def test_custom_types_as_tables(self): """ toml_content = textwrap.dedent(toml_content) expected = [ - ("chore", {"name": "Other Tasks", "showcontent": False, }), - ("feat", {"name": "Feat", "showcontent": True, }), - ("fix", {"name": "Fix", "showcontent": True, }), + ( + "chore", + { + "name": "Other Tasks", + "showcontent": False, + }, + ), + ( + "feat", + { + "name": "Feat", + "showcontent": True, + }, + ), + ( + "fix", + { + "name": "Fix", + "showcontent": True, + }, + ), ] expected = clt.OrderedDict(expected) - config = self.load_config_from_string(toml_content, ) + config = self.load_config_from_string( + toml_content, + ) actual = config["types"] self.assertDictEqual(expected, actual) diff --git a/src/towncrier/test/test_write.py b/src/towncrier/test/test_write.py index b3eddb58..5cb82e7a 100644 --- a/src/towncrier/test/test_write.py +++ b/src/towncrier/test/test_write.py @@ -1,13 +1,14 @@ # Copyright (c) Amber Brown, 2015 # See LICENSE for details. -from twisted.trial.unittest import TestCase - -import pkg_resources import os -from textwrap import dedent from collections import OrderedDict +from textwrap import dedent + +import pkg_resources + +from twisted.trial.unittest import TestCase from .._builder import render_fragments, split_fragments from .._writer import append_to_newsfile @@ -193,8 +194,8 @@ def test_append_at_top_with_hint(self): with open(os.path.join(tempdir, "NEWS.rst"), "w") as f: f.write( - "Hello there! Here is some info.\n\n" - ".. towncrier release notes start\nOld text.\n" + "Hello there! Here is some info.\n\n" + ".. towncrier release notes start\nOld text.\n" ) fragments = split_fragments(fragments, definitions) @@ -260,9 +261,11 @@ def test_multiple_file_no_start_string(self): with open(os.path.join(tempdir, "NEWS.rst")) as f: output = f.read() - expected_output = dedent("""\ + expected_output = dedent( + """\ MyProject 1.0 (never) ===================== - """) + """ + ) self.assertEqual(expected_output, output) diff --git a/tox.ini b/tox.ini index 033739d4..fa1ec2e9 100644 --- a/tox.ini +++ b/tox.ini @@ -65,4 +65,5 @@ commands = coverage erase [flake8] +# Allow for longer test strings. Code is formatted to 88 columns by Black. max-line-length = 99