Merge pull request #199 from Tim-Erwin/improved_config

added methods to load config from a file
This commit is contained in:
Eli Uriegas
2017-01-29 15:27:34 -06:00
committed by GitHub
5 changed files with 228 additions and 7 deletions

View File

@@ -1,5 +1,11 @@
class Config:
LOGO = """
import os
import types
class Config(dict):
def __init__(self, defaults=None):
super().__init__(defaults or {})
self.LOGO = """
▄▄▄▄▄
▀▀▀██████▄▄▄ _______________
▄▄▄▄▄ █████████▄ / \\
@@ -20,6 +26,65 @@ class Config:
▌ ▐ ▀▀▄▄▄▀
▀▀▄▄▀
"""
REQUEST_MAX_SIZE = 100000000 # 100 megababies
REQUEST_TIMEOUT = 60 # 60 seconds
ROUTER_CACHE_SIZE = 1024
self.REQUEST_MAX_SIZE = 100000000 # 100 megababies
self.REQUEST_TIMEOUT = 60 # 60 seconds
def __getattr__(self, attr):
try:
return self[attr]
except KeyError as ke:
raise AttributeError("Config has no '{}'".format(ke.args[0]))
def __setattr__(self, attr, value):
self[attr] = value
def from_envvar(self, variable_name):
"""Loads a configuration from an environment variable pointing to
a configuration file.
:param variable_name: name of the environment variable
:return: bool. ``True`` if able to load config, ``False`` otherwise.
"""
config_file = os.environ.get(variable_name)
if not config_file:
raise RuntimeError('The environment variable %r is not set and '
'thus configuration could not be loaded.' %
variable_name)
return self.from_pyfile(config_file)
def from_pyfile(self, filename):
"""Updates the values in the config from a Python file. Only the uppercase
variables in that module are stored in the config.
:param filename: an absolute path to the config file
"""
module = types.ModuleType('config')
module.__file__ = filename
try:
with open(filename) as config_file:
exec(compile(config_file.read(), filename, 'exec'),
module.__dict__)
except IOError as e:
e.strerror = 'Unable to load configuration file (%s)' % e.strerror
raise
self.from_object(module)
return True
def from_object(self, obj):
"""Updates the values from the given object.
Objects are usually either modules or classes.
Just the uppercase variables in that object are stored in the config.
Example usage::
from yourapplication import default_config
app.config.from_object(default_config)
You should not use this function to load the actual configuration but
rather configuration defaults. The actual config should be loaded
with :meth:`from_pyfile` and ideally from a location not within the
package because the package might be installed system wide.
:param obj: an object holding the configuration
"""
for key in dir(obj):
if key.isupper():
self[key] = getattr(obj, key)

View File

@@ -1,7 +1,6 @@
import re
from collections import defaultdict, namedtuple
from functools import lru_cache
from .config import Config
from .exceptions import NotFound, InvalidUsage
from .views import CompositionView
@@ -15,6 +14,8 @@ REGEX_TYPES = {
'alpha': (str, r'[A-Za-z]+'),
}
ROUTER_CACHE_SIZE = 1024
def url_hash(url):
return url.count('/')
@@ -198,7 +199,7 @@ class Router:
return self._get(request.url, request.method,
request.headers.get("Host", ''))
@lru_cache(maxsize=Config.ROUTER_CACHE_SIZE)
@lru_cache(maxsize=ROUTER_CACHE_SIZE)
def _get(self, url, method, host):
"""
Gets a request handler based on the URL of the request, or raises an