summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJannis Leidel <jannis@leidel.info>2012-02-20 00:29:48 +0100
committerJannis Leidel <jannis@leidel.info>2012-02-20 00:29:48 +0100
commit01f2d55e53abd8d81a7aaa559d01027b2e6660ad (patch)
tree7de4609f3fa7f1baedbab8aeafb15b235c3488a6
parentb18b857a2dc6a4592608b49ff2c5b68016ab5ac2 (diff)
parent4a821bbcbf63ec82382422502c12147beabb6960 (diff)
downloaddjango-appconf-0.5.tar.gz
Merge branch 'release/0.5'v0.5
-rw-r--r--.gitignore4
-rw-r--r--LICENSE2
-rw-r--r--README.rst25
-rw-r--r--appconf/__init__.py5
-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.py3
-rw-r--r--appconf/tests/tests.py (renamed from tests/testapp/tests.py)51
-rw-r--r--appconf/utils.py22
-rw-r--r--docs/changelog.rst11
-rw-r--r--docs/conf.py20
-rw-r--r--setup.py34
-rw-r--r--tests/testapp/__init__.py0
-rw-r--r--tests/tox.ini58
-rw-r--r--tox.ini64
17 files changed, 210 insertions, 129 deletions
diff --git a/.gitignore b/.gitignore
index 79f56c0..ae0531e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,5 +6,5 @@ MANIFEST
.tox/
*.egg
docs/_build/
-tests/.coverage
-tests/.tox \ No newline at end of file
+reports/
+.tox
diff --git a/LICENSE b/LICENSE
index a8d4cc9..51e70c3 100644
--- a/LICENSE
+++ b/LICENSE
@@ -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
diff --git a/README.rst b/README.rst
index 97de9bb..f01ffe0 100644
--- a/README.rst
+++ b/README.rst
@@ -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),
+}
diff --git a/setup.py b/setup.py
index 764cfe8..8766d43 100644
--- a/setup.py
+++ b/setup.py
@@ -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
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..6b5e296
--- /dev/null
+++ b/tox.ini
@@ -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