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

Conversation

picnixz
Copy link
Member

@picnixz picnixz commented Jun 25, 2024

Fixes #6. This is an alternative to #15.

@hugovk I've taken out your way of handling positional arguments (but would you consider a PR which refactors blurb in order to use argparse instead?). If you prefer --gh, I can also rename the variable!

@hugovk
Copy link
Member

hugovk commented Jun 25, 2024

would you consider a PR which refactors blurb in order to use argparse instead?

That could make things easier, but I've not used subcommands much in argparse, how are they? We'd need to make sure all the commands and options work in the same way, blurb is used in a few different bits of automation and we wouldn't want to break any of them.

@picnixz
Copy link
Member Author

picnixz commented Jun 26, 2024

That could make things easier, but I've not used subcommands much in argparse, how are they? We'd need to make sure all the commands and options work in the same way, blurb is used in a few different bits of automation and we wouldn't want to break any of them.

From my personal usage of subcommands, it works the same. Actually, a subcommand is just an action that invokes an ArgumentParser. However, it might indeed come with some corner cases which I would first extensively test. If you can tell me where it's being used in automaton parts, then I'd be glad to check if I can make the transition.

@hugovk
Copy link
Member

hugovk commented Jun 26, 2024

@hugovk hugovk added the enhancement New feature or request label Jun 26, 2024
Copy link
Contributor

@larryhastings larryhastings left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some initial comments. I'll confer further with Hugo.

@picnixz
Copy link
Member Author

picnixz commented Jul 12, 2024

Thank you Larry for your comments. I'll address them tomorrow (I don't have access to the project now)

picnixz added 5 commits July 13, 2024 09:35
- remove section IDs matching
- do not render the table in case of a multi-match
- simplify `add` docstring construction
- update tests
- update README.md
picnixz and others added 3 commits July 13, 2024 11:32
Co-authored-by: Hugo van Kemenade <[email protected]>
Co-authored-by: Hugo van Kemenade <[email protected]>
Copy link
Member

@hugovk hugovk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing matching the sections, blurb add --section core works, but not:

blurb add --section built
Invalid section name: 'built'

Choose from the following table:

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

Or:

blurb add --section api
Invalid section name: 'api'

Choose from the following table:

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

Should they?

Co-authored-by: Hugo van Kemenade <[email protected]>
@picnixz
Copy link
Member Author

picnixz commented Jul 13, 2024

Mmmh, I think I only matched from the beginning, not inside. Otherwise, you write 'l' and have a lot of matches (library, core and builtins, tools, etc). And I didn't want to special cases. But maybe we can use aliases? I don't remember now if 'capi' works (but maybe it should)

@hugovk
Copy link
Member

hugovk commented Jul 13, 2024

Mmmh, I think I only matched from the beginning, not inside. Otherwise, you write 'l' and have a lot of matches (library, core and builtins, tools, etc).

Yeah, that's not so useful.

And I didn't want to special cases. But maybe we can use aliases? I don't remember now if 'capi' works (but maybe it should)

"capi" doesn't work:

blurb add --section capi
Invalid section name: 'capi'

Choose from the following table:

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

I don't think we necessarily need to match "builtins" -> "Core and Builtins" or "demo" -> "Tools/Demos", but "capi" -> "C API" would help, and maybe also "api" -> "C API"?

@picnixz
Copy link
Member Author

picnixz commented Jul 13, 2024

I don't think we necessarily need to match "builtins" -> "Core and Builtins" or "demo" -> "Tools/Demos", but "capi" -> "C API" would help, and maybe also "api" -> "C API"?

I ended up making them match like that (the tests should reflect what is now possible). I don't have a better way to cover the use cases so don't hesistate to tell me which cases should be checked.

@larryhastings
Copy link
Contributor

Would it be sufficient to create a "nickname map", like

{ "".join(section.split()).lower(): section for section in sections }

@picnixz
Copy link
Member Author

picnixz commented Jul 13, 2024

{ "".join(section.split()).lower(): section for section in sections }

Yes. But to construct additional patterns, I needed to use:

    _sanitized = re.sub(r'[ /]', ' ', _section)
    _section_words = re.split(r'\s+', _sanitized)
    _section_names_lower_nosep[_section] = ''.join(_section_words).lower()

(Your suggestion is in my case implemented as ''.join(_section_words).lower())

@hugovk hugovk changed the title gh-6: add -i/--issue and -s/--section flags to blurb add Add -i/--issue and -s/--section flags to blurb add Jun 2, 2025
Copy link
Member

@hugovk hugovk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not fully sold on the smart matching, I don't think we need to worry about things like blurb add --section "cOre _ and - bUILtins".

Would case-insensitive substring matching be enough, as long as the substring is unique?

So these would work:

blurb add --section mac
blurb add --section core
blurb add --section build
blurb add --section built

But not:

blurb add --section buil
blurb add --section i

Comment on lines +835 to +836
if issue.startswith('gh-'):
issue = issue[3:]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if issue.startswith('gh-'):
issue = issue[3:]
issue = issue.removeprefix('gh-')

Comment on lines +866 to +874
del _sanitized
# '_', '-', ' ' and '/' are the allowed (user) separators
_section_pattern = r'[_\- /]?'.join(map(re.escape, _section_words))
# add '$' to avoid matching after the pattern
_section_pattern = f'{_section_pattern}$'
del _section_words
_section_pattern = re.compile(_section_pattern, re.I)
_section_special_patterns[_section].add(_section_pattern)
del _section_pattern, _section
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need these dels?

Suggested change
del _sanitized
# '_', '-', ' ' and '/' are the allowed (user) separators
_section_pattern = r'[_\- /]?'.join(map(re.escape, _section_words))
# add '$' to avoid matching after the pattern
_section_pattern = f'{_section_pattern}$'
del _section_words
_section_pattern = re.compile(_section_pattern, re.I)
_section_special_patterns[_section].add(_section_pattern)
del _section_pattern, _section
# '_', '-', ' ' and '/' are the allowed (user) separators
_section_pattern = r'[_\- /]?'.join(map(re.escape, _section_words))
# add '$' to avoid matching after the pattern
_section_pattern = f'{_section_pattern}$'
_section_pattern = re.compile(_section_pattern, re.I)
_section_special_patterns[_section].add(_section_pattern)

Comment on lines +1065 to +1069
del _sec_name_width
sections_table = '\n'.join(map(_format_row, sections))
del _format_row
sections_table = '\n'.join((_sec_row_rule, sections_table, _sec_row_rule))
del _sec_row_rule
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
del _sec_name_width
sections_table = '\n'.join(map(_format_row, sections))
del _format_row
sections_table = '\n'.join((_sec_row_rule, sections_table, _sec_row_rule))
del _sec_row_rule
sections_table = '\n'.join(map(_format_row, sections))
sections_table = '\n'.join((_sec_row_rule, sections_table, _sec_row_rule))

Comment on lines +86 to +88
def check(section, expect):
actual = blurb._extract_section_name(section)
assert actual == expect
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To match the other test files:

Suggested change
def check(section, expect):
actual = blurb._extract_section_name(section)
assert actual == expect
def check(section, expected):
actual = blurb._extract_section_name(section)
assert actual == expected

res = blurb._update_blurb_template(issue=None, section=section)
res = res.splitlines()
for section_name in blurb.sections:
if section_name == expect:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if section_name == expect:
if section_name == expected:

Comment on lines +100 to +107
('section', 'expect'),
tuple(zip(blurb.sections, blurb.sections))
)
def test_exact_names(self, section, expect):
self.check(section, expect)

@pytest.mark.parametrize(
('section', 'expect'), [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
('section', 'expect'),
tuple(zip(blurb.sections, blurb.sections))
)
def test_exact_names(self, section, expect):
self.check(section, expect)
@pytest.mark.parametrize(
('section', 'expect'), [
('section', 'expected'),
tuple(zip(blurb.sections, blurb.sections))
)
def test_exact_names(self, section, expected):
self.check(section, expected)
@pytest.mark.parametrize(
('section', 'expected'), [

Comment on lines +130 to +134
def test_partial_words(self, section, expect):
self.check(section, expect)

@pytest.mark.parametrize(
('section', 'expect'), [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def test_partial_words(self, section, expect):
self.check(section, expect)
@pytest.mark.parametrize(
('section', 'expect'), [
def test_partial_words(self, section, expected):
self.check(section, expected)
@pytest.mark.parametrize(
('section', 'expected'), [

Comment on lines +146 to +150
def test_partial_special_names(self, section, expect):
self.check(section, expect)

@pytest.mark.parametrize(
('section', 'expect'), [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def test_partial_special_names(self, section, expect):
self.check(section, expect)
@pytest.mark.parametrize(
('section', 'expect'), [
def test_partial_special_names(self, section, expected):
self.check(section, expected)
@pytest.mark.parametrize(
('section', 'expected'), [

Comment on lines +165 to +170
def test_partial_separators(self, section, expect):
# normalize the separtors '_', '-', ' ' and '/'
self.check(section, expect)

@pytest.mark.parametrize(
('prefix', 'expect'), [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plus a typo

Suggested change
def test_partial_separators(self, section, expect):
# normalize the separtors '_', '-', ' ' and '/'
self.check(section, expect)
@pytest.mark.parametrize(
('prefix', 'expect'), [
def test_partial_separators(self, section, expected):
# normalize the separators '_', '-', ' ' and '/'
self.check(section, expected)
@pytest.mark.parametrize(
('prefix', 'expected'), [

Comment on lines +184 to +200
def test_partial_prefix_words(self, prefix, expect):
# try to find a match using prefixes (without separators and lowercase)
self.check(prefix, expect)

@pytest.mark.parametrize(
('section', 'expect'),
[(name.lower(), name) for name in blurb.sections],
)
def test_exact_names_lowercase(self, section, expect):
self.check(section, expect)

@pytest.mark.parametrize(
('section', 'expect'),
[(name.upper(), name) for name in blurb.sections],
)
def test_exact_names_uppercase(self, section, expect):
self.check(section, expect)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def test_partial_prefix_words(self, prefix, expect):
# try to find a match using prefixes (without separators and lowercase)
self.check(prefix, expect)
@pytest.mark.parametrize(
('section', 'expect'),
[(name.lower(), name) for name in blurb.sections],
)
def test_exact_names_lowercase(self, section, expect):
self.check(section, expect)
@pytest.mark.parametrize(
('section', 'expect'),
[(name.upper(), name) for name in blurb.sections],
)
def test_exact_names_uppercase(self, section, expect):
self.check(section, expect)
def test_partial_prefix_words(self, prefix, expected):
# try to find a match using prefixes (without separators and lowercase)
self.check(prefix, expected)
@pytest.mark.parametrize(
('section', 'expected'),
[(name.lower(), name) for name in blurb.sections],
)
def test_exact_names_lowercase(self, section, expected):
self.check(section, expected)
@pytest.mark.parametrize(
('section', 'expected'),
[(name.upper(), name) for name in blurb.sections],
)
def test_exact_names_uppercase(self, section, expected):
self.check(section, expected)

@picnixz
Copy link
Member Author

picnixz commented Jul 1, 2025

I think it would be enough.

gpshead added a commit to gpshead/blurb that referenced this pull request Jul 4, 2025
Integrate the user-friendly features from PR python#16 by @picnixz into the
automation support from PR python#45, making the CLI more intuitive:

- Change --gh-issue to --issue, accepting multiple formats:
  * Plain numbers: --issue 12345
  * With gh- prefix: --issue gh-12345
  * GitHub URLs: --issue python/cpython#12345

- Add smart section matching with:
  * Case-insensitive matching: --section lib matches "Library"
  * Partial matching: --section doc matches "Documentation"
  * Common aliases: --section api matches "C API"
  * Separator normalization: --section core-and-builtins

- Improve error messages for invalid sections

This combines the automation features from PR python#45 with the interface
improvements suggested by @picnixz in PR python#16, as reviewed by @hugovk
and @larryhastings.

Co-authored-by: picnixz <[email protected]>
gpshead added a commit to gpshead/blurb that referenced this pull request Jul 4, 2025
Integrate the user-friendly features from PR python#16 by @picnixz into the automation support from PR python#45, making the CLI more intuitive:

- Change --gh-issue to --issue, accepting multiple formats:
  * Plain numbers: --issue 12345
  * With gh- prefix: --issue gh-12345
  * GitHub URLs: --issue python/cpython#12345

- Add smart section matching with:
  * Case-insensitive matching: --section lib matches "Library"
  * Partial matching: --section doc matches "Documentation"
  * Common aliases: --section api matches "C API"
  * Separator normalization: --section core-and-builtins

- Improve error messages for invalid sections

This combines the automation features from PR python#45 with the interface improvements suggested by @picnixz in PR python#16, as reviewed by @hugovk and @larryhastings.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add --gh and --section flags to "blurb add"
3 participants