Skip to content
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
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/1-bug.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ result = parser.parse_args([f"--config={config}", "--key2=val2", ...])
# If the problem is in the parsed result, print it to stdout
print(parser.dump(result))

# If the problem is in class instantiation
parser.instantiate_classes(result)
# If the problem is in instantiation
parser.instantiate(result)
```
-->

Expand Down
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/2-regression.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ config = json.dumps(
# If the problem is when parsing arguments
result = parser.parse_args([f"--config={config}", "--key2=val2", ...])

# If the problem is in class instantiation
parser.instantiate_classes(result)
# If the problem is in instantiation
parser.instantiate(result)
```

2. Preferably, run git bisect and include in the report the git commit hash that
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ Deprecated
argument) was deprecated and will be removed in v5.0.0. Pass components
explicitly; explicit is better than implicit (`#895
<https://github.com/omni-us/jsonargparse/pull/895>`__).
- ``instantiate_classes`` is deprecated and will be removed in v5.0.0. Instead
use ``instantiate`` (`#896
<https://github.com/omni-us/jsonargparse/pull/896>`__).


v4.48.0 (2026-04-10)
Expand Down
81 changes: 38 additions & 43 deletions DOCUMENTATION.rst
Original file line number Diff line number Diff line change
Expand Up @@ -483,10 +483,9 @@ Some notes about this support are:
null], default: null``.

- Normal classes can be used as a type, which are specified with a dict
containing ``class_path`` and optionally ``init_args``.
:meth:`instantiate_classes <.ArgumentParser.instantiate_classes>` can be used
to instantiate all classes in a config object. For more details see
:ref:`sub-classes`.
containing ``class_path`` and optionally ``init_args``. :meth:`instantiate
<.ArgumentParser.instantiate>` can be used to instantiate all classes in a
config object. For more details see :ref:`sub-classes`.

- ``Protocol`` types are also supported the same as subclasses. The protocols
are not required to be ``runtime_checkable``. But the accepted classes must
Expand All @@ -513,10 +512,10 @@ Some notes about this support are:
object or by giving a dict with a ``class_path`` and optionally ``init_args``
entries. The specified class must either instantiate into a callable or be a
subclass of the return type of the callable. For these cases running
:meth:`instantiate_classes <.ArgumentParser.instantiate_classes>` will
instantiate the class or provide a function that returns the instance of the
class. For more details see :ref:`callable-type`. Currently the callable's
argument and return types are not validated.
:meth:`instantiate <.ArgumentParser.instantiate>` will instantiate the class
or provide a function that returns the instance of the class. For more details
see :ref:`callable-type`. Currently the callable's argument and return types
are not validated.

- ``TypeAliasType`` is supported with values parsed as the aliased type and the
alias shown as the argument type in help.
Expand Down Expand Up @@ -1020,7 +1019,7 @@ A second option is a class that once instantiated becomes callable:
>>> cfg = parser.parse_args(["--callable", str(value)])
>>> cfg.callable
Namespace(class_path='__main__.OffsetSum', init_args=Namespace(offset=3))
>>> init = parser.instantiate_classes(cfg)
>>> init = parser.instantiate(cfg)
>>> init.callable(5)
8

Expand Down Expand Up @@ -1420,11 +1419,10 @@ and ``flag`` as an optional boolean with default value false.

Instantiation of several classes added with :meth:`add_class_arguments
<.SignatureArguments.add_class_arguments>` can be done more simply for an entire
config object using :meth:`instantiate_classes
<.ArgumentParser.instantiate_classes>`. For the example above running ``cfg =
parser.instantiate_classes(cfg)`` would result in ``cfg.myclass.init``
containing an instance of ``MyClass`` initialized with whatever command line
arguments were parsed.
config object using :meth:`instantiate <.ArgumentParser.instantiate>`. For the
example above running ``cfg = parser.instantiate(cfg)`` would result in
``cfg.myclass.init`` containing an instance of ``MyClass`` initialized with
whatever command line arguments were parsed.

