Skip to content

Commit dfab362

Browse files
Added [prop-decorator] code for unsupported property decorators (#14461) (#16571)
Using a decorator before a @Property now results in the narrower `prop-decorator` code, which is a subcode of `misc` for backward compatibility. I would have preferred to add a more general Unsupported error code and have this be a subcode of that, but this has to be a subcode of misc for backward compatibility. Fixes #14461
1 parent 3b97e6e commit dfab362

File tree

4 files changed

+40
-3
lines changed

4 files changed

+40
-3
lines changed

docs/source/error_code_list.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,29 @@ annotations in an unchecked function:
11711171
Note that mypy will still exit with return code ``0``, since such behaviour is
11721172
specified by :pep:`484`.
11731173

1174+
.. _code-prop-decorator:
1175+
1176+
Decorator preceding property not supported [prop-decorator]
1177+
-----------------------------------------------------------
1178+
1179+
Mypy does not yet support analysis of decorators that precede the property
1180+
decorator. If the decorator does not preserve the declared type of the property,
1181+
mypy will not infer the correct type for the declaration. If the decorator cannot
1182+
be moved after the ``@property`` decorator, then you must use a type ignore
1183+
comment:
1184+
1185+
.. code-block:: python
1186+
1187+
class MyClass
1188+
@special # type: ignore[prop-decorator]
1189+
@property
1190+
def magic(self) -> str:
1191+
return "xyzzy"
1192+
1193+
.. note::
1194+
1195+
For backward compatibility, this error code is a subcode of the generic ``[misc]`` code.
1196+
11741197
.. _code-syntax:
11751198

11761199
Report syntax errors [syntax]

mypy/errorcodes.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,6 @@ def __hash__(self) -> int:
262262
default_enabled=False,
263263
)
264264

265-
266265
# Syntax errors are often blocking.
267266
SYNTAX: Final[ErrorCode] = ErrorCode("syntax", "Report syntax errors", "General")
268267

@@ -281,6 +280,13 @@ def __hash__(self) -> int:
281280
sub_code_of=MISC,
282281
)
283282

283+
PROPERTY_DECORATOR = ErrorCode(
284+
"prop-decorator",
285+
"Decorators on top of @property are not supported",
286+
"General",
287+
sub_code_of=MISC,
288+
)
289+
284290
NARROWED_TYPE_NOT_SUBTYPE: Final[ErrorCode] = ErrorCode(
285291
"narrowed-type-not-subtype",
286292
"Warn if a TypeIs function's narrowed type is not a subtype of the original type",

mypy/semanal.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656

5757
from mypy import errorcodes as codes, message_registry
5858
from mypy.constant_fold import constant_fold_expr
59-
from mypy.errorcodes import ErrorCode
59+
from mypy.errorcodes import PROPERTY_DECORATOR, ErrorCode
6060
from mypy.errors import Errors, report_internal_error
6161
from mypy.exprtotype import TypeTranslationError, expr_to_unanalyzed_type
6262
from mypy.messages import (
@@ -1620,7 +1620,9 @@ def visit_decorator(self, dec: Decorator) -> None:
16201620
if not no_type_check and self.recurse_into_functions:
16211621
dec.func.accept(self)
16221622
if could_be_decorated_property and dec.decorators and dec.var.is_property:
1623-
self.fail("Decorators on top of @property are not supported", dec)
1623+
self.fail(
1624+
"Decorators on top of @property are not supported", dec, code=PROPERTY_DECORATOR
1625+
)
16241626
if (dec.func.is_static or dec.func.is_class) and dec.var.is_property:
16251627
self.fail("Only instance methods can be decorated with @property", dec)
16261628
if dec.func.abstract_status == IS_ABSTRACT and dec.func.is_final:

test-data/unit/semanal-errors.test

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,6 +1241,12 @@ class A:
12411241
@property # OK
12421242
@dec
12431243
def g(self) -> int: pass
1244+
@dec # type: ignore[misc]
1245+
@property
1246+
def h(self) -> int: pass
1247+
@dec # type: ignore[prop-decorator]
1248+
@property
1249+
def i(self) -> int: pass
12441250
[builtins fixtures/property.pyi]
12451251
[out]
12461252

0 commit comments

Comments
 (0)