| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 | 
							- #!/usr/bin/python2.4
 
- #
 
- # Copyright 2008 Google Inc.
 
- #
 
- # Licensed under the Apache License, Version 2.0 (the "License");
 
- # you may not use this file except in compliance with the License.
 
- # You may obtain a copy of the License at
 
- #
 
- #      http://www.apache.org/licenses/LICENSE-2.0
 
- #
 
- # Unless required by applicable law or agreed to in writing, software
 
- # distributed under the License is distributed on an "AS IS" BASIS,
 
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
- # See the License for the specific language governing permissions and
 
- # limitations under the License.
 
- # This file is used for testing.  The original is at:
 
- #   http://code.google.com/p/pymox/
 
- import inspect
 
- class StubOutForTesting:
 
-   """Sample Usage:
 
-      You want os.path.exists() to always return true during testing.
 
-      stubs = StubOutForTesting()
 
-      stubs.Set(os.path, 'exists', lambda x: 1)
 
-        ...
 
-      stubs.UnsetAll()
 
-      The above changes os.path.exists into a lambda that returns 1.  Once
 
-      the ... part of the code finishes, the UnsetAll() looks up the old value
 
-      of os.path.exists and restores it.
 
-   """
 
-   def __init__(self):
 
-     self.cache = []
 
-     self.stubs = []
 
-   def __del__(self):
 
-     self.SmartUnsetAll()
 
-     self.UnsetAll()
 
-   def SmartSet(self, obj, attr_name, new_attr):
 
-     """Replace obj.attr_name with new_attr. This method is smart and works
 
-        at the module, class, and instance level while preserving proper
 
-        inheritance. It will not stub out C types however unless that has been
 
-        explicitly allowed by the type.
 
-        This method supports the case where attr_name is a staticmethod or a
 
-        classmethod of obj.
 
-        Notes:
 
-       - If obj is an instance, then it is its class that will actually be
 
-         stubbed. Note that the method Set() does not do that: if obj is
 
-         an instance, it (and not its class) will be stubbed.
 
-       - The stubbing is using the builtin getattr and setattr. So, the __get__
 
-         and __set__ will be called when stubbing (TODO: A better idea would
 
-         probably be to manipulate obj.__dict__ instead of getattr() and
 
-         setattr()).
 
-        Raises AttributeError if the attribute cannot be found.
 
-     """
 
-     if (inspect.ismodule(obj) or
 
-         (not inspect.isclass(obj) and obj.__dict__.has_key(attr_name))):
 
-       orig_obj = obj
 
-       orig_attr = getattr(obj, attr_name)
 
-     else:
 
-       if not inspect.isclass(obj):
 
-         mro = list(inspect.getmro(obj.__class__))
 
-       else:
 
-         mro = list(inspect.getmro(obj))
 
-       mro.reverse()
 
-       orig_attr = None
 
-       for cls in mro:
 
-         try:
 
-           orig_obj = cls
 
-           orig_attr = getattr(obj, attr_name)
 
-         except AttributeError:
 
-           continue
 
-     if orig_attr is None:
 
-       raise AttributeError("Attribute not found.")
 
-     # Calling getattr() on a staticmethod transforms it to a 'normal' function.
 
-     # We need to ensure that we put it back as a staticmethod.
 
-     old_attribute = obj.__dict__.get(attr_name)
 
-     if old_attribute is not None and isinstance(old_attribute, staticmethod):
 
-       orig_attr = staticmethod(orig_attr)
 
-     self.stubs.append((orig_obj, attr_name, orig_attr))
 
-     setattr(orig_obj, attr_name, new_attr)
 
-   def SmartUnsetAll(self):
 
-     """Reverses all the SmartSet() calls, restoring things to their original
 
-     definition.  Its okay to call SmartUnsetAll() repeatedly, as later calls
 
-     have no effect if no SmartSet() calls have been made.
 
-     """
 
-     self.stubs.reverse()
 
-     for args in self.stubs:
 
-       setattr(*args)
 
-     self.stubs = []
 
-   def Set(self, parent, child_name, new_child):
 
-     """Replace child_name's old definition with new_child, in the context
 
-     of the given parent.  The parent could be a module when the child is a
 
-     function at module scope.  Or the parent could be a class when a class'
 
-     method is being replaced.  The named child is set to new_child, while
 
-     the prior definition is saved away for later, when UnsetAll() is called.
 
-     This method supports the case where child_name is a staticmethod or a
 
-     classmethod of parent.
 
-     """
 
-     old_child = getattr(parent, child_name)
 
-     old_attribute = parent.__dict__.get(child_name)
 
-     if old_attribute is not None and isinstance(old_attribute, staticmethod):
 
-       old_child = staticmethod(old_child)
 
-     self.cache.append((parent, old_child, child_name))
 
-     setattr(parent, child_name, new_child)
 
-   def UnsetAll(self):
 
-     """Reverses all the Set() calls, restoring things to their original
 
-     definition.  Its okay to call UnsetAll() repeatedly, as later calls have
 
-     no effect if no Set() calls have been made.
 
-     """
 
-     # Undo calls to Set() in reverse order, in case Set() was called on the
 
-     # same arguments repeatedly (want the original call to be last one undone)
 
-     self.cache.reverse()
 
-     for (parent, old_child, child_name) in self.cache:
 
-       setattr(parent, child_name, old_child)
 
-     self.cache = []
 
 
  |