From 5845eec874b1455daf1321ed63c82a2fc10fe2e8 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Sun, 17 Nov 2024 13:44:59 -0800 Subject: [PATCH 01/15] Add register() to argparse docs --- Doc/library/argparse.rst | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 7638798ca2552f..a9dc2ee347eafa 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1369,6 +1369,40 @@ this API may be passed as the ``action`` parameter to and return a string which will be used when printing the usage of the program. If such method is not provided, a sensible default will be used. + .. method:: register() + + :class:`!Action` instances can call :meth:`!register` to register + custom actions, types, or other objects with a parser. This method is + called when the action is added to the parser. :meth:`!register` takes + in the following arguments: + + * *registry_name* - the name of the internal registry where the object + will be stored (e.g. ``'action'``, ``'type'``, ``'formatter_class'``). + + * *value* - a string serves as the key under which the object will be + registered. + + * *object* - the object to be registered, such as a callable or class. + + The following example shows how to register a custom type with a parser:: + + import argparse + import enum + + class WinterMonths(enum.StrEnum): + JAN = 'January' + FEB = 'February' + DEC = 'December' + WinterMonths.__name__ = 'Winter Month' + + parser = argparse.ArgumentParser() + parser.register('type', 'Winter Month', WinterMonths) + parser.add_argument('--month', type=WinterMonths, action='store') + + In this example, :meth:`!register` allows the type converter to be + referenced by its registered name instead of the class name. This approach + can improve error message clarity and provide more user-friendly output. + The parse_args() method ----------------------- From 64d443903ec5a52074f1c235cfe464178975557c Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Sun, 17 Nov 2024 13:45:45 -0800 Subject: [PATCH 02/15] Add newline --- Doc/library/argparse.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index a9dc2ee347eafa..3751d2a5e60632 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1393,6 +1393,7 @@ this API may be passed as the ``action`` parameter to JAN = 'January' FEB = 'February' DEC = 'December' + WinterMonths.__name__ = 'Winter Month' parser = argparse.ArgumentParser() From 536c4d64779eb3c5ebdd1b25668f4afc79b0f50c Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Sun, 17 Nov 2024 13:47:44 -0800 Subject: [PATCH 03/15] Formatting --- Doc/library/argparse.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 3751d2a5e60632..e6474cc79c1d7a 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1377,7 +1377,7 @@ this API may be passed as the ``action`` parameter to in the following arguments: * *registry_name* - the name of the internal registry where the object - will be stored (e.g. ``'action'``, ``'type'``, ``'formatter_class'``). + will be stored (e.g. ``action``, ``type``). * *value* - a string serves as the key under which the object will be registered. @@ -1393,7 +1393,7 @@ this API may be passed as the ``action`` parameter to JAN = 'January' FEB = 'February' DEC = 'December' - + WinterMonths.__name__ = 'Winter Month' parser = argparse.ArgumentParser() From f963b014656f8e79cd1e16d4410910ff86562de2 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Sun, 17 Nov 2024 14:01:36 -0800 Subject: [PATCH 04/15] Fix codeblock --- Doc/library/argparse.rst | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index e6474cc79c1d7a..b13858e9162672 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1386,19 +1386,23 @@ this API may be passed as the ``action`` parameter to The following example shows how to register a custom type with a parser:: - import argparse - import enum - - class WinterMonths(enum.StrEnum): - JAN = 'January' - FEB = 'February' - DEC = 'December' - - WinterMonths.__name__ = 'Winter Month' - - parser = argparse.ArgumentParser() - parser.register('type', 'Winter Month', WinterMonths) - parser.add_argument('--month', type=WinterMonths, action='store') + >>> import argparse + >>> import enum + >>> class WinterMonths(enum.StrEnum): + ... JAN = 'January' + ... FEB = 'February' + ... DEC = 'December' + ... + >>> WinterMonths.__name__ = 'Winter Month' + >>> parser = argparse.ArgumentParser() + >>> parser.register('type', 'Winter Month', WinterMonths) + >>> parser.add_argument('--month', type=WinterMonths, action='store') + _StoreAction(option_strings=['--month'], dest='month', nargs=None, const=None, default=None, type=, choices=None, required=False, help=None, metavar=None, deprecated=False) + >>> parser.parse_args(['--month','January']) + Namespace(month=) + >>> parser.parse_args(['--month','March']) + usage: python.exe -m _pyrepl [-h] [--month MONTH] + python.exe -m _pyrepl: error: argument --month: invalid Winter Month value: 'March' In this example, :meth:`!register` allows the type converter to be referenced by its registered name instead of the class name. This approach From 59c7956dd7d1e6fd8d0dae3fee1c57a27a739164 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Sun, 17 Nov 2024 14:10:13 -0800 Subject: [PATCH 05/15] Move section --- Doc/library/argparse.rst | 79 ++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index b13858e9162672..343a7a42260735 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1369,45 +1369,6 @@ this API may be passed as the ``action`` parameter to and return a string which will be used when printing the usage of the program. If such method is not provided, a sensible default will be used. - .. method:: register() - - :class:`!Action` instances can call :meth:`!register` to register - custom actions, types, or other objects with a parser. This method is - called when the action is added to the parser. :meth:`!register` takes - in the following arguments: - - * *registry_name* - the name of the internal registry where the object - will be stored (e.g. ``action``, ``type``). - - * *value* - a string serves as the key under which the object will be - registered. - - * *object* - the object to be registered, such as a callable or class. - - The following example shows how to register a custom type with a parser:: - - >>> import argparse - >>> import enum - >>> class WinterMonths(enum.StrEnum): - ... JAN = 'January' - ... FEB = 'February' - ... DEC = 'December' - ... - >>> WinterMonths.__name__ = 'Winter Month' - >>> parser = argparse.ArgumentParser() - >>> parser.register('type', 'Winter Month', WinterMonths) - >>> parser.add_argument('--month', type=WinterMonths, action='store') - _StoreAction(option_strings=['--month'], dest='month', nargs=None, const=None, default=None, type=, choices=None, required=False, help=None, metavar=None, deprecated=False) - >>> parser.parse_args(['--month','January']) - Namespace(month=) - >>> parser.parse_args(['--month','March']) - usage: python.exe -m _pyrepl [-h] [--month MONTH] - python.exe -m _pyrepl: error: argument --month: invalid Winter Month value: 'March' - - In this example, :meth:`!register` allows the type converter to be - referenced by its registered name instead of the class name. This approach - can improve error message clarity and provide more user-friendly output. - The parse_args() method ----------------------- @@ -2201,6 +2162,46 @@ Intermixed parsing .. versionadded:: 3.7 +Registering custom types or actions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. method:: register() + + It is possible to register custom actions, types, or other objects with + a parser using :meth:`!register`. This method is called when the action is + added to the parser. :meth:`!register` takes in the following arguments: + + * *registry_name* - the name of the internal registry where the object + will be stored (e.g. ``action``, ``type``). + + * *value* - a string serves as the key under which the object will be + registered. + + * *object* - the object to be registered, such as a callable or class. + + The following example shows how to register a custom type with a parser:: + + >>> import argparse + >>> import enum + >>> class WinterMonths(enum.StrEnum): + ... JAN = 'January' + ... FEB = 'February' + ... DEC = 'December' + ... + >>> WinterMonths.__name__ = 'Winter Month' + >>> parser = argparse.ArgumentParser() + >>> parser.register('type', 'Winter Month', WinterMonths) + >>> parser.add_argument('--month', type=WinterMonths, action='store') + _StoreAction(option_strings=['--month'], dest='month', nargs=None, const=None, default=None, type=, choices=None, required=False, help=None, metavar=None, deprecated=False) + >>> parser.parse_args(['--month','January']) + Namespace(month=) + >>> parser.parse_args(['--month','March']) + usage: python.exe -m _pyrepl [-h] [--month MONTH] + python.exe -m _pyrepl: error: argument --month: invalid Winter Month value: 'March' + + In this example, :meth:`!register` allows the type converter to be + referenced by its registered name instead of the class name. This approach + can improve error message clarity and provide more user-friendly output. + Exceptions ---------- From 5ac622b2f84b50c5e6a72c46433189aa0906abba Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Sun, 17 Nov 2024 14:13:07 -0800 Subject: [PATCH 06/15] Add signature --- Doc/library/argparse.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 343a7a42260735..1a28121748232d 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -2164,7 +2164,7 @@ Intermixed parsing Registering custom types or actions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. method:: register() +.. method:: ArgumentParser.register(registry_name, value, object) It is possible to register custom actions, types, or other objects with a parser using :meth:`!register`. This method is called when the action is From ef5dfd2d8f52b89b448e388c7a51158eab6857d6 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Sun, 17 Nov 2024 14:13:43 -0800 Subject: [PATCH 07/15] Add newline --- Doc/library/argparse.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 1a28121748232d..85997a845f06d4 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -2164,6 +2164,7 @@ Intermixed parsing Registering custom types or actions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + .. method:: ArgumentParser.register(registry_name, value, object) It is possible to register custom actions, types, or other objects with From 75a40240dd80b10e48b574123aa279babb97a146 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Sun, 17 Nov 2024 14:20:18 -0800 Subject: [PATCH 08/15] Fix indent --- Doc/library/argparse.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 85997a845f06d4..1415b00be5d2e4 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -2171,13 +2171,13 @@ Registering custom types or actions a parser using :meth:`!register`. This method is called when the action is added to the parser. :meth:`!register` takes in the following arguments: - * *registry_name* - the name of the internal registry where the object - will be stored (e.g. ``action``, ``type``). + * *registry_name* - the name of the internal registry where the object + will be stored (e.g. ``action``, ``type``). - * *value* - a string serves as the key under which the object will be - registered. + * *value* - a string serves as the key under which the object will be + registered. - * *object* - the object to be registered, such as a callable or class. + * *object* - the object to be registered, such as a callable or class. The following example shows how to register a custom type with a parser:: From e97fba92249cfcadbd556315303ccf8a3d0971a6 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Sun, 17 Nov 2024 14:26:35 -0800 Subject: [PATCH 09/15] Fix indent take 2 --- Doc/library/argparse.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 1415b00be5d2e4..d8e0256eb08122 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -2171,13 +2171,13 @@ Registering custom types or actions a parser using :meth:`!register`. This method is called when the action is added to the parser. :meth:`!register` takes in the following arguments: - * *registry_name* - the name of the internal registry where the object - will be stored (e.g. ``action``, ``type``). + * *registry_name* - the name of the internal registry where the object + will be stored (e.g. ``action``, ``type``). - * *value* - a string serves as the key under which the object will be - registered. + * *value* - a string serves as the key under which the object will be + registered. - * *object* - the object to be registered, such as a callable or class. + * *object* - the object to be registered, such as a callable or class. The following example shows how to register a custom type with a parser:: From d71316a0e17f6eecaae12ee010190b5934679ef5 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Sun, 17 Nov 2024 14:33:56 -0800 Subject: [PATCH 10/15] Rephrase --- Doc/library/argparse.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index d8e0256eb08122..0b61c85600c3ac 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -2177,7 +2177,7 @@ Registering custom types or actions * *value* - a string serves as the key under which the object will be registered. - * *object* - the object to be registered, such as a callable or class. + * *object* - the callable object to be registered. The following example shows how to register a custom type with a parser:: From 58091f739681ebfa82a376f4392d1dd6e2d1e2bd Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Sun, 17 Nov 2024 14:34:59 -0800 Subject: [PATCH 11/15] Simplify language --- Doc/library/argparse.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 0b61c85600c3ac..251b428b687bd5 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -2174,8 +2174,7 @@ Registering custom types or actions * *registry_name* - the name of the internal registry where the object will be stored (e.g. ``action``, ``type``). - * *value* - a string serves as the key under which the object will be - registered. + * *value* - the key under which the object will be registered. * *object* - the callable object to be registered. From 079b2c2762fa5bc221698e28fa9e15bf7860534a Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Mon, 18 Nov 2024 16:54:11 -0800 Subject: [PATCH 12/15] Address PR comments --- Doc/library/argparse.rst | 43 +++++++++++++--------------------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 251b428b687bd5..596ee6e911c5d9 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -2167,41 +2167,26 @@ Registering custom types or actions .. method:: ArgumentParser.register(registry_name, value, object) - It is possible to register custom actions, types, or other objects with - a parser using :meth:`!register`. This method is called when the action is - added to the parser. :meth:`!register` takes in the following arguments: + Sometimes it's desirable to use a custom string in error messages to provide + more user-friendly output. In these cases, :meth:`!register` can be used to + register custom actions or types with a parser and allow you to reference the + type by their registered name instead of their callable name. - * *registry_name* - the name of the internal registry where the object - will be stored (e.g. ``action``, ``type``). - - * *value* - the key under which the object will be registered. - - * *object* - the callable object to be registered. + The :meth:`!register` method accepts three arguments - a *registry_name*, + specifying the internal registry where the object will be stored (e.g., + ``action``, ``type``), *value*, which is the key under which the object will + be registered, and object, the callable to be registered. The following example shows how to register a custom type with a parser:: >>> import argparse - >>> import enum - >>> class WinterMonths(enum.StrEnum): - ... JAN = 'January' - ... FEB = 'February' - ... DEC = 'December' - ... - >>> WinterMonths.__name__ = 'Winter Month' >>> parser = argparse.ArgumentParser() - >>> parser.register('type', 'Winter Month', WinterMonths) - >>> parser.add_argument('--month', type=WinterMonths, action='store') - _StoreAction(option_strings=['--month'], dest='month', nargs=None, const=None, default=None, type=, choices=None, required=False, help=None, metavar=None, deprecated=False) - >>> parser.parse_args(['--month','January']) - Namespace(month=) - >>> parser.parse_args(['--month','March']) - usage: python.exe -m _pyrepl [-h] [--month MONTH] - python.exe -m _pyrepl: error: argument --month: invalid Winter Month value: 'March' - - In this example, :meth:`!register` allows the type converter to be - referenced by its registered name instead of the class name. This approach - can improve error message clarity and provide more user-friendly output. - + >>> parser.register('type', 'hexadecimal integer', lambda s: int(s, 16)) + >>> parser.add_argument('--foo', type='hexadecimal integer') + _StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type='hexadecimal integer', choices=None, required=False, help=None, metavar=None, deprecated=False) + >>> parser.parse_args(['--foo', '1.2']) + usage: PROG [-h] [--foo FOO] + PROG: error: argument --foo: invalid 'hexadecimal integer' value: '1.2' Exceptions ---------- From 520eb6904ee9d304ca24519771ef5a4793ea4d45 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Mon, 18 Nov 2024 17:26:36 -0800 Subject: [PATCH 13/15] Add references to register in type and action --- Doc/library/argparse.rst | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 596ee6e911c5d9..dabf9984d7cbdf 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -801,7 +801,8 @@ Only actions that consume command-line arguments (e.g. ``'store'``, The recommended way to create a custom action is to extend :class:`Action`, overriding the :meth:`!__call__` method and optionally the :meth:`!__init__` and -:meth:`!format_usage` methods. +:meth:`!format_usage` methods. You can also register custom actions using the +:meth:`~ArgumentParser.register` method and reference them by their registered name. An example of a custom action:: @@ -1023,7 +1024,9 @@ is only applied if the default is a string. The argument to ``type`` can be any callable that accepts a single string. If the function raises :exc:`ArgumentTypeError`, :exc:`TypeError`, or :exc:`ValueError`, the exception is caught and a nicely formatted error -message is displayed. No other exception types are handled. +message is displayed. Other exception types are not handled. You can also +customize how the type is displayed in error messages by registering it with +the parser using :meth:`~ArgumentParser.register`. Common built-in types and functions can be used as type converters: @@ -2162,6 +2165,8 @@ Intermixed parsing .. versionadded:: 3.7 +.. _register-custom: + Registering custom types or actions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From e710509557cb3c98e4095414c7c0cf0c442dfc51 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Mon, 18 Nov 2024 17:29:34 -0800 Subject: [PATCH 14/15] Remove unnecessary reference --- Doc/library/argparse.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index dabf9984d7cbdf..3abf6dfedc0f6a 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -2165,7 +2165,6 @@ Intermixed parsing .. versionadded:: 3.7 -.. _register-custom: Registering custom types or actions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From bec6ea1f1773677c26cfaa8b2440cdd6c2f063b4 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Tue, 19 Nov 2024 17:52:39 -0800 Subject: [PATCH 15/15] Rephrase and add success case --- Doc/library/argparse.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 3abf6dfedc0f6a..a4695547921faa 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1021,12 +1021,11 @@ necessary type-checking and type conversions to be performed. If the type_ keyword is used with the default_ keyword, the type converter is only applied if the default is a string. -The argument to ``type`` can be any callable that accepts a single string. +The argument to ``type`` can be a callable that accepts a single string or +the name of a registered type (see :meth:`~ArgumentParser.register`) If the function raises :exc:`ArgumentTypeError`, :exc:`TypeError`, or :exc:`ValueError`, the exception is caught and a nicely formatted error -message is displayed. Other exception types are not handled. You can also -customize how the type is displayed in error messages by registering it with -the parser using :meth:`~ArgumentParser.register`. +message is displayed. Other exception types are not handled. Common built-in types and functions can be used as type converters: @@ -2188,6 +2187,8 @@ Registering custom types or actions >>> parser.register('type', 'hexadecimal integer', lambda s: int(s, 16)) >>> parser.add_argument('--foo', type='hexadecimal integer') _StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type='hexadecimal integer', choices=None, required=False, help=None, metavar=None, deprecated=False) + >>> parser.parse_args(['--foo', '0xFA']) + Namespace(foo=250) >>> parser.parse_args(['--foo', '1.2']) usage: PROG [-h] [--foo FOO] PROG: error: argument --foo: invalid 'hexadecimal integer' value: '1.2'