admin管理员组文章数量:1279124
I have a Pydantic class to represent how my general API response should look:
class RootDataResponseSchema(BaseModel):
status: Literal["success", "fail"]
data: BaseModel
I went with BaseModel
for data, as the idea would be I'd subclass RootDataResponseSchema
and add more specificity to specific endpoint responses, such as:
class NewItemResponse(RootDataResponseSchema):
status: Literal["success"] = "success"
data: NewItemResponseData
The problem I've run into seems to only affect the IDE (in my case VSCode), so I assume is a notice from pylance, but tells me that both status
and data
have changed from the root class. It does mention it's irrelevant, but as a subclassed object does count as the superclass in terms of comparison, is there a mechanism for narrowing the scope of type hints in Python? Or is this just an artifact of loosely typed Python?
I have a Pydantic class to represent how my general API response should look:
class RootDataResponseSchema(BaseModel):
status: Literal["success", "fail"]
data: BaseModel
I went with BaseModel
for data, as the idea would be I'd subclass RootDataResponseSchema
and add more specificity to specific endpoint responses, such as:
class NewItemResponse(RootDataResponseSchema):
status: Literal["success"] = "success"
data: NewItemResponseData
The problem I've run into seems to only affect the IDE (in my case VSCode), so I assume is a notice from pylance, but tells me that both status
and data
have changed from the root class. It does mention it's irrelevant, but as a subclassed object does count as the superclass in terms of comparison, is there a mechanism for narrowing the scope of type hints in Python? Or is this just an artifact of loosely typed Python?
2 Answers
Reset to default 2Those annotations don't just say what types can be observed for those attributes. They also say what types can be assigned to those attributes. Your annotations claim that if you have an instance of RootDataResponseSchema
, it is okay to perform
obj.status = 'fail'
Your subclass's annotations say that this assignment is not okay, hence the conflict.
If you don't want to allow these assignments, you can indicate that to type checkers with typing.Final
:
from typing import Final, Literal
class RootDataResponseSchema(BaseModel):
status: Final[Literal["success", "fail"]]
data: Final[BaseModel]
class NewItemResponse(RootDataResponseSchema):
status: Final[Literal["success"]] = "success"
data: Final[NewItemResponseData]
I am not sure whether Pydantic will do the right thing with these annotations, however. The Pydantic source code looks like it treats typing.Final
as marking a field frozen, but I can't find any documentation about the behavior, only a bug report about inconsistent handling from 2023, closed as completed with no pull request linked.
If you want a type with exactly two values, define an enumerated type. (While we're redefining things, your base class should probably be generic in the type of data
.)
T = TypeVar('T', bound=BaseModel)
class StatusType(StrEnum):
SUCCESS = "success"
FAILURE = "fail"
class RootDataResponseSchema(BaseModel, Generic[T]):
status: StatusType
data: T
class NewItemResponse(RootDataResponseSchema[NewItemResponseData]):
status = StatusType.SUCCESS
本文标签: pythonNarrowing typing on a subclassStack Overflow
版权声明:本文标题:python - Narrowing typing on a subclass - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741236730a2363161.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
Literal['success', 'fail']
andLiteral['success']
are two very distinct sets of items, the latter is not an instance or subclass of the former. You shouldn't get any warnings forstatus
if you just remove the type hint, because'success'
is a valid item from the literal type declared in the base class. – NotAName Commented Feb 25 at 0:57Field 'status' defined on a base class was overridden by a non-annotated attribute. All field definitions, including overrides, require a type annotation.
– Rohit Commented Feb 25 at 2:23status
after initialisation, but I presume it's rare that you'd want to. – dROOOze Commented 5 hours ago