Skip to content

Commit 8ca2a14

Browse files
committed
Support @deprecated() on overloaded __get__ for generic descriptors
1 parent 9ff9946 commit 8ca2a14

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

mypy/checker.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -7714,7 +7714,12 @@ def warn_deprecated(self, node: Node | None, context: Context) -> None:
77147714
warn(deprecated, context, code=codes.DEPRECATED)
77157715

77167716
def warn_deprecated_overload_item(
7717-
self, node: Node | None, context: Context, *, target: Type, selftype: Type | None = None
7717+
self,
7718+
node: Node | None,
7719+
context: Context,
7720+
*,
7721+
target: Type,
7722+
selftype: Instance | None = None,
77187723
) -> None:
77197724
"""Warn if the overload item corresponding to the given callable is deprecated."""
77207725
target = get_proper_type(target)
@@ -7724,7 +7729,9 @@ def warn_deprecated_overload_item(
77247729
candidate := item.func.type, CallableType
77257730
):
77267731
if selftype is not None:
7727-
candidate = bind_self(candidate, selftype)
7732+
candidate = bind_self(
7733+
expand_type_by_instance(candidate, selftype), selftype
7734+
)
77287735
if candidate == target:
77297736
self.warn_deprecated(item.func, context)
77307737

test-data/unit/check-deprecated.test

+15-1
Original file line numberDiff line numberDiff line change
@@ -506,9 +506,11 @@ C().g = "x" # E: function __main__.C.g is deprecated: use g2 instead \
506506
[case testDeprecatedDescriptor]
507507
# flags: --enable-error-code=deprecated
508508

509-
from typing import Any, Optional, Union
509+
from typing import Any, Generic, Optional, TypeVar, Union
510510
from typing_extensions import deprecated, overload
511511

512+
T = TypeVar("T")
513+
512514
@deprecated("use E1 instead")
513515
class D1:
514516
def __get__(self, obj: Optional[C], objtype: Any) -> Union[D1, int]: ...
@@ -536,10 +538,19 @@ class D3:
536538
def __set__(self, obj: C, value: str) -> None: ...
537539
def __set__(self, obj: C, value: Union[int, str]) -> None: ...
538540

541+
class D4(Generic[T]):
542+
@overload
543+
def __get__(self, obj: None, objtype: Any) -> T: ...
544+
@overload
545+
@deprecated("deprecated instance access")
546+
def __get__(self, obj: C, objtype: Any) -> T: ...
547+
def __get__(self, obj: Optional[C], objtype: Any) -> T: ...
548+
539549
class C:
540550
d1 = D1() # E: class __main__.D1 is deprecated: use E1 instead
541551
d2 = D2()
542552
d3 = D3()
553+
d4 = D4[int]()
543554

544555
c: C
545556
C.d1
@@ -554,6 +565,9 @@ C.d3 # E: overload def (self: __main__.D3, obj: None, objtype: Any) -> __main__
554565
c.d3 # E: overload def (self: __main__.D3, obj: __main__.C, objtype: Any) -> builtins.int of function __main__.D3.__get__ is deprecated: use E3.__get__ instead
555566
c.d3 = 1
556567
c.d3 = "x" # E: overload def (self: __main__.D3, obj: __main__.C, value: builtins.str) of function __main__.D3.__set__ is deprecated: use E3.__set__ instead
568+
569+
C.d4
570+
c.d4 # E: overload def (self: __main__.D4[T`1], obj: __main__.C, objtype: Any) -> T`1 of function __main__.D4.__get__ is deprecated: deprecated instance access
557571
[builtins fixtures/property.pyi]
558572

559573

0 commit comments

Comments
 (0)