Browse Source

Add black & isort to pre-commit

Use the default 88 columns from Black while allowing for 99 columns for longer (doc)strings.
pull/382/head
Hynek Schlawack 4 months ago
parent
commit
9a58911ea7
  1. 15
      .pre-commit-config.yaml
  2. 2
      admin/canonicalize_version.py
  3. 1
      admin/check_tag_version_match.py
  4. 5
      bin/towncrier
  5. 61
      docs/conf.py
  6. 5
      pyproject.toml
  7. 4
      setup.py
  8. 1
      src/towncrier/__init__.py
  9. 1
      src/towncrier/__main__.py
  10. 8
      src/towncrier/_builder.py
  11. 3
      src/towncrier/_git.py
  12. 6
      src/towncrier/_project.py
  13. 1
      src/towncrier/_settings/__init__.py
  14. 9
      src/towncrier/_settings/fragment_types.py
  15. 13
      src/towncrier/_settings/load.py
  16. 3
      src/towncrier/_shell.py
  17. 1
      src/towncrier/_version.py
  18. 31
      src/towncrier/build.py
  19. 10
      src/towncrier/check.py
  20. 13
      src/towncrier/create.py
  21. 106
      src/towncrier/test/test_build.py
  22. 4
      src/towncrier/test/test_builder.py
  23. 35
      src/towncrier/test/test_check.py
  24. 13
      src/towncrier/test/test_create.py
  25. 4
      src/towncrier/test/test_format.py
  26. 5
      src/towncrier/test/test_project.py
  27. 53
      src/towncrier/test/test_settings.py
  28. 19
      src/towncrier/test/test_write.py
  29. 1
      tox.ini

15
.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

2
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(

1
admin/check_tag_version_match.py

@ -11,6 +11,7 @@ import sys
import pep517.meta
TAG_PREFIX = "refs/tags/"
if len(sys.argv) < 2:

5
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()

61
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 @@ language = None
# 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 @@ todo_include_todos = False
# 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 @@ html_theme = 'alabaster'
# 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 @@ html_static_path = ['_static']
# 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 @@ html_sidebars = {
# -- 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 @@ latex_elements = {
# 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 @@ latex_elements = {
# (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 @@ latex_documents = [
# 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 @@ man_pages = [
# (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",
),
]

5
pyproject.toml

@ -54,6 +54,11 @@ exclude = '''
)
'''
[tool.isort]
profile = "attrs"
[build-system]
requires = [
"setuptools ~= 44.1.1",

4
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",

1
src/towncrier/__init__.py

@ -7,4 +7,5 @@ towncrier, a builder for your news files.
from ._version import __version__
__all__ = ["__version__"]

1
src/towncrier/__main__.py

@ -1,3 +1,4 @@
from towncrier._shell import cli
cli()

8
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)

3
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

6
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."
)

1
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

9
src/towncrier/_settings/fragment_types.py

@ -25,7 +25,7 @@ class BaseFragmentTypesLoader:
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)

13
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)

3
src/towncrier/_shell.py

@ -6,12 +6,13 @@ towncrier, a builder for your news files.
"""
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)

1
src/towncrier/_version.py

@ -7,5 +7,6 @@ Provides towncrier version information.
from incremental import Version
__version__ = Version("towncrier", 21, 9, 1, dev=0)
__all__ = ["__version__"]

31
src/towncrier/build.py

@ -7,16 +7,17 @@ Build a combined news file from news fragments.
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

10
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 = {

13
src/towncrier/create.py

@ -7,6 +7,7 @@ Create a new fragment.
import os
import click
from ._settings import load_config_from_options
@ -22,10 +23,11 @@ from ._settings import load_config_from_options
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

106
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 @@ class TestCli(TestCase):
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 @@ class TestCli(TestCase):
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 @@ class TestCli(TestCase):
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 @@ Deprecations and Removals
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 @@ Deprecations and Removals
],
)
expected_output = dedent("""\
expected_output = dedent(
"""\
Loading template...
Finding news fragments...
Rendering news fragments...
@ -761,7 +754,8 @@ Deprecations and Removals
- Adds levitation (#123)
- Extends levitation (#124)
""")
"""
)
self.assertEqual(0, result.exit_code)
self.assertEqual(expected_output, result.output)
@ -775,16 +769,22 @@ Deprecations and Removals
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 @@ Deprecations and Removals
{% endfor %}
{% endfor %}
{% endfor %}
"""))
"""
)
)
result = runner.invoke(
_main,
@ -812,7 +814,8 @@ Deprecations and Removals
],
)
expected_output = dedent("""\
expected_output = dedent(
"""\
Loading template...
Finding news fragments...
Rendering news fragments...
@ -822,7 +825,8 @@ Deprecations and Removals
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 @@ Deprecations and Removals
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 @@ Deprecations and Removals
with open("NEWS.rst") as f:
output = f.read()
expected_output = dedent("""\
expected_output = dedent(
"""\
a line
another
@ -880,7 +889,8 @@ Deprecations and Removals
- Adds levitation (#123)
""")
"""
)
self.assertEqual(expected_output, output)
@ -892,7 +902,9 @@ Deprecations and Removals
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 @@ Deprecations and Removals
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 @@ Deprecations and Removals
{% endfor %}
{% endfor %}
{% endfor %}
"""))
"""
)
)
result = runner.invoke(
_main,
@ -929,7 +947,8 @@ Deprecations and Removals
],
)
expected_output = dedent("""\
expected_output = dedent(
"""\
Loading template...
Finding news fragments...
Rendering news fragments...
@ -941,7 +960,8 @@ Deprecations and Removals
- Adds levitation
""")
"""
)
self.assertEqual(0, result.exit_code, result.output)
self.assertEqual(expected_output, result.output)

4
src/towncrier/test/test_builder.py

@ -73,11 +73,11 @@ class TestParseNewsfragmentBasename(TestCase):
"""
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),
)

35
src/towncrier/test/test_check.py

@ -5,9 +5,10 @@ import os
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 @@ class TestChecker(TestCase):
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 @@ class TestChecker(TestCase):
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 @@ class TestChecker(TestCase):
# 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 @@ class TestChecker(TestCase):
# 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 @@ class TestChecker(TestCase):
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"])

13
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 @@ class TestCli(TestCase):
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 @@ class TestCli(TestCase):
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)
)

4
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

5
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 @@ class InvocationTests(TestCase):
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)

53
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 @@ package = "foobar"
"""
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 @@ package = "foobar"
"""
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)

19
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 @@ Old text.
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 @@ Old text.
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)

1
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

Loading…
Cancel
Save