def _get_attr(obj, path): if not path: return obj attr_name = path[0] if isinstance(obj, ModuleType): if attr_name in obj.__dict__: return _get_attr(obj.__dict__[attr_name], path[1:]) elif attr_name in dir(obj): return _get_attr(obj[attr_name], path[1:]) # TRY FILESYSTEM File = get_module("mo_files").File possible_error = None python_file = (File(obj.__file__).parent / attr_name).set_extension("py") python_module = (File(obj.__file__).parent / attr_name / "__init__.py") if python_file.exists or python_module.exists: try: # THIS CASE IS WHEN THE __init__.py DOES NOT IMPORT THE SUBDIR FILE # WE CAN STILL PUT THE PATH TO THE FILE IN THE from CLAUSE if len(path) == 1: # GET MODULE OBJECT output = __import__(obj.__name__ + str(".") + str(attr_name), globals(), locals(), [str(attr_name)], 0) return output else: # GET VARIABLE IN MODULE output = __import__(obj.__name__ + str(".") + str(attr_name), globals(), locals(), [str(path[1])], 0) return _get_attr(output, path[1:]) except Exception as e: Except = get_module("mo_logs.exceptions.Except") possible_error = Except.wrap(e) # TRY A CASE-INSENSITIVE MATCH matched_attr_name = lower_match(attr_name, dir(obj)) if not matched_attr_name: get_logger().warning(PATH_NOT_FOUND + "({{name|quote}}) Returning None.", name=attr_name, cause=possible_error) elif len(matched_attr_name) > 1: get_logger().error(AMBIGUOUS_PATH_FOUND + " {{paths}}", paths=attr_name) else: return _get_attr(obj[matched_attr_name[0]], path[1:]) try: obj = obj[int(attr_name)] return _get_attr(obj, path[1:]) except Exception: pass try: obj = getattr(obj, attr_name) return _get_attr(obj, path[1:]) except Exception: pass try: obj = obj[attr_name] return _get_attr(obj, path[1:]) except Exception as f: return None