Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
elif isinstance(v, abstract.SimpleAbstractValue):
if v.cls:
ret = self.value_instance_to_pytd_type(
node, v.cls, v, seen=seen, view=view)
ret.Visit(visitors.FillInLocalPointers(
{"__builtin__": 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 ? for %s", v.name)
return pytd.AnythingType()
elif isinstance(v, abstract.Union):
return pytd.UnionType(tuple(self.value_to_pytd_type(node, o, seen, view)
for o in v.options))
elif isinstance(v, special_builtins.SuperInstance):
return pytd.NamedType("__builtin__.super")
elif isinstance(v, (abstract.Unsolvable, 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.
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__)
if not isinstance(actual, pytd.ClassType):
return self.unsolvable
base = actual.cls
else:
assert isinstance(pyval.base_type, pytd.ClassType)
base = pyval.base_type.cls
assert isinstance(base, pytd.Class), base
base_cls = self.constant_to_value(
base, subst, self.vm.root_cfg_node)
if not isinstance(base_cls, mixin.Class):
# base_cls can be, e.g., an unsolvable due to an mro error.
return self.unsolvable
if isinstance(pyval, pytd.TupleType):
abstract_class = abstract.TupleClass
template = list(range(len(pyval.parameters))) + [abstract_utils.T]
parameters = pyval.parameters + (pytd.UnionType(pyval.parameters),)
elif isinstance(pyval, pytd.CallableType):
abstract_class = abstract.CallableClass
template = list(range(len(pyval.args))) + [abstract_utils.ARGS,
abstract_utils.RET]
parameters = pyval.args + (pytd_utils.JoinTypes(pyval.args), pyval.ret)
else:
abstract_class = abstract.ParameterizedClass
if pyval.base_type.name == "typing.Generic":
pyval_template = pyval.parameters
else:
pyval_template = base.template
template = tuple(t.name for t in pyval_template)
parameters = pyval.parameters
assert (pyval.base_type.name == "typing.Generic" or
len(parameters) <= len(template))
# Delay type parameter loading to handle recursive types.
# compat_list :: [(compat, name)], where name is the more generalized
# type and compat is the less generalized one. (eg: name = float, compat =
# int)
compat_list = itertools.chain(
set((v, v) for _, v in pep484.COMPAT_ITEMS), pep484.COMPAT_ITEMS)
for compat, name in compat_list:
prefix = builtins.name + "."
full_name = prefix + compat
t = builtins.Lookup(full_name)
if isinstance(t, pytd.Class):
# Depending on python version, bytes can be an Alias, if so don't
# want it in our union
rmap[prefix + name].append(pytd.ClassType(full_name, t))
return {k: pytd.UnionType(tuple(v)) for k, v in six.iteritems(rmap)}
def unwrap_type(typ):
if isinstance(typ, (pytd.ClassType, pytd.NamedType)):
typ_name = typ.name
elif isinstance(typ, pytd.UnionType):
typ_name = 'Union[' + ', '.join(unwrap_type(t) for t in typ.type_list) + ']'
elif isinstance(typ, pytd.AnythingType):
typ_name = 'typing.Any'
else:
typ_name = pytd_utils.Print(typ)
return unknown_to_any(typ_name)
# The class itself doesn't have this method, but base classes might.
# TODO(kramm): This should do MRO order, not depth-first.
for base in cls2.parents:
if isinstance(base, pytd.AnythingType):
# AnythingType can contain any method. However, that would mean that
# a class that inherits from AnythingType contains any method
# imaginable, and hence is a match for anything. To prevent the bad
# results caused by that, return FALSE here.
return booleq.FALSE
elif isinstance(base, (pytd.ClassType, pytd.GenericType)):
if isinstance(base, pytd.ClassType):
cls = base.cls
values = tuple(pytd.AnythingType() for _ in cls.template)
elif isinstance(base, pytd.TupleType):
cls = base.base_type.cls
values = (pytd.UnionType(type_list=base.parameters),)
else:
cls = base.base_type.cls
values = base.parameters
if values:
subst = subst.copy()
for param, value in zip(cls.template, values):
subst[param.type_param] = value
implication = self.match_Function_against_Class(f1, cls, subst, cache)
if implication is not booleq.FALSE:
return implication
else:
# Funky types like UnionType are hard to match against (and shouldn't
# appear as a base class) so we treat them as catch-all.
log.warning("Assuming that %s has method %s",
pytd_utils.Print(base), f1.name)
return booleq.TRUE
def _normal_param(name, param_type, default, kwonly):
"""Return a pytd.Parameter object for a normal argument."""
if default is not None:
default_type = _type_for_default(default)
if default_type == pytd.NamedType("NoneType"):
if param_type is not None:
param_type = pytd.UnionType((param_type, default_type))
elif param_type is None:
param_type = default_type
if param_type is None:
param_type = pytd.AnythingType()
optional = default is not None
return pytd.Parameter(name, param_type, kwonly, optional, None)
def _get_parameters(self, t1, t2):
if isinstance(t1, pytd.TupleType) and isinstance(t2, pytd.TupleType):
# No change needed; the parameters will be compared element-wise.
return t1.parameters, t2.parameters
elif isinstance(t2, pytd.TupleType):
# Since we call _get_parameters after confirming that t1 and t2 have
# compatible base types, t1 is a homogeneous tuple here.
return (t1.element_type,) * len(t2.parameters), t2.parameters
elif isinstance(t1, pytd.TupleType):
return (pytd.UnionType(type_list=t1.parameters),), t2.parameters
elif (isinstance(t1, pytd.CallableType) and
isinstance(t2, pytd.CallableType)):
# Flip the arguments, since argument types are contravariant.
return t2.args + (t1.ret,), t1.args + (t2.ret,)
elif (t1.base_type.cls.name == "__builtin__.type" and
t2.base_type.cls.name == "typing.Callable"):
# We'll only check the return type, since getting the argument types for
# initializing a class is tricky.
return t1.parameters, (t2.parameters[-1],)
elif (t1.base_type.cls.name == "typing.Callable" and
t2.base_type.cls.name == "__builtin__.type"):
return (t1.parameters[-1],), t2.parameters
elif isinstance(t1, pytd.CallableType):
# We're matching against GenericType(Callable, (Any, _RET)), so we don't
# need the argument types.
return (pytd.AnythingType(), t1.ret), t2.parameters
def MakeHomogeneousContainer(self, base_type, parameters):
if parameters:
if len(parameters) > 1:
element_type = pytd.UnionType(parameters)
else:
element_type, = parameters
return pytd.HomogeneousContainerType(base_type=base_type,
parameters=(element_type,))
else:
return base_type
while queue:
t = queue.popleft()
if isinstance(t, pytd.UnionType):
queue.extendleft(reversed(t.type_list))
elif isinstance(t, pytd.NothingType):
pass
elif t not in seen:
new_types.append(t)
seen.add(t)
if len(new_types) == 1:
return new_types.pop()
elif any(isinstance(t, pytd.AnythingType) for t in new_types):
return pytd.AnythingType()
elif new_types:
return pytd.UnionType(tuple(new_types)) # tuple() to make unions hashable
else:
return pytd.NothingType()