allow setting config from individual env variables

This commit is contained in:
Raphael Deem 2017-03-21 18:37:46 -07:00
parent 7da4596ef8
commit c5b50fe3cf
4 changed files with 37 additions and 3 deletions

View File

@ -29,6 +29,14 @@ In general the convention is to only have UPPERCASE configuration parameters. Th
There are several ways how to load configuration. There are several ways how to load configuration.
### From environment variables.
Any variables defined with the `SANIC_` prefix will be applied to the sanic config. For example, setting `SANIC_REQUEST_TIMEOUT` will be loaded by the application automatically. You can pass the `load_vars` boolean to the Sanic constructor to override that:
```python
app = Sanic(load_vars=False)
```
### From an Object ### From an Object
If there are a lot of configuration values and they have sensible defaults it might be helpful to put them into a module: If there are a lot of configuration values and they have sensible defaults it might be helpful to put them into a module:

View File

@ -25,7 +25,8 @@ from sanic.websocket import WebSocketProtocol, ConnectionClosed
class Sanic: class Sanic:
def __init__(self, name=None, router=None, error_handler=None): def __init__(self, name=None, router=None, error_handler=None,
load_env=True):
# Only set up a default log handler if the # Only set up a default log handler if the
# end-user application didn't set anything up. # end-user application didn't set anything up.
if not logging.root.handlers and log.level == logging.NOTSET: if not logging.root.handlers and log.level == logging.NOTSET:
@ -44,7 +45,7 @@ class Sanic:
self.name = name self.name = name
self.router = router or Router() self.router = router or Router()
self.error_handler = error_handler or ErrorHandler() self.error_handler = error_handler or ErrorHandler()
self.config = Config() self.config = Config(load_env=load_env)
self.request_middleware = deque() self.request_middleware = deque()
self.response_middleware = deque() self.response_middleware = deque()
self.blueprints = {} self.blueprints = {}

View File

@ -1,9 +1,10 @@
import os import os
import types import types
SANIC_PREFIX = 'SANIC_'
class Config(dict): class Config(dict):
def __init__(self, defaults=None): def __init__(self, defaults=None, load_env=True):
super().__init__(defaults or {}) super().__init__(defaults or {})
self.LOGO = """ self.LOGO = """
@ -29,6 +30,9 @@ class Config(dict):
self.REQUEST_MAX_SIZE = 100000000 # 100 megababies self.REQUEST_MAX_SIZE = 100000000 # 100 megababies
self.REQUEST_TIMEOUT = 60 # 60 seconds self.REQUEST_TIMEOUT = 60 # 60 seconds
if load_env:
self.load_environment_vars()
def __getattr__(self, attr): def __getattr__(self, attr):
try: try:
return self[attr] return self[attr]
@ -90,3 +94,13 @@ class Config(dict):
for key in dir(obj): for key in dir(obj):
if key.isupper(): if key.isupper():
self[key] = getattr(obj, key) self[key] = getattr(obj, key)
def load_environment_vars(self):
for k, v in os.environ.items():
"""
Looks for any SANIC_ prefixed environment variables and applies
them to the configuration if present.
"""
if k.startswith(SANIC_PREFIX):
_, config_key = k.split(SANIC_PREFIX, 1)
self[config_key] = v

View File

@ -16,6 +16,17 @@ def test_load_from_object():
assert app.config.CONFIG_VALUE == 'should be used' assert app.config.CONFIG_VALUE == 'should be used'
assert 'not_for_config' not in app.config assert 'not_for_config' not in app.config
def test_auto_load_env():
environ["SANIC_TEST_ANSWER"] = "42"
app = Sanic()
assert app.config.TEST_ANSWER == "42"
del environ["SANIC_TEST_ANSWER"]
def test_auto_load_env():
environ["SANIC_TEST_ANSWER"] = "42"
app = Sanic(load_env=False)
assert getattr(app.config, 'TEST_ANSWER', None) == None
del environ["SANIC_TEST_ANSWER"]
def test_load_from_file(): def test_load_from_file():
app = Sanic('test_load_from_file') app = Sanic('test_load_from_file')