Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
data.append(pytd.Constant(name, t))
for name, var in defs.items():
if name in output.TOP_LEVEL_IGNORE or self._is_builtin(name, var.data):
continue
options = []
for value, is_annotation in pytd_convert.get_annotated_values(
self.exitpoint, name, var, annots):
if is_annotation:
data.append(pytd.Constant(name, value))
else:
options.append(value)
if (len(options) > 1 and
not all(isinstance(o, abstract.FUNCTION_TYPES) for o in options)):
# It's ambiguous whether this is a type, a function or something
# else, so encode it as a constant.
combined_types = pytd_utils.JoinTypes(t.to_type(self.exitpoint)
for t in options)
data.append(pytd.Constant(name, combined_types))
elif options:
for option in options:
try:
d = option.to_pytd_def(self.exitpoint, name) # Deep definition
except NotImplementedError:
d = option.to_type(self.exitpoint) # Type only
if isinstance(d, pytd.NothingType):
if isinstance(option, abstract.Empty):
d = pytd.AnythingType()
else:
assert isinstance(option, typing_overlay.NoReturn)
if isinstance(d, pytd.Type) and not isinstance(d, pytd.TypeParameter):
data.append(pytd.Constant(name, d))
else:
def _call_traces_to_function(call_traces, name_transform=lambda x: x):
funcs = collections.defaultdict(pytd_utils.OrderedSet)
for node, func, sigs, args, kws, retvar in call_traces:
# The lengths may be different in the presence of optional and kw args.
arg_names = max((sig.get_positional_names() for sig in sigs), key=len)
for i in range(len(arg_names)):
if not isinstance(func.data, abstract.BoundFunction) or i > 0:
arg_names[i] = function.argname(i)
arg_types = (a.data.to_type(node) for a in args)
ret = pytd_utils.JoinTypes(t.to_type(node) for t in retvar.data)
# TODO(kramm): Record these:
starargs = None
starstarargs = None
funcs[func.data.name].add(pytd.Signature(
tuple(pytd.Parameter(n, t, False, False, None)
for n, t in zip(arg_names, arg_types)) +
tuple(pytd.Parameter(name, a.data.to_type(node), False, False, None)
for name, a in kws),
starargs, starstarargs,
ret, exceptions=(), template=()))
functions = []
for name, signatures in funcs.items():
functions.append(pytd.Function(name_transform(name), tuple(signatures),
pytd.METHOD))
return functions
def _check_return(self, node, actual, formal, frames):
bad = self.matcher.bad_matches(actual, formal, node)
if bad:
with self.convert.pytd_convert.produce_detailed_output():
combined = pytd_utils.JoinTypes(
view[actual].data.to_type(node, view=view) for view in bad)
self.errorlog.bad_return_type(
frames, combined, formal.get_instance_type(node))
def get_function_params(pytd_fn):
"""Collect function param types from pytype."""
# We have turned call records on in the indexer, so a function will have a
# pytd signature for every tuple of call args. Here we iterate through those
# signatures and set every param's type to the union of every non-"unknown"
# call type for that param.
params = collections.OrderedDict()
for sig in pytd_fn.signatures:
for p in sig.params:
if p.name not in params:
params[p.name] = []
if '~unknown' not in str(p.type):
params[p.name].append(p.type)
for k in params:
params[k] = pytd_utils.JoinTypes(params[k])
return [(k, unwrap_type(v)) for k, v in params.items()]
def convert_string_type_list(types_as_string, unknown, mapping,
global_lookup, depth=0):
"""Like convert_string_type, but operate on a list."""
if not types_as_string or booleq.Solver.ANY_VALUE in types_as_string:
# If we didn't find a solution for a type (the list of matches is empty)
# then report it as "?", not as "nothing", because the latter is confusing.
return pytd.AnythingType()
return pytd_utils.JoinTypes(convert_string_type(type_as_string, unknown,
mapping, global_lookup, depth)
for type_as_string in types_as_string)
def VisitUnionType(self, union):
c = collections.Counter()
for t in set(union.type_list):
# TODO(rechen): How can we make this work with GenericType?
if isinstance(t, pytd.GENERIC_BASE_TYPE):
c += collections.Counter(self.hierarchy.ExpandSubClasses(str(t)))
# Below, c[str[t]] can be zero - that's the default for non-existent items
# in collections.Counter. It'll happen for types that are not
# instances of GENERIC_BASE_TYPE, like container types.
new_type_list = [t for t in union.type_list if c[str(t)] <= 1]
return pytd_utils.JoinTypes(new_type_list)
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.
# See the ParameterizedClass.formal_type_parameters() property.
type_parameters = abstract_utils.LazyFormalTypeParameters(
template, parameters, subst)
return abstract_class(base_cls, type_parameters, self.vm)
elif isinstance(pyval, pytd.Literal):
elif isinstance(v, abstract.CallableClass):
param_values = v.get_formal_type_parameter(t).instantiate(
node or self.vm.root_cfg_node).data
else:
param_values = [self.vm.convert.unsolvable]
if (param_values == [self.vm.convert.unsolvable] and
isinstance(v, abstract.ParameterizedClass) and
not self.vm.annotations_util.get_type_parameters(
v.get_formal_type_parameter(t))):
# When the instance's parameter value is unsolvable, we can get a
# more precise type from the class. Note that we need to be careful
# not to introduce unbound type parameters.
arg = self.value_instance_to_pytd_type(
node, v.get_formal_type_parameter(t), None, seen, view)
else:
arg = pytd_utils.JoinTypes(self.value_to_pytd_type(
node, p, seen, view) for p in param_values)
type_arguments.append(arg)
return type_arguments
else:
return [pytd.AnythingType() for _ in template]