From 08b35f8c63a775b1c0eb107a9126360c7e58fc50 Mon Sep 17 00:00:00 2001 From: ncoop57 Date: Mon, 30 Dec 2024 12:34:42 -0600 Subject: [PATCH 1/2] Add support for version flag in Param class --- fastcore/script.py | 10 +++-- nbs/08_script.ipynb | 91 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 91 insertions(+), 10 deletions(-) diff --git a/fastcore/script.py b/fastcore/script.py index ccec772c..23d81f34 100644 --- a/fastcore/script.py +++ b/fastcore/script.py @@ -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})" diff --git a/nbs/08_script.ipynb b/nbs/08_script.ipynb index 94e60638..6b466caf 100644 --- a/nbs/08_script.ipynb +++ b/nbs/08_script.ipynb @@ -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", @@ -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", @@ -398,7 +402,7 @@ "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", @@ -406,8 +410,9 @@ " 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" ] @@ -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", @@ -426,6 +432,77 @@ "p.print_help()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also check the version and help flaggs are working (you can ignore the error message below, this is expected behavior)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "progname 2.0.0\n" + ] + }, + { + "ename": "SystemExit", + "evalue": "0", + "output_type": "error", + "traceback": [ + "An exception has occurred, use %tb to see the full traceback.\n", + "\u001b[0;31mSystemExit\u001b[0m\u001b[0;31m:\u001b[0m 0\n" + ] + } + ], + "source": [ + "p.parse_args(['--v'])" + ] + }, + { + "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" + ] + }, + { + "ename": "SystemExit", + "evalue": "0", + "output_type": "error", + "traceback": [ + "An exception has occurred, use %tb to see the full traceback.\n", + "\u001b[0;31mSystemExit\u001b[0m\u001b[0;31m:\u001b[0m 0\n" + ] + } + ], + "source": [ + "p.parse_args(['-h'])" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -450,7 +527,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" From 35fad3ba18435d9c54e7b19b58e3390ea258d034 Mon Sep 17 00:00:00 2001 From: ncoop57 Date: Mon, 30 Dec 2024 12:40:15 -0600 Subject: [PATCH 2/2] Update version and help flag test in notebook --- nbs/08_script.ipynb | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/nbs/08_script.ipynb b/nbs/08_script.ipynb index 6b466caf..905d3263 100644 --- a/nbs/08_script.ipynb +++ b/nbs/08_script.ipynb @@ -436,7 +436,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We can also check the version and help flaggs are working (you can ignore the error message below, this is expected behavior)" + "We can also check the version and help flaggs are working." ] }, { @@ -450,19 +450,11 @@ "text": [ "progname 2.0.0\n" ] - }, - { - "ename": "SystemExit", - "evalue": "0", - "output_type": "error", - "traceback": [ - "An exception has occurred, use %tb to see the full traceback.\n", - "\u001b[0;31mSystemExit\u001b[0m\u001b[0;31m:\u001b[0m 0\n" - ] } ], "source": [ - "p.parse_args(['--v'])" + "try: p.parse_args(['--v'])\n", + "except: pass" ] }, { @@ -488,19 +480,11 @@ " --b B param 2 (default: test)\n", " --c {aa,bb,cc} param 3 (default: aa)\n" ] - }, - { - "ename": "SystemExit", - "evalue": "0", - "output_type": "error", - "traceback": [ - "An exception has occurred, use %tb to see the full traceback.\n", - "\u001b[0;31mSystemExit\u001b[0m\u001b[0;31m:\u001b[0m 0\n" - ] } ], "source": [ - "p.parse_args(['-h'])" + "try: p.parse_args(['-h'])\n", + "except: pass" ] }, {