Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI renamed to auto_cli to follow PEP 8 functions naming #640

Merged
merged 2 commits into from
Dec 25, 2024
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
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ Added
removal of ``pyyaml`` as a required dependency in v5.0.0 (`#652
<https://github.com/omni-us/jsonargparse/pull/652>`__).

Changed
^^^^^^^

- ``jsonargparse.CLI`` renamed to ``jsonargparse.auto_cli`` to follow `PEP 8
<https://peps.python.org/pep-0008/#function-and-variable-names>`__ functions
naming convention (`#640
<https://github.com/omni-us/jsonargparse/pull/640>`__).

Fixed
^^^^^
- Help for ``Protocol`` types not working correctly (`#645
Expand Down
49 changes: 24 additions & 25 deletions DOCUMENTATION.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ Basic usage
There are multiple ways of using jsonargparse. One is to construct low level
parsers (see :ref:`parsers`) being almost a drop in replacement of argparse.
However, argparse is too verbose and leads to unnecessary duplication. The
simplest and recommended way of using jsonargparse is by using the :func:`.CLI`
function, which has the benefit of minimizing boilerplate code. A simple example
is:
simplest and recommended way of using jsonargparse is by using the
:func:`.auto_cli` function, which has the benefit of minimizing boilerplate
code. A simple example is:

.. testcode::

from jsonargparse import CLI
from jsonargparse import auto_cli


def command(name: str, prize: int = 100):
Expand All @@ -26,7 +26,7 @@ is:


if __name__ == "__main__":
CLI(command)
auto_cli(command)

Note that the ``name`` and ``prize`` parameters have type hints and are
described in the docstring. These are shown in the help of the command line
Expand All @@ -49,15 +49,15 @@ tool. In a shell you could see the help and run a command as follows:
shown, jsonargparse needs to be installed with the ``signatures`` extras
require as explained in section :ref:`installation`.

When :func:`.CLI` receives a single class, the first arguments are for
When :func:`.auto_cli` receives a single class, the first arguments are for
parameters to instantiate the class, then a method name is expected (i.e.
methods become :ref:`sub-commands`) and the remaining arguments are for
parameters of this method. An example would be:

.. testcode::

from random import randint
from jsonargparse import CLI
from jsonargparse import auto_cli


class Main:
Expand All @@ -77,7 +77,7 @@ parameters of this method. An example would be:


if __name__ == "__main__":
print(CLI(Main))
print(auto_cli(Main))

Then in a shell you could run:

Expand All @@ -88,16 +88,16 @@ Then in a shell you could run:

.. doctest:: :hide:

>>> CLI(Main, args=["--max_prize=1000", "person", "Lucky"]) # doctest: +ELLIPSIS
>>> auto_cli(Main, args=["--max_prize=1000", "person", "Lucky"]) # doctest: +ELLIPSIS
'Lucky won ...€!'

If the class given does not have any methods, there will be no sub-commands and
:func:`.CLI` will return an instance of the class. For example:
:func:`.auto_cli` will return an instance of the class. For example:

.. testcode::

from dataclasses import dataclass
from jsonargparse import CLI
from jsonargparse import auto_cli


@dataclass
Expand All @@ -107,7 +107,7 @@ If the class given does not have any methods, there will be no sub-commands and


if __name__ == "__main__":
print(CLI(Settings, as_positional=False))
print(auto_cli(Settings, as_positional=False))

Then in a shell you could run:

Expand All @@ -118,17 +118,17 @@ Then in a shell you could run:

.. doctest:: :hide:

>>> CLI(Settings, as_positional=False, args=["--name=Lucky"]) # doctest: +ELLIPSIS
>>> auto_cli(Settings, as_positional=False, args=["--name=Lucky"]) # doctest: +ELLIPSIS
Settings(name='Lucky', prize=100)

Note the use of ``as_positional=False`` to make required arguments as
non-positional.

If more than one function is given to :func:`.CLI`, then any of them can be run
via :ref:`sub-commands` similar to the single class example above, i.e.
If more than one function is given to :func:`.auto_cli`, then any of them can be
run via :ref:`sub-commands` similar to the single class example above, i.e.
``example.py function [arguments]`` where ``function`` is the name of the
function to execute. If multiple classes or a mixture of functions and classes
is given to :func:`.CLI`, to execute a method of a class, two levels of
is given to :func:`.auto_cli`, to execute a method of a class, two levels of
:ref:`sub-commands` are required. The first sub-command would be the name of the
class and the second the name of the method, i.e. ``example.py class
[init_arguments] method [arguments]``.
Expand Down Expand Up @@ -159,7 +159,7 @@ Arbitrary levels of sub-commands with custom names can be defined by providing a
}

if __name__ == "__main__":
print(CLI(components))
print(auto_cli(components))

Then in a shell:

Expand All @@ -170,7 +170,7 @@ Then in a shell:

.. doctest:: :hide:

>>> CLI(components, args=["weekend", "tier1", "Lucky"])
>>> auto_cli(components, args=["weekend", "tier1", "Lucky"])
'Lucky won 300€!'

.. note::
Expand All @@ -186,7 +186,7 @@ Then in a shell:
Writing configuration files
---------------------------

All tools implemented with the :func:`.CLI` function have the ``--config``
All tools implemented with the :func:`.auto_cli` function have the ``--config``
option to provide settings in a config file (more details in
:ref:`configuration-files`). This becomes very useful when the number of
configurable parameters is large. To ease the writing of config files, there is
Expand All @@ -206,14 +206,14 @@ can be advised to follow the following steps:
Comparison to Fire
------------------

The :func:`.CLI` feature is similar to and inspired by `Fire
The :func:`.auto_cli` feature is similar to and inspired by `Fire
<https://pypi.org/project/fire/>`__. However, there are fundamental differences.
First, the purpose is not allowing to call any python object from the command
line. It is only intended for running functions and classes specifically written
for this purpose. Second, the arguments are expected to have type hints, and the
given values will be validated according to these. Third, the return values of
the functions are not automatically printed. :func:`.CLI` returns the value and
it is up to the developer to decide what to do with it.
the functions are not automatically printed. :func:`.auto_cli` returns the value
and it is up to the developer to decide what to do with it.


.. _tutorials:
Expand Down Expand Up @@ -316,8 +316,7 @@ without doing any parsing. For instance `sphinx-argparse
<https://sphinx-argparse.readthedocs.io/en/stable/>`__ can be used to include
the help of CLIs in automatically generated documentation of a package. To use
sphinx-argparse it is necessary to have a function that returns the parser.
Having a CLI function this could be easily implemented with
:func:`.capture_parser` as follows:
This can be easily implemented with :func:`.capture_parser` as follows:

.. testcode::

Expand All @@ -330,7 +329,7 @@ Having a CLI function this could be easily implemented with
.. note::

The official way to obtain the parser for command line tools based on
:func:`.CLI` is by using :func:`.capture_parser`.
:func:`.auto_cli` is by using :func:`.capture_parser`.


Functions as type
Expand Down
16 changes: 12 additions & 4 deletions jsonargparse/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,20 @@
from ._optionals import get_doc_short_description
from ._util import default_config_option_help

__all__ = ["CLI"]
__all__ = ["CLI", "auto_cli"]


ComponentType = Union[Callable, Type]
DictComponentsType = Dict[str, Union[ComponentType, "DictComponentsType"]]
ComponentsType = Optional[Union[ComponentType, List[ComponentType], DictComponentsType]]


def CLI(
def CLI(*args, **kwargs):
"""Alias of :func:`auto_cli`."""
return auto_cli(*args, _stacklevel=3, **kwargs)


def auto_cli(
components: ComponentsType = None,
args: Optional[List[str]] = None,
config_help: str = default_config_option_help,
Expand All @@ -30,6 +35,8 @@ def CLI(
):
"""Simple creation of command line interfaces.

Previously CLI, renamed to follow the standard of functions in lowercase.

Creates an argument parser from one or more functions/classes, parses
arguments and runs one of the functions or class methods depending on what
was parsed. If the 'components' parameter is not given, then the components
Expand All @@ -50,6 +57,7 @@ def CLI(
The value returned by the executed function or class method.
"""
return_parser = kwargs.pop("return_parser", False)
stacklevel = kwargs.pop("_stacklevel", 2)
caller = inspect.stack()[1][0]

if components is None:
Expand Down Expand Up @@ -89,7 +97,7 @@ def CLI(
if set_defaults is not None:
parser.set_defaults(set_defaults)
if return_parser:
deprecation_warning_cli_return_parser()
deprecation_warning_cli_return_parser(stacklevel)
return parser
cfg = parser.parse_args(args)
init = parser.instantiate_classes(cfg)
Expand All @@ -103,7 +111,7 @@ def CLI(
if set_defaults is not None:
parser.set_defaults(set_defaults)
if return_parser:
deprecation_warning_cli_return_parser()
deprecation_warning_cli_return_parser(stacklevel)
return parser
cfg = parser.parse_args(args)
init = parser.instantiate_classes(cfg)
Expand Down
4 changes: 2 additions & 2 deletions jsonargparse/_deprecated.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,8 +369,8 @@ def set_url_support(enabled: bool):
"""


def deprecation_warning_cli_return_parser():
deprecation_warning("CLI.__init__.return_parser", cli_return_parser_message, stacklevel=2)
def deprecation_warning_cli_return_parser(stacklevel):
deprecation_warning("CLI.__init__.return_parser", cli_return_parser_message, stacklevel=stacklevel)


logger_property_none_message = """
Expand Down
Loading
Loading