================
- **Breaking change**. There has been a change in the way the mount
directive works. There has also been a change in the way linking
between application works. The changes result in a simpler, more
powerful API and implementation.
The relevant changes are:
* You can now define your own custom ``__init__`` for
``morepath.App`` subclasses. Here you can specify the arguments
with which your application object should be mounted. The previous
``variables`` class attribute is now ignored.
It's not necessary to use ``super()`` when you subclass from
``morepath.App`` directly.
So, instead of this::
class MyApp(morepath.App):
variables = ['mount_id']
You should now write this::
class MyApp(morepath.App):
def __init__(self, mount_id):
self.mount_id = mount_id
* The ``mount`` directive should now return an *instance* of the
application being mounted, not a dictionary with mount
parameters. The application is specified using the ``app``
argument to the directive. So instead of this::
RootApp.mount(app=MyApp, path='sub/{id}')
def mount_sub(id):
return {
'mount_id': id
}
You should now use this::
RootApp.mount(app=MyApp, path='sub/{id}')
def mount_sub(id):
return MyApp(mount_id=id)
* The ``mount`` directive now takes a ``variables`` argument. This
works like the ``variables`` argument to the ``path``
directive and is used to construct links.
It is given an instance of the app being mounted, and it should
reconstruct those variables needed in its path as a dictionary. If
omitted, Morepath tries to get them as attributes from the
application instance, just like it tries to get attributes of any
model instance.
``MyApp`` above is a good example of where this is required: it
does store the correct information, but as the ``mount_id``
attribute, not the ``id`` attribute. You should add a ``variables``
argument to the ``mount`` directive to explain to Morepath how
to obtain ``id``::
RootApp.mount(app=MyApp, path='sub/{id}',
variables=lambda app: dict(id=app.mount_id))
def mount_sub(id):
return MyApp(mount_id=id)
The simplest way to avoid having to do this is to name the
attributes the same way as the variables in the paths, just like
you can do for model classes.
* In the past you'd get additional mount context variables as extra
variables in the function decorated by the ``path`` decorator.
This does not happen anymore. Instead you can add a special
``app`` parameter to this function. This gives you access to the
current application object, and you can extract its attributes
there.
So instead of this::
MyApp.path(path='models/{id}', model=Model)
def get_root(mount_id, id):
return Model(mount_id, id)
where ``mount_id`` is magically retrieved from the way ``MyApp`` was
mounted, you now write this::
MyApp.path(path='models/{id}', model=Model)
def get_root(app, id):
return Model(app.mount_id, id)
* There was an ``request.mounted`` attribute. This was a special an
instance of a special ``Mounted`` class. This ``Mounted`` class is
now gone -- instead mounted applications are simply instances of
their class. To access the currently mounted application, use
``request.app``.
* The ``Request`` object had ``child`` and ``sibling`` methods as
well as a ``parent`` attribute to navigate to different "link
makers". You'd navigate to the link maker of an application in
order to create links to objects in that application. These are
now gone. Instead you can do this navigation from the application
object directly, and instead of link makers, you get application
instances. You can pass an application instance as a special
``app`` argument to ``request.link`` and ``request.view``.
So instead of this::
request.child(foo).link(obj)
You now write this::
request.link(obj, app=request.app.child(foo))
And instead of this::
request.parent.link(obj)
You now write this::
request.link(obj, app=request.app.parent)
Note that the new ``defer_links`` directive can be used to
automate this behavior for particular models.
* The ``.child`` method on ``App`` can the app class as well as the
parameters for the function decorated by the ``mount`` directive::
app.child(MyApp, id='foo')
This can also be done by name. So, assuming ``MyApp`` was mounted
under ``my_app``::
app.child('my_app', id='foo')
This is how ``request.child`` worked already.
As an alternative you can now instead pass an app *instance*::
app.child(MyApp(mount_id='foo'))
Unlike the other ways to get the child, this takes the parameters
need to create the app instance, as opposed to taking the
parameters under which the app was mounted.
Motivation behind these changes:
Morepath used to have a ``Mount`` class separate from the ``App``
classes you define. Since Morepath 0.4 application objects became
classes, and it made sense to make their instances the same as the
mounted application. This unification has now taken place.
It then also made sense to use its navigation methods (``child`` and
friend) to navigate the mount tree, instead of using the rather
complicated "link maker" infrastructure we had before.
This change simplifies the implementation of mounting considerably,
without taking away features and actually making the APIs involved
more clear. This simplification in turn made it easier to implement
the new ``defer_links`` directive.
- **Breaking change**. The arguments to the ``render`` function have
changed. This is a function you can pass to a view directive. The
render function now takes a second argument, the request. You need
to update your render functions to take this into account. This only
affects code that supplies an explicit ``render`` function to the
``view``, ``json`` and ``html`` directives, and since not a lot of
those functions exist, the impact is expected to be minimal.
- **Breaking change**. In certain circumstances it was useful to
access the settings through an application instance using
``app.settings``. This does not work anymore; access the settings
through ``app.registry.settings`` instead.
- ``dump_json`` and ``load_json`` directives. This lets you
automatically convert an object going to a response to JSON, and
converts JSON coming in as a request body from JSON to an
object. See http://morepath.readthedocs.org/en/latest/json.html for
more information.
- ``defer_links`` directive. This directive can be used to declare
that a particular mounted application takes care of linking to
instances of a class. Besides deferring ``request.link()`` it will
also defer ``request.view``. This lets you combine applications with
more ease. By returning ``None`` from it you can also defer links to
this app's parent app.
- ``app.ancestors()`` method and ``app.root`` attribute. These can be
used for convenient access to the ancestor apps of a mounted
application. To access from the request, use ``request.app.root``
and ``request.app.ancestors()``.
- The ``App`` class now has a ``request_class`` class attribute. This
determines the class of the request that is created and can be
overridden by subclasses. ``more.static`` now makes use of this.
- Several generic functions that weren't really pulling their weight
are now gone as part of the mount simplification:
``generic.context`` and ``generic.traject`` are not needed anymore,
along with ``generic.link_maker``.
- Change documentation to use uppercase class names for App classes
everywhere. This reflects a change in 0.4 and should help clarity.
- Added documentation about auto-reloading Morepath during development.
- No longer silently suppress ImportError during scanning: this can
hide genuine ``ImportError`` in the underlying code.
We were suppressing ``ImportError`` before as it can be triggered
by packages that rely on optional dependencies.
This is a common case in the ``.tests`` subdirectory of a package
which may import a test runner like ``pytest``. ``pytest`` is only a
test dependency of the package and not a mainline dependencies, and
this can break scanning. To avoid this problem, Morepath's autosetup
and autoconfig now automatically ignore ``.tests`` and ``.test``
sub-packages.
Enhanced the API docs for ``autosetup`` and ``autoconfig`` to describe
scenarios which can generate legitimate ``ImportError`` exceptions
and how to handle them.
- Fix of examples in tween documentation.
- Minor improvement in docstrings.