Merge lp:~ricardokirkner/django-configglue/tox into lp:django-configglue

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
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 :

You can move common dependencies for each environment to [testenv] section. Like

[testenv]
deps = configglue
       mock

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
=== modified file 'django_configglue/__init__.py'
--- django_configglue/__init__.py 2011-01-10 21:43:27 +0000
+++ django_configglue/__init__.py 2011-04-13 17:14:29 +0000
@@ -42,7 +42,8 @@
42 options, args = parser.parse_args(self.argv)42 options, args = parser.parse_args(self.argv)
43 handle_default_options(options)43 handle_default_options(options)
44 except:44 except:
45 pass # Ignore any option errors at this point.45 # Ignore any option errors at this point.
46 args = self.argv
4647
47 try:48 try:
48 subcommand = self.argv[1]49 subcommand = self.argv[1]
4950
=== modified file 'django_configglue/management/commands/settings.py'
--- django_configglue/management/commands/settings.py 2011-01-10 21:43:27 +0000
+++ django_configglue/management/commands/settings.py 2011-04-13 17:14:29 +0000
@@ -106,7 +106,7 @@
106 else:106 else:
107 # looking in django settings107 # looking in django settings
108 for key in map(str.upper, keys):108 for key in map(str.upper, keys):
109 if key in settings.get_all_members():109 if key in dir(settings):
110 msg = "setting %s last defined in %r"110 msg = "setting %s last defined in %r"
111 output.append(msg % (key, os.path.realpath(location)))111 output.append(msg % (key, os.path.realpath(location)))
112 else:112 else:
113113
=== modified file 'django_configglue/schema.py'
--- django_configglue/schema.py 2011-02-19 23:14:11 +0000
+++ django_configglue/schema.py 2011-04-13 17:14:29 +0000
@@ -1,6 +1,7 @@
1# Copyright 2010 Canonical Ltd. This software is licensed under the1# Copyright 2010 Canonical Ltd. This software is licensed under the
2# GNU Lesser General Public License version 3 (see the file LICENSE).2# GNU Lesser General Public License version 3 (see the file LICENSE).
3import logging3import logging
4from copy import deepcopy
45
5from configglue.pyschema.schema import (6from configglue.pyschema.schema import (
6 BoolConfigOption,7 BoolConfigOption,
@@ -21,8 +22,20 @@
21gettext_noop = lambda s: s22gettext_noop = lambda s: s
2223
2324
25class UpperCaseDictConfigOption(DictConfigOption):
26 """ A DictConfigOption with all upper-case keys. """
27 def parse(self, section, parser=None, raw=False):
28 parsed = super(UpperCaseDictConfigOption, self).parse(
29 section, parser, raw)
30 result = {}
31 for k, v in parsed.items():
32 result[k.upper()] = v
33 return result
34
2435
25class BaseDjangoSchema(Schema):36class BaseDjangoSchema(Schema):
37 version = '1.0.2 final'
38
26 # Sections39 # Sections
27 django = ConfigSection('django')40 django = ConfigSection('django')
2841
@@ -256,6 +269,9 @@
256 "secret-key hashing algorithms. Set this in your settings, or "269 "secret-key hashing algorithms. Set this in your settings, or "
257 "Django will complain loudly")270 "Django will complain loudly")
258271
272 django.jing_path = StringConfigOption(default='/usr/bin/jing',
273 help="Path to the 'jing' executable -- needed to validate XMLFields")
274
259 django.default_file_storage = StringConfigOption(275 django.default_file_storage = StringConfigOption(
260 default='django.core.files.storage.FileSystemStorage',276 default='django.core.files.storage.FileSystemStorage',
261 help="Default file storage mechanism that holds media")277 help="Default file storage mechanism that holds media")
@@ -452,23 +468,500 @@
452 django.root_urlconf = StringConfigOption(default='urls')468 django.root_urlconf = StringConfigOption(default='urls')
453469
454470
455class Django102Schema(BaseDjangoSchema):
456 version = '1.0.2'
457
458 def __init__(self, *args, **kwargs):
459 super(Django102Schema, self).__init__(*args, **kwargs)
460
461 ################
462 # CORE #
463 ################
464
465 self.django.jing_path = StringConfigOption(default='/usr/bin/jing',
466 help="Path to the 'jing' executable -- needed to validate XMLFields")
467
468
469class Django112Schema(BaseDjangoSchema):471class Django112Schema(BaseDjangoSchema):
470 version = '1.1.2'472 version = '1.1.2'
471473
474 # sections
475 django = deepcopy(BaseDjangoSchema.django)
476
477 ################
478 # CORE #
479 ################
480
481 # update default value
482 django.languages.default = (
483 ('ar', gettext_noop('Arabic')),
484 ('bg', gettext_noop('Bulgarian')),
485 ('bn', gettext_noop('Bengali')),
486 ('bs', gettext_noop('Bosnian')),
487 ('ca', gettext_noop('Catalan')),
488 ('cs', gettext_noop('Czech')),
489 ('cy', gettext_noop('Welsh')),
490 ('da', gettext_noop('Danish')),
491 ('de', gettext_noop('German')),
492 ('el', gettext_noop('Greek')),
493 ('en', gettext_noop('English')),
494 ('es', gettext_noop('Spanish')),
495 ('es-ar', gettext_noop('Argentinean Spanish')),
496 ('et', gettext_noop('Estonian')),
497 ('eu', gettext_noop('Basque')),
498 ('fa', gettext_noop('Persian')),
499 ('fi', gettext_noop('Finnish')),
500 ('fr', gettext_noop('French')),
501 ('fy-nl', gettext_noop('Frisian')),
502 ('ga', gettext_noop('Irish')),
503 ('gl', gettext_noop('Galician')),
504 ('he', gettext_noop('Hebrew')),
505 ('hi', gettext_noop('Hindi')),
506 ('hr', gettext_noop('Croatian')),
507 ('hu', gettext_noop('Hungarian')),
508 ('is', gettext_noop('Icelandic')),
509 ('it', gettext_noop('Italian')),
510 ('ja', gettext_noop('Japanese')),
511 ('ka', gettext_noop('Georgian')),
512 ('km', gettext_noop('Khmer')),
513 ('kn', gettext_noop('Kannada')),
514 ('ko', gettext_noop('Korean')),
515 ('lt', gettext_noop('Lithuanian')),
516 ('lv', gettext_noop('Latvian')),
517 ('mk', gettext_noop('Macedonian')),
518 ('nl', gettext_noop('Dutch')),
519 ('no', gettext_noop('Norwegian')),
520 ('pl', gettext_noop('Polish')),
521 ('pt', gettext_noop('Portuguese')),
522 ('pt-br', gettext_noop('Brazilian Portuguese')),
523 ('ro', gettext_noop('Romanian')),
524 ('ru', gettext_noop('Russian')),
525 ('sk', gettext_noop('Slovak')),
526 ('sl', gettext_noop('Slovenian')),
527 ('sq', gettext_noop('Albanian')),
528 ('sr', gettext_noop('Serbian')),
529 ('sr-latn', gettext_noop('Serbian Latin')),
530 ('sv', gettext_noop('Swedish')),
531 ('ta', gettext_noop('Tamil')),
532 ('te', gettext_noop('Telugu')),
533 ('th', gettext_noop('Thai')),
534 ('tr', gettext_noop('Turkish')),
535 ('uk', gettext_noop('Ukrainian')),
536 ('zh-cn', gettext_noop('Simplified Chinese')),
537 ('zh-tw', gettext_noop('Traditional Chinese')),
538 )
539
540
541class Django125Schema(Django112Schema):
542 version = '1.2.5'
543
544 # sections
545 django = deepcopy(Django112Schema.django)
546
547 ################
548 # CORE #
549 ################
550
551 # update default value
552 django.languages.default = [
553 ('ar', gettext_noop('Arabic')),
554 ('bg', gettext_noop('Bulgarian')),
555 ('bn', gettext_noop('Bengali')),
556 ('bs', gettext_noop('Bosnian')),
557 ('ca', gettext_noop('Catalan')),
558 ('cs', gettext_noop('Czech')),
559 ('cy', gettext_noop('Welsh')),
560 ('da', gettext_noop('Danish')),
561 ('de', gettext_noop('German')),
562 ('el', gettext_noop('Greek')),
563 ('en', gettext_noop('English')),
564 ('en-gb', gettext_noop('British English')),
565 ('es', gettext_noop('Spanish')),
566 ('es-ar', gettext_noop('Argentinian Spanish')),
567 ('et', gettext_noop('Estonian')),
568 ('eu', gettext_noop('Basque')),
569 ('fa', gettext_noop('Persian')),
570 ('fi', gettext_noop('Finnish')),
571 ('fr', gettext_noop('French')),
572 ('fy-nl', gettext_noop('Frisian')),
573 ('ga', gettext_noop('Irish')),
574 ('gl', gettext_noop('Galician')),
575 ('he', gettext_noop('Hebrew')),
576 ('hi', gettext_noop('Hindi')),
577 ('hr', gettext_noop('Croatian')),
578 ('hu', gettext_noop('Hungarian')),
579 ('id', gettext_noop('Indonesian')),
580 ('is', gettext_noop('Icelandic')),
581 ('it', gettext_noop('Italian')),
582 ('ja', gettext_noop('Japanese')),
583 ('ka', gettext_noop('Georgian')),
584 ('km', gettext_noop('Khmer')),
585 ('kn', gettext_noop('Kannada')),
586 ('ko', gettext_noop('Korean')),
587 ('lt', gettext_noop('Lithuanian')),
588 ('lv', gettext_noop('Latvian')),
589 ('mk', gettext_noop('Macedonian')),
590 ('ml', gettext_noop('Malayalam')),
591 ('mn', gettext_noop('Mongolian')),
592 ('nl', gettext_noop('Dutch')),
593 ('no', gettext_noop('Norwegian')),
594 ('nb', gettext_noop('Norwegian Bokmal')),
595 ('nn', gettext_noop('Norwegian Nynorsk')),
596 ('pl', gettext_noop('Polish')),
597 ('pt', gettext_noop('Portuguese')),
598 ('pt-br', gettext_noop('Brazilian Portuguese')),
599 ('ro', gettext_noop('Romanian')),
600 ('ru', gettext_noop('Russian')),
601 ('sk', gettext_noop('Slovak')),
602 ('sl', gettext_noop('Slovenian')),
603 ('sq', gettext_noop('Albanian')),
604 ('sr', gettext_noop('Serbian')),
605 ('sr-latn', gettext_noop('Serbian Latin')),
606 ('sv', gettext_noop('Swedish')),
607 ('ta', gettext_noop('Tamil')),
608 ('te', gettext_noop('Telugu')),
609 ('th', gettext_noop('Thai')),
610 ('tr', gettext_noop('Turkish')),
611 ('uk', gettext_noop('Ukrainian')),
612 ('vi', gettext_noop('Vietnamese')),
613 ('zh-cn', gettext_noop('Simplified Chinese')),
614 ('zh-tw', gettext_noop('Traditional Chinese')),
615 ]
616
617 django.use_l10n = BoolConfigOption(
618 default=True,
619 help="If you set this to False, Django will not format dates, "
620 "numbers and calendars according to the current locale")
621
622 django.databases = DictConfigOption(
623 item=UpperCaseDictConfigOption(spec={
624 'engine': StringConfigOption(default='django.db.backends.'),
625 'name': StringConfigOption(),
626 'user': StringConfigOption(),
627 'password': StringConfigOption(),
628 'host': StringConfigOption(),
629 'port': StringConfigOption(),
630 }),
631 default={
632 'default': {
633 'engine': 'django.db.backends.',
634 'name': '',
635 'user': '',
636 'password': '',
637 'host': '',
638 'port': '',
639 }
640 })
641 django.database_routers = LinesConfigOption(
642 item=StringConfigOption(),
643 help="Classes used to implement db routing behaviour")
644
645 django.email_backend = StringConfigOption(
646 default='django.core.mail.backends.smtp.EmailBackend',
647 help="The email backend to use. For possible shortcuts see "
648 "django.core.mail. The default is to use the SMTP backend. "
649 "Third party backends can be specified by providing a Python "
650 "path to a module that defines an EmailBackend class.")
651
652 django.installed_apps.default = [
653 'django.contrib.auth',
654 'django.contrib.contenttypes',
655 'django.contrib.sessions',
656 'django.contrib.sites',
657 'django.contrib.messages',
658 ]
659
660 django.template_loaders.default = [
661 'django.template.loaders.filesystem.Loader',
662 'django.template.loaders.app_directories.Loader',
663 ]
664
665 django.template_context_processors.default = [
666 'django.contrib.auth.context_processors.auth',
667 'django.core.context_processors.debug',
668 'django.core.context_processors.i18n',
669 'django.core.context_processors.media',
670 'django.contrib.messages.context_processors.messages',
671 ]
672
673 django.format_module_path = StringConfigOption(
674 null=True, default=None,
675 help="Python module path where user will place custom format "
676 "definition. The directory where this setting is pointing "
677 "should contain subdirectories named as the locales, "
678 "containing a formats.py file")
679 django.short_date_format = StringConfigOption(
680 default='m/d/Y',
681 help="Default short formatting for date objects")
682 django.short_datetime_format = StringConfigOption(
683 default='m/d/Y P',
684 help="Default short formatting for datetime objects")
685 django.date_input_formats = LinesConfigOption(
686 item=StringConfigOption(),
687 default=[
688 '%%Y-%%m-%%d', '%%m/%%d/%%Y', '%%m/%%d/%%y', # '2006-10-25', '10/25/2006', '10/25/06'
689 '%%b %%d %%Y', '%%b %%d, %%Y', # 'Oct 25 2006', 'Oct 25, 2006'
690 '%%d %%b %%Y', '%%d %%b, %%Y', # '25 Oct 2006', '25 Oct, 2006'
691 '%%B %%d %%Y', '%%B %%d, %%Y', # 'October 25 2006', 'October 25, 2006'
692 '%%d %%B %%Y', '%%d %%B, %%Y', # '25 October 2006', '25 October, 2006'
693 ],
694 help="Default formats to be used when parsing dates from input "
695 "boxes, in order")
696 django.time_input_formats = LinesConfigOption(
697 item=StringConfigOption(),
698 default=[
699 '%%H:%%M:%%S', # '14:30:59'
700 '%%H:%%M', # '14:30'
701 ],
702 help="Default formats to be used when parsing times from input "
703 "boxes, in order")
704 django.datetime_input_formats = LinesConfigOption(
705 item=StringConfigOption(),
706 default=[
707 '%%Y-%%m-%%d %%H:%%M:%%S', # '2006-10-25 14:30:59'
708 '%%Y-%%m-%%d %%H:%%M', # '2006-10-25 14:30'
709 '%%Y-%%m-%%d', # '2006-10-25'
710 '%%m/%%d/%%Y %%H:%%M:%%S', # '10/25/2006 14:30:59'
711 '%%m/%%d/%%Y %%H:%%M', # '10/25/2006 14:30'
712 '%%m/%%d/%%Y', # '10/25/2006'
713 '%%m/%%d/%%y %%H:%%M:%%S', # '10/25/06 14:30:59'
714 '%%m/%%d/%%y %%H:%%M', # '10/25/06 14:30'
715 '%%m/%%d/%%y', # '10/25/06'
716 ],
717 help="Default formats to be used when parsing dates and times "
718 "from input boxes, in order")
719
720 django.first_day_of_week = IntConfigOption(
721 default=0,
722 help="First day of week, to be used on calendars. 0 means Sunday, "
723 "1 means Monday...")
724 django.decimal_separator = StringConfigOption(
725 default='.',
726 help="Decimal separator symbol")
727 django.use_thousand_separator = BoolConfigOption(
728 default=False,
729 help="Boolean that sets whether to add thousand separator when "
730 "formatting numbers")
731 django.number_grouping = IntConfigOption(
732 default=0,
733 help="Number of digits that will be together, when splitting them "
734 "by THOUSAND_SEPARATOR. 0 means no grouping, 3 means "
735 "splitting by thousands...")
736 django.thousand_separator = StringConfigOption(
737 default=',',
738 help="Thousand separator symbol")
739
740 ##############
741 # MIDDLEWARE #
742 ##############
743
744 django.middleware_classes.default = [
745 'django.middleware.common.CommonMiddleware',
746 'django.contrib.sessions.middleware.SessionMiddleware',
747 'django.middleware.csrf.CsrfViewMiddleware',
748 'django.contrib.auth.middleware.AuthenticationMiddleware',
749 'django.contrib.messages.middleware.MessageMiddleware',
750 ]
751
752 ########
753 # CSRF #
754 ########
755
756 django.csrf_failure_view = StringConfigOption(
757 default='django.views.csrf.csrf_failure',
758 help="Dotted path to callable to be used as view when a request "
759 "is rejected by the CSRF middleware")
760 django.csrf_cookie_name = StringConfigOption(
761 default='csrftoken',
762 help="Name for CSRF cookie")
763 django.csrf_cookie_domain = StringConfigOption(
764 null=True,
765 help="Domain for CSRF cookie")
766
767 ############
768 # MESSAGES #
769 ############
770
771 django.message_storage = StringConfigOption(
772 default='django.contrib.messages.storage.user_messages.'
773 'LegacyFallbackStorage',
774 help="Class to be used as messages backend")
775
776 ###########
777 # TESTING #
778 ###########
779
780 django.test_runner.default = (
781 'django.test.simple.DjangoTestSuiteRunner')
782 django.test_runner.help = (
783 "The name of the class to use to run the test suite")
784
785
786class Django13Schema(Django125Schema):
787 version = '1.3'
788
789 # sections
790 django = deepcopy(Django125Schema.django)
791
792 ################
793 # CORE #
794 ################
795
796 # update default value
797 django.languages.default = [
798 ('ar', gettext_noop('Arabic')),
799 ('az', gettext_noop('Azerbaijani')),
800 ('bg', gettext_noop('Bulgarian')),
801 ('bn', gettext_noop('Bengali')),
802 ('bs', gettext_noop('Bosnian')),
803 ('ca', gettext_noop('Catalan')),
804 ('cs', gettext_noop('Czech')),
805 ('cy', gettext_noop('Welsh')),
806 ('da', gettext_noop('Danish')),
807 ('de', gettext_noop('German')),
808 ('el', gettext_noop('Greek')),
809 ('en', gettext_noop('English')),
810 ('en-gb', gettext_noop('British English')),
811 ('es', gettext_noop('Spanish')),
812 ('es-ar', gettext_noop('Argentinian Spanish')),
813 ('es-mx', gettext_noop('Mexican Spanish')),
814 ('es-ni', gettext_noop('Nicaraguan Spanish')),
815 ('et', gettext_noop('Estonian')),
816 ('eu', gettext_noop('Basque')),
817 ('fa', gettext_noop('Persian')),
818 ('fi', gettext_noop('Finnish')),
819 ('fr', gettext_noop('French')),
820 ('fy-nl', gettext_noop('Frisian')),
821 ('ga', gettext_noop('Irish')),
822 ('gl', gettext_noop('Galician')),
823 ('he', gettext_noop('Hebrew')),
824 ('hi', gettext_noop('Hindi')),
825 ('hr', gettext_noop('Croatian')),
826 ('hu', gettext_noop('Hungarian')),
827 ('id', gettext_noop('Indonesian')),
828 ('is', gettext_noop('Icelandic')),
829 ('it', gettext_noop('Italian')),
830 ('ja', gettext_noop('Japanese')),
831 ('ka', gettext_noop('Georgian')),
832 ('km', gettext_noop('Khmer')),
833 ('kn', gettext_noop('Kannada')),
834 ('ko', gettext_noop('Korean')),
835 ('lt', gettext_noop('Lithuanian')),
836 ('lv', gettext_noop('Latvian')),
837 ('mk', gettext_noop('Macedonian')),
838 ('ml', gettext_noop('Malayalam')),
839 ('mn', gettext_noop('Mongolian')),
840 ('nl', gettext_noop('Dutch')),
841 ('no', gettext_noop('Norwegian')),
842 ('nb', gettext_noop('Norwegian Bokmal')),
843 ('nn', gettext_noop('Norwegian Nynorsk')),
844 ('pa', gettext_noop('Punjabi')),
845 ('pl', gettext_noop('Polish')),
846 ('pt', gettext_noop('Portuguese')),
847 ('pt-br', gettext_noop('Brazilian Portuguese')),
848 ('ro', gettext_noop('Romanian')),
849 ('ru', gettext_noop('Russian')),
850 ('sk', gettext_noop('Slovak')),
851 ('sl', gettext_noop('Slovenian')),
852 ('sq', gettext_noop('Albanian')),
853 ('sr', gettext_noop('Serbian')),
854 ('sr-latn', gettext_noop('Serbian Latin')),
855 ('sv', gettext_noop('Swedish')),
856 ('ta', gettext_noop('Tamil')),
857 ('te', gettext_noop('Telugu')),
858 ('th', gettext_noop('Thai')),
859 ('tr', gettext_noop('Turkish')),
860 ('uk', gettext_noop('Ukrainian')),
861 ('ur', gettext_noop('Urdu')),
862 ('vi', gettext_noop('Vietnamese')),
863 ('zh-cn', gettext_noop('Simplified Chinese')),
864 ('zh-tw', gettext_noop('Traditional Chinese')),
865 ]
866
867 django.template_context_processors.default = [
868 'django.contrib.auth.context_processors.auth',
869 'django.core.context_processors.debug',
870 'django.core.context_processors.i18n',
871 'django.core.context_processors.media',
872 'django.core.context_processors.static',
873 'django.contrib.messages.context_processors.messages',
874 ]
875
876 django.static_root = StringConfigOption(
877 default='',
878 help='Absolute path to the directory that holds static files.')
879
880 django.static_url = StringConfigOption(
881 null=True, default=None,
882 help='URL that handles the static files served from STATIC_ROOT.')
883
884 ############
885 # SESSIONS #
886 ############
887
888 django.session_cookie_httponly = BoolConfigOption(
889 default=False,
890 help='Whether to use the non-RFC standard htt pOnly flag (IE, FF3+, others)')
891
892 #########
893 # CACHE #
894 #########
895
896 # remove obsoleted setting
897 del django.cache_backend
898
899 django.caches = DictConfigOption()
900 django.cache_middleware_alias = StringConfigOption(default='default')
901
902 ############
903 # COMMENTS #
904 ############
905
906 django.profanities_list.default = ()
907
908 ###########
909 # LOGGING #
910 ###########
911
912 django.logging_config = StringConfigOption(
913 default='django.utils.log.dictConfig',
914 help='The callable to use to configure logging')
915 django.logging = DictConfigOption(
916 spec={
917 'version': IntConfigOption(default=1),
918 'disable_existing_loggers': BoolConfigOption(default=False),
919 'handlers': DictConfigOption(
920 spec={
921 'mail_admins': DictConfigOption(
922 spec={
923 'level': StringConfigOption(default='ERROR'),
924 'class': StringConfigOption(
925 default='django.utils.log.AdminEmailHandler'),
926 }),
927 }),
928 'loggers': DictConfigOption(
929 spec={
930 'django.request': DictConfigOption(
931 spec={
932 'handlers': LinesConfigOption(
933 item=StringConfigOption(),
934 default=['mail_admins']),
935 'level': StringConfigOption(default='ERROR'),
936 'propagate': BoolConfigOption(default=False),
937 }),
938 }),
939 },
940 help='The default logging configuration. This sends an email to the '
941 'site admins on every HTTP 500 error. All other records are sent '
942 'to the bit bucket.')
943
944 ###############
945 # STATICFILES #
946 ###############
947
948 django.staticfiles_dirs = LinesConfigOption(
949 item=StringConfigOption(),
950 help='A list of locations of additional static files')
951 django.staticfiles_storage = StringConfigOption(
952 default='django.contrib.staticfiles.storage.StaticFilesStorage',
953 help='The default file storage backend used during the build process')
954 django.staticfiles_finders = LinesConfigOption(
955 item=StringConfigOption(),
956 default=[
957 'django.contrib.staticfiles.finders.FileSystemFinder',
958 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
959 ],
960 help='List of finder classes that know how to find static files in '
961 'various locations.')
962
963 django.admin_media_prefix.default = '/static/admin/'
964
472965
473class DjangoSchemaFactory(object):966class DjangoSchemaFactory(object):
474 def __init__(self):967 def __init__(self):
@@ -506,8 +999,9 @@
506999
5071000
508schemas = DjangoSchemaFactory()1001schemas = DjangoSchemaFactory()
509schemas.register(Django102Schema)1002schemas.register(BaseDjangoSchema, '1.0.2 final')
1003schemas.register(BaseDjangoSchema, '1.0.4')
510schemas.register(Django112Schema)1004schemas.register(Django112Schema)
511# also register the same schema for lucid's django version (which is exported1005schemas.register(Django112Schema, '1.1.4')
512# as 1.1.1 but is essentially 1.1.21006schemas.register(Django125Schema)
513schemas.register(Django112Schema, '1.1.1')1007schemas.register(Django13Schema)
5141008
=== modified file 'django_configglue/tests/helpers.py'
--- django_configglue/tests/helpers.py 2011-01-17 15:32:29 +0000
+++ django_configglue/tests/helpers.py 2011-04-13 17:14:29 +0000
@@ -3,6 +3,7 @@
33
4import os4import os
5import sys5import sys
6import textwrap
6from StringIO import StringIO7from StringIO import StringIO
78
8import django9import django
@@ -15,13 +16,27 @@
15 COMMAND = ''16 COMMAND = ''
1617
17 def setUp(self):18 def setUp(self):
18 config = """19 config = textwrap.dedent("""
19[django]20 [django]
20database_engine = sqlite321 database_engine = sqlite3
21database_name = :memory:22 database_name = :memory:
22installed_apps = django_configglue23 installed_apps = django_configglue
23time_zone = Europe/London24 time_zone = Europe/London
24"""25 """)
26
27 if django.VERSION[:2] > (1, 1):
28 # since 1.2 use multi database settings format
29 config += textwrap.dedent("""
30 databases = databases
31
32 [databases]
33 default = db_default
34
35 [db_default]
36 engine = sqlite3
37 name = :memory:
38 """)
39
25 self.set_config(config)40 self.set_config(config)
26 self._DJANGO_SETTINGS_MODULE = self.load_settings()41 self._DJANGO_SETTINGS_MODULE = self.load_settings()
2742
@@ -39,10 +54,13 @@
3954
40 @property55 @property
41 def wrapped_settings(self):56 def wrapped_settings(self):
42 if django.VERSION[:2] < (1, 1):57 wrapped = '_target'
43 wrapped = '_target'58 if django.VERSION[:3] > (1, 0, 2):
44 else:
45 wrapped = '_wrapped'59 wrapped = '_wrapped'
60 # make sure the wrapped object is not None
61 # by just querying it for a setting
62 getattr(settings, 'DEBUG', False)
63 assert(getattr(settings, wrapped) != None)
46 return wrapped64 return wrapped
4765
48 def load_settings(self, module='django_configglue.tests.settings'):66 def load_settings(self, module='django_configglue.tests.settings'):
@@ -51,9 +69,8 @@
51 if old_module in sys.modules:69 if old_module in sys.modules:
52 del sys.modules[old_module]70 del sys.modules[old_module]
53 # keep runtime settings71 # keep runtime settings
54 if django.VERSION[:2] < (1, 1):72 extra_settings = {}
55 extra_settings = {}73 if django.VERSION[:2] == (1, 1):
56 else:
57 extra_settings = {74 extra_settings = {
58 'DATABASE_NAME': settings.DATABASE_NAME,75 'DATABASE_NAME': settings.DATABASE_NAME,
59 'DATABASE_SUPPORTS_TRANSACTIONS': getattr(76 'DATABASE_SUPPORTS_TRANSACTIONS': getattr(
6077
=== modified file 'django_configglue/tests/settings.py'
--- django_configglue/tests/settings.py 2011-01-17 15:32:29 +0000
+++ django_configglue/tests/settings.py 2011-04-13 17:14:29 +0000
@@ -6,6 +6,9 @@
6from django_configglue.schema import schemas6from django_configglue.schema import schemas
77
88
9DjangoSchema = schemas.get(django.get_version())9DjangoSchema = schemas.get(django.get_version(), strict=False)
10configglue(DjangoSchema, ['main.cfg', 'test.cfg'], __name__)10main_cfg = 'main.cfg'
11if DjangoSchema.version >= '1.2':
12 main_cfg = 'main-12.cfg'
13configglue(DjangoSchema, [main_cfg, 'test.cfg'], __name__)
1114
1215
=== modified file 'django_configglue/tests/test_configglue.py'
--- django_configglue/tests/test_configglue.py 2011-02-19 23:14:11 +0000
+++ django_configglue/tests/test_configglue.py 2011-04-13 17:14:29 +0000
@@ -2,9 +2,11 @@
2# Copyright 2010 Canonical Ltd. This software is licensed under the2# Copyright 2010 Canonical Ltd. This software is licensed under the
3# GNU Lesser General Public License version 3 (see the file LICENSE).3# GNU Lesser General Public License version 3 (see the file LICENSE).
44
5import textwrap
5from cStringIO import StringIO6from cStringIO import StringIO
6from unittest import TestCase7from unittest import TestCase
78
9import django
8from configglue.pyschema.schema import (10from configglue.pyschema.schema import (
9 DictConfigOption,11 DictConfigOption,
10 IntConfigOption,12 IntConfigOption,
@@ -26,10 +28,10 @@
26 update_settings,28 update_settings,
27)29)
28from django_configglue.schema import (30from django_configglue.schema import (
29 schemas,
30 BaseDjangoSchema,31 BaseDjangoSchema,
31 Django102Schema,
32 DjangoSchemaFactory,32 DjangoSchemaFactory,
33 UpperCaseDictConfigOption,
34 schemas,
33)35)
34from django_configglue.tests.helpers import ConfigGlueDjangoCommandTestCase36from django_configglue.tests.helpers import ConfigGlueDjangoCommandTestCase
3537
@@ -38,8 +40,9 @@
38 def test_get_django_settings(self):40 def test_get_django_settings(self):
39 class MySchema(Schema):41 class MySchema(Schema):
40 foo = IntConfigOption()42 foo = IntConfigOption()
41 bar = DictConfigOption({'baz': IntConfigOption(),43 bar = DictConfigOption(
42 'BAZ': IntConfigOption()})44 spec={'baz': IntConfigOption(),
45 'BAZ': IntConfigOption()})
4346
44 expected = {'FOO': 0, 'BAR': {'baz': 0, 'BAZ': 0}}47 expected = {'FOO': 0, 'BAR': {'baz': 0, 'BAZ': 0}}
4548
@@ -76,7 +79,7 @@
7679
77 def test_schemafactory_get(self):80 def test_schemafactory_get(self):
78 # test get valid version81 # test get valid version
79 self.assertEqual(schemas.get('1.0.2'), Django102Schema)82 self.assertEqual(schemas.get('1.0.2 final'), BaseDjangoSchema)
8083
81 # test get invalid version84 # test get invalid version
82 self.assertRaises(ValueError, schemas.get, '1.1')85 self.assertRaises(ValueError, schemas.get, '1.1')
@@ -85,64 +88,63 @@
85 def test_schemafactory_get_nonexisting_too_old(self, mock_logging):88 def test_schemafactory_get_nonexisting_too_old(self, mock_logging):
86 schema = schemas.get('0.96', strict=False)89 schema = schemas.get('0.96', strict=False)
8790
88 django_102 = schemas.get('1.0.2')91 django_102 = schemas.get('1.0.2 final')
89 self.assertEqual(schema, django_102)92 self.assertEqual(schema, django_102)
90 self.assertRaises(ValueError, schemas.get, '0.96')93 self.assertRaises(ValueError, schemas.get, '0.96')
9194
92 self.assertEqual(mock_logging.warn.call_args_list[0][0][0],95 self.assertEqual(mock_logging.warn.call_args_list[0][0][0],
93 "No schema registered for version '0.96'")96 "No schema registered for version '0.96'")
94 self.assertEqual(mock_logging.warn.call_args_list[1][0][0],97 self.assertEqual(mock_logging.warn.call_args_list[1][0][0],
95 "Falling back to schema for version '1.0.2'")98 "Falling back to schema for version '1.0.2 final'")
9699
97 @patch('django_configglue.schema.logging')100 @patch('django_configglue.schema.logging')
98 def test_schemafactory_get_nonexisting(self, mock_logging):101 def test_schemafactory_get_nonexisting(self, mock_logging):
99 schema = schemas.get('1.0.3', strict=False)102 schema = schemas.get('1.0.3', strict=False)
100103
101 django_102 = schemas.get('1.0.2')104 django_102 = schemas.get('1.0.2 final')
102 self.assertEqual(schema, django_102)105 self.assertEqual(schema, django_102)
103 self.assertRaises(ValueError, schemas.get, '1.0.3')106 self.assertRaises(ValueError, schemas.get, '1.0.3')
104107
105 self.assertEqual(mock_logging.warn.call_args_list[0][0][0],108 self.assertEqual(mock_logging.warn.call_args_list[0][0][0],
106 "No schema registered for version '1.0.3'")109 "No schema registered for version '1.0.3'")
107 self.assertEqual(mock_logging.warn.call_args_list[1][0][0],110 self.assertEqual(mock_logging.warn.call_args_list[1][0][0],
108 "Falling back to schema for version '1.0.2'")111 "Falling back to schema for version '1.0.2 final'")
109112
110 @patch('django_configglue.schema.logging')113 @patch('django_configglue.schema.logging')
111 def test_schemafactory_get_nonexisting_too_new(self, mock_logging):114 def test_schemafactory_get_nonexisting_too_new(self, mock_logging):
112 schema = schemas.get('1.2.0', strict=False)115 schema = schemas.get('1.2.0', strict=False)
113116
114 django_112 = schemas.get('1.1.2')117 django_112 = schemas.get('1.1.4')
115 self.assertEqual(schema, django_112)118 self.assertEqual(schema, django_112)
116 self.assertRaises(ValueError, schemas.get, '1.2.0')119 self.assertRaises(ValueError, schemas.get, '1.2.0')
117120
118 self.assertEqual(mock_logging.warn.call_args_list[0][0][0],121 self.assertEqual(mock_logging.warn.call_args_list[0][0][0],
119 "No schema registered for version '1.2.0'")122 "No schema registered for version '1.2.0'")
120 self.assertEqual(mock_logging.warn.call_args_list[1][0][0],123 self.assertEqual(mock_logging.warn.call_args_list[1][0][0],
121 "Falling back to schema for version '1.1.2'")124 "Falling back to schema for version '1.1.4'")
122125
123 @patch('django_configglue.schema.logging')126 @patch('django_configglue.schema.logging')
124 def test_schemafactory_get_no_versions_registered(self, mock_logging):127 def test_schemafactory_get_no_versions_registered(self, mock_logging):
125 schemas = DjangoSchemaFactory()128 schemas = DjangoSchemaFactory()
126 try:129 try:
127 schemas.get('1.0.2', strict=False)130 schemas.get('1.0.2 final', strict=False)
128 except ValueError, e:131 except ValueError, e:
129 self.assertEqual(str(e), "No schemas registered")132 self.assertEqual(str(e), "No schemas registered")
130 else:133 else:
131 self.fail("ValueError not raised")134 self.fail("ValueError not raised")
132135
133 mock_logging.warn.assert_called_with(136 mock_logging.warn.assert_called_with(
134 "No schema registered for version '1.0.2'")137 "No schema registered for version '1.0.2 final'")
135138
136 def test_schema_versions(self):139 def test_schema_versions(self):
137 django_102 = schemas.get('1.0.2')()140 django_102 = schemas.get('1.0.2 final')()
138 django_112 = schemas.get('1.1.2')()141 django_112 = schemas.get('1.1.2')()
139 self.assertEqual(django_102.version, '1.0.2')142 self.assertEqual(django_102.version, '1.0.2 final')
140 self.assertTrue(hasattr(django_102.django, 'jing_path'))
141 self.assertEqual(django_112.version, '1.1.2')143 self.assertEqual(django_112.version, '1.1.2')
142 self.assertFalse(hasattr(django_112.django, 'jing_path'))144 self.assertFalse(django_102 is django_112)
143145
144 def test_register_without_version(self):146 def test_register_without_version(self):
145 class MySchema(BaseDjangoSchema):147 class MySchema(Schema):
146 pass148 pass
147149
148 schemas = DjangoSchemaFactory()150 schemas = DjangoSchemaFactory()
@@ -150,12 +152,13 @@
150152
151 def test_configglue(self):153 def test_configglue(self):
152 target = {}154 target = {}
153 configglue(BaseDjangoSchema, [], target)155 schema = schemas.get(django.get_version(), strict=False)
156 configglue(schema, [], target)
154 # target is consistent with django's settings module157 # target is consistent with django's settings module
155 # except for a few keys158 # except for a few keys
156 shared_key = lambda x: (not x.startswith('__') and x.upper() == x and159 shared_key = lambda x: (not x.startswith('__') and x.upper() == x and
157 x not in ('DATABASE_SUPPORTS_TRANSACTIONS', 'SETTINGS_MODULE'))160 x not in ('DATABASE_SUPPORTS_TRANSACTIONS', 'SETTINGS_MODULE'))
158 expected_keys = set(filter(shared_key, settings.get_all_members()))161 expected_keys = set(filter(shared_key, dir(settings)))
159 target_keys = set(filter(shared_key, target.keys()))162 target_keys = set(filter(shared_key, target.keys()))
160163
161 self.assertEqual(expected_keys, target_keys)164 self.assertEqual(expected_keys, target_keys)
@@ -245,3 +248,22 @@
245 self.execute()248 self.execute()
246 self.assertTrue('Show settings attributes' in self.capture['stdout'])249 self.assertTrue('Show settings attributes' in self.capture['stdout'])
247250
251
252class UpperCaseDictConfigOptionTestCase(TestCase):
253 def test_parse(self):
254 class MySchema(Schema):
255 foo = UpperCaseDictConfigOption()
256 config = StringIO(textwrap.dedent("""
257 [__main__]
258 foo = mydict
259 [mydict]
260 bar = 42
261 """))
262
263 schema = MySchema()
264 parser = SchemaConfigParser(schema)
265 parser.readfp(config)
266 result = schema.foo.parse('mydict', parser)
267
268 self.assertEqual(result, {'BAR': '42'})
269
248270
=== modified file 'django_configglue/tests/test_settings.py'
--- django_configglue/tests/test_settings.py 2011-01-17 16:01:13 +0000
+++ django_configglue/tests/test_settings.py 2011-04-13 17:14:29 +0000
@@ -36,8 +36,11 @@
36 "SETTINGS_MODULE = 'django_configglue.tests.settings'",36 "SETTINGS_MODULE = 'django_configglue.tests.settings'",
37 "SETTINGS_ENCODING = '%s'" % SETTINGS_ENCODING,37 "SETTINGS_ENCODING = '%s'" % SETTINGS_ENCODING,
38 ]38 ]
39 if django.VERSION[:2] >= (1, 1):39 django_version = django.VERSION[:2]
40 if django_version == (1, 1):
40 expected_values.append("DATABASE_SUPPORTS_TRANSACTIONS = True")41 expected_values.append("DATABASE_SUPPORTS_TRANSACTIONS = True")
42 if django_version >= (1, 1):
43 expected_values.append("JING_PATH = '/usr/bin/jing'")
41 self.call_command(show_current=True)44 self.call_command(show_current=True)
42 output_lines = self.capture['stdout'].strip().split('\n')45 output_lines = self.capture['stdout'].strip().split('\n')
43 self.assertEqual(set(expected_values), set(output_lines))46 self.assertEqual(set(expected_values), set(output_lines))
@@ -94,16 +97,15 @@
94 wrapped.__CONFIGGLUE_PARSER__ = old_CONFIGGLUE_PARSER97 wrapped.__CONFIGGLUE_PARSER__ = old_CONFIGGLUE_PARSER
9598
96 def test_wrapped_settings(self):99 def test_wrapped_settings(self):
97 old_VERSION = django.VERSION100 # the settings object has a _target attribute
98101 # this is true for versions of django <= 1.0.2
99 try:102 expected = '_target'
100 django.VERSION = (1, 0, 2)103 if django.VERSION[:3] > (1, 0, 2):
101 self.assertEqual(self.wrapped_settings, '_target')104 # the settings object has a _wrapped attribute
102105 # this is true for versions of django > 1.0.2
103 django.VERSION = (1, 1, 2)106 expected = '_wrapped'
104 self.assertEqual(self.wrapped_settings, '_wrapped')107
105 finally:108 self.assertEqual(self.wrapped_settings, expected)
106 django.VERSION = old_VERSION
107109
108110
109class ValidateCommandTestCase(ConfigGlueDjangoCommandTestCase):111class ValidateCommandTestCase(ConfigGlueDjangoCommandTestCase):
110112
=== modified file 'django_configglue/utils.py'
--- django_configglue/utils.py 2011-01-17 15:32:29 +0000
+++ django_configglue/utils.py 2011-04-13 17:14:29 +0000
@@ -55,3 +55,4 @@
55 scp = SchemaConfigParser(schema_class())55 scp = SchemaConfigParser(schema_class())
56 scp.read(configs)56 scp.read(configs)
57 update_settings(scp, target)57 update_settings(scp, target)
58 return scp
5859
=== added file 'testproject/main-12.cfg'
--- testproject/main-12.cfg 1970-01-01 00:00:00 +0000
+++ testproject/main-12.cfg 2011-04-13 17:14:29 +0000
@@ -0,0 +1,12 @@
1[django]
2database_engine = sqlite3
3database_name = :memory:
4installed_apps = django_configglue
5databases = databases
6
7[databases]
8default = db_default
9
10[db_default]
11engine = sqlite3
12name = :memory:
013
=== modified file 'testproject/main.cfg'
--- testproject/main.cfg 2010-08-06 19:27:35 +0000
+++ testproject/main.cfg 2011-04-13 17:14:29 +0000
@@ -1,4 +1,3 @@
1
2[django]1[django]
3database_engine = sqlite32database_engine = sqlite3
4database_name = :memory:3database_name = :memory:
54
=== modified file 'testproject/testrunner.py'
--- testproject/testrunner.py 2010-10-13 16:11:56 +0000
+++ testproject/testrunner.py 2011-04-13 17:14:29 +0000
@@ -11,10 +11,8 @@
1111
12 os.environ['DJANGO_SETTINGS_MODULE'] = 'testproject.settings'12 os.environ['DJANGO_SETTINGS_MODULE'] = 'testproject.settings'
1313
14 from django.conf import settings14 from django.core.management import call_command
15 from django.test.utils import get_runner
1615
17 test_runner = get_runner(settings)16 call_command('test', 'django_configglue')
18 failures = test_runner(['django_configglue'], verbosity=1, interactive=True)17 sys.exit(0)
19 sys.exit(failures)
2018
2119
=== added file 'tox'
--- tox 1970-01-01 00:00:00 +0000
+++ tox 2011-04-13 17:14:29 +0000
@@ -0,0 +1,6 @@
1#!/usr/bin/env python
2import urllib
3url = "https://pytox.googlecode.com/hg/toxbootstrap.py"
4d = dict(__file__='toxbootstrap.py')
5exec urllib.urlopen(url).read() in d
6d['cmdline'](['--recreate'])
0\ No newline at end of file7\ No newline at end of file
18
=== added file 'tox.ini'
--- tox.ini 1970-01-01 00:00:00 +0000
+++ tox.ini 2011-04-13 17:14:29 +0000
@@ -0,0 +1,47 @@
1[tox]
2envlist =
3 py26-django102,
4 py26-django104,
5 py26-django112,
6 py26-django114,
7 py26-django125,
8 py26-django13
9
10[testenv]
11commands = python setup.py test
12
13[testenv:py26-django102]
14deps =
15 configglue
16 mock
17 django==1.0.2-final
18
19[testenv:py26-django104]
20deps =
21 configglue
22 mock
23 django==1.0.4
24
25[testenv:py26-django112]
26deps =
27 configglue
28 mock
29 django==1.1.2
30
31[testenv:py26-django114]
32deps =
33 configglue
34 mock
35 django==1.1.4
36
37[testenv:py26-django125]
38deps =
39 configglue
40 mock
41 django==1.2.5
42
43[testenv:py26-django13]
44deps =
45 configglue
46 mock
47 django==1.3

Subscribers

People subscribed via source and target branches

to all changes: