-
- Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Bug description
Pylint (C0103) generates contradictory invalid-name warnings for class-level attributes annotated with typing.Final.
- It flags a
snake_caseattribute annotated withFinalas an invalid constant (demandingUPPER_CASE). - It flags an
UPPER_CASEattribute annotated withFinalas an invalid attribute (demandingsnake_case).
This creates a catch-22 where no naming convention is considered valid.
A Simple Example
# file: example.py from dataclasses import dataclass from typing import Final @dataclass class ExampleClass: parameter_one: int = 10 parameter_two: str = "default" parameter_three: float = 3.14 # C0103: Class constant name "parameter_six" doesn't conform to UPPER_CASE naming style (invalid-name) parameter_six: Final[int] = 42 # C0103: Attribute name "PARAMETER_FIVE" doesn't conform to snake_case naming style (invalid-name) PARAMETER_FIVE: Final[int] = 42Analysis
The core purpose of both the UPPER_CASE naming convention (from PEP 8) and the typing.Final annotation is identical: to signal developer intent that a variable is a constant and should not be reassigned.
Pylint's linter appears to be applying two different rules inconsistently:
For parameter_six, it correctly identifies Final as indicating a constant and therefore demands the UPPER_CASE naming convention.
For PARAMETER_FIVE, it seems to ignore the Final annotation, classify the variable as a standard attribute (which can be modified), and therefore incorrectly demands the snake_case naming convention.
This logic is contradictory. The UPPER_CASE convention was created precisely to communicate the intent of immutability that typing.Final now enforces statically. These two signals should be seen as compatible and reinforcing, not mutually exclusive.
Proposed Behavior
When a class-level attribute is annotated with typing.Final, it should be treated as a constant for naming convention purposes.
PARAMETER_FIVE: Final[int] = 42(UPPER_CASE) should NOT raise an invalid-name warning. It correctly uses the constant naming convention.parameter_six: Final[int] = 42(snake_case) SHOULD (as it currently does) raise an invalid-name warning, suggesting theUPPER_CASEconvention is preferred forFinalattributes.
I suggest Pylint treats UPPER_CASE same as Final because they are basically flagging the same thing in the code, that is DO NOT modify this. The logic behind because UPPER_CASE attributes can be modified so it needs to be snake_case reverses the logic.
Configuration
pylint 3.3.8 python 3.11.14Command used
python -m pylint /home/ubuntu/GitHub/embedded-apps/example.pyPylint output
************* Module example example.py:21:4: C0103: Attribute name "PARAMETER_FIVE" doesn't conform to snake_case naming style (invalid-name) example.py:18:4: C0103: Class constant name "parameter_six" doesn't conform to UPPER_CASE naming style (invalid-name)Expected behavior
The first "PARAMETER_FIVE" is legit UPPER_CASE user case so pylint shouldn't raise anything.
Pylint version
pylint 3.3.8OS / Environment
Ubuntu 24.04.3
Additional dependencies
No.