Merge lp:~free.ekanayaka/landscape-client/create-package-lock into lp:~landscape/landscape-client/trunk

Proposed by Free Ekanayaka
Status: Merged
Approved by: Sidnei da Silva
Approved revision: not available
Merge reported by: Free Ekanayaka
Merged at revision: not available
Proposed branch: lp:~free.ekanayaka/landscape-client/create-package-lock
Merge into: lp:~landscape/landscape-client/trunk
Diff against target: 424 lines (+181/-16)
8 files modified
landscape/__init__.py (+9/-1)
landscape/manager/packagemanager.py (+5/-0)
landscape/manager/tests/test_packagemanager.py (+18/-1)
landscape/package/changer.py (+25/-0)
landscape/package/facade.py (+6/-1)
landscape/package/tests/helpers.py (+3/-1)
landscape/package/tests/test_changer.py (+90/-8)
landscape/package/tests/test_facade.py (+25/-4)
To merge this branch: bzr merge lp:~free.ekanayaka/landscape-client/create-package-lock
Reviewer Review Type Date Requested Status
Sidnei da Silva (community) Approve
Thomas Herve (community) Approve
Review via email: mp+18375@code.launchpad.net
To post a comment you must log in.
202. By Free Ekanayaka

Fix wrong status and result-code message field values.

Revision history for this message
Thomas Herve (therve) wrote :

[1]
+ The L{PackageManager.handle_change_package_locks} method is registered
+ has handler for messages of type C{"change-package-locks"}, and queues

Typo: as

Great small branch, +1!

review: Approve
Revision history for this message
Free Ekanayaka (free.ekanayaka) wrote :

Thanks Thomas! [1] got fixed.

Revision history for this message
Sidnei da Silva (sidnei) wrote :
Download full text (3.3 KiB)

Great branch. +1! Also the first one I use the new 'bzr ls-lint' command on. :)

There's a little lint here and there:

sidnei@sidnei-laptop:~/src/landscape/client/review/create-package-lock$ bzr ls-lint

= Landscape lint =

Linting changed files:
  landscape/__init__.py
  landscape/manager/packagemanager.py
  landscape/manager/tests/test_packagemanager.py
  landscape/package/changer.py
  landscape/package/facade.py
  landscape/package/tests/helpers.py
  landscape/package/tests/test_changer.py
  landscape/package/tests/test_facade.py

== lint ==

=== jslint ===

(No files to lint)

=== pep8 ===

landscape/package/tests/test_facade.py:39:9: E301 expected 1 blank line, found 0
landscape/package/tests/test_facade.py:39:34: E701 multiple statements on one line (colon)
landscape/package/tests/test_facade.py:56:9: E301 expected 1 blank line, found 0
landscape/package/tests/test_facade.py:56:34: E701 multiple statements on one line (colon)
landscape/package/tests/test_facade.py:347:9: E301 expected 1 blank line, found 0
landscape/package/tests/test_facade.py:396:9: E301 expected 1 blank line, found 0
landscape/package/tests/test_facade.py:396:34: E701 multiple statements on one line (colon)
landscape/package/tests/test_facade.py:456:13: E301 expected 1 blank line, found 0
landscape/package/tests/test_changer.py:38:80: E501 line too long (88 characters)
landscape/package/tests/test_changer.py:49:9: E301 expected 1 blank line, found 0
landscape/package/tests/test_changer.py:56:9: E301 expected 1 blank line, found 0
landscape/package/tests/test_changer.py:66:9: E301 expected 1 blank line, found 0
landscape/package/tests/test_changer.py:75:9: E301 expected 1 blank line, found 0
landscape/package/tests/test_changer.py:117:9: E301 expected 1 blank line, found 0
landscape/package/tests/test_changer.py:366:1: W291 trailing whitespace
landscape/package/tests/test_changer.py:570:5: E301 expected 1 blank line, found 2
landscape/package/tests/test_changer.py:615:1: W291 trailing whitespace
landscape/package/tests/test_changer.py:620:1: W291 trailing whitespace
landscape/package/tests/helpers.py:146:80: E501 line too long (80 characters)
landscape/package/tests/helpers.py:149:80: E501 line too long (81 characters)
landscape/package/tests/helpers.py:183:80: E501 line too long (80 characters)
landscape/package/tests/helpers.py:194:80: E501 line too long (132 characters)
landscape/package/tests/helpers.py:211:80: E501 line too long (132 characters)
landscape/package/tests/helpers.py:228:80: E501 line too long (94 characters)
landscape/package/tests/helpers.py:247:80: E501 line too long (80 characters)
landscape/package/tests/helpers.py:273:80: E501 line too long (91 characters)
landscape/package/tests/helpers.py:286:80: E501 line too long (80 characters)
landscape/package/tests/helpers.py:291:80: E501 line too long (80 characters)
landscape/package/tests/helpers.py:303:80: E501 line too long (91 characters)
landscape/package/tests/helpers.py:316:80: E501 line too long (80 characters)
landscape/package/tests/helpers.py:321:...

