Closed pjgao closed 2 months ago
Thank you for reporting this issue and the detailed reproduction code!
After a look at it, I don't see any bug. The behavior is working as expected. When the type is params:C
there are two ways to provide the nested parameters from command line:
cli.py --print_config --params '{"c": "x"}'
cli.py --print_config --params.c x
When a union is used, like params:Union[A,B,C]
, a given value is attempted to be parsed by each type from left to right. If the given value is A
(shorthand for {"class_path":"__main__.A"}
), then type A
parses successfully and there is no attempt on B
or C
. If the given value is B
, then parsing with A
fails, B
succeeds and C
is not attempted. To provide a value for C
it is the same as if there were no union, i.e. as --params '{"c": "x"}'
or --params.c x
, in which case A
and B
fail to parse, and C
succeeds.
Even though this is not a bug, it could be considered a feature request. This is closely related to #287. I do have in the roadmap to provide a way to choose which classes should work as subclasses and which not. With this, C
would be configured to work as a subclass base, and be required to use class_path
for it or its subclasses. And --params C
would work as you expected.
Thanks for your kindly reply! The main starting point of the problem is that when the dataclass type hint are nested in multiple layers, it is difficult to manually write the configuration file.
from dataclasses import dataclass
from typing import Union
from jsonargparse import CLI
@dataclass
class DataClass1:
a: str
b: int
@dataclass
class DataClass2:
c: DataClass1
d: str
@dataclass
class DataClass3:
e: DataClass2
f: int
when type hint is: DataClass3
def func(x: DataClass3):
pass
CLI(func)
print_config
(base) linux@DESKTOP-SSJTOLO:/mnt/d/projects/push$ python test.py --print_config
x:
e:
c:
a: null
b: null
d: null
f: null
😀Wow! Now I can know which params should have automatically!
when type hint is: Union[str, DataClass3]
def func(x: Union[str, DataClass3]):
pass
CLI(func)
print_config
(base) linux@DESKTOP-SSJTOLO:/mnt/d/projects/push$ python test.py --print_config
x: null
(base) linux@DESKTOP-SSJTOLO:/mnt/d/projects/push$ python test.py -h
usage: test.py [-h] [--config CONFIG] [--print_config[=flags]] x
<function func at 0x7f5d41942160>
positional arguments:
x (required, type: Union[str, DataClass3])
optional arguments:
-h, --help Show this help message and exit.
--config CONFIG Path to a configuration file.
--print_config[=flags]
Print the configuration after applying all other arguments and exit. The optional flags customizes the output and are one or more keywords separated by comma. The supported flags are: comments, skip_default, skip_null.
😪OOps. Must write params one by one manually.
Can dataclass should work as subclasses
solved this confusion?
Can
dataclass should work as subclasses
solved this confusion?
Yes, this would solve it.
Closing this in favor of #287.
🐛 Bug report
To reproduce
I have these classes,both
A
andB
are inherited fromBase
,C
is inherited frompydantic.BaseModel
(dataclass-like class):when type hint is
params:Base
we get:
print_config
gives config example rightly when we feed—params
right class (A
/B
/Base
)when type hint is
params:C
(dataclass-like class)we get:
print_config
givesc:c
rightly when--params
feeds nothing--params
feeds any classes (A
/B
/C
)raise exceptionwhen type hint is
Union[A,B,C]
,now I want know how to config params ifisinstance(params,C)
by usingprint_config
we get
no one gives
c:c
config example!Expected behavior
print_config
can printparams
's configEnvironment
pip install jsonargparse[all]