protobuf/python/stubout.py
Go to the documentation of this file.
1 #!/usr/bin/python2.4
2 #
3 # Copyright 2008 Google Inc.
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 
17 # This file is used for testing. The original is at:
18 # http://code.google.com/p/pymox/
19 
20 import inspect
21 
22 
23 class StubOutForTesting:
24  """Sample Usage:
25  You want os.path.exists() to always return true during testing.
26 
27  stubs = StubOutForTesting()
28  stubs.Set(os.path, 'exists', lambda x: 1)
29  ...
30  stubs.UnsetAll()
31 
32  The above changes os.path.exists into a lambda that returns 1. Once
33  the ... part of the code finishes, the UnsetAll() looks up the old value
34  of os.path.exists and restores it.
35 
36  """
37  def __init__(self):
38  self.cache = []
39  self.stubs = []
40 
41  def __del__(self):
42  self.SmartUnsetAll()
43  self.UnsetAll()
44 
45  def SmartSet(self, obj, attr_name, new_attr):
46  """Replace obj.attr_name with new_attr. This method is smart and works
47  at the module, class, and instance level while preserving proper
48  inheritance. It will not stub out C types however unless that has been
49  explicitly allowed by the type.
50 
51  This method supports the case where attr_name is a staticmethod or a
52  classmethod of obj.
53 
54  Notes:
55  - If obj is an instance, then it is its class that will actually be
56  stubbed. Note that the method Set() does not do that: if obj is
57  an instance, it (and not its class) will be stubbed.
58  - The stubbing is using the builtin getattr and setattr. So, the __get__
59  and __set__ will be called when stubbing (TODO: A better idea would
60  probably be to manipulate obj.__dict__ instead of getattr() and
61  setattr()).
62 
63  Raises AttributeError if the attribute cannot be found.
64  """
65  if (inspect.ismodule(obj) or
66  (not inspect.isclass(obj) and obj.__dict__.has_key(attr_name))):
67  orig_obj = obj
68  orig_attr = getattr(obj, attr_name)
69 
70  else:
71  if not inspect.isclass(obj):
72  mro = list(inspect.getmro(obj.__class__))
73  else:
74  mro = list(inspect.getmro(obj))
75 
76  mro.reverse()
77 
78  orig_attr = None
79 
80  for cls in mro:
81  try:
82  orig_obj = cls
83  orig_attr = getattr(obj, attr_name)
84  except AttributeError:
85  continue
86 
87  if orig_attr is None:
88  raise AttributeError("Attribute not found.")
89 
90  # Calling getattr() on a staticmethod transforms it to a 'normal' function.
91  # We need to ensure that we put it back as a staticmethod.
92  old_attribute = obj.__dict__.get(attr_name)
93  if old_attribute is not None and isinstance(old_attribute, staticmethod):
94  orig_attr = staticmethod(orig_attr)
95 
96  self.stubs.append((orig_obj, attr_name, orig_attr))
97  setattr(orig_obj, attr_name, new_attr)
98 
99  def SmartUnsetAll(self):
100  """Reverses all the SmartSet() calls, restoring things to their original
101  definition. Its okay to call SmartUnsetAll() repeatedly, as later calls
102  have no effect if no SmartSet() calls have been made.
103 
104  """
105  self.stubs.reverse()
106 
107  for args in self.stubs:
108  setattr(*args)
109 
110  self.stubs = []
111 
112  def Set(self, parent, child_name, new_child):
113  """Replace child_name's old definition with new_child, in the context
114  of the given parent. The parent could be a module when the child is a
115  function at module scope. Or the parent could be a class when a class'
116  method is being replaced. The named child is set to new_child, while
117  the prior definition is saved away for later, when UnsetAll() is called.
118 
119  This method supports the case where child_name is a staticmethod or a
120  classmethod of parent.
121  """
122  old_child = getattr(parent, child_name)
123 
124  old_attribute = parent.__dict__.get(child_name)
125  if old_attribute is not None and isinstance(old_attribute, staticmethod):
126  old_child = staticmethod(old_child)
127 
128  self.cache.append((parent, old_child, child_name))
129  setattr(parent, child_name, new_child)
130 
131  def UnsetAll(self):
132  """Reverses all the Set() calls, restoring things to their original
133  definition. Its okay to call UnsetAll() repeatedly, as later calls have
134  no effect if no Set() calls have been made.
135 
136  """
137  # Undo calls to Set() in reverse order, in case Set() was called on the
138  # same arguments repeatedly (want the original call to be last one undone)
139  self.cache.reverse()
140 
141  for (parent, old_child, child_name) in self.cache:
142  setattr(parent, child_name, old_child)
143  self.cache = []
stubout.StubOutForTesting.Set
def Set(self, parent, child_name, new_child)
Definition: bloaty/third_party/protobuf/python/stubout.py:112
make_dist_html.reverse
reverse
Definition: make_dist_html.py:119
stubout.StubOutForTesting.SmartSet
def SmartSet(self, obj, attr_name, new_attr)
Definition: bloaty/third_party/protobuf/python/stubout.py:45
stubout.StubOutForTesting.__init__
def __init__(self)
Definition: bloaty/third_party/protobuf/python/stubout.py:37
stubout.StubOutForTesting.stubs
stubs
Definition: bloaty/third_party/protobuf/python/stubout.py:39
stubout.StubOutForTesting.UnsetAll
def UnsetAll(self)
Definition: bloaty/third_party/protobuf/python/stubout.py:131
stubout.StubOutForTesting.cache
cache
Definition: bloaty/third_party/protobuf/python/stubout.py:38
stubout.StubOutForTesting.SmartUnsetAll
def SmartUnsetAll(self)
Definition: bloaty/third_party/protobuf/python/stubout.py:99
stubout.StubOutForTesting.__del__
def __del__(self)
Definition: bloaty/third_party/protobuf/python/stubout.py:41


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:01:27