Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: omni-us/jsonargparse
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v3.1.0
Choose a base ref
...
head repository: omni-us/jsonargparse
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v3.2.1
Choose a head ref
  • 10 commits
  • 40 files changed
  • 1 contributor

Commits on Dec 16, 2020

  1. Copy the full SHA
    2a8e097 View commit details
  2. Copy the full SHA
    52a7d94 View commit details
  3. Copy the full SHA
    61a6c62 View commit details

Commits on Dec 23, 2020

  1. - CLI now supports running methods from classes.

    - Correctly skip self in add_method_arguments for inherited methods.
    mauvilsa committed Dec 23, 2020
    Copy the full SHA
    e1c7960 View commit details
  2. Copy the full SHA
    31d5798 View commit details

Commits on Dec 29, 2020

  1. - Implemented generic _load_config and _ActionConfigLoad that are use…

    …d in signatures and jsonschema.
    
    - Signature arguments can now be loaded from independent config files #32.
    - parse_args now has a _skip_check option like the other parse methods.
    - Added explicit 'from ex' in some reraises.
    mauvilsa committed Dec 29, 2020
    Copy the full SHA
    37b46f4 View commit details

Commits on Dec 30, 2020

  1. - add_argument now supports enable_path for type based on jsonschema.

    - Prevent failure of dump in cleanup_actions due to new _ActionConfigLoad.
    - Prevent failure in save_paths for dict with int keys.
    - Made more consistent and compact the line breaks in changelog.
    - Added more explicit re-raising using the 'from' keyword.
    mauvilsa committed Dec 30, 2020
    Copy the full SHA
    4510d75 View commit details
  2. Copy the full SHA
    1a43603 View commit details
  3. - Avoid duplicate config check failure message with subcommands.

    - Prepare for v3.2.1 release.
    mauvilsa committed Dec 30, 2020
    Copy the full SHA
    22331b7 View commit details
  4. Copy the full SHA
    f550858 View commit details
Showing with 794 additions and 319 deletions.
  1. +1 −1 .bumpversion.cfg
  2. +1 −1 .sonarcloud.properties
  3. +25 −7 CHANGELOG.rst
  4. +97 −17 README.rst
  5. +1 −1 docs/.buildinfo
  6. +50 −14 docs/CHANGELOG.html
  7. +2 −2 docs/_modules/index.html
  8. +40 −17 docs/_modules/jsonargparse/actions.html
  9. +53 −27 docs/_modules/jsonargparse/cli.html
  10. +26 −29 docs/_modules/jsonargparse/core.html
  11. +6 −4 docs/_modules/jsonargparse/formatters.html
  12. +5 −5 docs/_modules/jsonargparse/jsonnet.html
  13. +7 −18 docs/_modules/jsonargparse/jsonschema.html
  14. +9 −9 docs/_modules/jsonargparse/optionals.html
  15. +10 −5 docs/_modules/jsonargparse/signatures.html
  16. +2 −2 docs/_modules/jsonargparse/typing.html
  17. +36 −5 docs/_modules/jsonargparse/util.html
  18. +25 −7 docs/_sources/CHANGELOG.rst.txt
  19. +1 −1 docs/_static/documentation_options.js
  20. +2 −2 docs/genindex.html
  21. +99 −28 docs/index.html
  22. BIN docs/objects.inv
  23. +2 −2 docs/py-modindex.html
  24. +2 −2 docs/search.html
  25. +1 −1 docs/searchindex.js
  26. +1 −1 jsonargparse/__init__.py
  27. +38 −15 jsonargparse/actions.py
  28. +51 −25 jsonargparse/cli.py
  29. +24 −27 jsonargparse/core.py
  30. +4 −2 jsonargparse/formatters.py
  31. +3 −3 jsonargparse/jsonnet.py
  32. +5 −16 jsonargparse/jsonschema.py
  33. +7 −7 jsonargparse/optionals.py
  34. +8 −3 jsonargparse/signatures.py
  35. +34 −3 jsonargparse/util.py
  36. +40 −2 jsonargparse_tests/cli_tests.py
  37. +7 −7 jsonargparse_tests/core_tests.py
  38. +5 −0 jsonargparse_tests/formatters_tests.py
  39. +63 −0 jsonargparse_tests/signatures_tests.py
  40. +1 −1 setup.cfg
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 3.1.0
current_version = 3.2.1
commit = True
tag = True
tag_name = v{new_version}
2 changes: 1 addition & 1 deletion .sonarcloud.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
sonar.sources=jsonargparse
sonar.projectVersion=3.1.0
sonar.projectVersion=3.2.1
32 changes: 25 additions & 7 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -9,12 +9,36 @@ follow `Semantic Versioning <https://semver.org/>`_
only be introduced in major versions with advance notice in the **Deprecated**
section of releases.

v3.1.0 (2020-12-09)
v3.2.1 (2020-12-30)
-------------------

Added
^^^^^
- Automatic Optional for arguments with default None #30.
- CLI now supports running methods from classes.
- Signature arguments can now be loaded from independent config files #32.
- add_argument now supports enable_path for type based on jsonschema.
- print_config can now be given as value skip_null to exclude null entries.

Changed
^^^^^^^
- Improved description of parser used as standalone and for ActionParser #34.
- Removed :code:`__cwd__` and top level :code:`__path__` that were not needed.

Fixed
^^^^^
- ActionYesNo argument in help the type is now bool.
- Correctly skip self in add_method_arguments for inherited methods.
- Prevent failure of dump in cleanup_actions due to new _ActionConfigLoad.
- Prevent failure in save_paths for dict with int keys.
- Avoid duplicate config check failure message with subcommands.


v3.1.0 (2020-12-09)
-------------------

Added
^^^^^
- Support for multiple levels of subcommands #29.
- Default description of subcommands explaining use of --help.

@@ -24,7 +48,6 @@ v3.0.1 (2020-12-02)

Fixed
^^^^^

- add_class_arguments incorrectly added arguments from :code:`__call__` instead
of :code:`__init__` for callable classes.

@@ -34,7 +57,6 @@ v3.0.0 (2020-12-01)

Added
^^^^^

- Functions to add arguments from classes, methods and functions.
- CLI function that allows creating a line command line interface with a single
line of code inspired by Fire.
@@ -44,20 +66,16 @@ Added
- Parsers now include --print_config option to dump defaults.
- Support argcomplete for tab completion of arguments.


Changed
^^^^^^^

- ArgumentParsers by default now use as error_handler the
usage_and_exit_error_handler.
- error_handler and formatter_class no longer accept as value a string.
- Changed SimpleNamespace to Namespace to avoid unnecessary differences with
argparse.


Deprecated
^^^^^^^^^^

- ActionOperators should no longer be used, the new alternative is
restricted number types.

114 changes: 97 additions & 17 deletions README.rst
Original file line number Diff line number Diff line change
@@ -125,24 +125,77 @@ Then in a shell you could run:
$ python example.py Lucky --prize=1000
Lucky won 1000€!
:func:`.CLI` without arguments searches for functions defined in the same module
and in the local context where :func:`.CLI` is called. If more than one function
is found, then any of them can be executed via :ref:`sub-commands`, e.g.
:code:`python example.py subcommand [arguments]`. Alternatively one or more
functions can be given to :func:`.CLI` skipping the automatic search.
:func:`.CLI` without arguments searches for functions and classes defined in the
same module and in the local context where :func:`.CLI` is called. Giving a
single or a list functions/classes as first argument to :func:`.CLI` skips the
automatic search and only includes what is given.

When :func:`.CLI` receives a single class, the first arguments are used to
instantiate the class, then a class method name must be given (see
:ref:`sub-commands`) and the remaining arguments are used to run the class
method. An example would be:

.. code-block:: python
from random import randint
from jsonargparse import CLI
class Main:
def __init__(
self,
max_prize: int = 100
):
"""
Args:
max_prize: Maximum prize that can be awarded.
"""
self.max_prize = max_prize
def person(
self,
name: str
):
"""
Args:
name: Name of winner.
"""
return f'{name} won {randint(0, self.max_prize)}€!'
if __name__ == '__main__':
print(CLI(Main))
Then in a shell you could run:

.. code-block:: bash
$ python example.py --max_prize=1000 person Lucky
Lucky won 632€!
If more than one function is given to :func:`.CLI`, then any of them can be
executed via :ref:`sub-commands` similar to the single class example above, e.g.
:code:`python example.py function [arguments]` where :code:`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 :ref:`sub-commands`
are required. The first sub-command would be name of the class and the second
the name of the method, i.e. :code:`python example.py class [init_arguments]
method [arguments]`. For more details about the automatic adding of arguments
from classes and functions and the use of configuration files refer to section
:ref:`classes-methods-functions`.

This simple way of usage is similar 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 specifically written for this
purpose. Second, the arguments of the functions are required to have type hints,
and the values will be validated according to these. Third, the return values of
the functions are not automatically printed. :func:`.CLI` returns its value and
it is up to the developer to decide what to do with it. Finally, jsonargparse
has many features designed to help in creating convenient argument parsers such
as: :ref:`nested-namespaces`, :ref:`configuration-files`, arguments from
:ref:`classes-methods-functions`, additional type hints (:ref:`parsing-paths`,
:ref:`restricted-numbers`, :ref:`restricted-strings`) and much more.
line. It is only intended for running functions and classes specifically written
for this purpose. Second, the arguments are required to have type hints, and the
values will be validated according to these. Third, the return values of the
functions are not automatically printed. :func:`.CLI` returns its value and it
is up to the developer to decide what to do with it. Finally, jsonargparse has
many features designed to help in creating convenient argument parsers such as:
:ref:`nested-namespaces`, :ref:`configuration-files`, additional type hints
(:ref:`parsing-paths`, :ref:`restricted-numbers`, :ref:`restricted-strings`) and
much more.

The next section explains how to create an argument parser in a very low level
argparse-style. However, as parsers get more complex, being able to define them
@@ -320,7 +373,10 @@ configuration content can also be provided.
All parsers include a :code:`--print_config` option. This is useful particularly
for command line tools with a large set of options to create an initial config
file including all default values.
file including all default values. This option by default all entries, including
the ones with :code:`null` values. If the argument is given as
:code:`--print_config=skip_null`, then the entries with :code:`null` values will
not be included.

The config file can also be provided as an environment variable as explained
in section :ref:`environment-variables`. The configuration file environment
@@ -395,6 +451,27 @@ since the init has the :code:`**kwargs` argument, the keyword arguments from
:code:`value` as a required float and :code:`flag` as an optional boolean with
default value false.

Instead of using :func:`namespace_to_dict` to convert the namespaces to a
dictionary, the :class:`.ArgumentParser` object can be instantiated with
:code:`parse_as_dict=True` to get directly a dictionary from the parsing
methods.

When parsing from a configuration file (see :ref:`configuration-files`) all the
values can be given in a single config file. However, for convenience it is also
possible that the values for each of the groups created by the calls to the add
signature methods can be parsed from independent files. This means that for the
example above there could be one general config file with contents:

.. code-block:: yaml
myclass:
init: myclass.yaml
method: mymethod.yaml
Then the files :code:`myclass.yaml` and :code:`mymethod.yaml` would only include
the settings for each of the instantiation of the class and the call to the
method respectively.

A wide range of type hints are supported. For exact details go to section
:ref:`type-hints`. Some notes about the support for automatic adding of
arguments are:
@@ -940,8 +1017,11 @@ populate the leaf nodes of the inner parser. In the example above, if
checked to populate :code:`inner.node.op1`.
An important detail to note is that the parsers that are given to
:class:`.ActionParser` are internally modified. So they should be instantiated
exclusively for the :class:`.ActionParser` and not used standalone.
:class:`.ActionParser` are internally modified. Therefore, to use the parser
both as standalone and an inner node, it is necessary to implement a function
that instantiates the parser. This function would be used in one place to get an
instance of the parser for standalone parsing, and in some other place use the
function to provide an instance of the parser to :class:`.ActionParser`.
Tab completion
2 changes: 1 addition & 1 deletion docs/.buildinfo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: 04ec28750e3cd287a0109fa160c8d588
config: 878f0894dcf8f9c240b49109bd5b5150
tags: 645f666f9bcd5a90fca523b33c5a78b7
64 changes: 50 additions & 14 deletions docs/CHANGELOG.html
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Changelog &mdash; jsonargparse 3.1.0 documentation</title>
<title>Changelog &mdash; jsonargparse 3.2.1 documentation</title>



@@ -59,7 +59,7 @@


<div class="version">
3.1.0
3.2.1
</div>


@@ -87,17 +87,23 @@
<!-- Local TOC -->
<div class="local-toc"><ul>
<li><a class="reference internal" href="#">Changelog</a><ul>
<li><a class="reference internal" href="#v3-1-0-2020-12-09">v3.1.0 (2020-12-09)</a><ul>
<li><a class="reference internal" href="#v3-2-1-2020-12-30">v3.2.1 (2020-12-30)</a><ul>
<li><a class="reference internal" href="#added">Added</a></li>
<li><a class="reference internal" href="#changed">Changed</a></li>
<li><a class="reference internal" href="#fixed">Fixed</a></li>
</ul>
</li>
<li><a class="reference internal" href="#v3-1-0-2020-12-09">v3.1.0 (2020-12-09)</a><ul>
<li><a class="reference internal" href="#id2">Added</a></li>
</ul>
</li>
<li><a class="reference internal" href="#v3-0-1-2020-12-02">v3.0.1 (2020-12-02)</a><ul>
<li><a class="reference internal" href="#fixed">Fixed</a></li>
<li><a class="reference internal" href="#id3">Fixed</a></li>
</ul>
</li>
<li><a class="reference internal" href="#v3-0-0-2020-12-01">v3.0.0 (2020-12-01)</a><ul>
<li><a class="reference internal" href="#id2">Added</a></li>
<li><a class="reference internal" href="#changed">Changed</a></li>
<li><a class="reference internal" href="#id4">Added</a></li>
<li><a class="reference internal" href="#id5">Changed</a></li>
<li><a class="reference internal" href="#deprecated">Deprecated</a></li>
</ul>
</li>
@@ -176,20 +182,50 @@
(<code class="docutils literal notranslate"><span class="pre">&lt;major&gt;.&lt;minor&gt;.&lt;patch&gt;</span></code>). Backward incompatible (breaking) changes will
only be introduced in major versions with advance notice in the <strong>Deprecated</strong>
section of releases.</p>
<div class="section" id="v3-1-0-2020-12-09">
<h2>v3.1.0 (2020-12-09)<a class="headerlink" href="#v3-1-0-2020-12-09" title="Permalink to this headline"></a></h2>
<div class="section" id="v3-2-1-2020-12-30">
<h2>v3.2.1 (2020-12-30)<a class="headerlink" href="#v3-2-1-2020-12-30" title="Permalink to this headline"></a></h2>
<div class="section" id="added">
<h3>Added<a class="headerlink" href="#added" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p>Automatic Optional for arguments with default None #30.</p></li>
<li><p>CLI now supports running methods from classes.</p></li>
<li><p>Signature arguments can now be loaded from independent config files #32.</p></li>
<li><p>add_argument now supports enable_path for type based on jsonschema.</p></li>
<li><p>print_config can now be given as value skip_null to exclude null entries.</p></li>
</ul>
</div>
<div class="section" id="changed">
<h3>Changed<a class="headerlink" href="#changed" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p>Improved description of parser used as standalone and for ActionParser #34.</p></li>
<li><p>Removed <code class="code docutils literal notranslate"><span class="pre">__cwd__</span></code> and top level <code class="code docutils literal notranslate"><span class="pre">__path__</span></code> that were not needed.</p></li>
</ul>
</div>
<div class="section" id="fixed">
<h3>Fixed<a class="headerlink" href="#fixed" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p>ActionYesNo argument in help the type is now bool.</p></li>
<li><p>Correctly skip self in add_method_arguments for inherited methods.</p></li>
<li><p>Prevent failure of dump in cleanup_actions due to new _ActionConfigLoad.</p></li>
<li><p>Prevent failure in save_paths for dict with int keys.</p></li>
<li><p>Avoid duplicate config check failure message with subcommands.</p></li>
</ul>
</div>
</div>
<div class="section" id="v3-1-0-2020-12-09">
<h2>v3.1.0 (2020-12-09)<a class="headerlink" href="#v3-1-0-2020-12-09" title="Permalink to this headline"></a></h2>
<div class="section" id="id2">
<h3>Added<a class="headerlink" href="#id2" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p>Support for multiple levels of subcommands #29.</p></li>
<li><p>Default description of subcommands explaining use of –help.</p></li>
</ul>
</div>
</div>
<div class="section" id="v3-0-1-2020-12-02">
<h2>v3.0.1 (2020-12-02)<a class="headerlink" href="#v3-0-1-2020-12-02" title="Permalink to this headline"></a></h2>
<div class="section" id="fixed">
<h3>Fixed<a class="headerlink" href="#fixed" title="Permalink to this headline"></a></h3>
<div class="section" id="id3">
<h3>Fixed<a class="headerlink" href="#id3" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p>add_class_arguments incorrectly added arguments from <code class="code docutils literal notranslate"><span class="pre">__call__</span></code> instead
of <code class="code docutils literal notranslate"><span class="pre">__init__</span></code> for callable classes.</p></li>
@@ -198,8 +234,8 @@ <h3>Fixed<a class="headerlink" href="#fixed" title="Permalink to this headline">
</div>
<div class="section" id="v3-0-0-2020-12-01">
<h2>v3.0.0 (2020-12-01)<a class="headerlink" href="#v3-0-0-2020-12-01" title="Permalink to this headline"></a></h2>
<div class="section" id="id2">
<h3>Added<a class="headerlink" href="#id2" title="Permalink to this headline"></a></h3>
<div class="section" id="id4">
<h3>Added<a class="headerlink" href="#id4" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p>Functions to add arguments from classes, methods and functions.</p></li>
<li><p>CLI function that allows creating a line command line interface with a single
@@ -211,8 +247,8 @@ <h3>Added<a class="headerlink" href="#id2" title="Permalink to this headline">¶
<li><p>Support argcomplete for tab completion of arguments.</p></li>
</ul>
</div>
<div class="section" id="changed">
<h3>Changed<a class="headerlink" href="#changed" title="Permalink to this headline"></a></h3>
<div class="section" id="id5">
<h3>Changed<a class="headerlink" href="#id5" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p>ArgumentParsers by default now use as error_handler the
usage_and_exit_error_handler.</p></li>
4 changes: 2 additions & 2 deletions docs/_modules/index.html
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Overview: module code &mdash; jsonargparse 3.1.0 documentation</title>
<title>Overview: module code &mdash; jsonargparse 3.2.1 documentation</title>



@@ -59,7 +59,7 @@


<div class="version">
3.1.0
3.2.1
</div>


57 changes: 40 additions & 17 deletions docs/_modules/jsonargparse/actions.html

Large diffs are not rendered by default.

80 changes: 53 additions & 27 deletions docs/_modules/jsonargparse/cli.html

Large diffs are not rendered by default.

55 changes: 26 additions & 29 deletions docs/_modules/jsonargparse/core.html

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions docs/_modules/jsonargparse/formatters.html
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>jsonargparse.formatters &mdash; jsonargparse 3.1.0 documentation</title>
<title>jsonargparse.formatters &mdash; jsonargparse 3.2.1 documentation</title>



@@ -59,7 +59,7 @@


<div class="version">
3.1.0
3.2.1
</div>


@@ -155,7 +155,7 @@ <h1>Source code for jsonargparse.formatters</h1><div class="highlight"><pre>

<span class="kn">from</span> <span class="nn">.util</span> <span class="k">import</span> <span class="n">_get_env_var</span>
<span class="kn">from</span> <span class="nn">.typing</span> <span class="k">import</span> <span class="n">type_to_str</span>
<span class="kn">from</span> <span class="nn">.actions</span> <span class="k">import</span> <span class="n">ActionParser</span><span class="p">,</span> <span class="n">ActionEnum</span><span class="p">,</span> <span class="n">ActionConfigFile</span>
<span class="kn">from</span> <span class="nn">.actions</span> <span class="k">import</span> <span class="n">ActionParser</span><span class="p">,</span> <span class="n">ActionEnum</span><span class="p">,</span> <span class="n">ActionYesNo</span><span class="p">,</span> <span class="n">ActionConfigFile</span>
<span class="kn">from</span> <span class="nn">.jsonschema</span> <span class="k">import</span> <span class="n">ActionJsonSchema</span>


@@ -228,7 +228,9 @@ <h1>Source code for jsonargparse.formatters</h1><div class="highlight"><pre>

<span class="k">def</span> <span class="nf">_get_type_str</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">action</span><span class="p">):</span>
<span class="n">type_str</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">if</span> <span class="n">action</span><span class="o">.</span><span class="n">type</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">action</span><span class="p">,</span> <span class="n">ActionYesNo</span><span class="p">):</span>
<span class="n">type_str</span> <span class="o">=</span> <span class="s1">&#39;bool&#39;</span>
<span class="k">elif</span> <span class="n">action</span><span class="o">.</span><span class="n">type</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">type_str</span> <span class="o">=</span> <span class="n">type_to_str</span><span class="p">(</span><span class="n">action</span><span class="o">.</span><span class="n">type</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">action</span><span class="p">,</span> <span class="n">ActionEnum</span><span class="p">):</span>
<span class="n">type_str</span> <span class="o">=</span> <span class="n">type_to_str</span><span class="p">(</span><span class="n">action</span><span class="o">.</span><span class="n">_enum</span><span class="p">)</span>
10 changes: 5 additions & 5 deletions docs/_modules/jsonargparse/jsonnet.html
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>jsonargparse.jsonnet &mdash; jsonargparse 3.1.0 documentation</title>
<title>jsonargparse.jsonnet &mdash; jsonargparse 3.2.1 documentation</title>



@@ -59,7 +59,7 @@


<div class="version">
3.1.0
3.2.1
</div>


@@ -222,7 +222,7 @@ <h1>Source code for jsonargparse.jsonnet</h1><div class="highlight"><pre>
<span class="k">try</span><span class="p">:</span>
<span class="n">schema</span> <span class="o">=</span> <span class="n">yaml</span><span class="o">.</span><span class="n">safe_load</span><span class="p">(</span><span class="n">schema</span><span class="p">)</span>
<span class="k">except</span> <span class="p">(</span><span class="n">yamlParserError</span><span class="p">,</span> <span class="n">yamlScannerError</span><span class="p">)</span> <span class="k">as</span> <span class="n">ex</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s1">&#39;Problems parsing schema :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s1">&#39;Problems parsing schema :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span> <span class="kn">from</span> <span class="nn">ex</span>
<span class="n">jsonvalidator</span><span class="o">.</span><span class="n">check_schema</span><span class="p">(</span><span class="n">schema</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_validator</span> <span class="o">=</span> <span class="n">ActionJsonSchema</span><span class="o">.</span><span class="n">_extend_jsonvalidator_with_default</span><span class="p">(</span><span class="n">jsonvalidator</span><span class="p">)(</span><span class="n">schema</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
@@ -269,7 +269,7 @@ <h1>Source code for jsonargparse.jsonnet</h1><div class="highlight"><pre>
<span class="n">value</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">=</span> <span class="n">val</span>
<span class="k">except</span> <span class="p">(</span><span class="ne">TypeError</span><span class="p">,</span> <span class="ne">RuntimeError</span><span class="p">,</span> <span class="n">yamlParserError</span><span class="p">,</span> <span class="n">yamlScannerError</span><span class="p">,</span> <span class="n">jsonschemaValidationError</span><span class="p">)</span> <span class="k">as</span> <span class="n">ex</span><span class="p">:</span>
<span class="n">elem</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">islist</span> <span class="k">else</span> <span class="s1">&#39; element &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">num</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s1">&#39;Parser key &quot;&#39;</span><span class="o">+</span><span class="bp">self</span><span class="o">.</span><span class="n">dest</span><span class="o">+</span><span class="s1">&#39;&quot;&#39;</span><span class="o">+</span><span class="n">elem</span><span class="o">+</span><span class="s1">&#39;: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span>
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s1">&#39;Parser key &quot;&#39;</span><span class="o">+</span><span class="bp">self</span><span class="o">.</span><span class="n">dest</span><span class="o">+</span><span class="s1">&#39;&quot;&#39;</span><span class="o">+</span><span class="n">elem</span><span class="o">+</span><span class="s1">&#39;: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span> <span class="kn">from</span> <span class="nn">ex</span>
<span class="k">return</span> <span class="n">value</span> <span class="k">if</span> <span class="n">islist</span> <span class="k">else</span> <span class="n">value</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>


@@ -325,7 +325,7 @@ <h1>Source code for jsonargparse.jsonnet</h1><div class="highlight"><pre>
<span class="k">try</span><span class="p">:</span>
<span class="n">values</span> <span class="o">=</span> <span class="n">yaml</span><span class="o">.</span><span class="n">safe_load</span><span class="p">(</span><span class="n">_jsonnet</span><span class="o">.</span><span class="n">evaluate_snippet</span><span class="p">(</span><span class="n">fname</span><span class="p">,</span> <span class="n">snippet</span><span class="p">,</span> <span class="n">ext_vars</span><span class="o">=</span><span class="n">ext_vars</span><span class="p">,</span> <span class="n">ext_codes</span><span class="o">=</span><span class="n">ext_codes</span><span class="p">))</span>
<span class="k">except</span> <span class="ne">RuntimeError</span> <span class="k">as</span> <span class="n">ex</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">ParserError</span><span class="p">(</span><span class="s1">&#39;Problems evaluating jsonnet &quot;&#39;</span><span class="o">+</span><span class="n">fname</span><span class="o">+</span><span class="s1">&#39;&quot; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span>
<span class="k">raise</span> <span class="n">ParserError</span><span class="p">(</span><span class="s1">&#39;Problems evaluating jsonnet &quot;&#39;</span><span class="o">+</span><span class="n">fname</span><span class="o">+</span><span class="s1">&#39;&quot; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span> <span class="kn">from</span> <span class="nn">ex</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_validator</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_validator</span><span class="o">.</span><span class="n">validate</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
<span class="k">if</span> <span class="n">with_meta</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="nb">dict</span><span class="p">)</span> <span class="ow">and</span> <span class="n">fpath</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
25 changes: 7 additions & 18 deletions docs/_modules/jsonargparse/jsonschema.html
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>jsonargparse.jsonschema &mdash; jsonargparse 3.1.0 documentation</title>
<title>jsonargparse.jsonschema &mdash; jsonargparse 3.2.1 documentation</title>



@@ -59,7 +59,7 @@


<div class="version">
3.1.0
3.2.1
</div>


@@ -168,6 +168,7 @@ <h1>Source code for jsonargparse.jsonschema</h1><div class="highlight"><pre>
<span class="n">ParserError</span><span class="p">,</span>
<span class="n">strip_meta</span><span class="p">,</span>
<span class="n">import_object</span><span class="p">,</span>
<span class="n">_load_config</span><span class="p">,</span>
<span class="n">_check_unknown_kwargs</span><span class="p">,</span>
<span class="n">_issubclass</span><span class="p">,</span>
<span class="p">)</span>
@@ -176,7 +177,6 @@ <h1>Source code for jsonargparse.jsonschema</h1><div class="highlight"><pre>
<span class="n">jsonschemaValidationError</span><span class="p">,</span>
<span class="n">jsonschema_support</span><span class="p">,</span>
<span class="n">import_jsonschema</span><span class="p">,</span>
<span class="n">get_config_read_mode</span><span class="p">,</span>
<span class="n">files_completer</span><span class="p">,</span>
<span class="n">argcomplete_warn_redraw_prompt</span><span class="p">,</span>
<span class="p">)</span>
@@ -240,7 +240,7 @@ <h1>Source code for jsonargparse.jsonschema</h1><div class="highlight"><pre>
<span class="k">try</span><span class="p">:</span>
<span class="n">schema</span> <span class="o">=</span> <span class="n">yaml</span><span class="o">.</span><span class="n">safe_load</span><span class="p">(</span><span class="n">schema</span><span class="p">)</span>
<span class="k">except</span> <span class="p">(</span><span class="n">yamlParserError</span><span class="p">,</span> <span class="n">yamlScannerError</span><span class="p">)</span> <span class="k">as</span> <span class="n">ex</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s1">&#39;Problems parsing schema :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s1">&#39;Problems parsing schema :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span> <span class="kn">from</span> <span class="nn">ex</span>
<span class="n">jsonvalidator</span><span class="o">.</span><span class="n">check_schema</span><span class="p">(</span><span class="n">schema</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_validator</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_extend_jsonvalidator_with_default</span><span class="p">(</span><span class="n">jsonvalidator</span><span class="p">)(</span><span class="n">schema</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_enable_path</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;enable_path&#39;</span><span class="p">,</span> <span class="kc">True</span><span class="p">)</span>
@@ -286,18 +286,7 @@ <h1>Source code for jsonargparse.jsonschema</h1><div class="highlight"><pre>
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">value</span><span class="p">]</span>
<span class="k">for</span> <span class="n">num</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">fpath</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span> <span class="ow">and</span> <span class="n">val</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="o">!=</span> <span class="s1">&#39;&#39;</span><span class="p">:</span>
<span class="n">parsed_val</span> <span class="o">=</span> <span class="n">yaml</span><span class="o">.</span><span class="n">safe_load</span><span class="p">(</span><span class="n">val</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">parsed_val</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
<span class="n">val</span> <span class="o">=</span> <span class="n">parsed_val</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_enable_path</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">fpath</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="n">get_config_read_mode</span><span class="p">())</span>
<span class="k">except</span> <span class="ne">TypeError</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">val</span> <span class="o">=</span> <span class="n">yaml</span><span class="o">.</span><span class="n">safe_load</span><span class="p">(</span><span class="n">fpath</span><span class="o">.</span><span class="n">get_content</span><span class="p">())</span>
<span class="n">val</span><span class="p">,</span> <span class="n">fpath</span> <span class="o">=</span> <span class="n">_load_config</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="n">enable_path</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_enable_path</span><span class="p">,</span> <span class="n">flat_namespace</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="n">Namespace</span><span class="p">):</span>
<span class="n">val</span> <span class="o">=</span> <span class="n">namespace_to_dict</span><span class="p">(</span><span class="n">val</span><span class="p">)</span>
<span class="n">val</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_adapt_types</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_annotation</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_subschemas</span><span class="p">,</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
@@ -311,7 +300,7 @@ <h1>Source code for jsonargparse.jsonschema</h1><div class="highlight"><pre>
<span class="n">value</span><span class="p">[</span><span class="n">num</span><span class="p">]</span> <span class="o">=</span> <span class="n">val</span>
<span class="k">except</span> <span class="p">(</span><span class="ne">TypeError</span><span class="p">,</span> <span class="n">yamlParserError</span><span class="p">,</span> <span class="n">yamlScannerError</span><span class="p">,</span> <span class="n">jsonschemaValidationError</span><span class="p">)</span> <span class="k">as</span> <span class="n">ex</span><span class="p">:</span>
<span class="n">elem</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">islist</span> <span class="k">else</span> <span class="s1">&#39; element &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">num</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s1">&#39;Parser key &quot;&#39;</span><span class="o">+</span><span class="bp">self</span><span class="o">.</span><span class="n">dest</span><span class="o">+</span><span class="s1">&#39;&quot;&#39;</span><span class="o">+</span><span class="n">elem</span><span class="o">+</span><span class="s1">&#39;: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span>
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s1">&#39;Parser key &quot;&#39;</span><span class="o">+</span><span class="bp">self</span><span class="o">.</span><span class="n">dest</span><span class="o">+</span><span class="s1">&#39;&quot;&#39;</span><span class="o">+</span><span class="n">elem</span><span class="o">+</span><span class="s1">&#39;: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span> <span class="kn">from</span> <span class="nn">ex</span>
<span class="k">return</span> <span class="n">value</span> <span class="k">if</span> <span class="n">islist</span> <span class="k">else</span> <span class="n">value</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>


@@ -386,7 +375,7 @@ <h1>Source code for jsonargparse.jsonschema</h1><div class="highlight"><pre>
<span class="n">init_args</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">instantiate_subclasses</span><span class="p">(</span><span class="n">val</span><span class="p">[</span><span class="s1">&#39;init_args&#39;</span><span class="p">])</span>
<span class="n">val</span> <span class="o">=</span> <span class="n">val_class</span><span class="p">(</span><span class="o">**</span><span class="n">init_args</span><span class="p">)</span> <span class="c1"># pylint: disable=not-a-mapping</span>
<span class="k">except</span> <span class="p">(</span><span class="ne">ImportError</span><span class="p">,</span> <span class="n">ModuleNotFound</span><span class="p">,</span> <span class="ne">AttributeError</span><span class="p">,</span> <span class="ne">AssertionError</span><span class="p">,</span> <span class="n">ParserError</span><span class="p">)</span> <span class="k">as</span> <span class="n">ex</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">ParserError</span><span class="p">(</span><span class="s1">&#39;Problem with given class_path &quot;&#39;</span><span class="o">+</span><span class="n">val</span><span class="p">[</span><span class="s1">&#39;class_path&#39;</span><span class="p">]</span><span class="o">+</span><span class="s1">&#39;&quot; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span>
<span class="k">raise</span> <span class="n">ParserError</span><span class="p">(</span><span class="s1">&#39;Problem with given class_path &quot;&#39;</span><span class="o">+</span><span class="n">val</span><span class="p">[</span><span class="s1">&#39;class_path&#39;</span><span class="p">]</span><span class="o">+</span><span class="s1">&#39;&quot; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span> <span class="kn">from</span> <span class="nn">ex</span>
<span class="k">return</span> <span class="n">val</span>

<span class="k">elif</span> <span class="n">annotation</span><span class="o">.</span><span class="n">__origin__</span> <span class="o">==</span> <span class="n">Union</span><span class="p">:</span>
18 changes: 9 additions & 9 deletions docs/_modules/jsonargparse/optionals.html
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>jsonargparse.optionals &mdash; jsonargparse 3.1.0 documentation</title>
<title>jsonargparse.optionals &mdash; jsonargparse 3.2.1 documentation</title>



@@ -59,7 +59,7 @@


<div class="version">
3.1.0
3.2.1
</div>


@@ -199,55 +199,55 @@ <h1>Source code for jsonargparse.optionals</h1><div class="highlight"><pre>
<span class="kn">from</span> <span class="nn">jsonschema</span> <span class="k">import</span> <span class="n">Draft7Validator</span> <span class="k">as</span> <span class="n">jsonvalidator</span>
<span class="k">return</span> <span class="n">jsonschema</span><span class="p">,</span> <span class="n">jsonvalidator</span>
<span class="k">except</span> <span class="p">(</span><span class="ne">ImportError</span><span class="p">,</span> <span class="n">ModuleNotFound</span><span class="p">)</span> <span class="k">as</span> <span class="n">ex</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;jsonschema package is required by &#39;</span><span class="o">+</span><span class="n">importer</span><span class="o">+</span><span class="s1">&#39; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span>
<span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;jsonschema package is required by &#39;</span><span class="o">+</span><span class="n">importer</span><span class="o">+</span><span class="s1">&#39; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span> <span class="kn">from</span> <span class="nn">ex</span>


<span class="k">def</span> <span class="nf">import_jsonnet</span><span class="p">(</span><span class="n">importer</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">_jsonnet</span>
<span class="k">return</span> <span class="n">_jsonnet</span>
<span class="k">except</span> <span class="p">(</span><span class="ne">ImportError</span><span class="p">,</span> <span class="n">ModuleNotFound</span><span class="p">)</span> <span class="k">as</span> <span class="n">ex</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;jsonnet package is required by &#39;</span><span class="o">+</span><span class="n">importer</span><span class="o">+</span><span class="s1">&#39; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span>
<span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;jsonnet package is required by &#39;</span><span class="o">+</span><span class="n">importer</span><span class="o">+</span><span class="s1">&#39; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span> <span class="kn">from</span> <span class="nn">ex</span>


<span class="k">def</span> <span class="nf">import_url_validator</span><span class="p">(</span><span class="n">importer</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">validators.url</span> <span class="k">import</span> <span class="n">url</span> <span class="k">as</span> <span class="n">url_validator</span>
<span class="k">return</span> <span class="n">url_validator</span>
<span class="k">except</span> <span class="p">(</span><span class="ne">ImportError</span><span class="p">,</span> <span class="n">ModuleNotFound</span><span class="p">)</span> <span class="k">as</span> <span class="n">ex</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;validators package is required by &#39;</span><span class="o">+</span><span class="n">importer</span><span class="o">+</span><span class="s1">&#39; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span>
<span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;validators package is required by &#39;</span><span class="o">+</span><span class="n">importer</span><span class="o">+</span><span class="s1">&#39; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span> <span class="kn">from</span> <span class="nn">ex</span>


<span class="k">def</span> <span class="nf">import_requests</span><span class="p">(</span><span class="n">importer</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">requests</span>
<span class="k">return</span> <span class="n">requests</span>
<span class="k">except</span> <span class="p">(</span><span class="ne">ImportError</span><span class="p">,</span> <span class="n">ModuleNotFound</span><span class="p">)</span> <span class="k">as</span> <span class="n">ex</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;requests package is required by &#39;</span><span class="o">+</span><span class="n">importer</span><span class="o">+</span><span class="s1">&#39; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span>
<span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;requests package is required by &#39;</span><span class="o">+</span><span class="n">importer</span><span class="o">+</span><span class="s1">&#39; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span> <span class="kn">from</span> <span class="nn">ex</span>


<span class="k">def</span> <span class="nf">import_docstring_parse</span><span class="p">(</span><span class="n">importer</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">docstring_parser</span> <span class="k">import</span> <span class="n">parse</span> <span class="k">as</span> <span class="n">docstring_parse</span>
<span class="k">return</span> <span class="n">docstring_parse</span>
<span class="k">except</span> <span class="p">(</span><span class="ne">ImportError</span><span class="p">,</span> <span class="n">ModuleNotFound</span><span class="p">)</span> <span class="k">as</span> <span class="n">ex</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;docstring-parser package is required by &#39;</span><span class="o">+</span><span class="n">importer</span><span class="o">+</span><span class="s1">&#39; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span>
<span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;docstring-parser package is required by &#39;</span><span class="o">+</span><span class="n">importer</span><span class="o">+</span><span class="s1">&#39; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span> <span class="kn">from</span> <span class="nn">ex</span>


<span class="k">def</span> <span class="nf">import_argcomplete</span><span class="p">(</span><span class="n">importer</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">argcomplete</span>
<span class="k">return</span> <span class="n">argcomplete</span>
<span class="k">except</span> <span class="p">(</span><span class="ne">ImportError</span><span class="p">,</span> <span class="n">ModuleNotFound</span><span class="p">)</span> <span class="k">as</span> <span class="n">ex</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;argcomplete package is required by &#39;</span><span class="o">+</span><span class="n">importer</span><span class="o">+</span><span class="s1">&#39; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span>
<span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;argcomplete package is required by &#39;</span><span class="o">+</span><span class="n">importer</span><span class="o">+</span><span class="s1">&#39; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span> <span class="kn">from</span> <span class="nn">ex</span>


<span class="k">def</span> <span class="nf">import_dataclasses</span><span class="p">(</span><span class="n">importer</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">dataclasses</span>
<span class="k">return</span> <span class="n">dataclasses</span>
<span class="k">except</span> <span class="p">(</span><span class="ne">ImportError</span><span class="p">,</span> <span class="n">ModuleNotFound</span><span class="p">)</span> <span class="k">as</span> <span class="n">ex</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;dataclasses package is required by &#39;</span><span class="o">+</span><span class="n">importer</span><span class="o">+</span><span class="s1">&#39; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span>
<span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;dataclasses package is required by &#39;</span><span class="o">+</span><span class="n">importer</span><span class="o">+</span><span class="s1">&#39; :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span> <span class="kn">from</span> <span class="nn">ex</span>


<div class="viewcode-block" id="set_url_support"><a class="viewcode-back" href="../../index.html#jsonargparse.optionals.set_url_support">[docs]</a><span class="k">def</span> <span class="nf">set_url_support</span><span class="p">(</span><span class="n">enabled</span><span class="p">:</span><span class="nb">bool</span><span class="p">):</span>
15 changes: 10 additions & 5 deletions docs/_modules/jsonargparse/signatures.html
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>jsonargparse.signatures &mdash; jsonargparse 3.1.0 documentation</title>
<title>jsonargparse.signatures &mdash; jsonargparse 3.2.1 documentation</title>



@@ -59,7 +59,7 @@


<div class="version">
3.1.0
3.2.1
</div>


@@ -155,7 +155,8 @@ <h1>Source code for jsonargparse.signatures</h1><div class="highlight"><pre>
<span class="kn">from</span> <span class="nn">typing</span> <span class="k">import</span> <span class="n">Union</span><span class="p">,</span> <span class="n">Optional</span><span class="p">,</span> <span class="n">List</span><span class="p">,</span> <span class="n">Container</span><span class="p">,</span> <span class="n">Type</span><span class="p">,</span> <span class="n">Callable</span>

<span class="kn">from</span> <span class="nn">.util</span> <span class="k">import</span> <span class="n">_issubclass</span>
<span class="kn">from</span> <span class="nn">.actions</span> <span class="k">import</span> <span class="n">ActionEnum</span>
<span class="kn">from</span> <span class="nn">.actions</span> <span class="k">import</span> <span class="n">ActionEnum</span><span class="p">,</span> <span class="n">_ActionConfigLoad</span>
<span class="kn">from</span> <span class="nn">.typing</span> <span class="k">import</span> <span class="n">is_optional</span>
<span class="kn">from</span> <span class="nn">.jsonschema</span> <span class="k">import</span> <span class="n">ActionJsonSchema</span>
<span class="kn">from</span> <span class="nn">.optionals</span> <span class="k">import</span> <span class="n">docstring_parser_support</span><span class="p">,</span> <span class="n">import_docstring_parse</span><span class="p">,</span> <span class="n">dataclasses_support</span><span class="p">,</span> <span class="n">import_dataclasses</span>

@@ -242,9 +243,9 @@ <h1>Source code for jsonargparse.signatures</h1><div class="highlight"><pre>
<span class="k">if</span> <span class="ow">not</span> <span class="n">inspect</span><span class="o">.</span><span class="n">isclass</span><span class="p">(</span><span class="n">theclass</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s1">&#39;Expected a class object.&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">theclass</span><span class="p">,</span> <span class="n">themethod</span><span class="p">)</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">callable</span><span class="p">(</span><span class="nb">getattr</span><span class="p">(</span><span class="n">theclass</span><span class="p">,</span> <span class="n">themethod</span><span class="p">)):</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s1">&#39;Expected the method to a callable member of the class.&#39;</span><span class="p">)</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s1">&#39;Expected the method to be a callable member of the class.&#39;</span><span class="p">)</span>

<span class="n">skip_first</span> <span class="o">=</span> <span class="kc">False</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">theclass</span><span class="o">.</span><span class="vm">__dict__</span><span class="p">[</span><span class="n">themethod</span><span class="p">],</span> <span class="nb">staticmethod</span><span class="p">)</span> <span class="k">else</span> <span class="kc">True</span>
<span class="n">skip_first</span> <span class="o">=</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">inspect</span><span class="o">.</span><span class="n">getattr_static</span><span class="p">(</span><span class="n">theclass</span><span class="p">,</span> <span class="n">themethod</span><span class="p">),</span> <span class="nb">staticmethod</span><span class="p">)</span>
<span class="n">themethod</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">theclass</span><span class="p">,</span> <span class="n">themethod</span><span class="p">)</span>

<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_add_signature_arguments</span><span class="p">([</span><span class="n">themethod</span><span class="p">],</span>
@@ -363,6 +364,8 @@ <h1>Source code for jsonargparse.signatures</h1><div class="highlight"><pre>
<span class="n">doc_group</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">objects</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="n">name</span> <span class="o">=</span> <span class="n">objects</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="vm">__name__</span> <span class="k">if</span> <span class="n">nested_key</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">nested_key</span>
<span class="n">group</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">add_argument_group</span><span class="p">(</span><span class="n">doc_group</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">name</span><span class="p">)</span> <span class="c1"># type: ignore</span>
<span class="k">if</span> <span class="n">nested_key</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">group</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">&#39;--&#39;</span><span class="o">+</span><span class="n">nested_key</span><span class="p">,</span> <span class="n">action</span><span class="o">=</span><span class="n">_ActionConfigLoad</span><span class="p">)</span> <span class="c1"># type: ignore</span>

<span class="c1">## Add objects arguments ##</span>
<span class="n">added_args</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
@@ -397,6 +400,8 @@ <h1>Source code for jsonargparse.signatures</h1><div class="highlight"><pre>
<span class="n">kwargs</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;help&#39;</span><span class="p">:</span> <span class="n">doc_params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="p">)}</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">is_required</span><span class="p">:</span>
<span class="n">kwargs</span><span class="p">[</span><span class="s1">&#39;default&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">default</span>
<span class="k">if</span> <span class="n">default</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">is_optional</span><span class="p">(</span><span class="n">annotation</span><span class="p">,</span> <span class="nb">object</span><span class="p">):</span>
<span class="n">annotation</span> <span class="o">=</span> <span class="n">Optional</span><span class="p">[</span><span class="n">annotation</span><span class="p">]</span>
<span class="k">elif</span> <span class="ow">not</span> <span class="n">as_positional</span><span class="p">:</span>
<span class="n">kwargs</span><span class="p">[</span><span class="s1">&#39;required&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">if</span> <span class="n">annotation</span> <span class="ow">in</span> <span class="p">{</span><span class="nb">str</span><span class="p">,</span> <span class="nb">int</span><span class="p">,</span> <span class="nb">float</span><span class="p">,</span> <span class="nb">bool</span><span class="p">}</span> <span class="ow">or</span> \
4 changes: 2 additions & 2 deletions docs/_modules/jsonargparse/typing.html
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>jsonargparse.typing &mdash; jsonargparse 3.1.0 documentation</title>
<title>jsonargparse.typing &mdash; jsonargparse 3.2.1 documentation</title>



@@ -59,7 +59,7 @@


<div class="version">
3.1.0
3.2.1
</div>


41 changes: 36 additions & 5 deletions docs/_modules/jsonargparse/util.html
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>jsonargparse.util &mdash; jsonargparse 3.1.0 documentation</title>
<title>jsonargparse.util &mdash; jsonargparse 3.2.1 documentation</title>



@@ -59,7 +59,7 @@


<div class="version">
3.1.0
3.2.1
</div>


@@ -154,6 +154,7 @@ <h1>Source code for jsonargparse.util</h1><div class="highlight"><pre>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">stat</span>
<span class="kn">import</span> <span class="nn">yaml</span>
<span class="kn">import</span> <span class="nn">inspect</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="kn">from</span> <span class="nn">copy</span> <span class="k">import</span> <span class="n">deepcopy</span>
@@ -163,7 +164,13 @@ <h1>Source code for jsonargparse.util</h1><div class="highlight"><pre>
<span class="kn">from</span> <span class="nn">yaml.parser</span> <span class="k">import</span> <span class="n">ParserError</span> <span class="k">as</span> <span class="n">yamlParserError</span>
<span class="kn">from</span> <span class="nn">yaml.scanner</span> <span class="k">import</span> <span class="n">ScannerError</span> <span class="k">as</span> <span class="n">yamlScannerError</span>

<span class="kn">from</span> <span class="nn">.optionals</span> <span class="k">import</span> <span class="n">ModuleNotFound</span><span class="p">,</span> <span class="n">url_support</span><span class="p">,</span> <span class="n">import_requests</span><span class="p">,</span> <span class="n">import_url_validator</span>
<span class="kn">from</span> <span class="nn">.optionals</span> <span class="k">import</span> <span class="p">(</span>
<span class="n">ModuleNotFound</span><span class="p">,</span>
<span class="n">url_support</span><span class="p">,</span>
<span class="n">import_requests</span><span class="p">,</span>
<span class="n">import_url_validator</span><span class="p">,</span>
<span class="n">get_config_read_mode</span><span class="p">,</span>
<span class="p">)</span>


<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span>
@@ -182,14 +189,38 @@ <h1>Source code for jsonargparse.util</h1><div class="highlight"><pre>
<span class="n">null_logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">Logger</span><span class="p">(</span><span class="s1">&#39;jsonargparse_null_logger&#39;</span><span class="p">)</span>
<span class="n">null_logger</span><span class="o">.</span><span class="n">addHandler</span><span class="p">(</span><span class="n">logging</span><span class="o">.</span><span class="n">NullHandler</span><span class="p">())</span>

<span class="n">meta_keys</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;__cwd__&#39;</span><span class="p">,</span> <span class="s1">&#39;__path__&#39;</span><span class="p">,</span> <span class="s1">&#39;__default_config__&#39;</span><span class="p">}</span>
<span class="n">meta_keys</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;__path__&#39;</span><span class="p">,</span> <span class="s1">&#39;__default_config__&#39;</span><span class="p">}</span>


<div class="viewcode-block" id="ParserError"><a class="viewcode-back" href="../../index.html#jsonargparse.util.ParserError">[docs]</a><span class="k">class</span> <span class="nc">ParserError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Error raised when parsing a value fails.&quot;&quot;&quot;</span>
<span class="k">pass</span></div>


<span class="k">def</span> <span class="nf">_load_config</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">enable_path</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">flat_namespace</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Parses yaml config in a string or a path&quot;&quot;&quot;</span>
<span class="n">cfg_path</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span> <span class="ow">and</span> <span class="n">value</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="o">!=</span> <span class="s1">&#39;&#39;</span><span class="p">:</span>
<span class="n">parsed_val</span> <span class="o">=</span> <span class="n">yaml</span><span class="o">.</span><span class="n">safe_load</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">parsed_val</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
<span class="n">value</span> <span class="o">=</span> <span class="n">parsed_val</span>
<span class="k">if</span> <span class="n">enable_path</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">cfg_path</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="n">get_config_read_mode</span><span class="p">())</span>
<span class="k">except</span> <span class="ne">TypeError</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">value</span> <span class="o">=</span> <span class="n">yaml</span><span class="o">.</span><span class="n">safe_load</span><span class="p">(</span><span class="n">cfg_path</span><span class="o">.</span><span class="n">get_content</span><span class="p">())</span>

<span class="k">if</span> <span class="n">flat_namespace</span><span class="p">:</span>
<span class="n">value</span> <span class="o">=</span> <span class="n">_dict_to_flat_namespace</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
<span class="k">if</span> <span class="n">cfg_path</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="nb">setattr</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="s1">&#39;__path__&#39;</span><span class="p">,</span> <span class="n">cfg_path</span><span class="p">)</span>
<span class="k">return</span> <span class="n">value</span>

<span class="k">return</span> <span class="n">value</span><span class="p">,</span> <span class="n">cfg_path</span>


<span class="k">def</span> <span class="nf">_get_key_value</span><span class="p">(</span><span class="n">cfg</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">parent</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Gets the value for a given key in a config object (dict or argparse.Namespace).&quot;&quot;&quot;</span>
<span class="k">def</span> <span class="nf">key_in_cfg</span><span class="p">(</span><span class="n">cfg</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
@@ -460,7 +491,7 @@ <h1>Source code for jsonargparse.util</h1><div class="highlight"><pre>
<span class="k">try</span><span class="p">:</span>
<span class="n">requests</span><span class="o">.</span><span class="n">head</span><span class="p">(</span><span class="n">abs_path</span><span class="p">)</span><span class="o">.</span><span class="n">raise_for_status</span><span class="p">()</span>
<span class="k">except</span> <span class="n">requests</span><span class="o">.</span><span class="n">HTTPError</span> <span class="k">as</span> <span class="n">ex</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="n">abs_path</span><span class="o">+</span><span class="s1">&#39; HEAD not accessible :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span>
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="n">abs_path</span><span class="o">+</span><span class="s1">&#39; HEAD not accessible :: &#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">ex</span><span class="p">))</span> <span class="kn">from</span> <span class="nn">ex</span>
<span class="k">elif</span> <span class="ow">not</span> <span class="n">skip_check</span><span class="p">:</span>
<span class="n">ptype</span> <span class="o">=</span> <span class="s1">&#39;Directory&#39;</span> <span class="k">if</span> <span class="s1">&#39;d&#39;</span> <span class="ow">in</span> <span class="n">mode</span> <span class="k">else</span> <span class="s1">&#39;File&#39;</span>
<span class="k">if</span> <span class="s1">&#39;c&#39;</span> <span class="ow">in</span> <span class="n">mode</span><span class="p">:</span>
32 changes: 25 additions & 7 deletions docs/_sources/CHANGELOG.rst.txt
Original file line number Diff line number Diff line change
@@ -9,12 +9,36 @@ follow `Semantic Versioning <https://semver.org/>`_
only be introduced in major versions with advance notice in the **Deprecated**
section of releases.

v3.1.0 (2020-12-09)
v3.2.1 (2020-12-30)
-------------------

Added
^^^^^
- Automatic Optional for arguments with default None #30.
- CLI now supports running methods from classes.
- Signature arguments can now be loaded from independent config files #32.
- add_argument now supports enable_path for type based on jsonschema.
- print_config can now be given as value skip_null to exclude null entries.

Changed
^^^^^^^
- Improved description of parser used as standalone and for ActionParser #34.
- Removed :code:`__cwd__` and top level :code:`__path__` that were not needed.

Fixed
^^^^^
- ActionYesNo argument in help the type is now bool.
- Correctly skip self in add_method_arguments for inherited methods.
- Prevent failure of dump in cleanup_actions due to new _ActionConfigLoad.
- Prevent failure in save_paths for dict with int keys.
- Avoid duplicate config check failure message with subcommands.


v3.1.0 (2020-12-09)
-------------------

Added
^^^^^
- Support for multiple levels of subcommands #29.
- Default description of subcommands explaining use of --help.

@@ -24,7 +48,6 @@ v3.0.1 (2020-12-02)

Fixed
^^^^^

- add_class_arguments incorrectly added arguments from :code:`__call__` instead
of :code:`__init__` for callable classes.

@@ -34,7 +57,6 @@ v3.0.0 (2020-12-01)

