Merge lp:~mvo/unattended-upgrades/pep8-again into lp:~mvo/unattended-upgrades/debian-sid-mirror
- pep8-again
- Merge into debian-sid-mirror
Proposed by
Michael Vogt
Status: | Needs review |
---|---|
Proposed branch: | lp:~mvo/unattended-upgrades/pep8-again |
Merge into: | lp:~mvo/unattended-upgrades/debian-sid-mirror |
Diff against target: |
2030 lines (+493/-285) 23 files modified
.bzrignore (+2/-0) debian/changelog (+32/-2) debian/control (+5/-4) debian/rules (+13/-11) debian/tests/control (+2/-0) debian/tests/run-tests (+4/-0) debian/unattended-upgrades.init (+1/-1) pm/sleep.d/10_unattended-upgrades-hibernate (+1/-1) setup.py (+4/-3) test/Makefile (+9/-2) test/create_debug_lock.py (+2/-1) test/test_against_real_archive.py (+14/-4) test/test_conffile.py (+30/-6) test/test_in_chroot.py (+41/-34) test/test_logdir.py (+3/-2) test/test_mail.py (+33/-16) test/test_minimal_partitions.py (+9/-9) test/test_origin_pattern.py (+31/-15) test/test_pep8.py (+18/-0) test/test_pyflakes.py (+4/-2) test/test_substitute.py (+2/-7) unattended-upgrade (+207/-149) unattended-upgrade-shutdown (+26/-16) |
To merge this branch: | bzr merge lp:~mvo/unattended-upgrades/pep8-again |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Vogt | Pending | ||
Review via email: mp+128280@code.launchpad.net |
Commit message
Description of the change
Fix pep8 errors and include unattended-
To post a comment you must log in.
Unmerged revisions
- 305. By Michael Vogt
-
add unattended-
upgrades- shutdown in the pep8/pyflakes checks too - 304. By Michael Vogt
-
* lp:~mvo/unattended-upgrades/create-logdir-in-shutdown-helper-lp1013363:
- create logdir in the shutdown helper if needed (LP: #1013363) - 303. By Michael Vogt
-
* lp:~mvo/unattended-upgrades/lp1061498:
- fix crash in dpkg_conffile_prompt( ) (LP: #1061498) - 302. By Michael Vogt
-
test/Makefile: fix cleanup
- 301. By Michael Vogt
-
debian/
tests/run- tests: add run-test script - 300. By Michael Vogt
-
add dep8 tests
- 299. By Michael Vogt
-
Fixed debug output when a package has no candidates (LP: #1046438)
- 298. By Michael Vogt
-
releasing version 0.79.3ubuntu1
- 297. By Michael Vogt
-
fully pep8 clean (yeah!)
- 296. By Michael Vogt
-
add pyflakes/pep8 tests
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file '.bzrignore' |
2 | --- .bzrignore 1970-01-01 00:00:00 +0000 |
3 | +++ .bzrignore 2012-10-05 15:48:44 +0000 |
4 | @@ -0,0 +1,2 @@ |
5 | +__pycache__ |
6 | +build |
7 | |
8 | === modified file 'debian/changelog' |
9 | --- debian/changelog 2012-08-14 13:04:45 +0000 |
10 | +++ debian/changelog 2012-10-05 15:48:44 +0000 |
11 | @@ -1,3 +1,33 @@ |
12 | +unattended-upgrades (0.79.3ubuntu3) UNRELEASEDquantal; urgency=low |
13 | + |
14 | + * lp:~mvo/unattended-upgrades/lp1061498: |
15 | + - fix crash in dpkg_conffile_prompt() (LP: #1061498) |
16 | + * lp:~mvo/unattended-upgrades/create-logdir-in-shutdown-helper-lp1013363: |
17 | + - create logdir in the shutdown helper if needed (LP: #1013363) |
18 | + |
19 | + -- Michael Vogt <michael.vogt@ubuntu.com> Fri, 05 Oct 2012 16:59:08 +0200 |
20 | + |
21 | +unattended-upgrades (0.79.3ubuntu2) quantal; urgency=low |
22 | + |
23 | + [ Marc Tardif ] |
24 | + * Fixed debug output when a package has no candidates (LP: #1046438) |
25 | + |
26 | + [ Michael Vogt ] |
27 | + * debian/test/: |
28 | + - add dep8 tests |
29 | + |
30 | + -- Marc Tardif <marc@ubuntu.com> Thu, 13 Sep 2012 16:16:04 -0400 |
31 | + |
32 | +unattended-upgrades (0.79.3ubuntu1) quantal; urgency=low |
33 | + |
34 | + [ Thomas Kluyver ] |
35 | + * Port to Python 3 |
36 | + |
37 | + [ Brian Murray ] |
38 | + * unattended-upgrade: fix typo in debugging output |
39 | + |
40 | + -- Michael Vogt <michael.vogt@ubuntu.com> Mon, 10 Sep 2012 09:55:19 +0200 |
41 | + |
42 | unattended-upgrades (0.79.4) UNRELEASED; urgency=low |
43 | |
44 | * data/50unattended-upgrades.{Debian,Ubuntu}: |
45 | @@ -63,7 +93,7 @@ |
46 | - added, thanks to Pedro Ribeiro, closes: #678738 |
47 | * po/sk.po: |
48 | - added, thanks to helix84, closes: #677471 |
49 | - |
50 | + |
51 | [ Teodor MICU ] |
52 | * debian/unattended-upgrades.init: |
53 | - fixes new style lsb-init output, closes: #678030 |
54 | @@ -93,7 +123,7 @@ |
55 | - updated, thanks to Joe Dalton, closes: #677804 |
56 | * po/de.po: |
57 | - updated, thanks to Chris Leick (closes: #678204) |
58 | - |
59 | + |
60 | [ Teodor MICU ] |
61 | * debian/unattended-upgrades.init: |
62 | - use new style lsb-init output, closes: #678030 |
63 | |
64 | === modified file 'debian/control' |
65 | --- debian/control 2012-07-13 18:51:00 +0000 |
66 | +++ debian/control 2012-10-05 15:48:44 +0000 |
67 | @@ -3,14 +3,15 @@ |
68 | Priority: optional |
69 | Maintainer: Michael Vogt <michael.vogt@ubuntu.com> |
70 | Build-Depends: debhelper (>= 7.0.50~), po-debconf, lsb-release |
71 | -Build-Depends-Indep: python (>= 2.6.6-3~), python-distutils-extra |
72 | -Standards-Version: 3.8.3 |
73 | +Build-Depends-Indep: python3, python3-distutils-extra |
74 | +Standards-Version: 3.9.3 |
75 | Vcs-Bzr: http://code.launchpad.net/~ubuntu-core-dev/unattended-upgrades/ubuntu/ |
76 | +XS-Testsuite: autopkgtest |
77 | |
78 | Package: unattended-upgrades |
79 | Architecture: all |
80 | -Depends: ${shlibs:Depends}, ${misc:Depends}, debconf, python, |
81 | - python-apt (>= 0.7.90), apt-utils, apt, ucf, lsb-release, |
82 | +Depends: ${shlibs:Depends}, ${misc:Depends}, debconf, python3, |
83 | + python3-apt (>= 0.7.90), apt-utils, apt, ucf, lsb-release, |
84 | lsb-base (>= 3.2-14) |
85 | Suggests: bsd-mailx, mail-transport-agent |
86 | Description: automatic installation of security upgrades |
87 | |
88 | === modified file 'debian/rules' |
89 | --- debian/rules 2011-11-09 19:20:50 +0000 |
90 | +++ debian/rules 2012-10-05 15:48:44 +0000 |
91 | @@ -3,24 +3,26 @@ |
92 | DIST=$(shell /usr/bin/lsb_release -i -s) |
93 | |
94 | %: |
95 | - dh $@ --with python2 |
96 | + dh $@ --with python3 |
97 | |
98 | override_dh_auto_build: |
99 | # copy the right template into place |
100 | cp data/50unattended-upgrades.$(DIST) data/50unattended-upgrades |
101 | - dh_auto_build |
102 | + python3 setup.py build |
103 | + |
104 | +override_dh_auto_install: |
105 | + python3 setup.py install \ |
106 | + --root=$(CURDIR)/debian/unattended-upgrades \ |
107 | + --install-layout=deb |
108 | |
109 | override_dh_auto_clean: |
110 | # Sanity-check before upload. |
111 | - set -e; if [ -e /usr/lib/python$(PYVER)/py_compile.py ]; then \ |
112 | - for f in unattended-upgrade unattended-upgrade-shutdown; do \ |
113 | - ln -nsf $$f $$f.py; \ |
114 | - python$(PYVER) /usr/lib/python$(PYVER)/py_compile.py \ |
115 | - $$f.py; \ |
116 | - rm -f $$f.py; \ |
117 | - done; \ |
118 | - fi |
119 | - dh_auto_clean |
120 | + set -e; for f in unattended-upgrade unattended-upgrade-shutdown; do \ |
121 | + ln -nsf $$f $$f.py; \ |
122 | + py3compile $$f.py; \ |
123 | + rm -f $$f.py; \ |
124 | + done |
125 | + python3 setup.py clean -a |
126 | |
127 | override_dh_installinit: |
128 | # we do not want to run the init script in the postinst/prerm, its |
129 | |
130 | === added directory 'debian/tests' |
131 | === added file 'debian/tests/control' |
132 | --- debian/tests/control 1970-01-01 00:00:00 +0000 |
133 | +++ debian/tests/control 2012-10-05 15:48:44 +0000 |
134 | @@ -0,0 +1,2 @@ |
135 | +Tests: run-tests |
136 | +Depends: @, make, python-dev, python3-dev, python-coverage |
137 | |
138 | === added file 'debian/tests/run-tests' |
139 | --- debian/tests/run-tests 1970-01-01 00:00:00 +0000 |
140 | +++ debian/tests/run-tests 2012-10-05 15:48:44 +0000 |
141 | @@ -0,0 +1,4 @@ |
142 | +#!/bin/sh |
143 | + |
144 | +cd test |
145 | +make |
146 | |
147 | === modified file 'debian/unattended-upgrades.init' |
148 | --- debian/unattended-upgrades.init 2012-06-29 08:09:25 +0000 |
149 | +++ debian/unattended-upgrades.init 2012-10-05 15:48:44 +0000 |
150 | @@ -33,7 +33,7 @@ |
151 | stop) |
152 | if [ -e $SHUTDOWN_HELPER ]; then |
153 | [ "$VERBOSE" != "no" ] && log_action_begin_msg "Checking for running $DESC" |
154 | - python $SHUTDOWN_HELPER |
155 | + python3 $SHUTDOWN_HELPER |
156 | [ "$VERBOSE" != "no" ] && log_action_end_msg $? "$NAME" |
157 | fi |
158 | ;; |
159 | |
160 | === modified file 'pm/sleep.d/10_unattended-upgrades-hibernate' |
161 | --- pm/sleep.d/10_unattended-upgrades-hibernate 2011-11-08 16:56:58 +0000 |
162 | +++ pm/sleep.d/10_unattended-upgrades-hibernate 2012-10-05 15:48:44 +0000 |
163 | @@ -17,7 +17,7 @@ |
164 | case "${1}" in |
165 | hibernate) |
166 | if [ -e $SHUTDOWN_HELPER ]; then |
167 | - python $SHUTDOWN_HELPER |
168 | + python3 $SHUTDOWN_HELPER |
169 | fi |
170 | ;; |
171 | resume|thaw) |
172 | |
173 | === modified file 'setup.py' |
174 | --- setup.py 2011-10-24 10:20:18 +0000 |
175 | +++ setup.py 2012-10-05 15:48:44 +0000 |
176 | @@ -1,9 +1,10 @@ |
177 | #!/usr/bin/env python |
178 | |
179 | from distutils.core import setup |
180 | -from DistUtilsExtra.command import * |
181 | -import glob |
182 | -import os |
183 | +from DistUtilsExtra.command import ( |
184 | + build_extra, |
185 | + build_i18n, |
186 | + ) |
187 | |
188 | |
189 | setup(name='unattended-upgrades', version='0.1', |
190 | |
191 | === modified file 'test/Makefile' |
192 | --- test/Makefile 2011-10-07 09:22:19 +0000 |
193 | +++ test/Makefile 2012-10-05 15:48:44 +0000 |
194 | @@ -3,12 +3,15 @@ |
195 | all: check |
196 | |
197 | check: |
198 | + # test with both py2 and py3 for now and also use coverage for the py2 |
199 | set -e; \ |
200 | find . -name 'test_*.py' | \ |
201 | while read file; do \ |
202 | - echo "Running $$file"; \ |
203 | if [ -x $$file ]; then \ |
204 | - python $$file ; \ |
205 | + echo "Running $$file with python3"; \ |
206 | + python3 $$file ; \ |
207 | + echo "Running $$file with python"; \ |
208 | + python-coverage run -a $$file; \ |
209 | fi \ |
210 | done |
211 | |
212 | @@ -16,4 +19,8 @@ |
213 | rm -rf ./aptroot/var/cache/ |
214 | rm -rf ./aptroot/var/lib/apt |
215 | rm -rf ./aptroot/var/run |
216 | + find .. -type d -name __pycache__ | xargs rm -rf |
217 | |
218 | +coverage-html: |
219 | + echo "output in htmlcov/ |
220 | + python-coverage html |
221 | \ No newline at end of file |
222 | |
223 | === modified file 'test/create_debug_lock.py' |
224 | --- test/create_debug_lock.py 2011-06-16 07:10:07 +0000 |
225 | +++ test/create_debug_lock.py 2012-10-05 15:48:44 +0000 |
226 | @@ -1,4 +1,4 @@ |
227 | -#!/usr/bin/python |
228 | +#!/usr/bin/python3 |
229 | # |
230 | # create a lock file so that unattended-upgrades-shutdown pauses |
231 | # on shutdown -- useful for testing |
232 | @@ -7,6 +7,7 @@ |
233 | import os |
234 | import time |
235 | |
236 | + |
237 | pid = os.fork() |
238 | if pid == 0: |
239 | os.setsid() |
240 | |
241 | === modified file 'test/test_against_real_archive.py' (properties changed: +x to -x) |
242 | --- test/test_against_real_archive.py 2012-02-28 10:48:18 +0000 |
243 | +++ test/test_against_real_archive.py 2012-10-05 15:48:44 +0000 |
244 | @@ -1,22 +1,31 @@ |
245 | -#!/usr/bin/python |
246 | +#!/usr/bin/python3 |
247 | +"""Test unattended_upgrades against the real archive in a chroot. |
248 | + |
249 | +Note that this test is not run by the makefile in this folder, as it requires |
250 | +network access, and it fails in some situations (unclear which). |
251 | +""" |
252 | |
253 | import apt |
254 | import apt_pkg |
255 | import glob |
256 | +import logging |
257 | import os |
258 | import re |
259 | import unittest |
260 | |
261 | import unattended_upgrade |
262 | |
263 | + |
264 | apt_pkg.config.set("APT::Architecture", "amd64") |
265 | |
266 | + |
267 | class MockOptions(): |
268 | def __init__(self, debug=True, dry_run=True): |
269 | self.debug = debug |
270 | self.dry_run = dry_run |
271 | self.minimal_upgrade_steps = False |
272 | |
273 | + |
274 | class TestAgainstRealArchive(unittest.TestCase): |
275 | |
276 | def setUp(self): |
277 | @@ -40,11 +49,13 @@ |
278 | apt_pkg.config.set("APT::UnattendedUpgrades::LogDir", logdir) |
279 | unattended_upgrade.DISTRO_CODENAME = "lucid" |
280 | res = unattended_upgrade.main(options, os.path.abspath("./aptroot")) |
281 | + logging.debug(res) |
282 | # check if the log file exists |
283 | self.assertTrue(os.path.exists(logfile)) |
284 | - log = open(logfile).read() |
285 | + with open(logfile) as fp: |
286 | + log = fp.read() |
287 | # check that stuff worked |
288 | - self.assertFalse(" ERROR " in log) |
289 | + self.assertFalse(" ERROR " in log, log) |
290 | # check if we actually have the expected ugprade in it |
291 | self.assertTrue( |
292 | re.search("INFO Packages that are upgraded:.*awstats", log)) |
293 | @@ -59,4 +70,3 @@ |
294 | |
295 | if __name__ == "__main__": |
296 | unittest.main() |
297 | - |
298 | |
299 | === modified file 'test/test_conffile.py' |
300 | --- test/test_conffile.py 2012-06-28 20:06:37 +0000 |
301 | +++ test/test_conffile.py 2012-10-05 15:48:44 +0000 |
302 | @@ -1,11 +1,15 @@ |
303 | -#!/usr/bin/python |
304 | +#!/usr/bin/python3 |
305 | |
306 | import apt_pkg |
307 | import logging |
308 | import unittest |
309 | -import sys |
310 | - |
311 | -from unattended_upgrade import conffile_prompt |
312 | + |
313 | + |
314 | +from unattended_upgrade import ( |
315 | + conffile_prompt, |
316 | + dpkg_conffile_prompt, |
317 | + ) |
318 | + |
319 | |
320 | class ConffilePromptTestCase(unittest.TestCase): |
321 | |
322 | @@ -19,7 +23,7 @@ |
323 | test_pkg = "./packages/conf-test-package_1.1.deb" |
324 | self.assertTrue(conffile_prompt(test_pkg, prefix="./root.conffile"), |
325 | "conffile prompt detection incorrect") |
326 | - |
327 | + |
328 | def test_will_not_prompt(self): |
329 | # conf-test 0.9 is installed, 1.0 gets installed |
330 | # they both have the same config files |
331 | @@ -54,7 +58,27 @@ |
332 | "conffile prompt detection incorrect") |
333 | |
334 | |
335 | +class DpkgConffileTestCase(unittest.TestCase): |
336 | + """ |
337 | + This tests that the detection if dpkg will prompt at all works, |
338 | + i.e. if the user has decided to use a --force-conf{old,new} option |
339 | + """ |
340 | + |
341 | + def setUp(self): |
342 | + apt_pkg.config.clear("DPkg::Options") |
343 | + |
344 | + def test_no_dpkg_prompt_option(self): |
345 | + self.assertTrue(dpkg_conffile_prompt()) |
346 | + |
347 | + def test_regression_lp1061498(self): |
348 | + apt_pkg.config.set("DPkg::Options::", "muup") |
349 | + self.assertTrue(dpkg_conffile_prompt()) |
350 | + |
351 | + def test_dpkg_will_never_prompt(self): |
352 | + apt_pkg.config.set("DPkg::Options::", "--force-confold") |
353 | + self.assertFalse(dpkg_conffile_prompt()) |
354 | + |
355 | + |
356 | if __name__ == "__main__": |
357 | logging.basicConfig(level=logging.DEBUG) |
358 | unittest.main() |
359 | - |
360 | |
361 | === modified file 'test/test_in_chroot.py' |
362 | --- test/test_in_chroot.py 2012-06-28 20:06:37 +0000 |
363 | +++ test/test_in_chroot.py 2012-10-05 15:48:44 +0000 |
364 | @@ -1,4 +1,4 @@ |
365 | -#!/usr/bin/python |
366 | +#!/usr/bin/python3 |
367 | |
368 | import apt |
369 | import logging |
370 | @@ -15,7 +15,8 @@ |
371 | #SOURCES_LIST=""" |
372 | #deb http://ftp.de.debian.org/debian squeeze main contrib non-free |
373 | #deb http://ftp.de.debian.org/debian squeeze-updates main contrib non-free |
374 | -#deb http://ftp.de.debian.org/debian squeeze-proposed-updates main contrib non-f#ree |
375 | +#deb http://ftp.de.debian.org/debian squeeze-proposed-updates main contrib \ |
376 | +# non-free |
377 | #deb http://security.debian.org squeeze/updates main contrib non-free |
378 | #""" |
379 | #DISTRO="squeeze" |
380 | @@ -27,7 +28,7 @@ |
381 | |
382 | |
383 | # ubuntu |
384 | -SOURCES_LIST=""" |
385 | +SOURCES_LIST = """ |
386 | deb http://archive.ubuntu.com/ubuntu/ lucid main restricted |
387 | deb-src http://archive.ubuntu.com/ubuntu/ lucid main restricted |
388 | |
389 | @@ -37,35 +38,39 @@ |
390 | deb http://security.ubuntu.com/ubuntu/ lucid-security main restricted |
391 | deb-src http://security.ubuntu.com/ubuntu/ lucid-security main restricted |
392 | """ |
393 | -DISTRO="lucid" |
394 | -ARCH="i386" |
395 | -TARBALL="%s-%s.tgz" % (DISTRO, ARCH) |
396 | -MIRROR="http://archive.ubuntu.com/ubuntu" |
397 | -APT_CONF="""APT::Architecture "%s";""" % ARCH |
398 | -ORIGINS_PATTERN="origin=Ubuntu,archive=lucid-security" |
399 | +DISTRO = "lucid" |
400 | +ARCH = "i386" |
401 | +TARBALL = "%s-%s.tgz" % (DISTRO, ARCH) |
402 | +MIRROR = "http://archive.ubuntu.com/ubuntu" |
403 | +APT_CONF = """APT::Architecture "%s";""" % ARCH |
404 | +ORIGINS_PATTERN = "origin=Ubuntu,archive=lucid-security" |
405 | |
406 | apt.apt_pkg.config.set("APT::Architecture", ARCH) |
407 | sys.path.insert(0, "..") |
408 | import unattended_upgrade |
409 | |
410 | + |
411 | class MockOptions(object): |
412 | debug = True |
413 | dry_run = False |
414 | minimal_upgrade_steps = False |
415 | |
416 | + |
417 | class TestUnattendedUpgrade(unittest.TestCase): |
418 | |
419 | def _create_new_debootstrap_tarball(self, tarball, target): |
420 | - print "creating initial test tarball, this is needed only once" |
421 | + print("creating initial test tarball, this is needed only once") |
422 | # force i386 |
423 | - subprocess.call(["debootstrap", |
424 | - "--arch=%s" % ARCH, |
425 | - # smaller version of the minimal system |
426 | - "--variant=minbase", |
427 | - "--include=python-apt,apt-utils,gpgv,ubuntu-keyring,ca-certificates", |
428 | - DISTRO, |
429 | - target, |
430 | - MIRROR]) |
431 | + subprocess.call( |
432 | + ["debootstrap", |
433 | + "--arch=%s" % ARCH, |
434 | + # smaller version of the minimal system |
435 | + "--variant=minbase", |
436 | + "--include=python-apt,apt-utils,gpgv,ubuntu-keyring," |
437 | + "ca-certificates", |
438 | + DISTRO, |
439 | + target, |
440 | + MIRROR]) |
441 | subprocess.call(["chroot", target, "apt-get", "clean"]) |
442 | subprocess.call(["tar", "czf", tarball, target]) |
443 | |
444 | @@ -73,7 +78,7 @@ |
445 | subprocess.call(["tar", "xzf", tarball]) |
446 | |
447 | def test_normal_upgrade(self): |
448 | - print "Running normal unattended upgrade in chroot" |
449 | + print("Running normal unattended upgrade in chroot") |
450 | options = MockOptions() |
451 | options.minimal_upgrade_steps = False |
452 | # run it |
453 | @@ -82,7 +87,7 @@ |
454 | self.assertTrue(self._verify_install_log_in_real_chroot(target)) |
455 | |
456 | def test_minimal_steps_upgrade(self): |
457 | - print "Running minimal steps unattended upgrade in chroot" |
458 | + print("Running minimal steps unattended upgrade in chroot") |
459 | options = MockOptions() |
460 | options.minimal_upgrade_steps = True |
461 | # run it |
462 | @@ -91,14 +96,15 @@ |
463 | self.assertTrue(self._verify_install_log_in_real_chroot(target)) |
464 | |
465 | def test_upgrade_on_shutdown_upgrade(self): |
466 | - print "Running unattended upgrade on shutdown (download and install) in chroot" |
467 | + print("Running unattended upgrade on shutdown (download and install) " |
468 | + "in chroot") |
469 | # ensure that it actually installs in shutdown env mode |
470 | options = MockOptions() |
471 | os.environ["UNATTENDED_UPGRADES_FORCE_INSTALL_ON_SHUTDOWN"] = "1" |
472 | apt.apt_pkg.config.set("Unattended-Upgrade::InstallOnShutdown", "1") |
473 | target = self._run_upgrade_test_in_real_chroot(options) |
474 | self.assertTrue(self._verify_install_log_in_real_chroot(target)) |
475 | - |
476 | + |
477 | def _get_lockfile_location(self, target): |
478 | return os.path.join( |
479 | target, "var/log/unattended-upgrades/unattended-upgrades.log") |
480 | @@ -114,14 +120,13 @@ |
481 | open(os.path.join(target, "etc/apt/apt.conf"), "w").write(APT_CONF) |
482 | open(os.path.join(target, "etc/apt/sources.list"), "w").write( |
483 | SOURCES_LIST) |
484 | - |
485 | |
486 | def _run_upgrade_test_in_real_chroot(self, options, clean_chroot=True): |
487 | """ helper that runs the unattended-upgrade in a chroot |
488 | and does some basic verifications |
489 | """ |
490 | if os.getuid() != 0: |
491 | - print "Skipping because uid != 0" |
492 | + print("Skipping because uid != 0") |
493 | return |
494 | |
495 | # clear to avoid pollution in the chroot |
496 | @@ -130,7 +135,7 @@ |
497 | # create chroot |
498 | target = "./test-chroot.%s" % DISTRO |
499 | |
500 | - # setup chroot if needed |
501 | + # setup chroot if needed |
502 | if clean_chroot: |
503 | self._setup_chroot(target) |
504 | |
505 | @@ -143,7 +148,7 @@ |
506 | if not os.path.exists("/var/log/unattended-upgrades/"): |
507 | os.makedirs("/var/log/unattended-upgrades/") |
508 | # make sure we are up-to-date |
509 | - subprocess.call(["apt-get","update", "-q", "-q"]) |
510 | + subprocess.call(["apt-get", "update", "-q", "-q"]) |
511 | # run it |
512 | apt.apt_pkg.config.clear("Unattended-Upgrade::Allowed-Origins") |
513 | apt.apt_pkg.config.clear("Unattended-Upgrade::Origins-Pattern") |
514 | @@ -153,7 +158,7 @@ |
515 | unattended_upgrade.main(options) |
516 | os._exit(0) |
517 | else: |
518 | - has_progress=False |
519 | + has_progress = False |
520 | all_progress = "" |
521 | last_progress = "" |
522 | progress_log = os.path.join( |
523 | @@ -171,9 +176,9 @@ |
524 | if pid == apid: |
525 | ret = os.WEXITSTATUS(status) |
526 | break |
527 | - #print "*******************", all_progress |
528 | + #print("*******************", all_progress) |
529 | self.assertEqual(ret, 0) |
530 | - # this number is a bit random, we just want to be sure we have |
531 | + # this number is a bit random, we just want to be sure we have |
532 | # progress data |
533 | self.assertTrue(has_progress, True) |
534 | self.assertTrue(len(all_progress) > 5) |
535 | @@ -183,11 +188,12 @@ |
536 | # examine log |
537 | log = self._get_lockfile_location(target) |
538 | logfile = open(log).read() |
539 | - #print logfile |
540 | - NEEDLE_PKG="ca-certificates" |
541 | + #print(logfile) |
542 | + NEEDLE_PKG = "ca-certificates" |
543 | if not re.search( |
544 | "Packages that are upgraded:.*%s" % NEEDLE_PKG, logfile): |
545 | - logging.warn("Can not find expected %s upgrade in log" % NEEDLE_PKG) |
546 | + logging.warn("Can not find expected %s upgrade in log" % |
547 | + NEEDLE_PKG) |
548 | return False |
549 | if "ERROR Installing the upgrades failed" in logfile: |
550 | logging.warn("Got a ERROR in the logfile") |
551 | @@ -196,9 +202,10 @@ |
552 | target, "var/log/unattended-upgrades/*-dpkg*.log") |
553 | dpkg_logfile = open(glob.glob(dpkg_log)[0]).read() |
554 | if not "Preparing to replace %s" % NEEDLE_PKG in dpkg_logfile: |
555 | - logging.warn("Did not find %s upgrade in the dpkg.log" % NEEDLE_PKG) |
556 | + logging.warn("Did not find %s upgrade in the dpkg.log" % |
557 | + NEEDLE_PKG) |
558 | return False |
559 | - #print dpkg_logfile |
560 | + #print(dpkg_logfile) |
561 | return True |
562 | |
563 | |
564 | |
565 | === modified file 'test/test_logdir.py' |
566 | --- test/test_logdir.py 2012-06-29 07:08:35 +0000 |
567 | +++ test/test_logdir.py 2012-10-05 15:48:44 +0000 |
568 | @@ -1,9 +1,8 @@ |
569 | -#!/usr/bin/python |
570 | +#!/usr/bin/python3 |
571 | |
572 | import apt_pkg |
573 | import logging |
574 | import os |
575 | -import mock |
576 | import sys |
577 | import tempfile |
578 | import unittest |
579 | @@ -11,10 +10,12 @@ |
580 | sys.path.insert(0, "..") |
581 | from unattended_upgrade import _setup_logging |
582 | |
583 | + |
584 | class MockOptions: |
585 | dry_run = False |
586 | debug = False |
587 | |
588 | + |
589 | class TestLogdir(unittest.TestCase): |
590 | |
591 | def setUp(self): |
592 | |
593 | === modified file 'test/test_mail.py' |
594 | --- test/test_mail.py 2012-07-13 12:20:03 +0000 |
595 | +++ test/test_mail.py 2012-10-05 15:48:44 +0000 |
596 | @@ -1,11 +1,14 @@ |
597 | -#!/usr/bin/python |
598 | +#!/usr/bin/python3 |
599 | # -*- coding: utf-8 -*- |
600 | +from __future__ import unicode_literals |
601 | + |
602 | import apt_pkg |
603 | import os |
604 | +import sys |
605 | import unittest |
606 | |
607 | +from io import StringIO |
608 | from email.parser import Parser |
609 | -from StringIO import StringIO |
610 | |
611 | import unattended_upgrade |
612 | from unattended_upgrade import send_summary_mail, setup_apt_listchanges |
613 | @@ -40,9 +43,10 @@ |
614 | res = successful |
615 | pkgs_kept_back = [] |
616 | # include some unicode chars here for good measure |
617 | - mem_log = StringIO(u"mem_log text üöä") |
618 | + mem_log = StringIO("mem_log text üöä") |
619 | logfile_dpkg = "./apt-term.log" |
620 | - open("./apt-term.log", "w").write("logfile_dpkg text") |
621 | + with open("./apt-term.log", "w") as fp: |
622 | + fp.write("logfile_dpkg text") |
623 | return (pkgs, res, pkgs_kept_back, mem_log, logfile_dpkg) |
624 | |
625 | def _verify_common_mail_content(self, mail_txt): |
626 | @@ -50,47 +54,55 @@ |
627 | self.assertTrue(expected_string in mail_txt) |
628 | |
629 | def test_summary_mail_reboot(self): |
630 | - open("./reboot-required","w").write("") |
631 | + with open("./reboot-required", "w") as fp: |
632 | + fp.write("") |
633 | send_summary_mail(*self._return_mock_data()) |
634 | os.unlink("./reboot-required") |
635 | - mail_txt = open("mail.txt").read() |
636 | + # this is used for py2 compat for py3 only we can do |
637 | + # remove the "rb" and the subsequent '.decode("utf-8")' |
638 | + with open("mail.txt", "rb") as fp: |
639 | + mail_txt = fp.read().decode("utf-8") |
640 | self.assertTrue("[reboot required]" in mail_txt) |
641 | self._verify_common_mail_content(mail_txt) |
642 | - |
643 | + |
644 | def test_summary_mail_no_reboot(self): |
645 | send_summary_mail(*self._return_mock_data()) |
646 | - mail_txt = open("mail.txt").read() |
647 | + with open("mail.txt", "rb") as fp: |
648 | + mail_txt = fp.read().decode("utf-8") |
649 | self.assertFalse("[reboot required]" in mail_txt) |
650 | self._verify_common_mail_content(mail_txt) |
651 | - |
652 | + |
653 | def test_summary_mail_only_on_error(self): |
654 | # default is to always send mail, ensure this is correct |
655 | # for both success and failure |
656 | apt_pkg.config.set("Unattended-Upgrade::MailOnlyOnError", "false") |
657 | send_summary_mail(*self._return_mock_data(successful=True)) |
658 | - self._verify_common_mail_content(open("mail.txt").read()) |
659 | + with open("mail.txt", "rb") as fp: |
660 | + self._verify_common_mail_content(fp.read().decode("utf-8")) |
661 | os.remove("mail.txt") |
662 | # now with a simulated failure |
663 | send_summary_mail(*self._return_mock_data(successful=False)) |
664 | - self._verify_common_mail_content(open("mail.txt").read()) |
665 | + with open("mail.txt", "rb") as fp: |
666 | + self._verify_common_mail_content(fp.read().decode("utf-8")) |
667 | os.remove("mail.txt") |
668 | # now test with "MailOnlyOnError" |
669 | apt_pkg.config.set("Unattended-Upgrade::MailOnlyOnError", "true") |
670 | send_summary_mail(*self._return_mock_data(successful=True)) |
671 | self.assertFalse(os.path.exists("mail.txt")) |
672 | send_summary_mail(*self._return_mock_data(successful=False)) |
673 | - mail_txt = open("mail.txt").read() |
674 | + with open("mail.txt", "rb") as fp: |
675 | + mail_txt = fp.read().decode("utf-8") |
676 | self._verify_common_mail_content(mail_txt) |
677 | self.assertTrue("Unattended upgrade returned: False" in mail_txt) |
678 | self.assertTrue(os.path.exists("mail.txt")) |
679 | |
680 | def test_apt_listchanges(self): |
681 | # test with sendmail available |
682 | - unattended_upgrade.SENDMAIL_BINARY="/bin/true" |
683 | + unattended_upgrade.SENDMAIL_BINARY = "/bin/true" |
684 | setup_apt_listchanges("./data/listchanges.conf.mail") |
685 | self.assertEqual(os.environ["APT_LISTCHANGES_FRONTEND"], "mail") |
686 | # test without sendmail |
687 | - unattended_upgrade.SENDMAIL_BINARY="/bin/not-here-xxxxxxxxx" |
688 | + unattended_upgrade.SENDMAIL_BINARY = "/bin/not-here-xxxxxxxxx" |
689 | setup_apt_listchanges("./data/listchanges.conf.pager") |
690 | self.assertEqual(os.environ["APT_LISTCHANGES_FRONTEND"], "none") |
691 | |
692 | @@ -108,6 +120,7 @@ |
693 | # we don't accidently try |
694 | self.assertFalse('text/plain; charset="utf-8"' in mail_txt) |
695 | |
696 | + |
697 | class SendmailTestCase(CommonTestsForMailxAndSendmail, unittest.TestCase): |
698 | |
699 | def setUp(self): |
700 | @@ -117,10 +130,15 @@ |
701 | def _verify_common_mail_content(self, mail_txt): |
702 | CommonTestsForMailxAndSendmail._verify_common_mail_content( |
703 | self, mail_txt) |
704 | + |
705 | + # python2 needs this as utf8 encoded string (not unicode) |
706 | + if sys.version < '3': |
707 | + mail_txt = mail_txt.encode("utf-8") |
708 | + |
709 | msg = Parser().parsestr(mail_txt) |
710 | content_type = msg["Content-Type"] |
711 | self.assertEqual(content_type, 'text/plain; charset="utf-8"') |
712 | - |
713 | + |
714 | |
715 | class SendmailAndMailxTestCase(SendmailTestCase): |
716 | |
717 | @@ -132,4 +150,3 @@ |
718 | if __name__ == "__main__": |
719 | #logging.basicConfig(level=logging.DEBUG) |
720 | unittest.main() |
721 | - |
722 | |
723 | === modified file 'test/test_minimal_partitions.py' |
724 | --- test/test_minimal_partitions.py 2011-11-18 10:46:15 +0000 |
725 | +++ test/test_minimal_partitions.py 2012-10-05 15:48:44 +0000 |
726 | @@ -1,33 +1,32 @@ |
727 | -#!/usr/bin/python |
728 | +#!/usr/bin/python3 |
729 | |
730 | import apt |
731 | import apt_pkg |
732 | import os |
733 | -import logging |
734 | import unittest |
735 | -import sys |
736 | -import time |
737 | |
738 | import unattended_upgrade |
739 | |
740 | + |
741 | class LogInstallProgressMock(unattended_upgrade.LogInstallProgress): |
742 | |
743 | # klass data so that we can veriy in the test as the actual |
744 | # object is destroyed |
745 | DATA = [] |
746 | - |
747 | + |
748 | # overwrite to log the data |
749 | def status_change(self, pkg, percent, status): |
750 | - print pkg, percent |
751 | + print(pkg, percent) |
752 | self.DATA.append([pkg, percent]) |
753 | |
754 | + |
755 | class TestMinimalPartitions(unittest.TestCase): |
756 | |
757 | def setUp(self): |
758 | # setup dry-run mode for apt |
759 | apt_pkg.config.set("Dir::Cache", "/tmp") |
760 | - apt_pkg.config.set("Debug::NoLocking","1") |
761 | - apt_pkg.config.set("Debug::pkgDPkgPM","1") |
762 | + apt_pkg.config.set("Debug::NoLocking", "1") |
763 | + apt_pkg.config.set("Debug::pkgDPkgPM", "1") |
764 | apt_pkg.config.set("Dir::State::extended_states", "./extended_states") |
765 | apt_pkg.config.clear("Dpkg::Post-Invoke") |
766 | apt_pkg.config.clear("Dpkg::Pre-Install-Pkgs") |
767 | @@ -40,7 +39,8 @@ |
768 | def test_upgrade_in_minimal_steps(self): |
769 | self.cache.upgrade(True) |
770 | pkgs_to_upgrade = [pkg.name for pkg in self.cache.get_changes()] |
771 | - unattended_upgrade.PROGRESS_LOG="./aptroot/var/run/unatteded-upgrades.progress" |
772 | + unattended_upgrade.PROGRESS_LOG = \ |
773 | + "./aptroot/var/run/unatteded-upgrades.progress" |
774 | unattended_upgrade.LogInstallProgress = LogInstallProgressMock |
775 | unattended_upgrade.upgrade_in_minimal_steps( |
776 | self.cache, pkgs_to_upgrade) |
777 | |
778 | === modified file 'test/test_origin_pattern.py' |
779 | --- test/test_origin_pattern.py 2012-08-14 11:55:21 +0000 |
780 | +++ test/test_origin_pattern.py 2012-10-05 15:48:44 +0000 |
781 | @@ -1,4 +1,4 @@ |
782 | -#!/usr/bin/python |
783 | +#!/usr/bin/python3 |
784 | |
785 | import apt_pkg |
786 | import logging |
787 | @@ -12,49 +12,63 @@ |
788 | UnknownMatcherError, |
789 | ) |
790 | |
791 | + |
792 | class MockOrigin(): |
793 | pass |
794 | + |
795 | + |
796 | class MockCandidate(): |
797 | pass |
798 | + |
799 | + |
800 | class MockPackage(): |
801 | pass |
802 | + |
803 | + |
804 | class MockCache(list): |
805 | pass |
806 | + |
807 | + |
808 | class MockDepCache(): |
809 | pass |
810 | |
811 | + |
812 | class TestOriginPatern(unittest.TestCase): |
813 | |
814 | def setUp(self): |
815 | pass |
816 | + |
817 | def tearDown(self): |
818 | pass |
819 | + |
820 | def test_match_whitelist_string(self): |
821 | origin = self._get_mock_origin( |
822 | "OriginUbuntu", "LabelUbuntu", "ArchiveUbuntu", |
823 | "archive.ubuntu.com", "main") |
824 | # good |
825 | - s="o=OriginUbuntu" |
826 | + s = "o=OriginUbuntu" |
827 | self.assertTrue(match_whitelist_string(s, origin)) |
828 | - s="o=OriginUbuntu,l=LabelUbuntu,a=ArchiveUbuntu,site=archive.ubuntu.com" |
829 | + s = "o=OriginUbuntu,l=LabelUbuntu,a=ArchiveUbuntu," \ |
830 | + "site=archive.ubuntu.com" |
831 | self.assertTrue(match_whitelist_string(s, origin)) |
832 | # bad |
833 | - s="" |
834 | - self.assertFalse(match_whitelist_string(s, origin)) |
835 | - s="o=something" |
836 | - self.assertFalse(match_whitelist_string(s, origin)) |
837 | - s="o=LabelUbuntu,a=no-match" |
838 | + s = "" |
839 | + self.assertFalse(match_whitelist_string(s, origin)) |
840 | + s = "o=something" |
841 | + self.assertFalse(match_whitelist_string(s, origin)) |
842 | + s = "o=LabelUbuntu,a=no-match" |
843 | self.assertFalse(match_whitelist_string(s, origin)) |
844 | # with escaping |
845 | origin = self._get_mock_origin("Google, Inc.", archive="stable") |
846 | # good |
847 | - s="o=Google\, Inc.,a=stable" |
848 | + s = "o=Google\, Inc.,a=stable" |
849 | self.assertTrue(match_whitelist_string(s, origin)) |
850 | |
851 | def test_match_whitelist_from_conffile(self): |
852 | # read some |
853 | apt_pkg.config.clear("Unattended-Upgrade") |
854 | - apt_pkg.read_config_file(apt_pkg.config, "./data/50unattended-upgrades.Test") |
855 | + apt_pkg.read_config_file( |
856 | + apt_pkg.config, "./data/50unattended-upgrades.Test") |
857 | allowed_origins = unattended_upgrade.get_allowed_origins() |
858 | #print allowed_origins |
859 | self.assertTrue("o=aOrigin,a=aArchive" in allowed_origins) |
860 | @@ -63,7 +77,8 @@ |
861 | |
862 | def test_compatiblity(self): |
863 | apt_pkg.config.clear("Unattended-Upgrade") |
864 | - apt_pkg.read_config_file(apt_pkg.config, "./data/50unattended-upgrades.compat") |
865 | + apt_pkg.read_config_file( |
866 | + apt_pkg.config, "./data/50unattended-upgrades.compat") |
867 | allowed_origins = unattended_upgrade.get_allowed_origins() |
868 | #print allowed_origins |
869 | self.assertTrue("o=Google\, Inc.,a=stable" in allowed_origins) |
870 | @@ -74,7 +89,7 @@ |
871 | |
872 | def test_unkown_matcher(self): |
873 | apt_pkg.config.clear("Unattended-Upgrade") |
874 | - s="xxx=OriginUbuntu" |
875 | + s = "xxx=OriginUbuntu" |
876 | with self.assertRaises(UnknownMatcherError): |
877 | self.assertTrue(match_whitelist_string(s, None)) |
878 | |
879 | @@ -90,10 +105,12 @@ |
880 | allowed_origins = ["o=Ubuntu"] |
881 | blacklist = ["linux-.*"] |
882 | # with blacklist pkg |
883 | - self.assertFalse(check_changes_for_sanity(cache, allowed_origins, blacklist)) |
884 | + self.assertFalse( |
885 | + check_changes_for_sanity(cache, allowed_origins, blacklist)) |
886 | # with "normal" pkg |
887 | pkg.name = "apt" |
888 | - self.assertTrue(check_changes_for_sanity(cache, allowed_origins, blacklist)) |
889 | + self.assertTrue( |
890 | + check_changes_for_sanity(cache, allowed_origins, blacklist)) |
891 | |
892 | def _get_mock_origin(self, aorigin="", label="", archive="", |
893 | site="", component=""): |
894 | @@ -125,4 +142,3 @@ |
895 | if __name__ == "__main__": |
896 | logging.basicConfig(level=logging.DEBUG) |
897 | unittest.main() |
898 | - |
899 | |
900 | === added file 'test/test_pep8.py' |
901 | --- test/test_pep8.py 1970-01-01 00:00:00 +0000 |
902 | +++ test/test_pep8.py 2012-10-05 15:48:44 +0000 |
903 | @@ -0,0 +1,18 @@ |
904 | +import glob |
905 | +import os |
906 | +import subprocess |
907 | +import unittest |
908 | + |
909 | + |
910 | +class PackagePep8TestCase(unittest.TestCase): |
911 | + |
912 | + def test_all_code(self): |
913 | + res = 0 |
914 | + testdir = os.path.dirname(__file__) |
915 | + py_files = glob.glob(os.path.join(testdir, "*.py")) |
916 | + res += subprocess.call(["pep8", "--repeat", ] + py_files) |
917 | + self.assertEqual(res, 0) |
918 | + |
919 | + |
920 | +if __name__ == "__main__": |
921 | + unittest.main() |
922 | |
923 | === modified file 'test/test_pyflakes.py' |
924 | --- test/test_pyflakes.py 2012-07-13 16:40:10 +0000 |
925 | +++ test/test_pyflakes.py 2012-10-05 15:48:44 +0000 |
926 | @@ -2,12 +2,14 @@ |
927 | import subprocess |
928 | import unittest |
929 | |
930 | + |
931 | class TestPyflakesClean(unittest.TestCase): |
932 | """ ensure that the tree is pyflakes clean """ |
933 | |
934 | def test_pyflakes_clean(self): |
935 | - target = os.path.join(os.path.dirname(__file__), "..", "unattended-upgrade") |
936 | - self.assertEqual(subprocess.call(["pyflakes", target]), 0) |
937 | + path = os.path.join( |
938 | + os.path.dirname(__file__), "unattended_upgrade.py") |
939 | + self.assertEqual(subprocess.call(["pyflakes", path]), 0) |
940 | |
941 | |
942 | if __name__ == "__main__": |
943 | |
944 | === modified file 'test/test_substitute.py' |
945 | --- test/test_substitute.py 2011-02-04 11:05:12 +0000 |
946 | +++ test/test_substitute.py 2012-10-05 15:48:44 +0000 |
947 | @@ -1,17 +1,13 @@ |
948 | -#!/usr/bin/python |
949 | +#!/usr/bin/python3 |
950 | |
951 | -import apt |
952 | import apt_pkg |
953 | -import os |
954 | import logging |
955 | import unittest |
956 | -import sys |
957 | - |
958 | -from StringIO import StringIO |
959 | |
960 | import unattended_upgrade |
961 | from unattended_upgrade import substitute, get_allowed_origins |
962 | |
963 | + |
964 | class TestSubstitude(unittest.TestCase): |
965 | |
966 | def setUp(self): |
967 | @@ -36,4 +32,3 @@ |
968 | if __name__ == "__main__": |
969 | logging.basicConfig(level=logging.DEBUG) |
970 | unittest.main() |
971 | - |
972 | |
973 | === added symlink 'test/unattended_upgrade_shutdown.py' |
974 | === target is u'../unattended-upgrade-shutdown' |
975 | === modified file 'unattended-upgrade' |
976 | --- unattended-upgrade 2012-08-14 11:55:21 +0000 |
977 | +++ unattended-upgrade 2012-10-05 15:48:44 +0000 |
978 | @@ -1,4 +1,4 @@ |
979 | -#!/usr/bin/python |
980 | +#!/usr/bin/python3 |
981 | # Copyright (c) 2005-2012 Canonical Ltd |
982 | # |
983 | # AUTHOR: |
984 | @@ -20,26 +20,27 @@ |
985 | # along with unattended-upgrades; if not, write to the Free Software |
986 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
987 | # |
988 | - |
989 | import apt_inst |
990 | import apt_pkg |
991 | |
992 | import copy |
993 | import datetime |
994 | -import email.Charset |
995 | +import email.charset |
996 | import fcntl |
997 | import re |
998 | import os |
999 | import string |
1000 | import sys |
1001 | |
1002 | -from email.Message import Message |
1003 | +from io import StringIO |
1004 | +from email.message import Message |
1005 | from optparse import OptionParser |
1006 | -from StringIO import StringIO |
1007 | -from subprocess import Popen, PIPE |
1008 | - |
1009 | -import warnings |
1010 | -warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning) |
1011 | + |
1012 | +from subprocess import ( |
1013 | + Popen, |
1014 | + PIPE, |
1015 | + ) |
1016 | + |
1017 | import apt |
1018 | import logging |
1019 | import lsb_release |
1020 | @@ -57,29 +58,32 @@ |
1021 | DISTRO_ID = lsb_release.get_distro_information()['ID'] |
1022 | |
1023 | # progress information is written here |
1024 | -PROGRESS_LOG="/var/run/unattended-upgrades.progress" |
1025 | +PROGRESS_LOG = "/var/run/unattended-upgrades.progress" |
1026 | |
1027 | # set from the sigint signal handler |
1028 | -SIGNAL_STOP_REQUEST=False |
1029 | +SIGNAL_STOP_REQUEST = False |
1030 | + |
1031 | |
1032 | class UnknownMatcherError(ValueError): |
1033 | pass |
1034 | |
1035 | |
1036 | class UnattendedUpgradesCache(apt.Cache): |
1037 | - |
1038 | + |
1039 | def __init__(self, rootdir, allowed_origins): |
1040 | apt.Cache.__init__(self, rootdir=rootdir) |
1041 | self.allowed_origins = allowed_origins |
1042 | - # ensure we update the candidate versions |
1043 | + # ensure we update the candidate versions |
1044 | self.adjust_candidate_versions() |
1045 | + |
1046 | def clear(self): |
1047 | apt.Cache.clear(self) |
1048 | - # ensure we update the candidate versions |
1049 | + # ensure we update the candidate versions |
1050 | self.adjust_candidate_versions() |
1051 | + |
1052 | def adjust_candidate_versions(self): |
1053 | """ Adjust candidate versions to match highest allowed origin |
1054 | - |
1055 | + |
1056 | This adjusts the origin even if the candidate has a higher |
1057 | version |
1058 | """ |
1059 | @@ -114,20 +118,19 @@ |
1060 | (/var/run/unattended-upgrades.progress by default) |
1061 | """ |
1062 | |
1063 | - LOG = PROGRESS_LOG |
1064 | + LOG = PROGRESS_LOG |
1065 | |
1066 | def status_change(self, pkg, percent, status): |
1067 | - f=open(self.LOG, "w") |
1068 | - f.write(_("Progress: %s %% (%s)") % (percent, pkg)) |
1069 | - f.close() |
1070 | + with open(self.LOG, "w") as f: |
1071 | + f.write(_("Progress: %s %% (%s)") % (percent, pkg)) |
1072 | |
1073 | def _fixup_fds(self): |
1074 | - required_fds = [ 0, 1, 2, # stdin, stdout, stderr |
1075 | - self.writefd, |
1076 | - self.write_stream.fileno(), |
1077 | - self.statusfd, |
1078 | - self.status_stream.fileno() |
1079 | - ] |
1080 | + required_fds = [0, 1, 2, # stdin, stdout, stderr |
1081 | + self.writefd, |
1082 | + self.write_stream.fileno(), |
1083 | + self.statusfd, |
1084 | + self.status_stream.fileno() |
1085 | + ] |
1086 | # ensure that our required fds close on exec |
1087 | for fd in required_fds[3:]: |
1088 | old_flags = fcntl.fcntl(fd, fcntl.F_GETFD) |
1089 | @@ -140,19 +143,19 @@ |
1090 | try: |
1091 | fd = int(fdname) |
1092 | except Exception as e: |
1093 | - print "ERROR: can not get fd for '%s'" % fdname |
1094 | + print("ERROR: can not get fd for '%s'" % fdname) |
1095 | if fd in required_fds: |
1096 | continue |
1097 | try: |
1098 | os.close(fd) |
1099 | - #print "closed: ", fd |
1100 | + #print("closed: ", fd) |
1101 | except OSError as e: |
1102 | # there will be one fd that can not be closed |
1103 | # as its the fd from pythons internal diropen() |
1104 | # so its ok to ignore one close error |
1105 | error_count += 1 |
1106 | if error_count > 1: |
1107 | - print "ERROR: os.close(%s): %s" % (fd, e) |
1108 | + print("ERROR: os.close(%s): %s" % (fd, e)) |
1109 | |
1110 | def fork(self): |
1111 | pid = os.fork() |
1112 | @@ -162,53 +165,62 @@ |
1113 | |
1114 | |
1115 | class Unlocked: |
1116 | - """ context manager for unlocking the apt lock while cache.commit() |
1117 | - is run |
1118 | - """ |
1119 | + """ |
1120 | + Context manager for unlocking the apt lock while cache.commit() is run |
1121 | + """ |
1122 | + |
1123 | def __enter__(self): |
1124 | try: |
1125 | apt_pkg.pkgsystem_unlock() |
1126 | except: |
1127 | pass |
1128 | + |
1129 | def __exit__(self, exc_type, exc_value, exc_tb): |
1130 | try: |
1131 | apt_pkg.pkgsystem_unlock() |
1132 | except: |
1133 | pass |
1134 | |
1135 | + |
1136 | def is_dpkg_journal_dirty(): |
1137 | """ |
1138 | - test if the dpkg journal is dirty |
1139 | + Return True if the dpkg journal is dirty |
1140 | (similar to debSystem::CheckUpdates) |
1141 | """ |
1142 | - d = os.path.dirname( |
1143 | - apt_pkg.config.find_file("Dir::State::status"))+"/updates" |
1144 | + d = os.path.join( |
1145 | + os.path.dirname(apt_pkg.config.find_file("Dir::State::status")), |
1146 | + "updates") |
1147 | for f in os.listdir(d): |
1148 | if re.match("[0-9]+", f): |
1149 | return True |
1150 | return False |
1151 | |
1152 | + |
1153 | def signal_handler(signal, frame): |
1154 | logging.warn("SIGUSR1 recieved, will stop") |
1155 | global SIGNAL_STOP_REQUEST |
1156 | - SIGNAL_STOP_REQUEST=True |
1157 | + SIGNAL_STOP_REQUEST = True |
1158 | + |
1159 | |
1160 | def substitute(line): |
1161 | - """ substitude known mappings and return a new string |
1162 | + """ substitude known mappings and return a new string |
1163 | |
1164 | Currently supported ${distro-release} |
1165 | """ |
1166 | - mapping = {"distro_codename" : get_distro_codename(), |
1167 | - "distro_id" : get_distro_id(), |
1168 | + mapping = {"distro_codename": get_distro_codename(), |
1169 | + "distro_id": get_distro_id(), |
1170 | } |
1171 | return string.Template(line).substitute(mapping) |
1172 | - |
1173 | + |
1174 | + |
1175 | def get_distro_codename(): |
1176 | return DISTRO_CODENAME |
1177 | |
1178 | + |
1179 | def get_distro_id(): |
1180 | return DISTRO_ID |
1181 | |
1182 | + |
1183 | def get_allowed_origins_legacy(): |
1184 | """ legacy support for old Allowed-Origins var """ |
1185 | allowed_origins = [] |
1186 | @@ -222,10 +234,11 @@ |
1187 | distro_id = re.sub(r'([^\\]),', r'\1\\,', distro_id) |
1188 | distro_codename = re.sub(r'([^\\]),', r'\1\\,', distro_codename) |
1189 | # convert to new format |
1190 | - allowed_origins.append("o=%s,a=%s" % (substitute(distro_id), |
1191 | + allowed_origins.append("o=%s,a=%s" % (substitute(distro_id), |
1192 | substitute(distro_codename))) |
1193 | return allowed_origins |
1194 | |
1195 | + |
1196 | def get_allowed_origins(): |
1197 | """ return a list of allowed origins from apt.conf |
1198 | |
1199 | @@ -236,6 +249,7 @@ |
1200 | allowed_origins.append(substitute(s)) |
1201 | return allowed_origins |
1202 | |
1203 | + |
1204 | def match_whitelist_string(whitelist, origin): |
1205 | """ |
1206 | take a whitelist string in the form "origin=Debian,label=Debian-Security" |
1207 | @@ -251,9 +265,10 @@ |
1208 | whitelist = whitelist.replace("\,", "%2C") |
1209 | for token in whitelist.split(","): |
1210 | # strip and unquote the "," back |
1211 | - (what, value) = [s.strip().replace("%2C",",") |
1212 | + (what, value) = [s.strip().replace("%2C", ",") |
1213 | for s in token.split("=")] |
1214 | - #logging.debug("matching '%s'='%s' against '%s'" % (what, value, origin)) |
1215 | + #logging.debug("matching '%s'='%s' against '%s'" % ( |
1216 | + # what, value, origin)) |
1217 | # first char is apt-cache policy output, send is the name |
1218 | # in the Release file |
1219 | if what in ("o", "origin"): |
1220 | @@ -272,6 +287,7 @@ |
1221 | what, token)) |
1222 | return res |
1223 | |
1224 | + |
1225 | def upgrade_normal(cache, pkgs_to_upgrade, logfile_dpkg): |
1226 | error = None |
1227 | res = False |
1228 | @@ -279,17 +295,18 @@ |
1229 | try: |
1230 | with Unlocked(): |
1231 | res = cache.commit(install_progress=iprogress) |
1232 | - except SystemError,e: |
1233 | + except SystemError as e: |
1234 | error = e |
1235 | if res: |
1236 | logging.info(_("All upgrades installed")) |
1237 | else: |
1238 | logging.error(_("Installing the upgrades failed!")) |
1239 | logging.error(_("error message: '%s'") % error) |
1240 | - logging.error(_("dpkg returned a error! See '%s' for details") % \ |
1241 | + logging.error(_("dpkg returned a error! See '%s' for details") % |
1242 | logfile_dpkg) |
1243 | return res |
1244 | |
1245 | + |
1246 | def upgrade_in_minimal_steps(cache, pkgs_to_upgrade, logfile_dpkg=""): |
1247 | |
1248 | install_log = LogInstallProgress() |
1249 | @@ -320,13 +337,15 @@ |
1250 | smallest_partition = changes |
1251 | break |
1252 | if len(changes) < len(smallest_partition): |
1253 | - logging.debug("found partition of size %s (%s)" % (len(changes), changes)) |
1254 | + logging.debug("found partition of size %s (%s)" % ( |
1255 | + len(changes), changes)) |
1256 | smallest_partition = changes |
1257 | cache.clear() |
1258 | |
1259 | # write progress log information |
1260 | if len(pkgs_to_upgrade) > 0: |
1261 | - percent = (len(pkgs_to_upgrade)-len(to_upgrade)) / float(len(pkgs_to_upgrade))*100.0 |
1262 | + percent = ((len(pkgs_to_upgrade) - len(to_upgrade)) / |
1263 | + float(len(pkgs_to_upgrade)) * 100.0) |
1264 | else: |
1265 | percent = 100.0 |
1266 | install_log.status_change(pkg=",".join(smallest_partition), |
1267 | @@ -343,19 +362,20 @@ |
1268 | if not res: |
1269 | raise Exception("cache.commit() returned false") |
1270 | cache.open() |
1271 | - except Exception, e: |
1272 | + except Exception as e: |
1273 | logging.error(_("Installing the upgrades failed!")) |
1274 | logging.error(_("error message: '%s'") % e) |
1275 | - logging.error(_("dpkg returned a error! See '%s' for details") % \ |
1276 | + logging.error(_("dpkg returned a error! See '%s' for details") % |
1277 | logfile_dpkg) |
1278 | return False |
1279 | - to_upgrade = to_upgrade-set(smallest_partition) |
1280 | + to_upgrade = to_upgrade - set(smallest_partition) |
1281 | logging.debug("left to upgrade %s" % to_upgrade) |
1282 | if len(to_upgrade) == 0: |
1283 | logging.info(_("All upgrades installed")) |
1284 | break |
1285 | return True |
1286 | |
1287 | + |
1288 | def is_allowed_origin(ver, allowed_origins): |
1289 | if not ver: |
1290 | return False |
1291 | @@ -365,6 +385,7 @@ |
1292 | return True |
1293 | return False |
1294 | |
1295 | + |
1296 | def is_pkgname_in_blacklist(pkgname, blacklist): |
1297 | for blacklist_regexp in blacklist: |
1298 | if re.match(blacklist_regexp, pkgname): |
1299 | @@ -372,6 +393,7 @@ |
1300 | return True |
1301 | return False |
1302 | |
1303 | + |
1304 | def check_changes_for_sanity(cache, allowed_origins, blacklist): |
1305 | if cache._depcache.broken_count != 0: |
1306 | return False |
1307 | @@ -392,33 +414,39 @@ |
1308 | ignore_require_restart = apt_pkg.config.find_b( |
1309 | "Unattended-Upgrade::IgnoreAppsRequireRestart", False) |
1310 | if (pkg.marked_upgrade and |
1311 | - ignore_require_restart == False and |
1312 | + ignore_require_restart is False and |
1313 | pkg.candidate.record.get("Upgrade-Requires") == "app-restart"): |
1314 | - logging.debug("pkg '%s' requires app-restart, not safe to upgrade unattended") |
1315 | + logging.debug("pkg '%s' requires app-restart, not safe to " |
1316 | + "upgrade unattended") |
1317 | return False |
1318 | return True |
1319 | |
1320 | + |
1321 | def pkgname_from_deb(debfile): |
1322 | # FIXME: add error checking here |
1323 | try: |
1324 | control = apt_inst.DebFile(debfile).control.extractdata("control") |
1325 | sections = apt_pkg.TagSection(control) |
1326 | return sections["Package"] |
1327 | - except (IOError, SystemError), e: |
1328 | + except (IOError, SystemError) as e: |
1329 | logging.error("failed to read deb file '%s' (%s)" % (debfile, e)) |
1330 | # dumb fallback |
1331 | return debfile.split("_")[0] |
1332 | |
1333 | + |
1334 | def get_md5sum_for_file_in_deb(deb_file, conf_file): |
1335 | - dpkg_cmd = ["dpkg-deb","--fsys-tarfile", deb_file] |
1336 | - tar_cmd = ["tar","-x","-O", "-f","-", "."+conf_file] |
1337 | + dpkg_cmd = ["dpkg-deb", "--fsys-tarfile", deb_file] |
1338 | + tar_cmd = ["tar", "-x", "-O", "-f", "-", "." + conf_file] |
1339 | md5_cmd = ["md5sum"] |
1340 | dpkg_p = Popen(dpkg_cmd, stdout=PIPE) |
1341 | - tar_p = Popen(tar_cmd, stdin=dpkg_p.stdout, stdout=PIPE) |
1342 | - md5_p = Popen(md5_cmd, stdin=tar_p.stdout, stdout=PIPE) |
1343 | + tar_p = Popen(tar_cmd, stdin=dpkg_p.stdout, stdout=PIPE, |
1344 | + universal_newlines=True) |
1345 | + md5_p = Popen(md5_cmd, stdin=tar_p.stdout, stdout=PIPE, |
1346 | + universal_newlines=True) |
1347 | pkg_md5sum = md5_p.communicate()[0].split()[0] |
1348 | return pkg_md5sum |
1349 | |
1350 | + |
1351 | # prefix is *only* needed for the build-in tests |
1352 | def conffile_prompt(destFile, prefix=""): |
1353 | logging.debug("check_conffile_prompt('%s')" % destFile) |
1354 | @@ -426,7 +454,7 @@ |
1355 | |
1356 | # get the conffiles for the /var/lib/dpkg/status file |
1357 | status_file = apt_pkg.config.find("Dir::State::status") |
1358 | - tagfile = apt_pkg.TagFile(open(status_file,"r")) |
1359 | + tagfile = apt_pkg.TagFile(open(status_file, "r")) |
1360 | conffiles = "" |
1361 | for section in tagfile: |
1362 | if section.get("Package") == pkgname: |
1363 | @@ -440,21 +468,22 @@ |
1364 | pkg_conffiles = "" |
1365 | deb = apt_inst.DebFile(destFile) |
1366 | try: |
1367 | - pkg_conffiles = deb.control.extractdata("conffiles").strip() |
1368 | + pkg_conffiles = deb.control.extractdata("conffiles").strip().decode( |
1369 | + "utf-8") |
1370 | except LookupError as e: |
1371 | logging.debug("No conffiles in deb '%s' (%s)" % (destFile, e)) |
1372 | |
1373 | # Conffiles: |
1374 | # /etc/bash_completion.d/m-a c7780fab6b14d75ca54e11e992a6c11c |
1375 | dpkg_status_conffiles = {} |
1376 | - for line in string.split(conffiles,"\n"): |
1377 | + for line in conffiles.splitlines(): |
1378 | # ignore empty lines |
1379 | - line = string.strip(line) |
1380 | + line = line.strip() |
1381 | if not line: |
1382 | continue |
1383 | # show what we do |
1384 | logging.debug("conffile line: '%s'", line) |
1385 | - l = string.split(line) |
1386 | + l = line.split() |
1387 | conf_file = l[0] |
1388 | md5 = l[1] |
1389 | if len(l) > 2: |
1390 | @@ -462,13 +491,13 @@ |
1391 | else: |
1392 | obs = None |
1393 | # ignore if conffile is obsolete or does not exist |
1394 | - if obs == "obsolete" or not os.path.exists(prefix+conf_file): |
1395 | + if obs == "obsolete" or not os.path.exists(prefix + conf_file): |
1396 | continue |
1397 | # ignore state "newconffile" until its clearer if there |
1398 | # might be a dpkg prompt (LP: #936870) |
1399 | if md5 == "newconffile": |
1400 | continue |
1401 | - if (not pkg_conffiles or |
1402 | + if (not pkg_conffiles or |
1403 | not conf_file in pkg_conffiles.split("\n")): |
1404 | logging.debug("'%s' not in package conffiles '%s'" % ( |
1405 | conf_file, pkg_conffiles)) |
1406 | @@ -476,7 +505,8 @@ |
1407 | # record for later |
1408 | dpkg_status_conffiles[conf_file] = md5 |
1409 | # test against the installed file |
1410 | - current_md5 = apt_pkg.md5sum(open(prefix+conf_file).read()) |
1411 | + with open(prefix + conf_file, 'rb') as fb: |
1412 | + current_md5 = apt_pkg.md5sum(fb) |
1413 | logging.debug("current md5: %s" % current_md5) |
1414 | # hashes are the same, no conffile prompt |
1415 | if current_md5 == md5: |
1416 | @@ -484,7 +514,7 @@ |
1417 | # calculate md5sum from the deb (may take a bit) |
1418 | pkg_md5sum = get_md5sum_for_file_in_deb(destFile, conf_file) |
1419 | logging.debug("pkg_md5sum: %s" % pkg_md5sum) |
1420 | - # the md5sum in the deb is unchanged, this will not |
1421 | + # the md5sum in the deb is unchanged, this will not |
1422 | # trigger a conffile prompt |
1423 | if pkg_md5sum == md5: |
1424 | continue |
1425 | @@ -493,18 +523,19 @@ |
1426 | # and that will trigger a conffile prompt, we can |
1427 | # stop processing at this point and just return True |
1428 | return True |
1429 | - |
1430 | + |
1431 | # now check if there are conffiles in the pkg that where not there |
1432 | # in the previous version in the dpkg status file |
1433 | if pkg_conffiles: |
1434 | for conf_file in pkg_conffiles.split("\n"): |
1435 | if (not conf_file in dpkg_status_conffiles and |
1436 | - os.path.exists(prefix+conf_file)): |
1437 | + os.path.exists(prefix + conf_file)): |
1438 | logging.debug("found conffile '%s' in new pkg but on dpkg " |
1439 | "status" % conf_file) |
1440 | pkg_md5sum = get_md5sum_for_file_in_deb(destFile, conf_file) |
1441 | - if pkg_md5sum != apt_pkg.md5sum(open(prefix+conf_file).read()): |
1442 | - return True |
1443 | + with open(prefix + conf_file, 'rb') as fp: |
1444 | + if pkg_md5sum != apt_pkg.md5sum(fp): |
1445 | + return True |
1446 | return False |
1447 | |
1448 | |
1449 | @@ -512,9 +543,9 @@ |
1450 | if not "DPkg::Options" in apt_pkg.config: |
1451 | return True |
1452 | options = apt_pkg.config.value_list("DPkg::Options") |
1453 | - for option in map(string.strip, options): |
1454 | - if (option == "--force-confold" or |
1455 | - option == "--force-confnew"): |
1456 | + for option in options: |
1457 | + option = option.strip() |
1458 | + if option in ["--force-confold", "--force-confnew"]: |
1459 | return False |
1460 | return True |
1461 | |
1462 | @@ -535,7 +566,7 @@ |
1463 | def wrap(t, width=70, subsequent_indent=""): |
1464 | out = "" |
1465 | for s in t.split(): |
1466 | - if (len(out)-out.rfind("\n")) + len(s) > width: |
1467 | + if (len(out) - out.rfind("\n")) + len(s) > width: |
1468 | out += "\n" + subsequent_indent |
1469 | out += s + " " |
1470 | return out |
1471 | @@ -554,8 +585,9 @@ |
1472 | |
1473 | |
1474 | def _send_mail_using_mailx(to_address, subject, body): |
1475 | - mail = subprocess.Popen([ |
1476 | - MAIL_BINARY, "-s", subject, to_address], stdin=subprocess.PIPE) |
1477 | + mail = subprocess.Popen( |
1478 | + [MAIL_BINARY, "-s", subject, to_address], |
1479 | + stdin=subprocess.PIPE, universal_newlines=True) |
1480 | mail.stdin.write(body) |
1481 | mail.stdin.close() |
1482 | ret = mail.wait() |
1483 | @@ -565,14 +597,15 @@ |
1484 | def _send_mail_using_sendmail(to_address, subject, body): |
1485 | # format as a proper mail |
1486 | msg = Message() |
1487 | - charset = email.Charset.Charset("utf-8") |
1488 | - charset.body_encoding = email.Charset.QP |
1489 | + charset = email.charset.Charset("utf-8") |
1490 | + charset.body_encoding = email.charset.QP |
1491 | msg.set_charset(charset) |
1492 | msg.set_payload(body) |
1493 | msg['Subject'] = subject |
1494 | msg['To'] = to_address |
1495 | sendmail = subprocess.Popen( |
1496 | - [SENDMAIL_BINARY, "-oi", "-t"], stdin=subprocess.PIPE) |
1497 | + [SENDMAIL_BINARY, "-oi", "-t"], |
1498 | + stdin=subprocess.PIPE, universal_newlines=True) |
1499 | sendmail.stdin.write(msg.as_string()) |
1500 | sendmail.stdin.close() |
1501 | ret = sendmail.wait() |
1502 | @@ -594,16 +627,18 @@ |
1503 | # mails on on errors, just exit here |
1504 | if (res and |
1505 | apt_pkg.config.find_b("Unattended-Upgrade::MailOnlyOnError", False)): |
1506 | - return |
1507 | + return |
1508 | # Check if reboot-required flag is present |
1509 | logging.debug("Sending mail with '%s' to '%s'" % (logfile_dpkg, to_email)) |
1510 | if os.path.isfile(REBOOT_REQUIRED_FILE): |
1511 | - subject = _("[reboot required] unattended-upgrades result for '%s'") % host() |
1512 | + subject = _( |
1513 | + "[reboot required] unattended-upgrades result for '%s'") % host() |
1514 | else: |
1515 | subject = _("unattended-upgrades result for '%s'") % host() |
1516 | body = _("Unattended upgrade returned: %s\n\n") % res |
1517 | if os.path.isfile(REBOOT_REQUIRED_FILE): |
1518 | - body += _("Warning: A reboot is required to complete this upgrade.\n\n") |
1519 | + body += _( |
1520 | + "Warning: A reboot is required to complete this upgrade.\n\n") |
1521 | body += _("Packages that are upgraded:\n") |
1522 | body += " " + wrap(pkgs, 70, " ") |
1523 | body += "\n" |
1524 | @@ -613,15 +648,16 @@ |
1525 | body += "\n" |
1526 | body += "\n" |
1527 | if os.path.exists(logfile_dpkg): |
1528 | - body += _("Package installation log:")+"\n" |
1529 | - body += open(logfile_dpkg).read() |
1530 | + body += _("Package installation log:") + "\n" |
1531 | + with open(logfile_dpkg) as fp: |
1532 | + body += fp.read() |
1533 | body += "\n\n" |
1534 | body += _("Unattended-upgrades log:\n") |
1535 | body += mem_log.getvalue() |
1536 | |
1537 | - # ensure that the message a utf8 encoded string |
1538 | - if type(body) is unicode: |
1539 | - body= body.encode("utf-8", "replace") |
1540 | + # python2 needs this as utf8 encoded string (not unicode) |
1541 | + if sys.version < '3': |
1542 | + body = body.encode("utf-8") |
1543 | |
1544 | if os.path.exists(SENDMAIL_BINARY): |
1545 | ret = _send_mail_using_sendmail(to_email, subject, body) |
1546 | @@ -636,13 +672,13 @@ |
1547 | |
1548 | def do_install(cache, pkgs_to_upgrade, options, logfile_dpkg): |
1549 | # set debconf to NON_INTERACTIVE, redirect output |
1550 | - os.putenv("DEBIAN_FRONTEND","noninteractive"); |
1551 | + os.putenv("DEBIAN_FRONTEND", "noninteractive") |
1552 | setup_apt_listchanges() |
1553 | - |
1554 | + |
1555 | # redirect to log |
1556 | REDIRECT_INPUT = os.devnull |
1557 | fd = os.open(REDIRECT_INPUT, os.O_RDWR) |
1558 | - os.dup2(fd,0) |
1559 | + os.dup2(fd, 0) |
1560 | |
1561 | logging.info(_("Writing dpkg log to '%s'") % logfile_dpkg) |
1562 | |
1563 | @@ -651,18 +687,21 @@ |
1564 | old_stdout = 1 |
1565 | old_stderr = 2 |
1566 | else: |
1567 | - fd = os.open(logfile_dpkg, os.O_RDWR|os.O_CREAT, 0644) |
1568 | + fd = os.open(logfile_dpkg, os.O_RDWR | os.O_CREAT, 0o644) |
1569 | old_stdout = os.dup(1) |
1570 | old_stderr = os.dup(2) |
1571 | - os.dup2(fd,1) |
1572 | - os.dup2(fd,2) |
1573 | + os.dup2(fd, 1) |
1574 | + os.dup2(fd, 2) |
1575 | |
1576 | try: |
1577 | - if (options.minimal_upgrade_steps or |
1578 | + if (options.minimal_upgrade_steps or |
1579 | # COMPAT with the mispelling |
1580 | - apt_pkg.config.find_b("Unattended-Upgrades::MinimalSteps", False) or |
1581 | - apt_pkg.config.find_b("Unattended-Upgrade::MinimalSteps", False)): |
1582 | - open("/var/run/unattended-upgrades.pid", "w").write("%s" % os.getpid()) |
1583 | + apt_pkg.config.find_b( |
1584 | + "Unattended-Upgrades::MinimalSteps", False) or |
1585 | + apt_pkg.config.find_b( |
1586 | + "Unattended-Upgrade::MinimalSteps", False)): |
1587 | + with open("/var/run/unattended-upgrades.pid", "w") as fp: |
1588 | + fp.write("%s" % os.getpid()) |
1589 | # try upgrade all "pkgs" in minimal steps |
1590 | pkg_install_success = upgrade_in_minimal_steps( |
1591 | cache, [pkg.name for pkg in pkgs_to_upgrade], logfile_dpkg) |
1592 | @@ -685,15 +724,16 @@ |
1593 | apt_pkg.config.clear("Unattended-Upgrade") |
1594 | # read rootdir (taken from apt.Cache, but we need to run it |
1595 | # here before the cache gets initialized |
1596 | - if os.path.exists(rootdir+"/etc/apt/apt.conf"): |
1597 | + if os.path.exists(rootdir + "/etc/apt/apt.conf"): |
1598 | apt_pkg.read_config_file(apt_pkg.config, |
1599 | rootdir + "/etc/apt/apt.conf") |
1600 | - if os.path.isdir(rootdir+"/etc/apt/apt.conf.d"): |
1601 | + if os.path.isdir(rootdir + "/etc/apt/apt.conf.d"): |
1602 | apt_pkg.read_config_dir(apt_pkg.config, |
1603 | rootdir + "/etc/apt/apt.conf.d") |
1604 | |
1605 | + |
1606 | def _get_logdir(): |
1607 | - logdir= apt_pkg.config.find_dir( |
1608 | + logdir = apt_pkg.config.find_dir( |
1609 | "Unattended-Upgrade::LogDir", |
1610 | # COMPAT only |
1611 | apt_pkg.config.find_dir("APT::UnattendedUpgrades::LogDir", |
1612 | @@ -716,13 +756,12 @@ |
1613 | apt_pkg.config.find("APT::UnattendedUpgrades::LogFile", |
1614 | "unattended-upgrades.log"))) |
1615 | |
1616 | - if not options.dry_run and not os.path.exists(os.path.dirname(logfile)): |
1617 | - os.makedirs(os.path.dirname(logfile)) |
1618 | + if not options.dry_run and not os.path.exists(logdir): |
1619 | + os.makedirs(logdir) |
1620 | |
1621 | logging.basicConfig(level=logging.INFO, |
1622 | format='%(asctime)s %(levelname)s %(message)s', |
1623 | filename=logfile) |
1624 | - |
1625 | # additional logging |
1626 | logger = logging.getLogger() |
1627 | mem_log = StringIO() |
1628 | @@ -734,7 +773,7 @@ |
1629 | mem_log_handler = logging.StreamHandler(mem_log) |
1630 | logger.addHandler(mem_log_handler) |
1631 | return mem_log |
1632 | - |
1633 | + |
1634 | |
1635 | def main(options, rootdir=""): |
1636 | |
1637 | @@ -749,24 +788,28 @@ |
1638 | allowed_origins = get_allowed_origins() |
1639 | |
1640 | # pkgs that are (for some reason) not save to install |
1641 | - blacklisted_pkgs = apt_pkg.config.value_list("Unattended-Upgrade::Package-Blacklist") |
1642 | - logging.info(_("Initial blacklisted packages: %s"), " ".join(blacklisted_pkgs)) |
1643 | + blacklisted_pkgs = apt_pkg.config.value_list( |
1644 | + "Unattended-Upgrade::Package-Blacklist") |
1645 | + logging.info(_("Initial blacklisted packages: %s"), |
1646 | + " ".join(blacklisted_pkgs)) |
1647 | logging.info(_("Starting unattended upgrades script")) |
1648 | |
1649 | # display available origin |
1650 | - logging.info(_("Allowed origins are: %s") % map(str,allowed_origins)) |
1651 | + logging.info(_("Allowed origins are: %s") % allowed_origins) |
1652 | |
1653 | # check if the journal is dirty and if so, take emergceny action |
1654 | # the alternative is to leave the system potentially unsecure until |
1655 | # the user comes in and fixes |
1656 | if (is_dpkg_journal_dirty() and |
1657 | - apt_pkg.config.find_b("Unattended-Upgrade::AutoFixInterruptedDpkg", True)): |
1658 | + apt_pkg.config.find_b( |
1659 | + "Unattended-Upgrade::AutoFixInterruptedDpkg", True)): |
1660 | # ensure the dpkg database is not already locked (LP: #754330) |
1661 | admindir = os.path.dirname(apt_pkg.config.find("Dir::State::Status")) |
1662 | lockfd = apt_pkg.get_lock(os.path.join(admindir, "lock"), False) |
1663 | if lockfd > 0: |
1664 | - logging.warning(_("Unclean dpkg state detected, trying to correct")) |
1665 | - print _("Unclean dpkg state detected, trying to correct") |
1666 | + logging.warning( |
1667 | + _("Unclean dpkg state detected, trying to correct")) |
1668 | + print(_("Unclean dpkg state detected, trying to correct")) |
1669 | env = copy.copy(os.environ) |
1670 | env["DEBIAN_FRONTEND"] = "noninteractive" |
1671 | try: |
1672 | @@ -777,22 +820,23 @@ |
1673 | output = e.output |
1674 | logging.warning(_("dpkg --configure -a output:\n%s" % output)) |
1675 | else: |
1676 | - logging.debug("Unclean dpkg state, but locked, another package manager working?") |
1677 | - |
1678 | + logging.debug("Unclean dpkg state, but locked, another package " |
1679 | + "manager working?") |
1680 | + |
1681 | # check and get lock |
1682 | try: |
1683 | apt_pkg.pkgsystem_lock() |
1684 | - except SystemError, e: |
1685 | + except SystemError as e: |
1686 | logging.error(_("Lock could not be acquired (another package " |
1687 | "manager running?)")) |
1688 | - print _("Cache lock can not be acquired, exiting") |
1689 | + print(_("Cache lock can not be acquired, exiting")) |
1690 | sys.exit(1) |
1691 | |
1692 | # get a cache |
1693 | - cache = UnattendedUpgradesCache(rootdir=rootdir, |
1694 | + cache = UnattendedUpgradesCache(rootdir=rootdir, |
1695 | allowed_origins=allowed_origins) |
1696 | if cache._depcache.broken_count > 0: |
1697 | - print _("Cache has broken packages, exiting") |
1698 | + print(_("Cache has broken packages, exiting")) |
1699 | logging.error(_("Cache has broken packages, exiting")) |
1700 | sys.exit(1) |
1701 | # speed things up with latest apt |
1702 | @@ -802,13 +846,14 @@ |
1703 | # find out about the packages that are upgradable (in a allowed_origin) |
1704 | pkgs_to_upgrade = [] |
1705 | pkgs_kept_back = [] |
1706 | - pkgs_auto_removable = set([pkg.name for pkg in cache |
1707 | + pkgs_auto_removable = set([pkg.name for pkg in cache |
1708 | if pkg.is_auto_removable]) |
1709 | |
1710 | # now do the actual upgrade |
1711 | for pkg in cache: |
1712 | if options.debug and pkg.is_upgradable: |
1713 | - logging.debug("Checking: %s (%s)" % (pkg.name, map(str, pkg.candidate.origins))) |
1714 | + logging.debug("Checking: %s (%s)" % ( |
1715 | + pkg.name, map(str, getattr(pkg.candidate, "origins", [])))) |
1716 | if (pkg.is_upgradable and |
1717 | not is_pkgname_in_blacklist(pkg.name, blacklisted_pkgs) and |
1718 | is_allowed_origin(pkg.candidate, allowed_origins)): |
1719 | @@ -818,7 +863,7 @@ |
1720 | blacklisted_pkgs): |
1721 | # add to packages to upgrade |
1722 | pkgs_to_upgrade.append(pkg) |
1723 | - # re-eval pkgs_kept_back as the resolver may fail to |
1724 | + # re-eval pkgs_kept_back as the resolver may fail to |
1725 | # directly upgrade a pkg, but that may work during |
1726 | # a subsequent operation, see debian bug #639840 |
1727 | for pkgname in pkgs_kept_back: |
1728 | @@ -830,17 +875,18 @@ |
1729 | logging.debug("sanity check failed") |
1730 | rewind_cache(cache, pkgs_to_upgrade) |
1731 | pkgs_kept_back.append(pkg.name) |
1732 | - except SystemError, e: |
1733 | + except SystemError as e: |
1734 | # can't upgrade |
1735 | - logging.warning(_("package '%s' upgradable but fails to be marked for upgrade (%s)") % (pkg.name, e)) |
1736 | + logging.warning( |
1737 | + _("package '%s' upgradable but fails to " |
1738 | + "be marked for upgrade (%s)") % (pkg.name, e)) |
1739 | rewind_cache(cache, pkgs_to_upgrade) |
1740 | pkgs_kept_back.append(pkg.name) |
1741 | - |
1742 | |
1743 | pkgs_to_upgrade.sort(key=lambda p: p.name) |
1744 | pkgs = "\n".join([pkg.name for pkg in pkgs_to_upgrade]) |
1745 | logging.debug("pkgs that look like they should be upgraded: %s" % pkgs) |
1746 | - |
1747 | + |
1748 | # download what looks good |
1749 | if options.debug: |
1750 | fetcher = apt_pkg.Acquire(apt.progress.text.AcquireProgress()) |
1751 | @@ -851,8 +897,8 @@ |
1752 | recs = cache._records |
1753 | pm = apt_pkg.PackageManager(cache._depcache) |
1754 | try: |
1755 | - pm.get_archives(fetcher,list,recs) |
1756 | - except SystemError, e: |
1757 | + pm.get_archives(fetcher, list, recs) |
1758 | + except SystemError as e: |
1759 | logging.error(_("GetArchives() failed: '%s'") % e) |
1760 | res = fetcher.run() |
1761 | logging.debug("fetch.run() result: %s" % res) |
1762 | @@ -863,15 +909,19 @@ |
1763 | for item in fetcher.items: |
1764 | logging.debug("%s" % item) |
1765 | if item.status == item.STAT_ERROR: |
1766 | - print _("An error ocured: '%s'") % item.error_text |
1767 | + print(_("An error ocured: '%s'") % item.error_text) |
1768 | logging.error(_("An error ocured: '%s'") % item.error_text) |
1769 | if not item.complete: |
1770 | - print _("The URI '%s' failed to download, aborting") % item.desc_uri |
1771 | - logging.error(_("The URI '%s' failed to download, aborting") % item.desc_uri) |
1772 | + print(_("The URI '%s' failed to download, aborting") % |
1773 | + item.desc_uri) |
1774 | + logging.error(_("The URI '%s' failed to download, aborting") % |
1775 | + item.desc_uri) |
1776 | sys.exit(1) |
1777 | if not os.path.exists(item.destfile): |
1778 | - print _("Download finished, but file '%s' not there?!?" % item.destfile) |
1779 | - logging.error("Download finished, but file '%s' not there?!?" % item.destfile) |
1780 | + print(_("Download finished, but file '%s' not there?!?" % |
1781 | + item.destfile)) |
1782 | + logging.error("Download finished, but file '%s' not " |
1783 | + "there?!?" % item.destfile) |
1784 | sys.exit(1) |
1785 | if not item.is_trusted: |
1786 | blacklisted_pkgs.append(pkgname_from_deb(item.destfile)) |
1787 | @@ -879,18 +929,21 @@ |
1788 | # skip package (means to re-run the whole marking again |
1789 | # and making sure that the package will not be pulled in by |
1790 | # some other package again!) |
1791 | - # |
1792 | + # |
1793 | # print to stdout to ensure that this message is part of |
1794 | # the cron mail (only if no summary mail is requested) |
1795 | email = apt_pkg.config.find("Unattended-Upgrade::Mail", "") |
1796 | if not email: |
1797 | - print _("Package '%s' has conffile prompt and needs to be upgraded manually") % pkgname_from_deb(item.destfile) |
1798 | + print(_("Package '%s' has conffile prompt and needs " |
1799 | + "to be upgraded manually") % pkgname_from_deb( |
1800 | + item.destfile)) |
1801 | # log to the logfile |
1802 | - logging.warning(_("Package '%s' has conffile prompt and needs to be upgraded manually") % pkgname_from_deb(item.destfile)) |
1803 | + logging.warning(_("Package '%s' has conffile prompt and " |
1804 | + "needs to be upgraded manually") % |
1805 | + pkgname_from_deb(item.destfile)) |
1806 | blacklisted_pkgs.append(pkgname_from_deb(item.destfile)) |
1807 | pkgs_kept_back.append(pkgname_from_deb(item.destfile)) |
1808 | |
1809 | - |
1810 | # redo the selection about the packages to upgrade based on the new |
1811 | # blacklist |
1812 | logging.debug("blacklist: %s" % blacklisted_pkgs) |
1813 | @@ -904,7 +957,7 @@ |
1814 | pkg.mark_upgrade() |
1815 | if check_changes_for_sanity(cache, allowed_origins, |
1816 | blacklisted_pkgs): |
1817 | - pkgs_to_upgrade.append(pkg) |
1818 | + pkgs_to_upgrade.append(pkg) |
1819 | else: |
1820 | if not (pkg.name in pkgs_kept_back): |
1821 | pkgs_kept_back.append(pkg.name) |
1822 | @@ -916,23 +969,26 @@ |
1823 | logging.debug("dpkg is configured not to cause conffile prompts") |
1824 | |
1825 | # do auto-remove |
1826 | - if apt_pkg.config.find_b("Unattended-Upgrade::Remove-Unused-Dependencies", False): |
1827 | - now_auto_removable = set([pkg.name for pkg in cache |
1828 | + if apt_pkg.config.find_b( |
1829 | + "Unattended-Upgrade::Remove-Unused-Dependencies", False): |
1830 | + now_auto_removable = set([pkg.name for pkg in cache |
1831 | if pkg.is_auto_removable]) |
1832 | - for pkgname in now_auto_removable-pkgs_auto_removable: |
1833 | + for pkgname in now_auto_removable - pkgs_auto_removable: |
1834 | logging.debug("marking %s for remove" % pkgname) |
1835 | cache[pkgname].mark_delete() |
1836 | logging.info(_("Packages that are auto removed: '%s'") % |
1837 | - " ".join(now_auto_removable-pkgs_auto_removable)) |
1838 | + " ".join(now_auto_removable - pkgs_auto_removable)) |
1839 | |
1840 | - logging.debug("InstCount=%i DelCount=%i BrokenCout=%i" % (cache._depcache.inst_count, cache._depcache.del_count, cache._depcache.broken_count)) |
1841 | + logging.debug("InstCount=%i DelCount=%i BrokenCount=%i" % ( |
1842 | + cache._depcache.inst_count, cache._depcache.del_count, |
1843 | + cache._depcache.broken_count)) |
1844 | |
1845 | # exit if there is nothing to do and nothing to report |
1846 | if (len(pkgs_to_upgrade) == 0) and (len(pkgs_kept_back) == 0): |
1847 | logging.info(_("No packages found that can be upgraded unattended")) |
1848 | return |
1849 | |
1850 | - # check if its configured for install on shutdown, if so, the |
1851 | + # check if its configured for install on shutdown, if so, the |
1852 | # environment UNATTENDED_UPGRADES_FORCE_INSTALL_ON_SHUTDOWN will |
1853 | # be set by the unatteded-upgrades-shutdown script |
1854 | if (not "UNATTENDED_UPGRADES_FORCE_INSTALL_ON_SHUTDOWN" in os.environ and |
1855 | @@ -944,7 +1000,7 @@ |
1856 | # check if we are in dry-run mode |
1857 | if options.dry_run: |
1858 | logging.info("Option --dry-run given, *not* performing real actions") |
1859 | - apt_pkg.config.set("Debug::pkgDPkgPM","1") |
1860 | + apt_pkg.config.set("Debug::pkgDPkgPM", "1") |
1861 | |
1862 | # do the install based on the new list of pkgs |
1863 | pkgs = " ".join([pkg.name for pkg in pkgs_to_upgrade]) |
1864 | @@ -972,17 +1028,18 @@ |
1865 | pkgs, pkg_install_success, pkgs_kept_back, mem_log, logfile_dpkg) |
1866 | |
1867 | # auto-reboot (if required and the config for this is set |
1868 | - if (apt_pkg.config.find_b("Unattended-Upgrade::Automatic-Reboot", False) and |
1869 | + if (apt_pkg.config.find_b( |
1870 | + "Unattended-Upgrade::Automatic-Reboot", False) and |
1871 | os.path.exists(REBOOT_REQUIRED_FILE)): |
1872 | if shutdown_lock > 0: |
1873 | os.close(shutdown_lock) |
1874 | logging.warning("Found %s, rebooting" % REBOOT_REQUIRED_FILE) |
1875 | subprocess.call(["/sbin/reboot"]) |
1876 | - |
1877 | + |
1878 | |
1879 | if __name__ == "__main__": |
1880 | - localesApp="unattended-upgrades" |
1881 | - localesDir="/usr/share/locale" |
1882 | + localesApp = "unattended-upgrades" |
1883 | + localesDir = "/usr/share/locale" |
1884 | gettext.bindtextdomain(localesApp, localesDir) |
1885 | gettext.textdomain(localesApp) |
1886 | |
1887 | @@ -996,19 +1053,20 @@ |
1888 | help=_("Simulation, download but do not install")) |
1889 | parser.add_option("", "--minimal_upgrade_steps", |
1890 | action="store_true", default=False, |
1891 | - help=_("Upgrade in minimal steps (and allow interrupting with SIGINT")) |
1892 | + help=_("Upgrade in minimal steps (and allow " |
1893 | + "interrupting with SIGINT")) |
1894 | (options, args) = parser.parse_args() |
1895 | |
1896 | if os.getuid() != 0: |
1897 | - print _("You need to be root to run this application") |
1898 | + print(_("You need to be root to run this application")) |
1899 | sys.exit(1) |
1900 | |
1901 | # nice & ionce |
1902 | os.nice(19) |
1903 | - IONICE="/usr/bin/ionice" |
1904 | + IONICE = "/usr/bin/ionice" |
1905 | if os.path.exists(IONICE): |
1906 | with open(os.devnull, "w") as fstderr: |
1907 | - subprocess.call([IONICE, "-c3", "-p",str(os.getpid())], |
1908 | + subprocess.call([IONICE, "-c3", "-p", str(os.getpid())], |
1909 | stderr=fstderr) |
1910 | |
1911 | # ensure that we are not killed when the terminal goes away e.g. on |
1912 | |
1913 | === modified file 'unattended-upgrade-shutdown' |
1914 | --- unattended-upgrade-shutdown 2012-04-26 11:40:46 +0000 |
1915 | +++ unattended-upgrade-shutdown 2012-10-05 15:48:44 +0000 |
1916 | @@ -1,13 +1,13 @@ |
1917 | -#!/usr/bin/python |
1918 | +#!/usr/bin/python3 |
1919 | # Copyright (c) 2009 Canonical Ltd |
1920 | # |
1921 | # AUTHOR: |
1922 | # Michael Vogt <mvo@ubuntu.com> |
1923 | # |
1924 | -# unattended-upgrade-shutdown - helper that checks if a |
1925 | +# unattended-upgrade-shutdown - helper that checks if a |
1926 | # unattended-upgrade is in progress and waits until it exists |
1927 | # |
1928 | -# This file is part of unattended-upgrades |
1929 | +# This file is part of unattended-upgrades |
1930 | # |
1931 | # unattended-upgrades is free software; you can redistribute it and/or |
1932 | # modify it under the terms of the GNU General Public License as published |
1933 | @@ -47,16 +47,19 @@ |
1934 | logging.exception("importing of apt_pkg failed, exiting") |
1935 | sys.exit(0) |
1936 | |
1937 | + |
1938 | def do_usplash(msg): |
1939 | if os.path.exists("/sbin/usplash_write"): |
1940 | logging.debug("Running usplash_write") |
1941 | - subprocess.call(["/sbin/usplash_write","TEXT", msg]) |
1942 | - subprocess.call(["/sbin/usplash_write","PULSATE"]) |
1943 | + subprocess.call(["/sbin/usplash_write", "TEXT", msg]) |
1944 | + subprocess.call(["/sbin/usplash_write", "PULSATE"]) |
1945 | + |
1946 | |
1947 | def do_plymouth(msg): |
1948 | if os.path.exists("/bin/plymouth"): |
1949 | logging.debug("Running plymouth --text") |
1950 | - subprocess.call(["/bin/plymouth","message", "--text", msg]) |
1951 | + subprocess.call(["/bin/plymouth", "message", "--text", msg]) |
1952 | + |
1953 | |
1954 | def log_msg(msg, level=logging.WARN): |
1955 | """ helper that will print msg to usplash, plymouth, console """ |
1956 | @@ -64,6 +67,7 @@ |
1957 | do_plymouth(msg) |
1958 | do_usplash(msg) |
1959 | |
1960 | + |
1961 | def log_progress(): |
1962 | """ helper to log the install progress (if any) """ |
1963 | # wait a some seconds and try again |
1964 | @@ -76,10 +80,11 @@ |
1965 | # log it |
1966 | log_msg(msg) |
1967 | |
1968 | + |
1969 | if __name__ == "__main__": |
1970 | # setup gettext |
1971 | - localesApp="unattended-upgrades" |
1972 | - localesDir="/usr/share/locale" |
1973 | + localesApp = "unattended-upgrades" |
1974 | + localesDir = "/usr/share/locale" |
1975 | gettext.bindtextdomain(localesApp, localesDir) |
1976 | gettext.textdomain(localesApp) |
1977 | |
1978 | @@ -89,11 +94,11 @@ |
1979 | help="print debug messages") |
1980 | parser.add_option("", "--delay", default=10, |
1981 | help="delay in minutes to wait for unattended-upgrades") |
1982 | - parser.add_option("", "--lock-file", |
1983 | + parser.add_option("", "--lock-file", |
1984 | default="/var/run/unattended-upgrades.lock", |
1985 | help="lock file location") |
1986 | (options, args) = parser.parse_args() |
1987 | - |
1988 | + |
1989 | # setup logging |
1990 | level = logging.INFO |
1991 | if options.debug: |
1992 | @@ -101,7 +106,11 @@ |
1993 | |
1994 | # use a normal logfile instead of syslog too as on shutdown its too |
1995 | # easy to get syslog killed |
1996 | - logfile = "/var/log/unattended-upgrades/unattended-upgrades-shutdown.log" |
1997 | + logdir = apt_pkg.config.find_dir( |
1998 | + "Unattended-Upgrade::LogDir", "/var/log/unattended-upgrades/") |
1999 | + if not os.path.exists(logdir): |
2000 | + os.makedirs(logdir) |
2001 | + logfile = os.path.join(logdir, "unattended-upgrades-shutdown.log") |
2002 | logging.basicConfig(filename=logfile, |
2003 | level=level, |
2004 | format="%(asctime)s %(levelname)s - %(message)s") |
2005 | @@ -125,7 +134,7 @@ |
2006 | # run the monitoring loop and keep the "UI" updated |
2007 | start_time = time.time() |
2008 | lock_was_taken = False |
2009 | - while True: |
2010 | + while True: |
2011 | res = apt_pkg.get_lock(options.lock_file) |
2012 | logging.debug("get_lock returned %i" % res) |
2013 | # exit here if there is no lock |
2014 | @@ -141,11 +150,12 @@ |
2015 | os.kill(pid, signal.SIGUSR1) |
2016 | # show log |
2017 | log_progress() |
2018 | - time.sleep(5) |
2019 | - if (time.time() - start_time) > options.delay*60: |
2020 | - logging.warning(_("Giving up on lockfile after %s delay") % options.delay) |
2021 | + time.sleep(5) |
2022 | + if (time.time() - start_time) > options.delay * 60: |
2023 | + logging.warning( |
2024 | + _("Giving up on lockfile after %s delay") % options.delay) |
2025 | sys.exit(1) |
2026 | - |
2027 | + |
2028 | # add finished info to the log/terminal to help tracking down |
2029 | # LP: #434835 |
2030 | if lock_was_taken: |