Read more...

review: Approve
203. By Free Ekanayaka

Fix typo (Thomas [1])

204. By Free Ekanayaka

Make tests lint clean(er) (Sidnei)

Revision history for this message
Free Ekanayaka (free.ekanayaka) wrote :

Thanks Sidnei, I didn't check out ls-lint yet, but will do soon! I think I've fixed most of the warnings, however there are a few ones in helpers.py that are a bit hard, because there is some hard-coded text. Maybe will do it in another pass.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'landscape/__init__.py'
2--- landscape/__init__.py 2010-01-27 16:49:11 +0000
3+++ landscape/__init__.py 2010-02-02 13:46:11 +0000
4@@ -14,7 +14,15 @@
5
6 # The "client-api" field of outgoing messages will be set to this value, and
7 # used by the server to know which schema do the message types accepted by the
8-# client support. Bump it when the schema of an accepted message type changes.
9+# client support. Bump it when the schema of an accepted message type changes
10+# and update the changelog below as needed.
11+#
12+# Changelog:
13+#
14+# 3.3:
15+# * Add "binaries" field to "change-packages"
16+# * Add new "change-package-locks" client accepted message type.
17+#
18 CLIENT_API = "3.3"
19
20 from twisted.python import util
21
22=== modified file 'landscape/manager/packagemanager.py'
23--- landscape/manager/packagemanager.py 2009-10-28 10:11:13 +0000
24+++ landscape/manager/packagemanager.py 2010-02-02 13:46:11 +0000
25@@ -26,6 +26,8 @@
26
27 registry.register_message("change-packages",
28 self.handle_change_packages)
29+ registry.register_message("change-package-locks",
30+ self.handle_change_package_locks)
31 registry.register_message("release-upgrade",
32 self.handle_release_upgrade)
33
34@@ -39,6 +41,9 @@
35 def handle_change_packages(self, message):
36 return self._handle(PackageChanger, message)
37
38+ def handle_change_package_locks(self, message):
39+ return self._handle(PackageChanger, message)
40+
41 def handle_release_upgrade(self, message):
42 return self._handle(ReleaseUpgrader, message)
43
44
45=== modified file 'landscape/manager/tests/test_packagemanager.py'
46--- landscape/manager/tests/test_packagemanager.py 2009-10-30 15:09:34 +0000
47+++ landscape/manager/tests/test_packagemanager.py 2010-02-02 13:46:11 +0000
48@@ -144,7 +144,6 @@
49 self.mocker.replay()
50
51 message = {"type": "change-packages"}
52- service = self.broker_service
53 self.manager.dispatch_message(message)
54 task = self.package_store.get_next_task("changer")
55 self.assertTrue(task)
56@@ -316,3 +315,21 @@
57 os.chmod(dir, 0766)
58
59 return result.addCallback(got_result)
60+
61+ def test_change_package_locks_handling(self):
62+ """
63+ The L{PackageManager.handle_change_package_locks} method is registered
64+ as handler for messages of type C{"change-package-locks"}, and queues
65+ a package-changer task in the appropriate queue.
66+ """
67+ self.manager.add(self.package_manager)
68+
69+ package_manager_mock = self.mocker.patch(self.package_manager)
70+ package_manager_mock.spawn_handler(PackageChanger)
71+ self.mocker.replay()
72+
73+ message = {"type": "change-package-locks"}
74+ self.manager.dispatch_message(message)
75+ task = self.package_store.get_next_task("changer")
76+ self.assertTrue(task)
77+ self.assertEquals(task.data, message)
78
79=== modified file 'landscape/package/changer.py'
80--- landscape/package/changer.py 2010-01-20 10:05:27 +0000
81+++ landscape/package/changer.py 2010-02-02 13:46:11 +0000
82@@ -11,6 +11,7 @@
83 from landscape.package.reporter import find_reporter_command
84 from landscape.package.taskhandler import (
85 PackageTaskHandler, PackageTaskHandlerConfiguration, run_task_handler)
86+from landscape.manager.manager import SUCCEEDED
87
88
89 SUCCESS_RESULT = 1
90@@ -91,6 +92,8 @@
91 if message["type"] == "change-packages":
92 result = self._handle_change_packages(message)
93 return result.addErrback(self._check_expired_unknown_data, task)
94+ if message["type"] == "change-package-locks":
95+ return self._handle_change_package_locks(message)
96
97 def _warn_about_unknown_data(self, failure):
98 failure.trap(UnknownPackageData)
99@@ -209,6 +212,28 @@
100 "exchange urgently.")
101 return self._broker.send_message(message, True)
102
103+ def _handle_change_package_locks(self, message):
104+ """Handle a C{change-package-locks} message.
105+
106+ Create and delete package locks as requested by the given C{message}.
107+ """
108+
109+ for lock in message.get("create", ()):
110+ self._facade.set_package_lock(*lock)
111+ for lock in message.get("delete", ()):
112+ self._facade.remove_package_lock(*lock)
113+ self._facade.save_config()
114+
115+ response = {"type": "operation-result",
116+ "operation-id": message.get("operation-id"),
117+ "status": SUCCEEDED,
118+ "result-text": "Package locks successfully changed.",
119+ "result-code": 0}
120+
121+ logging.info("Queuing message with change package locks results to "
122+ "exchange urgently.")
123+ return self._broker.send_message(response, True)
124+
125 @staticmethod
126 def find_command():
127 return find_changer_command()
128
129=== modified file 'landscape/package/facade.py'
130--- landscape/package/facade.py 2009-11-26 02:54:44 +0000
131+++ landscape/package/facade.py 2010-02-02 13:46:11 +0000
132@@ -351,9 +351,14 @@
133 self._get_ctrl()
134 smart.pkgconf.setFlag("lock", name, relation, version)
135
136- def remove_package_lock(self, name, relation=(), version=()):
137+ def remove_package_lock(self, name, relation=None, version=None):
138 """Remove a package lock."""
139 self._validate_lock_condition(relation, version)
140 self._get_ctrl()
141 smart.pkgconf.clearFlag("lock", name=name, relation=relation,
142 version=version)
143+
144+ def save_config(self):
145+ """Flush the current smart configuration to disk."""
146+ control = self._get_ctrl()
147+ control.saveSysConf()
148
149=== modified file 'landscape/package/tests/helpers.py'
150--- landscape/package/tests/helpers.py 2010-01-20 10:00:02 +0000
151+++ landscape/package/tests/helpers.py 2010-02-02 13:46:11 +0000
152@@ -8,6 +8,7 @@
153
154 def set_up(self, test_case):
155 test_case.smart_dir = test_case.makeDir()
156+ test_case.smart_config = test_case.makeFile("")
157 test_case.repository_dir = test_case.makeDir()
158 create_simple_repository(test_case.repository_dir)
159
160@@ -31,7 +32,8 @@
161 self.add_channel_deb_dir(test_case.repository_dir)
162
163 test_case.Facade = Facade
164- test_case.facade = Facade({"datadir": test_case.smart_dir})
165+ test_case.facade = Facade({"datadir": test_case.smart_dir,
166+ "configfile": test_case.smart_config})
167
168
169 PKGNAME1 = "name1_version1-release1_all.deb"
170
171=== modified file 'landscape/package/tests/test_changer.py'
172--- landscape/package/tests/test_changer.py 2010-01-20 10:05:27 +0000
173+++ landscape/package/tests/test_changer.py 2010-02-02 13:46:11 +0000
174@@ -19,8 +19,8 @@
175 from landscape.tests.helpers import (
176 LandscapeIsolatedTest, RemoteBrokerHelper)
177 from landscape.package.tests.helpers import (
178- SmartFacadeHelper, HASH1, HASH2, HASH3, PKGDEB1, PKGDEB2, PKGDEB3,
179- PKGNAME2)
180+ SmartFacadeHelper, HASH1, HASH2, HASH3, PKGDEB1, PKGDEB2, PKGNAME2)
181+from landscape.manager.manager import SUCCEEDED
182
183
184 class PackageChangerTest(LandscapeIsolatedTest):
185@@ -35,16 +35,18 @@
186 self.config.data_path = self.makeDir()
187 os.mkdir(self.config.package_directory)
188 os.mkdir(self.config.binaries_path)
189- self.changer = PackageChanger(self.store, self.facade, self.remote, self.config)
190-
191+ self.changer = PackageChanger(self.store, self.facade, self.remote,
192+ self.config)
193 service = self.broker_service
194- service.message_store.set_accepted_types(["change-packages-result"])
195+ service.message_store.set_accepted_types(["change-packages-result",
196+ "operation-result"])
197
198 def get_pending_messages(self):
199 return self.broker_service.message_store.get_pending_messages()
200
201 def set_pkg1_installed(self):
202 previous = self.Facade.channels_reloaded
203+
204 def callback(self):
205 previous(self)
206 self.get_packages_by_name("name1")[0].installed = True
207@@ -52,6 +54,7 @@
208
209 def set_pkg2_upgrades_pkg1(self):
210 previous = self.Facade.channels_reloaded
211+
212 def callback(self):
213 from smart.backends.deb.base import DebUpgrades
214 previous(self)
215@@ -62,6 +65,7 @@
216
217 def set_pkg2_satisfied(self):
218 previous = self.Facade.channels_reloaded
219+
220 def callback(self):
221 previous(self)
222 pkg2 = self.get_packages_by_name("name2")[0]
223@@ -71,6 +75,7 @@
224
225 def set_pkg1_and_pkg2_satisfied(self):
226 previous = self.Facade.channels_reloaded
227+
228 def callback(self):
229 previous(self)
230
231@@ -113,6 +118,7 @@
232 # result of our previous message, which got *postponed*.
233 self.store.set_hash_ids({HASH2: 2})
234 result = self.changer.handle_tasks()
235+
236 def got_result(result):
237 self.assertMessages(self.get_pending_messages(),
238 [{"must-install": [2],
239@@ -362,7 +368,7 @@
240
241 def test_successful_operation(self):
242 """Simulate a *very* successful operation.
243-
244+
245 We'll do that by hacking perform_changes(), and returning our
246 *very* successful operation result.
247 """
248@@ -565,7 +571,6 @@
249 "operation-id": 123})
250 return self.changer.run()
251
252-
253 def test_run(self):
254 changer_mock = self.mocker.patch(self.changer)
255
256@@ -611,7 +616,7 @@
257
258 def test_main(self):
259 self.mocker.order()
260-
261+
262 run_task_handler = self.mocker.replace("landscape.package.taskhandler"
263 ".run_task_handler",
264 passthrough=False)
265@@ -752,3 +757,80 @@
266 self.makeFile(basename=existing_deb_path, content="foo")
267 self.changer._create_deb_dir_channel([])
268 self.assertFalse(os.path.exists(existing_deb_path))
269+
270+ def test_change_package_locks(self):
271+ """
272+ The L{PackageChanger.handle_tasks} method appropriately creates and
273+ deletes package locks as requested by the C{change-package-locks}
274+ message.
275+ """
276+ self.facade.set_package_lock("bar")
277+ self.store.add_task("changer", {"type": "change-package-locks",
278+ "create": [("foo", ">=", "1.0")],
279+ "delete": [("bar", None, None)],
280+ "operation-id": 123})
281+
282+ def assert_result(result):
283+ self.facade.deinit()
284+ self.assertEquals(self.facade.get_package_locks(),
285+ [("foo", ">=", "1.0")])
286+ self.assertIn("Queuing message with change package locks results "
287+ "to exchange urgently.", self.logfile.getvalue())
288+ self.assertMessages(self.get_pending_messages(),
289+ [{"type": "operation-result",
290+ "operation-id": 123,
291+ "status": SUCCEEDED,
292+ "result-text": "Package locks successfully"
293+ " changed.",
294+ "result-code": 0}])
295+
296+ result = self.changer.handle_tasks()
297+ return result.addCallback(assert_result)
298+
299+ def test_change_package_locks_create_with_already_existing(self):
300+ """
301+ The L{PackageChanger.handle_tasks} method gracefully handles requests
302+ for creating package locks that already exist.
303+ """
304+ self.facade.set_package_lock("foo")
305+ self.store.add_task("changer", {"type": "change-package-locks",
306+ "create": [("foo", None, None)],
307+ "operation-id": 123})
308+
309+ def assert_result(result):
310+ self.facade.deinit()
311+ self.assertEquals(self.facade.get_package_locks(),
312+ [("foo", "", "")])
313+ self.assertMessages(self.get_pending_messages(),
314+ [{"type": "operation-result",
315+ "operation-id": 123,
316+ "status": SUCCEEDED,
317+ "result-text": "Package locks successfully"
318+ " changed.",
319+ "result-code": 0}])
320+
321+ result = self.changer.handle_tasks()
322+ return result.addCallback(assert_result)
323+
324+ def test_change_package_locks_delete_without_already_existing(self):
325+ """
326+ The L{PackageChanger.handle_tasks} method gracefully handles requests
327+ for deleting package locks that don't exist.
328+ """
329+ self.store.add_task("changer", {"type": "change-package-locks",
330+ "delete": [("foo", ">=", "1.0")],
331+ "operation-id": 123})
332+
333+ def assert_result(result):
334+ self.facade.deinit()
335+ self.assertEquals(self.facade.get_package_locks(), [])
336+ self.assertMessages(self.get_pending_messages(),
337+ [{"type": "operation-result",
338+ "operation-id": 123,
339+ "status": SUCCEEDED,
340+ "result-text": "Package locks successfully"
341+ " changed.",
342+ "result-code": 0}])
343+
344+ result = self.changer.handle_tasks()
345+ return result.addCallback(assert_result)
346
347=== modified file 'landscape/package/tests/test_facade.py'
348--- landscape/package/tests/test_facade.py 2009-11-25 09:48:00 +0000
349+++ landscape/package/tests/test_facade.py 2010-02-02 13:46:11 +0000
350@@ -36,7 +36,10 @@
351 def test_get_packages_wont_return_non_debian_packages(self):
352 self.facade.reload_channels()
353 ctrl_mock = self.mocker.patch(Control)
354- class StubPackage(object): pass
355+
356+ class StubPackage(object):
357+ pass
358+
359 cache_mock = ctrl_mock.getCache()
360 cache_mock.getPackages()
361 self.mocker.result([StubPackage(), StubPackage()])
362@@ -53,7 +56,10 @@
363 def test_get_packages_by_name_wont_return_non_debian_packages(self):
364 self.facade.reload_channels()
365 ctrl_mock = self.mocker.patch(Control)
366- class StubPackage(object): pass
367+
368+ class StubPackage(object):
369+ pass
370+
371 cache_mock = ctrl_mock.getCache()
372 cache_mock.getPackages("name")
373 self.mocker.result([StubPackage(), StubPackage()])
374@@ -116,7 +122,7 @@
375 # Forcibly change the mtime of our repository, so that Smart
376 # will consider it as changed (if the change is inside the
377 # same second the directory's mtime will be the same)
378- mtime = int(time.time()+1)
379+ mtime = int(time.time() + 1)
380 os.utime(self.repository_dir, (mtime, mtime))
381
382 # Reload channels.
383@@ -344,6 +350,7 @@
384 self.facade.mark_install(pkg)
385
386 environ = []
387+
388 def check_environ(self, argv, output):
389 environ.append(os.environ.get("DEBIAN_FRONTEND"))
390 environ.append(os.environ.get("APT_LISTCHANGES_FRONTEND"))
391@@ -393,7 +400,10 @@
392 self.facade.deinit()
393
394 def test_reload_channels_wont_consider_non_debian_packages(self):
395- class StubPackage(object): pass
396+
397+ class StubPackage(object):
398+ pass
399+
400 pkg = StubPackage()
401
402 ctrl_mock = self.mocker.patch(Control)
403@@ -453,6 +463,7 @@
404 def do_test():
405 result = getProcessOutputAndValue("/usr/bin/dpkg",
406 ("--print-architecture",))
407+
408 def callback((out, err, code)):
409 self.assertEquals(self.facade.get_arch(), out.strip())
410 result.addCallback(callback)
411@@ -605,3 +616,13 @@
412 self.facade.set_package_lock("name1", "<", "version1")
413 self.facade.remove_package_lock("name1", "<", "version1")
414 self.assertEquals(self.facade.get_locked_packages(), [])
415+
416+ def test_save_config(self):
417+ """
418+ It is possible to lock a package by simply specifying its name.
419+ """
420+ self.facade.set_package_lock("python", "=>", "2.5")
421+ self.facade.save_config()
422+ self.facade.deinit()
423+ self.assertEquals(self.facade.get_package_locks(),
424+ [("python", "=>", "2.5")])

Subscribers

People subscribed via source and target branches

to all changes: