Skip to content
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

false positive for type-hinted Enum class instance variable #7402

Closed
huwcbjones opened this issue Sep 2, 2022 · 7 comments
Closed

false positive for type-hinted Enum class instance variable #7402

huwcbjones opened this issue Sep 2, 2022 · 7 comments
Labels
C: invalid-name False Positive 🦟 A message is emitted but nothing is wrong with the code

Comments

@huwcbjones
Copy link
Contributor

huwcbjones commented Sep 2, 2022

Bug description

As per https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html#classes, you can optionally declare instance variables in the class body. For normal classes, this is fine, but for Enums pylint raises a false positive

Define an enum with a type-hinted instance variable and you get an invalid name! 😞

class MyEnum(str, Enum):
    attr: int

    VALUE = "a", 1

    def __new__(cls, value, attr=None):
        obj = str.__new__(cls, value)
        obj._value_ = value
        obj.attr = attr
        return obj

Configuration

No response

Command used

pylint --disable=all --enable=invalid-name mwe.py

(pylint mwe.py also works, I just wanted to filter out the irrelavent messages)

Pylint output

************* Module mwe
mwe.py:5:4: C0103: Class constant name "attr" doesn't conform to UPPER_CASE naming style (invalid-name)

--------------------------------------------------------------------
Your code has been rated at 8.89/10

Expected behavior

No error

Pylint version

pylint 2.12.2/2.15.0
astroid 2.9.3/2.12.5
Python 3.9.1 (default, Mar 15 2021, 18:22:18)
[Clang 12.0.0 (clang-1200.0.32.27)]

OS / Environment

macOS

@huwcbjones huwcbjones added the Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling label Sep 2, 2022
@huwcbjones
Copy link
Contributor Author

From my quick peruse of the code, I believe that pylint will treat all Enum class variables as class constants, even if no value is assigned (the variable is for a type hint).
https://github.com/PyCQA/pylint/blob/880095c7266134a218e5f97075d1adeaa5b34b79/pylint/checkers/base/name_checker/checker.py#L459-L464

@mbyrnepr2
Copy link
Member

Thanks for reporting. I think this is expected since Enum members are expected to be constants. Quoting from the docs:

Because Enums are used to represent constants we recommend using UPPER_CASE names for enum members, and will be using that style in our examples.

https://docs.python.org/3/library/enum.html

@Pierre-Sassoulas Pierre-Sassoulas added Invalid Not a bug, already exists or already fixed C: invalid-name and removed Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling labels Sep 3, 2022
@Pierre-Sassoulas
Copy link
Member

I'd also say it's working as intended.

@Pierre-Sassoulas Pierre-Sassoulas closed this as not planned Won't fix, can't repro, duplicate, stale Sep 3, 2022
@andrei-korshikov
Copy link

@mbyrnepr2 not quite so. VALUE (from the example above) is enum member, it is constant, and it should be upper case. But attr is not enum member, it is the attribute of enum member, so it is just ordinary attribute of instance, it's not class constant.

As reference example, look at the Planet from Python docs. They don't write self.MASS, but self.mass. So for type hinting we have to write mass: int with the lower case in the class Planet (Enum) body.

And here is my own example (that is why I've dug out this issue):

from enum import Enum

class Color(Enum):
    """Represents colors as (red, green, blue) tuples."""

    YELLOW      = 250, 250,   0
    KHAKI       = 250, 250, 125
    MAGENTA     = 250,   0, 250
    VIOLET      = 250, 125, 250
    CYAN        =   0, 250, 250
    AQUAMARINE  = 125, 250, 250

    # Class constant name "red" doesn't conform to UPPER_CASE naming style (invalid-name)
    # Class constant name "green" doesn't conform to UPPER_CASE naming style (invalid-name)
    # Class constant name "blue" doesn't conform to UPPER_CASE naming style (invalid-name)
    red: int
    green: int
    blue: int

    def __init__(self, red: int, green: int, blue: int) -> None:
        self.red   = red
        self.green = green
        self.blue  = blue

    @property
    def as_hex(self) -> str:
        """Get hex 'abcdef' representation for a color."""
        return f'{self.red:0{2}x}{self.green:0{2}x}{self.blue:0{2}x}'

@Pierre-Sassoulas I disagree with you:) @huwcbjones clearly showed to us that Pylint sees no difference between enum member and its instance variables. Is it possible to reopen the issue?

@mbyrnepr2
Copy link
Member

Thank you @andrei-korshikov 👍 Completely agree with you.
I am working on fixing it 🎉

@mbyrnepr2 mbyrnepr2 reopened this Jul 31, 2023
mbyrnepr2 added a commit to mbyrnepr2/astroid that referenced this issue Jul 31, 2023
…, from the ``__members__`` container of an ``Enum`` class.

Refs pylint-dev/pylint#7402
mbyrnepr2 added a commit to mbyrnepr2/pylint that referenced this issue Jul 31, 2023
…ontainer before doing the ``invalid-name`` check.

Refs pylint-dev#7402
mbyrnepr2 added a commit to mbyrnepr2/pylint that referenced this issue Aug 3, 2023
…ontainer before doing the ``invalid-name`` check.

Refs pylint-dev#7402
@Pierre-Sassoulas Pierre-Sassoulas added False Positive 🦟 A message is emitted but nothing is wrong with the code and removed Invalid Not a bug, already exists or already fixed labels Aug 4, 2023
@Pierre-Sassoulas Pierre-Sassoulas added this to the 2.17.6 milestone Aug 4, 2023
mbyrnepr2 added a commit to mbyrnepr2/pylint that referenced this issue Aug 4, 2023
…ontainer before doing the ``invalid-name`` check.

Refs pylint-dev#7402
Pierre-Sassoulas pushed a commit to pylint-dev/astroid that referenced this issue Aug 5, 2023
…s__ container (#2263)

* Exclude type-annotated class attributes, which have no assigned value, from the ``__members__`` container of an ``Enum`` class.

Refs pylint-dev/pylint#7402

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Fix exising test.

The value if now `Uninferable` in the case of
an annotated attribute of an `enum.Enum` class with no assigned value.

* Update astroid/brain/brain_namedtuple_enum.py

Co-authored-by: Jacob Walls <jacobtylerwalls@gmail.com>

* Update tests.

* Update test: Use `infer()` instead of `inferred()`.

* Update type annotations of PEP 695 nodes (#2264)

These attributes cannot be none in real-world situations,
see python/cpython#106145.

* Update sphinx requirement from ~=7.0 to ~=7.1 (#2265)

Updates the requirements on [sphinx](https://github.com/sphinx-doc/sphinx) to permit the latest version.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES)
- [Commits](sphinx-doc/sphinx@v7.0.0...v7.1.1)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Ensure a node is inferred in the case when there is only one member.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Undo unintended changes.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Jacob Walls <jacobtylerwalls@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
mbyrnepr2 added a commit to mbyrnepr2/astroid that referenced this issue Sep 11, 2023
…and ``_value_`` sunders of an Enum member value.

Refs pylint-dev/pylint#7402
Pierre-Sassoulas pushed a commit to pylint-dev/astroid that referenced this issue Sep 12, 2023
#2289)


Refs pylint-dev/pylint#9015

* Fix a false positive for ``no-member`` when accessing the ``_name_`` and ``_value_`` sunders of an Enum member value.

Refs pylint-dev/pylint#7402
mbyrnepr2 added a commit to mbyrnepr2/pylint that referenced this issue Sep 23, 2023
…ontainer before doing the ``invalid-name`` check.

Refs pylint-dev#7402
@jacobtylerwalls jacobtylerwalls modified the milestones: 2.17.6, 3.0.0b1 Sep 23, 2023
@Pierre-Sassoulas Pierre-Sassoulas removed this from the 3.0.0b0 milestone Sep 25, 2023
@DanielNoord
Copy link
Collaborator

@mbyrnepr2 In which PR has this been fixed? Might be good to link here.

@mbyrnepr2
Copy link
Member

Two changes for this fix. A Pylint PR: #8905 and an astroid PR: pylint-dev/astroid#2263

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: invalid-name False Positive 🦟 A message is emitted but nothing is wrong with the code
Projects
None yet
Development

No branches or pull requests

6 participants