Merge lp:~bloodearnest/django-preflight/gargoyle into lp:~canonical-isd-hackers/django-preflight/gargoyle
- gargoyle
- Merge into gargoyle
Status: | Superseded |
---|---|
Proposed branch: | lp:~bloodearnest/django-preflight/gargoyle |
Merge into: | lp:~canonical-isd-hackers/django-preflight/gargoyle |
Diff against target: |
1016 lines (+274/-327) 20 files modified
MANIFEST.in (+1/-0) debian/changelog (+9/-0) debian/rules (+0/-1) doc/conf.py (+1/-1) doc/install.rst (+13/-9) example_project/app/preflight.py (+0/-38) example_project/app/templates/base.html (+0/-57) example_project/manage.py (+0/-13) example_project/run.py (+0/-31) example_project/settings.py (+0/-44) example_project/urls.py (+0/-15) preflight/__init__.py (+1/-1) preflight/conf.py (+6/-0) preflight/models.py (+41/-8) preflight/templates/preflight/overview.html (+32/-14) preflight/tests.py (+117/-31) preflight/views.py (+8/-9) setup.py (+17/-13) tox (+0/-6) tox.ini (+28/-36) |
To merge this branch: | bzr merge lp:~bloodearnest/django-preflight/gargoyle |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Canonical ISD hackers | Pending | ||
Review via email: mp+166838@code.launchpad.net |
Commit message
Description of the change
Add support for showing switches. Initially just gargoyle.
Unmerged revisions
- 26. By Simon Davy
-
more generic (less gargoyle specific), more gargoyle tests, embedded json switch data for automated scraping
- 25. By Simon Davy
-
Merge mfoord's branch into trunk, and make gargoyle optional in the process
- 24. By Łukasz Czyżykowski
-
[r=ricardokirkner] Updated code and tests to work with Django 1.5; dropped support for Python 2.5
- 23. By Anthony Lenton
-
[r=james-w] Fixed a silly bug that meant that hidden settings weren't really configurable via the PREFLIGHT_
HIDDEN_ SETTINGS setting. - 22. By Łukasz Czyżykowski
-
Updated debian/rules to be compatible with precise.
- 21. By Łukasz Czyżykowski
-
Added entry in the changelog
- 20. By Łukasz Czyżykowski
-
Merged the 1.4-release branch
- 19. By Anthony Lenton
-
[r=lukasz-
czyzykowski] Added configurable hidden settings. - 18. By Māris Fogels
-
[r=lukasz-
czyzykowski] Changed the default display template to the Django admin theme. - 17. By Jonathan Lange
-
[r=lukasz-
czyzykowski] Add platform to default versions
Preview Diff
1 | === added file 'MANIFEST.in' | |||
2 | --- MANIFEST.in 1970-01-01 00:00:00 +0000 | |||
3 | +++ MANIFEST.in 2013-05-31 15:53:26 +0000 | |||
4 | @@ -0,0 +1,1 @@ | |||
5 | 1 | include preflight/templates/preflight/*.html | ||
6 | 0 | \ No newline at end of file | 2 | \ No newline at end of file |
7 | 1 | 3 | ||
8 | === modified file 'debian/changelog' | |||
9 | --- debian/changelog 2011-10-04 14:33:24 +0000 | |||
10 | +++ debian/changelog 2013-05-31 15:53:26 +0000 | |||
11 | @@ -1,3 +1,12 @@ | |||
12 | 1 | django-preflight (0.1.4) precise; urgency=low | ||
13 | 2 | |||
14 | 3 | * Added display of settings on the preflight page | ||
15 | 4 | * Added configurable list of settings to hide | ||
16 | 5 | * Changed default base tamplate to Django admin base | ||
17 | 6 | * Added platform to default versions | ||
18 | 7 | |||
19 | 8 | -- Łukasz Czyżykowski <lukasz.czyzykowski@canonical.com> Wed, 03 Oct 2012 09:45:22 +0000 | ||
20 | 9 | |||
21 | 1 | django-preflight (0.1.1) lucid; urgency=low | 10 | django-preflight (0.1.1) lucid; urgency=low |
22 | 2 | 11 | ||
23 | 3 | * Use RequestContext instance when rendering the overview view | 12 | * Use RequestContext instance when rendering the overview view |
24 | 4 | 13 | ||
25 | === modified file 'debian/rules' | |||
26 | --- debian/rules 2011-02-07 16:06:51 +0000 | |||
27 | +++ debian/rules 2013-05-31 15:53:26 +0000 | |||
28 | @@ -4,4 +4,3 @@ | |||
29 | 4 | 4 | ||
30 | 5 | include /usr/share/cdbs/1/rules/debhelper.mk | 5 | include /usr/share/cdbs/1/rules/debhelper.mk |
31 | 6 | include /usr/share/cdbs/1/class/python-distutils.mk | 6 | include /usr/share/cdbs/1/class/python-distutils.mk |
32 | 7 | include /usr/share/cdbs/1/rules/langpack.mk | ||
33 | 8 | 7 | ||
34 | === modified file 'doc/conf.py' | |||
35 | --- doc/conf.py 2011-02-09 16:26:04 +0000 | |||
36 | +++ doc/conf.py 2013-05-31 15:53:26 +0000 | |||
37 | @@ -18,7 +18,7 @@ | |||
38 | 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. | 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. |
39 | 19 | sys.path.append(os.path.abspath('..')) | 19 | sys.path.append(os.path.abspath('..')) |
40 | 20 | 20 | ||
42 | 21 | os.environ['DJANGO_SETTINGS_MODULE'] = 'example_project.settings' | 21 | os.environ['DJANGO_SETTINGS_MODULE'] = 'preflight_example_project.settings' |
43 | 22 | 22 | ||
44 | 23 | # -- General configuration ----------------------------------------------------- | 23 | # -- General configuration ----------------------------------------------------- |
45 | 24 | 24 | ||
46 | 25 | 25 | ||
47 | === modified file 'doc/install.rst' | |||
48 | --- doc/install.rst 2012-05-25 16:34:25 +0000 | |||
49 | +++ doc/install.rst 2013-05-31 15:53:26 +0000 | |||
50 | @@ -38,19 +38,21 @@ | |||
51 | 38 | 38 | ||
52 | 39 | django-preflight by itself doesn't have any extra dependecies. | 39 | django-preflight by itself doesn't have any extra dependecies. |
53 | 40 | 40 | ||
56 | 41 | Because this project doesn't include any database models, there's no | 41 | Because this project doesn't include any models, there's no need of |
57 | 42 | need of updating your database schema. | 42 | updating your database schema. |
58 | 43 | 43 | ||
59 | 44 | 44 | ||
60 | 45 | Update ``urls.py`` | 45 | Update ``urls.py`` |
61 | 46 | ------------------ | 46 | ------------------ |
62 | 47 | 47 | ||
65 | 48 | Last bit of configuration is to include django-preflight into the | 48 | Last bit of configuration is to run preflight discovery code and to |
66 | 49 | project's ``urls.py`` file. It should look like the following: | 49 | include it somewhere in the url's definition. The easiest way for |
67 | 50 | doing both of those steps is to modify project's ``urls.py`` file. It | ||
68 | 51 | should look like the following: | ||
69 | 50 | 52 | ||
70 | 51 | .. testcode:: | 53 | .. testcode:: |
71 | 52 | 54 | ||
73 | 53 | from django.conf.urls.defaults import * | 55 | from django.conf.urls import * |
74 | 54 | 56 | ||
75 | 55 | import preflight | 57 | import preflight |
76 | 56 | import preflight.urls | 58 | import preflight.urls |
77 | @@ -78,10 +80,12 @@ | |||
78 | 78 | Compatibility | 80 | Compatibility |
79 | 79 | ------------- | 81 | ------------- |
80 | 80 | 82 | ||
84 | 81 | django-preflight is tested with released Django versions from | 83 | django-preflight is compatible with released Django versions since |
85 | 82 | 1.1 to 1.4. To be sure about this it's tested | 84 | 1.1, up to current 1.5. To be sure about this it's tested using tox_ |
86 | 83 | with tox_ against all of these versions. | 85 | against all of them. |
87 | 84 | 86 | ||
89 | 85 | Additionally it's tested on Python 2.5, 2.6 and 2.7, all on Ubuntu Linux. | 87 | Additionally it's tested on Python 2.6 and 2.7, all of that on `Ubuntu |
90 | 88 | Linux`_. | ||
91 | 86 | 89 | ||
92 | 87 | .. _tox: http://codespeak.net/tox/ | 90 | .. _tox: http://codespeak.net/tox/ |
93 | 91 | _Ubuntu Linux: http://www.ubuntu.com | ||
94 | 88 | 92 | ||
95 | === removed directory 'example_project' | |||
96 | === removed file 'example_project/__init__.py' | |||
97 | === removed directory 'example_project/app' | |||
98 | === removed file 'example_project/app/__init__.py' | |||
99 | === removed file 'example_project/app/models.py' | |||
100 | === removed file 'example_project/app/preflight.py' | |||
101 | --- example_project/app/preflight.py 2011-02-07 16:06:51 +0000 | |||
102 | +++ example_project/app/preflight.py 1970-01-01 00:00:00 +0000 | |||
103 | @@ -1,38 +0,0 @@ | |||
104 | 1 | # Copyright 2010 Canonical Ltd. This software is licensed under the | ||
105 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | ||
106 | 3 | |||
107 | 4 | from __future__ import absolute_import | ||
108 | 5 | |||
109 | 6 | from django.conf import settings | ||
110 | 7 | |||
111 | 8 | import os.path | ||
112 | 9 | import preflight | ||
113 | 10 | import tempfile | ||
114 | 11 | |||
115 | 12 | |||
116 | 13 | class AppPreflight(preflight.Preflight): | ||
117 | 14 | |||
118 | 15 | def authenticate(self, request): | ||
119 | 16 | # Allow everybody to access this page. Default implementation restricts | ||
120 | 17 | # this to people who can access /admin/ pages (user.is_stuff == True). | ||
121 | 18 | return True | ||
122 | 19 | |||
123 | 20 | def versions(self): | ||
124 | 21 | return [{'name': 'foo-bar', 'version': '1.2.3'}] | ||
125 | 22 | |||
126 | 23 | def check_media_root_is_writable(self): | ||
127 | 24 | """Check if current MEDIA_ROOT directory is writable.""" | ||
128 | 25 | path = os.path.realpath(settings.MEDIA_ROOT) | ||
129 | 26 | |||
130 | 27 | # Try writing to temporary file in MEDIA_ROOT | ||
131 | 28 | tmp = tempfile.TemporaryFile(dir=path) | ||
132 | 29 | tmp.write("test") | ||
133 | 30 | tmp.close() | ||
134 | 31 | |||
135 | 32 | # If we reached this point this means the directory itself is | ||
136 | 33 | # writable. In case of any errors an exception would cause the check to | ||
137 | 34 | # fail. Return value informs preflight that everything went right. | ||
138 | 35 | return True | ||
139 | 36 | |||
140 | 37 | |||
141 | 38 | preflight.register(AppPreflight) | ||
142 | 39 | 0 | ||
143 | === removed directory 'example_project/app/templates' | |||
144 | === removed file 'example_project/app/templates/base.html' | |||
145 | --- example_project/app/templates/base.html 2011-02-07 16:06:51 +0000 | |||
146 | +++ example_project/app/templates/base.html 1970-01-01 00:00:00 +0000 | |||
147 | @@ -1,57 +0,0 @@ | |||
148 | 1 | {# Copyright 2010 Canonical Ltd. This software is licensed under the #} | ||
149 | 2 | {# GNU Affero General Public License version 3 (see the file LICENSE). #} | ||
150 | 3 | <html> | ||
151 | 4 | <head> | ||
152 | 5 | <title>{% block title %}{% endblock %}</title> | ||
153 | 6 | <style> | ||
154 | 7 | #content { | ||
155 | 8 | font: 13.34px helvetica, arial, freesans, clean, sans-serif; | ||
156 | 9 | width: 600px; | ||
157 | 10 | margin: 32px auto; | ||
158 | 11 | border: 1px solid #ddd; | ||
159 | 12 | padding: 2em; | ||
160 | 13 | background-color: #f0f0f0; | ||
161 | 14 | } | ||
162 | 15 | #content p { | ||
163 | 16 | margin-top: 32px; | ||
164 | 17 | border-top: 1px solid #999; | ||
165 | 18 | text-align: center; | ||
166 | 19 | } | ||
167 | 20 | #content h1 { | ||
168 | 21 | margin: 64px 0 32px; | ||
169 | 22 | border-bottom: 3px solid #555; | ||
170 | 23 | } | ||
171 | 24 | #content h2 { | ||
172 | 25 | margin: 32px 0; | ||
173 | 26 | border-bottom: 3px solid #999; | ||
174 | 27 | } | ||
175 | 28 | #content table { | ||
176 | 29 | padding: 0; | ||
177 | 30 | border-spacing: 0; | ||
178 | 31 | width: 100%; | ||
179 | 32 | } | ||
180 | 33 | #content table th { | ||
181 | 34 | border-bottom: 1px solid #aaa; | ||
182 | 35 | } | ||
183 | 36 | #content table td, | ||
184 | 37 | #content table th { | ||
185 | 38 | padding: 0.3em; | ||
186 | 39 | } | ||
187 | 40 | #content .ok { | ||
188 | 41 | color: green; | ||
189 | 42 | } | ||
190 | 43 | #content .error { | ||
191 | 44 | color: red; | ||
192 | 45 | } | ||
193 | 46 | #content td.status { | ||
194 | 47 | text-align: center; | ||
195 | 48 | } | ||
196 | 49 | #content td.description { | ||
197 | 50 | font-size: 80%; | ||
198 | 51 | } | ||
199 | 52 | </style> | ||
200 | 53 | </head> | ||
201 | 54 | <body> | ||
202 | 55 | <div id="content">{% block content %}{% endblock %}</div> | ||
203 | 56 | </body> | ||
204 | 57 | </html> | ||
205 | 58 | 0 | ||
206 | === removed file 'example_project/manage.py' | |||
207 | --- example_project/manage.py 2011-02-07 16:06:51 +0000 | |||
208 | +++ example_project/manage.py 1970-01-01 00:00:00 +0000 | |||
209 | @@ -1,13 +0,0 @@ | |||
210 | 1 | #!/usr/bin/python | ||
211 | 2 | import sys | ||
212 | 3 | sys.path.append('..') | ||
213 | 4 | |||
214 | 5 | from django.core.management import execute_manager | ||
215 | 6 | try: | ||
216 | 7 | import settings # Assumed to be in the same directory. | ||
217 | 8 | except ImportError: | ||
218 | 9 | sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) | ||
219 | 10 | sys.exit(1) | ||
220 | 11 | |||
221 | 12 | if __name__ == "__main__": | ||
222 | 13 | execute_manager(settings) | ||
223 | 14 | 0 | ||
224 | === removed file 'example_project/run.py' | |||
225 | --- example_project/run.py 2011-02-07 16:06:51 +0000 | |||
226 | +++ example_project/run.py 1970-01-01 00:00:00 +0000 | |||
227 | @@ -1,31 +0,0 @@ | |||
228 | 1 | import os | ||
229 | 2 | import sys | ||
230 | 3 | |||
231 | 4 | os.environ['DJANGO_SETTINGS_MODULE'] = 'example_project.settings' | ||
232 | 5 | sys.path.insert(0, 'example_project') | ||
233 | 6 | |||
234 | 7 | try: | ||
235 | 8 | from django.test.utils import get_runner | ||
236 | 9 | except ImportError: | ||
237 | 10 | from django.test.simple import run_tests | ||
238 | 11 | get_runner = lambda s: run_tests | ||
239 | 12 | |||
240 | 13 | from django.conf import settings | ||
241 | 14 | |||
242 | 15 | |||
243 | 16 | |||
244 | 17 | def tests(): | ||
245 | 18 | TestRunner = get_runner(settings) | ||
246 | 19 | if hasattr(TestRunner, 'func_name'): | ||
247 | 20 | # Before change in Django 1.2 | ||
248 | 21 | failures = TestRunner(['preflight']) | ||
249 | 22 | else: | ||
250 | 23 | test_runner = TestRunner() | ||
251 | 24 | failures = test_runner.run_tests(['preflight']) | ||
252 | 25 | |||
253 | 26 | sys.exit(bool(failures)) | ||
254 | 27 | |||
255 | 28 | |||
256 | 29 | |||
257 | 30 | if __name__ == '__main__': | ||
258 | 31 | tests() | ||
259 | 32 | 0 | ||
260 | === removed file 'example_project/settings.py' | |||
261 | --- example_project/settings.py 2012-05-25 16:31:15 +0000 | |||
262 | +++ example_project/settings.py 1970-01-01 00:00:00 +0000 | |||
263 | @@ -1,44 +0,0 @@ | |||
264 | 1 | import os | ||
265 | 2 | |||
266 | 3 | DEBUG = True | ||
267 | 4 | TEMPLATE_DEBUG = DEBUG | ||
268 | 5 | |||
269 | 6 | ADMINS = () | ||
270 | 7 | MANAGERS = ADMINS | ||
271 | 8 | |||
272 | 9 | DATABASES = { | ||
273 | 10 | 'default': { | ||
274 | 11 | 'ENGINE': 'django.db.backends.sqlite3', | ||
275 | 12 | 'NAME': 'database.sqlit3', | ||
276 | 13 | } | ||
277 | 14 | } | ||
278 | 15 | |||
279 | 16 | # Old db setup | ||
280 | 17 | DATABASE_ENGINE = 'sqlite3' | ||
281 | 18 | DATABASE_NAME = 'database.sqlite3' | ||
282 | 19 | |||
283 | 20 | TIME_ZONE = 'America/Chicago' | ||
284 | 21 | LANGUAGE_CODE = 'en-us' | ||
285 | 22 | SITE_ID = 1 | ||
286 | 23 | MEDIA_ROOT = '' | ||
287 | 24 | MEDIA_URL = '' | ||
288 | 25 | ADMIN_MEDIA_PREFIX = '/media/' | ||
289 | 26 | SECRET_KEY = 'j0-wo!y4zwi)tejv1u(0skc41_379ls^@qbh91%#5o=greje6(' | ||
290 | 27 | |||
291 | 28 | ROOT_URLCONF = 'example_project.urls' | ||
292 | 29 | |||
293 | 30 | TEMPLATE_DIRS = ( | ||
294 | 31 | os.path.join(os.path.realpath(os.path.dirname(__file__)), 'templates'), | ||
295 | 32 | ) | ||
296 | 33 | |||
297 | 34 | INSTALLED_APPS = ( | ||
298 | 35 | 'django.contrib.auth', | ||
299 | 36 | 'django.contrib.contenttypes', | ||
300 | 37 | 'django.contrib.sessions', | ||
301 | 38 | 'django.contrib.sites', | ||
302 | 39 | 'preflight', | ||
303 | 40 | 'app', | ||
304 | 41 | 'gargoyle', | ||
305 | 42 | ) | ||
306 | 43 | |||
307 | 44 | PREFLIGHT_BASE_TEMPLATE = 'base.html' | ||
308 | 45 | 0 | ||
309 | === removed file 'example_project/urls.py' | |||
310 | --- example_project/urls.py 2011-10-04 15:54:50 +0000 | |||
311 | +++ example_project/urls.py 1970-01-01 00:00:00 +0000 | |||
312 | @@ -1,15 +0,0 @@ | |||
313 | 1 | # Copyright 2010 Canonical Ltd. This software is licensed under the | ||
314 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | ||
315 | 3 | |||
316 | 4 | from django.conf.urls.defaults import ( | ||
317 | 5 | handler404, handler500, include, patterns | ||
318 | 6 | ) | ||
319 | 7 | |||
320 | 8 | import preflight | ||
321 | 9 | |||
322 | 10 | |||
323 | 11 | preflight.autodiscover() | ||
324 | 12 | |||
325 | 13 | urlpatterns = patterns('', | ||
326 | 14 | (r'^preflight/', include('preflight.urls')), | ||
327 | 15 | ) | ||
328 | 16 | 0 | ||
329 | === modified file 'preflight/__init__.py' | |||
330 | --- preflight/__init__.py 2011-03-19 15:15:41 +0000 | |||
331 | +++ preflight/__init__.py 2013-05-31 15:53:26 +0000 | |||
332 | @@ -5,7 +5,7 @@ | |||
333 | 5 | 5 | ||
334 | 6 | from .models import REGISTRY | 6 | from .models import REGISTRY |
335 | 7 | 7 | ||
337 | 8 | __version__ = "0.1.1" | 8 | __version__ = "0.1.5" |
338 | 9 | 9 | ||
339 | 10 | 10 | ||
340 | 11 | def autodiscover(): | 11 | def autodiscover(): |
341 | 12 | 12 | ||
342 | === added file 'preflight/conf.py' | |||
343 | --- preflight/conf.py 1970-01-01 00:00:00 +0000 | |||
344 | +++ preflight/conf.py 2013-05-31 15:53:26 +0000 | |||
345 | @@ -0,0 +1,6 @@ | |||
346 | 1 | from django.conf import settings | ||
347 | 2 | |||
348 | 3 | |||
349 | 4 | BASE_TEMPLATE = getattr( | ||
350 | 5 | settings, 'PREFLIGHT_BASE_TEMPLATE', "admin/base.html") | ||
351 | 6 | TABLE_CLASS = getattr(settings, 'PREFLIGHT_TABLE_CLASS', "listing") | ||
352 | 0 | 7 | ||
353 | === modified file 'preflight/models.py' | |||
354 | --- preflight/models.py 2012-05-25 16:31:15 +0000 | |||
355 | +++ preflight/models.py 2013-05-31 15:53:26 +0000 | |||
356 | @@ -2,6 +2,8 @@ | |||
357 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
358 | 3 | 3 | ||
359 | 4 | from __future__ import absolute_import | 4 | from __future__ import absolute_import |
360 | 5 | |||
361 | 6 | import re | ||
362 | 5 | from django.conf import settings | 7 | from django.conf import settings |
363 | 6 | from django.views.debug import HIDDEN_SETTINGS | 8 | from django.views.debug import HIDDEN_SETTINGS |
364 | 7 | 9 | ||
365 | @@ -75,11 +77,13 @@ | |||
366 | 75 | data. | 77 | data. |
367 | 76 | 78 | ||
368 | 77 | """ | 79 | """ |
369 | 80 | import platform | ||
370 | 78 | import sys | 81 | import sys |
371 | 79 | import django | 82 | import django |
372 | 80 | import preflight | 83 | import preflight |
373 | 81 | 84 | ||
374 | 82 | items = [ | 85 | items = [ |
375 | 86 | {'name': 'Platform', 'version': platform.platform()}, | ||
376 | 83 | {'name': 'Django', 'version': django.get_version()}, | 87 | {'name': 'Django', 'version': django.get_version()}, |
377 | 84 | {'name': 'Python', 'version': sys.version}, | 88 | {'name': 'Python', 'version': sys.version}, |
378 | 85 | {'name': 'preflight', 'version': preflight.__version__} | 89 | {'name': 'preflight', 'version': preflight.__version__} |
379 | @@ -115,8 +119,13 @@ | |||
380 | 115 | names = sorted([x for x in settings._wrapped.__dict__ | 119 | names = sorted([x for x in settings._wrapped.__dict__ |
381 | 116 | if x.isupper() and not x.startswith('_')]) | 120 | if x.isupper() and not x.startswith('_')]) |
382 | 117 | settings_list = [] | 121 | settings_list = [] |
383 | 122 | hidden_settings = getattr(settings, 'PREFLIGHT_HIDDEN_SETTINGS', None) | ||
384 | 123 | if hidden_settings: | ||
385 | 124 | hidden_settings = re.compile(hidden_settings) | ||
386 | 125 | else: | ||
387 | 126 | hidden_settings = HIDDEN_SETTINGS | ||
388 | 118 | for name in names: | 127 | for name in names: |
390 | 119 | if HIDDEN_SETTINGS.match(name): | 128 | if hidden_settings.search(name): |
391 | 120 | value = '******************' | 129 | value = '******************' |
392 | 121 | else: | 130 | else: |
393 | 122 | value = getattr(settings, name, None) | 131 | value = getattr(settings, name, None) |
394 | @@ -135,16 +144,40 @@ | |||
395 | 135 | return all(class_().authenticate(request) for class_ in REGISTRY) | 144 | return all(class_().authenticate(request) for class_ in REGISTRY) |
396 | 136 | 145 | ||
397 | 137 | 146 | ||
398 | 147 | def gather_switches(): | ||
399 | 148 | """Gather all switches into one list.""" | ||
400 | 149 | switches = {} | ||
401 | 150 | if settings.USE_GARGOYLE: | ||
402 | 151 | gargoyle_switches = gather_gargoyle() | ||
403 | 152 | if gargoyle_switches: | ||
404 | 153 | switches['gargoyle'] = gargoyle_switches | ||
405 | 154 | return switches | ||
406 | 155 | |||
407 | 156 | |||
408 | 138 | def gather_gargoyle(): | 157 | def gather_gargoyle(): |
409 | 158 | if not settings.USE_GARGOYLE: | ||
410 | 159 | return None | ||
411 | 139 | try: | 160 | try: |
412 | 140 | from gargoyle.models import Switch | 161 | from gargoyle.models import Switch |
413 | 141 | except ImportError: | 162 | except ImportError: |
414 | 142 | return None | 163 | return None |
419 | 143 | switches = Switch.objects.all() | 164 | return [_format_gargoyle(switch) for switch in Switch.objects.all()] |
420 | 144 | return [_format_switch(switch) for switch in switches] | 165 | |
421 | 145 | 166 | ||
422 | 146 | def _format_switch(switch): | 167 | def _format_gargoyle(switch): |
423 | 168 | from gargoyle import gargoyle | ||
424 | 169 | """Formats a gargoyle switch into std format for display""" | ||
425 | 170 | d = switch.to_dict(gargoyle) | ||
426 | 171 | conditions = [] | ||
427 | 172 | for condition in d['conditions']: | ||
428 | 173 | params = ','.join('%s=%s' % (c[0], c[2]) | ||
429 | 174 | for c in condition['conditions']) | ||
430 | 175 | conditions.append("%s(%s)" % (condition['label'], params)) | ||
431 | 176 | |||
432 | 147 | return dict( | 177 | return dict( |
433 | 148 | name=switch.key, description=switch.description or '', | ||
434 | 149 | value=switch.value, status=switch.get_status_label() | ||
435 | 150 | ) | ||
436 | 151 | \ No newline at end of file | 178 | \ No newline at end of file |
437 | 179 | name=d['key'], | ||
438 | 180 | description=d['description'], | ||
439 | 181 | status=d['status'], | ||
440 | 182 | status_text=d['statusLabel'], | ||
441 | 183 | conditions=conditions, | ||
442 | 184 | ) | ||
443 | 152 | 185 | ||
444 | === modified file 'preflight/templates/preflight/overview.html' | |||
445 | --- preflight/templates/preflight/overview.html 2012-05-25 16:31:15 +0000 | |||
446 | +++ preflight/templates/preflight/overview.html 2013-05-31 15:53:26 +0000 | |||
447 | @@ -17,7 +17,9 @@ | |||
448 | 17 | {% endfor %} | 17 | {% endfor %} |
449 | 18 | <li><a href="#versions">Versions</a></li> | 18 | <li><a href="#versions">Versions</a></li> |
450 | 19 | <li><a href="#settings">Settings</a></li> | 19 | <li><a href="#settings">Settings</a></li> |
452 | 20 | <li><a href="#gargoyle">Gargoyle</a></li> | 20 | {% if switches %} |
453 | 21 | <li><a href="#switches">Switches</a></li> | ||
454 | 22 | {% endif %} | ||
455 | 21 | </ul> | 23 | </ul> |
456 | 22 | 24 | ||
457 | 23 | {% for application in applications %} | 25 | {% for application in applications %} |
458 | @@ -81,32 +83,48 @@ | |||
459 | 81 | {% endfor %} | 83 | {% endfor %} |
460 | 82 | </dl> | 84 | </dl> |
461 | 83 | 85 | ||
462 | 86 | {% if switches %} | ||
463 | 84 | <a href="#links" style="text-decoration : none;"> | 87 | <a href="#links" style="text-decoration : none;"> |
465 | 85 | <h1 id="gargoyle">{% trans "Gargoyle Switches" %}</h1> | 88 | <h1 id="switches">{% trans "Switches" %}</h1> |
466 | 86 | </a> | 89 | </a> |
469 | 87 | {% if gargoyle %} | 90 | <table id="switches-table" class="{{ preflight_table_class }}"> |
468 | 88 | <table id="gargoyle-table" class="{{ preflight_table_class }}"> | ||
470 | 89 | <thead> | 91 | <thead> |
471 | 90 | <tr> | 92 | <tr> |
472 | 91 | <th>{% trans "Name" %}</th> | 93 | <th>{% trans "Name" %}</th> |
473 | 92 | <th>{% trans "Description" %}</th> | 94 | <th>{% trans "Description" %}</th> |
475 | 93 | <th>{% trans "value" %}</th> | 95 | <th>{% trans "Conditions" %}</th> |
476 | 94 | <th>{% trans "Status" %}</th> | 96 | <th>{% trans "Status" %}</th> |
477 | 95 | </tr> | 97 | </tr> |
478 | 96 | </thead> | 98 | </thead> |
479 | 97 | <tbody> | 99 | <tbody> |
487 | 98 | {% for item in gargoyle %} | 100 | {% for type, type_switches in switches.items %} |
488 | 99 | <tr> | 101 | <tr><th colspan="4">{{ type }}</th></tr> |
489 | 100 | <td>{{ item.name }}</td> | 102 | {% for switch in type_switches %} |
490 | 101 | <td>{{ item.description }}</td> | 103 | <tr class="switch"> |
491 | 102 | <td>{{ item.value }}</td> | 104 | <td>{{ switch.name }}</td> |
492 | 103 | <td>{{ item.status }}</td> | 105 | <td>{{ switch.description }}</td> |
493 | 104 | </tr> | 106 | <td> |
494 | 107 | {% if switch.conditions %} | ||
495 | 108 | <ul> | ||
496 | 109 | {% for condition in switch.conditions %} | ||
497 | 110 | <li>{{ condition|first }}: {{ condition|last }}</li> | ||
498 | 111 | {% endfor %} | ||
499 | 112 | </ul> | ||
500 | 113 | {% endif %} | ||
501 | 114 | </td> | ||
502 | 115 | <td>{{ switch.status_text }}</td> | ||
503 | 116 | {% endfor %} | ||
504 | 117 | </tr> | ||
505 | 105 | {% endfor %} | 118 | {% endfor %} |
506 | 106 | </tbody> | 119 | </tbody> |
508 | 107 | </table> | 120 | </table> |
509 | 121 | <p>Switch data is included in JSON format in a script tag with id | ||
510 | 122 | "switches-json" to aid automated scripting</p> | ||
511 | 123 | <script id="switches-json"> | ||
512 | 124 | {{ switches_json|safe }} | ||
513 | 125 | </script> | ||
514 | 108 | {% else %} | 126 | {% else %} |
516 | 109 | <p>No gargoyle switches.</p> | 127 | <p>No switches.</p> |
517 | 110 | {% endif %} | 128 | {% endif %} |
518 | 111 | </div> | 129 | </div> |
519 | 112 | 130 | ||
520 | 113 | 131 | ||
521 | === modified file 'preflight/tests.py' | |||
522 | --- preflight/tests.py 2012-05-25 17:19:29 +0000 | |||
523 | +++ preflight/tests.py 2013-05-31 15:53:26 +0000 | |||
524 | @@ -1,19 +1,26 @@ | |||
525 | 1 | # Copyright 2010 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2010 Canonical Ltd. This software is licensed under the |
526 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
527 | 3 | import sys | 3 | import sys |
528 | 4 | import json | ||
529 | 5 | try: | ||
530 | 6 | from unittest import skipIf | ||
531 | 7 | except ImportError: | ||
532 | 8 | from unittest2 import skipIf # NOQA | ||
533 | 4 | 9 | ||
534 | 10 | from django.conf import settings | ||
535 | 5 | from django.core.management import call_command | 11 | from django.core.management import call_command |
536 | 6 | from django.core.urlresolvers import reverse | 12 | from django.core.urlresolvers import reverse |
537 | 7 | from django.http import HttpResponse | 13 | from django.http import HttpResponse |
538 | 8 | from django.test import TestCase | 14 | from django.test import TestCase |
541 | 9 | from django.template import RequestContext, TemplateDoesNotExist | 15 | from django.template import RequestContext |
542 | 10 | 16 | from django.template.loader import render_to_string | |
543 | 11 | from mock import ( | 17 | from mock import ( |
544 | 12 | Mock, | 18 | Mock, |
545 | 13 | patch, | 19 | patch, |
546 | 14 | ) | 20 | ) |
547 | 15 | 21 | ||
548 | 16 | from cStringIO import StringIO | 22 | from cStringIO import StringIO |
549 | 23 | from pyquery import PyQuery | ||
550 | 17 | 24 | ||
551 | 18 | from . import Preflight | 25 | from . import Preflight |
552 | 19 | from .models import ( | 26 | from .models import ( |
553 | @@ -22,11 +29,12 @@ | |||
554 | 22 | REGISTRY, | 29 | REGISTRY, |
555 | 23 | authenticate, | 30 | authenticate, |
556 | 24 | gather_checks, | 31 | gather_checks, |
557 | 32 | gather_switches, | ||
558 | 25 | gather_gargoyle, | 33 | gather_gargoyle, |
559 | 26 | gather_settings, | 34 | gather_settings, |
560 | 27 | gather_versions, | 35 | gather_versions, |
561 | 28 | ) | 36 | ) |
563 | 29 | 37 | from preflight.conf import BASE_TEMPLATE, TABLE_CLASS | |
564 | 30 | 38 | ||
565 | 31 | 39 | ||
566 | 32 | class CheckTestCase(TestCase): | 40 | class CheckTestCase(TestCase): |
567 | @@ -48,7 +56,8 @@ | |||
568 | 48 | self.assertEquals(check.description, "description") | 56 | self.assertEquals(check.description, "description") |
569 | 49 | 57 | ||
570 | 50 | def test_initialisation_when_doc_is_none(self): | 58 | def test_initialisation_when_doc_is_none(self): |
572 | 51 | def method(): pass | 59 | def method(): |
573 | 60 | pass | ||
574 | 52 | 61 | ||
575 | 53 | check = Check("check_name", method) | 62 | check = Check("check_name", method) |
576 | 54 | 63 | ||
577 | @@ -144,6 +153,7 @@ | |||
578 | 144 | def authenticate(self, request): | 153 | def authenticate(self, request): |
579 | 145 | return False | 154 | return False |
580 | 146 | 155 | ||
581 | 156 | |||
582 | 147 | def clear_registry(): | 157 | def clear_registry(): |
583 | 148 | while REGISTRY: | 158 | while REGISTRY: |
584 | 149 | REGISTRY.pop() | 159 | REGISTRY.pop() |
585 | @@ -184,6 +194,7 @@ | |||
586 | 184 | def versions(self): | 194 | def versions(self): |
587 | 185 | return [{'name': 'spam', 'version': 'ni'}] | 195 | return [{'name': 'spam', 'version': 'ni'}] |
588 | 186 | 196 | ||
589 | 197 | |||
590 | 187 | class ExtraVersionAsList(Preflight): | 198 | class ExtraVersionAsList(Preflight): |
591 | 188 | 199 | ||
592 | 189 | versions = [{'name': 'eggs', 'version': 'peng'}] | 200 | versions = [{'name': 'eggs', 'version': 'peng'}] |
593 | @@ -196,7 +207,7 @@ | |||
594 | 196 | 207 | ||
595 | 197 | versions = gather_versions() | 208 | versions = gather_versions() |
596 | 198 | 209 | ||
598 | 199 | self.assertEquals(len(versions), 3) | 210 | self.assertEquals(len(versions), 4) |
599 | 200 | for item in versions: | 211 | for item in versions: |
600 | 201 | self.assertTrue('name' in item and 'version' in item) | 212 | self.assertTrue('name' in item and 'version' in item) |
601 | 202 | 213 | ||
602 | @@ -206,7 +217,7 @@ | |||
603 | 206 | 217 | ||
604 | 207 | versions = gather_versions() | 218 | versions = gather_versions() |
605 | 208 | 219 | ||
607 | 209 | self.assertEquals(len(versions), 4) | 220 | self.assertEquals(len(versions), 5) |
608 | 210 | self.assertEquals(versions[-1]['name'], 'spam') | 221 | self.assertEquals(versions[-1]['name'], 'spam') |
609 | 211 | 222 | ||
610 | 212 | def test_get_extra_version_information_from_class_attribute(self): | 223 | def test_get_extra_version_information_from_class_attribute(self): |
611 | @@ -215,7 +226,7 @@ | |||
612 | 215 | 226 | ||
613 | 216 | versions = gather_versions() | 227 | versions = gather_versions() |
614 | 217 | 228 | ||
616 | 218 | self.assertEquals(len(versions), 4) | 229 | self.assertEquals(len(versions), 5) |
617 | 219 | self.assertEquals(versions[-1]['version'], 'peng') | 230 | self.assertEquals(versions[-1]['version'], 'peng') |
618 | 220 | 231 | ||
619 | 221 | 232 | ||
620 | @@ -241,8 +252,9 @@ | |||
621 | 241 | def test_overview_when_not_authenticated(self, mock_authenticate): | 252 | def test_overview_when_not_authenticated(self, mock_authenticate): |
622 | 242 | mock_authenticate.return_value = False | 253 | mock_authenticate.return_value = False |
623 | 243 | 254 | ||
626 | 244 | self.assertRaises(TemplateDoesNotExist, self.client.get, | 255 | response = self.client.get(reverse('preflight-overview')) |
627 | 245 | reverse('preflight-overview')) | 256 | |
628 | 257 | self.assertEqual(response.status_code, 404) | ||
629 | 246 | 258 | ||
630 | 247 | @patch('preflight.views.render_to_response') | 259 | @patch('preflight.views.render_to_response') |
631 | 248 | @patch('preflight.views.authenticate') | 260 | @patch('preflight.views.authenticate') |
632 | @@ -262,6 +274,7 @@ | |||
633 | 262 | def test_gather_settings_no_location(self, mock_settings): | 274 | def test_gather_settings_no_location(self, mock_settings): |
634 | 263 | mock_settings._wrapped.FOO = 'bar' | 275 | mock_settings._wrapped.FOO = 'bar' |
635 | 264 | mock_settings.FOO = 'bar' | 276 | mock_settings.FOO = 'bar' |
636 | 277 | mock_settings.PREFLIGHT_HIDDEN_SETTINGS = '' | ||
637 | 265 | settings = gather_settings() | 278 | settings = gather_settings() |
638 | 266 | expected = [{'name': 'FOO', 'value': 'bar', 'location': ''}] | 279 | expected = [{'name': 'FOO', 'value': 'bar', 'location': ''}] |
639 | 267 | self.assertEqual(expected, settings) | 280 | self.assertEqual(expected, settings) |
640 | @@ -270,6 +283,7 @@ | |||
641 | 270 | def test_gather_settings_with_location(self, mock_settings): | 283 | def test_gather_settings_with_location(self, mock_settings): |
642 | 271 | mock_settings._wrapped.FOO = 'bar' | 284 | mock_settings._wrapped.FOO = 'bar' |
643 | 272 | mock_settings.FOO = 'bar' | 285 | mock_settings.FOO = 'bar' |
644 | 286 | mock_settings.PREFLIGHT_HIDDEN_SETTINGS = '' | ||
645 | 273 | parser = Mock() | 287 | parser = Mock() |
646 | 274 | parser.locate.return_value = '/tmp/baz' | 288 | parser.locate.return_value = '/tmp/baz' |
647 | 275 | mock_settings.__CONFIGGLUE_PARSER__ = parser | 289 | mock_settings.__CONFIGGLUE_PARSER__ = parser |
648 | @@ -279,43 +293,115 @@ | |||
649 | 279 | 293 | ||
650 | 280 | @patch('preflight.models.settings') | 294 | @patch('preflight.models.settings') |
651 | 281 | def test_gather_settings_hidden(self, mock_settings): | 295 | def test_gather_settings_hidden(self, mock_settings): |
654 | 282 | mock_settings._wrapped.SECRET_FOO = 'bar' | 296 | mock_settings._wrapped.FOO_ZOGGLES = 'bar' |
655 | 283 | mock_settings.SECRET_FOO = 'bar' | 297 | mock_settings.FOO_ZOGGLES = 'bar' |
656 | 298 | mock_settings.PREFLIGHT_HIDDEN_SETTINGS = 'ZOGGLES' | ||
657 | 284 | settings = gather_settings() | 299 | settings = gather_settings() |
659 | 285 | expected = [{'name': 'SECRET_FOO', 'value': '*' * 18, 'location': ''}] | 300 | expected = [{'name': 'FOO_ZOGGLES', 'value': '*' * 18, 'location': ''}] |
660 | 286 | self.assertEqual(expected, settings) | 301 | self.assertEqual(expected, settings) |
661 | 287 | 302 | ||
662 | 288 | @patch('preflight.models.settings') | 303 | @patch('preflight.models.settings') |
663 | 289 | def test_gather_settings_omitted(self, mock_settings): | 304 | def test_gather_settings_omitted(self, mock_settings): |
664 | 290 | mock_settings._wrapped._FOO = 'bar' | 305 | mock_settings._wrapped._FOO = 'bar' |
665 | 291 | mock_settings._FOO = 'bar' | 306 | mock_settings._FOO = 'bar' |
666 | 307 | mock_settings.PREFLIGHT_HIDDEN_SETTINGS = '' | ||
667 | 292 | settings = gather_settings() | 308 | settings = gather_settings() |
668 | 293 | self.assertEqual([], settings) | 309 | self.assertEqual([], settings) |
669 | 294 | 310 | ||
670 | 295 | 311 | ||
671 | 312 | @skipIf(not settings.USE_GARGOYLE, 'skipping for Django 1.1') | ||
672 | 296 | class GargoyleTestCase(TestCase): | 313 | class GargoyleTestCase(TestCase): |
673 | 314 | from gargoyle import gargoyle # NOQA | ||
674 | 315 | from gargoyle.models import ( # NOQA | ||
675 | 316 | Switch, | ||
676 | 317 | DISABLED, | ||
677 | 318 | SELECTIVE, | ||
678 | 319 | GLOBAL, | ||
679 | 320 | INHERIT | ||
680 | 321 | ) | ||
681 | 322 | |||
682 | 323 | def setUp(self): | ||
683 | 324 | super(GargoyleTestCase, self).setUp() | ||
684 | 325 | from gargoyle.builtins import IPAddressConditionSet | ||
685 | 326 | |||
686 | 327 | self.gargoyle.register(IPAddressConditionSet()) | ||
687 | 328 | |||
688 | 329 | def get_switches(self): | ||
689 | 330 | switches = [ | ||
690 | 331 | self.Switch(key='DISABLED', status=self.DISABLED, | ||
691 | 332 | description='switch 1'), | ||
692 | 333 | self.Switch(key='SELECTIVE_1', status=self.SELECTIVE), | ||
693 | 334 | self.Switch(key='SELECTIVE_2', status=self.SELECTIVE), | ||
694 | 335 | self.Switch(key='GLOBAL', status=self.GLOBAL), | ||
695 | 336 | self.Switch(key='INHERIT', status=self.INHERIT), | ||
696 | 337 | ] | ||
697 | 338 | selective = switches[2] | ||
698 | 339 | selective.add_condition( | ||
699 | 340 | self.gargoyle, | ||
700 | 341 | condition_set='gargoyle.builtins.IPAddressConditionSet', | ||
701 | 342 | field_name='ip_address', | ||
702 | 343 | condition='127.0.0.1', | ||
703 | 344 | ) | ||
704 | 345 | return switches | ||
705 | 297 | 346 | ||
706 | 298 | @patch.dict(sys.modules, **{'gargoyle.models': None}) | 347 | @patch.dict(sys.modules, **{'gargoyle.models': None}) |
708 | 299 | def test_gather_gargoyle_no_gargoyle(self): | 348 | def test_gather_switches_no_gargoyle(self): |
709 | 300 | self.assertEqual(gather_gargoyle(), None) | 349 | self.assertEqual(gather_gargoyle(), None) |
710 | 301 | 350 | ||
725 | 302 | @patch.dict(sys.modules, **{'gargoyle.models': Mock()}) | 351 | def assert_switches_dict(self, actual): |
712 | 303 | def test_gather_gargoyle(self): | ||
713 | 304 | # Inner import to get the mocked version | ||
714 | 305 | from gargoyle.models import Switch as MockSwitch | ||
715 | 306 | |||
716 | 307 | mocks = [Mock(), Mock(), Mock()] | ||
717 | 308 | MockSwitch.objects.all.return_value = mocks | ||
718 | 309 | switches = [ | ||
719 | 310 | |||
720 | 311 | ] | ||
721 | 312 | for switch, mock in zip(switches, mocks): | ||
722 | 313 | for attr, value in switch: | ||
723 | 314 | setattr(mock, attr, value) | ||
724 | 315 | |||
726 | 316 | expected = [ | 352 | expected = [ |
730 | 317 | {}, | 353 | dict(name='DISABLED', |
731 | 318 | {}, | 354 | status=self.DISABLED, |
732 | 319 | {} | 355 | description='switch 1', |
733 | 356 | status_text=self.Switch.STATUS_LABELS[self.DISABLED], | ||
734 | 357 | conditions=[]), | ||
735 | 358 | dict(name='SELECTIVE_1', | ||
736 | 359 | status=self.SELECTIVE, | ||
737 | 360 | description=None, | ||
738 | 361 | status_text=self.Switch.STATUS_LABELS[self.GLOBAL], | ||
739 | 362 | conditions=[]), | ||
740 | 363 | dict(name='SELECTIVE_2', status=self.SELECTIVE, | ||
741 | 364 | description=None, | ||
742 | 365 | status_text=self.Switch.STATUS_LABELS[self.SELECTIVE], | ||
743 | 366 | conditions=['IP Address(ip_address=127.0.0.1)']), | ||
744 | 367 | dict(name='GLOBAL', status=self.GLOBAL, | ||
745 | 368 | description=None, | ||
746 | 369 | status_text=self.Switch.STATUS_LABELS[self.GLOBAL], | ||
747 | 370 | conditions=[]), | ||
748 | 371 | dict(name='INHERIT', status=self.INHERIT, | ||
749 | 372 | description=None, | ||
750 | 373 | status_text=self.Switch.STATUS_LABELS[self.INHERIT], | ||
751 | 374 | conditions=[]), | ||
752 | 320 | ] | 375 | ] |
754 | 321 | #self.assertEqual(gather_gargoyle(), expected) | 376 | self.assertEqual(actual, expected) |
755 | 377 | |||
756 | 378 | @patch('gargoyle.models.Switch.objects.all') | ||
757 | 379 | def test_gather_switches(self, mock_all): | ||
758 | 380 | mock_all.return_value = self.get_switches() | ||
759 | 381 | self.assert_switches_dict(gather_gargoyle()) | ||
760 | 382 | |||
761 | 383 | @patch('gargoyle.models.Switch.objects.all') | ||
762 | 384 | def test_gargoyle_template(self, mock_all): | ||
763 | 385 | switches = self.get_switches() | ||
764 | 386 | mock_all.return_value = switches | ||
765 | 387 | the_switches = gather_switches() | ||
766 | 388 | context = { | ||
767 | 389 | "switches": the_switches, | ||
768 | 390 | "switches_json": json.dumps(the_switches), | ||
769 | 391 | "preflight_base_template": BASE_TEMPLATE, | ||
770 | 392 | "preflight_table_class": TABLE_CLASS, | ||
771 | 393 | } | ||
772 | 394 | response = render_to_string('preflight/overview.html', context) | ||
773 | 395 | dom = PyQuery(response) | ||
774 | 396 | table = dom.find('#switches-table tbody') | ||
775 | 397 | self.assertEqual(table.find('tr')[0][0].text, 'gargoyle') | ||
776 | 398 | |||
777 | 399 | for row, switch in zip(table.find('tr.switch'), switches): | ||
778 | 400 | self.assertEqual(row[0].text, switch.key) | ||
779 | 401 | self.assertEqual(row[1].text, str(switch.description)) | ||
780 | 402 | self.assertEqual(row[3].text, switch.get_status_label()) | ||
781 | 403 | |||
782 | 404 | data = json.loads(dom.find('#switches-json').text()) | ||
783 | 405 | self.assertTrue('gargoyle' in data) | ||
784 | 406 | json_switches = data['gargoyle'] | ||
785 | 407 | self.assert_switches_dict(json_switches) | ||
786 | 322 | 408 | ||
787 | === modified file 'preflight/views.py' | |||
788 | --- preflight/views.py 2012-05-18 13:13:41 +0000 | |||
789 | +++ preflight/views.py 2013-05-31 15:53:26 +0000 | |||
790 | @@ -2,10 +2,10 @@ | |||
791 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
792 | 3 | 3 | ||
793 | 4 | from datetime import datetime | 4 | from datetime import datetime |
794 | 5 | import json | ||
795 | 5 | 6 | ||
796 | 6 | from django.views.decorators.cache import never_cache | 7 | from django.views.decorators.cache import never_cache |
797 | 7 | from django.http import Http404 | 8 | from django.http import Http404 |
798 | 8 | from django.conf import settings | ||
799 | 9 | from django.shortcuts import render_to_response | 9 | from django.shortcuts import render_to_response |
800 | 10 | from django.template import RequestContext | 10 | from django.template import RequestContext |
801 | 11 | 11 | ||
802 | @@ -14,8 +14,9 @@ | |||
803 | 14 | gather_checks, | 14 | gather_checks, |
804 | 15 | gather_settings, | 15 | gather_settings, |
805 | 16 | gather_versions, | 16 | gather_versions, |
807 | 17 | gather_gargoyle, | 17 | gather_switches, |
808 | 18 | ) | 18 | ) |
809 | 19 | from .conf import BASE_TEMPLATE, TABLE_CLASS | ||
810 | 19 | 20 | ||
811 | 20 | 21 | ||
812 | 21 | @never_cache | 22 | @never_cache |
813 | @@ -23,17 +24,15 @@ | |||
814 | 23 | if not authenticate(request): | 24 | if not authenticate(request): |
815 | 24 | raise Http404 | 25 | raise Http404 |
816 | 25 | 26 | ||
821 | 26 | base_template = getattr(settings, 'PREFLIGHT_BASE_TEMPLATE', | 27 | switches = gather_switches() |
818 | 27 | "index.1col.html") | ||
819 | 28 | table_class = getattr(settings, 'PREFLIGHT_TABLE_CLASS', "listing") | ||
820 | 29 | |||
822 | 30 | context = RequestContext(request, { | 28 | context = RequestContext(request, { |
823 | 31 | "applications": gather_checks(), | 29 | "applications": gather_checks(), |
824 | 32 | "versions": gather_versions(), | 30 | "versions": gather_versions(), |
825 | 33 | "settings": gather_settings(), | 31 | "settings": gather_settings(), |
827 | 34 | "gargoyle": gather_gargoyle(), | 32 | "switches": switches, |
828 | 33 | "switches_json": json.dumps(switches), | ||
829 | 35 | "now": datetime.now(), | 34 | "now": datetime.now(), |
832 | 36 | "preflight_base_template": base_template, | 35 | "preflight_base_template": BASE_TEMPLATE, |
833 | 37 | 'preflight_table_class': table_class, | 36 | "preflight_table_class": TABLE_CLASS, |
834 | 38 | }) | 37 | }) |
835 | 39 | return render_to_response("preflight/overview.html", context) | 38 | return render_to_response("preflight/overview.html", context) |
836 | 40 | 39 | ||
837 | === modified file 'setup.py' | |||
838 | --- setup.py 2011-02-11 13:06:42 +0000 | |||
839 | +++ setup.py 2013-05-31 15:53:26 +0000 | |||
840 | @@ -1,6 +1,8 @@ | |||
841 | 1 | # -*- encoding: utf-8 -*- | 1 | # -*- encoding: utf-8 -*- |
842 | 2 | # Copyright 2010 Canonical Ltd. This software is licensed under the | 2 | # Copyright 2010 Canonical Ltd. This software is licensed under the |
843 | 3 | # GNU Affero General Public License version 3 (see the file LICENSE). | 3 | # GNU Affero General Public License version 3 (see the file LICENSE). |
844 | 4 | import sys | ||
845 | 5 | |||
846 | 4 | try: | 6 | try: |
847 | 5 | from ast import PyCF_ONLY_AST | 7 | from ast import PyCF_ONLY_AST |
848 | 6 | except ImportError: | 8 | except ImportError: |
849 | @@ -14,24 +16,31 @@ | |||
850 | 14 | for line in open('preflight/__init__.py') | 16 | for line in open('preflight/__init__.py') |
851 | 15 | if line.startswith('__version__')][0] | 17 | if line.startswith('__version__')][0] |
852 | 16 | 18 | ||
853 | 19 | tests_require = [ | ||
854 | 20 | 'mock > 0.6', | ||
855 | 21 | 'gargoyle >= 0.6.0', | ||
856 | 22 | 'pyquery', | ||
857 | 23 | ] | ||
858 | 24 | |||
859 | 25 | if sys.version_info[:2] < (2, 7): | ||
860 | 26 | tests_require.append('unittest2') | ||
861 | 17 | 27 | ||
862 | 18 | setup( | 28 | setup( |
863 | 19 | name='django-preflight', | 29 | name='django-preflight', |
864 | 20 | version=get_version(), | 30 | version=get_version(), |
866 | 21 | author='Łukasz Czyżykowski', | 31 | author='Lukasz Czyzykowski', |
867 | 22 | author_email='lukasz.czyzykowski@canonical.com', | 32 | author_email='lukasz.czyzykowski@canonical.com', |
868 | 23 | description="Create a page for making sure all settings are correct.", | 33 | description="Create a page for making sure all settings are correct.", |
869 | 24 | long_description=open('README').read(), | 34 | long_description=open('README').read(), |
870 | 25 | url='https://launchpad.net/django-preflight', | 35 | url='https://launchpad.net/django-preflight', |
871 | 26 | download_url='https://launchpad.net/django-preflight/+download', | 36 | download_url='https://launchpad.net/django-preflight/+download', |
872 | 27 | classifiers=[ | 37 | classifiers=[ |
874 | 28 | "Development Status :: 4 - Beta", | 38 | "Development Status :: 5 - Production/Stable", |
875 | 29 | "Environment :: Web Environment", | 39 | "Environment :: Web Environment", |
876 | 30 | "Framework :: Django", | 40 | "Framework :: Django", |
877 | 31 | "Intended Audience :: Developers", | 41 | "Intended Audience :: Developers", |
878 | 32 | "License :: OSI Approved :: GNU Affero General Public License v3", | 42 | "License :: OSI Approved :: GNU Affero General Public License v3", |
879 | 33 | "Programming Language :: Python", | 43 | "Programming Language :: Python", |
880 | 34 | "Programming Language :: Python :: 2.5", | ||
881 | 35 | "Programming Language :: Python :: 2.6", | 44 | "Programming Language :: Python :: 2.6", |
882 | 36 | "Programming Language :: Python :: 2.7", | 45 | "Programming Language :: Python :: 2.7", |
883 | 37 | "Topic :: Internet :: WWW/HTTP :: Site Management", | 46 | "Topic :: Internet :: WWW/HTTP :: Site Management", |
884 | @@ -44,19 +53,14 @@ | |||
885 | 44 | 'preflight.management.commands', | 53 | 'preflight.management.commands', |
886 | 45 | ), | 54 | ), |
887 | 46 | package_data={ | 55 | package_data={ |
891 | 47 | 'preflight': [ | 56 | 'preflight': ['templates/preflight/*.html'], |
889 | 48 | 'templates/preflight/*', | ||
890 | 49 | ], | ||
892 | 50 | }, | 57 | }, |
893 | 51 | zip_safe=False, | ||
894 | 52 | install_requires=[ | 58 | install_requires=[ |
900 | 53 | 'django >= 1.0' | 59 | 'django >= 1.1', |
901 | 54 | ], | 60 | ], |
902 | 55 | tests_require=[ | 61 | tests_require=tests_require, |
898 | 56 | 'mock > 0.6' | ||
899 | 57 | ], | ||
903 | 58 | extras_require={ | 62 | extras_require={ |
904 | 59 | 'docs': ['Sphinx'], | 63 | 'docs': ['Sphinx'], |
905 | 60 | }, | 64 | }, |
907 | 61 | test_suite='example_project.run.tests', | 65 | test_suite='preflight_example_project.run.tests', |
908 | 62 | ) | 66 | ) |
909 | 63 | 67 | ||
910 | === removed file 'tox' | |||
911 | --- tox 2011-02-10 12:43:01 +0000 | |||
912 | +++ tox 1970-01-01 00:00:00 +0000 | |||
913 | @@ -1,6 +0,0 @@ | |||
914 | 1 | #!/usr/bin/env python | ||
915 | 2 | import urllib | ||
916 | 3 | url = "https://pytox.googlecode.com/hg/toxbootstrap.py" | ||
917 | 4 | d = dict(__file__='toxbootstrap.py') | ||
918 | 5 | exec urllib.urlopen(url).read() in d | ||
919 | 6 | d['cmdline'](['--recreate']) | ||
920 | 7 | \ No newline at end of file | 0 | \ No newline at end of file |
921 | 8 | 1 | ||
922 | === modified file 'tox.ini' | |||
923 | --- tox.ini 2012-05-18 13:13:41 +0000 | |||
924 | +++ tox.ini 2013-05-31 15:53:26 +0000 | |||
925 | @@ -1,8 +1,10 @@ | |||
926 | 1 | [tox] | 1 | [tox] |
931 | 2 | envlist = | 2 | envlist = |
932 | 3 | py2.5-django1.2, py2.5-django1.1, py2.5-django1.4, py2.5-django1.3, | 3 | py2.6-django1.1, py2.7-django1.1, |
933 | 4 | py2.6-django1.2, py2.6-django1.1, py2.6-django1.4, py2.6-django1.3, | 4 | py2.6-django1.2, py2.7-django1.2, |
934 | 5 | py2.7-django1.2, py2.7-django1.1, py2.7-django1.4, py2.7-django1.3, | 5 | py2.6-django1.3, py2.7-django1.3, |
935 | 6 | py2.6-django1.4, py2.7-django1.4, | ||
936 | 7 | py2.6-django1.5, py2.7-django1.5, | ||
937 | 6 | docs | 8 | docs |
938 | 7 | 9 | ||
939 | 8 | [testenv] | 10 | [testenv] |
940 | @@ -16,54 +18,44 @@ | |||
941 | 16 | sphinx-build -b doctest -d {envtmpdir}/doctrees . {envtmpdir}/doctest | 18 | sphinx-build -b doctest -d {envtmpdir}/doctrees . {envtmpdir}/doctest |
942 | 17 | sphinx-build -W -b html -d {envtmpdir}/doctrees . {envtmpdir}/html | 19 | sphinx-build -W -b html -d {envtmpdir}/doctrees . {envtmpdir}/html |
943 | 18 | 20 | ||
944 | 19 | # Python 2.5 | ||
945 | 20 | [testenv:py2.5-django1.2] | ||
946 | 21 | basepython = python2.5 | ||
947 | 22 | deps = django >= 1.2, < 1.3 | ||
948 | 23 | |||
949 | 24 | [testenv:py2.5-django1.1] | ||
950 | 25 | basepython = python2.5 | ||
951 | 26 | deps = django >= 1.1, < 1.2 | ||
952 | 27 | |||
953 | 28 | [testenv:py2.5-django1.4] | ||
954 | 29 | basetpython = python2.5 | ||
955 | 30 | deps = django >= 1.4, < 1.1 | ||
956 | 31 | |||
957 | 32 | [testenv:py2.5-django1.3] | ||
958 | 33 | basepython = python2.5 | ||
959 | 34 | deps = django >= 1.3, < 1.4 | ||
960 | 35 | |||
961 | 36 | # Python 2.6 | 21 | # Python 2.6 |
962 | 22 | [testenv:py2.6-django1.1] | ||
963 | 23 | basepython = python2.6 | ||
964 | 24 | deps = django >= 1.1, < 1.2 | ||
965 | 25 | |||
966 | 37 | [testenv:py2.6-django1.2] | 26 | [testenv:py2.6-django1.2] |
967 | 38 | basepython = python2.6 | 27 | basepython = python2.6 |
968 | 39 | deps = django >= 1.2, < 1.3 | 28 | deps = django >= 1.2, < 1.3 |
969 | 40 | 29 | ||
971 | 41 | [testenv:py2.6-django1.1] | 30 | [testenv:py2.6-django1.3] |
972 | 42 | basepython = python2.6 | 31 | basepython = python2.6 |
974 | 43 | deps = django >= 1.1, < 1.2 | 32 | deps = django >= 1.3, < 1.4 |
975 | 44 | 33 | ||
976 | 45 | [testenv:py2.6-django1.4] | 34 | [testenv:py2.6-django1.4] |
979 | 46 | basetpython = python2.6 | 35 | basepython = python2.6 |
980 | 47 | deps = django >= 1.4, < 1.1 | 36 | deps = django >= 1.4, < 1.5 |
981 | 48 | 37 | ||
983 | 49 | [testenv:py2.6-django1.3] | 38 | [testenv:py2.6-django1.5] |
984 | 50 | basepython = python2.6 | 39 | basepython = python2.6 |
986 | 51 | deps = django >= 1.3, < 1.4 | 40 | deps = django >= 1.5, < 1.6 |
987 | 52 | 41 | ||
988 | 53 | # Python 2.7 | 42 | # Python 2.7 |
989 | 43 | [testenv:py2.7-django1.1] | ||
990 | 44 | basepython = python2.7 | ||
991 | 45 | deps = django >= 1.1, < 1.2 | ||
992 | 46 | |||
993 | 54 | [testenv:py2.7-django1.2] | 47 | [testenv:py2.7-django1.2] |
994 | 55 | basepython = python2.7 | 48 | basepython = python2.7 |
995 | 56 | deps = django >= 1.2, < 1.3 | 49 | deps = django >= 1.2, < 1.3 |
996 | 57 | 50 | ||
998 | 58 | [testenv:py2.7-django1.1] | 51 | [testenv:py2.7-django1.3] |
999 | 59 | basepython = python2.7 | 52 | basepython = python2.7 |
1001 | 60 | deps = django >= 1.1, < 1.2 | 53 | deps = django >= 1.3, < 1.4 |
1002 | 61 | 54 | ||
1003 | 62 | [testenv:py2.7-django1.4] | 55 | [testenv:py2.7-django1.4] |
1011 | 63 | basetpython = python2.7 | 56 | basepython = python2.7 |
1012 | 64 | deps = django >= 1.4, < 1.1 | 57 | deps = django >= 1.4, < 1.5 |
1013 | 65 | 58 | ||
1014 | 66 | [testenv:py2.7-django1.3] | 59 | [testenv:py2.7-django1.5] |
1015 | 67 | basepython = python2.7 | 60 | basepython = python2.7 |
1016 | 68 | deps = django >= 1.3, < 1.4 | 61 | deps = django >= 1.5, < 1.6 |
1010 | 69 |