Skip to content

Parsing fails with mixture of classes and dataclasses #569

@williford

Description

@williford

🐛 Bug report

Validation fails when there is a union of dataclass and regular classes.

To reproduce (Updated Example)

Create cli.py:

from dataclasses import dataclass
from typing import Dict, Optional, Union

from jsonargparse import CLI


@dataclass
class MyData:
    val_a: Optional[str] = None
    val_b: Optional[str] = None


class MyClass:
    def __init__(self, val_1: str, val_2: str):
        self.val_1 = val_1
        self.val_2 = val_2


class MyContainer:
    def __init__(self, value: Union[MyData, MyClass]):
        self.value = value

def command(mycontainer: Optional[MyContainer] =[]) -> None:
    print("Success")


if __name__ == '__main__':
    CLI(command)

And config.yaml file:

mycontainer:
  class_path: MyContainer
  init_args:
    value:
      class_path: MyClass
      init_args:
        val_1: "A"
        val_2: "B"

Run the command:

python cli.py --config config.yaml

The following error results:

usage: cli.py [-h] [--config CONFIG] [--print_config[=flags]] [--mycontainer.help CLASS_PATH_OR_NAME] [--mycontainer MYCONTAINER]
              [--print_shtab {bash,zsh,tcsh}]
error: Validation failed: Parser key "mycontainer":
  Does not validate against any of the Union subtypes
  Subtypes: (<class '__main__.MyContainer'>, <class 'NoneType'>)
  Errors:
    - Problem with given class_path '__main__.MyContainer':
        Parser key "value":
          Does not validate against any of the Union subtypes
          Subtypes: (<class '__main__.MyData'>, <class '__main__.MyClass'>)
          Errors:
            - No action for key "class_path" to set its default.
            - Not a valid subclass of MyClass
              Subclass types expect one of:
              - a class path (str)
              - a dict with class_path entry
              - a dict without class_path but with init_args entry (class path given previously)
          Given value type: <class 'jsonargparse._namespace.Namespace'>
          Given value: Namespace(val_a=None, val_b=None, class_path='MyClass', init_args=Namespace(val_1='A', val_2='B'))
    - Expected a <class 'NoneType'>
  Given value type: <class 'jsonargparse._namespace.Namespace'>
  Given value: Namespace(class_path='__main__.MyContainer', init_args=Namespace(value=Namespace(val_a=None, val_b=None, class_path='MyClass', init_args=Namespace(val_1='A', val_2='B'))))

It should print "Success".

If the Union[MyData, MyClass] is replaced with Union[MyClass], then it is successful.

Environment

  • jsonargparse version: 4.32.1
  • Python version: 3.10.13
  • How jsonargparse was installed: pip install "jsonargparse[all]>=4.27.7"
  • OS: Ubuntu 24.04 LTS

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions