Merge lp:~gocept/landscape-client/python3 into lp:~landscape/landscape-client/trunk
- python3
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Данило Шеган |
Approved revision: | 974 |
Merged at revision: | 941 |
Proposed branch: | lp:~gocept/landscape-client/python3 |
Merge into: | lp:~landscape/landscape-client/trunk |
Diff against target: |
4348 lines (+897/-643) 97 files modified
.bzrignore (+1/-0) Makefile (+16/-4) debian/control (+1/-0) display_py2_testresults (+13/-0) landscape/broker/amp.py (+4/-3) landscape/broker/ping.py (+2/-2) landscape/broker/store.py (+7/-5) landscape/broker/tests/test_ping.py (+2/-2) landscape/broker/tests/test_transport.py (+1/-1) landscape/broker/transport.py (+3/-1) landscape/compat.py (+62/-0) landscape/configuration.py (+5/-5) landscape/deployment.py (+5/-3) landscape/diff.py (+2/-2) landscape/lib/amp.py (+20/-19) landscape/lib/bpickle.py (+0/-1) landscape/lib/bpickle3.py (+171/-0) landscape/lib/cloud.py (+4/-1) landscape/lib/disk.py (+10/-5) landscape/lib/encoding.py (+2/-1) landscape/lib/fetch.py (+8/-6) landscape/lib/gpg.py (+2/-1) landscape/lib/hashlib.py (+0/-1) landscape/lib/md5crypt.py (+0/-159) landscape/lib/network.py (+2/-0) landscape/lib/persist.py (+4/-4) landscape/lib/scriptcontent.py (+2/-2) landscape/lib/sequenceranges.py (+1/-0) landscape/lib/sysstats.py (+2/-1) landscape/lib/tests/test_amp.py (+7/-0) landscape/lib/tests/test_bootstrap.py (+6/-6) landscape/lib/tests/test_bpickle.py (+1/-1) landscape/lib/tests/test_disk.py (+6/-3) landscape/lib/tests/test_fetch.py (+4/-3) landscape/lib/tests/test_gpg.py (+2/-2) landscape/lib/tests/test_network.py (+2/-3) landscape/lib/tests/test_process.py (+3/-2) landscape/lib/tests/test_sysstats.py (+1/-1) landscape/lib/tests/test_twisted_util.py (+21/-10) landscape/lib/twisted_util.py (+5/-4) landscape/manager/aptsources.py (+3/-4) landscape/manager/customgraph.py (+9/-7) landscape/manager/keystonetoken.py (+1/-1) landscape/manager/plugin.py (+2/-1) landscape/manager/scriptexecution.py (+17/-13) landscape/manager/tests/test_aptsources.py (+19/-13) landscape/manager/tests/test_customgraph.py (+10/-25) landscape/manager/tests/test_packagemanager.py (+7/-7) landscape/manager/tests/test_scriptexecution.py (+18/-3) landscape/manager/usermanager.py (+1/-1) landscape/monitor/activeprocessinfo.py (+5/-3) landscape/monitor/aptpreferences.py (+3/-1) landscape/monitor/cephusage.py (+1/-0) landscape/monitor/computeruptime.py (+17/-15) landscape/monitor/mountinfo.py (+3/-2) landscape/monitor/rebootrequired.py (+1/-1) landscape/monitor/tests/test_aptpreferences.py (+2/-0) landscape/monitor/tests/test_cephusage.py (+1/-1) landscape/monitor/tests/test_mountinfo.py (+50/-58) landscape/monitor/tests/test_packagemonitor.py (+5/-5) landscape/monitor/updatemanager.py (+2/-2) landscape/package/changer.py (+2/-2) landscape/package/facade.py (+8/-5) landscape/package/releaseupgrader.py (+4/-3) landscape/package/reporter.py (+9/-5) landscape/package/skeleton.py (+3/-1) landscape/package/store.py (+16/-11) landscape/package/taskhandler.py (+3/-3) landscape/package/tests/helpers.py (+3/-3) landscape/package/tests/test_facade.py (+2/-0) landscape/package/tests/test_releaseupgrader.py (+17/-9) landscape/package/tests/test_reporter.py (+22/-12) landscape/package/tests/test_skeleton.py (+2/-0) landscape/package/tests/test_store.py (+2/-2) landscape/package/tests/test_taskhandler.py (+3/-3) landscape/reactor.py (+3/-3) landscape/schema.py (+6/-5) landscape/sysinfo/deployment.py (+3/-3) landscape/sysinfo/tests/test_disk.py (+5/-3) landscape/sysinfo/tests/test_sysinfo.py (+2/-2) landscape/tests/clock.py (+7/-2) landscape/tests/helpers.py (+16/-15) landscape/tests/subunit.py (+3/-2) landscape/tests/test_configuration.py (+17/-16) landscape/tests/test_deployment.py (+4/-4) landscape/tests/test_reactor.py (+5/-2) landscape/tests/test_schema.py (+6/-2) landscape/tests/test_sysvconfig.py (+6/-2) landscape/tests/test_watchdog.py (+23/-19) landscape/user/changes.py (+8/-6) landscape/user/management.py (+2/-4) landscape/user/provider.py (+35/-28) landscape/user/tests/helpers.py (+5/-3) landscape/user/tests/test_management.py (+2/-2) landscape/user/tests/test_provider.py (+28/-17) landscape/watchdog.py (+17/-17) trial5 (+11/-0) |
To merge this branch: | bzr merge lp:~gocept/landscape-client/python3 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Данило Шеган (community) | Approve | ||
🤖 Landscape Builder | test results | Approve | |
Free Ekanayaka (community) | Approve | ||
Adam Collard (community) | Abstain | ||
Steffen Allner (community) | Approve | ||
Daniel Havlik (community) | Approve | ||
Review via email: mp+315096@code.launchpad.net |
Commit message
* Changed a lot of files to be python 3.5 syntax compatible
* Introduced landscape.compat containing some helpers
* Used twisted.
* Almost all tests run with python 3.5 (2163 of 2178 - run them with make check3)
* Everything should still work with python 2 as before.
Description of the change
* Changed a lot of files to be python 3.5 syntax compatible
* Introduced landscape.compat containing some helpers
* Used twisted.
* Almost all tests run with python 3.5 (2163 of 2178 - run them with make check3)
* Everything should still work with python 2 as before.
🤖 Landscape Builder (landscape-builder) : | # |
🤖 Landscape Builder (landscape-builder) wrote : | # |
🤖 Landscape Builder (landscape-builder) : | # |
🤖 Landscape Builder (landscape-builder) : | # |
🤖 Landscape Builder (landscape-builder) : | # |
🤖 Landscape Builder (landscape-builder) wrote : | # |
Command: TRIAL_ARGS=-j4 make check
Result: Fail
Revno: 953
Branch: lp:~nilo/landscape-client/python3
Jenkins: https:/
Adam Collard (adam-collard) wrote : | # |
The failure messages from that Jenkins run are: http://
Adam Collard (adam-collard) wrote : | # |
Looking pretty good! Have added some initial comments inline.
- 954. By Daniel Havlik
-
use passlib provided salt generation (as passlib limits the characters for salt to ./a-zA-Z0-9)
🤖 Landscape Builder (landscape-builder) : | # |
🤖 Landscape Builder (landscape-builder) wrote : | # |
Command: TRIAL_ARGS=-j4 make check
Result: Success
Revno: 954
Branch: lp:~nilo/landscape-client/python3
Jenkins: https:/
Steffen Allner (sallner) wrote : | # |
I addressed the comments from r953 at https:/
Adam Collard (adam-collard) wrote : | # |
> I addressed the comments from r953 at https:/
> /landscape-
Hmm, this is arguably the Wrong Way To Do It™.
This will require Daniel to merge your branch into his. Ideally Daniel would have made these fixes and just "bzr push"'d the fixes (only Daniel has write permission to his branches).
Alternatively, you can create a team in Launchpad (e.g. ~gocept) then push the branch to that team's namespace (e.g. lp:~gocept/landscape-client/python3) and everyone in that team will have write permission. That gives you flexibility on your side on who does the work.
> Adam, did you already had a look
> at the rest of the MP?
I don't have further comments to make at this stage, but would like to take a fresh look with the fixes I suggested.
- 955. By Daniel Havlik
-
merge fixes by sallner
🤖 Landscape Builder (landscape-builder) : | # |
🤖 Landscape Builder (landscape-builder) wrote : | # |
Command: TRIAL_ARGS=-j4 make check
Result: Success
Revno: 955
Branch: lp:~nilo/landscape-client/python3
Jenkins: https:/
Daniel Havlik (nilo) : | # |
🤖 Landscape Builder (landscape-builder) : | # |
🤖 Landscape Builder (landscape-builder) wrote : | # |
Command: TRIAL_ARGS=-j4 make check
Result: Success
Revno: 955
Branch: lp:~nilo/landscape-client/python3
Jenkins: https:/
Adam Collard (adam-collard) wrote : | # |
Sorry this took so long to review. Please see inline comments about bpickle (and a couple of nit-picks)
- 956. By Daniel Havlik
-
remove dead code
- 957. By Daniel Havlik
-
revert compatibility changes on bpickle, use "new" bpickle3 instead / add compat import for cpickle
- 958. By Daniel Havlik
-
backmerge from trunk
🤖 Landscape Builder (landscape-builder) : | # |
🤖 Landscape Builder (landscape-builder) wrote : | # |
Command: TRIAL_ARGS=-j4 make check
Result: Success
Revno: 958
Branch: lp:~nilo/landscape-client/python3
Jenkins: https:/
Steffen Allner (sallner) wrote : | # |
Adam, we have addressed your comments and also merged the master into this branch. It would be good to have this branch merged into master, as it would be easier to directly depend on the master instead of this branch for further development.
Adam Collard (adam-collard) : | # |
🤖 Landscape Builder (landscape-builder) : | # |
🤖 Landscape Builder (landscape-builder) wrote : | # |
Command: TRIAL_ARGS=-j4 make check
Result: Success
Revno: 958
Branch: lp:~nilo/landscape-client/python3
Jenkins: https:/
Free Ekanayaka (free.ekanayaka) wrote : | # |
This branch looks mostly good to me.
The main concern I have is about the test skips being added. Assuming those are temporary, and will be removed in follow up branches, I'm +1 for landing. If that's not the case, please let me know.
- 959. By Daniel Havlik
-
Insert test for `long` and make them work under Python 3.
Steffen Allner (sallner) wrote : | # |
> This branch looks mostly good to me.
>
> The main concern I have is about the test skips being added. Assuming those
> are temporary, and will be removed in follow up branches, I'm +1 for landing.
> If that's not the case, please let me know.
The tests have been only skipped to allow a run of the testsuite in a reasonable time, as some got stuck or had a long timeout. I could already activate some in the MP to `landscape.lib.amp` https:/
Данило Шеган (danilo) wrote : | # |
I have to step out for a bit again: here're the comments so far (some are nitpicking trivials, sorry).
Please reply inline using the "reply" link next to each of my comments: that makes it so much easier to understand what you've done to address a comment.
I'll continue with this branch later.
Steffen Allner (sallner) wrote : | # |
Oh, mea culpa. I just realised how to save inline comments. So here are the now already old ones addressing Free's comments.
Данило Шеган (danilo) wrote : | # |
Not at all: that's not the most obvious part of Launchpad reviews. :-)
Here are a few more warnings: when you click on "Show diff comments" next to someone's comment, it will refresh the diff and show the revision they made the comments on. If you reply there and "save comment", those comments will still go against that older diff. If you, however, switch to a different revision, those comments will not show and might not get saved: you have to "save comment" while looking at the diff you made the comments on.
Данило Шеган (danilo) wrote : | # |
Btw, now there's the conflict in the Makefile I warned about in my last comments (click on "Show diff comments" next to my previous vote to see them again): test runner won't run until the conflict is resolved.
Данило Шеган (danilo) wrote : | # |
Ok, I've gone through the whole changeset: thanks for the great changes, and for a few lint fixes here and there (yes, I noticed :-)). A few nitpicks here, but there is one overarching theme: coerce_unicode() is a huge hammer that is rarely appropriate.
Basically, I would like you to do away with it and do exactly what's appropriate in each individual case. Some of the cases are pure bugs and changes in behaviour, some are unneeded, and others just indicate where code should have the decode moved elsewhere. In the few cases where a simple "decode_if_python2" logic _is_ appropriate, you might just as well inline the logic.
Another thing I'd like fixed is switch from FakeStatvfsResult to the real os.statvfs_result, but to speed up getting this landed, I am happy to have that done in a separate branch later.
Also, make sure to resolve conflicts.
Данило Шеган (danilo) wrote : | # |
Darn, most of my comments got lost when the branch moved from ~nilo to ~gocept. Resubmitting the rest.
(Note that you should go through my previous set of comments as well, which cover the first ~1000 lines of the diff, but some of them are now obsolete since I want you to drop coerce_unicode entirely)
Steffen Allner (sallner) wrote : | # |
I also got my comments deleted during the switch. This is the response to the very first batch. I am working on your other comments and agree with you on the removal of coerce_unicode(). It was introduced as a helper to get rid of the encoding/decoding errors and to run the tests with Python 3. But as you put so much effort into it already, we can remove it already at this point.
Данило Шеган (danilo) wrote : | # |
Thanks for addressing my comments so far. Feel free to say that
something is coming up in a follow up branch or two: you can also
highlight bits that you know are imperfect and which will be fixed
later and we can ignore them in reviews.
Also, I might sometimes misread a bit of code or diff, so if you think
I am wrong, shout! :)
I'll wait for the next round of changes to go over them next. Thanks
for bearing with me :-)
Данило Шеган (danilo) wrote : | # |
Btw, there's still a conflict in the Makefile "check" rule.
Steffen Allner (sallner) wrote : | # |
So I integrated the second batch of changes and will push it now. I should be able to have a look at the third batch today, so that maybe we can get a merge at the beginning of the week.
- 960. By Steffen Allner
-
Backmerge from trunk.
- 961. By Steffen Allner
-
Fix PEP-8 and extend output.
- 962. By Steffen Allner
-
Remove double import and improve documentation.
- 963. By Steffen Allner
-
Handle decoding explicitly here, instead of using the helper function.
- 964. By Steffen Allner
-
Restore correct docstring.
- 965. By Steffen Allner
-
Remove `landscape.
md5crypt` completely and use `passlib` instead. - 966. By Steffen Allner
-
Get rid of coerce_unicode and move encoding of script.
- 967. By Steffen Allner
-
Improve readability and PEP-8
- 968. By Steffen Allner
-
`read_file()` should do the decoding. That is coming with a future MP.
- 969. By Steffen Allner
-
Remove coerce_unicode().
- 970. By Steffen Allner
-
Formatting for readability.
- 971. By Steffen Allner
-
Remove coerce_unicode()
- 972. By Steffen Allner
-
Remove coerce_unicode() and move the decoding to the underlying function. We have to teach the makeFile() helper to write binary files for a broken encoding test.
- 973. By Steffen Allner
-
Use `os.statsvfs_
result( )` instead of the fake one and use a fixture in tests. - 974. By Steffen Allner
-
Remove coerce_unicode().
🤖 Landscape Builder (landscape-builder) : | # |
Steffen Allner (sallner) wrote : | # |
Oh, all your diff comments were shown combined, so I should be finished with it now. It is your turn again. The conflict in check should be solved with http://
🤖 Landscape Builder (landscape-builder) wrote : | # |
Command: TRIAL_ARGS=-j4 make check
Result: Success
Revno: 974
Branch: lp:~gocept/landscape-client/python3
Jenkins: https:/
Данило Шеган (danilo) wrote : | # |
(Save a few replies on the older rev, nothing to act on)
Данило Шеган (danilo) wrote : | # |
Right, all comments on a single revision will show combined: only when a code change is pushed after one set of comments they might be separate (though, it is still possible to make comments on earlier revisions, I prefer to do it on the latest one).
Anyway, this looks great now: thanks for all the extra work, and for addressing review comments in individual commits — allows me to easily see just the relevant change.
I'll get this landed now. Note that all/some dependant branches might start seeing conflicts and you'll need to re-merge trunk once this gets in.
Preview Diff
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2016-01-07 10:45:00 +0000 |
3 | +++ .bzrignore 2017-03-10 15:29:37 +0000 |
4 | @@ -23,3 +23,4 @@ |
5 | apt-update/apt-update |
6 | docs |
7 | tags |
8 | +_last_py2_res |
9 | |
10 | === modified file 'Makefile' |
11 | --- Makefile 2017-03-09 09:18:28 +0000 |
12 | +++ Makefile 2017-03-10 15:29:37 +0000 |
13 | @@ -1,8 +1,9 @@ |
14 | PYDOCTOR ?= pydoctor |
15 | -TXT2MAN ?= txt2man |
16 | +TXT2MAN ?= txt2man |
17 | PYTHON ?= python |
18 | -TRIAL_ARGS ?= |
19 | -TEST_COMMAND = trial --unclean-warnings $(TRIAL_ARGS) landscape |
20 | +TRIAL_ARGS ?= |
21 | +TEST_COMMAND_PY2 = trial --unclean-warnings $(TRIAL_ARGS) landscape |
22 | +TEST_COMMAND_PY3 = trial3 --unclean-warnings $(TRIAL_ARGS) landscape |
23 | UBUNTU_RELEASE := $(shell lsb_release -cs) |
24 | # version in the code is authoritative |
25 | # Use := here, not =, it's really important, otherwise UPSTREAM_VERSION |
26 | @@ -19,11 +20,22 @@ |
27 | |
28 | all: build |
29 | |
30 | +build3: |
31 | + python3 setup.py build_ext -i |
32 | + |
33 | build: |
34 | $(PYTHON) setup.py build_ext -i |
35 | |
36 | +check5: |
37 | + -trial --unclean-warnings --reporter=summary landscape > _last_py2_res |
38 | + -trial3 --unclean-warnings landscape |
39 | + ./display_py2_testresults |
40 | + |
41 | +check3: build3 |
42 | + LC_ALL=C $(TEST_COMMAND_PY3) |
43 | + |
44 | check: build |
45 | - LC_ALL=C $(TEST_COMMAND) |
46 | + LC_ALL=C $(TEST_COMMAND_PY2) |
47 | |
48 | lint: |
49 | bzr ls-lint |
50 | |
51 | === modified file 'debian/control' |
52 | --- debian/control 2017-01-18 09:11:59 +0000 |
53 | +++ debian/control 2017-03-10 15:29:37 +0000 |
54 | @@ -14,6 +14,7 @@ |
55 | python-twisted-core, |
56 | python-configobj, |
57 | python-apt, |
58 | + python-passlib, |
59 | ca-certificates, |
60 | python-gdbm, |
61 | lsb-release, |
62 | |
63 | === added file 'display_py2_testresults' |
64 | --- display_py2_testresults 1970-01-01 00:00:00 +0000 |
65 | +++ display_py2_testresults 2017-03-10 15:29:37 +0000 |
66 | @@ -0,0 +1,13 @@ |
67 | +#!/usr/bin/python |
68 | +with open('_last_py2_res', 'r') as py2res: |
69 | + lines = py2res.readlines() |
70 | + |
71 | +lastline = lines[-1] |
72 | + |
73 | +time, total, total, err, fail, skip = lastline.split() |
74 | + |
75 | +if "".join((err, fail, skip)) != "000": |
76 | + print("Python 2: \033[91mFAILED\033[0m (skips={}, failures={}, " |
77 | + "errors={}, total={})".format(skip, fail, err, total)) |
78 | +else: |
79 | + print("Python 2: \033[92mOK\033[0m (total={})".format(total)) |
80 | |
81 | === modified file 'landscape/broker/amp.py' |
82 | --- landscape/broker/amp.py 2015-03-04 14:22:17 +0000 |
83 | +++ landscape/broker/amp.py 2017-03-10 15:29:37 +0000 |
84 | @@ -1,4 +1,5 @@ |
85 | from twisted.internet.defer import maybeDeferred, execute, succeed |
86 | +from twisted.python.compat import iteritems |
87 | |
88 | from landscape.lib.amp import RemoteObject, MethodCallArgument |
89 | from landscape.amp import ComponentConnector, get_remote_methods |
90 | @@ -30,7 +31,7 @@ |
91 | """ |
92 | result = self.listen_events(handlers.keys()) |
93 | return result.addCallback( |
94 | - lambda (event_type, kwargs): handlers[event_type](**kwargs)) |
95 | + lambda args: handlers[args[0]](**args[1])) |
96 | |
97 | |
98 | class FakeRemoteBroker(object): |
99 | @@ -53,7 +54,7 @@ |
100 | def method(*args, **kwargs): |
101 | for arg in args: |
102 | assert MethodCallArgument.check(arg) |
103 | - for k, v in kwargs.iteritems(): |
104 | + for k, v in iteritems(kwargs): |
105 | assert MethodCallArgument.check(v) |
106 | return execute(original, *args, **kwargs) |
107 | return method |
108 | @@ -75,7 +76,7 @@ |
109 | """ |
110 | result = self.broker_server.listen_events(handlers.keys()) |
111 | return result.addCallback( |
112 | - lambda (event_type, kwargs): handlers[event_type](**kwargs)) |
113 | + lambda args: handlers[args[0]](**args[1])) |
114 | |
115 | def register(self): |
116 | return succeed(None) |
117 | |
118 | === modified file 'landscape/broker/ping.py' |
119 | --- landscape/broker/ping.py 2013-06-27 10:25:39 +0000 |
120 | +++ landscape/broker/ping.py 2017-03-10 15:29:37 +0000 |
121 | @@ -39,7 +39,7 @@ |
122 | from twisted.python.failure import Failure |
123 | from twisted.internet import defer |
124 | |
125 | -from landscape.lib.bpickle import loads |
126 | +from landscape.compat import bpickle |
127 | from landscape.lib.fetch import fetch |
128 | from landscape.lib.log import log_failure |
129 | |
130 | @@ -84,7 +84,7 @@ |
131 | the response indicates that their are messages waiting for |
132 | this computer, False otherwise. |
133 | """ |
134 | - if loads(webtext) == {"messages": True}: |
135 | + if bpickle.loads(webtext) == {"messages": True}: |
136 | return True |
137 | |
138 | |
139 | |
140 | === modified file 'landscape/broker/store.py' |
141 | --- landscape/broker/store.py 2014-12-12 13:25:39 +0000 |
142 | +++ landscape/broker/store.py 2017-03-10 15:29:37 +0000 |
143 | @@ -97,8 +97,10 @@ |
144 | import os |
145 | import uuid |
146 | |
147 | +from twisted.python.compat import iteritems |
148 | + |
149 | from landscape import DEFAULT_SERVER_API |
150 | -from landscape.lib import bpickle |
151 | +from landscape.compat import bpickle |
152 | from landscape.lib.fs import create_file |
153 | from landscape.lib.versioning import sort_versions, is_version_higher |
154 | |
155 | @@ -261,7 +263,7 @@ |
156 | data = self._get_content(self._message_dir(filename)) |
157 | try: |
158 | message = bpickle.loads(data) |
159 | - except ValueError, e: |
160 | + except ValueError as e: |
161 | logging.exception(e) |
162 | self._add_flags(filename, BROKEN) |
163 | else: |
164 | @@ -453,7 +455,7 @@ |
165 | flags = self._get_flags(old_filename) |
166 | try: |
167 | message = bpickle.loads(self._get_content(old_filename)) |
168 | - except ValueError, e: |
169 | + except ValueError as e: |
170 | logging.exception(e) |
171 | if HELD not in flags: |
172 | offset += 1 |
173 | @@ -500,7 +502,7 @@ |
174 | information, limited by scope. |
175 | """ |
176 | session_ids = self._persist.get("session-ids", {}) |
177 | - for session_id, stored_scope in session_ids.iteritems(): |
178 | + for session_id, stored_scope in iteritems(session_ids): |
179 | # This loop should be relatively short as it's intent is to limit |
180 | # session-ids to one per scope. The or condition here is not |
181 | # strictly necessary, but we *should* do "is" comparisons when we |
182 | @@ -524,7 +526,7 @@ |
183 | new_session_ids = {} |
184 | if scopes: |
185 | session_ids = self._persist.get("session-ids", {}) |
186 | - for session_id, session_scope in session_ids.iteritems(): |
187 | + for session_id, session_scope in iteritems(session_ids): |
188 | if session_scope not in scopes: |
189 | new_session_ids[session_id] = session_scope |
190 | self._persist.set("session-ids", new_session_ids) |
191 | |
192 | === modified file 'landscape/broker/tests/test_ping.py' |
193 | --- landscape/broker/tests/test_ping.py 2013-04-04 10:38:29 +0000 |
194 | +++ landscape/broker/tests/test_ping.py 2017-03-10 15:29:37 +0000 |
195 | @@ -2,7 +2,7 @@ |
196 | |
197 | from twisted.internet.defer import fail |
198 | |
199 | -from landscape.lib.bpickle import dumps |
200 | +from landscape.compat import bpickle |
201 | from landscape.lib.fetch import fetch |
202 | from landscape.reactor import FakeReactor |
203 | from landscape.broker.ping import PingClient, Pinger |
204 | @@ -25,7 +25,7 @@ |
205 | data. |
206 | """ |
207 | self.fetches.append((url, post, headers, data)) |
208 | - return dumps(self.response) |
209 | + return bpickle.dumps(self.response) |
210 | |
211 | def failing_get_page(self, url, post, headers, data): |
212 | """ |
213 | |
214 | === modified file 'landscape/broker/tests/test_transport.py' |
215 | --- landscape/broker/tests/test_transport.py 2016-03-04 08:57:40 +0000 |
216 | +++ landscape/broker/tests/test_transport.py 2017-03-10 15:29:37 +0000 |
217 | @@ -3,7 +3,7 @@ |
218 | from landscape import VERSION |
219 | from landscape.broker.transport import HTTPTransport |
220 | from landscape.lib.fetch import PyCurlError |
221 | -from landscape.lib import bpickle |
222 | +from landscape.compat import bpickle |
223 | |
224 | from landscape.tests.helpers import LandscapeTest, LogKeeperHelper |
225 | |
226 | |
227 | === modified file 'landscape/broker/transport.py' |
228 | --- landscape/broker/transport.py 2014-10-03 10:06:24 +0000 |
229 | +++ landscape/broker/transport.py 2017-03-10 15:29:37 +0000 |
230 | @@ -6,8 +6,10 @@ |
231 | |
232 | import pycurl |
233 | |
234 | +from twisted.python.compat import unicode |
235 | + |
236 | +from landscape.compat import bpickle |
237 | from landscape.lib.fetch import fetch |
238 | -from landscape.lib import bpickle |
239 | from landscape.log import format_delta |
240 | from landscape import SERVER_API, VERSION |
241 | |
242 | |
243 | === added file 'landscape/compat.py' |
244 | --- landscape/compat.py 1970-01-01 00:00:00 +0000 |
245 | +++ landscape/compat.py 2017-03-10 15:29:37 +0000 |
246 | @@ -0,0 +1,62 @@ |
247 | +from twisted.python.compat import _PY3 |
248 | + |
249 | +if _PY3: |
250 | + import _pickle as cPickle |
251 | + from landscape.lib import bpickle3 as bpickle |
252 | + from configparser import ConfigParser, NoOptionError |
253 | + SafeConfigParser = ConfigParser |
254 | + |
255 | + import _thread as thread |
256 | + |
257 | + from io import StringIO |
258 | + stringio = cstringio = StringIO |
259 | + |
260 | +else: |
261 | + import cPickle |
262 | + from landscape.lib import bpickle |
263 | + from ConfigParser import ConfigParser, NoOptionError, SafeConfigParser |
264 | + |
265 | + import thread |
266 | + |
267 | + from StringIO import StringIO |
268 | + stringio = StringIO |
269 | + from cStringIO import StringIO as cstringio |
270 | + |
271 | + |
272 | +def coerce_unicode(s, encoding='ascii', errors='strict'): |
273 | + """ |
274 | + Coerce byte strings into unicode for Python 2. |
275 | + |
276 | + In Python 2, decodes a byte string L{s} into unicode using the L{encoding}, |
277 | + returns unmodified if any other type. In Python 3, raises a L{TypeError} |
278 | + when passed a byte string in L{s}, returns unmodified otherwise. |
279 | + |
280 | + @param s: The string to be converted to unicode. |
281 | + @type s: L{bytes} or L{unicode} |
282 | + @raise UnicodeError: The input L{bytes} is not decodable |
283 | + with given encoding. |
284 | + @raise TypeError: The input is L{bytes} on Python 3. |
285 | + """ |
286 | + # In Python 2 C{unicode(b'bytes')} returns a unicode string C{'bytes'}. In |
287 | + # Python 3, the equivalent C{str(b'bytes')} will return C{"b'bytes'"} |
288 | + # instead. |
289 | + if isinstance(s, bytes): |
290 | + if _PY3: |
291 | + raise TypeError("Expected str not %r (bytes)" % (s,)) |
292 | + else: |
293 | + return s.decode(encoding, errors) |
294 | + else: |
295 | + return s |
296 | + |
297 | + |
298 | +def convert_buffer_to_string(mem_view): |
299 | + """ |
300 | + Converts a buffer in Python 2 or a memoryview in Python 3 to str. |
301 | + |
302 | + @param mem_view: The view to convert. |
303 | + """ |
304 | + if _PY3: |
305 | + result = mem_view.decode('ascii') |
306 | + else: |
307 | + result = str(mem_view) |
308 | + return result |
309 | |
310 | === modified file 'landscape/configuration.py' |
311 | --- landscape/configuration.py 2017-03-03 13:52:57 +0000 |
312 | +++ landscape/configuration.py 2017-03-10 15:29:37 +0000 |
313 | @@ -13,7 +13,7 @@ |
314 | import pwd |
315 | import sys |
316 | |
317 | -from StringIO import StringIO |
318 | +from landscape.compat import StringIO |
319 | |
320 | from landscape.lib.tag import is_valid_tag |
321 | |
322 | @@ -565,9 +565,9 @@ |
323 | def bootstrap_tree(config): |
324 | """Create the client directories tree.""" |
325 | bootstrap_list = [ |
326 | - BootstrapDirectory("$data_path", "landscape", "root", 0755), |
327 | + BootstrapDirectory("$data_path", "landscape", "root", 0o755), |
328 | BootstrapDirectory("$annotations_path", "landscape", "landscape", |
329 | - 0755)] |
330 | + 0o755)] |
331 | BootstrapList(bootstrap_list).bootstrap( |
332 | data_path=config.data_path, annotations_path=config.annotations_path) |
333 | |
334 | @@ -756,7 +756,7 @@ |
335 | config = LandscapeSetupConfiguration() |
336 | try: |
337 | config.load(args) |
338 | - except ImportOptionError, error: |
339 | + except ImportOptionError as error: |
340 | print_text(str(error), error=True) |
341 | sys.exit(1) |
342 | |
343 | @@ -775,7 +775,7 @@ |
344 | # Setup client configuration. |
345 | try: |
346 | setup(config) |
347 | - except Exception, e: |
348 | + except Exception as e: |
349 | print_text(str(e)) |
350 | sys.exit("Aborting Landscape configuration") |
351 | |
352 | |
353 | === modified file 'landscape/deployment.py' |
354 | --- landscape/deployment.py 2014-09-24 08:09:55 +0000 |
355 | +++ landscape/deployment.py 2017-03-10 15:29:37 +0000 |
356 | @@ -13,6 +13,8 @@ |
357 | |
358 | from landscape.upgraders import UPGRADE_MANAGERS |
359 | |
360 | +from twisted.python.compat import StringType as basestring |
361 | + |
362 | |
363 | def init_logging(configuration, program_name): |
364 | """Given a basic configuration, set up logging.""" |
365 | @@ -40,8 +42,8 @@ |
366 | |
367 | def add_option(self, *args, **kwargs): |
368 | option = OptionParser.add_option(self, *args, **kwargs) |
369 | - print dir(option) |
370 | - print option.get_opt_string() |
371 | + print(dir(option)) |
372 | + print(option.get_opt_string()) |
373 | return option |
374 | |
375 | |
376 | @@ -235,7 +237,7 @@ |
377 | try: |
378 | config_obj = ConfigObj(config_source, list_values=False, |
379 | raise_errors=False, write_empty_values=True) |
380 | - except ConfigObjError, e: |
381 | + except ConfigObjError as e: |
382 | logger = getLogger() |
383 | logger.warn(str(e)) |
384 | # Good configuration values are recovered here |
385 | |
386 | === modified file 'landscape/diff.py' |
387 | --- landscape/diff.py 2008-06-10 10:56:01 +0000 |
388 | +++ landscape/diff.py 2017-03-10 15:29:37 +0000 |
389 | @@ -4,8 +4,8 @@ |
390 | @return: A 3-tuple of dicts with the changes that would need to be |
391 | made to convert C{old} into C{new}: C{(creates, updates, deletes)} |
392 | """ |
393 | - new_keys = set(new.iterkeys()) |
394 | - old_keys = set(old.iterkeys()) |
395 | + new_keys = set(new) |
396 | + old_keys = set(old) |
397 | |
398 | creates = {} |
399 | for key in new_keys - old_keys: |
400 | |
401 | === modified file 'landscape/lib/amp.py' |
402 | --- landscape/lib/amp.py 2013-05-13 12:51:30 +0000 |
403 | +++ landscape/lib/amp.py 2017-03-10 15:29:37 +0000 |
404 | @@ -49,11 +49,12 @@ |
405 | from twisted.internet.defer import Deferred, maybeDeferred, succeed |
406 | from twisted.internet.protocol import ServerFactory, ReconnectingClientFactory |
407 | from twisted.python.failure import Failure |
408 | +from twisted.python.compat import xrange |
409 | |
410 | from twisted.protocols.amp import ( |
411 | Argument, String, Integer, Command, AMP, MAX_VALUE_LENGTH, CommandLocator) |
412 | |
413 | -from landscape.lib.bpickle import loads, dumps, dumps_table |
414 | +from landscape.compat import bpickle |
415 | |
416 | |
417 | class MethodCallArgument(Argument): |
418 | @@ -61,16 +62,16 @@ |
419 | |
420 | def toString(self, inObject): |
421 | """Serialize an argument.""" |
422 | - return dumps(inObject) |
423 | + return bpickle.dumps(inObject) |
424 | |
425 | def fromString(self, inString): |
426 | """Unserialize an argument.""" |
427 | - return loads(inString) |
428 | + return bpickle.loads(inString) |
429 | |
430 | @classmethod |
431 | def check(cls, inObject): |
432 | """Check if an argument is serializable.""" |
433 | - return type(inObject) in dumps_table |
434 | + return type(inObject) in bpickle.dumps_table |
435 | |
436 | |
437 | class MethodCallError(Exception): |
438 | @@ -95,13 +96,13 @@ |
439 | and C{kwargs} the keyword ones. |
440 | """ |
441 | |
442 | - arguments = [("sequence", Integer()), |
443 | - ("method", String()), |
444 | - ("arguments", String())] |
445 | - |
446 | - response = [("result", MethodCallArgument())] |
447 | - |
448 | - errors = {MethodCallError: "METHOD_CALL_ERROR"} |
449 | + arguments = [(b"sequence", Integer()), |
450 | + (b"method", String()), |
451 | + (b"arguments", String())] |
452 | + |
453 | + response = [(b"result", MethodCallArgument())] |
454 | + |
455 | + errors = {MethodCallError: b"METHOD_CALL_ERROR"} |
456 | |
457 | |
458 | class MethodCallChunk(Command): |
459 | @@ -119,12 +120,12 @@ |
460 | being split and buffered. |
461 | """ |
462 | |
463 | - arguments = [("sequence", Integer()), |
464 | - ("chunk", String())] |
465 | - |
466 | - response = [("result", Integer())] |
467 | - |
468 | - errors = {MethodCallError: "METHOD_CALL_ERROR"} |
469 | + arguments = [(b"sequence", Integer()), |
470 | + (b"chunk", String())] |
471 | + |
472 | + response = [(b"result", Integer())] |
473 | + |
474 | + errors = {MethodCallError: b"METHOD_CALL_ERROR"} |
475 | |
476 | |
477 | class MethodCallReceiver(CommandLocator): |
478 | @@ -164,7 +165,7 @@ |
479 | chunks.append(arguments) |
480 | arguments = "".join(chunks) |
481 | |
482 | - args, kwargs = loads(arguments) |
483 | + args, kwargs = bpickle.loads(arguments) |
484 | |
485 | if not method in self._methods: |
486 | raise MethodCallError("Forbidden method '%s'" % method) |
487 | @@ -260,7 +261,7 @@ |
488 | invoked on the remote object. If the remote method itself returns |
489 | a deferred, we fire with the callback value of such deferred. |
490 | """ |
491 | - arguments = dumps((args, kwargs)) |
492 | + arguments = bpickle.dumps((args, kwargs)) |
493 | sequence = uuid4().int |
494 | |
495 | # Split the given arguments in one or more chunks |
496 | |
497 | === modified file 'landscape/lib/bpickle.py' |
498 | --- landscape/lib/bpickle.py 2008-06-10 10:56:01 +0000 |
499 | +++ landscape/lib/bpickle.py 2017-03-10 15:29:37 +0000 |
500 | @@ -158,4 +158,3 @@ |
501 | "t": loads_tuple, |
502 | "d": loads_dict, |
503 | "n": loads_none }) |
504 | - |
505 | |
506 | === added file 'landscape/lib/bpickle3.py' |
507 | --- landscape/lib/bpickle3.py 1970-01-01 00:00:00 +0000 |
508 | +++ landscape/lib/bpickle3.py 2017-03-10 15:29:37 +0000 |
509 | @@ -0,0 +1,171 @@ |
510 | +"""Copyright (c) 2006, Gustavo Niemeyer <gustavo@niemeyer.net> |
511 | +Port to python 3 was done by Chris Glass <chris.glass@canonical.com> |
512 | + |
513 | +All rights reserved. |
514 | + |
515 | +Redistribution and use in source and binary forms, with or without |
516 | +modification, are permitted provided that the following conditions are met: |
517 | + |
518 | + * Redistributions of source code must retain the above copyright notice, |
519 | + this list of conditions and the following disclaimer. |
520 | + * Redistributions in binary form must reproduce the above copyright notice, |
521 | + this list of conditions and the following disclaimer in the documentation |
522 | + and/or other materials provided with the distribution. |
523 | + * Neither the name of the copyright holder nor the names of its |
524 | + contributors may be used to endorse or promote products derived from |
525 | + this software without specific prior written permission. |
526 | + |
527 | +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
528 | +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
529 | +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
530 | +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
531 | +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
532 | +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
533 | +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
534 | +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
535 | +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
536 | +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
537 | +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
538 | + |
539 | +This file is modified from the original to work with python3, but should be |
540 | +wire compatible and behave the same way (bugs notwithstanding). |
541 | +""" |
542 | + |
543 | + |
544 | +dumps_table = {} |
545 | +loads_table = {} |
546 | + |
547 | + |
548 | +def dumps(obj, _dt=dumps_table): |
549 | + try: |
550 | + return _dt[type(obj)](obj).encode("UTF-8") |
551 | + except KeyError as e: |
552 | + raise ValueError("Unsupported type: %s" % e) |
553 | + |
554 | + |
555 | +def loads(byte_string, _lt=loads_table): |
556 | + if not byte_string: |
557 | + raise ValueError("Can't load empty string") |
558 | + unicode_string = byte_string.decode() |
559 | + try: |
560 | + return _lt[unicode_string[0]](unicode_string, 0)[0] |
561 | + except KeyError as e: |
562 | + raise ValueError("Unknown type character: %s" % e) |
563 | + except IndexError: #pragma: nocover |
564 | + # NOTE: Not sure if reachable (chrisglass during py3 conversion) |
565 | + raise ValueError("Corrupted data") |
566 | + |
567 | + |
568 | +def dumps_bool(obj): |
569 | + return "b%d" % int(obj) |
570 | + |
571 | + |
572 | +def dumps_int(obj): |
573 | + return "i%s;" % obj |
574 | + |
575 | + |
576 | +def dumps_float(obj): |
577 | + return "f%r;" % obj |
578 | + |
579 | + |
580 | +def dumps_str(obj): |
581 | + return "s%s:%s" % (len(obj), obj) |
582 | + |
583 | + |
584 | +def dumps_list(obj, _dt=dumps_table): |
585 | + return "l%s;" % "".join([_dt[type(val)](val) for val in obj]) |
586 | + |
587 | + |
588 | +def dumps_tuple(obj, _dt=dumps_table): |
589 | + return "t%s;" % "".join([_dt[type(val)](val) for val in obj]) |
590 | + |
591 | + |
592 | +def dumps_dict(obj, _dt=dumps_table): |
593 | + keys = list(obj.keys()) |
594 | + keys.sort() |
595 | + res = [] |
596 | + append = res.append |
597 | + for key in keys: |
598 | + val = obj[key] |
599 | + append(_dt[type(key)](key)) |
600 | + append(_dt[type(val)](val)) |
601 | + return "d%s;" % "".join(res) |
602 | + |
603 | + |
604 | +def dumps_none(obj): |
605 | + return "n" |
606 | + |
607 | + |
608 | +def loads_bool(str, pos): |
609 | + return bool(int(str[pos+1])), pos+2 |
610 | + |
611 | + |
612 | +def loads_int(str, pos): |
613 | + endpos = str.index(";", pos) |
614 | + return int(str[pos+1:endpos]), endpos+1 |
615 | + |
616 | + |
617 | +def loads_float(str, pos): |
618 | + endpos = str.index(";", pos) |
619 | + return float(str[pos+1:endpos]), endpos+1 |
620 | + |
621 | + |
622 | +def loads_str(str, pos): |
623 | + startpos = str.index(":", pos)+1 |
624 | + endpos = startpos+int(str[pos+1:startpos-1]) |
625 | + return str[startpos:endpos], endpos |
626 | + |
627 | + |
628 | +def loads_list(str, pos, _lt=loads_table): |
629 | + pos += 1 |
630 | + res = [] |
631 | + append = res.append |
632 | + while str[pos] != ";": |
633 | + obj, pos = _lt[str[pos]](str, pos) |
634 | + append(obj) |
635 | + return res, pos+1 |
636 | + |
637 | + |
638 | +def loads_tuple(str, pos, _lt=loads_table): |
639 | + pos += 1 |
640 | + res = [] |
641 | + append = res.append |
642 | + while str[pos] != ";": |
643 | + obj, pos = _lt[str[pos]](str, pos) |
644 | + append(obj) |
645 | + return tuple(res), pos+1 |
646 | + |
647 | + |
648 | +def loads_dict(str, pos, _lt=loads_table): |
649 | + pos += 1 |
650 | + res = {} |
651 | + while str[pos] != ";": |
652 | + key, pos = _lt[str[pos]](str, pos) |
653 | + val, pos = _lt[str[pos]](str, pos) |
654 | + res[key] = val |
655 | + return res, pos+1 |
656 | + |
657 | + |
658 | +def loads_none(str, pos): |
659 | + return None, pos+1 |
660 | + |
661 | + |
662 | +dumps_table.update({ bool: dumps_bool, |
663 | + int: dumps_int, |
664 | + float: dumps_float, |
665 | + str: dumps_str, |
666 | + list: dumps_list, |
667 | + tuple: dumps_tuple, |
668 | + dict: dumps_dict, |
669 | + type(None): dumps_none }) |
670 | + |
671 | +loads_table.update({ "b": loads_bool, |
672 | + "i": loads_int, |
673 | + "f": loads_float, |
674 | + "s": loads_str, |
675 | + "u": loads_str, |
676 | + "l": loads_list, |
677 | + "t": loads_tuple, |
678 | + "d": loads_dict, |
679 | + "n": loads_none }) |
680 | + |
681 | |
682 | === modified file 'landscape/lib/cloud.py' |
683 | --- landscape/lib/cloud.py 2016-06-16 20:40:47 +0000 |
684 | +++ landscape/lib/cloud.py 2017-03-10 15:29:37 +0000 |
685 | @@ -1,5 +1,8 @@ |
686 | from landscape.lib.fetch import fetch_async |
687 | |
688 | +from landscape.compat import coerce_unicode |
689 | + |
690 | + |
691 | EC2_HOST = "169.254.169.254" |
692 | EC2_API = "http://%s/latest" % (EC2_HOST,) |
693 | MAX_LENGTH = 64 |
694 | @@ -24,7 +27,7 @@ |
695 | |
696 | def _process_result(value): |
697 | if value is not None: |
698 | - return value.decode("utf-8")[:MAX_LENGTH] |
699 | + return coerce_unicode(value, "utf-8")[:MAX_LENGTH] |
700 | |
701 | (instance_id, instance_type, ami_id) = cloud_data |
702 | return { |
703 | |
704 | === modified file 'landscape/lib/disk.py' |
705 | --- landscape/lib/disk.py 2013-05-15 16:06:14 +0000 |
706 | +++ landscape/lib/disk.py 2017-03-10 15:29:37 +0000 |
707 | @@ -1,8 +1,10 @@ |
708 | from __future__ import division |
709 | |
710 | import os |
711 | -import statvfs |
712 | import re |
713 | +import codecs |
714 | + |
715 | +from twisted.python.compat import _PY3 |
716 | |
717 | |
718 | # List of filesystem types authorized when generating disk use statistics. |
719 | @@ -32,7 +34,10 @@ |
720 | for line in open(mounts_file): |
721 | try: |
722 | device, mount_point, filesystem = line.split()[:3] |
723 | - mount_point = mount_point.decode("string-escape") |
724 | + if _PY3: |
725 | + mount_point = codecs.decode(mount_point, "unicode_escape") |
726 | + else: |
727 | + mount_point = codecs.decode(mount_point, "string_escape") |
728 | except ValueError: |
729 | continue |
730 | if (filesystems_whitelist is not None and |
731 | @@ -43,9 +48,9 @@ |
732 | stats = statvfs_(mount_point) |
733 | except OSError: |
734 | continue |
735 | - block_size = stats[statvfs.F_BSIZE] |
736 | - total_space = (stats[statvfs.F_BLOCKS] * block_size) // megabytes |
737 | - free_space = (stats[statvfs.F_BFREE] * block_size) // megabytes |
738 | + block_size = stats.f_bsize |
739 | + total_space = (stats.f_blocks * block_size) // megabytes |
740 | + free_space = (stats.f_bfree * block_size) // megabytes |
741 | yield {"device": device, "mount-point": mount_point, |
742 | "filesystem": filesystem, "total-space": total_space, |
743 | "free-space": free_space} |
744 | |
745 | === modified file 'landscape/lib/encoding.py' |
746 | --- landscape/lib/encoding.py 2013-03-19 14:58:59 +0000 |
747 | +++ landscape/lib/encoding.py 2017-03-10 15:29:37 +0000 |
748 | @@ -1,3 +1,4 @@ |
749 | +from twisted.python.compat import iteritems, unicode |
750 | |
751 | |
752 | def encode_if_needed(value): |
753 | @@ -13,6 +14,6 @@ |
754 | """ |
755 | A wrapper taking a dict and passing each of the values to encode_if_needed. |
756 | """ |
757 | - for key, value in values.iteritems(): |
758 | + for key, value in iteritems(values): |
759 | values[key] = encode_if_needed(value) |
760 | return values |
761 | |
762 | === modified file 'landscape/lib/fetch.py' |
763 | --- landscape/lib/fetch.py 2016-08-02 12:52:30 +0000 |
764 | +++ landscape/lib/fetch.py 2017-03-10 15:29:37 +0000 |
765 | @@ -2,10 +2,12 @@ |
766 | import sys |
767 | |
768 | from optparse import OptionParser |
769 | -from StringIO import StringIO |
770 | |
771 | +from twisted.internet.defer import DeferredList |
772 | from twisted.internet.threads import deferToThread |
773 | -from twisted.internet.defer import DeferredList |
774 | +from twisted.python.compat import iteritems |
775 | + |
776 | +from landscape.compat import StringIO |
777 | |
778 | |
779 | class FetchError(Exception): |
780 | @@ -84,7 +86,7 @@ |
781 | |
782 | if headers: |
783 | curl.setopt(pycurl.HTTPHEADER, |
784 | - ["%s: %s" % pair for pair in sorted(headers.iteritems())]) |
785 | + ["%s: %s" % pair for pair in sorted(iteritems(headers))]) |
786 | |
787 | if insecure: |
788 | curl.setopt(pycurl.SSL_VERIFYPEER, False) |
789 | @@ -109,7 +111,7 @@ |
790 | |
791 | try: |
792 | curl.perform() |
793 | - except pycurl.error, e: |
794 | + except pycurl.error as e: |
795 | raise PyCurlError(e.args[0], e.args[1]) |
796 | |
797 | body = input.getvalue() |
798 | @@ -197,8 +199,8 @@ |
799 | parser.add_option("--data", default="") |
800 | parser.add_option("--cainfo") |
801 | options, (url,) = parser.parse_args(args) |
802 | - print fetch(url, post=options.post, data=options.data, |
803 | - cainfo=options.cainfo) |
804 | + print(fetch(url, post=options.post, data=options.data, |
805 | + cainfo=options.cainfo)) |
806 | |
807 | |
808 | if __name__ == "__main__": |
809 | |
810 | === modified file 'landscape/lib/gpg.py' |
811 | --- landscape/lib/gpg.py 2009-10-27 09:33:45 +0000 |
812 | +++ landscape/lib/gpg.py 2017-03-10 15:29:37 +0000 |
813 | @@ -22,7 +22,8 @@ |
814 | shutil.rmtree(gpg_home) |
815 | return ignored |
816 | |
817 | - def check_gpg_exit_code((out, err, code)): |
818 | + def check_gpg_exit_code(args): |
819 | + out, err, code = args |
820 | if code != 0: |
821 | raise InvalidGPGSignature("%s failed (out='%s', err='%s', " |
822 | "code='%d')" % (gpg, out, err, code)) |
823 | |
824 | === modified file 'landscape/lib/hashlib.py' |
825 | --- landscape/lib/hashlib.py 2013-01-03 07:09:48 +0000 |
826 | +++ landscape/lib/hashlib.py 2017-03-10 15:29:37 +0000 |
827 | @@ -1,6 +1,5 @@ |
828 | """Provide backward compatible access to hashlib functions.""" |
829 | |
830 | - |
831 | try: |
832 | _hashlib = __import__("hashlib") |
833 | except ImportError: |
834 | |
835 | === removed file 'landscape/lib/md5crypt.py' |
836 | --- landscape/lib/md5crypt.py 2009-08-23 07:05:22 +0000 |
837 | +++ landscape/lib/md5crypt.py 1970-01-01 00:00:00 +0000 |
838 | @@ -1,159 +0,0 @@ |
839 | -######################################################### |
840 | -# md5crypt.py |
841 | -# |
842 | -# 0423.2000 by michal wallace http://www.sabren.com/ |
843 | -# based on perl's Crypt::PasswdMD5 by Luis Munoz (lem@cantv.net) |
844 | -# based on /usr/src/libcrypt/crypt.c from FreeBSD 2.2.5-RELEASE |
845 | -# |
846 | -# MANY THANKS TO |
847 | -# |
848 | -# Carey Evans - http://home.clear.net.nz/pages/c.evans/ |
849 | -# Dennis Marti - http://users.starpower.net/marti1/ |
850 | -# |
851 | -# For the patches that got this thing working! |
852 | -# |
853 | -######################################################### |
854 | -"""md5crypt.py - Provides interoperable MD5-based crypt() function |
855 | - |
856 | -SYNOPSIS |
857 | - |
858 | - import md5crypt.py |
859 | - |
860 | - cryptedpassword = md5crypt.md5crypt(password, salt); |
861 | - |
862 | -DESCRIPTION |
863 | - |
864 | -unix_md5_crypt() provides a crypt()-compatible interface to the |
865 | -rather new MD5-based crypt() function found in modern operating systems. |
866 | -It's based on the implementation found on FreeBSD 2.2.[56]-RELEASE and |
867 | -contains the following license in it: |
868 | - |
869 | - "THE BEER-WARE LICENSE" (Revision 42): |
870 | - <phk@login.dknet.dk> wrote this file. As long as you retain this notice you |
871 | - can do whatever you want with this stuff. If we meet some day, and you think |
872 | - this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp |
873 | - |
874 | -apache_md5_crypt() provides a function compatible with Apache's |
875 | -.htpasswd files. This was contributed by Bryan Hart <bryan@eai.com>. |
876 | - |
877 | -""" |
878 | - |
879 | -MAGIC = '$1$' # Magic string |
880 | -ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" |
881 | - |
882 | -from landscape.lib.hashlib import md5 |
883 | - |
884 | -def to64 (v, n): |
885 | - ret = '' |
886 | - while (n - 1 >= 0): |
887 | - n = n - 1 |
888 | - ret = ret + ITOA64[v & 0x3f] |
889 | - v = v >> 6 |
890 | - return ret |
891 | - |
892 | - |
893 | -def apache_md5_crypt (pw, salt): |
894 | - # change the Magic string to match the one used by Apache |
895 | - return unix_md5_crypt(pw, salt, '$apr1$') |
896 | - |
897 | - |
898 | -def unix_md5_crypt(pw, salt, magic=None): |
899 | - |
900 | - if magic==None: |
901 | - magic = MAGIC |
902 | - |
903 | - # Take care of the magic string if present |
904 | - if salt[:len(magic)] == magic: |
905 | - salt = salt[len(magic):] |
906 | - |
907 | - |
908 | - # salt can have up to 8 characters: |
909 | - import string |
910 | - salt = string.split(salt, '$', 1)[0] |
911 | - salt = salt[:8] |
912 | - |
913 | - ctx = pw + magic + salt |
914 | - |
915 | - final = md5(pw + salt + pw).digest() |
916 | - |
917 | - for pl in range(len(pw),0,-16): |
918 | - if pl > 16: |
919 | - ctx = ctx + final[:16] |
920 | - else: |
921 | - ctx = ctx + final[:pl] |
922 | - |
923 | - |
924 | - # Now the 'weird' xform (??) |
925 | - |
926 | - i = len(pw) |
927 | - while i: |
928 | - if i & 1: |
929 | - ctx = ctx + chr(0) #if ($i & 1) { $ctx->add(pack("C", 0)); } |
930 | - else: |
931 | - ctx = ctx + pw[0] |
932 | - i = i >> 1 |
933 | - |
934 | - final = md5(ctx).digest() |
935 | - |
936 | - # The following is supposed to make |
937 | - # things run slower. |
938 | - |
939 | - # my question: WTF??? |
940 | - |
941 | - for i in range(1000): |
942 | - ctx1 = '' |
943 | - if i & 1: |
944 | - ctx1 = ctx1 + pw |
945 | - else: |
946 | - ctx1 = ctx1 + final[:16] |
947 | - |
948 | - if i % 3: |
949 | - ctx1 = ctx1 + salt |
950 | - |
951 | - if i % 7: |
952 | - ctx1 = ctx1 + pw |
953 | - |
954 | - if i & 1: |
955 | - ctx1 = ctx1 + final[:16] |
956 | - else: |
957 | - ctx1 = ctx1 + pw |
958 | - |
959 | - |
960 | - final = md5(ctx1).digest() |
961 | - |
962 | - |
963 | - # Final xform |
964 | - |
965 | - passwd = '' |
966 | - |
967 | - passwd = passwd + to64((int(ord(final[0])) << 16) |
968 | - |(int(ord(final[6])) << 8) |
969 | - |(int(ord(final[12]))),4) |
970 | - |
971 | - passwd = passwd + to64((int(ord(final[1])) << 16) |
972 | - |(int(ord(final[7])) << 8) |
973 | - |(int(ord(final[13]))), 4) |
974 | - |
975 | - passwd = passwd + to64((int(ord(final[2])) << 16) |
976 | - |(int(ord(final[8])) << 8) |
977 | - |(int(ord(final[14]))), 4) |
978 | - |
979 | - passwd = passwd + to64((int(ord(final[3])) << 16) |
980 | - |(int(ord(final[9])) << 8) |
981 | - |(int(ord(final[15]))), 4) |
982 | - |
983 | - passwd = passwd + to64((int(ord(final[4])) << 16) |
984 | - |(int(ord(final[10])) << 8) |
985 | - |(int(ord(final[5]))), 4) |
986 | - |
987 | - passwd = passwd + to64((int(ord(final[11]))), 2) |
988 | - |
989 | - |
990 | - return magic + salt + '$' + passwd |
991 | - |
992 | - |
993 | -## assign a wrapper function: |
994 | -md5crypt = unix_md5_crypt |
995 | - |
996 | -if __name__ == "__main__": |
997 | - print unix_md5_crypt("cat", "hat") |
998 | |
999 | === modified file 'landscape/lib/network.py' |
1000 | --- landscape/lib/network.py 2013-05-20 08:22:52 +0000 |
1001 | +++ landscape/lib/network.py 2017-03-10 15:29:37 +0000 |
1002 | @@ -8,6 +8,8 @@ |
1003 | import errno |
1004 | import logging |
1005 | |
1006 | +from twisted.python.compat import long |
1007 | + |
1008 | __all__ = ["get_active_device_info", "get_network_traffic", "is_64"] |
1009 | |
1010 | # from header /usr/include/bits/ioctls.h |
1011 | |
1012 | === modified file 'landscape/lib/persist.py' |
1013 | --- landscape/lib/persist.py 2013-11-21 08:32:12 +0000 |
1014 | +++ landscape/lib/persist.py 2017-03-10 15:29:37 +0000 |
1015 | @@ -590,7 +590,7 @@ |
1016 | class PickleBackend(Backend): |
1017 | |
1018 | def __init__(self): |
1019 | - import cPickle |
1020 | + from landscape.compat import cPickle |
1021 | self._pickle = cPickle |
1022 | |
1023 | def new(self): |
1024 | @@ -614,21 +614,21 @@ |
1025 | class BPickleBackend(Backend): |
1026 | |
1027 | def __init__(self): |
1028 | - from landscape.lib import bpickle |
1029 | + from landscape.compat import bpickle |
1030 | self._bpickle = bpickle |
1031 | |
1032 | def new(self): |
1033 | return {} |
1034 | |
1035 | def load(self, filepath): |
1036 | - file = open(filepath) |
1037 | + file = open(filepath, "r") |
1038 | try: |
1039 | return self._bpickle.loads(file.read()) |
1040 | finally: |
1041 | file.close() |
1042 | |
1043 | def save(self, filepath, map): |
1044 | - file = open(filepath, "w") |
1045 | + file = open(filepath, "wb") |
1046 | try: |
1047 | file.write(self._bpickle.dumps(map)) |
1048 | finally: |
1049 | |
1050 | === modified file 'landscape/lib/scriptcontent.py' |
1051 | --- landscape/lib/scriptcontent.py 2009-08-23 07:05:22 +0000 |
1052 | +++ landscape/lib/scriptcontent.py 2017-03-10 15:29:37 +0000 |
1053 | @@ -1,11 +1,11 @@ |
1054 | from landscape.lib.hashlib import md5 |
1055 | |
1056 | + |
1057 | def build_script(interpreter, code): |
1058 | """ |
1059 | Concatenates a interpreter and script into an executable script. |
1060 | """ |
1061 | - return "#!%s\n%s" % ((interpreter or u"").encode("utf-8"), |
1062 | - (code or u"").encode("utf-8")) |
1063 | + return u"#!{}\n{}".format(interpreter or u"", code or u"") |
1064 | |
1065 | |
1066 | def generate_script_hash(script): |
1067 | |
1068 | === modified file 'landscape/lib/sequenceranges.py' |
1069 | --- landscape/lib/sequenceranges.py 2013-09-12 13:14:20 +0000 |
1070 | +++ landscape/lib/sequenceranges.py 2017-03-10 15:29:37 +0000 |
1071 | @@ -1,3 +1,4 @@ |
1072 | +from twisted.python.compat import xrange |
1073 | |
1074 | |
1075 | class SequenceError(Exception): |
1076 | |
1077 | === modified file 'landscape/lib/sysstats.py' |
1078 | --- landscape/lib/sysstats.py 2012-12-27 20:10:05 +0000 |
1079 | +++ landscape/lib/sysstats.py 2017-03-10 15:29:37 +0000 |
1080 | @@ -57,7 +57,8 @@ |
1081 | def get_logged_in_users(): |
1082 | result = getProcessOutputAndValue("who", ["-q"], env=os.environ) |
1083 | |
1084 | - def parse_output((stdout_data, stderr_data, status)): |
1085 | + def parse_output(args): |
1086 | + stdout_data, stderr_data, status = args |
1087 | if status != 0: |
1088 | raise CommandError(stderr_data) |
1089 | first_line = stdout_data.split("\n", 1)[0] |
1090 | |
1091 | === modified file 'landscape/lib/tests/test_amp.py' |
1092 | --- landscape/lib/tests/test_amp.py 2016-05-25 19:52:32 +0000 |
1093 | +++ landscape/lib/tests/test_amp.py 2017-03-10 15:29:37 +0000 |
1094 | @@ -10,6 +10,9 @@ |
1095 | MethodCallSender) |
1096 | from landscape.tests.helpers import LandscapeTest |
1097 | |
1098 | +from unittest import skipIf |
1099 | +from twisted.python.compat import _PY3 |
1100 | + |
1101 | |
1102 | class FakeTransport(object): |
1103 | """Accumulate written data into a list.""" |
1104 | @@ -619,6 +622,7 @@ |
1105 | self.client.stopTrying() |
1106 | connector.disconnect() |
1107 | |
1108 | + @skipIf(_PY3, 'Takes long with Python3, probably unclean Reactor') |
1109 | @inlineCallbacks |
1110 | def test_retry(self): |
1111 | """ |
1112 | @@ -640,6 +644,7 @@ |
1113 | self.client.stopTrying() |
1114 | connector.disconnect() |
1115 | |
1116 | + @skipIf(_PY3, 'Takes long with Python3, probably unclean Reactor') |
1117 | @inlineCallbacks |
1118 | def test_retry_with_method_call_error(self): |
1119 | """ |
1120 | @@ -661,6 +666,7 @@ |
1121 | self.client.stopTrying() |
1122 | connector.disconnect() |
1123 | |
1124 | + @skipIf(_PY3, 'Takes long with Python3, probably unclean Reactor') |
1125 | @inlineCallbacks |
1126 | def test_wb_retry_with_while_still_disconnected(self): |
1127 | """ |
1128 | @@ -704,6 +710,7 @@ |
1129 | self.client.stopTrying() |
1130 | connector.disconnect() |
1131 | |
1132 | + @skipIf(_PY3, 'Takes long with Python3, probably unclean Reactor') |
1133 | @inlineCallbacks |
1134 | def test_retry_with_many_method_calls(self): |
1135 | """ |
1136 | |
1137 | === modified file 'landscape/lib/tests/test_bootstrap.py' |
1138 | --- landscape/lib/tests/test_bootstrap.py 2016-06-15 17:49:11 +0000 |
1139 | +++ landscape/lib/tests/test_bootstrap.py 2017-03-10 15:29:37 +0000 |
1140 | @@ -52,10 +52,10 @@ |
1141 | |
1142 | @patch("os.chmod") |
1143 | def test_mode(self, chmod): |
1144 | - file = self.bootstrap_class(self.path, mode=0644) |
1145 | + file = self.bootstrap_class(self.path, mode=0o644) |
1146 | file.bootstrap(my_var="my_var_value") |
1147 | |
1148 | - chmod.assert_called_with(self.real_path, 0644) |
1149 | + chmod.assert_called_with(self.real_path, 0o644) |
1150 | |
1151 | @patch("os.chmod") |
1152 | @patch("os.chown") |
1153 | @@ -71,25 +71,25 @@ |
1154 | getgrnam.return_value = Mock() |
1155 | getgrnam.return_value.gr_gid = 5678 |
1156 | |
1157 | - file = self.bootstrap_class(self.path, "username", "group", 0644) |
1158 | + file = self.bootstrap_class(self.path, "username", "group", 0o644) |
1159 | file.bootstrap(my_var="my_var_value") |
1160 | |
1161 | getuid.assert_called_with() |
1162 | getpwnam.assert_called_with("username") |
1163 | getgrnam.assert_called_with("group") |
1164 | chown.assert_called_with(self.real_path, 1234, 5678) |
1165 | - chmod.assert_called_with(self.real_path, 0644) |
1166 | + chmod.assert_called_with(self.real_path, 0o644) |
1167 | |
1168 | @patch("os.chmod") |
1169 | @patch("os.getuid") |
1170 | def test_all_details_with_non_root(self, getuid, chmod): |
1171 | getuid.return_value = 1000 |
1172 | |
1173 | - file = self.bootstrap_class(self.path, "username", "group", 0644) |
1174 | + file = self.bootstrap_class(self.path, "username", "group", 0o644) |
1175 | file.bootstrap(my_var="my_var_value") |
1176 | |
1177 | getuid.assert_called_with() |
1178 | - chmod.assert_called_with(self.real_path, 0644) |
1179 | + chmod.assert_called_with(self.real_path, 0o644) |
1180 | |
1181 | |
1182 | class BootstrapCreationTest(BootstrapPathTest): |
1183 | |
1184 | === modified file 'landscape/lib/tests/test_bpickle.py' |
1185 | --- landscape/lib/tests/test_bpickle.py 2011-07-05 05:09:11 +0000 |
1186 | +++ landscape/lib/tests/test_bpickle.py 2017-03-10 15:29:37 +0000 |
1187 | @@ -1,6 +1,6 @@ |
1188 | import unittest |
1189 | |
1190 | -from landscape.lib import bpickle |
1191 | +from landscape.compat import bpickle |
1192 | |
1193 | |
1194 | class BPickleTest(unittest.TestCase): |
1195 | |
1196 | === modified file 'landscape/lib/tests/test_disk.py' |
1197 | --- landscape/lib/tests/test_disk.py 2016-06-15 18:21:36 +0000 |
1198 | +++ landscape/lib/tests/test_disk.py 2017-03-10 15:29:37 +0000 |
1199 | @@ -42,7 +42,8 @@ |
1200 | f.write(content) |
1201 | f.close() |
1202 | for point in points: |
1203 | - self.stat_results[point] = (4096, 0, 1000, 500, 0, 0, 0, 0, 0) |
1204 | + self.stat_results[point] = os.statvfs_result( |
1205 | + (4096, 0, 1000, 500, 0, 0, 0, 0, 0, 0)) |
1206 | |
1207 | def test_get_filesystem_for_path(self): |
1208 | self.set_mount_points(["/"]) |
1209 | @@ -51,7 +52,8 @@ |
1210 | |
1211 | def test_get_filesystem_subpath(self): |
1212 | self.set_mount_points(["/"]) |
1213 | - self.stat_results["/"] = (4096, 0, 1000, 500, 0, 0, 0, 0, 0) |
1214 | + self.stat_results["/"] = os.statvfs_result( |
1215 | + (4096, 0, 1000, 500, 0, 0, 0, 0, 0, 0)) |
1216 | info = get_filesystem_for_path("/home", self.mount_file, self.statvfs) |
1217 | self.assertEqual(info["mount-point"], "/") |
1218 | |
1219 | @@ -99,7 +101,8 @@ |
1220 | f.write(content) |
1221 | f.close() |
1222 | |
1223 | - self.stat_results["/home"] = (4096, 0, 1000, 500, 0, 0, 0, 0, 0) |
1224 | + self.stat_results["/home"] = os.statvfs_result( |
1225 | + (4096, 0, 1000, 500, 0, 0, 0, 0, 0, 0)) |
1226 | |
1227 | result = [x for x in get_mount_info(self.mount_file, self.statvfs)] |
1228 | expected = {"device": "/dev/sda1", "mount-point": "/home", |
1229 | |
1230 | === modified file 'landscape/lib/tests/test_fetch.py' |
1231 | --- landscape/lib/tests/test_fetch.py 2016-08-04 16:13:11 +0000 |
1232 | +++ landscape/lib/tests/test_fetch.py 2017-03-10 15:29:37 +0000 |
1233 | @@ -4,6 +4,7 @@ |
1234 | import pycurl |
1235 | |
1236 | from twisted.internet.defer import FirstError |
1237 | +from twisted.python.compat import itervalues, unicode |
1238 | |
1239 | from landscape.lib.fetch import ( |
1240 | fetch, fetch_async, fetch_many_async, fetch_to_files, |
1241 | @@ -214,7 +215,7 @@ |
1242 | curl = CurlStub("result", {pycurl.HTTP_CODE: 404}) |
1243 | try: |
1244 | fetch("http://example.com", curl=curl) |
1245 | - except HTTPCodeError, error: |
1246 | + except HTTPCodeError as error: |
1247 | self.assertEqual(error.http_code, 404) |
1248 | self.assertEqual(error.body, "result") |
1249 | else: |
1250 | @@ -232,7 +233,7 @@ |
1251 | curl = CurlStub(error=pycurl.error(60, "pycurl error")) |
1252 | try: |
1253 | fetch("http://example.com", curl=curl) |
1254 | - except PyCurlError, error: |
1255 | + except PyCurlError as error: |
1256 | self.assertEqual(error.error_code, 60) |
1257 | self.assertEqual(error.message, "pycurl error") |
1258 | else: |
1259 | @@ -418,7 +419,7 @@ |
1260 | result = fetch_to_files(url_results.keys(), directory, curl=curl) |
1261 | |
1262 | def check_files(ignored): |
1263 | - for result in url_results.itervalues(): |
1264 | + for result in itervalues(url_results): |
1265 | fd = open(os.path.join(directory, result)) |
1266 | self.assertEqual(fd.read(), result) |
1267 | fd.close() |
1268 | |
1269 | === modified file 'landscape/lib/tests/test_gpg.py' |
1270 | --- landscape/lib/tests/test_gpg.py 2016-05-23 13:44:24 +0000 |
1271 | +++ landscape/lib/tests/test_gpg.py 2017-03-10 15:29:37 +0000 |
1272 | @@ -19,7 +19,7 @@ |
1273 | gpg = self.makeFile("#!/bin/sh\n" |
1274 | "touch $3/trustdb.gpg\n" |
1275 | "echo -n $@ > %s\n" % gpg_options) |
1276 | - os.chmod(gpg, 0755) |
1277 | + os.chmod(gpg, 0o755) |
1278 | gpg_home = self.makeDir() |
1279 | deferred = Deferred() |
1280 | |
1281 | @@ -48,7 +48,7 @@ |
1282 | provided signature is not valid. |
1283 | """ |
1284 | gpg = self.makeFile("#!/bin/sh\necho out; echo err >&2; exit 1\n") |
1285 | - os.chmod(gpg, 0755) |
1286 | + os.chmod(gpg, 0o755) |
1287 | gpg_home = self.makeDir() |
1288 | deferred = Deferred() |
1289 | |
1290 | |
1291 | === modified file 'landscape/lib/tests/test_network.py' |
1292 | --- landscape/lib/tests/test_network.py 2016-06-15 17:38:24 +0000 |
1293 | +++ landscape/lib/tests/test_network.py 2017-03-10 15:29:37 +0000 |
1294 | @@ -2,14 +2,13 @@ |
1295 | import socket |
1296 | |
1297 | from mock import patch, ANY |
1298 | - |
1299 | -from cStringIO import StringIO |
1300 | from subprocess import Popen, PIPE |
1301 | + |
1302 | from landscape.tests.helpers import LandscapeTest |
1303 | - |
1304 | from landscape.lib.network import ( |
1305 | get_network_traffic, get_active_device_info, get_active_interfaces, |
1306 | get_fqdn, get_network_interface_speed) |
1307 | +from landscape.compat import StringIO |
1308 | |
1309 | |
1310 | class NetworkInfoTest(LandscapeTest): |
1311 | |
1312 | === modified file 'landscape/lib/tests/test_process.py' |
1313 | --- landscape/lib/tests/test_process.py 2016-06-15 17:28:14 +0000 |
1314 | +++ landscape/lib/tests/test_process.py 2017-03-10 15:29:37 +0000 |
1315 | @@ -42,7 +42,8 @@ |
1316 | |
1317 | @mock.patch("landscape.lib.process.detect_jiffies", return_value=1) |
1318 | @mock.patch("os.listdir") |
1319 | - def test_missing_process_race(self, list_dir_mock, jiffies_mock): |
1320 | + @mock.patch("landscape.monitor.computeruptime.get_uptime") |
1321 | + def test_missing_process_race(self, get_uptime_mock, list_dir_mock, jiffies_mock): |
1322 | """ |
1323 | We use os.listdir("/proc") to get the list of active processes, if a |
1324 | process ends before we attempt to read the process' information, then |
1325 | @@ -68,9 +69,9 @@ |
1326 | self.closed = True |
1327 | |
1328 | list_dir_mock.return_value = ["12345"] |
1329 | + get_uptime_mock.return_value = 1.0 |
1330 | fakefile1 = FakeFile("test-binary") |
1331 | fakefile2 = FakeFile(None) |
1332 | - |
1333 | with mock.patch("__builtin__.open", mock.mock_open()) as open_mock: |
1334 | # This means "return fakefile1, then fakefile2" |
1335 | open_mock.side_effect = [fakefile1, fakefile2] |
1336 | |
1337 | === modified file 'landscape/lib/tests/test_sysstats.py' |
1338 | --- landscape/lib/tests/test_sysstats.py 2012-12-27 20:10:05 +0000 |
1339 | +++ landscape/lib/tests/test_sysstats.py 2017-03-10 15:29:37 +0000 |
1340 | @@ -79,7 +79,7 @@ |
1341 | who.write("echo '# users=%d'\n" % len(users.split())) |
1342 | who.close() |
1343 | |
1344 | - os.chmod(self.who_path, 0770) |
1345 | + os.chmod(self.who_path, 0o770) |
1346 | |
1347 | |
1348 | class LoggedInUsersTest(FakeWhoQTest): |
1349 | |
1350 | === modified file 'landscape/lib/tests/test_twisted_util.py' |
1351 | --- landscape/lib/tests/test_twisted_util.py 2011-08-04 16:05:10 +0000 |
1352 | +++ landscape/lib/tests/test_twisted_util.py 2017-03-10 15:29:37 +0000 |
1353 | @@ -1,8 +1,11 @@ |
1354 | import os |
1355 | |
1356 | +from twisted.python.compat import _PY3 |
1357 | +from unittest import skipIf |
1358 | + |
1359 | +from landscape.lib.fs import create_file |
1360 | +from landscape.lib.twisted_util import spawn_process |
1361 | from landscape.tests.helpers import LandscapeTest |
1362 | -from landscape.lib.twisted_util import spawn_process |
1363 | -from landscape.lib.fs import create_file |
1364 | |
1365 | |
1366 | class SpawnProcessTest(LandscapeTest): |
1367 | @@ -10,7 +13,7 @@ |
1368 | def setUp(self): |
1369 | super(SpawnProcessTest, self).setUp() |
1370 | self.command = self.makeFile("#!/bin/sh\necho -n $@") |
1371 | - os.chmod(self.command, 0755) |
1372 | + os.chmod(self.command, 0o755) |
1373 | |
1374 | def test_spawn_process_return_value(self): |
1375 | """ |
1376 | @@ -18,7 +21,8 @@ |
1377 | """ |
1378 | create_file(self.command, "#!/bin/sh\nexit 2") |
1379 | |
1380 | - def callback((out, err, code)): |
1381 | + def callback(args): |
1382 | + out, err, code = args |
1383 | self.assertEqual(out, "") |
1384 | self.assertEqual(err, "") |
1385 | self.assertEqual(code, 2) |
1386 | @@ -31,7 +35,8 @@ |
1387 | """ |
1388 | The process returns the expected standard output. |
1389 | """ |
1390 | - def callback((out, err, code)): |
1391 | + def callback(args): |
1392 | + out, err, code = args |
1393 | self.assertEqual(out, "a b") |
1394 | self.assertEqual(err, "") |
1395 | self.assertEqual(code, 0) |
1396 | @@ -46,7 +51,8 @@ |
1397 | """ |
1398 | create_file(self.command, "#!/bin/sh\necho -n $@ >&2") |
1399 | |
1400 | - def callback((out, err, code)): |
1401 | + def callback(args): |
1402 | + out, err, code = args |
1403 | self.assertEqual(out, "") |
1404 | self.assertEqual(err, "a b") |
1405 | self.assertEqual(code, 0) |
1406 | @@ -68,7 +74,8 @@ |
1407 | def line_received(line): |
1408 | lines.append(line) |
1409 | |
1410 | - def callback((out, err, code)): |
1411 | + def callback(args): |
1412 | + out, err, code = args |
1413 | self.assertEqual(expected, lines) |
1414 | |
1415 | result = spawn_process(self.command, args=(param,), |
1416 | @@ -88,7 +95,8 @@ |
1417 | def line_received(line): |
1418 | lines.append(line) |
1419 | |
1420 | - def callback((out, err, code)): |
1421 | + def callback(args): |
1422 | + out, err, code = args |
1423 | self.assertEqual(expected, lines) |
1424 | |
1425 | result = spawn_process(self.command, args=(param,), |
1426 | @@ -109,7 +117,8 @@ |
1427 | def line_received(line): |
1428 | lines.append(line) |
1429 | |
1430 | - def callback((out, err, code)): |
1431 | + def callback(args): |
1432 | + out, err, code = args |
1433 | self.assertEqual(expected, lines) |
1434 | |
1435 | result = spawn_process(self.command, args=(param,), |
1436 | @@ -117,13 +126,15 @@ |
1437 | result.addCallback(callback) |
1438 | return result |
1439 | |
1440 | + @skipIf(_PY3, 'Takes long with Python3, probably unclean Reactor') |
1441 | def test_spawn_process_with_stdin(self): |
1442 | """ |
1443 | Optionally C{spawn_process} accepts a C{stdin} argument. |
1444 | """ |
1445 | create_file(self.command, "#!/bin/sh\n/bin/cat") |
1446 | |
1447 | - def callback((out, err, code)): |
1448 | + def callback(args): |
1449 | + out, err, code = args |
1450 | self.assertEqual("hello", out) |
1451 | |
1452 | result = spawn_process(self.command, stdin="hello") |
1453 | |
1454 | === modified file 'landscape/lib/twisted_util.py' |
1455 | --- landscape/lib/twisted_util.py 2013-07-19 09:12:16 +0000 |
1456 | +++ landscape/lib/twisted_util.py 2017-03-10 15:29:37 +0000 |
1457 | @@ -2,8 +2,9 @@ |
1458 | from twisted.internet.protocol import ProcessProtocol |
1459 | from twisted.internet.process import Process, ProcessReader |
1460 | from twisted.internet import reactor |
1461 | +from twisted.python.compat import itervalues |
1462 | |
1463 | -import cStringIO |
1464 | +from landscape.compat import StringIO |
1465 | |
1466 | |
1467 | def gather_results(deferreds, consume_errors=False): |
1468 | @@ -19,8 +20,8 @@ |
1469 | |
1470 | def __init__(self, deferred, stdin=None, line_received=None): |
1471 | self.deferred = deferred |
1472 | - self.outBuf = cStringIO.StringIO() |
1473 | - self.errBuf = cStringIO.StringIO() |
1474 | + self.outBuf = StringIO() |
1475 | + self.errBuf = StringIO() |
1476 | self.errReceived = self.errBuf.write |
1477 | self.stdin = stdin |
1478 | self.line_received = line_received |
1479 | @@ -103,7 +104,7 @@ |
1480 | be used in place of this workaround. |
1481 | """ |
1482 | if process.pipes and not process.pid: |
1483 | - for pipe in process.pipes.itervalues(): |
1484 | + for pipe in itervalues(process.pipes): |
1485 | if isinstance(pipe, ProcessReader): |
1486 | # Read whatever is left |
1487 | pipe.doRead() |
1488 | |
1489 | === modified file 'landscape/manager/aptsources.py' |
1490 | --- landscape/manager/aptsources.py 2017-01-11 15:44:41 +0000 |
1491 | +++ landscape/manager/aptsources.py 2017-03-10 15:29:37 +0000 |
1492 | @@ -86,9 +86,8 @@ |
1493 | for key in message["gpg-keys"]: |
1494 | fd, path = tempfile.mkstemp() |
1495 | os.close(fd) |
1496 | - key_file = file(path, "w") |
1497 | - key_file.write(key) |
1498 | - key_file.close() |
1499 | + with open(path, "w") as key_file: |
1500 | + key_file.write(key) |
1501 | deferred.addCallback( |
1502 | lambda ignore, path=path: |
1503 | self._run_process("/usr/bin/apt-key", ["add", path])) |
1504 | @@ -131,7 +130,7 @@ |
1505 | "landscape-%s.list" % source["name"]) |
1506 | with open(filename, "w") as sources_file: |
1507 | sources_file.write(source["content"]) |
1508 | - os.chmod(filename, 0644) |
1509 | + os.chmod(filename, 0o644) |
1510 | return self._run_reporter().addCallback(lambda ignored: None) |
1511 | |
1512 | def _run_reporter(self): |
1513 | |
1514 | === modified file 'landscape/manager/customgraph.py' |
1515 | --- landscape/manager/customgraph.py 2013-05-21 14:18:29 +0000 |
1516 | +++ landscape/manager/customgraph.py 2017-03-10 15:29:37 +0000 |
1517 | @@ -3,7 +3,9 @@ |
1518 | import logging |
1519 | |
1520 | from twisted.internet.defer import fail, DeferredList, succeed |
1521 | +from twisted.python.compat import iteritems |
1522 | |
1523 | +from landscape.compat import coerce_unicode |
1524 | from landscape.lib.scriptcontent import generate_script_hash |
1525 | from landscape.accumulate import Accumulator |
1526 | from landscape.manager.plugin import ManagerPlugin |
1527 | @@ -129,7 +131,8 @@ |
1528 | logging.error(u"Attempt to add graph with unknown user %s" % |
1529 | user) |
1530 | else: |
1531 | - script_file = file(filename, "w") |
1532 | + script_file = open(filename, "w") |
1533 | + # file is closed in write_script_file |
1534 | self.write_script_file( |
1535 | script_file, filename, shell, code, uid, gid) |
1536 | if graph_id in self._data: |
1537 | @@ -158,7 +161,7 @@ |
1538 | message = {"type": self.message_type, "data": self._data} |
1539 | |
1540 | new_data = {} |
1541 | - for graph_id, item in self._data.iteritems(): |
1542 | + for graph_id, item in iteritems(self._data): |
1543 | script_hash = item["script-hash"] |
1544 | new_data[graph_id] = { |
1545 | "values": [], "error": u"", "script-hash": script_hash} |
1546 | @@ -186,7 +189,7 @@ |
1547 | if graph_id not in self._data: |
1548 | return |
1549 | if failure.check(ProcessFailedError): |
1550 | - failure_value = failure.value.data.decode("utf-8") |
1551 | + failure_value = coerce_unicode(failure.value.data, "utf-8") |
1552 | if failure.value.exit_code: |
1553 | failure_value = ("%s (process exited with code %d)" % |
1554 | (failure_value, failure.value.exit_code)) |
1555 | @@ -199,9 +202,8 @@ |
1556 | failure.value) |
1557 | |
1558 | def _get_script_hash(self, filename): |
1559 | - file_object = file(filename) |
1560 | - script_content = file_object.read() |
1561 | - file_object.close() |
1562 | + with open(filename) as file_object: |
1563 | + script_content = file_object.read() |
1564 | return generate_script_hash(script_content) |
1565 | |
1566 | def run(self): |
1567 | @@ -235,7 +237,7 @@ |
1568 | self._data[graph_id]["script-hash"] = script_hash |
1569 | try: |
1570 | uid, gid, path = get_user_info(user) |
1571 | - except UnknownUserError, e: |
1572 | + except UnknownUserError as e: |
1573 | d = fail(e) |
1574 | d.addErrback(self._handle_error, graph_id) |
1575 | deferred_list.append(d) |
1576 | |
1577 | === modified file 'landscape/manager/keystonetoken.py' |
1578 | --- landscape/manager/keystonetoken.py 2013-07-11 20:27:10 +0000 |
1579 | +++ landscape/manager/keystonetoken.py 2017-03-10 15:29:37 +0000 |
1580 | @@ -1,7 +1,7 @@ |
1581 | import os |
1582 | import logging |
1583 | -from ConfigParser import ConfigParser, NoOptionError |
1584 | |
1585 | +from landscape.compat import ConfigParser, NoOptionError |
1586 | from landscape.monitor.plugin import DataWatcher |
1587 | from landscape.lib.persist import Persist |
1588 | |
1589 | |
1590 | === modified file 'landscape/manager/plugin.py' |
1591 | --- landscape/manager/plugin.py 2013-05-08 22:18:47 +0000 |
1592 | +++ landscape/manager/plugin.py 2017-03-10 15:29:37 +0000 |
1593 | @@ -43,7 +43,8 @@ |
1594 | log_failure(failure, msg=msg) |
1595 | return FAILED, text |
1596 | |
1597 | - def send((status, text)): |
1598 | + def send(args): |
1599 | + status, text = args |
1600 | result = {"type": "operation-result", |
1601 | "status": status, |
1602 | "operation-id": message["operation-id"]} |
1603 | |
1604 | === modified file 'landscape/manager/scriptexecution.py' |
1605 | --- landscape/manager/scriptexecution.py 2016-10-06 11:02:53 +0000 |
1606 | +++ landscape/manager/scriptexecution.py 2017-03-10 15:29:37 +0000 |
1607 | @@ -12,13 +12,14 @@ |
1608 | from twisted.internet.defer import ( |
1609 | Deferred, fail, inlineCallbacks, returnValue, succeed) |
1610 | from twisted.internet.error import ProcessDone |
1611 | +from twisted.python.compat import unicode, _PY3 |
1612 | |
1613 | from landscape import VERSION |
1614 | from landscape.constants import UBUNTU_PATH |
1615 | -from landscape.lib.scriptcontent import build_script |
1616 | +from landscape.lib.encoding import encode_if_needed |
1617 | from landscape.lib.fetch import fetch_async, HTTPCodeError |
1618 | from landscape.lib.persist import Persist |
1619 | -from landscape.lib.encoding import encode_if_needed |
1620 | +from landscape.lib.scriptcontent import build_script |
1621 | from landscape.manager.plugin import ManagerPlugin, SUCCEEDED, FAILED |
1622 | |
1623 | |
1624 | @@ -111,10 +112,14 @@ |
1625 | # It would be nice to use fchown(2) and fchmod(2), but they're not |
1626 | # available in python and using it with ctypes is pretty tedious, not |
1627 | # to mention we can't get errno. |
1628 | - os.chmod(filename, 0700) |
1629 | + os.chmod(filename, 0o700) |
1630 | if uid is not None: |
1631 | os.chown(filename, uid, gid) |
1632 | - script_file.write(build_script(shell, code)) |
1633 | + |
1634 | + script = build_script(shell, code) |
1635 | + if not _PY3: |
1636 | + script = script.encode('utf-8') |
1637 | + script_file.write(script) |
1638 | script_file.close() |
1639 | |
1640 | def _run_script(self, filename, uid, gid, path, env, time_limit): |
1641 | @@ -178,7 +183,7 @@ |
1642 | d.addCallback(self._respond_success, opid) |
1643 | d.addErrback(self._respond_failure, opid) |
1644 | return d |
1645 | - except Exception, e: |
1646 | + except Exception as e: |
1647 | self._respond(FAILED, self._format_exception(e), opid) |
1648 | raise |
1649 | |
1650 | @@ -223,13 +228,12 @@ |
1651 | cainfo=self.registry.config.ssl_public_key, |
1652 | headers=headers) |
1653 | full_filename = os.path.join(attachment_dir, filename) |
1654 | - attachment = file(full_filename, "wb") |
1655 | - os.chmod(full_filename, 0600) |
1656 | - if uid is not None: |
1657 | - os.chown(full_filename, uid, gid) |
1658 | - attachment.write(data) |
1659 | - attachment.close() |
1660 | - os.chmod(attachment_dir, 0700) |
1661 | + with open(full_filename, "wb") as attachment: |
1662 | + os.chmod(full_filename, 0o600) |
1663 | + if uid is not None: |
1664 | + os.chown(full_filename, uid, gid) |
1665 | + attachment.write(data) |
1666 | + os.chmod(attachment_dir, 0o700) |
1667 | if uid is not None: |
1668 | os.chown(attachment_dir, uid, gid) |
1669 | returnValue(attachment_dir) |
1670 | @@ -270,7 +274,7 @@ |
1671 | env = {"PATH": UBUNTU_PATH, "USER": user or "", "HOME": path or ""} |
1672 | if server_supplied_env: |
1673 | env.update(server_supplied_env) |
1674 | - old_umask = os.umask(0022) |
1675 | + old_umask = os.umask(0o022) |
1676 | |
1677 | if attachments: |
1678 | persist = Persist( |
1679 | |
1680 | === modified file 'landscape/manager/tests/test_aptsources.py' |
1681 | --- landscape/manager/tests/test_aptsources.py 2017-01-13 15:49:40 +0000 |
1682 | +++ landscape/manager/tests/test_aptsources.py 2017-03-10 15:29:37 +0000 |
1683 | @@ -57,7 +57,7 @@ |
1684 | "gpg-keys": [], |
1685 | "operation-id": 1}) |
1686 | |
1687 | - with file(self.sourceslist.SOURCES_LIST) as sources: |
1688 | + with open(self.sourceslist.SOURCES_LIST) as sources: |
1689 | self.assertEqual( |
1690 | "# Landscape manages repositories for this computer\n" |
1691 | "# Original content of sources.list can be found in " |
1692 | @@ -79,7 +79,7 @@ |
1693 | |
1694 | saved_sources_path = "{}.save".format(self.sourceslist.SOURCES_LIST) |
1695 | self.assertTrue(os.path.exists(saved_sources_path)) |
1696 | - with file(saved_sources_path) as saved_sources: |
1697 | + with open(saved_sources_path) as saved_sources: |
1698 | self.assertEqual("oki\n\ndoki\n#comment\n # other comment\n", |
1699 | saved_sources.read()) |
1700 | |
1701 | @@ -102,7 +102,7 @@ |
1702 | "operation-id": 1}) |
1703 | |
1704 | self.assertTrue(os.path.exists(saved_sources_path)) |
1705 | - with file(saved_sources_path) as saved_sources: |
1706 | + with open(saved_sources_path) as saved_sources: |
1707 | self.assertEqual("original content\n", saved_sources.read()) |
1708 | |
1709 | def test_restore_sources_list(self): |
1710 | @@ -123,7 +123,7 @@ |
1711 | "gpg-keys": [], |
1712 | "operation-id": 1}) |
1713 | |
1714 | - with file(self.sourceslist.SOURCES_LIST) as sources: |
1715 | + with open(self.sourceslist.SOURCES_LIST) as sources: |
1716 | self.assertEqual("original content\n", sources.read()) |
1717 | |
1718 | def test_sources_list_permissions(self): |
1719 | @@ -236,12 +236,16 @@ |
1720 | dev_file = os.path.join(self.sourceslist.SOURCES_LIST_D, |
1721 | "landscape-dev.list") |
1722 | self.assertTrue(os.path.exists(dev_file)) |
1723 | - self.assertEqual("oki\n", file(dev_file).read()) |
1724 | + with open(dev_file) as file: |
1725 | + result = file.read() |
1726 | + self.assertEqual("oki\n", result) |
1727 | |
1728 | lucid_file = os.path.join(self.sourceslist.SOURCES_LIST_D, |
1729 | "landscape-lucid.list") |
1730 | self.assertTrue(os.path.exists(lucid_file)) |
1731 | - self.assertEqual("doki\n", file(lucid_file).read()) |
1732 | + with open(lucid_file) as file: |
1733 | + result = file.read() |
1734 | + self.assertEqual("doki\n", result) |
1735 | |
1736 | def test_import_gpg_keys(self): |
1737 | """ |
1738 | @@ -254,7 +258,9 @@ |
1739 | self.assertEqual("/usr/bin/apt-key", command) |
1740 | self.assertEqual("add", args[0]) |
1741 | filename = args[1] |
1742 | - self.assertEqual("Some key content", file(filename).read()) |
1743 | + with open(filename) as file: |
1744 | + result = file.read() |
1745 | + self.assertEqual("Some key content", result) |
1746 | deferred.callback(("ok", "", 0)) |
1747 | return deferred |
1748 | |
1749 | @@ -376,17 +382,17 @@ |
1750 | |
1751 | self.sourceslist._run_process = _run_process |
1752 | |
1753 | - sources = file(self.sourceslist.SOURCES_LIST, "w") |
1754 | - sources.write("oki\n\ndoki\n#comment\n") |
1755 | - sources.close() |
1756 | + with open(self.sourceslist.SOURCES_LIST, "w") as sources: |
1757 | + sources.write("oki\n\ndoki\n#comment\n") |
1758 | |
1759 | self.manager.dispatch_message( |
1760 | {"type": "apt-sources-replace", "sources": [], "gpg-keys": ["key"], |
1761 | "operation-id": 1}) |
1762 | |
1763 | - self.assertEqual( |
1764 | - "oki\n\ndoki\n#comment\n", |
1765 | - file(self.sourceslist.SOURCES_LIST).read()) |
1766 | + with open(self.sourceslist.SOURCES_LIST) as sources_list: |
1767 | + result = sources_list.read() |
1768 | + |
1769 | + self.assertEqual("oki\n\ndoki\n#comment\n", result) |
1770 | |
1771 | return deferred |
1772 | |
1773 | |
1774 | === modified file 'landscape/manager/tests/test_customgraph.py' |
1775 | --- landscape/manager/tests/test_customgraph.py 2016-06-15 23:35:19 +0000 |
1776 | +++ landscape/manager/tests/test_customgraph.py 2017-03-10 15:29:37 +0000 |
1777 | @@ -105,7 +105,7 @@ |
1778 | "bar")]) |
1779 | |
1780 | mock_chown.assert_called_with(mock.ANY, 1234, 5678) |
1781 | - mock_chmod.assert_called_with(mock.ANY, 0700) |
1782 | + mock_chmod.assert_called_with(mock.ANY, 0o700) |
1783 | mock_getpwnam.assert_called_with("bar") |
1784 | |
1785 | def test_remove_unknown_graph(self): |
1786 | @@ -114,10 +114,7 @@ |
1787 | "graph-id": 123}) |
1788 | |
1789 | def test_remove_graph(self): |
1790 | - filename = self.makeFile() |
1791 | - tempfile = file(filename, "w") |
1792 | - tempfile.write("foo") |
1793 | - tempfile.close() |
1794 | + filename = self.makeFile(content='foo') |
1795 | self.store.add_graph(123, filename, u"user") |
1796 | self.manager.dispatch_message( |
1797 | {"type": "custom-graph-remove", |
1798 | @@ -125,11 +122,8 @@ |
1799 | self.assertFalse(os.path.exists(filename)) |
1800 | |
1801 | def test_run(self): |
1802 | - filename = self.makeFile() |
1803 | - tempfile = file(filename, "w") |
1804 | - tempfile.write("#!/bin/sh\necho 1") |
1805 | - tempfile.close() |
1806 | - os.chmod(filename, 0777) |
1807 | + filename = self.makeFile(content="#!/bin/sh\necho 1") |
1808 | + os.chmod(filename, 0o777) |
1809 | self.store.add_graph(123, filename, None) |
1810 | |
1811 | def check(ignore): |
1812 | @@ -144,18 +138,12 @@ |
1813 | return self.graph_manager.run().addCallback(check) |
1814 | |
1815 | def test_run_multiple(self): |
1816 | - filename = self.makeFile() |
1817 | - tempfile = file(filename, "w") |
1818 | - tempfile.write("#!/bin/sh\necho 1") |
1819 | - tempfile.close() |
1820 | - os.chmod(filename, 0777) |
1821 | + filename = self.makeFile(content="#!/bin/sh\necho 1") |
1822 | + os.chmod(filename, 0o777) |
1823 | self.store.add_graph(123, filename, None) |
1824 | |
1825 | - filename = self.makeFile() |
1826 | - tempfile = file(filename, "w") |
1827 | - tempfile.write("#!/bin/sh\necho 2") |
1828 | - tempfile.close() |
1829 | - os.chmod(filename, 0777) |
1830 | + filename = self.makeFile(content="#!/bin/sh\necho 2") |
1831 | + os.chmod(filename, 0o777) |
1832 | self.store.add_graph(124, filename, None) |
1833 | |
1834 | def check(ignore): |
1835 | @@ -176,11 +164,8 @@ |
1836 | return self.graph_manager.run().addCallback(check) |
1837 | |
1838 | def test_run_with_nonzero_exit_code(self): |
1839 | - filename = self.makeFile() |
1840 | - tempfile = file(filename, "w") |
1841 | - tempfile.write("#!/bin/sh\nexit 1") |
1842 | - tempfile.close() |
1843 | - os.chmod(filename, 0777) |
1844 | + filename = self.makeFile(content="#!/bin/sh\nexit 1") |
1845 | + os.chmod(filename, 0o777) |
1846 | self.store.add_graph(123, filename, None) |
1847 | |
1848 | def check(ignore): |
1849 | |
1850 | === modified file 'landscape/manager/tests/test_packagemanager.py' |
1851 | --- landscape/manager/tests/test_packagemanager.py 2016-06-16 16:59:17 +0000 |
1852 | +++ landscape/manager/tests/test_packagemanager.py 2017-03-10 15:29:37 +0000 |
1853 | @@ -186,7 +186,7 @@ |
1854 | when passed the L{PackageChanger} class as argument. |
1855 | """ |
1856 | command = self.makeFile("#!/bin/sh\necho 'I am the changer!' >&2\n") |
1857 | - os.chmod(command, 0755) |
1858 | + os.chmod(command, 0o755) |
1859 | find_command_mock.return_value = command |
1860 | |
1861 | self.package_store.add_task("changer", "Do something!") |
1862 | @@ -210,7 +210,7 @@ |
1863 | when passed the L{ReleaseUpgrader} class as argument. |
1864 | """ |
1865 | command = self.makeFile("#!/bin/sh\necho 'I am the upgrader!' >&2\n") |
1866 | - os.chmod(command, 0755) |
1867 | + os.chmod(command, 0o755) |
1868 | find_command_mock.return_value = command |
1869 | |
1870 | self.package_store.add_task("release-upgrader", "Do something!") |
1871 | @@ -244,7 +244,7 @@ |
1872 | @mock.patch("landscape.package.changer.find_changer_command") |
1873 | def test_spawn_handler_copies_environment(self, find_command_mock): |
1874 | command = self.makeFile("#!/bin/sh\necho VAR: $VAR\n") |
1875 | - os.chmod(command, 0755) |
1876 | + os.chmod(command, 0o755) |
1877 | find_command_mock.return_value = command |
1878 | |
1879 | self.manager.add(self.package_manager) |
1880 | @@ -264,7 +264,7 @@ |
1881 | @mock.patch("landscape.package.changer.find_changer_command") |
1882 | def test_spawn_handler_passes_quiet_option(self, find_command_mock): |
1883 | command = self.makeFile("#!/bin/sh\necho OPTIONS: $@\n") |
1884 | - os.chmod(command, 0755) |
1885 | + os.chmod(command, 0o755) |
1886 | find_command_mock.return_value = command |
1887 | |
1888 | self.manager.add(self.package_manager) |
1889 | @@ -281,7 +281,7 @@ |
1890 | |
1891 | def test_spawn_handler_wont_run_without_tasks(self): |
1892 | command = self.makeFile("#!/bin/sh\necho RUN!\n") |
1893 | - os.chmod(command, 0755) |
1894 | + os.chmod(command, 0o755) |
1895 | |
1896 | self.manager.add(self.package_manager) |
1897 | result = self.package_manager.spawn_handler(PackageChanger) |
1898 | @@ -295,7 +295,7 @@ |
1899 | @mock.patch("landscape.package.changer.find_changer_command") |
1900 | def test_spawn_handler_doesnt_chdir(self, find_command_mock): |
1901 | command = self.makeFile("#!/bin/sh\necho RUN\n") |
1902 | - os.chmod(command, 0755) |
1903 | + os.chmod(command, 0o755) |
1904 | cwd = os.getcwd() |
1905 | self.addCleanup(os.chdir, cwd) |
1906 | dir = self.makeDir() |
1907 | @@ -313,7 +313,7 @@ |
1908 | log = self.logfile.getvalue() |
1909 | self.assertIn("RUN", log) |
1910 | # restore permissions to the dir so tearDown can clean it up |
1911 | - os.chmod(dir, 0766) |
1912 | + os.chmod(dir, 0o766) |
1913 | |
1914 | return result.addCallback(got_result) |
1915 | |
1916 | |
1917 | === modified file 'landscape/manager/tests/test_scriptexecution.py' |
1918 | --- landscape/manager/tests/test_scriptexecution.py 2016-10-24 10:59:47 +0000 |
1919 | +++ landscape/manager/tests/test_scriptexecution.py 2017-03-10 15:29:37 +0000 |
1920 | @@ -6,9 +6,12 @@ |
1921 | |
1922 | import mock |
1923 | |
1924 | +from unittest import skipIf |
1925 | + |
1926 | from twisted.internet.defer import gatherResults, succeed, fail |
1927 | from twisted.internet.error import ProcessDone |
1928 | from twisted.python.failure import Failure |
1929 | +from twisted.python.compat import _PY3 |
1930 | |
1931 | from landscape import VERSION |
1932 | from landscape.lib.fetch import HTTPCodeError |
1933 | @@ -40,6 +43,7 @@ |
1934 | self.plugin = ScriptExecutionPlugin() |
1935 | self.manager.add(self.plugin) |
1936 | |
1937 | + @skipIf(_PY3, 'Takes long with Python3, probably not an unclean Reactor') |
1938 | def test_basic_run(self): |
1939 | """ |
1940 | The plugin returns a Deferred resulting in the output of basic |
1941 | @@ -49,18 +53,21 @@ |
1942 | result.addCallback(self.assertEqual, "hi\n") |
1943 | return result |
1944 | |
1945 | + @skipIf(_PY3, 'Takes long with Python3, probably not an unclean Reactor') |
1946 | def test_snap_path(self): |
1947 | """The bin path for snaps is included in the PATH.""" |
1948 | deferred = self.plugin.run_script("/bin/sh", "echo $PATH") |
1949 | return deferred.addCallback( |
1950 | lambda result: self.assertIn("/snap/bin", result)) |
1951 | |
1952 | + @skipIf(_PY3, 'Takes long with Python3, probably not an unclean Reactor') |
1953 | def test_other_interpreter(self): |
1954 | """Non-shell interpreters can be specified.""" |
1955 | result = self.plugin.run_script("/usr/bin/python", "print 'hi'") |
1956 | result.addCallback(self.assertEqual, "hi\n") |
1957 | return result |
1958 | |
1959 | + @skipIf(_PY3, 'Takes long with Python3, probably not an unclean Reactor') |
1960 | def test_other_interpreter_env(self): |
1961 | """ |
1962 | Non-shell interpreters don't have their paths set by the shell, so we |
1963 | @@ -77,6 +84,7 @@ |
1964 | result.addCallback(check_environment) |
1965 | return result |
1966 | |
1967 | + @skipIf(_PY3, 'Takes long with Python3, probably not an unclean Reactor') |
1968 | def test_server_supplied_env(self): |
1969 | """ |
1970 | Server-supplied environment variables are merged with default |
1971 | @@ -98,6 +106,7 @@ |
1972 | result.addCallback(check_environment) |
1973 | return result |
1974 | |
1975 | + @skipIf(_PY3, 'Takes long with Python3, probably not an unclean Reactor') |
1976 | def test_server_supplied_env_overrides_client(self): |
1977 | """ |
1978 | Server-supplied environment variables override client default |
1979 | @@ -118,6 +127,7 @@ |
1980 | result.addCallback(check_environment) |
1981 | return result |
1982 | |
1983 | + @skipIf(_PY3, 'Takes long with Python3, probably not an unclean Reactor') |
1984 | def test_concurrent(self): |
1985 | """ |
1986 | Scripts run with the ScriptExecutionPlugin plugin are run concurrently. |
1987 | @@ -134,6 +144,7 @@ |
1988 | d2.addCallback(self.assertEqual, "") |
1989 | return gatherResults([d1, d2]) |
1990 | |
1991 | + @skipIf(_PY3, 'Takes long with Python3, probably not an unclean Reactor') |
1992 | def test_accented_run_in_code(self): |
1993 | """ |
1994 | Scripts can contain accented data both in the code and in the |
1995 | @@ -146,6 +157,7 @@ |
1996 | self.assertEqual, "%s\n" % (accented_content.encode("utf-8"),)) |
1997 | return result |
1998 | |
1999 | + @skipIf(_PY3, 'Takes long with Python3, probably not an unclean Reactor') |
2000 | def test_accented_run_in_interpreter(self): |
2001 | """ |
2002 | Scripts can also contain accents in the interpreter. |
2003 | @@ -161,9 +173,10 @@ |
2004 | result.addCallback(check) |
2005 | return result |
2006 | |
2007 | + @skipIf(_PY3, 'Takes long with Python3, probably not an unclean Reactor') |
2008 | def test_set_umask_appropriately(self): |
2009 | """ |
2010 | - We should be setting the umask to 0022 before executing a script, and |
2011 | + We should be setting the umask to 0o022 before executing a script, and |
2012 | restoring it to the previous value when finishing. |
2013 | """ |
2014 | # Get original umask. |
2015 | @@ -183,6 +196,7 @@ |
2016 | result.addCallback(check) |
2017 | return result.addCallback(lambda _: patch_umask.stop()) |
2018 | |
2019 | + @skipIf(_PY3, "mock does not get cleaned up, poisoning all other tests.") |
2020 | def test_restore_umask_in_event_of_error(self): |
2021 | """ |
2022 | We set the umask before executing the script, in the event that there's |
2023 | @@ -298,6 +312,7 @@ |
2024 | |
2025 | return result.addCallback(check).addBoth(cleanup) |
2026 | |
2027 | + @skipIf(_PY3, 'Takes long with Python3, probably not an unclean Reactor') |
2028 | def test_self_remove_script(self): |
2029 | """ |
2030 | If a script removes itself, it doesn't create an error when the script |
2031 | @@ -416,9 +431,9 @@ |
2032 | spawn = factory.spawns[0] |
2033 | self.assertIn("LANDSCAPE_ATTACHMENTS", spawn[3]) |
2034 | attachment_dir = spawn[3]["LANDSCAPE_ATTACHMENTS"] |
2035 | - self.assertEqual(stat.S_IMODE(os.stat(attachment_dir).st_mode), 0700) |
2036 | + self.assertEqual(stat.S_IMODE(os.stat(attachment_dir).st_mode), 0o700) |
2037 | filename = os.path.join(attachment_dir, "file 1") |
2038 | - self.assertEqual(stat.S_IMODE(os.stat(filename).st_mode), 0600) |
2039 | + self.assertEqual(stat.S_IMODE(os.stat(filename).st_mode), 0o600) |
2040 | |
2041 | protocol = spawn[0] |
2042 | protocol.childDataReceived(1, "foobar") |
2043 | |
2044 | === modified file 'landscape/manager/usermanager.py' |
2045 | --- landscape/manager/usermanager.py 2013-05-07 23:06:56 +0000 |
2046 | +++ landscape/manager/usermanager.py 2017-03-10 15:29:37 +0000 |
2047 | @@ -62,7 +62,7 @@ |
2048 | if len(parts) > 1: |
2049 | if parts[1].startswith("!"): |
2050 | locked_users.append(parts[0].strip()) |
2051 | - except IOError, e: |
2052 | + except IOError as e: |
2053 | logging.error("Error reading shadow file. %s" % e) |
2054 | return locked_users |
2055 | |
2056 | |
2057 | === modified file 'landscape/monitor/activeprocessinfo.py' |
2058 | --- landscape/monitor/activeprocessinfo.py 2013-07-12 09:49:47 +0000 |
2059 | +++ landscape/monitor/activeprocessinfo.py 2017-03-10 15:29:37 +0000 |
2060 | @@ -1,5 +1,7 @@ |
2061 | import subprocess |
2062 | |
2063 | +from twisted.python.compat import itervalues |
2064 | + |
2065 | from landscape.diff import diff |
2066 | from landscape.lib.process import ProcessInformation |
2067 | from landscape.lib.jiffies import detect_jiffies |
2068 | @@ -67,11 +69,11 @@ |
2069 | processes = self._get_processes() |
2070 | creates, updates, deletes = diff(self._persist_processes, processes) |
2071 | if creates: |
2072 | - changes["add-processes"] = list(creates.itervalues()) |
2073 | + changes["add-processes"] = list(itervalues(creates)) |
2074 | if updates: |
2075 | - changes["update-processes"] = list(updates.itervalues()) |
2076 | + changes["update-processes"] = list(itervalues(updates)) |
2077 | if deletes: |
2078 | - changes["kill-processes"] = list(deletes.iterkeys()) |
2079 | + changes["kill-processes"] = list(deletes) |
2080 | |
2081 | # Update cached values for use on the next run. |
2082 | self._previous_processes = processes |
2083 | |
2084 | === modified file 'landscape/monitor/aptpreferences.py' |
2085 | --- landscape/monitor/aptpreferences.py 2013-07-05 12:52:40 +0000 |
2086 | +++ landscape/monitor/aptpreferences.py 2017-03-10 15:29:37 +0000 |
2087 | @@ -1,5 +1,7 @@ |
2088 | import os |
2089 | |
2090 | +from twisted.python.compat import iteritems, unicode |
2091 | + |
2092 | from landscape.lib.fs import read_file |
2093 | from landscape.constants import APT_PREFERENCES_SIZE_LIMIT |
2094 | |
2095 | @@ -46,7 +48,7 @@ |
2096 | return None |
2097 | |
2098 | item_size_limit = self.size_limit / len(data.keys()) |
2099 | - for filename, contents in data.iteritems(): |
2100 | + for filename, contents in iteritems(data): |
2101 | if len(filename) + len(contents) > item_size_limit: |
2102 | truncated_contents_size = item_size_limit - len(filename) |
2103 | data[filename] = data[filename][0:truncated_contents_size] |
2104 | |
2105 | === modified file 'landscape/monitor/cephusage.py' |
2106 | --- landscape/monitor/cephusage.py 2014-05-20 14:20:21 +0000 |
2107 | +++ landscape/monitor/cephusage.py 2017-03-10 15:29:37 +0000 |
2108 | @@ -3,6 +3,7 @@ |
2109 | import os |
2110 | |
2111 | from twisted.internet import threads |
2112 | +from twisted.python.compat import unicode |
2113 | |
2114 | from landscape.accumulate import Accumulator |
2115 | from landscape.lib.monitor import CoverageMonitor |
2116 | |
2117 | === modified file 'landscape/monitor/computeruptime.py' |
2118 | --- landscape/monitor/computeruptime.py 2013-07-05 12:52:40 +0000 |
2119 | +++ landscape/monitor/computeruptime.py 2017-03-10 15:29:37 +0000 |
2120 | @@ -12,7 +12,8 @@ |
2121 | This parses a file in /proc/uptime format and returns a floating point |
2122 | version of the first value (the actual uptime). |
2123 | """ |
2124 | - data = file(uptime_file, "r").readline() |
2125 | + with open(uptime_file, 'r') as ufile: |
2126 | + data = ufile.readline() |
2127 | up, idle = data.split() |
2128 | return float(up) |
2129 | |
2130 | @@ -86,21 +87,22 @@ |
2131 | def get_times(self): |
2132 | reboot_times = [] |
2133 | shutdown_times = [] |
2134 | - reader = LoginInfoReader(file(self._filename)) |
2135 | - self._last_boot = self._boots_newer_than |
2136 | - self._last_shutdown = self._shutdowns_newer_than |
2137 | + with open(self._filename) as login_info_file: |
2138 | + reader = LoginInfoReader(login_info_file) |
2139 | + self._last_boot = self._boots_newer_than |
2140 | + self._last_shutdown = self._shutdowns_newer_than |
2141 | |
2142 | - for info in reader.login_info(): |
2143 | - if info.tty_device.startswith("~"): |
2144 | - timestamp = to_timestamp(info.entry_time) |
2145 | - if (info.username == "reboot" |
2146 | - and timestamp > self._last_boot): |
2147 | - reboot_times.append(timestamp) |
2148 | - self._last_boot = timestamp |
2149 | - elif (info.username == "shutdown" |
2150 | - and timestamp > self._last_shutdown): |
2151 | - shutdown_times.append(timestamp) |
2152 | - self._last_shutdown = timestamp |
2153 | + for info in reader.login_info(): |
2154 | + if info.tty_device.startswith("~"): |
2155 | + timestamp = to_timestamp(info.entry_time) |
2156 | + if (info.username == "reboot" and |
2157 | + timestamp > self._last_boot): |
2158 | + reboot_times.append(timestamp) |
2159 | + self._last_boot = timestamp |
2160 | + elif (info.username == "shutdown" and |
2161 | + timestamp > self._last_shutdown): |
2162 | + shutdown_times.append(timestamp) |
2163 | + self._last_shutdown = timestamp |
2164 | return reboot_times, shutdown_times |
2165 | |
2166 | def get_last_boot_time(self): |
2167 | |
2168 | === modified file 'landscape/monitor/mountinfo.py' |
2169 | --- landscape/monitor/mountinfo.py 2013-07-05 12:52:40 +0000 |
2170 | +++ landscape/monitor/mountinfo.py 2017-03-10 15:29:37 +0000 |
2171 | @@ -1,9 +1,10 @@ |
2172 | +import codecs |
2173 | import time |
2174 | import os |
2175 | |
2176 | +from landscape.accumulate import Accumulator |
2177 | from landscape.lib.disk import get_mount_info, is_device_removable |
2178 | from landscape.lib.monitor import CoverageMonitor |
2179 | -from landscape.accumulate import Accumulator |
2180 | from landscape.monitor.plugin import MonitorPlugin |
2181 | |
2182 | |
2183 | @@ -134,7 +135,7 @@ |
2184 | for line in file: |
2185 | try: |
2186 | device, mount_point, filesystem, options = line.split()[:4] |
2187 | - mount_point = mount_point.decode("string-escape") |
2188 | + mount_point = codecs.decode(mount_point, "unicode_escape") |
2189 | except ValueError: |
2190 | continue |
2191 | if "bind" in options.split(","): |
2192 | |
2193 | === modified file 'landscape/monitor/rebootrequired.py' |
2194 | --- landscape/monitor/rebootrequired.py 2013-07-05 12:52:40 +0000 |
2195 | +++ landscape/monitor/rebootrequired.py 2017-03-10 15:29:37 +0000 |
2196 | @@ -35,7 +35,7 @@ |
2197 | return [] |
2198 | |
2199 | lines = read_file(self._packages_filename).splitlines() |
2200 | - packages = set(line.strip().decode("utf-8") for line in lines if line) |
2201 | + packages = set(line.strip() for line in lines if line) |
2202 | return sorted(packages) |
2203 | |
2204 | def _create_message(self): |
2205 | |
2206 | === modified file 'landscape/monitor/tests/test_aptpreferences.py' |
2207 | --- landscape/monitor/tests/test_aptpreferences.py 2016-06-15 21:58:09 +0000 |
2208 | +++ landscape/monitor/tests/test_aptpreferences.py 2017-03-10 15:29:37 +0000 |
2209 | @@ -1,6 +1,8 @@ |
2210 | import os |
2211 | import mock |
2212 | |
2213 | +from twisted.python.compat import unicode |
2214 | + |
2215 | from landscape.monitor.aptpreferences import AptPreferences |
2216 | from landscape.tests.helpers import LandscapeTest |
2217 | from landscape.tests.helpers import MonitorHelper |
2218 | |
2219 | === modified file 'landscape/monitor/tests/test_cephusage.py' |
2220 | --- landscape/monitor/tests/test_cephusage.py 2016-08-17 20:33:47 +0000 |
2221 | +++ landscape/monitor/tests/test_cephusage.py 2017-03-10 15:29:37 +0000 |
2222 | @@ -141,7 +141,7 @@ |
2223 | reached. |
2224 | """ |
2225 | interval = 300 |
2226 | - stats = {"kb": 10240L, "kb_avail": 8192L, "kb_used": 2048L} |
2227 | + stats = {"kb": 10240, "kb_avail": 8192, "kb_used": 2048} |
2228 | |
2229 | plugin = CephUsage( |
2230 | create_time=self.reactor.time, interval=interval, |
2231 | |
2232 | === modified file 'landscape/monitor/tests/test_mountinfo.py' |
2233 | --- landscape/monitor/tests/test_mountinfo.py 2017-02-22 10:55:15 +0000 |
2234 | +++ landscape/monitor/tests/test_mountinfo.py 2017-03-10 15:29:37 +0000 |
2235 | @@ -1,6 +1,10 @@ |
2236 | import mock |
2237 | +import os |
2238 | import tempfile |
2239 | |
2240 | +from twisted.python.compat import StringType as basestring |
2241 | +from twisted.python.compat import long |
2242 | + |
2243 | from landscape.monitor.mountinfo import MountInfo |
2244 | from landscape.tests.helpers import LandscapeTest, mock_counter, MonitorHelper |
2245 | |
2246 | @@ -8,6 +12,11 @@ |
2247 | mb = lambda x: x * 1024 * 1024 |
2248 | |
2249 | |
2250 | +def statvfs_result_fixture(path): |
2251 | + """Fixture for a dummy statvfs_result.""" |
2252 | + return os.statvfs_result((4096, 0, mb(1000), mb(100), 0, 0, 0, 0, 0, 0)) |
2253 | + |
2254 | + |
2255 | class MountInfoTest(LandscapeTest): |
2256 | """Tests for mount-info plugin.""" |
2257 | |
2258 | @@ -24,7 +33,8 @@ |
2259 | if "mtab_file" not in kwargs: |
2260 | kwargs["mtab_file"] = self.makeFile("/dev/hda1 / ext3 rw 0 0\n") |
2261 | if "statvfs" not in kwargs: |
2262 | - kwargs["statvfs"] = lambda path: (0,) * 1000 |
2263 | + kwargs["statvfs"] = lambda path: os.statvfs_result( |
2264 | + (0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) |
2265 | plugin = MountInfo(*args, **kwargs) |
2266 | # To make sure tests are isolated from the real system by default. |
2267 | plugin.is_device_removable = lambda x: False |
2268 | @@ -65,9 +75,11 @@ |
2269 | """ |
2270 | def statvfs(path): |
2271 | if path == "/": |
2272 | - return (4096, 0, mb(1000L), mb(100L), 0L, 0L, 0L, 0, 0) |
2273 | + return os.statvfs_result( |
2274 | + (4096, 0, mb(1000), mb(100), 0, 0, 0, 0, 0, 0)) |
2275 | else: |
2276 | - return (4096, 0, mb(10000L), mb(1000L), 0L, 0L, 0L, 0, 0) |
2277 | + return os.statvfs_result( |
2278 | + (4096, 0, mb(10000), mb(1000), 0, 0, 0, 0, 0, 0)) |
2279 | |
2280 | filename = self.makeFile("""\ |
2281 | rootfs / rootfs rw 0 0 |
2282 | @@ -138,7 +150,8 @@ |
2283 | function which should cause it to queue new messages. |
2284 | """ |
2285 | def statvfs(path, multiplier=mock_counter(1).next): |
2286 | - return (4096, 0, mb(multiplier() * 1000), mb(100), 0, 0, 0, 0, 0) |
2287 | + return os.statvfs_result( |
2288 | + (4096, 0, mb(multiplier() * 1000), mb(100), 0, 0, 0, 0, 0, 0)) |
2289 | |
2290 | plugin = self.get_mount_info( |
2291 | statvfs=statvfs, create_time=self.reactor.time, |
2292 | @@ -170,8 +183,10 @@ |
2293 | """ |
2294 | def statvfs(path, multiplier=mock_counter(1).next): |
2295 | if path == "/": |
2296 | - return (4096, 0, mb(1000), mb(100), 0, 0, 0, 0, 0) |
2297 | - return (4096, 0, mb(multiplier() * 1000), mb(100), 0, 0, 0, 0, 0) |
2298 | + return os.statvfs_result( |
2299 | + (4096, 0, mb(1000), mb(100), 0, 0, 0, 0, 0, 0)) |
2300 | + return os.statvfs_result( |
2301 | + (4096, 0, mb(multiplier() * 1000), mb(100), 0, 0, 0, 0, 0, 0)) |
2302 | |
2303 | filename = self.makeFile("""\ |
2304 | /dev/hda1 / ext3 rw 0 0 |
2305 | @@ -213,11 +228,8 @@ |
2306 | messages collected bewteen exchange periods should be |
2307 | delivered in a single message. |
2308 | """ |
2309 | - def statvfs(path): |
2310 | - return (4096, 0, mb(1000), mb(100), 0, 0, 0, 0, 0) |
2311 | - |
2312 | plugin = self.get_mount_info( |
2313 | - statvfs=statvfs, create_time=self.reactor.time) |
2314 | + statvfs=statvfs_result_fixture, create_time=self.reactor.time) |
2315 | step_size = self.monitor.step_size |
2316 | self.monitor.add(plugin) |
2317 | |
2318 | @@ -244,11 +256,8 @@ |
2319 | Duplicate message should never be created. If no data is |
2320 | available, None will be returned when messages are created. |
2321 | """ |
2322 | - def statvfs(path): |
2323 | - return (4096, 0, mb(1000), mb(100), 0, 0, 0, 0, 0) |
2324 | - |
2325 | plugin = self.get_mount_info( |
2326 | - statvfs=statvfs, create_time=self.reactor.time) |
2327 | + statvfs=statvfs_result_fixture, create_time=self.reactor.time) |
2328 | self.monitor.add(plugin) |
2329 | |
2330 | self.reactor.advance(self.monitor.step_size) |
2331 | @@ -266,16 +275,14 @@ |
2332 | really test anything since the current behaviour is to ignore |
2333 | any mount point for which the device doesn't start with /dev. |
2334 | """ |
2335 | - def statvfs(path): |
2336 | - return (4096, 0, mb(1000), mb(100), 0, 0, 0, 0, 0) |
2337 | - |
2338 | filename = self.makeFile("""\ |
2339 | /dev/hdc4 /mm xfs rw 0 0 |
2340 | /mm/ubuntu-mirror /home/dchroot/warty/mirror none bind 0 0 |
2341 | /mm/ubuntu-mirror /home/dchroot/hoary/mirror none bind 0 0 |
2342 | /mm/ubuntu-mirror /home/dchroot/breezy/mirror none bind 0 0 |
2343 | """) |
2344 | - plugin = self.get_mount_info(mounts_file=filename, statvfs=statvfs, |
2345 | + plugin = self.get_mount_info(mounts_file=filename, |
2346 | + statvfs=statvfs_result_fixture, |
2347 | create_time=self.reactor.time, |
2348 | mtab_file=filename) |
2349 | step_size = self.monitor.step_size |
2350 | @@ -327,7 +334,8 @@ |
2351 | def test_sample_free_space(self): |
2352 | """Test collecting information about free space.""" |
2353 | def statvfs(path, multiplier=mock_counter(1).next): |
2354 | - return (4096, 0, mb(1000), mb(multiplier() * 100), 0, 0, 0, 0, 0) |
2355 | + return os.statvfs_result( |
2356 | + (4096, 0, mb(1000), mb(multiplier() * 100), 0, 0, 0, 0, 0, 0)) |
2357 | |
2358 | plugin = self.get_mount_info( |
2359 | statvfs=statvfs, create_time=self.reactor.time) |
2360 | @@ -362,13 +370,11 @@ |
2361 | Test ensures all expected messages are created and contain the |
2362 | right datatypes. |
2363 | """ |
2364 | - def statvfs(path): |
2365 | - return (4096, 0, mb(1000), mb(100), 0, 0, 0, 0, 0) |
2366 | - |
2367 | filename = self.makeFile("""\ |
2368 | /dev/hda2 / xfs rw 0 0 |
2369 | """) |
2370 | - plugin = self.get_mount_info(mounts_file=filename, statvfs=statvfs, |
2371 | + plugin = self.get_mount_info(mounts_file=filename, |
2372 | + statvfs=statvfs_result_fixture, |
2373 | create_time=self.reactor.time, |
2374 | mtab_file=filename) |
2375 | step_size = self.monitor.step_size |
2376 | @@ -393,10 +399,8 @@ |
2377 | On the reactor "resynchronize" event, new mount-info messages |
2378 | should be sent. |
2379 | """ |
2380 | - def statvfs(path): |
2381 | - return (4096, 0, mb(1000), mb(100), 0, 0, 0, 0, 0) |
2382 | plugin = self.get_mount_info( |
2383 | - create_time=self.reactor.time, statvfs=statvfs) |
2384 | + create_time=self.reactor.time, statvfs=statvfs_result_fixture) |
2385 | self.monitor.add(plugin) |
2386 | |
2387 | plugin.run() |
2388 | @@ -420,9 +424,6 @@ |
2389 | shouldn't be listed, as they have the same free space/used space as the |
2390 | device they're bound to. |
2391 | """ |
2392 | - def statvfs(path): |
2393 | - return (4096, 0, mb(1000), mb(100), 0, 0, 0, 0, 0) |
2394 | - |
2395 | # From this test data, we expect only two mount points to be returned, |
2396 | # and the other two to be ignored (the rebound /dev/hda2 -> /mnt |
2397 | # mounting) |
2398 | @@ -439,19 +440,20 @@ |
2399 | /opt /mnt none rw,bind 0 0 |
2400 | /opt /media/Boot\\040OSX none rw,bind 0 0 |
2401 | """) |
2402 | - plugin = MountInfo(mounts_file=filename, create_time=self.reactor.time, |
2403 | - statvfs=statvfs, mtab_file=mtab_filename) |
2404 | + plugin = MountInfo( |
2405 | + mounts_file=filename, create_time=self.reactor.time, |
2406 | + statvfs=statvfs_result_fixture, mtab_file=mtab_filename) |
2407 | |
2408 | self.monitor.add(plugin) |
2409 | plugin.run() |
2410 | message = plugin.create_mount_info_message() |
2411 | self.assertEqual(message.get("mount-info"), |
2412 | [(0, {"device": "/dev/devices/by-uuid/12345567", |
2413 | - "mount-point": "/", "total-space": 4096000L, |
2414 | + "mount-point": "/", "total-space": 4096000, |
2415 | "filesystem": "ext3"}), |
2416 | (0, {"device": "/dev/hda2", |
2417 | "mount-point": "/usr", |
2418 | - "total-space": 4096000L, |
2419 | + "total-space": 4096000, |
2420 | "filesystem": "ext3"}), |
2421 | ]) |
2422 | |
2423 | @@ -461,9 +463,6 @@ |
2424 | bind mounted directories, so any filesystems in /proc/mounts will be |
2425 | reported. |
2426 | """ |
2427 | - def statvfs(path): |
2428 | - return (4096, 0, mb(1000), mb(100), 0, 0, 0, 0, 0) |
2429 | - |
2430 | # In this test, we expect all mount points to be returned, as we can't |
2431 | # identify any as bind mounts. |
2432 | filename = self.makeFile("""\ |
2433 | @@ -474,22 +473,23 @@ |
2434 | # mktemp isn't normally secure, due to race conditions, but in this |
2435 | # case, we don't actually create the file at all. |
2436 | mtab_filename = tempfile.mktemp() |
2437 | - plugin = MountInfo(mounts_file=filename, create_time=self.reactor.time, |
2438 | - statvfs=statvfs, mtab_file=mtab_filename) |
2439 | + plugin = MountInfo( |
2440 | + mounts_file=filename, create_time=self.reactor.time, |
2441 | + statvfs=statvfs_result_fixture, mtab_file=mtab_filename) |
2442 | self.monitor.add(plugin) |
2443 | plugin.run() |
2444 | message = plugin.create_mount_info_message() |
2445 | self.assertEqual(message.get("mount-info"), |
2446 | [(0, {"device": "/dev/devices/by-uuid/12345567", |
2447 | - "mount-point": "/", "total-space": 4096000L, |
2448 | + "mount-point": "/", "total-space": 4096000, |
2449 | "filesystem": "ext3"}), |
2450 | (0, {"device": "/dev/hda2", |
2451 | "mount-point": "/usr", |
2452 | - "total-space": 4096000L, |
2453 | + "total-space": 4096000, |
2454 | "filesystem": "ext3"}), |
2455 | (0, {"device": "/dev/devices/by-uuid/12345567", |
2456 | "mount-point": "/mnt", |
2457 | - "total-space": 4096000L, |
2458 | + "total-space": 4096000, |
2459 | "filesystem": "ext3"})]) |
2460 | |
2461 | def test_no_message_if_not_accepted(self): |
2462 | @@ -498,10 +498,6 @@ |
2463 | accepting their type. |
2464 | """ |
2465 | self.mstore.set_accepted_types([]) |
2466 | - |
2467 | - def statvfs(path): |
2468 | - return (4096, 0, mb(1000), mb(100), 0, 0, 0, 0, 0) |
2469 | - |
2470 | # From this test data, we expect only two mount points to be returned, |
2471 | # and the third to be ignored (the rebound /dev/hda2 -> /mnt mounting) |
2472 | filename = self.makeFile("""\ |
2473 | @@ -516,8 +512,9 @@ |
2474 | /opt /mnt none rw,bind 0 0 |
2475 | """) |
2476 | |
2477 | - plugin = MountInfo(mounts_file=filename, create_time=self.reactor.time, |
2478 | - statvfs=statvfs, mtab_file=mtab_filename) |
2479 | + plugin = MountInfo( |
2480 | + mounts_file=filename, create_time=self.reactor.time, |
2481 | + statvfs=statvfs_result_fixture, mtab_file=mtab_filename) |
2482 | self.monitor.add(plugin) |
2483 | self.reactor.advance(self.monitor.step_size * 2) |
2484 | self.monitor.exchange() |
2485 | @@ -547,14 +544,12 @@ |
2486 | didn't get the mount info at all. This test ensures that mount info are |
2487 | only saved when exchange happens. |
2488 | """ |
2489 | - def statvfs(path): |
2490 | - return (4096, 0, mb(1000), mb(100), 0, 0, 0, 0, 0) |
2491 | - |
2492 | filename = self.makeFile("""\ |
2493 | /dev/hda1 / ext3 rw 0 0 |
2494 | """) |
2495 | - plugin = MountInfo(mounts_file=filename, create_time=self.reactor.time, |
2496 | - statvfs=statvfs, mtab_file=filename) |
2497 | + plugin = MountInfo( |
2498 | + mounts_file=filename, create_time=self.reactor.time, |
2499 | + statvfs=statvfs_result_fixture, mtab_file=filename) |
2500 | self.monitor.add(plugin) |
2501 | plugin.run() |
2502 | message1 = plugin.create_mount_info_message() |
2503 | @@ -563,7 +558,7 @@ |
2504 | [(0, {"device": "/dev/hda1", |
2505 | "filesystem": "ext3", |
2506 | "mount-point": "/", |
2507 | - "total-space": 4096000L})]) |
2508 | + "total-space": 4096000})]) |
2509 | plugin.run() |
2510 | message2 = plugin.create_mount_info_message() |
2511 | self.assertEqual( |
2512 | @@ -571,7 +566,7 @@ |
2513 | [(0, {"device": "/dev/hda1", |
2514 | "filesystem": "ext3", |
2515 | "mount-point": "/", |
2516 | - "total-space": 4096000L})]) |
2517 | + "total-space": 4096000})]) |
2518 | # Run again, calling create_mount_info_message purge the information |
2519 | plugin.run() |
2520 | plugin.exchange() |
2521 | @@ -584,11 +579,8 @@ |
2522 | In order not to overload the server, the client should stagger the |
2523 | exchange of free-space messages. |
2524 | """ |
2525 | - def statvfs(path): |
2526 | - return (4096, 0, mb(1000), mb(100), 0, 0, 0, 0, 0) |
2527 | - |
2528 | plugin = self.get_mount_info( |
2529 | - statvfs=statvfs, create_time=self.reactor.time) |
2530 | + statvfs=statvfs_result_fixture, create_time=self.reactor.time) |
2531 | # Limit the test exchange to 5 items. |
2532 | plugin.max_free_space_items_to_exchange = 5 |
2533 | step_size = self.monitor.step_size |
2534 | |
2535 | === modified file 'landscape/monitor/tests/test_packagemonitor.py' |
2536 | --- landscape/monitor/tests/test_packagemonitor.py 2016-06-16 16:38:13 +0000 |
2537 | +++ landscape/monitor/tests/test_packagemonitor.py 2017-03-10 15:29:37 +0000 |
2538 | @@ -130,7 +130,7 @@ |
2539 | |
2540 | def test_spawn_reporter(self): |
2541 | command = self.makeFile("#!/bin/sh\necho 'I am the reporter!' >&2\n") |
2542 | - os.chmod(command, 0755) |
2543 | + os.chmod(command, 0o755) |
2544 | find_command_mock_patcher = mock.patch( |
2545 | "landscape.monitor.packagemonitor.find_reporter_command", |
2546 | return_value=command) |
2547 | @@ -167,7 +167,7 @@ |
2548 | |
2549 | def test_spawn_reporter_copies_environment(self): |
2550 | command = self.makeFile("#!/bin/sh\necho VAR: $VAR\n") |
2551 | - os.chmod(command, 0755) |
2552 | + os.chmod(command, 0o755) |
2553 | find_command_mock_patcher = mock.patch( |
2554 | "landscape.monitor.packagemonitor.find_reporter_command", |
2555 | return_value=command) |
2556 | @@ -190,7 +190,7 @@ |
2557 | |
2558 | def test_spawn_reporter_passes_quiet_option(self): |
2559 | command = self.makeFile("#!/bin/sh\necho OPTIONS: $@\n") |
2560 | - os.chmod(command, 0755) |
2561 | + os.chmod(command, 0o755) |
2562 | find_command_mock_patcher = mock.patch( |
2563 | "landscape.monitor.packagemonitor.find_reporter_command", |
2564 | return_value=command) |
2565 | @@ -277,7 +277,7 @@ |
2566 | |
2567 | def test_spawn_reporter_doesnt_chdir(self): |
2568 | command = self.makeFile("#!/bin/sh\necho RUN\n") |
2569 | - os.chmod(command, 0755) |
2570 | + os.chmod(command, 0o755) |
2571 | cwd = os.getcwd() |
2572 | self.addCleanup(os.chdir, cwd) |
2573 | dir = self.makeDir() |
2574 | @@ -298,7 +298,7 @@ |
2575 | log = self.logfile.getvalue() |
2576 | self.assertIn("RUN", log) |
2577 | # restore permissions to the dir so tearDown can clean it up |
2578 | - os.chmod(dir, 0766) |
2579 | + os.chmod(dir, 0o766) |
2580 | find_command_mock_patcher.stop() |
2581 | |
2582 | return result.addCallback(got_result) |
2583 | |
2584 | === modified file 'landscape/monitor/updatemanager.py' |
2585 | --- landscape/monitor/updatemanager.py 2013-07-05 12:52:40 +0000 |
2586 | +++ landscape/monitor/updatemanager.py 2017-03-10 15:29:37 +0000 |
2587 | @@ -1,7 +1,7 @@ |
2588 | -import ConfigParser |
2589 | import os |
2590 | import logging |
2591 | |
2592 | +from landscape.compat import SafeConfigParser |
2593 | from landscape.monitor.plugin import MonitorPlugin |
2594 | |
2595 | |
2596 | @@ -39,7 +39,7 @@ |
2597 | # There is no config, so we just act as if it's set to 'normal' |
2598 | return "normal" |
2599 | config_file = open(self.update_manager_filename) |
2600 | - parser = ConfigParser.SafeConfigParser() |
2601 | + parser = SafeConfigParser() |
2602 | parser.readfp(config_file) |
2603 | prompt = parser.get("DEFAULT", "Prompt") |
2604 | valid_prompts = ["lts", "never", "normal"] |
2605 | |
2606 | === modified file 'landscape/package/changer.py' |
2607 | --- landscape/package/changer.py 2015-01-08 18:36:25 +0000 |
2608 | +++ landscape/package/changer.py 2017-03-10 15:29:37 +0000 |
2609 | @@ -232,10 +232,10 @@ |
2610 | count += 1 |
2611 | try: |
2612 | result.text = self._facade.perform_changes() |
2613 | - except TransactionError, exception: |
2614 | + except TransactionError as exception: |
2615 | result.code = ERROR_RESULT |
2616 | result.text = exception.args[0] |
2617 | - except DependencyError, exception: |
2618 | + except DependencyError as exception: |
2619 | for package in exception.packages: |
2620 | hash = self._facade.get_package_hash(package) |
2621 | id = self._store.get_hash_id(hash) |
2622 | |
2623 | === modified file 'landscape/package/facade.py' |
2624 | --- landscape/package/facade.py 2016-01-07 10:45:00 +0000 |
2625 | +++ landscape/package/facade.py 2017-03-10 15:29:37 +0000 |
2626 | @@ -5,7 +5,7 @@ |
2627 | import subprocess |
2628 | import sys |
2629 | import tempfile |
2630 | -from cStringIO import StringIO |
2631 | + |
2632 | from operator import attrgetter |
2633 | |
2634 | # Importing apt throws a FutureWarning on hardy, that we don't want to |
2635 | @@ -21,7 +21,10 @@ |
2636 | from aptsources.sourceslist import SourcesList |
2637 | from apt.progress.text import AcquireProgress |
2638 | from apt.progress.base import InstallProgress |
2639 | - |
2640 | +from twisted.python.compat import itervalues |
2641 | + |
2642 | + |
2643 | +from landscape.compat import StringIO |
2644 | from landscape.lib.fs import append_file, create_file, read_file, touch_file |
2645 | from landscape.package.skeleton import build_skeleton_apt |
2646 | |
2647 | @@ -168,7 +171,7 @@ |
2648 | |
2649 | def get_packages(self): |
2650 | """Get all the packages available in the channels.""" |
2651 | - return self._hash2pkg.itervalues() |
2652 | + return itervalues(self._hash2pkg) |
2653 | |
2654 | def get_locked_packages(self): |
2655 | """Get all packages in the channels that are locked. |
2656 | @@ -662,7 +665,7 @@ |
2657 | install_progress=install_progress) |
2658 | if not install_progress.dpkg_exited: |
2659 | raise SystemError("dpkg didn't exit cleanly.") |
2660 | - except (apt.cache.LockFailedException, SystemError), exception: |
2661 | + except (apt.cache.LockFailedException, SystemError) as exception: |
2662 | result_text = (fetch_output.getvalue() |
2663 | + read_file(install_output_path)) |
2664 | error = TransactionError(exception.args[0] + |
2665 | @@ -745,7 +748,7 @@ |
2666 | if now_broken_packages != already_broken_packages: |
2667 | try: |
2668 | fixer.resolve(True) |
2669 | - except SystemError, error: |
2670 | + except SystemError as error: |
2671 | raise TransactionError(error.args[0] + "\n" + |
2672 | self._get_unmet_dependency_info()) |
2673 | else: |
2674 | |
2675 | === modified file 'landscape/package/releaseupgrader.py' |
2676 | --- landscape/package/releaseupgrader.py 2014-12-12 13:25:39 +0000 |
2677 | +++ landscape/package/releaseupgrader.py 2017-03-10 15:29:37 +0000 |
2678 | @@ -5,10 +5,10 @@ |
2679 | import shutil |
2680 | import logging |
2681 | import tarfile |
2682 | -import cStringIO |
2683 | |
2684 | from twisted.internet.defer import succeed |
2685 | |
2686 | +from landscape.compat import StringIO |
2687 | from landscape.lib.fetch import url_to_filename, fetch_to_files |
2688 | from landscape.lib.lsb_release import parse_lsb_release, LSB_RELEASE_FILENAME |
2689 | from landscape.lib.gpg import gpg_verify |
2690 | @@ -186,7 +186,7 @@ |
2691 | @param err: The standard error of the upgrade-tool process. |
2692 | @return: A text aggregating the process output, error and log files. |
2693 | """ |
2694 | - buf = cStringIO.StringIO() |
2695 | + buf = StringIO() |
2696 | |
2697 | for label, content in [("output", out), ("error", err)]: |
2698 | if content: |
2699 | @@ -222,7 +222,8 @@ |
2700 | result = spawn_process(upgrade_tool_filename, args=args, env=env, |
2701 | path=upgrade_tool_directory, wait_pipes=False) |
2702 | |
2703 | - def send_operation_result((out, err, code)): |
2704 | + def send_operation_result(args): |
2705 | + out, err, code = args |
2706 | if code == 0: |
2707 | status = SUCCEEDED |
2708 | else: |
2709 | |
2710 | === modified file 'landscape/package/reporter.py' |
2711 | --- landscape/package/reporter.py 2016-08-04 16:13:11 +0000 |
2712 | +++ landscape/package/reporter.py 2017-03-10 15:29:37 +0000 |
2713 | @@ -1,4 +1,8 @@ |
2714 | -import urlparse |
2715 | +try: |
2716 | + import urlparse |
2717 | +except ImportError: |
2718 | + import urllib.parse as urlparse |
2719 | + |
2720 | import logging |
2721 | import time |
2722 | import sys |
2723 | @@ -13,8 +17,8 @@ |
2724 | from landscape.lib.twisted_util import gather_results, spawn_process |
2725 | from landscape.lib.fetch import fetch_async |
2726 | from landscape.lib.fs import touch_file |
2727 | -from landscape.lib import bpickle |
2728 | |
2729 | +from landscape.compat import convert_buffer_to_string, bpickle |
2730 | from landscape.package.taskhandler import ( |
2731 | PackageTaskHandlerConfiguration, PackageTaskHandler, run_task_handler) |
2732 | from landscape.package.store import UnknownHashIDRequest, FakePackageStore |
2733 | @@ -278,8 +282,8 @@ |
2734 | env["https_proxy"] = self._config.https_proxy |
2735 | result = spawn_process(self.apt_update_filename, env=env) |
2736 | |
2737 | - def callback((out, err, code), deferred): |
2738 | - return deferred.callback((out, err, code)) |
2739 | + def callback(args, deferred): |
2740 | + return deferred.callback(args) |
2741 | |
2742 | return result.addCallback(callback, deferred) |
2743 | |
2744 | @@ -703,7 +707,7 @@ |
2745 | messages = global_store.get_messages_by_ids(not_sent) |
2746 | sent = [] |
2747 | for message_id, message in messages: |
2748 | - message = bpickle.loads(str(message)) |
2749 | + message = bpickle.loads(convert_buffer_to_string(message)) |
2750 | if message["type"] not in got_type: |
2751 | got_type.add(message["type"]) |
2752 | sent.append(message_id) |
2753 | |
2754 | === modified file 'landscape/package/skeleton.py' |
2755 | --- landscape/package/skeleton.py 2017-01-11 10:48:09 +0000 |
2756 | +++ landscape/package/skeleton.py 2017-03-10 15:29:37 +0000 |
2757 | @@ -2,6 +2,8 @@ |
2758 | |
2759 | import apt_pkg |
2760 | |
2761 | +from twisted.python.compat import unicode, _PY3 |
2762 | + |
2763 | |
2764 | PACKAGE = 1 << 0 |
2765 | PROVIDES = 1 << 1 |
2766 | @@ -146,7 +148,7 @@ |
2767 | skeleton.size = version.size |
2768 | if version.installed_size > 0: |
2769 | skeleton.installed_size = version.installed_size |
2770 | - if with_unicode: |
2771 | + if with_unicode and not _PY3: |
2772 | skeleton.section = skeleton.section.decode("utf-8") |
2773 | skeleton.summary = skeleton.summary.decode("utf-8") |
2774 | # Avoid double-decoding package descriptions in build_skeleton_apt, |
2775 | |
2776 | === modified file 'landscape/package/store.py' |
2777 | --- landscape/package/store.py 2012-05-09 19:33:57 +0000 |
2778 | +++ landscape/package/store.py 2017-03-10 15:29:37 +0000 |
2779 | @@ -6,7 +6,10 @@ |
2780 | except ImportError: |
2781 | from pysqlite2 import dbapi2 as sqlite3 |
2782 | |
2783 | -from landscape.lib import bpickle |
2784 | +from twisted.python.compat import iteritems, long |
2785 | +from twisted.python.compat import StringType as basestring |
2786 | + |
2787 | +from landscape.compat import convert_buffer_to_string, bpickle |
2788 | from landscape.lib.store import with_cursor |
2789 | |
2790 | |
2791 | @@ -40,14 +43,15 @@ |
2792 | |
2793 | @param hash_ids: a C{dict} of hash=>id mappings. |
2794 | """ |
2795 | - for hash, id in hash_ids.iteritems(): |
2796 | + for hash, id in iteritems(hash_ids): |
2797 | cursor.execute("REPLACE INTO hash VALUES (?, ?)", |
2798 | - (id, buffer(hash))) |
2799 | + (id, sqlite3.Binary(hash))) |
2800 | |
2801 | @with_cursor |
2802 | def get_hash_id(self, cursor, hash): |
2803 | """Return the id associated to C{hash}, or C{None} if not available.""" |
2804 | - cursor.execute("SELECT id FROM hash WHERE hash=?", (buffer(hash),)) |
2805 | + cursor.execute("SELECT id FROM hash WHERE hash=?", |
2806 | + (sqlite3.Binary(hash),)) |
2807 | value = cursor.fetchone() |
2808 | if value: |
2809 | return value[0] |
2810 | @@ -127,7 +131,7 @@ |
2811 | |
2812 | try: |
2813 | hash_id_store.check_sanity() |
2814 | - except InvalidHashIdDb, e: |
2815 | + except InvalidHashIdDb as e: |
2816 | # propagate the error |
2817 | raise e |
2818 | |
2819 | @@ -253,7 +257,7 @@ |
2820 | hashes = list(hashes) |
2821 | cursor.execute("INSERT INTO hash_id_request (hashes, timestamp)" |
2822 | " VALUES (?,?)", |
2823 | - (buffer(bpickle.dumps(hashes)), time.time())) |
2824 | + (sqlite3.Binary(bpickle.dumps(hashes)), time.time())) |
2825 | return HashIDRequest(self._db, cursor.lastrowid) |
2826 | |
2827 | @with_cursor |
2828 | @@ -276,8 +280,9 @@ |
2829 | @with_cursor |
2830 | def add_task(self, cursor, queue, data): |
2831 | data = bpickle.dumps(data) |
2832 | - cursor.execute("INSERT INTO task (queue, timestamp, data) " |
2833 | - "VALUES (?,?,?)", (queue, time.time(), buffer(data))) |
2834 | + cursor.execute( |
2835 | + "INSERT INTO task (queue, timestamp, data) VALUES (?,?,?)", |
2836 | + (queue, time.time(), sqlite3.Binary(data))) |
2837 | return PackageTask(self._db, cursor.lastrowid) |
2838 | |
2839 | @with_cursor |
2840 | @@ -307,7 +312,7 @@ |
2841 | @with_cursor |
2842 | def save_message(self, cursor, message): |
2843 | cursor.execute("INSERT INTO message (data) VALUES (?)", |
2844 | - (buffer(bpickle.dumps(message)),)) |
2845 | + (sqlite3.Binary(bpickle.dumps(message)),)) |
2846 | |
2847 | @with_cursor |
2848 | def get_message_ids(self, cursor): |
2849 | @@ -340,7 +345,7 @@ |
2850 | def hashes(self, cursor): |
2851 | cursor.execute("SELECT hashes FROM hash_id_request WHERE id=?", |
2852 | (self.id,)) |
2853 | - return bpickle.loads(str(cursor.fetchone()[0])) |
2854 | + return bpickle.loads(convert_buffer_to_string(cursor.fetchone()[0])) |
2855 | |
2856 | @with_cursor |
2857 | def _get_timestamp(self, cursor): |
2858 | @@ -389,7 +394,7 @@ |
2859 | |
2860 | self.queue = row[0] |
2861 | self.timestamp = row[1] |
2862 | - self.data = bpickle.loads(str(row[2])) |
2863 | + self.data = bpickle.loads(convert_buffer_to_string(row[2])) |
2864 | |
2865 | @with_cursor |
2866 | def remove(self, cursor): |
2867 | |
2868 | === modified file 'landscape/package/taskhandler.py' |
2869 | --- landscape/package/taskhandler.py 2016-06-16 23:11:55 +0000 |
2870 | +++ landscape/package/taskhandler.py 2017-03-10 15:29:37 +0000 |
2871 | @@ -214,7 +214,7 @@ |
2872 | |
2873 | try: |
2874 | lsb_release_info = parse_lsb_release(self.lsb_release_filename) |
2875 | - except IOError, error: |
2876 | + except IOError as error: |
2877 | logging.warning(warning % str(error)) |
2878 | return None |
2879 | try: |
2880 | @@ -276,8 +276,8 @@ |
2881 | init_logging(config, "-".join(word.lower() for word in words)) |
2882 | |
2883 | # Setup our umask for Apt to use, this needs to setup file permissions to |
2884 | - # 0644 so... |
2885 | - os.umask(022) |
2886 | + # 0o644 so... |
2887 | + os.umask(0o022) |
2888 | |
2889 | package_store = cls.package_store_class(config.store_filename) |
2890 | # Delay importing of the facades so that we don't |
2891 | |
2892 | === modified file 'landscape/package/tests/helpers.py' |
2893 | --- landscape/package/tests/helpers.py 2017-01-10 16:32:56 +0000 |
2894 | +++ landscape/package/tests/helpers.py 2017-03-10 15:29:37 +0000 |
2895 | @@ -301,9 +301,9 @@ |
2896 | "GadWR2ltRC651hGpxw4et/u8phTny3Vdfvy2dgAAAAAAAAAAANjRE6Lr2rEAKAAACg==") |
2897 | |
2898 | |
2899 | -HASH1 = base64.decodestring("/ezv4AefpJJ8DuYFSq4RiEHJYP4=") |
2900 | -HASH2 = base64.decodestring("glP4DwWOfMULm0AkRXYsH/exehc=") |
2901 | -HASH3 = base64.decodestring("NJM05mj86veaSInYxxqL1wahods=") |
2902 | +HASH1 = base64.decodestring(b"/ezv4AefpJJ8DuYFSq4RiEHJYP4=") |
2903 | +HASH2 = base64.decodestring(b"glP4DwWOfMULm0AkRXYsH/exehc=") |
2904 | +HASH3 = base64.decodestring(b"NJM05mj86veaSInYxxqL1wahods=") |
2905 | HASH_MINIMAL = "6\xce\x8f\x1bM\x82MWZ\x1a\xffjAc(\xdb(\xa1\x0eG" |
2906 | HASH_SIMPLE_RELATIONS = ( |
2907 | "'#\xab&k\xe6\xf5E\xcfB\x9b\xceO7\xe6\xec\xa9\xddY\xaa") |
2908 | |
2909 | === modified file 'landscape/package/tests/test_facade.py' |
2910 | --- landscape/package/tests/test_facade.py 2016-06-15 19:02:40 +0000 |
2911 | +++ landscape/package/tests/test_facade.py 2017-03-10 15:29:37 +0000 |
2912 | @@ -9,6 +9,8 @@ |
2913 | from aptsources.sourceslist import SourcesList |
2914 | from apt.cache import LockFailedException |
2915 | |
2916 | +from twisted.python.compat import unicode |
2917 | + |
2918 | from landscape.lib.fs import read_file, create_file |
2919 | from landscape.package.facade import ( |
2920 | TransactionError, DependencyError, ChannelError, AptFacade, |
2921 | |
2922 | === modified file 'landscape/package/tests/test_releaseupgrader.py' |
2923 | --- landscape/package/tests/test_releaseupgrader.py 2016-06-16 16:26:32 +0000 |
2924 | +++ landscape/package/tests/test_releaseupgrader.py 2017-03-10 15:29:37 +0000 |
2925 | @@ -3,9 +3,11 @@ |
2926 | import signal |
2927 | import tarfile |
2928 | import unittest |
2929 | +from unittest import skipIf |
2930 | |
2931 | from twisted.internet import reactor |
2932 | from twisted.internet.defer import succeed, fail, Deferred |
2933 | +from twisted.python.compat import _PY3 |
2934 | |
2935 | from landscape.lib.gpg import InvalidGPGSignature |
2936 | from landscape.lib.fetch import HTTPCodeError |
2937 | @@ -284,7 +286,8 @@ |
2938 | "stderr\n\n" |
2939 | "=== main.log ===\n\n" |
2940 | "long log\n\n") |
2941 | - |
2942 | + |
2943 | + @skipIf(_PY3, 'Takes long with Python3, probably unclean Reactor') |
2944 | def test_upgrade(self): |
2945 | """ |
2946 | The L{ReleaseUpgrader.upgrade} method spawns the appropropriate |
2947 | @@ -300,7 +303,7 @@ |
2948 | "echo PWD=$PWD\n" |
2949 | "echo out\n") |
2950 | fd.close() |
2951 | - os.chmod(upgrade_tool_filename, 0755) |
2952 | + os.chmod(upgrade_tool_filename, 0o755) |
2953 | env_backup = os.environ.copy() |
2954 | os.environ.clear() |
2955 | os.environ.update({"FOO": "bar"}) |
2956 | @@ -336,6 +339,7 @@ |
2957 | |
2958 | return deferred.addBoth(cleanup) |
2959 | |
2960 | + @skipIf(_PY3, 'Takes long with Python3, probably unclean Reactor') |
2961 | def test_upgrade_with_env_variables(self): |
2962 | """ |
2963 | The L{ReleaseUpgrader.upgrade} method optionally sets environment |
2964 | @@ -350,7 +354,7 @@ |
2965 | "echo RELEASE_UPRADER_ALLOW_THIRD_PARTY=" |
2966 | "$RELEASE_UPRADER_ALLOW_THIRD_PARTY\n") |
2967 | fd.close() |
2968 | - os.chmod(upgrade_tool_filename, 0755) |
2969 | + os.chmod(upgrade_tool_filename, 0o755) |
2970 | env_backup = os.environ.copy() |
2971 | os.environ.clear() |
2972 | deferred = Deferred() |
2973 | @@ -397,7 +401,7 @@ |
2974 | "echo err >&2\n" |
2975 | "exit 3") |
2976 | fd.close() |
2977 | - os.chmod(upgrade_tool_filename, 0755) |
2978 | + os.chmod(upgrade_tool_filename, 0o755) |
2979 | |
2980 | deferred = Deferred() |
2981 | |
2982 | @@ -452,7 +456,7 @@ |
2983 | " while True:\n" |
2984 | " time.sleep(2)\n" % child_pid_filename) |
2985 | fd.close() |
2986 | - os.chmod(upgrade_tool_filename, 0755) |
2987 | + os.chmod(upgrade_tool_filename, 0o755) |
2988 | os.environ.clear() |
2989 | os.environ.update({"FOO": "bar"}) |
2990 | deferred = Deferred() |
2991 | @@ -495,6 +499,8 @@ |
2992 | |
2993 | return deferred.addBoth(cleanup) |
2994 | |
2995 | + |
2996 | + @skipIf(_PY3, 'Takes long with Python3, probably unclean Reactor') |
2997 | def test_finish(self): |
2998 | """ |
2999 | The L{ReleaseUpgrader.finish} method wipes the upgrade-tool directory |
3000 | @@ -508,7 +514,7 @@ |
3001 | reporter_filename = self.makeFile("#!/bin/sh\n" |
3002 | "echo $@\n" |
3003 | "echo $(pwd)\n") |
3004 | - os.chmod(reporter_filename, 0755) |
3005 | + os.chmod(reporter_filename, 0o755) |
3006 | |
3007 | deferred = Deferred() |
3008 | |
3009 | @@ -518,7 +524,8 @@ |
3010 | find_reporter_mock.return_value = reporter_filename |
3011 | result = self.upgrader.finish() |
3012 | |
3013 | - def check_result((out, err, code)): |
3014 | + def check_result(args): |
3015 | + out, err, code = args |
3016 | self.assertFalse(os.path.exists(upgrade_tool_directory)) |
3017 | self.assertEqual(out, "--force-apt-update\n%s\n" |
3018 | % os.getcwd()) |
3019 | @@ -582,7 +589,7 @@ |
3020 | configuration file the release-upgrader was called with. |
3021 | """ |
3022 | reporter_filename = self.makeFile("#!/bin/sh\necho $@\n") |
3023 | - os.chmod(reporter_filename, 0755) |
3024 | + os.chmod(reporter_filename, 0o755) |
3025 | self.config.config = "/some/config" |
3026 | |
3027 | deferred = Deferred() |
3028 | @@ -593,7 +600,8 @@ |
3029 | find_reporter_mock.return_value = reporter_filename |
3030 | result = self.upgrader.finish() |
3031 | |
3032 | - def check_result((out, err, code)): |
3033 | + def check_result(args): |
3034 | + out, err, code = args |
3035 | self.assertEqual(out, "--force-apt-update " |
3036 | "--config=/some/config\n") |
3037 | self.assertEqual(err, "") |
3038 | |
3039 | === modified file 'landscape/package/tests/test_reporter.py' |
3040 | --- landscape/package/tests/test_reporter.py 2016-08-04 16:13:11 +0000 |
3041 | +++ landscape/package/tests/test_reporter.py 2017-03-10 15:29:37 +0000 |
3042 | @@ -10,7 +10,6 @@ |
3043 | |
3044 | from landscape.lib.fs import create_file, touch_file |
3045 | from landscape.lib.fetch import FetchError |
3046 | -from landscape.lib import bpickle |
3047 | from landscape.package.store import ( |
3048 | PackageStore, UnknownHashIDRequest, FakePackageStore) |
3049 | from landscape.package.reporter import ( |
3050 | @@ -25,6 +24,8 @@ |
3051 | LandscapeTest, BrokerServiceHelper, EnvironSaverHelper) |
3052 | from landscape.reactor import FakeReactor |
3053 | |
3054 | +from landscape.compat import convert_buffer_to_string, bpickle |
3055 | + |
3056 | SAMPLE_LSB_RELEASE = "DISTRIB_CODENAME=codename\n" |
3057 | |
3058 | |
3059 | @@ -89,7 +90,7 @@ |
3060 | "echo -n '%s'\n" |
3061 | "echo -n '%s' >&2\n" |
3062 | "exit %d" % (out, err, code)) |
3063 | - os.chmod(self.reporter.apt_update_filename, 0755) |
3064 | + os.chmod(self.reporter.apt_update_filename, 0o755) |
3065 | |
3066 | def test_set_package_ids_with_all_known(self): |
3067 | self.store.add_hash_id_request(["hash1", "hash2"]) |
3068 | @@ -1123,7 +1124,8 @@ |
3069 | def do_test(): |
3070 | result = self.reporter.run_apt_update() |
3071 | |
3072 | - def callback((out, err, code)): |
3073 | + def callback(args): |
3074 | + out, err, code = args |
3075 | self.assertEqual("output", out) |
3076 | self.assertEqual("error", err) |
3077 | self.assertEqual(0, code) |
3078 | @@ -1149,7 +1151,8 @@ |
3079 | |
3080 | result = self.reporter.run_apt_update() |
3081 | |
3082 | - def callback((out, err, code)): |
3083 | + def callback(args): |
3084 | + out, err, code = args |
3085 | self.assertEqual("output", out) |
3086 | |
3087 | result.addCallback(callback) |
3088 | @@ -1169,7 +1172,8 @@ |
3089 | |
3090 | result = self.reporter.run_apt_update() |
3091 | |
3092 | - def callback((out, err, code)): |
3093 | + def callback(args): |
3094 | + out, err, code = args |
3095 | self.assertEqual("output", out) |
3096 | |
3097 | result.addCallback(callback) |
3098 | @@ -1188,7 +1192,8 @@ |
3099 | |
3100 | result = self.reporter.run_apt_update() |
3101 | |
3102 | - def callback((out, err, code)): |
3103 | + def callback(args): |
3104 | + out, err, code = args |
3105 | self.assertEqual("output", out) |
3106 | self.assertEqual("error", err) |
3107 | self.assertEqual(2, code) |
3108 | @@ -1219,7 +1224,8 @@ |
3109 | |
3110 | result = self.reporter.run_apt_update() |
3111 | |
3112 | - def callback((out, err, code)): |
3113 | + def callback(args): |
3114 | + out, err, code = args |
3115 | self.assertEqual("", out) |
3116 | self.assertEqual("", err) |
3117 | self.assertEqual(100, code) |
3118 | @@ -1255,7 +1261,8 @@ |
3119 | |
3120 | result = self.reporter.run_apt_update() |
3121 | |
3122 | - def callback((out, err, code)): |
3123 | + def callback(args): |
3124 | + out, err, code = args |
3125 | self.assertEqual("output", out) |
3126 | self.assertEqual("error", err) |
3127 | self.assertEqual(0, code) |
3128 | @@ -1390,7 +1397,8 @@ |
3129 | def do_test(): |
3130 | result = self.reporter.run_apt_update() |
3131 | |
3132 | - def callback((out, err, code)): |
3133 | + def callback(args): |
3134 | + out, err, code = args |
3135 | self.assertEqual("", out) |
3136 | self.assertEqual("", err) |
3137 | self.assertEqual(0, code) |
3138 | @@ -1430,7 +1438,8 @@ |
3139 | def do_test(): |
3140 | result = self.reporter.run_apt_update() |
3141 | |
3142 | - def callback((out, err, code)): |
3143 | + def callback(args): |
3144 | + out, err, code = args |
3145 | self.assertEqual("", out) |
3146 | self.assertEqual("", err) |
3147 | self.assertEqual(0, code) |
3148 | @@ -1728,7 +1737,7 @@ |
3149 | message_store.set_accepted_types(["package-reporter-result"]) |
3150 | self.reporter.apt_update_filename = self.makeFile( |
3151 | "#!/bin/sh\necho -n error >&2\necho -n output\nexit 0") |
3152 | - os.chmod(self.reporter.apt_update_filename, 0755) |
3153 | + os.chmod(self.reporter.apt_update_filename, 0o755) |
3154 | deferred = Deferred() |
3155 | |
3156 | def do_test(): |
3157 | @@ -1745,7 +1754,8 @@ |
3158 | "SELECT id, data FROM message").fetchall()) |
3159 | self.assertEqual(1, len(stored)) |
3160 | self.assertEqual(1, stored[0][0]) |
3161 | - self.assertEqual(message, bpickle.loads(str(stored[0][1]))) |
3162 | + self.assertEqual(message, |
3163 | + bpickle.loads(convert_buffer_to_string(stored[0][1]))) |
3164 | result.addCallback(callback) |
3165 | result.chainDeferred(deferred) |
3166 | |
3167 | |
3168 | === modified file 'landscape/package/tests/test_skeleton.py' |
3169 | --- landscape/package/tests/test_skeleton.py 2017-01-12 08:01:31 +0000 |
3170 | +++ landscape/package/tests/test_skeleton.py 2017-03-10 15:29:37 +0000 |
3171 | @@ -13,6 +13,8 @@ |
3172 | HASH_OR_RELATIONS) |
3173 | from landscape.tests.helpers import LandscapeTest |
3174 | |
3175 | +from twisted.python.compat import unicode |
3176 | + |
3177 | |
3178 | class SkeletonTestHelper(object): |
3179 | """A helper to set up a repository for the skeleton tests.""" |
3180 | |
3181 | === modified file 'landscape/package/tests/test_store.py' |
3182 | --- landscape/package/tests/test_store.py 2016-06-16 00:08:40 +0000 |
3183 | +++ landscape/package/tests/test_store.py 2017-03-10 15:29:37 +0000 |
3184 | @@ -152,7 +152,7 @@ |
3185 | store_filename = junk_db_factory() |
3186 | try: |
3187 | self.store1.add_hash_id_db(store_filename) |
3188 | - except InvalidHashIdDb, e: |
3189 | + except InvalidHashIdDb as e: |
3190 | self.assertEqual(str(e), store_filename) |
3191 | else: |
3192 | self.fail() |
3193 | @@ -547,7 +547,7 @@ |
3194 | func2.store2 = PackageStore(self.filename) |
3195 | try: |
3196 | func2.store2.add_task("reporter", "data") |
3197 | - except Exception, e: |
3198 | + except Exception as e: |
3199 | error.append(str(e)) |
3200 | |
3201 | for func in [func1, func2]: |
3202 | |
3203 | === modified file 'landscape/package/tests/test_taskhandler.py' |
3204 | --- landscape/package/tests/test_taskhandler.py 2016-06-16 20:33:26 +0000 |
3205 | +++ landscape/package/tests/test_taskhandler.py 2017-03-10 15:29:37 +0000 |
3206 | @@ -379,7 +379,7 @@ |
3207 | |
3208 | # We also expect the umask to be set appropriately before running the |
3209 | # commands |
3210 | - umask.assert_called_once_with(022) |
3211 | + umask.assert_called_once_with(0o22) |
3212 | |
3213 | return result.addCallback(assert_task_handler) |
3214 | |
3215 | @@ -389,7 +389,7 @@ |
3216 | |
3217 | try: |
3218 | run_task_handler(PackageTaskHandler, ["-c", self.config_filename]) |
3219 | - except SystemExit, e: |
3220 | + except SystemExit as e: |
3221 | self.assertIn("default is already running", str(e)) |
3222 | else: |
3223 | self.fail("SystemExit not raised") |
3224 | @@ -400,7 +400,7 @@ |
3225 | try: |
3226 | run_task_handler(PackageTaskHandler, |
3227 | ["-c", self.config_filename, "--quiet"]) |
3228 | - except SystemExit, e: |
3229 | + except SystemExit as e: |
3230 | self.assertEqual(str(e), "") |
3231 | else: |
3232 | self.fail("SystemExit not raised") |
3233 | |
3234 | === modified file 'landscape/reactor.py' |
3235 | --- landscape/reactor.py 2013-07-15 15:25:08 +0000 |
3236 | +++ landscape/reactor.py 2017-03-10 15:29:37 +0000 |
3237 | @@ -399,14 +399,14 @@ |
3238 | self._current_time = call[0] |
3239 | try: |
3240 | call[1](*call[2], **call[3]) |
3241 | - except Exception, e: |
3242 | + except Exception as e: |
3243 | logging.exception(e) |
3244 | self._current_time += seconds |
3245 | |
3246 | def _in_thread(self, callback, errback, f, args, kwargs): |
3247 | try: |
3248 | result = f(*args, **kwargs) |
3249 | - except Exception, e: |
3250 | + except Exception as e: |
3251 | exc_info = sys.exc_info() |
3252 | if errback is None: |
3253 | self.call_in_main(logging.error, e, exc_info=exc_info) |
3254 | @@ -420,7 +420,7 @@ |
3255 | while self._threaded_callbacks: |
3256 | try: |
3257 | self._threaded_callbacks.pop(0)() |
3258 | - except Exception, e: |
3259 | + except Exception as e: |
3260 | logging.exception(e) |
3261 | |
3262 | def _hook_threaded_callbacks(self): |
3263 | |
3264 | === modified file 'landscape/schema.py' |
3265 | --- landscape/schema.py 2014-07-16 17:15:13 +0000 |
3266 | +++ landscape/schema.py 2017-03-10 15:29:37 +0000 |
3267 | @@ -1,4 +1,5 @@ |
3268 | """A schema system. Yes. Another one!""" |
3269 | +from twisted.python.compat import iteritems, unicode, long |
3270 | |
3271 | |
3272 | class InvalidError(Exception): |
3273 | @@ -83,10 +84,10 @@ |
3274 | self.encoding = encoding |
3275 | |
3276 | def coerce(self, value): |
3277 | - if isinstance(value, str): |
3278 | + if isinstance(value, bytes): |
3279 | try: |
3280 | value = value.decode(self.encoding) |
3281 | - except UnicodeDecodeError, e: |
3282 | + except UnicodeDecodeError as e: |
3283 | raise InvalidError("%r can't be decoded: %s" % (value, str(e))) |
3284 | if not isinstance(value, unicode): |
3285 | raise InvalidError("%r isn't a unicode" % (value,)) |
3286 | @@ -108,7 +109,7 @@ |
3287 | for i, subvalue in enumerate(value): |
3288 | try: |
3289 | new_list[i] = self.schema.coerce(subvalue) |
3290 | - except InvalidError, e: |
3291 | + except InvalidError as e: |
3292 | raise InvalidError( |
3293 | "%r could not coerce with %s: %s" |
3294 | % (subvalue, self.schema, e)) |
3295 | @@ -155,13 +156,13 @@ |
3296 | new_dict = {} |
3297 | if not isinstance(value, dict): |
3298 | raise InvalidError("%r is not a dict." % (value,)) |
3299 | - for k, v in value.iteritems(): |
3300 | + for k, v in iteritems(value): |
3301 | if k not in self.schema: |
3302 | raise InvalidError("%r is not a valid key as per %r" |
3303 | % (k, self.schema)) |
3304 | try: |
3305 | new_dict[k] = self.schema[k].coerce(v) |
3306 | - except InvalidError, e: |
3307 | + except InvalidError as e: |
3308 | raise InvalidError( |
3309 | "Value of %r key of dict %r could not coerce with %s: %s" |
3310 | % (k, value, self.schema[k], e)) |
3311 | |
3312 | === modified file 'landscape/sysinfo/deployment.py' |
3313 | --- landscape/sysinfo/deployment.py 2014-03-26 12:33:14 +0000 |
3314 | +++ landscape/sysinfo/deployment.py 2017-03-10 15:29:37 +0000 |
3315 | @@ -94,7 +94,7 @@ |
3316 | """ |
3317 | try: |
3318 | setup_logging() |
3319 | - except IOError, e: |
3320 | + except IOError as e: |
3321 | sys.exit("Unable to setup logging. %s" % e) |
3322 | |
3323 | if sysinfo is None: |
3324 | @@ -107,8 +107,8 @@ |
3325 | sysinfo.add(plugin) |
3326 | |
3327 | def show_output(result): |
3328 | - print format_sysinfo(sysinfo.get_headers(), sysinfo.get_notes(), |
3329 | - sysinfo.get_footnotes(), indent=" ") |
3330 | + print(format_sysinfo(sysinfo.get_headers(), sysinfo.get_notes(), |
3331 | + sysinfo.get_footnotes(), indent=" ")) |
3332 | |
3333 | def run_sysinfo(): |
3334 | return sysinfo.run().addCallback(show_output) |
3335 | |
3336 | === modified file 'landscape/sysinfo/tests/test_disk.py' |
3337 | --- landscape/sysinfo/tests/test_disk.py 2011-07-05 05:09:11 +0000 |
3338 | +++ landscape/sysinfo/tests/test_disk.py 2017-03-10 15:29:37 +0000 |
3339 | @@ -1,7 +1,9 @@ |
3340 | +import os |
3341 | + |
3342 | from twisted.internet.defer import Deferred |
3343 | |
3344 | +from landscape.sysinfo.disk import Disk, format_megabytes |
3345 | from landscape.sysinfo.sysinfo import SysInfoPluginRegistry |
3346 | -from landscape.sysinfo.disk import Disk, format_megabytes |
3347 | from landscape.tests.helpers import LandscapeTest |
3348 | |
3349 | |
3350 | @@ -21,8 +23,8 @@ |
3351 | fs="ext3", device=None): |
3352 | if device is None: |
3353 | device = "/dev/" + point.replace("/", "_") |
3354 | - self.stat_results[point] = (block_size, 0, capacity, unused, |
3355 | - 0, 0, 0, 0, 0) |
3356 | + self.stat_results[point] = os.statvfs_result( |
3357 | + (block_size, 0, capacity, unused, 0, 0, 0, 0, 0, 0)) |
3358 | f = open(self.mount_file, "a") |
3359 | f.write("/dev/%s %s %s rw 0 0\n" % (device, point, fs)) |
3360 | f.close() |
3361 | |
3362 | === modified file 'landscape/sysinfo/tests/test_sysinfo.py' |
3363 | --- landscape/sysinfo/tests/test_sysinfo.py 2016-06-15 20:32:14 +0000 |
3364 | +++ landscape/sysinfo/tests/test_sysinfo.py 2017-03-10 15:29:37 +0000 |
3365 | @@ -1,12 +1,12 @@ |
3366 | -from cStringIO import StringIO |
3367 | from logging import getLogger, StreamHandler |
3368 | import mock |
3369 | import os |
3370 | |
3371 | from twisted.internet.defer import Deferred, succeed, fail |
3372 | |
3373 | +from landscape.compat import StringIO |
3374 | +from landscape.plugin import PluginRegistry |
3375 | from landscape.sysinfo.sysinfo import SysInfoPluginRegistry, format_sysinfo |
3376 | -from landscape.plugin import PluginRegistry |
3377 | from landscape.tests.helpers import LandscapeTest |
3378 | |
3379 | |
3380 | |
3381 | === modified file 'landscape/tests/clock.py' |
3382 | --- landscape/tests/clock.py 2008-06-10 10:56:01 +0000 |
3383 | +++ landscape/tests/clock.py 2017-03-10 15:29:37 +0000 |
3384 | @@ -31,10 +31,13 @@ |
3385 | C{seconds} argument until after Twisted 2.2. |
3386 | """ |
3387 | |
3388 | +import functools |
3389 | |
3390 | from twisted.internet import error |
3391 | from twisted.python.runtime import seconds as runtimeSeconds |
3392 | from twisted.python import reflect |
3393 | +from twisted.python.compat import iteritems |
3394 | + |
3395 | import traceback |
3396 | |
3397 | |
3398 | @@ -71,7 +74,7 @@ |
3399 | self.calls.remove, |
3400 | lambda c: None, |
3401 | self.seconds)) |
3402 | - self.calls.sort(lambda a, b: cmp(a.getTime(), b.getTime())) |
3403 | + self.calls.sort(key=lambda a: a.getTime()) |
3404 | return self.calls[-1] |
3405 | |
3406 | |
3407 | @@ -246,7 +249,9 @@ |
3408 | if self.kw: |
3409 | L.append(", ") |
3410 | if self.kw: |
3411 | - L.append(", ".join(['%s=%s' % (k, reflect.safe_repr(v)) for (k, v) in self.kw.iteritems()])) |
3412 | + L.append(", ".join([ |
3413 | + '%s=%s' % (k, reflect.safe_repr(v)) |
3414 | + for (k, v) in iteritems(self.kw)])) |
3415 | L.append(")") |
3416 | |
3417 | if self.debug: |
3418 | |
3419 | === modified file 'landscape/tests/helpers.py' |
3420 | --- landscape/tests/helpers.py 2017-01-10 13:28:12 +0000 |
3421 | +++ landscape/tests/helpers.py 2017-03-10 15:29:37 +0000 |
3422 | @@ -1,5 +1,3 @@ |
3423 | -from cStringIO import StringIO |
3424 | -from ConfigParser import ConfigParser |
3425 | import logging |
3426 | import shutil |
3427 | import pprint |
3428 | @@ -12,9 +10,14 @@ |
3429 | |
3430 | from logging import Handler, ERROR, Formatter |
3431 | from twisted.trial.unittest import TestCase |
3432 | +from twisted.python.compat import StringType as basestring |
3433 | +from twisted.python.compat import _PY3 |
3434 | from twisted.python.failure import Failure |
3435 | from twisted.internet.defer import Deferred |
3436 | |
3437 | +from landscape.compat import ConfigParser |
3438 | +from landscape.compat import stringio, cstringio |
3439 | + |
3440 | from landscape.tests.subunit import run_isolated |
3441 | from landscape.watchdog import bootstrap_list |
3442 | |
3443 | @@ -186,11 +189,11 @@ |
3444 | and comments may be different but the actual parameters and sections |
3445 | must be the same. |
3446 | """ |
3447 | - first_fp = StringIO(first) |
3448 | + first_fp = cstringio(first) |
3449 | first_parser = ConfigParser() |
3450 | first_parser.readfp(first_fp) |
3451 | |
3452 | - second_fp = StringIO(second) |
3453 | + second_fp = cstringio(second) |
3454 | second_parser = ConfigParser() |
3455 | second_parser.readfp(second_fp) |
3456 | |
3457 | @@ -216,7 +219,7 @@ |
3458 | return persist_filename |
3459 | |
3460 | def makeFile(self, content=None, suffix="", prefix="tmp", basename=None, |
3461 | - dirname=None, path=None): |
3462 | + dirname=None, path=None, mode="w"): |
3463 | """Create a temporary file and return the path to it. |
3464 | |
3465 | @param content: Initial content for the file. |
3466 | @@ -237,9 +240,8 @@ |
3467 | if content is None: |
3468 | os.unlink(path) |
3469 | if content is not None: |
3470 | - file = open(path, "w") |
3471 | - file.write(content) |
3472 | - file.close() |
3473 | + with open(path, mode) as file: |
3474 | + file.write(content) |
3475 | self.addCleanup(self._clean_file, path) |
3476 | return path |
3477 | |
3478 | @@ -324,7 +326,7 @@ |
3479 | self.error_handler = ErrorHandler() |
3480 | test_case.log_helper = self |
3481 | test_case.logger = logger = logging.getLogger() |
3482 | - test_case.logfile = StringIO() |
3483 | + test_case.logfile = cstringio() |
3484 | handler = logging.StreamHandler(test_case.logfile) |
3485 | format = ("%(levelname)8s: %(message)s") |
3486 | handler.setFormatter(logging.Formatter(format)) |
3487 | @@ -480,7 +482,7 @@ |
3488 | |
3489 | def __init__(self, output, return_codes=None): |
3490 | self.output = output |
3491 | - self.stdout = StringIO(output) |
3492 | + self.stdout = cstringio(output) |
3493 | self.popen_inputs = [] |
3494 | self.return_codes = return_codes |
3495 | |
3496 | @@ -500,13 +502,12 @@ |
3497 | class StandardIOHelper(object): |
3498 | |
3499 | def set_up(self, test_case): |
3500 | - from StringIO import StringIO |
3501 | - |
3502 | test_case.old_stdout = sys.stdout |
3503 | test_case.old_stdin = sys.stdin |
3504 | - test_case.stdout = sys.stdout = StringIO() |
3505 | - test_case.stdin = sys.stdin = StringIO() |
3506 | - test_case.stdin.encoding = "UTF-8" |
3507 | + test_case.stdout = sys.stdout = stringio() |
3508 | + test_case.stdin = sys.stdin = stringio() |
3509 | + if not _PY3: |
3510 | + test_case.stdin.encoding = "UTF-8" |
3511 | |
3512 | def tear_down(self, test_case): |
3513 | sys.stdout = test_case.old_stdout |
3514 | |
3515 | === modified file 'landscape/tests/subunit.py' |
3516 | --- landscape/tests/subunit.py 2009-11-13 15:47:51 +0000 |
3517 | +++ landscape/tests/subunit.py 2017-03-10 15:29:37 +0000 |
3518 | @@ -16,13 +16,14 @@ |
3519 | # along with this program; if not, write to the Free Software |
3520 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
3521 | # |
3522 | - |
3523 | import os |
3524 | -from StringIO import StringIO |
3525 | import subprocess |
3526 | import sys |
3527 | import unittest |
3528 | |
3529 | +from landscape.compat import StringIO |
3530 | + |
3531 | + |
3532 | def test_suite(): |
3533 | import subunit.tests |
3534 | return subunit.tests.test_suite() |
3535 | |
3536 | === modified file 'landscape/tests/test_configuration.py' |
3537 | --- landscape/tests/test_configuration.py 2017-03-07 16:47:17 +0000 |
3538 | +++ landscape/tests/test_configuration.py 2017-03-10 15:29:37 +0000 |
3539 | @@ -1,15 +1,16 @@ |
3540 | from __future__ import print_function |
3541 | |
3542 | +import mock |
3543 | from functools import partial |
3544 | -from ConfigParser import ConfigParser |
3545 | -from cStringIO import StringIO |
3546 | import os |
3547 | import sys |
3548 | import unittest |
3549 | |
3550 | -import mock |
3551 | from twisted.internet.defer import succeed, fail, Deferred |
3552 | +from twisted.python.compat import iteritems |
3553 | |
3554 | +from landscape.compat import ConfigParser |
3555 | +from landscape.compat import StringIO |
3556 | from landscape.broker.registration import RegistrationError |
3557 | from landscape.broker.tests.helpers import ( |
3558 | RemoteBrokerHelper, BrokerConfigurationHelper) |
3559 | @@ -776,8 +777,8 @@ |
3560 | |
3561 | config = self.get_config([], data_path=client_path) |
3562 | bootstrap_tree(config) |
3563 | - mock_chmod.assert_any_call(client_path, 0755) |
3564 | - mock_chmod.assert_called_with(annotations_path, 0755) |
3565 | + mock_chmod.assert_any_call(client_path, 0o755) |
3566 | + mock_chmod.assert_called_with(annotations_path, 0o755) |
3567 | self.assertTrue(os.path.isdir(client_path)) |
3568 | self.assertTrue(os.path.isdir(annotations_path)) |
3569 | |
3570 | @@ -840,7 +841,7 @@ |
3571 | "Access group [webservers]: ": u"databases", |
3572 | "Tags [london, server]: ": u"glasgow, laptop", |
3573 | } |
3574 | - for key, value in fixtures.iteritems(): |
3575 | + for key, value in iteritems(fixtures): |
3576 | if key in prompt: |
3577 | return value |
3578 | raise KeyError("Couldn't find answer for {}".format(prompt)) |
3579 | @@ -848,7 +849,7 @@ |
3580 | def side_effect_getpass(prompt): |
3581 | fixtures = {"Account registration key:": "New Password", |
3582 | "Please confirm:": "New Password"} |
3583 | - for key, value in fixtures.iteritems(): |
3584 | + for key, value in iteritems(fixtures): |
3585 | if key in prompt: |
3586 | return value |
3587 | raise KeyError("Couldn't find answer for {}".format(prompt)) |
3588 | @@ -1440,7 +1441,7 @@ |
3589 | try: |
3590 | self.get_config(["--config", config_filename, "--silent", |
3591 | "--import", import_filename]) |
3592 | - except ImportOptionError, error: |
3593 | + except ImportOptionError as error: |
3594 | self.assertEqual(str(error), |
3595 | "Nothing to import at %s." % import_filename) |
3596 | else: |
3597 | @@ -1454,7 +1455,7 @@ |
3598 | try: |
3599 | self.get_config(["--config", config_filename, "--silent", |
3600 | "--import", import_filename]) |
3601 | - except ImportOptionError, error: |
3602 | + except ImportOptionError as error: |
3603 | self.assertEqual(str(error), |
3604 | "File %s doesn't exist." % import_filename) |
3605 | else: |
3606 | @@ -1471,7 +1472,7 @@ |
3607 | try: |
3608 | self.get_config(["--config", config_filename, "--silent", |
3609 | "--import", import_filename]) |
3610 | - except ImportOptionError, error: |
3611 | + except ImportOptionError as error: |
3612 | self.assertEqual(str(error), |
3613 | "Nothing to import at %s." % import_filename) |
3614 | else: |
3615 | @@ -1486,7 +1487,7 @@ |
3616 | try: |
3617 | self.get_config(["--config", config_filename, "--silent", |
3618 | "--import", import_filename]) |
3619 | - except ImportOptionError, error: |
3620 | + except ImportOptionError as error: |
3621 | self.assertIn("Nothing to import at %s" % import_filename, |
3622 | str(error)) |
3623 | else: |
3624 | @@ -1500,7 +1501,7 @@ |
3625 | import_filename = self.makeFile( |
3626 | "[client]\nfoo=bar", basename="import_config") |
3627 | # Remove read permissions |
3628 | - os.chmod(import_filename, os.stat(import_filename).st_mode - 0444) |
3629 | + os.chmod(import_filename, os.stat(import_filename).st_mode - 0o444) |
3630 | error = self.assertRaises( |
3631 | ImportOptionError, self.get_config, ["--import", import_filename]) |
3632 | expected_message = ("Couldn't read configuration from %s." % |
3633 | @@ -1635,7 +1636,7 @@ |
3634 | try: |
3635 | self.get_config(["--config", config_filename, "--silent", |
3636 | "--import", "https://config.url"]) |
3637 | - except ImportOptionError, error: |
3638 | + except ImportOptionError as error: |
3639 | self.assertEqual(str(error), |
3640 | "Couldn't download configuration from " |
3641 | "https://config.url: Server " |
3642 | @@ -1657,7 +1658,7 @@ |
3643 | try: |
3644 | self.get_config(["--config", config_filename, "--silent", |
3645 | "--import", "https://config.url"]) |
3646 | - except ImportOptionError, error: |
3647 | + except ImportOptionError as error: |
3648 | self.assertEqual(str(error), |
3649 | "Couldn't download configuration from " |
3650 | "https://config.url: Error 60: pycurl message") |
3651 | @@ -1674,7 +1675,7 @@ |
3652 | # Use a command line option as well to test the precedence. |
3653 | try: |
3654 | self.get_config(["--silent", "--import", "https://config.url"]) |
3655 | - except ImportOptionError, error: |
3656 | + except ImportOptionError as error: |
3657 | self.assertEqual(str(error), |
3658 | "Nothing to import at https://config.url.") |
3659 | else: |
3660 | @@ -1691,7 +1692,7 @@ |
3661 | # Use a command line option as well to test the precedence. |
3662 | try: |
3663 | self.get_config(["--silent", "--import", "https://config.url"]) |
3664 | - except ImportOptionError, error: |
3665 | + except ImportOptionError as error: |
3666 | self.assertEqual("Nothing to import at https://config.url.", |
3667 | str(error)) |
3668 | else: |
3669 | |
3670 | === modified file 'landscape/tests/test_deployment.py' |
3671 | --- landscape/tests/test_deployment.py 2016-06-15 16:35:06 +0000 |
3672 | +++ landscape/tests/test_deployment.py 2017-03-10 15:29:37 +0000 |
3673 | @@ -1,8 +1,9 @@ |
3674 | -import os |
3675 | from optparse import OptionParser |
3676 | -from StringIO import StringIO |
3677 | from textwrap import dedent |
3678 | +import mock |
3679 | +import os |
3680 | |
3681 | +from landscape.compat import StringIO |
3682 | from landscape.lib.fs import read_file, create_file |
3683 | |
3684 | from landscape.deployment import ( |
3685 | @@ -10,7 +11,6 @@ |
3686 | from landscape.manager.config import ManagerConfiguration |
3687 | |
3688 | from landscape.tests.helpers import LandscapeTest, LogKeeperHelper |
3689 | -import mock |
3690 | |
3691 | |
3692 | class BabbleConfiguration(Configuration): |
3693 | @@ -592,7 +592,7 @@ |
3694 | default_filename2) |
3695 | |
3696 | # If it is readable, than return the first default configuration file. |
3697 | - os.chmod(default_filename1, 0644) |
3698 | + os.chmod(default_filename1, 0o644) |
3699 | self.assertEqual(self.config.get_config_filename(), |
3700 | default_filename1) |
3701 | |
3702 | |
3703 | === modified file 'landscape/tests/test_reactor.py' |
3704 | --- landscape/tests/test_reactor.py 2013-07-10 09:17:14 +0000 |
3705 | +++ landscape/tests/test_reactor.py 2017-03-10 15:29:37 +0000 |
3706 | @@ -1,7 +1,7 @@ |
3707 | -import thread |
3708 | import types |
3709 | import time |
3710 | |
3711 | +from landscape.compat import thread |
3712 | from landscape.reactor import FakeReactor, LandscapeReactor |
3713 | from landscape.tests.helpers import LandscapeTest |
3714 | |
3715 | @@ -153,7 +153,10 @@ |
3716 | def test_events_result(self): |
3717 | reactor = self.get_reactor() |
3718 | |
3719 | - generator = iter([1, 2, 3]).next |
3720 | + iterable = iter([1, 2, 3]) |
3721 | + |
3722 | + def generator(): |
3723 | + return next(iterable) |
3724 | |
3725 | reactor.call_on("foobar", generator) |
3726 | reactor.call_on("foobar", generator) |
3727 | |
3728 | === modified file 'landscape/tests/test_schema.py' |
3729 | --- landscape/tests/test_schema.py 2013-10-25 21:23:47 +0000 |
3730 | +++ landscape/tests/test_schema.py 2017-03-10 15:29:37 +0000 |
3731 | @@ -4,6 +4,8 @@ |
3732 | InvalidError, Constant, Bool, Int, Float, Bytes, Unicode, List, KeyDict, |
3733 | Dict, Tuple, Any, Message) |
3734 | |
3735 | +from twisted.python.compat import long |
3736 | + |
3737 | |
3738 | class DummySchema(object): |
3739 | def coerce(self, value): |
3740 | @@ -42,7 +44,8 @@ |
3741 | self.assertEqual(Int().coerce(3), 3) |
3742 | |
3743 | def test_int_accepts_long(self): |
3744 | - self.assertEqual(Int().coerce(3L), 3) |
3745 | + # This test can be removed after dropping Python 2 support |
3746 | + self.assertEqual(Int().coerce(long(3)), 3) |
3747 | |
3748 | def test_int_bad_str(self): |
3749 | self.assertRaises(InvalidError, Int().coerce, "3") |
3750 | @@ -57,7 +60,8 @@ |
3751 | self.assertEqual(Float().coerce(3), 3.0) |
3752 | |
3753 | def test_float_accepts_long(self): |
3754 | - self.assertEqual(Float().coerce(3L), 3.0) |
3755 | + # This test can be removed after dropping Python 2 support |
3756 | + self.assertEqual(Float().coerce(long(3)), 3.0) |
3757 | |
3758 | def test_float_bad_str(self): |
3759 | self.assertRaises(InvalidError, Float().coerce, "3.0") |
3760 | |
3761 | === modified file 'landscape/tests/test_sysvconfig.py' |
3762 | --- landscape/tests/test_sysvconfig.py 2016-06-15 22:21:21 +0000 |
3763 | +++ landscape/tests/test_sysvconfig.py 2017-03-10 15:29:37 +0000 |
3764 | @@ -11,13 +11,17 @@ |
3765 | filename = self.makeFile("RUN=0\n") |
3766 | sysvconfig = SysVConfig(filename) |
3767 | sysvconfig.set_start_on_boot(True) |
3768 | - self.assertEqual(file(filename, "r").read(), "RUN=1\n") |
3769 | + with open(filename, "r") as res_file: |
3770 | + result = res_file.read() |
3771 | + self.assertEqual(result, "RUN=1\n") |
3772 | |
3773 | def test_set_to_not_run_on_boot(self): |
3774 | filename = self.makeFile("RUN=1\n") |
3775 | sysvconfig = SysVConfig(filename) |
3776 | sysvconfig.set_start_on_boot(False) |
3777 | - self.assertEqual(file(filename, "r").read(), "RUN=0\n") |
3778 | + with open(filename, "r") as res_file: |
3779 | + result = res_file.read() |
3780 | + self.assertEqual(result, "RUN=0\n") |
3781 | |
3782 | def test_configured_to_run(self): |
3783 | filename = self.makeFile("RUN=1\n") |
3784 | |
3785 | === modified file 'landscape/tests/test_watchdog.py' |
3786 | --- landscape/tests/test_watchdog.py 2016-08-18 17:30:03 +0000 |
3787 | +++ landscape/tests/test_watchdog.py 2017-03-10 15:29:37 +0000 |
3788 | @@ -25,6 +25,9 @@ |
3789 | |
3790 | import landscape.watchdog |
3791 | |
3792 | +from unittest import skipIf |
3793 | +from twisted.python.compat import _PY3 |
3794 | + |
3795 | |
3796 | class StubDaemon(object): |
3797 | program = "program-name" |
3798 | @@ -580,7 +583,7 @@ |
3799 | output_filename = self.makeFile("NOT RUN") |
3800 | self.makeFile('#!/bin/sh\necho "RUN $@" > %s' % output_filename, |
3801 | path=self.exec_name) |
3802 | - os.chmod(self.exec_name, 0755) |
3803 | + os.chmod(self.exec_name, 0o755) |
3804 | |
3805 | waiter = FileChangeWaiter(output_filename) |
3806 | |
3807 | @@ -597,7 +600,7 @@ |
3808 | output_filename = self.makeFile("NOT RUN") |
3809 | self.makeFile('#!/bin/sh\necho "RUN $@" > %s' % output_filename, |
3810 | path=self.exec_name) |
3811 | - os.chmod(self.exec_name, 0755) |
3812 | + os.chmod(self.exec_name, 0o755) |
3813 | |
3814 | waiter = FileChangeWaiter(output_filename) |
3815 | |
3816 | @@ -622,7 +625,7 @@ |
3817 | "time.sleep(1000)\n" |
3818 | % (sys.executable, output_filename), |
3819 | path=self.exec_name) |
3820 | - os.chmod(self.exec_name, 0755) |
3821 | + os.chmod(self.exec_name, 0o755) |
3822 | |
3823 | waiter = FileChangeWaiter(output_filename) |
3824 | self.daemon.start() |
3825 | @@ -646,7 +649,7 @@ |
3826 | "os.kill(os.getpid(), signal.SIGSTOP)\n" |
3827 | % (sys.executable, output_filename), |
3828 | path=self.exec_name) |
3829 | - os.chmod(self.exec_name, 0755) |
3830 | + os.chmod(self.exec_name, 0o755) |
3831 | |
3832 | self.addCleanup(setattr, landscape.watchdog, "SIGKILL_DELAY", |
3833 | landscape.watchdog.SIGKILL_DELAY) |
3834 | @@ -666,7 +669,7 @@ |
3835 | output_filename = self.makeFile("NOT RUN") |
3836 | self.makeFile('#!/bin/sh\necho "RUN" > %s' % output_filename, |
3837 | path=self.exec_name) |
3838 | - os.chmod(self.exec_name, 0755) |
3839 | + os.chmod(self.exec_name, 0o755) |
3840 | |
3841 | self.daemon.start() |
3842 | |
3843 | @@ -682,7 +685,7 @@ |
3844 | output_filename = self.makeFile("NOT RUN") |
3845 | self.makeFile('#!/bin/sh\necho "RUN" > %s' % output_filename, |
3846 | path=self.exec_name) |
3847 | - os.chmod(self.exec_name, 0755) |
3848 | + os.chmod(self.exec_name, 0o755) |
3849 | |
3850 | self.daemon.start() |
3851 | |
3852 | @@ -709,7 +712,7 @@ |
3853 | """ |
3854 | % {"exe": sys.executable, "out": output_filename}, |
3855 | path=self.exec_name) |
3856 | - os.chmod(self.exec_name, 0755) |
3857 | + os.chmod(self.exec_name, 0o755) |
3858 | |
3859 | self.addCleanup(setattr, landscape.watchdog, "GRACEFUL_WAIT_PERIOD", |
3860 | landscape.watchdog.GRACEFUL_WAIT_PERIOD) |
3861 | @@ -735,7 +738,7 @@ |
3862 | "os.kill(os.getpid(), signal.SIGSTOP)\n" |
3863 | % (sys.executable, output_filename), |
3864 | path=self.exec_name) |
3865 | - os.chmod(self.exec_name, 0755) |
3866 | + os.chmod(self.exec_name, 0o755) |
3867 | |
3868 | self.addCleanup(setattr, landscape.watchdog, "SIGKILL_DELAY", |
3869 | landscape.watchdog.SIGKILL_DELAY) |
3870 | @@ -789,7 +792,7 @@ |
3871 | |
3872 | self.makeFile("#!/bin/sh\necho RUN >> %s" % output_filename, |
3873 | path=self.exec_name) |
3874 | - os.chmod(self.exec_name, 0755) |
3875 | + os.chmod(self.exec_name, 0o755) |
3876 | |
3877 | def got_result(result): |
3878 | self.assertEqual(len(list(open(output_filename))), |
3879 | @@ -832,7 +835,7 @@ |
3880 | |
3881 | self.makeFile("#!/bin/sh\necho RUN >> %s" % output_filename, |
3882 | path=self.exec_name) |
3883 | - os.chmod(self.exec_name, 0755) |
3884 | + os.chmod(self.exec_name, 0o755) |
3885 | |
3886 | def got_result(result): |
3887 | # Pay attention to the +1 bellow. It's the reason for this test. |
3888 | @@ -947,6 +950,7 @@ |
3889 | mock.ANY, mock.ANY, args=mock.ANY, env=mock.ANY, uid=None, |
3890 | gid=None) |
3891 | |
3892 | + @skipIf(_PY3, 'Takes long with Python3, probably unclean Reactor') |
3893 | def test_request_exit(self): |
3894 | """The request_exit() method calls exit() on the broker process.""" |
3895 | |
3896 | @@ -958,7 +962,7 @@ |
3897 | "output_filename": output_filename, |
3898 | "socket": socket_filename}) |
3899 | |
3900 | - os.chmod(broker_filename, 0755) |
3901 | + os.chmod(broker_filename, 0o755) |
3902 | process_result = getProcessOutput(broker_filename, env=os.environ, |
3903 | errortoo=True) |
3904 | |
3905 | @@ -1230,14 +1234,14 @@ |
3906 | def mode(*suffix): |
3907 | return stat.S_IMODE(os.stat(path(*suffix)).st_mode) |
3908 | |
3909 | - self.assertEqual(mode(), 0755) |
3910 | - self.assertEqual(mode("messages"), 0755) |
3911 | - self.assertEqual(mode("package"), 0755) |
3912 | - self.assertEqual(mode("package/hash-id"), 0755) |
3913 | - self.assertEqual(mode("package/binaries"), 0755) |
3914 | - self.assertEqual(mode("sockets"), 0750) |
3915 | - self.assertEqual(mode("custom-graph-scripts"), 0755) |
3916 | - self.assertEqual(mode("package/database"), 0644) |
3917 | + self.assertEqual(mode(), 0o755) |
3918 | + self.assertEqual(mode("messages"), 0o755) |
3919 | + self.assertEqual(mode("package"), 0o755) |
3920 | + self.assertEqual(mode("package/hash-id"), 0o755) |
3921 | + self.assertEqual(mode("package/binaries"), 0o755) |
3922 | + self.assertEqual(mode("sockets"), 0o750) |
3923 | + self.assertEqual(mode("custom-graph-scripts"), 0o755) |
3924 | + self.assertEqual(mode("package/database"), 0o644) |
3925 | |
3926 | STUB_BROKER = """\ |
3927 | #!%(executable)s |
3928 | |
3929 | === modified file 'landscape/user/changes.py' |
3930 | --- landscape/user/changes.py 2016-01-11 18:34:49 +0000 |
3931 | +++ landscape/user/changes.py 2017-03-10 15:29:37 +0000 |
3932 | @@ -1,3 +1,5 @@ |
3933 | +from twisted.python.compat import iteritems, itervalues |
3934 | + |
3935 | from landscape.diff import diff |
3936 | |
3937 | |
3938 | @@ -54,7 +56,7 @@ |
3939 | |
3940 | def create_diff(self): |
3941 | """Returns the changes since the last snapshot. |
3942 | - |
3943 | + |
3944 | See landscape.message_schemas.USERS schema for a description of the |
3945 | dictionary returned by this method. |
3946 | """ |
3947 | @@ -74,11 +76,11 @@ |
3948 | changes = {} |
3949 | creates, updates, deletes = diff(self._old_users, self._new_users) |
3950 | if creates: |
3951 | - changes["create-users"] = list(creates.itervalues()) |
3952 | + changes["create-users"] = list(itervalues(creates)) |
3953 | if updates: |
3954 | - changes["update-users"] = list(updates.itervalues()) |
3955 | + changes["update-users"] = list(itervalues(updates)) |
3956 | if deletes: |
3957 | - changes["delete-users"] = list(deletes.iterkeys()) |
3958 | + changes["delete-users"] = list(deletes) |
3959 | return changes |
3960 | |
3961 | def _detect_group_changes(self): |
3962 | @@ -94,7 +96,7 @@ |
3963 | if creates: |
3964 | groups = [] |
3965 | create_members = {} |
3966 | - for value in creates.itervalues(): |
3967 | + for value in itervalues(creates): |
3968 | # Use a copy to avoid removing the 'members' element |
3969 | # from stored data. |
3970 | value = value.copy() |
3971 | @@ -110,7 +112,7 @@ |
3972 | remove_members = {} |
3973 | create_members = {} |
3974 | update_groups = [] |
3975 | - for groupname, new_data in updates.iteritems(): |
3976 | + for groupname, new_data in iteritems(updates): |
3977 | old_data = self._old_groups[groupname] |
3978 | old_members = set(old_data["members"]) |
3979 | new_members = set(new_data["members"]) |
3980 | |
3981 | === modified file 'landscape/user/management.py' |
3982 | --- landscape/user/management.py 2013-09-18 07:52:46 +0000 |
3983 | +++ landscape/user/management.py 2017-03-10 15:29:37 +0000 |
3984 | @@ -4,11 +4,10 @@ |
3985 | # subprocesses. liboobs (i.e. System Tools) is a possibility, and has |
3986 | # documentation now in the 2.17 series, but is not wrapped to Python. |
3987 | |
3988 | -import os |
3989 | import logging |
3990 | import subprocess |
3991 | +from passlib.hash import md5_crypt |
3992 | |
3993 | -from landscape.lib import md5crypt |
3994 | from landscape.user.provider import UserManagementError, UserProvider |
3995 | |
3996 | |
3997 | @@ -52,8 +51,7 @@ |
3998 | # XXX temporary workaround? We're getting unicode here. |
3999 | username = username.encode("ascii") |
4000 | password = password.encode("ascii") |
4001 | - salt = os.urandom(6).encode("base64")[:-1] |
4002 | - crypted = md5crypt.md5crypt(password, salt) |
4003 | + crypted = md5_crypt.encrypt(password) |
4004 | result, output = self.call_popen(["usermod", "-p", crypted, username]) |
4005 | if result != 0: |
4006 | raise UserManagementError("Error setting password for user " |
4007 | |
4008 | === modified file 'landscape/user/provider.py' |
4009 | --- landscape/user/provider.py 2008-06-12 17:46:35 +0000 |
4010 | +++ landscape/user/provider.py 2017-03-10 15:29:37 +0000 |
4011 | @@ -1,8 +1,10 @@ |
4012 | +from grp import struct_group |
4013 | from pwd import struct_passwd |
4014 | -from grp import struct_group |
4015 | import csv |
4016 | +import logging |
4017 | import subprocess |
4018 | -import logging |
4019 | + |
4020 | +from twisted.python.compat import _PY3 |
4021 | |
4022 | |
4023 | class UserManagementError(Exception): |
4024 | @@ -31,7 +33,7 @@ |
4025 | |
4026 | Each user is represented as a dict with the keys: C{username}, |
4027 | C{name}, C{uid}, C{enabled}, C{location}, C{work-phone} and |
4028 | - C{home-phone}. |
4029 | + C{home-phone}. |
4030 | """ |
4031 | users = [] |
4032 | found_usernames = set() |
4033 | @@ -40,8 +42,7 @@ |
4034 | user = struct_passwd(user) |
4035 | if user.pw_name in found_usernames: |
4036 | continue |
4037 | - gecos_data = [x.decode("utf-8", "replace") or None |
4038 | - for x in user.pw_gecos.split(",")[:4]] |
4039 | + gecos_data = [x or None for x in user.pw_gecos.split(",")[:4]] |
4040 | while len(gecos_data) < 4: |
4041 | gecos_data.append(None) |
4042 | name, location, work_phone, home_phone = tuple(gecos_data) |
4043 | @@ -70,7 +71,7 @@ |
4044 | continue |
4045 | member_names = user_names.intersection(group.gr_mem) |
4046 | groups.append({"name": group.gr_name, "gid": group.gr_gid, |
4047 | - "members": list(member_names)}) |
4048 | + "members": sorted(list(member_names))}) |
4049 | found_groupnames.add(group.gr_name) |
4050 | return groups |
4051 | |
4052 | @@ -96,6 +97,7 @@ |
4053 | return data["gid"] |
4054 | raise GroupNotFoundError("Group not found for group %s." % groupname) |
4055 | |
4056 | + |
4057 | class UserProvider(UserProviderBase): |
4058 | |
4059 | popen = subprocess.Popen |
4060 | @@ -117,26 +119,32 @@ |
4061 | directory, path to the user's shell) |
4062 | """ |
4063 | user_data = [] |
4064 | - passwd_file = open(self._passwd_file, "r") |
4065 | - reader = csv.DictReader(passwd_file, fieldnames=self.passwd_fields, |
4066 | - delimiter=":", quoting=csv.QUOTE_NONE) |
4067 | - current_line = 0 |
4068 | - for row in reader: |
4069 | - current_line += 1 |
4070 | - # This skips the NIS user marker in the passwd file. |
4071 | - if (row["username"].startswith("+") or |
4072 | - row["username"].startswith("-")): |
4073 | - continue |
4074 | - try: |
4075 | - user_data.append((row["username"], row["passwd"], |
4076 | - int(row["uid"]), int(row["primary-gid"]), |
4077 | - row["gecos"], row["home"], row["shell"])) |
4078 | - except (ValueError, TypeError): |
4079 | - |
4080 | - logging.warn("passwd file %s is incorrectly formatted: " |
4081 | - "line %d." % (self._passwd_file, current_line)) |
4082 | - |
4083 | - passwd_file.close() |
4084 | + if _PY3: |
4085 | + open_params = dict(errors='replace') |
4086 | + else: |
4087 | + open_params = dict() |
4088 | + with open(self._passwd_file, "r", **open_params) as passwd_file: |
4089 | + reader = csv.DictReader( |
4090 | + passwd_file, fieldnames=self.passwd_fields, delimiter=":", |
4091 | + quoting=csv.QUOTE_NONE) |
4092 | + current_line = 0 |
4093 | + for row in reader: |
4094 | + current_line += 1 |
4095 | + # This skips the NIS user marker in the passwd file. |
4096 | + if (row["username"].startswith("+") or |
4097 | + row["username"].startswith("-")): |
4098 | + continue |
4099 | + gecos = row["gecos"] |
4100 | + if not _PY3 and gecos is not None: |
4101 | + gecos = gecos.decode("utf-8", "replace") |
4102 | + try: |
4103 | + user_data.append((row["username"], row["passwd"], |
4104 | + int(row["uid"]), int(row["primary-gid"]), |
4105 | + gecos, row["home"], row["shell"])) |
4106 | + except (ValueError, TypeError): |
4107 | + logging.warn( |
4108 | + "passwd file %s is incorrectly formatted: line %d." |
4109 | + % (self._passwd_file, current_line)) |
4110 | return user_data |
4111 | |
4112 | def get_group_data(self): |
4113 | @@ -157,11 +165,10 @@ |
4114 | row["name"].startswith("-")): |
4115 | continue |
4116 | try: |
4117 | - group_data.append((row["name"], row["passwd"], int(row["gid"]), |
4118 | + group_data.append((row["name"], row["passwd"], int(row["gid"]), |
4119 | row["members"].split(","))) |
4120 | except (AttributeError, ValueError): |
4121 | logging.warn("group file %s is incorrectly formatted: " |
4122 | "line %d." % (self._group_file, current_line)) |
4123 | group_file.close() |
4124 | return group_data |
4125 | - |
4126 | |
4127 | === modified file 'landscape/user/tests/helpers.py' |
4128 | --- landscape/user/tests/helpers.py 2016-02-08 13:49:49 +0000 |
4129 | +++ landscape/user/tests/helpers.py 2017-03-10 15:29:37 +0000 |
4130 | @@ -1,3 +1,5 @@ |
4131 | +from twisted.python.compat import iteritems, itervalues |
4132 | + |
4133 | from landscape.user.management import UserManagementError |
4134 | from landscape.user.provider import UserProviderBase |
4135 | |
4136 | @@ -29,7 +31,7 @@ |
4137 | try: |
4138 | uid = 1000 |
4139 | if self._users: |
4140 | - uid = max([x["uid"] for x in self._users.itervalues()]) + 1 |
4141 | + uid = max([x["uid"] for x in itervalues(self._users)]) + 1 |
4142 | if self._groups: |
4143 | primary_gid = self.get_gid(primary_group_name) |
4144 | else: |
4145 | @@ -108,7 +110,7 @@ |
4146 | def add_group(self, name): |
4147 | gid = 1000 |
4148 | if self._groups: |
4149 | - gid = max([x["gid"] for x in self._groups.itervalues()]) + 1 |
4150 | + gid = max([x["gid"] for x in itervalues(self._groups)]) + 1 |
4151 | self._groups[name] = {"name": name, "gid": gid, "members": []} |
4152 | self.update_provider_from_groups() |
4153 | return "add_group succeeded" |
4154 | @@ -144,7 +146,7 @@ |
4155 | |
4156 | def update_provider_from_groups(self): |
4157 | provider_list = [] |
4158 | - for k, v in self._groups.iteritems(): |
4159 | + for k, v in iteritems(self._groups): |
4160 | provider_list.append((k, "x", v["gid"], v["members"])) |
4161 | self.provider.groups = provider_list |
4162 | |
4163 | |
4164 | === modified file 'landscape/user/tests/test_management.py' |
4165 | --- landscape/user/tests/test_management.py 2011-07-05 05:09:11 +0000 |
4166 | +++ landscape/user/tests/test_management.py 2017-03-10 15:29:37 +0000 |
4167 | @@ -1,13 +1,13 @@ |
4168 | -from landscape.lib import md5crypt |
4169 | from landscape.user.management import UserManagement, UserManagementError |
4170 | from landscape.user.tests.helpers import FakeUserProvider |
4171 | from landscape.user.provider import UserNotFoundError, GroupNotFoundError |
4172 | from landscape.tests.helpers import LandscapeTest, MockPopen |
4173 | +from passlib.hash import md5_crypt |
4174 | |
4175 | |
4176 | def guess_password(generated_password, plaintext_password): |
4177 | salt = generated_password[len("$1$"):generated_password.rfind("$")] |
4178 | - crypted = md5crypt.md5crypt(plaintext_password, salt) |
4179 | + crypted = md5_crypt.encrypt(plaintext_password, salt=salt) |
4180 | return crypted |
4181 | |
4182 | |
4183 | |
4184 | === modified file 'landscape/user/tests/test_provider.py' |
4185 | --- landscape/user/tests/test_provider.py 2011-07-05 05:09:11 +0000 |
4186 | +++ landscape/user/tests/test_provider.py 2017-03-10 15:29:37 +0000 |
4187 | @@ -1,13 +1,14 @@ |
4188 | import pwd |
4189 | import grp |
4190 | |
4191 | -from landscape.user.provider import (UserProvider, UserNotFoundError, |
4192 | - GroupNotFoundError) |
4193 | - |
4194 | +from twisted.python.compat import _PY3 |
4195 | + |
4196 | +from landscape.user.provider import ( |
4197 | + UserProvider, UserNotFoundError, GroupNotFoundError) |
4198 | + |
4199 | +from landscape.tests.helpers import LandscapeTest |
4200 | from landscape.user.tests.helpers import FakeUserProvider |
4201 | |
4202 | -from landscape.tests.helpers import LandscapeTest |
4203 | - |
4204 | |
4205 | class ProviderTest(LandscapeTest): |
4206 | |
4207 | @@ -131,12 +132,19 @@ |
4208 | name = u"Jos\N{LATIN SMALL LETTER E WITH ACUTE}" |
4209 | location = "F\N{LATIN SMALL LETTER I WITH DIAERESIS}nland" |
4210 | number = "N\N{LATIN SMALL LETTER AE}ver" |
4211 | - gecos = "%s,%s,%s,%s," % (name.encode("utf-8"), |
4212 | - location.encode("utf-8"), |
4213 | - number.encode("utf-8"), |
4214 | - number.encode("utf-8")) |
4215 | - data = [("jdoe", "x", 1000, 1000, gecos, "/home/jdoe", "/bin/zsh")] |
4216 | - provider = FakeUserProvider(users=data, shadow_file=self.shadow_file) |
4217 | + if _PY3: |
4218 | + gecos = "{},{},{},{},".format(name, location, number, number) |
4219 | + else: |
4220 | + gecos = "{},{},{},{},".format(name.encode("utf-8"), |
4221 | + location.encode("utf-8"), |
4222 | + number.encode("utf-8"), |
4223 | + number.encode("utf-8")) |
4224 | + passwd_file = self.makeFile("""\ |
4225 | +jdoe:x:1000:1000:{}:/home/jdoe:/bin/zsh |
4226 | +root:x:0:0:root:/root:/bin/bash |
4227 | +""".format(gecos)) |
4228 | + provider = UserProvider(passwd_file=passwd_file, |
4229 | + group_file=self.group_file) |
4230 | users = provider.get_users() |
4231 | self.assertEqual(users[0]["name"], name) |
4232 | self.assertEqual(users[0]["location"], location) |
4233 | @@ -148,10 +156,14 @@ |
4234 | If a GECOS field contains non-UTF8 data, it should be replaced |
4235 | with question marks. |
4236 | """ |
4237 | + passwd_file = self.makeFile(b"""\ |
4238 | +jdoe:x:1000:1000:\255,\255,\255,\255:/home/jdoe:/bin/zsh |
4239 | +root:x:0:0:root:/root:/bin/bash |
4240 | +""", mode="wb") |
4241 | + provider = UserProvider(passwd_file=passwd_file, |
4242 | + group_file=self.group_file) |
4243 | unicode_unknown = u'\N{REPLACEMENT CHARACTER}' |
4244 | - data = [("jdoe", "x", 1000, 1000, "\255,\255,\255,\255", "/home/jdoe", |
4245 | - "/bin/zsh")] |
4246 | - provider = FakeUserProvider(users=data, shadow_file=self.shadow_file) |
4247 | + provider = UserProvider(passwd_file=passwd_file, group_file=None) |
4248 | users = provider.get_users() |
4249 | self.assertEqual(users[0]["name"], unicode_unknown) |
4250 | self.assertEqual(users[0]["location"], unicode_unknown) |
4251 | @@ -180,8 +192,7 @@ |
4252 | for user in users: |
4253 | if user["username"] == user_0.pw_name: |
4254 | self.assertEqual(user["uid"], 0) |
4255 | - user_0_name = user_0.pw_gecos.split(",")[0].decode( |
4256 | - "utf-8", "replace") |
4257 | + user_0_name = user_0.pw_gecos.split(",")[0] |
4258 | self.assertEqual(user["name"], user_0_name) |
4259 | break |
4260 | else: |
4261 | @@ -390,7 +401,7 @@ |
4262 | "members": []}) |
4263 | self.assertEqual(groups[1], {"name": u"cdrom", |
4264 | "gid": 24, |
4265 | - "members": [u"kevin", u"haldaemon"]}) |
4266 | + "members": [u"haldaemon", u"kevin"]}) |
4267 | self.assertEqual(groups[2], {"name": u"kevin", |
4268 | "gid": 1000, |
4269 | "members": []}) |
4270 | |
4271 | === modified file 'landscape/watchdog.py' |
4272 | --- landscape/watchdog.py 2017-01-05 11:19:41 +0000 |
4273 | +++ landscape/watchdog.py 2017-03-10 15:29:37 +0000 |
4274 | @@ -480,12 +480,12 @@ |
4275 | if os.fork(): # launch child and... |
4276 | os._exit(0) # kill off parent again. |
4277 | # some argue that this umask should be 0, but that's annoying. |
4278 | - os.umask(077) |
4279 | + os.umask(0o077) |
4280 | null = os.open('/dev/null', os.O_RDWR) |
4281 | for i in range(3): |
4282 | try: |
4283 | os.dup2(null, i) |
4284 | - except OSError, e: |
4285 | + except OSError as e: |
4286 | if e.errno != errno.EBADF: |
4287 | raise |
4288 | os.close(null) |
4289 | @@ -576,20 +576,20 @@ |
4290 | |
4291 | |
4292 | bootstrap_list = BootstrapList([ |
4293 | - BootstrapDirectory("$data_path", "landscape", "root", 0755), |
4294 | - BootstrapDirectory("$data_path/package", "landscape", "root", 0755), |
4295 | - BootstrapDirectory( |
4296 | - "$data_path/package/hash-id", "landscape", "root", 0755), |
4297 | - BootstrapDirectory( |
4298 | - "$data_path/package/binaries", "landscape", "root", 0755), |
4299 | - BootstrapDirectory( |
4300 | - "$data_path/package/upgrade-tool", "landscape", "root", 0755), |
4301 | - BootstrapDirectory("$data_path/messages", "landscape", "root", 0755), |
4302 | - BootstrapDirectory("$data_path/sockets", "landscape", "root", 0750), |
4303 | - BootstrapDirectory( |
4304 | - "$data_path/custom-graph-scripts", "landscape", "root", 0755), |
4305 | - BootstrapDirectory("$log_dir", "landscape", "root", 0755), |
4306 | - BootstrapFile("$data_path/package/database", "landscape", "root", 0644)]) |
4307 | + BootstrapDirectory("$data_path", "landscape", "root", 0o755), |
4308 | + BootstrapDirectory("$data_path/package", "landscape", "root", 0o755), |
4309 | + BootstrapDirectory( |
4310 | + "$data_path/package/hash-id", "landscape", "root", 0o755), |
4311 | + BootstrapDirectory( |
4312 | + "$data_path/package/binaries", "landscape", "root", 0o755), |
4313 | + BootstrapDirectory( |
4314 | + "$data_path/package/upgrade-tool", "landscape", "root", 0o755), |
4315 | + BootstrapDirectory("$data_path/messages", "landscape", "root", 0o755), |
4316 | + BootstrapDirectory("$data_path/sockets", "landscape", "root", 0o750), |
4317 | + BootstrapDirectory( |
4318 | + "$data_path/custom-graph-scripts", "landscape", "root", 0o755), |
4319 | + BootstrapDirectory("$log_dir", "landscape", "root", 0o755), |
4320 | + BootstrapFile("$data_path/package/database", "landscape", "root", 0o644)]) |
4321 | |
4322 | |
4323 | def clean_environment(): |
4324 | @@ -600,7 +600,7 @@ |
4325 | postinst script. Some environment variables may be set which would affect |
4326 | *other* maintainer scripts which landscape-client invokes. |
4327 | """ |
4328 | - for key in os.environ.keys(): |
4329 | + for key in list(os.environ.keys()): |
4330 | if (key.startswith(("DEBIAN_", "DEBCONF_")) or |
4331 | key in ["LANDSCAPE_ATTACHMENTS", "MAIL"]): |
4332 | del os.environ[key] |
4333 | |
4334 | === added file 'trial5' |
4335 | --- trial5 1970-01-01 00:00:00 +0000 |
4336 | +++ trial5 2017-03-10 15:29:37 +0000 |
4337 | @@ -0,0 +1,11 @@ |
4338 | +echo -e "\e[1m\e[43m\e[34m \e[93m\e[44m \e[0m" |
4339 | +echo -e "\e[1m\e[43m\e[34m PYTHON \e[93m\e[44m 2 \e[0m" |
4340 | +echo -e "\e[1m\e[43m\e[34m \e[93m\e[44m \e[0m" |
4341 | +echo "-------------------------------------------------------------------------------" |
4342 | +trial --unclean-warnings $@ |
4343 | +echo -e "\e[1m\e[93m\e[44m \e[43m\e[34m \e[0m" |
4344 | +echo -e "\e[1m\e[93m\e[44m PYTHON \e[43m\e[34m 3 \e[0m" |
4345 | +echo -e "\e[1m\e[93m\e[44m \e[43m\e[34m \e[0m" |
4346 | +echo "-------------------------------------------------------------------------------" |
4347 | +trial3 --unclean-warnings $@ |
4348 | + |
Command: TRIAL_ARGS=-j4 make check /ci.lscape. net/job/ latch-test- precise/ 857/
Result: Fail
Revno: 953
Branch: lp:~nilo/landscape-client/python3
Jenkins: https:/