Giter Club home page Giter Club logo

Comments (9)

konradhalas avatar konradhalas commented on September 28, 2024

Hi Diogo,

first of all, thank you for creating the very first issue in this project :) It's good to know that someone is using (or trying to use!) dacite.

Regarding your question: I see your problem, but to be honest, I really don't know is it a good idea or maybe I should say - I don't know how to solve it properly.

I was trying to find a solution to a similar issue with Union type, my case looks like this:

from typing import Union

@dataclass
class Container:
    box: Union[Car, Person]

Currently dacite is looking for a data class on the provided list of types, if there is any, it takes first one and it tries to convert provided data into this inner data class. Of course, this is not the perfect solution, but it works.

But maybe dacite should try to convert data into each of this data class, and if it fails with the first one, it should take next on the list? Does it sound OK or is too "magic"?

We can also support TypeVar, but I thought it was mainly designed to handle "generic" functions and methods. Can you use Union in your case?

from dacite.

diogobaeder avatar diogobaeder commented on September 28, 2024

First of all, double thank you! 1), because of the quick reply and 2) because I've been trying to use TypeVar for the wrong purpose, without knowing that what I need is actually Union 😄 (I'm still inexperienced with type hinting in Python 3)

So your idea sounds very good to me - to try to convert to each type on the list, until one of them succeeds. The only problem I can think of, with this approach, is if it ends up returning an instance for the wrong type because the list of types is ambiguous, but, to be honest, it's the user's responsibility to make sure that they don't have ambiguity in their types or, if they do, it's up to them to do the proper conversions.

By the way, just to let you know what I'm trying to use your library for: I'm experimenting with it to know whether it's a good approach to have dicts converted to dataclass instances after validating them with OpenAPI 3. I've been struggling to have Marshmallow and other side libraries working well for my case - specially because I need the oneOf feature of OpenAPI 3 -, and now I'm experimenting with approaching it by starting with the JSON schema first (instead of having Python schemas determining the resulting schema for OpenAPI).

from dacite.

konradhalas avatar konradhalas commented on September 28, 2024

Good to hear that I could help :)

I implemented proper unions handling in feature/handle-unions branch. You can install this version with the following command:

pip install git+https://github.com/konradhalas/dacite@feature/handle-unions

It would be great if you found the time to test it in your case :) Let me know if it works as you want and as we described.

from dacite.

diogobaeder avatar diogobaeder commented on September 28, 2024

Hey man,

So, I created this file:

#!/usr/bin/env python

from typing import (
    List,
    Union,
)

import dacite
from dataclasses import dataclass


@dataclass
class Car:
    name: str


@dataclass
class Person:
    age: int


@dataclass
class Container:
    contained: Union[Car, Person]


@dataclass
class Containers:
    containers: List[Container]


raw_data = {
    'containers': [
        {
            'contained': {
                'name': 'Ford',
            },
        },
        {
            'contained': {
                'age': '21',
            },
        },
    ]
}


containers = dacite.from_dict(Containers, raw_data)
assert isinstance(containers.containers[0].contained, Car)
assert isinstance(containers.containers[1].contained, Person)

and running it I get:

$ ./test-union-dacite.py 
Traceback (most recent call last):
  File "./test-union-dacite.py", line 48, in <module>
    containers = dacite.from_dict(Containers, raw_data)
  File "/home/diogobaeder/Envs/tmp/lib/python3.6/site-packages/dacite.py", line 79, in from_dict
    field=field,
  File "/home/diogobaeder/Envs/tmp/lib/python3.6/site-packages/dacite.py", line 171, in _inner_from_dict_for_collection
    ) for item in data)
  File "/home/diogobaeder/Envs/tmp/lib/python3.6/site-packages/dacite.py", line 171, in <genexpr>
    ) for item in data)
  File "/home/diogobaeder/Envs/tmp/lib/python3.6/site-packages/dacite.py", line 72, in from_dict
    outer_config=config,
  File "/home/diogobaeder/Envs/tmp/lib/python3.6/site-packages/dacite.py", line 195, in _inner_from_dict_for_union
    raise UnionMatchError(field)
dacite.UnionMatchError: can not match the data to any type of "contained" union: typing.Union[__main__.Car, __main__.Person]

If I did anything wrong in that script, please let me know, but so far it doesn't seem to be working.

from dacite.

konradhalas avatar konradhalas commented on September 28, 2024

It looks like age (in raw_data) should be int instead of str. Am I right? ;)

from dacite.

diogobaeder avatar diogobaeder commented on September 28, 2024

Oh my gosh, I'm sorry, completely overlooked that...

Aaaaand it works beautifully! Good job! :-)

from dacite.

konradhalas avatar konradhalas commented on September 28, 2024

Awesome! I released new version 0.0.14. It's on PyPI now. Thank you once again :)

from dacite.

diogobaeder avatar diogobaeder commented on September 28, 2024

Awesome! Good job, man! :-)

from dacite.

diogobaeder avatar diogobaeder commented on September 28, 2024

Sorry to comment on a closed ticket again, but, man, what a terrific job! That change is working really well to me, and I'm even using it in nested dataclass models, with Config(transform=...). :-)

from dacite.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.