1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved.
2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# found in the LICENSE file.
4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)""".
6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)"""
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import collections
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# HIDDEN is a marker used to suppress a value, making it as if it were not set
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# in that object. This causes the search to continue through the tree.
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# This is most useful as a return value of dynamic values that want to find
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# the value they are shadowing.
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)HIDDEN = object()
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class VisitComplete(Exception):
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """Indicates a vist traversal has finished early."""
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class Visitor(object):
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """The base class for anything that wants to "visit" all variables.
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  The two main uses of visitor are search and export. They differ in that export
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  is trying to find all variables, whereas search is just looking for one.
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def __init__(self):
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self.stack = []
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def VisitNode(self, node):
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    """Called for every node in the tree."""
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if not node.enabled:
34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return self
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    try:
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      try:
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        self.stack.append(node)
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        self.StartNode()
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        # Visit all the values first
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        for key in self.KeysOf(node.values):
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          self.Visit(key, node.values[key])
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        # And now recurse into all the children
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        for child in  node.children:
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          self.VisitNode(child)
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      finally:
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        self.EndNode()
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        self.stack.pop()
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    except VisitComplete:
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if self.stack:
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        # propagate back up the stack
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        raise
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return self
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def Visit(self, key, value):
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    """Visit is called for every variable in each node."""
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def StartNode(self):
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    """StartNode is called once for each node before traversal."""
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def EndNode(self):
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    """Visit is called for every node after traversal."""
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  @property
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def root_node(self):
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    """Returns the variable at the root of the current traversal."""
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return self.stack[0]
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  @property
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def current_node(self):
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    """Returns the node currently being scanned."""
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return self.stack[-1]
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def Resolve(self, key, value):
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    """Returns a fully substituted value.
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    This asks the root node to do the actual work.
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Args:
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      key: The key being visited.
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      value: The unresolved value associated with the key.
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Returns:
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      the fully resolved value.
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    """
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return self.root_node.Resolve(self, key, value)
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def Where(self):
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    """Returns the current traversal stack as a string."""
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return '/'.join([entry.name for entry in self.stack])
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class SearchVisitor(Visitor):
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """A Visitor that finds a single matching key."""
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def __init__(self, key):
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    super(SearchVisitor, self).__init__()
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self.key = key
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self.found = False
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self.error = None
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def KeysOf(self, store):
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if self.key in store:
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      yield self.key
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def Visit(self, key, value):
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    value, error = self.Resolve(key, value)
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if value is not HIDDEN:
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      self.found = True
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      self.value = value
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      self.error = error
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      raise VisitComplete()
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class WhereVisitor(SearchVisitor):
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """A SearchVisitor that returns the path to the matching key."""
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def Visit(self, key, value):
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self.where = self.Where()
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    super(WhereVisitor, self).Visit(key, value)
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class ExportVisitor(Visitor):
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """A visitor that builds a fully resolved map of all variables."""
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def __init__(self, store):
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    super(ExportVisitor, self).__init__()
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self.store = store
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def KeysOf(self, store):
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if self.current_node.export is False:
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      # not exporting from this config
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for key in store.keys():
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if key in self.store:
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        # duplicate
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        continue
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (self.current_node.export is None) and key.startswith('_'):
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        # non exported name
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        continue
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      yield key
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def Visit(self, key, value):
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    value, _ = self.Resolve(key, value)
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if value is not HIDDEN:
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      self.store[key] = value
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class Node(object):
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """The base class for objects in a visitable node tree."""
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def __init__(self, name='--', enabled=True, export=True):
150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self._name = name
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self._children = collections.deque()
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self._values = {}
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self._viewers = []
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self.trail = []
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self._enabled = enabled
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self._export = export
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self._export_cache = None
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  @property
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def name(self):
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return self._name
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  @name.setter
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def name(self, value):
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self._name = value
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  @property
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def enabled(self):
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return self._enabled
170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  @enabled.setter
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def enabled(self, value):
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if self._enabled == value:
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self._enabled = value
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self.NotifyChanged()
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  @property
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def export(self):
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return self._export
181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  @property
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def exported(self):
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if self._export_cache is None:
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      self._export_cache = ExportVisitor({}).VisitNode(self).store
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return self._export_cache
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  @property
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def values(self):
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return self._values
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  @property
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def children(self):
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return self._children
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def RegisterViewer(self, viewer):
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self._viewers.append(viewer)
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def UnregisterViewer(self, viewer):
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self._viewers.remove(viewer)
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def OnChanged(self, child):
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    _ = child
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self.NotifyChanged()
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def NotifyChanged(self):
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self._export_cache = None
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for viewers in self._viewers:
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      viewers.OnChanged(self)
210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def _AddChild(self, child):
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if child and child != self and child not in self._children:
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      self._children.appendleft(child)
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      child.RegisterViewer(self)
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def AddChild(self, child):
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self._AddChild(child)
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self.NotifyChanged()
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return self
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def AddChildren(self, *children):
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for child in children:
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      self._AddChild(child)
224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self.NotifyChanged()
225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return self
226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def Find(self, key):
228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    search = SearchVisitor(key).VisitNode(self)
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if not search.found:
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return None
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return search.value
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def WhereIs(self, key):
234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    search = WhereVisitor(key).VisitNode(self)
235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if not search.found:
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return None
237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return search.where
238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def Get(self, key, raise_errors=False):
240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    search = SearchVisitor(key).VisitNode(self)
241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if not search.found:
242010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      self.Missing(key)
243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if search.error and raise_errors:
244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      raise search.error  # bad type inference pylint: disable=raising-bad-type
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return search.value
246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
247010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  def Missing(self, key):
248010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    raise KeyError(key)
249010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def Resolve(self, visitor, key, value):
251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    _ = visitor, key
252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return value
253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def Wipe(self):
255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for child in self._children:
256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      child.UnregisterViewer(self)
257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self._children = collections.deque()
258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self._values = {}
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self.NotifyChanged()
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
261