Merge lp:~matttbe/wicd/ubuntu_python27 into lp:ubuntu/natty/wicd

Proposed by Matthieu Baerts on 2010-12-11
Status: Merged
Merged at revision: 18
Proposed branch: lp:~matttbe/wicd/ubuntu_python27
Merge into: lp:ubuntu/natty/wicd
Diff against target: 425 lines (+334/-15)
6 files modified
.pc/31-deepcopy+python27-fixes.patch/wicd/configmanager.py (+212/-0)
.pc/applied-patches (+1/-0)
debian/changelog (+8/-0)
debian/patches/31-deepcopy+python27-fixes.patch (+88/-0)
debian/patches/series (+1/-0)
wicd/configmanager.py (+24/-15)
To merge this branch: bzr merge lp:~matttbe/wicd/ubuntu_python27
Reviewer Review Type Date Requested Status
Stefano Rivera Needs Fixing on 2010-12-11
Ubuntu branches 2010-12-11 Pending
Review via email: mp+43413@code.launchpad.net

Description of the change

Wicd-daemon won't work since we use python 2.7 as default.

This branch propose a new patch mentioned on bug #602825 and applied on wicd-devel branch (and available on wicd 1.7.1 beta 2).

Please pull (or 'merge' or 'merge --pull') this branch on lp:ubuntu/wicd to fix this annoying bug :)

Thank you

To post a comment you must log in.
Stefano Rivera (stefanor) wrote :

No need to bump the standards version, we try not to deviate from Debian unnecessarily.

Also, in the future, please add descriptive headers to patches, i.e. DEP3 http://dep.debian.net/deps/dep3/

review: Needs Fixing
Matthieu Baerts (matttbe) wrote :

Thank you for your help!

I've overwrote my commit and push it. I hope everything is now correct! :)

Stefano Rivera (stefanor) wrote :

One more issue, the patch you added is a -p0 patch, but quilt expects -p1, so it won't apply and the build fails.

Suggestion: change debian/patches/series to say "31-deepcopy+python27-fixes.patch -p0"
then run: quilt push; quilt refresh

That should leave you with a -p1 patch.

review: Needs Fixing
lp:~matttbe/wicd/ubuntu_python27 updated on 2010-12-11
18. By Matthieu Baerts on 2010-12-11

