Esempio n. 1
0
 def test_named_type_with_module(self):
   """Test NamedTypeWithModule()."""
   self.assertEqual(pytd_utils.NamedTypeWithModule("name"),
                    pytd.NamedType("name"))
   self.assertEqual(pytd_utils.NamedTypeWithModule("name", None),
                    pytd.NamedType("name"))
   self.assertEqual(pytd_utils.NamedTypeWithModule("name", "package"),
                    pytd.NamedType("package.name"))
Esempio n. 2
0
  def value_instance_to_pytd_type(self, node, v, instance, seen, view):
    """Get the PyTD type an instance of this object would have.

    Args:
      node: The node.
      v: The object.
      instance: The instance.
      seen: Already seen instances.
      view: A Variable -> binding map.

    Returns:
      A PyTD type.
    """
    if isinstance(v, abstract.Union):
      return pytd.UnionType(tuple(
          self.value_instance_to_pytd_type(node, t, instance, seen, view)
          for t in v.options))
    elif isinstance(v, abstract.AnnotationContainer):
      return self.value_instance_to_pytd_type(
          node, v.base_cls, instance, seen, view)
    elif isinstance(v, mixin.Class):
      if not self._detailed and v.official_name is None:
        return pytd.AnythingType()
      if seen is None:
        # We make the set immutable to ensure that the seen instances for
        # different parameter values don't interfere with one another.
        seen = frozenset()
      if instance in seen:
        # We have a circular dependency in our types (e.g., lst[0] == lst). Stop
        # descending into the type parameters.
        type_params = ()
      else:
        type_params = tuple(t.name for t in v.template)
      if instance is not None:
        seen |= {instance}
      type_arguments = self._value_to_parameter_types(
          node, v, instance, type_params, seen, view)
      base = pytd_utils.NamedTypeWithModule(v.official_name or v.name, v.module)
      if self._is_tuple(v, instance):
        if type_arguments:
          homogeneous = False
        else:
          homogeneous = True
          type_arguments = [pytd.NothingType()]
      elif v.full_name == "typing.Callable":
        homogeneous = not isinstance(v, abstract.CallableClass)
      else:
        homogeneous = len(type_arguments) == 1
      return pytd_utils.MakeClassOrContainerType(
          base, type_arguments, homogeneous)
    elif isinstance(v, abstract.TypeParameter):
      # We generate the full definition because, if this type parameter is
      # imported, we will need the definition in order to declare it later.
      return self._typeparam_to_def(node, v, v.name)
    elif isinstance(v, typing_overlay.NoReturn):
      return pytd.NothingType()
    else:
      log.info("Using ? for instance of %s", v.name)
      return pytd.AnythingType()
Esempio n. 3
0
    def value_instance_to_pytd_type(self, node, v, instance, seen, view):
        """Get the PyTD type an instance of this object would have.

    Args:
      node: The node.
      v: The object.
      instance: The instance.
      seen: Already seen instances.
      view: A Variable -> binding map.

    Returns:
      A PyTD type.
    """
        if isinstance(v, abstract.Union):
            return pytd.UnionType(
                tuple(
                    self.value_instance_to_pytd_type(node, t, instance, seen,
                                                     view) for t in v.options))
        elif isinstance(v, abstract.AnnotationContainer):
            return self.value_instance_to_pytd_type(node, v.base_cls, instance,
                                                    seen, view)
        elif isinstance(v, abstract.LiteralClass):
            if not v.value:
                # TODO(b/173742489): Remove this workaround once we support literal
                # enums.
                return pytd.AnythingType()
            if isinstance(v.value.pyval, (str, bytes)):
                # Strings are stored as strings of their representations, prefix and
                # quotes and all.
                value = repr(v.value.pyval)
            elif isinstance(v.value.pyval, bool):
                # True and False are stored as pytd constants.
                value = self.vm.lookup_builtin(f"builtins.{v.value.pyval}")
            else:
                # Ints are stored as their literal values. Note that Literal[None] or a
                # nested literal will never appear here, since we simplified it to None
                # or unnested it, respectively, in typing_overlay. Literal[<enum>] does
                # not appear here yet because it is unsupported.
                assert isinstance(v.value.pyval, int), v.value.pyval
                value = v.value.pyval
            return pytd.Literal(value)
        elif isinstance(v, class_mixin.Class):
            if not self._detailed and v.official_name is None:
                return pytd.AnythingType()
            if seen is None:
                # We make the set immutable to ensure that the seen instances for
                # different parameter values don't interfere with one another.
                seen = frozenset()
            if instance in seen:
                # We have a circular dependency in our types (e.g., lst[0] == lst). Stop
                # descending into the type parameters.
                type_params = ()
            else:
                type_params = tuple(t.name for t in v.template)
            if instance is not None:
                seen |= {instance}
            type_arguments = self._value_to_parameter_types(
                node, v, instance, type_params, seen, view)
            base = pytd_utils.NamedTypeWithModule(v.official_name or v.name,
                                                  v.module)
            if self._is_tuple(v, instance):
                homogeneous = False
            elif v.full_name == "typing.Callable":
                homogeneous = not isinstance(v, abstract.CallableClass)
            else:
                homogeneous = len(type_arguments) == 1
            return pytd_utils.MakeClassOrContainerType(base, type_arguments,
                                                       homogeneous)
        elif isinstance(v, abstract.TypeParameter):
            # We generate the full definition because, if this type parameter is
            # imported, we will need the definition in order to declare it later.
            return self._typeparam_to_def(node, v, v.name)
        elif isinstance(v, typing_overlay.NoReturn):
            return pytd.NothingType()
        else:
            log.info("Using Any for instance of %s", v.name)
            return pytd.AnythingType()