Skip to content

Commit 099bb09

Browse files
authored
Docs now reference methods via the public ArgumentParser class instead of internal mixin classes (#901)
1 parent 36a2530 commit 099bb09

7 files changed

Lines changed: 160 additions & 137 deletions

File tree

CHANGELOG.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ paths are considered internals and can change in minor and patch releases.
1515
v4.49.0 (unreleased)
1616
--------------------
1717

18+
Changed
19+
^^^^^^^
20+
- Docs now reference methods via the public ``ArgumentParser`` class instead of
21+
internal mixin classes (`#901
22+
<https://github.com/omni-us/jsonargparse/pull/901>`__).
23+
1824
Deprecated
1925
^^^^^^^^^^
2026
- Implicit component discovery in ``auto_cli`` (calling without a ``components``

DOCUMENTATION.rst

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -699,10 +699,10 @@ which would be like ``--list+ file1 --list+ file2``. Not as simple as with
699699
The same ``list[<path_type>]`` behavior described here will work for arguments
700700
automatically created from type hints in signatures, that is with
701701
:func:`.auto_cli`, :meth:`add_function_arguments
702-
<.SignatureArguments.add_function_arguments>`, :meth:`add_class_arguments
703-
<.SignatureArguments.add_class_arguments>`, :meth:`add_method_arguments
704-
<.SignatureArguments.add_method_arguments>` and :meth:`add_subclass_arguments
705-
<.SignatureArguments.add_subclass_arguments>`.
702+
<.ArgumentParser.add_function_arguments>`, :meth:`add_method_arguments
703+
<.ArgumentParser.add_method_arguments>`, :meth:`add_class_arguments
704+
<.ArgumentParser.add_class_arguments>` and :meth:`add_subclass_arguments
705+
<.ArgumentParser.add_subclass_arguments>`.
706706

707707
.. note::
708708

@@ -1354,7 +1354,10 @@ these are described in the docstrings. To make this well written code
13541354
configurable, it wouldn't make sense to duplicate information of types and
13551355
parameter descriptions. To avoid this duplication, jsonargparse includes methods
13561356
to automatically add annotated parameters as arguments, see
1357-
:class:`.SignatureArguments`.
1357+
:meth:`add_function_arguments <.ArgumentParser.add_function_arguments>`,
1358+
:meth:`add_method_arguments <.ArgumentParser.add_method_arguments>`,
1359+
:meth:`add_class_arguments <.ArgumentParser.add_class_arguments>` and
1360+
:meth:`add_subclass_arguments <.ArgumentParser.add_subclass_arguments>`.
13581361

13591362
Take for example a class with its init and a method with docstrings as follows:
13601363

@@ -1406,19 +1409,19 @@ initialized and the method executed as follows:
14061409
myclass.mymethod(**cfg.myclass.method.as_dict())
14071410
14081411

1409-
The :meth:`add_class_arguments <.SignatureArguments.add_class_arguments>` call
1410-
adds to the ``myclass.init`` key the ``items`` argument with description as in
1411-
the docstring, sets it as required since it lacks a default value. When parsed,
1412-
it is validated according to the type hint, i.e., a dict with values ints or
1413-
list of ints. Also since the init has the ``**kwargs`` argument, the keyword
1412+
The :meth:`add_class_arguments <.ArgumentParser.add_class_arguments>` call adds
1413+
to the ``myclass.init`` key the ``items`` argument with description as in the
1414+
docstring, sets it as required since it lacks a default value. When parsed, it
1415+
is validated according to the type hint, i.e., a dict with values ints or list
1416+
of ints. Also since the init has the ``**kwargs`` argument, the keyword
14141417
arguments from ``MyBaseClass`` are also added to the parser. Similarly, the
1415-
:meth:`add_method_arguments <.SignatureArguments.add_method_arguments>` call
1416-
adds to the ``myclass.method`` key, the arguments ``value`` as a required float
1417-
and ``flag`` as an optional boolean with default value false.
1418+
:meth:`add_method_arguments <.ArgumentParser.add_method_arguments>` call adds to
1419+
the ``myclass.method`` key, the arguments ``value`` as a required float and
1420+
``flag`` as an optional boolean with default value false.
14181421

14191422

14201423
Instantiation of several classes added with :meth:`add_class_arguments
1421-
<.SignatureArguments.add_class_arguments>` can be done more simply for an entire
1424+
<.ArgumentParser.add_class_arguments>` can be done more simply for an entire
14221425
config object using :meth:`instantiate <.ArgumentParser.instantiate>`. For the
14231426
example above running ``cfg = parser.instantiate(cfg)`` would result in
14241427
``cfg.myclass.init`` containing an instance of ``MyClass`` initialized with
@@ -1889,7 +1892,7 @@ example from the standard library would be:
18891892
Namespace(uniform=Namespace(a=0.7, b=3.4))
18901893

18911894
Without the stubs resolver, the :meth:`add_function_arguments
1892-
<.SignatureArguments.add_function_arguments>` call requires the
1895+
<.ArgumentParser.add_function_arguments>` call requires the
18931896
``fail_untyped=False`` option. This has the disadvantage that type ``Any`` is
18941897
given to the ``a`` and ``b`` arguments, instead of ``float``. And this means
18951898
that the parser would not fail if given an invalid value, for instance a string.
@@ -1938,8 +1941,8 @@ with all nested subclasses instantiated, the :meth:`instantiate
19381941

19391942
In addition to using a class as type hint in signatures, for low level
19401943
construction of parsers, there are also the methods :meth:`add_class_arguments
1941-
<.SignatureArguments.add_class_arguments>` and :meth:`add_subclass_arguments
1942-
<.SignatureArguments.add_subclass_arguments>`. These methods accept a ``skip``
1944+
<.ArgumentParser.add_class_arguments>` and :meth:`add_subclass_arguments
1945+
<.ArgumentParser.add_subclass_arguments>`. These methods accept a ``skip``
19431946
argument that can be used to exclude parameters within subclasses. This is done
19441947
by giving its relative destination key, i.e. as ``param.init_args.subparam``. An
19451948
individual argument can also be added using a class as type, i.e.
@@ -2001,10 +2004,9 @@ But a subclass of ``Calendar`` with an extended set of init parameters would
20012004
also work.
20022005

20032006
If the previous example were changed to use :meth:`add_subclass_arguments
2004-
<.SignatureArguments.add_subclass_arguments>` instead of
2005-
:meth:`add_class_arguments <.SignatureArguments.add_class_arguments>`, then
2006-
subclasses ``MyClass`` would also be accepted. In this case the config would be
2007-
like:
2007+
<.ArgumentParser.add_subclass_arguments>` instead of :meth:`add_class_arguments
2008+
<.ArgumentParser.add_class_arguments>`, then subclasses ``MyClass`` would also
2009+
be accepted. In this case the config would be like:
20082010

20092011
.. code-block:: yaml
20102012
@@ -2410,7 +2412,7 @@ Argument linking
24102412
Some use cases could require adding arguments from multiple classes and some
24112413
parameters get a value automatically computed from other arguments. This
24122414
behavior can be obtained by using the :meth:`link_arguments
2413-
<.ArgumentLinking.link_arguments>` parser method.
2415+
<.ArgumentParser.link_arguments>` parser method.
24142416

24152417
There are two types of links, defined with ``apply_on='parse'`` or
24162418
``apply_on='instantiate'``. As the names suggest, the former are set when
@@ -2474,8 +2476,8 @@ Applied on instantiate
24742476
----------------------
24752477

24762478
For instantiation links, sources can be class groups (added with
2477-
:meth:`add_class_arguments <.SignatureArguments.add_class_arguments>`) or
2478-
subclass arguments (see :ref:`sub-classes`). The source key can be the entire
2479+
:meth:`add_class_arguments <.ArgumentParser.add_class_arguments>`) or subclass
2480+
arguments (see :ref:`sub-classes`). The source key can be the entire
24792481
instantiated object or an attribute of the object. The target key has to be a
24802482
single argument and can be inside init_args of a subclass. The order of
24812483
instantiation used by :meth:`instantiate <.ArgumentParser.instantiate>` is

jsonargparse/__init__.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,9 @@
2020
from ._instantiation import * # noqa: F403
2121
from ._jsonnet import * # noqa: F403
2222
from ._jsonschema import * # noqa: F403
23-
from ._link_arguments import * # noqa: F403
2423
from ._loaders_dumpers import * # noqa: F403
2524
from ._namespace import * # noqa: F403
2625
from ._paths import Path # noqa: F401
27-
from ._signatures import * # noqa: F403
2826
from ._subcommands import * # noqa: F403
2927
from ._util import * # noqa: F403
3028
from .typing import class_from_function, lazy_instance # noqa: F401
@@ -51,19 +49,15 @@
5149
_instantiation,
5250
_jsonnet,
5351
_jsonschema,
54-
_link_arguments,
5552
_loaders_dumpers,
5653
_namespace,
57-
_signatures,
5854
_subcommands,
5955
_util,
6056
)
6157

6258
__all__ += _cli.__all__
6359
__all__ += _core.__all__
64-
__all__ += _signatures.__all__
6560
__all__ += _from_config.__all__
66-
__all__ += _link_arguments.__all__
6761
__all__ += _subcommands.__all__
6862
__all__ += _jsonschema.__all__
6963
__all__ += _jsonnet.__all__

jsonargparse/_core.py

Lines changed: 24 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
previous_config,
2727
)
2828
from ._common import (
29-
LoggerProperty,
3029
debug_mode_active,
3130
get_optionals_as_positionals_actions,
3231
is_subclasses_disabled,
@@ -41,7 +40,7 @@
4140
)
4241
from ._deprecated import ParserDeprecations, deprecated_skip_check, deprecated_yaml_comments
4342
from ._formatters import DefaultHelpFormatter, get_env_var
44-
from ._instantiation import get_class_instantiators
43+
from ._instantiation import InstantiateMethod
4544
from ._jsonnet import ActionJsonnet
4645
from ._jsonschema import ActionJsonSchema
4746
from ._link_arguments import ActionLink, ArgumentLinking
@@ -56,12 +55,10 @@
5655
Namespace,
5756
NSKeyError,
5857
get_non_meta_sorted_keys,
59-
get_value_and_parent,
6058
is_meta_key,
6159
patch_namespace,
6260
recreate_branches,
6361
remove_meta,
64-
split_key,
6562
split_key_leaf,
6663
split_key_root,
6764
)
@@ -102,13 +99,13 @@
10299
return_parser_if_captured,
103100
)
104101

105-
__all__ = ["ArgumentParser", "ActionsContainer"]
102+
__all__ = ["ArgumentParser"]
106103

107104

108105
_parse_known_has_intermixed = "intermixed" in inspect.signature(argparse.ArgumentParser._parse_known_args).parameters
109106

110107

111-
class ActionsContainer(SignatureArguments, argparse._ActionsContainer):
108+
class ActionsContainer(ArgumentLinking, InstantiateMethod, SignatureArguments, argparse._ActionsContainer):
112109
"""Extension of ``argparse._ActionsContainer`` to support additional functionalities."""
113110

114111
_action_groups: Sequence["ArgumentGroup"] # type: ignore[assignment]
@@ -229,7 +226,7 @@ class ArgumentGroup(ActionsContainer, argparse._ArgumentGroup):
229226
parser: Optional[Union["ArgumentParser", ActionsContainer]] = None
230227

231228

232-
class ArgumentParser(ParserDeprecations, ActionsContainer, ArgumentLinking, LoggerProperty, argparse.ArgumentParser):
229+
class ArgumentParser(ParserDeprecations, ActionsContainer, argparse.ArgumentParser):
233230
"""Parser for command line, configuration files and environment variables."""
234231

235232
formatter_class: type[argparse.HelpFormatter]
@@ -287,10 +284,6 @@ def __init__(
287284

288285
## Parsing methods ##
289286

290-
def parse_known_args(self, *args, **kwargs) -> NoReturn:
291-
"""Raises ``NotImplementedError``, not supported since typos in configs would go unnoticed."""
292-
raise NotImplementedError("parse_known_args not supported because typos in configs would go unnoticed.")
293-
294287
def _parse_known_args_internal(self, args=None, namespace=None, *, argcomplete: bool = False):
295288
if argcomplete:
296289
namespace = get_argcomplete_namespace(self, namespace)
@@ -716,9 +709,13 @@ def _load_config_parser_mode(
716709

717710
## Methods for adding to the parser ##
718711

719-
def add_subparsers(self, *args, **kwargs) -> NoReturn:
720-
"""Raises a ``NotImplementedError`` since jsonargparse uses ``add_subcommands``."""
721-
raise NotImplementedError("In jsonargparse subcommands are added using the add_subcommands method.")
712+
add_argument = ActionsContainer.add_argument
713+
add_argument_group = ActionsContainer.add_argument_group
714+
add_function_arguments = SignatureArguments.add_function_arguments
715+
add_method_arguments = SignatureArguments.add_method_arguments
716+
add_class_arguments = SignatureArguments.add_class_arguments
717+
add_subclass_arguments = SignatureArguments.add_subclass_arguments
718+
link_arguments = ArgumentLinking.link_arguments
722719

723720
def add_subcommands(self, required: bool = True, dest: str = "subcommand", **kwargs) -> ActionSubCommands:
724721
"""Adds subcommand parsers to the ArgumentParser.
@@ -1064,6 +1061,8 @@ def get_defaults(self, skip_validation: bool = False, **kwargs) -> Namespace:
10641061

10651062
return cfg
10661063

1064+
set_defaults = ActionsContainer.set_defaults
1065+
10671066
## Completion script methods ##
10681067

10691068
def _raise_invalidated_by_completion_script(self, *args, **kwargs) -> NoReturn:
@@ -1202,94 +1201,7 @@ def check_values(cfg):
12021201
if not skip_required and not lenient_check.get():
12031202
check_required(cfg, self, prefix)
12041203

1205-
def instantiate(
1206-
self,
1207-
cfg: Namespace,
1208-
instantiate_groups: bool = True,
1209-
) -> Namespace:
1210-
"""Instantiates all signature components in a configuration namespace.
1211-
1212-
Processes the configuration recursively, converting each signature
1213-
component registered with the parser into its corresponding Python
1214-
object:
1215-
1216-
- **Class/subclass type arguments** (``add_argument`` with a class type
1217-
or ``add_class_arguments``/``add_subclass_arguments``): An object with
1218-
``class_path`` and optionally ``init_args`` is replaced by an instance
1219-
of the referenced class, created by calling
1220-
``class_type(**init_args)``. For the case of classes with disabled
1221-
subclasses, the namespace can have directly the init args without the
1222-
``class_path`` + ``init_args`` wrapper.
1223-
1224-
- **Callable type arguments**: A dot-import string pointing to a
1225-
function or method is resolved to the callable object. When
1226-
``class_path``/``init_args`` is given instead and the class
1227-
instantiates into a callable (or is a subclass of the callable's
1228-
return type), the result is either a class instance or — when not all
1229-
call arguments are provided yet — a :func:`functools.partial` bound to
1230-
the given ``init_args``.
1231-
1232-
- **Instantiation order**: Components are processed in the order
1233-
determined by argument links applied on instantiation.
1234-
1235-
Args:
1236-
cfg: The configuration object to use. Must have been produced by
1237-
one of the ``parse_*`` methods and not modified in a way that
1238-
breaks the structure expected by the parser.
1239-
instantiate_groups: Whether class groups should be instantiated.
1240-
1241-
Returns:
1242-
A new configuration object where every registered signature
1243-
component has been replaced by its corresponding Python object.
1244-
"""
1245-
components: list[Union[ActionTypeHint, _ActionConfigLoad, ArgumentGroup]] = []
1246-
for action in filter_non_parsing_actions(self._actions):
1247-
if isinstance(action, ActionTypeHint):
1248-
components.append(action)
1249-
elif isinstance(action, ActionLink) and isinstance(action.target[1], ActionTypeHint):
1250-
components.append(action.target[1])
1251-
1252-
if instantiate_groups:
1253-
skip = {c.dest for c in components}
1254-
groups = [g for g in self._action_groups if hasattr(g, "instantiate_class") and g.dest not in skip]
1255-
components.extend(groups)
1256-
1257-
components.sort(key=lambda x: -len(split_key(x.dest))) # type: ignore[arg-type]
1258-
order = ActionLink.instantiation_order(self)
1259-
components = ActionLink.reorder(order, components)
1260-
1261-
cfg = cfg.clone(with_meta=False)
1262-
for component in components:
1263-
ActionLink.apply_instantiation_links(self, cfg, target=component.dest)
1264-
if isinstance(component, ActionTypeHint):
1265-
try:
1266-
value, parent, key = get_value_and_parent(cfg, component.dest)
1267-
except (KeyError, AttributeError):
1268-
pass
1269-
else:
1270-
if value is not None:
1271-
with parser_context(
1272-
parent_parser=self,
1273-
nested_links=ActionLink.get_nested_links(self, component),
1274-
class_instantiators=get_class_instantiators(self),
1275-
applied_instantiation_links=cfg.get("__applied_instantiation_links__"),
1276-
):
1277-
parent[key] = component.instantiate_classes(value)
1278-
else:
1279-
with parser_context(
1280-
load_value_mode=self.parser_mode,
1281-
class_instantiators=get_class_instantiators(self),
1282-
applied_instantiation_links=cfg.get("__applied_instantiation_links__"),
1283-
):
1284-
component.instantiate_class(component, cfg)
1285-
1286-
ActionLink.apply_instantiation_links(self, cfg, order=order)
1287-
1288-
subcommand, subparser = get_subcommand(self, cfg, fail_no_subcommand=False)
1289-
if subcommand is not None and subparser is not None:
1290-
cfg[subcommand] = subparser.instantiate(cfg[subcommand], instantiate_groups=instantiate_groups)
1291-
1292-
return cfg
1204+
instantiate = InstantiateMethod.instantiate
12931205

12941206
def strip_unknown(self, cfg: Namespace) -> Namespace:
12951207
"""Removes all unknown keys from a configuration object.
@@ -1623,6 +1535,16 @@ def dump_header(self, dump_header: Optional[list[str]]):
16231535
raise ValueError("Expected dump_header to be None or a list of strings.")
16241536
self._dump_header = dump_header
16251537

1538+
# Not supported methods
1539+
1540+
def parse_known_args(self, *args, **kwargs) -> NoReturn:
1541+
"""Raises ``NotImplementedError`` since typos in configs would go unnoticed."""
1542+
raise NotImplementedError("parse_known_args not supported because typos in configs would go unnoticed.")
1543+
1544+
def add_subparsers(self, *args, **kwargs) -> NoReturn:
1545+
"""Raises ``NotImplementedError`` since jsonargparse uses ``add_subcommands``."""
1546+
raise NotImplementedError("In jsonargparse subcommands are added using the add_subcommands method.")
1547+
16261548

16271549
from ._deprecated import parse_as_dict_patch # noqa: E402
16281550

0 commit comments

Comments
 (0)