Merge lp:~matttbe/wicd/ubuntu_python27 into lp:ubuntu/natty/wicd
- ubuntu_python27
- Merge into natty
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 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Stefano Rivera | Needs Fixing | ||
Ubuntu branches | Pending | ||
Review via email: mp+43413@code.launchpad.net |
Commit message
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
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/
then run: quilt push; quilt refresh
That should leave you with a -p1 patch.
- 18. By Matthieu Baerts
-
* 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
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 |
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/