Merge lp:~takluyver/unattended-upgrades/py3 into lp:~ubuntu-core-dev/unattended-upgrades/ubuntu
- py3
- Merge into ubuntu
Status: | Merged |
---|---|
Approved by: | Barry Warsaw |
Approved revision: | 285 |
Merge reported by: | Barry Warsaw |
Merged at revision: | not available |
Proposed branch: | lp:~takluyver/unattended-upgrades/py3 |
Merge into: | lp:~ubuntu-core-dev/unattended-upgrades/ubuntu |
Diff against target: |
712 lines (+115/-93) 18 files modified
.bzrignore (+2/-0) debian/changelog (+4/-1) debian/control (+4/-4) debian/rules (+13/-11) debian/unattended-upgrades.init (+1/-1) pm/sleep.d/10_unattended-upgrades-hibernate (+1/-1) test/Makefile (+2/-2) test/create_debug_lock.py (+1/-1) test/test_against_real_archive.py (+9/-3) test/test_conffile.py (+1/-1) test/test_in_chroot.py (+9/-9) test/test_logdir.py (+1/-1) test/test_mail.py (+16/-9) test/test_minimal_partitions.py (+2/-5) test/test_origin_pattern.py (+1/-1) test/test_substitute.py (+2/-2) unattended-upgrade (+43/-38) unattended-upgrade-shutdown (+3/-3) |
To merge this branch: | bzr merge lp:~takluyver/unattended-upgrades/py3 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Barry Warsaw (community) | Approve | ||
Michael Vogt | upload to debian | Pending | |
Review via email: mp+110684@code.launchpad.net |
Commit message
Description of the change
As part of Ubuntu's push for Python 3 in Quantal (https:/
The tests pass, and I've checked that it contains equivalent files to the current package (http://
Thomas Kluyver (takluyver) wrote : | # |
- 278. By Michael Vogt
-
* po/da.po:
- updated, thanks to Joe Dalton, closes: #677804 - 279. By Michael Vogt
-
* debian/
unattended- upgrades. init:
- use new style lsb-init output, closes: #678030 - 280. By Michael Vogt
-
honor verbose
Barry Warsaw (barry) wrote : | # |
Looks like there are some text conflicts as well, but I can try to fix those.
Barry Warsaw (barry) wrote : | # |
Oh also, the conversion to bytes in send_summary_mail() isn't right. It's generally accepted wisdom that in Python 3, Popen() should be passed universal_
Barry Warsaw (barry) wrote : | # |
Thomas, thanks for taking this work on! I appreciate everything you can do to
help us in our porting efforts. A few comments, and then I'll work on merging
this for you.
- I don't know how to test unattended-
can come up with something.
- How hard would it be to fix the failing Python 2 test? If it fails in Py2
it would be nice to fix, but I don't think it should necessarily block your
work.
- Note that unless you're holding out the possibility to revert to Python 2,
or if you're being annoyed by pyflakes warnings, you really don't need to
future import print_function for Python 3.
- Line 433 would probably be better rewritten:
with open(prefix + conf_file, 'rb') as fp:
current_md5 = fp.read()
I can fix that for you when I merge your branch.
Other than that, the diff looks pretty good.
Barry Warsaw (barry) wrote : | # |
Also, test_against_
=======
FAIL: test_against_
-------
Traceback (most recent call last):
File "./test_
self.
AssertionError: True is not false
-------
Ran 1 test in 9.248s
- 281. By Barry Warsaw
-
Merge Thomas's branch: Port to Python 3
- Additional fixes by Barry
Barry Warsaw (barry) wrote : | # |
Thomas, for now I'm going to mark this branch as needs fixing. Please look at my branch, which merges yours into trunk and contains additional fixes that will be necessary. If you can get the remaining tests to pass, I'll be happy to re-review the branch and sponsor it for you.
Thomas Kluyver (takluyver) wrote : | # |
Thanks Barry,
On 19 June 2012 20:25, Barry Warsaw <email address hidden> wrote:
> - How hard would it be to fix the failing Python 2 test? If it fails in Py2
> it would be nice to fix, but I don't think it should necessarily block your
> work.
I should have been clearer about this - I meant 'it fails *even* in
Python 2, so I haven't tried it in Python 3 yet'. To further
complicate matters, it tests in a Lucid chroot, and there's no
python3-apt in Lucid. I don't know whether testing in an old version
is an intentional way to make sure there's updates available, or just
because the test was written then and hasn't been changed.
For reference, I've re-run it (in Python 2) and put the last part of
the output at https:/
> - Note that unless you're holding out the possibility to revert to Python 2,
> or if you're being annoyed by pyflakes warnings, you really don't need to
> future import print_function for Python 3.
Do any other distributions use unattended-
keep running it in Python 2, it's very easy for me to enable that. If
not, I agree that it's slightly tidier not to.
> - Line 433 would probably be better rewritten:
>
> with open(prefix + conf_file, 'rb') as fp:
> current_md5 = fp.read()
>
> I can fix that for you when I merge your branch.
I see you did fix it; thanks.
Thomas
Thomas Kluyver (takluyver) wrote : | # |
Thanks for the tip about Popen(), I didn't know about that argument. It seems rather unintuitive to have universal_newlines control text/bytes mode, though.
I've checked out your branch - I don't see the failure in test_against_
Barry Warsaw (barry) wrote : | # |
On Jun 20, 2012, at 12:15 AM, Thomas Kluyver wrote:
>I've checked out your branch - I don't see the failure in
>test_against_
>https:/
That probably means it's dependent on the environment. Something in my
environment (on precise and quantal, on both a normal desktop and chroot) is
causing the test to fail. That plus the fact that the test hits the network
tell me that it's not a very good test.
The problem is, if I want to sponsor this for you, I have to build the source
package. To do that, I'd have to disable the test since the source package
won't build with a failing test. Maybe that's the best we can do with such a
bad test.
It's not clear to me what this test is actually trying to do though. Do you
think you could take a crack at improving the test so that it isn't dependent
on the environment, and/or that it doesn't hit the network? Failing that, we
might just have to bite the bullet and disable the test.
As for continuing to support Python 2, perhaps the only reason to do so is if
it needs to be backported to earlier versions that don't have Python 3. If
not, then I personally think it would be fine to drop it.
- 282. By Thomas Kluyver
-
Fix subprocess communication on Python 3
- 283. By Thomas Kluyver
-
Disable test that requires network access
- 284. By Thomas Kluyver
-
Remove Python 2 compatible imports
Thomas Kluyver (takluyver) wrote : | # |
I think the nature of that test needs network communications - 'against real archive' seems to mean the Ubuntu package archive. I've disabled it so that "cd test/; make" doesn't see it (it checks the executable flag on the files). The package building doesn't appear to run any tests, however.
I've also dropped the backwards compatible imports, so it will only work with Python 3.
Barry Warsaw (barry) wrote : | # |
On Jun 24, 2012, at 03:46 PM, Thomas Kluyver wrote:
>I think the nature of that test needs network communications - 'against real
>archive' seems to mean the Ubuntu package archive. I've disabled it so that
>"cd test/; make" doesn't see it (it checks the executable flag on the
>files). The package building doesn't appear to run any tests, however.
>
>I've also dropped the backwards compatible imports, so it will only work with
>Python 3.
Quick response: I'm now getting a text conflict against trunk in
debian/
I was able to build the package locally and everything else looks fine, so
once you push an non-conflicting update, I'll try to sponsor this for you.
Thanks for your work on porting this to Python 3!
- 285. By Thomas Kluyver
-
Merge trunk
Thomas Kluyver (takluyver) wrote : | # |
Thanks, Barry. I've merged in trunk and resolved the conflict.
Barry Warsaw (barry) wrote : | # |
Thanks Thomas, looks great. I've pushed the merge to trunk, but it's up to Michael to upload the new package. I think it has to go to Debian first, and then it'll get sync'd into Quantal.
Barry Warsaw (barry) : | # |
Preview Diff
1 | === added file '.bzrignore' | |||
2 | --- .bzrignore 1970-01-01 00:00:00 +0000 | |||
3 | +++ .bzrignore 2012-06-25 20:04:38 +0000 | |||
4 | @@ -0,0 +1,2 @@ | |||
5 | 1 | __pycache__ | ||
6 | 2 | build | ||
7 | 0 | 3 | ||
8 | === modified file 'debian/changelog' | |||
9 | --- debian/changelog 2012-06-25 07:11:57 +0000 | |||
10 | +++ debian/changelog 2012-06-25 20:04:38 +0000 | |||
11 | @@ -16,6 +16,9 @@ | |||
12 | 16 | * debian/unattended-upgrades.init: | 16 | * debian/unattended-upgrades.init: |
13 | 17 | - fixes new style lsb-init output, closes: #678030 | 17 | - fixes new style lsb-init output, closes: #678030 |
14 | 18 | 18 | ||
15 | 19 | [ Thomas Kluyver ] | ||
16 | 20 | * Port to Python 3 | ||
17 | 21 | |||
18 | 19 | -- Michael Vogt <michael.vogt@ubuntu.com> Mon, 25 Jun 2012 08:42:23 +0200 | 22 | -- Michael Vogt <michael.vogt@ubuntu.com> Mon, 25 Jun 2012 08:42:23 +0200 |
19 | 20 | 23 | ||
20 | 21 | unattended-upgrades (0.78) unstable; urgency=low | 24 | unattended-upgrades (0.78) unstable; urgency=low |
21 | @@ -28,7 +31,7 @@ | |||
22 | 28 | - updated, thanks to Joe Dalton, closes: #677804 | 31 | - updated, thanks to Joe Dalton, closes: #677804 |
23 | 29 | * po/de.po: | 32 | * po/de.po: |
24 | 30 | - updated, thanks to Chris Leick (closes: #678204) | 33 | - updated, thanks to Chris Leick (closes: #678204) |
26 | 31 | 34 | ||
27 | 32 | [ Teodor MICU ] | 35 | [ Teodor MICU ] |
28 | 33 | * debian/unattended-upgrades.init: | 36 | * debian/unattended-upgrades.init: |
29 | 34 | - use new style lsb-init output, closes: #678030 | 37 | - use new style lsb-init output, closes: #678030 |
30 | 35 | 38 | ||
31 | === modified file 'debian/control' | |||
32 | --- debian/control 2012-06-19 15:26:37 +0000 | |||
33 | +++ debian/control 2012-06-25 20:04:38 +0000 | |||
34 | @@ -3,14 +3,14 @@ | |||
35 | 3 | Priority: optional | 3 | Priority: optional |
36 | 4 | Maintainer: Michael Vogt <michael.vogt@ubuntu.com> | 4 | Maintainer: Michael Vogt <michael.vogt@ubuntu.com> |
37 | 5 | Build-Depends: debhelper (>= 7.0.50~), po-debconf, lsb-release | 5 | Build-Depends: debhelper (>= 7.0.50~), po-debconf, lsb-release |
40 | 6 | Build-Depends-Indep: python (>= 2.6.6-3~), python-distutils-extra | 6 | Build-Depends-Indep: python3, python3-distutils-extra |
41 | 7 | Standards-Version: 3.8.3 | 7 | Standards-Version: 3.9.3 |
42 | 8 | Vcs-Bzr: http://code.launchpad.net/~ubuntu-core-dev/unattended-upgrades/ubuntu/ | 8 | Vcs-Bzr: http://code.launchpad.net/~ubuntu-core-dev/unattended-upgrades/ubuntu/ |
43 | 9 | 9 | ||
44 | 10 | Package: unattended-upgrades | 10 | Package: unattended-upgrades |
45 | 11 | Architecture: all | 11 | Architecture: all |
48 | 12 | Depends: ${shlibs:Depends}, ${misc:Depends}, debconf, python, | 12 | Depends: ${shlibs:Depends}, ${misc:Depends}, debconf, python3, |
49 | 13 | python-apt (>= 0.7.90), apt-utils, apt, ucf, lsb-release, | 13 | python3-apt (>= 0.7.90), apt-utils, apt, ucf, lsb-release, |
50 | 14 | lsb-base (>= 3.2-14) | 14 | lsb-base (>= 3.2-14) |
51 | 15 | Suggests: bsd-mailx | 15 | Suggests: bsd-mailx |
52 | 16 | Description: automatic installation of security upgrades | 16 | Description: automatic installation of security upgrades |
53 | 17 | 17 | ||
54 | === modified file 'debian/rules' | |||
55 | --- debian/rules 2011-11-09 19:20:50 +0000 | |||
56 | +++ debian/rules 2012-06-25 20:04:38 +0000 | |||
57 | @@ -3,24 +3,26 @@ | |||
58 | 3 | DIST=$(shell /usr/bin/lsb_release -i -s) | 3 | DIST=$(shell /usr/bin/lsb_release -i -s) |
59 | 4 | 4 | ||
60 | 5 | %: | 5 | %: |
62 | 6 | dh $@ --with python2 | 6 | dh $@ --with python3 |
63 | 7 | 7 | ||
64 | 8 | override_dh_auto_build: | 8 | override_dh_auto_build: |
65 | 9 | # copy the right template into place | 9 | # copy the right template into place |
66 | 10 | cp data/50unattended-upgrades.$(DIST) data/50unattended-upgrades | 10 | cp data/50unattended-upgrades.$(DIST) data/50unattended-upgrades |
68 | 11 | dh_auto_build | 11 | python3 setup.py build |
69 | 12 | |||
70 | 13 | override_dh_auto_install: | ||
71 | 14 | python3 setup.py install \ | ||
72 | 15 | --root=$(CURDIR)/debian/unattended-upgrades \ | ||
73 | 16 | --install-layout=deb | ||
74 | 12 | 17 | ||
75 | 13 | override_dh_auto_clean: | 18 | override_dh_auto_clean: |
76 | 14 | # Sanity-check before upload. | 19 | # Sanity-check before upload. |
86 | 15 | set -e; if [ -e /usr/lib/python$(PYVER)/py_compile.py ]; then \ | 20 | set -e; for f in unattended-upgrade unattended-upgrade-shutdown; do \ |
87 | 16 | for f in unattended-upgrade unattended-upgrade-shutdown; do \ | 21 | ln -nsf $$f $$f.py; \ |
88 | 17 | ln -nsf $$f $$f.py; \ | 22 | py3compile $$f.py; \ |
89 | 18 | python$(PYVER) /usr/lib/python$(PYVER)/py_compile.py \ | 23 | rm -f $$f.py; \ |
90 | 19 | $$f.py; \ | 24 | done |
91 | 20 | rm -f $$f.py; \ | 25 | python3 setup.py clean -a |
83 | 21 | done; \ | ||
84 | 22 | fi | ||
85 | 23 | dh_auto_clean | ||
92 | 24 | 26 | ||
93 | 25 | override_dh_installinit: | 27 | override_dh_installinit: |
94 | 26 | # we do not want to run the init script in the postinst/prerm, its | 28 | # we do not want to run the init script in the postinst/prerm, its |
95 | 27 | 29 | ||
96 | === modified file 'debian/unattended-upgrades.init' | |||
97 | --- debian/unattended-upgrades.init 2012-06-25 07:07:39 +0000 | |||
98 | +++ debian/unattended-upgrades.init 2012-06-25 20:04:38 +0000 | |||
99 | @@ -33,7 +33,7 @@ | |||
100 | 33 | stop) | 33 | stop) |
101 | 34 | if [ -e $SHUTDOWN_HELPER ]; then | 34 | if [ -e $SHUTDOWN_HELPER ]; then |
102 | 35 | [ "$VERBOSE" != "no" ] && log_action_begin_msg "Checking for running $DESC" | 35 | [ "$VERBOSE" != "no" ] && log_action_begin_msg "Checking for running $DESC" |
104 | 36 | python $SHUTDOWN_HELPER | 36 | python3 $SHUTDOWN_HELPER |
105 | 37 | [ "$VERBOSE" != "no" ] && log_action_end_msg $? "$NAME" | 37 | [ "$VERBOSE" != "no" ] && log_action_end_msg $? "$NAME" |
106 | 38 | fi | 38 | fi |
107 | 39 | ;; | 39 | ;; |
108 | 40 | 40 | ||
109 | === modified file 'pm/sleep.d/10_unattended-upgrades-hibernate' | |||
110 | --- pm/sleep.d/10_unattended-upgrades-hibernate 2011-11-08 16:56:58 +0000 | |||
111 | +++ pm/sleep.d/10_unattended-upgrades-hibernate 2012-06-25 20:04:38 +0000 | |||
112 | @@ -17,7 +17,7 @@ | |||
113 | 17 | case "${1}" in | 17 | case "${1}" in |
114 | 18 | hibernate) | 18 | hibernate) |
115 | 19 | if [ -e $SHUTDOWN_HELPER ]; then | 19 | if [ -e $SHUTDOWN_HELPER ]; then |
117 | 20 | python $SHUTDOWN_HELPER | 20 | python3 $SHUTDOWN_HELPER |
118 | 21 | fi | 21 | fi |
119 | 22 | ;; | 22 | ;; |
120 | 23 | resume|thaw) | 23 | resume|thaw) |
121 | 24 | 24 | ||
122 | === modified file 'test/Makefile' | |||
123 | --- test/Makefile 2011-10-07 09:22:19 +0000 | |||
124 | +++ test/Makefile 2012-06-25 20:04:38 +0000 | |||
125 | @@ -6,9 +6,9 @@ | |||
126 | 6 | set -e; \ | 6 | set -e; \ |
127 | 7 | find . -name 'test_*.py' | \ | 7 | find . -name 'test_*.py' | \ |
128 | 8 | while read file; do \ | 8 | while read file; do \ |
129 | 9 | echo "Running $$file"; \ | ||
130 | 10 | if [ -x $$file ]; then \ | 9 | if [ -x $$file ]; then \ |
132 | 11 | python $$file ; \ | 10 | echo "Running $$file"; \ |
133 | 11 | python3 $$file ; \ | ||
134 | 12 | fi \ | 12 | fi \ |
135 | 13 | done | 13 | done |
136 | 14 | 14 | ||
137 | 15 | 15 | ||
138 | === modified file 'test/create_debug_lock.py' | |||
139 | --- test/create_debug_lock.py 2011-06-16 07:10:07 +0000 | |||
140 | +++ test/create_debug_lock.py 2012-06-25 20:04:38 +0000 | |||
141 | @@ -1,4 +1,4 @@ | |||
143 | 1 | #!/usr/bin/python | 1 | #!/usr/bin/python3 |
144 | 2 | # | 2 | # |
145 | 3 | # create a lock file so that unattended-upgrades-shutdown pauses | 3 | # create a lock file so that unattended-upgrades-shutdown pauses |
146 | 4 | # on shutdown -- useful for testing | 4 | # on shutdown -- useful for testing |
147 | 5 | 5 | ||
148 | === modified file 'test/test_against_real_archive.py' (properties changed: +x to -x) | |||
149 | --- test/test_against_real_archive.py 2012-02-28 10:48:18 +0000 | |||
150 | +++ test/test_against_real_archive.py 2012-06-25 20:04:38 +0000 | |||
151 | @@ -1,4 +1,9 @@ | |||
153 | 1 | #!/usr/bin/python | 1 | #!/usr/bin/python3 |
154 | 2 | """Test unattended_upgrades against the real archive in a chroot. | ||
155 | 3 | |||
156 | 4 | Note that this test is not run by the makefile in this folder, as it requires | ||
157 | 5 | network access, and it fails in some situations (unclear which). | ||
158 | 6 | """ | ||
159 | 2 | 7 | ||
160 | 3 | import apt | 8 | import apt |
161 | 4 | import apt_pkg | 9 | import apt_pkg |
162 | @@ -42,9 +47,10 @@ | |||
163 | 42 | res = unattended_upgrade.main(options, os.path.abspath("./aptroot")) | 47 | res = unattended_upgrade.main(options, os.path.abspath("./aptroot")) |
164 | 43 | # check if the log file exists | 48 | # check if the log file exists |
165 | 44 | self.assertTrue(os.path.exists(logfile)) | 49 | self.assertTrue(os.path.exists(logfile)) |
167 | 45 | log = open(logfile).read() | 50 | with open(logfile) as fp: |
168 | 51 | log = fp.read() | ||
169 | 46 | # check that stuff worked | 52 | # check that stuff worked |
171 | 47 | self.assertFalse(" ERROR " in log) | 53 | self.assertFalse(" ERROR " in log, log) |
172 | 48 | # check if we actually have the expected ugprade in it | 54 | # check if we actually have the expected ugprade in it |
173 | 49 | self.assertTrue( | 55 | self.assertTrue( |
174 | 50 | re.search("INFO Packages that are upgraded:.*awstats", log)) | 56 | re.search("INFO Packages that are upgraded:.*awstats", log)) |
175 | 51 | 57 | ||
176 | === modified file 'test/test_conffile.py' | |||
177 | --- test/test_conffile.py 2011-04-28 16:29:19 +0000 | |||
178 | +++ test/test_conffile.py 2012-06-25 20:04:38 +0000 | |||
179 | @@ -1,4 +1,4 @@ | |||
181 | 1 | #!/usr/bin/python | 1 | #!/usr/bin/python3 |
182 | 2 | 2 | ||
183 | 3 | import apt_pkg | 3 | import apt_pkg |
184 | 4 | import logging | 4 | import logging |
185 | 5 | 5 | ||
186 | === modified file 'test/test_in_chroot.py' | |||
187 | --- test/test_in_chroot.py 2012-01-02 13:14:02 +0000 | |||
188 | +++ test/test_in_chroot.py 2012-06-25 20:04:38 +0000 | |||
189 | @@ -1,4 +1,4 @@ | |||
191 | 1 | #!/usr/bin/python | 1 | #!/usr/bin/python3 |
192 | 2 | 2 | ||
193 | 3 | import apt | 3 | import apt |
194 | 4 | import logging | 4 | import logging |
195 | @@ -56,7 +56,7 @@ | |||
196 | 56 | class TestUnattendedUpgrade(unittest.TestCase): | 56 | class TestUnattendedUpgrade(unittest.TestCase): |
197 | 57 | 57 | ||
198 | 58 | def _create_new_debootstrap_tarball(self, tarball, target): | 58 | def _create_new_debootstrap_tarball(self, tarball, target): |
200 | 59 | print "creating initial test tarball, this is needed only once" | 59 | print("creating initial test tarball, this is needed only once") |
201 | 60 | # force i386 | 60 | # force i386 |
202 | 61 | subprocess.call(["debootstrap", | 61 | subprocess.call(["debootstrap", |
203 | 62 | "--arch=%s" % ARCH, | 62 | "--arch=%s" % ARCH, |
204 | @@ -73,7 +73,7 @@ | |||
205 | 73 | subprocess.call(["tar", "xzf", tarball]) | 73 | subprocess.call(["tar", "xzf", tarball]) |
206 | 74 | 74 | ||
207 | 75 | def test_normal_upgrade(self): | 75 | def test_normal_upgrade(self): |
209 | 76 | print "Running normal unattended upgrade in chroot" | 76 | print("Running normal unattended upgrade in chroot") |
210 | 77 | options = MockOptions() | 77 | options = MockOptions() |
211 | 78 | options.minimal_upgrade_steps = False | 78 | options.minimal_upgrade_steps = False |
212 | 79 | # run it | 79 | # run it |
213 | @@ -82,7 +82,7 @@ | |||
214 | 82 | self.assertTrue(self._verify_install_log_in_real_chroot(target)) | 82 | self.assertTrue(self._verify_install_log_in_real_chroot(target)) |
215 | 83 | 83 | ||
216 | 84 | def test_minimal_steps_upgrade(self): | 84 | def test_minimal_steps_upgrade(self): |
218 | 85 | print "Running minimal steps unattended upgrade in chroot" | 85 | print("Running minimal steps unattended upgrade in chroot") |
219 | 86 | options = MockOptions() | 86 | options = MockOptions() |
220 | 87 | options.minimal_upgrade_steps = True | 87 | options.minimal_upgrade_steps = True |
221 | 88 | # run it | 88 | # run it |
222 | @@ -91,7 +91,7 @@ | |||
223 | 91 | self.assertTrue(self._verify_install_log_in_real_chroot(target)) | 91 | self.assertTrue(self._verify_install_log_in_real_chroot(target)) |
224 | 92 | 92 | ||
225 | 93 | def test_upgrade_on_shutdown_upgrade(self): | 93 | def test_upgrade_on_shutdown_upgrade(self): |
227 | 94 | print "Running unattended upgrade on shutdown (download and install) in chroot" | 94 | print("Running unattended upgrade on shutdown (download and install) in chroot") |
228 | 95 | # ensure that it actually installs in shutdown env mode | 95 | # ensure that it actually installs in shutdown env mode |
229 | 96 | options = MockOptions() | 96 | options = MockOptions() |
230 | 97 | os.environ["UNATTENDED_UPGRADES_FORCE_INSTALL_ON_SHUTDOWN"] = "1" | 97 | os.environ["UNATTENDED_UPGRADES_FORCE_INSTALL_ON_SHUTDOWN"] = "1" |
231 | @@ -121,7 +121,7 @@ | |||
232 | 121 | and does some basic verifications | 121 | and does some basic verifications |
233 | 122 | """ | 122 | """ |
234 | 123 | if os.getuid() != 0: | 123 | if os.getuid() != 0: |
236 | 124 | print "Skipping because uid != 0" | 124 | print("Skipping because uid != 0") |
237 | 125 | return | 125 | return |
238 | 126 | 126 | ||
239 | 127 | # clear to avoid pollution in the chroot | 127 | # clear to avoid pollution in the chroot |
240 | @@ -171,7 +171,7 @@ | |||
241 | 171 | if pid == apid: | 171 | if pid == apid: |
242 | 172 | ret = os.WEXITSTATUS(status) | 172 | ret = os.WEXITSTATUS(status) |
243 | 173 | break | 173 | break |
245 | 174 | #print "*******************", all_progress | 174 | #print("*******************", all_progress) |
246 | 175 | self.assertEqual(ret, 0) | 175 | self.assertEqual(ret, 0) |
247 | 176 | # this number is a bit random, we just want to be sure we have | 176 | # this number is a bit random, we just want to be sure we have |
248 | 177 | # progress data | 177 | # progress data |
249 | @@ -183,7 +183,7 @@ | |||
250 | 183 | # examine log | 183 | # examine log |
251 | 184 | log = self._get_lockfile_location(target) | 184 | log = self._get_lockfile_location(target) |
252 | 185 | logfile = open(log).read() | 185 | logfile = open(log).read() |
254 | 186 | #print logfile | 186 | #print(logfile) |
255 | 187 | NEEDLE_PKG="ca-certificates" | 187 | NEEDLE_PKG="ca-certificates" |
256 | 188 | if not re.search( | 188 | if not re.search( |
257 | 189 | "Packages that are upgraded:.*%s" % NEEDLE_PKG, logfile): | 189 | "Packages that are upgraded:.*%s" % NEEDLE_PKG, logfile): |
258 | @@ -198,7 +198,7 @@ | |||
259 | 198 | if not "Preparing to replace %s" % NEEDLE_PKG in dpkg_logfile: | 198 | if not "Preparing to replace %s" % NEEDLE_PKG in dpkg_logfile: |
260 | 199 | logging.warn("Did not find %s upgrade in the dpkg.log" % NEEDLE_PKG) | 199 | logging.warn("Did not find %s upgrade in the dpkg.log" % NEEDLE_PKG) |
261 | 200 | return False | 200 | return False |
263 | 201 | #print dpkg_logfile | 201 | #print(dpkg_logfile) |
264 | 202 | return True | 202 | return True |
265 | 203 | 203 | ||
266 | 204 | 204 | ||
267 | 205 | 205 | ||
268 | === modified file 'test/test_logdir.py' | |||
269 | --- test/test_logdir.py 2011-03-04 15:04:54 +0000 | |||
270 | +++ test/test_logdir.py 2012-06-25 20:04:38 +0000 | |||
271 | @@ -1,4 +1,4 @@ | |||
273 | 1 | #!/usr/bin/python | 1 | #!/usr/bin/python3 |
274 | 2 | 2 | ||
275 | 3 | import apt_pkg | 3 | import apt_pkg |
276 | 4 | import logging | 4 | import logging |
277 | 5 | 5 | ||
278 | === modified file 'test/test_mail.py' | |||
279 | --- test/test_mail.py 2011-02-03 19:50:16 +0000 | |||
280 | +++ test/test_mail.py 2012-06-25 20:04:38 +0000 | |||
281 | @@ -1,4 +1,4 @@ | |||
283 | 1 | #!/usr/bin/python | 1 | #!/usr/bin/python3 |
284 | 2 | 2 | ||
285 | 3 | import apt | 3 | import apt |
286 | 4 | import apt_pkg | 4 | import apt_pkg |
287 | @@ -7,7 +7,7 @@ | |||
288 | 7 | import unittest | 7 | import unittest |
289 | 8 | import sys | 8 | import sys |
290 | 9 | 9 | ||
292 | 10 | from StringIO import StringIO | 10 | from io import StringIO |
293 | 11 | 11 | ||
294 | 12 | import unattended_upgrade | 12 | import unattended_upgrade |
295 | 13 | import unattended_upgrade | 13 | import unattended_upgrade |
296 | @@ -36,7 +36,8 @@ | |||
297 | 36 | pkgs_kept_back = [] | 36 | pkgs_kept_back = [] |
298 | 37 | mem_log = StringIO("mem_log text") | 37 | mem_log = StringIO("mem_log text") |
299 | 38 | logfile_dpkg = "./apt-term.log" | 38 | logfile_dpkg = "./apt-term.log" |
301 | 39 | open("./apt-term.log", "w").write("logfile_dpkg text") | 39 | with open("./apt-term.log", "w") as fp: |
302 | 40 | fp.write("logfile_dpkg text") | ||
303 | 40 | return (pkgs, res, pkgs_kept_back, mem_log, logfile_dpkg) | 41 | return (pkgs, res, pkgs_kept_back, mem_log, logfile_dpkg) |
304 | 41 | 42 | ||
305 | 42 | def _verify_common_mail_content(self, mail_txt): | 43 | def _verify_common_mail_content(self, mail_txt): |
306 | @@ -45,16 +46,19 @@ | |||
307 | 45 | self.assertTrue("Packages that are upgraded:\n 2vcard" in mail_txt) | 46 | self.assertTrue("Packages that are upgraded:\n 2vcard" in mail_txt) |
308 | 46 | 47 | ||
309 | 47 | def test_summary_mail_reboot(self): | 48 | def test_summary_mail_reboot(self): |
311 | 48 | open("./reboot-required","w").write("") | 49 | with open("./reboot-required","w") as fp: |
312 | 50 | fp.write("") | ||
313 | 49 | send_summary_mail(*self._return_mock_data()) | 51 | send_summary_mail(*self._return_mock_data()) |
314 | 50 | os.unlink("./reboot-required") | 52 | os.unlink("./reboot-required") |
316 | 51 | mail_txt = open("mail.txt").read() | 53 | with open("mail.txt") as fp: |
317 | 54 | mail_txt = fp.read() | ||
318 | 52 | self.assertTrue("[reboot required]" in mail_txt) | 55 | self.assertTrue("[reboot required]" in mail_txt) |
319 | 53 | self._verify_common_mail_content(mail_txt) | 56 | self._verify_common_mail_content(mail_txt) |
320 | 54 | 57 | ||
321 | 55 | def test_summary_mail_no_reboot(self): | 58 | def test_summary_mail_no_reboot(self): |
322 | 56 | send_summary_mail(*self._return_mock_data()) | 59 | send_summary_mail(*self._return_mock_data()) |
324 | 57 | mail_txt = open("mail.txt").read() | 60 | with open("mail.txt") as fp: |
325 | 61 | mail_txt = fp.read() | ||
326 | 58 | self.assertFalse("[reboot required]" in mail_txt) | 62 | self.assertFalse("[reboot required]" in mail_txt) |
327 | 59 | self._verify_common_mail_content(mail_txt) | 63 | self._verify_common_mail_content(mail_txt) |
328 | 60 | 64 | ||
329 | @@ -63,18 +67,21 @@ | |||
330 | 63 | # for both success and failure | 67 | # for both success and failure |
331 | 64 | apt_pkg.config.set("Unattended-Upgrade::MailOnlyOnError", "false") | 68 | apt_pkg.config.set("Unattended-Upgrade::MailOnlyOnError", "false") |
332 | 65 | send_summary_mail(*self._return_mock_data(successful=True)) | 69 | send_summary_mail(*self._return_mock_data(successful=True)) |
334 | 66 | self._verify_common_mail_content(open("mail.txt").read()) | 70 | with open("mail.txt") as fp: |
335 | 71 | self._verify_common_mail_content(fp.read()) | ||
336 | 67 | os.remove("mail.txt") | 72 | os.remove("mail.txt") |
337 | 68 | # now with a simulated failure | 73 | # now with a simulated failure |
338 | 69 | send_summary_mail(*self._return_mock_data(successful=False)) | 74 | send_summary_mail(*self._return_mock_data(successful=False)) |
340 | 70 | self._verify_common_mail_content(open("mail.txt").read()) | 75 | with open("mail.txt") as fp: |
341 | 76 | self._verify_common_mail_content(fp.read()) | ||
342 | 71 | os.remove("mail.txt") | 77 | os.remove("mail.txt") |
343 | 72 | # now test with "MailOnlyOnError" | 78 | # now test with "MailOnlyOnError" |
344 | 73 | apt_pkg.config.set("Unattended-Upgrade::MailOnlyOnError", "true") | 79 | apt_pkg.config.set("Unattended-Upgrade::MailOnlyOnError", "true") |
345 | 74 | send_summary_mail(*self._return_mock_data(successful=True)) | 80 | send_summary_mail(*self._return_mock_data(successful=True)) |
346 | 75 | self.assertFalse(os.path.exists("mail.txt")) | 81 | self.assertFalse(os.path.exists("mail.txt")) |
347 | 76 | send_summary_mail(*self._return_mock_data(successful=False)) | 82 | send_summary_mail(*self._return_mock_data(successful=False)) |
349 | 77 | mail_txt = open("mail.txt").read() | 83 | with open("mail.txt") as fp: |
350 | 84 | mail_txt = fp.read() | ||
351 | 78 | self._verify_common_mail_content(mail_txt) | 85 | self._verify_common_mail_content(mail_txt) |
352 | 79 | self.assertTrue("Unattended upgrade returned: False" in mail_txt) | 86 | self.assertTrue("Unattended upgrade returned: False" in mail_txt) |
353 | 80 | self.assertTrue(os.path.exists("mail.txt")) | 87 | self.assertTrue(os.path.exists("mail.txt")) |
354 | 81 | 88 | ||
355 | === modified file 'test/test_minimal_partitions.py' | |||
356 | --- test/test_minimal_partitions.py 2011-11-18 10:46:15 +0000 | |||
357 | +++ test/test_minimal_partitions.py 2012-06-25 20:04:38 +0000 | |||
358 | @@ -1,12 +1,9 @@ | |||
360 | 1 | #!/usr/bin/python | 1 | #!/usr/bin/python3 |
361 | 2 | 2 | ||
362 | 3 | import apt | 3 | import apt |
363 | 4 | import apt_pkg | 4 | import apt_pkg |
364 | 5 | import os | 5 | import os |
365 | 6 | import logging | ||
366 | 7 | import unittest | 6 | import unittest |
367 | 8 | import sys | ||
368 | 9 | import time | ||
369 | 10 | 7 | ||
370 | 11 | import unattended_upgrade | 8 | import unattended_upgrade |
371 | 12 | 9 | ||
372 | @@ -18,7 +15,7 @@ | |||
373 | 18 | 15 | ||
374 | 19 | # overwrite to log the data | 16 | # overwrite to log the data |
375 | 20 | def status_change(self, pkg, percent, status): | 17 | def status_change(self, pkg, percent, status): |
377 | 21 | print pkg, percent | 18 | print(pkg, percent) |
378 | 22 | self.DATA.append([pkg, percent]) | 19 | self.DATA.append([pkg, percent]) |
379 | 23 | 20 | ||
380 | 24 | class TestMinimalPartitions(unittest.TestCase): | 21 | class TestMinimalPartitions(unittest.TestCase): |
381 | 25 | 22 | ||
382 | === modified file 'test/test_origin_pattern.py' | |||
383 | --- test/test_origin_pattern.py 2011-11-22 12:54:47 +0000 | |||
384 | +++ test/test_origin_pattern.py 2012-06-25 20:04:38 +0000 | |||
385 | @@ -1,4 +1,4 @@ | |||
387 | 1 | #!/usr/bin/python | 1 | #!/usr/bin/python3 |
388 | 2 | 2 | ||
389 | 3 | import apt | 3 | import apt |
390 | 4 | import apt_pkg | 4 | import apt_pkg |
391 | 5 | 5 | ||
392 | === modified file 'test/test_substitute.py' | |||
393 | --- test/test_substitute.py 2011-02-04 11:05:12 +0000 | |||
394 | +++ test/test_substitute.py 2012-06-25 20:04:38 +0000 | |||
395 | @@ -1,4 +1,4 @@ | |||
397 | 1 | #!/usr/bin/python | 1 | #!/usr/bin/python3 |
398 | 2 | 2 | ||
399 | 3 | import apt | 3 | import apt |
400 | 4 | import apt_pkg | 4 | import apt_pkg |
401 | @@ -7,7 +7,7 @@ | |||
402 | 7 | import unittest | 7 | import unittest |
403 | 8 | import sys | 8 | import sys |
404 | 9 | 9 | ||
406 | 10 | from StringIO import StringIO | 10 | from io import StringIO |
407 | 11 | 11 | ||
408 | 12 | import unattended_upgrade | 12 | import unattended_upgrade |
409 | 13 | from unattended_upgrade import substitute, get_allowed_origins | 13 | from unattended_upgrade import substitute, get_allowed_origins |
410 | 14 | 14 | ||
411 | === modified file 'unattended-upgrade' | |||
412 | --- unattended-upgrade 2012-05-31 07:51:04 +0000 | |||
413 | +++ unattended-upgrade 2012-06-25 20:04:38 +0000 | |||
414 | @@ -1,4 +1,4 @@ | |||
416 | 1 | #!/usr/bin/python | 1 | #!/usr/bin/python3 |
417 | 2 | # Copyright (c) 2005-2012 Canonical Ltd | 2 | # Copyright (c) 2005-2012 Canonical Ltd |
418 | 3 | # | 3 | # |
419 | 4 | # AUTHOR: | 4 | # AUTHOR: |
420 | @@ -20,11 +20,10 @@ | |||
421 | 20 | # along with unattended-upgrades; if not, write to the Free Software | 20 | # along with unattended-upgrades; if not, write to the Free Software |
422 | 21 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 21 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
423 | 22 | # | 22 | # |
424 | 23 | |||
425 | 24 | import apt_inst | 23 | import apt_inst |
426 | 25 | import apt_pkg | 24 | import apt_pkg |
427 | 26 | 25 | ||
429 | 27 | import ConfigParser | 26 | import configparser |
430 | 28 | import copy | 27 | import copy |
431 | 29 | import datetime | 28 | import datetime |
432 | 30 | import fcntl | 29 | import fcntl |
433 | @@ -33,7 +32,7 @@ | |||
434 | 33 | import string | 32 | import string |
435 | 34 | import sys | 33 | import sys |
436 | 35 | 34 | ||
438 | 36 | from StringIO import StringIO | 35 | from io import StringIO |
439 | 37 | from optparse import OptionParser | 36 | from optparse import OptionParser |
440 | 38 | from subprocess import Popen, PIPE | 37 | from subprocess import Popen, PIPE |
441 | 39 | 38 | ||
442 | @@ -112,9 +111,8 @@ | |||
443 | 112 | LOG = PROGRESS_LOG | 111 | LOG = PROGRESS_LOG |
444 | 113 | 112 | ||
445 | 114 | def status_change(self, pkg, percent, status): | 113 | def status_change(self, pkg, percent, status): |
449 | 115 | f=open(self.LOG, "w") | 114 | with open(self.LOG, "w") as f: |
450 | 116 | f.write(_("Progress: %s %% (%s)") % (percent, pkg)) | 115 | f.write(_("Progress: %s %% (%s)") % (percent, pkg)) |
448 | 117 | f.close() | ||
451 | 118 | 116 | ||
452 | 119 | def _fixup_fds(self): | 117 | def _fixup_fds(self): |
453 | 120 | required_fds = [ 0, 1, 2, # stdin, stdout, stderr | 118 | required_fds = [ 0, 1, 2, # stdin, stdout, stderr |
454 | @@ -135,19 +133,19 @@ | |||
455 | 135 | try: | 133 | try: |
456 | 136 | fd = int(fdname) | 134 | fd = int(fdname) |
457 | 137 | except Exception as e: | 135 | except Exception as e: |
459 | 138 | print "ERROR: can not get fd for '%s'" % fdname | 136 | print("ERROR: can not get fd for '%s'" % fdname) |
460 | 139 | if fd in required_fds: | 137 | if fd in required_fds: |
461 | 140 | continue | 138 | continue |
462 | 141 | try: | 139 | try: |
463 | 142 | os.close(fd) | 140 | os.close(fd) |
465 | 143 | #print "closed: ", fd | 141 | #print("closed: ", fd) |
466 | 144 | except OSError as e: | 142 | except OSError as e: |
467 | 145 | # there will be one fd that can not be closed | 143 | # there will be one fd that can not be closed |
468 | 146 | # as its the fd from pythons internal diropen() | 144 | # as its the fd from pythons internal diropen() |
469 | 147 | # so its ok to ignore one close error | 145 | # so its ok to ignore one close error |
470 | 148 | error_count += 1 | 146 | error_count += 1 |
471 | 149 | if error_count > 1: | 147 | if error_count > 1: |
473 | 150 | print "ERROR: os.close(%s): %s" % (fd, e) | 148 | print("ERROR: os.close(%s): %s" % (fd, e)) |
474 | 151 | 149 | ||
475 | 152 | def fork(self): | 150 | def fork(self): |
476 | 153 | pid = os.fork() | 151 | pid = os.fork() |
477 | @@ -270,7 +268,7 @@ | |||
478 | 270 | try: | 268 | try: |
479 | 271 | with Unlocked(): | 269 | with Unlocked(): |
480 | 272 | res = cache.commit(install_progress=iprogress) | 270 | res = cache.commit(install_progress=iprogress) |
482 | 273 | except SystemError,e: | 271 | except SystemError as e: |
483 | 274 | error = e | 272 | error = e |
484 | 275 | if res: | 273 | if res: |
485 | 276 | logging.info(_("All upgrades installed")) | 274 | logging.info(_("All upgrades installed")) |
486 | @@ -334,7 +332,7 @@ | |||
487 | 334 | if not res: | 332 | if not res: |
488 | 335 | raise Exception("cache.commit() returned false") | 333 | raise Exception("cache.commit() returned false") |
489 | 336 | cache.open() | 334 | cache.open() |
491 | 337 | except Exception, e: | 335 | except Exception as e: |
492 | 338 | logging.error(_("Installing the upgrades failed!")) | 336 | logging.error(_("Installing the upgrades failed!")) |
493 | 339 | logging.error(_("error message: '%s'") % e) | 337 | logging.error(_("error message: '%s'") % e) |
494 | 340 | logging.error(_("dpkg returned a error! See '%s' for details") % \ | 338 | logging.error(_("dpkg returned a error! See '%s' for details") % \ |
495 | @@ -390,7 +388,7 @@ | |||
496 | 390 | control = apt_inst.DebFile(debfile).control.extractdata("control") | 388 | control = apt_inst.DebFile(debfile).control.extractdata("control") |
497 | 391 | sections = apt_pkg.TagSection(control) | 389 | sections = apt_pkg.TagSection(control) |
498 | 392 | return sections["Package"] | 390 | return sections["Package"] |
500 | 393 | except (IOError, SystemError), e: | 391 | except (IOError, SystemError) as e: |
501 | 394 | logging.error("failed to read deb file '%s' (%s)" % (debfile, e)) | 392 | logging.error("failed to read deb file '%s' (%s)" % (debfile, e)) |
502 | 395 | # dumb fallback | 393 | # dumb fallback |
503 | 396 | return debfile.split("_")[0] | 394 | return debfile.split("_")[0] |
504 | @@ -408,9 +406,9 @@ | |||
505 | 408 | conffiles = section.get("Conffiles") | 406 | conffiles = section.get("Conffiles") |
506 | 409 | # Conffiles: | 407 | # Conffiles: |
507 | 410 | # /etc/bash_completion.d/m-a c7780fab6b14d75ca54e11e992a6c11c | 408 | # /etc/bash_completion.d/m-a c7780fab6b14d75ca54e11e992a6c11c |
509 | 411 | for line in string.split(conffiles,"\n"): | 409 | for line in conffiles.splitlines(): |
510 | 412 | logging.debug("conffile line: %s", line) | 410 | logging.debug("conffile line: %s", line) |
512 | 413 | l = string.split(string.strip(line)) | 411 | l = line.strip().split() |
513 | 414 | conf_file = l[0] | 412 | conf_file = l[0] |
514 | 415 | md5 = l[1] | 413 | md5 = l[1] |
515 | 416 | if len(l) > 2: | 414 | if len(l) > 2: |
516 | @@ -428,7 +426,7 @@ | |||
517 | 428 | # does not have conffiles anymore | 426 | # does not have conffiles anymore |
518 | 429 | deb = apt_inst.DebFile(destFile) | 427 | deb = apt_inst.DebFile(destFile) |
519 | 430 | try: | 428 | try: |
521 | 431 | pkg_conffiles = deb.control.extractdata("conffiles") | 429 | pkg_conffiles = deb.control.extractdata("conffiles").decode('utf-8') |
522 | 432 | except LookupError as e: | 430 | except LookupError as e: |
523 | 433 | logging.debug("No conffiles in %s anymore? (%s)" % (destFile, e)) | 431 | logging.debug("No conffiles in %s anymore? (%s)" % (destFile, e)) |
524 | 434 | pkg_conffiles = "" | 432 | pkg_conffiles = "" |
525 | @@ -437,7 +435,8 @@ | |||
526 | 437 | logging.debug("'%s' not in package conffiles '%s'" % (conf_file, pkg_conffiles)) | 435 | logging.debug("'%s' not in package conffiles '%s'" % (conf_file, pkg_conffiles)) |
527 | 438 | continue | 436 | continue |
528 | 439 | # test against the installed file | 437 | # test against the installed file |
530 | 440 | current_md5 = apt_pkg.md5sum(open(prefix+conf_file).read()) | 438 | with open(prefix+conf_file, 'rb') as fp: |
531 | 439 | current_md5 = apt_pkg.md5sum(fp.read()) | ||
532 | 441 | logging.debug("current md5: %s" % current_md5) | 440 | logging.debug("current md5: %s" % current_md5) |
533 | 442 | # hashes are the same, no conffile prompt | 441 | # hashes are the same, no conffile prompt |
534 | 443 | if current_md5 == md5: | 442 | if current_md5 == md5: |
535 | @@ -446,9 +445,12 @@ | |||
536 | 446 | dpkg_cmd = ["dpkg-deb","--fsys-tarfile",destFile] | 445 | dpkg_cmd = ["dpkg-deb","--fsys-tarfile",destFile] |
537 | 447 | tar_cmd = ["tar","-x","-O", "-f","-", "."+conf_file] | 446 | tar_cmd = ["tar","-x","-O", "-f","-", "."+conf_file] |
538 | 448 | md5_cmd = ["md5sum"] | 447 | md5_cmd = ["md5sum"] |
542 | 449 | dpkg_p = Popen(dpkg_cmd, stdout=PIPE) | 448 | dpkg_p = Popen(dpkg_cmd, stdout=PIPE, |
543 | 450 | tar_p = Popen(tar_cmd, stdin=dpkg_p.stdout, stdout=PIPE) | 449 | universal_newlines=True) |
544 | 451 | md5_p = Popen(md5_cmd, stdin=tar_p.stdout, stdout=PIPE) | 450 | tar_p = Popen(tar_cmd, stdin=dpkg_p.stdout, stdout=PIPE, |
545 | 451 | universal_newlines=True) | ||
546 | 452 | md5_p = Popen(md5_cmd, stdin=tar_p.stdout, stdout=PIPE, | ||
547 | 453 | universal_newlines=True) | ||
548 | 452 | pkg_md5sum = md5_p.communicate()[0].split()[0] | 454 | pkg_md5sum = md5_p.communicate()[0].split()[0] |
549 | 453 | logging.debug("pkg_md5sum: %s" % pkg_md5sum) | 455 | logging.debug("pkg_md5sum: %s" % pkg_md5sum) |
550 | 454 | # the md5sum in the deb is unchanged, this will not | 456 | # the md5sum in the deb is unchanged, this will not |
551 | @@ -496,7 +498,7 @@ | |||
552 | 496 | """ deal with apt-listchanges """ | 498 | """ deal with apt-listchanges """ |
553 | 497 | if os.path.exists(conf): | 499 | if os.path.exists(conf): |
554 | 498 | # check if mail is used by apt-listchanges | 500 | # check if mail is used by apt-listchanges |
556 | 499 | cf = ConfigParser.ConfigParser() | 501 | cf = configparser.ConfigParser() |
557 | 500 | cf.read(conf) | 502 | cf.read(conf) |
558 | 501 | if cf.has_section("apt") and cf.has_option("apt", "frontend"): | 503 | if cf.has_section("apt") and cf.has_option("apt", "frontend"): |
559 | 502 | frontend = cf.get("apt","frontend") | 504 | frontend = cf.get("apt","frontend") |
560 | @@ -520,15 +522,16 @@ | |||
561 | 520 | # mails on on errors, just exit here | 522 | # mails on on errors, just exit here |
562 | 521 | if (res and | 523 | if (res and |
563 | 522 | apt_pkg.config.find_b("Unattended-Upgrade::MailOnlyOnError", False)): | 524 | apt_pkg.config.find_b("Unattended-Upgrade::MailOnlyOnError", False)): |
565 | 523 | return | 525 | return |
566 | 524 | # Check if reboot-required flag is present | 526 | # Check if reboot-required flag is present |
567 | 525 | logging.debug("Sending mail with '%s' to '%s'" % (logfile_dpkg, email)) | 527 | logging.debug("Sending mail with '%s' to '%s'" % (logfile_dpkg, email)) |
568 | 526 | if os.path.isfile(REBOOT_REQUIRED_FILE): | 528 | if os.path.isfile(REBOOT_REQUIRED_FILE): |
569 | 527 | subject = _("[reboot required] unattended-upgrades result for '%s'") % host() | 529 | subject = _("[reboot required] unattended-upgrades result for '%s'") % host() |
570 | 528 | else: | 530 | else: |
571 | 529 | subject = _("unattended-upgrades result for '%s'") % host() | 531 | subject = _("unattended-upgrades result for '%s'") % host() |
574 | 530 | mail = subprocess.Popen([MAIL_BINARY, "-s", subject, | 532 | mail = subprocess.Popen([MAIL_BINARY, "-s", subject, email], |
575 | 531 | email], stdin=subprocess.PIPE) | 533 | stdin=subprocess.PIPE, |
576 | 534 | universal_newlines=True) | ||
577 | 532 | s = _("Unattended upgrade returned: %s\n\n") % res | 535 | s = _("Unattended upgrade returned: %s\n\n") % res |
578 | 533 | if os.path.isfile(REBOOT_REQUIRED_FILE): | 536 | if os.path.isfile(REBOOT_REQUIRED_FILE): |
579 | 534 | s += _("Warning: A reboot is required to complete this upgrade.\n\n") | 537 | s += _("Warning: A reboot is required to complete this upgrade.\n\n") |
580 | @@ -542,7 +545,8 @@ | |||
581 | 542 | s += "\n" | 545 | s += "\n" |
582 | 543 | if os.path.exists(logfile_dpkg): | 546 | if os.path.exists(logfile_dpkg): |
583 | 544 | s += _("Package installation log:")+"\n" | 547 | s += _("Package installation log:")+"\n" |
585 | 545 | s += open(logfile_dpkg).read() | 548 | with open(logfile_dpkg) as fp: |
586 | 549 | s += fp.read() | ||
587 | 546 | s += "\n\n" | 550 | s += "\n\n" |
588 | 547 | s += _("Unattended-upgrades log:\n") | 551 | s += _("Unattended-upgrades log:\n") |
589 | 548 | s += mem_log.getvalue() | 552 | s += mem_log.getvalue() |
590 | @@ -569,7 +573,7 @@ | |||
591 | 569 | old_stdout = 1 | 573 | old_stdout = 1 |
592 | 570 | old_stderr = 2 | 574 | old_stderr = 2 |
593 | 571 | else: | 575 | else: |
595 | 572 | fd = os.open(logfile_dpkg, os.O_RDWR|os.O_CREAT, 0644) | 576 | fd = os.open(logfile_dpkg, os.O_RDWR|os.O_CREAT, 0o644) |
596 | 573 | old_stdout = os.dup(1) | 577 | old_stdout = os.dup(1) |
597 | 574 | old_stderr = os.dup(2) | 578 | old_stderr = os.dup(2) |
598 | 575 | os.dup2(fd,1) | 579 | os.dup2(fd,1) |
599 | @@ -580,7 +584,8 @@ | |||
600 | 580 | # COMPAT with the mispelling | 584 | # COMPAT with the mispelling |
601 | 581 | apt_pkg.config.find_b("Unattended-Upgrades::MinimalSteps", False) or | 585 | apt_pkg.config.find_b("Unattended-Upgrades::MinimalSteps", False) or |
602 | 582 | apt_pkg.config.find_b("Unattended-Upgrade::MinimalSteps", False)): | 586 | apt_pkg.config.find_b("Unattended-Upgrade::MinimalSteps", False)): |
604 | 583 | open("/var/run/unattended-upgrades.pid", "w").write("%s" % os.getpid()) | 587 | with open("/var/run/unattended-upgrades.pid", "w") as fp: |
605 | 588 | fp.write("%s" % os.getpid()) | ||
606 | 584 | # try upgrade all "pkgs" in minimal steps | 589 | # try upgrade all "pkgs" in minimal steps |
607 | 585 | pkg_install_success = upgrade_in_minimal_steps( | 590 | pkg_install_success = upgrade_in_minimal_steps( |
608 | 586 | cache, [pkg.name for pkg in pkgs_to_upgrade], logfile_dpkg) | 591 | cache, [pkg.name for pkg in pkgs_to_upgrade], logfile_dpkg) |
609 | @@ -677,7 +682,7 @@ | |||
610 | 677 | lockfd = apt_pkg.get_lock(os.path.join(admindir, "lock"), False) | 682 | lockfd = apt_pkg.get_lock(os.path.join(admindir, "lock"), False) |
611 | 678 | if lockfd > 0: | 683 | if lockfd > 0: |
612 | 679 | logging.warning(_("Unclean dpkg state detected, trying to correct")) | 684 | logging.warning(_("Unclean dpkg state detected, trying to correct")) |
614 | 680 | print _("Unclean dpkg state detected, trying to correct") | 685 | print(_("Unclean dpkg state detected, trying to correct")) |
615 | 681 | env = copy.copy(os.environ) | 686 | env = copy.copy(os.environ) |
616 | 682 | env["DEBIAN_FRONTEND"] = "noninteractive" | 687 | env["DEBIAN_FRONTEND"] = "noninteractive" |
617 | 683 | try: | 688 | try: |
618 | @@ -693,17 +698,17 @@ | |||
619 | 693 | # check and get lock | 698 | # check and get lock |
620 | 694 | try: | 699 | try: |
621 | 695 | apt_pkg.pkgsystem_lock() | 700 | apt_pkg.pkgsystem_lock() |
623 | 696 | except SystemError, e: | 701 | except SystemError as e: |
624 | 697 | logging.error(_("Lock could not be acquired (another package " | 702 | logging.error(_("Lock could not be acquired (another package " |
625 | 698 | "manager running?)")) | 703 | "manager running?)")) |
627 | 699 | print _("Cache lock can not be acquired, exiting") | 704 | print(_("Cache lock can not be acquired, exiting")) |
628 | 700 | sys.exit(1) | 705 | sys.exit(1) |
629 | 701 | 706 | ||
630 | 702 | # get a cache | 707 | # get a cache |
631 | 703 | cache = UnattendedUpgradesCache(rootdir=rootdir, | 708 | cache = UnattendedUpgradesCache(rootdir=rootdir, |
632 | 704 | allowed_origins=allowed_origins) | 709 | allowed_origins=allowed_origins) |
633 | 705 | if cache._depcache.broken_count > 0: | 710 | if cache._depcache.broken_count > 0: |
635 | 706 | print _("Cache has broken packages, exiting") | 711 | print(_("Cache has broken packages, exiting")) |
636 | 707 | logging.error(_("Cache has broken packages, exiting")) | 712 | logging.error(_("Cache has broken packages, exiting")) |
637 | 708 | sys.exit(1) | 713 | sys.exit(1) |
638 | 709 | # speed things up with latest apt | 714 | # speed things up with latest apt |
639 | @@ -739,7 +744,7 @@ | |||
640 | 739 | logging.debug("sanity check failed") | 744 | logging.debug("sanity check failed") |
641 | 740 | rewind_cache(cache, pkgs_to_upgrade) | 745 | rewind_cache(cache, pkgs_to_upgrade) |
642 | 741 | pkgs_kept_back.append(pkg.name) | 746 | pkgs_kept_back.append(pkg.name) |
644 | 742 | except SystemError, e: | 747 | except SystemError as e: |
645 | 743 | # can't upgrade | 748 | # can't upgrade |
646 | 744 | logging.warning(_("package '%s' upgradable but fails to be marked for upgrade (%s)") % (pkg.name, e)) | 749 | logging.warning(_("package '%s' upgradable but fails to be marked for upgrade (%s)") % (pkg.name, e)) |
647 | 745 | rewind_cache(cache, pkgs_to_upgrade) | 750 | rewind_cache(cache, pkgs_to_upgrade) |
648 | @@ -761,7 +766,7 @@ | |||
649 | 761 | pm = apt_pkg.PackageManager(cache._depcache) | 766 | pm = apt_pkg.PackageManager(cache._depcache) |
650 | 762 | try: | 767 | try: |
651 | 763 | pm.get_archives(fetcher,list,recs) | 768 | pm.get_archives(fetcher,list,recs) |
653 | 764 | except SystemError, e: | 769 | except SystemError as e: |
654 | 765 | logging.error(_("GetArchives() failed: '%s'") % e) | 770 | logging.error(_("GetArchives() failed: '%s'") % e) |
655 | 766 | res = fetcher.run() | 771 | res = fetcher.run() |
656 | 767 | 772 | ||
657 | @@ -771,14 +776,14 @@ | |||
658 | 771 | for item in fetcher.items: | 776 | for item in fetcher.items: |
659 | 772 | logging.debug("%s" % item) | 777 | logging.debug("%s" % item) |
660 | 773 | if item.status == item.STAT_ERROR: | 778 | if item.status == item.STAT_ERROR: |
662 | 774 | print _("An error ocured: '%s'") % item.error_text | 779 | print(_("An error ocured: '%s'") % item.error_text) |
663 | 775 | logging.error(_("An error ocured: '%s'") % item.error_text) | 780 | logging.error(_("An error ocured: '%s'") % item.error_text) |
664 | 776 | if not item.complete: | 781 | if not item.complete: |
666 | 777 | print _("The URI '%s' failed to download, aborting") % item.desc_uri | 782 | print(_("The URI '%s' failed to download, aborting") % item.desc_uri) |
667 | 778 | logging.error(_("The URI '%s' failed to download, aborting") % item.desc_uri) | 783 | logging.error(_("The URI '%s' failed to download, aborting") % item.desc_uri) |
668 | 779 | sys.exit(1) | 784 | sys.exit(1) |
669 | 780 | if not os.path.exists(item.destfile): | 785 | if not os.path.exists(item.destfile): |
671 | 781 | print _("Download finished, but file '%s' not there?!?" % item.destfile) | 786 | print(_("Download finished, but file '%s' not there?!?" % item.destfile)) |
672 | 782 | logging.error("Download finished, but file '%s' not there?!?" % item.destfile) | 787 | logging.error("Download finished, but file '%s' not there?!?" % item.destfile) |
673 | 783 | sys.exit(1) | 788 | sys.exit(1) |
674 | 784 | if not item.is_trusted: | 789 | if not item.is_trusted: |
675 | @@ -792,7 +797,7 @@ | |||
676 | 792 | # the cron mail (only if no summary mail is requested) | 797 | # the cron mail (only if no summary mail is requested) |
677 | 793 | email = apt_pkg.config.find("Unattended-Upgrade::Mail", "") | 798 | email = apt_pkg.config.find("Unattended-Upgrade::Mail", "") |
678 | 794 | if not email: | 799 | if not email: |
680 | 795 | print _("Package '%s' has conffile prompt and needs to be upgraded manually") % pkgname_from_deb(item.destfile) | 800 | print(_("Package '%s' has conffile prompt and needs to be upgraded manually") % pkgname_from_deb(item.destfile)) |
681 | 796 | # log to the logfile | 801 | # log to the logfile |
682 | 797 | logging.warning(_("Package '%s' has conffile prompt and needs to be upgraded manually") % pkgname_from_deb(item.destfile)) | 802 | logging.warning(_("Package '%s' has conffile prompt and needs to be upgraded manually") % pkgname_from_deb(item.destfile)) |
683 | 798 | blacklisted_pkgs.append(pkgname_from_deb(item.destfile)) | 803 | blacklisted_pkgs.append(pkgname_from_deb(item.destfile)) |
684 | @@ -907,7 +912,7 @@ | |||
685 | 907 | (options, args) = parser.parse_args() | 912 | (options, args) = parser.parse_args() |
686 | 908 | 913 | ||
687 | 909 | if os.getuid() != 0: | 914 | if os.getuid() != 0: |
689 | 910 | print _("You need to be root to run this application") | 915 | print(_("You need to be root to run this application")) |
690 | 911 | sys.exit(1) | 916 | sys.exit(1) |
691 | 912 | 917 | ||
692 | 913 | # nice & ionce | 918 | # nice & ionce |
693 | 914 | 919 | ||
694 | === modified file 'unattended-upgrade-shutdown' | |||
695 | --- unattended-upgrade-shutdown 2012-04-26 11:40:46 +0000 | |||
696 | +++ unattended-upgrade-shutdown 2012-06-25 20:04:38 +0000 | |||
697 | @@ -1,4 +1,4 @@ | |||
699 | 1 | #!/usr/bin/python | 1 | #!/usr/bin/python3 |
700 | 2 | # Copyright (c) 2009 Canonical Ltd | 2 | # Copyright (c) 2009 Canonical Ltd |
701 | 3 | # | 3 | # |
702 | 4 | # AUTHOR: | 4 | # AUTHOR: |
703 | @@ -141,8 +141,8 @@ | |||
704 | 141 | os.kill(pid, signal.SIGUSR1) | 141 | os.kill(pid, signal.SIGUSR1) |
705 | 142 | # show log | 142 | # show log |
706 | 143 | log_progress() | 143 | log_progress() |
709 | 144 | time.sleep(5) | 144 | time.sleep(5) |
710 | 145 | if (time.time() - start_time) > options.delay*60: | 145 | if (time.time() - start_time) > options.delay*60: |
711 | 146 | logging.warning(_("Giving up on lockfile after %s delay") % options.delay) | 146 | logging.warning(_("Giving up on lockfile after %s delay") % options.delay) |
712 | 147 | sys.exit(1) | 147 | sys.exit(1) |
713 | 148 | 148 |
I've just noticed that test_in_chroot.py isn't run with the other tests. It appears to fail on Python 2. How much attention should I pay to it?