@@ -867,6 +867,82 @@ class B(A):
867867 assert inferred [0 ] is Uninferable
868868
869869
870+ def test_isinstance_multiple_inheritance ():
871+ """Test constraint for an object that inherits from more than one parent class."""
872+ n1 , n2 , n3 = builder .extract_node (
873+ """
874+ class A:
875+ pass
876+
877+ class B:
878+ pass
879+
880+ class C(A, B):
881+ pass
882+
883+ x = C()
884+
885+ if isinstance(x, C):
886+ x #@
887+
888+ if isinstance(x, A):
889+ x #@
890+
891+ if isinstance(x, B):
892+ x #@
893+ """
894+ )
895+
896+ for node in (n1 , n2 , n3 ):
897+ inferred = node .inferred ()
898+ assert len (inferred ) == 1
899+ assert isinstance (inferred [0 ], Instance )
900+ assert isinstance (inferred [0 ]._proxied , nodes .ClassDef )
901+ assert inferred [0 ].name == "C"
902+
903+
904+ def test_isinstance_diamond_inheritance ():
905+ """Test constraint for an object that inherits from parent classes
906+ in diamond inheritance.
907+ """
908+ n1 , n2 , n3 , n4 = builder .extract_node (
909+ """
910+ class A():
911+ pass
912+
913+ class B(A):
914+ pass
915+
916+ class C(A):
917+ pass
918+
919+ class D(B, C):
920+ pass
921+
922+ x = D()
923+
924+ if isinstance(x, D):
925+ x #@
926+
927+ if isinstance(x, B):
928+ x #@
929+
930+ if isinstance(x, C):
931+ x #@
932+
933+ if isinstance(x, A):
934+ x #@
935+ """
936+ )
937+
938+ for node in (n1 , n2 , n3 , n4 ):
939+ inferred = node .inferred ()
940+ assert len (inferred ) == 1
941+ assert isinstance (inferred [0 ], Instance )
942+ assert isinstance (inferred [0 ]._proxied , nodes .ClassDef )
943+ assert inferred [0 ].name == "D"
944+
945+
870946def test_isinstance_keyword_arguments ():
871947 """Test that constraint does not apply when `isinstance` is called
872948 with keyword arguments.
@@ -907,3 +983,68 @@ def test_isinstance_extra_argument():
907983 assert len (inferred ) == 1
908984 assert isinstance (inferred [0 ], nodes .Const )
909985 assert inferred [0 ].value == 3
986+
987+
988+ def test_isinstance_classinfo_inference_error ():
989+ """Test that constraint is satisfied when `isinstance` is called with
990+ classinfo that raises an inference error.
991+ """
992+ node = builder .extract_node (
993+ """
994+ x = 3
995+
996+ if isinstance(x, undefined_type):
997+ x #@
998+ """
999+ )
1000+
1001+ inferred = node .inferred ()
1002+ assert len (inferred ) == 1
1003+ assert isinstance (inferred [0 ], nodes .Const )
1004+ assert inferred [0 ].value == 3
1005+
1006+
1007+ def test_isinstance_uninferable_classinfo ():
1008+ """Test that constraint is satisfied when `isinstance` is called with
1009+ uninferable classinfo.
1010+ """
1011+ node = builder .extract_node (
1012+ """
1013+ def f(classinfo):
1014+ x = 3
1015+
1016+ if isinstance(x, classinfo):
1017+ x #@
1018+ """
1019+ )
1020+
1021+ inferred = node .inferred ()
1022+ assert len (inferred ) == 1
1023+ assert isinstance (inferred [0 ], nodes .Const )
1024+ assert inferred [0 ].value == 3
1025+
1026+
1027+ def test_isinstance_mro_error ():
1028+ """Test that constraint is satisfied when computing the object's
1029+ method resolution order raises an MRO error.
1030+ """
1031+ node = builder .extract_node (
1032+ """
1033+ class A():
1034+ pass
1035+
1036+ class B(A, A):
1037+ pass
1038+
1039+ x = B()
1040+
1041+ if isinstance(x, A):
1042+ x #@
1043+ """
1044+ )
1045+
1046+ inferred = node .inferred ()
1047+ assert len (inferred ) == 1
1048+ assert isinstance (inferred [0 ], Instance )
1049+ assert isinstance (inferred [0 ]._proxied , nodes .ClassDef )
1050+ assert inferred [0 ].name == "B"
0 commit comments