def test_get_or_set(self):
     """Test get_or_setting values
     """
     self.hod = HierarchicalOrderedDict()
     self.assertRaises(KeyError, self.hod.get, 'a')
     self.assertEqual(self.hod.get_or_set('a', 42), 42)
     self.assertEqual(self.hod.get('a'), 42)
     self.hod['a'] = 52
     self.assertEqual(self.hod.get_or_set('a', 42), 52)
    def test_merge_empty(self):
        """Test merging in empty mapping
        """
        self.hod = HierarchicalOrderedDict()
        self.hod['a'] = 12
        self.hod['b'] = 13
        self.hod['c.d'] = 14
        self.hod['e.f.g'] = 15
        items = list(self.hod.items())

        m_2 = HierarchicalOrderedDict()
        self.hod.merge(m_2)
        self.assertEqual(len(self.hod), 4)
        for key, value in items:
            self.hod[key] = value
Example #3
0
 def test_boolean_spec(self):
     """Test generating a spec from a boolean
     """
     default = HierarchicalOrderedDict()
     default['a'] = True
     self.assert_equal_encoded_list(
         ohm_to_spec(default),
         ["a = boolean(default=True)"])
Example #4
0
 def test_string_spec(self):
     """Test generating a spec from a string
     """
     default = HierarchicalOrderedDict()
     default['a'] = "bla"
     self.assert_equal_encoded_list(
         ohm_to_spec(default),
         ["a = string(default=bla)"])
Example #5
0
 def test_float_spec(self):
     """Test generating a spec from a float
     """
     default = HierarchicalOrderedDict()
     default['a'] = 1.2
     self.assert_equal_encoded_list(
         ohm_to_spec(default),
         ["a = float(default=1.2)"])
Example #6
0
 def test_int_spec(self):
     """Test generating a spec from an integer
     """
     default = HierarchicalOrderedDict()
     default['a'] = 12
     self.assert_equal_encoded_list(
         ohm_to_spec(default),
         ["a = integer(default=12)"])
Example #7
0
 def test_level1_spec(self):
     """Test generating a spec with one level
     """
     default = HierarchicalOrderedDict()
     default['a.b'] = 1.2
     self.assert_equal_encoded_list(
         ohm_to_spec(default),
         ["[a]", "b = float(default=1.2)"])
    def test_merge_same(self):
        """Test merging mapping with same keys
        """
        self.hod = HierarchicalOrderedDict()
        self.hod['a'] = 12
        self.hod['b'] = 13
        self.hod['c.d'] = 14
        self.hod['e.f.g'] = 15
        items = list(self.hod.items())

        m_2 = HierarchicalOrderedDict()
        m_2['a'] = 12
        m_2['b'] = 13
        m_2['c.d'] = 14
        m_2['e.f.g'] = 15
        self.hod.merge(m_2)
        self.assertEqual(len(self.hod), 4)
        for key, value in items:
            self.hod[key] = value
def conf_to_ohm(conf, ohm=None, section_name=''):
    """Converts a configobj to an OrderedHierarchicalMapping
    """
    if conf is None:
        return HierarchicalOrderedDict()

    if ohm is None:
        ohm = HierarchicalOrderedDict()

    for key, value in conf.items():
        if not section_name == '':
            new_key = (section_name +
                       HierarchicalOrderedDict.SECTION_SEPARATOR + key)
        else:
            new_key = key
        if not isinstance(value, configobj.Section):
            ohm[new_key] = value
        else:
            conf_to_ohm(value, ohm=ohm, section_name=new_key)
    return ohm
    def test_merge_other_keys(self):
        """Test merging in mapping with other keys
        """
        self.hod = HierarchicalOrderedDict()
        self.hod['a'] = 12
        self.hod['b'] = 13
        self.hod['c.d'] = 14
        self.hod['e.f.g'] = 15
        items = list(self.hod.items())

        m_2 = HierarchicalOrderedDict()
        m_2['k'] = 13
        m_2['l.m.n'] = 'bla'
        items2 = list(m_2.items())

        self.hod.merge(m_2)

        self.assertEqual(len(self.hod), 6)
        for key, value in items + items2:
            self.hod[key] = value
    def test_base_keys(self):
        """Test getting the base keys
        """
        self.hod = HierarchicalOrderedDict()
        self.hod['a'] = 12
        self.hod['b'] = 13
        self.hod['c.d'] = 14
        self.hod['e.f.g'] = 15

        base_keys = self.hod.base_keys()
        self.assertIn('a', base_keys)
        self.assertIn('b', base_keys)
        self.assertIn('c', base_keys)
        self.assertIn('e', base_keys)
        self.assertNotIn('c.d', base_keys)
        self.assertNotIn('d', base_keys)
        self.assertNotIn('e.f', base_keys)
        self.assertNotIn('e.f.g', base_keys)
        self.assertNotIn('f.g', base_keys)
        self.assertNotIn('f', base_keys)
        self.assertNotIn('g', base_keys)
Example #12
0
 def test_level2_spec(self):
     """Test generating a spec with two levels
     """
     default = HierarchicalOrderedDict()
     default['a.b'] = 1.2
     default['a.c.d'] = 3
     self.assert_equal_encoded_list(
         ohm_to_spec(default),
         ["[a]",
          "b = float(default=1.2)",
          "[[c]]",
          "d = integer(default=3)"])
    def test_merge_overlapping(self):
        """Test merging in mapping with overlapping keys
        """
        self.hod['a'] = 12
        self.hod['b'] = 13
        self.hod['c.d'] = 14
        self.hod['e.f.g'] = 15
        items = list(self.hod.items())

        m_2 = HierarchicalOrderedDict()
        m_2['c.d'] = 10
        m_2['k'] = 13
        m_2['l.m.n'] = 'bla'
        items2 = list(m_2.items())

        self.hod.merge(m_2)

        self.assertEqual(len(self.hod), 6)
        for key, value in items:
            self.hod[key] = value
        for key, value in items2:
            if key not in [item[0] for item in items]:
                self.hod[key] = value
Example #14
0
 def test_level1_spec_unordered(self):
     """Test generating a spec with one level and wrong order
     """
     default = HierarchicalOrderedDict()
     default['a.b'] = 1.2
     default['c'] = 3.4
     default['n.k'] = 2
     default['d.a'] = 3
     default['a.a'] = 1
     self.assert_equal_encoded_list(
         ohm_to_spec(default),
         ["c = float(default=3.4)",
          "[a]",
          "a = integer(default=1)",
          "b = float(default=1.2)",
          "[d]",
          "a = integer(default=3)",
          "[n]",
          "k = integer(default=2)"])
class TestHierarchicalOrderedDict(unittest.TestCase):
    """Test the ``HierarchicalOrderedDict``
    """
    def setUp(self):
        """Set up the test fixture
        """
        self.hod = HierarchicalOrderedDict()

    def test_len_empty_mapping(self):
        """Test if the empty mapping is really empty
        """
        self.assertEqual(len(self.hod), 0)

    def test_insert_retrieve_base_level(self):
        """Make sure we can use the container at the base
        """
        self.hod['a'] = 12

        self.assertEqual(self.hod['a'], 12)

    def test_retrieve_second_level(self):
        """Make sure we can use the container at the second level
        """
        self.hod['hello.world'] = 12
        self.assertEqual(self.hod['hello.world'], 12)

    def test_len_after_first_level(self):
        """Test if the length is correct after inserting at the first level
        """
        self.assertEqual(len(self.hod), 0)

        # New keys should increase the length
        for i, key in enumerate(['a', 'b', 'c', 'd', 'e', 'f']):
            self.hod[key] = i ** 2
            self.assertEqual(len(self.hod), i + 1)

        # Existing keys should keep the length
        for key in ['a', 'b', 'c', 'd', 'e', 'f']:
            self.hod[key] = 12
            self.assertEqual(len(self.hod), 5 + 1)

    def test_inserting_higher_levels(self):
        """Test if the length is correct after inserting at the first level
        """
        self.assertEqual(len(self.hod), 0)

        # New keys should increase the length
        i = 0
        for key1 in ['a', 'b', 'c', 'd', 'e', 'f']:
            for key2 in ['a', 'b', 'c', 'd', 'e', 'f']:
                i += 1
                self.hod[key1 + '.' + key2] = i
                self.assertEqual(len(self.hod), i)

    def test_keys(self):
        """Test the keys method on the mapping
        """
        self.assertEqual(len(self.hod), 0)

        # New keys
        keys = ['a', 'b', 'c', 'd', 'e', 'f']
        for i, key in enumerate(keys):
            self.hod[key] = i
        self.assertEqual(list(self.hod.keys()), keys)

    def test_contains(self):
        """Test the HierarchicalOrderedDict with `in`
        """
        self.assertEqual(len(self.hod), 0)

        self.assertFalse('a' in self.hod)
        self.hod['a'] = 1
        self.assertTrue('a' in self.hod)

        self.assertFalse('b.c.d' in self.hod)
        self.hod['b.c.d'] = 1
        self.assertTrue('b.c.d' in self.hod)

    def test_get(self):
        """Test getting values with and without default values
        """
        self.assertRaises(KeyError, self.hod.get, 'a')
        self.assertEqual(self.hod.get('a', 42), 42)
        self.hod['a'] = 123
        self.assertEqual(self.hod.get('a', 42), 123)

    def test_get_or_set(self):
        """Test get_or_setting values
        """
        self.hod = HierarchicalOrderedDict()
        self.assertRaises(KeyError, self.hod.get, 'a')
        self.assertEqual(self.hod.get_or_set('a', 42), 42)
        self.assertEqual(self.hod.get('a'), 42)
        self.hod['a'] = 52
        self.assertEqual(self.hod.get_or_set('a', 42), 52)

    def test_set_wrong_key(self):
        """Test error is raised when keys are not strings
        """
        self.assertRaises(TypeError, self.hod.__setitem__, 12, 13)

    def test_base_keys(self):
        """Test getting the base keys
        """
        self.hod = HierarchicalOrderedDict()
        self.hod['a'] = 12
        self.hod['b'] = 13
        self.hod['c.d'] = 14
        self.hod['e.f.g'] = 15

        base_keys = self.hod.base_keys()
        self.assertIn('a', base_keys)
        self.assertIn('b', base_keys)
        self.assertIn('c', base_keys)
        self.assertIn('e', base_keys)
        self.assertNotIn('c.d', base_keys)
        self.assertNotIn('d', base_keys)
        self.assertNotIn('e.f', base_keys)
        self.assertNotIn('e.f.g', base_keys)
        self.assertNotIn('f.g', base_keys)
        self.assertNotIn('f', base_keys)
        self.assertNotIn('g', base_keys)

    def test_merge_empty(self):
        """Test merging in empty mapping
        """
        self.hod = HierarchicalOrderedDict()
        self.hod['a'] = 12
        self.hod['b'] = 13
        self.hod['c.d'] = 14
        self.hod['e.f.g'] = 15
        items = list(self.hod.items())

        m_2 = HierarchicalOrderedDict()
        self.hod.merge(m_2)
        self.assertEqual(len(self.hod), 4)
        for key, value in items:
            self.hod[key] = value

    def test_merge_same(self):
        """Test merging mapping with same keys
        """
        self.hod = HierarchicalOrderedDict()
        self.hod['a'] = 12
        self.hod['b'] = 13
        self.hod['c.d'] = 14
        self.hod['e.f.g'] = 15
        items = list(self.hod.items())

        m_2 = HierarchicalOrderedDict()
        m_2['a'] = 12
        m_2['b'] = 13
        m_2['c.d'] = 14
        m_2['e.f.g'] = 15
        self.hod.merge(m_2)
        self.assertEqual(len(self.hod), 4)
        for key, value in items:
            self.hod[key] = value

    def test_merge_other_keys(self):
        """Test merging in mapping with other keys
        """
        self.hod = HierarchicalOrderedDict()
        self.hod['a'] = 12
        self.hod['b'] = 13
        self.hod['c.d'] = 14
        self.hod['e.f.g'] = 15
        items = list(self.hod.items())

        m_2 = HierarchicalOrderedDict()
        m_2['k'] = 13
        m_2['l.m.n'] = 'bla'
        items2 = list(m_2.items())

        self.hod.merge(m_2)

        self.assertEqual(len(self.hod), 6)
        for key, value in items + items2:
            self.hod[key] = value

    def test_merge_overlapping(self):
        """Test merging in mapping with overlapping keys
        """
        self.hod['a'] = 12
        self.hod['b'] = 13
        self.hod['c.d'] = 14
        self.hod['e.f.g'] = 15
        items = list(self.hod.items())

        m_2 = HierarchicalOrderedDict()
        m_2['c.d'] = 10
        m_2['k'] = 13
        m_2['l.m.n'] = 'bla'
        items2 = list(m_2.items())

        self.hod.merge(m_2)

        self.assertEqual(len(self.hod), 6)
        for key, value in items:
            self.hod[key] = value
        for key, value in items2:
            if key not in [item[0] for item in items]:
                self.hod[key] = value

    def test_section_keys(self):
        """Test the section_keys method on the mapping
        """
        self.assertEqual(len(list(self.hod.section_keys())), 0)

        # New keys
        keys = ['a', 'b.c', 'd.e.f', 'g.h', 'j.k.l.m']
        for i, key in enumerate(keys):
            self.hod[key] = i

        self.assertIn('b', self.hod.section_keys())
        self.assertIn('d.e', self.hod.section_keys())
        self.assertIn('g', self.hod.section_keys())
        self.assertIn('j.k.l', self.hod.section_keys())
        self.assertNotIn('a', self.hod.section_keys())
        self.assertNotIn('c', self.hod.section_keys())
        self.assertNotIn('b.c', self.hod.section_keys())
        self.assertNotIn('e', self.hod.section_keys())
        self.assertNotIn('e.f', self.hod.section_keys())
        self.assertNotIn('d.e.f', self.hod.section_keys())
        self.assertNotIn('h', self.hod.section_keys())
        self.assertNotIn('m', self.hod.section_keys())