* debian/patches/
 - Added 31-deepcopy+python27-fixes.patch for python 2.7
   (credit to Archlinux and Remy Oudompheng - LP: #602825)

Matthieu Baerts (matttbe) wrote :

Thank you Stefano!
I've recreated the patch correctly. I think it's much better now!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory '.pc/31-deepcopy+python27-fixes.patch'
2=== added directory '.pc/31-deepcopy+python27-fixes.patch/wicd'
3=== added file '.pc/31-deepcopy+python27-fixes.patch/wicd/configmanager.py'
4--- .pc/31-deepcopy+python27-fixes.patch/wicd/configmanager.py 1970-01-01 00:00:00 +0000
5+++ .pc/31-deepcopy+python27-fixes.patch/wicd/configmanager.py 2010-12-11 12:25:11 +0000
6@@ -0,0 +1,212 @@
7+#!/usr/bin/env python
8+
9+""" configmanager -- Wicd configuration file manager
10+
11+Wrapper around ConfigParser for wicd, though it should be
12+reusable for other purposes as well.
13+
14+"""
15+
16+#
17+# Copyright (C) 2008-2009 Adam Blackburn
18+# Copyright (C) 2008-2009 Dan O'Reilly
19+#
20+# This program is free software; you can redistribute it and/or modify
21+# it under the terms of the GNU General Public License Version 2 as
22+# published by the Free Software Foundation.
23+#
24+# This program is distributed in the hope that it will be useful,
25+# but WITHOUT ANY WARRANTY; without even the implied warranty of
26+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27+# GNU General Public License for more details.
28+#
29+# You should have received a copy of the GNU General Public License
30+# along with this program. If not, see <http://www.gnu.org/licenses/>.
31+#
32+
33+import os, copy
34+
35+from ConfigParser import RawConfigParser, ParsingError
36+
37+from wicd.misc import Noneify, to_unicode
38+
39+from dbus import Int32
40+
41+class ConfigManager(RawConfigParser):
42+ """ A class that can be used to manage a given configuration file. """
43+ def __init__(self, path, debug=False, mark_whitespace="`'`"):
44+ RawConfigParser.__init__(self)
45+ self.config_file = path
46+ self.debug = debug
47+ self.mrk_ws = mark_whitespace
48+ try:
49+ self.read(path)
50+ except ParsingError, e:
51+ self.write()
52+ try:
53+ self.read(path)
54+ except ParsingError, p:
55+ import sys
56+ print "Could not start wicd: %s" % p.message
57+ sys.exit(1)
58+
59+ def __repr__(self):
60+ return self.config_file
61+
62+ def __str__(self):
63+ return self.config_file
64+
65+ def get_config(self):
66+ """ Returns the path to the loaded config file. """
67+ return self.config_file
68+
69+ def set_option(self, section, option, value, write=False):
70+ """ Wrapper around ConfigParser.set
71+
72+ Adds the option to write the config file change right away.
73+ Also forces all the values being written to type str, and
74+ adds the section the option should be written to if it
75+ doesn't exist already.
76+
77+ """
78+ if not self.has_section(section):
79+ self.add_section(section)
80+ if isinstance(value, basestring):
81+ value = to_unicode(value)
82+ if value.startswith(' ') or value.endswith(' '):
83+ value = "%(ws)s%(value)s%(ws)s" % {"value" : value,
84+ "ws" : self.mrk_ws}
85+ RawConfigParser.set(self, section, str(option), value)
86+ if write:
87+ self.write()
88+
89+ def set(self, *args, **kargs):
90+ """ Calls the set_option method. """
91+ self.set_option(*args, **kargs)
92+
93+ def get_option(self, section, option, default="__None__"):
94+ """ Wrapper around ConfigParser.get.
95+
96+ Automatically adds any missing sections, adds the ability
97+ to write a default value, and if one is provided prints if
98+ the default or a previously saved value is returned.
99+
100+ """
101+ if not self.has_section(section):
102+ if default != "__None__":
103+ self.add_section(section)
104+ else:
105+ return None
106+
107+ if self.has_option(section, option):
108+ ret = RawConfigParser.get(self, section, option)
109+ if (isinstance(ret, basestring) and ret.startswith(self.mrk_ws)
110+ and ret.endswith(self.mrk_ws)):
111+ ret = ret[3:-3]
112+ if default:
113+ if self.debug:
114+ print ''.join(['found ', option, ' in configuration ',
115+ str(ret)])
116+ else:
117+ if default != "__None__":
118+ print 'did not find %s in configuration, setting default %s' % (option, str(default))
119+ self.set(section, option, str(default), write=True)
120+ ret = default
121+ else:
122+ ret = None
123+
124+ # Try to intelligently handle the type of the return value.
125+ try:
126+ if not ret.startswith('0') or len(ret) == 1:
127+ ret = int(ret)
128+ except (ValueError, TypeError, AttributeError):
129+ ret = Noneify(ret)
130+ # This is a workaround for a python-dbus issue on 64-bit systems.
131+ if isinstance(ret, (int, long)):
132+ try:
133+ Int32(ret)
134+ except OverflowError:
135+ ret = str(ret)
136+ return to_unicode(ret)
137+
138+ def get(self, *args, **kargs):
139+ """ Calls the get_option method """
140+ return self.get_option(*args, **kargs)
141+
142+ def _write_one(self):
143+ """ Writes the loaded config file to disk. """
144+ for section in self.sections():
145+ if not section:
146+ self.remove_section(section)
147+ configfile = open(self.config_file, 'w')
148+ RawConfigParser.write(self, configfile)
149+ configfile.close()
150+
151+ def remove_section(self, section):
152+ """ Wrapper around the ConfigParser.remove_section() method.
153+
154+ This method only calls the ConfigParser.remove_section() method
155+ if the section actually exists.
156+
157+ """
158+ if self.has_section(section):
159+ RawConfigParser.remove_section(self, section)
160+
161+ def reload(self):
162+ """ Re-reads the config file, in case it was edited out-of-band. """
163+ self.read(self.config_file)
164+
165+ def read(self, path):
166+ """ Reads the config file specified by 'path' then reads all the
167+ files in the directory obtained by adding '.d' to 'path'. The files
168+ in the '.d' directory are read in normal sorted order and section
169+ entries in these files override entries in the main file.
170+ """
171+ RawConfigParser.read(self, path)
172+
173+ path_d = path + ".d"
174+ files = []
175+
176+ if os.path.exists(path_d):
177+ files = [ os.path.join(path_d, f) for f in os.listdir(path_d) ]
178+ files.sort()
179+
180+ for fname in files:
181+ p = RawConfigParser()
182+ p.read(fname)
183+ for section_name in p.sections():
184+ # New files override old, so remove first to avoid DuplicateSectionError.
185+ self.remove_section(section_name)
186+ self.add_section(section_name)
187+ for (name, value) in p.items(section_name):
188+ self.set(section_name, name, value)
189+ # Store the filename this section was read from.
190+ self.set(section_name, '_filename_', fname)
191+
192+
193+ def _copy_section(self, name):
194+ # Yes, deepcopy sucks, but it is robust to changes in both
195+ # this class and RawConfigParser.
196+ p = copy.deepcopy(self)
197+ for sname in p.sections():
198+ if sname != name:
199+ p.remove_section(sname)
200+ p.config_file = p.get_option(name, '_filename_', p.config_file)
201+ p.remove_option(name, '_filename_')
202+ return p
203+
204+ def write(self):
205+ """ Writes the loaded config file to disk. """
206+ # Really don't like this deepcopy.
207+ p = copy.deepcopy(self)
208+ for sname in p.sections():
209+ fname = p.get_option(sname, '_filename_')
210+ if fname and fname != self.config_file:
211+ section = self._copy_section(sname)
212+ p.remove_section(sname)
213+ section._write_one()
214+
215+ for sname in p.sections():
216+ p.remove_option(sname, '_filename_')
217+ p._write_one()
218+
219
220=== modified file '.pc/applied-patches'
221--- .pc/applied-patches 2010-05-29 09:17:32 +0000
222+++ .pc/applied-patches 2010-12-11 12:25:11 +0000
223@@ -17,3 +17,4 @@
224 28-announce_dhclient.conf.template.patch
225 29-document_variables_passed_to_scripts.patch
226 30-make_connection_info_selectable.patch
227+31-deepcopy+python27-fixes.patch
228
229=== modified file 'debian/changelog'
230--- debian/changelog 2010-05-29 09:17:32 +0000
231+++ debian/changelog 2010-12-11 12:25:11 +0000
232@@ -1,3 +1,11 @@
233+wicd (1.7.0+ds1-5ubuntu1) natty; urgency=low
234+
235+ * debian/patches/
236+ - Added 31-deepcopy+python27-fixes.patch for python 2.7
237+ (credit to Archlinux and Remy Oudompheng - LP: #602825)
238+
239+ -- Matthieu Baerts (matttbe) <matttbe@gmail.com> Sat, 11 Dec 2010 13:22:08 +0100
240+
241 wicd (1.7.0+ds1-5) unstable; urgency=medium
242
243 * debian/patches/series:
244
245=== added file 'debian/patches/31-deepcopy+python27-fixes.patch'
246--- debian/patches/31-deepcopy+python27-fixes.patch 1970-01-01 00:00:00 +0000
247+++ debian/patches/31-deepcopy+python27-fixes.patch 2010-12-11 12:25:11 +0000
248@@ -0,0 +1,88 @@
249+From: Matthieu Baerts <matttbe@gmail.com>
250+Subject: Added the compatibility with python2.7
251+Origin: vendor, http://repos.archlinux.org/wsvn/packages/wicd/trunk/deepcopy%2Bpython27-fixes.patch
252+Origin: upstream, http://bazaar.launchpad.net/~wicd-devel/wicd/experimental/revision/564
253+Bug: https://bugs.launchpad.net/wicd/+bug/602825
254+Forwarded: yes
255+
256+Index: wicd/wicd/configmanager.py
257+===================================================================
258+--- wicd.orig/wicd/configmanager.py 2010-12-11 13:12:12.755976821 +0100
259++++ wicd/wicd/configmanager.py 2010-12-11 13:12:32.636294327 +0100
260+@@ -24,7 +24,7 @@
261+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
262+ #
263+
264+-import os, copy
265++import sys, os, copy
266+
267+ from ConfigParser import RawConfigParser, ParsingError
268+
269+@@ -35,7 +35,10 @@
270+ class ConfigManager(RawConfigParser):
271+ """ A class that can be used to manage a given configuration file. """
272+ def __init__(self, path, debug=False, mark_whitespace="`'`"):
273+- RawConfigParser.__init__(self)
274++ if sys.version_info >= (2, 7, 0):
275++ RawConfigParser.__init__(self, allow_no_value=True)
276++ else:
277++ RawConfigParser.__init__(self)
278+ self.config_file = path
279+ self.debug = debug
280+ self.mrk_ws = mark_whitespace
281+@@ -46,7 +49,6 @@
282+ try:
283+ self.read(path)
284+ except ParsingError, p:
285+- import sys
286+ print "Could not start wicd: %s" % p.message
287+ sys.exit(1)
288+
289+@@ -185,28 +187,35 @@
290+
291+
292+ def _copy_section(self, name):
293+- # Yes, deepcopy sucks, but it is robust to changes in both
294+- # this class and RawConfigParser.
295+- p = copy.deepcopy(self)
296+- for sname in p.sections():
297+- if sname != name:
298+- p.remove_section(sname)
299++ p = ConfigManager("", self.debug, self.mrk_ws)
300++ p.add_section(name)
301++ for (iname, value) in self.items(name):
302++ p.set(name, iname, value)
303++ # Store the filename this section was read from.
304+ p.config_file = p.get_option(name, '_filename_', p.config_file)
305+ p.remove_option(name, '_filename_')
306+ return p
307+
308+ def write(self):
309+ """ Writes the loaded config file to disk. """
310+- # Really don't like this deepcopy.
311+- p = copy.deepcopy(self)
312+- for sname in p.sections():
313+- fname = p.get_option(sname, '_filename_')
314++ in_this_file = []
315++ for sname in self.sections():
316++ fname = self.get_option(sname, '_filename_')
317+ if fname and fname != self.config_file:
318++ # Write sections from other files
319+ section = self._copy_section(sname)
320+- p.remove_section(sname)
321+ section._write_one()
322++ else:
323++ # Save names of local sections
324++ in_this_file.append(sname)
325+
326+- for sname in p.sections():
327++ # Make an instance with only these sections
328++ p = ConfigManager("", self.debug, self.mrk_ws)
329++ p.config_file = self.config_file
330++ for sname in in_this_file:
331++ p.add_section(sname)
332++ for (iname, value) in self.items(sname):
333++ p.set(sname, iname, value)
334+ p.remove_option(sname, '_filename_')
335+ p._write_one()
336+
337
338=== modified file 'debian/patches/series'
339--- debian/patches/series 2010-05-29 09:17:32 +0000
340+++ debian/patches/series 2010-12-11 12:25:11 +0000
341@@ -21,3 +21,4 @@
342 28-announce_dhclient.conf.template.patch
343 29-document_variables_passed_to_scripts.patch
344 30-make_connection_info_selectable.patch
345+31-deepcopy+python27-fixes.patch
346
347=== modified file 'wicd/configmanager.py'
348--- wicd/configmanager.py 2010-03-05 18:12:51 +0000
349+++ wicd/configmanager.py 2010-12-11 12:25:11 +0000
350@@ -24,7 +24,7 @@
351 # along with this program. If not, see <http://www.gnu.org/licenses/>.
352 #
353
354-import os, copy
355+import sys, os, copy
356
357 from ConfigParser import RawConfigParser, ParsingError
358
359@@ -35,7 +35,10 @@
360 class ConfigManager(RawConfigParser):
361 """ A class that can be used to manage a given configuration file. """
362 def __init__(self, path, debug=False, mark_whitespace="`'`"):
363- RawConfigParser.__init__(self)
364+ if sys.version_info >= (2, 7, 0):
365+ RawConfigParser.__init__(self, allow_no_value=True)
366+ else:
367+ RawConfigParser.__init__(self)
368 self.config_file = path
369 self.debug = debug
370 self.mrk_ws = mark_whitespace
371@@ -46,7 +49,6 @@
372 try:
373 self.read(path)
374 except ParsingError, p:
375- import sys
376 print "Could not start wicd: %s" % p.message
377 sys.exit(1)
378
379@@ -185,28 +187,35 @@
380
381
382 def _copy_section(self, name):
383- # Yes, deepcopy sucks, but it is robust to changes in both
384- # this class and RawConfigParser.
385- p = copy.deepcopy(self)
386- for sname in p.sections():
387- if sname != name:
388- p.remove_section(sname)
389+ p = ConfigManager("", self.debug, self.mrk_ws)
390+ p.add_section(name)
391+ for (iname, value) in self.items(name):
392+ p.set(name, iname, value)
393+ # Store the filename this section was read from.
394 p.config_file = p.get_option(name, '_filename_', p.config_file)
395 p.remove_option(name, '_filename_')
396 return p
397
398 def write(self):
399 """ Writes the loaded config file to disk. """
400- # Really don't like this deepcopy.
401- p = copy.deepcopy(self)
402- for sname in p.sections():
403- fname = p.get_option(sname, '_filename_')
404+ in_this_file = []
405+ for sname in self.sections():
406+ fname = self.get_option(sname, '_filename_')
407 if fname and fname != self.config_file:
408+ # Write sections from other files
409 section = self._copy_section(sname)
410- p.remove_section(sname)
411 section._write_one()
412+ else:
413+ # Save names of local sections
414+ in_this_file.append(sname)
415
416- for sname in p.sections():
417+ # Make an instance with only these sections
418+ p = ConfigManager("", self.debug, self.mrk_ws)
419+ p.config_file = self.config_file
420+ for sname in in_this_file:
421+ p.add_section(sname)
422+ for (iname, value) in self.items(sname):
423+ p.set(sname, iname, value)
424 p.remove_option(sname, '_filename_')
425 p._write_one()
426

Subscribers

People subscribed via source and target branches