root / trunk / src / haizea / common / config.py @ 641
1 |
# -------------------------------------------------------------------------- #
|
---|---|
2 |
# Copyright 2006-2009, University of Chicago #
|
3 |
# Copyright 2008-2009, Distributed Systems Architecture Group, Universidad #
|
4 |
# Complutense de Madrid (dsa-research.org) #
|
5 |
# #
|
6 |
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
7 |
# not use this file except in compliance with the License. You may obtain #
|
8 |
# a copy of the License at #
|
9 |
# #
|
10 |
# http://www.apache.org/licenses/LICENSE-2.0 #
|
11 |
# #
|
12 |
# Unless required by applicable law or agreed to in writing, software #
|
13 |
# distributed under the License is distributed on an "AS IS" BASIS, #
|
14 |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
15 |
# See the License for the specific language governing permissions and #
|
16 |
# limitations under the License. #
|
17 |
# -------------------------------------------------------------------------- #
|
18 |
|
19 |
import ConfigParser |
20 |
from mx.DateTime import ISO |
21 |
from mx.DateTime import TimeDelta |
22 |
import textwrap |
23 |
|
24 |
OPTTYPE_INT = 0
|
25 |
OPTTYPE_FLOAT = 1
|
26 |
OPTTYPE_STRING = 2
|
27 |
OPTTYPE_BOOLEAN = 3
|
28 |
OPTTYPE_DATETIME = 4
|
29 |
OPTTYPE_TIMEDELTA = 5
|
30 |
|
31 |
class ConfigException(Exception): |
32 |
"""A simple exception class used for configuration exceptions"""
|
33 |
pass
|
34 |
|
35 |
class Section(object): |
36 |
def __init__(self, name, required, required_if=None, doc=None): |
37 |
self.name = name
|
38 |
self.required = required
|
39 |
self.required_if = required_if
|
40 |
self.doc = doc
|
41 |
self.options = {}
|
42 |
|
43 |
def get_doc(self): |
44 |
return textwrap.dedent(self.doc).strip() |
45 |
|
46 |
|
47 |
class Option(object): |
48 |
def __init__(self, name, getter, type, required, required_if=None, default=None, valid=None, doc=None): |
49 |
self.name = name
|
50 |
self.getter = getter
|
51 |
self.type = type |
52 |
self.required = required
|
53 |
self.required_if = required_if
|
54 |
self.default = default
|
55 |
self.valid = valid
|
56 |
self.doc = doc
|
57 |
|
58 |
def get_doc(self): |
59 |
return textwrap.dedent(self.doc).strip() |
60 |
|
61 |
class Config(object): |
62 |
def __init__(self, config, sections): |
63 |
self.config = config
|
64 |
self.sections = sections
|
65 |
self._options = {}
|
66 |
|
67 |
self.__load_all()
|
68 |
|
69 |
def __load_all(self): |
70 |
required_sections = [s for s in self.sections if s.required] |
71 |
conditional_sections = [s for s in self.sections if not s.required and s.required_if != None] |
72 |
optional_sections = [s for s in self.sections if not s.required and s.required_if == None] |
73 |
|
74 |
sections = required_sections + conditional_sections + optional_sections |
75 |
|
76 |
for sec in sections: |
77 |
has_section = self.config.has_section(sec.name)
|
78 |
|
79 |
# If the section is required, check if it exists
|
80 |
if sec.required and not has_section: |
81 |
raise ConfigException, "Required section [%s] not found" % sec.name |
82 |
|
83 |
# If the section is conditionally required, check that
|
84 |
# it meets the conditions
|
85 |
if sec.required_if != None: |
86 |
for req in sec.required_if: |
87 |
(condsec,condopt) = req[0]
|
88 |
condvalue = req[1]
|
89 |
|
90 |
if self.config.has_option(condsec,condopt) and self.config.get(condsec,condopt) == condvalue: |
91 |
if not has_section: |
92 |
raise ConfigException, "Section '%s' is required when %s.%s==%s" % (sec.name, condsec, condopt, condvalue) |
93 |
|
94 |
# Load options
|
95 |
if has_section:
|
96 |
for opt in sec.options: |
97 |
self.__load_option(sec, opt)
|
98 |
|
99 |
|
100 |
def __load_option(self, sec, opt): |
101 |
# Load a single option
|
102 |
secname = sec.name |
103 |
optname = opt.name |
104 |
|
105 |
has_option = self.config.has_option(secname, optname)
|
106 |
|
107 |
if not has_option: |
108 |
if opt.required:
|
109 |
raise ConfigException, "Required option '%s.%s' not found" % (secname, optname) |
110 |
if opt.required_if != None: |
111 |
for req in opt.required_if: |
112 |
(condsec,condopt) = req[0]
|
113 |
condvalue = req[1]
|
114 |
|
115 |
if self.config.has_option(condsec,condopt) and self.config.get(condsec,condopt) == condvalue: |
116 |
raise ConfigException, "Option '%s.%s' is required when %s.%s==%s" % (secname, optname, condsec, condopt, condvalue) |
117 |
|
118 |
value = opt.default |
119 |
else:
|
120 |
if opt.type == OPTTYPE_INT:
|
121 |
value = self.config.getint(secname, optname)
|
122 |
elif opt.type == OPTTYPE_FLOAT:
|
123 |
value = self.config.getfloat(secname, optname)
|
124 |
elif opt.type == OPTTYPE_STRING:
|
125 |
value = self.config.get(secname, optname)
|
126 |
elif opt.type == OPTTYPE_BOOLEAN:
|
127 |
value = self.config.getboolean(secname, optname)
|
128 |
elif opt.type == OPTTYPE_DATETIME:
|
129 |
value = self.config.get(secname, optname)
|
130 |
value = ISO.ParseDateTime(value) |
131 |
elif opt.type == OPTTYPE_TIMEDELTA:
|
132 |
value = self.config.getint(secname, optname)
|
133 |
value = TimeDelta(seconds=value) |
134 |
|
135 |
if opt.valid != None: |
136 |
if not value in opt.valid: |
137 |
raise ConfigException, "Invalid value specified for '%s.%s'. Valid values are %s" % (secname, optname, opt.valid) |
138 |
|
139 |
self._options[opt.getter] = value
|
140 |
|
141 |
def get(self, opt): |
142 |
return self._options[opt] |
143 |
|
144 |
@classmethod
|
145 |
def from_file(cls, configfile): |
146 |
file = open (configfile, "r") |
147 |
c = ConfigParser.ConfigParser() |
148 |
c.readfp(file)
|
149 |
cfg = cls(c) |
150 |
return cfg
|
151 |
|
152 |
|
153 |
|