Merge lp:~paulliu/unity-scope-click/showratings into lp:unity-scope-click
- showratings
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~paulliu/unity-scope-click/showratings |
Merge into: | lp:unity-scope-click |
Diff against target: |
221 lines (+186/-2) 3 files modified
src/Makefile.am (+2/-1) src/click-scope.vala (+7/-1) src/rnrclient.vala (+177/-0) |
To merge this branch: | bzr merge lp:~paulliu/unity-scope-click/showratings |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
dobey (community) | Needs Fixing | ||
Manuel de la Peña (community) | Needs Fixing | ||
Review via email: mp+198349@code.launchpad.net |
This proposal has been superseded by a proposal from 2013-12-12.
Commit message
Provide reviews/ratings from server in previews.
Description of the change
Provide reviews/ratings from server in previews.
PS Jenkins bot (ps-jenkins) wrote : | # |
Manuel de la Peña (mandel) wrote : | # |
Can you explain what is the following line doing:
var reviews = yield rnrClient.
Is "any" some kind of keyword??? Should we use a constant?
We have the following var names:
node1, node2, gvar1
Can we use names that add some information to the reviewer, I have no context of what the data should be and such names do not help. Maybe something like rootNode, ratingNode etc...?
Should we log something in this exception:
182 + try {
183 + gvar1 = Json.gvariant_
184 + } catch (GLib.Error e) {
185 + continue;
186 + }
It might be a good thing to do when debugging and I do not trust the server side not changing things or always working ;)
Why do you use in some cases the var keyword and in others you do not? For example:
143 + Rest.Proxy proxy = new Rest.Proxy(
144 + var call = proxy.new_call();
Could not have used bar in both cases?
In the following code:
257 + try {
258 + parser.
259 + } catch (GLib.Error e) {
260 + }
It might be a good idea to deal with the exception in case some other developer changes the testData wrongly and has bad results in the tests, what do you think???
All the rest of the code looks great, thx!!!
dobey (dobey) wrote : | # |
48 + --pkg rest-0.7 \
I thought we agreed to not use librest, but just use soup for everything?
Also, the test doesn't seem to actually test anything, as I read it. It's fake data in a JSON dict, and you parse it as such. We don't need to write unit tests for json-glib in our code. It's also a bit weird to define a test method inside a fake class, and simply have the actual test method call that method, doing the assertion inside the fake class. Fake classes should really only be used to override methods which require network or dbus access to other daemons, to prevent such access and isolate the tests. Fake data should probably be placed in external files for use in the tests, or at the very least, encoded in the fake-data.vala source file. And the actual test and assertion should happen within the test function itself, not inside a set of methods in another class.
dobey (dobey) wrote : | # |
118 + const string REVIEWS_URL = "http://
Also, this needs to be HTTPS, and should be split up such that the base URL can be changed via environment variable, for testing against staging. See click-webservic
Ying-Chun Liu (paulliu) wrote : | # |
I'll rewrite it to use libsoup because I really cannot make the SSO work with librest.
But maybe we want to use librest for the future at some time as it makes the code cleaner and easier to be maintained?
Ying-Chun Liu (paulliu) wrote : | # |
the reviews retriviing doesn't need the SSO. So I'll keep the http here.
The submit reviews function will be implemented in another branch which will use https.
dobey (dobey) wrote : | # |
77 + const string REVIEWS_BASE_URL = "http://
86 + string from_environ (string env_name, string default_value) {
87 + string env_value = Environment.
88 + return env_value != null ? env_value : default_value;
89 + }
90 +
91 + string get_base_url () {
92 + return from_environ ("U1_REVIEWS_
93 + }
This is still wrong. Why are you not using HTTPS here? Also, the _BASE_URL should only be "https:/
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:91
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:93
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
dobey (dobey) wrote : | # |
130 + public async Variant? get_reviews(string packagename, string? language,
131 + string? origin, string? distroseries,
132 + string? version, string appname,
133 + string page, string sort) {
I wonder if we can abstract all these arguments to a new object, or just pass in the AppDetails object here, and get the language internally rather than taking an argument for it. It's better to have an object containing a bunch of args, than to pass many options individually like this.
- 90. By dobey
-
Don't reimplement generated rules for vala.
Take advantage of VALA_CHECK_MODULES to find vala packages.
Split non-compatible mdoules to another PKG_CHECK_MODULES.
Build majority of the code as a noinst lib, which click-scope and tests link to.
Update the .bzrignore for an autools project.
. Fixes: https://bugs.launchpad .net/bugs/ 1258559. Approved by Roberto Alsina, Mike McCracken, PS Jenkins bot.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:94
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 91. By Ying-Chun Liu
-
get reviews & ratings from server.
- 92. By Ying-Chun Liu
-
remvoe server-status as we don't need to use it.
- 93. By Ying-Chun Liu
-
Add comments.
- 94. By Ying-Chun Liu
-
Change origin to "click".
- 95. By Ying-Chun Liu
-
Merge upstream.
- 96. By Ying-Chun Liu
-
fix indent
- 97. By Ying-Chun Liu
-
Add some unit tests.
Partly fix the issues in comment 465611 - 98. By Ying-Chun Liu
-
Add version/framework
- 99. By Ying-Chun Liu
-
merge trunk
- 100. By Ying-Chun Liu
-
fix indent.
- 101. By Ying-Chun Liu
-
fix comment for ReviewFilter.
- 102. By Ying-Chun Liu
-
fix indent.
Add test for from_environ
fix framework. - 103. By Ying-Chun Liu
-
Add 2014 to copyright.
- 104. By Ying-Chun Liu
-
revert part of the previous commit - change back framework as string list.
Add a TODO to indicate that we should use system's framework. - 105. By Ying-Chun Liu
-
use "click" as framework.
Unmerged revisions
Preview Diff
1 | === modified file 'src/Makefile.am' | |||
2 | --- src/Makefile.am 2013-12-11 16:46:03 +0000 | |||
3 | +++ src/Makefile.am 2013-12-12 14:18:57 +0000 | |||
4 | @@ -43,7 +43,8 @@ | |||
5 | 43 | click-interface.vala \ | 43 | click-interface.vala \ |
6 | 44 | ubuntuone-credentials.vala \ | 44 | ubuntuone-credentials.vala \ |
7 | 45 | non-click-scope.vala \ | 45 | non-click-scope.vala \ |
9 | 46 | utils.vala | 46 | utils.vala \ |
10 | 47 | rnrclient.vala | ||
11 | 47 | 48 | ||
12 | 48 | click_scope_VALAFLAGS = \ | 49 | click_scope_VALAFLAGS = \ |
13 | 49 | --thread \ | 50 | --thread \ |
14 | 50 | 51 | ||
15 | === modified file 'src/click-scope.vala' | |||
16 | --- src/click-scope.vala 2013-12-10 22:21:24 +0000 | |||
17 | +++ src/click-scope.vala 2013-12-12 14:18:57 +0000 | |||
18 | @@ -80,6 +80,7 @@ | |||
19 | 80 | const string LABEL_COMMENTS = "Comments"; | 80 | const string LABEL_COMMENTS = "Comments"; |
20 | 81 | 81 | ||
21 | 82 | ClickInterface click_if = new ClickInterface (); | 82 | ClickInterface click_if = new ClickInterface (); |
22 | 83 | RNRClient rnrClient = new RNRClient(); | ||
23 | 83 | 84 | ||
24 | 84 | public ClickScope () | 85 | public ClickScope () |
25 | 85 | { | 86 | { |
26 | @@ -118,7 +119,12 @@ | |||
27 | 118 | preview.add_info(new Unity.InfoHint.with_variant(HINT_PUBLISHER, "Publisher", null, new Variant.string(details.publisher))); | 119 | preview.add_info(new Unity.InfoHint.with_variant(HINT_PUBLISHER, "Publisher", null, new Variant.string(details.publisher))); |
28 | 119 | preview.add_info(new Unity.InfoHint.with_variant(HINT_SCREENSHOTS, LABEL_SCREENSHOTS, null, new Variant.strv(details.more_screenshot_urls))); | 120 | preview.add_info(new Unity.InfoHint.with_variant(HINT_SCREENSHOTS, LABEL_SCREENSHOTS, null, new Variant.strv(details.more_screenshot_urls))); |
29 | 120 | preview.add_info(new Unity.InfoHint.with_variant(HINT_KEYWORDS, LABEL_KEYWORDS, null, new Variant.strv(details.keywords))); | 121 | preview.add_info(new Unity.InfoHint.with_variant(HINT_KEYWORDS, LABEL_KEYWORDS, null, new Variant.strv(details.keywords))); |
31 | 121 | // TODO: get the proper ratings and reviews from the rnr web service | 122 | // get the proper ratings and reviews from the rnr web service |
32 | 123 | var reviews = yield rnrClient.get_reviews(details); | ||
33 | 124 | if (reviews != null) { | ||
34 | 125 | preview.add_info(new Unity.InfoHint.with_variant(HINT_REVIEWS, LABEL_REVIEWS, null, reviews)); | ||
35 | 126 | debug("Add reviews "+reviews.print(true)); | ||
36 | 127 | } | ||
37 | 122 | return preview; | 128 | return preview; |
38 | 123 | } catch (WebserviceError e) { | 129 | } catch (WebserviceError e) { |
39 | 124 | debug ("Error calling webservice: %s", e.message); | 130 | debug ("Error calling webservice: %s", e.message); |
40 | 125 | 131 | ||
41 | === added file 'src/rnrclient.vala' | |||
42 | --- src/rnrclient.vala 1970-01-01 00:00:00 +0000 | |||
43 | +++ src/rnrclient.vala 2013-12-12 14:18:57 +0000 | |||
44 | @@ -0,0 +1,177 @@ | |||
45 | 1 | /* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ | ||
46 | 2 | /* | ||
47 | 3 | * Copyright (C) 2013 Canonical, Ltd. | ||
48 | 4 | * | ||
49 | 5 | * This program is free software; you can redistribute it and/or modify | ||
50 | 6 | * it under the terms of the GNU General Public License as published by | ||
51 | 7 | * the Free Software Foundation; version 3. | ||
52 | 8 | * | ||
53 | 9 | * This program is distributed in the hope that it will be useful, | ||
54 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
55 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
56 | 12 | * GNU General Public License for more details. | ||
57 | 13 | * | ||
58 | 14 | * You should have received a copy of the GNU General Public License | ||
59 | 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
60 | 16 | */ | ||
61 | 17 | |||
62 | 18 | using Json; | ||
63 | 19 | |||
64 | 20 | class RNRClient : GLib.Object | ||
65 | 21 | { | ||
66 | 22 | UbuntuoneCredentials u1creds; | ||
67 | 23 | const string CONSUMER_KEY = "consumer_key"; | ||
68 | 24 | const string CONSUMER_SECRET = "consumer_secret"; | ||
69 | 25 | const string TOKEN = "token"; | ||
70 | 26 | const string TOKEN_SECRET = "token_secret"; | ||
71 | 27 | const string REVIEWS_BASE_URL = "https://reviews.ubuntu.com/reviews"; | ||
72 | 28 | |||
73 | 29 | internal Soup.SessionAsync http_session; | ||
74 | 30 | |||
75 | 31 | construct { | ||
76 | 32 | http_session = WebClient.get_webclient(); | ||
77 | 33 | u1creds = new UbuntuoneCredentials (); | ||
78 | 34 | } | ||
79 | 35 | |||
80 | 36 | string from_environ (string env_name, string default_value) { | ||
81 | 37 | string env_value = Environment.get_variable (env_name); | ||
82 | 38 | return env_value != null ? env_value : default_value; | ||
83 | 39 | } | ||
84 | 40 | |||
85 | 41 | string get_base_url () { | ||
86 | 42 | return from_environ ("U1_REVIEWS_BASE_URL", REVIEWS_BASE_URL); | ||
87 | 43 | } | ||
88 | 44 | |||
89 | 45 | string get_status_url() { | ||
90 | 46 | return get_base_url() + "/api/1.0/server-status"; | ||
91 | 47 | } | ||
92 | 48 | |||
93 | 49 | string get_review_url() { | ||
94 | 50 | return get_base_url() + "/api/1.0/reviews/filter/%s/%s/%s/%s/%s%s/page/%s/%s/"; | ||
95 | 51 | } | ||
96 | 52 | |||
97 | 53 | public async string server_status() { | ||
98 | 54 | WebserviceError failure = null; | ||
99 | 55 | string url = get_status_url(); | ||
100 | 56 | string response=""; | ||
101 | 57 | |||
102 | 58 | var message = new Soup.Message ("GET", url); | ||
103 | 59 | http_session.queue_message(message, (http_session, message) => { | ||
104 | 60 | if (message.status_code != Soup.KnownStatusCode.OK) { | ||
105 | 61 | var msg = "Web request failed: HTTP %u %s".printf( | ||
106 | 62 | message.status_code, message.reason_phrase); | ||
107 | 63 | failure = new WebserviceError.HTTP_ERROR(msg); | ||
108 | 64 | } else { | ||
109 | 65 | message.response_body.flatten (); | ||
110 | 66 | response = (string) message.response_body.data; | ||
111 | 67 | debug ("response is %s", response); | ||
112 | 68 | } | ||
113 | 69 | server_status.callback(); | ||
114 | 70 | }); | ||
115 | 71 | yield; | ||
116 | 72 | if (failure != null) { | ||
117 | 73 | return "no"; | ||
118 | 74 | } | ||
119 | 75 | return response; | ||
120 | 76 | } | ||
121 | 77 | |||
122 | 78 | public async Variant? get_reviews(AppDetails details) { | ||
123 | 79 | string[] languages = GLib.Intl.get_language_names(); | ||
124 | 80 | string? language = null; | ||
125 | 81 | if (languages.length > 0) { | ||
126 | 82 | language = languages[0]; | ||
127 | 83 | } | ||
128 | 84 | var filter = new ReviewFilter(); | ||
129 | 85 | filter.language = language; | ||
130 | 86 | filter.appname = details.title; | ||
131 | 87 | return yield get_reviews_core(filter); | ||
132 | 88 | } | ||
133 | 89 | |||
134 | 90 | public async Variant? get_reviews_core(ReviewFilter filter) { | ||
135 | 91 | Variant? ret = null; | ||
136 | 92 | WebserviceError failure = null; | ||
137 | 93 | string url = get_review_url().printf(filter.language, | ||
138 | 94 | filter.origin, | ||
139 | 95 | filter.distroseries, | ||
140 | 96 | filter.version, | ||
141 | 97 | filter.packagename, | ||
142 | 98 | filter.appname, | ||
143 | 99 | filter.page, | ||
144 | 100 | filter.sort); | ||
145 | 101 | string response=""; | ||
146 | 102 | |||
147 | 103 | debug ("url is %s", url); | ||
148 | 104 | |||
149 | 105 | var message = new Soup.Message ("GET", url); | ||
150 | 106 | http_session.queue_message(message, (http_session, message) => { | ||
151 | 107 | if (message.status_code != Soup.KnownStatusCode.OK) { | ||
152 | 108 | var msg = "Web request failed: HTTP %u %s".printf( | ||
153 | 109 | message.status_code, message.reason_phrase); | ||
154 | 110 | failure = new WebserviceError.HTTP_ERROR(msg); | ||
155 | 111 | } else { | ||
156 | 112 | message.response_body.flatten (); | ||
157 | 113 | response = (string) message.response_body.data; | ||
158 | 114 | debug ("response is %s", response); | ||
159 | 115 | } | ||
160 | 116 | get_reviews_core.callback(); | ||
161 | 117 | }); | ||
162 | 118 | yield; | ||
163 | 119 | if (failure != null) { | ||
164 | 120 | debug("cannot get reviews error %s", failure.message); | ||
165 | 121 | return ret; | ||
166 | 122 | } | ||
167 | 123 | var parser = new Json.Parser(); | ||
168 | 124 | try { | ||
169 | 125 | parser.load_from_data(response); | ||
170 | 126 | } catch (GLib.Error e) { | ||
171 | 127 | debug ("parse reviews response error %s", e.message); | ||
172 | 128 | return ret; | ||
173 | 129 | } | ||
174 | 130 | |||
175 | 131 | ret = convertJSONtoVariant(parser); | ||
176 | 132 | return ret; | ||
177 | 133 | } | ||
178 | 134 | |||
179 | 135 | protected Variant? convertJSONtoVariant(Json.Parser parser) { | ||
180 | 136 | Variant? ret = null; | ||
181 | 137 | var root_object = parser.get_root(); | ||
182 | 138 | var builder = new VariantBuilder(new VariantType("av")); | ||
183 | 139 | |||
184 | 140 | foreach (var node in root_object.get_array().get_elements()) { | ||
185 | 141 | var ht = new VariantBuilder(new VariantType("a{sv}")); | ||
186 | 142 | var node_object = node.get_object(); | ||
187 | 143 | foreach (var node_member in node_object.get_members()) { | ||
188 | 144 | Variant? gvar_member = null; | ||
189 | 145 | try { | ||
190 | 146 | gvar_member = Json.gvariant_deserialize(node_object.get_member(node_member), null); | ||
191 | 147 | } catch (GLib.Error e) { | ||
192 | 148 | debug ("gvariant deserialize error: %s",e.message); | ||
193 | 149 | continue; | ||
194 | 150 | } | ||
195 | 151 | if (gvar_member == null) { | ||
196 | 152 | continue; | ||
197 | 153 | } | ||
198 | 154 | if (gvar_member.is_of_type(VariantType.MAYBE) && gvar_member.get_maybe() == null) { | ||
199 | 155 | continue; | ||
200 | 156 | } | ||
201 | 157 | ht.add("{sv}", node_member, gvar_member); | ||
202 | 158 | } | ||
203 | 159 | Variant dict = ht.end(); | ||
204 | 160 | builder.add("v", dict); | ||
205 | 161 | } | ||
206 | 162 | |||
207 | 163 | ret = builder.end(); | ||
208 | 164 | return ret; | ||
209 | 165 | } | ||
210 | 166 | } | ||
211 | 167 | |||
212 | 168 | class ReviewFilter : GLib.Object { | ||
213 | 169 | public string packagename = ""; | ||
214 | 170 | public string language = "any"; | ||
215 | 171 | public string origin = "any"; | ||
216 | 172 | public string distroseries = "any"; | ||
217 | 173 | public string version = "any"; | ||
218 | 174 | public string appname = ""; | ||
219 | 175 | public string page = "1"; | ||
220 | 176 | public string sort = "helpful"; | ||
221 | 177 | } |
PASSED: Continuous integration, rev:90 jenkins. qa.ubuntu. com/job/ unity-scope- click-ci/ 118/ jenkins. qa.ubuntu. com/job/ unity-scope- click-trusty- amd64-ci/ 16 jenkins. qa.ubuntu. com/job/ unity-scope- click-trusty- armhf-ci/ 16
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- scope-click- ci/118/ rebuild
http://