Beispiel #1
0
def get_views(variables, node):
    """Get all possible views of the given variables at a particular node.

  For performance reasons, this method uses node.CanHaveCombination for
  filtering. For a more precise check, you can call
  node.HasCombination(list(view.values())). Do so judiciously, as the latter
  method can be very slow.

  This function can be used either as a regular generator or in an optimized way
  to yield only functionally unique views:
    views = get_views(...)
    skip_future = None
    while True:
      try:
        view = views.send(skip_future)
      except StopIteration:
        break
      ...
    The caller should set `skip_future` to True when it is safe to skip
    equivalent future views and False otherwise.

  Args:
    variables: The variables.
    node: The node.

  Yields:
    A datatypes.AcessTrackingDict mapping variables to bindings.
  """
    try:
        combinations = cfg_utils.deep_variable_product(variables)
    except cfg_utils.TooComplexError:
        combinations = ((var.AddBinding(node.program.default_data, [], node)
                         for var in variables), )
    seen = []  # the accessed subsets of previously seen views
    for combination in combinations:
        view = {value.variable: value for value in combination}
        if any(subset <= six.viewitems(view) for subset in seen):
            # Optimization: This view can be skipped because it matches the accessed
            # subset of a previous one.
            log.info("Skipping view (already seen): %r", view)
            continue
        combination = list(view.values())
        if not node.CanHaveCombination(combination):
            log.info("Skipping combination (unreachable): %r", combination)
            continue
        view = datatypes.AccessTrackingDict(view)
        skip_future = yield view
        if skip_future:
            # Skip future views matching this accessed subset.
            seen.append(six.viewitems(view.accessed_subset))
Beispiel #2
0
 def setUp(self):
     super().setUp()
     self.d = datatypes.AccessTrackingDict({"a": 1, "b": 2})