Source code for tkp.config.parse

"""Utilities for loading parameters from config files, with automatic type 
conversion."""

import ast
import logging
import datetime
from tkp.utility import adict

logger = logging.getLogger(__name__)


## Use prefix loads / dumps for 'load string', 'dump string', a la JSON.
dt_w_microsecond_format = '%Y-%m-%dT%H:%M:%S.%f'


[docs]def loads_timestamp_w_microseconds(dt_str): """Loads and returns timestamp with microsecond precission""" return datetime.datetime.strptime(dt_str, dt_w_microsecond_format)
loads_methods = (ast.literal_eval, loads_timestamp_w_microseconds)
[docs]def parse_to_dict(config): """Loads the ConfigParser object as a nested dictionary. Automatically converts strings representing ints and floats to their respective types, through the magic of ast.literal_eval. This functionality is extensible via the loads_methods list. Each loads (load string) method is tested in turn to see if it throws an exception. If all throw, we assume the value is meant to be string. Any values that you don't want to be converted should simply be surrounded with quote marks in the parset - then ast.literal_eval knows to load it as a string. Args: config: A ConfigParser object. Returns: Nested dict {sections -> keys -> values } representing parsed params. """ pars = adict() #'DEFAULT' section is not listed by ``sections()``, # but we sometimes (ab)use it. sections = config.sections() if len(config.items('DEFAULT')): sections.append('DEFAULT') for section_name in sections: if section_name not in pars: pars[section_name] = adict() for k, rawval in config.items(section_name): val = rawval for func in loads_methods: try: val = func(rawval) break # Drop out of loop if exception not thrown except (ValueError, SyntaxError): pass # Try the next method if val == rawval: logger.debug("Parsing section: [%s]\n" "Could not parse key-value pair:\n%s = %s\n" "-assuming string value", section_name, k, rawval) pars[section_name][k] = val return pars