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

Buggy behavior on Unions #2501

Closed
AllanDaemon opened this issue Mar 9, 2021 · 1 comment
Closed

Buggy behavior on Unions #2501

AllanDaemon opened this issue Mar 9, 2021 · 1 comment
Labels
bug V1 Bug related to Pydantic V1.X

Comments

@AllanDaemon
Copy link

When I set a mode item to be a union of many others, instead of just checking it coerces the item to that Union, incorrectly. It's strange because I created the item using the correct model, but it totally ignores it and try to convert it to another class in the union. The code above explains it better.

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

             pydantic version: 1.8
            pydantic compiled: True
                 install path: /home/user/project/.venv/lib64/python3.9/site-packages/pydantic
               python version: 3.9.2 (default, Feb 20 2021, 00:00:00)  [GCC 10.2.1 20201125 (Red Hat 10.2.1-9)]
                     platform: Linux-5.10.19-200.fc33.x86_64-x86_64-with-glibc2.32
     optional deps. installed: ['dotenv', 'email-validator', 'typing-extensions']

Bug

Minimal version

from typing import Union
from pydantic import BaseModel

class A(BaseModel): ...
class B(BaseModel): ...

class Container(BaseModel):
	some: Union[A, B]

assert A != B

b = B()
assert type(b) != A
assert type(b) == B
print(type(b))
# <class '__main__.B'>

c = Container(some = b)
print(type(c.some))
# <class '__main__.A'>

assert type(c.some) == A # Works, but it shoudn't
# assert type(c.some) == B # Doesn't works, but it should

Longer version

#!/usr/bin/env python

from __future__ import annotations
from typing import Any, Optional, Union

from pydantic import BaseModel



class ActionItemBuy(BaseModel):
	type: str = "buy"

class ActionItemLink(BaseModel):
	type: str = "link"
	uri: str
	text: str
	default: Optional[bool]
	metadata: Optional[Any]

class ActionItemPostback(BaseModel):
	type: str = "postback"
	text: str
	payload: str
	metadata: Optional[Any]

class ActionItemReply(BaseModel):
	type: str = "reply"
	text: str
	payload: str
	metadata: Optional[Any]
	iconUrl: Optional[str]


ActionItem = Union[
	ActionItemBuy,
	ActionItemLink,
	ActionItemPostback,
	ActionItemReply,
]


class Container(BaseModel):
	action: ActionItem

assert ActionItemPostback != ActionItemBuy

ac = ActionItemPostback(text='Action Text', payload='Action Payload')

print(type(ac))
# ActionItemPostback

assert type(ac) == ActionItemPostback
assert type(ac) != ActionItemBuy

c = Container(action = ac)
print(type(c.action))
# ActionItemBuy

# Works, but it shoudn't
assert type(c.action) == ActionItemPostback

# Doesn't work, but it should
assert type(c.action) == ActionItemBuy

Adding some non optional property that doesn't have in the last class makes this work, but it makes no sense why it's taking its content rather than the class (the type).

@AllanDaemon AllanDaemon added the bug V1 Bug related to Pydantic V1.X label Mar 9, 2021
@PrettyWood
Copy link
Member

Hi @AllanDaemon
It's a known issue and I hope to have a proper solution for v1.9
See #2135 (comment) for more info

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

3 participants