0.13.0a5 add LetterSubparsers.add_verbose()

This commit is contained in:
Yusur 2026-06-01 11:34:47 +02:00
parent 4f1c1226c3
commit a3a58ac782
3 changed files with 47 additions and 11 deletions

View file

@ -2,7 +2,8 @@
## 0.13.0
+ Added module `argparse` with class `LetterSubparsers()`
+ Added module `argparse` with class `LetterSubparsers()`, which allows pacman-style args by preprocessing them
before feeding them to parse_args
+ Module `sqlalchemy`:
* removed deprecated alias `entity_base()`. use `declarative_base()` instead.
* fix imports.

View file

@ -41,7 +41,7 @@ from .color import OKLabColor, chalk, WebColor, RGBColor, LinearRGBColor, \
from .mat import Matrix
from .argparse import LetterSubparsers
__version__ = "0.13.0a4"
__version__ = "0.13.0a5"
__all__ = (
'ColorFormatter',

View file

@ -33,12 +33,22 @@ class LetterSubparsers(object):
_parser: argparse.ArgumentParser
_letters: dict[str, str]
_subparsers: argparse._SubParsersAction[argparse.ArgumentParser]
_has_verbose: bool = False
def __init__(self, parser : argparse.ArgumentParser, *, dest: str = 'action', **kwargs):
self._parser = parser
self._letters = {}
self._subparsers = parser.add_subparsers(dest = dest, **kwargs)
def add_verbose(self, *, help: str = "show more logs (e.g. debug)"):
"""
Add a "-v" / "--verbose" argument to the main parser.
This allows the argument to be everywhere in the argv.
"""
self._parser.add_argument('-v', '--verbose', action='count', help=help)
self._has_verbose = True
def action(self, /, letter: str, name: str | None = None, **kwargs):
"""
Decorator which adds a subparser of an argument parser's subparsers, and specifies a letter to make a shorthand in pacman style.
@ -65,11 +75,11 @@ class LetterSubparsers(object):
return func
return decorator
def parse_args(self, argv = None, system_exit: bool = True):
def parse_args(self, argv: list[str] = None, system_exit: bool = True):
"""
Variation of ArgumentParser.parse_args() that takes shortcut letters into account.
Best used together with letter_action().
Best used together with .action().
"""
if argv is None:
@ -77,15 +87,21 @@ class LetterSubparsers(object):
else:
argv = list(argv)
opt_start = 0
# preprocess the letters
if len(argv) > 0:
first_arg = argv.pop(0)
if first_arg.startswith('-') and len(first_arg) >= 2:
letter, rest = first_arg[1], first_arg[2:]
if letter in self._letters:
argv.insert(0, self._letters[letter])
if rest:
argv.insert(1, "-" + rest)
for idx, letter in enumerate(first_arg):
rest = first_arg[1:idx] + first_arg[idx+1:]
if letter in self._letters:
argv.insert(0, self._letters[letter])
if rest:
argv.insert(1, "-" + rest)
opt_start = 1
break
else:
# put it back
argv.insert(0, first_arg)
@ -93,12 +109,31 @@ class LetterSubparsers(object):
# put it back
argv.insert(0, first_arg)
# preprocess the verbose
if self._has_verbose and len(argv) > opt_start:
nargv = argv[:opt_start]
vc = 0
for arg in argv[opt_start:]:
if arg.startswith('-') and not arg.startswith('--'):
arg_vc = sum(1 for l in arg[1:] if l == 'v')
arg_vless = arg.replace('v', '')
if arg_vless != '-':
nargv.append(arg_vless)
vc += arg_vc
elif arg == '--verbose':
vc += 1
else:
nargv.append(arg)
argv = ["--verbose"] * vc + nargv
try:
return self._parser.parse_args(argv)
args = self._parser.parse_args(argv)
except SystemExit:
# prevent SystemExit at parse fail
if system_exit:
raise
else:
return args
__all__ = ('LetterSubparsers',)