@@ -383,24 +383,6 @@ will work as expected. Additionally, the following cases are also valid:
383383 --o2=val2b `` would result in ``o2=val2a ``.
384384
385385
386- Functions as type
387- -----------------
388-
389- Using a function as a type, like ``int_or_off `` below, is supported though
390- discouraged. A basic requirement is that the function be idempotent, i.e.,
391- applying the function two or more times should not modify the value. Instead of
392- a function, it is recommended to implement a type, see :ref: `custom-types `.
393-
394- .. testcode ::
395-
396- # either int larger than zero or 'off' string
397- def int_or_off(x):
398- return x if x == "off" else int(x)
399-
400-
401- parser.add_argument("--int_or_off", type=int_or_off)
402-
403-
404386Always fail arguments
405387---------------------
406388
@@ -2649,17 +2631,19 @@ variables.
26492631Subcommands
26502632===========
26512633
2652- One way to define parsers modularly is what in argparse is known as
2653- `subcommands <https://docs.python.org/3/library/argparse.html#subcommands >`__.
2654- However, to promote modularity, in jsonargparse subcommands work a bit
2655- different from argparse. To add subcommands to a parser, the
2656- :meth: `add_subcommands <.ArgumentParser.add_subcommands> ` method is used. Then
2657- an existing parser is added as a subcommand using :meth: `add_subcommand
2658- <.ActionSubCommands.add_subcommand> `. In a parsed
2659- config object the subcommand will be stored in the ``subcommand `` entry (or
2660- whatever ``dest `` was set to), and the values of the subcommand will be in an
2661- entry with the same name as the respective subcommand. An example of defining a
2662- parser with subcommands is the following:
2634+ Subcommands provide a modular approach to defining parsers, similar to the
2635+ concept of `subcommands
2636+ <https://docs.python.org/3/library/argparse.html#subcommands> `__ in argparse.
2637+ However, in jsonargparse, subcommands behave somewhat differently; refer to
2638+ :ref: `argparse-deviations ` for further details.
2639+
2640+ To incorporate subcommands into a parser, use the :meth: `add_subcommands
2641+ <.ArgumentParser.add_subcommands> ` method. You can then add an existing parser
2642+ as a subcommand via :meth: `add_subcommand <.ActionSubCommands.add_subcommand> `.
2643+ In the resulting parsed namespace, the selected subcommand is stored under the
2644+ ``subcommand `` key (or the key specified by ``dest ``), and the arguments for the
2645+ subcommand are nested under a key matching the subcommand's name. The following
2646+ example demonstrates how to define a parser with subcommands:
26632647
26642648.. testcode ::
26652649
@@ -3029,6 +3013,105 @@ it as follows:
30293013 $ example.py --bool false
30303014
30313015
3016+ .. _argparse-deviations :
3017+
3018+ Deviations from argparse
3019+ ========================
3020+
3021+ To ensure a high level of compatibility with argparse, the argparse tests from
3022+ the Python standard library are run against jsonargparse. Some of these tests
3023+ are skipped for the following reasons: 1) they cover intentional deviations from
3024+ argparse, 2) they are not relevant for jsonargparse, or 3) they are under
3025+ investigation and may be enabled in the future. The tests to skip are configured
3026+ in the ``argparse_tests_generate.py `` file.
3027+
3028+ The following sections describe the main intentional deviations from argparse.
3029+ In addition, deprecated features in argparse are not supported.
3030+
3031+ Subcommands
3032+ -----------
3033+
3034+ In argparse, when a parser has subcommands, the resulting namespace merges the
3035+ main parser and subparser options into a single flat namespace. Since
3036+ jsonargparse supports nested namespaces, it was a deliberate design choice to
3037+ place subcommand options in a dedicated subnamespace for greater clarity and
3038+ user convenience.
3039+
3040+ Additionally, in argparse, ``add_subparsers `` must be called with the ``dest ``
3041+ parameter to include the name of the selected subcommand in the resulting
3042+ namespace. In jsonargparse, the chosen subcommand is available by default,
3043+ without requiring any extra parameters.
3044+
3045+ Furthermore, to promote modularity, subparsers in jsonargparse can be created
3046+ independently, just like the main parser. The subparser object is then added as
3047+ a subcommand. This enables defining functions that return subparsers, which can
3048+ be used both as standalone parsers and as subcommands. In contrast, argparse
3049+ subparsers are tightly coupled to the main parser and cannot be defined
3050+ independently. To avoid confusion with respect to argparse, the method names for
3051+ adding subcommands in jsonargparse are intentionally different.
3052+
3053+ To migrate from argparse to jsonargparse, instead of:
3054+
3055+ .. testcode ::
3056+
3057+ import argparse
3058+
3059+ parser = argparse.ArgumentParser()
3060+ subparsers = parser.add_subparsers()
3061+ subparser1 = subparsers.add_parser("foo")
3062+ subparser1.add_argument("--key")
3063+ ...
3064+
3065+ The code would be changed to:
3066+
3067+ .. testcode ::
3068+
3069+ import jsonargparse
3070+
3071+ subparser1 = jsonargparse.ArgumentParser()
3072+ subparser1.add_argument("--key")
3073+
3074+ ...
3075+
3076+ parser = jsonargparse.ArgumentParser()
3077+ subcommands = parser.add_subcommands()
3078+ subcommands.add_subcommand("foo", subparser1)
3079+
3080+ Parse known arguments
3081+ ---------------------
3082+
3083+ Argparse provides the ``parse_known_args `` method, which allows for more lenient
3084+ parsing by ignoring unrecognized arguments. However, jsonargparse is designed
3085+ for complex parsing scenarios, such as: multiple subcommands, a large number of
3086+ arguments derived from signatures, class instantiation, and configuration files.
3087+ Allowing unrecognized arguments could make it harder for users to detect errors,
3088+ such as typos in configuration files. For this reason, jsonargparse
3089+ intentionally does not support ``parse_known_args ``.
3090+
3091+ User defined types
3092+ ------------------
3093+
3094+ In argparse, when adding an argument, the ``type `` parameter can be set to a
3095+ user-defined function or class. Providing a function is supported in
3096+ jsonargparse, with the additional requirement that the function must be
3097+ idempotent. That is, applying the function two or more times should not alter
3098+ the value. For example:
3099+
3100+ .. testcode ::
3101+
3102+ # either int larger than zero or 'off' string
3103+ def int_or_off(x):
3104+ return x if x == "off" else int(x)
3105+
3106+
3107+ parser.add_argument("--int_or_off", type=int_or_off)
3108+
3109+ Specifying a class as the type conflicts with the signature and type hint
3110+ support that is central to jsonargparse. Therefore, providing a class as the
3111+ type does not work the same way as in argparse. The recommended alternative is
3112+ to implement a custom type; see :ref: `custom-types `.
3113+
3114+
30323115.. _logging :
30333116
30343117Troubleshooting and logging
0 commit comments