Skip to content

Commit f3c94f0

Browse files
committed
Add `-i/--issue option to blurb add
1 parent 0ea760c commit f3c94f0

File tree

4 files changed

+144
-7
lines changed

4 files changed

+144
-7
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## 2.1.0
4+
5+
- Add the `-i` / `--issue` option to the 'blurb add' command.
6+
This lets you pre-fill the `gh-issue` field in the template.
7+
38
## 2.0.0
49

510
* Move 'blurb test' subcommand into test suite by @hugovk in https://github.com/python/blurb/pull/37

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,13 @@ Here's how you interact with the file:
108108

109109
* Add the GitHub issue number for this commit to the
110110
end of the `.. gh-issue:` line.
111+
The issue can also be specified via the ``-i`` / ``--issue`` option:
112+
113+
```shell
114+
$ blurb add -i 109198
115+
# or equivalently
116+
$ blurb add -i https://github.com/python/cpython/issues/109198
117+
```
111118

112119
* Uncomment the line with the relevant `Misc/NEWS` section for this entry.
113120
For example, if this should go in the `Library` section, uncomment

src/blurb/blurb.py

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -824,25 +824,63 @@ def find_editor():
824824
error('Could not find an editor! Set the EDITOR environment variable.')
825825

826826

827-
def _template_text_for_temp_file():
827+
def _extract_issue_number(issue, /):
828+
if issue is None:
829+
return None
830+
issue = issue.strip()
831+
832+
if issue.startswith(('GH-', 'gh-')):
833+
stripped = issue[3:]
834+
else:
835+
stripped = issue.removeprefix('#')
836+
try:
837+
return int(stripped)
838+
except ValueError:
839+
pass
840+
841+
# Allow GitHub URL with or without the scheme
842+
stripped = issue.removeprefix('https://')
843+
stripped = stripped.removeprefix('github.com/python/cpython/issues/')
844+
try:
845+
return int(stripped)
846+
except ValueError:
847+
pass
848+
849+
sys.exit(f"Invalid GitHub issue number: {issue}")
850+
851+
852+
def _blurb_template_text(*, issue):
853+
issue_number = _extract_issue_number(issue)
854+
828855
text = template
829856

830857
# Ensure that there is a trailing space after '.. gh-issue:' to make
831-
# filling in the template easier.
858+
# filling in the template easier, unless an issue number was given
859+
# through the --issue command-line flag.
832860
issue_line = ".. gh-issue:"
833861
without_space = "\n" + issue_line + "\n"
834-
with_space = "\n" + issue_line + " \n"
835862
if without_space not in text:
836-
sys.exit("Can't find gh-issue line to ensure there's a space on the end!")
837-
text = text.replace(without_space, with_space)
863+
sys.exit("Can't find gh-issue line in the template!")
864+
if issue_number is None:
865+
with_space = "\n" + issue_line + " \n"
866+
text = text.replace(without_space, with_space)
867+
else:
868+
with_issue_number = f"\n{issue_line} {issue_number}\n"
869+
text = text.replace(without_space, with_issue_number)
838870

839871
return text
840872

841873

842874
@subcommand
843-
def add():
875+
def add(*, issue=None):
844876
"""
845877
Add a blurb (a Misc/NEWS.d/next entry) to the current CPython repo.
878+
879+
Use -i/--issue to specify a GitHub issue number or link, e.g.:
880+
881+
blurb add -i 12345
882+
# or
883+
blurb add -i https://github.com/python/cpython/issues/12345
846884
"""
847885

848886
editor = find_editor()
@@ -851,7 +889,7 @@ def add():
851889
os.close(handle)
852890
atexit.register(lambda : os.unlink(tmp_path))
853891

854-
text = _template_text_for_temp_file()
892+
text = _blurb_template_text(issue=issue)
855893
with open(tmp_path, "w", encoding="utf-8") as file:
856894
file.write(text)
857895

tests/test_blurb_add.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import re
2+
3+
import pytest
4+
5+
from blurb import blurb
6+
7+
8+
def test_valid_no_issue_number():
9+
assert blurb._extract_issue_number(None) is None
10+
res = blurb._blurb_template_text(issue=None)
11+
lines = frozenset(res.splitlines())
12+
assert '.. gh-issue:' not in lines
13+
assert '.. gh-issue: ' in lines
14+
15+
16+
@pytest.mark.parametrize('issue', (
17+
# issue given by their number
18+
'12345',
19+
' 12345 ',
20+
# issue given by their number and a 'GH-' prefix
21+
'GH-12345',
22+
' GH-12345 ',
23+
# issue given by their number and a 'gh-' prefix
24+
'gh-12345',
25+
' gh-12345 ',
26+
# issue given by their number and a '#' prefix
27+
'#12345',
28+
' #12345 ',
29+
# issue given by their URL (no scheme)
30+
'github.com/python/cpython/issues/12345',
31+
' github.com/python/cpython/issues/12345 ',
32+
# issue given by their URL (with scheme)
33+
'https://github.com/python/cpython/issues/12345',
34+
' https://github.com/python/cpython/issues/12345 ',
35+
))
36+
def test_valid_issue_number_12345(issue):
37+
actual = blurb._extract_issue_number(issue)
38+
assert actual == 12345
39+
40+
res = blurb._blurb_template_text(issue=issue)
41+
lines = frozenset(res.splitlines())
42+
assert '.. gh-issue:' not in lines
43+
assert '.. gh-issue: ' not in lines
44+
assert '.. gh-issue: 12345' in lines
45+
46+
47+
@pytest.mark.parametrize('issue', (
48+
'',
49+
'abc',
50+
'Gh-123',
51+
'gh-abc',
52+
'gh- 123',
53+
'gh -123',
54+
'gh-',
55+
'bpo-',
56+
'bpo-12345',
57+
'github.com/python/cpython/issues',
58+
'github.com/python/cpython/issues/',
59+
'github.com/python/cpython/issues/abc',
60+
'github.com/python/cpython/issues/gh-abc',
61+
'github.com/python/cpython/issues/gh-123',
62+
'github.com/python/cpython/issues/1234?param=1',
63+
'https://github.com/python/cpython/issues',
64+
'https://github.com/python/cpython/issues/',
65+
'https://github.com/python/cpython/issues/abc',
66+
'https://github.com/python/cpython/issues/gh-abc',
67+
'https://github.com/python/cpython/issues/gh-123',
68+
'https://github.com/python/cpython/issues/1234?param=1',
69+
))
70+
def test_invalid_issue_number(issue):
71+
error_message = re.escape(f'Invalid GitHub issue: {issue}')
72+
with pytest.raises(SystemExit, match=error_message):
73+
blurb._blurb_template_text(issue=issue)
74+
75+
76+
@pytest.mark.parametrize('invalid', (
77+
'gh-issue: ',
78+
'gh-issue: 1',
79+
'gh-issue',
80+
))
81+
def test_malformed_gh_issue_line(invalid, monkeypatch):
82+
template = blurb.template.replace('.. gh-issue:', invalid)
83+
error_message = re.escape("Can't find gh-issue line in the template!")
84+
with monkeypatch.context() as cm:
85+
cm.setattr(blurb, 'template', template)
86+
with pytest.raises(SystemExit, match=error_message):
87+
blurb._blurb_template_text(issue='1234')

0 commit comments

Comments
 (0)