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, ParsingError
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
44
except ParsingError, e:
48
except ParsingError, p:
50
print "Could not start wicd: %s" % p.message
54
return self.config_file
57
return self.config_file
60
""" Returns the path to the loaded config file. """
61
return self.config_file
63
def set_option(self, section, option, value, write=False):
64
""" Wrapper around ConfigParser.set
66
Adds the option to write the config file change right away.
67
Also forces all the values being written to type str, and
68
adds the section the option should be written to if it
69
doesn't exist already.
72
if not self.has_section(section):
73
self.add_section(section)
74
if isinstance(value, basestring):
75
value = to_unicode(value)
76
if value.startswith(' ') or value.endswith(' '):
77
value = "%(ws)s%(value)s%(ws)s" % {"value" : value,
79
RawConfigParser.set(self, section, str(option), value)
83
def set(self, *args, **kargs):
84
""" Calls the set_option method. """
85
self.set_option(*args, **kargs)
87
def get_option(self, section, option, default="__None__"):
88
""" Wrapper around ConfigParser.get.
90
Automatically adds any missing sections, adds the ability
91
to write a default value, and if one is provided prints if
92
the default or a previously saved value is returned.
95
if not self.has_section(section):
96
if default != "__None__":
97
self.add_section(section)
101
if self.has_option(section, option):
102
ret = RawConfigParser.get(self, section, option)
103
if (isinstance(ret, basestring) and ret.startswith(self.mrk_ws)
104
and ret.endswith(self.mrk_ws)):
108
print ''.join(['found ', option, ' in configuration ',
111
if default != "__None__":
112
print 'did not find %s in configuration, setting default %s' % (option, str(default))
113
self.set(section, option, str(default), write=True)
118
# Try to intelligently handle the type of the return value.
120
if not ret.startswith('0') or len(ret) == 1:
122
except (ValueError, TypeError, AttributeError):
124
# This is a workaround for a python-dbus issue on 64-bit systems.
125
if isinstance(ret, (int, long)):
128
except OverflowError:
130
return to_unicode(ret)
132
def get(self, *args, **kargs):
133
""" Calls the get_option method """
134
return self.get_option(*args, **kargs)
136
def _write_one(self):
137
""" Writes the loaded config file to disk. """
138
for section in self.sections():
140
self.remove_section(section)
141
configfile = open(self.config_file, 'w')
142
RawConfigParser.write(self, configfile)
145
def remove_section(self, section):
146
""" Wrapper around the ConfigParser.remove_section() method.
148
This method only calls the ConfigParser.remove_section() method
149
if the section actually exists.
152
if self.has_section(section):
153
RawConfigParser.remove_section(self, section)
156
""" Re-reads the config file, in case it was edited out-of-band. """
157
self.read(self.config_file)
159
def read(self, path):
160
""" Reads the config file specified by 'path' then reads all the
161
files in the directory obtained by adding '.d' to 'path'. The files
162
in the '.d' directory are read in normal sorted order and section
163
entries in these files override entries in the main file.
165
RawConfigParser.read(self, path)
170
if os.path.exists(path_d):
171
files = [ os.path.join(path_d, f) for f in os.listdir(path_d) ]
175
p = RawConfigParser()
177
for section_name in p.sections():
178
# New files override old, so remove first to avoid DuplicateSectionError.
179
self.remove_section(section_name)
180
self.add_section(section_name)
181
for (name, value) in p.items(section_name):
182
self.set(section_name, name, value)
183
# Store the filename this section was read from.
184
self.set(section_name, '_filename_', fname)
187
def _copy_section(self, name):
188
# Yes, deepcopy sucks, but it is robust to changes in both
189
# this class and RawConfigParser.
190
p = copy.deepcopy(self)
191
for sname in p.sections():
193
p.remove_section(sname)
194
p.config_file = p.get_option(name, '_filename_', p.config_file)
195
p.remove_option(name, '_filename_')
199
""" Writes the loaded config file to disk. """
200
# Really don't like this deepcopy.
201
p = copy.deepcopy(self)
202
for sname in p.sections():
203
fname = p.get_option(sname, '_filename_')
204
if fname and fname != self.config_file:
205
section = self._copy_section(sname)
206
p.remove_section(sname)
209
for sname in p.sections():
210
p.remove_option(sname, '_filename_')