# Path: confab/files.py
# def _import(module_name, dir_name):
#     """
#     Load python module from file system without reloading.
# 
#     Raises ImportError if not found.
#     """
#     # assign module a name that's not likely to conflict
#     safe_name = _safe_name(module_name, dir_name)
# 
#     # check if module is already loaded
#     existing = sys.modules.get(safe_name)
#     if existing:
#         return existing
# 
#     # try to load module
#     module_info = imp.find_module(module_name, [dir_name])
#     try:
#         module = imp.load_module(safe_name, *module_info)
#     except ImportError as e:
#         # In the normal case, an import error is raised during imp.find_module()
#         # because the module is not found. However, ImportError can also be raised
#         # if the module itself contains other ImportErrors. Rather than depend on the
#         # error message or invent a non-standard exception type, decorate the error
#         # with the path to the module that was found.
#         e.module_path = module_info[1]
#         raise e
#     return module
# 
# def _import_string(module_name, content):
#     """
#     Load python module from an in-memory string without reloading.
#     """
# 
#     # assign module a name that's not likely to conflict
#     safe_name = _safe_name(module_name, content)
# 
#     # check if module is already loaded
#     existing = sys.modules.get(safe_name)
#     if existing:
#         return existing
# 
#     # try to load module
#     module = imp.new_module(safe_name)
#     exec content in module.__dict__
#     return module
# 
# Path: confab/merge.py
# def merge(*args):
#     """
#     Recursively merge multiple dictionaries.
#     """
#     return reduce(_merge, args, {})
# 
# Path: confab/options.py
# def _should_render(mime_type):
# def _is_empty(mime_type):
# def _is_not_temporary(file_name):
# def _is_not_internal(file_name):
# def _filter_func(file_name):
# def _get_mime_type(file_name):
# def _diff(a, b, fromfile=None, tofile=None):
# def _as_dict(module):
# def _get_base_dir():
#     def __init__(self, **kwargs):
#     def __enter__(self):
#     def __exit__(self, exc_type, value, traceback):
# def assume_yes():
# class Options(object):
# 
# Path: confab/hooks.py
# class Hook(object):
# class HookRegistry(object):
# class ScopeAndHooks(object):
#     def __init__(self, hook_func, filter_func=None):
#     def __call__(self, module_name):
#     def filter(self, componentdef):
#     def __init__(self):
#     def add_hook(self, scope, hook):
#     def remove_hook(self, scope, hook):
#     def for_scope(self, scope):
#     def __init__(self, *scope_and_hooks):
#     def __enter__(self):
#     def __exit__(self, type, value, traceback):
# def add_data_hook(scope, hook):
# def remove_data_hook(scope, hook):


from os.path import join
from itertools import chain
from fabric.api import puts
from gusset.output import debug
from jinja2 import Environment, FileSystemLoader, TemplateNotFound
from confab.files import _import, _import_string
from confab.merge import merge
from confab.options import options
from confab.hooks import hooks
                                                                       data_dir=data_dir))
        except TemplateNotFound:
            debug("Could not load {module_name} from {data_dir}",
                  module_name=module_name,
                  data_dir=data_dir)
            raise ModuleNotFound("No module named {}".format(module_name))

    return module


def import_configuration(module_name, *data_dirs, **kwargs):
    """
    Load configuration from a python module as a dictionary.

    :param data_dirs: List of directories to load from.
    :param scope: (kwargs) Containing folder name for module.
    """
    def add_scope(data_dirs, scope):
        if scope is None:
            return data_dirs
        return list(chain(*zip(data_dirs, map(lambda data_dir: join(data_dir, scope), data_dirs))))

    for data_dir in add_scope(data_dirs, kwargs.get('scope')):
        try:
            module = _import_configuration(module_name, data_dir)
            return options.module_as_dict(module)
        except ModuleNotFound:
            pass  # try the next directory

    # module not found in any directory

# Path: confab/files.py
# def _import(module_name, dir_name):
#     """
#     Load python module from file system without reloading.
# 
#     Raises ImportError if not found.
#     """
#     # assign module a name that's not likely to conflict
#     safe_name = _safe_name(module_name, dir_name)
# 
#     # check if module is already loaded
#     existing = sys.modules.get(safe_name)
#     if existing:
#         return existing
# 
#     # try to load module
#     module_info = imp.find_module(module_name, [dir_name])
#     try:
#         module = imp.load_module(safe_name, *module_info)
#     except ImportError as e:
#         # In the normal case, an import error is raised during imp.find_module()
#         # because the module is not found. However, ImportError can also be raised
#         # if the module itself contains other ImportErrors. Rather than depend on the
#         # error message or invent a non-standard exception type, decorate the error
#         # with the path to the module that was found.
#         e.module_path = module_info[1]
#         raise e
#     return module
# 
# def _import_string(module_name, content):
#     """
#     Load python module from an in-memory string without reloading.
#     """
# 
#     # assign module a name that's not likely to conflict
#     safe_name = _safe_name(module_name, content)
# 
#     # check if module is already loaded
#     existing = sys.modules.get(safe_name)
#     if existing:
#         return existing
# 
#     # try to load module
#     module = imp.new_module(safe_name)
#     exec content in module.__dict__
#     return module
# 
# Path: confab/merge.py
# def merge(*args):
#     """
#     Recursively merge multiple dictionaries.
#     """
#     return reduce(_merge, args, {})
# 
# Path: confab/options.py
# def _should_render(mime_type):
# def _is_empty(mime_type):
# def _is_not_temporary(file_name):
# def _is_not_internal(file_name):
# def _filter_func(file_name):
# def _get_mime_type(file_name):
# def _diff(a, b, fromfile=None, tofile=None):
# def _as_dict(module):
# def _get_base_dir():
#     def __init__(self, **kwargs):
#     def __enter__(self):
#     def __exit__(self, exc_type, value, traceback):
# def assume_yes():
# class Options(object):
# 
# Path: confab/hooks.py
# class Hook(object):
# class HookRegistry(object):
# class ScopeAndHooks(object):
#     def __init__(self, hook_func, filter_func=None):
#     def __call__(self, module_name):
#     def filter(self, componentdef):
#     def __init__(self):
#     def add_hook(self, scope, hook):
#     def remove_hook(self, scope, hook):
#     def for_scope(self, scope):
#     def __init__(self, *scope_and_hooks):
#     def __enter__(self):
#     def __exit__(self, type, value, traceback):
# def add_data_hook(scope, hook):
# def remove_data_hook(scope, hook):


# Path: confab/data.py
from os.path import join
from itertools import chain
from fabric.api import puts
from gusset.output import debug
from jinja2 import Environment, FileSystemLoader, TemplateNotFound
from confab.files import _import, _import_string
from confab.merge import merge
from confab.options import options
from confab.hooks import hooks

                                                                       data_dir=data_dir))
        except TemplateNotFound:
            debug("Could not load {module_name} from {data_dir}",
                  module_name=module_name,
                  data_dir=data_dir)
            raise ModuleNotFound("No module named {}".format(module_name))

    return module


def import_configuration(module_name, *data_dirs, **kwargs):
    """
    Load configuration from a python module as a dictionary.

    :param data_dirs: List of directories to load from.
    :param scope: (kwargs) Containing folder name for module.
    """
    def add_scope(data_dirs, scope):
        if scope is None:
            return data_dirs
        return list(chain(*zip(data_dirs, map(lambda data_dir: join(data_dir, scope), data_dirs))))

    for data_dir in add_scope(data_dirs, kwargs.get('scope')):
        try:
            module = _import_configuration(module_name, data_dir)
            return options.module_as_dict(module)
        except ModuleNotFound:
            pass  # try the next directory

    # module not found in any directory

    return options.module_as_dict({})