Cannot configure fields of optional dataclasses using env-vars
maticus opened this issue Β· comments
π Bug report
Prompted by the super-quick fix of #507 (thanks!) I'm doing some more testing of jsonargparse with nested optional dataclasses, and found out:
Cannot configure fields of optional dataclasses using env-vars
To reproduce
Following script
import jsonargparse
from typing import Optional
from dataclasses import dataclass
@dataclass
class B:
c: int = 3
@dataclass
class A:
b: B
ob: Optional[B]
def fun(a: A):
print(a)
jsonargparse.CLI(fun, default_env=True, env_prefix="FOO")
when ran:
FOO_A__OB__C=7 FOO_A__B__C=8 python python-jsonargparse-optional-dataclass.py
displays:
A(b=B(c=8), ob=None)
Note, I can still configure this filed using --a.ob.c
:
$ python python-jsonargparse-optional-dataclass.py --a.b.c 77 --a.ob.c 78
A(b=B(c=77), ob=B(c=78))
Expected behavior
FOO_A__OB__C=7
env-var should configure the appropriate field.
Additionally, the FOO_A__OB__C
should be visible in generated help (running script with -h
) - related to #509
Environment
- jsonargparse version: today's master :-) (git-describe: v4.28.0-10-gf44ba32)
- Python version: 3.10
- How jsonargparse was installed:
pip install -e ".[dev,all]"
from checked-out repo. - OS: Ubuntu Jammy
This behavior is expected. Might seem inconsistent but not a bug. Let me explain. When there is b: B
the only possibility is that b
will be an instance of B
. Each of the fields of B
can be added to the parser since they are always supported. In contrast, when ob: Optional[B]
then the fields of B
are not always supported, and thus not added to the parser. Only --a.ob
is available in the parser and its corresponding env var. This can be observed by using --help
. Note that Optional[B]
is equivalent to a union B | None
, and could be a much more complex type, e.g. int | B | X | None
. Allowing all possibilities to be set by environment variables would be rather complex to implement, and there wouldn't even be a way to show the corresponding var names in the help. And would create weird cases, e.g. env vars given for B
field and X
field.
Even though FOO_A__OB__C
is not available, it is possible to set like:
$ FOO_A__OB='{"c": 4}' ./issue_510.py
A(b=B(c=3), ob=B(c=4))