from collections import namedtuple try: # Python 2 from ConfigParser import ConfigParser except ImportError: # Python 3 from configparser import ConfigParser CONFIG_SECTION_LOCATION = 'location' CONFIG_SECTION_RETENTION = 'retention' CONFIG_FORMAT = { CONFIG_SECTION_LOCATION: ('source_directories', 'repository'), CONFIG_SECTION_RETENTION: ('keep_daily', 'keep_weekly', 'keep_monthly'), } LocationConfig = namedtuple('LocationConfig', CONFIG_FORMAT[CONFIG_SECTION_LOCATION]) RetentionConfig = namedtuple('RetentionConfig', CONFIG_FORMAT[CONFIG_SECTION_RETENTION]) def parse_configuration(config_filename): ''' Given a config filename of the expected format, return the parse configuration as a tuple of (LocationConfig, RetentionConfig). Raise IOError if the file cannot be read, or ValueError if the format is not as expected. ''' parser = ConfigParser() parser.readfp(open(config_filename)) section_names = parser.sections() expected_section_names = CONFIG_FORMAT.keys() if set(section_names) != set(expected_section_names): raise ValueError( 'Expected config sections {} but found sections: {}'.format( ', '.join(expected_section_names), ', '.join(section_names) ) ) for section_name in section_names: option_names = parser.options(section_name) expected_option_names = CONFIG_FORMAT[section_name] if set(option_names) != set(expected_option_names): raise ValueError( 'Expected options {} in config section {} but found options: {}'.format( ', '.join(expected_option_names), section_name, ', '.join(option_names) ) ) return ( LocationConfig(*( parser.get(CONFIG_SECTION_LOCATION, option_name) for option_name in CONFIG_FORMAT[CONFIG_SECTION_LOCATION] )), RetentionConfig(*( parser.getint(CONFIG_SECTION_RETENTION, option_name) for option_name in CONFIG_FORMAT[CONFIG_SECTION_RETENTION] )) )