def _set_attr(self, attr, value): enforcer, _, _ = util.get_properties(self._schema[attr]) if not callable(enforcer): raise util.ConfigError('Attribute {} has no enforcer'.format(attr)) try: self._data[attr] = enforcer(value) except util.ConfigError as e: raise util.ConfigError('Error for attribute {}: '.format(attr) + str(e))
def _check_against_schema(self): for key, subschema in six.iteritems(self._schema): _, default, required = util.get_properties(subschema) if key not in self._data and default: setattr(self, util.as_attr(key), default) if key not in self._data and required: raise util.ConfigError('Attribute {} is required.'.format(key))
def policy_alias(self, value): """ Setter for this policy's alias, if it exists. :returns str: """ if value not in self.aliases: raise util.ConfigError( "Alias {} not specified in config, or it wasn't set before policies." .format(value)) self._set_attr('policy-alias', value)
def pin(self, value): """ Setter for the pinned keys for this policy :returns list: """ if value not in self.pinsets: raise util.ConfigError( "Pin {} not specified in config, or it wasn't set before policies." .format(value)) self._set_attr('pin', value)
def update(self, newer_config, merge=False): """Create a fresh config combining the new and old configs. It does this by iterating over the 'config_properties' class attribute which contains names of property attributes for the config. Two methods of combining configs are possible, an 'update' and a 'merge', the latter set by the keyword argument 'merge=True'. An update overrides older values with new values -- even if those new values are None. Update will remove values that are present in the old config if they are not present in the new config. A merge by comparison will allow old values to persist if they are not specified in the new config. This can be used for end-user customizations to override specific settings without having to re-create large portions of a config to override it. Arguments: newer_config: A config object to combine with the current config. merge: Allows old values not overridden to survive into the fresh config. Returns: A config object of the same sort as called upon. """ # removed 'merge' kw arg - and it was passed to constructor # make a note to not do that, consume it on the param list fresh_config = self.__class__(schema=self._schema) logger.debug('from parent update merge %s', merge) if not isinstance(newer_config, MergableConfig): raise util.ConfigError('Attempting to update a %s with a %s' % (self.__class__, newer_config.__class__)) for prop_name in self._schema.keys(): # get the specified property off of the current class prop = self.__class__.__dict__.get(util.as_attr(prop_name)) assert prop new_value = prop.fget(newer_config) old_value = prop.fget(self) if merge and new_value is not None: if isinstance(new_value, dict) and isinstance(old_value, dict): new_value = old_value.update(new_value) elif isinstance(new_value, list) and isinstance( old_value, list): new_value = old_value.extend(new_value) if new_value is not None: prop.fset(fresh_config, new_value) elif merge and old_value is not None: prop.fset(fresh_config, old_value) return fresh_config
def policy_alias(self, value): """ This type of policy can't be aliased. Throws an error on access.""" # pylint: disable=unused-argument raise util.ConfigError( 'PolicyNoAlias object cannot have policy-alias field!')