コード例 #1
0
ファイル: types.py プロジェクト: Global19/pytype
 def to_pytd_literal(self):
   """Make a pytd node from Literal[self.value]."""
   if self.value is None:
     return pytd.NamedType("None")
   if self.type in _STRING_TYPES:
     val = self.repr_str()
   elif self.type == "float":
     raise ParseError(f"Invalid type `float` in Literal[{self.value}].")
   else:
     val = self.value
   return pytd.Literal(val)
コード例 #2
0
 def visit_AnnAssign(self, node):
   self.convert_node_annotations(node)
   name = node.target.id
   typ = node.annotation
   val = self.convert_node(node.value)
   msg = f"Default value for {name}: {typ.name} can only be '...', got {val}"
   if typ.name and pytd_utils.MatchesFullName(typ, _FINAL_IDS):
     if isinstance(node.value, types.Pyval):
       # to_pytd_literal raises an exception if the value is a float, but
       # checking upfront allows us to generate a nicer error message.
       if isinstance(node.value.value, float):
         msg = (f"Default value for {name}: Final can only be '...' or a "
                f"legal Literal parameter, got {val}")
       else:
         typ = node.value.to_pytd_literal()
         val = pytd.AnythingType()
     elif isinstance(val, pytd.NamedType):
       typ = pytd.Literal(val)
       val = pytd.AnythingType()
   if val and not types.is_any(val):
     raise ParseError(msg)
   return pytd.Constant(name, typ, val)
コード例 #3
0
ファイル: output.py プロジェクト: mic1234/pytype
    def value_to_pytd_type(self, node, v, seen, view):
        """Get a PyTD type representing this object, as seen at a node.

    Args:
      node: The node from which we want to observe this object.
      v: The object.
      seen: The set of values seen before while computing the type.
      view: A Variable -> binding map.

    Returns:
      A PyTD type.
    """
        if isinstance(v, (abstract.Empty, typing_overlay.NoReturn)):
            return pytd.NothingType()
        elif isinstance(v, abstract.TypeParameterInstance):
            if v.module in self._scopes:
                return self._typeparam_to_def(node, v.param, v.param.name)
            elif v.instance.get_instance_type_parameter(v.full_name).bindings:
                # The type parameter was initialized. Set the view to None, since we
                # don't include v.instance in the view.
                return pytd_utils.JoinTypes(
                    self.value_to_pytd_type(node, p, seen, None) for p in
                    v.instance.get_instance_type_parameter(v.full_name).data)
            elif v.param.constraints:
                return pytd_utils.JoinTypes(
                    self.value_instance_to_pytd_type(node, p, None, seen, view)
                    for p in v.param.constraints)
            elif v.param.bound:
                return self.value_instance_to_pytd_type(
                    node, v.param.bound, None, seen, view)
            else:
                return pytd.AnythingType()
        elif isinstance(v, typing_overlay.TypeVar):
            return pytd.NamedType("builtins.type")
        elif isinstance(v, dataclass_overlay.FieldInstance):
            if not v.default:
                return pytd.AnythingType()
            return pytd_utils.JoinTypes(
                self.value_to_pytd_type(node, d, seen, view)
                for d in v.default.data)
        elif isinstance(v, abstract.FUNCTION_TYPES):
            try:
                signatures = abstract_utils.get_signatures(v)
            except NotImplementedError:
                return pytd.NamedType("typing.Callable")
            if len(signatures) == 1:
                val = self.signature_to_callable(signatures[0])
                if not isinstance(
                        v, abstract.PYTD_FUNCTION_TYPES) or not val.formal:
                    # This is a workaround to make sure we don't put unexpected type
                    # parameters in call traces.
                    return self.value_instance_to_pytd_type(
                        node, val, None, seen, view)
            return pytd.NamedType("typing.Callable")
        elif isinstance(v, (abstract.ClassMethod, abstract.StaticMethod)):
            return self.value_to_pytd_type(node, v.method, seen, view)
        elif isinstance(v, (special_builtins.IsInstance,
                            special_builtins.ClassMethodCallable)):
            return pytd.NamedType("typing.Callable")
        elif isinstance(v, class_mixin.Class):
            param = self.value_instance_to_pytd_type(node, v, None, seen, view)
            return pytd.GenericType(base_type=pytd.NamedType("builtins.type"),
                                    parameters=(param, ))
        elif isinstance(v, abstract.Module):
            return pytd.NamedType("builtins.module")
        elif (self._output_mode >= Converter.OutputMode.LITERAL
              and isinstance(v, abstract.ConcreteValue)
              and isinstance(v.pyval, (int, str, bytes))):
            # LITERAL mode is used only for pretty-printing, so we just stringify the
            # inner value rather than properly converting it.
            return pytd.Literal(repr(v.pyval))
        elif isinstance(v, abstract.SimpleValue):
            if v.cls:
                ret = self.value_instance_to_pytd_type(node,
                                                       v.cls,
                                                       v,
                                                       seen=seen,
                                                       view=view)
                ret.Visit(
                    visitors.FillInLocalPointers(
                        {"builtins": self.vm.loader.builtins}))
                return ret
            else:
                # We don't know this type's __class__, so return AnythingType to
                # indicate that we don't know anything about what this is.
                # This happens e.g. for locals / globals, which are returned from the
                # code in class declarations.
                log.info("Using Any for %s", v.name)
                return pytd.AnythingType()
        elif isinstance(v, abstract.Union):
            opts = []
            for o in v.options:
                # NOTE: Guarding printing of type parameters behind _detailed until
                # round-tripping is working properly.
                if self._detailed and isinstance(o, abstract.TypeParameter):
                    opt = self._typeparam_to_def(node, o, o.name)
                else:
                    opt = self.value_to_pytd_type(node, o, seen, view)
                opts.append(opt)
            return pytd.UnionType(tuple(opts))
        elif isinstance(v, special_builtins.SuperInstance):
            return pytd.NamedType("builtins.super")
        elif isinstance(v, abstract.TypeParameter):
            # Arguably, the type of a type parameter is NamedType("typing.TypeVar"),
            # but pytype doesn't know how to handle that, so let's just go with Any
            # unless self._detailed is set.
            if self._detailed:
                return pytd.NamedType("typing.TypeVar")
            else:
                return pytd.AnythingType()
        elif isinstance(v, abstract.Unsolvable):
            return pytd.AnythingType()
        elif isinstance(v, abstract.Unknown):
            return pytd.NamedType(v.class_name)
        elif isinstance(v, abstract.BuildClass):
            return pytd.NamedType("typing.Callable")
        else:
            raise NotImplementedError(v.__class__.__name__)
コード例 #4
0
ファイル: output.py プロジェクト: mic1234/pytype
    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()
コード例 #5
0
ファイル: output.py プロジェクト: astroparam/pytype
    def value_to_pytd_type(self, node, v, seen, view):
        """Get a PyTD type representing this object, as seen at a node.

    Args:
      node: The node from which we want to observe this object.
      v: The object.
      seen: The set of values seen before while computing the type.
      view: A Variable -> binding map.

    Returns:
      A PyTD type.
    """
        if isinstance(v, (abstract.Empty, typing_overlay.NoReturn)):
            return pytd.NothingType()
        elif isinstance(v, abstract.TypeParameterInstance):
            if (v.module in self._scopes
                    or v.instance is abstract_utils.DUMMY_CONTAINER):
                return self._typeparam_to_def(node, v.param, v.param.name)
            elif v.instance.get_instance_type_parameter(v.full_name).bindings:
                # The type parameter was initialized. Set the view to None, since we
                # don't include v.instance in the view.
                return pytd_utils.JoinTypes(
                    self.value_to_pytd_type(node, p, seen, None) for p in
                    v.instance.get_instance_type_parameter(v.full_name).data)
            elif v.param.constraints:
                return pytd_utils.JoinTypes(
                    self.value_instance_to_pytd_type(node, p, None, seen, view)
                    for p in v.param.constraints)
            elif v.param.bound:
                return self.value_instance_to_pytd_type(
                    node, v.param.bound, None, seen, view)
            else:
                return pytd.AnythingType()
        elif isinstance(v, typing_overlay.TypeVar):
            return pytd.NamedType("builtins.type")
        elif isinstance(v, dataclass_overlay.FieldInstance):
            if not v.default:
                return pytd.AnythingType()
            return pytd_utils.JoinTypes(
                self.value_to_pytd_type(node, d, seen, view)
                for d in v.default.data)
        elif isinstance(v, attr_overlay.AttribInstance):
            ret = self.value_to_pytd_type(node, v.typ, seen, view)
            md = metadata.to_pytd(v.to_metadata())
            return pytd.Annotated(ret, ("'pytype_metadata'", md))
        elif isinstance(v, special_builtins.PropertyInstance):
            return pytd.NamedType("builtins.property")
        elif isinstance(v, typed_dict.TypedDict):
            return pytd.NamedType(v.props.name)
        elif isinstance(v, abstract.FUNCTION_TYPES):
            try:
                signatures = function.get_signatures(v)
            except NotImplementedError:
                return pytd.NamedType("typing.Callable")
            if len(signatures) == 1:
                val = self.signature_to_callable(signatures[0])
                if not isinstance(
                        v, abstract.PYTD_FUNCTION_TYPES) or not val.formal:
                    # This is a workaround to make sure we don't put unexpected type
                    # parameters in call traces.
                    return self.value_instance_to_pytd_type(
                        node, val, None, seen, view)
            return pytd.NamedType("typing.Callable")
        elif isinstance(v, (abstract.ClassMethod, abstract.StaticMethod)):
            return self.value_to_pytd_type(node, v.method, seen, view)
        elif isinstance(v, (special_builtins.IsInstance,
                            special_builtins.ClassMethodCallable)):
            return pytd.NamedType("typing.Callable")
        elif isinstance(v, abstract.Class):
            param = self.value_instance_to_pytd_type(node, v, None, seen, view)
            return pytd.GenericType(base_type=pytd.NamedType("builtins.type"),
                                    parameters=(param, ))
        elif isinstance(v, abstract.Module):
            return pytd.Alias(v.name,
                              pytd.Module(v.name, module_name=v.full_name))
        elif (self._output_mode >= Converter.OutputMode.LITERAL
              and isinstance(v, abstract.ConcreteValue)
              and isinstance(v.pyval, (int, str, bytes))):
            # LITERAL mode is used only for pretty-printing, so we just stringify the
            # inner value rather than properly converting it.
            return pytd.Literal(repr(v.pyval))
        elif isinstance(v, abstract.SimpleValue):
            ret = self.value_instance_to_pytd_type(node,
                                                   v.cls,
                                                   v,
                                                   seen=seen,
                                                   view=view)
            ret.Visit(
                visitors.FillInLocalPointers(
                    {"builtins": self.ctx.loader.builtins}))
            return ret
        elif isinstance(v, abstract.Union):
            return pytd_utils.JoinTypes(
                self.value_to_pytd_type(node, o, seen, view)
                for o in v.options)
        elif isinstance(v, special_builtins.SuperInstance):
            return pytd.NamedType("builtins.super")
        elif isinstance(v, abstract.TypeParameter):
            # Arguably, the type of a type parameter is NamedType("typing.TypeVar"),
            # but pytype doesn't know how to handle that, so let's just go with Any
            # unless self._detailed is set.
            if self._detailed:
                return pytd.NamedType("typing.TypeVar")
            else:
                return pytd.AnythingType()
        elif isinstance(v, abstract.Unsolvable):
            return pytd.AnythingType()
        elif isinstance(v, abstract.Unknown):
            return pytd.NamedType(v.class_name)
        elif isinstance(v, abstract.BuildClass):
            return pytd.NamedType("typing.Callable")
        elif isinstance(v, abstract.FinalAnnotation):
            param = self.value_to_pytd_type(node, v.annotation, seen, view)
            return pytd.GenericType(base_type=pytd.NamedType("typing.Final"),
                                    parameters=(param, ))
        else:
            raise NotImplementedError(v.__class__.__name__)