3
""" configmanager -- Wicd configuration file manager
5
Wrapper around ConfigParser for wicd, though it should be
6
reusable for other purposes as well.
11
# Copyright (C) 2008-2009 Adam Blackburn
12
# Copyright (C) 2008-2009 Dan O'Reilly
14
# This program is free software; you can redistribute it and/or modify
15
# it under the terms of the GNU General Public License Version 2 as
16
# published by the Free Software Foundation.
18
# This program is distributed in the hope that it will be useful,
19
# but WITHOUT ANY WARRANTY; without even the implied warranty of
20
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
# GNU General Public License for more details.
23
# You should have received a copy of the GNU General Public License
24
# along with this program. If not, see <http://www.gnu.org/licenses/>.
29
from ConfigParser import RawConfigParser
31
from wicd.misc import Noneify, to_unicode
33
from dbus import Int32
35
class ConfigManager(RawConfigParser):
36
""" A class that can be used to manage a given configuration file. """
37
def __init__(self, path, debug=False, mark_whitespace="`'`"):
38
RawConfigParser.__init__(self)
39
self.config_file = path
41
self.mrk_ws = mark_whitespace
45
return self.config_file
48
return self.config_file
51
""" Returns the path to the loaded config file. """
52
return self.config_file
54
def set_option(self, section, option, value, write=False):
55
""" Wrapper around ConfigParser.set
57
Adds the option to write the config file change right away.
58
Also forces all the values being written to type str, and
59
adds the section the option should be written to if it
60
doesn't exist already.
63
if not self.has_section(section):
64
self.add_section(section)
65
if isinstance(value, basestring):
66
value = to_unicode(value)
67
if value.startswith(' ') or value.endswith(' '):
68
value = "%(ws)s%(value)s%(ws)s" % {"value" : value,
70
RawConfigParser.set(self, section, str(option), value)
74
def set(self, *args, **kargs):
75
""" Calls the set_option method. """
76
self.set_option(*args, **kargs)
78
def get_option(self, section, option, default="__None__"):
79
""" Wrapper around ConfigParser.get.
81
Automatically adds any missing sections, adds the ability
82
to write a default value, and if one is provided prints if
83
the default or a previously saved value is returned.
86
if not self.has_section(section):
87
if default != "__None__":
88
self.add_section(section)
92
if self.has_option(section, option):
93
ret = RawConfigParser.get(self, section, option)
94
if (isinstance(ret, basestring) and ret.startswith(self.mrk_ws)
95
and ret.endswith(self.mrk_ws)):
99
print ''.join(['found ', option, ' in configuration ',
102
if default != "__None__":
103
print 'did not find %s in configuration, setting default %s' % (option, str(default))
104
self.set(section, option, str(default), write=True)
109
# Try to intelligently handle the type of the return value.
111
if not ret.startswith('0') or len(ret) == 1:
113
except (ValueError, TypeError, AttributeError):
115
# This is a workaround for a python-dbus issue on 64-bit systems.
116
if isinstance(ret, (int, long)):
119
except OverflowError:
121
return to_unicode(ret)
123
def get(self, *args, **kargs):
124
""" Calls the get_option method """
125
return self.get_option(*args, **kargs)
127
def _write_one(self):
128
""" Writes the loaded config file to disk. """
129
for section in self.sections():
131
self.remove_section(section)
132
configfile = open(self.config_file, 'w')
133
RawConfigParser.write(self, configfile)
136
def remove_section(self, section):
137
""" Wrapper around the ConfigParser.remove_section() method.
139
This method only calls the ConfigParser.remove_section() method
140
if the section actually exists.
143
if self.has_section(section):
144
RawConfigParser.remove_section(self, section)
147
""" Re-reads the config file, in case it was edited out-of-band. """
148
self.read(self.config_file)
150
def read(self, path):
151
""" Reads the config file specified by 'path' then reads all the
152
files in the directory obtained by adding '.d' to 'path'. The files
153
in the '.d' directory are read in normal sorted order and section
154
entries in these files override entries in the main file.
156
RawConfigParser.read(self, path)
161
if os.path.exists(path_d):
162
files = [ os.path.join(path_d, f) for f in os.listdir(path_d) ]
166
p = RawConfigParser()
168
for section_name in p.sections():
169
# New files override old, so remove first to avoid DuplicateSectionError.
170
self.remove_section(section_name)
171
self.add_section(section_name)
172
for (name, value) in p.items(section_name):
173
self.set(section_name, name, value)
174
# Store the filename this section was read from.
175
self.set(section_name, '_filename_', fname)
178
def _copy_section(self, name):
179
# Yes, deepcopy sucks, but it is robust to changes in both
180
# this class and RawConfigParser.
181
p = copy.deepcopy(self)
182
for sname in p.sections():
184
p.remove_section(sname)
185
p.config_file = p.get_option(name, '_filename_', p.config_file)
186
p.remove_option(name, '_filename_')
190
""" Writes the loaded config file to disk. """
191
# Really don't like this deepcopy.
192
p = copy.deepcopy(self)
193
for sname in p.sections():
194
fname = p.get_option(sname, '_filename_')
195
if fname and fname != self.config_file:
196
section = self._copy_section(sname)
197
p.remove_section(sname)
200
for sname in p.sections():
201
p.remove_option(sname, '_filename_')