What changed in version 4.0¶
Upgrading¶
This release has been a long time in the making and comes with many changes. Various changes have been made to the underlying database schema. To upgrade a production system, install the new system in a new virtualenv, then migrate your database:
reahl migratedb etc
Bootstrap¶
All the Widget
s in this release are based on Bootstrap. The older home-rolled Widget
styling we
had was removed.
The basic Widget
s in reahl.web.ui
represent basic HTML and
thus are unstyled. These are not really meant to be used directly.
More interesting Widget
s only have Bootstrap-based versions and
they live in modules inside the reahl.web.bootstrap
package.
If you develop a site and use basic HTML Widget
s, like
P
, import all of them from from:
reahl.web.bootstrap.ui
.
Backwards-incompatible changes¶
Since this version is a major version update it is not backwards-compatible with previous versions. Everything what was deprecated in older versions is removed now.
- Infrastructure
ReahlApplication
(which is used to fire up you app via WSGI) was renamed toReahlWSGIApplication
.- Internationalisation
Translator
was renamed toCatalogue
.- Layout
The way one creates a
ColumnLayout
and specifies options for creating columns has changed. A new class,ColumnOptions
is now used to specify various options relating to a specific column. This includes the offset of the column, which previously used to be specified as part of itsResponsiveSize
.The arguments to
ColumnLayout()
that define the columns can now be one of:- either just the column name as a string (which assumes default
ColumnOptions
); or - a tuple with the column name and a
ColumnOptions
object (previously this had to be aResponsiveSize
).
- either just the column name as a string (which assumes default
- Basic Widgets
A single checkbox is used fetch boolean input from a user, but a list of related checkboxes lets the user choose from a list of choices.
The
CheckboxInput
is a high-level construct which can be used for either purpose, depending on whether it is used with aBooleanField
or aMultiChoiceField
.reahl.web.bootstrap.forms.RadioButtonInput
is now namedRadioButtonSelectInput
and reahl.web.ui.RadioButtonInput is :code:now namedRadioButtonSelectInput
.Amongst the plain HTML
Widget
s,CheckboxInput
serves the first purpose;CheckboxSelectInput
was added for the second.- Fields and app construction
The slot_definitions kwarg no longer exists on
define_view()
. Rather callset_slot()
on the returnedViewFactory
to define the contents of the new view.The methods
as_with_validation_constraint
andas_without_validation_constraint
onField
have been renamed towith_validation_constraint()
andwithout_validation_constraint()
for consistency with our coding conventions.- Menus
Menu
was moved toreahl.web.bootstrap.navs
. It is not meant to be used directly, rather useNav
. The.add_item
and.add_submenu
methods were removed in favour of the consistently named variants for adding items:add_a()
,add_bookmark()
andadd_dropdown()
.- Declarative implementation
- An issue was discovered regarding the correct handling of
MultiChoiceField
s when aDomainException
occurred. In order to correctly save the input provided by a user, the methods onUserInputProtocol
were changed to take an extra argument, entered_input_type.
Passwords¶
Previous releases used md5 to encrypt passwords in the database. This practice is no longer viewed as being secure. This release uses pbkdf2_sha512 password hashes via passlib.
Older passwords will automatically be changed to pbkdf2_sha512 upon a successful login.
Commandline tools¶
The reahl and reahl-control tools have both been rolled into a single reahl commandline tool. The commands it has vary depending on which parts of Reahl you have installed. With reahl-dev installed, for example, it will include commands only used in development.
Development environment¶
Development on Reahl itself now happens on a Vagrant image using a publicly available box, called reahl/bionic64. This may be useful for projects using Reahl as well. An example Vagrantfile for your projects is supplied in file vagrant/Vagrantfile.example in the Reahl source code.
See Development environment setup for details.
As part of the move to develop in a Vagrant machine, we added a new component, reahl-workstation. You can pip install reahl-workstation on your actual host. This gives you a simple reahl commandline outside of the vagrant machine which helps with a few simple things such as attaching to the xpra display running inside.
Mysql¶
In addition to PostgreSQL and Sqlite we now support MySql as well. Include reahl-mysqlsupport in your dependencies to be able to use mysql as a backend.
Tofu - pytest instead of nosetests¶
A lot of changes in this release happened behind the scenes and in our development environment. One such change is that our tests run on pytest now, instead of on nosetests.
Tofu changed extensively to make this possible.
Support for nose has now been dropped from
Fixture
s, and instead we now support pytest.
A Fixture
should not to be confused with
pytest.fixture. Whereas a pytest.fixture is a factory function that
pytest calls at appropriate times to create a single resource needed
by one or more tests, a Fixture
is still a
collection of test resources that are used together by a test.
Fixture
s further differ from pytest.fixture in that you import them
where needed–there is no magic to how they are named or reused.
The old idea of a run fixture (built by means of a nose plugin) has
been removed. Instead Fixture
s now have scope similar to the scope
of pytest.fixtures.
Here is an example of how to use a Fixture
with pytest:
from reahl.tofu import Fixture, with_fixtures
class MyFixture(Fixture):
def new_thing(self):
return 'thing'
@with_fixtures(MyFixture)
def test_something(f):
assert f.thing == 'thing'
Previously a test could only have a single Fixture
. That has been
changed: multiple Fixture
s can be used now. Note that the argument
names declared with the test function are not important. Fixture
s
are assigned to arguments based on position only:
from reahl.tofu import Fixture, with_fixtures
class MyFixture(Fixture):
def new_thing(self):
return 'thing'
class OtherFixture(Fixture):
def new_thing(self):
return 'other thing'
@with_fixtures(MyFixture, OtherFixture)
def test_something(f, f2):
assert f.thing == 'thing'
assert f2.thing == 'other thing'
Fixture
s can also depend on other Fixture
s. In this case use
uses()
to decorate the Fixture
class, stating
which other Fixture
classes it depends on, and what to name
these. At runtime, each Fixture
is created and assigned to an
attribute on the Fixture
that depends on it:
from reahl.tofu import Fixture, with_fixtures, uses
class MyFixture(Fixture):
def new_thing(self):
return 'thing'
@uses(my_fix=MyFixture)
class OtherFixture(Fixture):
def new_thing(self):
return 'other %s' % self.my_fix.thing
@with_fixtures(OtherFixture)
def test_something(f):
assert f.thing == 'other thing'
By default, a Fixture
has ‘function’ scope, meaning it is created
and set up before a test function, and torn down after the test
function ran. scope()
is used as decoration on the
Fixture
class to change the scope. Currently, only ‘function’ and
‘session’ scopes are supported. A Fixture
that has ‘session’ scope
is set up only once per test process, and torn down when the test
process ends:
from reahl.tofu import Fixture, with_fixtures, uses
@scope('session')
class MyFixture(Fixture):
def new_thing(self):
return 'thing'
@with_fixtures(MyFixture)
def test_something(f):
assert f.thing == 'other thing' # f here is the same instance in all tests
@with_fixtures(MyFixture)
def test_something_else(f):
assert f.thing == 'other thing' # f here is the same instance in all tests
Tofu - other changes¶
Some changes in Fixture
is not related to the pytest move.
Previously, you could add a method with name starting with ‘del_’ if
you needed to tear down one of the Fixture
attributes created with a
corresponding ‘new_’ method. Support for these ‘del_’ methods have now
been removed. Instead, tear down can now happen inside the ‘new_’
method which creates the instance by making use of a yield statement:
from reahl.tofu import Fixture
class MyFixture(Fixture):
def new_thing(self):
thing = 'thing'
yield thing
# tear down thing here
Fixture
previously also had a default contextmanager, assumed to be
created with a new_context method on the fixture. This was present
because of our use of an ExecutionContext
and our need to make sure
test code always ran within an appropriate ExecutionContext
.
The idea of ExecutionContext
does not belong in the domain of
Fixture
s, however, and it was really impossible to explain why a
Fixture
should have an additional context manager without explaining
ExecutionContext
.
For these reasons, Fixture
now does not support or need an extra
contextmanager. Instead, a new
ContextAwareFixture
was added–as
part of reahl.dev.fixtures
–making the design of a Fixture
simpler.
Git vs Bzr¶
We have switched internally to use git and GitHub. Previously, we needed to provide our own file_finder function so that setuptools would know which source files to include in a distribution, based on whether the file was added to Bzr. Since we’re not using Bzr anymore, the Bzr file_finder was removed. If you still use Bzr, you can easily roll your own.
Devpi¶
We have also stopped using Devpi internally and hence removed the devpitest and devpipush commands from the reahl commandline tool.
Updated dependencies¶
Some included thirdparty JavaScript and CSS libraries were updated:
- JQuery to 3.3.1 with JQuery-migrate 3.0.1.
- JQueryUI to 1.12.1 - but our distribution includes only the widget factory, nothing else.
- JQuery.validation was updated to 1.17.0 (and patched).
- jquery-metadata plugin was removed.
- Bootstrap to 4.0.0.
- JQuery BBQ to 1.3pre (patched).
- JQuery-form to 4.2.2.
- HTML5shiv to 3.7.3.
Some were added:
- Added Popper 1.12.9.
The versions of some external dependencies were updated:
- BeautifulSoup to 4.6.
- Wheel to 0.29.
- setuptools to 32.3.
- Lxml version to 3.8.
- SqlAlchemy to 1.2.0.
- Alembic to 0.9.6.
- Twine to 1.11.
- Lxml to 4.2.