|
|
@ -132,12 +132,17 @@ def import_attribute(name):
|
|
|
|
# dotted path is not the last-before-end word
|
|
|
|
# dotted path is not the last-before-end word
|
|
|
|
# E.g.: package_a.package_b.module_a.ClassA.my_static_method
|
|
|
|
# E.g.: package_a.package_b.module_a.ClassA.my_static_method
|
|
|
|
# Thus we remove the bits from the end of the name until we can import it
|
|
|
|
# Thus we remove the bits from the end of the name until we can import it
|
|
|
|
|
|
|
|
#
|
|
|
|
|
|
|
|
# Sometimes the failure during importing is due to a genuine coding error in the imported module
|
|
|
|
|
|
|
|
# In this case, the exception is logged as a warning for ease of debugging.
|
|
|
|
|
|
|
|
# The above logic will apply anyways regardless of the cause of the import error.
|
|
|
|
while len(module_name_bits):
|
|
|
|
while len(module_name_bits):
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
module_name = '.'.join(module_name_bits)
|
|
|
|
module_name = '.'.join(module_name_bits)
|
|
|
|
module = importlib.import_module(module_name)
|
|
|
|
module = importlib.import_module(module_name)
|
|
|
|
break
|
|
|
|
break
|
|
|
|
except ImportError:
|
|
|
|
except ImportError:
|
|
|
|
|
|
|
|
logging.warning("Import error for '%s'" % module_name, exc_info=True)
|
|
|
|
attribute_bits.insert(0, module_name_bits.pop())
|
|
|
|
attribute_bits.insert(0, module_name_bits.pop())
|
|
|
|
|
|
|
|
|
|
|
|
if module is None:
|
|
|
|
if module is None:
|
|
|
|