Implementation Overview¶
Introduction¶
This documentation contains an overview of how the implementation of Morepath works. This includes a description of the different pieces of Morepath as well as an overview of the internal APIs.
How it all works¶
import-time¶
When a Morepath-based application starts, the first thing that happens
is that all directives in modules that are imported are registered
with Morepath’s configuration engine. This configuration engine is
implemented using the Dectate library. Configuration is associated
with morepath.App
subclasses.
Only the minimum code is executed to register the directives with their App classes; the directive actions are not performed yet.
Besides normal Python imports, morepath.scan()
and
morepath.autoscan()
can be used to automatically import modules
so that their directives are registered.
commit¶
Configuration is then committed using morepath.App.commit()
, or
the more low-level morepath.commit()
.
This causes dectate.commit()
to be called for a particular App
class. This takes all the configuration as recorded during import-time
and resolves it. This involves:
- detect any conflicts between documentation and reporting it.
- detect any
morepath.error.DirectiveError
errors raised by individual directive actions. - resolve subclassing so that apps inherit from base apps and can override as well.
- performing the resulting configuration actions in the correct order.
All this is implemented by Dectate.
Morepath specific directives are defined in
morepath.directive
. Each directly or indirectly cause
dectate.Action
objects to be created. When the action is
performed various configuration registry objects are affected. These
registries are the end result of configuration.
morepath.directive.RegRegistry
is the most advanced of
registries used in Morepath and is based on reg.Registry
. In
this registry generic dispatch functions as defined in
morepath.generic
get individual implementations registered for
them. Reg dispatches to specific implementations based on the function
arguments used to call the generic function. Much of the functionality
in Morepath ultimately causes a registration into the Reg registry and
during runtime uses the API in morepath.generic
.
A special registry contains the settings; setting functions as
declared by morepath.App.setting()
and
morepath.App.setting_section()
are executed and stored in a
morepath.directive.SettingRegistry
which is accessible through
morepath.App.settings
.
instantiate the app¶
Once configuration has successfully completed, the app can be instantiated. Apps are also instantiated during run-time when they are mounted and a path resolves into a mounted app.
The app is now also a WSGI function so can be run with any WSGI server.
run-time¶
When a request comes in through WSGI into
morepath.App.__call__()
, a morepath.Request
object is
created.
morepath.publish.publish()
defines the core Morepath
publication procedure, which turns requests into responses. This
is done by first resolving the model and then rendering the resulting
model instance as a response.
During the first request, tweens (as declared using
morepath.App.tween_factory()
) are created and wrapped around
morepath.publish.publish()
. Tweens are request/response based
middleware functions. A standard Morepath tween implemented by
morepath.core.excview_tween_factory()
, renders exceptions
raised by application code as views. The default Morepath tween
factories are declared in morepath.core
and tween factories get
registered into morepath.directive.TweenRegistry
.
resolve the model¶
morepath.publish.resolve_model()
looks up a model object as
created by the factory functions the user declared with the
morepath.App.path()
directive and the morepath.App.mount()
directives.
morepath.path
contains the
morepath.directive.PathRegistry
that has the API to register
paths.
The route registration and resolution system is implemented by
morepath.traject
.
Default converters used during this step are declared in
morepath.core
. Converters are declared with the
morepath.App.converter()
directive and are registered in the
morepath.directive.ConverterRegistry
.
render the model object¶
morepath.publish.resolve_response()
then renders the model
object to a response using a view function as declared by user with
the morepath.App.view()
directive (and morepath.App.json()
and morepath.App.html()
).
This behavior is implemented using the
morepath.directive.ViewRegistry
. This builds on Reg and uses
special predicates declared in morepath.core
and registered
into the Reg registry using
morepath.directive.PredicateRegistry
. The views are
registered in the Reg registry too.
Views can use templates as declared with the
morepath.App.template_directory
,
morepath.App.template_loader
and
morepath.App.template_render
directives. These are registered
into the morepath.directive.TemplateEngineRegistry
.
Before a view is rendered a permission check is done for a model
object and an identity. This uses the rules defined by
morepath.App.permission_rule()
are used. These are registered
into the Reg registry.
Permission checks use morepath.Request.identity
. When this is
accessed the first time during a request the user’s identity is
constructed from information in the request according to the
morepath.App.identity_policy()
, as implemented by
morepath.authentication
.
creating links¶
During the rendering of the model object to a response a link can be
generated for a model object by user code that invokes
morepath.Request.link
. morepath.App
has a bunch of
private functions (morepath.App._get_path
etc) that implement
constructing paths. This uses inverse path information
(morepath.path.Path
) stored into the Reg registry using
morepath.directive.PathRegistry.register_inverse_path()
.
Dependencies¶
Morepath uses the following dependencies:
- Webob: a request and response implementation based on WSGI.
- Reg: a generic dispatch library. This is used for all functions you can register that are aware of subclassing, in particular views.
- Dectate: the configuration engine. This is used to implement directives and how configuration actions are executed during commit.
- importscan: automatically recursively import all modules in a package.
Internal APIs¶
These are the internal modules used by Morepath. For more information
click on the module headings to see the internal APIs. See also
morepath
for the public API and morepath.directive
for
the extension API.
morepath.app
– App classmorepath.authentication
– Authenticationmorepath.autosetup
– Configuration Automationmorepath.cachingreg
– Caching reg registrymorepath.compat
– Python 2/3 Compatibilitymorepath.converter
– Convert URL variablesmorepath.core
– Default Morepath Configurationmorepath.generic
– Generic dispatch functionsmorepath.implicit
– Implicit Dispatch Lookupmorepath.path
– Path registrymorepath.predicate
– Predicate registrymorepath.publish
– Web publishermorepath.reify
– Caching propertymorepath.request
– Request and Responsemorepath.settings
– Settingsmorepath.template
– Template Enginesmorepath.toposort
– Topological sortingmorepath.traject
– Routingmorepath.tween
– Tweensmorepath.view
– View registry
morepath.error
and morepath.pdbsupport
are documented as
part of the public API.