Source code for morse.helpers.loading
"""Loading
Helpers for 'classpath' configuration
"""
import logging; logger = logging.getLogger("morse." + __name__)
import sys
[docs]def get_class(classpath):
""" Returns the class object from a full classpath (like toto.tata.MyTata)
"""
module_name, class_name = classpath.rsplit('.', 1)
klass = load_module_attribute(module_name, class_name)
if not klass:
logger.error("Could not load the class %s in %s"% (class_name, module_name))
return None
return klass
[docs]def load_module_attribute(module_name, attribute_name):
"""Dynamically import a Python attribute."""
try:
__import__(module_name)
except ImportError as detail:
logger.error("Module not found: %s" % detail)
return None
module = sys.modules[module_name]
# Create an instance of the object class
try:
attribute = getattr(module, attribute_name)
except AttributeError as detail:
logger.error("Module attribute not found: %s" % detail)
return None
return attribute
[docs]def create_instance(classpath, *args, **kwargs):
"""Creates an instances of a class."""
klass = get_class(classpath)
if not klass:
logger.error("Could not create an instance of %s"%str(classpath))
return None
return klass(*args, **kwargs)
[docs]def create_instance_level(classpath, level, *args, **kwargs):
"""Creates an instances of a class from a component abstration level."""
klass = get_class(classpath)
if not klass:
logger.error("Could not create an instance of %s"%str(classpath))
return None
# Component abstration levels
if level:
if not hasattr(klass, "_levels"):
if level != "default":
logger.error("Class <%s> does not define abstraction levels. You can not use them here." % str(classpath))
return None
if level == "default":
# iterate over levels to find the one with the default flag
for key, value in klass._levels.items():
if value[2]:
level = key
logger.info("Using default level <%s> for component <%s>" % (level, classpath))
break
if level == "default":
logger.error("Class <%s> does not define a default abstraction level. You must explicitely set one with <cmpt>.level(<level>). Check the component documentation." % classpath)
return None
if level not in klass._levels:
logger.error("Class <%s> does not define the abstraction level <%s>. Check your scene." % (classpath, level))
return None
# The level may define a custom classpath to implement the component
# behaviour, or 'None' if the parent class is to be used.
if klass._levels[level][0]:
return create_instance(klass._levels[level][0], *args, **kwargs)
return klass(*args, **kwargs)