Skip to content

Commit

Permalink
Fix namespace swithc in django apps
Browse files Browse the repository at this point in the history
  • Loading branch information
rochacbruno committed May 21, 2018
1 parent da8c501 commit ad1e583
Show file tree
Hide file tree
Showing 14 changed files with 219 additions and 25 deletions.
4 changes: 4 additions & 0 deletions HISTORY
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ Changelog

These are all the changes in Dynaconf since the first public release.

0.7.6
-----
- Namespace switching fix (for django extension)

0.7.5
-----
- Added django extension
Expand Down
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ test_examples:
@cd example/;pwd;python full_example.py | grep -c full_example
@cd example/;pwd;python compat.py
@cd example/app;pwd;python app.py | grep -c app
@cd example/namespaces;pwd;python app.py
@cd example/app_with_dotenv;pwd;python app.py | grep -c app_with_dotenv
@cd example/multiple_sources;pwd;python app.py | grep -c multiple_sources
@cd example/toml_example/settings_module/;pwd;python app.py | grep -c toml_example
@cd example/toml_example/;pwd;python app.py | grep -c toml_example
@cd example/yaml_example/settings_module/;pwd;python app.py | grep -c yaml_example
@cd example/yaml_example/yaml_as_extra_config/;pwd;python app.py | grep -c yaml_as_extra_config
@cd example/flask_with_dotenv;pwd;flask routes | grep -c flask_with_dotenv
Expand Down Expand Up @@ -50,6 +51,7 @@ clean:
rm -rf dist
rm -rf *.egg-info
rm -rf htmlcov
rm -rf .tox/
python setup.py develop

doc:
Expand Down
4 changes: 2 additions & 2 deletions dynaconf/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ def loaded_by_loaders(self):
return self._loaded_by_loaders

@contextmanager
def using_namespace(self, namespace, clean=True, silent=False):
def using_namespace(self, namespace, clean=True, silent=True):
"""
This context manager allows the contextual use of a different namespace
Example:
Expand All @@ -344,7 +344,7 @@ def using_namespace(self, namespace, clean=True, silent=False):
self.logger.debug("In Namespace: %s", namespace)
yield
finally:
if namespace != self.NAMESPACE_FOR_DYNACONF:
if namespace.lower() != self.NAMESPACE_FOR_DYNACONF.lower():
del self.loaded_namespaces[-1]
self.logger.debug("Out Namespace: %s", namespace)
self.namespace(self.current_namespace, clean=clean)
Expand Down
2 changes: 1 addition & 1 deletion example/django_example/.env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
DYNACONF_SERVER='prod_server_fromenv.com'
DEV_SERVER='dev_server_fromenv.com'
# switch namespaces or omit to default to DYNACONF
NAMESPACE_FOR_DYNACONF=dev
# NAMESPACE_FOR_DYNACONF=dev
2 changes: 1 addition & 1 deletion example/django_example/.secrets.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[dynaconf]
[dev]
password = 'My5up3r53c4et'
15 changes: 12 additions & 3 deletions example/django_example/polls/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,17 @@
class SettingsTest(TestCase):

def test_settings(self):
self.assertEqual(settings.SERVER, 'dev_server_fromenv.com')
self.assertEqual(settings.SERVER, 'prod_server_fromenv.com')
self.assertEqual(
settings.STATIC_URL, '/changed/in/settings.toml/by/dynaconf/')
self.assertEqual(settings.USERNAME, 'dev user')
self.assertEqual(settings.PASSWORD, 'My5up3r53c4et')
self.assertEqual(settings.USERNAME, 'prod user')
self.assertEqual(settings.PASSWORD, False)

with settings.using_namespace('dev'):
self.assertEqual(settings.SERVER, 'dev_server_fromenv.com')
self.assertEqual(settings.PASSWORD, 'My5up3r53c4et')
self.assertEqual(settings.USERNAME, 'dev user')

self.assertEqual(settings.SERVER, 'prod_server_fromenv.com')
self.assertEqual(settings.PASSWORD, False)
self.assertEqual(settings.USERNAME, 'prod user')
18 changes: 8 additions & 10 deletions example/django_example/polls/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ def index(request):
tests.append("""<pre>[dynaconf]
server = 'foo.com'
username = 'prod user'
password = false
password = false # in prod this value must come from .secrets.toml or vault server
STATIC_URL = '/changed/in/settings.toml/by/dynaconf/'
[dev]
username = 'dev user'</pre>
""")
tests.append('<b>.secrets.toml</b>')
tests.append("""<pre>[dynaconf]
tests.append("""<pre>[dev]
password = 'My5up3r53c4et'</pre>
""")

Expand All @@ -34,14 +34,12 @@ def index(request):
tests.append(f"settings.USERNAME: {settings.USERNAME}")
tests.append(f"settings.PASSWORD: {settings.PASSWORD}")

