basedmypy icon indicating copy to clipboard operation
basedmypy copied to clipboard

Support asymmetric properties

Open sterliakov opened this issue 2 years ago • 1 comments

Currently asymmetric properties are not supported by mypy. It mypy this is considered a bug with high priority (issue).

basemypy decided to go this way further and assume that properties are symmetric even without annotations on setter. To quote docs:

The types in overload implementations (including properties) can be inferred:

class A:
   @property
   def foo(self) -> int: ...
   @foo.setter
   def foo(self, value): ...  # no need for annotations

I suggest to think about this solution and consider allowing asymmetric properties, because cases like below with value normalization are quire common.

Code sample:

from collections.abc import Iterable


class A:
    def __init__(self):
        self._foo: list[str] = []
        
    @property
    def foo(self) -> list[str]:
        return self._foo
    
    @foo.setter
    def foo(self, __val: Iterable[str]):
        self._foo = list(__val)
        

a = A()
reveal_type(a.foo)  # N: Revealed type is "list[str]"
a.foo = ('a',)  # E: Incompatible types in assignment (expression has type "(str,)", variable has type "list[str]")  [assignment]

sterliakov avatar Jul 20 '23 00:07 sterliakov

I think that asymmetric properties sound very based and I have personally voted for that issue. I'd totally add support for them if that's what the community is asking for.

The current functionality of basedmypy is that the types on setters and deleters are inferred from the type of the getter. This is not enforced and is only a convenience feature, you are free to override the inference by manually specifying the annotations:

class A:
    _foo = 0
    @property
    def foo(self) -> int:
        return self._foo
    @foo.setter
    def(self, value: object):
        self._foo = value if isinstance(value, int) else 0

Obviously you will currently see the same error as you would with mypy.

KotlinIsland avatar Jul 20 '23 08:07 KotlinIsland