diff options
Diffstat (limited to 'rpki/config.py')
-rw-r--r-- | rpki/config.py | 87 |
1 files changed, 46 insertions, 41 deletions
diff --git a/rpki/config.py b/rpki/config.py index 0e30982b..b8d25896 100644 --- a/rpki/config.py +++ b/rpki/config.py @@ -32,23 +32,16 @@ logger = logging.getLogger(__name__) ## @var default_filename # Default name of config file if caller doesn't specify one explictly. -default_filename = "rpki.conf" - -## @var default_dirname -# Default name of directory to check for global config file, or None -# if no global config file. Autoconf-generated code may set this to a -# non-None value during script startup. - try: import rpki.autoconf - default_dirname = rpki.autoconf.sysconfdir + default_filename = os.path.join(rpki.autoconf.sysconfdir, "rpki.conf") except ImportError: - default_dirname = None + default_filename = None -## @var default_envname +## @var rpki_conf_envname # Name of environment variable containing config file name. -default_envname = "RPKI_CONF" +rpki_conf_envname = "RPKI_CONF" class parser(object): """ @@ -61,44 +54,48 @@ class parser(object): get-methods with default values and default section name. - If no filename is given to the constructor (filename = None), we - check for an environment variable naming the config file, then we - check for a default filename in the current directory, then finally - we check for a global config file if autoconf provided a directory - name to check. + If no filename is given to the constructor (filename and + set_filename both None), we check for an environment variable naming + the config file, then finally we check for a global config file if + autoconf provided a directory name to check. + + NB: Programs which accept a configuration filename on the command + lines should pass that filename using set_filename so that we can + set the magic environment variable. Constraints from some external + libraries (principally Django) sometimes require library code to + look things up in the configuration file without the knowledge of + the controlling program, but setting the environment variable + insures that everybody's reading from the same script, as it were. """ - def __init__(self, filename = None, section = None, allow_missing = False): + # Odd keyword-only calling sequence is a defense against old code + # that thinks it knows how __init__() handles positional arguments. + + def __init__(self, **kwargs): + section = kwargs.pop("section", None) + allow_missing = kwargs.pop("allow_missing", False) + set_filename = kwargs.pop("set_filename", None) + filename = kwargs.pop("filename", set_filename) + + assert not kwargs, "Unexpected keyword arguments: " + ", ".join("%s = %r" % kv for kv in kwargs.iteritems()) + + if set_filename is not None: + os.environ[rpki_conf_envname] = set_filename self.cfg = ConfigParser.RawConfigParser() self.default_section = section - filenames = [] - if filename is not None: - filenames.append(filename) - else: - if default_envname in os.environ: - filenames.append(os.environ[default_envname]) - filenames.append(default_filename) - if default_dirname is not None: - filenames.append("%s/%s" % (default_dirname, default_filename)) + self.filename = filename or os.getenv(rpki_conf_envname) or default_filename - f = fn = None + try: + with open(self.filename, "r") as f: + self.cfg.readfp(f) + except IOError: + if allow_missing: + self.filename = None + else: + raise - for fn in filenames: - try: - f = open(fn) - break - except IOError: - f = None - - if f is not None: - self.filename = fn - self.cfg.readfp(f, fn) - elif allow_missing: - self.filename = None - else: - raise def has_section(self, section): """ @@ -107,6 +104,7 @@ class parser(object): return self.cfg.has_section(section) + def has_option(self, option, section = None): """ Test whether an option exists. @@ -116,6 +114,7 @@ class parser(object): section = self.default_section return self.cfg.has_option(section, option) + def multiget(self, option, section = None): """ Parse OpenSSL-style foo.0, foo.1, ... subscripted options. @@ -134,6 +133,7 @@ class parser(object): for option in matches: yield self.cfg.get(section, option) + _regexp = re.compile("\\${(.*?)::(.*?)}") def _repl(self, m): @@ -148,6 +148,7 @@ class parser(object): else: return self.cfg.get(section, option) + def get(self, option, default = None, section = None): """ Get an option, perhaps with a default value. @@ -163,6 +164,7 @@ class parser(object): if not modified: return val + def getboolean(self, option, default = None, section = None): """ Get a boolean option, perhaps with a default value. @@ -176,6 +178,7 @@ class parser(object): v = self.cfg._boolean_states[v] return v + def getint(self, option, default = None, section = None): """ Get an integer option, perhaps with a default value. @@ -183,6 +186,7 @@ class parser(object): return int(self.get(option, default, section)) + def getlong(self, option, default = None, section = None): """ Get a long integer option, perhaps with a default value. @@ -190,6 +194,7 @@ class parser(object): return long(self.get(option, default, section)) + def set_global_flags(self): """ Consolidated control for all the little global control flags |