Usage¶
Invenio application loader.
Quickstart¶
Invenio-Base is taking advantage of advanced patterns for building Flask application. It assumes you already have understanding of patterns for Flask.
Dependencies¶
First we need to install and import dependencies:
$ mkvirtualenv example
(example)$ pip install invenio-base
Now you can create new file app.py
with following imports:
import os
import sys
from invenio_base.app import create_app_factory, create_cli
from invenio_base.wsgi import create_wsgi_factory
Configuration¶
Tell the application factory how to load configuration by creating
config_loader
function that accepts an application instance:
class Config(object):
"""Example configuration."""
DEBUG = True
SECRET_KEY = 'CHANGE_ME'
def config_loader(app, **kwargs):
"""Custom config loader."""
app.config.from_object(Config)
app.config.update(**kwargs)
The recommended way is to use Invenio-Config that provides a default
configuration loader invenio_config.utils.create_config_loader()
which is
sufficient for most cases:
from invenio_config import create_config_loader
config_loader = create_config_loader(config=Config, env_prefix='APP')
In the next step you should set an absolute path for the instance folder in order to load configuration files and other data from deployment specific location. The instance folder is also perfect place for dropping static files if you do not serve them from CDN:
env_prefix = 'APP'
instance_path = os.getenv(env_prefix + '_INSTANCE_PATH') or \
os.path.join(sys.prefix, 'var', 'example-instance')
"""Instance path for Invenio.
Defaults to ``<env_prefix>_INSTANCE_PATH`` or if environment variable is not
set ``<sys.prefix>/var/<app_name>-instance``.
"""
static_folder = os.getenv(env_prefix + '_STATIC_FOLDER') or \
os.path.join(instance_path, 'static')
"""Static folder path.
Defaults to ``<env_prefix>_STATIC_FOLDER`` or if environment variable is not
set ``<sys.prefix>/var/<app_name>-instance/static``.
"""
In our example the variables are read from environment variables first with the purpose that they can be easily changed without modifying code for various deployment usecases.
Combining Applications¶
It is highly recommendended to separate Invenio UI and REST applications then different exception handlers, URL converters and session management can be installed on each application instance. You can even install your own WSGI application side by side with Invenio ones.
Invenio packages provide apps (extensions), blueprints, and URL converters via
entry points invenio_base.[api_]<apps,blueprints,converters>
. You can
specify multiple entry point groups for each application factory (e.g.
myservice.blueprints
):
create_api = create_app_factory(
'example',
config_loader=config_loader,
blueprint_entry_points=['invenio_base.api_blueprints'],
extension_entry_points=['invenio_base.api_apps'],
converter_entry_points=['invenio_base.api_converters'],
instance_path=instance_path,
)
create_app = create_app_factory(
'example',
config_loader=config_loader,
blueprint_entry_points=['invenio_base.blueprints'],
extension_entry_points=['invenio_base.apps'],
converter_entry_points=['invenio_base.converters'],
wsgi_factory=create_wsgi_factory({'/api': create_api}),
instance_path=instance_path,
static_folder=static_folder,
)
You provide instances of your own apps, blueprints, or URL converters directly to the factory:
from flask import Blueprint
blueprint = Blueprint('example', __name__)
@blueprint.route('/')
def index():
return 'Hello from Example application.'
create_app = create_app_factory(
'example',
blueprints=[blueprint],
# other parameters as shown in previous example
)
Running¶
To run you application you need to first instantiate the application object:
app = application = create_app()
"""The application object."""
Then you need to tell the ``flask`` command where is your file located
by setting environment variable FLASK_APP=app.py
:
$ export FLASK_APP=app.py
$ flask run
If you prefer to make your own executable script then you can use following pattern:
from invenio_base.app import create_cli
cli = create_cli(create_app=create_app)
if __name__ == '__main__':
cli()
Do not worry, you do not have to write all this by yourself. Follow next steps
and use inveniomanage
command that generates the scaffold code for you.
The inveniomanage
command¶
Invenio-Base installs the inveniomanage
command. By default only three
subcommands are available:
$ inveniomanage --help
Usage: inveniomanage [OPTIONS] COMMAND [ARGS]...
Command Line Interface for Invenio.
Options:
-a, --app TEXT The application to run.
--debug / --no-debug Enable or disable debug mode.
--help Show this message and exit.
Commands:
run Run development server.
shell Run shell in the app context.
The run
and shell
commands only works if you have specified the
--app
option or the FLASK_APP
environment variable. See
Flask documentation for further
information.
Listing all entrypoints of an Invenio instance¶
The instance entrypoints
subcommand helps you list all entrypoints of your
Invenio application:
$ inveniomanage instance entrypoints
The output of the command will be in the below format:
<entrypoint_group_name>
<entrypoint>
You can also restrict the output of the command to list all entrypoints for a specific entrypoint group by passing the name via the -e option:
$ inveniomanage instance entrypoints -e <entrypoint_group_name>
For further details about the available options run the help command:
$ inveniomanage instance entrypoints --help
...
Migrating the application’s old secret key¶
The instance migrate_secret_key
subcommand helps you migrate your
application’s old secret key:
$ inveniomanage instance migrate_secret_key --old-key <old_key>
The purpose of this command is to provide the administrator the capability to change the Invenio application’s secret_key and migrate that change in all database’s EncryptedType properties through an entrypoint group called invenio_base.secret_key’. There you can specify your migration function that will receive the old secret_key that can be used to decrypt the old properties and encrypt them again with the application’s new secret_key.
You can register your migration function as shown below in your package’s entrypoints in the setup.py:
entrypoints= {
'invenio_base.secret_key': [
'<entrypoint_name> = <entrypoint_function>'
]
}
Also you can see an example of use in invenio_oauthclient package’s setup.py.
Note
You should change your application’s secret_key in the config before calling the migration command.
For further details about the available options run the help command:
$ inveniomanage instance migrate_secret_key --help
...