Skip to content

Commit 3807423

Browse files
Make untyped decorator its own code (#19911)
Since this apparently comes up a lot, it shouldn't just be misc (it is, however, a subcode of misc, at least at the moment, for extra backwards compatibility). Fixes #19148 I didn't add any tests for this and it seems like our old tests don't have codes enabled because they didn't have to be changed. I did add documentation for this, as required by the relevant test. --------- Co-authored-by: A5rocks <[email protected]>
1 parent 6dc4698 commit 3807423

File tree

4 files changed

+47
-1
lines changed

4 files changed

+47
-1
lines changed

docs/source/error_code_list2.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,3 +676,26 @@ Example:
676676
print("red")
677677
case _:
678678
print("other")
679+
680+
.. _code-untyped-decorator:
681+
682+
Error if an untyped decorator makes a typed function effectively untyped [untyped-decorator]
683+
--------------------------------------------------------------------------------------------
684+
685+
If enabled with :option:`--disallow-untyped-decorators <mypy --disallow-untyped-decorators>`
686+
mypy generates an error if a typed function is wrapped by an untyped decorator
687+
(as this would effectively remove the benefits of typing the function).
688+
689+
Example:
690+
691+
.. code-block:: python
692+
693+
def printing_decorator(func):
694+
def wrapper(*args, **kwds):
695+
print("Calling", func)
696+
return func(*args, **kwds)
697+
return wrapper
698+
# A decorated function.
699+
@printing_decorator # E: Untyped decorator makes function "add_forty_two" untyped [untyped-decorator]
700+
def add_forty_two(value: int) -> int:
701+
return value + 42

mypy/errorcodes.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,10 @@ def __hash__(self) -> int:
302302
sub_code_of=MISC,
303303
)
304304

305+
UNTYPED_DECORATOR: Final = ErrorCode(
306+
"untyped-decorator", "Error if an untyped decorator makes a typed function untyped", "General"
307+
)
308+
305309
NARROWED_TYPE_NOT_SUBTYPE: Final = ErrorCode(
306310
"narrowed-type-not-subtype",
307311
"Warn if a TypeIs function's narrowed type is not a subtype of the original type",

mypy/messages.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2008,7 +2008,11 @@ def untyped_decorated_function(self, typ: Type, context: Context) -> None:
20082008
)
20092009

20102010
def typed_function_untyped_decorator(self, func_name: str, context: Context) -> None:
2011-
self.fail(f'Untyped decorator makes function "{func_name}" untyped', context)
2011+
self.fail(
2012+
f'Untyped decorator makes function "{func_name}" untyped',
2013+
context,
2014+
code=codes.UNTYPED_DECORATOR,
2015+
)
20122016

20132017
def bad_proto_variance(
20142018
self, actual: int, tvar_name: str, expected: int, context: Context

test-data/unit/check-errorcodes.test

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,21 @@ def f() -> None:
394394
def g():
395395
pass
396396

397+
[case testErrorCodeUntypedDecorator]
398+
# flags: --disallow-untyped-decorators --warn-unused-ignores
399+
def d(f): return f
400+
401+
@d # E: Untyped decorator makes function "x" untyped [untyped-decorator]
402+
def x() -> int: return 1
403+
@d # type: ignore
404+
def y() -> int: return 2
405+
@d # type: ignore[untyped-decorator]
406+
def best() -> int: return 3
407+
@d # type: ignore[misc] # E: Unused "type: ignore" comment [unused-ignore] \
408+
# E: Untyped decorator makes function "z" untyped [untyped-decorator] \
409+
# N: Error code "untyped-decorator" not covered by "type: ignore" comment
410+
def z() -> int: return 4
411+
397412
[case testErrorCodeIndexing]
398413
from typing import Dict
399414
x: Dict[int, int]

0 commit comments

Comments
 (0)