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$
|
:Updater: $Author$
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
from milla import util
|
||||||
from milla.controllers import FaviconController
|
from milla.controllers import FaviconController
|
||||||
from milla.util import asbool
|
|
||||||
from webob.exc import HTTPNotFound, WSGIHTTPException, HTTPMethodNotAllowed
|
from webob.exc import HTTPNotFound, WSGIHTTPException, HTTPMethodNotAllowed
|
||||||
import milla.dispatch.traversal
|
import milla.dispatch.traversal
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['Application']
|
__all__ = [
|
||||||
|
'Application',
|
||||||
|
'BaseApplication',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class Application(object):
|
class BaseApplication(object):
|
||||||
'''Represents a Milla web application
|
'''Base class for Milla applications
|
||||||
|
|
||||||
Constructing an ``Application`` instance needs a dispatcher, or
|
This class can be used by applications that need to customize the
|
||||||
alternatively, a root object that will be passed to a new
|
behavior of the framework. In most cases, :py:class:`Application`
|
||||||
:py:class:`milla.dispatch.traversal.Traverser`.
|
instances can be created directly and a sublcass is not necessary.
|
||||||
|
|
||||||
: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``.
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, obj):
|
DEFAULT_CONFIG = {}
|
||||||
if not hasattr(obj, 'resolve'):
|
|
||||||
# Object is not a dispatcher, but the root object for traversal
|
def __init__(self):
|
||||||
obj = milla.dispatch.traversal.Traverser(obj)
|
self.config = self.DEFAULT_CONFIG.copy()
|
||||||
self.dispatcher = obj
|
self.setup_routes()
|
||||||
self.config = {'milla.favicon': True}
|
|
||||||
|
|
||||||
def __call__(self, environ, start_response):
|
def __call__(self, environ, start_response):
|
||||||
start_response = StartResponseWrapper(start_response)
|
start_response = StartResponseWrapper(start_response)
|
||||||
|
@ -127,6 +120,32 @@ class Application(object):
|
||||||
return self._find_attr(obj.func, attr)
|
return self._find_attr(obj.func, attr)
|
||||||
raise
|
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):
|
def make_request(self, environ):
|
||||||
'''Create a :py:class:`~milla.Request` from a WSGI environment
|
'''Create a :py:class:`~milla.Request` from a WSGI environment
|
||||||
|
|
||||||
|
@ -162,7 +181,7 @@ class Application(object):
|
||||||
return self.dispatcher.resolve(path_info)
|
return self.dispatcher.resolve(path_info)
|
||||||
except milla.dispatch.UnresolvedPath:
|
except milla.dispatch.UnresolvedPath:
|
||||||
if (path_info == '/favicon.ico' and
|
if (path_info == '/favicon.ico' and
|
||||||
asbool(self.config.get('milla.favicon'))):
|
util.asbool(self.config.get('milla.favicon'))):
|
||||||
return FaviconController()
|
return FaviconController()
|
||||||
else:
|
else:
|
||||||
return path_not_found
|
return path_not_found
|
||||||
|
@ -182,6 +201,36 @@ class Application(object):
|
||||||
raise
|
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():
|
class StartResponseWrapper():
|
||||||
|
|
||||||
def __init__(self, start_response):
|
def __init__(self, start_response):
|
||||||
|
|
Loading…
Reference in New Issue