예제 #1
0
 def _create_new_unknown_value(self, action):
   if not action or not self.ctx.vm.frame:
     return abstract.Unknown(self.ctx)
   # We allow only one Unknown at each point in the program, regardless of
   # what the call stack is.
   key = ("unknown", self.ctx.vm.frame.current_opcode, action)
   if key not in self._convert_cache:
     self._convert_cache[key] = abstract.Unknown(self.ctx)
   return self._convert_cache[key]
예제 #2
0
 def test_call_single_bindings(self):
   right = self.new_var(self._str_class)
   left = self.new_var(self._str)
   self.assert_call({self._ctx.convert.true: {"left:0 right:0"}}, left, right)
   left = self.new_var(self._int)
   self.assert_call({self._ctx.convert.false: {"left:0 right:0"}}, left, right)
   left = self.new_var(abstract.Unknown(self._ctx))
   self.assert_call(
       {self._bool: {"left:0 right:0"}},
       left, right)
예제 #3
0
 def test_call_wrong_keywords(self):
   self._ctx.vm.push_frame(frame_state.SimpleFrame())
   x = self.new_var(abstract.Unknown(self._ctx))
   node, result = self._is_instance.call(
       self._node, None, function.Args(
           (x, x), self.new_dict(foo=x), None, None))
   self.assertEqual(self._node, node)
   self.assertIsInstance(abstract_utils.get_atomic_value(result),
                         abstract.Unsolvable)
   self.assertRegex(
       str(self._ctx.errorlog), r"foo.*isinstance.*\[wrong-keyword-args\]")
예제 #4
0
  def test_flatten(self):
    def maybe_var(v):
      return v if isinstance(v, cfg.Variable) else self.new_var(v)

    def new_tuple(*args):
      pyval = tuple(maybe_var(a) for a in args)
      return self._ctx.convert.tuple_to_value(pyval)

    def check(expected_ambiguous, expected_classes, value):
      classes = []
      ambiguous = abstract_utils.flatten(value, classes)
      self.assertEqual(expected_ambiguous, ambiguous)
      self.assertEqual(expected_classes, classes)

    unknown = abstract.Unknown(self._ctx)

    # Simple values.
    check(False, [self._str_class], self._str_class)
    check(True, [], self._str)
    check(True, [], unknown)

    # (str, int)
    check(False, [self._str_class, self._int_class],
          new_tuple(self._str_class, self._int_class))
    # (str, ?, int)
    check(True, [self._str_class, self._int_class],
          new_tuple(self._str_class, unknown, self._int_class))
    # (str, (int, object))
    check(False, [self._str_class, self._int_class, self._obj_class],
          new_tuple(
              self._str_class,
              new_tuple(self._int_class, self._obj_class)))
    # (str, (?, object))
    check(True, [self._str_class, self._obj_class],
          new_tuple(
              self._str_class,
              new_tuple(unknown, self._obj_class)))
    # A variable with multiple bindings is ambiguous.
    # (str, int | object)
    check(True, [self._str_class],
          new_tuple(self._str_class,
                    self.new_var(self._int_class, self._obj_class)))
예제 #5
0
  def test_is_instance(self):
    def check(expected, left, right):
      self.assertEqual(expected, self._is_instance._is_instance(left, right))

    # Unknown and Unsolvable are ambiguous.
    check(None, abstract.Unknown(self._ctx), self._obj_class)
    check(None, abstract.Unsolvable(self._ctx), self._obj_class)

    # If the object's class has multiple bindings, result is ambiguous.
    obj = abstract.SimpleValue("foo", self._ctx)
    check(None, obj, self._obj_class)
    obj.set_class(self._node, self.new_var(
        self._str_class, self._int_class))
    check(None, obj, self._str_class)

    # If the class_spec is not a class, result is ambiguous.
    check(None, self._str, self._str)

    # Result is True/False depending on if the class is in the object's mro.
    check(True, self._str, self._obj_class)
    check(True, self._str, self._str_class)
    check(False, self._str, self._int_class)
예제 #6
0
 def setUp(self):
     super().setUp()
     self._var = self._program.NewVariable()
     self._var.AddBinding(abstract.Unknown(self._ctx), [], self._node)
예제 #7
0
 def test_compatible_with__after_unknown_update(self):
     # Updating an empty dict with an unknown value makes the former ambiguous.
     self._d.update(self._node, abstract.Unknown(self._ctx))
     self.assertAmbiguous(self._d)