Skip to content
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

Add version action support to Param class #662

Merged
merged 2 commits into from
Dec 30, 2024
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
10 changes: 7 additions & 3 deletions fastcore/script.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,20 @@ def clean_type_str(x:str):
class Param:
"A parameter in a function used in `anno_parser` or `call_parse`"
def __init__(self, help="", type=None, opt=True, action=None, nargs=None, const=None,
choices=None, required=None, default=None):
if type in (store_true,bool): type,action,default=None,'store_true' ,False
choices=None, required=None, default=None, version=None):
if type in (store_true,bool): type,action,default=None,'store_true',False
if type==store_false: type,action,default=None,'store_false',True
if type and isinstance(type,typing.Type) and issubclass(type,enum.Enum) and not choices: choices=list(type)
help = help or ""
store_attr()

def set_default(self, d):
if self.action == "version":
if d != inspect.Parameter.empty: self.version = d
self.opt = True
return
if self.default is None:
if d==inspect.Parameter.empty: self.opt = False
if d == inspect.Parameter.empty: self.opt = False
else: self.default = d
if self.default is not None:
self.help += f" (default: {self.default})"
Expand Down
75 changes: 68 additions & 7 deletions nbs/08_script.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -246,16 +246,20 @@
"class Param:\n",
" \"A parameter in a function used in `anno_parser` or `call_parse`\"\n",
" def __init__(self, help=\"\", type=None, opt=True, action=None, nargs=None, const=None,\n",
" choices=None, required=None, default=None):\n",
" if type in (store_true,bool): type,action,default=None,'store_true' ,False\n",
" choices=None, required=None, default=None, version=None):\n",
" if type in (store_true,bool): type,action,default=None,'store_true',False\n",
" if type==store_false: type,action,default=None,'store_false',True\n",
" if type and isinstance(type,typing.Type) and issubclass(type,enum.Enum) and not choices: choices=list(type)\n",
" help = help or \"\"\n",
" store_attr()\n",
"\n",
" def set_default(self, d):\n",
" if self.action == \"version\":\n",
" if d != inspect.Parameter.empty: self.version = d\n",
" self.opt = True\n",
" return\n",
" if self.default is None:\n",
" if d==inspect.Parameter.empty: self.opt = False\n",
" if d == inspect.Parameter.empty: self.opt = False\n",
" else: self.default = d\n",
" if self.default is not None:\n",
" self.help += f\" (default: {self.default})\"\n",
Expand Down Expand Up @@ -288,7 +292,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Each parameter in your function should have an annotation `Param(...)`. You can pass the following when calling `Param`: `help`,`type`,`opt`,`action`,`nargs`,`const`,`choices`,`required` (i.e. it takes the same parameters as `argparse.ArgumentParser.add_argument`, plus `opt`). Except for `opt`, all of these are just passed directly to `argparse`, so you have all the power of that module at your disposal. Generally you'll want to pass at least `help` (since this is provided as the help string for that parameter) and `type` (to ensure that you get the type of data you expect).\n",
"Each parameter in your function should have an annotation `Param(...)`. You can pass the following when calling `Param`: `help`,`type`,`opt`,`action`,`nargs`,`const`,`choices`,`required`, `version` (i.e. it takes the same parameters as `argparse.ArgumentParser.add_argument`, plus `opt`). Except for `opt`, all of these are just passed directly to `argparse`, so you have all the power of that module at your disposal. Generally you'll want to pass at least `help` (since this is provided as the help string for that parameter) and `type` (to ensure that you get the type of data you expect).\n",
"\n",
"`opt` is a bool that defines whether a param is optional or required (positional) - but you'll generally not need to set this manually, because fastcore.script will set it for you automatically based on *default* values. You should provide a default (after the `=`) for any *optional* parameters. If you don't provide a default for a parameter, then it will be a *positional* parameter.\n",
"\n",
Expand Down Expand Up @@ -398,16 +402,17 @@
"name": "stdout",
"output_type": "stream",
"text": [
"usage: progname [-h] [--b B] [--c {aa,bb,cc}] required a\n",
"usage: progname [-h] [--v] [--b B] [--c {aa,bb,cc}] required a\n",
"\n",
"my docs\n",
"\n",
"positional arguments:\n",
" required Required param\n",
" a param 1\n",
"\n",
"optional arguments:\n",
"options:\n",
" -h, --help show this help message and exit\n",
" --v Print version\n",
" --b B param 2 (default: test)\n",
" --c {aa,bb,cc} param 3 (default: aa)\n"
]
Expand All @@ -417,6 +422,7 @@
"_en = str_enum('_en', 'aa','bb','cc')\n",
"def f(required:Param(\"Required param\", int),\n",
" a:Param(\"param 1\", bool_arg),\n",
" v:Param(\"Print version\", action='version', version='%(prog)s 2.0.0'),\n",
" b:Param(\"param 2\", str)=\"test\",\n",
" c:Param(\"param 3\", _en)=_en.aa):\n",
" \"my docs\"\n",
Expand All @@ -426,6 +432,61 @@
"p.print_help()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can also check the version and help flaggs are working."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"progname 2.0.0\n"
]
}
],
"source": [
"try: p.parse_args(['--v'])\n",
"except: pass"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"usage: progname [-h] [--v] [--b B] [--c {aa,bb,cc}] required a\n",
"\n",
"my docs\n",
"\n",
"positional arguments:\n",
" required Required param\n",
" a param 1\n",
"\n",
"options:\n",
" -h, --help show this help message and exit\n",
" --v Print version\n",
" --b B param 2 (default: test)\n",
" --c {aa,bb,cc} param 3 (default: aa)\n"
]
}
],
"source": [
"try: p.parse_args(['-h'])\n",
"except: pass"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand All @@ -450,7 +511,7 @@
" required Required param\n",
" a param 1\n",
"\n",
"optional arguments:\n",
"options:\n",
" -h, --help show this help message and exit\n",
" --b B param 2 (default: test)\n",
" --c {aa,bb,cc} param 3 (default: aa)\n"
Expand Down
Loading