Giter Club home page Giter Club logo

Comments (10)

Fatal1ty avatar Fatal1ty commented on July 23, 2024

Hi @gshank.

If str is on the first place of Union args, then it will be on the first place in Union inside of InvalidFieldValue exception. There is no reordering under the hood. I suggest you double check the dataclass field types.

Anyway, if you put List[str] on the first place, then input data might be coerced to List[str] from a str value because str supports iterator protocol and there is no strict validation with isinstance at the moment. However, in this case you can avoid this problem by coercing a value to a list of values:

@dataclass
class NodeConfig(DataClassDictMixin):
    unique_key: Optional[Union[List[str], str]] = None

    @classmethod
    def __pre_deserialize__(cls, d):
        unique_key = d.get('unique_key')
        if isinstance(unique_key, str):
            d['unique_key'] = [unique_key]
        return d

from mashumaro.

gshank avatar gshank commented on July 23, 2024

'str' is in the first place of the Union args, but somehow it's still ending up in second place in the InvalidFieldValue exception, so something is reordering it. Thanks for the example, but we'd prefer it the other way, where if it's a single str it stays that way. I wonder if this could be a Python bug? I'll try it with some other Python versions.

from mashumaro.

gshank avatar gshank commented on July 23, 2024

You can see the definition here, in the NodeConfig class: https://github.com/dbt-labs/dbt-core/blob/main/core/dbt/contracts/graph/model_config.py

from mashumaro.

Fatal1ty avatar Fatal1ty commented on July 23, 2024

I wonder if this could be a Python bug?

I don't think so.

I see that you make some non-trivial changes to the input data with hooks. If the problem occurs in the tests only, I think logging the data value at the beginning and at the end of __pre_deserialize__ method can help to figure it out. I'd like to know what's going on with the initial dictionary after pre_hook and post_hook applied.

from mashumaro.

gshank avatar gshank commented on July 23, 2024

It looks like it's a bug in typing.get_type_hints. In that particular case it returns: 'unique_key': typing.Union[typing.List[str], str, NoneType]. I'm going to change the definition from Optional[Union[str, List[str]] to Union[str, List[str], None], which so far seems to work. It's intermittent (since in most other case it doesn't do that), and I'm not up for debugging Python.

Thanks for taking a look.

from mashumaro.

Fatal1ty avatar Fatal1ty commented on July 23, 2024

@gshank I think you didn't try mashumaro 2.11 at least? There were some fixes for Union and None: https://github.com/Fatal1ty/mashumaro/releases/tag/v2.11.
Release 2.9.1 also contains a fix for deserialization override for Union types: https://github.com/Fatal1ty/mashumaro/releases/tag/v2.9.1

P.S. I should definitely create a template for the issues :)

from mashumaro.

Fatal1ty avatar Fatal1ty commented on July 23, 2024

Anyway, if the problem is solved, we can close this issue.

from mashumaro.

gshank avatar gshank commented on July 23, 2024

We're on mashumaro 2.9 right now. I did a typing.get_type_hints(NodeConfig) (which leaves mashumaro out of it entirely), and the order came out different than it was in the code. I believe that for Unions mashumaro constructs code that tries the various types in order?

It's not totally clear to me that this is actually a typing.get_type_hintsbug. In theory, I guess that elements in the Union should be transposable. But this doesn't work very well for some types when trying to serialize by trying them out. Perhaps the solution is some kind of combined str/List[str] type which would handle this properly.

from mashumaro.

Fatal1ty avatar Fatal1ty commented on July 23, 2024

I believe that for Unions mashumaro constructs code that tries the various types in order?

Yes, it does it in the initial order. Union arguments are stored in __args__ attribute.

In theory, I guess that elements in the Union should be transposable.

Ideally, yes. But without strict validation of input data types it's not possible. I'm working on a validation feature that would help with this.

Perhaps the solution is some kind of combined str/List[str] type which would handle this properly.

Or just create a list of one element during deserialization in case of str value since List[str] is a valid type here :)

from mashumaro.

gshank avatar gshank commented on July 23, 2024

That works too :)

from mashumaro.

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.