Skip to content

False not-an-iterable on subclasses of functools.cached_property #10377

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
mharding-hpe opened this issue May 12, 2025 · 3 comments · Fixed by pylint-dev/astroid#2735
Closed
Labels
False Positive 🦟 A message is emitted but nothing is wrong with the code Needs astroid update Needs an astroid update (probably a release too) before being mergable

Comments

@mharding-hpe
Copy link

mharding-hpe commented May 12, 2025

Bug description

# pylint: disable=missing-module-docstring,missing-class-docstring,invalid-name,too-few-public-methods,missing-function-docstring

from typing import reveal_type, NoReturn
from functools import cached_property

class cached_property_readonly[T](cached_property[T]):
    def __set__(self, instance: object, val: T) -> NoReturn:
        raise AttributeError("BAD")


class ice_weasels:
    @cached_property
    def harf(self) -> list[int]:
        return [1, 2, 3]

    @cached_property_readonly
    def blah(self) -> list[int]:
        return [1, 2, 3]


d = ice_weasels()
reveal_type(d.harf) # mypy reports list[int]
reveal_type(d.blah) # mypy reports list[int]
for _ in d.harf: # No complaints from mypy or pylint
    pass
for _ in d.blah: # No complaints from mypy, but pylint gives not-an-iterable
    pass

# If the cached_property_readonly class is not Generic over T and inheriting from
# cached_property[T], then mypy reports the revealed type of blah as Any.

Configuration

Command used

pylint test.py

Pylint output

************* Module test
test.py:26:9: E1133: Non-iterable value d.blah is used in an iterating context (not-an-iterable)

Expected behavior

No errors

Pylint version

pylint 3.3.7
astroid 3.3.10
Python 3.12.9 (main, Mar 18 2025, 03:28:39) [GCC 12.2.0]

(but I have reproduced on Python 3.10 and 3.13 as well)

OS / Environment

docker.io/python:3.12 x86_64 image

https://mypy-play.net/?mypy=latest&python=3.12&gist=00a0d22bec726e12655bc2ea85c8de5d

Additional dependencies

@mharding-hpe mharding-hpe added the Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling label May 12, 2025
@mharding-hpe
Copy link
Author

I should mention that the problem actually reproduces even if I leave the body of the cached_property_readonly class empty -- it is not the __set__ method definition which introduces the problem. Adding that method was my original motivation for making the class, but this pylint issue happens even without that present.

@mharding-hpe
Copy link
Author

I wonder if this block needs to be updated to include cached_property, because I notice that cached_property is not a subclass of property.

@mharding-hpe
Copy link
Author

mharding-hpe commented May 12, 2025

I realize I can work around this by running pylint with --init-hook="import astroid.bases; astroid.bases.POSSIBLE_PROPERTIES.add('cached_property_readonly')", but it seems that should only be necessary for property-like classes that can't be inferred because they don't directly inherit from core Python properties (like property or cached_property)

@Pierre-Sassoulas Pierre-Sassoulas added False Positive 🦟 A message is emitted but nothing is wrong with the code Needs astroid update Needs an astroid update (probably a release too) before being mergable and removed Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling labels May 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
False Positive 🦟 A message is emitted but nothing is wrong with the code Needs astroid update Needs an astroid update (probably a release too) before being mergable
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants