A lot of time and effort has gone into revamping the developer documentation, which includes:
Separation of Developer Guide (this) and API Reference
List of terminology used throughout the framework and documentation
Thorough guide of all builtin extensions
The naming conventions and library paths in Cement 2 were laborious to type and remember. Now all modules/methods/etc are importable from
cement namespace directly, and the naming is simplified (ex:
CementApp is now
CementHandler is now
from cement import App, Controller, exclass Base(Controller):class Meta:label = 'base'@ex(help='this is a command')def cmd1(self):print('Inside Base.cmd1()')class MyApp(App):class Meta:label = 'myapp'handlers = [Base]
The Cement Developer Tools allow developers to quickly generate projects, plugins, extensions, and scripts:
$ cement generate project ./myappINFO: Generating cement project in ./myapp/$ cement generate plugin ./myapp/plugins/INFO: Generating cement plugin in ./myapp/plugins/$ cement generate extension ./myapp/ext/INFO: Generating cement extension in ./myapp/ext/$ cement generate script .INFO: Generating cement script in .
In Cement 2, the design of the interface and handler system was not easy to follow for new developers to the framework. It was also loosely modeled after ZopeInterface, and that may have lead to some odd naming conventions (IMeta, IMyInterface, etc), and an implementation that just felt weird.
Cement now includes a fully functioning docker setup out-of-the-box for local development of the framework that includes all dependencies, and dependency services like Redis, Memcached, etc.
Getting up and running is as simple as running the following:
$ make dev|> cement <| src #
This drops you into a shell within a docker container, and environment so that everything required to dev, and test is ready to roll:
|> cement <| src # make test|> cement <| src # make docs
Makefile for more common development tasks (for framework development).
Cement now supports the ability to override all config object settings via their associated environment variables. For example:
from cement import App, init_defaultsCONFIG = init_defaults('myapp')CONFIG['myapp']['foo'] = 'bar'class MyApp(App):class Meta:label = 'myapp'config_defaults = CONFIGwith MyApp() as app:app.run()foo = app.config.get('myapp', 'foo')print('Foo => %s' % foo)
$ python myapp.pyFoo => bar$ export MYAPP_FOO='not-bar'$ python myapp.pyFoo => not-bar
Environment variables are logically mapped to configuration settings based on their config keys and are prefixed with
MYAPP_ (based on the label of the app). So:
Rendering of template data (content, files, etc). Existing output handler extensions were also updated to include an associated template handler (
Used primarily in development as a replacement for standard
Adds the ability to easily obfuscate sensitive data from rendered output (think IP addresses, credit card numbers, etc)
Adds the ability for application developers to add a