Added
^^^^^

- Functions to add arguments from classes, methods and functions.
- CLI function that allows creating a line command line interface with a single
line of code inspired by Fire.
@@ -44,20 +66,16 @@ Added
- Parsers now include --print_config option to dump defaults.
- Support argcomplete for tab completion of arguments.


Changed
^^^^^^^

- ArgumentParsers by default now use as error_handler the
usage_and_exit_error_handler.
- error_handler and formatter_class no longer accept as value a string.
- Changed SimpleNamespace to Namespace to avoid unnecessary differences with
argparse.


Deprecated
^^^^^^^^^^

- ActionOperators should no longer be used, the new alternative is
restricted number types.

2 changes: 1 addition & 1 deletion docs/_static/documentation_options.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
var DOCUMENTATION_OPTIONS = {
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
VERSION: '3.1.0',
VERSION: '3.2.1',
LANGUAGE: 'None',
COLLAPSE_INDEX: false,
BUILDER: 'html',
4 changes: 2 additions & 2 deletions docs/genindex.html
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Index &mdash; jsonargparse 3.1.0 documentation</title>
<title>Index &mdash; jsonargparse 3.2.1 documentation</title>



@@ -59,7 +59,7 @@


<div class="version">
3.1.0
3.2.1
</div>


127 changes: 99 additions & 28 deletions docs/index.html

Large diffs are not rendered by default.

Binary file modified docs/objects.inv
Binary file not shown.
4 changes: 2 additions & 2 deletions docs/py-modindex.html
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Python Module Index &mdash; jsonargparse 3.1.0 documentation</title>
<title>Python Module Index &mdash; jsonargparse 3.2.1 documentation</title>



@@ -62,7 +62,7 @@


<div class="version">
3.1.0
3.2.1
</div>


4 changes: 2 additions & 2 deletions docs/search.html
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Search &mdash; jsonargparse 3.1.0 documentation</title>
<title>Search &mdash; jsonargparse 3.2.1 documentation</title>



@@ -61,7 +61,7 @@


<div class="version">
3.1.0
3.2.1
</div>


2 changes: 1 addition & 1 deletion docs/searchindex.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion jsonargparse/__init__.py
Original file line number Diff line number Diff line change
@@ -20,4 +20,4 @@
)


