summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--extendmock.py133
-rw-r--r--mock.py10
-rw-r--r--tests/testpatch.py29
3 files changed, 23 insertions, 149 deletions
diff --git a/extendmock.py b/extendmock.py
index 07f0ec0..0550d9f 100644
--- a/extendmock.py
+++ b/extendmock.py
@@ -1,132 +1 @@
-# NOTE: merged into moock.py in Mock 0.7
-
-import inspect
-from mock import Mock
-
-__all__ = ('mocksignature', 'MagicMock')
-
-"""
-extendmock adds additional features to the mock module.
-
-The mocksignature function creates wrapper functions that call a mock whilst
-preserving the signature of the original function.
-
-Note that when a function signature is mocked with mocksignature it will *always* be
-called with positional arguments and not keyword arguments (except where it
-collects arguments with \*\*). Defaults will explicitly be supplied where the function
-is called with missing arguments (as normal).
-
-MagicMock is a class that adds magic method support to Mock. You add magic methods
-to mock instances in the same way you mock other attributes::
-
- mock = Mock()
- mock.__repr__ = lambda self: 'some string'
-
-Note that functions (or callable objects like a Mock instance) that are used for
-magic methods must take self as the first argument.
-
-The only unsupported magic methods (that I'm aware of) are:
-
-* Used by Mock: __init__, __new__, __getattr__, __setattr__, __delattr__, __call__
-* Rare: __dir__,
-* Can cause bad interactions with other functionality:
-
- - __reversed__, __missing__, __del__, __unicode__, __getattribute__
- - __get__, __set__, __delete__
-
-* Context manager methods are not directly supported (__enter__ and __exit__) as
- Python doesn't lookup these methods on the class as it should (in Python 2.5 / 2.6
- anyway).
-
-For more examples of how to use mocksignature and MagicMock see the tests.
-"""
-
-# getsignature and mocksignature heavily "inspired" by
-# the decorator module: http://pypi.python.org/pypi/decorator/
-# by Michele Simionato
-
-DELEGATE = MISSING = object()
-
-def getsignature(func):
- assert inspect.ismethod(func) or inspect.isfunction(func)
- regargs, varargs, varkwargs, defaults = inspect.getargspec(func)
-
- # instance methods need to lose the self argument
- im_self = getattr(func, 'im_self', None)
- if im_self is not None:
- regargs = regargs[1:]
-
- argnames = list(regargs)
- if varargs:
- argnames.append(varargs)
- if varkwargs:
- argnames.append(varkwargs)
- assert '_mock_' not in argnames, ("_mock_ is a reserved argument name, can't mock signatures using _mock_")
- signature = inspect.formatargspec(regargs, varargs, varkwargs, defaults, formatvalue=lambda value: "")
- return signature[1:-1]
-
-
-def mocksignature(func, mock):
- signature = getsignature(func)
- src = "lambda %(signature)s: _mock_(%(signature)s)" % {'signature': signature}
-
- funcopy = eval(src, dict(_mock_=mock))
- funcopy.__name__ = func.__name__
- funcopy.__doc__ = func.__doc__
- funcopy.__dict__.update(func.__dict__)
- funcopy.__module__ = func.__module__
- funcopy.func_defaults = func.func_defaults
- return funcopy
-
-
-class MagicMock(Mock):
- def __new__(cls, *args, **kw):
- class MagicMock(cls):
- # every instance has its own class
- # so we can create magic methods on the
- # class without stomping on other mocks
- pass
- return Mock.__new__(MagicMock, *args, **kw)
-
- def __setattr__(self, name, value):
- if name in _all_magics:
- method = _all_magics[name]
- setattr(self.__class__, name, method)
- return Mock.__setattr__(self, name, value)
-
- def __delattr__(self, name):
- if name in _all_magics and name in self.__class__.__dict__:
- delattr(self.__class__, name)
- return Mock.__delattr__(self, name)
-
-
-magic_methods = (
- "lt le gt ge eq ne "
- "getitem setitem delitem "
- "len contains iter "
- "hash repr str "
- "nonzero "
- "divmod neg pos abs invert "
- "complex int long float oct hex index "
-)
-
-numerics = "add sub mul div truediv floordiv mod lshift rshift and xor or "
-inplace = ' '.join('i%s' % n for n in numerics.split())
-right = ' '.join('r%s' % n for n in numerics.split())
-
-
-def get_method(name):
- def func(self, *args, **kw):
- return self.__dict__[name](self, *args, **kw)
- func.__name__ = name
- return func
-
-_all_magics = {}
-for method in sum([methods.split() for methods in [magic_methods, numerics, inplace, right]], []):
- name = '__%s__' % method
- _all_magics[name] = get_method(name)
-
-import mock
-if mock.__version__ > '0.6.0':
- mockssignature = mock.mocksignature
- MagicMock = mock.Mock \ No newline at end of file
+# merged into mock.py in Mock 0.7
diff --git a/mock.py b/mock.py
index 62d593c..248d24f 100644
--- a/mock.py
+++ b/mock.py
@@ -621,8 +621,8 @@ class _patch(object):
if original is DEFAULT and not self.create:
# for mocking signature on methods with
# patch.object(...)
- original = getattr(self.target, self.attribute)
- new_attr = mocksignature(original, new)
+ original_for_sig = getattr(self.target, self.attribute)
+ new_attr = mocksignature(original_for_sig, new)
self.temp_original = original
setattr(self.target, self.attribute, new_attr)
@@ -636,6 +636,9 @@ class _patch(object):
delattr(self.target, self.attribute)
del self.temp_original
+ start = __enter__
+ stop = __exit__
+
def _patch_object(target, attribute, new=DEFAULT, spec=None, create=False,
mocksignature=False, spec_set=None):
@@ -805,6 +808,9 @@ class _patch_dict(object):
self._unpatch_dict()
return False
+ start = __enter__
+ stop = __exit__
+
def _clear_dict(in_dict):
try:
diff --git a/tests/testpatch.py b/tests/testpatch.py
index bd856a6..d3f4719 100644
--- a/tests/testpatch.py
+++ b/tests/testpatch.py
@@ -3,6 +3,7 @@
# http://www.voidspace.org.uk/python/mock/
import os
+import sys
import warnings
from tests import support
@@ -18,6 +19,8 @@ if not inPy3k:
else:
builtin_string = 'builtins'
+PTModule = sys.modules[__name__]
+
# for use in the test
something = sentinel.Something
@@ -99,17 +102,12 @@ class PatchTest(unittest2.TestCase):
def testPatch(self):
- import __main__
- __main__.something = sentinel.Something
-
@apply
- @patch('__main__.something', sentinel.Something2)
+ @patch('%s.something' % __name__, sentinel.Something2)
def test():
- self.assertEqual(__main__.something, sentinel.Something2, "unpatched")
-
- self.assertEqual(__main__.something, sentinel.Something, "patch not restored")
+ self.assertEqual(PTModule.something, sentinel.Something2, "unpatched")
- import tests.testpatch as PTModule
+ self.assertEqual(PTModule.something, sentinel.Something, "patch not restored")
@patch('tests.testpatch.something', sentinel.Something2)
@patch('tests.testpatch.something_else', sentinel.SomethingElse)
@@ -374,25 +372,22 @@ class PatchTest(unittest2.TestCase):
def testPatchClassDecorator(self):
- import __main__
- __main__.something = sentinel.Something
-
class Something(object):
attribute = sentinel.Original
class Foo(object):
def test_method(other_self, mock_something):
- self.assertEqual(__main__.something, mock_something, "unpatched")
+ self.assertEqual(PTModule.something, mock_something, "unpatched")
def not_test_method(other_self):
- self.assertEqual(__main__.something, sentinel.Something, "non-test method patched")
- Foo = patch('__main__.something')(Foo)
+ self.assertEqual(PTModule.something, sentinel.Something, "non-test method patched")
+ Foo = patch('%s.something' % __name__)(Foo)
f = Foo()
f.test_method()
f.not_test_method()
self.assertEqual(Something.attribute, sentinel.Original, "patch not restored")
- self.assertEqual(__main__.something, sentinel.Something, "patch not restored")
+ self.assertEqual(PTModule.something, sentinel.Something, "patch not restored")
@unittest2.skipUnless(with_available, "test requires Python >= 2.5")
def testPatchObjectDeprecation(self):
@@ -632,6 +627,10 @@ class PatchTest(unittest2.TestCase):
self.assertRaises(AttributeError, test)
+ def DONTtestPatchStartStop(self):
+ patcher = patch()
+
+
if __name__ == '__main__':
unittest2.main()