Install & Compatibility
Where this runs
tested against v25.8.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.000s · 20.5MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 2.0s · import 0.000s · 21MB
19MB installed
● package 19MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
towncrier
✓ import towncrier
✗ import subprocess
This quickstart demonstrates how to set up Towncrier in a minimal Python project. It creates a `pyproject.toml` configuration, adds a few news fragments of different types, then uses `towncrier build --draft` to preview the generated news file, and finally `towncrier build --yes` to generate the `NEWS.rst` file and remove the fragments. The example cleans up the created directory afterwards.
import subprocess
import os
from pathlib import Path
import shutil
def run_towncrier_quickstart():
project_root = Path("./my_project_with_news")
news_dir = project_root / "newsfragments"
news_file = project_root / "NEWS.rst"
# Clean up previous run if any
if project_root.exists():
shutil.rmtree(project_root)
project_root.mkdir()
news_dir.mkdir()
# 1. Create pyproject.toml configuration
pyproject_toml_content = '''
[project]
name = "my-project"
version = "1.0.0"
[tool.towncrier]
directory = "newsfragments"
filename = "NEWS.rst"
issue_format = "#{issue}"
'''
(project_root / "pyproject.toml").write_text(pyproject_toml_content)
# 2. Create news fragments
(news_dir / "123.feature").write_text("Added an awesome new feature.")
(news_dir / "456.bugfix").write_text("Fixed a critical bug in component X.")
(news_dir / "789.doc").write_text("Improved documentation for API Y.")
print(f"\n--- Running 'towncrier build --draft' in {project_root.name} ---")
subprocess.run(['towncrier', 'build', '--draft'], cwd=project_root, check=True)
print(f"\n--- Running 'towncrier build' in {project_root.name} ---")
# 'towncrier build' automatically removes fragments for tracked files by default (since 24.7.0)
# If you were in a real git repo, you'd then 'git add NEWS.rst' and 'git commit'
subprocess.run(['towncrier', 'build', '--yes'], cwd=project_root, check=True)
print("\n--- Generated NEWS.rst content ---")
print(news_file.read_text())
print("\n--- News fragments after build ---")
if list(news_dir.iterdir()):
print(f"Fragments still exist in {news_dir}. This might happen if they were not git-tracked or --keep was used.")
else:
print(f"No fragments found in {news_dir} (expected).")
# Clean up
shutil.rmtree(project_root)
run_towncrier_quickstart()
towncrier --version
Debug
Known issues
breakingPython 3.8 support has been removed in Towncrier 25.8.0. Users on Python 3.8 or older will need to upgrade their Python version or use an earlier Towncrier release.fixUpgrade to Python 3.9 or newer. If unable to upgrade Python, pin Towncrier to a version older than 25.8.0 (e.g., `towncrier<25.8.0`).
affects: 25.8.0+
gotchaTowncrier uses a specific configuration file precedence: `towncrier.toml` takes precedence over `pyproject.toml`. If both exist, settings in `towncrier.toml` will override those in `pyproject.toml`.fixStandardize on one configuration file (`pyproject.toml` is generally recommended for modern Python projects) or be aware of the precedence rules when mixing them.
affects: All versions
gotchaBy default, `towncrier build` will remove news fragments after successfully generating the news file. If you wish to keep the fragments (e.g., for review before manual deletion), you must use the `--keep` flag.fixAlways use `towncrier build --keep` if you want to retain the fragment files after generation, or ensure your workflow accounts for their automatic removal. Note that fragments not tracked by Git may not be removed automatically.
affects: All versions
gotchaWhen defining custom news fragment types in your configuration, using a TOML mapping (e.g., `[tool.towncrier.fragment.mytype]`) will result in fragment types being sorted alphabetically in the output. To control the order, use a TOML array of tables (`[[tool.towncrier.type]]`).fixDefine your custom fragment types using the array of tables syntax (e.g., `[[tool.towncrier.type]]` for each type) to explicitly define their order in the generated news file.
affects: Versions using TOML configuration, particularly since changes around 22.8.0
deprecatedSupport for the `towncrier.ini` configuration file was removed in favor of `pyproject.toml` (and `towncrier.toml`).fixMigrate your configuration from `towncrier.ini` to `pyproject.toml` under the `[tool.towncrier]` table or a dedicated `towncrier.toml` file.
affects: 17.8.0+
Upgrade
Version history
25.8.0latest on PyPI · released Aug 30, 2025
Audit
Dependencies
clickrequiredCommand-line interface toolkit
Jinja2requiredTemplating engine for news file generation
tomloptionalParsing pyproject.toml configuration (implicitly for Python <3.11)
gitoptionalUsed by 'towncrier build' for fragment removal and 'towncrier check'
mercurialoptionalOptional SCM support (added in 25.8.0)