-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Failure to override an inherited field with a computed field #7250
Comments
Looks like a bug. We should either fix it so in this example BTW, there's no way to avoid the pyright complaint since that's just dataclass transforms doing their thing. PR welcome to fix this. |
Should this even be allowed? In general, overriding an attribute with a property is not allowed, e.g. because it cannot be assigned to. So even if we could allow this, I think it's technically incorrect to allow it. It wouldn't be the first time we do something "not theoretically correct" for the sake of usability, but we should maybe rethink if this is complex to implement as well. @sydney-runkle is going to look into what the implementation would look like. |
Here's an example: class Foo:
name: str
class Bar(Foo):
@property
def name(self) -> str:
raise NotImplementedError MyPy says:
Pyright says:
Even within a Pydantic context: from pydantic import BaseModel, computed_field
class Foo(BaseModel):
name: str
class Bar(Foo):
@computed_field
@property
def name(self) -> str:
raise NotImplementedError
def f(a: Foo) -> Foo:
a.name *= 2
return a
f(Foo(name='a'))
f(Bar()) # TypeError: unsupported operand type(s) for *=: 'property' and 'int' Even without the runtime error type checkers that use PEP 681 won't handle this override correctly (which was pointed out in the issue's first comment). |
Going off of Samuel's original comment, I've opened the above ^^ PR to raise an error when a computed field overrides an inherited field. Following up with @adriangb's inquiry, I don't think this behavior should be allowed in |
Implementing a setter would have revealed that this is valid, at least according to mypy. from dataclasses import dataclass
@dataclass
class A:
b: int
class B(A):
def __init__(self) -> None:
self._b = 2
@property
def b(self) -> int:
return self._b
@b.setter
def b(self, value: int) -> None:
self._b = value Type checks with mypy 1.5.1, and behaves like you'd expect. Same goes without ... py:12: error: Dataclass attribute may only be overridden by another attribute [misc] |
@adriangb, given the increased number of questions about this recently (I've seen 3 in the past week), I think it makes sense to update the docs with an example. Do you agree? I'd be happy to open a PR if so. |
Yes docs updates are always a good path forward! |
Initial Checks
Description
It seems that overriding a regular field with a computed field doesn't behave as expected. Instead of a value being returned by accessing the property the property object itself is returned. And as for
@cached_property
causes an exception withinpydantic/_internal/_utils.py:smart_deepcopy
.Example Code
Edit: After some further playing around, removing the default
name = "Foo"
fromFoo
it's clear thatname
withinBar
is in some kind of weird hybrid state.Python, Pydantic & OS Version
Selected Assignee: @hramezani
The text was updated successfully, but these errors were encountered: