diff --git a/.flake8 b/.flake8 index 3907f28c..815b43f4 100644 --- a/.flake8 +++ b/.flake8 @@ -4,3 +4,5 @@ max-line-length = 99 extend-ignore = # Conflict between flake8 & black about whitespace in slices. E203 + # Conflict between flake8 & black about empty lines after imports. + E302 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3b6f4392..5504250f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ ci: repos: - repo: https://github.com/psf/black-pre-commit-mirror - rev: 25.12.0 + rev: 26.3.0 hooks: - id: black @@ -15,7 +15,7 @@ repos: args: [--py39-plus] - repo: https://github.com/PyCQA/isort - rev: 7.0.0 + rev: 8.0.1 hooks: - id: isort additional_dependencies: [toml] diff --git a/admin/check_tag_version_match.py b/admin/check_tag_version_match.py index 25ae1809..0c3d87df 100644 --- a/admin/check_tag_version_match.py +++ b/admin/check_tag_version_match.py @@ -12,7 +12,6 @@ from importlib import metadata - TAG_PREFIX = "refs/tags/" if len(sys.argv) < 2: diff --git a/bin/towncrier b/bin/towncrier index a5604922..30c43f33 100755 --- a/bin/towncrier +++ b/bin/towncrier @@ -4,11 +4,9 @@ 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 f98d50c8..d6335ad6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -34,7 +34,6 @@ from datetime import date from importlib.metadata import version - towncrier_version = version("towncrier") diff --git a/noxfile.py b/noxfile.py index 494085c7..8df551d9 100644 --- a/noxfile.py +++ b/noxfile.py @@ -4,7 +4,6 @@ import nox - nox.options.sessions = ["pre_commit", "docs", "typecheck", "tests"] nox.options.reuse_existing_virtualenvs = True nox.options.error_on_external_run = True diff --git a/pyproject.toml b/pyproject.toml index f39dd740..0918f788 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -129,13 +129,17 @@ exclude = ''' [tool.isort] -profile = "attrs" +atomic = true +force_grid_wrap = 0 +include_trailing_comma = true line_length = 88 - +lines_after_imports = -1 +lines_between_types = 1 +multi_line_output = 3 +use_parentheses = true [tool.ruff.isort] -# Match isort's "attrs" profile -lines-after-imports = 2 +lines-after-imports = 1 lines-between-types = 1 diff --git a/src/towncrier/__main__.py b/src/towncrier/__main__.py index cf8d9378..49481253 100644 --- a/src/towncrier/__main__.py +++ b/src/towncrier/__main__.py @@ -2,5 +2,4 @@ from towncrier._shell import cli - cli() diff --git a/src/towncrier/_settings/__init__.py b/src/towncrier/_settings/__init__.py index 0f25f2f4..645d820b 100644 --- a/src/towncrier/_settings/__init__.py +++ b/src/towncrier/_settings/__init__.py @@ -4,7 +4,6 @@ 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/load.py b/src/towncrier/_settings/load.py index 0170a024..a6177957 100644 --- a/src/towncrier/_settings/load.py +++ b/src/towncrier/_settings/load.py @@ -18,7 +18,6 @@ from .._settings import fragment_types as ft - if sys.version_info < (3, 10): import importlib_resources as resources else: diff --git a/src/towncrier/_writer.py b/src/towncrier/_writer.py index 634b5f19..661a45a9 100644 --- a/src/towncrier/_writer.py +++ b/src/towncrier/_writer.py @@ -13,7 +13,6 @@ from pathlib import Path from typing import Any - if sys.version_info < (3, 10): # Compatibility shim for newline parameter to write_text, added in 3.10 def _newline_write_text(path: Path, content: str, **kwargs: Any) -> None: diff --git a/src/towncrier/build.py b/src/towncrier/build.py index df4798c2..29c7140a 100644 --- a/src/towncrier/build.py +++ b/src/towncrier/build.py @@ -25,7 +25,6 @@ from ._settings import ConfigError, config_option_help, load_config_from_options from ._writer import append_to_newsfile - if sys.version_info < (3, 10): import importlib_resources as resources else: diff --git a/src/towncrier/click_default_group.py b/src/towncrier/click_default_group.py index a50cce0d..7d0528b3 100644 --- a/src/towncrier/click_default_group.py +++ b/src/towncrier/click_default_group.py @@ -52,11 +52,11 @@ def bar(): bar """ + import warnings import click - __all__ = ["DefaultGroup"] __version__ = "1.2.2" diff --git a/src/towncrier/create.py b/src/towncrier/create.py index e78fb658..cfbe7d3a 100644 --- a/src/towncrier/create.py +++ b/src/towncrier/create.py @@ -17,7 +17,6 @@ from ._builder import FragmentsPath from ._settings import config_option_help, load_config_from_options - DEFAULT_CONTENT = "Add your info here" diff --git a/src/towncrier/test/test_build.py b/src/towncrier/test/test_build.py index 7ff1ecab..b364fc3e 100644 --- a/src/towncrier/test/test_build.py +++ b/src/towncrier/test/test_build.py @@ -62,8 +62,7 @@ def _test_command(self, command, runner): self.assertEqual(0, result.exit_code, result.output) self.assertEqual( result.output, - dedent( - """\ + dedent("""\ Loading template... Finding news fragments... Rendering news fragments... @@ -89,8 +88,7 @@ def _test_command(self, command, runner): - """ - ), + """), ) def test_command(self): @@ -164,12 +162,10 @@ def test_in_different_dir_config_option(self, runner): self.assertEqual(0, result.exit_code) self.assertTrue((project_dir / "NEWS.rst").exists()) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] directory = "changelog.d" - """ - ) + """) def test_in_different_dir_with_nondefault_newsfragments_directory(self, runner): """ Using the `--dir` CLI argument, the NEWS file can @@ -253,43 +249,27 @@ def test_section_and_type_sorting(self): def run_order_scenario(sections, types): with runner.isolated_filesystem(): with open("pyproject.toml", "w") as f: - f.write( - dedent( - """ + f.write(dedent(""" [tool.towncrier] package = "foo" directory = "news" - """ - ) - ) + """)) for section in sections: - f.write( - dedent( - """ + f.write(dedent(""" [[tool.towncrier.section]] path = "{section}" name = "{section}" - """.format( - section=section - ) - ) - ) + """.format(section=section))) for type_ in types: - f.write( - dedent( - """ + f.write(dedent(""" [[tool.towncrier.type]] directory = "{type_}" name = "{type_}" showcontent = true - """.format( - type_=type_ - ) - ) - ) + """.format(type_=type_))) os.mkdir("foo") with open("foo/__init__.py", "w") as f: @@ -565,8 +545,7 @@ def test_projectless_changelog(self, runner): self.assertEqual(0, result.exit_code) self.assertEqual( result.output, - dedent( - """ + dedent(""" Loading template... Finding news fragments... Rendering news fragments... @@ -584,16 +563,13 @@ def test_projectless_changelog(self, runner): - """ - ).lstrip(), + """).lstrip(), ) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] version = "7.8.9" - """ - ) + """) def test_version_in_config(self, runner): """Calling towncrier with version defined in configfile. @@ -609,8 +585,7 @@ def test_version_in_config(self, runner): self.assertEqual(0, result.exit_code, result.output) self.assertEqual( result.output, - dedent( - """ + dedent(""" Loading template... Finding news fragments... Rendering news fragments... @@ -627,16 +602,13 @@ def test_version_in_config(self, runner): - """ - ).lstrip(), + """).lstrip(), ) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] name = "ImGoProject" - """ - ) + """) def test_project_name_in_config(self, runner): """The calling towncrier with project name defined in configfile. @@ -654,8 +626,7 @@ def test_project_name_in_config(self, runner): self.assertEqual(0, result.exit_code, result.output) self.assertEqual( result.output, - dedent( - """ + dedent(""" Loading template... Finding news fragments... Rendering news fragments... @@ -672,8 +643,7 @@ def test_project_name_in_config(self, runner): - """ - ).lstrip(), + """).lstrip(), ) @with_project(config="[tool.towncrier]") @@ -697,8 +667,7 @@ def test_no_package_changelog(self, runner): self.assertEqual(0, result.exit_code, result.output) self.assertEqual( result.output, - dedent( - """ + dedent(""" Loading template... Finding news fragments... Rendering news fragments... @@ -715,17 +684,14 @@ def test_no_package_changelog(self, runner): - """ - ).lstrip(), + """).lstrip(), ) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] single_file=false filename="{version}-notes.rst" - """ - ) + """) def test_release_notes_in_separate_files(self, runner): """ When `single_file = false` the release notes for each version are stored @@ -774,8 +740,7 @@ def do_build_once_with(version, fragment_file, fragment): self.assertEqual( outputs[0], - dedent( - """ + dedent(""" foo 7.8.9 (01-01-2001) ====================== @@ -783,13 +748,11 @@ def do_build_once_with(version, fragment_file, fragment): -------- - Adds levitation (#123) - """ - ).lstrip(), + """).lstrip(), ) self.assertEqual( outputs[1], - dedent( - """ + dedent(""" foo 7.9.0 (01-01-2001) ====================== @@ -797,16 +760,13 @@ def do_build_once_with(version, fragment_file, fragment): -------- - Adds catapult (#456) - """ - ).lstrip(), + """).lstrip(), ) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] singlefile="fail!" - """ - ) + """) def test_singlefile_errors_and_explains_cleanly(self, runner): """ Failure to find the configuration file results in a clean explanation @@ -883,8 +843,7 @@ def do_build_once_with(version, fragment_file, fragment): self.assertEqual( output, - dedent( - """ + dedent(""" foo 7.9.0 (01-01-2001) ====================== @@ -901,17 +860,14 @@ def do_build_once_with(version, fragment_file, fragment): -------- - Adds levitation (#123) - """ - ).lstrip(), + """).lstrip(), ) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] template="towncrier:single-file-no-bullets" all_bullets=false - """ - ) + """) def test_bullet_points_false(self, runner): """ When all_bullets is false, subsequent lines are not indented. @@ -947,8 +903,7 @@ def test_bullet_points_false(self, runner): self.assertEqual( output, - dedent( - """ + dedent(""" foo 7.8.9 (01-01-2001) ====================== @@ -981,17 +936,14 @@ def test_bullet_points_false(self, runner): - Hyphen based bullet list. (#125) - """ - ).lstrip(), + """).lstrip(), ) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] package = "foo" title_format = "[{project_date}] CUSTOM RELEASE for {name} version {version}" - """ - ) + """) def test_title_format_custom(self, runner): """ A non-empty title format adds the specified title. @@ -1015,8 +967,7 @@ def test_title_format_custom(self, runner): ], ) - expected_output = dedent( - """\ + expected_output = dedent("""\ Loading template... Finding news fragments... Rendering news fragments... @@ -1034,20 +985,17 @@ def test_title_format_custom(self, runner): - """ - ) + """) self.assertEqual(0, result.exit_code) self.assertEqual(expected_output, result.output) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] package = "foo" filename = "NEWS.md" title_format = "[{project_date}] CUSTOM RELEASE for {name} version {version}" - """ - ) + """) def test_title_format_custom_markdown(self, runner): """ A non-empty title format adds the specified title, and if the target filename is @@ -1076,8 +1024,7 @@ def test_title_format_custom_markdown(self, runner): ], ) - expected_output = dedent( - """\ + expected_output = dedent("""\ Loading template... Finding news fragments... Rendering news fragments... @@ -1092,20 +1039,17 @@ def test_title_format_custom_markdown(self, runner): - """ - ) + """) self.assertEqual(0, result.exit_code) self.assertEqual(expected_output, result.output) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] package = "foo" filename = "NEWS.md" title_format = "### [{project_date}] CUSTOM RELEASE for {name} version {version}" - """ - ) + """) def test_markdown_injected_after_header(self, runner): """ Test that we can inject markdown after some fixed header @@ -1145,8 +1089,7 @@ def test_markdown_injected_after_header(self, runner): self.assertEqual(0, result.exit_code, result.output) output = read("NEWS.md") - expected_output = dedent( - """ + expected_output = dedent(""" # Top title ## Section title @@ -1167,28 +1110,23 @@ def test_markdown_injected_after_header(self, runner): a footer! - """ - ) + """) self.assertEqual(expected_output, output) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] package = "foo" title_format = false template = "template.rst" - """ - ) + """) def test_title_format_false(self, runner): """ Setting the title format to false disables the explicit title. This would be used, for example, when the template creates the title itself. """ 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 %} @@ -1201,9 +1139,7 @@ def test_title_format_false(self, runner): {% endfor %} {% endfor %} {% endfor %} - """ - ) - ) + """)) result = runner.invoke( _main, @@ -1219,8 +1155,7 @@ def test_title_format_false(self, runner): catch_exceptions=False, ) - expected_output = dedent( - """\ + expected_output = dedent("""\ Loading template... Finding news fragments... Rendering news fragments... @@ -1230,18 +1165,15 @@ def test_title_format_false(self, runner): Here's a hardcoded title added by the template ============================================== - """ - ) + """) self.assertEqual(0, result.exit_code) self.assertEqual(expected_output, result.output) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] start_string="Release notes start marker" - """ - ) + """) def test_start_string(self, runner): """ The `start_string` configuration is used to detect the starting point @@ -1271,8 +1203,7 @@ def test_start_string(self, runner): self.assertTrue(os.path.exists("NEWS.rst"), os.listdir(".")) output = read("NEWS.rst") - expected_output = dedent( - """\ + expected_output = dedent("""\ a line another @@ -1288,8 +1219,7 @@ def test_start_string(self, runner): a footer! - """ - ) + """) self.assertEqual(expected_output, output) @@ -1319,8 +1249,7 @@ def test_default_start_string(self, runner): self.assertEqual(0, result.exit_code, result.output) output = read("NEWS.rst") - expected_output = dedent( - """ + expected_output = dedent(""" a line another @@ -1337,18 +1266,15 @@ def test_default_start_string(self, runner): a footer! - """ - ) + """) self.assertEqual(expected_output, output) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] package = "foo" filename = "NEWS.md" - """ - ) + """) def test_default_start_string_markdown(self, runner): """ The default start string is ```` for @@ -1375,8 +1301,7 @@ def test_default_start_string_markdown(self, runner): self.assertEqual(0, result.exit_code, result.output) output = read("NEWS.md") - expected_output = dedent( - """ + expected_output = dedent(""" a line another @@ -1391,20 +1316,17 @@ def test_default_start_string_markdown(self, runner): a footer! - """ - ) + """) self.assertEqual(expected_output, output) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] name = "" directory = "changes" filename = "NEWS.md" version = "1.2.3" - """ - ) + """) def test_markdown_no_name_title(self, runner): """ When configured with an empty `name` option, @@ -1429,8 +1351,7 @@ def test_markdown_no_name_title(self, runner): self.assertEqual(0, result.exit_code, result.output) output = read("NEWS.md") - expected_output = dedent( - """ + expected_output = dedent(""" A line @@ -1440,13 +1361,11 @@ def test_markdown_no_name_title(self, runner): ## Features - Adds levitation (#123) - """ - ) + """) self.assertEqual(expected_output, output) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] title_format = "{version} - {project_date}" template = "template.rst" @@ -1455,8 +1374,7 @@ def test_markdown_no_name_title(self, runner): directory = "feature" name = "" showcontent = true - """ - ) + """) def test_with_topline_and_template_and_draft(self, runner): """ Spacing is proper when drafting with a topline and a template. @@ -1465,9 +1383,7 @@ def test_with_topline_and_template_and_draft(self, runner): 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] %} @@ -1478,9 +1394,7 @@ def test_with_topline_and_template_and_draft(self, runner): {% endfor %} {% endfor %} {% endfor %} - """ - ) - ) + """)) result = runner.invoke( _main, @@ -1492,8 +1406,7 @@ def test_with_topline_and_template_and_draft(self, runner): ], ) - expected_output = dedent( - """\ + expected_output = dedent("""\ Loading template... Finding news fragments... Rendering news fragments... @@ -1506,17 +1419,14 @@ def test_with_topline_and_template_and_draft(self, runner): - Adds levitation - """ - ) + """) self.assertEqual(0, result.exit_code, result.output) self.assertEqual(expected_output, result.output) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] - """ - ) + """) def test_orphans_in_non_showcontent(self, runner): """ When ``showcontent`` is false (like in the ``misc`` category by default), @@ -1541,8 +1451,7 @@ def test_orphans_in_non_showcontent(self, runner): ], ) - expected_output = dedent( - """\ + expected_output = dedent("""\ Loading template... Finding news fragments... Rendering news fragments... @@ -1561,18 +1470,15 @@ def test_orphans_in_non_showcontent(self, runner): - """ - ) + """) self.assertEqual(0, result.exit_code, result.output) self.assertEqual(expected_output, result.output) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] filename = "CHANGES.md" - """ - ) + """) def test_orphans_in_non_showcontent_markdown(self, runner): """ When ``showcontent`` is false (like in the ``misc`` category by default), @@ -1597,8 +1503,7 @@ def test_orphans_in_non_showcontent_markdown(self, runner): ], ) - expected_output = dedent( - """\ + expected_output = dedent("""\ Loading template... Finding news fragments... Rendering news fragments... @@ -1615,8 +1520,7 @@ def test_orphans_in_non_showcontent_markdown(self, runner): - """ - ) + """) self.assertEqual(0, result.exit_code, result.output) self.assertEqual(expected_output, result.output) @@ -1657,8 +1561,7 @@ def test_uncommitted_files(self, runner, commit): news_contents = open(path).read() self.assertEqual( news_contents, - dedent( - """\ + dedent("""\ Foo 1.2.3 (01-01-2001) ====================== @@ -1669,17 +1572,14 @@ def test_uncommitted_files(self, runner, commit): - Extends levitation. File modified in Git. Extended for an hour. (#124) - Baz levitation. Staged file. (#125) - Fix (literal) crash. File unknown to Git. (#126) - """ - ), + """), ) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] package = "foo" ignore = ["template.jinja", "CAPYBARAS.md", "seq_wildcard_[ab]"] - """ - ) + """) def test_ignored_files(self, runner): """ When `ignore` is set in config, files with those names are ignored. @@ -1699,13 +1599,11 @@ def test_ignored_files(self, runner): result = runner.invoke(_main, ["--draft"]) self.assertEqual(0, result.exit_code, result.output) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] package = "foo" ignore = [] - """ - ) + """) def test_invalid_fragment_name(self, runner): """ When `ignore` is set in config, invalid filenames cause failure. @@ -1719,14 +1617,12 @@ def test_invalid_fragment_name(self, runner): self.assertEqual(1, result.exit_code, result.output) self.assertIn("Invalid news fragment name: feature.124", result.output) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] package = "foo" template = "foo/newsfragments/template.j2" ignore = ["placeholder-to-trigger-strict-checks.txt"] - """ - ) + """) def test_ignore_template_filename(self, runner): """ The `template` filename is automatically ignored when it @@ -1736,8 +1632,7 @@ def test_ignore_template_filename(self, runner): f.write("Brand new thing.") with open("foo/newsfragments/template.j2", "w") as f: # Just a simple template to check that the file is rendered. - f.write( - """ + f.write(""" {% for section, _ in sections.items() %} {% for category, val in definitions.items() if category in sections[section]%} {{ definitions[category]['name'] }} @@ -1748,8 +1643,7 @@ def test_ignore_template_filename(self, runner): {% endfor %} {% endfor %} -""" - ) +""") result = runner.invoke(_main, ["--draft"]) self.assertEqual(0, result.exit_code, result.output) @@ -1771,8 +1665,7 @@ def test_no_ignore_configured(self, runner): ) self.assertEqual(0, result.exit_code, result.output) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] package = "foo" title_format = "{version} - {project_date}" @@ -1781,8 +1674,7 @@ def test_no_ignore_configured(self, runner): directory = "feature" name = "Feature" # showcontent is not defined in TOML - """ - ) + """) def test_showcontent_default_toml_array(self, runner): """ When configuring custom fragment types with a TOML array @@ -1793,8 +1685,7 @@ def test_showcontent_default_toml_array(self, runner): _main, ["--date", "01-01-2001", "--version", "1.0.0", "--yes"] ) news = read("NEWS.rst") - expected = textwrap.dedent( - """\ + expected = textwrap.dedent("""\ 1.0.0 - 01-01-2001 ================== @@ -1802,13 +1693,11 @@ def test_showcontent_default_toml_array(self, runner): ------- - An exciting new feature! - """ - ) + """) self.assertEqual(0, result.exit_code, result.output) self.assertEqual(expected, news, news) - @with_project( - config=""" + @with_project(config=""" [tool.towncrier] package = "foo" title_format = "{version} - {project_date}" @@ -1821,8 +1710,7 @@ def test_showcontent_default_toml_array(self, runner): [[tool.towncrier.type]] directory = "deps" name = "Dependency" - """ - ) + """) def test_directory_default_toml_array(self, runner): """ When configuring custom fragment types with a TOML array @@ -1835,8 +1723,7 @@ def test_directory_default_toml_array(self, runner): _main, ["--date", "01-01-2001", "--version", "1.0.0", "--yes"] ) news = read("NEWS.rst") - expected = textwrap.dedent( - """\ + expected = textwrap.dedent("""\ 1.0.0 - 01-01-2001 ================== @@ -1850,7 +1737,6 @@ def test_directory_default_toml_array(self, runner): ---------- - We bumped our dependencies. - """ - ) + """) self.assertEqual(0, result.exit_code, result.output) self.assertEqual(expected, news, news) diff --git a/src/towncrier/test/test_builder.py b/src/towncrier/test/test_builder.py index 31108fdf..10334b47 100644 --- a/src/towncrier/test/test_builder.py +++ b/src/towncrier/test/test_builder.py @@ -148,8 +148,7 @@ class TestNewsFragmentsOrdering(TestCase): fragments within a section. """ - template = dedent( - """ + template = dedent(""" {% for section_name, category in sections.items() %} {% if section_name %}# {{ section_name }}{% endif %} {%- for category_name, issues in category.items() %} @@ -160,8 +159,7 @@ class TestNewsFragmentsOrdering(TestCase): {% endfor %} {% endfor -%} {% endfor -%} - """ - ) + """) def render(self, fragments): return render_fragments( @@ -198,13 +196,11 @@ def test_ordering(self): ) # "Eggs" are first because they have an issue with no number, and the first # issue for each fragment is what is used for sorting the overall list. - assert output == dedent( - """ + assert output == dedent(""" ## feature - Added Eggs (random, gh-2) - Added Milk (gh-1) - Added Cheese (gh-3, gh-25, #4, #10) - Added Bread - Added Fish -""" - ) +""") diff --git a/src/towncrier/test/test_create.py b/src/towncrier/test/test_create.py index dc6f6b9d..6ae72057 100644 --- a/src/towncrier/test/test_create.py +++ b/src/towncrier/test/test_create.py @@ -98,13 +98,11 @@ def test_edit_markdown_extension(self): mock_edit.return_value = "This is line 1" self._test_success( content=["This is line 1"], - config=dedent( - """\ + config=dedent("""\ [tool.towncrier] package = "foo" filename = "README.md" - """ - ), + """), additional_args=["--edit"], ) mock_edit.assert_called_once_with( @@ -123,13 +121,11 @@ def test_edit_unknown_extension(self): mock_edit.return_value = "This is line 1" self._test_success( content=["This is line 1"], - config=dedent( - """\ + config=dedent("""\ [tool.towncrier] package = "foo" filename = "README.FIRST" - """ - ), + """), additional_args=["--edit"], ) mock_edit.assert_called_once_with( @@ -153,13 +149,11 @@ def test_content_without_eof_newline(self): argument. The text editor is not invoked, and no eof newline is added if the config option is set. """ - config = dedent( - """\ + config = dedent("""\ [tool.towncrier] package = "foo" create_eof_newline = false - """ - ) + """) content_line = "This is a content" self._test_success( content=[content_line], @@ -190,12 +184,10 @@ def test_message_and_edit(self): def test_different_directory(self): """Ensure non-standard directories are used.""" runner = CliRunner() - config = dedent( - """\ + config = dedent("""\ [tool.towncrier] directory = "releasenotes" - """ - ) + """) with runner.isolated_filesystem(): setup_simple_project(config=config, mkdir_newsfragments=False) @@ -374,11 +366,9 @@ def test_without_filename_orphan(self, runner: CliRunner): mock_edit.assert_called_once() expected = os.path.join(os.getcwd(), "foo", "newsfragments", "+") self.assertTrue( - result.output.startswith( - f"""Issue number (`+` if none): + + result.output.startswith(f"""Issue number (`+` if none): + Fragment type (feature, bugfix, doc, removal, misc): feature -Created news fragment at {expected}""" - ), +Created news fragment at {expected}"""), result.output, ) # Check that the file was created with a random name @@ -424,16 +414,14 @@ def test_sections(self, runner: CliRunner): The default section is either the section with a blank path, or else the first section defined in the configuration file. """ - setup_simple_project( - extra_config=""" + setup_simple_project(extra_config=""" [[tool.towncrier.section]] name = "Backend" path = "backend" [[tool.towncrier.section]] name = "Frontend" path = "" -""" - ) +""") result = runner.invoke(_main, ["123.feature.rst"]) self.assertFalse(result.exception, result.output) frag_path = Path("foo", "newsfragments") @@ -459,8 +447,7 @@ def test_sections_without_filename(self, runner: CliRunner): When multiple sections exist when the interactive prompt is used, the user is prompted to select a section. """ - setup_simple_project( - extra_config=""" + setup_simple_project(extra_config=""" [[tool.towncrier.section]] name = "Backend" path = "" @@ -468,8 +455,7 @@ def test_sections_without_filename(self, runner: CliRunner): [[tool.towncrier.section]] name = "Frontend" path = "frontend" -""" - ) +""") with mock.patch("click.edit") as mock_edit: mock_edit.return_value = "Edited content" result = runner.invoke(_main, input="2\n123\nfeature\n") @@ -498,8 +484,7 @@ def test_sections_without_filename_with_section_option(self, runner: CliRunner): When multiple sections exist and the section is provided via the command line, the user isn't prompted to select a section. """ - setup_simple_project( - extra_config=""" + setup_simple_project(extra_config=""" [[tool.towncrier.section]] name = "Backend" path = "" @@ -507,8 +492,7 @@ def test_sections_without_filename_with_section_option(self, runner: CliRunner): [[tool.towncrier.section]] name = "Frontend" path = "frontend" -""" - ) +""") with mock.patch("click.edit") as mock_edit: mock_edit.return_value = "Edited content" result = runner.invoke( @@ -534,8 +518,7 @@ def test_sections_all_with_paths(self, runner: CliRunner): """ When all sections have paths, the first is the default. """ - setup_simple_project( - extra_config=""" + setup_simple_project(extra_config=""" [[tool.towncrier.section]] name = "Frontend" path = "frontend" @@ -543,8 +526,7 @@ def test_sections_all_with_paths(self, runner: CliRunner): [[tool.towncrier.section]] name = "Backend" path = "backend" -""" - ) +""") result = runner.invoke(_main, ["123.feature.rst"]) self.assertFalse(result.exception, result.output) frag_path = Path("foo", "frontend", "newsfragments") diff --git a/src/towncrier/test/test_hg.py b/src/towncrier/test/test_hg.py index d1b95fdf..1c72c405 100644 --- a/src/towncrier/test/test_hg.py +++ b/src/towncrier/test/test_hg.py @@ -15,7 +15,6 @@ from .helpers import setup_simple_project, write - hg_available = shutil.which("hg") is not None diff --git a/src/towncrier/test/test_project.py b/src/towncrier/test/test_project.py index a93ef190..5b1c6a9e 100644 --- a/src/towncrier/test/test_project.py +++ b/src/towncrier/test/test_project.py @@ -13,7 +13,6 @@ from .._shell import cli as towncrier_cli from .helpers import write - towncrier_cli.name = "towncrier" @@ -53,8 +52,7 @@ def test_incremental(self): os.makedirs(os.path.join(temp, "mytestprojinc")) with open(os.path.join(temp, "mytestprojinc", "__init__.py"), "w") as f: - f.write( - """ + f.write(""" class Version: ''' This is emulating a Version object from incremental. @@ -68,8 +66,7 @@ def base(self): return '.'.join(map(str, self.version)) __version__ = Version(1, 3, 12, "rc1") - """ - ) + """) version = get_version(temp, "mytestprojinc") self.assertEqual(version, "1.3.12rc1") @@ -88,16 +85,14 @@ def test_not_incremental(self): os.makedirs(os.path.join(temp, "mytestprojnotinc")) with open(os.path.join(temp, "mytestprojnotinc", "__init__.py"), "w") as f: - f.write( - """ + f.write(""" class WeirdVersion: def base(self, some_arg): return "shouldn't get here" __version__ = WeirdVersion() -""" - ) +""") with self.assertRaises(Exception) as e: get_version(temp, "mytestprojnotinc") diff --git a/src/towncrier/test/test_settings.py b/src/towncrier/test/test_settings.py index f46db2b2..1532aa58 100644 --- a/src/towncrier/test/test_settings.py +++ b/src/towncrier/test/test_settings.py @@ -43,13 +43,11 @@ def test_base(self): """ Test a "base config". """ - project_dir = self.mktemp_project( - pyproject_toml=""" + project_dir = self.mktemp_project(pyproject_toml=""" [tool.towncrier] package = "foobar" orphan_prefix = "~" - """ - ) + """) config = load_config(project_dir) self.assertEqual(config.package, "foobar") @@ -63,13 +61,11 @@ def test_markdown(self): If the filename references an .md file and the builtin template doesn't have an extension, add .md rather than .rst. """ - project_dir = self.mktemp_project( - pyproject_toml=""" + project_dir = self.mktemp_project(pyproject_toml=""" [tool.towncrier] package = "foobar" filename = "NEWS.md" - """ - ) + """) config = load_config(project_dir) @@ -82,14 +78,12 @@ def test_explicit_template_extension(self): If the filename references an .md file and the builtin template has an extension, don't change it. """ - project_dir = self.mktemp_project( - pyproject_toml=""" + project_dir = self.mktemp_project(pyproject_toml=""" [tool.towncrier] package = "foobar" filename = "NEWS.md" template = "towncrier:default.rst" - """ - ) + """) config = load_config(project_dir) @@ -102,13 +96,11 @@ def test_template_extended(self): resource's 'templates' package, it could also be in the specified resource directly. """ - project_dir = self.mktemp_project( - pyproject_toml=""" + project_dir = self.mktemp_project(pyproject_toml=""" [tool.towncrier] package = "foobar" template = "towncrier.templates:default.rst" - """ - ) + """) config = load_config(project_dir) @@ -118,12 +110,10 @@ def test_incorrect_single_file(self): """ single_file must be a bool. """ - project_dir = self.mktemp_project( - pyproject_toml=""" + project_dir = self.mktemp_project(pyproject_toml=""" [tool.towncrier] single_file = "a" - """ - ) + """) with self.assertRaises(ConfigError) as e: load_config(project_dir) @@ -134,12 +124,10 @@ def test_incorrect_all_bullets(self): """ all_bullets must be a bool. """ - project_dir = self.mktemp_project( - pyproject_toml=""" + project_dir = self.mktemp_project(pyproject_toml=""" [tool.towncrier] all_bullets = "a" - """ - ) + """) with self.assertRaises(ConfigError) as e: load_config(project_dir) @@ -150,12 +138,10 @@ def test_mistype_singlefile(self): """ singlefile is not accepted, single_file is. """ - project_dir = self.mktemp_project( - pyproject_toml=""" + project_dir = self.mktemp_project(pyproject_toml=""" [tool.towncrier] singlefile = "a" - """ - ) + """) with self.assertRaises(ConfigError) as e: load_config(project_dir) @@ -211,18 +197,14 @@ def test_pyproject_assert_fallback(self): This both tests when things are *only* in the pyproject.toml and default usage of the data in the towncrier.toml file. """ - pyproject_toml = dedent( - """ + pyproject_toml = dedent(""" [project] name = "foo" [tool.towncrier] - """ - ) - towncrier_toml = dedent( - """ + """) + towncrier_toml = dedent(""" [tool.towncrier] - """ - ) + """) tests = [ "", "name = '{name}'", @@ -303,12 +285,10 @@ def test_missing_template(self): """ Towncrier will raise an exception saying when it can't find a template. """ - project_dir = self.mktemp_project( - towncrier_toml=""" + project_dir = self.mktemp_project(towncrier_toml=""" [tool.towncrier] template = "foo.rst" - """ - ) + """) with self.assertRaises(ConfigError) as e: load_config(project_dir) @@ -325,12 +305,10 @@ def test_missing_template_in_towncrier(self): Towncrier will raise an exception saying when it can't find a template from the Towncrier templates. """ - project_dir = self.mktemp_project( - towncrier_toml=""" + project_dir = self.mktemp_project(towncrier_toml=""" [tool.towncrier] template = "towncrier:foo" - """ - ) + """) with self.assertRaises(ConfigError) as e: load_config(project_dir) @@ -348,8 +326,7 @@ def test_custom_types_as_tables_array_deprecated(self): This functionality is considered deprecated, but we continue to support it to keep backward compatibility. """ - project_dir = self.mktemp_project( - pyproject_toml=""" + project_dir = self.mktemp_project(pyproject_toml=""" [tool.towncrier] package = "foobar" [[tool.towncrier.type]] @@ -367,8 +344,7 @@ def test_custom_types_as_tables_array_deprecated(self): name="Automatic" showcontent=true check=false - """ - ) + """) config = load_config(project_dir) expected = [ ( @@ -405,8 +381,7 @@ def test_custom_types_as_tables(self): Custom fragment categories can be defined inside the toml config file using tables. """ - project_dir = self.mktemp_project( - pyproject_toml=""" + project_dir = self.mktemp_project(pyproject_toml=""" [tool.towncrier] package = "foobar" [tool.towncrier.fragment.feat] @@ -418,8 +393,7 @@ def test_custom_types_as_tables(self): [tool.towncrier.fragment.auto] name = "Automatic" check = false - """ - ) + """) config = load_config(project_dir) expected = { "chore": { diff --git a/src/towncrier/test/test_write.py b/src/towncrier/test/test_write.py index 563fde6f..a3a72ba2 100644 --- a/src/towncrier/test/test_write.py +++ b/src/towncrier/test/test_write.py @@ -247,12 +247,10 @@ 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) @@ -285,15 +283,11 @@ def do_build_once(): # `single_file` default as true with runner.isolated_filesystem(): with open("pyproject.toml", "w") as f: - f.write( - dedent( - """ + f.write(dedent(""" [tool.towncrier] title_format="{name} {version} ({project_date})" filename="{version}-notes.rst" - """ - ).lstrip() - ) + """).lstrip()) with open("{version}-notes.rst", "w") as f: f.write("Release Notes\n\n.. towncrier release notes start\n") os.mkdir("newsfragments") @@ -336,16 +330,12 @@ def do_build_once(): # single_file = false with runner.isolated_filesystem(): with open("pyproject.toml", "w") as f: - f.write( - dedent( - """ + f.write(dedent(""" [tool.towncrier] single_file=false title_format="{name} {version} ({project_date})" filename="{version}-notes.rst" - """ - ).lstrip() - ) + """).lstrip()) os.mkdir("newsfragments") result = do_build_once() @@ -361,8 +351,7 @@ def do_build_once(): with open(notes[0]) as f: output = f.read() - expected_output = dedent( - """\ + expected_output = dedent("""\ foo 7.8.9 (01-01-2001) ====================== @@ -370,7 +359,6 @@ def do_build_once(): -------- - Adds levitation (#123) - """ - ) + """) self.assertEqual(expected_output, output)