Merge lp:~cjohnston/ubuntu-ci-services-itself/ts-project into lp:ubuntu-ci-services-itself
- ts-project
- Merge into trunk
Proposed by
Chris Johnston
Status: | Merged |
---|---|
Approved by: | Chris Johnston |
Approved revision: | 19 |
Merged at revision: | 22 |
Proposed branch: | lp:~cjohnston/ubuntu-ci-services-itself/ts-project |
Merge into: | lp:ubuntu-ci-services-itself |
Diff against target: |
375 lines (+316/-0) 8 files modified
ticket_system/project/__init__.py (+14/-0) ticket_system/project/admin.py (+31/-0) ticket_system/project/api.py (+42/-0) ticket_system/project/migrations/0001_initial.py (+51/-0) ticket_system/project/models.py (+38/-0) ticket_system/project/tests.py (+136/-0) ticket_system/ticket_system/settings.py (+1/-0) ticket_system/ticket_system/urls.py (+3/-0) |
To merge this branch: | bzr merge lp:~cjohnston/ubuntu-ci-services-itself/ts-project |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andy Doan (community) | Approve | ||
Review via email:
|
Commit message
Add project app and read API
Description of the change
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andy Doan (doanac) wrote : | # |
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andy Doan (doanac) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory 'ticket_system/project' | |||
2 | === added file 'ticket_system/project/__init__.py' | |||
3 | --- ticket_system/project/__init__.py 1970-01-01 00:00:00 +0000 | |||
4 | +++ ticket_system/project/__init__.py 2013-12-09 19:42:24 +0000 | |||
5 | @@ -0,0 +1,14 @@ | |||
6 | 1 | # Ubuntu Continuous Integration Engine | ||
7 | 2 | # Copyright 2013 Canonical Ltd. | ||
8 | 3 | |||
9 | 4 | # This program is free software: you can redistribute it and/or modify it | ||
10 | 5 | # under the terms of the GNU Affero General Public License version 3, as | ||
11 | 6 | # published by the Free Software Foundation. | ||
12 | 7 | |||
13 | 8 | # This program is distributed in the hope that it will be useful, but | ||
14 | 9 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
15 | 10 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
16 | 11 | # PURPOSE. See the GNU Affero General Public License for more details. | ||
17 | 12 | |||
18 | 13 | # You should have received a copy of the GNU Affero General Public License | ||
19 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | 0 | 15 | ||
21 | === added file 'ticket_system/project/admin.py' | |||
22 | --- ticket_system/project/admin.py 1970-01-01 00:00:00 +0000 | |||
23 | +++ ticket_system/project/admin.py 2013-12-09 19:42:24 +0000 | |||
24 | @@ -0,0 +1,31 @@ | |||
25 | 1 | # Ubuntu Continuous Integration Engine | ||
26 | 2 | # Copyright 2013 Canonical Ltd. | ||
27 | 3 | |||
28 | 4 | # This program is free software: you can redistribute it and/or modify it | ||
29 | 5 | # under the terms of the GNU Affero General Public License version 3, as | ||
30 | 6 | # published by the Free Software Foundation. | ||
31 | 7 | |||
32 | 8 | # This program is distributed in the hope that it will be useful, but | ||
33 | 9 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
34 | 10 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
35 | 11 | # PURPOSE. See the GNU Affero General Public License for more details. | ||
36 | 12 | |||
37 | 13 | # You should have received a copy of the GNU Affero General Public License | ||
38 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
39 | 15 | |||
40 | 16 | from django.contrib import admin | ||
41 | 17 | from project.models import SourcePackage, BinaryPackage | ||
42 | 18 | |||
43 | 19 | |||
44 | 20 | class SourcePackageAdmin(admin.ModelAdmin): | ||
45 | 21 | search_fields = ['name'] | ||
46 | 22 | list_display = ('name',) | ||
47 | 23 | |||
48 | 24 | |||
49 | 25 | class BinaryPackageAdmin(admin.ModelAdmin): | ||
50 | 26 | list_filter = ['seeded'] | ||
51 | 27 | search_fields = ['name', 'sourcepackage'] | ||
52 | 28 | list_display = ('name', 'sourcepackage', 'seeded') | ||
53 | 29 | |||
54 | 30 | admin.site.register(SourcePackage, SourcePackageAdmin) | ||
55 | 31 | admin.site.register(BinaryPackage, BinaryPackageAdmin) | ||
56 | 0 | 32 | ||
57 | === added file 'ticket_system/project/api.py' | |||
58 | --- ticket_system/project/api.py 1970-01-01 00:00:00 +0000 | |||
59 | +++ ticket_system/project/api.py 2013-12-09 19:42:24 +0000 | |||
60 | @@ -0,0 +1,42 @@ | |||
61 | 1 | # Ubuntu Continuous Integration Engine | ||
62 | 2 | # Copyright 2013 Canonical Ltd. | ||
63 | 3 | |||
64 | 4 | # This program is free software: you can redistribute it and/or modify it | ||
65 | 5 | # under the terms of the GNU Affero General Public License version 3, as | ||
66 | 6 | # published by the Free Software Foundation. | ||
67 | 7 | |||
68 | 8 | # This program is distributed in the hope that it will be useful, but | ||
69 | 9 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
70 | 10 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
71 | 11 | # PURPOSE. See the GNU Affero General Public License for more details. | ||
72 | 12 | |||
73 | 13 | # You should have received a copy of the GNU Affero General Public License | ||
74 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
75 | 15 | |||
76 | 16 | from tastypie import fields | ||
77 | 17 | from tastypie.resources import ModelResource | ||
78 | 18 | from tastypie.constants import ALL | ||
79 | 19 | from project.models import SourcePackage, BinaryPackage | ||
80 | 20 | |||
81 | 21 | |||
82 | 22 | class SourcePackageResource(ModelResource): | ||
83 | 23 | |||
84 | 24 | class Meta: | ||
85 | 25 | queryset = SourcePackage.objects.all() | ||
86 | 26 | allowed_methods = ['get'] | ||
87 | 27 | filtering = { | ||
88 | 28 | "name": ('exact', 'startswith'), | ||
89 | 29 | } | ||
90 | 30 | |||
91 | 31 | |||
92 | 32 | class BinaryPackageResource(ModelResource): | ||
93 | 33 | sourcepackage = fields.ToOneField(SourcePackageResource, 'sourcepackage', | ||
94 | 34 | full=True) | ||
95 | 35 | |||
96 | 36 | class Meta: | ||
97 | 37 | queryset = BinaryPackage.objects.all() | ||
98 | 38 | allowed_methods = ['get'] | ||
99 | 39 | filtering = { | ||
100 | 40 | "name": ('exact', 'startswith'), | ||
101 | 41 | "seeded": ALL, | ||
102 | 42 | } | ||
103 | 0 | 43 | ||
104 | === added directory 'ticket_system/project/migrations' | |||
105 | === added file 'ticket_system/project/migrations/0001_initial.py' | |||
106 | --- ticket_system/project/migrations/0001_initial.py 1970-01-01 00:00:00 +0000 | |||
107 | +++ ticket_system/project/migrations/0001_initial.py 2013-12-09 19:42:24 +0000 | |||
108 | @@ -0,0 +1,51 @@ | |||
109 | 1 | # -*- coding: utf-8 -*- | ||
110 | 2 | import datetime | ||
111 | 3 | from south.db import db | ||
112 | 4 | from south.v2 import SchemaMigration | ||
113 | 5 | from django.db import models | ||
114 | 6 | |||
115 | 7 | |||
116 | 8 | class Migration(SchemaMigration): | ||
117 | 9 | |||
118 | 10 | def forwards(self, orm): | ||
119 | 11 | # Adding model 'SourcePackage' | ||
120 | 12 | db.create_table('sourcepackage', ( | ||
121 | 13 | (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
122 | 14 | ('name', self.gf('django.db.models.fields.CharField')(max_length=4096)), | ||
123 | 15 | )) | ||
124 | 16 | db.send_create_signal(u'project', ['SourcePackage']) | ||
125 | 17 | |||
126 | 18 | # Adding model 'BinaryPackage' | ||
127 | 19 | db.create_table('binarypackage', ( | ||
128 | 20 | (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
129 | 21 | ('name', self.gf('django.db.models.fields.CharField')(max_length=4096)), | ||
130 | 22 | ('sourcepackage', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['project.SourcePackage'])), | ||
131 | 23 | ('seeded', self.gf('django.db.models.fields.BooleanField')(default=False)), | ||
132 | 24 | )) | ||
133 | 25 | db.send_create_signal(u'project', ['BinaryPackage']) | ||
134 | 26 | |||
135 | 27 | |||
136 | 28 | def backwards(self, orm): | ||
137 | 29 | # Deleting model 'SourcePackage' | ||
138 | 30 | db.delete_table('sourcepackage') | ||
139 | 31 | |||
140 | 32 | # Deleting model 'BinaryPackage' | ||
141 | 33 | db.delete_table('binarypackage') | ||
142 | 34 | |||
143 | 35 | |||
144 | 36 | models = { | ||
145 | 37 | u'project.binarypackage': { | ||
146 | 38 | 'Meta': {'object_name': 'BinaryPackage', 'db_table': "'binarypackage'"}, | ||
147 | 39 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
148 | 40 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '4096'}), | ||
149 | 41 | 'seeded': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
150 | 42 | 'sourcepackage': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['project.SourcePackage']"}) | ||
151 | 43 | }, | ||
152 | 44 | u'project.sourcepackage': { | ||
153 | 45 | 'Meta': {'object_name': 'SourcePackage', 'db_table': "'sourcepackage'"}, | ||
154 | 46 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
155 | 47 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '4096'}) | ||
156 | 48 | } | ||
157 | 49 | } | ||
158 | 50 | |||
159 | 51 | complete_apps = ['project'] | ||
160 | 0 | \ No newline at end of file | 52 | \ No newline at end of file |
161 | 1 | 53 | ||
162 | === added file 'ticket_system/project/migrations/__init__.py' | |||
163 | === added file 'ticket_system/project/models.py' | |||
164 | --- ticket_system/project/models.py 1970-01-01 00:00:00 +0000 | |||
165 | +++ ticket_system/project/models.py 2013-12-09 19:42:24 +0000 | |||
166 | @@ -0,0 +1,38 @@ | |||
167 | 1 | # Ubuntu Continuous Integration Engine | ||
168 | 2 | # Copyright 2013 Canonical Ltd. | ||
169 | 3 | |||
170 | 4 | # This program is free software: you can redistribute it and/or modify it | ||
171 | 5 | # under the terms of the GNU Affero General Public License version 3, as | ||
172 | 6 | # published by the Free Software Foundation. | ||
173 | 7 | |||
174 | 8 | # This program is distributed in the hope that it will be useful, but | ||
175 | 9 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
176 | 10 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
177 | 11 | # PURPOSE. See the GNU Affero General Public License for more details. | ||
178 | 12 | |||
179 | 13 | # You should have received a copy of the GNU Affero General Public License | ||
180 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
181 | 15 | |||
182 | 16 | from django.db import models | ||
183 | 17 | |||
184 | 18 | |||
185 | 19 | class SourcePackage(models.Model): | ||
186 | 20 | class Meta: | ||
187 | 21 | db_table = "sourcepackage" | ||
188 | 22 | |||
189 | 23 | name = models.CharField(max_length=4096) | ||
190 | 24 | |||
191 | 25 | def __unicode__(self): | ||
192 | 26 | return self.name | ||
193 | 27 | |||
194 | 28 | |||
195 | 29 | class BinaryPackage(models.Model): | ||
196 | 30 | class Meta: | ||
197 | 31 | db_table = "binarypackage" | ||
198 | 32 | |||
199 | 33 | name = models.CharField(max_length=4096) | ||
200 | 34 | sourcepackage = models.ForeignKey("SourcePackage") | ||
201 | 35 | seeded = models.BooleanField(default=False) | ||
202 | 36 | |||
203 | 37 | def __unicode__(self): | ||
204 | 38 | return self.name | ||
205 | 0 | 39 | ||
206 | === added file 'ticket_system/project/tests.py' | |||
207 | --- ticket_system/project/tests.py 1970-01-01 00:00:00 +0000 | |||
208 | +++ ticket_system/project/tests.py 2013-12-09 19:42:24 +0000 | |||
209 | @@ -0,0 +1,136 @@ | |||
210 | 1 | # Ubuntu Continuous Integration Engine | ||
211 | 2 | # Copyright 2013 Canonical Ltd. | ||
212 | 3 | |||
213 | 4 | # This program is free software: you can redistribute it and/or modify it | ||
214 | 5 | # under the terms of the GNU Affero General Public License version 3, as | ||
215 | 6 | # published by the Free Software Foundation. | ||
216 | 7 | |||
217 | 8 | # This program is distributed in the hope that it will be useful, but | ||
218 | 9 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
219 | 10 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
220 | 11 | # PURPOSE. See the GNU Affero General Public License for more details. | ||
221 | 12 | |||
222 | 13 | # You should have received a copy of the GNU Affero General Public License | ||
223 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
224 | 15 | |||
225 | 16 | from django.test import TestCase | ||
226 | 17 | from tastypie.test import ResourceTestCase | ||
227 | 18 | from project.models import SourcePackage, BinaryPackage | ||
228 | 19 | |||
229 | 20 | |||
230 | 21 | def create_sourcepackage(name="awesome-package"): | ||
231 | 22 | package = SourcePackage() | ||
232 | 23 | package.name = name | ||
233 | 24 | package.save() | ||
234 | 25 | return package | ||
235 | 26 | |||
236 | 27 | |||
237 | 28 | def create_binarypackage(name="awesome-binary", sourcepackage=None, | ||
238 | 29 | seeded=False): | ||
239 | 30 | binary = BinaryPackage() | ||
240 | 31 | binary.name = name | ||
241 | 32 | binary.sourcepackage = sourcepackage | ||
242 | 33 | binary.seeded = seeded | ||
243 | 34 | binary.save() | ||
244 | 35 | return binary | ||
245 | 36 | |||
246 | 37 | |||
247 | 38 | class SourcePackageModelTest(TestCase): | ||
248 | 39 | |||
249 | 40 | def test_creating_a_sourcepackage(self): | ||
250 | 41 | package = create_sourcepackage() | ||
251 | 42 | package_in_database = SourcePackage.objects.all() | ||
252 | 43 | self.assertEquals(len(package_in_database), 1) | ||
253 | 44 | only_package_in_database = package_in_database[0] | ||
254 | 45 | self.assertEquals(only_package_in_database, package) | ||
255 | 46 | |||
256 | 47 | self.assertEquals(only_package_in_database.name, "awesome-package") | ||
257 | 48 | |||
258 | 49 | |||
259 | 50 | class BinaryPackageModelTest(TestCase): | ||
260 | 51 | |||
261 | 52 | def setUp(self): | ||
262 | 53 | self.sourcepackage = create_sourcepackage() | ||
263 | 54 | self.binarypackage = create_binarypackage( | ||
264 | 55 | sourcepackage=self.sourcepackage) | ||
265 | 56 | |||
266 | 57 | def test_creating_a_binarypackage(self): | ||
267 | 58 | binarypackage_in_database = BinaryPackage.objects.all() | ||
268 | 59 | self.assertEquals(len(binarypackage_in_database), 1) | ||
269 | 60 | only_binarypackage_in_database = binarypackage_in_database[0] | ||
270 | 61 | self.assertEquals(only_binarypackage_in_database, self.binarypackage) | ||
271 | 62 | |||
272 | 63 | self.assertEquals(only_binarypackage_in_database.name, | ||
273 | 64 | "awesome-binary") | ||
274 | 65 | |||
275 | 66 | |||
276 | 67 | class SourcePackageResourceTest(ResourceTestCase): | ||
277 | 68 | |||
278 | 69 | def setUp(self): | ||
279 | 70 | super(SourcePackageResourceTest, self).setUp() | ||
280 | 71 | create_sourcepackage() | ||
281 | 72 | self.sourcepackage_1 = SourcePackage.objects.get( | ||
282 | 73 | name='awesome-package') | ||
283 | 74 | self.detail_url = '/api/v1/sourcepackage/{0}/'.format( | ||
284 | 75 | self.sourcepackage_1.pk) | ||
285 | 76 | |||
286 | 77 | def test_get_sourcepackage_list_json(self): | ||
287 | 78 | resp = self.api_client.get('/api/v1/sourcepackage/', format='json') | ||
288 | 79 | self.assertValidJSONResponse(resp) | ||
289 | 80 | self.assertEqual(len(self.deserialize(resp)['objects']), 1) | ||
290 | 81 | self.assertEqual(self.deserialize(resp)['objects'][0], { | ||
291 | 82 | u'id': self.sourcepackage_1.pk, | ||
292 | 83 | u'name': u'awesome-package', | ||
293 | 84 | u'resource_uri': u'/api/v1/sourcepackage/{0}/'.format( | ||
294 | 85 | self.sourcepackage_1.pk) | ||
295 | 86 | }) | ||
296 | 87 | |||
297 | 88 | def test_get_sourcepackage_detail_json(self): | ||
298 | 89 | resp = self.api_client.get(self.detail_url) | ||
299 | 90 | self.assertValidJSONResponse(resp) | ||
300 | 91 | |||
301 | 92 | # We use ``assertKeys`` here to just verify the keys, not all the data. | ||
302 | 93 | self.assertKeys(self.deserialize(resp), | ||
303 | 94 | ['id', 'name', 'resource_uri']) | ||
304 | 95 | self.assertEqual(self.deserialize(resp)['name'], 'awesome-package') | ||
305 | 96 | |||
306 | 97 | |||
307 | 98 | class BinaryPackageResourceTest(ResourceTestCase): | ||
308 | 99 | |||
309 | 100 | def setUp(self): | ||
310 | 101 | super(BinaryPackageResourceTest, self).setUp() | ||
311 | 102 | create_sourcepackage() | ||
312 | 103 | self.sourcepackage_1 = SourcePackage.objects.get( | ||
313 | 104 | name='awesome-package') | ||
314 | 105 | create_binarypackage(sourcepackage=self.sourcepackage_1) | ||
315 | 106 | self.binarypackage_1 = BinaryPackage.objects.get( | ||
316 | 107 | name='awesome-binary') | ||
317 | 108 | self.detail_url = '/api/v1/binarypackage/{0}/'.format( | ||
318 | 109 | self.binarypackage_1.pk) | ||
319 | 110 | |||
320 | 111 | def test_get_binarypackage_list_json(self): | ||
321 | 112 | resp = self.api_client.get('/api/v1/binarypackage/', format='json') | ||
322 | 113 | self.assertValidJSONResponse(resp) | ||
323 | 114 | self.assertEqual(len(self.deserialize(resp)['objects']), 1) | ||
324 | 115 | self.assertEqual(self.deserialize(resp)['objects'][0], { | ||
325 | 116 | u'id': self.binarypackage_1.pk, | ||
326 | 117 | u'name': u'awesome-binary', | ||
327 | 118 | u'seeded': False, | ||
328 | 119 | u'sourcepackage': { | ||
329 | 120 | u'id': self.sourcepackage_1.pk, | ||
330 | 121 | u'name': u'awesome-package', | ||
331 | 122 | u'resource_uri': u'/api/v1/sourcepackage/{0}/'.format( | ||
332 | 123 | self.sourcepackage_1.pk)}, | ||
333 | 124 | u'resource_uri': u'/api/v1/binarypackage/{0}/'.format( | ||
334 | 125 | self.binarypackage_1.pk) | ||
335 | 126 | }) | ||
336 | 127 | |||
337 | 128 | def test_get_binarypackage_detail_json(self): | ||
338 | 129 | resp = self.api_client.get(self.detail_url) | ||
339 | 130 | self.assertValidJSONResponse(resp) | ||
340 | 131 | |||
341 | 132 | # We use ``assertKeys`` here to just verify the keys, not all the data. | ||
342 | 133 | self.assertKeys(self.deserialize(resp), | ||
343 | 134 | ['id', 'name', 'resource_uri', 'seeded', | ||
344 | 135 | 'sourcepackage']) | ||
345 | 136 | self.assertEqual(self.deserialize(resp)['name'], 'awesome-binary') | ||
346 | 0 | 137 | ||
347 | === modified file 'ticket_system/ticket_system/settings.py' | |||
348 | --- ticket_system/ticket_system/settings.py 2013-12-09 17:43:12 +0000 | |||
349 | +++ ticket_system/ticket_system/settings.py 2013-12-09 19:42:24 +0000 | |||
350 | @@ -140,6 +140,7 @@ | |||
351 | 140 | 140 | ||
352 | 141 | LOCAL_APPS = ( | 141 | LOCAL_APPS = ( |
353 | 142 | 'people', | 142 | 'people', |
354 | 143 | 'project', | ||
355 | 143 | ) | 144 | ) |
356 | 144 | 145 | ||
357 | 145 | INSTALLED_APPS = LOCAL_APPS + INSTALLED_APPS | 146 | INSTALLED_APPS = LOCAL_APPS + INSTALLED_APPS |
358 | 146 | 147 | ||
359 | === modified file 'ticket_system/ticket_system/urls.py' | |||
360 | --- ticket_system/ticket_system/urls.py 2013-12-09 17:43:12 +0000 | |||
361 | +++ ticket_system/ticket_system/urls.py 2013-12-09 19:42:24 +0000 | |||
362 | @@ -17,10 +17,13 @@ | |||
363 | 17 | from django.contrib import admin | 17 | from django.contrib import admin |
364 | 18 | from tastypie.api import Api | 18 | from tastypie.api import Api |
365 | 19 | from people.api import PersonResource | 19 | from people.api import PersonResource |
366 | 20 | from project.api import SourcePackageResource, BinaryPackageResource | ||
367 | 20 | 21 | ||
368 | 21 | admin.autodiscover() | 22 | admin.autodiscover() |
369 | 22 | v1_api = Api(api_name='v1') | 23 | v1_api = Api(api_name='v1') |
370 | 23 | v1_api.register(PersonResource()) | 24 | v1_api.register(PersonResource()) |
371 | 25 | v1_api.register(SourcePackageResource()) | ||
372 | 26 | v1_api.register(BinaryPackageResource()) | ||
373 | 24 | 27 | ||
374 | 25 | urlpatterns = patterns( | 28 | urlpatterns = patterns( |
375 | 26 | '', | 29 | '', |
stuff like:
287 + resp = self.api_ client. get('/api/ v1/sourcepackag e/', format='json') dJSONResponse( resp) l(len(self. deserialize( resp)[' objects' ]), 1)
288 + self.assertVali
289 + self.assertEqua
could probably get folded into:
http:// bazaar. launchpad. net/~canonical- ci-engineering/ ubuntu- ci-services- itself/ trunk/view/ head:/ci- utils/ci_ utils/tastypie/ test.py
In particular it could probably work with the getResource method.