-
-
Notifications
You must be signed in to change notification settings - Fork 374
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
Initialization order of fields overridden in subclasses #707
Comments
I don't think we'll do subclassing DC style, but I could be convinced by a good design for #637 I think. (The reason I don't like DC style is that it's not apparent from |
Sounds like another approach here may be lazy factory for The example from the first post seems to be solvable with pure |
The main thing I want to get out of this is construction-time type checking, so I really must be able to override at least the type annotation of Also, I didn't mention, but I use slotted frozen classes, and @cached_property wouldn't work. My current workaround looks like this:
My previous workaround asserted for the type of the_x in post_init, and in all extension functions, which is kind of a pain. But now that I'm thinking about it, I might use a |
Why don't use def validate_type(self, attr, value):
assert isinstance(value, attr.type)
@attr.dataclass(frozen=True, slots=True) # .dataclass( is shorter than .s(auto_attribs=True,
class XContainer:
the_x: X = attr.ib(validator=validate_type)
@property
def x_metadata(self) -> XMetadata:
return self.the_x.get_metadata()
@attr.dataclass(frozen=True, slots=True)
class BetterXContainer(XContainer):
# Note, that attr.ib is required, as auto_attribs=True will create empty attr.ib automatically (thus - override all validators)
the_x: XButBetter = attr.ib(validator=validate_type)
# Not sure if it's needed, but in case your metadata types are different you can help mypy like that:
if typing.TYPE_CHECKING:
@property
def x_metadata(self) -> XButBetterMetadata: ... |
Huh,
It solves the "ton of asserts in the methods" problem while not breaking anything (like initialization order and constructor parameter order). Runtime type checking can be done in Unfortunately my main remaining concern is static type checking at construction-time, and the mypy attrs plugin does not seem to care about this (see https://github.com/python/mypy/blob/master/mypy/plugins/attrs.py#L320 |
The comment in question says:
This was definitely what I observed when I coded this up though it might've changed since then. Let me put it to the test:
This gives me:
So in But I was definitely not thinking of subclassing so that's probably another story. When you say:
What do you mean? Usually |
Hi! Thanks for joining in 😄 It seems that attr.ib() attributes behind
When it really should in the last line. If I omit the I guess in the attrs plugin, only simple, top-level assignments are "detected" when you do
|
Oh right. We're actually trying to read code in the middle of mypy. Ok so I think the workaround might be:
|
Oh, I've missed the whole point about order of parameters in If I'd really cared about that - I would make all non-redefinable attributes
|
I have a code similar to the following, that relies very heavily on mypy for correctness:
The last line fails with
AttributeError: 'BetterXContainer' object has no attribute 'the_x'
, because the initialization order of the attributes changed in the subclass. Another similar issue is described on stackoverflow.Any plans on implementing subclassing similarly to dataclasses? Would that be a breaking API change? (Probably.)
Related attrs issue I found: #637
PS.: I realize this is subclassing issue n+1 when subclassing is frowned upon, and this is somewhat similar to the classic OOP problem of subclassing Circle from Ellipse, so feel free to just say "damn man, this is not proper OOP, so wontfix".
The text was updated successfully, but these errors were encountered: