diff --git a/changelog_gen/cli/command.py b/changelog_gen/cli/command.py index 8c9d985..b054c08 100644 --- a/changelog_gen/cli/command.py +++ b/changelog_gen/cli/command.py @@ -319,7 +319,7 @@ def _gen( # noqa: PLR0913, C901, PLR0915 if date_fmt: version_string += f" {datetime.now(timezone.utc).strftime(date_fmt)}" - w = writer.new_writer(context, extension, dry_run=dry_run) + w = writer.new_writer(context, extension, dry_run=dry_run, change_template=cfg.change_template) w.add_version(version_string) w.consume(cfg.type_headers, changes) diff --git a/changelog_gen/config.py b/changelog_gen/config.py index 35fa2af..46db96c 100644 --- a/changelog_gen/config.py +++ b/changelog_gen/config.py @@ -90,6 +90,7 @@ class Config: version_string: str = "v{new_version}" footer_parsers: list[str] = dataclasses.field(default_factory=lambda: FOOTER_PARSERS[::]) link_parsers: list[dict[str, str]] = dataclasses.field(default_factory=list) + change_template: str | None = None # Hooks post_process: PostProcessConfig | None = None diff --git a/changelog_gen/extractor.py b/changelog_gen/extractor.py index ceeec5c..a663997 100644 --- a/changelog_gen/extractor.py +++ b/changelog_gen/extractor.py @@ -50,14 +50,6 @@ def issue_ref(self: t.Self) -> str: return footer.value return "" - @property - def authors(self: t.Self) -> str: - """Extract authors from footers.""" - for footer in self.footers: - if footer.footer == "Authors": - return footer.value - return "" - class ChangeExtractor: """Parse commit logs and generate change list.""" @@ -101,7 +93,7 @@ def extract(self: t.Self) -> list[Change]: # noqa: C901, PLR0912, PLR0915 footers = {} commit_type = m[1].lower() - scope = (m[2] or "").replace("(", "(`").replace(")", "`)") + scope = (m[2] or "").replace("(", "").replace(")", "") breaking = m[3] is not None description = m[4].strip() prm = re.search(r"\(#\d+\)$", description) diff --git a/changelog_gen/writer.py b/changelog_gen/writer.py index c49bdf4..9a92800 100644 --- a/changelog_gen/writer.py +++ b/changelog_gen/writer.py @@ -8,6 +8,8 @@ from pathlib import Path from tempfile import NamedTemporaryFile +from jinja2 import BaseLoader, Environment + from changelog_gen.util import timer if t.TYPE_CHECKING: @@ -34,6 +36,7 @@ def __init__( self: t.Self, changelog: Path, context: Context, + change_template: str | None = None, *, dry_run: bool = False, ) -> None: @@ -45,6 +48,7 @@ def __init__( self.existing = lines[self.file_header_line_count + 1 :] self.content = [] self.dry_run = dry_run + self._change_template = change_template @timer def add_version(self: t.Self, version: str) -> None: @@ -74,27 +78,15 @@ def add_section(self: t.Self, header: str, changes: list[Change]) -> None: """Add a section to changelog file.""" self._add_section_header(header) for change in sorted(changes): - description = f"{change.scope} {change.description}" if change.scope else change.description - description = f"{self.bold_string('Breaking:')} {description}" if change.breaking else description - description = f"{description} {change.authors}" if change.authors else description - - self._add_section_line( - description, - change, - ) + self._add_section_line(change) self._post_section() - @timer - def bold_string(self: t.Self, string: str) -> str: - """Render a string as bold.""" - return f"**{string.strip()}**" - @timer def _add_section_header(self: t.Self, header: str) -> None: raise NotImplementedError @timer - def _add_section_line(self: t.Self, description: str, change: Change) -> None: + def _add_section_line(self: t.Self, change: Change) -> None: raise NotImplementedError @timer @@ -132,6 +124,20 @@ class MdWriter(BaseWriter): file_header = "# Changelog\n" extension = Extension.MD + @timer + def __init__(self: t.Self, *args, **kwargs) -> None: + super().__init__(*args, **kwargs) + self._change_template = ( + self._change_template + or """ +-{% if change.scope %} (`{{change.scope}}`){% endif %} +{% if change.breaking %} **Breaking**{% endif %} + {{ change.description }} +{% for footer in change.footers %}{% if footer.footer == "Authors"%} {{footer.value}}{% endif %}{% endfor %} +{% for link in change.links %} [[{{ link.text }}]({{ link.link }})]{% endfor %} +""" + ) + @timer def _add_version(self: t.Self, version: str) -> None: self.content.extend([f"## {version}", ""]) @@ -141,11 +147,10 @@ def _add_section_header(self: t.Self, header: str) -> None: self.content.extend([f"### {header}", ""]) @timer - def _add_section_line(self: t.Self, description: str, change: Change) -> None: - line = f"- {description}" + def _add_section_line(self: t.Self, change: Change) -> None: + rtemplate = Environment(loader=BaseLoader()).from_string(self._change_template.replace("\n", "")) # noqa: S701 - for link in change.links: - line = f"{line} [[{link.text}]({link.link})]" + line = rtemplate.render(change=change) self.content.append(line) @@ -164,6 +169,16 @@ class RstWriter(BaseWriter): @timer def __init__(self: t.Self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) + self._change_template = ( + self._change_template + or """ +*{% if change.scope %} (`{{change.scope}}`){% endif %} +{% if change.breaking %} **Breaking**{% endif %} + {{ change.description }} +{% for footer in change.footers %}{% if footer.footer == "Authors"%} {{footer.value}}{% endif %}{% endfor %} +{% for link in change.links %} [`{{ link.text }}`_]{% endfor %} +""" + ) self._links = {} @timer @@ -185,15 +200,17 @@ def _add_section_header(self: t.Self, header: str) -> None: self.content.extend([header, "-" * len(header), ""]) @timer - def _add_section_line(self: t.Self, description: str, change: Change) -> None: - line = f"* {description}" + def _add_section_line(self: t.Self, change: Change) -> None: + rtemplate = Environment(loader=BaseLoader()).from_string(self._change_template.replace("\n", "")) # noqa: S701 + + line = rtemplate.render(change=change) + + self.content.extend([line, ""]) for link in change.links: line = f"{line} [`{link.text}`_]" self._links[link.text] = link.link - self.content.extend([line, ""]) - @timer def write(self: t.Self) -> str: """Write contents to destination.""" @@ -206,6 +223,7 @@ def write(self: t.Self) -> str: def new_writer( context: Context, extension: Extension, + change_template: str | None = None, *, dry_run: bool = False, ) -> BaseWriter: @@ -213,9 +231,9 @@ def new_writer( changelog = Path(f"CHANGELOG.{extension.value}") if extension == Extension.MD: - return MdWriter(changelog, context, dry_run=dry_run) + return MdWriter(changelog, context, dry_run=dry_run, change_template=change_template) if extension == Extension.RST: - return RstWriter(changelog, context, dry_run=dry_run) + return RstWriter(changelog, context, dry_run=dry_run, change_template=change_template) msg = f'Changelog extension "{extension.value}" not supported.' raise ValueError(msg) diff --git a/docs/configuration.md b/docs/configuration.md index 8519fb0..b71e3d1 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -238,6 +238,30 @@ key = "value" a_list = ["key", "key2"] ``` +### `change_template` + _**[optional]**_
+ **default**: None + + Customise how changelog entries are formatted, uses + [Jinja2](https://jinja.palletsprojects.com/en/3.1.x/) formatting. + + The template will provided with the change object and can render all + extracted information as desired. For readability the template can be split + over multiple lines, it will be flattened before it is rendered to generate a + single line entry. + + Example: + +```toml +[tool.changelog_gen] +change_template = """ +-{% if change.scope %} (`{{change.scope}}`){% endif %} +{% if change.breaking %} **Breaking**{% endif %} + {{ change.description }} +{% for footer in change.footers %}{% if footer.footer == "Authors"%} {{footer.value}}{% endif %}{% endfor %} +{% for link in change.links %} [[{{ link.text }}]({{ link.link }})]{% endfor %} +""" +``` ## Versioning diff --git a/poetry.lock b/poetry.lock index 10728fd..a12a615 100644 --- a/poetry.lock +++ b/poetry.lock @@ -340,6 +340,92 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +[[package]] +name = "jinja2" +version = "3.1.4" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, + {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "markupsafe" +version = "2.1.5" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, +] + [[package]] name = "mock" version = "5.1.0" @@ -873,4 +959,4 @@ test = ["httpx"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "28dd2fc89e8e46c5b2f6d9a9609d20fd2d521a60cf7f499aa1364bb821d72a37" +content-hash = "f04ea0b85db33001468dc6d104afc441a4ac9996a54f434484c9e51c5661ebe2" diff --git a/pyproject.toml b/pyproject.toml index 352ed7b..96e8cb4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,6 +41,7 @@ rtoml = ">=0.9" gitpython = "^3.1.43" pygments = "^2.18.0" typing_extensions = { version = "^4.7.0", python = "<3.10" } +jinja2 = "^3.1.4" [tool.poetry.extras] post-process = ["httpx"] diff --git a/tests/test_extractor.py b/tests/test_extractor.py index 6760ad0..7c7f905 100644 --- a/tests/test_extractor.py +++ b/tests/test_extractor.py @@ -148,7 +148,7 @@ def test_git_commit_extraction(conventional_commits): "Features and Improvements", "Detail about 3", breaking=True, - scope="(`docs`)", + scope="docs", short_hash=hashes[2][:7], commit_hash=hashes[2], commit_type="feat", @@ -163,7 +163,7 @@ def test_git_commit_extraction(conventional_commits): Change( "Bug fixes", "Detail about 4", - scope="(`config`)", + scope="config", short_hash=hashes[0][:7], commit_hash=hashes[0], commit_type="fix", @@ -222,7 +222,7 @@ def test_git_commit_extraction_include_all(conventional_commits): "Features and Improvements", "Detail about 3", breaking=True, - scope="(`docs`)", + scope="docs", short_hash=hashes[2][:7], commit_hash=hashes[2], commit_type="feat", @@ -240,7 +240,7 @@ def test_git_commit_extraction_include_all(conventional_commits): Change( "Bug fixes", "Detail about 4", - scope="(`config`)", + scope="config", short_hash=hashes[0][:7], commit_hash=hashes[0], commit_type="fix", @@ -302,7 +302,7 @@ def test_git_commit_extraction_handles_random_tags(conventional_commits, multive "Features and Improvements", "Detail about 3", breaking=True, - scope="(`docs`)", + scope="docs", short_hash=hashes[2][:7], commit_hash=hashes[2], commit_type="feat", @@ -313,7 +313,7 @@ def test_git_commit_extraction_handles_random_tags(conventional_commits, multive Change( "Bug fixes", "Detail about 4", - scope="(`config`)", + scope="config", short_hash=hashes[0][:7], commit_hash=hashes[0], commit_type="fix", diff --git a/tests/test_writer.py b/tests/test_writer.py index fc78308..ca48d42 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -107,7 +107,7 @@ def test_base_methods_not_implemented(self, changelog, ctx): w._add_section_header("header") with pytest.raises(NotImplementedError): - w._add_section_line("description", Change("header", "issue_ref", "description", "fix")) + w._add_section_line(Change("header", "issue_ref", "description", "fix")) with pytest.raises(NotImplementedError): w._add_version("0.0.0") @@ -136,22 +136,19 @@ def test_add_section(self, monkeypatch, changelog, ctx): "fix", footers=[Footer("Refs", ": ", "#2"), Footer("Authors", ": ", "(a, b)")], ), - Change("header", "line3", "fix", scope="(config)", footers=[Footer("Refs", ": ", "#3")]), + Change("header", "line3", "fix", scope="config", footers=[Footer("Refs", ": ", "#3")]), ], ) assert w._add_section_header.call_args == mock.call("header") assert w._add_section_line.call_args_list == [ mock.call( - "**Breaking:** line1", Change("header", "line1", "fix", breaking=True, footers=[Footer("Refs", ": ", "#1")]), ), mock.call( - "(config) line3", - Change("header", "line3", "fix", scope="(config)", footers=[Footer("Refs", ": ", "#3")]), + Change("header", "line3", "fix", scope="config", footers=[Footer("Refs", ": ", "#3")]), ), mock.call( - "line2 (a, b)", Change( "header", "line2", @@ -177,22 +174,19 @@ def test_add_section_sorting(self, monkeypatch, changelog, ctx): "fix", footers=[Footer("Refs", ": ", "#2"), Footer("Authors", ": ", "(a, b)")], ), - Change("header", "line1", "fix", scope="(config)", footers=[Footer("Refs", ": ", "#1")]), + Change("header", "line1", "fix", scope="config", footers=[Footer("Refs", ": ", "#1")]), ], ) assert w._add_section_header.call_args == mock.call("header") assert w._add_section_line.call_args_list == [ mock.call( - "**Breaking:** line3", Change("header", "line3", "fix", breaking=True, footers=[Footer("Refs", ": ", "#3")]), ), mock.call( - "(config) line1", - Change("header", "line1", "fix", scope="(config)", footers=[Footer("Refs", ": ", "#1")]), + Change("header", "line1", "fix", scope="config", footers=[Footer("Refs", ": ", "#1")]), ), mock.call( - "line2 (a, b)", Change( "header", "line2", @@ -265,23 +259,24 @@ def test_add_section_header(self, changelog_md, ctx): def test_add_section_line(self, changelog_md, ctx): w = writer.MdWriter(changelog_md, ctx) - w._add_section_line("line", Change("header", "line", "fix", footers=[Footer("Refs", ": ", "#1")])) + w._add_section_line(Change("header", "line", "fix", footers=[Footer("Refs", ": ", "#1")])) assert w.content == ["- line"] - def test_add_section_line_ignores_placeholder(self, changelog_md, ctx): + def test_add_section_line_with_metadata(self, changelog_md, ctx): w = writer.MdWriter(changelog_md, ctx) - w._add_section_line("line", Change("header", "line", "fix")) + w._add_section_line( + Change("header", "line", "fix", scope="config", breaking=True, footers=[Footer("Authors", ": ", "(a, b)")]), + ) - assert w.content == ["- line"] + assert w.content == ["- (`config`) **Breaking** line (a, b)"] def test_add_section_line_with_links(self, changelog_md): ctx = Context(Config(current_version="0.0.0")) w = writer.MdWriter(changelog_md, ctx) w._add_section_line( - "line", Change( "header", "line", @@ -300,7 +295,7 @@ def test_write_dry_run_doesnt_write_to_file(self, changelog_md, ctx): [ Change("header", "line1", "fix", footers=[Footer("Refs", ": ", "#1")]), Change("header", "line2", "fix", footers=[Footer("Refs", ": ", "#2")]), - Change("header", "line3", "fix", scope="(config)", footers=[Footer("Refs", ": ", "#3")]), + Change("header", "line3", "fix", scope="config", footers=[Footer("Refs", ": ", "#3")]), ], ) @@ -315,7 +310,7 @@ def test_write(self, changelog_md, ctx): [ Change("header", "line1", "fix", footers=[Footer("Refs", ": ", "#1")]), Change("header", "line2", "fix", footers=[Footer("Refs", ": ", "#2")]), - Change("header", "line3", "fix", scope="(config)", footers=[Footer("Refs", ": ", "#3")]), + Change("header", "line3", "fix", scope="config", footers=[Footer("Refs", ": ", "#3")]), ], ) @@ -328,7 +323,7 @@ def test_write(self, changelog_md, ctx): ### header -- (config) line3 +- (`config`) line3 - line1 - line2 """ @@ -355,7 +350,7 @@ def test_write_with_existing_content(self, changelog_md, ctx): [ Change("header", "line4", "fix", footers=[Footer("Refs", ": ", "#4")]), Change("header", "line5", "fix", footers=[Footer("Refs", ": ", "#5")]), - Change("header", "line6", "fix", scope="(config)", footers=[Footer("Refs", ": ", "#6")]), + Change("header", "line6", "fix", scope="config", footers=[Footer("Refs", ": ", "#6")]), ], ) @@ -369,7 +364,7 @@ def test_write_with_existing_content(self, changelog_md, ctx): ### header -- (config) line6 +- (`config`) line6 - line4 - line5 @@ -456,23 +451,24 @@ def test_add_section_header(self, changelog_rst, ctx): def test_add_section_line(self, changelog_rst, ctx): w = writer.RstWriter(changelog_rst, ctx) - w._add_section_line("line", Change("header", "line", "fix", footers=[Footer("Refs", ": ", "#1")])) + w._add_section_line(Change("header", "line", "fix", footers=[Footer("Refs", ": ", "#1")])) assert w.content == ["* line", ""] - def test_add_section_line_ignores_placeholder(self, changelog_rst, ctx): + def test_add_section_line_with_metadata(self, changelog_rst, ctx): w = writer.RstWriter(changelog_rst, ctx) - w._add_section_line("line", Change("header", "line", "fix")) + w._add_section_line( + Change("header", "line", "fix", scope="config", breaking=True, footers=[Footer("Authors", ": ", "(a, b)")]), + ) - assert w.content == ["* line", ""] + assert w.content == ["* (`config`) **Breaking** line (a, b)", ""] def test_add_section_line_with_links(self, changelog_rst): ctx = Context(Config(current_version="0.0.0")) w = writer.RstWriter(changelog_rst, ctx) w._add_section_line( - "line", Change( "header", "line", @@ -489,7 +485,7 @@ def test_add_section_line_without_links(self, changelog_rst): ctx = Context(Config(current_version="0.0.0")) w = writer.RstWriter(changelog_rst, ctx) - w._add_section_line("line", Change("header", "line", "fix")) + w._add_section_line(Change("header", "line", "fix")) assert w.content == ["* line", ""] assert w._links == {} @@ -505,7 +501,7 @@ def test_str_with_links(self, changelog_rst): [ Change("header", "line1", "fix", links=[Link("#1", "http://url/issues/1")]), Change("header", "line2", "fix", links=[Link("#2", "http://url/issues/2")]), - Change("header", "line3", "fix", scope="(config)", links=[Link("#3", "http://url/issues/3")]), + Change("header", "line3", "fix", scope="config", links=[Link("#3", "http://url/issues/3")]), ], ) @@ -519,7 +515,7 @@ def test_str_with_links(self, changelog_rst): header ------ -* (config) line3 [`#3`_] +* (`config`) line3 [`#3`_] * line1 [`#1`_] @@ -540,7 +536,7 @@ def test_write_dry_run_doesnt_write_to_file(self, changelog_rst, ctx): [ Change("header", "line1", "fix", footers=[Footer("Refs", ": ", "#1")]), Change("header", "line2", "fix", footers=[Footer("Refs", ": ", "#2")]), - Change("header", "line3", "fix", scope="(config)", footers=[Footer("Refs", ": ", "#3")]), + Change("header", "line3", "fix", scope="config", footers=[Footer("Refs", ": ", "#3")]), ], ) @@ -561,7 +557,7 @@ def test_write(self, changelog_rst, ctx): [ Change("header", "line1", "fix", footers=[Footer("Refs", ": ", "#1")]), Change("header", "line2", "fix", footers=[Footer("Refs", ": ", "#2")]), - Change("header", "line3", "fix", scope="(config)", footers=[Footer("Refs", ": ", "#3")]), + Change("header", "line3", "fix", scope="config", footers=[Footer("Refs", ": ", "#3")]), ], ) @@ -578,7 +574,7 @@ def test_write(self, changelog_rst, ctx): header ------ -* (config) line3 +* (`config`) line3 * line1 @@ -614,7 +610,7 @@ def test_write_with_existing_content(self, changelog_rst): [ Change("header", "line4", "fix", footers=[Footer("Refs", ": ", "#4")]), Change("header", "line5", "fix", footers=[Footer("Refs", ": ", "#5")]), - Change("header", "line6", "fix", scope="(config)", footers=[Footer("Refs", ": ", "#6")]), + Change("header", "line6", "fix", scope="config", footers=[Footer("Refs", ": ", "#6")]), ], ) @@ -632,7 +628,7 @@ def test_write_with_existing_content(self, changelog_rst): header ------ -* (config) line6 +* (`config`) line6 * line4