Exemple #1
0
    def __set__(self, obj, value):
        value = remove_convertible(value)
        self._check_type(value)
        if not isinstance(value, ScopedDict):
            value = ScopedDict(value) if value is not None else value

        Field.__set__(self, obj, value)
Exemple #2
0
def test_scoped_dict_field():
    class FieldTester:
        field = fields.ScopedDictField(int)
        field_maybe_none = fields.ScopedDictField(
            int, type(None))

    tester = FieldTester()

    # Test valid assignments
    tester.field = {
        'a': {'k1': 1, 'k2': 2},
        'a:b': {'k1': 3, 'k3': 4},
        'a:b:c': {'k2': 5, 'k3': 6},
        '*': {'k1': 7, 'k3': 9, 'k4': 10}
    }
    tester.field_maybe_none = None

    # Check that we have indeed a ScopedDict here
    assert isinstance(FieldTester.field, fields.ScopedDictField)
    assert isinstance(tester.field, ScopedDict)
    assert 10 == tester.field['a:k4']

    # Test invalid assignments
    with pytest.raises(TypeError):
        tester.field = {1: "a", 2: "b"}

    with pytest.raises(TypeError):
        tester.field = [('a', 1), ('b', 2)]

    with pytest.raises(TypeError):
        tester.field = {'a': {1: 'k1'}, 'b': {2: 'k2'}}

    # Test assigning a ScopedDict already
    tester.field = ScopedDict({})
Exemple #3
0
    def test_scoped_dict_field(self):
        class FieldTester:
            field = fields.ScopedDictField('field', int)
            field_maybe_none = fields.ScopedDictField('field_maybe_none', int,
                                                      type(None))

        tester = FieldTester()

        # Test valid assignments
        tester.field = {
            'a': {
                'k1': 1,
                'k2': 2
            },
            'a:b': {
                'k1': 3,
                'k3': 4
            },
            'a:b:c': {
                'k2': 5,
                'k3': 6
            },
            '*': {
                'k1': 7,
                'k3': 9,
                'k4': 10
            }
        }
        tester.field_maybe_none = None

        # Check that we have indeed a ScopedDict here
        self.assertIsInstance(FieldTester.field, fields.ScopedDictField)
        self.assertIsInstance(tester.field, ScopedDict)
        self.assertEqual(10, tester.field['a:k4'])

        # Test invalid assignments
        self.assertRaises(TypeError, exec, 'tester.field = {1: "a", 2: "b" }',
                          globals(), locals())
        self.assertRaises(TypeError, exec,
                          "tester.field = [('a', 1), ('b', 2)]", globals(),
                          locals())
        self.assertRaises(
            TypeError, exec, """tester.field = {'a': {1: 'k1'},
                                             'b': {2: 'k2'}}""", globals(),
            locals())

        # Test assigning a ScopedDict already
        tester.field = ScopedDict({})
Exemple #4
0
    def select_subconfig(self,
                         system_fullname=None,
                         ignore_resolve_errors=False):
        if (self._local_system is not None
                and self._local_system == system_fullname):
            return

        system_fullname = system_fullname or self._detect_system()
        getlogger().debug(f'Selecting subconfig for {system_fullname!r}')
        try:
            system_name, part_name = system_fullname.split(':', maxsplit=1)
        except ValueError:
            # system_name does not have a partition
            system_name, part_name = system_fullname, None

        # Start from a fresh copy of the site_config, because we will be
        # modifying it
        site_config = copy.deepcopy(self._site_config)
        self._local_config = {}
        systems = list(
            filter(lambda x: x['name'] == system_name, site_config['systems']))
        if not systems:
            raise ConfigError(f"could not find a configuration entry "
                              f"for the requested system: '{system_name}'")

        if part_name is not None:
            # Filter out also partitions
            systems[0]['partitions'] = list(
                filter(lambda x: x['name'] == part_name,
                       systems[0]['partitions']))

        if not systems[0]['partitions']:
            raise ConfigError(
                f"could not find a configuration entry "
                f"for the requested system/partition combination: "
                f"'{system_name}:{part_name}'")

        # Create local configuration for the current or the requested system
        self._local_config['systems'] = systems
        for name, section in site_config.items():
            if name == 'systems':
                # The systems sections has already been treated
                continue

            # Convert section to a scoped dict that will handle correctly and
            # transparently the system/partition resolution
            scoped_section = ScopedDict()
            for obj in section:
                key = obj.get('name', name)
                target_systems = obj.get(
                    'target_systems',
                    _match_option(f'{name}/target_systems',
                                  self._schema['defaults']))
                for t in target_systems:
                    scoped_section[f'{t}:{key}'] = obj

            unique_keys = set()
            for obj in section:
                key = obj.get('name', name)
                if key in unique_keys:
                    continue

                unique_keys.add(key)
                try:
                    val = scoped_section[f"{system_fullname}:{key}"]
                except KeyError:
                    pass
                else:
                    self._local_config.setdefault(name, [])
                    self._local_config[name].append(val)

        required_sections = self._schema['required']
        for name in required_sections:
            if name not in self._local_config.keys():
                if not ignore_resolve_errors:
                    raise ConfigError(f"section '{name}' not defined "
                                      f"for system '{system_fullname}'")

        # Verify that all environments defined by the system are defined for
        # the current system
        if not ignore_resolve_errors:
            sys_environs = {
                *itertools.chain(*(p['environs']
                                   for p in systems[0]['partitions']))
            }
            found_environs = {
                e['name']
                for e in self._local_config['environments']
            }
            undefined_environs = sys_environs - found_environs
            if undefined_environs:
                env_descr = ', '.join(f"'{e}'" for e in undefined_environs)
                raise ConfigError(f"environments {env_descr} "
                                  f"are not defined for '{system_fullname}'")

        self._local_system = system_fullname