added methods to load config from a file

This commit is contained in:
Tim Mundt 2016-12-16 16:07:14 +01:00
parent 545d9eb59b
commit 04798cbf5b
2 changed files with 74 additions and 16 deletions

View File

@ -1,5 +1,11 @@
class Config: import os
LOGO = """ import types
class Config(dict):
def __init__(self, defaults=None):
dict.__init__(self, defaults or {})
self.LOGO = """
_______________ _______________
/ \\ / \\
@ -20,6 +26,63 @@ class Config:
""" """
REQUEST_MAX_SIZE = 100000000 # 100 megababies self.REQUEST_MAX_SIZE = 100000000 # 100 megababies
REQUEST_TIMEOUT = 60 # 60 seconds self.REQUEST_TIMEOUT = 60 # 60 seconds
ROUTER_CACHE_SIZE = 1024 self.ROUTER_CACHE_SIZE = 1024
def __getattr__(self, attr):
return self[attr]
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
varibales 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
"""
for key in dir(obj):
if key.isupper():
self[key] = getattr(obj, key)

View File

@ -1,7 +1,6 @@
import re import re
from collections import defaultdict, namedtuple from collections import defaultdict, namedtuple
from functools import lru_cache from functools import lru_cache
from .config import Config
from .exceptions import NotFound, InvalidUsage from .exceptions import NotFound, InvalidUsage
Route = namedtuple('Route', ['handler', 'methods', 'pattern', 'parameters']) Route = namedtuple('Route', ['handler', 'methods', 'pattern', 'parameters'])
@ -14,6 +13,8 @@ REGEX_TYPES = {
'alpha': (str, r'[A-Za-z]+'), 'alpha': (str, r'[A-Za-z]+'),
} }
ROUTER_CACHE_SIZE = 1024
def url_hash(url): def url_hash(url):
return url.count('/') return url.count('/')
@ -30,17 +31,11 @@ class Router:
@sanic.route('/my/url/<my_parameter>', methods=['GET', 'POST', ...]) @sanic.route('/my/url/<my_parameter>', methods=['GET', 'POST', ...])
def my_route(request, my_parameter): def my_route(request, my_parameter):
do stuff... do stuff...
or
@sanic.route('/my/url/<my_paramter>:type', methods['GET', 'POST', ...])
def my_route_with_type(request, my_parameter):
do stuff...
Parameters will be passed as keyword arguments to the request handling Parameters will be passed as keyword arguments to the request handling
function. Provided parameters can also have a type by appending :type to function provided Parameters can also have a type by appending :type to
the <parameter>. Given parameter must be able to be type-casted to this. the <parameter>. If no type is provided, a string is expected. A regular
If no type is provided, a string is expected. A regular expression can expression can also be passed in as the type
also be passed in as the type. The argument given to the function will
always be a string, independent of the type.
""" """
routes_static = None routes_static = None
routes_dynamic = None routes_dynamic = None
@ -118,7 +113,7 @@ class Router:
""" """
return self._get(request.url, request.method) return self._get(request.url, request.method)
@lru_cache(maxsize=Config.ROUTER_CACHE_SIZE) @lru_cache(maxsize=ROUTER_CACHE_SIZE)
def _get(self, url, method): def _get(self, url, method):
""" """
Gets a request handler based on the URL of the request, or raises an Gets a request handler based on the URL of the request, or raises an