When parsing from a config file (see :ref:`configuration-files`) all the values
can be given in a single config file. For convenience it is also possible that
Expand Down Expand Up @@ -1569,9 +1567,8 @@ Classes from functions
----------------------

In some cases there are functions which return an instance of a class. To add
this to a parser such that :meth:`instantiate_classes
<.ArgumentParser.instantiate_classes>` calls this function, the example above
would change to:
this to a parser such that :meth:`instantiate <.ArgumentParser.instantiate>`
calls this function, the example above would change to:

.. testsetup:: class_from_function

Expand Down Expand Up @@ -1653,7 +1650,7 @@ Take for example the following parsing and instantiation:
parser = ArgumentParser()
parser.add_argument("--myclass", type=MyClass)
cfg = parser.parse_args()
cfg_init = parser.instantiate_classes(cfg)
cfg_init = parser.instantiate(cfg)

If ``MyClass.__init__`` has ``**kwargs`` with some unresolved parameters, the
following could be a valid config file:
Expand Down Expand Up @@ -1850,9 +1847,8 @@ parameters behave differently and are shown in the help with the default like
these parameters are not included in :meth:`get_defaults
<.ArgumentParser.get_defaults>` or the output of ``--print_config``. This is
necessary because the parser does not know which of the calls will be used at
runtime, and adding them would cause :meth:`instantiate_classes
<.ArgumentParser.instantiate_classes>` to fail due to unexpected keyword
arguments.
runtime, and adding them would cause :meth:`instantiate
<.ArgumentParser.instantiate>` to fail due to unexpected keyword arguments.

.. note::

Expand Down Expand Up @@ -1937,8 +1933,8 @@ instantiate it. When parsing, it will be checked that the class can be imported,
that it is a subclass of the given type and that ``init_args`` values correspond
to valid arguments to instantiate it. After parsing, the config object will
include the ``class_path`` and ``init_args`` entries. To get a config object
with all nested subclasses instantiated, the :meth:`instantiate_classes
<.ArgumentParser.instantiate_classes>` method is used.
with all nested subclasses instantiated, the :meth:`instantiate
<.ArgumentParser.instantiate>` method is used.

In addition to using a class as type hint in signatures, for low level
construction of parsers, there are also the methods :meth:`add_class_arguments
Expand Down Expand Up @@ -1992,7 +1988,7 @@ Then in Python:
>>> cfg.myclass.calendar.as_dict()
{'class_path': 'calendar.Calendar', 'init_args': {'firstweekday': 1}}

>>> cfg = parser.instantiate_classes(cfg)
>>> cfg = parser.instantiate(cfg)
>>> isinstance(cfg.myclass, MyClass)
True
>>> isinstance(cfg.myclass.calendar, Calendar)
Expand Down Expand Up @@ -2041,11 +2037,11 @@ As explained at the beginning of section :ref:`dependency-injection`, callables
that return instances of classes, referred to as instance factories, represent
an alternative approach to dependency injection. This is useful to support
dependency injection of classes that require parameters that are only available
after injection. For this case, when :meth:`instantiate_classes
<.ArgumentParser.instantiate_classes>` is run, a partial function is provided,
which might accept parameters and return the instance of the class. Two options
are possible: using ``Callable`` or ``Protocol``. To illustrate the
``Callable`` option, take for example the classes:
after injection. For this case, when :meth:`instantiate
<.ArgumentParser.instantiate>` is run, a partial function is provided, which
might accept parameters and return the instance of the class. Two options are
possible: using ``Callable`` or ``Protocol``. To illustrate the ``Callable``
option, take for example the classes:

.. testcode:: callable

Expand Down Expand Up @@ -2079,7 +2075,7 @@ A possible parser and callable behavior would be:
>>> cfg = parser.parse_args(["--optimizer", str(value)])
>>> cfg.optimizer
Namespace(class_path='__main__.SGD', init_args=Namespace(lr=0.01))
>>> init = parser.instantiate_classes(cfg)
>>> init = parser.instantiate(cfg)
>>> optimizer = init.optimizer([1, 2, 3])
>>> isinstance(optimizer, SGD)
True
Expand Down Expand Up @@ -2112,7 +2108,7 @@ Then a parser and behavior could be:
>>> cfg = parser.get_defaults()
>>> cfg.model.optimizer
Namespace(class_path='__main__.SGD', init_args=Namespace(lr=0.05))
>>> init = parser.instantiate_classes(cfg)
>>> init = parser.instantiate(cfg)
>>> optimizer = init.model.optimizer([1, 2, 3])
>>> optimizer.params, optimizer.lr
([1, 2, 3], 0.05)
Expand Down Expand Up @@ -2159,7 +2155,7 @@ Then a parser and protocol behavior would be:
>>> cfg = parser.parse_args(["--optimizer", str(value)])
>>> cfg.optimizer
Namespace(class_path='__main__.SGD', init_args=Namespace(lr=0.02))
>>> init = parser.instantiate_classes(cfg)
>>> init = parser.instantiate(cfg)
>>> optimizer = init.optimizer(params=[6, 5])
>>> optimizer.params, optimizer.lr
([6, 5], 0.02)
Expand Down Expand Up @@ -2249,9 +2245,9 @@ are supported with a particular behavior and recommendations. An example is:
Adding this class to a parser will work without issues. The :ref:`ast-resolver`
in limited cases determines how to instantiate the original default. The parsing
methods would provide a dict with ``class_path`` and ``init_args`` instead of
the class instance. Furthermore, if :meth:`instantiate_classes
<.ArgumentParser.instantiate_classes>` is used, a new instance of the class is
created, thereby avoiding issues related to the mutability of the default.
the class instance. Furthermore, if :meth:`instantiate
<.ArgumentParser.instantiate>` is used, a new instance of the class is created,
thereby avoiding issues related to the mutability of the default.

Since the :ref:`ast-resolver` only supports limited cases, or when the source
code is not available, a second approach is to use the special function
Expand Down Expand Up @@ -2419,7 +2415,7 @@ behavior can be obtained by using the :meth:`link_arguments
There are two types of links, defined with ``apply_on='parse'`` or
``apply_on='instantiate'``. As the names suggest, the former are set when
calling one of the parse methods and the latter are set when calling
:meth:`instantiate_classes <.ArgumentParser.instantiate_classes>`.
:meth:`instantiate <.ArgumentParser.instantiate>`.

