Fix the leading indentation issue.
This commit is contained in:
parent
24bd40737a
commit
1a99638ba2
3200
mox3/mox.py
3200
mox3/mox.py
File diff suppressed because it is too large
Load Diff
220
mox3/stubout.py
220
mox3/stubout.py
|
@ -20,126 +20,126 @@ import inspect
|
|||
|
||||
|
||||
class StubOutForTesting(object):
|
||||
"""Sample Usage:
|
||||
You want os.path.exists() to always return true during testing.
|
||||
"""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()
|
||||
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 attr_name in obj.__dict__)):
|
||||
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.
|
||||
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.
|
||||
|
||||
"""
|
||||
self.stubs.reverse()
|
||||
def __init__(self):
|
||||
self.cache = []
|
||||
self.stubs = []
|
||||
|
||||
for args in self.stubs:
|
||||
setattr(*args)
|
||||
def __del__(self):
|
||||
self.SmartUnsetAll()
|
||||
self.UnsetAll()
|
||||
|
||||
self.stubs = []
|
||||
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.
|
||||
|
||||
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 attr_name is a staticmethod or a
|
||||
classmethod of obj.
|
||||
|
||||
This method supports the case where child_name is a staticmethod or a
|
||||
classmethod of parent.
|
||||
"""
|
||||
old_child = getattr(parent, child_name)
|
||||
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()).
|
||||
|
||||
old_attribute = parent.__dict__.get(child_name)
|
||||
if old_attribute is not None:
|
||||
if isinstance(old_attribute, staticmethod):
|
||||
old_child = staticmethod(old_child)
|
||||
elif isinstance(old_attribute, classmethod):
|
||||
old_child = classmethod(old_child.__func__)
|
||||
Raises AttributeError if the attribute cannot be found.
|
||||
"""
|
||||
if (inspect.ismodule(obj) or
|
||||
(not inspect.isclass(obj) and attr_name in obj.__dict__)):
|
||||
orig_obj = obj
|
||||
orig_attr = getattr(obj, attr_name)
|
||||
|
||||
self.cache.append((parent, old_child, child_name))
|
||||
setattr(parent, child_name, new_child)
|
||||
else:
|
||||
if not inspect.isclass(obj):
|
||||
mro = list(inspect.getmro(obj.__class__))
|
||||
else:
|
||||
mro = list(inspect.getmro(obj))
|
||||
|
||||
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.
|
||||
mro.reverse()
|
||||
|
||||
"""
|
||||
# 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()
|
||||
orig_attr = None
|
||||
|
||||
for (parent, old_child, child_name) in self.cache:
|
||||
setattr(parent, child_name, old_child)
|
||||
self.cache = []
|
||||
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:
|
||||
if isinstance(old_attribute, staticmethod):
|
||||
old_child = staticmethod(old_child)
|
||||
elif isinstance(old_attribute, classmethod):
|
||||
old_child = classmethod(old_child.__func__)
|
||||
|
||||
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 = []
|
||||
|
|
|
@ -33,113 +33,113 @@ from mox3 import mox
|
|||
|
||||
|
||||
class ExampleMoxTestMixin(object):
|
||||
"""Mix-in class for mox test case class.
|
||||
"""Mix-in class for mox test case class.
|
||||
|
||||
It stubs out the same function as one of the test methods in
|
||||
the example test case. Both tests must pass as meta class wraps
|
||||
test methods in all base classes.
|
||||
"""
|
||||
It stubs out the same function as one of the test methods in
|
||||
the example test case. Both tests must pass as meta class wraps
|
||||
test methods in all base classes.
|
||||
"""
|
||||
|
||||
def testStat(self):
|
||||
self.mox.StubOutWithMock(os, 'stat')
|
||||
os.stat(self.DIR_PATH)
|
||||
self.mox.ReplayAll()
|
||||
os.stat(self.DIR_PATH)
|
||||
def testStat(self):
|
||||
self.mox.StubOutWithMock(os, 'stat')
|
||||
os.stat(self.DIR_PATH)
|
||||
self.mox.ReplayAll()
|
||||
os.stat(self.DIR_PATH)
|
||||
|
||||
|
||||
class ExampleMoxTest(mox.MoxTestBase, ExampleMoxTestMixin):
|
||||
|
||||
DIR_PATH = '/path/to/some/directory'
|
||||
DIR_PATH = '/path/to/some/directory'
|
||||
|
||||
def testSuccess(self):
|
||||
self.mox.StubOutWithMock(os, 'listdir')
|
||||
os.listdir(self.DIR_PATH)
|
||||
self.mox.ReplayAll()
|
||||
os.listdir(self.DIR_PATH)
|
||||
def testSuccess(self):
|
||||
self.mox.StubOutWithMock(os, 'listdir')
|
||||
os.listdir(self.DIR_PATH)
|
||||
self.mox.ReplayAll()
|
||||
os.listdir(self.DIR_PATH)
|
||||
|
||||
def testExpectedNotCalled(self):
|
||||
self.mox.StubOutWithMock(os, 'listdir')
|
||||
os.listdir(self.DIR_PATH)
|
||||
self.mox.ReplayAll()
|
||||
def testExpectedNotCalled(self):
|
||||
self.mox.StubOutWithMock(os, 'listdir')
|
||||
os.listdir(self.DIR_PATH)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
def testUnexpectedCall(self):
|
||||
self.mox.StubOutWithMock(os, 'listdir')
|
||||
os.listdir(self.DIR_PATH)
|
||||
self.mox.ReplayAll()
|
||||
os.listdir('/path/to/some/other/directory')
|
||||
os.listdir(self.DIR_PATH)
|
||||
def testUnexpectedCall(self):
|
||||
self.mox.StubOutWithMock(os, 'listdir')
|
||||
os.listdir(self.DIR_PATH)
|
||||
self.mox.ReplayAll()
|
||||
os.listdir('/path/to/some/other/directory')
|
||||
os.listdir(self.DIR_PATH)
|
||||
|
||||
def testFailure(self):
|
||||
self.assertTrue(False)
|
||||
def testFailure(self):
|
||||
self.assertTrue(False)
|
||||
|
||||
def testStatOther(self):
|
||||
self.mox.StubOutWithMock(os, 'stat')
|
||||
os.stat(self.DIR_PATH)
|
||||
self.mox.ReplayAll()
|
||||
os.stat(self.DIR_PATH)
|
||||
def testStatOther(self):
|
||||
self.mox.StubOutWithMock(os, 'stat')
|
||||
os.stat(self.DIR_PATH)
|
||||
self.mox.ReplayAll()
|
||||
os.stat(self.DIR_PATH)
|
||||
|
||||
def testHasStubs(self):
|
||||
listdir_list = []
|
||||
def testHasStubs(self):
|
||||
listdir_list = []
|
||||
|
||||
def MockListdir(directory):
|
||||
listdir_list.append(directory)
|
||||
def MockListdir(directory):
|
||||
listdir_list.append(directory)
|
||||
|
||||
self.stubs.Set(os, 'listdir', MockListdir)
|
||||
os.listdir(self.DIR_PATH)
|
||||
self.assertEqual([self.DIR_PATH], listdir_list)
|
||||
self.stubs.Set(os, 'listdir', MockListdir)
|
||||
os.listdir(self.DIR_PATH)
|
||||
self.assertEqual([self.DIR_PATH], listdir_list)
|
||||
|
||||
|
||||
class TestClassFromAnotherModule(object):
|
||||
|
||||
def __init__(self):
|
||||
return None
|
||||
def __init__(self):
|
||||
return None
|
||||
|
||||
def Value(self):
|
||||
return 'Not mock'
|
||||
def Value(self):
|
||||
return 'Not mock'
|
||||
|
||||
|
||||
class ChildClassFromAnotherModule(TestClassFromAnotherModule):
|
||||
"""A child class of TestClassFromAnotherModule.
|
||||
"""A child class of TestClassFromAnotherModule.
|
||||
|
||||
Used to test stubbing out unbound methods, where child classes
|
||||
are eventually bound.
|
||||
"""
|
||||
Used to test stubbing out unbound methods, where child classes
|
||||
are eventually bound.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
TestClassFromAnotherModule.__init__(self)
|
||||
def __init__(self):
|
||||
TestClassFromAnotherModule.__init__(self)
|
||||
|
||||
|
||||
class CallableClass(object):
|
||||
|
||||
def __init__(self, one, two, nine=None):
|
||||
pass
|
||||
def __init__(self, one, two, nine=None):
|
||||
pass
|
||||
|
||||
def __call__(self, one):
|
||||
return 'Not mock'
|
||||
def __call__(self, one):
|
||||
return 'Not mock'
|
||||
|
||||
def Value(self):
|
||||
return 'Not mock'
|
||||
def Value(self):
|
||||
return 'Not mock'
|
||||
|
||||
|
||||
def MyTestFunction(one, two, nine=None):
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
class ExampleClass(object):
|
||||
def __init__(self, foo='bar'):
|
||||
pass
|
||||
def __init__(self, foo='bar'):
|
||||
pass
|
||||
|
||||
def TestMethod(self, one, two, nine=None):
|
||||
pass
|
||||
def TestMethod(self, one, two, nine=None):
|
||||
pass
|
||||
|
||||
def NamedParams(self, ignore, foo='bar', baz='qux'):
|
||||
pass
|
||||
def NamedParams(self, ignore, foo='bar', baz='qux'):
|
||||
pass
|
||||
|
||||
def SpecialArgs(self, *args, **kwargs):
|
||||
pass
|
||||
def SpecialArgs(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
# This class is used to test stubbing out __init__ of a parent class.
|
||||
class ChildExampleClass(ExampleClass):
|
||||
def __init__(self):
|
||||
ExampleClass.__init__(self)
|
||||
def __init__(self):
|
||||
ExampleClass.__init__(self)
|
||||
|
|
|
@ -18,4 +18,4 @@
|
|||
|
||||
|
||||
def SampleFunction():
|
||||
raise Exception('I should never be called!')
|
||||
raise Exception('I should never be called!')
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,26 +23,26 @@ from . import stubout_helper
|
|||
|
||||
|
||||
class StubOutForTestingTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.mox = mox.Mox()
|
||||
self.sample_function_backup = stubout_helper.SampleFunction
|
||||
def setUp(self):
|
||||
self.mox = mox.Mox()
|
||||
self.sample_function_backup = stubout_helper.SampleFunction
|
||||
|
||||
def tearDown(self):
|
||||
stubout_helper.SampleFunction = self.sample_function_backup
|
||||
def tearDown(self):
|
||||
stubout_helper.SampleFunction = self.sample_function_backup
|
||||
|
||||
def testSmartSetOnModule(self):
|
||||
mock_function = self.mox.CreateMockAnything()
|
||||
mock_function()
|
||||
def testSmartSetOnModule(self):
|
||||
mock_function = self.mox.CreateMockAnything()
|
||||
mock_function()
|
||||
|
||||
stubber = stubout.StubOutForTesting()
|
||||
stubber.SmartSet(stubout_helper, 'SampleFunction', mock_function)
|
||||
stubber = stubout.StubOutForTesting()
|
||||
stubber.SmartSet(stubout_helper, 'SampleFunction', mock_function)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
self.mox.ReplayAll()
|
||||
|
||||
stubout_helper.SampleFunction()
|
||||
stubout_helper.SampleFunction()
|
||||
|
||||
self.mox.VerifyAll()
|
||||
self.mox.VerifyAll()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
unittest.main()
|
||||
|
|
4
setup.py
4
setup.py
|
@ -17,5 +17,5 @@
|
|||
import setuptools
|
||||
|
||||
setuptools.setup(
|
||||
setup_requires=['d2to1>=0.2.10,<0.3', 'pbr>=0.5.10,<0.6'],
|
||||
d2to1=True)
|
||||
setup_requires=['d2to1>=0.2.10,<0.3', 'pbr>=0.5.10,<0.6'],
|
||||
d2to1=True)
|
||||
|
|
Loading…
Reference in New Issue