Merge lp:~milo/linaro-patchmetrics/bug1013577 into lp:linaro-patchmetrics

Proposed by Milo Casagrande
Status: Merged
Merged at revision: 365
Proposed branch: lp:~milo/linaro-patchmetrics/bug1013577
Merge into: lp:linaro-patchmetrics
Diff against target: 219 lines (+79/-31)
4 files modified
apps/patchmetrics/bin/sync-gerrit-changes.py (+25/-18)
apps/patchmetrics/gerrit.py (+18/-9)
apps/patchmetrics/gerrit_values.py (+12/-1)
apps/patchmetrics/tests/test_gerrit.py (+24/-3)
To merge this branch: bzr merge lp:~milo/linaro-patchmetrics/bug1013577
Reviewer Review Type Date Requested Status
Deepti B. Kalakeri (community) Approve
Review via email: mp+112290@code.launchpad.net

Description of the change

Hello,

requesting a new merge: we are still getting the error from gerrit about user not found, but this should be handled correctly. I fixed the error string we get back to be exactly as the one we receive, fixed also the query parameters to use to start a new query from the last value. I renamed one module to use a more generic name in order to store also other values than JSON keys.

To post a comment you must log in.
370. By Milo Casagrande

Remove white chars from email, just in case.

371. By Milo Casagrande

Force string on the query, and remove white spaces.

372. By Milo Casagrande

Fixed param name on docstring.

Revision history for this message
Deepti B. Kalakeri (deeptik) wrote :

As discussed on IRC, somehow the email formation/query seems to be incorrect in the existing code even before the changes done here. I will wait for you to push the changes for the query format and will then proceed with the review.

Thanks!!!
Deepti.

373. By Milo Casagrande

Fixed query quoting.

Revision history for this message
Deepti B. Kalakeri (deeptik) wrote :

=== modified file 'apps/patchmetrics/tests/test_gerrit.py'
--- apps/patchmetrics/tests/test_gerrit.py 2012-06-22 14:33:32 +0000
+++ apps/patchmetrics/tests/test_gerrit.py 2012-06-27 10:48:42 +0000
@@ -102,10 +102,11 @@
     def test_create_request_query_url(self):
         """Tests the creation of a valid request URL."""
         params = {'format': 'JSON', 'n': 100}
- query_params = {'owner': '<email address hidden>', 'sortkey_after': 'abcd'}
+ query_params = {'owner': '<email address hidden>',
+ 'resume_sortkey': 'abcd'}
         expected_result = ROOT_REST_URL + CHANGES_QUERY_PATH + \
         QUERY_STRING_START + \
- "n=100&format=JSON&q=owner:<email address hidden>+sortkey_after:abcd"
+ "n=100&format=JSON&q=owner:<email address hidden>+resume_sortkey:abcd"

