=================
- **Breaking change**. Morepath has a new, extensively refactored
configuration system based on dectate_ and importscan_. Dectate is
an extracted, and heavily refactored version of Morepath's
configuration system that used to be in ``morepath.config``
module. It's finally documented too!
.. _dectate: http://dectate.readthedocs.org
.. _importscan: http://importscan.readthedocs.org
Dectate and thus Morepath does not use Venusian (or Venusifork)
anymore so that dependency is gone.
Code that uses ``morepath.autosetup`` should still work.
Code that uses ``morepath.setup`` and scans and commits manually
needs to change. Change this::
from morepath import setup
config = morepath.setup()
config.scan(package)
config.commit()
into this::
import morepath
morepath.scan(package)
morepath.autocommit()
Similarly ``config.scan()`` without arguments to scan its own
package needs to be rewritten to use ``morepath.scan()`` without
arguments.
Anything you import directly now does not need to be scanned
anymore; the act of importing a module directly registers the
directives with Morepath, though as before they won't be active
until you commit. But scanning something you've imported before
won't do any harm.
The signature for ``morepath.scan`` is somewhat different than that
of the old ``config.scan``. There is no third argument
``recursive=True`` anymore. The ``onerror`` argument has been
renamed to ``handle_error`` and has different behavior; the
importscan_ documentation describes the details.
If you were writing tests that involve Morepath, the old structure of
the test was::
import morepath
def test_foo():
config = morepath.setup()
class App(morepath.App):
testing_config = config
... use directives on App ...
config.commit()
... do asserts ...
This now needs to change to::
import morepath
def test_foo():
class App(morepath.App):
pass
... use directives on App ...
morepath.commit([App])
... do asserts ...
So, you need to use the ``morepath.commit()`` function and give it a
list of the application objects you want to commit,
explicitly. ``morepath.autocommit()`` won't work in the context of a
test.
If you used a test that scanned code you need to adjust it too, from::
import morepath
import some_package
def test_foo():
config = morepath.setup()
config.scan(some_package)
config.commit()
... do asserts ...
to this::
import morepath
import some_package
def test_foo():
morepath.scan(some_package)
morepath.commit([some_package.App])
... do asserts ...
Again you need to be explicit and use ``morepath.commit`` to commit
those apps you want to test.
If you had a low-level reference to ``app.registry`` in your code it
will break; the registry has been split up and is now under
``app.config``. If you want access to ``lookup`` you can use
``app.lookup``.
If you created custom directives, the way to create directives
is now documented as part of the dectate_ project. The main updates you
need to do are:
* subclass from `dectate.Action` instead of `morepath.Directive`.
* no more ``app`` first argument.
* no ``super`` call is needed anymore in ``__init__``.
* add a ``config`` class variable to declare the registries
you want to affect. Until we break up the main registry this
is::
from morepath.app import Registry
...
config = { 'registry': Registry }
* reverse the arguments to ``perform``, so that the object
being registered comes first. So change::
def perform(self, registry, obj):
...
into::
def perform(self, obj, registry):
...
But instead of ``registry`` use the registry you set up in your
action's ``config``.
* no more ``prepare``. Do error checking inside the ``perform``
method and raise a ``DirectiveError`` if something is wrong.
If you created sub-actions from ``prepare``, subclass from
`dectate.Composite` instead and implement an ``actions`` method.
* ``group_key`` method has changed to ``group_class`` class variable.
If you were using ``morepath.sphinxext`` to document directives
using Sphinx autodoc, use ``dectate.sphinxext`` instead.
- **Breaking change** If you want to use Morepath directives on
``staticmethod``, you need to change the order in which these are
applied. In the past::
App.path(model=Foo, path='bar')
staticmethod
def get_foo():
....
But now you need to write::
staticmethod
App.path(model=Foo, path='bar')
def get_foo():
....
- **Breaking change** You cannot use a Morepath ``path`` directive on
a ``classmethod`` directly anymore. Instead you can do this::
class Foo(object):
classmethod
def get_something():
pass
App.path('/', model=Something)(Foo.get_something)
- **Breaking change**. Brought `app.settings` back, a shortcut to the
settings registry. If you use settings, you need to replace any
references to ``app.registry.settings`` to ``app.settings``.
- Add `request.class_link`. This lets you link using classes instead
of instances as an optimization. In some cases instantiating an
object just so you can generate a link to it is relatively
expensive. In that case you can use `request.class_link`
instead. This lets you link to a model class and supply a
`variables` dictionary manually.
- **Breaking change**. In Morepath versions before this there was an
class attribute on ``App`` subclasses called ``registry``. This was
a giant mixed registry which subclassed a lot of different
registries used by Morepath (reg registry, converter registry,
traject registry, etc). The Dectate configuration system allows us
to break this registry into a lot of smaller interdependent registries
that are configured in the ``config`` of the directives.
While normally you shouldn't be, if you were somehow relying on
``App.registry`` in your code you should now rewrite it to use
``App.config.reg_registry``, ``App.config.setting_registry``,
``App.config.path_registry`` etc.