iiNitori
iiNitori

Reputation: 71

PyCharm say "Property can not be read" on valid code

Let's look at the following code:

import typing

def make_getter(field: str) -> typing.Callable[['A'], int]:
    def getter(self: 'A') -> int:
        return int(self.dict[field])
    return getter

def make_setter(field: str) -> typing.Callable[['A', int], None]:
    def setter(self: 'A', value: int):
        self.dict[field] = str(value)
    return setter

class A:
    def __init__(self, d: dict):
        super().__init__()
        self.dict = d

    get_x = make_getter('foo')
    set_x = make_setter('foo')
    x = property(get_x, set_x)

    def get_y(self) -> int:
        return int(self.dict['bar'])
    def set_y(self, value: int):
        self.dict['bar'] = str(value)
    y = property(get_y, set_y)

I defined 2 properties: x and y. Both should work fine w/o any problems, both should have the same behavior. Next, following code:

a = A(dict())
a.x = 10
print(a.x)
a.y = 20
print(a.y)

PyCharm editor it says: "Property can not be read" on a.x. But this code executed well w/o any problems.

The first thought was PyCharm incorrectly inferring types. But look at this short video I recorded. I can't see any problems with types.

Also:

print(repr(a.get_x), repr(a.get_y))
print(repr(A.get_x), repr(A.get_y))
print(repr(A.x), repr(A.y))

It's output:

<bound method make_getter.<locals>.getter of <__main__.A object at 0x7f7d25145f28>> <bound method A.get_y of <__main__.A object at 0x7f7d25145f28>>
<function make_getter.<locals>.getter at 0x7f7d25132e18> <function A.get_y at 0x7f7d25132f28>
<property object at 0x7f7d25143c78> <property object at 0x7f7d25143cc8>

... so x and y almost equivalent.

Why PyCharm says that? I did something wrong or it's kind of bug? How to fix it (w/o disabling this type of warning)?

Upvotes: 5

Views: 1354

Answers (4)

jeffknupp
jeffknupp

Reputation: 6284

I'm not sure why PyCharm requires this, but explicitly giving the return type of __init__ made the warnings go away:

def __init__(self, d: dict) -> object:

Upvotes: 1

A. J. Parr
A. J. Parr

Reputation: 8026

I was seeing a similar warning in Pycharm, what I did was add a type hint for the return value of the getter method and it stopped providing the warning.

This sort of code resulted in a warning when using Example().my_property

class Example(object):

    def get_my_property(self):
        return self.something and self.something.something_else

    my_property = property(get_my_property)

This sort of code does not result in the warning for me

class Example(object):

    def get_my_property(self) -> bool:
        return self.something and self.something.something_else

    my_property = property(get_my_property)

Upvotes: 0

Just run into the same issue. What is interesting, this will work properly:

class InlineProperties:
  value = 5

  a = property(lambda self: self.value)


print(InlineProperties().a)
# prints out 5

Somehow, this is the only way PyCharm knows that this method with self argument is a proper function that will be a property. No idea why. Also, that works only for getters.

Upvotes: 0

akshayc11
akshayc11

Reputation: 575

Setting it to __init__(self, d: dict) -> None seems to work now.

Upvotes: 2

Related Questions