Add a changelog and supporting infrastructure (towncrier)
Marco Ricci

Marco Ricci commited on 2024-07-21 23:15:20
Zeige 12 geänderte Dateien mit 162 Einfügungen und 1 Löschungen.

... ...
@@ -0,0 +1 @@
1
+docs/changelog.md
0 2
\ No newline at end of file
... ...
@@ -0,0 +1 @@
1
+docs/Keep_a_changelog-E05735.svg
0 2
\ No newline at end of file
... ...
@@ -0,0 +1 @@
1
+docs/SemVer-3F4551.svg
0 2
\ No newline at end of file
... ...
@@ -0,0 +1,2 @@
1
+<!-- Originally downloaded from https://img.shields.io/badge/Keep-a-changelog-E05735?logoColor=fff&logo=keepachangelog&logoSize=auto on 2024-07-21. Used under CC0, as per https://github.com/badges/shields/blob/1e4c8f54d7743381e723a1ca3f79db7868c2f95e/LICENSE . -->
2
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="127.21161107182145" height="20" role="img" aria-label="Keep a changelog"><title>Keep a changelog</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="127.21161107182145" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="0" height="20" fill="#555"/><rect x="0" width="127.21161107182145" height="20" fill="#e05735"/><rect width="127.21161107182145" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14.21161107182145" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjZmZmIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyMy42NDI3NjMyMTAwOTQ4NjYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPktlZXAgYSBDaGFuZ2Vsb2c8L3RpdGxlPjxwYXRoIGQ9Ik05LjgwMzEgMC4wMDAzQzkuMTA4MSAtMC4wMDQ3IDguNDEzMSAwLjA2MTMgNy43MjAxIDAuMjAxM0M1LjYzOTEgMC42MTgzIDMuOTc0MSAxLjY0OTMgMi43NzAxIDMuMjY2M0MxLjIzMjEgNS4zMzYzIDAuMzY3MSA3Ljg5MzMgMC4wNDkxIDExLjMxMzNDLTAuMDc1OSAxMi42NjYzIDAuMDU3MSAxNC4wMjQzIDAuMjMwMSAxNS41MjkzQzAuNDI4MyAxNy40MzczIDEuMTcyNyAxOS4yNDc3IDIuMzc0MSAyMC43NDMzQzMuMzA3MSAyMS45MDAzIDQuMzc4MSAyMi42NjAzIDUuNjQ2MSAyMy4wNjczQzYuNzI1MyAyMy40MTU2IDcuODQ4NiAyMy42MDg5IDguOTgyMSAyMy42NDEzQzkuMjQ3NiAyMy42NDcxIDkuNTEzMSAyMy42MzU4IDkuNzc3MSAyMy42MDczTDEwLjE5MzEgMjMuNTY2M0MxMC43Njc0IDIzLjUwOTYgMTEuMzQxMSAyMy40NDc2IDExLjkxNDEgMjMuMzgwM0MxNC40OTUgMjMuMDgyNyAxNy4wMDAxIDIyLjMxNzkgMTkuMzA3MSAyMS4xMjMzQzIxLjMxNDEgMjAuMDc1MyAyMi43MTcxIDE4LjUyOTMgMjMuNDc3MSAxNi41MjYzQzIzLjgzMTEgMTUuNTk2MyAyNC4wMDAxIDE0LjgxMzMgMjQuMDAwMSAxNC4wODEzQzI0IDEzLjgyNTkgMjMuOTc4NiAxMy41NzEgMjMuOTM2MSAxMy4zMTkzQzIzLjUzMTEgMTAuOTQwMyAyMi43MDExIDguODkxMyAyMS4zODExIDcuMDU1M0MxOS43NDcxIDQuNzc5MyAxOC4wOTMxIDMuMTc3MyAxNi4xNzkxIDIuMDEwM0MxMy45OTMxIDAuNjgxMyAxMS44OTAxIDAuMDE0MyA5LjgwMzEgMC4wMDEzWk05LjM2NDEgMS4wNjQzQzEwLjEzNDEgMS4wNDMzIDEwLjkyNDEgMS4xMjIzIDExLjc0MDEgMS4zMDEzSDExLjczOTFDMTQuNDY5MSAxLjg5ODMgMTYuODc2MSAzLjMwMzMgMTguODkzMSA1LjQ3NDNDMjEuMTgxMSA3LjkzNDMgMjIuNDg0MSAxMC41MTkzIDIyLjg4MTEgMTMuMzczM0MyMi45NTIxIDEzLjkwMTMgMjIuODY4MSAxNC40ODczIDIyLjc4NTEgMTQuOTk1M0MyMi4zOTcxIDE3LjMyMjMgMjEuMTIyMSAxOS4wNTgzIDE4Ljk5OTEgMjAuMTU1M0MxNi43NjA1IDIxLjMwNjIgMTQuMzMzMyAyMi4wNDUzIDExLjgzMzEgMjIuMzM3M0MxMS4yNzUxIDIyLjQwMzMgMTAuNzEzMSAyMi40NjAzIDEwLjA3NjEgMjIuNTI0M0w5Ljk4ODEgMjIuNTM0M0M5LjQzNjMgMjIuNTkxNSA4Ljg3OTUgMjIuNTgxNSA4LjMzMDEgMjIuNTA0M0M3LjY0MDEgMjIuNDA2MyA2Ljg1ODEgMjIuMjk0MyA2LjEwNjEgMjIuMTE1M0M0LjMzOTEgMjEuNjk1MyAzLjAzNzEgMjAuNDkzMyAyLjEyODEgMTguNDU3M0MxLjQ0NDEgMTYuOTE5MyAxLjA5MDEgMTUuMjEyMyAxLjA0NzEgMTMuMjI0M0MwLjk4NjUgMTAuOTA1MiAxLjM3NjcgOC41OTY1IDIuMTk2MSA2LjQyNjNDMi44MTYxIDQuNzg1MyAzLjcxMzEgMi45NzMzIDUuNjU4MSAyLjAwODNDNi44MDg3IDEuNDI0MSA4LjA3NDMgMS4xMDE3IDkuMzY0MSAxLjA2NDNaTTEwLjQ3MjEgMi41MzQzQzkuNzA5MyAyLjU1OTggOC45NTQ1IDIuNjk4IDguMjMyMSAyLjk0NDNDNi42MzIxIDMuNDY5MyA1LjUxNDEgNC4yNDgzIDQuNzA5MSA1LjM4MjNDMy4yMTAxIDcuNTAwMyAyLjQzNDEgOS45NjIzIDIuMzk5MSAxMi43MDczQzIuMzM3MiAxNC4yMTE0IDIuNjExNSAxNS43MTA1IDMuMjAyMSAxNy4wOTUzQzQuMjgzMSAxOS42NjQzIDYuMjU1MSAyMS4xNTkzIDguOTA5MSAyMS40MjEzQzExLjcwNTEgMjEuNjkxMyAxNC40NTIxIDIxLjA0MDMgMTcuMDg3MSAxOS40ODQzQzE4LjIwNjUgMTguODQyMiAxOS4xNTY3IDE3Ljk0MjcgMTkuODU5MSAxNi44NjAzQzIwLjYxMzIgMTUuNzEzNCAyMS4wMTg4IDE0LjM3MjcgMjEuMDI3MSAxMy4wMDAzQzIxLjAyNzEgMTAuODM4MyAyMC4wMTIxIDguNTMwMyAxNy45NzgxIDYuMTM4M0MxNy43NjIyIDUuODg0NiAxNy41MjY4IDUuNjQ4MyAxNy4yNzQxIDUuNDMxM0MxNC45NDExIDMuNDI1MyAxMi43MDcxIDIuNDY1MyAxMC40NzIxIDIuNTMzM1pNMTAuNTcxMSAzLjU2OTNDMTIuMDYzMSAzLjU0NzMgMTMuNTg2MSA0LjA0NDMgMTUuMjQzMSA1LjA3NzNDMTcuMDI2MSA2LjE5NDMgMTguNDA0MSA3Ljg0MDMgMTkuMzM0MSA5Ljk4NjNDMjAuMjIxMSAxMi4wMDYzIDIwLjIzOTEgMTMuOTI0MyAxOS4zOTIxIDE1LjY4MjNDMTguNzU5NCAxNi45NTc3IDE3Ljc0MjcgMTguMDAyNyAxNi40ODUxIDE4LjY3MDNDMTQuMjMyMSAxOS45MDIzIDEyLjE3MDEgMjAuNDQ2MyAxMC4wMjcxIDIwLjM4MzNIMTAuMDA1MUM4LjQ1NTEgMjAuNDQzMyA3LjExNTEgMjAuMDYzMyA1LjkwNzEgMTkuMjIwM0M1LjIwNzEgMTguNzMyMyA0LjY2NjEgMTguMDE4MyA0LjI1MjEgMTcuMDM3M0MzLjY3NzYgMTUuNjg1OSAzLjM4MTEgMTQuMjMyNyAzLjM4MDEgMTIuNzY0M0MzLjM5NzkgMTEuMDk0OSAzLjc0NTkgOS40NDU1IDQuNDA0MSA3LjkxMTNDNC42NTQgNy4zNDkzIDQuOTQ2MiA2LjgwNyA1LjI3ODEgNi4yODkzTDUuNDQxMSA2LjAxOTNDNi4xMTExIDQuOTExMyA3LjE2NjEgNC4zODAzIDguNTQ0MSAzLjkyMDNDOS4xOTggMy43MDA4IDkuODgxNiAzLjU4MjggMTAuNTcxMSAzLjU3MDNaTTEwLjYwMTEgNS4xODkzQzkuNDIxMSA1LjIyNjMgOC4zMjExIDUuNjU0MyA3LjMxMjEgNi40NzIzQzUuOTE3MSA3LjYwMjMgNS4wODIxIDkuMTkyMyA0LjY4MjEgMTEuNDY1M0M0LjM5MjcgMTMuMDM1NCA0LjYzMDQgMTQuNjU3MiA1LjM1ODEgMTYuMDc4M0M2LjQyMDEgMTguMTMyMyA4LjE1ODEgMTkuMTg4MyAxMC4zODQxIDE5LjEyODNIMTAuMzkyMUMxMy4zNTAxIDE4Ljk3MzMgMTUuNTAyMSAxNy44NzkzIDE2Ljk2NTEgMTUuNzgxM0MxNy42NDczIDE0LjgzNjEgMTguMDE3OCAxMy43MDE4IDE4LjAyNTEgMTIuNTM2M0MxOC4wMjMxIDExLjk4MTIgMTcuOTQxNiAxMS40MjkyIDE3Ljc4MzEgMTAuODk3M0MxNy4wNjMxIDguNDYyMyAxNS42MjIxIDYuNzUyMyAxMy40OTMxIDUuODEyM0MxMi40ODQxIDUuMzY3MyAxMS41MTkxIDUuMTYwMyAxMC42MDExIDUuMTg4M1pNMTAuOTEzMSA2LjI1MzNDMTEuNjgzMSA2LjI2MTMgMTIuNDYwMSA2LjQ0NDMgMTMuMjYzMSA2LjgwMzNDMTUuMTI1MSA3LjYzNjMgMTYuMzM2MSA5LjEzNTMgMTYuODYxMSAxMS4yNjUzQzE3LjM4NzEgMTMuMzk1MyAxNi41OTExIDE1LjQ3MDMgMTQuNzk1MSAxNi42ODgzQzEzLjMxNjEgMTcuNjg3MyAxMS44NjUxIDE4LjEzNTMgMTAuMzU3MSAxOC4wNTUzSDEwLjMxNzFDOS4zMTMxIDE4LjEzNTMgOC4zMjMxIDE3LjgyOTMgNy4zNzQxIDE3LjE0NTNDNi43ODIgMTYuNzEzNyA2LjMzMjcgMTYuMTE0NiA2LjA4NDEgMTUuNDI1M0M1Ljc0NzggMTQuNTU1MyA1LjU3MzYgMTMuNjMxIDUuNTcwMSAxMi42OTgzQzUuNTgzOSAxMS41MzIyIDUuODM4MiAxMC4zODE1IDYuMzE3MSA5LjMxODNDNi45OTMxIDcuNzYyMyA4LjA0MTEgNi44MTUzIDkuNTMyMSA2LjQyNTNDOS45OTIxIDYuMzA1MyAxMC40NTExIDYuMjQ3MyAxMC45MTIxIDYuMjUzM1pNOS40NTUxIDguNTc5M1YxNS40NjEzSDEwLjYxMDFWMTMuNTUzM0wxMi4yOTAxIDE1LjQ2MTNIMTMuNzUyMUwxMS40NzkxIDEyLjk2MTNMMTMuMzUwMSAxMS4wMDMzSDExLjg0MTFMMTAuNjEwMSAxMi4zNDAzVjguNTc5M1oiLz48L3N2Zz4="/><text aria-hidden="true" x="727.1161107182145" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="990">Keep a changelog</text><text x="727.1161107182145" y="140" transform="scale(.1)" fill="#fff" textLength="990">Keep a changelog</text></g></svg>
... ...
@@ -0,0 +1,2 @@
1
+<!-- Originally downloaded from https://img.shields.io/badge/SemVer-3F4551?logoColor=fff&logo=semver&logoSize=auto on 2024-07-21. Used under CC0, as per https://github.com/badges/shields/blob/1e4c8f54d7743381e723a1ca3f79db7868c2f95e/LICENSE . -->
2
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="71.00018479842694" height="20" role="img" aria-label="SemVer"><title>SemVer</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="71.00018479842694" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="0" height="20" fill="#555"/><rect x="0" width="71.00018479842694" height="20" fill="#3f4551"/><rect width="71.00018479842694" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14.00018479842695" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZXNtb2tlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNC4wMDAzNzU5MjkyNjAxNTUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPlNlbVZlcjwvdGl0bGU+PHBhdGggZD0iTTAuMzU3IDkuMDI0NkMtMC41OTQzIDEyLjg0ODcgMC4zODExIDE2Ljg5NjUgMi45NyAxOS44Njc2QzUuNTU4IDIyLjgzNjkgOS40MzM5IDI0LjM1NCAxMy4zNSAyMy45MzA2QzIxLjExOCAyMy4yMjc2IDI2LjQzNiAxNC4xMzE2IDIyLjg2NyA3LjEzMDZDMjIuNDUxIDUuOTQwNiAyMC43OTcgNi43NjI2IDIwLjk2NCA3LjcyNjZDMjEuMjUxIDguNDI2NiAyMS40OSA5LjE0NzYgMjEuNjc3IDkuODgxNkMyMi41MzI1IDEzLjc3NTcgMjAuOTg5IDE3LjgwNTQgMTcuNzUxIDIwLjEzMTZDMTIuNzA2NiAyMy43NTI1IDUuNjE0OSAyMS45MjgyIDIuOTQ0IDE2LjMyMjZDMS4yMjY3IDEyLjcyNDMgMS44MTQ4IDguNDQ5NCA0LjQ0IDUuNDQ4NkM1LjcyNDEgMy45ODE0IDcuNDEwNCAyLjkyMyA5LjI5IDIuNDA0NkMxMS42Mjc4IDEuNzQzNSAxNC4xMjc0IDEuOTY4MiAxNi4zMSAzLjAzNTZDMTYuNDY2OCAzLjExNTIgMTYuNTM0NyAzLjMwMzEgMTYuNDY1IDMuNDY0NkwxMi41MDMgMTQuMDg0NkMxMi4zOTYgMTQuODk0NiAxMS44MTMgMTQuODcwNiAxMS43MDYgMTQuMDg0Nkw5LjMyNiA2LjcxNDZDOS4yMTY1IDYuMjkyMiA4LjkzNjYgNS45MzQ0IDguNTUzIDUuNzI2NkM3LjM2MyA1LjE2NjYgNS40NiA2LjM5MzYgNi4xNzQgNy44ODE2TDEwLjA4OCAxOC4zMjI2QzEwLjYxMiAxOS43MTU2IDExLjExMSAyMC4xNTY2IDEyLjE0NiAyMC4xNTY2UzEzLjY4MSAxOS43MTY2IDE0LjIwNCAxOC4zMjI2TDIwIDMuOTQwNkMyMC4xNTU5IDMuNTA2IDIwLjAwNTQgMy4wMjA3IDE5LjYzMSAyLjc1MDZDMTMuMSAtMi45MDY0IDIuMzIgMC42NDE2IDAuMzU3IDkuMDIzNloiLz48L3N2Zz4="/><text aria-hidden="true" x="445.0018479842695" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">SemVer</text><text x="445.0018479842695" y="140" transform="scale(.1)" fill="#fff" textLength="430">SemVer</text></g></svg>
... ...
@@ -0,0 +1,48 @@
1
+# Changelog for `derivepassphrase`
2
+
3
+[![Keeping a changelog][CHANGELOG_BADGE]][KEEP_A_CHANGELOG]
4
+[![Using Semantic Versioning][SEMVER_BADGE]][SEMANTIC_VERSIONING]
5
+
6
+  [CHANGELOG_BADGE]: Keep_a_changelog-E05735.svg
7
+  [SEMVER_BADGE]: SemVer-3F4551.svg
8
+  [KEEP_A_CHANGELOG]: https://keepachangelog.com/en/1.1.0/ 'Keeping a changelog'
9
+  [SEMANTIC_VERSIONING]: https://semver.org/ 'Using Semantic Versioning'
10
+
11
+<aside markdown><small>
12
+(All entries are from the perspective of a user, not a developer.
13
+The <q>public API</q>, as defined by Semantic Versioning, is outlined in the
14
+[Reference section][REFERENCE]: the set of documented modules, classes,
15
+methods and functions, and the documented behavior, options and arguments of
16
+the command-line tools.
17
+As per the Semantic Versioning and the Keep a Changelog terminology,
18
+<q>Fixed</q> entries justify a <q>patch</q> release,
19
+<q>Added</q> and <q>Deprecated</q> entries a <q>minor</q> release,
20
+and <q>Changed</q> and <q>Removed</q> entries a <q>major</q> release.
21
+<q>Security</q> can justify any type of release;
22
+if <q>major</q> or <q>minor</q>, these are accompanied by corresponding
23
+entries of the respective types above.
24
+Again as per Semantic Versioning, at major version zero, the above
25
+justification is not yet binding, and <em>any</em> new release may
26
+effectively constitute a new <q>major</q> release.)
27
+</small></aside>
28
+
29
+  [REFERENCE]: reference.md
30
+
31
+<!-- towncrier release notes start -->
32
+
33
+## 0.1.1 (2024-07-14)
34
+
35
+#### Fixed
36
+
37
+- Restore the `__version__` attribute in all top-level packages.
38
+- Declare compatibility with Python 3.10 in project metadata, and include
39
+  necessary version-specific dependencies.
40
+- Publish the documentation online, and link to it in the repository metadata
41
+  and the Python package metadata.
42
+
43
+
44
+## 0.1.0 (2024-07-14)
45
+
46
+#### Added
47
+
48
+- Initial release.
... ...
@@ -87,12 +87,14 @@ nav:
87 87
     - Module sequin: reference/sequin.md
88 88
     - Module ssh_agent_client: reference/ssh_agent_client.md
89 89
   #- Design & Background: explanation.md
90
+  - Changelog: changelog.md
90 91
 
91 92
 markdown_extensions:
92 93
   - abbr
93 94
   - attr_list
94 95
   - def_list
95 96
   - footnotes
97
+  - md_in_html
96 98
   - admonition
97 99
   - smarty
98 100
   - toc:
... ...
@@ -31,7 +31,7 @@ version = "0.1.1"
31 31
 
32 32
 [project.optional-dependencies]
33 33
 dev = ["black", "coverage", "hatch>=1.10", "mkdocs", "mkdocs-material",
34
-       "mkdocstrings[python]", "pytest>=8.1"]
34
+       "mkdocstrings[python]", "pytest>=8.1", "towncrier>=23.11"]
35 35
 
36 36
 [project.urls]
37 37
 Documentation = "https://the13thletter.info/derivepassphrase/"
... ...
@@ -150,3 +150,49 @@ parametrize-names-type = 'list'
150 150
 [tool.hatch.envs.hatch-static-analysis]
151 151
 config-path = "ruff_defaults_v0.5.0.toml"
152 152
 dependencies = ["ruff==0.5.0"]
153
+
154
+[tool.hatch.envs.release]
155
+dependencies = ['towncrier>=23.11']
156
+
157
+[tool.hatch.envs.release.scripts]
158
+
159
+[tool.towncrier]
160
+package = 'derivepassphrase'
161
+package_dir = 'src'
162
+directory = 'towncrier.d'
163
+filename = 'docs/changelog.md'
164
+template = 'towncrier-template.md'
165
+#title_format = '[{version}](https://github.com/the-13th-letter/derivepassphrase/tree/{version}) – {project_date}'
166
+underlines = ['', '', '']
167
+issue_format = '[#{issue}]: https://github.com/the-13th-letter/derivepassphrase/{issue}'
168
+wrap = true
169
+
170
+[[tool.towncrier.type]]
171
+directory = "security"
172
+name = "Security"
173
+showcontent = true
174
+
175
+[[tool.towncrier.type]]
176
+directory = "added"
177
+name = "Added"
178
+showcontent = true
179
+
180
+[[tool.towncrier.type]]
181
+directory = "fixed"
182
+name = "Fixed"
183
+showcontent = true
184
+
185
+[[tool.towncrier.type]]
186
+directory = "removed"
187
+name = "Removed"
188
+showcontent = true
189
+
190
+[[tool.towncrier.type]]
191
+directory = "changed"
192
+name = "Changed"
193
+showcontent = true
194
+
195
+[[tool.towncrier.type]]
196
+directory = "deprecated"
197
+name = "Deprecated"
198
+showcontent = true
... ...
@@ -0,0 +1,54 @@
1
+{% if render_title %}
2
+## {{ versiondata.version }} ({{ versiondata.date }})
3
+{% endif %}
4
+{% for section, _ in sections.items() %}
5
+{% if section %}
6
+
7
+### {{section}}
8
+{% endif %}
9
+
10
+{% if sections[section] %}
11
+{% for category, val in definitions.items() if category in sections[section] %}
12
+#### {{ definitions[category]['name'] }}
13
+
14
+{% for text, values in sections[section][category].items() %}
15
+- {{ text }}
16
+{%- if values %}
17
+{% if "\n  - " in text or '\n  * ' in text %}
18
+
19
+
20
+  (
21
+{%- else %}
22
+{% if text %} ({% endif %}
23
+{%- endif -%}
24
+{%- for issue in values %}
25
+{{ issue.split(": ", 1)[0] }}{% if not loop.last %}, {% endif %}
26
+{%- endfor %}
27
+{% if text %}){% endif %}
28
+
29
+{% else %}
30
+
31
+{% endif %}
32
+{% endfor %}
33
+
34
+{% if issues_by_category[section][category] and "]: " in issues_by_category[section][category][0] %}
35
+{% for issue in issues_by_category[section][category] %}
36
+{{ issue }}
37
+{% endfor %}
38
+
39
+{% endif %}
40
+{% if sections[section][category]|length == 0 %}
41
+No significant changes.
42
+
43
+{% else %}
44
+{% endif %}
45
+{% endfor %}
46
+{% else %}
47
+No significant changes.
48
+
49
+{% endif %}
50
+{% endfor +%}
51
+{#
52
+This comment adds one more newline at the end of the rendered newsfile content.
53
+In this way the there are 2 newlines between the latest release and the previous release content.
54
+#}
... ...
@@ -0,0 +1,2 @@
1
+
2
+Set up a changelog, using [towncrier](https://pypi.org/package/towncrier).
... ...
@@ -0,0 +1,2 @@
1
+
2
+Lint and reformat all code using [ruff](https://astral.sh/ruff/).