Skip to content

Commit 566d315

Browse files
SmileyChrispre-commit-ci[bot]hynek
authored
Fix create for a bare orphan in a section not adding random hex (#468)
* Fix `create` for a bare orphan in a section not adding random hex * Add change * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Make test_create_orphane_fragment os independent * Add tests for a custom orphan prefix * Fix a test to actually test what it should test * This ain't Markdown --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Hynek Schlawack <[email protected]>
1 parent 53dd3e2 commit 566d315

File tree

3 files changed

+60
-15
lines changed

3 files changed

+60
-15
lines changed

src/towncrier/create.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,16 @@ def __main(
8181
"""
8282
base_directory, config = load_config_from_options(directory, config_path)
8383

84-
if config.orphan_prefix and filename.startswith(f"{config.orphan_prefix}."):
84+
file_dir, file_basename = os.path.split(filename)
85+
if config.orphan_prefix and file_basename.startswith(f"{config.orphan_prefix}."):
8586
# Append a random hex string to the orphan news fragment base name.
86-
filename = f"{config.orphan_prefix}{os.urandom(4).hex()}{filename[1:]}"
87+
filename = os.path.join(
88+
file_dir,
89+
(
90+
f"{config.orphan_prefix}{os.urandom(4).hex()}"
91+
f"{file_basename[len(config.orphan_prefix):]}"
92+
),
93+
)
8794
if len(filename.split(".")) < 2 or (
8895
filename.split(".")[-1] not in config.types
8996
and filename.split(".")[-2] not in config.types
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix creating fragment in a section not adding random characters.
2+
3+
For example, ``towncrier create some_section/+.feature`` should end up as a fragment named something like ``news/some_section/+a4e22da1.feature``.

src/towncrier/test/test_create.py

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22
# See LICENSE for details.
33

44
import os
5+
import string
56

7+
from pathlib import Path
68
from textwrap import dedent
79
from unittest import mock
810

911
from click.testing import CliRunner
1012
from twisted.trial.unittest import TestCase
1113

1214
from ..create import _main
13-
from .helpers import setup_simple_project
15+
from .helpers import setup_simple_project, with_isolated_runner
1416

1517

1618
class TestCli(TestCase):
@@ -164,25 +166,58 @@ def test_file_exists(self):
164166
self.assertEqual(type(result.exception), SystemExit)
165167
self.assertIn("123.feature.rst already exists", result.output)
166168

167-
def test_create_orphan_fragment(self):
169+
@with_isolated_runner
170+
def test_create_orphan_fragment(self, runner: CliRunner):
168171
"""
169172
When a fragment starts with the only the orphan prefix (``+`` by default), the
170173
create CLI automatically extends the new file's base name to contain a random
171174
value to avoid commit collisions.
172175
"""
173-
runner = CliRunner()
176+
setup_simple_project()
174177

175-
with runner.isolated_filesystem():
176-
setup_simple_project()
178+
frag_path = Path("foo", "newsfragments")
179+
sub_frag_path = frag_path / "subsection"
180+
sub_frag_path.mkdir()
177181

178-
self.assertEqual([], os.listdir("foo/newsfragments"))
182+
result = runner.invoke(_main, ["+.feature"])
183+
self.assertEqual(0, result.exit_code)
184+
result = runner.invoke(
185+
_main, [str(Path("subsection", "+.feature"))], catch_exceptions=False
186+
)
187+
self.assertEqual(0, result.exit_code, result.output)
188+
189+
fragments = [p for p in frag_path.rglob("*") if p.is_file()]
190+
self.assertEqual(2, len(fragments))
191+
change1, change2 = fragments
179192

180-
runner.invoke(_main, ["+.feature"])
181-
fragments = os.listdir("foo/newsfragments")
193+
self.assertEqual(change1.suffix, ".feature")
194+
self.assertTrue(change1.stem.startswith("+"))
195+
# Length should be '+' character and 8 random hex characters.
196+
self.assertEqual(len(change1.stem), 9)
182197

183-
self.assertEqual(1, len(fragments))
184-
filename = fragments[0]
185-
self.assertTrue(filename.endswith(".feature"))
186-
self.assertTrue(filename.startswith("+"))
198+
self.assertEqual(change2.suffix, ".feature")
199+
self.assertTrue(change2.stem.startswith("+"))
200+
self.assertEqual(change2.parent, sub_frag_path)
187201
# Length should be '+' character and 8 random hex characters.
188-
self.assertEqual(len(filename.split(".")[0]), 9)
202+
self.assertEqual(len(change2.stem), 9)
203+
204+
@with_isolated_runner
205+
def test_create_orphan_fragment_custom_prefix(self, runner: CliRunner):
206+
"""
207+
Check that the orphan prefix can be customized.
208+
"""
209+
setup_simple_project(extra_config='orphan_prefix = "$$$"')
210+
211+
frag_path = Path("foo", "newsfragments")
212+
213+
result = runner.invoke(_main, ["$$$.feature"])
214+
self.assertEqual(0, result.exit_code, result.output)
215+
216+
fragments = list(frag_path.rglob("*"))
217+
self.assertEqual(len(fragments), 1)
218+
change = fragments[0]
219+
self.assertTrue(change.stem.startswith("$$$"))
220+
# Length should be '$$$' characters and 8 random hex characters.
221+
self.assertEqual(len(change.stem), 11)
222+
# Check the remainder are all hex characters.
223+
self.assertTrue(all(c in string.hexdigits for c in change.stem[3:]))

0 commit comments

Comments
 (0)