Skip to content

Commit

Permalink
Added [prop-decorator] code for unsupported property decorators (#14461
Browse files Browse the repository at this point in the history
…) (#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
  • Loading branch information
analog-cbarber committed May 18, 2024
1 parent 3b97e6e commit dfab362
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 3 deletions.
23 changes: 23 additions & 0 deletions docs/source/error_code_list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1171,6 +1171,29 @@ annotations in an unchecked function:
Note that mypy will still exit with return code ``0``, since such behaviour is
specified by :pep:`484`.

.. _code-prop-decorator:

Decorator preceding property not supported [prop-decorator]
-----------------------------------------------------------

Mypy does not yet support analysis of decorators that precede the property
decorator. If the decorator does not preserve the declared type of the property,
mypy will not infer the correct type for the declaration. If the decorator cannot
be moved after the ``@property`` decorator, then you must use a type ignore
comment:

.. code-block:: python
class MyClass
@special # type: ignore[prop-decorator]
@property
def magic(self) -> str:
return "xyzzy"
.. note::

For backward compatibility, this error code is a subcode of the generic ``[misc]`` code.

.. _code-syntax:

Report syntax errors [syntax]
Expand Down
8 changes: 7 additions & 1 deletion mypy/errorcodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,6 @@ def __hash__(self) -> int:
default_enabled=False,
)


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

Expand All @@ -281,6 +280,13 @@ def __hash__(self) -> int:
sub_code_of=MISC,
)

PROPERTY_DECORATOR = ErrorCode(
"prop-decorator",
"Decorators on top of @property are not supported",
"General",
sub_code_of=MISC,
)

NARROWED_TYPE_NOT_SUBTYPE: Final[ErrorCode] = ErrorCode(
"narrowed-type-not-subtype",
"Warn if a TypeIs function's narrowed type is not a subtype of the original type",
Expand Down
6 changes: 4 additions & 2 deletions mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@

from mypy import errorcodes as codes, message_registry
from mypy.constant_fold import constant_fold_expr
from mypy.errorcodes import ErrorCode
from mypy.errorcodes import PROPERTY_DECORATOR, ErrorCode
from mypy.errors import Errors, report_internal_error
from mypy.exprtotype import TypeTranslationError, expr_to_unanalyzed_type
from mypy.messages import (
Expand Down Expand Up @@ -1620,7 +1620,9 @@ def visit_decorator(self, dec: Decorator) -> None:
if not no_type_check and self.recurse_into_functions:
dec.func.accept(self)
if could_be_decorated_property and dec.decorators and dec.var.is_property:
self.fail("Decorators on top of @property are not supported", dec)
self.fail(
"Decorators on top of @property are not supported", dec, code=PROPERTY_DECORATOR
)
if (dec.func.is_static or dec.func.is_class) and dec.var.is_property:
self.fail("Only instance methods can be decorated with @property", dec)
if dec.func.abstract_status == IS_ABSTRACT and dec.func.is_final:
Expand Down
6 changes: 6 additions & 0 deletions test-data/unit/semanal-errors.test
Original file line number Diff line number Diff line change
Expand Up @@ -1241,6 +1241,12 @@ class A:
@property # OK
@dec
def g(self) -> int: pass
@dec # type: ignore[misc]
@property
def h(self) -> int: pass
@dec # type: ignore[prop-decorator]
@property
def i(self) -> int: pass
[builtins fixtures/property.pyi]
[out]

Expand Down

0 comments on commit dfab362

Please sign in to comment.