Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

External dict-like type gets mapped to dict (unwanted behaviour) #2311

Closed
4 tasks done
phinate opened this issue Feb 2, 2021 · 3 comments
Closed
4 tasks done

External dict-like type gets mapped to dict (unwanted behaviour) #2311

phinate opened this issue Feb 2, 2021 · 3 comments
Labels

Comments

@phinate
Copy link

phinate commented Feb 2, 2021

Checks

  • I added a descriptive title to this issue
  • I have searched (google, github) for similar issues and couldn't find anything
  • I have read and followed the docs and couldn't find an answer
  • After submitting this, I commit to one of:
    • Look through open issues and helped at least one other person
    • Hit the "watch" button on this repo to receive notifications and I commit to help at least 2 people that ask questions in the future
    • Implement a Pull Request for a confirmed bug

Question

I'm trying to instantiate a class inheriting from BaseModel that has one member variable. I want this to be an immutable mapping type; currently, I'm using FrozenDict from flax while waiting for PEP 603.

The problem is that pydantic seems to recognise this type as a dict, and tries to cast to a dict as stated in the docs when typing.Dict is used for a field. This works regardless of setting arbitrary_types_allowed to True or False. Is there any way I can circumvent this behaviour in this one case, while still having the isinstance check I would expect for arbitrary_types_allowed = True?

Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":

             pydantic version: 1.7.3
            pydantic compiled: True
                 install path: /Users/phinate/.venvs/clarinet/lib/python3.8/site-packages/pydantic
               python version: 3.8.3 (default, May 19 2020, 13:54:14)  [Clang 10.0.0 ]
                     platform: macOS-10.15.7-x86_64-i386-64bit
     optional deps. installed: []
from pydantic import BaseModel
from flax.core import FrozenDict, freezeclass Example(BaseModel):
    dct: FrozenDict[str, int]
​
d = freeze(dict(x=3))
type(d)
> flax.core.frozen_dict.FrozenDict

class_d = Example(dct=d).dct
type(class_d)
> dict

...
@PrettyWood
Copy link
Member

Hi @phinate!

Yeah it's currently expected from pydantic. I guess we could try to keep the original type by adding

    elif issubclass(type(v), Mapping):
        return type(v)(result), None

here https://github.com/samuelcolvin/pydantic/blob/bd9c5723c676395363689549268738153e45a7e5/pydantic/fields.py#L737-L740

In the meantime the easiest workaround is to add a validator

class Example(BaseModel):
    dct: FrozenDict[str, int]

    @validator('dct')
    def to_frozendict(cls, v):
        return FrozenDict(v)

Hope it helps!

@phinate
Copy link
Author

phinate commented Feb 2, 2021

Thanks, this works great!

I'd say from a user perspective, it would be nice to not have implicit casting (you could lose access to class methods, for example), but that's ultimately your decision.

Oh and thanks for working on pydantic, its pretty awesome :)

@ofek
Copy link
Contributor

ofek commented Feb 7, 2021

fyi: #2325

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants