1"""Tests for abstract.py.""" 2 3from pytype import abstract 4from pytype import abstract_utils 5from pytype import config 6from pytype import errors 7from pytype import function 8from pytype import load_pytd 9from pytype import special_builtins 10from pytype import state as frame_state 11from pytype import vm 12from pytype.pytd import pytd 13from pytype.pytd import pytd_utils 14from pytype.tests import test_base 15from pytype.typegraph import cfg 16 17import unittest 18 19 20class AbstractTestBase(test_base.UnitTest): 21 22 def setUp(self): 23 super().setUp() 24 options = config.Options.create(python_version=self.python_version) 25 self._vm = vm.VirtualMachine( 26 errors.ErrorLog(), options, load_pytd.Loader(None, self.python_version)) 27 self._program = self._vm.program 28 self._node = self._vm.root_node.ConnectNew("test_node") 29 30 def new_var(self, *values): 31 """Create a Variable bound to the given values.""" 32 var = self._program.NewVariable() 33 for value in values: 34 var.AddBinding(value, source_set=(), where=self._node) 35 return var 36 37 def new_dict(self, **kwargs): 38 """Create a Dict from keywords mapping names to Variable objects.""" 39 d = abstract.Dict(self._vm) 40 for name, var in kwargs.items(): 41 d.set_str_item(self._node, name, var) 42 return d 43 44 45class IsInstanceTest(AbstractTestBase): 46 47 def setUp(self): 48 super().setUp() 49 self._is_instance = special_builtins.IsInstance.make(self._vm) 50 # Easier access to some primitive instances. 51 self._bool = self._vm.convert.primitive_class_instances[bool] 52 self._int = self._vm.convert.primitive_class_instances[int] 53 self._str = self._vm.convert.primitive_class_instances[str] 54 # Values that represent primitive classes. 55 self._obj_class = self._vm.convert.primitive_classes[object] 56 self._int_class = self._vm.convert.primitive_classes[int] 57 self._str_class = self._vm.convert.primitive_classes[str] 58 59 def assert_call(self, expected, left, right): 60 """Check that call() returned the desired results. 61 62 Args: 63 expected: A dict from values to source sets, where a source set is 64 represented by the sorted binding names separated by spaces, for 65 example "left:0 right:1" would indicate binding #0 of variable 66 "left" and binding #1 of variable "right". 67 left: A Variable to use as the first arg to call(). 68 right: A Variable to use as the second arg to call(). 69 """ 70 name_map = {left: "left", right: "right"} 71 node, result = self._is_instance.call( 72 self._node, None, function.Args( 73 (left, right), self.new_dict(), None, None)) 74 self.assertIn(node, self._node.outgoing) 75 result_map = {} 76 # Turning source sets into canonical string representations of the binding 77 # names makes it much easier to debug failures. 78 for b in result.bindings: 79 terms = set() 80 for o in b.origins: 81 self.assertEqual(node, o.where) 82 for sources in o.source_sets: 83 terms.add(" ".join(sorted( 84 "%s:%d" % (name_map[b.variable], b.variable.bindings.index(b)) 85 for b in sources))) 86 result_map[b.data] = terms 87 self.assertEqual(expected, result_map) 88 89 def test_call_single_bindings(self): 90 right = self.new_var(self._str_class) 91 left = self.new_var(self._str) 92 self.assert_call( 93 {self._vm.convert.true: {"left:0 right:0"}}, 94 left, right) 95 left = self.new_var(self._int) 96 self.assert_call( 97 {self._vm.convert.false: {"left:0 right:0"}}, 98 left, right) 99 left = self.new_var(abstract.Unknown(self._vm)) 100 self.assert_call( 101 {self._bool: {"left:0 right:0"}}, 102 left, right) 103 104 def test_call_multiple_bindings(self): 105 left = self.new_var(self._int, self._str) 106 right = self.new_var(self._int_class, self._str_class) 107 self.assert_call( 108 { 109 self._vm.convert.true: {"left:0 right:0", "left:1 right:1"}, 110 self._vm.convert.false: {"left:0 right:1", "left:1 right:0"}, 111 }, left, right) 112 113 def test_call_wrong_argcount(self): 114 self._vm.push_frame(frame_state.SimpleFrame()) 115 node, result = self._is_instance.call( 116 self._node, None, function.Args((), self.new_dict(), None, None)) 117 self.assertEqual(self._node, node) 118 self.assertIsInstance(abstract_utils.get_atomic_value(result), 119 abstract.Unsolvable) 120 self.assertRegex(str(self._vm.errorlog), "missing-parameter") 121 122 def test_call_wrong_keywords(self): 123 self._vm.push_frame(frame_state.SimpleFrame()) 124 x = self.new_var(abstract.Unknown(self._vm)) 125 node, result = self._is_instance.call( 126 self._node, None, function.Args( 127 (x, x), self.new_dict(foo=x), None, None)) 128 self.assertEqual(self._node, node) 129 self.assertIsInstance(abstract_utils.get_atomic_value(result), 130 abstract.Unsolvable) 131 self.assertRegex(str(self._vm.errorlog), 132 r"foo.*isinstance.*\[wrong-keyword-args\]") 133 134 def test_is_instance(self): 135 def check(expected, left, right): 136 self.assertEqual(expected, self._is_instance._is_instance(left, right)) 137 138 # Unknown and Unsolvable are ambiguous. 139 check(None, abstract.Unknown(self._vm), self._obj_class) 140 check(None, abstract.Unsolvable(self._vm), self._obj_class) 141 142 # If the object's class has multiple bindings, result is ambiguous. 143 obj = abstract.SimpleValue("foo", self._vm) 144 check(None, obj, self._obj_class) 145 obj.set_class(self._node, self.new_var( 146 self._str_class, self._int_class)) 147 check(None, obj, self._str_class) 148 149 # If the class_spec is not a class, result is ambiguous. 150 check(None, self._str, self._str) 151 152 # Result is True/False depending on if the class is in the object's mro. 153 check(True, self._str, self._obj_class) 154 check(True, self._str, self._str_class) 155 check(False, self._str, self._int_class) 156 157 def test_flatten(self): 158 def maybe_var(v): 159 return v if isinstance(v, cfg.Variable) else self.new_var(v) 160 161 def new_tuple(*args): 162 pyval = tuple(maybe_var(a) for a in args) 163 return self._vm.convert.tuple_to_value(pyval) 164 165 def check(expected_ambiguous, expected_classes, value): 166 classes = [] 167 ambiguous = abstract_utils._flatten(value, classes) 168 self.assertEqual(expected_ambiguous, ambiguous) 169 self.assertEqual(expected_classes, classes) 170 171 unknown = abstract.Unknown(self._vm) 172 173 # Simple values. 174 check(False, [self._str_class], self._str_class) 175 check(True, [], self._str) 176 check(True, [], unknown) 177 178 # (str, int) 179 check(False, [self._str_class, self._int_class], 180 new_tuple(self._str_class, self._int_class)) 181 # (str, ?, int) 182 check(True, [self._str_class, self._int_class], 183 new_tuple(self._str_class, unknown, self._int_class)) 184 # (str, (int, object)) 185 check(False, [self._str_class, self._int_class, self._obj_class], 186 new_tuple( 187 self._str_class, 188 new_tuple(self._int_class, self._obj_class))) 189 # (str, (?, object)) 190 check(True, [self._str_class, self._obj_class], 191 new_tuple( 192 self._str_class, 193 new_tuple(unknown, self._obj_class))) 194 # A variable with multiple bindings is ambiguous. 195 # (str, int | object) 196 check(True, [self._str_class], 197 new_tuple(self._str_class, 198 self.new_var(self._int_class, self._obj_class))) 199 200 201class PyTDTest(AbstractTestBase): 202 """Tests for abstract -> pytd type conversions.""" 203 204 def test_metaclass(self): 205 cls = abstract.InterpreterClass("X", [], {}, None, self._vm) 206 meta = abstract.InterpreterClass("M", [], {}, None, self._vm) 207 meta.official_name = "M" 208 cls.cls = meta 209 pytd_cls = cls.to_pytd_def(self._vm.root_node, "X") 210 self.assertEqual(pytd_cls.metaclass, pytd.NamedType("M")) 211 212 def test_inherited_metaclass(self): 213 parent = abstract.InterpreterClass("X", [], {}, None, self._vm) 214 parent.official_name = "X" 215 meta = abstract.InterpreterClass("M", [], {}, None, self._vm) 216 meta.official_name = "M" 217 parent.cls = meta 218 child = abstract.InterpreterClass("Y", 219 [parent.to_variable(self._vm.root_node)], 220 {}, None, self._vm) 221 self.assertIs(child.cls, parent.cls) 222 pytd_cls = child.to_pytd_def(self._vm.root_node, "Y") 223 self.assertIs(pytd_cls.metaclass, None) 224 225 def test_metaclass_union(self): 226 cls = abstract.InterpreterClass("X", [], {}, None, self._vm) 227 meta1 = abstract.InterpreterClass("M1", [], {}, None, self._vm) 228 meta2 = abstract.InterpreterClass("M2", [], {}, None, self._vm) 229 meta1.official_name = "M1" 230 meta2.official_name = "M2" 231 cls.cls = abstract.Union([meta1, meta2], self._vm) 232 pytd_cls = cls.to_pytd_def(self._vm.root_node, "X") 233 self.assertEqual(pytd_cls.metaclass, pytd.UnionType( 234 (pytd.NamedType("M1"), pytd.NamedType("M2")))) 235 236 def test_to_type_with_view1(self): 237 # to_type(<instance of List[int or unsolvable]>, view={T: int}) 238 instance = abstract.List([], self._vm) 239 instance.merge_instance_type_parameter( 240 self._vm.root_node, abstract_utils.T, 241 self._vm.program.NewVariable([self._vm.convert.unsolvable], [], 242 self._vm.root_node)) 243 param_binding = instance.get_instance_type_parameter( 244 abstract_utils.T).AddBinding( 245 self._vm.convert.primitive_class_instances[int], [], 246 self._vm.root_node) 247 view = { 248 instance.get_instance_type_parameter(abstract_utils.T): param_binding} 249 pytd_type = instance.to_type(self._vm.root_node, seen=None, view=view) 250 self.assertEqual("builtins.list", pytd_type.name) 251 self.assertSetEqual({"builtins.int"}, 252 {t.name for t in pytd_type.parameters}) 253 254 def test_to_type_with_view2(self): 255 # to_type(<tuple (int or str,)>, view={0: str}) 256 param1 = self._vm.convert.primitive_class_instances[int] 257 param2 = self._vm.convert.primitive_class_instances[str] 258 param_var = param1.to_variable(self._vm.root_node) 259 str_binding = param_var.AddBinding(param2, [], self._vm.root_node) 260 instance = abstract.Tuple((param_var,), self._vm) 261 view = {param_var: str_binding} 262 pytd_type = instance.to_type(self._vm.root_node, seen=None, view=view) 263 self.assertEqual(pytd_type.parameters[0], 264 pytd.NamedType("builtins.str")) 265 266 def test_to_type_with_view_and_empty_param(self): 267 instance = abstract.List([], self._vm) 268 pytd_type = instance.to_type(self._vm.root_node, seen=None, view={}) 269 self.assertEqual("builtins.list", pytd_type.name) 270 self.assertSequenceEqual((pytd.NothingType(),), pytd_type.parameters) 271 272 def test_typing_container(self): 273 cls = self._vm.convert.list_type 274 container = abstract.AnnotationContainer("List", self._vm, cls) 275 expected = pytd.GenericType(pytd.NamedType("builtins.list"), 276 (pytd.AnythingType(),)) 277 actual = container.get_instance_type(self._vm.root_node) 278 self.assertEqual(expected, actual) 279 280 281# TODO(rechen): Test InterpreterFunction. 282class FunctionTest(AbstractTestBase): 283 284 def _make_pytd_function(self, params, name="f"): 285 pytd_params = [] 286 for i, p in enumerate(params): 287 p_type = pytd.ClassType(p.name) 288 p_type.cls = p 289 pytd_params.append( 290 pytd.Parameter(function.argname(i), p_type, False, False, None)) 291 pytd_sig = pytd.Signature( 292 tuple(pytd_params), None, None, pytd.AnythingType(), (), ()) 293 sig = function.PyTDSignature(name, pytd_sig, self._vm) 294 return abstract.PyTDFunction( 295 name, (sig,), pytd.MethodTypes.METHOD, self._vm) 296 297 def _call_pytd_function(self, f, args): 298 b = f.to_binding(self._vm.root_node) 299 return f.call(self._vm.root_node, b, function.Args(posargs=args)) 300 301 def test_call_with_empty_arg(self): 302 self.assertRaises(AssertionError, self._call_pytd_function, 303 self._make_pytd_function(params=()), 304 (self._vm.program.NewVariable(),)) 305 306 def test_call_with_bad_arg(self): 307 f = self._make_pytd_function( 308 (self._vm.lookup_builtin("builtins.str"),)) 309 arg = self._vm.convert.primitive_class_instances[int].to_variable( 310 self._vm.root_node) 311 self.assertRaises( 312 function.WrongArgTypes, self._call_pytd_function, f, (arg,)) 313 314 def test_simple_call(self): 315 f = self._make_pytd_function( 316 (self._vm.lookup_builtin("builtins.str"),)) 317 arg = self._vm.convert.primitive_class_instances[str].to_variable( 318 self._vm.root_node) 319 node, ret = self._call_pytd_function(f, (arg,)) 320 self.assertIs(node, self._vm.root_node) 321 retval, = ret.bindings 322 self.assertIs(retval.data, self._vm.convert.unsolvable) 323 324 def test_call_with_multiple_arg_bindings(self): 325 f = self._make_pytd_function( 326 (self._vm.lookup_builtin("builtins.str"),)) 327 arg = self._vm.program.NewVariable() 328 arg.AddBinding(self._vm.convert.primitive_class_instances[str], [], 329 self._vm.root_node) 330 arg.AddBinding(self._vm.convert.primitive_class_instances[int], [], 331 self._vm.root_node) 332 node, ret = self._call_pytd_function(f, (arg,)) 333 self.assertIs(node, self._vm.root_node) 334 retval, = ret.bindings 335 self.assertIs(retval.data, self._vm.convert.unsolvable) 336 337 def test_call_with_skipped_combination(self): 338 f = self._make_pytd_function( 339 (self._vm.lookup_builtin("builtins.str"),)) 340 node = self._vm.root_node.ConnectNew() 341 arg = self._vm.convert.primitive_class_instances[str].to_variable(node) 342 node, ret = self._call_pytd_function(f, (arg,)) 343 self.assertIs(node, self._vm.root_node) 344 self.assertFalse(ret.bindings) 345 346 def test_signature_from_pytd(self): 347 # def f(self: Any, *args: Any) 348 self_param = pytd.Parameter("self", pytd.AnythingType(), False, False, None) 349 args_param = pytd.Parameter("args", pytd.AnythingType(), False, True, None) 350 sig = function.Signature.from_pytd( 351 self._vm, "f", pytd.Signature( 352 (self_param,), args_param, None, pytd.AnythingType(), (), ())) 353 self.assertEqual(repr(sig), "def f(self: Any, *args: Any) -> Any") 354 self.assertEqual(sig.name, "f") 355 self.assertSequenceEqual(sig.param_names, ("self",)) 356 self.assertEqual(sig.varargs_name, "args") 357 self.assertFalse(sig.kwonly_params) 358 self.assertIs(sig.kwargs_name, None) 359 self.assertSetEqual(set(sig.annotations), {"self", "args", "return"}) 360 self.assertTrue(sig.has_return_annotation) 361 self.assertTrue(sig.has_param_annotations) 362 363 def test_signature_from_callable(self): 364 # Callable[[int, str], Any] 365 params = {0: self._vm.convert.int_type, 1: self._vm.convert.str_type} 366 params[abstract_utils.ARGS] = abstract.Union( 367 (params[0], params[1]), self._vm) 368 params[abstract_utils.RET] = self._vm.convert.unsolvable 369 callable_val = abstract.CallableClass( 370 self._vm.convert.function_type, params, self._vm) 371 sig = function.Signature.from_callable(callable_val) 372 self.assertEqual(repr(sig), "def <callable>(_0: int, _1: str) -> Any") 373 self.assertEqual(sig.name, "<callable>") 374 self.assertSequenceEqual(sig.param_names, ("_0", "_1")) 375 self.assertIs(sig.varargs_name, None) 376 self.assertFalse(sig.kwonly_params) 377 self.assertIs(sig.kwargs_name, None) 378 self.assertCountEqual(sig.annotations.keys(), sig.param_names) 379 self.assertFalse(sig.has_return_annotation) 380 self.assertTrue(sig.has_param_annotations) 381 382 def test_signature_annotations(self): 383 # def f(self: Any, *args: Any) 384 self_param = pytd.Parameter("self", pytd.AnythingType(), False, False, None) 385 # Imitate the parser's conversion of '*args: Any' to '*args: Tuple[Any]'. 386 tup = pytd.ClassType("builtins.tuple") 387 tup.cls = self._vm.convert.tuple_type.pytd_cls 388 any_tuple = pytd.GenericType(tup, (pytd.AnythingType(),)) 389 args_param = pytd.Parameter("args", any_tuple, False, True, None) 390 sig = function.Signature.from_pytd( 391 self._vm, "f", pytd.Signature( 392 (self_param,), args_param, None, pytd.AnythingType(), (), ())) 393 self.assertEqual(repr(sig), 394 "def f(self: Any, *args: Tuple[Any, ...]) -> Any") 395 self.assertIs(sig.annotations["self"], self._vm.convert.unsolvable) 396 args_type = sig.annotations["args"] 397 self.assertIsInstance(args_type, abstract.ParameterizedClass) 398 self.assertIs(args_type.base_cls, self._vm.convert.tuple_type) 399 self.assertListEqual(list(args_type.formal_type_parameters.items()), 400 [(abstract_utils.T, self._vm.convert.unsolvable)]) 401 self.assertIs(sig.drop_first_parameter().annotations["args"], args_type) 402 403 def test_signature_annotations_existence(self): 404 # def f(v: "X") -> "Y" 405 sig = function.Signature( 406 name="f", 407 param_names=("v",), 408 varargs_name=None, 409 kwonly_params=(), 410 kwargs_name=None, 411 defaults={}, 412 annotations={}, 413 ) 414 self.assertFalse(sig.has_param_annotations) 415 self.assertFalse(sig.has_return_annotation) 416 sig.set_annotation("v", self._vm.convert.unsolvable) 417 self.assertTrue(sig.has_param_annotations) 418 self.assertFalse(sig.has_return_annotation) 419 sig.set_annotation("return", self._vm.convert.unsolvable) 420 self.assertTrue(sig.has_param_annotations) 421 self.assertTrue(sig.has_return_annotation) 422 423 def test_signature_posarg_only_param_count(self): 424 # def f(x): ... 425 sig = function.Signature( 426 name="f", 427 param_names=("x",), 428 varargs_name=None, 429 kwonly_params=(), 430 kwargs_name=None, 431 defaults={}, 432 annotations={}, 433 ) 434 self.assertEqual(repr(sig), "def f(x) -> Any") 435 self.assertEqual(sig.mandatory_param_count(), 1) 436 self.assertEqual(sig.maximum_param_count(), 1) 437 438 def test_signature_posarg_and_kwarg_param_count(self): 439 # def f(x, y=None): ... 440 sig = function.Signature( 441 name="f", 442 param_names=("x", "y",), 443 varargs_name=None, 444 kwonly_params=(), 445 kwargs_name=None, 446 defaults={"y": self._vm.convert.none_type.to_variable(self._node)}, 447 annotations={}, 448 ) 449 self.assertEqual(repr(sig), "def f(x, y = None) -> Any") 450 self.assertEqual(sig.mandatory_param_count(), 1) 451 self.assertEqual(sig.maximum_param_count(), 2) 452 453 def test_signature_varargs_param_count(self): 454 # def f(*args): ... 455 sig = function.Signature( 456 name="f", 457 param_names=(), 458 varargs_name="args", 459 kwonly_params=(), 460 kwargs_name=None, 461 defaults={}, 462 annotations={}, 463 ) 464 self.assertEqual(repr(sig), "def f(*args) -> Any") 465 self.assertEqual(sig.mandatory_param_count(), 0) 466 self.assertIsNone(sig.maximum_param_count()) 467 468 def test_signature_kwargs_param_count(self): 469 # def f(**kwargs): ... 470 sig = function.Signature( 471 name="f", 472 param_names=(), 473 varargs_name=None, 474 kwonly_params=(), 475 kwargs_name="kwargs", 476 defaults={}, 477 annotations={}, 478 ) 479 self.assertEqual(repr(sig), "def f(**kwargs) -> Any") 480 self.assertEqual(sig.mandatory_param_count(), 0) 481 self.assertIsNone(sig.maximum_param_count()) 482 483 def test_signature_kwonly_param_count(self): 484 # def f(*, y=None): ... 485 sig = function.Signature( 486 name="f", 487 param_names=(), 488 varargs_name=None, 489 kwonly_params=("y",), 490 kwargs_name=None, 491 defaults={"y": self._vm.convert.none_type.to_variable(self._node)}, 492 annotations={}, 493 ) 494 self.assertEqual(repr(sig), "def f(*, y = None) -> Any") 495 self.assertEqual(sig.mandatory_param_count(), 0) 496 self.assertEqual(sig.maximum_param_count(), 1) 497 498 def test_signature_has_param(self): 499 # def f(x, *args, y, **kwargs): ... 500 sig = function.Signature( 501 name="f", 502 param_names=("x",), 503 varargs_name="args", 504 kwonly_params={"y"}, 505 kwargs_name="kwargs", 506 defaults={}, 507 annotations={}, 508 ) 509 self.assertEqual(repr(sig), "def f(x, *args, y, **kwargs) -> Any") 510 for param in ("x", "args", "y", "kwargs"): 511 self.assertTrue(sig.has_param(param)) 512 self.assertFalse(sig.has_param("rumpelstiltskin")) 513 514 def test_signature_insert_varargs_and_kwargs(self): 515 # def f(x, *args, y, **kwargs): ... 516 sig = function.Signature( 517 name="f", 518 param_names=("x",), 519 varargs_name="args", 520 kwonly_params={"y"}, 521 kwargs_name="kwargs", 522 defaults={}, 523 annotations={}, 524 ) 525 # f(1, 2, y=3, z=4) 526 int_inst = self._vm.convert.primitive_class_instances[int] 527 int_binding = int_inst.to_binding(self._node) 528 arg_dict = { 529 "x": int_binding, "_1": int_binding, "y": int_binding, "z": int_binding} 530 sig = sig.insert_varargs_and_kwargs(arg_dict) 531 self.assertEqual(sig.name, "f") 532 self.assertSequenceEqual(sig.param_names, ("x", "_1", "z")) 533 self.assertEqual(sig.varargs_name, "args") 534 self.assertSetEqual(sig.kwonly_params, {"y"}) 535 self.assertEqual(sig.kwargs_name, "kwargs") 536 self.assertFalse(sig.annotations) 537 538 def test_signature_del_param_annotation(self): 539 # def f(x) -> int: ... 540 sig = function.Signature( 541 name="f", 542 param_names=("x",), 543 varargs_name=None, 544 kwonly_params=(), 545 kwargs_name=None, 546 defaults={}, 547 annotations={"x": self._vm.convert.unsolvable, 548 "return": self._vm.convert.unsolvable}, 549 ) 550 sig.del_annotation("x") 551 self.assertCountEqual(sig.annotations.keys(), {"return"}) 552 self.assertFalse(sig.has_param_annotations) 553 self.assertTrue(sig.has_return_annotation) 554 555 def test_signature_del_return_annotation(self): 556 # def f(x) -> int: ... 557 sig = function.Signature( 558 name="f", 559 param_names=("x",), 560 varargs_name=None, 561 kwonly_params=(), 562 kwargs_name=None, 563 defaults={}, 564 annotations={"x": self._vm.convert.unsolvable, 565 "return": self._vm.convert.unsolvable}, 566 ) 567 sig.del_annotation("return") 568 self.assertCountEqual(sig.annotations.keys(), {"x"}) 569 self.assertTrue(sig.has_param_annotations) 570 self.assertFalse(sig.has_return_annotation) 571 572 def test_signature_del_nonexistent_annotation(self): 573 # def f(): ... 574 sig = function.Signature( 575 name="f", 576 param_names=(), 577 varargs_name=None, 578 kwonly_params=(), 579 kwargs_name=None, 580 defaults={}, 581 annotations={}, 582 ) 583 self.assertRaises(KeyError, sig.del_annotation, "rumpelstiltskin") 584 585 def test_constructor_args(self): 586 f = abstract.PyTDFunction.make("open", self._vm, "builtins") 587 self.assertEqual(f.full_name, "builtins.open") 588 self.assertCountEqual( 589 {sig.pytd_sig for sig in f.signatures}, 590 self._vm.lookup_builtin("builtins.open").signatures) 591 self.assertIs(f.kind, pytd.MethodTypes.METHOD) 592 self.assertIs(f.vm, self._vm) 593 594 def test_constructor_args_pyval(self): 595 sig = pytd.Signature((), None, None, pytd.AnythingType(), (), ()) 596 pyval = pytd.Function("blah", (sig,), pytd.MethodTypes.STATICMETHOD, 0) 597 f = abstract.PyTDFunction.make("open", self._vm, "builtins", pyval=pyval) 598 self.assertEqual(f.full_name, "builtins.open") 599 f_sig, = f.signatures 600 self.assertIs(f_sig.pytd_sig, sig) 601 self.assertIs(f.kind, pytd.MethodTypes.STATICMETHOD) 602 self.assertIs(f.vm, self._vm) 603 604 def test_get_constructor_args(self): 605 f = abstract.PyTDFunction.make( 606 "TypeVar", self._vm, "typing", pyval_name="_typevar_new") 607 self.assertEqual(f.full_name, "typing.TypeVar") 608 self.assertCountEqual( 609 {sig.pytd_sig for sig in f.signatures}, 610 self._vm.loader.import_name("typing").Lookup( 611 "typing._typevar_new").signatures) 612 self.assertIs(f.kind, pytd.MethodTypes.METHOD) 613 self.assertIs(f.vm, self._vm) 614 615 def test_bound_function_repr(self): 616 f = self._make_pytd_function(params=()) 617 callself = self._vm.program.NewVariable( 618 [abstract.BaseValue(name, self._vm) for name in ("test1", "test2")], [], 619 self._vm.root_node) 620 bound = abstract.BoundFunction(callself, f) 621 self.assertCountEqual(bound.repr_names(), ["test1.f", "test2.f"]) 622 self.assertRegex(repr(bound), r"test(1|2)\.f") 623 624 def test_bound_function_callself_repr(self): 625 f = self._make_pytd_function(params=()) 626 callself = self._vm.program.NewVariable( 627 [abstract.BaseValue("test", self._vm)], [], self._vm.root_node) 628 bound = abstract.BoundFunction(callself, f) 629 callself_repr = lambda v: v.name + "foo" 630 self.assertCountEqual(bound.repr_names(callself_repr), ["testfoo.f"]) 631 632 def test_bound_function_nested_repr(self): 633 f = self._make_pytd_function(params=()) 634 callself1 = self._vm.program.NewVariable( 635 [abstract.BaseValue("test1", self._vm)], [], self._vm.root_node) 636 bound1 = abstract.BoundFunction(callself1, f) 637 callself2 = self._vm.program.NewVariable( 638 [abstract.BaseValue("test2", self._vm)], [], self._vm.root_node) 639 bound2 = abstract.BoundFunction(callself2, bound1) 640 # `bound2` is BoundFunction(test2, BoundFunction(test1, f)) 641 self.assertCountEqual(bound2.repr_names(), ["test2.f"]) 642 643 def test_bound_function_repr_no_callself(self): 644 f = self._make_pytd_function(params=()) 645 callself = self._vm.program.NewVariable() 646 bound = abstract.BoundFunction(callself, f) 647 self.assertCountEqual(bound.repr_names(), ["<class>.f"]) 648 649 def test_bound_function_repr_replace_parent(self): 650 f = self._make_pytd_function(params=(), name="foo.f") 651 callself = self._vm.program.NewVariable( 652 [abstract.BaseValue("test", self._vm)], [], self._vm.root_node) 653 bound = abstract.BoundFunction(callself, f) 654 self.assertCountEqual(bound.repr_names(), ["test.f"]) 655 656 657class AbstractMethodsTest(AbstractTestBase): 658 659 def test_abstract_method(self): 660 func = abstract.Function("f", self._vm).to_variable(self._vm.root_node) 661 func.data[0].is_abstract = True 662 cls = abstract.InterpreterClass("X", [], {"f": func}, None, self._vm) 663 self.assertCountEqual(cls.abstract_methods, {"f"}) 664 665 def test_inherited_abstract_method(self): 666 sized_pytd = self._vm.loader.typing.Lookup("typing.Sized") 667 sized = self._vm.convert.constant_to_value(sized_pytd, {}, 668 self._vm.root_node) 669 cls = abstract.InterpreterClass("X", 670 [sized.to_variable(self._vm.root_node)], {}, 671 None, self._vm) 672 self.assertCountEqual(cls.abstract_methods, {"__len__"}) 673 674 def test_overridden_abstract_method(self): 675 sized_pytd = self._vm.loader.typing.Lookup("typing.Sized") 676 sized = self._vm.convert.constant_to_value(sized_pytd, {}, 677 self._vm.root_node) 678 bases = [sized.to_variable(self._vm.root_node)] 679 members = {"__len__": self._vm.new_unsolvable(self._vm.root_node)} 680 cls = abstract.InterpreterClass("X", bases, members, None, self._vm) 681 self.assertFalse(cls.abstract_methods) 682 683 def test_overridden_abstract_method_still_abstract(self): 684 sized_pytd = self._vm.loader.typing.Lookup("typing.Sized") 685 sized = self._vm.convert.constant_to_value(sized_pytd, {}, 686 self._vm.root_node) 687 bases = [sized.to_variable(self._vm.root_node)] 688 func = abstract.Function("__len__", self._vm) 689 func.is_abstract = True 690 members = {"__len__": func.to_variable(self._vm.root_node)} 691 cls = abstract.InterpreterClass("X", bases, members, None, self._vm) 692 self.assertCountEqual(cls.abstract_methods, {"__len__"}) 693 694 695class SimpleFunctionTest(AbstractTestBase): 696 697 def _make_func(self, name="_", param_names=None, varargs_name=None, 698 kwonly_params=(), kwargs_name=None, defaults=(), 699 annotations=None): 700 return abstract.SimpleFunction(name, param_names or (), varargs_name, 701 kwonly_params, kwargs_name, defaults, 702 annotations or {}, self._vm) 703 704 def _simple_sig(self, param_types, ret_type=None): 705 annots = {("_%d" % i): t for i, t in enumerate(param_types)} 706 params = tuple(annots.keys()) 707 if ret_type: 708 annots["return"] = ret_type 709 return self._make_func(param_names=params, annotations=annots) 710 711 def test_simple_call(self): 712 f = self._simple_sig([self._vm.convert.str_type], 713 ret_type=self._vm.convert.int_type) 714 args = function.Args((self._vm.convert.build_string(self._vm.root_node, 715 "hello"),)) 716 node, ret = f.call(self._vm.root_node, f, args) 717 self.assertIs(node, self._vm.root_node) 718 ret_val, = ret.data 719 self.assertEqual(ret_val.cls, self._vm.convert.int_type) 720 721 def test_call_with_bad_arg(self): 722 f = self._make_func(param_names=("test",), 723 annotations={"test": self._vm.convert.str_type}) 724 args = function.Args((self._vm.convert.build_int(self._vm.root_node),)) 725 self.assertRaises(function.WrongArgTypes, f.call, self._vm.root_node, f, 726 args) 727 728 def test_call_with_no_args(self): 729 f = self._simple_sig([self._vm.convert.str_type, self._vm.convert.int_type]) 730 args = function.Args(()) 731 self.assertRaises(function.MissingParameter, f.call, self._vm.root_node, f, 732 args) 733 734 def test_call_with_multiple_arg_bindings(self): 735 f = self._simple_sig([self._vm.convert.str_type]) 736 arg = self._vm.program.NewVariable() 737 arg.AddBinding(self._vm.convert.primitive_class_instances[str], [], 738 self._vm.root_node) 739 arg.AddBinding(self._vm.convert.primitive_class_instances[int], [], 740 self._vm.root_node) 741 args = function.Args((arg,)) 742 node, ret = f.call(self._vm.root_node, f, args) 743 self.assertIs(node, self._vm.root_node) 744 self.assertIs(ret.data[0], self._vm.convert.none) 745 746 def test_call_with_varargs(self): 747 f = self._make_func( 748 varargs_name="arg", 749 annotations={"arg": self._vm.convert.str_type, 750 "return": self._vm.convert.str_type} 751 ) 752 starargs = abstract.Tuple( 753 (self._vm.convert.build_string(self._vm.root_node, ""),), 754 self._vm).to_variable(self._vm.root_node) 755 args = function.Args(posargs=(), starargs=starargs) 756 node, ret = f.call(self._vm.root_node, f, args) 757 self.assertIs(node, self._vm.root_node) 758 self.assertIs(ret.data[0].cls, self._vm.convert.str_type) 759 760 def test_call_with_bad_varargs(self): 761 f = self._make_func( 762 varargs_name="arg", 763 annotations={"arg": self._vm.convert.str_type}) 764 starargs = abstract.Tuple( 765 (self._vm.convert.build_string(self._vm.root_node, ""), 766 self._vm.convert.build_int(self._vm.root_node)), 767 self._vm).to_variable(self._vm.root_node) 768 args = function.Args(posargs=(), starargs=starargs) 769 self.assertRaises(function.WrongArgTypes, f.call, self._vm.root_node, f, 770 args) 771 772 def test_call_with_multiple_varargs_bindings(self): 773 f = self._make_func( 774 varargs_name="arg", 775 annotations={"arg": self._vm.convert.str_type}) 776 arg = self._vm.program.NewVariable() 777 arg.AddBinding(self._vm.convert.primitive_class_instances[str], [], 778 self._vm.root_node) 779 arg.AddBinding(self._vm.convert.primitive_class_instances[int], [], 780 self._vm.root_node) 781 starargs = abstract.Tuple((arg,), self._vm) 782 starargs = starargs.to_variable(self._vm.root_node) 783 args = function.Args(posargs=(), starargs=starargs) 784 f.call(self._vm.root_node, f, args) 785 786 def test_call_with_kwargs(self): 787 f = self._make_func( 788 kwargs_name="kwarg", 789 annotations={"kwarg": self._vm.convert.str_type}) 790 kwargs = abstract.Dict(self._vm) 791 kwargs.update( 792 self._vm.root_node, { 793 "_1": self._vm.convert.build_string(self._vm.root_node, "1"), 794 "_2": self._vm.convert.build_string(self._vm.root_node, "2") 795 }) 796 kwargs = kwargs.to_variable(self._vm.root_node) 797 args = function.Args( 798 posargs=(), 799 namedargs=abstract.Dict(self._vm), 800 starstarargs=kwargs 801 ) 802 f.call(self._vm.root_node, f, args) 803 804 def test_call_with_bad_kwargs(self): 805 f = self._make_func( 806 kwargs_name="kwarg", 807 annotations={"kwarg": self._vm.convert.str_type}) 808 kwargs = abstract.Dict(self._vm) 809 kwargs.update(self._vm.root_node, 810 {"_1": self._vm.convert.build_int(self._vm.root_node)}) 811 kwargs = kwargs.to_variable(self._vm.root_node) 812 args = function.Args( 813 posargs=(), 814 namedargs=abstract.Dict(self._vm), 815 starstarargs=kwargs 816 ) 817 self.assertRaises(function.WrongArgTypes, f.call, self._vm.root_node, f, 818 args) 819 820 def test_call_with_kwonly_args(self): 821 f = self._make_func( 822 param_names=("test",), 823 kwonly_params=("a", "b"), 824 annotations={ 825 "test": self._vm.convert.str_type, 826 "a": self._vm.convert.str_type, 827 "b": self._vm.convert.str_type 828 } 829 ) 830 kwargs = abstract.Dict(self._vm) 831 kwargs.update( 832 self._vm.root_node, { 833 "a": self._vm.convert.build_string(self._vm.root_node, "2"), 834 "b": self._vm.convert.build_string(self._vm.root_node, "3") 835 }) 836 kwargs = kwargs.to_variable(self._vm.root_node) 837 args = function.Args( 838 posargs=(self._vm.convert.build_string(self._vm.root_node, "1"),), 839 namedargs=abstract.Dict(self._vm), 840 starstarargs=kwargs) 841 f.call(self._vm.root_node, f, args) 842 kwargs = abstract.Dict(self._vm) 843 kwargs.update(self._vm.root_node, 844 {"b": self._vm.convert.build_string(self._vm.root_node, "3")}) 845 kwargs = kwargs.to_variable(self._vm.root_node) 846 args = function.Args( 847 posargs=(self._vm.convert.build_string(self._vm.root_node, "1"), 848 self._vm.convert.build_int(self._vm.root_node)), 849 namedargs=abstract.Dict(self._vm), 850 starstarargs=kwargs) 851 self.assertRaises(function.MissingParameter, f.call, self._vm.root_node, f, 852 args) 853 854 def test_call_with_all_args(self): 855 f = self._make_func( 856 param_names=("a", "b", "c"), 857 varargs_name="arg", 858 kwargs_name="kwarg", 859 defaults=(self._vm.convert.build_int(self._vm.root_node),), 860 annotations={ 861 "a": self._vm.convert.str_type, 862 "b": self._vm.convert.int_type, 863 "c": self._vm.convert.int_type, 864 "arg": self._vm.convert.primitive_classes[float], 865 "kwarg": self._vm.convert.primitive_classes[bool] 866 }) 867 posargs = (self._vm.convert.build_string(self._vm.root_node, "1"), 868 self._vm.convert.build_int(self._vm.root_node)) 869 float_inst = self._vm.convert.primitive_class_instances[float] 870 stararg = abstract.Tuple((float_inst.to_variable(self._vm.root_node),), 871 self._vm).to_variable(self._vm.root_node) 872 namedargs = abstract.Dict(self._vm) 873 kwarg = abstract.Dict(self._vm) 874 kwarg.update( 875 self._vm.root_node, { 876 "x": self._vm.convert.build_bool(self._vm.root_node), 877 "y": self._vm.convert.build_bool(self._vm.root_node) 878 }) 879 kwarg = kwarg.to_variable(self._vm.root_node) 880 args = function.Args(posargs, namedargs, stararg, kwarg) 881 f.call(self._vm.root_node, f, args) 882 883 def test_call_with_defaults(self): 884 f = self._make_func( 885 param_names=("a", "b", "c"), 886 defaults=(self._vm.convert.build_int(self._vm.root_node),), 887 annotations={ 888 "a": self._vm.convert.int_type, 889 "b": self._vm.convert.int_type, 890 "c": self._vm.convert.int_type 891 }) 892 args = function.Args( 893 posargs=(self._vm.convert.build_int(self._vm.root_node), 894 self._vm.convert.build_int(self._vm.root_node))) 895 f.call(self._vm.root_node, f, args) 896 args = function.Args( 897 posargs=(self._vm.convert.build_int(self._vm.root_node), 898 self._vm.convert.build_int(self._vm.root_node), 899 self._vm.convert.build_int(self._vm.root_node))) 900 f.call(self._vm.root_node, f, args) 901 args = function.Args( 902 posargs=(self._vm.convert.build_int(self._vm.root_node),)) 903 self.assertRaises(function.MissingParameter, f.call, self._vm.root_node, f, 904 args) 905 906 def test_call_with_bad_default(self): 907 f = self._make_func( 908 param_names=("a", "b"), 909 defaults=(self._vm.convert.build_string(self._vm.root_node, ""),), 910 annotations={ 911 "a": self._vm.convert.int_type, 912 "b": self._vm.convert.str_type 913 }) 914 args = function.Args( 915 posargs=(self._vm.convert.build_int(self._vm.root_node), 916 self._vm.convert.build_int(self._vm.root_node))) 917 self.assertRaises(function.WrongArgTypes, f.call, self._vm.root_node, f, 918 args) 919 920 def test_call_with_duplicate_keyword(self): 921 f = self._simple_sig([self._vm.convert.int_type]*2) 922 args = function.Args( 923 posargs=(self._vm.convert.build_int(self._vm.root_node), 924 self._vm.convert.build_int(self._vm.root_node)), 925 namedargs={"_1": self._vm.convert.build_int(self._vm.root_node)}) 926 self.assertRaises(function.DuplicateKeyword, f.call, self._vm.root_node, f, 927 args) 928 929 def test_call_with_wrong_arg_count(self): 930 f = self._simple_sig([self._vm.convert.int_type]) 931 args = function.Args( 932 posargs=(self._vm.convert.build_int(self._vm.root_node), 933 self._vm.convert.build_int(self._vm.root_node))) 934 self.assertRaises(function.WrongArgCount, f.call, self._vm.root_node, f, 935 args) 936 937 def test_change_defaults(self): 938 f = self._make_func( 939 param_names=("a", "b", "c"), 940 defaults=(self._vm.convert.build_int(self._vm.root_node),)) 941 args = function.Args( 942 posargs=(self._vm.convert.build_int(self._vm.root_node), 943 self._vm.convert.build_int(self._vm.root_node))) 944 f.call(self._vm.root_node, f, args) 945 new_defaults = abstract.Tuple((self._vm.convert.build_int( 946 self._vm.root_node), self._vm.convert.build_int(self._vm.root_node)), 947 self._vm).to_variable(self._vm.root_node) 948 f.set_function_defaults(self._vm.root_node, new_defaults) 949 f.call(self._vm.root_node, f, args) 950 args = function.Args( 951 posargs=(self._vm.convert.build_int(self._vm.root_node),)) 952 f.call(self._vm.root_node, f, args) 953 954 def test_call_with_type_parameter(self): 955 ret_cls = abstract.ParameterizedClass( 956 self._vm.convert.list_type, 957 {abstract_utils.T: abstract.TypeParameter(abstract_utils.T, self._vm)}, 958 self._vm 959 ) 960 f = self._make_func( 961 param_names=("test",), 962 annotations={ 963 "test": abstract.TypeParameter(abstract_utils.T, self._vm), 964 "return": ret_cls 965 } 966 ) 967 args = function.Args( 968 posargs=(self._vm.convert.build_int(self._vm.root_node),)) 969 _, ret = f.call(self._vm.root_node, f, args) 970 # ret is an Instance(ParameterizedClass(list, {abstract_utils.T: int})) 971 # but we really only care about T. 972 self.assertIs(ret.data[0].cls.formal_type_parameters[abstract_utils.T], 973 self._vm.convert.int_type) 974 975 def test_signature_func_output_basic(self): 976 node = self._vm.root_node 977 f = self._make_func(name="basic", param_names=("a", "b")) 978 fp = self._vm.convert.pytd_convert.value_to_pytd_def(node, f, f.name) 979 self.assertEqual(pytd_utils.Print(fp), "def basic(a, b) -> None: ...") 980 981 def test_signature_func_output_annotations(self): 982 node = self._vm.root_node 983 f = self._make_func( 984 name="annots", 985 param_names=("a", "b"), 986 annotations={ 987 "a": self._vm.convert.int_type, 988 "b": self._vm.convert.str_type, 989 "return": self._vm.convert.int_type 990 } 991 ) 992 fp = self._vm.convert.pytd_convert.value_to_pytd_def(node, f, f.name) 993 self.assertEqual(pytd_utils.Print(fp), 994 "def annots(a: int, b: str) -> int: ...") 995 996 def test_signature_func_output(self): 997 node = self._vm.root_node 998 dict_type = abstract.ParameterizedClass( 999 self._vm.convert.dict_type, 1000 {abstract_utils.K: self._vm.convert.str_type, 1001 abstract_utils.V: self._vm.convert.int_type}, 1002 self._vm) 1003 f = self._make_func( 1004 name="test", 1005 param_names=("a", "b"), 1006 varargs_name="c", 1007 kwonly_params=("d", "e"), 1008 kwargs_name="f", 1009 defaults={ 1010 "b": self._vm.convert.build_int(node), 1011 "d": self._vm.convert.build_int(node) 1012 }, 1013 annotations={ 1014 "a": self._vm.convert.str_type, 1015 "b": self._vm.convert.int_type, 1016 "c": self._vm.convert.str_type, 1017 "d": dict_type, 1018 "e": self._vm.convert.int_type, 1019 "f": self._vm.convert.str_type, 1020 "return": self._vm.convert.str_type 1021 } 1022 ) 1023 fp = self._vm.convert.pytd_convert.value_to_pytd_def(node, f, f.name) 1024 f_str = ("def test(a: str, b: int = ..., *c: str, d: Dict[str, int] = ...," 1025 " e: int, **f: str) -> str: ...") 1026 self.assertEqual(pytd_utils.Print(fp), f_str) 1027 1028 1029class AbstractTest(AbstractTestBase): 1030 1031 def test_interpreter_class_official_name(self): 1032 cls = abstract.InterpreterClass("X", [], {}, None, self._vm) 1033 cls.update_official_name("Z") 1034 self.assertEqual(cls.official_name, "Z") 1035 cls.update_official_name("A") # takes effect because A < Z 1036 self.assertEqual(cls.official_name, "A") 1037 cls.update_official_name("Z") # no effect 1038 self.assertEqual(cls.official_name, "A") 1039 cls.update_official_name("X") # takes effect because X == cls.name 1040 self.assertEqual(cls.official_name, "X") 1041 cls.update_official_name("A") # no effect 1042 self.assertEqual(cls.official_name, "X") 1043 1044 def test_type_parameter_official_name(self): 1045 param = abstract.TypeParameter("T", self._vm) 1046 self._vm.frame = frame_state.SimpleFrame() # for error logging 1047 param.update_official_name("T") 1048 self.assertFalse(self._vm.errorlog.has_error()) 1049 param.update_official_name("Q") 1050 self.assertTrue(self._vm.errorlog.has_error()) 1051 1052 def test_type_parameter_equality(self): 1053 param1 = abstract.TypeParameter("S", self._vm) 1054 param2 = abstract.TypeParameter("T", self._vm) 1055 cls = abstract.InterpreterClass("S", [], {}, None, self._vm) 1056 self.assertEqual(param1, param1) 1057 self.assertNotEqual(param1, param2) 1058 self.assertNotEqual(param1, cls) 1059 1060 def test_union_equality(self): 1061 union1 = abstract.Union((self._vm.convert.unsolvable,), self._vm) 1062 union2 = abstract.Union((self._vm.convert.none,), self._vm) 1063 cls = abstract.InterpreterClass("Union", [], {}, None, self._vm) 1064 self.assertEqual(union1, union1) 1065 self.assertNotEqual(union1, union2) 1066 self.assertNotEqual(union1, cls) 1067 1068 def test_instantiate_type_parameter_type(self): 1069 params = { 1070 abstract_utils.T: abstract.TypeParameter(abstract_utils.T, self._vm)} 1071 cls = abstract.ParameterizedClass( 1072 self._vm.convert.type_type, params, self._vm) 1073 self.assertListEqual(cls.instantiate(self._node).data, 1074 [self._vm.convert.unsolvable]) 1075 1076 def test_super_type(self): 1077 supercls = special_builtins.Super(self._vm) 1078 self.assertEqual(supercls.get_class(), self._vm.convert.type_type) 1079 1080 def test_instantiate_interpreter_class(self): 1081 cls = abstract.InterpreterClass("X", [], {}, None, self._vm) 1082 # When there is no current frame, create a new instance every time. 1083 v1 = abstract_utils.get_atomic_value(cls.instantiate(self._node)) 1084 v2 = abstract_utils.get_atomic_value(cls.instantiate(self._node)) 1085 self.assertIsNot(v1, v2) 1086 # Create one instance per opcode. 1087 fake_opcode = object() 1088 self._vm.push_frame(frame_state.SimpleFrame(fake_opcode)) 1089 v3 = abstract_utils.get_atomic_value(cls.instantiate(self._node)) 1090 v4 = abstract_utils.get_atomic_value(cls.instantiate(self._node)) 1091 self.assertIsNot(v1, v3) 1092 self.assertIsNot(v2, v3) 1093 self.assertIs(v3, v4) 1094 1095 def test_set_module_on_module(self): 1096 # A module's 'module' attribute should always remain None, and no one 1097 # should attempt to set it to something besides the module's name or None. 1098 ast = pytd_utils.CreateModule("some_mod") 1099 mod = abstract.Module(self._vm, ast.name, {}, ast) 1100 mod.module = ast.name 1101 self.assertIsNone(mod.module) 1102 self.assertEqual(ast.name, mod.full_name) 1103 mod.module = None 1104 self.assertIsNone(mod.module) 1105 self.assertEqual(ast.name, mod.full_name) 1106 def set_module(): 1107 mod.module = "other_mod" 1108 self.assertRaises(AssertionError, set_module) 1109 1110 def test_call_type_parameter_instance(self): 1111 instance = abstract.Instance(self._vm.convert.list_type, self._vm) 1112 instance.merge_instance_type_parameter( 1113 self._vm.root_node, abstract_utils.T, 1114 self._vm.convert.int_type.to_variable(self._vm.root_node)) 1115 t = abstract.TypeParameter(abstract_utils.T, self._vm) 1116 t_instance = abstract.TypeParameterInstance(t, instance, self._vm) 1117 node, ret = t_instance.call(self._node, t_instance.to_binding(self._node), 1118 function.Args(posargs=())) 1119 self.assertIs(node, self._node) 1120 retval, = ret.data 1121 self.assertEqual(retval.cls, self._vm.convert.int_type) 1122 1123 def test_call_empty_type_parameter_instance(self): 1124 instance = abstract.Instance(self._vm.convert.list_type, self._vm) 1125 t = abstract.TypeParameter(abstract_utils.T, self._vm) 1126 t_instance = abstract.TypeParameterInstance(t, instance, self._vm) 1127 node, ret = t_instance.call(self._node, t_instance.to_binding(self._node), 1128 function.Args(posargs=())) 1129 self.assertIs(node, self._node) 1130 retval, = ret.data 1131 self.assertIs(retval, self._vm.convert.empty) 1132 1133 def test_call_type_parameter_instance_with_wrong_args(self): 1134 instance = abstract.Instance(self._vm.convert.list_type, self._vm) 1135 instance.merge_instance_type_parameter( 1136 self._vm.root_node, abstract_utils.T, 1137 self._vm.convert.int_type.to_variable(self._vm.root_node)) 1138 t = abstract.TypeParameter(abstract_utils.T, self._vm) 1139 t_instance = abstract.TypeParameterInstance(t, instance, self._vm) 1140 posargs = (self._vm.new_unsolvable(self._node),) * 3 1141 node, ret = t_instance.call(self._node, t_instance.to_binding(self._node), 1142 function.Args(posargs=posargs)) 1143 self.assertIs(node, self._node) 1144 self.assertTrue(ret.bindings) 1145 error, = self._vm.errorlog 1146 self.assertEqual(error.name, "wrong-arg-count") 1147 1148 def test_instantiate_tuple_class_for_sub(self): 1149 type_param = abstract.TypeParameter(abstract_utils.K, self._vm) 1150 cls = abstract.TupleClass( 1151 self._vm.convert.tuple_type, 1152 {0: type_param, abstract_utils.T: type_param}, self._vm) 1153 # Instantiate the tuple class. 1154 subst_value = cls.instantiate(self._vm.root_node, 1155 abstract_utils.DUMMY_CONTAINER) 1156 # Recover the class from the instance. 1157 subbed_cls = self._vm.annotations_util.sub_one_annotation( 1158 self._vm.root_node, type_param, [{ 1159 abstract_utils.K: subst_value 1160 }]) 1161 self.assertEqual(cls, subbed_cls) 1162 1163 def test_singleton(self): 1164 self.assertIs(abstract.Unsolvable(self._vm), abstract.Unsolvable(self._vm)) 1165 1166 def test_singleton_subclass(self): 1167 self.assertIs(abstract.Empty(self._vm), abstract.Empty(self._vm)) 1168 self.assertIsNot(abstract.Deleted(self._vm), abstract.Empty(self._vm)) 1169 1170 1171if __name__ == "__main__": 1172 unittest.main() 1173