From 7427b82ea700015d9305670425dd23989004498a Mon Sep 17 00:00:00 2001 From: Michael Foord Date: Sun, 25 Mar 2012 17:39:04 +0100 Subject: Fix various bugs around spec arguments to patchers --- mock.py | 55 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 17 deletions(-) (limited to 'mock.py') diff --git a/mock.py b/mock.py index 75aaf73..e852bcf 100644 --- a/mock.py +++ b/mock.py @@ -1089,7 +1089,7 @@ class _patch(object): raise ValueError( "Cannot use 'new' and 'new_callable' together" ) - if autospec is not False: + if autospec is not None: raise ValueError( "Cannot use 'autospec' and 'new_callable' together" ) @@ -1218,17 +1218,38 @@ class _patch(object): new_callable = self.new_callable self.target = self.getter() + # normalise False to None + if spec is False: + spec = None + if spec_set is False: + spec_set = None + if autospec is False: + autospec = None + + if spec is not None and autospec is not None: + raise TypeError("Can't specify spec and autospec") + if ((spec is not None or autospec is not None) and + spec_set not in (True, None)): + raise TypeError("Can't provide explicit spec_set *and* spec or autospec") + original, local = self.get_original() - if new is DEFAULT and autospec is False: + if new is DEFAULT and autospec is None: inherit = False - if spec_set == True: - spec_set = original - elif spec == True: + if spec is True: # set spec to the object we are replacing spec = original + if spec_set is True: + spec_set = original + spec = None + elif spec is not None: + if spec_set is True: + spec_set = spec + spec = None + elif spec_set is True: + spec_set = original - if (spec or spec_set) is not None: + if spec is not None or spec_set is not None: if original is DEFAULT: raise TypeError("Can't use 'spec' with create=True") if isinstance(original, ClassTypes): @@ -1259,14 +1280,17 @@ class _patch(object): if inherit and _is_instance_mock(new): # we can only tell if the instance should be callable if the # spec is not a list - if (not _is_list(spec or spec_set) and not - _instance_callable(spec or spec_set)): + this_spec = spec + if spec_set is not None: + this_spec = spec_set + if (not _is_list(this_spec) and not + _instance_callable(this_spec)): Klass = NonCallableMagicMock _kwargs.pop('name') new.return_value = Klass(_new_parent=new, _new_name='()', **_kwargs) - elif autospec is not False: + elif autospec is not None: # spec is ignored, new *must* be default, spec_set is treated # as a boolean. Should we check spec is not None and that spec_set # is a bool? @@ -1343,13 +1367,12 @@ def _get_target(target): def _patch_object( target, attribute, new=DEFAULT, spec=None, - create=False, spec_set=None, autospec=False, + create=False, spec_set=None, autospec=None, new_callable=None, **kwargs ): """ patch.object(target, attribute, new=DEFAULT, spec=None, create=False, - spec_set=None, autospec=False, - new_callable=None, **kwargs) + spec_set=None, autospec=None, new_callable=None, **kwargs) patch the named member (`attribute`) on an object (`target`) with a mock object. @@ -1370,9 +1393,8 @@ def _patch_object( ) -def _patch_multiple(target, spec=None, create=False, - spec_set=None, autospec=False, - new_callable=None, **kwargs +def _patch_multiple(target, spec=None, create=False, spec_set=None, + autospec=None, new_callable=None, **kwargs ): """Perform multiple patches in a single call. It takes the object to be patched (either as an object or a string to fetch the object by importing) @@ -1423,8 +1445,7 @@ def _patch_multiple(target, spec=None, create=False, def patch( target, new=DEFAULT, spec=None, create=False, - spec_set=None, autospec=False, - new_callable=None, **kwargs + spec_set=None, autospec=None, new_callable=None, **kwargs ): """ `patch` acts as a function decorator, class decorator or a context -- cgit v1.2.1