Skip to content

Commit baf5528

Browse files
committed
Only add note if we see .setter or .deleter
1 parent 6ab9453 commit baf5528

File tree

2 files changed

+112
-1
lines changed

2 files changed

+112
-1
lines changed

mypy/semanal.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7159,12 +7159,20 @@ def already_defined(
71597159
)
71607160

71617161
if (
7162-
isinstance(ctx, (OverloadedFuncDef, Decorator))
7162+
self.maybe_property_setter_or_deleter(ctx)
71637163
and node is not None
71647164
and self.maybe_property_definition(node)
71657165
):
71667166
self.note("Property setter and deleter must be adjacent to the getter.", ctx)
71677167

7168+
def maybe_property_setter_or_deleter(self, node: SymbolNode) -> bool:
7169+
if isinstance(node, OverloadedFuncDef) and node.unanalyzed_items:
7170+
node = node.unanalyzed_items[0]
7171+
return isinstance(node, Decorator) and any(
7172+
isinstance(dec, MemberExpr) and dec.name in ("setter", "deleter")
7173+
for dec in node.decorators
7174+
)
7175+
71687176
def maybe_property_definition(self, node: SymbolNode) -> bool:
71697177
if isinstance(node, Decorator) and node.func.is_property:
71707178
return True

test-data/unit/check-classes.test

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1919,6 +1919,109 @@ class E:
19191919
def val(self): ...
19201920

19211921
reveal_type(val) # N: Revealed type is "builtins.property"
1922+
1923+
class F:
1924+
@property
1925+
def val(self): ...
1926+
1927+
reveal_type(val) # N: Revealed type is "builtins.property"
1928+
def _other(self) -> None: ...
1929+
1930+
@val.setter # E: Name "val" already defined on line 78 \
1931+
# N: Property setter and deleter must be adjacent to the getter.
1932+
def val(self, val): ...
1933+
1934+
reveal_type(val) # N: Revealed type is "builtins.property"
1935+
def _other2(self) -> None: ...
1936+
1937+
@val.deleter # E: Name "val" already defined on line 78 \
1938+
# N: Property setter and deleter must be adjacent to the getter.
1939+
def val(self): ...
1940+
1941+
reveal_type(val) # N: Revealed type is "builtins.property"
1942+
[builtins fixtures/property-full.pyi]
1943+
1944+
[case testPropertyRedefinition]
1945+
class A1:
1946+
@property
1947+
def fn(self) -> None: ...
1948+
1949+
@property # E: Only supported top decorator is @fn.setter
1950+
def fn(self) -> None: ...
1951+
1952+
class B1:
1953+
@property
1954+
def fn(self) -> None: ...
1955+
1956+
def foo(self) -> None: ...
1957+
1958+
@property # E: Name "fn" already defined on line 9
1959+
def fn(self) -> None: ...
1960+
1961+
class A2:
1962+
@property
1963+
def fn(self) -> None: ...
1964+
@fn.setter
1965+
def fn(self, _: None) -> None: ...
1966+
1967+
@property # E: Only supported top decorator is @fn.setter
1968+
def fn(self) -> None: ...
1969+
1970+
class B2:
1971+
@property
1972+
def fn(self) -> None: ...
1973+
@fn.setter
1974+
def fn(self, _: None) -> None: ...
1975+
1976+
def foo(self) -> None: ...
1977+
1978+
@property # E: Name "fn" already defined on line 27
1979+
def fn(self) -> None: ...
1980+
1981+
class A3:
1982+
@property
1983+
def fn(self) -> None: ...
1984+
@fn.setter
1985+
def fn(self, _: None) -> None: ...
1986+
1987+
@property # E: Only supported top decorator is @fn.setter
1988+
def fn(self) -> None: ...
1989+
@fn.setter
1990+
def fn(self, _: None) -> None: ...
1991+
1992+
class B3:
1993+
@property
1994+
def fn(self) -> None: ...
1995+
@fn.setter
1996+
def fn(self, _: None) -> None: ...
1997+
1998+
def foo(self) -> None: ...
1999+
2000+
@property # E: Name "fn" already defined on line 49
2001+
def fn(self) -> None: ...
2002+
@fn.setter
2003+
def fn(self, _: None) -> None: ...
2004+
2005+
class A4:
2006+
@property
2007+
def fn(self) -> None: ...
2008+
@fn.setter
2009+
def fn(self, _: None) -> None: ...
2010+
2011+
@fn.setter
2012+
def fn(self, _: None) -> None: ...
2013+
2014+
class B4:
2015+
@property
2016+
def fn(self) -> None: ...
2017+
@fn.setter
2018+
def fn(self, _: None) -> None: ...
2019+
2020+
def foo(self) -> None: ...
2021+
2022+
@fn.setter # E: Name "fn" already defined on line 71 \
2023+
# N: Property setter and deleter must be adjacent to the getter.
2024+
def fn(self, _: None) -> None: ...
19222025
[builtins fixtures/property-full.pyi]
19232026

19242027
-- Descriptors

0 commit comments

Comments
 (0)