DictMethodRunner
Manage the invocation of dictionary methods implemented as class methods.
Source code in mmcif/api/DictMethodRunner.py
class DictMethodRunner(object):
"""Manage the invocation of dictionary methods implemented as class methods."""
def __init__(self, dictionaryApi, modulePathMap=None, **kwargs):
"""Manage invocation of dictionary methods referenced in external modules.
Arguments:
dictionaryApi {object} -- instance of DictionaryApi() for dictionary with target method definitions
Keyword Arguments:
modulePathMap {dict str} -- mapping between dictionary module path and execution path (default: {None})
cacheModuleFlag {bool} -- flag to cache module instances (defaullt: True)
implentationSource {str} -- method implementation (default: 'reference')
methodCodes (list str) -- filter methods by codes {default: ['calculation']}
"""
self.__dApi = dictionaryApi
self.__modulePathMap = modulePathMap if modulePathMap else {}
self.__cacheModuleFlag = kwargs.get("cacheModuleFlag", True)
methodCodes = kwargs.get("methodCodes", ["calculation"])
implementationSource = kwargs.get("implementationCodes", "reference")
#
self.__kwargs = kwargs
#
# Preserve and reuse the module instances if caching is enabled
self.__moduleCache = {}
#
self.__methodD = self.__getMethodInfo(implementationSource=implementationSource, methodCodes=methodCodes)
logger.debug("Method index %r", self.__methodD.items())
def __getMethodInfo(self, implementationSource="reference", methodCodes=None):
"""Get method implementation with the input implementation source."""
catName = atName = mId = mType = methDef = None
methodCodes = methodCodes if methodCodes else ["calculation"]
methodD = {}
try:
methodIndex = self.__dApi.getMethodIndex()
for _, mrL in methodIndex.items():
for mr in mrL:
mId = mr.getId()
catName = mr.getCategoryName()
atName = mr.getAttributeName()
mType = mr.getType()
if (catName, atName) not in methodD:
methodD[(catName, atName)] = []
methDef = self.__dApi.getMethod(mId)
logger.debug("Category %s attribute %s mId %r type %r methDef %r", catName, atName, mId, mType, methDef)
mSource = methDef.getImplementationSource()
mCode = methDef.getCode()
if mSource == implementationSource and mCode in methodCodes:
mPriority = methDef.getPriority()
mLang = methDef.getLanguage()
mImplement = methDef.getImplementation()
dD = {"METHOD_LANGUAGE": mLang, "METHOD_IMPLEMENT": mImplement, "METHOD_TYPE": mType, "METHOD_CODE": mCode, "METHOD_PRIORITY": mPriority}
methodD[(catName, atName)].append(dD)
#
except Exception as e:
logger.exception("Failing for category %r attribute %r mId %r type %r methDef %r with %s", catName, atName, mId, mType, methDef, str(e))
##
logger.debug("Method dictionary %r", methodD)
return methodD
def __invokeAttributeMethod(self, methodPath, dataContainer, catName, atName, **kwargs):
"""Invoke the input attribute method"""
ok = False
try:
modulePath, methodName = self.__methodPathSplit(methodPath)
mObj = self.__getModuleInstance(modulePath, **kwargs)
theMeth = getattr(mObj, methodName, None)
ok = theMeth(dataContainer, catName, atName, **kwargs)
except Exception as e:
logger.exception("Failed invoking attribute %s %s method %r with %s", catName, atName, methodPath, str(e))
return ok
def __invokeCategoryMethod(self, methodPath, dataContainer, catName, **kwargs):
"""Invoke the input category method"""
ok = False
try:
modulePath, methodName = self.__methodPathSplit(methodPath)
mObj = self.__getModuleInstance(modulePath, **kwargs)
theMeth = getattr(mObj, methodName, None)
ok = theMeth(dataContainer, catName, **kwargs)
except Exception as e:
logger.exception("Failed invoking category %s method %r with %s", catName, methodPath, str(e))
return ok
def __invokeDatablockMethod(self, methodPath, dataContainer, blockName, **kwargs):
"""Invoke the input data block method"""
ok = False
try:
modulePath, methodName = self.__methodPathSplit(methodPath)
mObj = self.__getModuleInstance(modulePath, **kwargs)
theMeth = getattr(mObj, methodName, None)
ok = theMeth(dataContainer, blockName, **kwargs)
except Exception as e:
logger.exception("Failed invoking block %s method %r with %s", blockName, methodPath, str(e))
return ok
def apply(self, dataContainer):
"""Apply category, attribute and block level dictionary methods on the input data container."""
kwargs = self.__kwargs
mTupL = self.__getCategoryMethods()
logger.debug("Category methods %r", mTupL)
for catName, _, methodPath, _ in mTupL:
self.__invokeCategoryMethod(methodPath, dataContainer, catName, **kwargs)
mTupL = self.__getAttributeMethods()
logger.debug("Attribute methods %r", mTupL)
for catName, atName, methodPath, _ in mTupL:
self.__invokeAttributeMethod(methodPath, dataContainer, catName, atName, **kwargs)
mTupL = self.__getDatablockMethods()
logger.debug("Datablock methods %r", mTupL)
for _, _, methodPath, _ in mTupL:
self.__invokeDatablockMethod(methodPath, dataContainer, dataContainer.getName(), **kwargs)
return True
def __getDatablockMethods(self):
mL = []
try:
for (dictName, _), mDL in self.__methodD.items():
for mD in mDL:
if mD["METHOD_TYPE"].lower() == "datablock":
methodPath = mD["METHOD_IMPLEMENT"]
mL.append((dictName, None, methodPath, mD["METHOD_PRIORITY"]))
mL = sorted(mL, key=itemgetter(3))
return mL
except Exception as e:
logger.exception("Failing dictName %s with %s", dictName, str(e))
return mL
def __getCategoryMethods(self):
mL = []
try:
for (catName, _), mDL in self.__methodD.items():
for mD in mDL:
if mD["METHOD_TYPE"].lower() == "category":
methodPath = mD["METHOD_IMPLEMENT"]
mL.append((catName, None, methodPath, mD["METHOD_PRIORITY"]))
mL = sorted(mL, key=itemgetter(3))
return mL
except Exception as e:
logger.exception("Failing catName %r with %s", catName, str(e))
return mL
def __getAttributeMethods(self):
mL = []
try:
for (catName, atName), mDL in self.__methodD.items():
for mD in mDL:
if mD["METHOD_TYPE"].lower() == "attribute":
methodPath = mD["METHOD_IMPLEMENT"]
mL.append((catName, atName, methodPath, mD["METHOD_PRIORITY"]))
mL = sorted(mL, key=itemgetter(3))
return mL
except Exception as e:
logger.exception("Failing catName %s atName %s with %s", catName, atName, str(e))
return mL
def __methodPathSplit(self, methodPath):
"""Extract module path and the method name from the input path. Optional
remap the module path.
Arguments:
methodPath {str} -- implementation path from dictionary method definition
Returns:
{tuple str} -- module path, method name
"""
try:
# Strip off any leading path of the module from the method path.
mpL = str(methodPath).split(".")
methodName = mpL[-1]
tp = ".".join(mpL[:-1])
modulePath = self.__modulePathMap[tp] if tp in self.__modulePathMap else tp
return modulePath, methodName
except Exception as e:
logger.error("Failing for method path %r with %s", methodPath, str(e))
return None, None
def __getModuleInstance(self, modulePath, **kwargs):
#
if self.__cacheModuleFlag and modulePath in self.__moduleCache:
return self.__moduleCache[modulePath]
#
mObj = None
try:
aMod = __import__(modulePath, globals(), locals(), [""])
sys.modules[modulePath] = aMod
#
# Strip off any leading path to the module before we instaniate the module object.
mpL = str(modulePath).split(".")
moduleName = mpL[-1]
#
# Add the internal dictionaryApi object instance as a kw option
#
kwargs["dictionaryApi"] = self.__dApi
mObj = getattr(aMod, moduleName)(**kwargs)
self.__moduleCache[modulePath] = mObj
except Exception as e:
logger.error("Failing to instance helper %r with %s", modulePath, str(e))
return mObj
__init__(self, dictionaryApi, modulePathMap=None, **kwargs)
special
Manage invocation of dictionary methods referenced in external modules.
Keyword arguments:
Name | Type | Description |
---|---|---|
modulePathMap |
{dict str} -- mapping between dictionary module path and execution path (default |
{None}) |
cacheModuleFlag |
{bool} -- flag to cache module instances (defaullt |
True) |
implentationSource |
{str} -- method implementation (default |
'reference') |
methodCodes |
list str) -- filter methods by codes {default |
['calculation']} |
Source code in mmcif/api/DictMethodRunner.py
def __init__(self, dictionaryApi, modulePathMap=None, **kwargs):
"""Manage invocation of dictionary methods referenced in external modules.
Arguments:
dictionaryApi {object} -- instance of DictionaryApi() for dictionary with target method definitions
Keyword Arguments:
modulePathMap {dict str} -- mapping between dictionary module path and execution path (default: {None})
cacheModuleFlag {bool} -- flag to cache module instances (defaullt: True)
implentationSource {str} -- method implementation (default: 'reference')
methodCodes (list str) -- filter methods by codes {default: ['calculation']}
"""
self.__dApi = dictionaryApi
self.__modulePathMap = modulePathMap if modulePathMap else {}
self.__cacheModuleFlag = kwargs.get("cacheModuleFlag", True)
methodCodes = kwargs.get("methodCodes", ["calculation"])
implementationSource = kwargs.get("implementationCodes", "reference")
#
self.__kwargs = kwargs
#
# Preserve and reuse the module instances if caching is enabled
self.__moduleCache = {}
#
self.__methodD = self.__getMethodInfo(implementationSource=implementationSource, methodCodes=methodCodes)
logger.debug("Method index %r", self.__methodD.items())
apply(self, dataContainer)
Apply category, attribute and block level dictionary methods on the input data container.
Source code in mmcif/api/DictMethodRunner.py
def apply(self, dataContainer):
"""Apply category, attribute and block level dictionary methods on the input data container."""
kwargs = self.__kwargs
mTupL = self.__getCategoryMethods()
logger.debug("Category methods %r", mTupL)
for catName, _, methodPath, _ in mTupL:
self.__invokeCategoryMethod(methodPath, dataContainer, catName, **kwargs)
mTupL = self.__getAttributeMethods()
logger.debug("Attribute methods %r", mTupL)
for catName, atName, methodPath, _ in mTupL:
self.__invokeAttributeMethod(methodPath, dataContainer, catName, atName, **kwargs)
mTupL = self.__getDatablockMethods()
logger.debug("Datablock methods %r", mTupL)
for _, _, methodPath, _ in mTupL:
self.__invokeDatablockMethod(methodPath, dataContainer, dataContainer.getName(), **kwargs)
return True