Merge lp:~mvo/software-center/webapps-activation into lp:software-center

Proposed by Michael Vogt
Status: Merged
Merged at revision: 3278
Proposed branch: lp:~mvo/software-center/webapps-activation
Merge into: lp:software-center
Diff against target: 296 lines (+166/-7)
9 files modified
setup.py (+3/-2)
softwarecenter/db/pkginfo.py (+4/-0)
softwarecenter/db/pkginfo_impl/aptcache.py (+4/-0)
softwarecenter/paths.py (+1/-0)
softwarecenter/plugin.py (+1/-0)
softwarecenter/plugins/webapps_activation.py (+57/-0)
tests/test_region.py (+1/-0)
tests/test_webapps_activation_plugin.py (+90/-0)
tests/utils.py (+5/-5)
To merge this branch: bzr merge lp:~mvo/software-center/webapps-activation
Reviewer Review Type Date Requested Status
dobey Approve
Michael Vogt Needs Resubmitting
Review via email: mp+134459@code.launchpad.net

Description of the change

This add support to activate webapps automatically on install.

To post a comment you must log in.
Revision history for this message
dobey (dobey) wrote :

134 + def activate_unity_webapp_for_domain(self, domain):
135 + try:
136 + from gi.repository import UnityWebapps
137 + except ImportError:
138 + LOG.warn("failed to import UnityWebapps GIR")
139 + LOG.debug("activating webapp for domain '%s'", domain)
140 + UnityWebapps.permissions_allow_domain(domain)

The last two lines in this function need to be inside an else: I think. Otherwise an exception will be raised when permissions_allow_domain() is called, if the import failed, since you're not returning in the except handler. I guess this wasn't caught in your tests, as you're mocking that function.

+ # instal backend

Typo.

review: Needs Fixing
3243. By Michael Vogt

softwarecenter/plugins/webapps_activation.py: if UnityWebapps GIR can not be imported, just return (thanks to Rodney Dawes!)

Revision history for this message
Michael Vogt (mvo) wrote :

Thanks a lot Rodney!

Indeed, the import failure was not tested and I overlooked it, fixed in r3243 now. I also fixed the typo now.

review: Needs Resubmitting
Revision history for this message
dobey (dobey) wrote :

There's a text conflict in softwarecenter/paths.py now.

3244. By Michael Vogt

tests/test_webapps_activation_plugin.py: fix typo, thanks dobey

3245. By Michael Vogt

merged trunk and resolved conflicts

Revision history for this message
Michael Vogt (mvo) wrote :

Thanks again, I fixed the conflict and pushed the typo fix.

