Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 3 additions & 2 deletions fastcore/script.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def main(msg:Annotated[str, "The message"],

## Short flags

A capital letter in a parameter name declares a short flag: the capitalized letter becomes the short spelling and the lowercased name the long one, so `Resume:int=None` gets both `-r` and `--resume`. The capital can be any letter (`sUggest:str=None` gives `-u/--suggest`), only the first capital counts, and names without capitals get a long flag only. Since the flags are lowercased, the parameter's actual name keeps its capital -- so a Python caller writes `main(Resume=3)`, which usefully advertises that it's invoking a CLI entry point. Positional (default-less) parameters have no flags, so capitals there are left alone.
A capital letter in a parameter name declares a short flag: the capitalized letter becomes the short spelling and the lowercased name the long one, so `Resume:int=None` gets both `-r` and `--resume`. The capital can be any letter (`sUggest:str=None` gives `-u/--suggest`), only the first capital counts, and names without capitals get a long flag only. Underscores in optional parameter names appear as hyphens (`cache_dir` becomes `--cache-dir`), while the Python argument keeps its underscore. Since the flags are lowercased, the parameter's actual name keeps its capital -- so a Python caller writes `main(Resume=3)`, which usefully advertises that it's invoking a CLI entry point. Positional (default-less) parameters have no flags, so capitals there are left alone.

## Positional params

Expand Down Expand Up @@ -141,7 +141,7 @@ def _arg_kw(k, anno, doc, default, extra, mv=None):
else: action,d = 'store_true',False
if action=='version':
if 'version' not in extra and d is not inspect.Parameter.empty: extra['version'] = d
return f'--{k}', {'help':doc or '', **extra}
return f'--{k.replace("_", "-")}', {'help':doc or '', **extra}
kw = {}
if action and 'action' not in extra: kw['action'] = action
if anno is not None:
Expand All @@ -154,6 +154,7 @@ def _arg_kw(k, anno, doc, default, extra, mv=None):
kw['help'] = (doc or '') + (f" (default: {dshow})" if 'default' in kw else '')
if negated: kw['dest'] = k
name = f'no-{k}' if negated else k
if opt: name = name.replace('_', '-')
short = first(c for c in k if c.isupper()) if opt else None
if short is None: return f"{'--' if opt else ''}{name}", {**kw, **extra}
kw['dest'] = k # flags are lowercased, so argparse's derived dest would drop the capital
Expand Down
9 changes: 5 additions & 4 deletions nbs/06_script.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@
"#| export\n",
"## Short flags\n",
"\n",
"A capital letter in a parameter name declares a short flag: the capitalized letter becomes the short spelling and the lowercased name the long one, so `Resume:int=None` gets both `-r` and `--resume`. The capital can be any letter (`sUggest:str=None` gives `-u/--suggest`), only the first capital counts, and names without capitals get a long flag only. Since the flags are lowercased, the parameter's actual name keeps its capital -- so a Python caller writes `main(Resume=3)`, which usefully advertises that it's invoking a CLI entry point. Positional (default-less) parameters have no flags, so capitals there are left alone."
"A capital letter in a parameter name declares a short flag: the capitalized letter becomes the short spelling and the lowercased name the long one, so `Resume:int=None` gets both `-r` and `--resume`. The capital can be any letter (`sUggest:str=None` gives `-u/--suggest`), only the first capital counts, and names without capitals get a long flag only. Underscores in optional parameter names appear as hyphens (`cache_dir` becomes `--cache-dir`), while the Python argument keeps its underscore. Since the flags are lowercased, the parameter's actual name keeps its capital -- so a Python caller writes `main(Resume=3)`, which usefully advertises that it's invoking a CLI entry point. Positional (default-less) parameters have no flags, so capitals there are left alone."
]
},
{
Expand Down Expand Up @@ -295,7 +295,7 @@
" else: action,d = 'store_true',False\n",
" if action=='version':\n",
" if 'version' not in extra and d is not inspect.Parameter.empty: extra['version'] = d\n",
" return f'--{k}', {'help':doc or '', **extra}\n",
" return f'--{k.replace(\"_\", \"-\")}', {'help':doc or '', **extra}\n",
" kw = {}\n",
" if action and 'action' not in extra: kw['action'] = action\n",
" if anno is not None:\n",
Expand All @@ -308,6 +308,7 @@
" kw['help'] = (doc or '') + (f\" (default: {dshow})\" if 'default' in kw else '')\n",
" if negated: kw['dest'] = k\n",
" name = f'no-{k}' if negated else k\n",
" if opt: name = name.replace('_', '-')\n",
" short = first(c for c in k if c.isupper()) if opt else None\n",
" if short is None: return f\"{'--' if opt else ''}{name}\", {**kw, **extra}\n",
" kw['dest'] = k # flags are lowercased, so argparse's derived dest would drop the capital\n",
Expand Down Expand Up @@ -371,9 +372,9 @@
"metadata": {},
"outputs": [],
"source": [
"test_eq(_arg_kw('a', int, 'help', 1, {}), ('--a', dict(type=int, default=1, help='help (default: 1)')))\n",
"test_eq(_arg_kw('some_flag', int, 'help', 1, {}), ('--some-flag', dict(type=int, default=1, help='help (default: 1)')))\n",
"test_eq(_arg_kw('a', int, 'help', inspect.Parameter.empty, {}), ('a', dict(type=int, help='help')))\n",
"test_eq(_arg_kw('up', bool, 'upper?', True, {}), ('--no-up', dict(action='store_false', default=True, help='upper? (default: True)', dest='up')))\n",
"test_eq(_arg_kw('some_flag', bool, 'enabled?', True, {}), ('--no-some-flag', dict(action='store_false', default=True, help='enabled? (default: True)', dest='some_flag')))\n",
"test_eq(_arg_kw('p', str, 'path', inspect.Parameter.empty, dict(opt=False, nargs='?', default='-')),\n",
" ('p', dict(type=str, default='-', help='path (default: -)', nargs='?')))\n",
"test_eq(_arg_kw('a', int, 'help', 1, {}, 'int'), ('--a', dict(type=int, default=1, help='help (default: 1)', metavar='(int)')))\n",
Expand Down