Project

General

Profile

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