1"""Utilities for abstract.py."""
2
3import collections
4import hashlib
5import logging
6from typing import Any, Collection, Dict, Iterable, Mapping, Optional, Sequence, Tuple, Union
7
8from pytype import datatypes
9from pytype import utils
10from pytype.pyc import opcodes
11from pytype.pyc import pyc
12from pytype.pytd import mro
13from pytype.typegraph import cfg
14from pytype.typegraph import cfg_utils
15
16log = logging.getLogger(__name__)
17
18# We can't import abstract here due to a circular dep.
19_BaseValue = Any  # abstract.BaseValue
20_TypeParameter = Any  # abstract.TypeParameter
21
22# Type parameter names matching the ones in builtins.pytd and typing.pytd.
23T = "_T"
24T2 = "_T2"
25K = "_K"
26V = "_V"
27ARGS = "_ARGS"
28RET = "_RET"
29
30# TODO(rechen): Stop supporting all variants except _HAS_DYNAMIC_ATTRIBUTES.
31DYNAMIC_ATTRIBUTE_MARKERS = [
32    "HAS_DYNAMIC_ATTRIBUTES",
33    "_HAS_DYNAMIC_ATTRIBUTES",
34    "has_dynamic_attributes",
35]
36
37# A dummy container object for use in instantiating type parameters.
38# A container is needed to preserve type parameter names for error messages
39# and for sub_(one_)annotation(s).
40DUMMY_CONTAINER = object()
41
42# Names defined on every module/class that should be ignored in most cases.
43TOP_LEVEL_IGNORE = frozenset({
44    "__builtins__",
45    "__doc__",
46    "__file__",
47    "__future__",
48    "__module__",
49    "__name__",
50    "__annotations__",
51    "google_type_annotations",
52})
53CLASS_LEVEL_IGNORE = frozenset({
54    "__builtins__",
55    "__class__",
56    "__module__",
57    "__name__",
58    "__qualname__",
59    "__slots__",
60    "__annotations__",
61})
62
63
64class ConversionError(ValueError):
65  pass
66
67
68class EvaluationError(Exception):
69  """Used to signal an errorlog error during type name evaluation."""
70
71  @property
72  def errors(self):
73    return utils.message(self)
74
75  @property
76  def details(self):
77    return "\n".join(error.message for error in self.errors)
78
79
80class GenericTypeError(Exception):
81  """The error for user-defined generic types."""
82
83  def __init__(self, annot, error):
84    super().__init__(annot, error)
85    self.annot = annot
86    self.error = error
87
88
89class AsInstance:
90  """Wrapper, used for marking things that we want to convert to an instance."""
91
92  def __init__(self, cls):
93    self.cls = cls
94
95
96class AsReturnValue(AsInstance):
97  """Specially mark return values, to handle NoReturn properly."""
98
99
100# For lazy evaluation of ParameterizedClass.formal_type_parameters
101LazyFormalTypeParameters = collections.namedtuple(
102    "LazyFormalTypeParameters", ("template", "parameters", "subst"))
103
104
105# Sentinel for get_atomic_value
106class _None:
107  pass
108
109
110def get_atomic_value(variable, constant_type=None, default=_None()):
111  """Get the atomic value stored in this variable."""
112  if len(variable.bindings) == 1:
113    v, = variable.bindings
114    if isinstance(v.data, constant_type or object):
115      return v.data  # success
116  if not isinstance(default, _None):
117    # If a default is specified, we return it instead of failing.
118    return default
119  # Determine an appropriate failure message.
120  if not variable.bindings:
121    raise ConversionError("Cannot get atomic value from empty variable.")
122  bindings = variable.bindings
123  name = bindings[0].data.vm.convert.constant_name(constant_type)
124  raise ConversionError(
125      "Cannot get atomic value %s from variable. %s %s"
126      % (name, variable, [b.data for b in bindings]))
127
128
129def get_atomic_python_constant(variable, constant_type=None):
130  """Get the concrete atomic Python value stored in this variable.
131
132  This is used for things that are stored in cfg.Variable, but we
133  need the actual data in order to proceed. E.g. function / class definitions.
134
135  Args:
136    variable: A cfg.Variable. It can only have one possible value.
137    constant_type: Optionally, the required type of the constant.
138  Returns:
139    A Python constant. (Typically, a string, a tuple, or a code object.)
140  Raises:
141    ConversionError: If the value in this Variable is purely abstract, i.e.
142      doesn't store a Python value, or if it has more than one possible value.
143  """
144  atomic = get_atomic_value(variable)
145  return atomic.vm.convert.value_to_constant(atomic, constant_type)
146
147
148def get_views(variables, node):
149  """Get all possible views of the given variables at a particular node.
150
151  For performance reasons, this method uses node.CanHaveCombination for
152  filtering. For a more precise check, you can call
153  node.HasCombination(list(view.values())). Do so judiciously, as the latter
154  method can be very slow.
155
156  This function can be used either as a regular generator or in an optimized way
157  to yield only functionally unique views:
158    views = get_views(...)
159    skip_future = None
160    while True:
161      try:
162        view = views.send(skip_future)
163      except StopIteration:
164        break
165      ...
166    The caller should set `skip_future` to True when it is safe to skip
167    equivalent future views and False otherwise.
168
169  Args:
170    variables: The variables.
171    node: The node.
172
173  Yields:
174    A datatypes.AcessTrackingDict mapping variables to bindings.
175  """
176  try:
177    combinations = cfg_utils.deep_variable_product(variables)
178  except cfg_utils.TooComplexError:
179    combinations = ((var.AddBinding(node.program.default_data, [], node)
180                     for var in variables),)
181  seen = []  # the accessed subsets of previously seen views
182  for combination in combinations:
183    view = {value.variable: value for value in combination}
184    if any(subset <= view.items() for subset in seen):
185      # Optimization: This view can be skipped because it matches the accessed
186      # subset of a previous one.
187      log.info("Skipping view (already seen): %r", view)
188      continue
189    combination = list(view.values())
190    if not node.CanHaveCombination(combination):
191      log.info("Skipping combination (unreachable): %r", combination)
192      continue
193    view = datatypes.AccessTrackingDict(view)
194    skip_future = yield view
195    if skip_future:
196      # Skip future views matching this accessed subset.
197      seen.append(view.accessed_subset.items())
198
199
200def get_signatures(func):
201  """Gets the given function's signatures."""
202  if func.isinstance_PyTDFunction():
203    return [sig.signature for sig in func.signatures]
204  elif func.isinstance_InterpreterFunction():
205    return [f.signature for f in func.signature_functions()]
206  elif func.isinstance_BoundFunction():
207    sigs = get_signatures(func.underlying)
208    return [sig.drop_first_parameter() for sig in sigs]  # drop "self"
209  elif func.isinstance_ClassMethod() or func.isinstance_StaticMethod():
210    return get_signatures(func.method)
211  elif func.isinstance_SimpleFunction():
212    return [func.signature]
213  else:
214    raise NotImplementedError(func.__class__.__name__)
215
216
217def func_name_is_class_init(name):
218  """Return True if |name| is that of a class' __init__ method."""
219  # Python 3's MAKE_FUNCTION byte code takes an explicit fully qualified
220  # function name as an argument and that is used for the function name.
221  # On the other hand, Python 2's MAKE_FUNCTION does not take any name
222  # argument so we pick the name from the code object. This name is not
223  # fully qualified. Hence, constructor names in Python 3 are fully
224  # qualified ending in '.__init__', and constructor names in Python 2
225  # are all '__init__'. So, we identify a constructor by matching its
226  # name with one of these patterns.
227  return name == "__init__" or name.endswith(".__init__")
228
229
230def equivalent_to(binding, cls):
231  """Whether binding.data is equivalent to cls, modulo parameterization."""
232  return (binding.data.isinstance_Class() and
233          binding.data.full_name == cls.full_name)
234
235
236def apply_mutations(node, get_mutations):
237  """Apply mutations yielded from a get_mutations function."""
238  log.info("Applying mutations")
239  num_mutations = 0
240  for obj, name, value in get_mutations():
241    if not num_mutations:
242      # mutations warrant creating a new CFG node
243      node = node.ConnectNew(node.name)
244    num_mutations += 1
245    obj.merge_instance_type_parameter(node, name, value)
246  log.info("Applied %d mutations", num_mutations)
247  return node
248
249
250def get_template(val):
251  """Get the value's class template."""
252  if val.isinstance_Class():
253    res = {t.full_name for t in val.template}
254    if val.isinstance_ParameterizedClass():
255      res.update(get_template(val.base_cls))
256    elif val.isinstance_PyTDClass() or val.isinstance_InterpreterClass():
257      for base in val.bases():
258        base = get_atomic_value(base, default=val.vm.convert.unsolvable)
259        res.update(get_template(base))
260    return res
261  elif val.cls:
262    return get_template(val.cls)
263  else:
264    return set()
265
266
267def get_mro_bases(bases, vm):
268  """Get bases for MRO computation."""
269  mro_bases = []
270  has_user_generic = False
271  for base_var in bases:
272    if not base_var.data:
273      continue
274    # A base class is a Variable. If it has multiple options, we would
275    # technically get different MROs. But since ambiguous base classes are rare
276    # enough, we instead just pick one arbitrary option per base class.
277    base = get_atomic_value(base_var, default=vm.convert.unsolvable)
278    mro_bases.append(base)
279    # check if it contains user-defined generic types
280    if (base.isinstance_ParameterizedClass() and
281        base.full_name != "typing.Generic"):
282      has_user_generic = True
283  # if user-defined generic type exists, we won't add `typing.Generic` to
284  # the final result list
285  if has_user_generic:
286    return [b for b in mro_bases if b.full_name != "typing.Generic"]
287  else:
288    return mro_bases
289
290
291def _merge_type(t0, t1, name, cls):
292  """Merge two types.
293
294  Rules: Type `Any` can match any type, we will return the other type if one
295  of them is `Any`. Return the sub-class if the types have inheritance
296  relationship.
297
298  Args:
299    t0: The first type.
300    t1: The second type.
301    name: Type parameter name.
302    cls: The class_mixin.Class on which any error should be reported.
303  Returns:
304    A type.
305  Raises:
306    GenericTypeError: if the types don't match.
307  """
308  if t0 is None or t0.isinstance_Unsolvable():
309    return t1
310  if t1 is None or t1.isinstance_Unsolvable():
311    return t0
312  # t0 is parent of t1
313  if t0 in t1.mro:
314    return t1
315  # t1 is parent of t0
316  if t1 in t0.mro:
317    return t0
318  raise GenericTypeError(cls, "Conflicting value for TypeVar %s" % name)
319
320
321def parse_formal_type_parameters(
322    base, prefix, formal_type_parameters, container=None):
323  """Parse type parameters from base class.
324
325  Args:
326    base: base class.
327    prefix: the full name of subclass of base class.
328    formal_type_parameters: the mapping of type parameter name to its type.
329    container: An abstract value whose class template is used when prefix=None
330      to decide how to handle type parameters that are aliased to other type
331      parameters. Values that are in the class template are kept, while all
332      others are ignored.
333
334  Raises:
335    GenericTypeError: If the lazy types of type parameter don't match
336  """
337  def merge(t0, t1, name):
338    return _merge_type(t0, t1, name, base)
339
340  if base.isinstance_ParameterizedClass():
341    if base.full_name == "typing.Generic":
342      return
343    if (base.base_cls.isinstance_InterpreterClass() or
344        base.base_cls.isinstance_PyTDClass()):
345      # merge the type parameters info from base class
346      formal_type_parameters.merge_from(
347          base.base_cls.all_formal_type_parameters, merge)
348    params = base.get_formal_type_parameters()
349    if getattr(container, "cls", None):
350      container_template = container.cls.template
351    else:
352      container_template = ()
353    for name, param in params.items():
354      if param.isinstance_TypeParameter():
355        # We have type parameter renaming, e.g.,
356        #  class List(Generic[T]): pass
357        #  class Foo(List[U]): pass
358        if prefix:
359          formal_type_parameters.add_alias(
360              name, prefix + "." + param.name, merge)
361        elif param in container_template:
362          formal_type_parameters[name] = param
363      else:
364        # We have either a non-formal parameter, e.g.,
365        # class Foo(List[int]), or a non-1:1 parameter mapping, e.g.,
366        # class Foo(List[K or V]). Initialize the corresponding instance
367        # parameter appropriately.
368        if name not in formal_type_parameters:
369          formal_type_parameters[name] = param
370        else:
371          # Two unrelated containers happen to use the same type
372          # parameter but with different types.
373          last_type = formal_type_parameters[name]
374          formal_type_parameters[name] = merge(last_type, param, name)
375  else:
376    if base.isinstance_InterpreterClass() or base.isinstance_PyTDClass():
377      # merge the type parameters info from base class
378      formal_type_parameters.merge_from(
379          base.all_formal_type_parameters, merge)
380    if base.template:
381      # handle unbound type parameters
382      for item in base.template:
383        if item.isinstance_TypeParameter():
384          # This type parameter will be set as `ANY`.
385          name = full_type_name(base, item.name)
386          if name not in formal_type_parameters:
387            formal_type_parameters[name] = None
388
389
390def full_type_name(val, name):
391  """Compute complete type parameter name with scope.
392
393  Args:
394    val: The object with type parameters.
395    name: The short type parameter name (e.g., T).
396
397  Returns:
398    The full type parameter name (e.g., List.T).
399  """
400  if val.isinstance_Instance():
401    return full_type_name(val.cls, name)
402  # The type is in current `class`
403  for t in val.template:
404    if t.name == name:
405      return val.full_name + "." + name
406    elif t.full_name == name:
407      return t.full_name
408  # The type is instantiated in `base class`
409  for t in val.all_template_names:
410    if t.split(".")[-1] == name or t == name:
411      return t
412  return name
413
414
415def maybe_extract_tuple(t):
416  """Returns a tuple of Variables."""
417  values = t.data
418  if len(values) > 1:
419    return (t,)
420  v, = values
421  if not v.isinstance_Tuple():
422    return (t,)
423  return v.pyval
424
425
426def compute_template(val):
427  """Compute the precedence list of template parameters according to C3.
428
429  1. For the base class list, if it contains `typing.Generic`, then all the
430  type parameters should be provided. That means we don't need to parse extra
431  base class and then we can get all the type parameters.
432  2. If there is no `typing.Generic`, parse the precedence list according to
433  C3 based on all the base classes.
434  3. If `typing.Generic` exists, it must contain at least one type parameters.
435  And there is at most one `typing.Generic` in the base classes. Report error
436  if the check fails.
437
438  Args:
439    val: The abstract.BaseValue to compute a template for.
440
441  Returns:
442    parsed type parameters
443
444  Raises:
445    GenericTypeError: if the type annotation for generic type is incorrect
446  """
447  if val.isinstance_PyTDClass():
448    return [val.vm.convert.constant_to_value(itm.type_param)
449            for itm in val.pytd_cls.template]
450  elif not val.isinstance_InterpreterClass():
451    return ()
452  bases = [get_atomic_value(base, default=val.vm.convert.unsolvable)
453           for base in val.bases()]
454  template = []
455
456  # Compute the number of `typing.Generic` and collect the type parameters
457  for base in bases:
458    if base.full_name == "typing.Generic":
459      if base.isinstance_PyTDClass():
460        raise GenericTypeError(val, "Cannot inherit from plain Generic")
461      if template:
462        raise GenericTypeError(
463            val, "Cannot inherit from Generic[...] multiple times")
464      for item in base.template:
465        param = base.formal_type_parameters.get(item.name)
466        template.append(param.with_module(val.full_name))
467
468  if template:
469    # All type parameters in the base classes should appear in
470    # `typing.Generic`
471    for base in bases:
472      if base.full_name != "typing.Generic":
473        if base.isinstance_ParameterizedClass():
474          for item in base.template:
475            param = base.formal_type_parameters.get(item.name)
476            if param.isinstance_TypeParameter():
477              t = param.with_module(val.full_name)
478              if t not in template:
479                raise GenericTypeError(
480                    val, "Generic should contain all the type variables")
481  else:
482    # Compute template parameters according to C3
483    seqs = []
484    for base in bases:
485      if base.isinstance_ParameterizedClass():
486        seq = []
487        for item in base.template:
488          param = base.formal_type_parameters.get(item.name)
489          if param.isinstance_TypeParameter():
490            seq.append(param.with_module(val.full_name))
491        seqs.append(seq)
492    try:
493      template.extend(mro.MergeSequences(seqs))
494    except ValueError as e:
495      raise GenericTypeError(
496          val, "Illegal type parameter order in class %s" % val.name) from e
497
498  return template
499
500
501def _hash_dict(vardict, names):
502  """Hash a dictionary.
503
504  This contains the keys and the full hashes of the data in the values.
505
506  Arguments:
507    vardict: A dictionary mapping str to Variable.
508    names: If this is non-None, the snapshot will include only those
509      dictionary entries whose keys appear in names.
510
511  Returns:
512    A hash of the dictionary.
513  """
514  if names is not None:
515    vardict = {name: vardict[name] for name in names.intersection(vardict)}
516  m = hashlib.md5()
517  for name, var in sorted(vardict.items()):
518    m.update(str(name).encode("utf-8"))
519    for value in var.bindings:
520      m.update(value.data.get_fullhash())
521  return m.digest()
522
523
524def hash_all_dicts(*hash_args):
525  """Convenience method for hashing a sequence of dicts."""
526  return hashlib.md5(b"".join(_hash_dict(*args) for args in hash_args)).digest()
527
528
529def _matches_generator(type_obj, allowed_types):
530  """Check if type_obj matches a Generator/AsyncGenerator type."""
531  if type_obj.isinstance_Union():
532    return all(_matches_generator(sub_type, allowed_types)
533               for sub_type in type_obj.options)
534  else:
535    base_cls = type_obj
536    if type_obj.isinstance_ParameterizedClass():
537      base_cls = type_obj.base_cls
538    return ((base_cls.isinstance_PyTDClass() and
539             base_cls.name in allowed_types) or
540            base_cls.isinstance_AMBIGUOUS_OR_EMPTY())
541
542
543def matches_generator(type_obj):
544  allowed_types = ("generator", "Iterable", "Iterator")
545  return _matches_generator(type_obj, allowed_types)
546
547
548def matches_async_generator(type_obj):
549  allowed_types = ("asyncgenerator", "AsyncIterable", "AsyncIterator")
550  return _matches_generator(type_obj, allowed_types)
551
552
553def var_map(func, var):
554  return (func(v) for v in var.data)
555
556
557def eval_expr(vm, node, f_globals, f_locals, expr):
558  """Evaluate an expression with the given node and globals."""
559  # This is used to resolve type comments and late annotations.
560  #
561  # We don't chain node and f_globals as we want to remain in the context
562  # where we've just finished evaluating the module. This would prevent
563  # nasty things like:
564  #
565  # def f(a: "A = 1"):
566  #   pass
567  #
568  # def g(b: "A"):
569  #   pass
570  #
571  # Which should simply complain at both annotations that 'A' is not defined
572  # in both function annotations. Chaining would cause 'b' in 'g' to yield a
573  # different error message.
574  log.info("Evaluating expr: %r", expr)
575
576  # Any errors logged here will have a filename of None and a linenumber of 1
577  # when what we really want is to allow the caller to handle/log the error
578  # themselves.  Thus we checkpoint the errorlog and then restore and raise
579  # an exception if anything was logged.
580  with vm.errorlog.checkpoint() as record:
581    try:
582      code = vm.compile_src(expr, mode="eval")
583    except pyc.CompileError as e:
584      # We keep only the error message, since the filename and line number are
585      # for a temporary file.
586      vm.errorlog.python_compiler_error(None, 0, e.error)
587      ret = vm.new_unsolvable(node)
588    else:
589      _, _, _, ret = vm.run_bytecode(node, code, f_globals, f_locals)
590  log.info("Finished evaluating expr: %r", expr)
591  if record.errors:
592    # Annotations are constants, so tracebacks aren't needed.
593    e = EvaluationError([error.drop_traceback() for error in record.errors])
594  else:
595    e = None
596  return ret, e
597
598
599def check_classes(var, check):
600  """Check whether the cls of each value in `var` is a class and passes `check`.
601
602  Args:
603    var: A cfg.Variable or empty.
604    check: (BaseValue) -> bool.
605
606  Returns:
607    Whether the check passes.
608  """
609  return var and all(
610      v.cls.isinstance_Class() and check(v.cls) for v in var.data if v.cls)
611
612
613def match_type_container(typ, container_type_name: Union[str, Tuple[str, ...]]):
614  """Unpack the type parameter from ContainerType[T]."""
615  if typ is None:
616    return None
617  if isinstance(container_type_name, str):
618    container_type_name = (container_type_name,)
619  if not (typ.isinstance_ParameterizedClass() and
620          typ.full_name in container_type_name):
621    return None
622  param = typ.get_formal_type_parameter(T)
623  return param
624
625
626def get_annotations_dict(members):
627  """Get __annotations__ from a members map.
628
629  Returns None rather than {} if the dict does not exist so that callers always
630  have a reference to the actual dictionary, and can mutate it if needed.
631
632  Args:
633    members: A dict of member name to variable
634
635  Returns:
636    members['__annotations__'] unpacked as a python dict, or None
637  """
638  if "__annotations__" not in members:
639    return None
640  annots_var = members["__annotations__"]
641  try:
642    annots = get_atomic_value(annots_var)
643  except ConversionError:
644    return None
645  return annots if annots.isinstance_AnnotationsDict() else None
646
647
648class Local:
649  """A possibly annotated local variable."""
650
651  def __init__(
652      self,
653      node,
654      op: Optional[opcodes.Opcode],
655      typ: Optional[_BaseValue],
656      orig: Optional[cfg.Variable],
657      vm):
658    self._ops = [op]
659    if typ:
660      self.typ = vm.program.NewVariable([typ], [], node)
661    else:
662      # Creating too many variables bloats the typegraph, hurting performance,
663      # so we use None instead of an empty variable.
664      self.typ = None
665    self.orig = orig
666    self.vm = vm
667
668  @property
669  def stack(self):
670    return self.vm.simple_stack(self._ops[-1])
671
672  def update(self, node, op, typ, orig):
673    """Update this variable's annotation and/or value."""
674    if op in self._ops:
675      return
676    self._ops.append(op)
677    if typ:
678      if self.typ:
679        self.typ.AddBinding(typ, [], node)
680      else:
681        self.typ = self.vm.program.NewVariable([typ], [], node)
682    if orig:
683      self.orig = orig
684
685  def get_type(self, node, name):
686    """Gets the variable's annotation."""
687    if not self.typ:
688      return None
689    values = self.typ.Data(node)
690    if len(values) > 1:
691      self.vm.errorlog.ambiguous_annotation(self.stack, values, name)
692      return self.vm.convert.unsolvable
693    elif values:
694      return values[0]
695    else:
696      return None
697
698
699def is_literal(annot: Optional[_BaseValue]):
700  if not annot:
701    return False
702  if annot.isinstance_Union():
703    return all(is_literal(o) for o in annot.options)
704  return annot.isinstance_LiteralClass()
705
706
707def is_concrete_dict(val: _BaseValue):
708  return val.isinstance_Dict() and not val.could_contain_anything
709
710
711def is_concrete_list(val: _BaseValue):
712  return val.isinstance_List() and not val.could_contain_anything
713
714
715def is_concrete(val: _BaseValue):
716  return (val.isinstance_PythonConstant() and
717          not getattr(val, "could_contain_anything", False))
718
719
720def is_indefinite_iterable(val: _BaseValue):
721  """True if val is a non-concrete instance of typing.Iterable."""
722  instance = val.isinstance_Instance()
723  concrete = is_concrete(val)
724  cls_instance = val.cls and val.cls.isinstance_Class()
725  if not (instance and cls_instance and not concrete):
726    return False
727  for cls in val.cls.mro:
728    if cls.full_name == "builtins.str":
729      return False
730    elif cls.full_name == "builtins.tuple":
731      # A tuple's cls attribute may point to either PyTDClass(tuple) or
732      # TupleClass; only the former is indefinite.
733      return cls.isinstance_PyTDClass()
734    elif cls.full_name == "typing.Iterable":
735      return True
736  return False
737
738
739def is_var_indefinite_iterable(var):
740  """True if all bindings of var are indefinite sequences."""
741  return all(is_indefinite_iterable(x) for x in var.data)
742
743
744def merged_type_parameter(node, var, param):
745  if not var.bindings:
746    return node.program.NewVariable()
747  if is_var_splat(var):
748    var = unwrap_splat(var)
749  params = [v.get_instance_type_parameter(param) for v in var.data]
750  return var.data[0].vm.join_variables(node, params)
751
752
753def is_var_splat(var):
754  if var.data and var.data[0].isinstance_Splat():
755    # A splat should never have more than one binding, since we create and use
756    # it immediately.
757    assert len(var.bindings) == 1
758    return True
759  return False
760
761
762def unwrap_splat(var):
763  return var.data[0].iterable
764
765
766def is_callable(value: _BaseValue):
767  """Returns whether 'value' is a callable."""
768  if (value.isinstance_Function() or
769      value.isinstance_BoundFunction() or
770      value.isinstance_ClassMethod() or
771      value.isinstance_ClassMethodInstance() or
772      value.isinstance_StaticMethod() or
773      value.isinstance_StaticMethodInstance()):
774    return True
775  if not value.cls or not value.cls.isinstance_Class():
776    return False
777  _, attr = value.vm.attribute_handler.get_attribute(
778      value.vm.root_node, value.cls, "__call__")
779  return attr is not None
780
781
782def expand_type_parameter_instances(bindings: Iterable[cfg.Binding]):
783  bindings = list(bindings)
784  while bindings:
785    b = bindings.pop(0)
786    if b.data.isinstance_TypeParameterInstance():
787      param_value = b.data.instance.get_instance_type_parameter(b.data.name)
788      if param_value.bindings:
789        bindings = param_value.bindings + bindings
790        continue
791    yield b
792
793
794def get_type_parameter_substitutions(
795    val: _BaseValue, type_params: Iterable[_TypeParameter]
796) -> Mapping[str, cfg.Variable]:
797  """Get values for type_params from val's type parameters."""
798  subst = {}
799  for p in type_params:
800    if val.isinstance_Class():
801      param_value = val.get_formal_type_parameter(p.name).instantiate(
802          val.vm.root_node)
803    else:
804      param_value = val.get_instance_type_parameter(p.name)
805    subst[p.full_name] = param_value
806  return subst
807
808
809def build_generic_template(
810    type_params: Sequence[_BaseValue], base_type: _BaseValue
811) -> Tuple[Sequence[str], Sequence[_TypeParameter]]:
812  """Build a typing.Generic template from a sequence of type parameters."""
813  if not all(item.isinstance_TypeParameter() for item in type_params):
814    base_type.vm.errorlog.invalid_annotation(
815        base_type.vm.frames, base_type,
816        "Parameters to Generic[...] must all be type variables")
817    type_params = [item for item in type_params
818                   if item.isinstance_TypeParameter()]
819
820  template = [item.name for item in type_params]
821
822  if len(set(template)) != len(template):
823    base_type.vm.errorlog.invalid_annotation(
824        base_type.vm.frames, base_type,
825        "Parameters to Generic[...] must all be unique")
826
827  return template, type_params
828
829
830def is_generic_protocol(val: _BaseValue) -> bool:
831  return (val.isinstance_ParameterizedClass() and
832          val.full_name == "typing.Protocol")
833
834
835def combine_substs(
836    substs1: Optional[Collection[Dict[str, cfg.Variable]]],
837    substs2: Optional[Collection[Dict[str, cfg.Variable]]]
838) -> Collection[Dict[str, cfg.Variable]]:
839  """Combines the two collections of type parameter substitutions."""
840  if substs1 and substs2:
841    return tuple({**sub1, **sub2} for sub1 in substs1 for sub2 in substs2)  # pylint: disable=g-complex-comprehension
842  elif substs1:
843    return substs1
844  elif substs2:
845    return substs2
846  else:
847    return ()
848
849
850def _flatten(value, classes):
851  """Flatten the contents of value into classes.
852
853  If value is a Class, it is appended to classes.
854  If value is a PythonConstant of type tuple, then each element of the tuple
855  that has a single binding is also flattened.
856  Any other type of value, or tuple elements that have multiple bindings are
857  ignored.
858
859  Args:
860    value: An abstract value.
861    classes: A list to be modified.
862
863  Returns:
864    True iff a value was ignored during flattening.
865  """
866  # Used by special_builtins.IsInstance and IsSubclass
867  if value.isinstance_AnnotationClass():
868    value = value.base_cls
869  if value.isinstance_Class():
870    # A single class, no ambiguity.
871    classes.append(value)
872    return False
873  elif value.isinstance_Tuple():
874    # A tuple, need to process each element.
875    ambiguous = False
876    for var in value.pyval:
877      if (len(var.bindings) != 1 or
878          _flatten(var.bindings[0].data, classes)):
879        # There were either multiple bindings or ambiguity deeper in the
880        # recursion.
881        ambiguous = True
882    return ambiguous
883  else:
884    return True
885
886
887def check_against_mro(vm, target, class_spec):
888  """Check if any of the classes are in the target's MRO.
889
890  Args:
891    vm: The virtual machine.
892    target: A BaseValue whose MRO will be checked.
893    class_spec: A Class or PythonConstant tuple of classes (i.e. the second
894      argument to isinstance or issubclass).
895
896  Returns:
897    True if any class in classes is found in the target's MRO,
898    False if no match is found and None if it's ambiguous.
899  """
900  # Determine the flattened list of classes to check.
901  classes = []
902  ambiguous = _flatten(class_spec, classes)
903
904  for c in classes:
905    if vm.matcher(None).match_from_mro(target, c, allow_compat_builtins=False):
906      return True  # A definite match.
907  # No matches, return result depends on whether flatten() was
908  # ambiguous.
909  return None if ambiguous else False
910