diff options
author | Jannis Leidel <jannis@leidel.info> | 2012-02-20 00:29:48 +0100 |
---|---|---|
committer | Jannis Leidel <jannis@leidel.info> | 2012-02-20 00:29:48 +0100 |
commit | 01f2d55e53abd8d81a7aaa559d01027b2e6660ad (patch) | |
tree | 7de4609f3fa7f1baedbab8aeafb15b235c3488a6 | |
parent | b18b857a2dc6a4592608b49ff2c5b68016ab5ac2 (diff) | |
parent | 4a821bbcbf63ec82382422502c12147beabb6960 (diff) | |
download | django-appconf-0.5.tar.gz |
Merge branch 'release/0.5'v0.5
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | LICENSE | 2 | ||||
-rw-r--r-- | README.rst | 25 | ||||
-rw-r--r-- | appconf/__init__.py | 5 | ||||
-rw-r--r-- | appconf/base.py (renamed from appconf.py) | 28 | ||||
-rw-r--r-- | appconf/test_settings.py (renamed from tests/settings.py) | 10 | ||||
-rw-r--r-- | appconf/tests/__init__.py (renamed from tests/__init__.py) | 0 | ||||
-rw-r--r-- | appconf/tests/models.py (renamed from tests/testapp/models.py) | 2 | ||||
-rw-r--r-- | appconf/tests/settings.py | 3 | ||||
-rw-r--r-- | appconf/tests/tests.py (renamed from tests/testapp/tests.py) | 51 | ||||
-rw-r--r-- | appconf/utils.py | 22 | ||||
-rw-r--r-- | docs/changelog.rst | 11 | ||||
-rw-r--r-- | docs/conf.py | 20 | ||||
-rw-r--r-- | setup.py | 34 | ||||
-rw-r--r-- | tests/testapp/__init__.py | 0 | ||||
-rw-r--r-- | tests/tox.ini | 58 | ||||
-rw-r--r-- | tox.ini | 64 |
17 files changed, 210 insertions, 129 deletions
@@ -6,5 +6,5 @@ MANIFEST .tox/ *.egg docs/_build/ -tests/.coverage -tests/.tox
\ No newline at end of file +reports/ +.tox @@ -1,4 +1,4 @@ -Copyright (c) 2011, Jannis Leidel and individual contributors. +Copyright (c) 2011-2012, Jannis Leidel and individual contributors. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -67,3 +67,28 @@ In case you want to use a different settings object instead of the default class Meta: prefix = 'acme' holder = 'acme.conf.settings' + +If you ship an ``AppConf`` class with your reusable Django app, it's +recommended to put it in a ``conf.py`` file of you app package and +import ``django.conf.settings`` in it, too:: + + from django.conf import settings + from appconf import AppConf + + class MyAppConf(AppConf): + SETTING_1 = "one" + SETTING_2 = ( + "two", + ) + +In the other files of your app you can easily make sure the settings +are correctly loaded if you import Django's settings object from that +module, e.g. in your app's ``views.py``:: + + from django.http import HttpResponse + from myapp.conf import settings + + def index(request): + text = 'Setting 1 is: %s' % settings.MYAPP_SETTING_1 + return HttpResponse(text) + diff --git a/appconf/__init__.py b/appconf/__init__.py new file mode 100644 index 0000000..eddc0ae --- /dev/null +++ b/appconf/__init__.py @@ -0,0 +1,5 @@ +from __future__ import absolute_import +from .base import AppConf # noqa + +# following PEP 386 +__version__ = "0.5" diff --git a/appconf.py b/appconf/base.py index 2c2e6a6..80eb233 100644 --- a/appconf.py +++ b/appconf/base.py @@ -1,7 +1,5 @@ import sys - -# following PEP 386, versiontools will pick it up -__version__ = (0, 4, 1, "final", 0) +from .utils import import_attribute class AppConfOptions(object): @@ -56,7 +54,8 @@ class AppConfMetaClass(type): if hasattr(parent, '_meta'): new_class._meta.names.update(parent._meta.names) new_class._meta.defaults.update(parent._meta.defaults) - new_class._meta.configured_data.update(parent._meta.configured_data) + new_class._meta.configured_data.update( + parent._meta.configured_data) for name in filter(lambda name: name == name.upper(), attrs): prefixed_name = new_class._meta.prefixed_name(name) @@ -93,27 +92,6 @@ class AppConfMetaClass(type): cls._meta.configured_data = obj.configure() -def import_attribute(import_path, exception_handler=None): - from django.utils.importlib import import_module - module_name, object_name = import_path.rsplit('.', 1) - try: - module = import_module(module_name) - except: # pragma: no cover - if callable(exception_handler): - exctype, excvalue, tb = sys.exc_info() - return exception_handler(import_path, exctype, excvalue, tb) - else: - raise - try: - return getattr(module, object_name) - except: # pragma: no cover - if callable(exception_handler): - exctype, excvalue, tb = sys.exc_info() - return exception_handler(import_path, exctype, excvalue, tb) - else: - raise - - class AppConf(object): """ An app setting object to be used for handling app setting defaults diff --git a/tests/settings.py b/appconf/test_settings.py index c23374c..263a0aa 100644 --- a/tests/settings.py +++ b/appconf/test_settings.py @@ -12,5 +12,13 @@ INSTALLED_APPS = [ 'django.contrib.sites', 'django.contrib.auth', 'django.contrib.admin', - 'tests.testapp', + 'django_jenkins', + 'appconf.tests', ] + +JENKINS_TASKS = ( + 'django_jenkins.tasks.run_pyflakes', + 'django_jenkins.tasks.run_pep8', + 'django_jenkins.tasks.with_coverage', + 'django_jenkins.tasks.django_tests', +) diff --git a/tests/__init__.py b/appconf/tests/__init__.py index e69de29..e69de29 100644 --- a/tests/__init__.py +++ b/appconf/tests/__init__.py diff --git a/tests/testapp/models.py b/appconf/tests/models.py index 99dc4de..cb96f83 100644 --- a/tests/testapp/models.py +++ b/appconf/tests/models.py @@ -61,5 +61,5 @@ class CustomHolderConf(AppConf): SIMPLE_VALUE = True class Meta: - holder = 'testapp.models.custom_holder' # instead of django.conf.settings + holder = 'appconf.tests.models.custom_holder' # instead of django.conf.settings prefix = 'custom_holder' diff --git a/appconf/tests/settings.py b/appconf/tests/settings.py new file mode 100644 index 0000000..ef7df4e --- /dev/null +++ b/appconf/tests/settings.py @@ -0,0 +1,3 @@ +SIMPLE_VALUE = True + +CONFIGURED_VALUE = 'wrong' diff --git a/tests/testapp/tests.py b/appconf/tests/tests.py index dbec07a..45738a6 100644 --- a/tests/testapp/tests.py +++ b/appconf/tests/tests.py @@ -1,58 +1,59 @@ +from __future__ import absolute_import from django.conf import settings from django.test import TestCase -from testapp.models import (TestConf, PrefixConf, YetAnotherPrefixConf, - SeparateConf, ProxyConf, CustomHolderConf, - custom_holder) +from .models import (TestConf, PrefixConf, YetAnotherPrefixConf, + SeparateConf, ProxyConf, CustomHolderConf, + custom_holder) class TestConfTests(TestCase): def test_basic(self): - self.assertEquals(TestConf._meta.prefix, 'testapp') + self.assertEquals(TestConf._meta.prefix, 'tests') def test_simple(self): - self.assertTrue(hasattr(settings, 'TESTAPP_SIMPLE_VALUE')) - self.assertEquals(settings.TESTAPP_SIMPLE_VALUE, True) + self.assertTrue(hasattr(settings, 'TESTS_SIMPLE_VALUE')) + self.assertEquals(settings.TESTS_SIMPLE_VALUE, True) def test_configured(self): - self.assertTrue(hasattr(settings, 'TESTAPP_CONFIGURED_VALUE')) - self.assertEquals(settings.TESTAPP_CONFIGURED_VALUE, 'correct') + self.assertTrue(hasattr(settings, 'TESTS_CONFIGURED_VALUE')) + self.assertEquals(settings.TESTS_CONFIGURED_VALUE, 'correct') def test_configure_method(self): - self.assertTrue(hasattr(settings, 'TESTAPP_CONFIGURE_METHOD_VALUE')) - self.assertEquals(settings.TESTAPP_CONFIGURE_METHOD_VALUE, True) + self.assertTrue(hasattr(settings, 'TESTS_CONFIGURE_METHOD_VALUE')) + self.assertEquals(settings.TESTS_CONFIGURE_METHOD_VALUE, True) def test_init_kwargs(self): custom_conf = TestConf(CUSTOM_VALUE='custom') self.assertEquals(custom_conf.CUSTOM_VALUE, 'custom') - self.assertEquals(settings.TESTAPP_CUSTOM_VALUE, 'custom') - self.assertRaises(AttributeError, lambda: custom_conf.TESTAPP_CUSTOM_VALUE) + self.assertEquals(settings.TESTS_CUSTOM_VALUE, 'custom') + self.assertRaises(AttributeError, lambda: custom_conf.TESTS_CUSTOM_VALUE) custom_conf.CUSTOM_VALUE_SETATTR = 'custom' - self.assertEquals(settings.TESTAPP_CUSTOM_VALUE_SETATTR, 'custom') + self.assertEquals(settings.TESTS_CUSTOM_VALUE_SETATTR, 'custom') custom_conf.custom_value_lowercase = 'custom' self.assertRaises(AttributeError, lambda: settings.custom_value_lowercase) def test_init_kwargs_with_prefix(self): - custom_conf = TestConf(TESTAPP_CUSTOM_VALUE2='custom2') - self.assertEquals(custom_conf.TESTAPP_CUSTOM_VALUE2, 'custom2') - self.assertEquals(settings.TESTAPP_CUSTOM_VALUE2, 'custom2') + custom_conf = TestConf(TESTS_CUSTOM_VALUE2='custom2') + self.assertEquals(custom_conf.TESTS_CUSTOM_VALUE2, 'custom2') + self.assertEquals(settings.TESTS_CUSTOM_VALUE2, 'custom2') def test_proxy(self): custom_conf = ProxyConf(CUSTOM_VALUE3='custom3') self.assertEquals(custom_conf.CUSTOM_VALUE3, 'custom3') - self.assertEquals(settings.TESTAPP_CUSTOM_VALUE3, 'custom3') - self.assertEquals(custom_conf.TESTAPP_CUSTOM_VALUE3, 'custom3') - self.assertTrue('tests.testapp' in custom_conf.INSTALLED_APPS) + self.assertEquals(settings.TESTS_CUSTOM_VALUE3, 'custom3') + self.assertEquals(custom_conf.TESTS_CUSTOM_VALUE3, 'custom3') + self.assertTrue('appconf.tests' in custom_conf.INSTALLED_APPS) def test_dir_members(self): custom_conf = TestConf() - self.assertTrue('TESTAPP_SIMPLE_VALUE' in dir(settings)) - self.assertTrue('TESTAPP_SIMPLE_VALUE' in settings.__members__) + self.assertTrue('TESTS_SIMPLE_VALUE' in dir(settings)) + self.assertTrue('TESTS_SIMPLE_VALUE' in settings.__members__) self.assertTrue('SIMPLE_VALUE' in dir(custom_conf)) self.assertTrue('SIMPLE_VALUE' in custom_conf.__members__) - self.assertFalse('TESTAPP_SIMPLE_VALUE' in dir(custom_conf)) - self.assertFalse('TESTAPP_SIMPLE_VALUE' in custom_conf.__members__) + self.assertFalse('TESTS_SIMPLE_VALUE' in dir(custom_conf)) + self.assertFalse('TESTS_SIMPLE_VALUE' in custom_conf.__members__) def test_custom_holder(self): custom_conf = CustomHolderConf() @@ -60,8 +61,8 @@ class TestConfTests(TestCase): self.assertEquals(custom_holder.CUSTOM_HOLDER_SIMPLE_VALUE, True) def test_subclass_configured_data(self): - self.assertTrue('TESTAPP_CONFIGURE_METHOD_VALUE2' in dir(settings)) - self.assertEquals(settings.TESTAPP_CONFIGURE_METHOD_VALUE2, False) + self.assertTrue('TESTS_CONFIGURE_METHOD_VALUE2' in dir(settings)) + self.assertEquals(settings.TESTS_CONFIGURE_METHOD_VALUE2, False) class PrefixConfTests(TestCase): diff --git a/appconf/utils.py b/appconf/utils.py new file mode 100644 index 0000000..e8f911c --- /dev/null +++ b/appconf/utils.py @@ -0,0 +1,22 @@ +import sys + + +def import_attribute(import_path, exception_handler=None): + from django.utils.importlib import import_module + module_name, object_name = import_path.rsplit('.', 1) + try: + module = import_module(module_name) + except: # pragma: no cover + if callable(exception_handler): + exctype, excvalue, tb = sys.exc_info() + return exception_handler(import_path, exctype, excvalue, tb) + else: + raise + try: + return getattr(module, object_name) + except: # pragma: no cover + if callable(exception_handler): + exctype, excvalue, tb = sys.exc_info() + return exception_handler(import_path, exctype, excvalue, tb) + else: + raise diff --git a/docs/changelog.rst b/docs/changelog.rst index 8a8a4a7..7479402 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,17 @@ Changelog ========= +0.5 (2012-02-20) +---------------- + +* Install as a package instead of a module. + +* Refactored tests to use `django-jenkins`_ for `enn.io`_'s `CI server`_. + +.. _`django-jenkins`: https://github.com/kmmbvnr/django-jenkins +.. _`enn.io`: http://enn.io +.. _`CI server`: https://ci.enn.io/job/django-appconf/ + 0.4.1 (2011-09-09) ------------------ diff --git a/docs/conf.py b/docs/conf.py index e18f46b..b919253 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -41,16 +41,20 @@ master_doc = 'index' # General information about the project. project = u'django-appconf' -copyright = u'2011, Jannis Leidel and individual contributors' +copyright = u'2011-2012, Jannis Leidel and individual contributors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # -# The short X.Y version. -version = '0.4' -# The full version, including alpha/beta/rc tags. -release = '0.4.1' +try: + from appconf import __version__ + # The short X.Y version. + version = '.'.join(__version__.split('.')[:2]) + # The full version, including alpha/beta/rc tags. + release = __version__ +except ImportError: + version = release = 'dev' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -217,4 +221,8 @@ man_pages = [ # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'http://docs.python.org/': None} +intersphinx_mapping = { + 'python': ('http://python.readthedocs.org/en/v2.7.2/', None), + 'django': ('http://django.readthedocs.org/en/latest/', None), + 'celery': ('http://celery.readthedocs.org/en/latest/', None), +} @@ -1,22 +1,39 @@ -from os import path import codecs +import re +from os import path from setuptools import setup -read = lambda filepath: codecs.open(filepath, 'r', 'utf-8').read() + +def read(*parts): + file_path = path.join(path.dirname(__file__), *parts) + return open(file_path).read() + + +def find_version(*parts): + version_file = read(*parts) + version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", + version_file, re.M) + if version_match: + return version_match.group(1) + raise RuntimeError("Unable to find version string.") + setup( name='django-appconf', - version=":versiontools:appconf:", + version=find_version('appconf', '__init__.py'), description='A helper class for handling configuration defaults ' 'of packaged apps gracefully.', - long_description=read(path.join(path.dirname(__file__), 'README.rst')), + long_description=read('README.rst'), author='Jannis Leidel', author_email='jannis@leidel.info', - license = 'BSD', + license='BSD', url='http://django-appconf.readthedocs.org/', - py_modules=['appconf'], + packages=[ + 'appconf', + 'appconf.tests', + ], classifiers=[ - "Development Status :: 4 - Beta", + 'Development Status :: 4 - Beta', 'Environment :: Web Environment', 'Framework :: Django', 'Intended Audience :: Developers', @@ -28,7 +45,4 @@ setup( 'Programming Language :: Python :: 2.7', 'Topic :: Utilities', ], - setup_requires=[ - 'versiontools >= 1.6', - ], ) diff --git a/tests/testapp/__init__.py b/tests/testapp/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/tests/testapp/__init__.py +++ /dev/null diff --git a/tests/tox.ini b/tests/tox.ini deleted file mode 100644 index 646f10f..0000000 --- a/tests/tox.ini +++ /dev/null @@ -1,58 +0,0 @@ -[tox] -setupdir = .. -distribute = false - -[testenv] -recreate = True -commands = - {envbindir}/coverage erase - {envbindir}/coverage run --branch --source=appconf {envbindir}/django-admin.py test {posargs:testapp} --settings=settings - {envbindir}/coverage report --omit=*test* - {envbindir}/coverage html --omit=*test* -d {envtmpdir} - echo "Type the following to open the coverage report: python -m webbrowser -t file://{envtmpdir}/index.html" -downloadcache = {toxworkdir}/_download/ - -[testenv:docs] -changedir = ../docs -deps = - Sphinx -commands = - make clean - make html - -[testenv:py25-1.2.X] -basepython = python2.5 -deps = - coverage - django==1.2.5 - -[testenv:py26-1.2.X] -basepython = python2.6 -deps = - coverage - django==1.2.5 - -[testenv:py27-1.2.X] -basepython = python2.7 -deps = - coverage - django==1.2.5 - - -[testenv:py25-1.3.X] -basepython = python2.5 -deps = - coverage - django==1.3 - -[testenv:py26-1.3.X] -basepython = python2.6 -deps = - coverage - django==1.3 - -[testenv:py27-1.3.X] -basepython = python2.7 -deps = - coverage - django==1.3 @@ -0,0 +1,64 @@ +[testenv] +downloadcache = {toxworkdir}/_download/ +commands = + {envbindir}/python {envbindir}/django-admin.py jenkins {posargs:tests} +setenv = + DJANGO_SETTINGS_MODULE = appconf.test_settings + +[testenv:docs] +basepython = python2.7 +deps = + Sphinx==1.0.7 + Django==1.3.1 +commands = + rm -rf docs/_build + {envbindir}/sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html + +[testenv:py25-1.2.X] +basepython = python2.5 +deps = + django==1.2.5 + pep8 + pyflakes + django-jenkins + +[testenv:py26-1.2.X] +basepython = python2.6 +deps = + django==1.2.5 + pep8 + pyflakes + django-jenkins + +[testenv:py27-1.2.X] +basepython = python2.7 +deps = + django==1.2.5 + pep8 + pyflakes + django-jenkins + + +[testenv:py25-1.3.X] +basepython = python2.5 +deps = + django==1.3 + pep8 + pyflakes + django-jenkins + +[testenv:py26-1.3.X] +basepython = python2.6 +deps = + django==1.3 + pep8 + pyflakes + django-jenkins + +[testenv:py27-1.3.X] +basepython = python2.7 +deps = + django==1.3 + pep8 + pyflakes + django-jenkins |