# **************************************************************************
# *
# * Authors: J.M. De la Rosa Trevin (jmdelarosa@cnb.csic.es)
# *
# * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
# *
# * This program is free software; you can redistribute it and/or modify
# * it under the terms of the GNU General Public License as published by
# * the Free Software Foundation; either version 3 of the License, or
# * (at your option) any later version.
# *
# * This program is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# * GNU General Public License for more details.
# *
# * You should have received a copy of the GNU General Public License
# * along with this program; if not, write to the Free Software
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# * 02111-1307 USA
# *
# * All comments concerning this program package may be sent to the
# * e-mail address 'scipion@cnb.csic.es'
# *
# **************************************************************************
"""
This module contains reflection utilities
(dynamically load classes, inspect object properties and others)
"""
import os
from os.path import exists, join
import sys
from inspect import isclass
[docs]def getModules(path):
""" Try to find possible sub-modules under path.
A dictionary will be returned with modules names
as keys and the modules objects as values.
"""
sys.path.append(path)
folders = os.listdir(path)
modules = {}
for f in folders:
if exists(join(path, f, '__init__.py')):
try:
m = __import__(f)
modules[f] = m
checkPlugin(m)
except Exception as ex:
print(">>> Error loading module: '%s'" % f)
print(">>> Exception: ", ex)
import traceback
traceback.print_exc()
return modules
[docs]def getSubclassesFromModules(BaseClass, modules, debug=False):
""" Find subclasses of BaseClass from a give dict of modules.
"""
subclasses = {}
for m in modules.values():
if debug:
print("loading module: ", m.__name__)
subDict = getSubclasses(BaseClass, m.__dict__)
for subclass in subDict.values():
# some protocols have pyworkflow.em.packages. in the __module__ and other no
moduleName = subclass.__module__.replace('pwem.packages.', '')
if moduleName.startswith(m.__name__):
subclass._package = m
if debug:
print(" found: ", subclass.__name__, "module: ", subclass.__module__)
subclasses.update(subDict)
return subclasses
[docs]def getSubclassesFromPath(BaseClass, path):
""" Try to find possible sub-packages under path
and find subclasses of BaseClass from them
Return a dictionary containing the subclasses.
"""
modules = getModules(path)
return getSubclassesFromModules(BaseClass, modules)
[docs]def getSubclasses(BaseClass, inputDict):
""" Iterate over inputDict and find all subclasses
of BaseClass, that will be set in outputDict.
"""
outputDict = {}
for k, v in inputDict.items():
# Do not add the base class that is imported in all modules
if (not v==BaseClass) and isclass(v) and issubclass(v, BaseClass):
outputDict[k] = v
return outputDict
[docs]def checkPlugin(module):
if not getattr(module, '_plugin', None):
print('WARNING: module "%s" using old package structure, '
'_plugin attribute missing' % module.__name__)
[docs]def isSameFunction(function1, function2):
""" Check if the content of 2 functions is the same.
This could be used to check if a method has been overridden or not
From https://stackoverflow.com/questions/13620542/detecting-empty-function-definitions-in-python"""
return function1.__code__.co_code == function2.__code__.co_code
[docs]def isModuleAFolder(modulename):
""" Returns True if a python module is a folder"""
# So far e can test for the filename
module = sys.modules[modulename]
return module.__file__.endswith("__init__.py")
[docs]def isModuleLoaded(modulename):
"""
Return True if a python module is loaded, False otherwise
"""
return modulename in sys.modules