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

A Union[Dict[str, str], List[Any]] field parses dict, when it should parse List[str] for 2-character inputs #2271

Closed
3 tasks done
MartinThoma opened this issue Jan 20, 2021 · 1 comment
Labels
bug V1 Bug related to Pydantic V1.X

Comments

@MartinThoma
Copy link

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 still think this is a bug

Versions

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

             pydantic version: 1.7.3
            pydantic compiled: True
                 install path: /home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/pydantic
               python version: 3.9.1 (default, Jan 16 2021, 13:41:30)  [GCC 9.3.0]
                     platform: Linux-5.4.0-62-generic-x86_64-with-glibc2.31
     optional deps. installed: ['typing-extensions']

Bug

When I pass a List[str] with the string being 2 characters long (e.g. ["ab"]) to a field which is annotated with Union[Dict[str, str], List[Any]], I get a dictionary {"a": "b"} instead of ["ab"].

Example:

from typing import Union, List, Any, Dict

from pydantic import BaseModel


class Foo(BaseModel):
    values: Union[Dict[str, str], List[Any]]

class Foo2(BaseModel):
    values: Union[List[Any], Dict[str, str]]


print(Foo.parse_obj({"values": ["L1"]}))
print(Foo.parse_obj({"values": ["L11"]}))
print(Foo2.parse_obj({"values": ["L1"]}))

Results in:

values={'L': '1'}  # Unexpected - why do I get a dict?
values=['L11']  # expected value, but surprising after seeing output (1)
values=['L1']  # expected value, but surprising after seeing output (1)
@MartinThoma MartinThoma added the bug V1 Bug related to Pydantic V1.X label Jan 20, 2021
@PrettyWood
Copy link
Member

PrettyWood commented Jan 20, 2021

Hello @MartinThoma
Yes it's a very common issue on pydantic as it tries to coerce the value with types inside the Union in order (so the first one will take precedence over the second one if possible).
So here it first tries to coerce ["L1"] with Dict[str, str], which works because dict(["11"]) == {'1': '1'}.
I'm working on a way to prevent this in #2092. The whole behaviour will change in v2.
Please have a look at linked issues to this PR if you want more information

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug V1 Bug related to Pydantic V1.X
Projects
None yet
Development

No branches or pull requests

2 participants