What changed in version 5.0¶
To upgrade a production system, install the new system in a new virtualenv, then migrate your database:
reahl migratedb etc
Since this version is a major version update it is not backwards-compatible with previous versions. Everything that was deprecated in older versions is removed, and some new backwards-incompatible changes have been added.
Previously, if you marked a method with
exposed, its returned
FieldIndexdid not take into account possible methods higher up in the inheritance hierarchy. This has been changed -
exposednow always calls each method higher up in a hierarchy, thus the resultant
FieldIndexnow contains all
Fields added by overridden methods in the hierarchy.
- Python 2 support
Since Python 2 is now officially retired, this release drops support for Python < 3.5.
ButtonInputnow creates its own layout upon construction. Instead of setting your own
Layouton an already-created
ButtonInput, use one or more of
ButtonInput's new keyword arguments upon construction: style, outline, size, active, wide or text_wrap
- Unique input names and IDs
The name of an
Inputis derived from the name of its
Inputnames used to be adapted automatically so as to prevent name clashes between different
Inputs on a
Form. This is no longer the case: you now have to explicitly disambiguate an Input that has a name clash with another by passing it a
Fieldwith a modified name (see
Every Input is also now generated with a name and an ID that include the
Form's ID and hence are unique on the entire page.
- Changes to nested_transaction
nested_transaction()used to yield the transaction object. It now yields a
TransactionVetoobject which can be used to force the transaction to be committed or not by setting
should_committo True or False.
HTML5Pageused to be in
reahl.web.bootstrap.ui, but now resides in
reahl.web.bootstrap.pagedue to unavoidable dependency issues. You need to change your code to import it from the new module.
- Project metadata changes
In a .reahlproject file, the runtime dependencies of a project used to be declared at the top-level with a
`<deps purpose="run">`tag. The format of this file has now changed. Each released minor version of the project is now listed in a separate
`<version>`tag, and the runtime dependencies are now stated inside the
`version`tag for which those dependencies hold. In keepoing with this change,
Migrations no longer have a
`version`attribute to indicate which version they are for. See XML reference for .reahlproject.
Changing contents in response to a changing Input¶
We’ve done that by adding the refresh_widget keyword argument of
PrimitiveInput(). When constructing a
PrimitiveInput you can pass an
HTMLWidget as the refresh_widget
PrimitiveInput. When the
PrimitiveInput is changed, it will
trigger a refresh of its refresh_widget. As before, it is necessary
enable_refresh() on such an
HTMLWidget for this to work.
Two examples were added to explain usage of this feature:
This release adds functionality that guards against one user overwriting changes made concurrently to the same data by another user.
Consider, for example, the following sequence of events:
user A opens page X
user B opens page X
user A changes input on a form on page X, and clicks on a
ButtonInputthat submits it
the database is changed as a result of user A’s changes in such a way that page X would not render the same anymore
yet, user B still has the old page X open, and now makes similar changes on that page and clicks on a
ButtonInputthat submits the info
Without intervention in the above scenario user B’s changes might overwrite those of user A or the application could break - depending on how the code was written.
Reahl now computes a hash of all the input values on a form on a page. When the page is submitted, this hash is sent back to the server which recomputes the hash. If any differences are picked up, the user is shown an error message explaining that someone else has changed the same data and given the chance to refresh the values and try again.
This mechanism can also be customised to:
For more info, see the HOWTO:
Previously if an application encountered an unexpected exception, it would return an HTTP 5xx error code to the browser, which typically displays an unhelpful, unattractive error page.
In this release introduces the concept of a default_error_view.
The effect of this is that error messages can be rendered within the general look, feel and layout of your application. This happens by default, but the mechanism can also be customised at several different levels of your application.
For more info, see the HOWTO:
Database schema evolution¶
Previously, if you had a database with schema for a particular version of Reahl components (and your own), you could migrate said schema (and your data) to the next new version of Reahl components. For example, if you were using Reahl 3.0, you could upgrade to 3.1.
You could not do an upgrade that jumped versions. For example if your app’s version 1.0 depended on Reahl 3.0, you could not migrate successfully to a version 2.0 of your app which used Reahl 5.0.
The database migration machinery in this version was extensively overhauled to be able to handle any upgrade scenario we could imagine. (This includes scenarios where, for example, dependencies of components change amongst different versions of a component.)
Each Reahl component still only carries knowledge of its own
Migrations so that a diverse set of components can be used together
in the same database without knowledge of one another.
are still written as before.
What has changed is what metadata is kept of a project. Instead of only stating a project’s current version and its dependencies, you now have to list all released versions of the form major.minor. For each such version also state its dependencies and migrations.
Migrations do not have a version class attribute anymore.
For more info, see the tutorial example:
- Table footers
reahl.web.bootstrap.tables.Table.with_data()gained a footer_items keyword argument. This allows one to supply content for the table footer.
- Domain exceptions and exception Alerts
DomainExceptionwas changed to hold onto a list of possible error messages via its new detail_messages keyword argument. This is used, for example, by
ValidationExceptionsignals that there were validation errors and its detail_messages provide a list of all the specific validation failures.
If an exception is present on a
Formyou should display it. Previously displaying its message in an
Alertwould have been enough, but with the list of detail_messages now included, one should really display that list as well - and with it all styled better.
To do this
add_alert_for_domain_exception()was added to
reahl.web.bootstrap.forms.FormLayout. This provides an easy way to add an error message in cases where there is an exception present on a
add_alert_for_domain_exception()also includes a way for a user to react to the case where it is detected that another user made concurrent changes to underlying data.
- Simple FormLayout
reahl.web.ui.FormLayoutwas added to provide similar functionality to
reahl.web.bootstrap.forms.FormLayouton a lower level. This is especially used in tests.
A more expressive and composable XPath¶
XPath has been changed significantly to make it more useful and expressive in tests.
You can now construct an
XPath by chaining and composition. For
example, you can find a div with a specific css class like this:
XPath instances can be further composed in terms of one another:
A more Ajax-friendly DriverBrowser¶
When one generally tests an application, it is to be expected that user actions could trigger ajax refreshes or generally refer to elements that aren’t visible on the page yet - but that have to be waited for to appear.
Test code that continually triggers such events and waits for the results can obfuscate the intent of a test.
For this reason several
DriverBrowser methods have been changed to
automatically do “the right thing” in such circumstances.
click(), for example, now always trigger a
blur event on the
PrimitiveInput targeted and then wait for any
ajax that might have been triggered in response to finish before
This default behaviour can be overridden using keyword arguments where appropriate.
- Creating a new project
You can now start a new project by checking out one of our examples, but with a different name. In such checked-out code module, package, and various other names are renamed appropriately. (See reahl example -h)
- Help with configuration
You can also create a fresh new configuration directory with configuration based on having answered a few questions interactively. (See reahl createconfig -h)
- Hosting static files
Sometimes you need to host static files directly via a proxy such as nginx. You can now get to all those static files by running reahl exportstatic. (See reahl exportstatic -h)
Docker instead of Vagrant¶
Maintaining our Vagrant boxes for development became a bit cumbersome. With this release we have switched to using a Docker image for that purpose.
Downloading the Docker dev image is the quickest way to get started with Reahl because in it Reahl is installed in a clean venv ready for use.
The Docker development image is not meant for production use. It comes with Reahl as well as a bunch of development tools installed.
More info on using it can be found in: Development environment setup.
When running your app under uwsgi, the uWSGI server first imports your application and then forks several worker processes. If you start your application at module level (so that it is started after uwsgi imported your application) your application is also already connected to its database…and the forked processes inherit these established connections.
Such database connections are not thread-safe and cannot be shared between processes.
The start_on_first_request=True of
ReahlWSGIApplication ensures that your application
need not be started when created. Instead, it will be started when it receives its first
request and avoid this problem:
import os from reahl.web.fw import ReahlWSGIApplication application = ReahlWSGIApplication.from_directory('%s/etc' % os.path.expanduser('~'), start_on_first_request=True)
JQuery to 3.5.1
Bootstrap to 4.5.2
JQueryUI to 1.12.1 - but our distribution includes only the widget factory with :focusable and :tabbable, nothing else.
JQuery.validate was updated to 1.19.1 (and patched).
JQuery.form to 4.2.2
JQuery.blockUI to 2.70.0
js.cookie to 1.4.1
Popper to 1.16
holder to 2.9.7
JQuery BBQ 1.3pre (patched).
HTML5shiv to 3.7.3
The versions of some external dependencies were updated:
alembic to 0.9.6
Babel to 2.8
beautifulsoup4 to 4.6
docutils to 0.14
lxml to 4.2
mysqlclient to 1.3
Pillow to 2.5
ply to 3.8
prompt_toolkit to 2.0.10
psycopg2-binary to 2.7
Pygments to 2.1.0
python-dateutil to 2.8
selenium to 2.42
setuptools-git to 1.1
SQLAlchemy to 1.2.0
twine to 1.15.0
tzlocal to 2.0.0
watchdog to 0.8.3
WebOb to 1.4
wheel to 0.34.0
wrapt to 1.10.2