8000 Add `-i/--issue` and `-s/--section` flags to `blurb add` by picnixz · Pull Request #16 · python/blurb · GitHub
[go: up one dir, main page]

Skip to content

Add -i/--issue and -s/--section flags to blurb add #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
d5d11a2
Improve `blurb add` command.
picnixz Jun 25, 2024
eaddee3
update version
picnixz Jun 25, 2024
403d387
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 25, 2024
ad230fe
fix CI/CD
picnixz Jun 25, 2024
edd8eea
Merge branch 'add-gh-flags' of github.com:picnixz/blurb into add-gh-f…
picnixz Jun 25, 2024
9856548
fixup! typos
picnixz Jun 26, 2024
a2a1fce
add test for known section names
picnixz Jun 26, 2024
7d67830
expand tests
picnixz Jun 26, 2024
635c8ac
improve section name detection
picnixz Jun 26, 2024
992b8ec
improve tests
picnixz Jun 26, 2024
842bc2d
address review!
picnixz Jun 26, 2024
99261a5
remove extraneous line
picnixz Jun 26, 2024
114013c
Merge branch 'main' into add-gh-flags
picnixz Jul 12, 2024
18a5563
address Larry's comments
picnixz Jul 13, 2024
350daeb
remove local fix
picnixz Jul 13, 2024
0e25cc0
remove un-necessary blank line
picnixz Jul 13, 2024
2b976e2
...
picnixz Jul 13, 2024
d578f92
use the same example in the README and the docstring of `add`
picnixz Jul 13, 2024
f11b9f1
Update README.md
picnixz Jul 13, 2024
6737ea4
Update README.md
picnixz Jul 13, 2024
384079d
Update src/blurb/blurb.py
picnixz Jul 13, 2024
9242ddc
Update src/blurb/blurb.py
hugovk Jul 13, 2024
8619bc2
Update README.md
picnixz Jul 13, 2024
9de55af
improve matching algorithm
picnixz Jul 13, 2024
a7cd263
increase test coverage
picnixz Jul 13, 2024
ba33c38
update comments
picnixz Jul 13, 2024
cb04947
simplify supported separators
picnixz Jul 13, 2024
33ae76e
fix regex
picnixz Jul 13, 2024
48fc24b
improve error messages
picnixz Jul 13, 2024
15271e1
cleanup
picnixz Jul 13, 2024
a3899ec
Merge branch 'main' into add-gh-flags
picnixz Aug 14, 2024
026052c
Update README.md
picnixz Aug 14, 2024
5fe40bd
Update CHANGELOG.md
picnixz Aug 14, 2024
1f789b0
Merge branch 'main' into add-gh-flags
picnixz Nov 1, 2024
792c0a6
Merge branch 'main' into add-gh-flags
picnixz Jun 1, 2025
9775d8f
Apply suggestions from code review
picnixz Jun 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
address Larry's comments
- remove section IDs matching
- do not render the table in case of a multi-match
- simplify `add` docstring construction
- update tests
- update README.md
  • Loading branch information
picnixz committed Jul 13, 2024
commit 18a5563f48515193059cc8681fe294016f6b82f9
41 changes: 21 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ Here's how you interact with the file:
be specified via the ``-i/--issue`` option:

```shell
blurb add -i 109198
$ blurb add -i 109198
# or equivalently
blurb add -i https://github.com/python/cpython/issues/109198
$ blurb add -i https://github.com/python/cpython/issues/109198
```

* Uncomment the line with the relevant `Misc/NEWS` section for this entry.
Expand All @@ -125,27 +125,28 @@ Here's how you interact with the file:
be specified via the ``-s/--section`` option:

```shell
blurb add -s "Library"
$ blurb add -s 'Library'
# or equivalently
blurb add -s 3
$ blurb add -s lib
```

The section can be referred to from its name (case insensitive) or its ID
defined according to the following table:

| ID | Section |
|----|-------------------|
| 1 | Security |
| 2 | Core and Builtins |
| 3 | Library |
| 4 | Documentation |
| 5 | Tests |
| 6 | Build |
| 7 | Windows |
| 8 | macOS |
| 9 | IDLE |
| 10 | Tools/Demos |
| 11 | C API |
The known section names are given in the following table. The match
is performed casse insensitively and partial matching is supported
as long as the match is unique:

| Section Name |
|-------------------|
| Security |
| Core and Builtins |
| Library |
| Documentation |
| Tests |
| Build |
| Windows |
| macOS |
| IDLE |
| Tools/Demos |
| C API |

* Finally, go to the end of the file, and enter your `NEWS` entry.
This should be a single paragraph of English text using
Expand Down
66 changes: 29 additions & 37 deletions src/blurb/blurb.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,19 @@
import time
import unittest

from . import __version__
try:
from . import __version__
except ImportError:
__version__ = 12343


#
# This template is the canonical list of acceptable section names!
# It's parsed internally into the "sections" set.
#
# Do not forget to update the example for the 'add' command if
# the section names change as well as the corresponding tests.
#

template = """

Expand Down Expand Up @@ -897,16 +903,8 @@ def _extract_section_name(section):
return None

section = raw_section = section.strip()
if section.strip('+-').isdigit():
section_index = int(section) - 1
if not (0 <= section_index < len(sections)):
sys.exit(f"Invalid section ID: {int(section)}\n\n"
f"Choose from the following table:\n\n"
f'{sections_table}')
return sections[section_index]

if not section:
sys.exit(f"Empty section name!")
sys.exit("Empty section name!")

sanitized = re.sub(r'[_-]', ' ', section)
section_words = re.split(r'\s+', sanitized)
Expand All @@ -919,16 +917,14 @@ def _extract_section_name(section):
matches.append(section_name)

if not matches:
sys.exit(f"Invalid section name: {raw_section}\n\n"
sys.exit(f"Invalid section name: {raw_section!r}\n\n"
f"Choose from the following table:\n\n"
f'{sections_table}')

if len(matches) > 1:
multiple_matches = ', '.join(map(repr, sorted(matches)))
sys.exit(f"More than one match for: {raw_section}\n"
f"Matches: {multiple_matches}\n\n"
f"Choose from the following table:\n\n"
f'{sections_table}')
sys.exit(f"More than one match for: {raw_section!r}\n"
f"Matches: {multiple_matches}")

return matches[0]

Expand Down Expand Up @@ -971,20 +967,22 @@ def add(*, issue=None, section=None):
Use -i/--issue to specify a GitHub issue number or link, e.g.:

blurb add -i 109198

# or equivalently
blurb add -i https://github.com/python/cpython/issues/109198

The blurb's section can be specified via -s/--section
with its ID or name (case insenstitive), e.g.:
with its name (case insenstitive), e.g.:

blurb add -s %(section_example_name)r
# or equivalently
blurb add -s %(section_example_id)d
blurb add -s 'Core and Builtins'

# or using a partial matching
blurb add -s core

The known sections IDs and names are defined as follows,
and spaces in names can be substituted for underscores:
The known sections names are defined as follows and
spaces in names can be substituted for underscores:

%(sections)s
{sections}
"""

editor = find_editor()
Expand Down Expand Up @@ -1048,21 +1046,15 @@ def init_tmp_with_template():


