app: Add BaseApplication class
The `Application` class is now a sub-class of `BaseApplication`. Applications that require more control of the framework's behavior can extend `BaseApplication` instead of `Application`. The `BaseApplication` class also provides some new features: * `BaseApplication.setup_routes` is always called when an instance is created, and can be used to configure the request dispatcher * `BaseApplication.update_config` updates the application configuration from a configuration file The major difference between `BaseApplication` and `Application` is that the latter requires a request dispatcher, while the former does not. This pattern allows simple applications to construct a `Router` or root object and then initialize the `Application` without needing to define a sub-class.master
parent
4090df1286
commit
44a28fda68
|
@ -21,40 +21,33 @@ Please give me a docstring!
|
|||
:Updater: $Author$
|
||||
'''
|
||||
|
||||
from milla import util
|
||||
from milla.controllers import FaviconController
|
||||
from milla.util import asbool
|
||||
from webob.exc import HTTPNotFound, WSGIHTTPException, HTTPMethodNotAllowed
|
||||
import milla.dispatch.traversal
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
__all__ = ['Application']
|
||||
__all__ = [
|
||||
'Application',
|
||||
'BaseApplication',
|
||||
]
|
||||
|
||||
|
||||
class Application(object):
|
||||
'''Represents a Milla web application
|
||||
class BaseApplication(object):
|
||||
'''Base class for Milla applications
|
||||
|
||||
Constructing an ``Application`` instance needs a dispatcher, or
|
||||
alternatively, a root object that will be passed to a new
|
||||
:py:class:`milla.dispatch.traversal.Traverser`.
|
||||
|
||||
:param obj: An object implementing the dispatcher protocol, or an
|
||||
object to be used as the root for a Traverser
|
||||
|
||||
``Application`` instances are WSGI applications.
|
||||
|
||||
.. py:attribute:: config
|
||||
|
||||
A mapping of configuration settings. For each request, the
|
||||
configuration is copied and assigned to ``request.config``.
|
||||
This class can be used by applications that need to customize the
|
||||
behavior of the framework. In most cases, :py:class:`Application`
|
||||
instances can be created directly and a sublcass is not necessary.
|
||||
'''
|
||||
|
||||
def __init__(self, obj):
|
||||
if not hasattr(obj, 'resolve'):
|
||||
# Object is not a dispatcher, but the root object for traversal
|
||||
obj = milla.dispatch.traversal.Traverser(obj)
|
||||
self.dispatcher = obj
|
||||
self.config = {'milla.favicon': True}
|
||||
DEFAULT_CONFIG = {}
|
||||
|
||||
def __init__(self):
|
||||
self.config = self.DEFAULT_CONFIG.copy()
|
||||
self.setup_routes()
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
start_response = StartResponseWrapper(start_response)
|
||||
|
@ -127,6 +120,32 @@ class Application(object):
|
|||
return self._find_attr(obj.func, attr)
|
||||
raise
|
||||
|
||||
def update_config(self, filename):
|
||||
'''Update application configuration from a file
|
||||
|
||||
:param filename: Path to configuration file
|
||||
|
||||
This method will update the application configuration using
|
||||
the values found in the specified configuration file. If the
|
||||
specified file does not exist or is not accessible, no
|
||||
changes will be made.
|
||||
|
||||
The configuration file will be read using
|
||||
:py:func:`milla.util.read_config`.
|
||||
'''
|
||||
|
||||
if filename and os.access(filename, os.R_OK):
|
||||
self.config.update(util.read_config(filename))
|
||||
|
||||
def setup_routes(self):
|
||||
'''Initialize the request dispatcher
|
||||
|
||||
The default implementation of this method does nothing, but it
|
||||
is called when an instance of :py:class:`BaseApplication` is
|
||||
created, and can be used by subclasses to set up the request
|
||||
dispatcher.
|
||||
'''
|
||||
|
||||
def make_request(self, environ):
|
||||
'''Create a :py:class:`~milla.Request` from a WSGI environment
|
||||
|
||||
|
@ -162,7 +181,7 @@ class Application(object):
|
|||
return self.dispatcher.resolve(path_info)
|
||||
except milla.dispatch.UnresolvedPath:
|
||||
if (path_info == '/favicon.ico' and
|
||||
asbool(self.config.get('milla.favicon'))):
|
||||
util.asbool(self.config.get('milla.favicon'))):
|
||||
return FaviconController()
|
||||
else:
|
||||
return path_not_found
|
||||
|
@ -182,6 +201,36 @@ class Application(object):
|
|||
raise
|
||||
|
||||
|
||||
class Application(BaseApplication):
|
||||
'''Represents a Milla web application
|
||||
|
||||
Constructing an ``Application`` instance needs a dispatcher, or
|
||||
alternatively, a root object that will be passed to a new
|
||||
:py:class:`milla.dispatch.traversal.Traverser`.
|
||||
|
||||
:param obj: An object implementing the dispatcher protocol, or an
|
||||
object to be used as the root for a Traverser
|
||||
|
||||
``Application`` instances are WSGI applications.
|
||||
|
||||
.. py:attribute:: config
|
||||
|
||||
A mapping of configuration settings. For each request, the
|
||||
configuration is copied and assigned to ``request.config``.
|
||||
'''
|
||||
|
||||
DEFAULT_CONFIG = {
|
||||
'milla.favicon': True,
|
||||
}
|
||||
|
||||
def __init__(self, obj):
|
||||
super(Application, self).__init__()
|
||||
if not hasattr(obj, 'resolve'):
|
||||
# Object is not a dispatcher, but the root object for traversal
|
||||
obj = milla.dispatch.traversal.Traverser(obj)
|
||||
self.dispatcher = obj
|
||||
|
||||
|
||||
class StartResponseWrapper():
|
||||
|
||||
def __init__(self, start_response):
|
||||
|
|
Loading…
Reference in New Issue