omni-us / jsonargparse

Implement minimal boilerplate CLIs derived from type hints and parse from command line, config files and environment variables
https://jsonargparse.readthedocs.io
MIT License
319 stars 47 forks source link

`CLI` fails to instantiate a Pydantic object if it has `typing.Optional` annotation #521

Closed rusmux closed 3 months ago

rusmux commented 3 months ago

🐛 Bug report

CLI fails to instantiate a Pydantic object if it has typing.Optional annotation.

To reproduce

In main.py:

import typing as tp

import pydantic
from jsonargparse import CLI

class A(pydantic.BaseModel):
    value: int

class B:

    def __init__(self, a: tp.Optional[A] = None) -> None:
        self.a = a

def main(b: B) -> None:
    print(b)

if __name__ == "__main__":
    CLI(main)

In config.yaml:

b:
  class_path: __main__.B
  init_args:
    a:
      value: 1

In terminal:

python -m main --config config.yaml

Gives error:

error: Validation failed: Parser key "b":
  Problem with given class_path '__main__.B':
    Parser key "a":
      Does not validate against any of the Union subtypes
      Subtypes: (<class '__main__.A'>, <class 'NoneType'>)
      Errors:
        - __pydantic_private__
        - Expected a <class 'NoneType'>
      Given value type: <class 'jsonargparse._namespace.Namespace'>
      Given value: Namespace(value=1)

If I use this signature:

def __init__(self, a: A) -> None:
        self.a = a

Everything works as expected.

Expected behavior

The above code should run without errors.

Environment

mauvilsa commented 3 months ago

Thank you for reporting! I will look at it.