Beispiel #1
0
    def __init__(self, parser, name, validate=None, default_dict=None):
        '''
        New Section, used to describe options and validation
        rules for a configuration section.
        '''

        #   Validate validator callback if specified.
        if validate:
            _validate_validator(validate)

        #   Populate private attributes from call.
        self._name          = name
        self._rule_list     = list()
        self._validator     = validate

        #   Populate _value_dict from default dictionary, updating with
        #   data parsed from this configuration section.
        self._value_dict = AttrDict()
        if default_dict:
            self._value_dict.update(default_dict.items())
        self._value_dict.update(parser.items(name))
        return
Beispiel #2
0
class Section(object):
    '''Representation of a configuration section.'''

    _msg_prefix_all     = 'configuration validation error:'
    _msg_prefix_section = ' '.join((_msg_prefix_all,        'section \'%s\':'))
    _msg_prefix_option  = ' '.join((_msg_prefix_section,    'option \'%s\':'))

    def _make_option_exception(self, rule, msg):
        '''Format and return an exception for an option validation error.'''
        msg = (self._msg_prefix_option + ' %s') % (self.name, rule.option, msg)
        return Config.ValidationError(msg)

    def _make_section_exception(self, msg):
        '''Format and return an exception for an section validation error.'''
        msg = (self._msg_prefix_section + ' %s') % (self.name, msg)
        return Config.ValidationError(msg)
        
    #####

    def __init__(self, parser, name, validate=None, default_dict=None):
        '''
        New Section, used to describe options and validation
        rules for a configuration section.
        '''

        #   Validate validator callback if specified.
        if validate:
            _validate_validator(validate)

        #   Populate private attributes from call.
        self._name          = name
        self._rule_list     = list()
        self._validator     = validate

        #   Populate _value_dict from default dictionary, updating with
        #   data parsed from this configuration section.
        self._value_dict = AttrDict()
        if default_dict:
            self._value_dict.update(default_dict.items())
        self._value_dict.update(parser.items(name))
        return

    #####

    def __getattr__(self, attr):
        '''Allow Section's value dictionary to be accessed as attribute.'''
        return self._value_dict[attr.lower()]

    #####

    def __str__(self):
        return  '%s:%x' % (self._name, id(self))

    #####

    def add_rule(self, rule):
        '''
        Add OptionRule to this section. Returns section object so
        that multiple invocations of this method call can be chained.
        '''

        #   Validate that rule is subclass of expected type.
        if not isinstance(rule, OptionRule):
            raise TypeError('wrong type object %s' % str(rule))

        #   Append rule to internal rule list.
        self._rule_list.append(rule)
        return self

    #####

    def get_option(self, option_name):
        '''Returns option by name.'''
        return self.__getattr__(option_name)

    #####

    @property
    def name(self):
        '''Name of section.'''
        return self._name

    #####

    def options(self):
        '''Returns list of configuration options found for this section.'''
        return sorted(self._value_dict.keys())

    #####

    def rules(self):
        '''Returns list of option rules defined for this section.'''
        return sorted(self._rule_list, key=lambda x : x.option)

    #####

    def validate(self):
        '''Validate configuration section.'''

        #   List for errors accumulated by validation.
        error_list  = list()

        #   pylint: disable=E1101
        logging.debug('validating section \'%s\'', self.name)

        temp_value_dict = dict()

        #   Iterate over all defined rules.
        for rule in self._rule_list:
            #   pylint: disable=E1101
            logging.debug('validating option \'%s\'', rule.option)

            #   Does section have this attribute?
            if not hasattr(self, rule.option):
                #   Append error to error list if option doesn't appear in
                #   options for section; skip further processing of this rule.
                logging.debug('option \'%s\' missing', rule.option)
                error_list.append(self._make_option_exception(rule, 
                                  'required option missing'))
                continue

            #   If valid rule type specified, perform type conversion.
            if rule.type:
                try:
                    value = self._convert_type(rule)
                    temp_value_dict[rule.option.lower()] = value

                except Config.ValidationError as exc:
                    error_list.append(exc)

                #   pylint: disable=W0703
                except Exception as exc:
                    #   Append any error produced by type conversion to
                    #   error list.
                    log.log_exception()
                    error_list.append \
                        (self._make_option_exception(rule, 
                                                     'EXCEPTION: %s' % exc))

                    #   pylint: disable=E1101
                    logging.debug \
                        ('option \'%s\' failed to convert to %s', 
                         rule.option, rule.type.__name__)
                    continue

                #   pylint: disable=E1101
                logging.debug \
                    ('option \'%s\' converted to %s', 
                     rule.option, rule.type.__name__)

            else:
                #   No type converstion necessary for string option.
                value = getattr(self, rule.option)

            #   If rule validator callback is specified, call it with
            #   AttrDict consisting of a single rule/value pair.
            if rule.validator:
                try:
                    #   Call rule validator callback with converted value.
                    self._run_rule_validator(rule, value)
    
                except Config.ValidationError as exc:
                    error_list.append(exc)
                    logging.debug('option \'%s\' failed to validate', 
                                        rule.option)

                except Exception as exc:
                    #   Log exception.
                    log.log_exception()
                    #   Append error produced by rule validator to error list.
                    error_list.append(exc)
                    logging.debug('option \'%s\' failed to validate', 
                                        rule.option)
                    continue

                logging.debug('option \'%s\' validated', rule.option)

        #   If section validator callback is specified, call it with
        #   AttrDict consisting of a single rule/value pair.
        if self.validator:
            try:
                self._run_section_validator()

            except Config.ValidationError as exc:
                error_list.append(exc)

            except Exception as exc:
                #   Log exception.
                log.log_exception()
                #   Append error produced by validator callback to error list.
                error_list.append(exc)

            else:
                logging.debug('section \'%s\' failed to validate', self)


        #   Process errors produced by any validation steps.
        if error_list:
            raise ConfigError(*error_list)

        self._value_dict.update(temp_value_dict)
        return

    #####

    @property
    def validator(self):
        '''Validator function reference.'''
        return self._validator

    #####

    def _convert_type(self, rule):
        '''Perform requested type conversion on specified rule.'''

        try:
            #   Retrieve attribute value and perform type conversion.
            value = rule.convert(getattr(self, rule.option))

        except ValueError:
            raise self._make_option_exception \
                    (rule, 'type conversion to %s failed' % rule.type.__name__)

        #   Method completed without error; return converted value.
        return value

    #####

    def _run_rule_validator(self, rule, value):
        '''Run validator callback on specified rule.'''

        #   pylint: disable=E1101
        logging.debug('running rule validator %s for option \'%s\'', 
                      rule.validator.__name__, rule.option)

        try:
            rule.validator(AttrDict({ rule.option : value }))

        except Config.ValidationError as exc:
            raise self._make_option_exception(rule, exc)
            
        #   Method completed without error.
        return

    #####

    def _run_section_validator(self):
        '''Run validator callback on Section.'''

        #   pylint: disable=E1101
        logging.debug('running section validator %s', 
                      self._validator.__name__)

        try:
            self.validator(self)

        except Config.ValidationError as exc:
            raise self._make_section_exception(exc)

        #   Method completed without error.
        return