Skip to content

Commit 548d17c

Browse files
committed
Capture the behavior of descriptors that don't define __get__
1 parent 2c0ca37 commit 548d17c

File tree

2 files changed

+16
-14
lines changed

2 files changed

+16
-14
lines changed

mypy/checkmember.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -209,10 +209,6 @@ def analyze_member_var_access(name: str, itype: Instance, info: TypeInfo,
209209
return dunder_set_type.arg_types[1]
210210
else:
211211
msg.fail("Can't set a data descriptor with no __set__ method", node)
212-
else:
213-
# TODO: Capture setting a non-data descriptor to infer types
214-
# later
215-
return AnyType()
216212
else:
217213
# this is a descriptor, use the output type of the __get__ method
218214
if dunder_get:
@@ -227,12 +223,6 @@ def analyze_member_var_access(name: str, itype: Instance, info: TypeInfo,
227223
return dunder_get_type.ret_type
228224
else:
229225
return AnyType()
230-
else:
231-
# TODO: Per the docs: "If [a descriptor] does not define __get__(),
232-
# then accessing the attribute will return the descriptor object
233-
# itself unless there is a value in the object’s instance dictionary".
234-
# Can we actually capture that during type inference?
235-
return AnyType()
236226

237227
return analyze_var(name, v, itype, info, node, is_lvalue, msg, not_ready_callback)
238228
elif isinstance(v, FuncDef):

test-data/unit/check-classes.test

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -898,8 +898,6 @@ a.f.x # E: "int" has no attribute "x"
898898

899899

900900
[case testAccessingNonDataDescriptor]
901-
import typing
902-
903901
class D():
904902
def __get__(self, instance: Any, owner: Any) -> str:
905903
return 'some string'
@@ -911,8 +909,6 @@ a = A() # type: A
911909
reveal_type(a.f) # E: Revealed type is 'builtins.str'
912910

913911
[case testSettingDataDescriptor]
914-
import typing
915-
916912
class D():
917913
def __get__(self, instance: Any, owner: Any) -> str:
918914
return 'some string'
@@ -927,6 +923,22 @@ a = A() # type: A
927923
a.f = ''
928924
a.f = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "str")
929925

926+
[case testReadingDescriptorWithoutDunderGet]
927+
from typing import Union
928+
929+
class D():
930+
def __set__(self, instance: Any, value: str) -> None:
931+
pass
932+
933+
class A:
934+
f = D() # type: Union[D, str]
935+
936+
def __init__(self):
937+
self.f = 'some string' # type: str
938+
939+
a = A() # type: A
940+
reveal_type(a.f) # E: Revealed type is 'Union[__main__.D, builtins.str]'
941+
930942

931943
-- Multiple inheritance, non-object built-in class as base
932944
-- -------------------------------------------------------

0 commit comments

Comments
 (0)