Merge lp:~ricardokirkner/django-configglue/tox into lp:django-configglue
- tox
- Merge into trunk
Proposed by
Ricardo Kirkner
Status: | Merged |
---|---|
Approved by: | Ricardo Kirkner |
Approved revision: | 59 |
Merged at revision: | 43 |
Proposed branch: | lp:~ricardokirkner/django-configglue/tox |
Merge into: | lp:django-configglue |
Diff against target: |
1016 lines (+674/-72) 13 files modified
django_configglue/__init__.py (+2/-1) django_configglue/management/commands/settings.py (+1/-1) django_configglue/schema.py (+512/-18) django_configglue/tests/helpers.py (+30/-13) django_configglue/tests/settings.py (+5/-2) django_configglue/tests/test_configglue.py (+42/-20) django_configglue/tests/test_settings.py (+13/-11) django_configglue/utils.py (+1/-0) testproject/main-12.cfg (+12/-0) testproject/main.cfg (+0/-1) testproject/testrunner.py (+3/-5) tox (+6/-0) tox.ini (+47/-0) |
To merge this branch: | bzr merge lp:~ricardokirkner/django-configglue/tox |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Foord (community) | Approve | ||
Review via email: mp+57378@code.launchpad.net |
Commit message
use tox to test all major django versions
Description of the change
This branch adds support for testing django_configglue against all major django versions using tox.
Existing tests have now been made to run against versions
- 1.0.2 final
- 1.0.4
- 1.1.2
- 1.1.4
- 1.2.5
- 1.3
using python 2.6.
Adding more tests and testing against other versions of Python is left for future work.
How to test
===========
Simply run
./tox
To post a comment you must log in.
Revision history for this message
Łukasz Czyżykowski (lukasz-czyzykowski) wrote : | # |
Revision history for this message
Michael Foord (mfoord) wrote : | # |
We need a better solution than deepcopying, but it is a hard problem. Other than that great.
review:
Approve
- 58. By Ricardo Kirkner
-
fixed small style issue per review
- 59. By Ricardo Kirkner
-
fixed style issues per review
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'django_configglue/__init__.py' | |||
2 | --- django_configglue/__init__.py 2011-01-10 21:43:27 +0000 | |||
3 | +++ django_configglue/__init__.py 2011-04-13 17:14:29 +0000 | |||
4 | @@ -42,7 +42,8 @@ | |||
5 | 42 | options, args = parser.parse_args(self.argv) | 42 | options, args = parser.parse_args(self.argv) |
6 | 43 | handle_default_options(options) | 43 | handle_default_options(options) |
7 | 44 | except: | 44 | except: |
9 | 45 | pass # Ignore any option errors at this point. | 45 | # Ignore any option errors at this point. |
10 | 46 | args = self.argv | ||
11 | 46 | 47 | ||
12 | 47 | try: | 48 | try: |
13 | 48 | subcommand = self.argv[1] | 49 | subcommand = self.argv[1] |
14 | 49 | 50 | ||
15 | === modified file 'django_configglue/management/commands/settings.py' | |||
16 | --- django_configglue/management/commands/settings.py 2011-01-10 21:43:27 +0000 | |||
17 | +++ django_configglue/management/commands/settings.py 2011-04-13 17:14:29 +0000 | |||
18 | @@ -106,7 +106,7 @@ | |||
19 | 106 | else: | 106 | else: |
20 | 107 | # looking in django settings | 107 | # looking in django settings |
21 | 108 | for key in map(str.upper, keys): | 108 | for key in map(str.upper, keys): |
23 | 109 | if key in settings.get_all_members(): | 109 | if key in dir(settings): |
24 | 110 | msg = "setting %s last defined in %r" | 110 | msg = "setting %s last defined in %r" |
25 | 111 | output.append(msg % (key, os.path.realpath(location))) | 111 | output.append(msg % (key, os.path.realpath(location))) |
26 | 112 | else: | 112 | else: |
27 | 113 | 113 | ||
28 | === modified file 'django_configglue/schema.py' | |||
29 | --- django_configglue/schema.py 2011-02-19 23:14:11 +0000 | |||
30 | +++ django_configglue/schema.py 2011-04-13 17:14:29 +0000 | |||
31 | @@ -1,6 +1,7 @@ | |||
32 | 1 | # Copyright 2010 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2010 Canonical Ltd. This software is licensed under the |
33 | 2 | # GNU Lesser General Public License version 3 (see the file LICENSE). | 2 | # GNU Lesser General Public License version 3 (see the file LICENSE). |
34 | 3 | import logging | 3 | import logging |
35 | 4 | from copy import deepcopy | ||
36 | 4 | 5 | ||
37 | 5 | from configglue.pyschema.schema import ( | 6 | from configglue.pyschema.schema import ( |
38 | 6 | BoolConfigOption, | 7 | BoolConfigOption, |
39 | @@ -21,8 +22,20 @@ | |||
40 | 21 | gettext_noop = lambda s: s | 22 | gettext_noop = lambda s: s |
41 | 22 | 23 | ||
42 | 23 | 24 | ||
43 | 25 | class UpperCaseDictConfigOption(DictConfigOption): | ||
44 | 26 | """ A DictConfigOption with all upper-case keys. """ | ||
45 | 27 | def parse(self, section, parser=None, raw=False): | ||
46 | 28 | parsed = super(UpperCaseDictConfigOption, self).parse( | ||
47 | 29 | section, parser, raw) | ||
48 | 30 | result = {} | ||
49 | 31 | for k, v in parsed.items(): | ||
50 | 32 | result[k.upper()] = v | ||
51 | 33 | return result | ||
52 | 34 | |||
53 | 24 | 35 | ||
54 | 25 | class BaseDjangoSchema(Schema): | 36 | class BaseDjangoSchema(Schema): |
55 | 37 | version = '1.0.2 final' | ||
56 | 38 | |||
57 | 26 | # Sections | 39 | # Sections |
58 | 27 | django = ConfigSection('django') | 40 | django = ConfigSection('django') |
59 | 28 | 41 | ||
60 | @@ -256,6 +269,9 @@ | |||
61 | 256 | "secret-key hashing algorithms. Set this in your settings, or " | 269 | "secret-key hashing algorithms. Set this in your settings, or " |
62 | 257 | "Django will complain loudly") | 270 | "Django will complain loudly") |
63 | 258 | 271 | ||
64 | 272 | django.jing_path = StringConfigOption(default='/usr/bin/jing', | ||
65 | 273 | help="Path to the 'jing' executable -- needed to validate XMLFields") | ||
66 | 274 | |||
67 | 259 | django.default_file_storage = StringConfigOption( | 275 | django.default_file_storage = StringConfigOption( |
68 | 260 | default='django.core.files.storage.FileSystemStorage', | 276 | default='django.core.files.storage.FileSystemStorage', |
69 | 261 | help="Default file storage mechanism that holds media") | 277 | help="Default file storage mechanism that holds media") |
70 | @@ -452,23 +468,500 @@ | |||
71 | 452 | django.root_urlconf = StringConfigOption(default='urls') | 468 | django.root_urlconf = StringConfigOption(default='urls') |
72 | 453 | 469 | ||
73 | 454 | 470 | ||
74 | 455 | class Django102Schema(BaseDjangoSchema): | ||
75 | 456 | version = '1.0.2' | ||
76 | 457 | |||
77 | 458 | def __init__(self, *args, **kwargs): | ||
78 | 459 | super(Django102Schema, self).__init__(*args, **kwargs) | ||
79 | 460 | |||
80 | 461 | ################ | ||
81 | 462 | # CORE # | ||
82 | 463 | ################ | ||
83 | 464 | |||
84 | 465 | self.django.jing_path = StringConfigOption(default='/usr/bin/jing', | ||
85 | 466 | help="Path to the 'jing' executable -- needed to validate XMLFields") | ||
86 | 467 | |||
87 | 468 | |||
88 | 469 | class Django112Schema(BaseDjangoSchema): | 471 | class Django112Schema(BaseDjangoSchema): |
89 | 470 | version = '1.1.2' | 472 | version = '1.1.2' |
90 | 471 | 473 | ||
91 | 474 | # sections | ||
92 | 475 | django = deepcopy(BaseDjangoSchema.django) | ||
93 | 476 | |||
94 | 477 | ################ | ||
95 | 478 | # CORE # | ||
96 | 479 | ################ | ||
97 | 480 | |||
98 | 481 | # update default value | ||
99 | 482 | django.languages.default = ( | ||
100 | 483 | ('ar', gettext_noop('Arabic')), | ||
101 | 484 | ('bg', gettext_noop('Bulgarian')), | ||
102 | 485 | ('bn', gettext_noop('Bengali')), | ||
103 | 486 | ('bs', gettext_noop('Bosnian')), | ||
104 | 487 | ('ca', gettext_noop('Catalan')), | ||
105 | 488 | ('cs', gettext_noop('Czech')), | ||
106 | 489 | ('cy', gettext_noop('Welsh')), | ||
107 | 490 | ('da', gettext_noop('Danish')), | ||
108 | 491 | ('de', gettext_noop('German')), | ||
109 | 492 | ('el', gettext_noop('Greek')), | ||
110 | 493 | ('en', gettext_noop('English')), | ||
111 | 494 | ('es', gettext_noop('Spanish')), | ||
112 | 495 | ('es-ar', gettext_noop('Argentinean Spanish')), | ||
113 | 496 | ('et', gettext_noop('Estonian')), | ||
114 | 497 | ('eu', gettext_noop('Basque')), | ||
115 | 498 | ('fa', gettext_noop('Persian')), | ||
116 | 499 | ('fi', gettext_noop('Finnish')), | ||
117 | 500 | ('fr', gettext_noop('French')), | ||
118 | 501 | ('fy-nl', gettext_noop('Frisian')), | ||
119 | 502 | ('ga', gettext_noop('Irish')), | ||
120 | 503 | ('gl', gettext_noop('Galician')), | ||
121 | 504 | ('he', gettext_noop('Hebrew')), | ||
122 | 505 | ('hi', gettext_noop('Hindi')), | ||
123 | 506 | ('hr', gettext_noop('Croatian')), | ||
124 | 507 | ('hu', gettext_noop('Hungarian')), | ||
125 | 508 | ('is', gettext_noop('Icelandic')), | ||
126 | 509 | ('it', gettext_noop('Italian')), | ||
127 | 510 | ('ja', gettext_noop('Japanese')), | ||
128 | 511 | ('ka', gettext_noop('Georgian')), | ||
129 | 512 | ('km', gettext_noop('Khmer')), | ||
130 | 513 | ('kn', gettext_noop('Kannada')), | ||
131 | 514 | ('ko', gettext_noop('Korean')), | ||
132 | 515 | ('lt', gettext_noop('Lithuanian')), | ||
133 | 516 | ('lv', gettext_noop('Latvian')), | ||
134 | 517 | ('mk', gettext_noop('Macedonian')), | ||
135 | 518 | ('nl', gettext_noop('Dutch')), | ||
136 | 519 | ('no', gettext_noop('Norwegian')), | ||
137 | 520 | ('pl', gettext_noop('Polish')), | ||
138 | 521 | ('pt', gettext_noop('Portuguese')), | ||
139 | 522 | ('pt-br', gettext_noop('Brazilian Portuguese')), | ||
140 | 523 | ('ro', gettext_noop('Romanian')), | ||
141 | 524 | ('ru', gettext_noop('Russian')), | ||
142 | 525 | ('sk', gettext_noop('Slovak')), | ||
143 | 526 | ('sl', gettext_noop('Slovenian')), | ||
144 | 527 | ('sq', gettext_noop('Albanian')), | ||
145 | 528 | ('sr', gettext_noop('Serbian')), | ||
146 | 529 | ('sr-latn', gettext_noop('Serbian Latin')), | ||
147 | 530 | ('sv', gettext_noop('Swedish')), | ||
148 | 531 | ('ta', gettext_noop('Tamil')), | ||
149 | 532 | ('te', gettext_noop('Telugu')), | ||
150 | 533 | ('th', gettext_noop('Thai')), | ||
151 | 534 | ('tr', gettext_noop('Turkish')), | ||
152 | 535 | ('uk', gettext_noop('Ukrainian')), | ||
153 | 536 | ('zh-cn', gettext_noop('Simplified Chinese')), | ||
154 | 537 | ('zh-tw', gettext_noop('Traditional Chinese')), | ||
155 | 538 | ) | ||
156 | 539 | |||
157 | 540 | |||
158 | 541 | class Django125Schema(Django112Schema): | ||
159 | 542 | version = '1.2.5' | ||
160 | 543 | |||
161 | 544 | # sections | ||
162 | 545 | django = deepcopy(Django112Schema.django) | ||
163 | 546 | |||
164 | 547 | ################ | ||
165 | 548 | # CORE # | ||
166 | 549 | ################ | ||
167 | 550 | |||
168 | 551 | # update default value | ||
169 | 552 | django.languages.default = [ | ||
170 | 553 | ('ar', gettext_noop('Arabic')), | ||
171 | 554 | ('bg', gettext_noop('Bulgarian')), | ||
172 | 555 | ('bn', gettext_noop('Bengali')), | ||
173 | 556 | ('bs', gettext_noop('Bosnian')), | ||
174 | 557 | ('ca', gettext_noop('Catalan')), | ||
175 | 558 | ('cs', gettext_noop('Czech')), | ||
176 | 559 | ('cy', gettext_noop('Welsh')), | ||
177 | 560 | ('da', gettext_noop('Danish')), | ||
178 | 561 | ('de', gettext_noop('German')), | ||
179 | 562 | ('el', gettext_noop('Greek')), | ||
180 | 563 | ('en', gettext_noop('English')), | ||
181 | 564 | ('en-gb', gettext_noop('British English')), | ||
182 | 565 | ('es', gettext_noop('Spanish')), | ||
183 | 566 | ('es-ar', gettext_noop('Argentinian Spanish')), | ||
184 | 567 | ('et', gettext_noop('Estonian')), | ||
185 | 568 | ('eu', gettext_noop('Basque')), | ||
186 | 569 | ('fa', gettext_noop('Persian')), | ||
187 | 570 | ('fi', gettext_noop('Finnish')), | ||
188 | 571 | ('fr', gettext_noop('French')), | ||
189 | 572 | ('fy-nl', gettext_noop('Frisian')), | ||
190 | 573 | ('ga', gettext_noop('Irish')), | ||
191 | 574 | ('gl', gettext_noop('Galician')), | ||
192 | 575 | ('he', gettext_noop('Hebrew')), | ||
193 | 576 | ('hi', gettext_noop('Hindi')), | ||
194 | 577 | ('hr', gettext_noop('Croatian')), | ||
195 | 578 | ('hu', gettext_noop('Hungarian')), | ||
196 | 579 | ('id', gettext_noop('Indonesian')), | ||
197 | 580 | ('is', gettext_noop('Icelandic')), | ||
198 | 581 | ('it', gettext_noop('Italian')), | ||
199 | 582 | ('ja', gettext_noop('Japanese')), | ||
200 | 583 | ('ka', gettext_noop('Georgian')), | ||
201 | 584 | ('km', gettext_noop('Khmer')), | ||
202 | 585 | ('kn', gettext_noop('Kannada')), | ||
203 | 586 | ('ko', gettext_noop('Korean')), | ||
204 | 587 | ('lt', gettext_noop('Lithuanian')), | ||
205 | 588 | ('lv', gettext_noop('Latvian')), | ||
206 | 589 | ('mk', gettext_noop('Macedonian')), | ||
207 | 590 | ('ml', gettext_noop('Malayalam')), | ||
208 | 591 | ('mn', gettext_noop('Mongolian')), | ||
209 | 592 | ('nl', gettext_noop('Dutch')), | ||
210 | 593 | ('no', gettext_noop('Norwegian')), | ||
211 | 594 | ('nb', gettext_noop('Norwegian Bokmal')), | ||
212 | 595 | ('nn', gettext_noop('Norwegian Nynorsk')), | ||
213 | 596 | ('pl', gettext_noop('Polish')), | ||
214 | 597 | ('pt', gettext_noop('Portuguese')), | ||
215 | 598 | ('pt-br', gettext_noop('Brazilian Portuguese')), | ||
216 | 599 | ('ro', gettext_noop('Romanian')), | ||
217 | 600 | ('ru', gettext_noop('Russian')), | ||
218 | 601 | ('sk', gettext_noop('Slovak')), | ||
219 | 602 | ('sl', gettext_noop('Slovenian')), | ||
220 | 603 | ('sq', gettext_noop('Albanian')), | ||
221 | 604 | ('sr', gettext_noop('Serbian')), | ||
222 | 605 | ('sr-latn', gettext_noop('Serbian Latin')), | ||
223 | 606 | ('sv', gettext_noop('Swedish')), | ||
224 | 607 | ('ta', gettext_noop('Tamil')), | ||
225 | 608 | ('te', gettext_noop('Telugu')), | ||
226 | 609 | ('th', gettext_noop('Thai')), | ||
227 | 610 | ('tr', gettext_noop('Turkish')), | ||
228 | 611 | ('uk', gettext_noop('Ukrainian')), | ||
229 | 612 | ('vi', gettext_noop('Vietnamese')), | ||
230 | 613 | ('zh-cn', gettext_noop('Simplified Chinese')), | ||
231 | 614 | ('zh-tw', gettext_noop('Traditional Chinese')), | ||
232 | 615 | ] | ||
233 | 616 | |||
234 | 617 | django.use_l10n = BoolConfigOption( | ||
235 | 618 | default=True, | ||
236 | 619 | help="If you set this to False, Django will not format dates, " | ||
237 | 620 | "numbers and calendars according to the current locale") | ||
238 | 621 | |||
239 | 622 | django.databases = DictConfigOption( | ||
240 | 623 | item=UpperCaseDictConfigOption(spec={ | ||
241 | 624 | 'engine': StringConfigOption(default='django.db.backends.'), | ||
242 | 625 | 'name': StringConfigOption(), | ||
243 | 626 | 'user': StringConfigOption(), | ||
244 | 627 | 'password': StringConfigOption(), | ||
245 | 628 | 'host': StringConfigOption(), | ||
246 | 629 | 'port': StringConfigOption(), | ||
247 | 630 | }), | ||
248 | 631 | default={ | ||
249 | 632 | 'default': { | ||
250 | 633 | 'engine': 'django.db.backends.', | ||
251 | 634 | 'name': '', | ||
252 | 635 | 'user': '', | ||
253 | 636 | 'password': '', | ||
254 | 637 | 'host': '', | ||
255 | 638 | 'port': '', | ||
256 | 639 | } | ||
257 | 640 | }) | ||
258 | 641 | django.database_routers = LinesConfigOption( | ||
259 | 642 | item=StringConfigOption(), | ||
260 | 643 | help="Classes used to implement db routing behaviour") | ||
261 | 644 | |||
262 | 645 | django.email_backend = StringConfigOption( | ||
263 | 646 | default='django.core.mail.backends.smtp.EmailBackend', | ||
264 | 647 | help="The email backend to use. For possible shortcuts see " | ||
265 | 648 | "django.core.mail. The default is to use the SMTP backend. " | ||
266 | 649 | "Third party backends can be specified by providing a Python " | ||
267 | 650 | "path to a module that defines an EmailBackend class.") | ||
268 | 651 | |||
269 | 652 | django.installed_apps.default = [ | ||
270 | 653 | 'django.contrib.auth', | ||
271 | 654 | 'django.contrib.contenttypes', | ||
272 | 655 | 'django.contrib.sessions', | ||
273 | 656 | 'django.contrib.sites', | ||
274 | 657 | 'django.contrib.messages', | ||
275 | 658 | ] | ||
276 | 659 | |||
277 | 660 | django.template_loaders.default = [ | ||
278 | 661 | 'django.template.loaders.filesystem.Loader', | ||
279 | 662 | 'django.template.loaders.app_directories.Loader', | ||
280 | 663 | ] | ||
281 | 664 | |||
282 | 665 | django.template_context_processors.default = [ | ||
283 | 666 | 'django.contrib.auth.context_processors.auth', | ||
284 | 667 | 'django.core.context_processors.debug', | ||
285 | 668 | 'django.core.context_processors.i18n', | ||
286 | 669 | 'django.core.context_processors.media', | ||
287 | 670 | 'django.contrib.messages.context_processors.messages', | ||
288 | 671 | ] | ||
289 | 672 | |||
290 | 673 | django.format_module_path = StringConfigOption( | ||
291 | 674 | null=True, default=None, | ||
292 | 675 | help="Python module path where user will place custom format " | ||
293 | 676 | "definition. The directory where this setting is pointing " | ||
294 | 677 | "should contain subdirectories named as the locales, " | ||
295 | 678 | "containing a formats.py file") | ||
296 | 679 | django.short_date_format = StringConfigOption( | ||
297 | 680 | default='m/d/Y', | ||
298 | 681 | help="Default short formatting for date objects") | ||
299 | 682 | django.short_datetime_format = StringConfigOption( | ||
300 | 683 | default='m/d/Y P', | ||
301 | 684 | help="Default short formatting for datetime objects") | ||
302 | 685 | django.date_input_formats = LinesConfigOption( | ||
303 | 686 | item=StringConfigOption(), | ||
304 | 687 | default=[ | ||
305 | 688 | '%%Y-%%m-%%d', '%%m/%%d/%%Y', '%%m/%%d/%%y', # '2006-10-25', '10/25/2006', '10/25/06' | ||
306 | 689 | '%%b %%d %%Y', '%%b %%d, %%Y', # 'Oct 25 2006', 'Oct 25, 2006' | ||
307 | 690 | '%%d %%b %%Y', '%%d %%b, %%Y', # '25 Oct 2006', '25 Oct, 2006' | ||
308 | 691 | '%%B %%d %%Y', '%%B %%d, %%Y', # 'October 25 2006', 'October 25, 2006' | ||
309 | 692 | '%%d %%B %%Y', '%%d %%B, %%Y', # '25 October 2006', '25 October, 2006' | ||
310 | 693 | ], | ||
311 | 694 | help="Default formats to be used when parsing dates from input " | ||
312 | 695 | "boxes, in order") | ||
313 | 696 | django.time_input_formats = LinesConfigOption( | ||
314 | 697 | item=StringConfigOption(), | ||
315 | 698 | default=[ | ||
316 | 699 | '%%H:%%M:%%S', # '14:30:59' | ||
317 | 700 | '%%H:%%M', # '14:30' | ||
318 | 701 | ], | ||
319 | 702 | help="Default formats to be used when parsing times from input " | ||
320 | 703 | "boxes, in order") | ||
321 | 704 | django.datetime_input_formats = LinesConfigOption( | ||
322 | 705 | item=StringConfigOption(), | ||
323 | 706 | default=[ | ||
324 | 707 | '%%Y-%%m-%%d %%H:%%M:%%S', # '2006-10-25 14:30:59' | ||
325 | 708 | '%%Y-%%m-%%d %%H:%%M', # '2006-10-25 14:30' | ||
326 | 709 | '%%Y-%%m-%%d', # '2006-10-25' | ||
327 | 710 | '%%m/%%d/%%Y %%H:%%M:%%S', # '10/25/2006 14:30:59' | ||
328 | 711 | '%%m/%%d/%%Y %%H:%%M', # '10/25/2006 14:30' | ||
329 | 712 | '%%m/%%d/%%Y', # '10/25/2006' | ||
330 | 713 | '%%m/%%d/%%y %%H:%%M:%%S', # '10/25/06 14:30:59' | ||
331 | 714 | '%%m/%%d/%%y %%H:%%M', # '10/25/06 14:30' | ||
332 | 715 | '%%m/%%d/%%y', # '10/25/06' | ||
333 | 716 | ], | ||
334 | 717 | help="Default formats to be used when parsing dates and times " | ||
335 | 718 | "from input boxes, in order") | ||
336 | 719 | |||
337 | 720 | django.first_day_of_week = IntConfigOption( | ||
338 | 721 | default=0, | ||
339 | 722 | help="First day of week, to be used on calendars. 0 means Sunday, " | ||
340 | 723 | "1 means Monday...") | ||
341 | 724 | django.decimal_separator = StringConfigOption( | ||
342 | 725 | default='.', | ||
343 | 726 | help="Decimal separator symbol") | ||
344 | 727 | django.use_thousand_separator = BoolConfigOption( | ||
345 | 728 | default=False, | ||
346 | 729 | help="Boolean that sets whether to add thousand separator when " | ||
347 | 730 | "formatting numbers") | ||
348 | 731 | django.number_grouping = IntConfigOption( | ||
349 | 732 | default=0, | ||
350 | 733 | help="Number of digits that will be together, when splitting them " | ||
351 | 734 | "by THOUSAND_SEPARATOR. 0 means no grouping, 3 means " | ||
352 | 735 | "splitting by thousands...") | ||
353 | 736 | django.thousand_separator = StringConfigOption( | ||
354 | 737 | default=',', | ||
355 | 738 | help="Thousand separator symbol") | ||
356 | 739 | |||
357 | 740 | ############## | ||
358 | 741 | # MIDDLEWARE # | ||
359 | 742 | ############## | ||
360 | 743 | |||
361 | 744 | django.middleware_classes.default = [ | ||
362 | 745 | 'django.middleware.common.CommonMiddleware', | ||
363 | 746 | 'django.contrib.sessions.middleware.SessionMiddleware', | ||
364 | 747 | 'django.middleware.csrf.CsrfViewMiddleware', | ||
365 | 748 | 'django.contrib.auth.middleware.AuthenticationMiddleware', | ||
366 | 749 | 'django.contrib.messages.middleware.MessageMiddleware', | ||
367 | 750 | ] | ||
368 | 751 | |||
369 | 752 | ######## | ||
370 | 753 | # CSRF # | ||
371 | 754 | ######## | ||
372 | 755 | |||
373 | 756 | django.csrf_failure_view = StringConfigOption( | ||
374 | 757 | default='django.views.csrf.csrf_failure', | ||
375 | 758 | help="Dotted path to callable to be used as view when a request " | ||
376 | 759 | "is rejected by the CSRF middleware") | ||
377 | 760 | django.csrf_cookie_name = StringConfigOption( | ||
378 | 761 | default='csrftoken', | ||
379 | 762 | help="Name for CSRF cookie") | ||
380 | 763 | django.csrf_cookie_domain = StringConfigOption( | ||
381 | 764 | null=True, | ||
382 | 765 | help="Domain for CSRF cookie") | ||
383 | 766 | |||
384 | 767 | ############ | ||
385 | 768 | # MESSAGES # | ||
386 | 769 | ############ | ||
387 | 770 | |||
388 | 771 | django.message_storage = StringConfigOption( | ||
389 | 772 | default='django.contrib.messages.storage.user_messages.' | ||
390 | 773 | 'LegacyFallbackStorage', | ||
391 | 774 | help="Class to be used as messages backend") | ||
392 | 775 | |||
393 | 776 | ########### | ||
394 | 777 | # TESTING # | ||
395 | 778 | ########### | ||
396 | 779 | |||
397 | 780 | django.test_runner.default = ( | ||
398 | 781 | 'django.test.simple.DjangoTestSuiteRunner') | ||
399 | 782 | django.test_runner.help = ( | ||
400 | 783 | "The name of the class to use to run the test suite") | ||
401 | 784 | |||
402 | 785 | |||
403 | 786 | class Django13Schema(Django125Schema): | ||
404 | 787 | version = '1.3' | ||
405 | 788 | |||
406 | 789 | # sections | ||
407 | 790 | django = deepcopy(Django125Schema.django) | ||
408 | 791 | |||
409 | 792 | ################ | ||
410 | 793 | # CORE # | ||
411 | 794 | ################ | ||
412 | 795 | |||
413 | 796 | # update default value | ||
414 | 797 | django.languages.default = [ | ||
415 | 798 | ('ar', gettext_noop('Arabic')), | ||
416 | 799 | ('az', gettext_noop('Azerbaijani')), | ||
417 | 800 | ('bg', gettext_noop('Bulgarian')), | ||
418 | 801 | ('bn', gettext_noop('Bengali')), | ||
419 | 802 | ('bs', gettext_noop('Bosnian')), | ||
420 | 803 | ('ca', gettext_noop('Catalan')), | ||
421 | 804 | ('cs', gettext_noop('Czech')), | ||
422 | 805 | ('cy', gettext_noop('Welsh')), | ||
423 | 806 | ('da', gettext_noop('Danish')), | ||
424 | 807 | ('de', gettext_noop('German')), | ||
425 | 808 | ('el', gettext_noop('Greek')), | ||
426 | 809 | ('en', gettext_noop('English')), | ||
427 | 810 | ('en-gb', gettext_noop('British English')), | ||
428 | 811 | ('es', gettext_noop('Spanish')), | ||
429 | 812 | ('es-ar', gettext_noop('Argentinian Spanish')), | ||
430 | 813 | ('es-mx', gettext_noop('Mexican Spanish')), | ||
431 | 814 | ('es-ni', gettext_noop('Nicaraguan Spanish')), | ||
432 | 815 | ('et', gettext_noop('Estonian')), | ||
433 | 816 | ('eu', gettext_noop('Basque')), | ||
434 | 817 | ('fa', gettext_noop('Persian')), | ||
435 | 818 | ('fi', gettext_noop('Finnish')), | ||
436 | 819 | ('fr', gettext_noop('French')), | ||
437 | 820 | ('fy-nl', gettext_noop('Frisian')), | ||
438 | 821 | ('ga', gettext_noop('Irish')), | ||
439 | 822 | ('gl', gettext_noop('Galician')), | ||
440 | 823 | ('he', gettext_noop('Hebrew')), | ||
441 | 824 | ('hi', gettext_noop('Hindi')), | ||
442 | 825 | ('hr', gettext_noop('Croatian')), | ||
443 | 826 | ('hu', gettext_noop('Hungarian')), | ||
444 | 827 | ('id', gettext_noop('Indonesian')), | ||
445 | 828 | ('is', gettext_noop('Icelandic')), | ||
446 | 829 | ('it', gettext_noop('Italian')), | ||
447 | 830 | ('ja', gettext_noop('Japanese')), | ||
448 | 831 | ('ka', gettext_noop('Georgian')), | ||
449 | 832 | ('km', gettext_noop('Khmer')), | ||
450 | 833 | ('kn', gettext_noop('Kannada')), | ||
451 | 834 | ('ko', gettext_noop('Korean')), | ||
452 | 835 | ('lt', gettext_noop('Lithuanian')), | ||
453 | 836 | ('lv', gettext_noop('Latvian')), | ||
454 | 837 | ('mk', gettext_noop('Macedonian')), | ||
455 | 838 | ('ml', gettext_noop('Malayalam')), | ||
456 | 839 | ('mn', gettext_noop('Mongolian')), | ||
457 | 840 | ('nl', gettext_noop('Dutch')), | ||
458 | 841 | ('no', gettext_noop('Norwegian')), | ||
459 | 842 | ('nb', gettext_noop('Norwegian Bokmal')), | ||
460 | 843 | ('nn', gettext_noop('Norwegian Nynorsk')), | ||
461 | 844 | ('pa', gettext_noop('Punjabi')), | ||
462 | 845 | ('pl', gettext_noop('Polish')), | ||
463 | 846 | ('pt', gettext_noop('Portuguese')), | ||
464 | 847 | ('pt-br', gettext_noop('Brazilian Portuguese')), | ||
465 | 848 | ('ro', gettext_noop('Romanian')), | ||
466 | 849 | ('ru', gettext_noop('Russian')), | ||
467 | 850 | ('sk', gettext_noop('Slovak')), | ||
468 | 851 | ('sl', gettext_noop('Slovenian')), | ||
469 | 852 | ('sq', gettext_noop('Albanian')), | ||
470 | 853 | ('sr', gettext_noop('Serbian')), | ||
471 | 854 | ('sr-latn', gettext_noop('Serbian Latin')), | ||
472 | 855 | ('sv', gettext_noop('Swedish')), | ||
473 | 856 | ('ta', gettext_noop('Tamil')), | ||
474 | 857 | ('te', gettext_noop('Telugu')), | ||
475 | 858 | ('th', gettext_noop('Thai')), | ||
476 | 859 | ('tr', gettext_noop('Turkish')), | ||
477 | 860 | ('uk', gettext_noop('Ukrainian')), | ||
478 | 861 | ('ur', gettext_noop('Urdu')), | ||
479 | 862 | ('vi', gettext_noop('Vietnamese')), | ||
480 | 863 | ('zh-cn', gettext_noop('Simplified Chinese')), | ||
481 | 864 | ('zh-tw', gettext_noop('Traditional Chinese')), | ||
482 | 865 | ] | ||
483 | 866 | |||
484 | 867 | django.template_context_processors.default = [ | ||
485 | 868 | 'django.contrib.auth.context_processors.auth', | ||
486 | 869 | 'django.core.context_processors.debug', | ||
487 | 870 | 'django.core.context_processors.i18n', | ||
488 | 871 | 'django.core.context_processors.media', | ||
489 | 872 | 'django.core.context_processors.static', | ||
490 | 873 | 'django.contrib.messages.context_processors.messages', | ||
491 | 874 | ] | ||
492 | 875 | |||
493 | 876 | django.static_root = StringConfigOption( | ||
494 | 877 | default='', | ||
495 | 878 | help='Absolute path to the directory that holds static files.') | ||
496 | 879 | |||
497 | 880 | django.static_url = StringConfigOption( | ||
498 | 881 | null=True, default=None, | ||
499 | 882 | help='URL that handles the static files served from STATIC_ROOT.') | ||
500 | 883 | |||
501 | 884 | ############ | ||
502 | 885 | # SESSIONS # | ||
503 | 886 | ############ | ||
504 | 887 | |||
505 | 888 | django.session_cookie_httponly = BoolConfigOption( | ||
506 | 889 | default=False, | ||
507 | 890 | help='Whether to use the non-RFC standard htt pOnly flag (IE, FF3+, others)') | ||
508 | 891 | |||
509 | 892 | ######### | ||
510 | 893 | # CACHE # | ||
511 | 894 | ######### | ||
512 | 895 | |||
513 | 896 | # remove obsoleted setting | ||
514 | 897 | del django.cache_backend | ||
515 | 898 | |||
516 | 899 | django.caches = DictConfigOption() | ||
517 | 900 | django.cache_middleware_alias = StringConfigOption(default='default') | ||
518 | 901 | |||
519 | 902 | ############ | ||
520 | 903 | # COMMENTS # | ||
521 | 904 | ############ | ||
522 | 905 | |||
523 | 906 | django.profanities_list.default = () | ||
524 | 907 | |||
525 | 908 | ########### | ||
526 | 909 | # LOGGING # | ||
527 | 910 | ########### | ||
528 | 911 | |||
529 | 912 | django.logging_config = StringConfigOption( | ||
530 | 913 | default='django.utils.log.dictConfig', | ||
531 | 914 | help='The callable to use to configure logging') | ||
532 | 915 | django.logging = DictConfigOption( | ||
533 | 916 | spec={ | ||
534 | 917 | 'version': IntConfigOption(default=1), | ||
535 | 918 | 'disable_existing_loggers': BoolConfigOption(default=False), | ||
536 | 919 | 'handlers': DictConfigOption( | ||
537 | 920 | spec={ | ||
538 | 921 | 'mail_admins': DictConfigOption( | ||
539 | 922 | spec={ | ||
540 | 923 | 'level': StringConfigOption(default='ERROR'), | ||
541 | 924 | 'class': StringConfigOption( | ||
542 | 925 | default='django.utils.log.AdminEmailHandler'), | ||
543 | 926 | }), | ||
544 | 927 | }), | ||
545 | 928 | 'loggers': DictConfigOption( | ||
546 | 929 | spec={ | ||
547 | 930 | 'django.request': DictConfigOption( | ||
548 | 931 | spec={ | ||
549 | 932 | 'handlers': LinesConfigOption( | ||
550 | 933 | item=StringConfigOption(), | ||
551 | 934 | default=['mail_admins']), | ||
552 | 935 | 'level': StringConfigOption(default='ERROR'), | ||
553 | 936 | 'propagate': BoolConfigOption(default=False), | ||
554 | 937 | }), | ||
555 | 938 | }), | ||
556 | 939 | }, | ||
557 | 940 | help='The default logging configuration. This sends an email to the ' | ||
558 | 941 | 'site admins on every HTTP 500 error. All other records are sent ' | ||
559 | 942 | 'to the bit bucket.') | ||
560 | 943 | |||
561 | 944 | ############### | ||
562 | 945 | # STATICFILES # | ||
563 | 946 | ############### | ||
564 | 947 | |||
565 | 948 | django.staticfiles_dirs = LinesConfigOption( | ||
566 | 949 | item=StringConfigOption(), | ||
567 | 950 | help='A list of locations of additional static files') | ||
568 | 951 | django.staticfiles_storage = StringConfigOption( | ||
569 | 952 | default='django.contrib.staticfiles.storage.StaticFilesStorage', | ||
570 | 953 | help='The default file storage backend used during the build process') | ||
571 | 954 | django.staticfiles_finders = LinesConfigOption( | ||
572 | 955 | item=StringConfigOption(), | ||
573 | 956 | default=[ | ||
574 | 957 | 'django.contrib.staticfiles.finders.FileSystemFinder', | ||
575 | 958 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder', | ||
576 | 959 | ], | ||
577 | 960 | help='List of finder classes that know how to find static files in ' | ||
578 | 961 | 'various locations.') | ||
579 | 962 | |||
580 | 963 | django.admin_media_prefix.default = '/static/admin/' | ||
581 | 964 | |||
582 | 472 | 965 | ||
583 | 473 | class DjangoSchemaFactory(object): | 966 | class DjangoSchemaFactory(object): |
584 | 474 | def __init__(self): | 967 | def __init__(self): |
585 | @@ -506,8 +999,9 @@ | |||
586 | 506 | 999 | ||
587 | 507 | 1000 | ||
588 | 508 | schemas = DjangoSchemaFactory() | 1001 | schemas = DjangoSchemaFactory() |
590 | 509 | schemas.register(Django102Schema) | 1002 | schemas.register(BaseDjangoSchema, '1.0.2 final') |
591 | 1003 | schemas.register(BaseDjangoSchema, '1.0.4') | ||
592 | 510 | schemas.register(Django112Schema) | 1004 | schemas.register(Django112Schema) |
596 | 511 | # also register the same schema for lucid's django version (which is exported | 1005 | schemas.register(Django112Schema, '1.1.4') |
597 | 512 | # as 1.1.1 but is essentially 1.1.2 | 1006 | schemas.register(Django125Schema) |
598 | 513 | schemas.register(Django112Schema, '1.1.1') | 1007 | schemas.register(Django13Schema) |
599 | 514 | 1008 | ||
600 | === modified file 'django_configglue/tests/helpers.py' | |||
601 | --- django_configglue/tests/helpers.py 2011-01-17 15:32:29 +0000 | |||
602 | +++ django_configglue/tests/helpers.py 2011-04-13 17:14:29 +0000 | |||
603 | @@ -3,6 +3,7 @@ | |||
604 | 3 | 3 | ||
605 | 4 | import os | 4 | import os |
606 | 5 | import sys | 5 | import sys |
607 | 6 | import textwrap | ||
608 | 6 | from StringIO import StringIO | 7 | from StringIO import StringIO |
609 | 7 | 8 | ||
610 | 8 | import django | 9 | import django |
611 | @@ -15,13 +16,27 @@ | |||
612 | 15 | COMMAND = '' | 16 | COMMAND = '' |
613 | 16 | 17 | ||
614 | 17 | def setUp(self): | 18 | def setUp(self): |
622 | 18 | config = """ | 19 | config = textwrap.dedent(""" |
623 | 19 | [django] | 20 | [django] |
624 | 20 | database_engine = sqlite3 | 21 | database_engine = sqlite3 |
625 | 21 | database_name = :memory: | 22 | database_name = :memory: |
626 | 22 | installed_apps = django_configglue | 23 | installed_apps = django_configglue |
627 | 23 | time_zone = Europe/London | 24 | time_zone = Europe/London |
628 | 24 | """ | 25 | """) |
629 | 26 | |||
630 | 27 | if django.VERSION[:2] > (1, 1): | ||
631 | 28 | # since 1.2 use multi database settings format | ||
632 | 29 | config += textwrap.dedent(""" | ||
633 | 30 | databases = databases | ||
634 | 31 | |||
635 | 32 | [databases] | ||
636 | 33 | default = db_default | ||
637 | 34 | |||
638 | 35 | [db_default] | ||
639 | 36 | engine = sqlite3 | ||
640 | 37 | name = :memory: | ||
641 | 38 | """) | ||
642 | 39 | |||
643 | 25 | self.set_config(config) | 40 | self.set_config(config) |
644 | 26 | self._DJANGO_SETTINGS_MODULE = self.load_settings() | 41 | self._DJANGO_SETTINGS_MODULE = self.load_settings() |
645 | 27 | 42 | ||
646 | @@ -39,10 +54,13 @@ | |||
647 | 39 | 54 | ||
648 | 40 | @property | 55 | @property |
649 | 41 | def wrapped_settings(self): | 56 | def wrapped_settings(self): |
653 | 42 | if django.VERSION[:2] < (1, 1): | 57 | wrapped = '_target' |
654 | 43 | wrapped = '_target' | 58 | if django.VERSION[:3] > (1, 0, 2): |
652 | 44 | else: | ||
655 | 45 | wrapped = '_wrapped' | 59 | wrapped = '_wrapped' |
656 | 60 | # make sure the wrapped object is not None | ||
657 | 61 | # by just querying it for a setting | ||
658 | 62 | getattr(settings, 'DEBUG', False) | ||
659 | 63 | assert(getattr(settings, wrapped) != None) | ||
660 | 46 | return wrapped | 64 | return wrapped |
661 | 47 | 65 | ||
662 | 48 | def load_settings(self, module='django_configglue.tests.settings'): | 66 | def load_settings(self, module='django_configglue.tests.settings'): |
663 | @@ -51,9 +69,8 @@ | |||
664 | 51 | if old_module in sys.modules: | 69 | if old_module in sys.modules: |
665 | 52 | del sys.modules[old_module] | 70 | del sys.modules[old_module] |
666 | 53 | # keep runtime settings | 71 | # keep runtime settings |
670 | 54 | if django.VERSION[:2] < (1, 1): | 72 | extra_settings = {} |
671 | 55 | extra_settings = {} | 73 | if django.VERSION[:2] == (1, 1): |
669 | 56 | else: | ||
672 | 57 | extra_settings = { | 74 | extra_settings = { |
673 | 58 | 'DATABASE_NAME': settings.DATABASE_NAME, | 75 | 'DATABASE_NAME': settings.DATABASE_NAME, |
674 | 59 | 'DATABASE_SUPPORTS_TRANSACTIONS': getattr( | 76 | 'DATABASE_SUPPORTS_TRANSACTIONS': getattr( |
675 | 60 | 77 | ||
676 | === modified file 'django_configglue/tests/settings.py' | |||
677 | --- django_configglue/tests/settings.py 2011-01-17 15:32:29 +0000 | |||
678 | +++ django_configglue/tests/settings.py 2011-04-13 17:14:29 +0000 | |||
679 | @@ -6,6 +6,9 @@ | |||
680 | 6 | from django_configglue.schema import schemas | 6 | from django_configglue.schema import schemas |
681 | 7 | 7 | ||
682 | 8 | 8 | ||
685 | 9 | DjangoSchema = schemas.get(django.get_version()) | 9 | DjangoSchema = schemas.get(django.get_version(), strict=False) |
686 | 10 | configglue(DjangoSchema, ['main.cfg', 'test.cfg'], __name__) | 10 | main_cfg = 'main.cfg' |
687 | 11 | if DjangoSchema.version >= '1.2': | ||
688 | 12 | main_cfg = 'main-12.cfg' | ||
689 | 13 | configglue(DjangoSchema, [main_cfg, 'test.cfg'], __name__) | ||
690 | 11 | 14 | ||
691 | 12 | 15 | ||
692 | === modified file 'django_configglue/tests/test_configglue.py' | |||
693 | --- django_configglue/tests/test_configglue.py 2011-02-19 23:14:11 +0000 | |||
694 | +++ django_configglue/tests/test_configglue.py 2011-04-13 17:14:29 +0000 | |||
695 | @@ -2,9 +2,11 @@ | |||
696 | 2 | # Copyright 2010 Canonical Ltd. This software is licensed under the | 2 | # Copyright 2010 Canonical Ltd. This software is licensed under the |
697 | 3 | # GNU Lesser General Public License version 3 (see the file LICENSE). | 3 | # GNU Lesser General Public License version 3 (see the file LICENSE). |
698 | 4 | 4 | ||
699 | 5 | import textwrap | ||
700 | 5 | from cStringIO import StringIO | 6 | from cStringIO import StringIO |
701 | 6 | from unittest import TestCase | 7 | from unittest import TestCase |
702 | 7 | 8 | ||
703 | 9 | import django | ||
704 | 8 | from configglue.pyschema.schema import ( | 10 | from configglue.pyschema.schema import ( |
705 | 9 | DictConfigOption, | 11 | DictConfigOption, |
706 | 10 | IntConfigOption, | 12 | IntConfigOption, |
707 | @@ -26,10 +28,10 @@ | |||
708 | 26 | update_settings, | 28 | update_settings, |
709 | 27 | ) | 29 | ) |
710 | 28 | from django_configglue.schema import ( | 30 | from django_configglue.schema import ( |
711 | 29 | schemas, | ||
712 | 30 | BaseDjangoSchema, | 31 | BaseDjangoSchema, |
713 | 31 | Django102Schema, | ||
714 | 32 | DjangoSchemaFactory, | 32 | DjangoSchemaFactory, |
715 | 33 | UpperCaseDictConfigOption, | ||
716 | 34 | schemas, | ||
717 | 33 | ) | 35 | ) |
718 | 34 | from django_configglue.tests.helpers import ConfigGlueDjangoCommandTestCase | 36 | from django_configglue.tests.helpers import ConfigGlueDjangoCommandTestCase |
719 | 35 | 37 | ||
720 | @@ -38,8 +40,9 @@ | |||
721 | 38 | def test_get_django_settings(self): | 40 | def test_get_django_settings(self): |
722 | 39 | class MySchema(Schema): | 41 | class MySchema(Schema): |
723 | 40 | foo = IntConfigOption() | 42 | foo = IntConfigOption() |
726 | 41 | bar = DictConfigOption({'baz': IntConfigOption(), | 43 | bar = DictConfigOption( |
727 | 42 | 'BAZ': IntConfigOption()}) | 44 | spec={'baz': IntConfigOption(), |
728 | 45 | 'BAZ': IntConfigOption()}) | ||
729 | 43 | 46 | ||
730 | 44 | expected = {'FOO': 0, 'BAR': {'baz': 0, 'BAZ': 0}} | 47 | expected = {'FOO': 0, 'BAR': {'baz': 0, 'BAZ': 0}} |
731 | 45 | 48 | ||
732 | @@ -76,7 +79,7 @@ | |||
733 | 76 | 79 | ||
734 | 77 | def test_schemafactory_get(self): | 80 | def test_schemafactory_get(self): |
735 | 78 | # test get valid version | 81 | # test get valid version |
737 | 79 | self.assertEqual(schemas.get('1.0.2'), Django102Schema) | 82 | self.assertEqual(schemas.get('1.0.2 final'), BaseDjangoSchema) |
738 | 80 | 83 | ||
739 | 81 | # test get invalid version | 84 | # test get invalid version |
740 | 82 | self.assertRaises(ValueError, schemas.get, '1.1') | 85 | self.assertRaises(ValueError, schemas.get, '1.1') |
741 | @@ -85,64 +88,63 @@ | |||
742 | 85 | def test_schemafactory_get_nonexisting_too_old(self, mock_logging): | 88 | def test_schemafactory_get_nonexisting_too_old(self, mock_logging): |
743 | 86 | schema = schemas.get('0.96', strict=False) | 89 | schema = schemas.get('0.96', strict=False) |
744 | 87 | 90 | ||
746 | 88 | django_102 = schemas.get('1.0.2') | 91 | django_102 = schemas.get('1.0.2 final') |
747 | 89 | self.assertEqual(schema, django_102) | 92 | self.assertEqual(schema, django_102) |
748 | 90 | self.assertRaises(ValueError, schemas.get, '0.96') | 93 | self.assertRaises(ValueError, schemas.get, '0.96') |
749 | 91 | 94 | ||
750 | 92 | self.assertEqual(mock_logging.warn.call_args_list[0][0][0], | 95 | self.assertEqual(mock_logging.warn.call_args_list[0][0][0], |
751 | 93 | "No schema registered for version '0.96'") | 96 | "No schema registered for version '0.96'") |
752 | 94 | self.assertEqual(mock_logging.warn.call_args_list[1][0][0], | 97 | self.assertEqual(mock_logging.warn.call_args_list[1][0][0], |
754 | 95 | "Falling back to schema for version '1.0.2'") | 98 | "Falling back to schema for version '1.0.2 final'") |
755 | 96 | 99 | ||
756 | 97 | @patch('django_configglue.schema.logging') | 100 | @patch('django_configglue.schema.logging') |
757 | 98 | def test_schemafactory_get_nonexisting(self, mock_logging): | 101 | def test_schemafactory_get_nonexisting(self, mock_logging): |
758 | 99 | schema = schemas.get('1.0.3', strict=False) | 102 | schema = schemas.get('1.0.3', strict=False) |
759 | 100 | 103 | ||
761 | 101 | django_102 = schemas.get('1.0.2') | 104 | django_102 = schemas.get('1.0.2 final') |
762 | 102 | self.assertEqual(schema, django_102) | 105 | self.assertEqual(schema, django_102) |
763 | 103 | self.assertRaises(ValueError, schemas.get, '1.0.3') | 106 | self.assertRaises(ValueError, schemas.get, '1.0.3') |
764 | 104 | 107 | ||
765 | 105 | self.assertEqual(mock_logging.warn.call_args_list[0][0][0], | 108 | self.assertEqual(mock_logging.warn.call_args_list[0][0][0], |
766 | 106 | "No schema registered for version '1.0.3'") | 109 | "No schema registered for version '1.0.3'") |
767 | 107 | self.assertEqual(mock_logging.warn.call_args_list[1][0][0], | 110 | self.assertEqual(mock_logging.warn.call_args_list[1][0][0], |
769 | 108 | "Falling back to schema for version '1.0.2'") | 111 | "Falling back to schema for version '1.0.2 final'") |
770 | 109 | 112 | ||
771 | 110 | @patch('django_configglue.schema.logging') | 113 | @patch('django_configglue.schema.logging') |
772 | 111 | def test_schemafactory_get_nonexisting_too_new(self, mock_logging): | 114 | def test_schemafactory_get_nonexisting_too_new(self, mock_logging): |
773 | 112 | schema = schemas.get('1.2.0', strict=False) | 115 | schema = schemas.get('1.2.0', strict=False) |
774 | 113 | 116 | ||
776 | 114 | django_112 = schemas.get('1.1.2') | 117 | django_112 = schemas.get('1.1.4') |
777 | 115 | self.assertEqual(schema, django_112) | 118 | self.assertEqual(schema, django_112) |
778 | 116 | self.assertRaises(ValueError, schemas.get, '1.2.0') | 119 | self.assertRaises(ValueError, schemas.get, '1.2.0') |
779 | 117 | 120 | ||
780 | 118 | self.assertEqual(mock_logging.warn.call_args_list[0][0][0], | 121 | self.assertEqual(mock_logging.warn.call_args_list[0][0][0], |
781 | 119 | "No schema registered for version '1.2.0'") | 122 | "No schema registered for version '1.2.0'") |
782 | 120 | self.assertEqual(mock_logging.warn.call_args_list[1][0][0], | 123 | self.assertEqual(mock_logging.warn.call_args_list[1][0][0], |
784 | 121 | "Falling back to schema for version '1.1.2'") | 124 | "Falling back to schema for version '1.1.4'") |
785 | 122 | 125 | ||
786 | 123 | @patch('django_configglue.schema.logging') | 126 | @patch('django_configglue.schema.logging') |
787 | 124 | def test_schemafactory_get_no_versions_registered(self, mock_logging): | 127 | def test_schemafactory_get_no_versions_registered(self, mock_logging): |
788 | 125 | schemas = DjangoSchemaFactory() | 128 | schemas = DjangoSchemaFactory() |
789 | 126 | try: | 129 | try: |
791 | 127 | schemas.get('1.0.2', strict=False) | 130 | schemas.get('1.0.2 final', strict=False) |
792 | 128 | except ValueError, e: | 131 | except ValueError, e: |
793 | 129 | self.assertEqual(str(e), "No schemas registered") | 132 | self.assertEqual(str(e), "No schemas registered") |
794 | 130 | else: | 133 | else: |
795 | 131 | self.fail("ValueError not raised") | 134 | self.fail("ValueError not raised") |
796 | 132 | 135 | ||
797 | 133 | mock_logging.warn.assert_called_with( | 136 | mock_logging.warn.assert_called_with( |
799 | 134 | "No schema registered for version '1.0.2'") | 137 | "No schema registered for version '1.0.2 final'") |
800 | 135 | 138 | ||
801 | 136 | def test_schema_versions(self): | 139 | def test_schema_versions(self): |
803 | 137 | django_102 = schemas.get('1.0.2')() | 140 | django_102 = schemas.get('1.0.2 final')() |
804 | 138 | django_112 = schemas.get('1.1.2')() | 141 | django_112 = schemas.get('1.1.2')() |
807 | 139 | self.assertEqual(django_102.version, '1.0.2') | 142 | self.assertEqual(django_102.version, '1.0.2 final') |
806 | 140 | self.assertTrue(hasattr(django_102.django, 'jing_path')) | ||
808 | 141 | self.assertEqual(django_112.version, '1.1.2') | 143 | self.assertEqual(django_112.version, '1.1.2') |
810 | 142 | self.assertFalse(hasattr(django_112.django, 'jing_path')) | 144 | self.assertFalse(django_102 is django_112) |
811 | 143 | 145 | ||
812 | 144 | def test_register_without_version(self): | 146 | def test_register_without_version(self): |
814 | 145 | class MySchema(BaseDjangoSchema): | 147 | class MySchema(Schema): |
815 | 146 | pass | 148 | pass |
816 | 147 | 149 | ||
817 | 148 | schemas = DjangoSchemaFactory() | 150 | schemas = DjangoSchemaFactory() |
818 | @@ -150,12 +152,13 @@ | |||
819 | 150 | 152 | ||
820 | 151 | def test_configglue(self): | 153 | def test_configglue(self): |
821 | 152 | target = {} | 154 | target = {} |
823 | 153 | configglue(BaseDjangoSchema, [], target) | 155 | schema = schemas.get(django.get_version(), strict=False) |
824 | 156 | configglue(schema, [], target) | ||
825 | 154 | # target is consistent with django's settings module | 157 | # target is consistent with django's settings module |
826 | 155 | # except for a few keys | 158 | # except for a few keys |
827 | 156 | shared_key = lambda x: (not x.startswith('__') and x.upper() == x and | 159 | shared_key = lambda x: (not x.startswith('__') and x.upper() == x and |
828 | 157 | x not in ('DATABASE_SUPPORTS_TRANSACTIONS', 'SETTINGS_MODULE')) | 160 | x not in ('DATABASE_SUPPORTS_TRANSACTIONS', 'SETTINGS_MODULE')) |
830 | 158 | expected_keys = set(filter(shared_key, settings.get_all_members())) | 161 | expected_keys = set(filter(shared_key, dir(settings))) |
831 | 159 | target_keys = set(filter(shared_key, target.keys())) | 162 | target_keys = set(filter(shared_key, target.keys())) |
832 | 160 | 163 | ||
833 | 161 | self.assertEqual(expected_keys, target_keys) | 164 | self.assertEqual(expected_keys, target_keys) |
834 | @@ -245,3 +248,22 @@ | |||
835 | 245 | self.execute() | 248 | self.execute() |
836 | 246 | self.assertTrue('Show settings attributes' in self.capture['stdout']) | 249 | self.assertTrue('Show settings attributes' in self.capture['stdout']) |
837 | 247 | 250 | ||
838 | 251 | |||
839 | 252 | class UpperCaseDictConfigOptionTestCase(TestCase): | ||
840 | 253 | def test_parse(self): | ||
841 | 254 | class MySchema(Schema): | ||
842 | 255 | foo = UpperCaseDictConfigOption() | ||
843 | 256 | config = StringIO(textwrap.dedent(""" | ||
844 | 257 | [__main__] | ||
845 | 258 | foo = mydict | ||
846 | 259 | [mydict] | ||
847 | 260 | bar = 42 | ||
848 | 261 | """)) | ||
849 | 262 | |||
850 | 263 | schema = MySchema() | ||
851 | 264 | parser = SchemaConfigParser(schema) | ||
852 | 265 | parser.readfp(config) | ||
853 | 266 | result = schema.foo.parse('mydict', parser) | ||
854 | 267 | |||
855 | 268 | self.assertEqual(result, {'BAR': '42'}) | ||
856 | 269 | |||
857 | 248 | 270 | ||
858 | === modified file 'django_configglue/tests/test_settings.py' | |||
859 | --- django_configglue/tests/test_settings.py 2011-01-17 16:01:13 +0000 | |||
860 | +++ django_configglue/tests/test_settings.py 2011-04-13 17:14:29 +0000 | |||
861 | @@ -36,8 +36,11 @@ | |||
862 | 36 | "SETTINGS_MODULE = 'django_configglue.tests.settings'", | 36 | "SETTINGS_MODULE = 'django_configglue.tests.settings'", |
863 | 37 | "SETTINGS_ENCODING = '%s'" % SETTINGS_ENCODING, | 37 | "SETTINGS_ENCODING = '%s'" % SETTINGS_ENCODING, |
864 | 38 | ] | 38 | ] |
866 | 39 | if django.VERSION[:2] >= (1, 1): | 39 | django_version = django.VERSION[:2] |
867 | 40 | if django_version == (1, 1): | ||
868 | 40 | expected_values.append("DATABASE_SUPPORTS_TRANSACTIONS = True") | 41 | expected_values.append("DATABASE_SUPPORTS_TRANSACTIONS = True") |
869 | 42 | if django_version >= (1, 1): | ||
870 | 43 | expected_values.append("JING_PATH = '/usr/bin/jing'") | ||
871 | 41 | self.call_command(show_current=True) | 44 | self.call_command(show_current=True) |
872 | 42 | output_lines = self.capture['stdout'].strip().split('\n') | 45 | output_lines = self.capture['stdout'].strip().split('\n') |
873 | 43 | self.assertEqual(set(expected_values), set(output_lines)) | 46 | self.assertEqual(set(expected_values), set(output_lines)) |
874 | @@ -94,16 +97,15 @@ | |||
875 | 94 | wrapped.__CONFIGGLUE_PARSER__ = old_CONFIGGLUE_PARSER | 97 | wrapped.__CONFIGGLUE_PARSER__ = old_CONFIGGLUE_PARSER |
876 | 95 | 98 | ||
877 | 96 | def test_wrapped_settings(self): | 99 | def test_wrapped_settings(self): |
888 | 97 | old_VERSION = django.VERSION | 100 | # the settings object has a _target attribute |
889 | 98 | 101 | # this is true for versions of django <= 1.0.2 | |
890 | 99 | try: | 102 | expected = '_target' |
891 | 100 | django.VERSION = (1, 0, 2) | 103 | if django.VERSION[:3] > (1, 0, 2): |
892 | 101 | self.assertEqual(self.wrapped_settings, '_target') | 104 | # the settings object has a _wrapped attribute |
893 | 102 | 105 | # this is true for versions of django > 1.0.2 | |
894 | 103 | django.VERSION = (1, 1, 2) | 106 | expected = '_wrapped' |
895 | 104 | self.assertEqual(self.wrapped_settings, '_wrapped') | 107 | |
896 | 105 | finally: | 108 | self.assertEqual(self.wrapped_settings, expected) |
887 | 106 | django.VERSION = old_VERSION | ||
897 | 107 | 109 | ||
898 | 108 | 110 | ||
899 | 109 | class ValidateCommandTestCase(ConfigGlueDjangoCommandTestCase): | 111 | class ValidateCommandTestCase(ConfigGlueDjangoCommandTestCase): |
900 | 110 | 112 | ||
901 | === modified file 'django_configglue/utils.py' | |||
902 | --- django_configglue/utils.py 2011-01-17 15:32:29 +0000 | |||
903 | +++ django_configglue/utils.py 2011-04-13 17:14:29 +0000 | |||
904 | @@ -55,3 +55,4 @@ | |||
905 | 55 | scp = SchemaConfigParser(schema_class()) | 55 | scp = SchemaConfigParser(schema_class()) |
906 | 56 | scp.read(configs) | 56 | scp.read(configs) |
907 | 57 | update_settings(scp, target) | 57 | update_settings(scp, target) |
908 | 58 | return scp | ||
909 | 58 | 59 | ||
910 | === added file 'testproject/main-12.cfg' | |||
911 | --- testproject/main-12.cfg 1970-01-01 00:00:00 +0000 | |||
912 | +++ testproject/main-12.cfg 2011-04-13 17:14:29 +0000 | |||
913 | @@ -0,0 +1,12 @@ | |||
914 | 1 | [django] | ||
915 | 2 | database_engine = sqlite3 | ||
916 | 3 | database_name = :memory: | ||
917 | 4 | installed_apps = django_configglue | ||
918 | 5 | databases = databases | ||
919 | 6 | |||
920 | 7 | [databases] | ||
921 | 8 | default = db_default | ||
922 | 9 | |||
923 | 10 | [db_default] | ||
924 | 11 | engine = sqlite3 | ||
925 | 12 | name = :memory: | ||
926 | 0 | 13 | ||
927 | === modified file 'testproject/main.cfg' | |||
928 | --- testproject/main.cfg 2010-08-06 19:27:35 +0000 | |||
929 | +++ testproject/main.cfg 2011-04-13 17:14:29 +0000 | |||
930 | @@ -1,4 +1,3 @@ | |||
931 | 1 | |||
932 | 2 | [django] | 1 | [django] |
933 | 3 | database_engine = sqlite3 | 2 | database_engine = sqlite3 |
934 | 4 | database_name = :memory: | 3 | database_name = :memory: |
935 | 5 | 4 | ||
936 | === modified file 'testproject/testrunner.py' | |||
937 | --- testproject/testrunner.py 2010-10-13 16:11:56 +0000 | |||
938 | +++ testproject/testrunner.py 2011-04-13 17:14:29 +0000 | |||
939 | @@ -11,10 +11,8 @@ | |||
940 | 11 | 11 | ||
941 | 12 | os.environ['DJANGO_SETTINGS_MODULE'] = 'testproject.settings' | 12 | os.environ['DJANGO_SETTINGS_MODULE'] = 'testproject.settings' |
942 | 13 | 13 | ||
945 | 14 | from django.conf import settings | 14 | from django.core.management import call_command |
944 | 15 | from django.test.utils import get_runner | ||
946 | 16 | 15 | ||
950 | 17 | test_runner = get_runner(settings) | 16 | call_command('test', 'django_configglue') |
951 | 18 | failures = test_runner(['django_configglue'], verbosity=1, interactive=True) | 17 | sys.exit(0) |
949 | 19 | sys.exit(failures) | ||
952 | 20 | 18 | ||
953 | 21 | 19 | ||
954 | === added file 'tox' | |||
955 | --- tox 1970-01-01 00:00:00 +0000 | |||
956 | +++ tox 2011-04-13 17:14:29 +0000 | |||
957 | @@ -0,0 +1,6 @@ | |||
958 | 1 | #!/usr/bin/env python | ||
959 | 2 | import urllib | ||
960 | 3 | url = "https://pytox.googlecode.com/hg/toxbootstrap.py" | ||
961 | 4 | d = dict(__file__='toxbootstrap.py') | ||
962 | 5 | exec urllib.urlopen(url).read() in d | ||
963 | 6 | d['cmdline'](['--recreate']) | ||
964 | 0 | \ No newline at end of file | 7 | \ No newline at end of file |
965 | 1 | 8 | ||
966 | === added file 'tox.ini' | |||
967 | --- tox.ini 1970-01-01 00:00:00 +0000 | |||
968 | +++ tox.ini 2011-04-13 17:14:29 +0000 | |||
969 | @@ -0,0 +1,47 @@ | |||
970 | 1 | [tox] | ||
971 | 2 | envlist = | ||
972 | 3 | py26-django102, | ||
973 | 4 | py26-django104, | ||
974 | 5 | py26-django112, | ||
975 | 6 | py26-django114, | ||
976 | 7 | py26-django125, | ||
977 | 8 | py26-django13 | ||
978 | 9 | |||
979 | 10 | [testenv] | ||
980 | 11 | commands = python setup.py test | ||
981 | 12 | |||
982 | 13 | [testenv:py26-django102] | ||
983 | 14 | deps = | ||
984 | 15 | configglue | ||
985 | 16 | mock | ||
986 | 17 | django==1.0.2-final | ||
987 | 18 | |||
988 | 19 | [testenv:py26-django104] | ||
989 | 20 | deps = | ||
990 | 21 | configglue | ||
991 | 22 | mock | ||
992 | 23 | django==1.0.4 | ||
993 | 24 | |||
994 | 25 | [testenv:py26-django112] | ||
995 | 26 | deps = | ||
996 | 27 | configglue | ||
997 | 28 | mock | ||
998 | 29 | django==1.1.2 | ||
999 | 30 | |||
1000 | 31 | [testenv:py26-django114] | ||
1001 | 32 | deps = | ||
1002 | 33 | configglue | ||
1003 | 34 | mock | ||
1004 | 35 | django==1.1.4 | ||
1005 | 36 | |||
1006 | 37 | [testenv:py26-django125] | ||
1007 | 38 | deps = | ||
1008 | 39 | configglue | ||
1009 | 40 | mock | ||
1010 | 41 | django==1.2.5 | ||
1011 | 42 | |||
1012 | 43 | [testenv:py26-django13] | ||
1013 | 44 | deps = | ||
1014 | 45 | configglue | ||
1015 | 46 | mock | ||
1016 | 47 | django==1.3 |
You can move common dependencies for each environment to [testenv] section. Like
[testenv]
deps = configglue
mock