File tree Expand file tree Collapse file tree 3 files changed +58
-0
lines changed Expand file tree Collapse file tree 3 files changed +58
-0
lines changed Original file line number Diff line number Diff line change @@ -187,6 +187,11 @@ def visit_callable_type(self, t: CallableType) -> ProperType:
187
187
if is_equivalent (t , self .s ):
188
188
return combine_similar_callables (t , self .s )
189
189
result = join_similar_callables (t , self .s )
190
+ # We set the from_type_type flag to suppress error when a collection of
191
+ # concrete class objects gets inferred as their common abstract superclass.
192
+ if not ((t .is_type_obj () and t .type_object ().is_abstract ) or
193
+ (self .s .is_type_obj () and self .s .type_object ().is_abstract )):
194
+ result .from_type_type = True
190
195
if any (isinstance (tp , (NoneType , UninhabitedType ))
191
196
for tp in get_proper_types (result .arg_types )):
192
197
# We don't want to return unusable Callable, attempt fallback instead.
Original file line number Diff line number Diff line change @@ -533,6 +533,11 @@ def visit_callable_type(self, t: CallableType) -> ProperType:
533
533
if is_equivalent (t , self .s ):
534
534
return combine_similar_callables (t , self .s )
535
535
result = meet_similar_callables (t , self .s )
536
+ # We set the from_type_type flag to suppress error when a collection of
537
+ # concrete class objects gets inferred as their common abstract superclass.
538
+ if not ((t .is_type_obj () and t .type_object ().is_abstract ) or
539
+ (self .s .is_type_obj () and self .s .type_object ().is_abstract )):
540
+ result .from_type_type = True
536
541
if isinstance (get_proper_type (result .ret_type ), UninhabitedType ):
537
542
# Return a plain None or <uninhabited> instead of a weird function.
538
543
return self .default (self .s )
Original file line number Diff line number Diff line change @@ -951,3 +951,51 @@ default = Config({'cannot': 'modify'}) # OK
951
951
default[1] = 2 # E: Unsupported target for indexed assignment
952
952
[builtins fixtures/dict.pyi]
953
953
[typing fixtures/typing-full.pyi]
954
+
955
+ [case testSubclassOfABCFromDictionary]
956
+ from abc import abstractmethod, ABCMeta
957
+
958
+ class MyAbstractType(metaclass=ABCMeta):
959
+ @abstractmethod
960
+ def do(self): pass
961
+
962
+ class MyConcreteA(MyAbstractType):
963
+ def do(self):
964
+ print('A')
965
+
966
+ class MyConcreteB(MyAbstractType):
967
+ def do(self):
968
+ print('B')
969
+
970
+ class MyAbstractA(MyAbstractType):
971
+ @abstractmethod
972
+ def do(self): pass
973
+
974
+ class MyAbstractB(MyAbstractType):
975
+ @abstractmethod
976
+ def do(self): pass
977
+
978
+ my_concrete_types = {
979
+ 'A': MyConcreteA,
980
+ 'B': MyConcreteB,
981
+ }
982
+
983
+ my_abstract_types = {
984
+ 'A': MyAbstractA,
985
+ 'B': MyAbstractB,
986
+ }
987
+
988
+ reveal_type(my_concrete_types) # N: Revealed type is 'builtins.dict[builtins.str*, def () -> __main__.MyAbstractType]'
989
+ reveal_type(my_abstract_types) # N: Revealed type is 'builtins.dict[builtins.str*, def () -> __main__.MyAbstractType]'
990
+
991
+ a = my_concrete_types['A']()
992
+ a.do()
993
+ b = my_concrete_types['B']()
994
+ b.do()
995
+
996
+ c = my_abstract_types['A']() # E: Cannot instantiate abstract class 'MyAbstractType' with abstract attribute 'do'
997
+ c.do()
998
+ d = my_abstract_types['B']() # E: Cannot instantiate abstract class 'MyAbstractType' with abstract attribute 'do'
999
+ d.do()
1000
+
1001
+ [builtins fixtures/dict.pyi]
You can’t perform that action at this time.
0 commit comments