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

When using Unions inside BaseModel ints and booleans are converted to str #436

Closed
JakeSummers opened this issue Mar 27, 2019 · 2 comments
Closed
Labels
documentation help wanted Pull Request welcome

Comments

@JakeSummers
Copy link

System Info:

  • OS: Linux
  • Python version 3.7.1
  • Pydantic version 0.21

Suppose I have a class and tests like this:

from typing import Union

from pydantic import BaseModel

class Simple(BaseModel):
    value: Union[int, str, bool, None]


def test_simple_booleans_are_not_lost():

    simple = Simple(value=True)
    print(f"simple.value is of type {type(simple.value)}")
    assert simple.value == True


def test_simple_ints_are_not_lost():
    simple = Simple(value=404)
    print(f"simple.value is of type {type(simple.value)}")
    assert simple.value == 404


def test_simple_strings_are_not_lost():
    simple = Simple(value="Jake")
    print(f"simple.value is of type {type(simple.value)}")
    assert simple.value == "Jake"


def test_simple_Nones_are_not_lost():
    simple = Simple(value=None)
    print(f"simple.value is of type {type(simple.value)}")
    assert simple.value == None

This works great!

Oddly, if I change the definition of Simple from:

class Simple(BaseModel):
    value: Union[int, str, bool, None]

To:

class Simple(BaseModel):
    value: Union[str, bool, None, int]

This causes some of the tests to fail. Specifically, the test_simple_booleans_are_not_lost and test_simple_ints_are_not_lost will fail. This is because the values are converted to strings. Output from the test:

simple.value is of type <class 'str'>

.../test_simple.py:15 (test_simple_ints_are_not_lost)
404 != 404

Expected :404
Actual   :404
 <Click to see difference>

def test_simple_ints_are_not_lost():
        simple = Simple(value=404)
        print(f"simple.value is of type {type(simple.value)}")
>       assert simple.value == 404
E       AssertionError: assert '404' == 404
E        +  where '404' = <Simple value='404'>.value

test_simple.py:19: AssertionError

The documentation on typing.Union specifies that order of items in a Union is irrelevant.

image

@samuelcolvin
Copy link
Member

What the docs say is

when comparing unions, the argument order is ignored

In the case of pydantic the order is not ignored, we could better document this, but I don't think it's worth fixing since it would require lots more checking and would slow things down.

@samuelcolvin
Copy link
Member

This has it's own section in the new docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation help wanted Pull Request welcome
Projects
None yet
Development

No branches or pull requests

2 participants