/usr/share/pyshared/pebl/config.py is in python-pebl 1.0.2-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | """Classes and functions for specifying and working with parameters."""
from __future__ import with_statement
import sys
import os.path
from ConfigParser import ConfigParser
from itertools import groupby
from time import asctime
from operator import attrgetter
from pebl.util import unzip, as_list
#
# Global list of parameters
#
_parameters = {}
#
# Validator Factories (they return validator functions)
#
def between(min, max):
"""Returns validator that checks whether value is between min and max."""
v = lambda x: x >= min and x <= max
v.__doc__ = "Parameter value should be between %d and %d." % (min,max)
return v
def oneof(*values):
"""Returns validator that checks whether value is in approved list."""
v = lambda x: x in values
v.__doc__ = "Parameter value should be one of {%s}." % ', '.join(values)
return v
def atleast(min):
"""Returns validator that checks whether value is > min."""
v = lambda x: x >= min
v.__doc__ = "Parameter value should be at least %d." % min
return v
def atmost(max):
"""Returns validator that checks whether value is < max."""
v = lambda x: x <= max
v.__doc__ = "Parameter value should be at most %d." % max
return v
def fileexists():
"""Returns validator that checks whether value is an existing file."""
v = lambda x: os.path.exists(x) and os.path.isfile(x)
v.__doc__ = "Parameter value should be a file that exists."
return v
#
# Parameter classes
#
def default_validator(x):
return True
class Parameter:
"""Classes for configuration parameters."""
datatype = None
def __init__(self, name, description, validator=default_validator, default=None):
nameparts = name.split('.')
if len(nameparts) is not 2:
raise Exception("Parameter name has to be of the form 'section.name'")
self.name = name.lower()
self.section, self.option = nameparts
self.description = description
self.validator = validator
self.value = self.default = default
self.source = None
# add self to the parameter registry
_parameters[self.name] = self
class StringParameter(Parameter): datatype=str
class IntParameter(Parameter): datatype=int
class FloatParameter(Parameter): datatype=float
#
# Functions for {get/set/read/write/list}ing parameters
#
def set(name, value, source='config.set'):
"""Set a parameter value.
- name should be of the form "section.name".
- value can be a string which will be casted to the required datatype.
- source specifies where this parameter value was specified (config file,
command line, interactive shell, etc).
"""
name = name.lower()
if name not in _parameters:
msg = "Parameter %s is unknown." % name
raise KeyError(msg)
param = _parameters[name]
# try coercing value to required data type
try:
value = param.datatype(value)
except ValueError, e:
msg = "Cannot convert value to required datatype: %s" % e.message
raise Exception(msg)
# try validating
try:
valid = param.validator(value)
except:
msg = "Validator for parameter %s caused an error while validating" + \
"value %s"
raise Exception(msg % (name, value))
if not valid:
raise Exception("Value %s is not valid for parameter %s. %s" % \
(value, name, param.validator.__doc__ or 'error unknown'))
param.value = value
param.source = source
def get(name):
"""Returns value of parameter.
Raises KeyError if parameter not found.
Examples::
from pebl import config
config.get('data.filename')
config.get('result.format')
The value returned could be the default value or the latest value set using
config.set or config.read
"""
name = name.lower()
if name in _parameters:
return _parameters[name].value
else:
raise KeyError("Parameter %s not found." % name)
def read(filename):
"""Reads parameter from config file.
Config files should conform to the format specified in the ConfigParser
module from Python's standard library. A Parameter's name has two parts:
the section and the option name. These correspond to 'section' and
'option' as defined in ConfigParser.
For example, parameter 'foo.bar' would be specified in the config file as::
[foo]
bar = 5
"""
config = ConfigParser()
config.read(filename)
errors = []
for section in config.sections():
for option,value in config.items(section):
name = "%s.%s" % (section, option)
try:
set(name, value, "config file %s" % filename)
except Exception, e:
errors.append(str(e))
if errors:
errheader = "%d errors encountered:" % len(errors)
raise Exception("\n".join([errheader] + errors))
def write(filename, include_defaults=False):
"""Writes parameters to config file.
If include_default is True, writes all parameters. Else, only writes
parameters that were specifically set (via config file, command line, etc).
"""
config = ConfigParser()
params = _parameters.values() if include_defaults \
else [p for p in _parameters.values() if p.source]
for param in params:
config.set(param.section, param.option, param.value)
with file(filename, 'w') as f:
config.write(f)
def parameters(section=None):
"""Returns list of parameters.
If section is specified, returns parameters for that section only.
section can be a section name or a search string to use with
string.startswith(..)
"""
if section:
return [p for p in _parameters.values() if p.name.startswith(section)]
else:
return _parameters.values()
def paramdocs(section=None, section_header=False):
lines = []
params = sorted(parameters(section), key=attrgetter('name'))
lines += [".. Autogenerated by pebl.config.paramdocs at %s\n\n" % asctime()]
for section, options in groupby(params, lambda p:p.section):
if section_header:
lines += ["%s\n%s\n\n" % (section, '-'*len(section))]
lines += [".. confparam:: %s\n\n\t%s\n\tdefault=%s\n\n" %
(o.name,
o.description,
'None' if o.default is None else o.default)
for o in options]
return ''.join(lines)
def configobj(params):
"""Given a list of parameters, returns a ConfigParser object.
This function can be used to convert a list of parameters to a config
object which can then be written to file.
"""
if isinstance(params, list):
params = dict((p.name, p.value) for p in params)
configobj = ConfigParser()
for key,value in params.items():
section,name = key.strip().split('.')
if section not in configobj.sections():
configobj.add_section(section)
configobj.set(section, name, value)
return configobj
def setparams(obj, options):
"""Sets attributes of self based on options and pebl.config."""
for p in getattr(obj, '_params', []):
setattr(obj, p.option, options.get(p.option, get(p.name)))
|