# Path: confab/definitions.py
# class Settings(object):
#     """
#     Collection of :term:`environment`, :term:`role`, and :term:`component` definitions.
# 
#     :param directory: optional configuration directory
# 
#     Supports convenient iteration. For example::
# 
#         # Iterate over all hosts and roles
#         for host_and_role in settings.for_env("env").all():
#             print host_and_role
# 
#         # Iterate over selected hosts and/or roles
#         for host_and_role in settings.for_env("env").with_hosts("host1", "host2").with_roles("role1").all():
#             print host_and_role
# 
#         # Iterate over all hosts and roles, then all components
#         for host_and_role in settings.for_env("dev").all():
#             environment, host, role = host_and_role
#             for component in host_and_role.components():
#                 print component
# 
#         # Iterate over components
#         for component in settings.for_env("dev").components():
#             environment, host, role, name = component
#             print component
#     """
# 
#     KEYS = ["environmentdefs", "roledefs", "componentdefs"]
# 
#     def __init__(self, directory=None):
#         self.directory = directory
#         self.environmentdefs = {}
#         self.roledefs = {}
#         self.componentdefs = {}
# 
#     @classmethod
#     def load_from_module(cls, settings_path=None):
#         """
#         Load settings from a Python module.
# 
#         :param settings_path: path to settings module. a full path or directory name.
#                               module name defaults to ``settings``. directory defaults
#                               to the current working directory.
#         """
#         if settings_path:
#             if settings_path.endswith(".py"):
#                 dir_name, module = os.path.split(settings_path)
#                 module_name, _ = os.path.splitext(module)
#             else:
#                 dir_name, module_name = settings_path, None
#         else:
#             dir_name, module_name = os.getcwd(), None
# 
#         settings_ = Settings(dir_name)
#         try:
#             module = _import(module_name or 'settings', dir_name)
#         except ImportError as e:
#             raise Exception("Unable to load {settings}: {error}"
#                             .format(settings=os.path.join(dir_name, module_name or "settings.py"),
#                                     error=e))
# 
#         for key in Settings.KEYS:
#             setattr(settings_, key, getattr(module, key, {}))
#         return settings_
# 
#     @classmethod
#     def load_from_dict(cls, dct):
#         """
#         Load settings from a Python dictionary.
#         """
#         settings = Settings()
#         for key in Settings.KEYS:
#             setattr(settings, key, dct.get(key, {}))
#         return settings
# 
#     def for_env(self, environment):
#         """
#         Obtain a specific :term:`environment` definition.
# 
#         Raises exceptions if the environment is not known
#         """
#         if not environment:
#             raise ValueError("Environment was not specified")
#         if environment not in self.environmentdefs:
#             raise KeyError("Environment '{}' is not defined".format(environment))
#         if not self.environmentdefs[environment]:
#             warn("Environment '{}' does not have any hosts defined.".format(environment))
#         for host in self.environmentdefs[environment]:
#             if not self._roles_for_host(host):
#                 raise Exception("Host '{}' does not have any configured roles".format(host))
#         return EnvironmentDefinition(self, environment)
# 
#     def all(self):
#         """
#         Iterate through all valid enviornments.
#         """
#         for environment in self.environmentdefs:
#             yield self.for_env(environment)
# 
#     def _roles_for_host(self, host):
#         """
#         Compute complete list of roles for a host.
#         """
#         return [role for (role, hosts) in self.roledefs.iteritems() if host in hosts]


from os.path import dirname, join
from nose.tools import eq_
from unittest import TestCase
from warnings import catch_warnings
from confab.definitions import Settings
            "role1": ["compgroup1"],
            "compgroup1": ["compgroup2"],
            "compgroup2": ["compgroup1"],
        }
        with self.assertRaises(Exception):
            map(lambda c: c.name, self.settings.for_env("env").with_roles("role1").components())

    def test_multiple_paths(self):
        """
        Fail if componentdefs has multiple paths to a leaf component.
        """
        self.settings.environmentdefs = {
            "env": ["host1"],
        }
        self.settings.roledefs = {
            "role1": ["host1"],
        }
        self.settings.componentdefs = {
            "role1": ["comp1", "compgroup"],
            "compgroup": ["comp1"],
        }
        with self.assertRaises(Exception):
            map(lambda c: c.name, self.settings.for_env("env").with_roles("role1").components())


class TestHostDefinition(TestCase):
    """
    Test host iteration.
    """
    def setUp(self):

