Status: | Merged |
---|---|
Merged at revision: | 100 |
Proposed branch: | lp:~ev/apt-clone/python3 |
Merge into: | lp:apt-clone |
Diff against target: |
485 lines (+119/-83) 8 files modified
apt-clone (+10/-8) apt_clone.py (+46/-40) debian/changelog (+18/-1) tests/Makefile (+3/-1) tests/test_clone.py (+19/-11) tests/test_clone_upgrade.py (+15/-16) tests/test_in_chroot.py (+5/-3) tests/test_merge_sources.py (+3/-3) |
To merge this branch: | bzr merge lp:~ev/apt-clone/python3 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Colin Watson | Approve | ||
Review via email:
|
Commit message
Description of the change
Port to Python3.
To post a comment you must log in.
lp:~ev/apt-clone/python3
updated
- 109. By Evan
-
* Finish port to Python 3:
- Handle unicode changes.
- Do not leak file descriptors.
- Test against both Python2.7 and Python3.
- Do not use the deprecated failUnless.
- Use the io module instead of StringIO.
- Fix a failing test caused by acpi-support being in main. - 110. By Evan
-
Actually use python3 :)
lp:~ev/apt-clone/python3
updated
I've addressed the issues Colin raises as r111, r112, and r113.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Colin Watson (cjwatson) wrote : | # |
Thanks, looks good to me now. I think this is Michael's upstream branch so he may want to flip the version back to 0.2.3 for upload to Debian.
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'apt-clone' | |||
2 | --- apt-clone 2012-01-27 23:47:38 +0000 | |||
3 | +++ apt-clone 2012-06-12 09:23:17 +0000 | |||
4 | @@ -1,4 +1,4 @@ | |||
6 | 1 | #!/usr/bin/python | 1 | #!/usr/bin/python3 |
7 | 2 | # Copyright (C) 2011 Canonical | 2 | # Copyright (C) 2011 Canonical |
8 | 3 | # | 3 | # |
9 | 4 | # Authors: | 4 | # Authors: |
10 | @@ -17,6 +17,8 @@ | |||
11 | 17 | # this program; if not, write to the Free Software Foundation, Inc., | 17 | # this program; if not, write to the Free Software Foundation, Inc., |
12 | 18 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 18 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
13 | 19 | 19 | ||
14 | 20 | from __future__ import print_function | ||
15 | 21 | |||
16 | 20 | import argparse | 22 | import argparse |
17 | 21 | from apt_clone import AptClone | 23 | from apt_clone import AptClone |
18 | 22 | 24 | ||
19 | @@ -79,19 +81,19 @@ | |||
20 | 79 | clone = AptClone() | 81 | clone = AptClone() |
21 | 80 | if args.command == "info": | 82 | if args.command == "info": |
22 | 81 | info = clone.info(args.source) | 83 | info = clone.info(args.source) |
24 | 82 | print info | 84 | print(info) |
25 | 83 | if args.command == "clone": | 85 | if args.command == "clone": |
26 | 84 | clone.save_state(args.source, args.destination, | 86 | clone.save_state(args.source, args.destination, |
27 | 85 | args.with_dpkg_repack, args.with_dpkg_status) | 87 | args.with_dpkg_repack, args.with_dpkg_status) |
30 | 86 | print "not installable: %s" % ", ".join(clone.not_downloadable) | 88 | print("not installable: %s" % ", ".join(clone.not_downloadable)) |
31 | 87 | print "version mismatch: %s" % ", ".join(clone.version_mismatch) | 89 | print("version mismatch: %s" % ", ".join(clone.version_mismatch)) |
32 | 88 | if not args.with_dpkg_repack: | 90 | if not args.with_dpkg_repack: |
35 | 89 | print "\nNote that you can use --with-dpkg-repack to include "\ | 91 | print("\nNote that you can use --with-dpkg-repack to include " |
36 | 90 | "those packages in the clone file." | 92 | "those packges in the clone file.") |
37 | 91 | elif args.command == "restore": | 93 | elif args.command == "restore": |
38 | 92 | if args.simulate: | 94 | if args.simulate: |
39 | 93 | miss = clone.simulate_restore_state(args.source) | 95 | miss = clone.simulate_restore_state(args.source) |
41 | 94 | print "missing: %s" % ",".join(sorted(list(miss))) | 96 | print("missing: %s" % ",".join(sorted(list(miss)))) |
42 | 95 | else: | 97 | else: |
43 | 96 | clone.restore_state(args.source, args.destination) | 98 | clone.restore_state(args.source, args.destination) |
44 | 97 | elif args.command == "restore-new-distro": | 99 | elif args.command == "restore-new-distro": |
45 | @@ -111,7 +113,7 @@ | |||
46 | 111 | if args.simulate: | 113 | if args.simulate: |
47 | 112 | miss = clone.simulate_restore_state( | 114 | miss = clone.simulate_restore_state( |
48 | 113 | args.source, args.new_distro_codename) | 115 | args.source, args.new_distro_codename) |
50 | 114 | print "missing: %s" % ",".join(sorted(list(miss))) | 116 | print("missing: %s" % ",".join(sorted(list(miss)))) |
51 | 115 | else: | 117 | else: |
52 | 116 | clone.restore_state( | 118 | clone.restore_state( |
53 | 117 | args.source, args.destination, args.new_distro_codename, protect_installed) | 119 | args.source, args.destination, args.new_distro_codename, protect_installed) |
54 | 118 | 120 | ||
55 | === modified file 'apt_clone.py' | |||
56 | --- apt_clone.py 2012-01-27 17:14:05 +0000 | |||
57 | +++ apt_clone.py 2012-06-12 09:23:17 +0000 | |||
58 | @@ -16,6 +16,8 @@ | |||
59 | 16 | # this program; if not, write to the Free Software Foundation, Inc., | 16 | # this program; if not, write to the Free Software Foundation, Inc., |
60 | 17 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 17 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
61 | 18 | 18 | ||
62 | 19 | from __future__ import print_function | ||
63 | 20 | |||
64 | 19 | import apt | 21 | import apt |
65 | 20 | from apt.cache import FetchFailedException | 22 | from apt.cache import FetchFailedException |
66 | 21 | import apt_pkg | 23 | import apt_pkg |
67 | @@ -29,7 +31,7 @@ | |||
68 | 29 | import tempfile | 31 | import tempfile |
69 | 30 | import time | 32 | import time |
70 | 31 | 33 | ||
72 | 32 | from StringIO import StringIO | 34 | from io import BytesIO |
73 | 33 | 35 | ||
74 | 34 | if "APT_CLONE_DEBUG_RESOLVER" in os.environ: | 36 | if "APT_CLONE_DEBUG_RESOLVER" in os.environ: |
75 | 35 | apt_pkg.config.set("Debug::pkgProblemResolver", "1") | 37 | apt_pkg.config.set("Debug::pkgProblemResolver", "1") |
76 | @@ -158,9 +160,9 @@ | |||
77 | 158 | 'arch' : apt_pkg.config.find("APT::Architecture") | 160 | 'arch' : apt_pkg.config.find("APT::Architecture") |
78 | 159 | } | 161 | } |
79 | 160 | # save it | 162 | # save it |
81 | 161 | f = tempfile.NamedTemporaryFile() | 163 | f = tempfile.NamedTemporaryFile(mode='w') |
82 | 162 | info = "\n".join(["%s: %s" % (key, value) | 164 | info = "\n".join(["%s: %s" % (key, value) |
84 | 163 | for (key, value) in host_info.iteritems()]) | 165 | for (key, value) in host_info.items()]) |
85 | 164 | f.write(info+"\n") | 166 | f.write(info+"\n") |
86 | 165 | f.flush() | 167 | f.flush() |
87 | 166 | tar.add(f.name, arcname="./var/lib/apt-clone/uname") | 168 | tar.add(f.name, arcname="./var/lib/apt-clone/uname") |
88 | @@ -180,9 +182,10 @@ | |||
89 | 180 | self.version_mismatch.add(pkg.name) | 182 | self.version_mismatch.add(pkg.name) |
90 | 181 | # store the installed.pkgs | 183 | # store the installed.pkgs |
91 | 182 | tarinfo = tarfile.TarInfo("./var/lib/apt-clone/installed.pkgs") | 184 | tarinfo = tarfile.TarInfo("./var/lib/apt-clone/installed.pkgs") |
92 | 185 | s = s.encode('utf-8') | ||
93 | 183 | tarinfo.size = len(s) | 186 | tarinfo.size = len(s) |
94 | 184 | tarinfo.mtime = time.time() | 187 | tarinfo.mtime = time.time() |
96 | 185 | tar.addfile(tarinfo, StringIO(s)) | 188 | tar.addfile(tarinfo, BytesIO(s)) |
97 | 186 | 189 | ||
98 | 187 | def _write_state_dpkg_status(self, tar): | 190 | def _write_state_dpkg_status(self, tar): |
99 | 188 | # store dpkg-status, this is not strictly needed as installed.pkgs | 191 | # store dpkg-status, this is not strictly needed as installed.pkgs |
100 | @@ -232,11 +235,11 @@ | |||
101 | 232 | self.commands.repack_deb(pkgname, tdir) | 235 | self.commands.repack_deb(pkgname, tdir) |
102 | 233 | tar.add(tdir, arcname="./var/lib/apt-clone/debs") | 236 | tar.add(tdir, arcname="./var/lib/apt-clone/debs") |
103 | 234 | shutil.rmtree(tdir) | 237 | shutil.rmtree(tdir) |
105 | 235 | #print tdir | 238 | #print(tdir) |
106 | 236 | 239 | ||
107 | 237 | # detect prefix | 240 | # detect prefix |
108 | 238 | def _detect_tarprefix(self, tar): | 241 | def _detect_tarprefix(self, tar): |
110 | 239 | #print tar.getnames() | 242 | #print(tar.getnames()) |
111 | 240 | if tar.getnames()[-1].startswith("./"): | 243 | if tar.getnames()[-1].startswith("./"): |
112 | 241 | self.TARPREFIX = "./" | 244 | self.TARPREFIX = "./" |
113 | 242 | else: | 245 | else: |
114 | @@ -313,7 +316,7 @@ | |||
115 | 313 | self._detect_tarprefix(tar) | 316 | self._detect_tarprefix(tar) |
116 | 314 | 317 | ||
117 | 315 | if not os.path.exists(targetdir): | 318 | if not os.path.exists(targetdir): |
119 | 316 | print "Dir '%s' does not exist, need to bootstrap first" % targetdir | 319 | print("Dir '%s' does not exist, need to bootstrap first" % targetdir) |
120 | 317 | distro = self._get_info_distro(statefile) | 320 | distro = self._get_info_distro(statefile) |
121 | 318 | self.commands.debootstrap(targetdir, distro) | 321 | self.commands.debootstrap(targetdir, distro) |
122 | 319 | 322 | ||
123 | @@ -401,7 +404,7 @@ | |||
124 | 401 | # the actiongroup will help libapt to speed up the following loop | 404 | # the actiongroup will help libapt to speed up the following loop |
125 | 402 | with cache.actiongroup(): | 405 | with cache.actiongroup(): |
126 | 403 | for line in f.readlines(): | 406 | for line in f.readlines(): |
128 | 404 | line = line.strip() | 407 | line = line.strip().decode('utf-8') |
129 | 405 | if line.startswith("#") or line == "": | 408 | if line.startswith("#") or line == "": |
130 | 406 | continue | 409 | continue |
131 | 407 | (name, version, auto) = line.split() | 410 | (name, version, auto) = line.split() |
132 | @@ -416,7 +419,7 @@ | |||
133 | 416 | if cache.broken_count > 0: | 419 | if cache.broken_count > 0: |
134 | 417 | resolver.resolve() | 420 | resolver.resolve() |
135 | 418 | if not cache[name].marked_install: | 421 | if not cache[name].marked_install: |
137 | 419 | raise SystemError, "pkg %s not marked upgrade" % name | 422 | raise SystemError("pkg %s not marked upgrade" % name) |
138 | 420 | else: | 423 | else: |
139 | 421 | # normal mode, this assume the system is consistent | 424 | # normal mode, this assume the system is consistent |
140 | 422 | cache[name].mark_install(from_user=from_user) | 425 | cache[name].mark_install(from_user=from_user) |
141 | @@ -519,9 +522,10 @@ | |||
142 | 519 | owned = set() | 522 | owned = set() |
143 | 520 | dpkg_basedir = os.path.dirname(apt_pkg.config.get("Dir::State::status")) | 523 | dpkg_basedir = os.path.dirname(apt_pkg.config.get("Dir::State::status")) |
144 | 521 | for f in glob.glob(os.path.join(dpkg_basedir, "info", "*.list")): | 524 | for f in glob.glob(os.path.join(dpkg_basedir, "info", "*.list")): |
148 | 522 | for line in open(f): | 525 | with open(f) as fp: |
149 | 523 | if line.startswith("/etc/"): | 526 | for line in fp: |
150 | 524 | owned.add(line.strip()) | 527 | if line.startswith("/etc/"): |
151 | 528 | owned.add(line.strip()) | ||
152 | 525 | # now go over etc | 529 | # now go over etc |
153 | 526 | unowned = set() | 530 | unowned = set() |
154 | 527 | for dirpath, dirnames, filenames in os.walk(etcdir): | 531 | for dirpath, dirnames, filenames in os.walk(etcdir): |
155 | @@ -535,37 +539,39 @@ | |||
156 | 535 | dpkg_status = sourcedir+apt_pkg.config.find("Dir::State::status") | 539 | dpkg_status = sourcedir+apt_pkg.config.find("Dir::State::status") |
157 | 536 | modified = set() | 540 | modified = set() |
158 | 537 | # iterate dpkg-status file | 541 | # iterate dpkg-status file |
186 | 538 | tag = apt_pkg.TagFile(open(dpkg_status)) | 542 | with open(dpkg_status) as fp: |
187 | 539 | for entry in tag: | 543 | tag = apt_pkg.TagFile(fp) |
188 | 540 | if "conffiles" in entry: | 544 | for entry in tag: |
189 | 541 | for line in entry["conffiles"].split("\n"): | 545 | if "conffiles" in entry: |
190 | 542 | obsolete = None | 546 | for line in entry["conffiles"].split("\n"): |
191 | 543 | if len(line.split()) == 3: | 547 | obsolete = None |
192 | 544 | name, md5sum, obsolete = line.split() | 548 | if len(line.split()) == 3: |
193 | 545 | else: | 549 | name, md5sum, obsolete = line.split() |
194 | 546 | name, md5sum = line.split() | 550 | else: |
195 | 547 | # update | 551 | name, md5sum = line.split() |
196 | 548 | path = sourcedir+name | 552 | # update |
197 | 549 | md5sum = md5sum.strip() | 553 | path = sourcedir+name |
198 | 550 | # ignore oboslete conffiles | 554 | md5sum = md5sum.strip() |
199 | 551 | if obsolete == "obsolete": | 555 | # ignore oboslete conffiles |
200 | 552 | continue | 556 | if obsolete == "obsolete": |
201 | 553 | # user removed conffile | 557 | continue |
202 | 554 | if not os.path.exists(path): | 558 | # user removed conffile |
203 | 555 | logging.debug("conffile %s removed" % path) | 559 | if not os.path.exists(path): |
204 | 556 | modified.add(path) | 560 | logging.debug("conffile %s removed" % path) |
205 | 557 | continue | 561 | modified.add(path) |
206 | 558 | # check content | 562 | continue |
207 | 559 | md5 = hashlib.md5() | 563 | # check content |
208 | 560 | md5.update(open(path).read()) | 564 | md5 = hashlib.md5() |
209 | 561 | if md5.hexdigest() != md5sum: | 565 | with open(path, 'rb') as fp: |
210 | 562 | logging.debug("conffile %s (%s != %s)" % ( | 566 | md5.update(fp.read()) |
211 | 563 | path, md5.hexdigest(), md5sum)) | 567 | if md5.hexdigest() != md5sum: |
212 | 564 | modified.add(path) | 568 | logging.debug("conffile %s (%s != %s)" % ( |
213 | 569 | path, md5.hexdigest(), md5sum)) | ||
214 | 570 | modified.add(path) | ||
215 | 565 | return modified | 571 | return modified |
216 | 566 | 572 | ||
217 | 567 | def _dump_debconf_database(self, sourcedir): | 573 | def _dump_debconf_database(self, sourcedir): |
219 | 568 | print "not implemented yet" | 574 | print("not implemented yet") |
220 | 569 | # debconf-copydb configdb newdb --config=Name:newdb --config=Driver:File --config=Filename:/tmp/lala.db | 575 | # debconf-copydb configdb newdb --config=Name:newdb --config=Driver:File --config=Filename:/tmp/lala.db |
221 | 570 | # | 576 | # |
222 | 571 | # debconf-copydb newdb configdb --config=Name:newdb --config=Driver:File --config=Filename:/tmp/lala.db | 577 | # debconf-copydb newdb configdb --config=Name:newdb --config=Driver:File --config=Filename:/tmp/lala.db |
223 | 572 | 578 | ||
224 | === modified file 'debian/changelog' | |||
225 | --- debian/changelog 2012-01-27 16:54:20 +0000 | |||
226 | +++ debian/changelog 2012-06-12 09:23:17 +0000 | |||
227 | @@ -1,11 +1,28 @@ | |||
229 | 1 | apt-clone (0.2.3) UNRELEASED; urgency=low | 1 | apt-clone (0.2.2ubuntu1) UNRELEASED; urgency=low |
230 | 2 | 2 | ||
231 | 3 | [ Michael Vogt ] | ||
232 | 3 | * apt_clone.py: | 4 | * apt_clone.py: |
233 | 4 | - fix restoring of the clone with later apt versions (thanks | 5 | - fix restoring of the clone with later apt versions (thanks |
234 | 5 | to Colin Watson) | 6 | to Colin Watson) |
235 | 6 | - bind mount /proc, /sys on restore to chroot (thanks to | 7 | - bind mount /proc, /sys on restore to chroot (thanks to |
236 | 7 | Colin Watson) | 8 | Colin Watson) |
237 | 8 | 9 | ||
238 | 10 | [ Colin Watson ] | ||
239 | 11 | * Port to Python 3: | ||
240 | 12 | - Use Python 3-style print functions. | ||
241 | 13 | - Use "raise Exception(value)" syntax rather than the old-style "raise | ||
242 | 14 | Exception, value". | ||
243 | 15 | - Use dict.items() rather than dict.iteritems(). | ||
244 | 16 | |||
245 | 17 | [ Evan Dandrea ] | ||
246 | 18 | * Finish port to Python 3: | ||
247 | 19 | - Handle unicode changes. | ||
248 | 20 | - Do not leak file descriptors. | ||
249 | 21 | - Test against both Python2.7 and Python3. | ||
250 | 22 | - Do not use the deprecated failUnless. | ||
251 | 23 | - Use the io module instead of StringIO. | ||
252 | 24 | - Fix a failing test caused by acpi-support being in main. | ||
253 | 25 | |||
254 | 9 | -- Michael Vogt <michael.vogt@ubuntu.com> Fri, 27 Jan 2012 16:29:17 +0100 | 26 | -- Michael Vogt <michael.vogt@ubuntu.com> Fri, 27 Jan 2012 16:29:17 +0100 |
255 | 10 | 27 | ||
256 | 11 | apt-clone (0.2.2) unstable; urgency=low | 28 | apt-clone (0.2.2) unstable; urgency=low |
257 | 12 | 29 | ||
258 | === modified file 'tests/Makefile' | |||
259 | --- tests/Makefile 2011-04-08 14:36:22 +0000 | |||
260 | +++ tests/Makefile 2012-06-12 09:23:17 +0000 | |||
261 | @@ -4,7 +4,9 @@ | |||
262 | 4 | test: | 4 | test: |
263 | 5 | pyflakes ../apt-clone ../apt_clone.py | 5 | pyflakes ../apt-clone ../apt_clone.py |
264 | 6 | set -e; for f in *.py; do \ | 6 | set -e; for f in *.py; do \ |
266 | 7 | PYTHONPATH=.. python $$f; \ | 7 | for ver in python3 python2; do \ |
267 | 8 | PYTHONPATH=.. $$ver $$f; \ | ||
268 | 9 | done; \ | ||
269 | 8 | done; \ | 10 | done; \ |
270 | 9 | # cruft from the tests | 11 | # cruft from the tests |
271 | 10 | rm -f ./data/mock-system/var/cache/apt/*.bin | 12 | rm -f ./data/mock-system/var/cache/apt/*.bin |
272 | 11 | 13 | ||
273 | === modified file 'tests/test_clone.py' | |||
274 | --- tests/test_clone.py 2012-01-02 18:08:31 +0000 | |||
275 | +++ tests/test_clone.py 2012-06-12 09:23:17 +0000 | |||
276 | @@ -1,5 +1,7 @@ | |||
277 | 1 | #!/usr/bin/python | 1 | #!/usr/bin/python |
278 | 2 | 2 | ||
279 | 3 | from __future__ import print_function | ||
280 | 4 | |||
281 | 3 | import apt | 5 | import apt |
282 | 4 | import apt_pkg | 6 | import apt_pkg |
283 | 5 | import mock | 7 | import mock |
284 | @@ -10,7 +12,7 @@ | |||
285 | 10 | import tempfile | 12 | import tempfile |
286 | 11 | import unittest | 13 | import unittest |
287 | 12 | 14 | ||
289 | 13 | from StringIO import StringIO | 15 | from io import StringIO |
290 | 14 | 16 | ||
291 | 15 | sys.path.insert(0, "..") | 17 | sys.path.insert(0, "..") |
292 | 16 | import apt_clone | 18 | import apt_clone |
293 | @@ -31,7 +33,8 @@ | |||
294 | 31 | os.makedirs(os.path.join(self.tempdir, "var/lib/dpkg/")) | 33 | os.makedirs(os.path.join(self.tempdir, "var/lib/dpkg/")) |
295 | 32 | # ensure we are the right arch | 34 | # ensure we are the right arch |
296 | 33 | os.makedirs(os.path.join(self.tempdir, "etc/apt")) | 35 | os.makedirs(os.path.join(self.tempdir, "etc/apt")) |
298 | 34 | open(os.path.join(self.tempdir, "etc/apt/apt.conf"), "w").write(''' | 36 | with open(os.path.join(self.tempdir, "etc/apt/apt.conf"), "w") as fp: |
299 | 37 | fp.write(''' | ||
300 | 35 | #clear Dpkg::Post-Invoke; | 38 | #clear Dpkg::Post-Invoke; |
301 | 36 | #clear Dpkg::Pre-Invoke; | 39 | #clear Dpkg::Pre-Invoke; |
302 | 37 | #clear APT::Update; | 40 | #clear APT::Update; |
303 | @@ -59,7 +62,7 @@ | |||
304 | 59 | tarname = os.path.join(targetdir, clone.CLONE_FILENAME) | 62 | tarname = os.path.join(targetdir, clone.CLONE_FILENAME) |
305 | 60 | self.assertTrue(os.path.exists(tarname)) | 63 | self.assertTrue(os.path.exists(tarname)) |
306 | 61 | tar = tarfile.open(tarname) | 64 | tar = tarfile.open(tarname) |
308 | 62 | #print tar.getmembers() | 65 | #print(tar.getmembers()) |
309 | 63 | # verify members in tar | 66 | # verify members in tar |
310 | 64 | members = [m.name for m in tar.getmembers()] | 67 | members = [m.name for m in tar.getmembers()] |
311 | 65 | self.assertTrue("./etc/apt/sources.list" in members) | 68 | self.assertTrue("./etc/apt/sources.list" in members) |
312 | @@ -108,11 +111,14 @@ | |||
313 | 108 | # create target dir | 111 | # create target dir |
314 | 109 | targetdir = self.tempdir | 112 | targetdir = self.tempdir |
315 | 110 | # status file from maverick (to simulate running on a maverick live-cd) | 113 | # status file from maverick (to simulate running on a maverick live-cd) |
317 | 111 | s=open("./data/dpkg-status/dpkg-status-ubuntu-maverick").read() | 114 | with open("./data/dpkg-status/dpkg-status-ubuntu-maverick") as fp: |
318 | 115 | s = fp.read() | ||
319 | 112 | s = s.replace( | 116 | s = s.replace( |
320 | 113 | "Architecture: i386", | 117 | "Architecture: i386", |
321 | 114 | "Architecture: %s" % apt_pkg.config.find("Apt::Architecture")) | 118 | "Architecture: %s" % apt_pkg.config.find("Apt::Architecture")) |
323 | 115 | open(os.path.join(targetdir, "var/lib/dpkg", "status"), "w").write(s) | 119 | path = os.path.join(targetdir, "var/lib/dpkg", "status") |
324 | 120 | with open(path, "w") as fp: | ||
325 | 121 | fp.write(s) | ||
326 | 116 | # test upgrade clone from lucid system to maverick | 122 | # test upgrade clone from lucid system to maverick |
327 | 117 | clone = AptClone(cache_cls=MockAptCache) | 123 | clone = AptClone(cache_cls=MockAptCache) |
328 | 118 | clone.restore_state( | 124 | clone.restore_state( |
329 | @@ -121,14 +127,16 @@ | |||
330 | 121 | "maverick") | 127 | "maverick") |
331 | 122 | sources_list = os.path.join(targetdir, "etc","apt","sources.list") | 128 | sources_list = os.path.join(targetdir, "etc","apt","sources.list") |
332 | 123 | self.assertTrue(os.path.exists(sources_list)) | 129 | self.assertTrue(os.path.exists(sources_list)) |
335 | 124 | self.assertTrue("maverick" in open(sources_list).read()) | 130 | with open(sources_list) as fp: |
336 | 125 | self.assertFalse("lucid" in open(sources_list).read()) | 131 | self.assertTrue("maverick" in fp.read()) |
337 | 132 | with open(sources_list) as fp: | ||
338 | 133 | self.assertFalse("lucid" in fp.read()) | ||
339 | 126 | 134 | ||
340 | 127 | def test_restore_state_simulate(self): | 135 | def test_restore_state_simulate(self): |
341 | 128 | clone = AptClone() | 136 | clone = AptClone() |
342 | 129 | missing = clone.simulate_restore_state("./data/apt-state.tar.gz") | 137 | missing = clone.simulate_restore_state("./data/apt-state.tar.gz") |
343 | 130 | # missing, because clone does not have universe enabled | 138 | # missing, because clone does not have universe enabled |
345 | 131 | self.assertEqual(list(missing), ["accerciser", "acpi-support"]) | 139 | self.assertEqual(list(missing), ["accerciser"]) |
346 | 132 | 140 | ||
347 | 133 | def test_restore_state_simulate_with_new_release(self): | 141 | def test_restore_state_simulate_with_new_release(self): |
348 | 134 | #apt_pkg.config.set("Debug::PkgProblemResolver", "1") | 142 | #apt_pkg.config.set("Debug::PkgProblemResolver", "1") |
349 | @@ -139,7 +147,7 @@ | |||
350 | 139 | missing = clone.simulate_restore_state( | 147 | missing = clone.simulate_restore_state( |
351 | 140 | "./data/apt-state-ubuntu-lucid.tar.gz", "maverick") | 148 | "./data/apt-state-ubuntu-lucid.tar.gz", "maverick") |
352 | 141 | # FIXME: check that the stuff in missing is ok | 149 | # FIXME: check that the stuff in missing is ok |
354 | 142 | print missing | 150 | print(missing) |
355 | 143 | 151 | ||
356 | 144 | def test_modified_conffiles(self): | 152 | def test_modified_conffiles(self): |
357 | 145 | clone = AptClone() | 153 | clone = AptClone() |
358 | @@ -162,13 +170,13 @@ | |||
359 | 162 | "Dir::state::status", | 170 | "Dir::state::status", |
360 | 163 | "/var/lib/dpkg/status") | 171 | "/var/lib/dpkg/status") |
361 | 164 | unowned = clone._find_unowned_in_etc() | 172 | unowned = clone._find_unowned_in_etc() |
363 | 165 | #print unowned | 173 | #print(unowned) |
364 | 166 | self.assertNotEqual(unowned, set()) | 174 | self.assertNotEqual(unowned, set()) |
365 | 167 | # negative test, is created by the installer | 175 | # negative test, is created by the installer |
366 | 168 | self.assertTrue("/etc/apt/sources.list" in unowned) | 176 | self.assertTrue("/etc/apt/sources.list" in unowned) |
367 | 169 | # postivie test, belongs to base-files | 177 | # postivie test, belongs to base-files |
368 | 170 | self.assertFalse("/etc/issue" in unowned) | 178 | self.assertFalse("/etc/issue" in unowned) |
370 | 171 | print "\n".join(sorted(unowned)) | 179 | print("\n".join(sorted(unowned))) |
371 | 172 | 180 | ||
372 | 173 | if __name__ == "__main__": | 181 | if __name__ == "__main__": |
373 | 174 | unittest.main() | 182 | unittest.main() |
374 | 175 | 183 | ||
375 | === modified file 'tests/test_clone_upgrade.py' | |||
376 | --- tests/test_clone_upgrade.py 2011-04-07 13:02:27 +0000 | |||
377 | +++ tests/test_clone_upgrade.py 2012-06-12 09:23:17 +0000 | |||
378 | @@ -9,7 +9,7 @@ | |||
379 | 9 | import tempfile | 9 | import tempfile |
380 | 10 | import unittest | 10 | import unittest |
381 | 11 | 11 | ||
383 | 12 | from StringIO import StringIO | 12 | from io import StringIO |
384 | 13 | 13 | ||
385 | 14 | sys.path.insert(0, "..") | 14 | sys.path.insert(0, "..") |
386 | 15 | import apt_clone | 15 | import apt_clone |
387 | @@ -60,7 +60,8 @@ | |||
388 | 60 | sources_list = os.path.join(tmpdir, "etc", "apt", "sources.list") | 60 | sources_list = os.path.join(tmpdir, "etc", "apt", "sources.list") |
389 | 61 | if not os.path.exists(os.path.dirname(sources_list)): | 61 | if not os.path.exists(os.path.dirname(sources_list)): |
390 | 62 | os.makedirs(os.path.dirname(sources_list)) | 62 | os.makedirs(os.path.dirname(sources_list)) |
392 | 63 | open(os.path.join(sources_list), "w").write(""" | 63 | with open(os.path.join(sources_list), "w") as fp: |
393 | 64 | fp.write(""" | ||
394 | 64 | deb http://archive.ubuntu.com/ubuntu %s main restricted universe multiverse | 65 | deb http://archive.ubuntu.com/ubuntu %s main restricted universe multiverse |
395 | 65 | """ % from_dist) | 66 | """ % from_dist) |
396 | 66 | cache = apt.Cache(rootdir=tmpdir) | 67 | cache = apt.Cache(rootdir=tmpdir) |
397 | @@ -74,20 +75,18 @@ | |||
398 | 74 | dpkg_status = os.path.join(tmpdir, "var", "lib", "dpkg", "status") | 75 | dpkg_status = os.path.join(tmpdir, "var", "lib", "dpkg", "status") |
399 | 75 | if not os.path.exists(os.path.dirname(dpkg_status)): | 76 | if not os.path.exists(os.path.dirname(dpkg_status)): |
400 | 76 | os.makedirs(os.path.dirname(dpkg_status)) | 77 | os.makedirs(os.path.dirname(dpkg_status)) |
415 | 77 | dpkg = open(dpkg_status, "w") | 78 | with open(dpkg_status, "w") as dpkg: |
416 | 78 | installed = open(installed_pkgs, "w") | 79 | with open(installed_pkgs, "w") as installed: |
417 | 79 | for pkg in cache: | 80 | for pkg in cache: |
418 | 80 | if pkg.marked_install: | 81 | if pkg.marked_install: |
419 | 81 | s = str(pkg.candidate.record) | 82 | s = str(pkg.candidate.record) |
420 | 82 | s = s.replace("Package: %s\n" % pkg.name, | 83 | s = s.replace("Package: %s\n" % pkg.name, |
421 | 83 | "Package: %s\n%s\n" % ( | 84 | "Package: %s\n%s\n" % ( |
422 | 84 | pkg.name, "Status: install ok installed")) | 85 | pkg.name, "Status: install ok installed")) |
423 | 85 | dpkg.write("%s\n" % s) | 86 | dpkg.write("%s\n" % s) |
424 | 86 | installed.write("%s %s %s\n" % (pkg.name, | 87 | installed.write("%s %s %s\n" % (pkg.name, |
425 | 87 | pkg.candidate.version, | 88 | pkg.candidate.version, |
426 | 88 | int(pkg.is_auto_installed))) | 89 | int(pkg.is_auto_installed))) |
413 | 89 | dpkg.close() | ||
414 | 90 | installed.close() | ||
427 | 91 | return tmpdir | 90 | return tmpdir |
428 | 92 | 91 | ||
429 | 93 | 92 | ||
430 | 94 | 93 | ||
431 | === modified file 'tests/test_in_chroot.py' | |||
432 | --- tests/test_in_chroot.py 2012-01-27 17:14:05 +0000 | |||
433 | +++ tests/test_in_chroot.py 2012-06-12 09:23:17 +0000 | |||
434 | @@ -1,5 +1,7 @@ | |||
435 | 1 | #!/usr/bin/python | 1 | #!/usr/bin/python |
436 | 2 | 2 | ||
437 | 3 | from __future__ import print_function | ||
438 | 4 | |||
439 | 3 | import apt | 5 | import apt |
440 | 4 | import logging | 6 | import logging |
441 | 5 | import os | 7 | import os |
442 | @@ -25,7 +27,7 @@ | |||
443 | 25 | 27 | ||
444 | 26 | def test_real(self): | 28 | def test_real(self): |
445 | 27 | if os.getuid() != 0: | 29 | if os.getuid() != 0: |
447 | 28 | print "Skipping because uid != 0" | 30 | print("Skipping because uid != 0") |
448 | 29 | return | 31 | return |
449 | 30 | # do it | 32 | # do it |
450 | 31 | target = "./test-chroot" | 33 | target = "./test-chroot" |
451 | @@ -34,8 +36,8 @@ | |||
452 | 34 | subprocess.call(["debootstrap", "--arch=i386", | 36 | subprocess.call(["debootstrap", "--arch=i386", |
453 | 35 | "maverick", target]) | 37 | "maverick", target]) |
454 | 36 | # force i386 | 38 | # force i386 |
457 | 37 | open(os.path.join(target, "etc/apt/apt.conf"), "w").write( | 39 | with open(os.path.join(target, "etc/apt/apt.conf"), "w") as fp: |
458 | 38 | 'APT::Architecture "i386";') | 40 | fp.write('APT::Architecture "i386";') |
459 | 39 | 41 | ||
460 | 40 | # restore | 42 | # restore |
461 | 41 | clone = AptClone() | 43 | clone = AptClone() |
462 | 42 | 44 | ||
463 | === modified file 'tests/test_merge_sources.py' | |||
464 | --- tests/test_merge_sources.py 2011-04-06 14:06:31 +0000 | |||
465 | +++ tests/test_merge_sources.py 2012-06-12 09:23:17 +0000 | |||
466 | @@ -26,8 +26,8 @@ | |||
467 | 26 | if line != '\n' and not line.startswith('#'): | 26 | if line != '\n' and not line.startswith('#'): |
468 | 27 | tally[line] += 1 | 27 | tally[line] += 1 |
469 | 28 | # There should not be any duplicate source lines. | 28 | # There should not be any duplicate source lines. |
472 | 29 | for line, count in tally.iteritems(): | 29 | for line, count in tally.items(): |
473 | 30 | self.failUnless(count == 1, '"%s" occurred %d times.' | 30 | self.assertTrue(count == 1, '"%s" occurred %d times.' |
474 | 31 | % (line, count)) | 31 | % (line, count)) |
475 | 32 | 32 | ||
476 | 33 | # Check for extras, others... | 33 | # Check for extras, others... |
477 | @@ -43,7 +43,7 @@ | |||
478 | 43 | for line in fp: | 43 | for line in fp: |
479 | 44 | if line == match: | 44 | if line == match: |
480 | 45 | found = True | 45 | found = True |
482 | 46 | self.failUnless(found, | 46 | self.assertTrue(found, |
483 | 47 | '%s repository not present or disabled.' % pocket) | 47 | '%s repository not present or disabled.' % pocket) |
484 | 48 | 48 | ||
485 | 49 | if __name__ == "__main__": | 49 | if __name__ == "__main__": |
> === modified file 'apt_clone.py' TarInfo( "./var/ lib/apt- clone/installed .pkgs") tarinfo, StringIO(s)) tarinfo, BytesIO(s))
> --- apt_clone.py 2012-01-27 17:14:05 +0000
> +++ apt_clone.py 2012-06-11 15:50:47 +0000
> @@ -182,7 +184,8 @@
> tarinfo = tarfile.
> tarinfo.size = len(s)
> tarinfo.mtime = time.time()
> - tar.addfile(
> + s = s.encode('utf-8')
> + tar.addfile(
tarinfo.size will be wrong if s isn't entirely ASCII. I think you need
to encode earlier.
> - #print tar.getnames() getnames( ))
> + print(tar.
Did you mean to uncomment this?
> === modified file 'debian/changelog'
> --- debian/changelog 2012-01-27 16:54:20 +0000
> +++ debian/changelog 2012-06-11 15:50:47 +0000
> @@ -8,6 +8,16 @@
>
> -- Michael Vogt <email address hidden> Fri, 27 Jan 2012 16:29:17 +0100
>
> +apt-clone (0.2.2ubuntu1) UNRELEASED; urgency=low
> +
> + * Port to Python 3:
> + - Use Python 3-style print functions.
> + - Use "raise Exception(value)" syntax rather than the old-style "raise
> + Exception, value".
> + - Use dict.items() rather than dict.iteritems().
> +
> + -- Colin Watson <email address hidden> Mon, 11 Jun 2012 09:12:14 +0100
> +
> apt-clone (0.2.2) unstable; urgency=low
>
> * fix extraction of no-longer downloadable debs, thanks
>
This might need updating :-)
The rest looks good to me.
review needs-fixing