Skip to content

Slots does not work with typing.Final dataclass attribute #115879

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

Closed
NicoHood opened this issue Feb 24, 2024 · 7 comments
Closed

Slots does not work with typing.Final dataclass attribute #115879

NicoHood opened this issue Feb 24, 2024 · 7 comments
Labels
stdlib Python modules in the Lib dir topic-typing type-bug An unexpected behavior, bug, or error

Comments

@NicoHood
Copy link

NicoHood commented Feb 24, 2024

Bug report

Bug description:

Hi,
I discovered a bug when using the Final attribute along with slots=True in dataclasses. The bug is more described in this stackoverflow post where someone with more knowledge has explained to me why this happens and which code line causes this issue:
https://stackoverflow.com/questions/78039353/why-does-slots-not-work-with-final-dataclass-attribute

Here is a minimal example:

#!/usr/bin/env python3

from __future__ import annotations
from dataclasses import dataclass
from typing import Final, ClassVar

@dataclass(slots=True)
class Child():
    VERSION: Final[str] = '1.0.0'

    @classmethod
    def check_version(cls, version: str) -> bool:
        return version == cls.VERSION

print(Child.check_version('1.0.0'))
# Returns False

CPython versions tested on:

3.11

Operating systems tested on:

Linux

@NicoHood NicoHood added the type-bug An unexpected behavior, bug, or error label Feb 24, 2024
@AlexWaygood
Copy link
Member

Interesting -- possibly a duplicate of #89547

@AlexWaygood AlexWaygood added stdlib Python modules in the Lib dir topic-typing labels Feb 25, 2024
@sobolevn
Copy link
Member

I don't think that this is a bug, actually. Let's "compile" what's happening into simplier python code:

@dataclass(slots=True)
class Child:
    VERSION: Final[str] = '1.0.0'

Turns into:

class Child:
    __slots__ = ('VERSION',)
    def __init__(self, VERSION) -> None:
         self.VERSION: Final[str] = '1.0.0'

Remember that all field: annotation = default statements inside a dataclass are translated into instance attributes.

So, when you access cls.VERSION you get <member 'VERSION' of 'Child' objects>. This is also correct.

If you want to use Final with class-level variables right now you have to do something like:

class Base:
    VERSION: Final[str] = '1.0.0'

@dataclass(slots=True)
class Child(Base):
    ...

I agree with @AlexWaygood that this is a duplicate of #89547 and the proper solution would be to use something like ClassVar[Final[]] for this in the future.

I am going to close this issue as a duplicate, but feel free to ask any questions you might have :)

@sobolevn sobolevn closed this as not planned Won't fix, can't repro, duplicate, stale Feb 25, 2024
@NicoHood
Copy link
Author

NicoHood commented Mar 5, 2024

So is ClassVar[Final[]] the correct solution or not? You wrote "in the future". So what should I do now?

@sobolevn
Copy link
Member

sobolevn commented Mar 5, 2024

Now you can do this:

class Base:
    VERSION: Final[str] = '1.0.0'

@dataclass(slots=True)
class Child(Base):
    ...

@NicoHood
Copy link
Author

NicoHood commented Sep 6, 2024

But what if the version must be in the child, as I have different child implementations?

@sobolevn
Copy link
Member

sobolevn commented Sep 6, 2024

Use VERSION: ClassVar[str] = '1.2.3' then.

@NicoHood
Copy link
Author

But a classvar is not final, isnt it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stdlib Python modules in the Lib dir topic-typing type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

3 participants