# # Django threading is having problems with namespace switch
# # using the .namespace method
# with settings.using_namespace('dev'):
# tests.append('<b>$ In dev namespace</b>')
# tests.append(f"settings.STATIC_URL: {settings.STATIC_URL}")
# tests.append(f"settings.SERVER: {settings.SERVER}")
# tests.append(f"settings.USERNAME: {settings.USERNAME}")
# tests.append(f"settings.PASSWORD: {settings.PASSWORD}")
with settings.using_namespace('dev'):
tests.append('<b>$ In dev namespace</b>')
tests.append(f"settings.STATIC_URL: {settings.STATIC_URL}")
tests.append(f"settings.SERVER: {settings.SERVER}")
tests.append(f"settings.USERNAME: {settings.USERNAME}")
tests.append(f"settings.PASSWORD: {settings.PASSWORD}")

# settings.namespace('dev')
return HttpResponse(
Expand Down
2 changes: 1 addition & 1 deletion example/django_example/settings.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[dynaconf]
server = 'foo.com'
username = 'prod user'
password = false
password = false # in prod this value must come from .secrets.toml or vault server
STATIC_URL = '/changed/in/settings.toml/by/dynaconf/'
[dev]
username = 'dev user'
141 changes: 141 additions & 0 deletions example/namespaces/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
from dynaconf import settings


print('# 1 all values in {} + {}: namespace of yaml file:'.format(
settings.BASE_NAMESPACE_FOR_DYNACONF,
settings.current_namespace))
assert settings.current_namespace == 'DEVELOPMENT'
print('HOST::', settings.HOST)
print('PORT:', settings.PORT)
print('USERNAME:', settings.USERNAME)
print('PASSWORD:', settings.PASSWORD)
print('LEVELS:', settings.LEVELS)
print('TEST_LOADERS:', settings.TEST_LOADERS)
print('MONEY:', settings.MONEY)
print('AGE:', settings.AGE)
print('ENABLED:', settings.ENABLED)
print('ENVIRONMENT:', settings.get('ENVIRONMENT'))
print('WORKS:', settings.WORKS)

with settings.using_namespace('TESTING'):
print('# 2 using {}: namespace values for context:'.format(
settings.current_namespace))
assert settings.current_namespace == 'TESTING'
print('HOST::', settings.HOST)
print('PORT:', settings.PORT)
print('USERNAME:', settings.USERNAME)
print('PASSWORD:', settings.PASSWORD)
print('LEVELS:', settings.LEVELS)
print('TEST_LOADERS:', settings.TEST_LOADERS)
print('MONEY:', settings.MONEY)
print('AGE:', settings.AGE)
print('ENABLED:', settings.ENABLED)
print('ENVIRONMENT:', settings.get('ENVIRONMENT'))
print('WORKS:', settings.WORKS)

print('# 3 back to default {}: namespace:'.format(settings.current_namespace))
assert settings.current_namespace == 'DEVELOPMENT'
print('HOST::', settings.HOST)
print('PORT:', settings.PORT)
print('USERNAME:', settings.USERNAME)
print('PASSWORD:', settings.PASSWORD)
print('LEVELS:', settings.LEVELS)
print('TEST_LOADERS:', settings.TEST_LOADERS)
print('MONEY:', settings.MONEY)
print('AGE:', settings.AGE)
print('ENABLED:', settings.ENABLED)
print('ENVIRONMENT:', settings.get('ENVIRONMENT'))
print('WORKS:', settings.WORKS)

settings.namespace('testing')
print('# 4 Set to {}: namespace:'.format(settings.current_namespace))
assert settings.current_namespace == 'TESTING'
print('HOST::', settings.HOST)
print('PORT:', settings.PORT)
print('USERNAME:', settings.USERNAME)
print('PASSWORD:', settings.PASSWORD)
print('LEVELS:', settings.LEVELS)
print('TEST_LOADERS:', settings.TEST_LOADERS)
print('MONEY:', settings.MONEY)
print('AGE:', settings.AGE)
print('ENABLED:', settings.ENABLED)
print('ENVIRONMENT:', settings.get('ENVIRONMENT'))
print('WORKS:', settings.WORKS)

settings.namespace()
print('# 5 back to default {}: namespace:'.format(settings.current_namespace))
assert settings.current_namespace == 'DEVELOPMENT'
print('HOST::', settings.HOST)
print('PORT:', settings.PORT)
print('USERNAME:', settings.USERNAME)
print('PASSWORD:', settings.PASSWORD)
print('LEVELS:', settings.LEVELS)
print('TEST_LOADERS:', settings.TEST_LOADERS)
print('MONEY:', settings.MONEY)
print('AGE:', settings.AGE)
print('ENABLED:', settings.ENABLED)
print('ENVIRONMENT:', settings.get('ENVIRONMENT'))
print('WORKS:', settings.WORKS)


with settings.using_namespace('staging'):
print('# 6 using {}: namespace values for context:'.format(
settings.current_namespace))
assert settings.current_namespace == 'STAGING'
print('HOST::', settings.HOST)
print('PORT:', settings.PORT)
print('USERNAME:', settings.USERNAME)
print('PASSWORD:', settings.PASSWORD)
print('LEVELS:', settings.LEVELS)
print('TEST_LOADERS:', settings.TEST_LOADERS)
print('MONEY:', settings.MONEY)
print('AGE:', settings.AGE)
print('ENABLED:', settings.ENABLED)
print('ENVIRONMENT:', settings.get('ENVIRONMENT'))
print('WORKS:', settings.WORKS)

print('# 7 back to default {}: namespace:'.format(settings.current_namespace))
assert settings.current_namespace == 'DEVELOPMENT'
print('HOST::', settings.HOST)
print('PORT:', settings.PORT)
print('USERNAME:', settings.USERNAME)
print('PASSWORD:', settings.PASSWORD)
print('LEVELS:', settings.LEVELS)
print('TEST_LOADERS:', settings.TEST_LOADERS)
print('MONEY:', settings.MONEY)
print('AGE:', settings.AGE)
print('ENABLED:', settings.ENABLED)
print('ENVIRONMENT:', settings.get('ENVIRONMENT'))
print('WORKS:', settings.WORKS)

settings.namespace('staging')
assert settings.current_namespace == 'STAGING'
print('# 8 Set to {}: namespace:'.format(settings.current_namespace))
print('HOST::', settings.HOST)
print('PORT:', settings.PORT)
print('USERNAME:', settings.USERNAME)
print('PASSWORD:', settings.PASSWORD)
print('LEVELS:', settings.LEVELS)
print('TEST_LOADERS:', settings.TEST_LOADERS)
print('MONEY:', settings.MONEY)
print('AGE:', settings.AGE)
print('ENABLED:', settings.ENABLED)
print('ENVIRONMENT:', settings.get('ENVIRONMENT'))
print('WORKS:', settings.WORKS)

settings.namespace()
print('# 9 back to default {}: namespace:'.format(settings.current_namespace))
print('HOST::', settings.HOST)
print('PORT:', settings.PORT)
print('USERNAME:', settings.USERNAME)
print('PASSWORD:', settings.PASSWORD)
print('LEVELS:', settings.LEVELS)
print('TEST_LOADERS:', settings.TEST_LOADERS)
print('MONEY:', settings.MONEY)
print('AGE:', settings.AGE)
print('ENABLED:', settings.ENABLED)
print('ENVIRONMENT:', settings.get('ENVIRONMENT'))
print('WORKS:', settings.WORKS)


assert settings.current_namespace == 'DEVELOPMENT'
44 changes: 44 additions & 0 deletions example/namespaces/settings.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# This is the BASE namespace
# the values from [prod] will be always loaded and used as default values
# by default it was called [dynaconf] but in the .env file we changed the BASE_NAMESPACE_FOR_DYNACONF to PROD
[prod]
host = "server.com from TOML"
port = 5000.0
username = "admin"
PASSWORD = "Secret"
levels = [
"debug",
"info",
"warning"
]
money = 500.5
age = 42.0
enabled = true
works = "only_in_prod"

[prod.test_loaders]
dev = "test_dev"
prod = "test_prod"


# If other namespace is set by NAMESPACE_FOR_DYNACONF env var
# or switch using settings.namespace or settings.using_namespace
# then the [prod] values will be overwritten with:

# When NAMESPACE_FOR_DYNACONF=TESTING
[testing]
environment = "this is testing from toml"
host = "test_server.com from toml"
works = 'only_in_test'

# When NAMESPACE_FOR_DYNACONF=DEVELOPMENT
[development]
environment = "this is development from toml"
host = "dev_server.com from toml"
works = 'only_in_dev'

# When NAMESPACE_FOR_DYNACONF=STAGING
[staging]
environment = "this is staging from toml"
host = "staging_server.com from toml"
works = 'only_in_staging'
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
from dynaconf import settings

# export DYNACONF_SETTINGS=settings.yaml
# or run $ source env.sh

# print all values in dynaconf: namespace of yaml file
print(settings.HOST)
print(settings.PORT)
Expand All @@ -20,7 +17,7 @@
print(settings.HOST)

# back to default dynaconf: namespace
print(settings.get('ENVIRONMENT'))
print(settings.get('ENVIRONMENT')) # None
print(settings.HOST)

# set namespace to development:
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def read(*names, **kwargs):

setup(
name='dynaconf',
version="0.7.5",
version="0.7.6",
url='https://github.com/rochacbruno/dynaconf',
license='MIT',
author="Bruno Rocha",
Expand Down
1 change: 0 additions & 1 deletion tests/test_ini_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ def test_load_from_multiple_ini():
assert settings.PASSWORD == 99999



def test_no_filename_is_none():
"""Assert if passed no filename return is None"""
assert load(settings) is None
Expand Down

0 comments on commit ad1e583

Please sign in to comment.