Revision history for this message
dobey (dobey) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'setup.py'
2--- setup.py 2012-11-22 08:28:45 +0000
3+++ setup.py 2012-12-17 17:32:21 +0000
4@@ -125,6 +125,7 @@
5 'softwarecenter.db.pkginfo_impl',
6 'softwarecenter.db.history_impl',
7 'softwarecenter.distro',
8+ 'softwarecenter.plugins',
9 'softwarecenter.sso',
10 'softwarecenter.ui',
11 'softwarecenter.ui.gtk3',
12@@ -150,9 +151,9 @@
13 # sso
14 ('share/software-center/ui/sso/', glob.glob("data/ui/sso/*.ui")),
15 # dbus
16- ('../etc/dbus-1/system.d/',
17+ ('../etc/dbus-1/system.d/',
18 ["data/dbus/com.ubuntu.SoftwareCenter.conf"]),
19- ('share/dbus-1/services',
20+ ('share/dbus-1/services',
21 ["data/dbus/com.ubuntu.SoftwareCenterDataProvider.service"]),
22 # images
23 ('share/software-center/images/',
24
25=== modified file 'softwarecenter/db/pkginfo.py'
26--- softwarecenter/db/pkginfo.py 2012-11-28 17:23:44 +0000
27+++ softwarecenter/db/pkginfo.py 2012-12-17 17:32:21 +0000
28@@ -49,6 +49,10 @@
29 return []
30
31 @property
32+ def record(self):
33+ return {}
34+
35+ @property
36 def not_automatic(self):
37 """ should not be installed/upgraded automatically, the user needs
38 to opt-in once (used for e.g. ubuntu-backports)
39
40=== modified file 'softwarecenter/db/pkginfo_impl/aptcache.py'
41--- softwarecenter/db/pkginfo_impl/aptcache.py 2012-12-14 16:44:25 +0000
42+++ softwarecenter/db/pkginfo_impl/aptcache.py 2012-12-17 17:32:21 +0000
43@@ -95,6 +95,10 @@
44 return self.ver.origins
45
46 @property
47+ def record(self):
48+ return self.ver.record
49+
50+ @property
51 def downloadable(self):
52 return self.ver.downloadable
53
54
55=== modified file 'softwarecenter/paths.py'
56--- softwarecenter/paths.py 2012-11-28 16:58:59 +0000
57+++ softwarecenter/paths.py 2012-12-17 17:32:21 +0000
58@@ -47,6 +47,7 @@
59 os.environ.get("SOFTWARE_CENTER_PLUGINS_DIR", ""),
60 os.path.join(SOFTWARE_CENTER_BASE, "plugins"),
61 os.path.join(xdg.xdg_data_home, "software-center", "plugins"),
62+ os.path.join(os.path.dirname(__file__), "plugins"),
63 ]
64
65 # FIXME: use relative paths here
66
67=== modified file 'softwarecenter/plugin.py'
68--- softwarecenter/plugin.py 2012-11-28 16:58:59 +0000
69+++ softwarecenter/plugin.py 2012-12-17 17:32:21 +0000
70@@ -115,6 +115,7 @@
71 for plugin in self._find_plugins(module):
72 plugin.app = self._app
73 try:
74+ LOG.info("activating plugin '%s'" % module)
75 plugin.init_plugin()
76 self._plugins.append(plugin)
77 except:
78
79=== added directory 'softwarecenter/plugins'
80=== added file 'softwarecenter/plugins/__init__.py'
81=== added file 'softwarecenter/plugins/webapps_activation.py'
82--- softwarecenter/plugins/webapps_activation.py 1970-01-01 00:00:00 +0000
83+++ softwarecenter/plugins/webapps_activation.py 2012-12-17 17:32:21 +0000
84@@ -0,0 +1,57 @@
85+# -*- coding: utf-8 -*-
86+# Copyright (C) 2012 Canonical
87+#
88+# Authors:
89+# Michael Vogt
90+#
91+# This program is free software; you can redistribute it and/or modify it under
92+# the terms of the GNU General Public License as published by the Free Software
93+# Foundation; version 3.
94+#
95+# This program is distributed in the hope that it will be useful, but WITHOUT
96+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
97+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
98+# details.
99+#
100+# You should have received a copy of the GNU General Public License along with
101+# this program; if not, write to the Free Software Foundation, Inc.,
102+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
103+
104+import logging
105+
106+import softwarecenter.plugin
107+from softwarecenter.db.pkginfo import get_pkg_info
108+from softwarecenter.backend.installbackend import get_install_backend
109+
110+LOG = logging.getLogger(__name__)
111+
112+
113+class UnityWebappsActivationPlugin(softwarecenter.plugin.Plugin):
114+ """Webapps activation plugin """
115+
116+ def init_plugin(self):
117+ self.pkg_info = get_pkg_info()
118+ self.install_backend = get_install_backend()
119+ self.install_backend.connect(
120+ "transaction-finished", self._on_transaction_finished)
121+
122+ def _on_transaction_finished(self, backend, result):
123+ if not result.success or not result.pkgname:
124+ return
125+ if not result.pkgname in self.pkg_info:
126+ return
127+ pkg = self.pkg_info[result.pkgname]
128+ if not pkg.candidate:
129+ return
130+ webdomain = pkg.candidate.record.get("Ubuntu-Webapps-Domain", None)
131+ if webdomain:
132+ self.activate_unity_webapp_for_domain(webdomain)
133+
134+ def activate_unity_webapp_for_domain(self, domain):
135+ try:
136+ from gi.repository import UnityWebapps
137+ except ImportError:
138+ LOG.warn("failed to import UnityWebapps GIR")
139+ return
140+ LOG.debug("activating webapp for domain '%s'", domain)
141+ UnityWebapps.permissions_allow_domain(domain)
142
143=== modified file 'tests/test_region.py'
144--- tests/test_region.py 2012-07-19 09:29:16 +0000
145+++ tests/test_region.py 2012-12-17 17:32:21 +0000
146@@ -58,5 +58,6 @@
147 self.assertTrue(self.region._get_region_dumb.called)
148 self.assertTrue(self.region._get_region_geoclue.called)
149
150+
151 if __name__ == "__main__":
152 unittest.main()
153
154=== added file 'tests/test_webapps_activation_plugin.py'
155--- tests/test_webapps_activation_plugin.py 1970-01-01 00:00:00 +0000
156+++ tests/test_webapps_activation_plugin.py 2012-12-17 17:32:21 +0000
157@@ -0,0 +1,90 @@
158+import unittest
159+
160+from mock import (
161+ Mock,
162+ patch)
163+
164+from tests.utils import (
165+ setup_test_env,
166+ FakedCache,
167+ ObjectWithSignals,
168+)
169+setup_test_env()
170+
171+from softwarecenter.plugins.webapps_activation import (
172+ UnityWebappsActivationPlugin)
173+
174+
175+def make_install_result_mock(pkgname, success):
176+ mock_install_result = Mock()
177+ mock_install_result.success = success
178+ mock_install_result.pkgname = pkgname
179+ return mock_install_result
180+
181+
182+def make_mock_package_with_record(pkgname, record):
183+ pkg = Mock()
184+ pkg.candidate = Mock()
185+ pkg.candidate.record = record
186+ return pkg
187+
188+
189+class FakedInstallBackend(ObjectWithSignals):
190+ pass
191+
192+
193+class WebappsActivationTestCase(unittest.TestCase):
194+ """Tests the webapps activation plugin """
195+
196+ def setUp(self):
197+ # create webapp
198+ unity_webapp = make_mock_package_with_record(
199+ "unity-webapp", { 'Ubuntu-Webapps-Domain': 'mail.ubuntu.com' })
200+ # create a non-webapp
201+ non_unity_webapp = make_mock_package_with_record(
202+ "unity-webapp", {})
203+ # pkginfo
204+ self.mock_pkginfo = FakedCache()
205+ self.mock_pkginfo["unity-webapp"] = unity_webapp
206+ self.mock_pkginfo["non-unity-webapp"] = non_unity_webapp
207+ # install backend
208+ self.mock_installbackend = FakedInstallBackend()
209+
210+ @patch("softwarecenter.plugins.webapps_activation.get_install_backend")
211+ @patch("softwarecenter.plugins.webapps_activation.get_pkg_info")
212+ def _get_patched_unity_webapps_activation_plugin(self,
213+ mock_get_pkg_info,
214+ mock_install_backend):
215+ mock_install_backend.return_value = self.mock_installbackend
216+ mock_get_pkg_info.return_value = self.mock_pkginfo
217+ w = UnityWebappsActivationPlugin()
218+ w.init_plugin()
219+ patcher = patch.object(w, "activate_unity_webapp_for_domain")
220+ patcher.start()
221+ self.addCleanup(patcher.stop)
222+ return w
223+
224+ def test_activation(self):
225+ w = self._get_patched_unity_webapps_activation_plugin()
226+ self.mock_installbackend.emit(
227+ "transaction-finished",
228+ make_install_result_mock("unity-webapp", True))
229+ self.assertTrue(w.activate_unity_webapp_for_domain.called)
230+ w.activate_unity_webapp_for_domain.assert_called_with("mail.ubuntu.com")
231+
232+ def test_no_activation_on_fail(self):
233+ w = self._get_patched_unity_webapps_activation_plugin()
234+ self.mock_installbackend.emit(
235+ "transaction-finished",
236+ make_install_result_mock("unity-webapp", False))
237+ self.assertFalse(w.activate_unity_webapp_for_domain.called)
238+
239+ def test_no_activation_on_non_webapp(self):
240+ w = self._get_patched_unity_webapps_activation_plugin()
241+ self.mock_installbackend.emit(
242+ "transaction-finished",
243+ make_install_result_mock("non-unity-webapp", True))
244+ self.assertFalse(w.activate_unity_webapp_for_domain.called)
245+
246+if __name__ == "__main__":
247+ unittest.main()
248
249=== modified file 'tests/utils.py'
250--- tests/utils.py 2012-12-17 09:43:31 +0000
251+++ tests/utils.py 2012-12-17 17:32:21 +0000
252@@ -58,7 +58,7 @@
253
254 def url_accessable(url, needle):
255 """Return true if needle is found in the url
256-
257+
258 This is useful as a unittest.skip decorator
259 """
260 f = urlopen(url)
261@@ -235,7 +235,7 @@
262 not even look at doc)
263 """
264 # provide some defaults
265- values = {
266+ values = {
267 'appname': 'some Appname',
268 'pkgname': 'apkg',
269 'categories': 'cat1,cat2,lolcat',
270@@ -253,7 +253,7 @@
271 mock_property_helper.get_categories.return_value = values["categories"]
272 mock_property_helper.get_display_price.return_value = values[
273 "display_price"]
274-
275+
276 mock_property_helper.db = Mock()
277 mock_property_helper.db._aptcache = FakedCache()
278 mock_property_helper.db.get_pkgname.return_value = values["pkgname"]
279@@ -267,7 +267,7 @@
280 mock_property_helper.get_icon_at_size.return_value = values["icon"]
281 mock_property_helper.icons = Mock()
282 mock_property_helper.icons.load_icon.return_value = values["icon"]
283- return mock_property_helper
284+ return mock_property_helper
285
286
287 def setup_test_env():
288@@ -461,7 +461,7 @@
289 def emit(self, signal, *args, **kwargs):
290 """Emit 'signal' passing *args, **kwargs to every callback."""
291 for callback in self._callbacks[signal]:
292- callback(*args, **kwargs)
293+ callback(self, *args, **kwargs)
294
295
296 class FakedCache(ObjectWithSignals, dict):

Subscribers

People subscribed via source and target branches