# Path: confab/definitions.py
# class Settings(object):
#     """
#     Collection of :term:`environment`, :term:`role`, and :term:`component` definitions.
# 
#     :param directory: optional configuration directory
# 
#     Supports convenient iteration. For example::
# 
#         # Iterate over all hosts and roles
#         for host_and_role in settings.for_env("env").all():
#             print host_and_role
# 
#         # Iterate over selected hosts and/or roles
#         for host_and_role in settings.for_env("env").with_hosts("host1", "host2").with_roles("role1").all():
#             print host_and_role
# 
#         # Iterate over all hosts and roles, then all components
#         for host_and_role in settings.for_env("dev").all():
#             environment, host, role = host_and_role
#             for component in host_and_role.components():
#                 print component
# 
#         # Iterate over components
#         for component in settings.for_env("dev").components():
#             environment, host, role, name = component
#             print component
#     """
# 
#     KEYS = ["environmentdefs", "roledefs", "componentdefs"]
# 
#     def __init__(self, directory=None):
#         self.directory = directory
#         self.environmentdefs = {}
#         self.roledefs = {}
#         self.componentdefs = {}
# 
#     @classmethod
#     def load_from_module(cls, settings_path=None):
#         """
#         Load settings from a Python module.
# 
#         :param settings_path: path to settings module. a full path or directory name.
#                               module name defaults to ``settings``. directory defaults
#                               to the current working directory.
#         """
#         if settings_path:
#             if settings_path.endswith(".py"):
#                 dir_name, module = os.path.split(settings_path)
#                 module_name, _ = os.path.splitext(module)
#             else:
#                 dir_name, module_name = settings_path, None
#         else:
#             dir_name, module_name = os.getcwd(), None
# 
#         settings_ = Settings(dir_name)
#         try:
#             module = _import(module_name or 'settings', dir_name)
#         except ImportError as e:
#             raise Exception("Unable to load {settings}: {error}"
#                             .format(settings=os.path.join(dir_name, module_name or "settings.py"),
#                                     error=e))
# 
#         for key in Settings.KEYS:
#             setattr(settings_, key, getattr(module, key, {}))
#         return settings_
# 
#     @classmethod
#     def load_from_dict(cls, dct):
#         """
#         Load settings from a Python dictionary.
#         """
#         settings = Settings()
#         for key in Settings.KEYS:
#             setattr(settings, key, dct.get(key, {}))
#         return settings
# 
#     def for_env(self, environment):
#         """
#         Obtain a specific :term:`environment` definition.
# 
#         Raises exceptions if the environment is not known
#         """
#         if not environment:
#             raise ValueError("Environment was not specified")
#         if environment not in self.environmentdefs:
#             raise KeyError("Environment '{}' is not defined".format(environment))
#         if not self.environmentdefs[environment]:
#             warn("Environment '{}' does not have any hosts defined.".format(environment))
#         for host in self.environmentdefs[environment]:
#             if not self._roles_for_host(host):
#                 raise Exception("Host '{}' does not have any configured roles".format(host))
#         return EnvironmentDefinition(self, environment)
# 
#     def all(self):
#         """
#         Iterate through all valid enviornments.
#         """
#         for environment in self.environmentdefs:
#             yield self.for_env(environment)
# 
#     def _roles_for_host(self, host):
#         """
#         Compute complete list of roles for a host.
#         """
#         return [role for (role, hosts) in self.roledefs.iteritems() if host in hosts]


# Path: confab/tests/test_definitions.py
from os.path import dirname, join
from nose.tools import eq_
from unittest import TestCase
from warnings import catch_warnings
from confab.definitions import Settings

            "role1": ["compgroup1"],
            "compgroup1": ["compgroup2"],
            "compgroup2": ["compgroup1"],
        }
        with self.assertRaises(Exception):
            map(lambda c: c.name, self.settings.for_env("env").with_roles("role1").components())

    def test_multiple_paths(self):
        """
        Fail if componentdefs has multiple paths to a leaf component.
        """
        self.settings.environmentdefs = {
            "env": ["host1"],
        }
        self.settings.roledefs = {
            "role1": ["host1"],
        }
        self.settings.componentdefs = {
            "role1": ["comp1", "compgroup"],
            "compgroup": ["comp1"],
        }
        with self.assertRaises(Exception):
            map(lambda c: c.name, self.settings.for_env("env").with_roles("role1").components())


class TestHostDefinition(TestCase):
    """
    Test host iteration.
    """
    def setUp(self):

        self.settings = Settings()