Should this be fixed to the address the <email address hidden> ?
or have one more test for it ?
         self.assertEquals(expected_result,
                           create_request_query_url(ROOT_REST_URL,
                                                    CHANGES_QUERY_PATH,

review: Needs Fixing
374. By Milo Casagrande

Fixed tests.

Revision history for this message
Milo Casagrande (milo) wrote :

Thanks Deepti,

fixed those as well, and added a new one.

Revision history for this message
Deepti B. Kalakeri (deeptik) wrote :

112 query_params = {'owner': '<email address hidden>', 'sortkey_after': 'abcd'}
113 expected_result = (ROOT_REST_URL + CHANGES_QUERY_PATH +
114 QUERY_STRING_START + "n=100&format=JSON&q=owner:"
115 "person%40example.org+sortkey_after:abcd")

Should not this be resume_key instead of sortkery_after ?

review: Needs Fixing
375. By Milo Casagrande

Fixed wrong query parameter.

Revision history for this message
Milo Casagrande (milo) wrote :

> Should not this be resume_key instead of sortkery_after ?

Yep, it should be "resume_sortkey", now is fixed.
Thanks again.

Revision history for this message
Deepti B. Kalakeri (deeptik) wrote :

looks good +1.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'apps/patchmetrics/bin/sync-gerrit-changes.py'
2--- apps/patchmetrics/bin/sync-gerrit-changes.py 2012-06-25 09:12:00 +0000
3+++ apps/patchmetrics/bin/sync-gerrit-changes.py 2012-06-27 12:19:18 +0000
4@@ -10,7 +10,7 @@
5 create_or_update_patches_from_aosp_changes,
6 get_aosp_changes_from,
7 )
8-from patchmetrics.gerrit_json import (
9+from patchmetrics.gerrit_values import (
10 GERRIT_MORE_CHANGES,
11 GERRIT_SORT_KEY,
12 )
13@@ -18,30 +18,37 @@
14
15 linaro_engineers = Person.objects.filter(
16 user__id__in=TeamMembership.objects.values('member').query).distinct()
17+
18 for person in linaro_engineers:
19- start_after = None
20+ resume_key = None
21+ # We are just being a little bit paranoid here.
22+ user_email = person.email.strip()
23 while True:
24 try:
25- results = get_aosp_changes_from(person.email,
26- start_after=start_after)
27+ results = get_aosp_changes_from(user_email, resume_key=resume_key)
28 except GerritError, e:
29- if '%s not found' % person.email in str(e):
30+ if ('User %s not found' % user_email) in str(e):
31 # Gerrit returns an error when you search for changes owned by
32 # an email address that's not registered, but in this case we
33 # just skip to the next email.
34 break
35 raise
36- # If we get all the changes in a single batch, the GERRIT_MORE_CHANGES
37- # key will not be in the JSON output, so we set it to False.
38- more_changes = results[-1].get(GERRIT_MORE_CHANGES) or False
39- created_or_updated_patches = (
40- create_or_update_patches_from_aosp_changes(results, person))
41-
42- # If there are less created/updated changes than the number of changes
43- # returned by Gerrit we know we can stop as they're sorted most
44- # recently updated first.
45- if len(results) != len(created_or_updated_patches) or \
46- (not more_changes):
47+
48+ if results:
49+ # If we get all the changes in a single batch, the
50+ # GERRIT_MORE_CHANGES key will not be in the JSON output, so we
51+ # set it to False.
52+ more_changes = results[-1].get(GERRIT_MORE_CHANGES) or False
53+ created_or_updated_patches = (
54+ create_or_update_patches_from_aosp_changes(results, person))
55+
56+ # If there are less created/updated changes than the number of
57+ # changes returned by Gerrit we know we can stop as they're sorted
58+ # most recently updated first.
59+ if len(results) != len(created_or_updated_patches) or \
60+ (not more_changes):
61+ break
62+
63+ resume_key = results[-1].get(GERRIT_SORT_KEY)
64+ else:
65 break
66-
67- start_after = results[-1].get(GERRIT_SORT_KEY)
68
69=== modified file 'apps/patchmetrics/gerrit.py'
70--- apps/patchmetrics/gerrit.py 2012-06-25 12:50:28 +0000
71+++ apps/patchmetrics/gerrit.py 2012-06-27 12:19:18 +0000
72@@ -1,17 +1,22 @@
73 from datetime import datetime
74 import email
75+import urllib
76 import urllib2
77-from urllib import urlencode
78
79 import json
80
81 from patchwork.models import Patch, Project, State
82 from patchmetrics.models import GerritChange
83-from patchmetrics.gerrit_json import (
84+from patchmetrics.gerrit_values import (
85 GERRIT_CREATED_KEY,
86+ GERRIT_DEFAULT_JSON,
87 GERRIT_ID_KEY,
88 GERRIT_NUMBER_KEY,
89 GERRIT_PROJECT_KEY,
90+ GERRIT_QUERY_FORMAT,
91+ GERRIT_QUERY_OWNER,
92+ GERRIT_QUERY_PG_SIZE,
93+ GERRIT_QUERY_RESUME_SORTKEY,
94 GERRIT_SANITIZABLE_VALUE,
95 GERRIT_STATUS_KEY,
96 GERRIT_SUBJECT_KEY,
97@@ -40,12 +45,12 @@
98 """The gerrit server returned an error in response to a query."""
99
100
101-def get_aosp_changes_from(email, start_after=None, page_size=25,
102- return_format='JSON_COMPACT'):
103+def get_aosp_changes_from(email, resume_key=None, page_size=25,
104+ return_format=GERRIT_DEFAULT_JSON):
105 """Get the list of changes authored by the given email address.
106
107 :param email: The email of the user to get the changes of.
108- :param start_after: Only include changes whose 'sortkey_after' is lower
109+ :param resume_key: Only include changes whose 'sortkey_after' is lower
110 than this. Use None if you want to start from the
111 beginning.
112 :param page_size: Number of items to include in the list, defaults to 25.
113@@ -53,8 +58,10 @@
114 'JSON_COMPACT' for JSON format without spaces, also
115 possible to specify 'JSON'.
116 """
117- params = {'format': return_format, 'n': page_size}
118- query_params = {'owner': email, 'sortkey_after': start_after}
119+ params = {GERRIT_QUERY_FORMAT: return_format,
120+ GERRIT_QUERY_PG_SIZE: page_size}
121+ query_params = {GERRIT_QUERY_OWNER: email,
122+ GERRIT_QUERY_RESUME_SORTKEY: resume_key}
123 return rest_api_request(ROOT_REST_URL, CHANGES_QUERY_PATH, params,
124 query_params)
125
126@@ -88,7 +95,7 @@
127 path += '/'
128 request_url = url + path + QUERY_STRING_START
129
130- request_url += urlencode(params)
131+ request_url += urllib.urlencode(params)
132 request_url += create_gerrit_rest_query(query_params)
133
134 return request_url
135@@ -113,7 +120,9 @@
136 for key, value in query_params.iteritems():
137 # We cannot have None values here, we just skip them.
138 if value is not None:
139- params_list.append(":".join((key, value)))
140+ # We need strings here, and we remove white spaces.
141+ params_list.append(":".join((key,
142+ urllib.quote(str(value).strip()))))
143 # The resulting query string, without separators or prefixes, should be in
144 # the form of:
145 # key:value+key:value
146
147=== renamed file 'apps/patchmetrics/gerrit_json.py' => 'apps/patchmetrics/gerrit_values.py'
148--- apps/patchmetrics/gerrit_json.py 2012-06-22 14:33:32 +0000
149+++ apps/patchmetrics/gerrit_values.py 2012-06-27 12:19:18 +0000
150@@ -1,4 +1,4 @@
151-# File with all the gerrit JSON valid keys.
152+# File with the gerrit JSON valid keys and other gerrit values.
153 # For more information about the values defined here, look:
154 # https://gerrit-review.googlesource.com/Documentation/json.html
155 # Also, on bug https://bugs.launchpad.net/linaro-patchmetrics/+bug/1013577,
156@@ -14,7 +14,18 @@
157 GERRIT_STATUS_KEY = 'status'
158 GERRIT_PROJECT_KEY = 'project'
159 GERRIT_SUBJECT_KEY = 'subject'
160+
161 # Gerrit JSON output starts with a magic prefix, making it not valid JSON.
162 # For more info:
163 # https://gerrit-review.googlesource.com/Documentation/rest-api.html
164 GERRIT_SANITIZABLE_VALUE = ")]}'"
165+
166+# The possible values for the output format of the Gerrit query.
167+GERRIT_DEFAULT_JSON = 'JSON_COMPACT'
168+GERRIT_NORMAL_JSON = 'JSON'
169+
170+# Gerrit query parameters
171+GERRIT_QUERY_OWNER = 'owner'
172+GERRIT_QUERY_FORMAT = 'format'
173+GERRIT_QUERY_PG_SIZE = 'n'
174+GERRIT_QUERY_RESUME_SORTKEY = 'resume_sortkey'
175
176=== modified file 'apps/patchmetrics/tests/test_gerrit.py'
177--- apps/patchmetrics/tests/test_gerrit.py 2012-06-22 14:33:32 +0000
178+++ apps/patchmetrics/tests/test_gerrit.py 2012-06-27 12:19:18 +0000
179@@ -3,6 +3,13 @@
180
181 from django.test import TestCase
182
183+from patchmetrics.gerrit_values import (
184+ GERRIT_QUERY_FORMAT,
185+ GERRIT_QUERY_OWNER,
186+ GERRIT_QUERY_PG_SIZE,
187+ GERRIT_QUERY_RESUME_SORTKEY,
188+)
189+
190 from patchmetrics.gerrit import (
191 CHANGES_QUERY_PATH,
192 QUERY_STRING_START,
193@@ -103,9 +110,23 @@
194 """Tests the creation of a valid request URL."""
195 params = {'format': 'JSON', 'n': 100}
196 query_params = {'owner': 'person@example.org', 'sortkey_after': 'abcd'}
197- expected_result = ROOT_REST_URL + CHANGES_QUERY_PATH + \
198- QUERY_STRING_START + \
199- "n=100&format=JSON&q=owner:person@example.org+sortkey_after:abcd"
200+ expected_result = (ROOT_REST_URL + CHANGES_QUERY_PATH +
201+ QUERY_STRING_START + "n=100&format=JSON&q=owner:"
202+ "person%40example.org+resume_sortkey:abcd")
203+ self.assertEquals(expected_result,
204+ create_request_query_url(ROOT_REST_URL,
205+ CHANGES_QUERY_PATH,
206+ params, query_params))
207+
208+ def test_create_request_query_url_quoted(self):
209+ """Tests the creation of a valid request URL with a complex email."""
210+ params = {GERRIT_QUERY_FORMAT: 'JSON', GERRIT_QUERY_PG_SIZE: 100}
211+ query_params = {GERRIT_QUERY_OWNER: 'name+surname.person@example.org',
212+ GERRIT_QUERY_RESUME_SORTKEY: 'abcd'}
213+ expected_result = (ROOT_REST_URL + CHANGES_QUERY_PATH +
214+ QUERY_STRING_START + "n=100&format=JSON&q=owner:"
215+ "name%2Bsurname.person%40example.org+"
216+ "resume_sortkey:abcd")
217 self.assertEquals(expected_result,
218 create_request_query_url(ROOT_REST_URL,
219 CHANGES_QUERY_PATH,

Subscribers

People subscribed via source and target branches