OpenSemanticLab / osw-python

GNU Affero General Public License v3.0
3 stars 2 forks source link

Casting to base class occurs in typed param classes #62

Open simontaurus opened 1 month ago

simontaurus commented 1 month ago

If a common base class (here Entity) is used for typing, casting to this class occurs when annotating a (param) class accordingly. This is not the case when using BaseModel for annotation.

from pydantic import BaseModel

class Entity(BaseModel):
    pass

class Item(BaseModel):
    pass

class Person(Item):
    pass

class ParamA(BaseModel):
    p: BaseModel

class ParamB(BaseModel):
    p: Entity

print(type(ParamA(p=Person()).p).__name__) # => Person
print(type(ParamB(p=Person()).p).__name__) # => Entity
from typing import Optional

from pydantic import BaseModel

class Entity(BaseModel):
    pass

class Item(BaseModel):
    pass

class Person(Item):
    pass

def test1(x: BaseModel):
    print(type(x).__name__)

def test2(x: Entity):
    print(type(x).__name__)

class ParamA(BaseModel):
    p: BaseModel

class ParamB(BaseModel):
    p: Entity

def test3(x: ParamA):
    print(type(x.p).__name__)

def test4(x: ParamB):
    print(type(x.p).__name__)

test1(Person()) # => 'Person'
test2(Person()) # => 'Person'
test3(ParamA(p=Person())) # => 'Person'
test4(ParamB(p=Person())) # => 'Entity'

see also: https://github.com/OpenSemanticLab/osw-python/commit/1a4c7f27a27adfee29e4144d362ea01a73cec040

simontaurus commented 1 month ago

I made a typo - actually this use case works

from pydantic import BaseModel

class Entity(BaseModel):
    pass

class Item(Entity):
    pass

class Person(Item):
    pass

class ParamA(BaseModel):
    p: BaseModel

class ParamB(BaseModel):
    p: Entity

print(type(ParamA(p=Person()).p).__name__) # => Person
print(type(ParamB(p=Person()).p).__name__) # => Person