__version__ = '3.1.0'
__version__ = '3.2.1'
53 changes: 38 additions & 15 deletions jsonargparse/actions.py
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
namespace_to_dict,
dict_to_namespace,
Path,
_load_config,
_flat_namespace_to_dict,
_dict_to_flat_namespace,
_check_unknown_kwargs,
@@ -103,32 +104,54 @@ def _apply_config(parser, namespace, dest, value):
cfg_path = None
cfg_file = parser.parse_string(value, env=False, defaults=False, _skip_check=True)
except (TypeError, yamlParserError, yamlScannerError) as ex_str:
raise TypeError('Parser key "'+dest+'": '+str(ex_str))
raise TypeError('Parser key "'+dest+'": '+str(ex_str)) from ex_str
else:
cfg_file = parser.parse_path(value, env=False, defaults=False, _skip_check=True)
cfg_file = _dict_to_flat_namespace(namespace_to_dict(cfg_file))
getattr(namespace, dest).append(cfg_path)
for key, val in vars(cfg_file).items():
if key == '__cwd__' and hasattr(namespace, '__cwd__'):
setattr(namespace, key, getattr(namespace, key)+val)
else:
setattr(namespace, key, val)
setattr(namespace, key, val)


class _ActionPrintConfig(Action):
def __init__(self,
option_strings,
dest=SUPPRESS,
default=SUPPRESS,
help='print configuration and exit'):
default=SUPPRESS):
super().__init__(option_strings=option_strings,
dest=dest,
default=default,
nargs=0,
help=help)
nargs='?',
metavar='skip_null',
help='Print configuration and exit.')

def __call__(self, parser, namespace, value, option_string=None):
kwargs = {'skip_none': False}
if value is not None and 'skip_null' in value:
kwargs['skip_none'] = True
parser._print_config = kwargs


class _ActionConfigLoad(Action):

def __init__(self, **kwargs):
kwargs['help'] = SUPPRESS
kwargs['default'] = SUPPRESS
super().__init__(**kwargs)

def __call__(self, parser, namespace, value, option_string=None):
cfg_file = self._load_config(value)
for key, val in vars(cfg_file).items():
setattr(namespace, self.dest+'.'+key, val)

def __call__(self, parser, *args, **kwargs):
parser._print_config = True
def _load_config(self, value):
try:
return _load_config(value)
except (TypeError, yamlParserError, yamlScannerError) as ex:
raise TypeError('Parser key "'+self.dest+'": '+str(ex)) from ex

def _check_type(self, value, cfg=None):
return self._load_config(value)


class ActionYesNo(Action):
@@ -341,7 +364,7 @@ def _check_type(self, value, cfg=None):
if fpath is not None:
value.__path__ = fpath
except KeyError as ex:
raise type(ex)(re.sub('^Parser key ([^:]+):', 'Parser key '+self.dest+'.\\1: ', str(ex)))
raise type(ex)(re.sub('^Parser key ([^:]+):', 'Parser key '+self.dest+'.\\1: ', str(ex))) from ex
return value

@staticmethod
@@ -535,7 +558,7 @@ def _check_type(self, value, cfg=None, islist=None):
val = Path(val, mode=self._mode, skip_check=self._skip_check)
value[num] = val
except TypeError as ex:
raise TypeError('Parser key "'+self.dest+'": '+str(ex))
raise TypeError('Parser key "'+self.dest+'": '+str(ex)) from ex
return value if islist else value[0]