Applied on parse
----------------
Expand Down Expand Up @@ -2482,10 +2478,9 @@ For instantiation links, sources can be class groups (added with
subclass arguments (see :ref:`sub-classes`). The source key can be the entire
instantiated object or an attribute of the object. The target key has to be a
single argument and can be inside init_args of a subclass. The order of
instantiation used by :meth:`instantiate_classes
<.ArgumentParser.instantiate_classes>` is automatically determined based on the
links. The set of all instantiation links must be a directed acyclic graph. An
example would be the following:
instantiation used by :meth:`instantiate <.ArgumentParser.instantiate>` is
automatically determined based on the links. The set of all instantiation links
must be a directed acyclic graph. An example would be the following:

.. testcode::

Expand All @@ -2504,9 +2499,9 @@ example would be the following:
parser.add_class_arguments(Data, "data")
parser.link_arguments("data.num_classes", "model.num_classes", apply_on="instantiate")

This link would imply that :meth:`instantiate_classes
<.ArgumentParser.instantiate_classes>` instantiates ``Data`` first, then use the
``num_classes`` attribute to instantiate ``Model``.
This link would imply that :meth:`instantiate <.ArgumentParser.instantiate>`
instantiates ``Data`` first, then use the ``num_classes`` attribute to
instantiate ``Model``.


OmegaConf variable interpolation
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Powerful argparse-like low level parsers:
parser.add_class_arguments(SomeClass, "class") # add class parameters
...
cfg = parser.parse_args()
init = parser.instantiate_classes(cfg)
init = parser.instantiate(cfg)
...


Expand Down
4 changes: 2 additions & 2 deletions jsonargparse/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def auto_cli(
deprecation_warning_cli_return_parser(stacklevel)
return parser
cfg = parser.parse_args(args)
init = parser.instantiate_classes(cfg)
init = parser.instantiate(cfg)
return _run_component(components, init)

elif isinstance(components, list):
Expand All @@ -105,7 +105,7 @@ def auto_cli(
deprecation_warning_cli_return_parser(stacklevel)
return parser
cfg = parser.parse_args(args)
init = parser.instantiate_classes(cfg)
init = parser.instantiate(cfg)
components_ns = dict_to_namespace(components)
subcommand = init.get("subcommand")
while isinstance(init.get(subcommand), Namespace) and isinstance(init[subcommand].get("subcommand"), str):
Expand Down
38 changes: 32 additions & 6 deletions jsonargparse/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1211,7 +1211,7 @@ def add_instantiator(
subclasses: bool = True,
prepend: bool = False,
) -> None:
"""Adds a custom instantiator for a class type. Used by ``instantiate_classes``.
"""Adds a custom instantiator for a class type. Used by ``instantiate``.

Instantiator functions are expected to have as signature ``(class_type:
Type[ClassType], *args, **kwargs) -> ClassType``.
Expand Down Expand Up @@ -1254,19 +1254,45 @@ def _get_instantiators(self):
instantiators.update({k: v for k, v in context_instantiators.items() if k not in instantiators})
return instantiators

def instantiate_classes(
def instantiate(
self,
cfg: Namespace,
instantiate_groups: bool = True,
) -> Namespace:
"""Recursively instantiates all subclasses defined by ``class_path`` + ``init_args`` and class groups.
"""Instantiates all signature components in a configuration namespace.

Processes the configuration recursively, converting each signature
component registered with the parser into its corresponding Python
object:

- **Class/subclass type arguments** (``add_argument`` with a class type
or ``add_class_arguments``/``add_subclass_arguments``): An object with
``class_path`` and optionally ``init_args`` is replaced by an instance
of the referenced class, created by calling
``class_type(**init_args)``. For the case of classes with disabled
subclasses, the namespace can have directly the init args without the
``class_path`` + ``init_args`` wrapper.

- **Callable type arguments**: A dot-import string pointing to a
function or method is resolved to the callable object. When
``class_path``/``init_args`` is given instead and the class
instantiates into a callable (or is a subclass of the callable's
return type), the result is either a class instance or — when not all
call arguments are provided yet — a :func:`functools.partial` bound to
the given ``init_args``.

- **Instantiation order**: Components are processed in the order
determined by argument links applied on instantiation.

Args:
cfg: The configuration object to use.
cfg: The configuration object to use. Must have been produced by
one of the ``parse_*`` methods and not modified in a way that
breaks the structure expected by the parser.
instantiate_groups: Whether class groups should be instantiated.

Returns:
A configuration object with all subclasses and class groups instantiated.
A new configuration object where every registered signature
component has been replaced by its corresponding Python object.
"""
components: list[Union[ActionTypeHint, _ActionConfigLoad, ArgumentGroup]] = []
for action in filter_non_parsing_actions(self._actions):
Expand Down Expand Up @@ -1313,7 +1339,7 @@ def instantiate_classes(

subcommand, subparser = get_subcommand(self, cfg, fail_no_subcommand=False)
if subcommand is not None and subparser is not None:
cfg[subcommand] = subparser.instantiate_classes(cfg[subcommand], instantiate_groups=instantiate_groups)
cfg[subcommand] = subparser.instantiate(cfg[subcommand], instantiate_groups=instantiate_groups)

return cfg

Expand Down
26 changes: 12 additions & 14 deletions jsonargparse/_deprecated.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,18 +159,6 @@ def patched_parse(
patch_parse_method("parse_env")
patch_parse_method("parse_string")

# Patch instantiate_classes
def patched_instantiate_classes(
self, cfg: Union[Namespace, Dict[str, Any]], **kwargs
) -> Union[Namespace, Dict[str, Any]]:
if isinstance(cfg, dict):
cfg = self._apply_actions(cfg)
cfg = self._unpatched_instantiate_classes(cfg, **kwargs)
return cfg.as_dict() if self._parse_as_dict else cfg

ArgumentParser._unpatched_instantiate_classes = ArgumentParser.instantiate_classes
ArgumentParser.instantiate_classes = patched_instantiate_classes

# Patch dump
def patched_dump(self, cfg: Union[Namespace, Dict[str, Any]], *args, **kwargs) -> str:
if isinstance(cfg, dict):
Expand Down Expand Up @@ -633,12 +621,22 @@ def default_meta(self, default_meta: bool):
else:
raise ValueError("default_meta expects a boolean.")

@deprecated("""
``instantiate_classes`` was deprecated in v4.49.0 and will be removed in v5.0.0.
Instead use ``instantiate``.
""")
def instantiate_classes(self, cfg: Union[Namespace, Dict[str, Any]], **kwargs) -> Union[Namespace, Dict[str, Any]]:
if isinstance(cfg, dict):
cfg = self._apply_actions(cfg) # type: ignore[attr-defined]
cfg = self.instantiate(cfg, **kwargs) # type: ignore[attr-defined]
return cfg.as_dict() if self._parse_as_dict else cfg # type: ignore[attr-defined]

@deprecated("""
instantiate_subclasses was deprecated in v4.0.0 and will be removed in v5.0.0.
Instead use instantiate_classes.
Instead use instantiate.
""")
def instantiate_subclasses(self, cfg: Namespace) -> Namespace:
return self.instantiate_classes(cfg, instantiate_groups=False) # type: ignore[attr-defined]
return self.instantiate(cfg, instantiate_groups=False) # type: ignore[attr-defined]

@deprecated("""
add_dataclass_arguments was deprecated in v4.35.0 and will be removed in
Expand Down
2 changes: 1 addition & 1 deletion jsonargparse/_from_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def _parse_class_kwargs_from_config(cls: Type[T], config: Union[str, PathLike, d
for required in iter_required_keys(parser):
clear_required(parser, required)
cfg = parser.parse_object(config, defaults=False)
return parser.instantiate_classes(cfg).as_dict(), cls
return parser.instantiate(cfg).as_dict(), cls


def _override_init_defaults(cls: Type[T], parser_kwargs: dict) -> None:
Expand Down
5 changes: 3 additions & 2 deletions jsonargparse/_signatures.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ def add_class_arguments(
as_positional: Whether to add required parameters as positional arguments.
default: Default value used to override parameter defaults.
skip: Names of parameters or number of positionals that should be skipped.
instantiate: Whether the class group should be instantiated by ``instantiate_classes``.
instantiate: Whether the class group should be instantiated by
:meth:`instantiate <.ArgumentParser.instantiate>`.
fail_untyped: Whether to raise exception if a required parameter does not have a type.
sub_configs: Whether subclass type hints should be loadable from inner config file.

Expand Down Expand Up @@ -254,7 +255,7 @@ def _add_signature_arguments(
skip: Names of parameters or number of positionals that should be skipped.
fail_untyped: Whether to raise exception if a required parameter does not have a type.
sub_configs: Whether subclass type hints should be loadable from inner config file.
instantiate: Whether the class group should be instantiated by ``instantiate_classes``.
instantiate: Whether the class group should be instantiated.

Returns:
The list of arguments added.
Expand Down
Loading
Loading