From 8a8f99ab68b958a9382fc607a0cfe5c9b038d394 Mon Sep 17 00:00:00 2001 From: joke2k Date: Thu, 17 Apr 2014 16:22:31 +0200 Subject: [PATCH 1/3] add *.pyc to .gitignore; remove repeated INSTALLED_APPS from test_project.settings; fix check dj-database-url returned None values to empty string --- .gitignore | 3 ++- test_project/test_project/settings.py | 14 -------------- tests/test_values.py | 8 ++++---- 3 files changed, 6 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index 4401d89..636d3f0 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ docs/_build *.egg test.db build/ -.tox/ \ No newline at end of file +.tox/ +*.pyc diff --git a/test_project/test_project/settings.py b/test_project/test_project/settings.py index 334cee6..1ffe526 100644 --- a/test_project/test_project/settings.py +++ b/test_project/test_project/settings.py @@ -160,20 +160,6 @@ class Base(Configuration): } } - INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.messages', - 'django.contrib.staticfiles', - # Uncomment the next line to enable the admin: - # 'django.contrib.admin', - # Uncomment the next line to enable admin documentation: - # 'django.contrib.admindocs', - 'configurations', - ) - class Debug(Base): YEAH = True diff --git a/tests/test_values.py b/tests/test_values.py index ad1ed90..314529d 100644 --- a/tests/test_values.py +++ b/tests/test_values.py @@ -246,11 +246,11 @@ class ValueTests(TestCase): self.assertEqual(value.setup('DATABASE_URL'), { 'default': { 'ENGINE': 'django.db.backends.sqlite3', - 'HOST': None, + 'HOST': '', 'NAME': ':memory:', - 'PASSWORD': None, - 'PORT': None, - 'USER': None, + 'PASSWORD': '', + 'PORT': '', + 'USER': '', }}) def test_email_url_value(self): From 5279ae4acebf5da4cec9ddd63d2c67a36054df28 Mon Sep 17 00:00:00 2001 From: joke2k Date: Thu, 17 Apr 2014 16:23:36 +0200 Subject: [PATCH 2/3] add support to load .env file into os.environ --- configurations/base.py | 33 +++++++++++++++++++++++++++++++++ test_project/.env | 1 + tests/settings/main.py | 5 +++++ tests/test_env.py | 10 ++++++++++ 4 files changed, 49 insertions(+) create mode 100644 test_project/.env create mode 100644 tests/test_env.py diff --git a/configurations/base.py b/configurations/base.py index 8601c73..b4ea2ab 100644 --- a/configurations/base.py +++ b/configurations/base.py @@ -41,6 +41,39 @@ class ConfigurationBase(type): return "".format(self.__module__, self.__name__) + @staticmethod + def read_env(env_file='.env', **overrides): + """ + Pulled from Honcho code with minor updates, reads local default + environment variables from a .env file located in the project root + directory. + + http://www.wellfireinteractive.com/blog/easier-12-factor-django/ + https://gist.github.com/bennylope/2999704 + """ + import re + import os + + with open(env_file) as f: + content = f.read() + + for line in content.splitlines(): + m1 = re.match(r'\A([A-Za-z_0-9]+)=(.*)\Z', line) + if not m1: + continue + key, val = m1.group(1), m1.group(2) + m2 = re.match(r"\A'(.*)'\Z", val) + if m2: + val = m2.group(1) + m3 = re.match(r'\A"(.*)"\Z', val) + if m3: + val = re.sub(r'\\(.)', r'\1', m3.group(1)) + os.environ.setdefault(key, val) + + # set defaults + for key, value in overrides.items(): + os.environ.setdefault(key, value) + class Configuration(six.with_metaclass(ConfigurationBase)): """ diff --git a/test_project/.env b/test_project/.env new file mode 100644 index 0000000..977f829 --- /dev/null +++ b/test_project/.env @@ -0,0 +1 @@ +DJANGO_ENV_LOADED=True \ No newline at end of file diff --git a/tests/settings/main.py b/tests/settings/main.py index dd425fd..9693f5b 100644 --- a/tests/settings/main.py +++ b/tests/settings/main.py @@ -3,9 +3,13 @@ import uuid import django from configurations import Configuration, pristinemethod +from configurations.values import BooleanValue class Test(Configuration): + + ENV_LOADED = BooleanValue(False) + DEBUG = True SITE_ID = 1 @@ -60,6 +64,7 @@ class Test(Configuration): @classmethod def pre_setup(cls): cls.PRE_SETUP_TEST_SETTING = 6 + cls.read_env('test_project/.env') @classmethod def post_setup(cls): diff --git a/tests/test_env.py b/tests/test_env.py new file mode 100644 index 0000000..637f188 --- /dev/null +++ b/tests/test_env.py @@ -0,0 +1,10 @@ +import os +from django.test import TestCase +from configurations.values import BooleanValue +from mock import patch + +class EnvValueTests(TestCase): + + def test_env_loaded(self): + check_value = BooleanValue(False) + self.assertEqual(check_value.setup('ENV_LOADED'), True) \ No newline at end of file From 27eb748d68f4593643804c2ff03e6438ea0c091a Mon Sep 17 00:00:00 2001 From: joke2k Date: Thu, 17 Apr 2014 18:07:33 +0200 Subject: [PATCH 3/3] refactoring of DotConfiguration --- configurations/__init__.py | 4 +- configurations/base.py | 80 ++++++++++++++++----------- test_project/test_project/settings.py | 2 +- tests/settings/dot_env.py | 6 ++ tests/settings/main.py | 1 - tests/test_env.py | 11 ++-- 6 files changed, 63 insertions(+), 41 deletions(-) create mode 100644 tests/settings/dot_env.py diff --git a/configurations/__init__.py b/configurations/__init__.py index 1ae1e42..373fa53 100644 --- a/configurations/__init__.py +++ b/configurations/__init__.py @@ -1,9 +1,9 @@ # flake8: noqa -from .base import Settings, Configuration +from .base import Settings, Configuration, DotConfiguration from .decorators import pristinemethod __version__ = '0.8' -__all__ = ['Configuration', 'pristinemethod', 'Settings'] +__all__ = ['Configuration', 'DotConfiguration', 'pristinemethod', 'Settings'] def load_ipython_extension(ipython): diff --git a/configurations/base.py b/configurations/base.py index b4ea2ab..658cf12 100644 --- a/configurations/base.py +++ b/configurations/base.py @@ -41,39 +41,6 @@ class ConfigurationBase(type): return "".format(self.__module__, self.__name__) - @staticmethod - def read_env(env_file='.env', **overrides): - """ - Pulled from Honcho code with minor updates, reads local default - environment variables from a .env file located in the project root - directory. - - http://www.wellfireinteractive.com/blog/easier-12-factor-django/ - https://gist.github.com/bennylope/2999704 - """ - import re - import os - - with open(env_file) as f: - content = f.read() - - for line in content.splitlines(): - m1 = re.match(r'\A([A-Za-z_0-9]+)=(.*)\Z', line) - if not m1: - continue - key, val = m1.group(1), m1.group(2) - m2 = re.match(r"\A'(.*)'\Z", val) - if m2: - val = m2.group(1) - m3 = re.match(r'\A"(.*)"\Z', val) - if m3: - val = re.sub(r'\\(.)', r'\1', m3.group(1)) - os.environ.setdefault(key, val) - - # set defaults - for key, value in overrides.items(): - os.environ.setdefault(key, value) - class Configuration(six.with_metaclass(ConfigurationBase)): """ @@ -114,6 +81,53 @@ class Configuration(six.with_metaclass(ConfigurationBase)): setup_value(cls, name, value) +class DotConfiguration(Configuration): + + DOT_ENV = None + DOT_ENV_LOADED = False + + @classmethod + def pre_setup(cls): + Configuration.pre_setup() + if not cls.DOT_ENV_LOADED and cls.DOT_ENV: + cls.read_env(cls.DOT_ENV) + + @classmethod + def read_env(cls, env_file='.env', **overrides): + """ + Pulled from Honcho code with minor updates, reads local default + environment variables from a .env file located in the project root + or provided directory. + + http://www.wellfireinteractive.com/blog/easier-12-factor-django/ + https://gist.github.com/bennylope/2999704 + """ + import re + import os + + with open(env_file) as f: + content = f.read() + + for line in content.splitlines(): + m1 = re.match(r'\A([A-Za-z_0-9]+)=(.*)\Z', line) + if not m1: + continue + key, val = m1.group(1), m1.group(2) + m2 = re.match(r"\A'(.*)'\Z", val) + if m2: + val = m2.group(1) + m3 = re.match(r'\A"(.*)"\Z', val) + if m3: + val = re.sub(r'\\(.)', r'\1', m3.group(1)) + os.environ.setdefault(key, val) + + # set defaults + for key, value in overrides.items(): + os.environ.setdefault(key, value) + + cls.DOT_ENV_LOADED = True + + class Settings(Configuration): @classmethod diff --git a/test_project/test_project/settings.py b/test_project/test_project/settings.py index 1ffe526..db6500c 100644 --- a/test_project/test_project/settings.py +++ b/test_project/test_project/settings.py @@ -1,7 +1,7 @@ from configurations import Configuration, values -class Base(Configuration): +class Base(DotConfiguration): # Django settings for test_project project. DEBUG = values.BooleanValue(True, environ=True) diff --git a/tests/settings/dot_env.py b/tests/settings/dot_env.py new file mode 100644 index 0000000..6d7acbb --- /dev/null +++ b/tests/settings/dot_env.py @@ -0,0 +1,6 @@ +from configurations import DotConfiguration + + +class DotEnvConfiguration(DotConfiguration): + + DOT_ENV = 'test_project/.env' diff --git a/tests/settings/main.py b/tests/settings/main.py index 9693f5b..d646271 100644 --- a/tests/settings/main.py +++ b/tests/settings/main.py @@ -64,7 +64,6 @@ class Test(Configuration): @classmethod def pre_setup(cls): cls.PRE_SETUP_TEST_SETTING = 6 - cls.read_env('test_project/.env') @classmethod def post_setup(cls): diff --git a/tests/test_env.py b/tests/test_env.py index 637f188..70e7a53 100644 --- a/tests/test_env.py +++ b/tests/test_env.py @@ -1,10 +1,13 @@ import os from django.test import TestCase -from configurations.values import BooleanValue from mock import patch -class EnvValueTests(TestCase): +class DotEnvLoadingTests(TestCase): + + @patch.dict(os.environ, clear=True, + DJANGO_CONFIGURATION='DotEnvConfiguration', + DJANGO_SETTINGS_MODULE='tests.settings.dot_env') def test_env_loaded(self): - check_value = BooleanValue(False) - self.assertEqual(check_value.setup('ENV_LOADED'), True) \ No newline at end of file + from tests.settings import dot_env + self.assertTrue(dot_env.DOT_ENV_LOADED) \ No newline at end of file