Skip to content

Conversation

@joao-faria-dev
Copy link

Description

Fixes a false positive where module-level constants were incorrectly classified as variables when a class-level attribute with the same name exists. I added a scope check so now when we check for reassignments, we make sure we only look at nodes within the same scope

Closes #10719

@joao-faria-dev joao-faria-dev force-pushed the fix-c0103-module-class-name-conflict branch 2 times, most recently from 1a5cff6 to 178bdc8 Compare November 6, 2025 17:52
Copy link
Member

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great first PR, thank you. Could you add a functional test in tests/functional to check it automatically, please ?

@joao-faria-dev
Copy link
Author

joao-faria-dev commented Nov 6, 2025

Thanks for the review @Pierre-Sassoulas, just added it!

@github-actions

This comment has been minimized.

Copy link
Member

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made a suggestion to match the example from the issue, let me know what you think. Changed Input to input, maybe it was the reason for the second invalid-name (shouldn't have been pascal case ?)

@@ -0,0 +1,8 @@
"""Test module-level constants with class attribute same name"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""Test module-level constants with class attribute same name"""
"""Test module-level constants with class attribute same name
Regression test for #10719.
"""

Comment on lines 7 to 8
class MyClass:
MY_CONST = 10
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
class MyClass:
MY_CONST = 10
class MyClass:
MY_CONST = 10
class Theme:
INPUT = ">>> "
INPUT = Theme()
input = Theme()
OUTPUT = Theme()
output = Theme()

@@ -0,0 +1,3 @@
Fixed false positive for ``invalid-name`` (C0103) where module-level constants were incorrectly classified as variables when a class-level attribute with the same name exists.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Fixed false positive for ``invalid-name`` (C0103) where module-level constants were incorrectly classified as variables when a class-level attribute with the same name exists.
Fixed false positive for ``invalid-name`` where module-level constants were incorrectly classified as variables when a class-level attribute with the same name exists.

(The reason is that we're going to change this to ``:ref: ìnvalid-name``` when we can handle it automatically in the changelog later, and this will print the (C0103) automatically, so less work later on.)

Copy link
Author

@joao-faria-dev joao-faria-dev Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Comments applied

@joao-faria-dev joao-faria-dev force-pushed the fix-c0103-module-class-name-conflict branch from 8f658a3 to 6459607 Compare November 6, 2025 19:48
@github-actions

This comment has been minimized.

@Pierre-Sassoulas
Copy link
Member

There's lot of changes from the primer which is worrying. Also the tests are not passing you can launch them with pytest locally, see https://pylint.readthedocs.io/en/stable/development_guide/contributor_guide/tests/launching_test.html#pytest

@Pierre-Sassoulas Pierre-Sassoulas modified the milestones: 4.0.3, 4.0.4 Nov 9, 2025
@joao-faria-dev joao-faria-dev force-pushed the fix-c0103-module-class-name-conflict branch 2 times, most recently from 23c90df to 284a794 Compare November 11, 2025 01:48
@jacobtylerwalls jacobtylerwalls self-requested a review November 11, 2025 22:21
Copy link
Member

@jacobtylerwalls jacobtylerwalls left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I checked a few of the primer changes, and they look good. Does anything look concerning to you?

if isinstance(a, (nodes.ClassDef, nodes.FunctionDef)):
if a.parent and a.parent.scope() == node_scope:
return True
elif a.scope() == node_scope:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think is is usually used for specific node comparisons.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still applies

@joao-faria-dev joao-faria-dev force-pushed the fix-c0103-module-class-name-conflict branch from 284a794 to dc44856 Compare November 17, 2025 20:15
Copy link
Member

@jacobtylerwalls jacobtylerwalls left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good!

…ames

- Add scope comparision to avoid module-level constants to be incorrectly
classified as variables when a class-level attribute with the same name exists

Closes pylint-dev#10719
@joao-faria-dev joao-faria-dev force-pushed the fix-c0103-module-class-name-conflict branch from dc44856 to 47b22a7 Compare November 19, 2025 19:06
@codecov
Copy link

codecov bot commented Nov 19, 2025

Codecov Report

❌ Patch coverage is 95.23810% with 1 line in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@4f0716a). Learn more about missing BASE report.
⚠️ Report is 25 commits behind head on main.

Files with missing lines Patch % Lines
pylint/checkers/utils.py 95.23% 1 Missing ⚠️

❌ Your patch check has failed because the patch coverage (95.23%) is below the target coverage (100.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main   #10723   +/-   ##
=======================================
  Coverage        ?   95.98%           
=======================================
  Files           ?      176           
  Lines           ?    19559           
  Branches        ?        0           
=======================================
  Hits            ?    18773           
  Misses          ?      786           
  Partials        ?        0           
Files with missing lines Coverage Δ
pylint/checkers/utils.py 95.94% <95.23%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link
Contributor

🤖 Effect of this PR on checked open source code: 🤖

Effect on ansible:
The following messages are now emitted:

  1. invalid-name:
    Constant name "current_worker" doesn't conform to UPPER_CASE naming style
    https://github.com/ansible/ansible/blob/76fb182b63a321aa513ee1c259eb39dd390e94c5/lib/ansible/executor/process/worker.py#L52
  2. invalid-name:
    Constant name "cur_id" doesn't conform to UPPER_CASE naming style
    https://github.com/ansible/ansible/blob/76fb182b63a321aa513ee1c259eb39dd390e94c5/lib/ansible/utils/vars.py#L39
  3. invalid-name:
    Constant name "_module_tracebacks_enabled_events" doesn't conform to UPPER_CASE naming style
    https://github.com/ansible/ansible/blob/76fb182b63a321aa513ee1c259eb39dd390e94c5/lib/ansible/module_utils/_internal/_traceback.py#L68
  4. invalid-name:
    Constant name "module" doesn't conform to UPPER_CASE naming style
    https://github.com/ansible/ansible/blob/76fb182b63a321aa513ee1c259eb39dd390e94c5/lib/ansible/modules/file.py#L244
  5. invalid-name:
    Constant name "apt_key_bin" doesn't conform to UPPER_CASE naming style
    https://github.com/ansible/ansible/blob/76fb182b63a321aa513ee1c259eb39dd390e94c5/lib/ansible/modules/apt_key.py#L181
  6. invalid-name:
    Constant name "gpg_bin" doesn't conform to UPPER_CASE naming style
    https://github.com/ansible/ansible/blob/76fb182b63a321aa513ee1c259eb39dd390e94c5/lib/ansible/modules/apt_key.py#L182
  7. invalid-name:
    Constant name "locale" doesn't conform to UPPER_CASE naming style
    https://github.com/ansible/ansible/blob/76fb182b63a321aa513ee1c259eb39dd390e94c5/lib/ansible/modules/apt_key.py#L183
  8. invalid-name:
    Constant name "job_path" doesn't conform to UPPER_CASE naming style
    https://github.com/ansible/ansible/blob/76fb182b63a321aa513ee1c259eb39dd390e94c5/lib/ansible/modules/async_wrapper.py#L29

The following messages are no longer emitted:

  1. invalid-name:
    Variable name "CLIARGS" doesn't conform to snake_case naming style
    https://github.com/ansible/ansible/blob/76fb182b63a321aa513ee1c259eb39dd390e94c5/lib/ansible/context.py#L25

Effect on django:
The following messages are now emitted:

  1. invalid-name:
    Constant name "_exception" doesn't conform to UPPER_CASE naming style
    https://github.com/django/django/blob/3c005b5f79bf6d71f3f4c3692ed670e1722b0fb6/django/utils/autoreload.py#L35
  2. invalid-name:
    Constant name "_default" doesn't conform to UPPER_CASE naming style
    https://github.com/django/django/blob/3c005b5f79bf6d71f3f4c3692ed670e1722b0fb6/django/utils/translation/trans_real.py#L29
  3. invalid-name:
    Constant name "_worker_id" doesn't conform to UPPER_CASE naming style
    https://github.com/django/django/blob/3c005b5f79bf6d71f3f4c3692ed670e1722b0fb6/django/test/runner.py#L430

The following messages are no longer emitted:

  1. invalid-name:
    Variable name "SITE_CACHE" doesn't conform to snake_case naming style
    https://github.com/django/django/blob/3c005b5f79bf6d71f3f4c3692ed670e1722b0fb6/django/contrib/sites/models.py#L9

Effect on pandas:
The following messages are now emitted:

  1. invalid-name:
    Constant name "_evaluate" doesn't conform to UPPER_CASE naming style
    https://github.com/pandas-dev/pandas/blob/2d73d629552cfc5c6ecc1a73f753f383fc7966c1/pandas/core/computation/expressions.py#L33
  2. invalid-name:
    Constant name "_where" doesn't conform to UPPER_CASE naming style
    https://github.com/pandas-dev/pandas/blob/2d73d629552cfc5c6ecc1a73f753f383fc7966c1/pandas/core/computation/expressions.py#L34
  3. invalid-name:
    Constant name "_is_scipy_sparse" doesn't conform to UPPER_CASE naming style
    https://github.com/pandas-dev/pandas/blob/2d73d629552cfc5c6ecc1a73f753f383fc7966c1/pandas/core/dtypes/common.py#L73

The following messages are no longer emitted:

  1. invalid-name:
    Variable name "_TEST_RESULT" doesn't conform to snake_case naming style
    https://github.com/pandas-dev/pandas/blob/2d73d629552cfc5c6ecc1a73f753f383fc7966c1/pandas/core/computation/expressions.py#L31

Effect on pytest:
The following messages are no longer emitted:

  1. invalid-name:
    Variable name "RUNNER_CLASS" doesn't conform to snake_case naming style
    https://github.com/pytest-dev/pytest/blob/bbb0c0778a0fce3afb456fa8850994a63320a996/src/_pytest/doctest.py#L65
  2. invalid-name:
    Variable name "CHECKER_CLASS" doesn't conform to snake_case naming style
    https://github.com/pytest-dev/pytest/blob/bbb0c0778a0fce3afb456fa8850994a63320a996/src/_pytest/doctest.py#L67

Effect on flask:
The following messages are now emitted:

  1. invalid-name:
    Constant name "_werkzeug_version" doesn't conform to UPPER_CASE naming style
    https://github.com/pallets/flask/blob/2579ce9f18e67ec3213c6eceb5240310ccd46af8/src/flask/testing.py#L97

Effect on poetry-core:
The following messages are now emitted:

  1. invalid-name:
    Constant name "_executable" doesn't conform to UPPER_CASE naming style
    https://github.com/python-poetry/poetry-core/blob/acc1bc9dda925ee47311c951e69d7993e81cae62/src/poetry/core/vcs/git.py#L147

Effect on sentry:
The following messages are now emitted:

  1. invalid-name:
    Constant name "_local_cache_generation" doesn't conform to UPPER_CASE naming style
    https://github.com/getsentry/sentry/blob/ec5ed207fd261a4f8f1e60ea59618b33f8f40b12/src/sentry/db/models/manager/base.py#L29
  2. invalid-name:
    Constant name "_local_cache_enabled" doesn't conform to UPPER_CASE naming style
    https://github.com/getsentry/sentry/blob/ec5ed207fd261a4f8f1e60ea59618b33f8f40b12/src/sentry/db/models/manager/base.py#L30
  3. invalid-name:
    Constant name "_global_regions" doesn't conform to UPPER_CASE naming style
    https://github.com/getsentry/sentry/blob/ec5ed207fd261a4f8f1e60ea59618b33f8f40b12/src/sentry/types/region.py#L203
  4. invalid-name:
    Constant name "rust_geoip" doesn't conform to UPPER_CASE naming style
    https://github.com/getsentry/sentry/blob/ec5ed207fd261a4f8f1e60ea59618b33f8f40b12/src/sentry/utils/geo.py#L17
  5. invalid-name:
    Constant name "outcomes_publisher" doesn't conform to UPPER_CASE naming style
    https://github.com/getsentry/sentry/blob/ec5ed207fd261a4f8f1e60ea59618b33f8f40b12/src/sentry/utils/outcomes.py#L159
  6. invalid-name:
    Constant name "billing_publisher" doesn't conform to UPPER_CASE naming style
    https://github.com/getsentry/sentry/blob/ec5ed207fd261a4f8f1e60ea59618b33f8f40b12/src/sentry/utils/outcomes.py#L160
  7. invalid-name:
    Constant name "_from_email_domain_cache" doesn't conform to UPPER_CASE naming style
    https://github.com/getsentry/sentry/blob/ec5ed207fd261a4f8f1e60ea59618b33f8f40b12/src/sentry/utils/email/address.py#L14
  8. invalid-name:
    Constant name "__installed" doesn't conform to UPPER_CASE naming style
    https://github.com/getsentry/sentry/blob/ec5ed207fd261a4f8f1e60ea59618b33f8f40b12/src/sentry/runner/settings.py#L136
  9. invalid-name:
    Constant name "_accountant_backend" doesn't conform to UPPER_CASE naming style
    https://github.com/getsentry/sentry/blob/ec5ed207fd261a4f8f1e60ea59618b33f8f40b12/src/sentry/usage_accountant/accountant.py#L21
  10. invalid-name:
    Constant name "_last_validation_log" doesn't conform to UPPER_CASE naming style
    https://github.com/getsentry/sentry/blob/ec5ed207fd261a4f8f1e60ea59618b33f8f40b12/src/sentry/buffer/redis.py#L36
  11. invalid-name:
    Constant name "__rrweb_id" doesn't conform to UPPER_CASE naming style
    https://github.com/getsentry/sentry/blob/ec5ed207fd261a4f8f1e60ea59618b33f8f40b12/src/sentry/replays/testutils.py#L471
  12. invalid-name:
    Constant name "sync_publisher" doesn't conform to UPPER_CASE naming style
    https://github.com/getsentry/sentry/blob/ec5ed207fd261a4f8f1e60ea59618b33f8f40b12/src/sentry/replays/lib/kafka.py#L59
  13. invalid-name:
    Constant name "async_publisher" doesn't conform to UPPER_CASE naming style
    https://github.com/getsentry/sentry/blob/ec5ed207fd261a4f8f1e60ea59618b33f8f40b12/src/sentry/replays/lib/kafka.py#L60

The following messages are no longer emitted:

  1. invalid-name:
    Variable name "_LOGIN_URL" doesn't conform to snake_case naming style
    https://github.com/getsentry/sentry/blob/ec5ed207fd261a4f8f1e60ea59618b33f8f40b12/src/sentry/utils/auth.py#L36
  2. invalid-name:
    Variable name "AUTOFIX_POST_RESPONSE" doesn't conform to snake_case naming style
    https://github.com/getsentry/sentry/blob/ec5ed207fd261a4f8f1e60ea59618b33f8f40b12/src/sentry/apidocs/examples/autofix_examples.py#L3
  3. invalid-name:
    Variable name "AUTOFIX_GET_RESPONSE" doesn't conform to snake_case naming style
    https://github.com/getsentry/sentry/blob/ec5ed207fd261a4f8f1e60ea59618b33f8f40b12/src/sentry/apidocs/examples/autofix_examples.py#L12
  4. invalid-name:
    Variable name "_CONCURRENT_RATE_LIMITER" doesn't conform to snake_case naming style
    https://github.com/getsentry/sentry/blob/ec5ed207fd261a4f8f1e60ea59618b33f8f40b12/src/sentry/ratelimits/utils.py#L40

Effect on home-assistant:
The following messages are no longer emitted:

  1. invalid-name:
    Variable name "CONTROLLER_MODES" doesn't conform to snake_case naming style
    https://github.com/home-assistant/core/blob/433712b407600ef40771d7fa371ebca2df96695c/homeassistant/components/knx/const.py#L170

Effect on coverage:
The following messages are no longer emitted:

  1. invalid-name:
    Variable name "CANONICAL_FILENAME_CACHE" doesn't conform to snake_case naming style
    https://github.com/nedbat/coveragepy/blob/fff5e59b28e0a4660a5e19975eb02aeffcb05a01/coverage/files.py#L26

Effect on pygame:
The following messages are now emitted:

  1. invalid-name:
    Constant name "_ft_init" doesn't conform to UPPER_CASE naming style
    https://github.com/pygame/pygame/blob/85fda3f719d437cf27106afae8c890e6b88ba5f5/src_py/fastevent.py#L13
  2. invalid-name:
    Constant name "is_init" doesn't conform to UPPER_CASE naming style
    https://github.com/pygame/pygame/blob/85fda3f719d437cf27106afae8c890e6b88ba5f5/src_py/sysfont.py#L39
  3. invalid-name:
    Constant name "_is_init" doesn't conform to UPPER_CASE naming style
    https://github.com/pygame/pygame/blob/85fda3f719d437cf27106afae8c890e6b88ba5f5/src_py/camera.py#L9
  4. invalid-name:
    Constant name "_wq" doesn't conform to UPPER_CASE naming style
    https://github.com/pygame/pygame/blob/85fda3f719d437cf27106afae8c890e6b88ba5f5/src_py/threads/__init__.py#L28
  5. invalid-name:
    Constant name "_use_workers" doesn't conform to UPPER_CASE naming style
    https://github.com/pygame/pygame/blob/85fda3f719d437cf27106afae8c890e6b88ba5f5/src_py/threads/__init__.py#L31

This comment was generated for commit 47b22a7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pylint C0103 (invalid-name) contradiction when module level names matches will class level names

3 participants