@@ -598,7 +621,7 @@ def _check_type(self, value, cfg=None):
with sys.stdin if path_list_file == '-' else open(path_list_file, 'r') as f:
path_list = [x.strip() for x in f.readlines()]
except FileNotFoundError as ex:
raise TypeError('Problems reading path list: '+path_list_file+' :: '+str(ex))
raise TypeError('Problems reading path list: '+path_list_file+' :: '+str(ex)) from ex
cwd = os.getcwd()
if self._rel == 'list' and path_list_file != '-':
os.chdir(os.path.abspath(os.path.join(path_list_file, os.pardir)))
@@ -607,7 +630,7 @@ def _check_type(self, value, cfg=None):
try:
path_list[num] = Path(val, mode=self._mode)
except TypeError as ex:
raise TypeError('Path number '+str(num+1)+' in list '+path_list_file+', '+str(ex))
raise TypeError('Path number '+str(num+1)+' in list '+path_list_file+', '+str(ex)) from ex
finally:
os.chdir(cwd)
value += path_list
76 changes: 51 additions & 25 deletions jsonargparse/cli.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Simple creation of command line interfaces."""

import inspect
from typing import Union, List, Callable
from typing import Union, List, Callable, Type
from .core import ArgumentParser
from .actions import ActionConfigFile

@@ -10,63 +10,89 @@


def CLI(
functions: Union[Callable, List[Callable]] = None,
components: Union[Callable, Type, List[Union[Callable, Type]]] = None,
args: List[str] = None,
config_help: str = 'Path to a configuration file in json or yaml format.',
as_positional: bool = True,
**kwargs
):
"""Function for simple creation of command line interfaces.
Creates an argument parser from one or more functions, parses arguments and
runs one of the functions depending on what was parsed. If the functions
argument is not given, then the functions will be all the locals in the
context and defined in the same module as from where CLI is called.
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 argument is not given, then the components
will be all the locals in the context and defined in the same module as from
where CLI is called.
Args:
functions: One or more functions to include in the command line interface.
components: One or more functions/classes to include in the command line interface.
args: List of arguments to parse or None to use sys.argv.
config_help: Help string for config file option in help.
as_positional: Whether to add required parameters as positional arguments.
**kwargs: Used to instantiate :class:`.ArgumentParser`.
Returns:
The value returned by the executed function.
The value returned by the executed function or class method.
"""
caller = inspect.stack()[1][0]
if 'description' not in kwargs:
kwargs['description'] = caller.f_globals['__doc__']

if functions is None:
if components is None:
module = inspect.getmodule(caller).__name__ # type: ignore
functions = [
components = [
v for v in caller.f_locals.values()
if inspect.isfunction(v) and inspect.getmodule(v).__name__ == module # type: ignore
if (inspect.isfunction(v) or inspect.isclass(v)) and inspect.getmodule(v).__name__ == module # type: ignore
]
if len(functions) == 0:
raise ValueError('Either functions argument must be given or there must be at least one '
'function among the locals in the context where CLI is called.')
if len(components) == 0:
raise ValueError('Either components argument must be given or there must be at least one '
'function or class among the locals in the context where CLI is called.')

elif not isinstance(functions, list):
functions = [functions]
elif not isinstance(components, list):
components = [components]

parser = ArgumentParser(parse_as_dict=True, default_meta=False, **kwargs)
parser.add_argument('--config', action=ActionConfigFile, help=config_help)

if len(functions) == 1:
parser.add_function_arguments(functions[0], as_positional=as_positional)
if len(components) == 1:
component = components[0]
_add_component_to_parser(component, parser, as_positional)
cfg = parser.parse_args(args)
del cfg['config'] # pylint: disable=unsupported-delete-operation
return functions[0](**cfg) # type: ignore # pylint: disable=not-a-mapping
return _run_component(component, cfg)

else:
subcommands = parser.add_subcommands(required=True)
func_dict = {c.__name__: c for c in functions}
for name, function in func_dict.items():
comp_dict = {c.__name__: c for c in components}
for name, component in comp_dict.items():
subparser = ArgumentParser()
subparser.add_function_arguments(function, as_positional=as_positional)
subcommands.add_subcommand(name, subparser) # type: ignore
_add_component_to_parser(component, subparser, as_positional)

cfg = parser.parse_args(args)
function = func_dict[cfg['subcommand']] # type: ignore # pylint: disable=unsubscriptable-object
return function(**cfg[cfg['subcommand']]) # type: ignore # pylint: disable=unsubscriptable-object
subcommand = cfg.pop('subcommand')
component = comp_dict[subcommand]
return _run_component(component, cfg.get(subcommand))


def _add_component_to_parser(component, parser, as_positional):
if inspect.isfunction(component):
parser.add_function_arguments(component, as_positional=as_positional)
else:
parser.add_class_arguments(component, as_positional=as_positional)
subcommands = parser.add_subcommands(required=True)
for key in [k for k, v in inspect.getmembers(component) if callable(v) and k[0] != '_']:
subparser = ArgumentParser()
subparser.add_method_arguments(component, key, as_positional=as_positional)
subcommands.add_subcommand(key, subparser)


def _run_component(component, cfg):
if 'config' in cfg:
del cfg['config']
if inspect.isfunction(component):
return component(**cfg)
else:
subcommand = cfg.pop('subcommand')
subcommand_cfg = cfg.pop(subcommand)
component_obj = component(**cfg)
return getattr(component_obj, subcommand)(**subcommand_cfg)
51 changes: 24 additions & 27 deletions jsonargparse/core.py
Original file line number Diff line number Diff line change
@@ -35,6 +35,7 @@
ActionPath,
_ActionSubCommands,
_ActionPrintConfig,
_ActionConfigLoad,
_find_action,
_is_action_value_list,
)
@@ -69,39 +70,42 @@ def __init__(self, *args, **kwargs):
self.register('action', 'parsers', _ActionSubCommands)


def add_argument(self, *args, **kwargs):
def add_argument(self, *args, enable_path:bool=False, **kwargs):
"""Adds an argument to the parser or argument group.
All the arguments from `argparse.ArgumentParser.add_argument
<https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser.add_argument>`_
are supported.
are supported. Additionally it accepts:
Args:
enable_path: Whether to try parsing path/subconfig when argument is a complex type.
"""
if 'type' in kwargs:
if type_in(kwargs['type'], supported_types) or \
(inspect.isclass(kwargs['type']) and not _issubclass(kwargs['type'], (str, int, float, Enum, Path))):
kwargs['action'] = ActionJsonSchema(annotation=kwargs.pop('type'), enable_path=False)
kwargs['action'] = ActionJsonSchema(annotation=kwargs.pop('type'), enable_path=enable_path)
elif _issubclass(kwargs['type'], Enum):
kwargs['action'] = ActionEnum(enum=kwargs['type'])
action = super().add_argument(*args, **kwargs)
if not hasattr(action, 'completer') and action.type is not None:
completer_method = FilesCompleterMethod if isinstance(action.type, Path) else TypeCastCompleterMethod
action_class = action.__class__
action.__class__ = action_class.__class__(
action.__class__ = action_class.__class__( # type: ignore
action_class.__name__ + 'WithCompleter',
(action_class, completer_method),
{}
)
for key in meta_keys:
if key in action.dest:
raise ValueError('Argument with destination name "'+key+'" not allowed.')
parser = self.parser if hasattr(self, 'parser') else self
parser = self.parser if hasattr(self, 'parser') else self # type: ignore
if action.help is None and \
hasattr(self, 'formatter_class') and \
issubclass(self.formatter_class, DefaultHelpFormatter):
issubclass(self.formatter_class, DefaultHelpFormatter): # type: ignore
action.help = ' '
if action.required:
parser.required_args.add(action.dest)
action._required = True
action._required = True # type: ignore
action.required = False
if isinstance(action, ActionParser):
if action._parser == self:
@@ -275,20 +279,13 @@ def _parse_common(

cfg_ns = dict_to_namespace(cfg)

if hasattr(self, '_print_config') and self._print_config: # type: ignore
sys.stdout.write(self.dump(cfg_ns, skip_none=False, skip_check=True))
if hasattr(self, '_print_config'):
sys.stdout.write(self.dump(cfg_ns, skip_check=True, **self._print_config)) # type: ignore
self.exit()

if not skip_check:
self.check_config(cfg_ns)

if with_meta or (with_meta is None and self._default_meta):
if hasattr(cfg_ns, '__cwd__'):
if os.getcwd() not in cfg_ns.__cwd__:
cfg_ns.__cwd__.insert(0, os.getcwd())
else:
cfg_ns.__cwd__ = [os.getcwd()]

if log_message is not None:
self._logger.info(log_message)

@@ -303,6 +300,7 @@ def parse_args( # type: ignore[override]
defaults: bool = True,
nested: bool = True,
with_meta: bool = None,
_skip_check: bool = False,
) -> Union[Namespace, Dict[str, Any]]:
"""Parses command line argument strings.
@@ -339,7 +337,7 @@ def parse_args( # type: ignore[override]
defaults=defaults,
nested=nested,
with_meta=with_meta,
skip_check=False,
skip_check=_skip_check,
cfg_base=namespace,
log_message='Parsed command line arguments.',
)
@@ -517,11 +515,6 @@ def parse_path(
cfg_str = fpath.get_content()
parsed_cfg = self.parse_string(cfg_str, cfg_path, ext_vars, env, defaults, nested, with_meta=with_meta,
_skip_logging=True, _skip_check=_skip_check, _base=_base)
if with_meta or (with_meta is None and self._default_meta):
if self._parse_as_dict:
parsed_cfg['__path__'] = fpath
else:
parsed_cfg.__path__ = fpath # type: ignore
finally:
if not fpath.is_url:
os.chdir(cwd)
@@ -605,7 +598,7 @@ def _load_cfg(
try:
cfg = yaml.safe_load(cfg_str)
except (yamlParserError, yamlScannerError) as ex:
raise TypeError('Problems parsing config :: '+str(ex))
raise TypeError('Problems parsing config :: '+str(ex)) from ex
cfg = namespace_to_dict(_dict_to_flat_namespace(cfg))
if base is not None:
cfg = {base+'.'+k: v for k, v in cfg.items()}
@@ -704,7 +697,7 @@ def dump(

def cleanup_actions(cfg, actions):
for action in actions:
if action.help == SUPPRESS or \
if (action.help == SUPPRESS and not isinstance(action, _ActionConfigLoad)) or \
isinstance(action, ActionConfigFile) or \
(skip_none and action.dest in cfg and cfg[action.dest] is None):
del cfg[action.dest]
@@ -802,8 +795,8 @@ def save(
def save_paths(cfg, base=None):
replace_keys = {}
for key, val in cfg.items():
kbase = key if base is None else base+'.'+key
if isinstance(val, dict):
kbase = str(key) if base is None else base+'.'+str(key)
if '__path__' in val:
val_path = Path(os.path.join(dirname, os.path.basename(val['__path__']())), mode='fc')
if not overwrite and os.path.isfile(val_path()):
@@ -982,7 +975,11 @@ def check_values(cfg, base=None):
check_required(cfg)
check_values(cfg)
except (TypeError, KeyError) as ex:
raise type(ex)('Config checking failed :: '+str(ex))
prefix = 'Configuration check failed :: '
message = str(ex)
if prefix not in message:
message = prefix+message
raise type(ex)(message) from ex


def instantiate_subclasses(self, cfg:Union[Namespace, Dict[str, Any]]) -> Union[Namespace, Dict[str, Any]]:
@@ -1132,7 +1129,7 @@ def _check_value_key(action:Action, value:Any, key:str, cfg) -> Any:
for k, v in enumerate(value):
value[k] = action.type(v)
except (TypeError, ValueError) as ex:
raise TypeError('Parser key "'+str(key)+'": '+str(ex))
raise TypeError('Parser key "'+str(key)+'": '+str(ex)) from ex
return value


6 changes: 4 additions & 2 deletions jsonargparse/formatters.py
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@

from .util import _get_env_var
from .typing import type_to_str
from .actions import ActionParser, ActionEnum, ActionConfigFile
from .actions import ActionParser, ActionEnum, ActionYesNo, ActionConfigFile
from .jsonschema import ActionJsonSchema


@@ -78,7 +78,9 @@ def _expand_help(self, action):

def _get_type_str(self, action):
type_str = None
if action.type is not None:
if isinstance(action, ActionYesNo):
type_str = 'bool'
elif action.type is not None:
type_str = type_to_str(action.type)
elif isinstance(action, ActionEnum):
type_str = type_to_str(action._enum)
6 changes: 3 additions & 3 deletions jsonargparse/jsonnet.py
Original file line number Diff line number Diff line change
@@ -72,7 +72,7 @@ def __init__(self, **kwargs):
try:
schema = yaml.safe_load(schema)
except (yamlParserError, yamlScannerError) as ex:
raise ValueError('Problems parsing schema :: '+str(ex))
raise ValueError('Problems parsing schema :: '+str(ex)) from ex
jsonvalidator.check_schema(schema)
self._validator = ActionJsonSchema._extend_jsonvalidator_with_default(jsonvalidator)(schema)
else:
@@ -119,7 +119,7 @@ def _check_type(self, value, cfg):
value[num] = val
except (TypeError, RuntimeError, yamlParserError, yamlScannerError, jsonschemaValidationError) as ex:
elem = '' if not islist else ' element '+str(num+1)
raise TypeError('Parser key "'+self.dest+'"'+elem+': '+str(ex))
raise TypeError('Parser key "'+self.dest+'"'+elem+': '+str(ex)) from ex
return value if islist else value[0]


@@ -175,7 +175,7 @@ def parse(
try:
values = yaml.safe_load(_jsonnet.evaluate_snippet(fname, snippet, ext_vars=ext_vars, ext_codes=ext_codes))
except RuntimeError as ex:
raise ParserError('Problems evaluating jsonnet "'+fname+'" :: '+str(ex))
raise ParserError('Problems evaluating jsonnet "'+fname+'" :: '+str(ex)) from ex
if self._validator is not None:
self._validator.validate(values)
if with_meta and isinstance(values, dict) and fpath is not None:
21 changes: 5 additions & 16 deletions jsonargparse/jsonschema.py
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@
ParserError,
strip_meta,
import_object,
_load_config,
_check_unknown_kwargs,
_issubclass,
)
@@ -26,7 +27,6 @@
jsonschemaValidationError,
jsonschema_support,
import_jsonschema,
get_config_read_mode,
files_completer,
argcomplete_warn_redraw_prompt,
)
@@ -90,7 +90,7 @@ def __init__(self, **kwargs):
try:
schema = yaml.safe_load(schema)
except (yamlParserError, yamlScannerError) as ex:
raise ValueError('Problems parsing schema :: '+str(ex))
raise ValueError('Problems parsing schema :: '+str(ex)) from ex
jsonvalidator.check_schema(schema)
self._validator = self._extend_jsonvalidator_with_default(jsonvalidator)(schema)
self._enable_path = kwargs.get('enable_path', True)
@@ -136,18 +136,7 @@ def _check_type(self, value, cfg=None):
value = [value]
for num, val in enumerate(value):
try:
fpath = None
if isinstance(val, str) and val.strip() != '':
parsed_val = yaml.safe_load(val)
if not isinstance(parsed_val, str):
val = parsed_val
if self._enable_path and isinstance(val, str):
try:
fpath = Path(val, mode=get_config_read_mode())
except TypeError:
pass
else:
val = yaml.safe_load(fpath.get_content())
val, fpath = _load_config(val, enable_path=self._enable_path, flat_namespace=False)
if isinstance(val, Namespace):
val = namespace_to_dict(val)
val = self._adapt_types(val, self._annotation, self._subschemas, reverse=True)
@@ -161,7 +150,7 @@ def _check_type(self, value, cfg=None):
value[num] = val
except (TypeError, yamlParserError, yamlScannerError, jsonschemaValidationError) as ex:
elem = '' if not islist else ' element '+str(num+1)
raise TypeError('Parser key "'+self.dest+'"'+elem+': '+str(ex))
raise TypeError('Parser key "'+self.dest+'"'+elem+': '+str(ex)) from ex
return value if islist else value[0]


@@ -236,7 +225,7 @@ def validate_adapt(v, subschema):
init_args = parser.instantiate_subclasses(val['init_args'])
val = val_class(**init_args) # pylint: disable=not-a-mapping
except (ImportError, ModuleNotFound, AttributeError, AssertionError, ParserError) as ex:
raise ParserError('Problem with given class_path "'+val['class_path']+'" :: '+str(ex))
raise ParserError('Problem with given class_path "'+val['class_path']+'" :: '+str(ex)) from ex
return val

elif annotation.__origin__ == Union:
14 changes: 7 additions & 7 deletions jsonargparse/optionals.py
Original file line number Diff line number Diff line change
@@ -49,55 +49,55 @@ def import_jsonschema(importer):
from jsonschema import Draft7Validator as jsonvalidator
return jsonschema, jsonvalidator
except (ImportError, ModuleNotFound) as ex:
raise ImportError('jsonschema package is required by '+importer+' :: '+str(ex))
raise ImportError('jsonschema package is required by '+importer+' :: '+str(ex)) from ex


def import_jsonnet(importer):
try:
import _jsonnet
return _jsonnet
except (ImportError, ModuleNotFound) as ex:
raise ImportError('jsonnet package is required by '+importer+' :: '+str(ex))
raise ImportError('jsonnet package is required by '+importer+' :: '+str(ex)) from ex


def import_url_validator(importer):
try:
from validators.url import url as url_validator
return url_validator
except (ImportError, ModuleNotFound) as ex:
raise ImportError('validators package is required by '+importer+' :: '+str(ex))
raise ImportError('validators package is required by '+importer+' :: '+str(ex)) from ex


def import_requests(importer):
try:
import requests
return requests
except (ImportError, ModuleNotFound) as ex:
raise ImportError('requests package is required by '+importer+' :: '+str(ex))
raise ImportError('requests package is required by '+importer+' :: '+str(ex)) from ex


def import_docstring_parse(importer):
try:
from docstring_parser import parse as docstring_parse
return docstring_parse
except (ImportError, ModuleNotFound) as ex:
raise ImportError('docstring-parser package is required by '+importer+' :: '+str(ex))
raise ImportError('docstring-parser package is required by '+importer+' :: '+str(ex)) from ex


def import_argcomplete(importer):
try:
import argcomplete
return argcomplete
except (ImportError, ModuleNotFound) as ex:
raise ImportError('argcomplete package is required by '+importer+' :: '+str(ex))
raise ImportError('argcomplete package is required by '+importer+' :: '+str(ex)) from ex


def import_dataclasses(importer):
try:
import dataclasses
return dataclasses
except (ImportError, ModuleNotFound) as ex:
raise ImportError('dataclasses package is required by '+importer+' :: '+str(ex))
raise ImportError('dataclasses package is required by '+importer+' :: '+str(ex)) from ex


def set_url_support(enabled:bool):
11 changes: 8 additions & 3 deletions jsonargparse/signatures.py
Original file line number Diff line number Diff line change
@@ -5,7 +5,8 @@
from typing import Union, Optional, List, Container, Type, Callable

from .util import _issubclass
from .actions import ActionEnum
from .actions import ActionEnum, _ActionConfigLoad
from .typing import is_optional
from .jsonschema import ActionJsonSchema
from .optionals import docstring_parser_support, import_docstring_parse, dataclasses_support, import_dataclasses

@@ -92,9 +93,9 @@ def add_method_arguments(
if not inspect.isclass(theclass):
raise ValueError('Expected a class object.')
if not hasattr(theclass, themethod) or not callable(getattr(theclass, themethod)):
raise ValueError('Expected the method to a callable member of the class.')
raise ValueError('Expected the method to be a callable member of the class.')

skip_first = False if isinstance(theclass.__dict__[themethod], staticmethod) else True
skip_first = not isinstance(inspect.getattr_static(theclass, themethod), staticmethod)
themethod = getattr(theclass, themethod)

return self._add_signature_arguments([themethod],
@@ -213,6 +214,8 @@ def update_has_args_kwargs(base, has_args=True, has_kwargs=True):
doc_group = str(objects[0])
name = objects[0].__name__ if nested_key is None else nested_key
group = self.add_argument_group(doc_group, name=name) # type: ignore
if nested_key is not None:
group.add_argument('--'+nested_key, action=_ActionConfigLoad) # type: ignore

## Add objects arguments ##
added_args = set()
@@ -247,6 +250,8 @@ def update_has_args_kwargs(base, has_args=True, has_kwargs=True):
kwargs = {'help': doc_params.get(name)}
if not is_required:
kwargs['default'] = default
if default is None and not is_optional(annotation, object):
annotation = Optional[annotation]
elif not as_positional:
kwargs['required'] = True
if annotation in {str, int, float, bool} or \
37 changes: 34 additions & 3 deletions jsonargparse/util.py
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
import re
import sys
import stat
import yaml
import inspect
import logging
from copy import deepcopy
@@ -13,7 +14,13 @@
from yaml.parser import ParserError as yamlParserError
from yaml.scanner import ScannerError as yamlScannerError

from .optionals import ModuleNotFound, url_support, import_requests, import_url_validator
from .optionals import (
ModuleNotFound,
url_support,
import_requests,
import_url_validator,
get_config_read_mode,
)


__all__ = [
@@ -32,14 +39,38 @@
null_logger = logging.Logger('jsonargparse_null_logger')
null_logger.addHandler(logging.NullHandler())

meta_keys = {'__cwd__', '__path__', '__default_config__'}
meta_keys = {'__path__', '__default_config__'}


class ParserError(Exception):
"""Error raised when parsing a value fails."""
pass


def _load_config(value, enable_path=True, flat_namespace=True):
"""Parses yaml config in a string or a path"""
cfg_path = None
if isinstance(value, str) and value.strip() != '':
parsed_val = yaml.safe_load(value)
if not isinstance(parsed_val, str):
value = parsed_val
if enable_path and isinstance(value, str):
try:
cfg_path = Path(value, mode=get_config_read_mode())
except TypeError:
pass
else:
value = yaml.safe_load(cfg_path.get_content())

if flat_namespace:
value = _dict_to_flat_namespace(value)
if cfg_path is not None:
setattr(value, '__path__', cfg_path)
return value

return value, cfg_path


def _get_key_value(cfg, key, parent=False):
"""Gets the value for a given key in a config object (dict or argparse.Namespace)."""
def key_in_cfg(cfg, key):
@@ -310,7 +341,7 @@ def __init__(
try:
requests.head(abs_path).raise_for_status()
except requests.HTTPError as ex:
raise TypeError(abs_path+' HEAD not accessible :: '+str(ex))
raise TypeError(abs_path+' HEAD not accessible :: '+str(ex)) from ex
elif not skip_check:
ptype = 'Directory' if 'd' in mode else 'File'
if 'c' in mode:
42 changes: 40 additions & 2 deletions jsonargparse_tests/cli_tests.py
Original file line number Diff line number Diff line change
@@ -24,6 +24,34 @@ def cmd2(a2: str = 'X'):
self.assertEqual('Y', CLI(functions, args=['cmd2', '--a2=Y']))


def test_single_class_cli(self):
class Class1:
def __init__(self, i1: str):
self.i1 = i1
def method1(self, m1: int):
return self.i1, m1

self.assertEqual(('0', 2), CLI(Class1, args=['0', 'method1', '2']))


def test_function_and_class_cli(self):
def cmd1(a1: int):
return a1

class Cmd2:
def __init__(self, i1: str = 'd'):
self.i1 = i1
def method1(self, m1: float):
return self.i1, m1
def method2(self, m1: int = 0):
return self.i1, m1

components = [cmd1, Cmd2]
self.assertEqual(5, CLI(components, args=['cmd1', '5']))
self.assertEqual(('d', 1.2), CLI(components, args=['Cmd2', 'method1', '1.2']))
self.assertEqual(('b', 3), CLI(components, args=['Cmd2', '--i1=b', 'method2', '--m1=3']))


def test_empty_context(self):
def empty_context():
CLI()
@@ -32,13 +60,23 @@ def empty_context():


def test_non_empty_context(self):
def non_empty_context():
def non_empty_context_1():
def function(a1: float):
return a1

return CLI(args=['6.7'])

self.assertEqual(6.7, non_empty_context())
def non_empty_context_2():
class Class1:
def __init__(self, i1: str):
self.i1 = i1
def method1(self, m1: int):
return self.i1, m1

return CLI(args=['a', 'method1', '2'])

self.assertEqual(6.7, non_empty_context_1())
self.assertEqual(('a', 2), non_empty_context_2())


if __name__ == '__main__':
14 changes: 7 additions & 7 deletions jsonargparse_tests/core_tests.py
Original file line number Diff line number Diff line change
@@ -94,8 +94,6 @@ def test_parse_path(self):
self.assertEqual(cfg2, parser.parse_path(yaml_file, defaults=False))
self.assertNotEqual(cfg2, parser.parse_path(yaml_file, defaults=True))
self.assertNotEqual(cfg1, parser.parse_path(yaml_file, defaults=False))
self.assertTrue(hasattr(parser.parse_path(yaml_file, with_meta=True), '__cwd__'))
self.assertFalse(hasattr(parser.parse_path(yaml_file), '__cwd__'))

with open(yaml_file, 'w') as output_file:
output_file.write(example_yaml+' val2: eight\n')
@@ -191,7 +189,6 @@ def test_parse_as_dict(self):
with open('config.json', 'w') as f:
f.write('{}')
parser = ArgumentParser(parse_as_dict=True, default_meta=True)
self.assertEqual({'__path__', '__cwd__'}, set(parser.parse_path('config.json').keys()))


class ArgumentFeaturesTests(unittest.TestCase):
@@ -576,7 +573,6 @@ def test_save(self):

cfg2 = parser.parse_path(main_file, with_meta=True)
self.assertEqual(namespace_to_dict(cfg1), strip_meta(cfg2))
self.assertEqual(cfg2.__path__(), main_file)
self.assertEqual(cfg2.parser.__path__(absolute=False), 'parser.yaml')
if jsonschema_support:
self.assertEqual(cfg2.schema.__path__(absolute=False), 'schema.yaml')
@@ -631,6 +627,13 @@ def test_print_config(self):
outval = yaml.safe_load(out.getvalue())
self.assertEqual(outval, {'g1': {'v2': '2'}, 'g2': {'v3': None}, 'v1': 1})

out = StringIO()
with redirect_stdout(out), self.assertRaises(SystemExit):
parser.parse_args(['--print_config=skip_null'])

outval = yaml.safe_load(out.getvalue())
self.assertEqual(outval, {'g1': {'v2': '2'}, 'v1': 1})


class ConfigFilesTests(TempDirTestCase):

@@ -683,9 +686,6 @@ def test_ActionConfigFile_and_ActionPath(self):
self.assertEqual(abs_yaml_file, os.path.realpath(cfg.file(absolute=True)))
self.assertRaises(ParserError, lambda: parser.parse_args(['--cfg', abs_yaml_file+'~']))

cfg = parser.parse_args(['--cfg', abs_yaml_file, '--cfg', abs_yaml_file])
self.assertEqual(3, len(cfg.__cwd__))

cfg = parser.parse_args(['--cfg', 'file: '+abs_yaml_file+'\ndir: '+self.tmpdir+'\n'])
self.assertEqual(self.tmpdir, os.path.realpath(cfg.dir(absolute=True)))
self.assertEqual(None, cfg.cfg[0])
5 changes: 5 additions & 0 deletions jsonargparse_tests/formatters_tests.py
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@ def test_default_help_formatter(self):
parser2 = ArgumentParser()
parser2.add_argument('--v4')
parser.add_argument('--g2', action=ActionParser(parser=parser2))
parser.add_argument('--v5', action=ActionYesNo, default=True, help='Option v5.')

os.environ['COLUMNS'] = '150'
out = StringIO()
@@ -50,6 +51,10 @@ def test_default_help_formatter(self):
self.assertIn('APP_G2', outval)
self.assertIn('--g2.help', outval)

self.assertIn('--v5, --no_v5', outval)
self.assertIn('APP_V5', outval)
self.assertIn('Option v5. (type: bool, default: True)', outval)


if __name__ == '__main__':
unittest.main(verbosity=2)
63 changes: 63 additions & 0 deletions jsonargparse_tests/signatures_tests.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python3

import yaml
from enum import Enum
from io import StringIO
from typing import Dict, List, Tuple, Optional, Union, Any
@@ -386,6 +387,17 @@ def __init__(self, c1: Optional[Class1]):
self.assertEqual(2.3, cfg.c1.a2)


def test_implicit_optional(self):

def func(a1: int = None):
return a1

parser = ArgumentParser(error_handler=None)
parser.add_function_arguments(func)

self.assertIsNone(parser.parse_args(['--a1=null']).a1)


@unittest.skipIf(not docstring_parser_support, 'docstring-parser package is required')
def test_docstring_parse_fail(self):

@@ -409,5 +421,56 @@ def __init__(self, a1: int = 1):
self.assertNotIn('a1 description', help_str.getvalue())


@unittest.skipIf(not jsonschema_support, 'jsonschema package is required')
class SignaturesConfigTests(TempDirTestCase):

def test_add_function_arguments_config(self):

def func(a1 = '1',
a2: float = 2.0,
a3: bool = False):
return a1

parser = ArgumentParser(error_handler=None, default_meta=False)
parser.add_function_arguments(func, 'func')

cfg_path = 'config.yaml'
with open(cfg_path, 'w') as f:
f.write(yaml.dump({'a1': 'one', 'a3': True}))

cfg = parser.parse_args(['--func', cfg_path])
self.assertEqual(cfg.func, Namespace(a1='one', a2=2.0, a3=True))

cfg = parser.parse_args(['--func={"a1": "ONE"}'])
self.assertEqual(cfg.func, Namespace(a1='ONE', a2=2.0, a3=False))

self.assertRaises(ParserError, lambda: parser.parse_args(['--func="""']))


def test_config_within_config(self):

def func(a1 = '1',
a2: float = 2.0,
a3: bool = False):
return a1

parser = ArgumentParser(error_handler=None)
parser.add_argument('--cfg', action=ActionConfigFile)
parser.add_function_arguments(func, 'func')

cfg_path = 'subdir/config.yaml'
subcfg_path = 'subsubdir/func_config.yaml'
os.mkdir('subdir')
os.mkdir('subdir/subsubdir')
with open(cfg_path, 'w') as f:
f.write('func: '+subcfg_path+'\n')
with open(os.path.join('subdir', subcfg_path), 'w') as f:
f.write(yaml.dump({'a1': 'one', 'a3': True}))

cfg = parser.parse_args(['--cfg', cfg_path])
self.assertEqual(str(cfg.func.__path__), subcfg_path)
self.assertEqual(strip_meta(cfg.func), {'a1': 'one', 'a2': 2.0, 'a3': True})


if __name__ == '__main__':
unittest.main(verbosity=2)
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -48,7 +48,7 @@ doc =

[metadata]
name = jsonargparse
version = 3.1.0
version = 3.2.1
description = Parsing of command line options, yaml/jsonnet config files and/or environment variables based on argparse.
long_description_content_type = text/x-rst
author = Mauricio Villegas