Skip to content

Commit 205da9c

Browse files
committed
enabled fallback of name|package values to project.name
This fallback will only work if the pyproject.toml file is present. However, it will work for any combination of pyproject.toml or towncrier.toml configuration files. Note, that project.name is a required field in pyproject.toml files. Hence, the minimal requirement for using towncrier in python project is a no-op! Signed-off-by: Nick Papior <nickpapior@gmail.com>
1 parent cd0d2df commit 205da9c

File tree

3 files changed

+72
-10
lines changed

3 files changed

+72
-10
lines changed

docs/configuration.rst

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ A minimal configuration for a Python project looks like this:
1717
.. code-block:: toml
1818
1919
# pyproject.toml
20-
21-
[tool.towncrier]
22-
package = "myproject"
20+
[project]
21+
name = "myproject"
2322
2423
A minimal configuration for a non-Python project looks like this:
2524

@@ -36,9 +35,9 @@ Top level keys
3635
``name``
3736
The name of your project.
3837

39-
For Python projects that provide a ``package`` key, if left empty then the name will be automatically determined.
38+
For Python projects that provide a ``package`` key, if left empty then the name will be automatically determined from the ``package`` key.
4039

41-
``""`` by default.
40+
Defaults to the key ``[project.name]`` in ``pyproject.toml`` (if present), otherwise defaults to the empty string ``""``.
4241

4342
``version``
4443
The version of your project.
@@ -167,6 +166,8 @@ Extra top level keys for Python projects
167166
Allows ``name`` and ``version`` to be automatically determined from the Python package.
168167
Changes the default ``directory`` to be a ``newsfragments`` directory within this package.
169168

169+
Defaults to the key ``[project.name]`` in ``pyproject.toml`` (if present), otherwise defaults to the empty string ``""``.
170+
170171
``package_dir``
171172
The folder your package lives.
172173

src/towncrier/_settings/load.py

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,19 +118,44 @@ def load_config(directory: str) -> Config | None:
118118
towncrier_toml = os.path.join(directory, "towncrier.toml")
119119
pyproject_toml = os.path.join(directory, "pyproject.toml")
120120

121+
# In case the [tool.towncrier.name|package] is not specified
122+
# we'll read it from [project.name]
123+
124+
if os.path.exists(pyproject_toml):
125+
pyproject_config = load_toml_from_file(pyproject_toml)
126+
else:
127+
# make it empty so it won't be used as a backup plan
128+
pyproject_config = {}
129+
121130
if os.path.exists(towncrier_toml):
122-
config_file = towncrier_toml
131+
config_toml = towncrier_toml
123132
elif os.path.exists(pyproject_toml):
124-
config_file = pyproject_toml
133+
config_toml = pyproject_toml
125134
else:
126135
return None
127136

128-
return load_config_from_file(directory, config_file)
137+
# Read the default configuration. Depending on which exists
138+
config = load_config_from_file(directory, config_toml)
129139

140+
# Fallback certain values depending on the [project.name]
141+
if project_name := pyproject_config.get("project", {}).get("name", ""):
142+
# Fallback to the project name for the configuration name
143+
# and the configuration package entries.
144+
if not config.name:
145+
config.name = project_name
146+
if not config.package:
147+
config.package = project_name
130148

131-
def load_config_from_file(directory: str, config_file: str) -> Config:
149+
return config
150+
151+
152+
def load_toml_from_file(config_file: str) -> Mapping[str, Any]:
132153
with open(config_file, "rb") as conffile:
133-
config = tomllib.load(conffile)
154+
return tomllib.load(conffile)
155+
156+
157+
def load_config_from_file(directory: str, config_file: str) -> Config:
158+
config = load_toml_from_file(config_file)
134159

135160
return parse_toml(directory, config)
136161

src/towncrier/test/test_settings.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,42 @@ def test_towncrier_toml_preferred(self):
194194
config = load_config(project_dir)
195195
self.assertEqual(config.package, "a")
196196

197+
def test_pyproject_name_fallback_both(self):
198+
"""
199+
Towncrier will fallback to the [project.name] value in pyproject.toml.
200+
"""
201+
project_dir = self.mktemp_project(
202+
pyproject_toml="""
203+
[project]
204+
name = "a"
205+
""",
206+
)
207+
208+
config = load_config(project_dir)
209+
self.assertEqual(config.package, "a")
210+
self.assertEqual(config.name, "a")
211+
212+
def test_pyproject_name_fallback_towncrier(self):
213+
"""
214+
Towncrier will fallback to the [project.name] value in pyproject.toml.
215+
"""
216+
project_dir = self.mktemp_project(
217+
towncrier_toml="""
218+
[tool.towncrier]
219+
package = "a"
220+
""",
221+
pyproject_toml="""
222+
[project]
223+
name = "c"
224+
[tool.towncrier]
225+
name = "b"
226+
""",
227+
)
228+
229+
config = load_config(project_dir)
230+
self.assertEqual(config.package, "a")
231+
self.assertEqual(config.name, "c")
232+
197233
@with_isolated_runner
198234
def test_load_no_config(self, runner: CliRunner):
199235
"""

0 commit comments

Comments
 (0)