assert sections, 'sections is empty'
_sec_id_w = 2 + len(str(len(sections)))
_sec_name_w = 2 + max(map(len, sections))
_sec_rowrule = '+'.join(['', '-' * _sec_id_w, '-' * _sec_name_w, ''])
_format_row = ('| {:%d} | {:%d} |' % (_sec_id_w - 2, _sec_name_w - 2)).format
sections_table = '\n'.join(itertools.chain(
[_sec_rowrule, _format_row('ID', 'Section'),_sec_rowrule.replace('-', '=')],
itertools.starmap(_format_row, enumerate(sections, 1)),
[_sec_rowrule]
))
del _format_row, _sec_rowrule, _sec_name_w, _sec_id_w
add.__doc__ %= dict(
section_example_id=3,
section_example_name=sections[2],
sections=sections_table,
)
_sec_name_width = 2 + max(map(len, sections))
_sec_rowrule = '+'.join(['', '-' * _sec_name_width, ''])
_format_row = (f'| {{:{_sec_name_width - 2:d}}} |').format
del _sec_name_width
sections_table = '\n'.join(map(_format_row, sections))
del _format_row
sections_table = '\n'.join((_sec_rowrule, sections_table, _sec_rowrule))
del _sec_rowrule
add.__doc__ = add.__doc__.format(sections=sections_table)


@subcommand
Expand Down
48 changes: 5 additions & 43 deletions tests/test_blurb_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,46 +81,6 @@ def test_invalid_issue_number(issue):
blurb._update_blurb_template(issue=issue, section=None)


@pytest.mark.parametrize(('section_index', 'section_id', 'section_name'), (
(0, '1', 'Security'),
(1, '2', 'Core and Builtins'),
(2, '3', 'Library'),
(3, '4', 'Documentation'),
(4, '5', 'Tests'),
(5, '6', 'Build'),
(6, '7', 'Windows'),
(7, '8', 'macOS'),
(8, '9', 'IDLE'),
(9, '10', 'Tools/Demos'),
(10, '11', 'C API'),
))
def test_valid_section_id(section_index, section_id, section_name):
actual = blurb._extract_section_name(section_id)
assert actual == section_name
assert actual == blurb.sections[section_index]

res = blurb._update_blurb_template(issue=None, section=section_id)
res = res.splitlines()

for index, _ in enumerate(blurb.sections):
if index == section_index:
assert f'.. section: {blurb.sections[index]}' in res
else:
assert f'#.. section: {blurb.sections[index]}' in res
assert f'.. section: {blurb.sections[index]}' not in res


@pytest.mark.parametrize('section', ['-1', '0', '1337'])
def test_invalid_section_id(section):
error_message = re.escape(f'Invalid section ID: {int(section)}')
error_message = re.compile(rf'{error_message}\n\n.+', re.MULTILINE)
with pytest.raises(SystemExit, match=error_message):
blurb._extract_section_name(section)

with pytest.raises(SystemExit, match=error_message):
blurb._update_blurb_template(issue=None, section=section)


class TestValidSectionNames:
@staticmethod
def check(section, expect):
Expand Down Expand Up @@ -189,7 +149,7 @@ def test_empty_section_name(section):

@pytest.mark.parametrize('section', ['libraryy', 'Not a section'])
def test_invalid_section_name(section):
error_message = re.escape(f'Invalid section name: {section}')
error_message = re.escape(f'Invalid section name: {section!r}')
error_message = re.compile(rf'{error_message}\n\n.+', re.MULTILINE)
with pytest.raises(SystemExit, match=error_message):
blurb._extract_section_name(section)
Expand All @@ -200,14 +160,16 @@ def test_invalid_section_name(section):

@pytest.mark.parametrize(('section', 'matches'), [
# 'matches' must be a sorted sequence of matching section names
('c', ['C API', 'Core and Builtins']),
('C', ['C API', 'Core and Builtins']),
('t', ['Tests', 'Tools/Demos']),
('T', ['Tests', 'Tools/Demos']),
])
def test_ambiguous_section_name(section, matches):
match 54BB ing_list = ', '.join(map(repr, matches))
error_message = re.escape(f'More than one match for: {section}\n'
error_message = re.escape(f'More than one match for: {section!r}\n'
f'Matches: {matching_list}')
error_message = re.compile(rf'{error_message}\n\n.+', re.MULTILINE)
error_message = re.compile(rf'{error_message}', re.MULTILINE)
with pytest.raises(SystemExit, match=error_message):
blurb._extract_section_name(section)

Expand Down
0