Example #16
0
 def reset_instance(cls):
     """Overloads reset_instance to reset the DEFAULT_CONFIG
     """
     cls.DEFAULT_CONFIG = HierarchicalOrderedDict()
     super(Config, cls).reset_instance()
Example #17
0
 def test_empty_ohm(self):
     """Test converting empty ohm
     """
     ohm = HierarchicalOrderedDict()
     conf = ohm_to_spec(ohm)
     self.assertIsInstance(conf, list)
 def setUp(self):
     """Set up the test fixture
     """
     self.hod = HierarchicalOrderedDict()
Example #19
0
class Config(
        HierarchicalMapping,  # pylint: disable=too-many-ancestors
        DefaultSingleton):
    """Represents a singleton configuration object.
    """
    CONFIG_SPEC_PATH = 'configspec.ini'
    """Path of the file with the specification for configurations.
    """

    DEFAULT_CONFIG = HierarchicalOrderedDict()
    """Default configuration, later used by initialize
    """
    @classmethod
    def _is_section(cls, obj):
        """Returns true if obj is a section
        """
        return isinstance(obj, configobj.Section)

    @classmethod
    def reset_instance(cls):
        """Overloads reset_instance to reset the DEFAULT_CONFIG
        """
        cls.DEFAULT_CONFIG = HierarchicalOrderedDict()
        super(Config, cls).reset_instance()

    @classmethod
    def _get_pseudo_instance(cls):
        """Overloaded method returning the DEFAULT_CONFIG with added methods
        """
        def save_unitialized(filename):
            """Saves an unitialized config
            """
            cls.initialize()
            cls.get_instance().save(filename)

        cls.DEFAULT_CONFIG.reset_instance = Config.reset_instance
        cls.DEFAULT_CONFIG.load = cls.initialize
        cls.DEFAULT_CONFIG.save = save_unitialized

        return cls.DEFAULT_CONFIG

    def _new_section(self, parent, level):
        """Creates a new section Mapping
        """
        return configobj.Section(parent, level, self.base)

    def __init__(self,
                 filename=None,
                 spec=CONFIG_SPEC_PATH,
                 options=None,
                 default_spec=None):
        """Initializer
        """
        super(Config, self).__init__()
        self.read_from_file = None
        self.filename = None

        # Merge specs, giving precedence to user spec, then, before_init_spec,
        # then default_spec
        if ((spec == self.CONFIG_SPEC_PATH
             and not os.path.isfile(self.CONFIG_SPEC_PATH))):
            spec = None

        user_spec_ohm = thread_first(spec, convert_spec, conf_to_ohm)
        before_init_spec_ohm = thread_first(self.DEFAULT_CONFIG, ohm_to_spec,
                                            convert_spec, conf_to_ohm)
        default_spec_ohm = thread_first(default_spec, convert_spec,
                                        conf_to_ohm)

        user_spec_ohm.merge(before_init_spec_ohm)
        user_spec_ohm.merge(default_spec_ohm)
        full_spec = ohm_to_spec_list(user_spec_ohm)

        # Load the configuration and overload it with the options
        if filename is not None:
            self.load(filename, full_spec, options)
        else:
            self.base = configobj.ConfigObj()

        # Unless the options are already there, overload them with the defaults
        # set before initialization
        for key, value in self.DEFAULT_CONFIG.items():
            if key not in self:
                self[key] = value

    def override_with_args(self, options):
        """Override configuration with option dictionary
        """
        for key, value in options:
            self[key] = value

    @staticmethod
    def validate_config(config):
        """Validate configuration
        """
        validator = validate.Validator()
        result = config.validate(validator, copy=True, preserve_errors=True)

        if not isinstance(result, bool):
            raise ValueError("Configuration does not adhere"
                             " to the specification: %s" %
                             configobj.flatten_errors(config, result))
        elif not result:
            # This should never happen
            raise RuntimeError(  # pragma: no cover
                "Configuration validated to false.")

    def load(self, filename, spec=None, options=None):
        """Loads a configuration from filename (or string). Missing values
        will be read from the specification file or string.
        """
        # Check if config file exists
        read_from_file = os.path.isfile(filename)
        if read_from_file:
            self.filename = filename

        # Create the configuration (overriding the default with user
        # specs if necessary)
        self.base = configobj.ConfigObj(filename, configspec=spec)

        # Override options
        if options is not None:
            self.override_with_args(options)

        # Validate the configuration
        if spec is not None:
            self.validate_config(self.base)

        # Add some more info
        self.base.read_from_file = read_from_file

    def save(self, filename):
        """Write configuration to file
        """
        if self.base is None:
            # This should never happen
            raise RuntimeError(  # pragma: no cover
                "Configuration not initialized yet.")
        else:
            with open(filename, 'wb') as outfile:
                self.base.write(outfile)