Merge lp:~fgallina/rnr-server/django16 into lp:rnr-server
- django16
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Fabián Ezequiel Gallina |
Approved revision: | 263 |
Merged at revision: | 254 |
Proposed branch: | lp:~fgallina/rnr-server/django16 |
Merge into: | lp:rnr-server |
Diff against target: |
854 lines (+348/-160) 18 files modified
.bzrignore (+5/-0) django_project/config_dev/config/main.cfg (+4/-0) django_project/manage.py (+10/-16) fabtasks/bootstrap.py (+26/-3) requirements.txt (+0/-5) src/clickreviews/tests/__init__.py (+0/-11) src/clickreviews/tests/factory.py (+7/-2) src/clickreviews/tests/test_handlers.py (+60/-55) src/reviewsapp/migrations/0016_update_permissions.py (+186/-0) src/reviewsapp/models/reviews.py (+1/-1) src/reviewsapp/preflight.py (+4/-3) src/reviewsapp/schema.py (+1/-1) src/reviewsapp/tests/__init__.py (+0/-37) src/reviewsapp/tests/factory.py (+4/-0) src/reviewsapp/tests/helpers.py (+26/-1) src/reviewsapp/tests/test_handlers.py (+3/-1) src/reviewsapp/tests/test_middleware.py (+0/-24) src/reviewsapp/tests/test_wsgi.py (+11/-0) |
To merge this branch: | bzr merge lp:~fgallina/rnr-server/django16 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Matias Bordese (community) | Approve | ||
Review via email: mp+228332@code.launchpad.net |
Commit message
Upgrade to Django 1.6.5
Description of the change
Ubuntu One Auto Pilot (otto-pilot) wrote : | # |
The attempt to merge lp:~fgallina/rnr-server/django16 into lp:rnr-server failed. Below is the output from the failed tests.
[localhost] local: /usr/bin/python /usr/bin/virtualenv --no-site-packages virtualenv
The --no-site-packages flag is deprecated; it is now the default behavior.
New python executable in virtualenv/
Installing distribute.
Installing pip....
[localhost] local: virtualenv/bin/pip install -r requirements.txt
Downloading/
Downloading linux_metrics-
Running setup.py egg_info for package from http://
Downloading/
Running setup.py egg_info for package bzr
No Cython, trying Pyrex...
The python package 'Pyrex' is not available. If the .c files are available,
they will be built, but modifying the .pyx files will not rebuild them.
Downloading/
Running setup.py egg_info for package coverage
warning: no previously-included files matching '*.pyc' found anywhere in distribution
Downloading/
Running setup.py egg_info for package django-pgtools
Downloading/
Downloading django_
Running setup.py egg_info for package django-factory
warning: no previously-included files matching '*.pyc' found anywhere in distribution
Downloading/
Running setup.py egg_info for package httplib2
Downloading/
Running setup.py egg_info for package launchpadlib
Downloading/
Running setup.py egg_info for package lazr.restfulclient
Downloading/
Running setup.py egg_info for package mechanize
Downloading/
Running setup.py egg_info for package mock
warning: no files found matching '*.png' under directory 'docs'
warning: no files found matching '*.css' under directory 'docs'
warning: no files found matching '*.html' under directory 'docs'
warning: no files found matching '*.js' under directory 'docs'
Downloading/
Running setup.py egg_info for package oauthlib
Downloading/
Downloading oops-0.0.13.tar.gz
Running setup.py egg_info for package oops
Downloading/
Downloading oops_datedir_
...
- 263. By Fabián Ezequiel Gallina
-
Fixes for sqlite based test runs
Preview Diff
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2014-07-11 19:05:55 +0000 |
3 | +++ .bzrignore 2014-07-25 17:44:55 +0000 |
4 | @@ -11,7 +11,12 @@ |
5 | django_project/rnrclient.py |
6 | django_project/mockssoservice |
7 | django_project/canonical |
8 | +django_project/configglue |
9 | +django_project/django |
10 | +django_project/django_openid_auth |
11 | +django_project/preflight |
12 | django_project/piston |
13 | +django_project/south |
14 | django_project/oops_dictconfig |
15 | django_project/oops_wsgi |
16 | django_project/adminaudit |
17 | |
18 | === modified file 'django_project/config_dev/config/main.cfg' |
19 | --- django_project/config_dev/config/main.cfg 2014-07-11 19:05:55 +0000 |
20 | +++ django_project/config_dev/config/main.cfg 2014-07-25 17:44:55 +0000 |
21 | @@ -64,8 +64,12 @@ |
22 | |
23 | root_urlconf = urls |
24 | |
25 | +session_serializer = django.contrib.sessions.serializers.PickleSerializer |
26 | + |
27 | template_dirs = ./django_project/templates/ |
28 | |
29 | +test_runner = django.test.runner.DiscoverRunner |
30 | + |
31 | installed_apps = adminaudit |
32 | django.contrib.admin |
33 | django.contrib.auth |
34 | |
35 | === modified file 'django_project/manage.py' |
36 | --- django_project/manage.py 2011-03-17 10:19:07 +0000 |
37 | +++ django_project/manage.py 2014-07-25 17:44:55 +0000 |
38 | @@ -1,17 +1,11 @@ |
39 | #!/usr/bin/env python |
40 | - |
41 | -from django.core.management import execute_manager |
42 | -try: |
43 | - import settings # Assumed to be in a directory on the path. |
44 | -except ImportError: |
45 | - import sys |
46 | - sys.stderr.write( |
47 | - "Error: Can't find the file 'settings.py' within the " |
48 | - "django_project. It appears you've customized things.\n" |
49 | - "You'll have to run django-admin.py, passing it your " |
50 | - "settings module.\n(If the file settings.py does indeed " |
51 | - "exist, it's causing an ImportError somehow.)\n") |
52 | - sys.exit(1) |
53 | - |
54 | -if __name__ == "__main__": |
55 | - execute_manager(settings) |
56 | +import os |
57 | +import sys |
58 | + |
59 | + |
60 | +if __name__ == '__main__': |
61 | + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') |
62 | + |
63 | + from django_configglue.management import execute_from_command_line |
64 | + |
65 | + execute_from_command_line(sys.argv) |
66 | |
67 | === modified file 'fabtasks/bootstrap.py' |
68 | --- fabtasks/bootstrap.py 2014-07-11 19:05:55 +0000 |
69 | +++ fabtasks/bootstrap.py 2014-07-25 17:44:55 +0000 |
70 | @@ -113,21 +113,44 @@ |
71 | "django_project/txstatsd") |
72 | |
73 | _get_or_pull_bzr_branch( |
74 | - "lp:~ubuntuone-hackers/django-configglue/trunk", |
75 | - "django-configglue") |
76 | + "lp:~configglue/configglue/trunk", "configglue", revision=112) |
77 | + _symlink("branches/configglue/configglue", "django_project/configglue") |
78 | + |
79 | + _get_or_pull_bzr_branch( |
80 | + "lp:django-configglue", "django-configglue", revision=79) |
81 | _symlink( |
82 | "branches/django-configglue/django_configglue", |
83 | "django_project/django_configglue") |
84 | |
85 | _get_or_pull_bzr_branch( |
86 | + "lp:~ubuntuone-pqm-team/django/stable", "django", revision="1.6.5") |
87 | + _symlink("branches/django/django", "django_project/django") |
88 | + |
89 | + _get_or_pull_bzr_branch( |
90 | + "lp:~ubuntuone-pqm-team/django-openid-auth/stable", |
91 | + "django-openid-auth", revision=104) |
92 | + _symlink( |
93 | + "branches/django-openid-auth/django_openid_auth", |
94 | + "django_project/django_openid_auth") |
95 | + |
96 | + _get_or_pull_bzr_branch( |
97 | + "lp:~canonical-isd-hackers/django-preflight/trunk", |
98 | + "django-preflight", revision=30) |
99 | + _symlink("branches/django-preflight/preflight", "django_project/preflight") |
100 | + |
101 | + _get_or_pull_bzr_branch( |
102 | "lp:~ubuntuone-pqm-team/django-piston/stable", |
103 | "django-piston", |
104 | - revision=4) |
105 | + revision=5) |
106 | _symlink( |
107 | "branches/django-piston/piston", |
108 | "django_project/piston") |
109 | |
110 | _get_or_pull_bzr_branch( |
111 | + "lp:~ubuntuone-hackers/django-south/trunk", "django-south", revision=5) |
112 | + _symlink("branches/django-south/south", "django_project/south") |
113 | + |
114 | + _get_or_pull_bzr_branch( |
115 | "lp:~canonical-isd-hackers/django-adminaudit/trunk", |
116 | "django-adminaudit", |
117 | revision=53) |
118 | |
119 | === modified file 'requirements.txt' |
120 | --- requirements.txt 2014-07-22 12:32:55 +0000 |
121 | +++ requirements.txt 2014-07-25 17:44:55 +0000 |
122 | @@ -3,12 +3,8 @@ |
123 | -f http://code.google.com/p/httplib2/downloads/list |
124 | -f https://launchpad.net/django-pgtools/+download |
125 | bzr |
126 | -configglue==1.0.1 |
127 | coverage |
128 | -django-openid-auth==0.2 |
129 | django-pgtools==0.1 |
130 | -django-preflight |
131 | -django==1.5.1 |
132 | django_factory==0.11 |
133 | http://corey-projects.googlecode.com/files/linux_metrics-0.1.0.tar.gz |
134 | httplib2==0.6.0 |
135 | @@ -25,7 +21,6 @@ |
136 | python-openid |
137 | pytz |
138 | setuptools |
139 | -south==0.7.6 |
140 | storm |
141 | testtools |
142 | wsgi_intercept==0.4 |
143 | |
144 | === modified file 'src/clickreviews/tests/__init__.py' |
145 | --- src/clickreviews/tests/__init__.py 2014-06-23 20:12:52 +0000 |
146 | +++ src/clickreviews/tests/__init__.py 2014-07-25 17:44:55 +0000 |
147 | @@ -1,11 +0,0 @@ |
148 | -from clickreviews.tests.test_utilities import VerifyPackageTestCase |
149 | -from clickreviews.tests.test_handlers import ( |
150 | - ClickReviewsHandlerGetTestCase, |
151 | - ClickReviewsHandlerPostTestCase, |
152 | - ClickReviewsStatsHandlerTestCase, |
153 | -) |
154 | -from clickreviews.tests.test_forms import ClickPackageReviewFormTestCase |
155 | -from clickreviews.tests.test_models import ( |
156 | - ClickPackageModelTestCase, |
157 | - ClickPackageReviewModelTestCase, |
158 | -) |
159 | |
160 | === modified file 'src/clickreviews/tests/factory.py' |
161 | --- src/clickreviews/tests/factory.py 2014-06-24 11:10:39 +0000 |
162 | +++ src/clickreviews/tests/factory.py 2014-07-25 17:44:55 +0000 |
163 | @@ -40,7 +40,8 @@ |
164 | def makeClickPackageReview( |
165 | self, reviewer=None, click_package=None, version=None, rating="5", |
166 | summary=None, review_text=None, date_created=None, language=None, |
167 | - hide=False, num_flags=0, architecture='i386', deleted=False): |
168 | + hide=False, num_flags=0, architecture='i386', |
169 | + usefulness_wilson_rating=None, deleted=False): |
170 | if reviewer is None: |
171 | reviewer = self.makeUser() |
172 | if click_package is None: |
173 | @@ -60,6 +61,8 @@ |
174 | date_deleted = datetime.now(pytz.utc) |
175 | else: |
176 | date_deleted = None |
177 | + if usefulness_wilson_rating is None: |
178 | + usefulness_wilson_rating = 0.0 |
179 | |
180 | architecture, created = Architecture.objects.get_or_create( |
181 | tag=architecture) |
182 | @@ -69,7 +72,9 @@ |
183 | version=version, rating=rating, summary=summary, |
184 | review_text=review_text, language=language, |
185 | hide=hide, date_created=date_created, |
186 | - architecture=architecture, date_deleted=date_deleted) |
187 | + architecture=architecture, |
188 | + usefulness_wilson_rating=usefulness_wilson_rating, |
189 | + date_deleted=date_deleted) |
190 | |
191 | review.click_package.update_stats() |
192 | |
193 | |
194 | === modified file 'src/clickreviews/tests/test_handlers.py' |
195 | --- src/clickreviews/tests/test_handlers.py 2014-07-03 17:57:21 +0000 |
196 | +++ src/clickreviews/tests/test_handlers.py 2014-07-25 17:44:55 +0000 |
197 | @@ -6,18 +6,16 @@ |
198 | from datetime import datetime |
199 | from io import BytesIO |
200 | |
201 | -from django.contrib.auth.models import User |
202 | from django.conf import settings |
203 | from django.core.cache import cache |
204 | from django.core.serializers.json import DateTimeAwareJSONEncoder |
205 | from django.core.urlresolvers import reverse |
206 | -from django_factory import TestCase |
207 | |
208 | from clickreviews.models import ClickPackage, ClickPackageReview |
209 | from clickreviews.tests.factory import TestCaseWithFactory |
210 | |
211 | |
212 | -class ClickReviewsHandlerPostTestCase(TestCase): |
213 | +class ClickReviewsHandlerPostTestCase(TestCaseWithFactory): |
214 | |
215 | def setUp(self): |
216 | super(ClickReviewsHandlerPostTestCase, self).setUp() |
217 | @@ -38,6 +36,7 @@ |
218 | |
219 | def make_data(self, package_name='com.ubuntu.dev.uname.pkgid', |
220 | rating=5): |
221 | + self.factory.makeArch('i386') |
222 | return { |
223 | 'package_name': package_name, |
224 | 'summary': 'Excellent', |
225 | @@ -51,9 +50,8 @@ |
226 | def _post_new_review(self, data, user=None, verify_result=True): |
227 | # Post a review as an authenticated user. |
228 | url = reverse('click-api-reviews') |
229 | - |
230 | if user is None: |
231 | - user = self.factory.make_one(User) |
232 | + user = self.factory.makeUser() |
233 | self.client.login(username=user.username, password='test') |
234 | |
235 | response = self.client.post( |
236 | @@ -125,19 +123,23 @@ |
237 | self.assertEqual(5, click_package.ratings_average) |
238 | |
239 | |
240 | -class ClickReviewsHandlerGetTestCase(TestCase): |
241 | +class ClickReviewsHandlerGetTestCase(TestCaseWithFactory): |
242 | |
243 | def _get_reviews(self, data=None): |
244 | url = reverse('click-api-reviews') |
245 | kwargs = {} |
246 | if data is not None: |
247 | kwargs['data'] = data |
248 | - return self.client.get(url, **kwargs) |
249 | + is_authenticated_method = ( |
250 | + 'reviewsapp.auth.SSOOAuthAuthentication.is_authenticated') |
251 | + with mock.patch(is_authenticated_method) as mock_is_authenticated: |
252 | + mock_is_authenticated.return_value = False |
253 | + return self.client.get(url, **kwargs) |
254 | |
255 | def test_get_multiple_reviews_for_package(self): |
256 | - package = self.factory.make_one(ClickPackage) |
257 | - reviews = self.factory.make(5, ClickPackageReview, |
258 | - click_package=package) |
259 | + package = self.factory.makeClickPackage() |
260 | + for _ in range(5): |
261 | + self.factory.makeClickPackageReview(click_package=package) |
262 | |
263 | json_result = self._get_reviews(data={ |
264 | 'package_name': package.package_name, |
265 | @@ -148,10 +150,10 @@ |
266 | self.assertEqual(5, len(result)) |
267 | |
268 | def test_get_reviews_contains_correct_data(self): |
269 | - package = self.factory.make_one(ClickPackage, |
270 | - package_name="com.example.me.myapp") |
271 | - review = self.factory.make_one( |
272 | - ClickPackageReview, click_package=package, language='en', |
273 | + package = self.factory.makeClickPackage( |
274 | + package_name="com.example.me.myapp") |
275 | + review = self.factory.makeClickPackageReview( |
276 | + click_package=package, language='en', |
277 | rating=5, summary='Best app', review_text='Unlimited fun!', |
278 | version='0.1.1', date_created=datetime( |
279 | 2014, 1, 15, 11, 13, 55, 123456, tzinfo=pytz.UTC)) |
280 | @@ -163,7 +165,7 @@ |
281 | result = json.loads(json_result.content) |
282 | self.assertEqual(1, len(result)) |
283 | result_review = result[0] |
284 | - testme = DateTimeAwareJSONEncoder().encode( |
285 | + DateTimeAwareJSONEncoder().encode( |
286 | review.date_created).strip('"') |
287 | self.assertEqual({ |
288 | 'id': review.id, |
289 | @@ -190,10 +192,10 @@ |
290 | json.loads(result.content)['errors'].keys()) |
291 | |
292 | def test_doesnt_include_deleted(self): |
293 | - package = self.factory.make_one(ClickPackage) |
294 | - review = self.factory.make_one(ClickPackageReview, |
295 | - click_package=package, |
296 | - date_deleted=datetime.now(pytz.UTC)) |
297 | + package = self.factory.makeClickPackage() |
298 | + self.factory.makeClickPackageReview( |
299 | + click_package=package, |
300 | + deleted=True) |
301 | |
302 | json_result = self._get_reviews(data={ |
303 | 'package_name': package.package_name, |
304 | @@ -203,11 +205,12 @@ |
305 | self.assertEqual(0, len(result)) |
306 | |
307 | def test_ordered_by_wilson_rating(self): |
308 | - package = self.factory.make_one(ClickPackage) |
309 | + package = self.factory.makeClickPackage() |
310 | wilson_ratings = [-1.5, 0, -2.5, 5.5] |
311 | reviews = [ |
312 | - self.factory.make_one(ClickPackageReview, click_package=package, |
313 | - usefulness_wilson_rating=wilson_rating) |
314 | + self.factory.makeClickPackageReview( |
315 | + click_package=package, |
316 | + usefulness_wilson_rating=wilson_rating) |
317 | for wilson_rating in wilson_ratings |
318 | ] |
319 | expected_review_ids = [ |
320 | @@ -233,6 +236,29 @@ |
321 | super(ClickReviewsStatsHandlerTestCase, self).setUp() |
322 | self.clear_cache() |
323 | |
324 | + def make_stats_response( |
325 | + self, pk=1, package_name='org.some.package', |
326 | + histogram='[0, 0, 0, 0, 1]', ratings_total=1, |
327 | + ratings_average='5.00'): |
328 | + |
329 | + # XXX: To be cleaned up once support for sqlite is dropped. |
330 | + # Using sqlite does not honor the settings for the |
331 | + # ratings_average DecimalField spec, ignoring max_digits and |
332 | + # decimal_places when returning the formatted value. |
333 | + db_engine = settings.DATABASES['default']['ENGINE'] |
334 | + if db_engine == 'django.db.backends.sqlite3': |
335 | + ratings_average = ratings_average.rstrip('0') |
336 | + if ratings_average.endswith('.'): |
337 | + ratings_average = ratings_average[0:-1] |
338 | + |
339 | + return { |
340 | + 'id': pk, |
341 | + 'package_name': package_name, |
342 | + 'histogram': histogram, |
343 | + 'ratings_total': ratings_total, |
344 | + 'ratings_average': ratings_average, |
345 | + } |
346 | + |
347 | def clear_cache(self): |
348 | cache._cache.clear() |
349 | cache._expire_info.clear() |
350 | @@ -260,19 +286,11 @@ |
351 | foo = foo_review.click_package |
352 | bar = bar_review.click_package |
353 | self.assertEqual(2, len(reviews)) |
354 | - self.assertEqual(reviews, [{ |
355 | - 'id': foo.pk, |
356 | - 'package_name': foo.package_name, |
357 | - 'histogram': '[0, 0, 0, 0, 1]', |
358 | - 'ratings_total': 1, |
359 | - 'ratings_average': '5', |
360 | - }, { |
361 | - 'id': bar.pk, |
362 | - 'package_name': bar.package_name, |
363 | - 'histogram': '[0, 0, 0, 0, 1]', |
364 | - 'ratings_total': 1, |
365 | - 'ratings_average': '5', |
366 | - }]) |
367 | + self.assertEqual(reviews, [ |
368 | + self.make_stats_response( |
369 | + pk=foo.pk, package_name=foo.package_name), |
370 | + self.make_stats_response( |
371 | + pk=bar.pk, package_name=bar.package_name)]) |
372 | |
373 | def test_read_for_package(self): |
374 | foo_review = self.factory.makeClickPackageReview( |
375 | @@ -286,13 +304,8 @@ |
376 | reviews = json.loads(response.content) |
377 | |
378 | foo = foo_review.click_package |
379 | - self.assertEqual(reviews, { |
380 | - 'id': foo.pk, |
381 | - 'package_name': foo.package_name, |
382 | - 'histogram': '[0, 0, 0, 0, 1]', |
383 | - 'ratings_total': 1, |
384 | - 'ratings_average': '5', |
385 | - }) |
386 | + self.assertEqual(reviews, self.make_stats_response( |
387 | + pk=foo.pk, package_name=foo.package_name)) |
388 | |
389 | def test_read_for_missing_package(self): |
390 | response = self._request_stats(package_name='not_found') |
391 | @@ -343,19 +356,11 @@ |
392 | |
393 | foo = foo_review.click_package |
394 | bar = bar_review.click_package |
395 | - self.assertEqual(reviews, [{ |
396 | - 'id': foo.pk, |
397 | - 'package_name': foo.package_name, |
398 | - 'histogram': '[0, 0, 0, 0, 1]', |
399 | - 'ratings_total': 1, |
400 | - 'ratings_average': '5', |
401 | - }, { |
402 | - 'id': bar.pk, |
403 | - 'package_name': bar.package_name, |
404 | - 'histogram': '[0, 0, 0, 0, 1]', |
405 | - 'ratings_total': 1, |
406 | - 'ratings_average': '5', |
407 | - }]) |
408 | + self.assertEqual(reviews, [ |
409 | + self.make_stats_response( |
410 | + pk=foo.pk, package_name=foo.package_name), |
411 | + self.make_stats_response( |
412 | + pk=bar.pk, package_name=bar.package_name)]) |
413 | |
414 | def test_vary_headers(self): |
415 | response = self._request_stats() |
416 | |
417 | === added file 'src/reviewsapp/migrations/0016_update_permissions.py' |
418 | --- src/reviewsapp/migrations/0016_update_permissions.py 1970-01-01 00:00:00 +0000 |
419 | +++ src/reviewsapp/migrations/0016_update_permissions.py 2014-07-25 17:44:55 +0000 |
420 | @@ -0,0 +1,186 @@ |
421 | +# -*- coding: utf-8 -*- |
422 | +from django.contrib.auth.management import create_permissions |
423 | +from django.db import transaction |
424 | +from django.db.models import get_app, get_models |
425 | +from south.v2 import DataMigration |
426 | + |
427 | + |
428 | +class Migration(DataMigration): |
429 | + |
430 | + def forwards(self, orm): |
431 | + """Ensures that all Permission objects for models are up to date. |
432 | + |
433 | + Given this is Django a version updgrade, and there's a South |
434 | + bug[0] that won't let it track the permissions Meta for |
435 | + models, we need to ensure all of them get synced correctly for |
436 | + all installed apps. |
437 | + |
438 | + [0] http://south.aeracode.org/ticket/211 |
439 | + """ |
440 | + models = get_models() |
441 | + apps = [get_app(model._meta.app_label) for model in models] |
442 | + for app in apps: |
443 | + # Safeguard for sqlite. See: http://bit.ly/1rRHC9Y |
444 | + with transaction.autocommit(): |
445 | + create_permissions(app, models, verbosity=0) |
446 | + |
447 | + models = { |
448 | + u'auth.group': { |
449 | + 'Meta': {'object_name': 'Group'}, |
450 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
451 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), |
452 | + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) |
453 | + }, |
454 | + u'auth.permission': { |
455 | + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, |
456 | + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
457 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), |
458 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
459 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) |
460 | + }, |
461 | + u'auth.user': { |
462 | + 'Meta': {'object_name': 'User'}, |
463 | + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), |
464 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), |
465 | + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
466 | + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), |
467 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
468 | + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
469 | + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
470 | + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
471 | + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), |
472 | + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
473 | + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), |
474 | + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), |
475 | + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) |
476 | + }, |
477 | + u'contenttypes.contenttype': { |
478 | + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, |
479 | + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
480 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
481 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
482 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) |
483 | + }, |
484 | + 'reviewsapp.architecture': { |
485 | + 'Meta': {'object_name': 'Architecture'}, |
486 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
487 | + 'tag': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '16'}) |
488 | + }, |
489 | + 'reviewsapp.consumer': { |
490 | + 'Meta': {'object_name': 'Consumer'}, |
491 | + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), |
492 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
493 | + 'key': ('django.db.models.fields.CharField', [], {'max_length': '64'}), |
494 | + 'secret': ('django.db.models.fields.CharField', [], {'default': "'aVPDdxZfSorFGKwCrQKmArDJpMiQrq'", 'max_length': '255', 'blank': 'True'}), |
495 | + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), |
496 | + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'oauth_consumer'", 'unique': 'True', 'to': u"orm['auth.User']"}) |
497 | + }, |
498 | + 'reviewsapp.nonce': { |
499 | + 'Meta': {'object_name': 'Nonce'}, |
500 | + 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['reviewsapp.Consumer']"}), |
501 | + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), |
502 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
503 | + 'nonce': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), |
504 | + 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['reviewsapp.Token']"}) |
505 | + }, |
506 | + 'reviewsapp.repository': { |
507 | + 'Meta': {'object_name': 'Repository'}, |
508 | + 'distroseries': ('django.db.models.fields.SlugField', [], {'max_length': '25'}), |
509 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
510 | + 'origin': ('django.db.models.fields.SlugField', [], {'max_length': '100'}) |
511 | + }, |
512 | + 'reviewsapp.review': { |
513 | + 'Meta': {'object_name': 'Review'}, |
514 | + 'app_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}), |
515 | + 'architecture': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['reviewsapp.Architecture']"}), |
516 | + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 7, 25, 0, 0)'}), |
517 | + 'date_deleted': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), |
518 | + 'hide': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), |
519 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
520 | + 'language': ('django.db.models.fields.SlugField', [], {'max_length': '10'}), |
521 | + 'rating': ('reviewsapp.fields.IntegerRangeField', [], {}), |
522 | + 'repository': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['reviewsapp.Repository']"}), |
523 | + 'review_text': ('django.db.models.fields.CharField', [], {'max_length': '5000'}), |
524 | + 'reviewer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}), |
525 | + 'softwareitem': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['reviewsapp.SoftwareItem']"}), |
526 | + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '80'}), |
527 | + 'usefulness_favorable': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
528 | + 'usefulness_percentage': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
529 | + 'usefulness_total': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
530 | + 'usefulness_wilson_rating': ('django.db.models.fields.FloatField', [], {'default': '0.0'}), |
531 | + 'version': ('reviewsapp.fields.DebVersionField', [], {'max_length': '100', 'db_index': 'True'}) |
532 | + }, |
533 | + 'reviewsapp.reviewmoderation': { |
534 | + 'Meta': {'object_name': 'ReviewModeration'}, |
535 | + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 7, 25, 0, 0)'}), |
536 | + 'date_moderated': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), |
537 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
538 | + 'moderation_text': ('django.db.models.fields.TextField', [], {'blank': 'True'}), |
539 | + 'moderator': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}), |
540 | + 'review': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['reviewsapp.Review']"}), |
541 | + 'status': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}) |
542 | + }, |
543 | + 'reviewsapp.reviewmoderationflag': { |
544 | + 'Meta': {'ordering': "['-date_created']", 'object_name': 'ReviewModerationFlag'}, |
545 | + 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 7, 25, 0, 0)'}), |
546 | + 'description': ('django.db.models.fields.TextField', [], {}), |
547 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
548 | + 'review_moderation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['reviewsapp.ReviewModeration']"}), |
549 | + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200'}), |
550 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True'}) |
551 | + }, |
552 | + 'reviewsapp.rnrsettings': { |
553 | + 'Meta': {'object_name': 'RNRSettings'}, |
554 | + 'blacklist_words': ('django.db.models.fields.TextField', [], {'default': "''"}), |
555 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
556 | + 'moderation_mode': ('django.db.models.fields.CharField', [], {'default': "'passive'", 'max_length': '8'}) |
557 | + }, |
558 | + 'reviewsapp.softwareitem': { |
559 | + 'Meta': {'object_name': 'SoftwareItem'}, |
560 | + 'date_ratings_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 7, 25, 0, 0)'}), |
561 | + 'histogram': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), |
562 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
563 | + 'package_name': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'}), |
564 | + 'ratings_average': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '3', 'decimal_places': '2'}), |
565 | + 'ratings_total': ('django.db.models.fields.IntegerField', [], {'default': '0'}) |
566 | + }, |
567 | + 'reviewsapp.softwareiteminorigin': { |
568 | + 'Meta': {'unique_together': "(('softwareitem', 'origin'),)", 'object_name': 'SoftwareItemInOrigin'}, |
569 | + 'date_ratings_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 7, 25, 0, 0)'}), |
570 | + 'histogram': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), |
571 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
572 | + 'origin': ('django.db.models.fields.SlugField', [], {'max_length': '100'}), |
573 | + 'ratings_average': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '3', 'decimal_places': '2'}), |
574 | + 'ratings_total': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
575 | + 'softwareitem': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['reviewsapp.SoftwareItem']"}) |
576 | + }, |
577 | + 'reviewsapp.softwareiteminrepository': { |
578 | + 'Meta': {'unique_together': "(('softwareitem', 'repository'),)", 'object_name': 'SoftwareItemInRepository'}, |
579 | + 'date_ratings_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 7, 25, 0, 0)'}), |
580 | + 'histogram': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), |
581 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
582 | + 'ratings_average': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '3', 'decimal_places': '2'}), |
583 | + 'ratings_total': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
584 | + 'repository': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['reviewsapp.Repository']"}), |
585 | + 'softwareitem': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['reviewsapp.SoftwareItem']"}) |
586 | + }, |
587 | + 'reviewsapp.token': { |
588 | + 'Meta': {'object_name': 'Token'}, |
589 | + 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['reviewsapp.Consumer']"}), |
590 | + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), |
591 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), |
592 | + 'token': ('django.db.models.fields.CharField', [], {'default': "'TLaXclobaNdHsvKHbaNzyQOqCpmMIZxlDXxmFPXlgEWMTLQUCM'", 'max_length': '50', 'primary_key': 'True'}), |
593 | + 'token_secret': ('django.db.models.fields.CharField', [], {'default': "'JpBcFHPeJycAHuRJQFueAPjWmIirzaXhGkyULCemxhyTVHsqSc'", 'max_length': '50'}), |
594 | + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) |
595 | + }, |
596 | + 'reviewsapp.usefulness': { |
597 | + 'Meta': {'object_name': 'Usefulness'}, |
598 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
599 | + 'review': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['reviewsapp.Review']"}), |
600 | + 'useful': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), |
601 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) |
602 | + } |
603 | + } |
604 | + |
605 | + complete_apps = ['reviewsapp'] |
606 | + symmetrical = True |
607 | |
608 | === modified file 'src/reviewsapp/models/reviews.py' |
609 | --- src/reviewsapp/models/reviews.py 2014-06-23 20:19:03 +0000 |
610 | +++ src/reviewsapp/models/reviews.py 2014-07-25 17:44:55 +0000 |
611 | @@ -445,7 +445,7 @@ |
612 | class Usefulness(models.Model): |
613 | review = models.ForeignKey(Review, db_index=True) |
614 | user = models.ForeignKey(User) |
615 | - useful = models.BooleanField(db_index=True) |
616 | + useful = models.BooleanField(db_index=True, default=False) |
617 | |
618 | def username(self): |
619 | return self.user.username |
620 | |
621 | === modified file 'src/reviewsapp/preflight.py' |
622 | --- src/reviewsapp/preflight.py 2014-07-22 12:32:55 +0000 |
623 | +++ src/reviewsapp/preflight.py 2014-07-25 17:44:55 +0000 |
624 | @@ -27,9 +27,9 @@ |
625 | import launchpadlib |
626 | import openid |
627 | import piston.utils |
628 | +import preflight |
629 | import south |
630 | from django.conf import settings |
631 | -from preflight import Preflight, register |
632 | |
633 | import reviewsapp |
634 | from reviewsapp.utilities import web_services |
635 | @@ -38,7 +38,7 @@ |
636 | logger = logging.getLogger(__name__) |
637 | |
638 | |
639 | -class RNRPreflight(Preflight): |
640 | +class RNRPreflight(preflight.Preflight): |
641 | |
642 | def versions(self): |
643 | return [ |
644 | @@ -47,6 +47,7 @@ |
645 | {'name': 'openid', 'version': openid.__version__}, |
646 | {'name': 'launchpadlib', 'version': launchpadlib.__version__}, |
647 | {'name': 'piston', 'version': piston.utils.__version__}, |
648 | + {'name': 'preflight', 'version': preflight.__version__}, |
649 | {'name': 'South', 'version': south.__version__}, |
650 | ] |
651 | |
652 | @@ -102,4 +103,4 @@ |
653 | return type(pubs) == dict |
654 | |
655 | |
656 | -register(RNRPreflight) |
657 | +preflight.register(RNRPreflight) |
658 | |
659 | === modified file 'src/reviewsapp/schema.py' |
660 | --- src/reviewsapp/schema.py 2014-07-18 11:17:57 +0000 |
661 | +++ src/reviewsapp/schema.py 2014-07-25 17:44:55 +0000 |
662 | @@ -28,7 +28,7 @@ |
663 | from django_configglue.schema import schemas |
664 | from oops_dictconfig.configglue_options import OopsOption |
665 | |
666 | -DjangoSchema = schemas.get(django.get_version()) |
667 | +DjangoSchema = schemas.get('1.6') |
668 | |
669 | |
670 | class RnRSchema(DjangoSchema): |
671 | |
672 | === modified file 'src/reviewsapp/tests/__init__.py' |
673 | --- src/reviewsapp/tests/__init__.py 2012-10-22 14:18:20 +0000 |
674 | +++ src/reviewsapp/tests/__init__.py 2014-07-25 17:44:55 +0000 |
675 | @@ -1,37 +0,0 @@ |
676 | -# This file is part of Software Center Ratings and Reviews |
677 | -# Copyright (C) 2010 Canonical Ltd. |
678 | -# |
679 | -# This program is free software: you can redistribute it and/or modify |
680 | -# it under the terms of the GNU Affero General Public License as |
681 | -# published by the Free Software Foundation, either version 3 of the |
682 | -# License, or (at your option) any later version. |
683 | -# |
684 | -# This program is distributed in the hope that it will be useful, |
685 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
686 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
687 | -# GNU Affero General Public License for more details. |
688 | -# |
689 | -# You should have received a copy of the GNU Affero General Public License |
690 | -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
691 | - |
692 | -"""Pull in the different test cases so that Django's test runner finds them. |
693 | - |
694 | -Note: each module should define __all__ to ensure we're not importing more |
695 | -than intended. |
696 | -""" |
697 | - |
698 | -from __future__ import absolute_import |
699 | - |
700 | -from reviewsapp.tests.test_auth import * |
701 | -from reviewsapp.tests.test_command_populate import * |
702 | -from reviewsapp.tests.test_command_update_stats import * |
703 | -from reviewsapp.tests.test_decorators import * |
704 | -from reviewsapp.tests.test_handlers import * |
705 | -from reviewsapp.tests.test_middleware import * |
706 | -from reviewsapp.tests.test_models import * |
707 | -from reviewsapp.tests.test_rnrclient import * |
708 | -from reviewsapp.tests.test_preflight import * |
709 | -from reviewsapp.tests.test_utilities import * |
710 | -from reviewsapp.tests.test_views import * |
711 | -from reviewsapp.tests.test_wsgi import * |
712 | -from reviewsapp.tests.test_pep8 import * |
713 | |
714 | === modified file 'src/reviewsapp/tests/factory.py' |
715 | --- src/reviewsapp/tests/factory.py 2014-07-16 16:02:40 +0000 |
716 | +++ src/reviewsapp/tests/factory.py 2014-07-25 17:44:55 +0000 |
717 | @@ -81,6 +81,10 @@ |
718 | prefix = "generic-string" |
719 | return prefix + str(self.getUniqueInteger()) |
720 | |
721 | + def makeArch(self, tag='i386'): |
722 | + """Gets or create an Arch with provided tag.""" |
723 | + return Architecture.objects.get_or_create(tag=tag) |
724 | + |
725 | def makeOAuthTokenAndConsumer( |
726 | self, user=None, consumer_secret=None, token_string=None, |
727 | token_secret=None, save=True): |
728 | |
729 | === modified file 'src/reviewsapp/tests/helpers.py' |
730 | --- src/reviewsapp/tests/helpers.py 2014-06-23 20:19:03 +0000 |
731 | +++ src/reviewsapp/tests/helpers.py 2014-07-25 17:44:55 +0000 |
732 | @@ -27,15 +27,39 @@ |
733 | from contextlib import contextmanager |
734 | from unittest import TestCase |
735 | |
736 | +from django.db import ( |
737 | + close_connection, |
738 | + close_old_connections, |
739 | + connection, |
740 | +) |
741 | from django.conf import settings |
742 | +from django.core import signals |
743 | from wsgi_intercept import add_wsgi_intercept, remove_wsgi_intercept |
744 | from wsgi_intercept.httplib2_intercept import install, uninstall |
745 | +from wsgi_intercept.urllib2_intercept import install_opener, uninstall_opener |
746 | |
747 | |
748 | class WSGIInterceptedTestCase(TestCase): |
749 | - def setUp(self, callbacks): |
750 | + def setUp(self, callbacks=None): |
751 | super(WSGIInterceptedTestCase, self).setUp() |
752 | + if callbacks is None: |
753 | + callbacks = {} |
754 | + |
755 | + # Django 1.6 changed the way db connections are managed in the |
756 | + # request cycle, now it cleans up connections at request start |
757 | + # and end by detecting if the are usable or not. Because the |
758 | + # current connection in tests generates outside of the patched |
759 | + # wsgi request, such connections are closed and therefore |
760 | + # tests fail. This code prevents that: |
761 | + signals.request_started.disconnect(close_old_connections) |
762 | + signals.request_finished.disconnect(close_old_connections) |
763 | + self.addCleanup( |
764 | + signals.request_started.connect, close_old_connections) |
765 | + self.addCleanup( |
766 | + signals.request_finished.connect, close_old_connections) |
767 | + |
768 | self.intercepted = [] |
769 | + install_opener() |
770 | install() |
771 | |
772 | for key, callback in callbacks.items(): |
773 | @@ -48,6 +72,7 @@ |
774 | def tearDown(self): |
775 | for host, port in self.intercepted: |
776 | remove_wsgi_intercept(host, port) |
777 | + uninstall_opener() |
778 | uninstall() |
779 | super(WSGIInterceptedTestCase, self).tearDown() |
780 | |
781 | |
782 | === modified file 'src/reviewsapp/tests/test_handlers.py' |
783 | --- src/reviewsapp/tests/test_handlers.py 2014-07-03 17:57:21 +0000 |
784 | +++ src/reviewsapp/tests/test_handlers.py 2014-07-25 17:44:55 +0000 |
785 | @@ -888,7 +888,9 @@ |
786 | |
787 | |
788 | class SubmitReviewHandlerTestCase(TestCaseWithFactory): |
789 | + |
790 | def setUp(self): |
791 | + super(SubmitReviewHandlerTestCase, self).setUp() |
792 | self.required_data = { |
793 | 'package_name': 'inkscape', |
794 | 'summary': 'Excellent', |
795 | @@ -900,7 +902,7 @@ |
796 | 'language': 'en', |
797 | 'arch_tag': 'i386', |
798 | } |
799 | - super(SubmitReviewHandlerTestCase, self).setUp() |
800 | + self.factory.makeArch('i386') |
801 | |
802 | def _post_new_review(self, data, user=None, verify_result=True): |
803 | # Post a review as an authenticated user. |
804 | |
805 | === modified file 'src/reviewsapp/tests/test_middleware.py' |
806 | --- src/reviewsapp/tests/test_middleware.py 2014-01-03 15:37:31 +0000 |
807 | +++ src/reviewsapp/tests/test_middleware.py 2014-07-25 17:44:55 +0000 |
808 | @@ -88,27 +88,3 @@ |
809 | |
810 | key = '.exceptions.ZeroDivisionError' |
811 | self.assert_stat_sent(key, mock_send) |
812 | - |
813 | - |
814 | -class SoftTimeoutMiddlewareTestCase(TestCase): |
815 | - @patch('django.test.client.RequestFactory._base_environ') |
816 | - def test_delay_triggers_oops_report(self, mock_environ): |
817 | - environ = { |
818 | - 'REQUEST_METHOD': 'GET', |
819 | - 'SERVER_NAME': 'testserver', |
820 | - 'SERVER_PORT': '80', |
821 | - 'wsgi.input': '' |
822 | - } |
823 | - |
824 | - def get_environ(**request): |
825 | - environ.update(request) |
826 | - return environ |
827 | - mock_environ.side_effect = get_environ |
828 | - # soft_request_timeout is an IntConfigOption, but a float works too |
829 | - with patch_settings(ENABLE_ARTIFICIAL_OOPS=True, |
830 | - SOFT_REQUEST_TIMEOUT=0.1): |
831 | - reload(reviewsapp.urls) |
832 | - self.client.get('/reviews/delay/0.1/') |
833 | - |
834 | - reload(reviewsapp.urls) |
835 | - self.assertTrue('dump-oops' in environ) |
836 | |
837 | === modified file 'src/reviewsapp/tests/test_wsgi.py' |
838 | --- src/reviewsapp/tests/test_wsgi.py 2014-01-03 15:53:10 +0000 |
839 | +++ src/reviewsapp/tests/test_wsgi.py 2014-07-25 17:44:55 +0000 |
840 | @@ -97,3 +97,14 @@ |
841 | self.assertEqual(oops.get('type'), 'ZeroDivisionError') |
842 | self.assertIn('tb_text', oops) |
843 | self.assertTrue(oops['tb_text'].startswith(' File ')) |
844 | + |
845 | + def test_delay_triggers_an_oops(self): |
846 | + self.environ['PATH_INFO'] = '/reviews/delay/0.1/' |
847 | + |
848 | + with patch_settings(SOFT_TIMEOUT_MILLISECONDS=1): |
849 | + self.request_wsgi_response(self.environ) |
850 | + |
851 | + oops_content = self.read_oops_from_disk() |
852 | + self.assertEqual('SoftRequestTimeout', oops_content['type']) |
853 | + expected = u'Start_response over timeout 1.' |
854 | + self.assertEqual(expected, oops_content['value']) |
LGTM