Simplify the mock mixin required work

This approach does not require the user to call `super().setUp()`
This commit is contained in:
Pedro Algarvio 2017-03-16 01:13:55 +00:00
parent 1f7a0aa65b
commit 30f62f22ec
No known key found for this signature in database
GPG key ID: BB36BF6584A298FF

View file

@ -17,6 +17,7 @@ import copy
import pprint
import logging
import warnings
import functools
import subprocess
# Import Salt Testing Libs
@ -411,89 +412,112 @@ class _FixLoaderModuleMockMixinMroOrder(type):
for idx, base in enumerate(bases):
if base.__name__ == 'LoaderModuleMockMixin':
bases.insert(0, bases.pop(idx))
if 'loader_module' not in cls_dict:
raise RuntimeError(
'You need to provide the \'loader_module\' attribute to {} '
'in order for the \'LoaderModuleMockMixin\' to do it\'s magic'.format(cls_name)
)
break
return super(_FixLoaderModuleMockMixinMroOrder, mcs).__new__(mcs, cls_name, tuple(bases), cls_dict)
# Create the class instance
instance = super(_FixLoaderModuleMockMixinMroOrder, mcs).__new__(mcs, cls_name, tuple(bases), cls_dict)
# Define our setUp function decorator
def set_up_loader_mocks(setup_func):
@functools.wraps(setup_func)
def wrapper(self):
loader_modules = getattr(self, 'loader_module', None)
if loader_modules is None:
return
if NO_MOCK:
self.skipTest(NO_MOCK_REASON)
if not isinstance(loader_modules, (list, tuple)):
loader_modules = [loader_modules]
loader_module_globals = getattr(self, 'loader_module_globals', None)
loader_module_blacklisted_dunders = getattr(self, 'loader_module_blacklisted_dunders', ())
if loader_module_globals is None:
loader_module_globals = {}
elif callable(loader_module_globals):
loader_module_globals = loader_module_globals()
else:
loader_module_globals = copy.deepcopy(loader_module_globals)
minion_funcs = None
if '__salt__' in loader_module_globals and loader_module_globals['__salt__'] == 'autoload':
if '__opts__' not in loader_module_globals:
raise RuntimeError(
'You must provide __opts__ in the loader_module_globals to auto load the minion functions'
)
import salt.loader
ctx = {}
if '__utils__' not in loader_module_globals:
utils = salt.loader.utils(loader_module_globals['__opts__'],
context=loader_module_globals.get('__context__') or ctx)
loader_module_globals['__utils__'] = utils
minion_funcs = salt.loader.minion_mods(
loader_module_globals['__opts__'],
context=loader_module_globals.get('__context__') or ctx,
utils=loader_module_globals.get('__utils__'),
)
loader_module_globals['__salt__'] = minion_funcs
salt_dunders = (
'__opts__', '__salt__', '__runner__', '__context__', '__utils__',
'__ext_pillar__', '__thorium__', '__states__', '__serializers__', '__ret__',
'__grains__', '__pillar__', '__sdb__',
# Proxy is commented out on purpose since some code in salt expects a NameError
# and is most of the time not a required dunder
# '__proxy__'
)
for dunder_name in salt_dunders:
if dunder_name not in loader_module_globals:
if dunder_name in loader_module_blacklisted_dunders:
continue
loader_module_globals[dunder_name] = {}
for loader_module in loader_modules:
for key in loader_module_globals:
if not hasattr(loader_module, key):
if key in salt_dunders:
setattr(loader_module, key, {})
else:
setattr(loader_module, key, None)
if loader_module_globals:
patcher = patch.multiple(loader_module, **loader_module_globals)
patcher.start()
def cleanup(patcher, loader_module_globals):
patcher.stop()
del loader_module_globals
self.addCleanup(cleanup, patcher, loader_module_globals)
if minion_funcs is not None:
# Since we autoloaded the minion_funcs, let's namespace the functions with the globals
# used to patch above
import salt.utils
for func in minion_funcs:
minion_funcs[func] = salt.utils.namespaced_function(
minion_funcs[func],
loader_module_globals,
preserve_context=True
)
return setup_func(self)
return wrapper
# Apply our setUp function decorator
instance.setUp = set_up_loader_mocks(instance.setUp)
return instance
class LoaderModuleMockMixin(six.with_metaclass(_FixLoaderModuleMockMixinMroOrder, object)):
def setUp(self):
loader_modules = getattr(self, 'loader_module', None)
if loader_modules is None:
return
'''
This class will setup salt loader dunders.
if NO_MOCK:
self.skipTest(NO_MOCK_REASON)
if not isinstance(loader_modules, (list, tuple)):
loader_modules = [loader_modules]
loader_module_globals = getattr(self, 'loader_module_globals', None)
loader_module_blacklisted_dunders = getattr(self, 'loader_module_blacklisted_dunders', ())
if loader_module_globals is None:
loader_module_globals = {}
elif callable(loader_module_globals):
loader_module_globals = loader_module_globals()
else:
loader_module_globals = copy.deepcopy(loader_module_globals)
minion_funcs = None
if '__salt__' in loader_module_globals and loader_module_globals['__salt__'] == 'autoload':
if '__opts__' not in loader_module_globals:
raise RuntimeError(
'You must provide __opts__ in the loader_module_globals to auto load the minion functions'
)
import salt.loader
ctx = {}
if '__utils__' not in loader_module_globals:
utils = salt.loader.utils(loader_module_globals['__opts__'],
context=loader_module_globals.get('__context__') or ctx)
loader_module_globals['__utils__'] = utils
minion_funcs = salt.loader.minion_mods(
loader_module_globals['__opts__'],
context=loader_module_globals.get('__context__') or ctx,
utils=loader_module_globals.get('__utils__'),
)
loader_module_globals['__salt__'] = minion_funcs
salt_dunders = (
'__opts__', '__salt__', '__runner__', '__context__', '__utils__',
'__ext_pillar__', '__thorium__', '__states__', '__serializers__', '__ret__',
'__grains__', '__pillar__', '__sdb__',
# Proxy is commented out on purpose since some code in salt expects a NameError
# and is most of the time not a required dunder
# '__proxy__'
)
for dunder_name in salt_dunders:
if dunder_name not in loader_module_globals:
if dunder_name in loader_module_blacklisted_dunders:
continue
loader_module_globals[dunder_name] = {}
for loader_module in loader_modules:
for key in loader_module_globals:
if not hasattr(loader_module, key):
if key in salt_dunders:
setattr(loader_module, key, {})
else:
setattr(loader_module, key, None)
if loader_module_globals:
patcher = patch.multiple(loader_module, **loader_module_globals)
patcher.start()
def cleanup(patcher, loader_module_globals):
patcher.stop()
del loader_module_globals
self.addCleanup(cleanup, patcher, loader_module_globals)
if minion_funcs is not None:
# Since we autoloaded the minion_funcs, let's namespace the functions with the globals
# used to patch above
import salt.utils
for func in minion_funcs:
minion_funcs[func] = salt.utils.namespaced_function(
minion_funcs[func],
loader_module_globals,
preserve_context=True
)
super(LoaderModuleMockMixin, self).setUp()
Please check `set_up_loader_mocks` above
'''