Skip to content

Commit

Permalink
allow for more than one plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
nhoening committed Apr 12, 2021
1 parent 0d924d5 commit a50a92e
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 22 deletions.
8 changes: 5 additions & 3 deletions documentation/configuration.rst
Expand Up @@ -55,12 +55,14 @@ Default: ``{"flexmeasures.io": "2021-01"}``

.. _plugin-config:

FLEXMEASURES_PLUGIN_PATH
FLEXMEASURES_PLUGIN_PATHS
^^^^^^^^^^^^^^^^^^^^^^^^^

Absolute path to a blueprint-based plugin for FlexMeasures (e.g. for custom views or CLI functions). See :ref:`plugins` on what is expected for content.
A list of absolute paths to Blueprint-based plugins for FlexMeasures (e.g. for custom views or CLI functions).
Each plugin path points to a folder, which should contain an ``__init__.py`` file where the Blueprint is defined.
See :ref:`plugins` on what is expected for content.

Default: ``""``
Default: ``[]``


FLEXMEASURES_DB_BACKUP_PATH
Expand Down
21 changes: 13 additions & 8 deletions documentation/dev/plugins.rst
@@ -1,4 +1,4 @@
.. plugins:
.. _plugins:

Writing Plugins
====================
Expand All @@ -13,12 +13,12 @@ A FlexMeasures plugin works as a `Flask Blueprint <https://flask.palletsprojects
How it works
^^^^^^^^^^^^^^

Use the setting :ref:`plugin-config` to point to your plugin.
Use the config setting :ref:`plugin-config` to point to your plugin(s).

Here are the assumptions FlexMeasures makes to be able to import the Blueprint:
Here are the assumptions FlexMeasures makes to be able to import your Blueprint:

- Your plugin folder contains an __init__.py file.
- In this init, you define a Blueprint object called <plugin folder>_bp
- The plugin folder contains an __init__.py file.
- In this init, you define a Blueprint object called ``<plugin folder>_bp``.

We'll refer to the plugin with the name of your plugin folder.

Expand All @@ -29,11 +29,11 @@ Showcase
Here is a showcase file which constitutes a FlexMeasures plugin. We imagine that we made a plugin to implement some custom logic for a client.

We created the file ``<some_folder>/our_client/__init__.py``. So, ``our_client`` is the plugin folder and becomes the plugin name.
All else that is needed for this showcase (not shown here) is ``<some_folder>/our_client/templates/metrics.html``, which works just as other FlexMeasures templates (they are Jinja2 templates).
All else that is needed for this showcase (not shown here) is ``<some_folder>/our_client/templates/metrics.html``, which works just as other FlexMeasures templates (they are Jinja2 templates and you can start them with ``{% extends "base.html" %}`` for integration into the FlexMeasures structure).

We demonstrate adding a view which can be rendered via the FlexMeasures base templates. When added to the FlexMeasures UI menu (name it in :ref:`menu-config`).

We also showcase a CLI function which has access to the FlexMeasures `app` object. It can be called via ``flexmeasures our_client test``.
* We demonstrate adding a view which can be rendered via the FlexMeasures base templates.
* We also showcase a CLI function which has access to the FlexMeasures `app` object. It can be called via ``flexmeasures our_client test``.

.. code-block:: python
Expand All @@ -53,6 +53,7 @@ We also showcase a CLI function which has access to the FlexMeasures `app` objec
@login_required
def metrics():
msg = "I am part of FM !"
# Note that we render via the in-built FlexMeasures way
return render_flexmeasures_template(
"metrics.html",
message=msg,
Expand All @@ -72,3 +73,7 @@ We also showcase a CLI function which has access to the FlexMeasures `app` objec
@with_appcontext
def oc_test():
print(f"I am a CLI command, part of FlexMeasures: {current_app}")
.. note:: Plugin views can also be added to the FlexMeasures UI menu ― just name them in the config setting :ref:`menu-config`.
4 changes: 2 additions & 2 deletions flexmeasures/app.py
Expand Up @@ -104,9 +104,9 @@ def create(env: Optional[str] = None, path_to_config: Optional[str] = None) -> F

register_ui_at(app)

from flexmeasures.utils.app_utils import register_plugin
from flexmeasures.utils.app_utils import register_plugins

register_plugin(app)
register_plugins(app)

# Profile endpoints (if needed, e.g. during development)
@app.before_request
Expand Down
20 changes: 12 additions & 8 deletions flexmeasures/utils/app_utils.py
Expand Up @@ -67,20 +67,24 @@ def set_secret_key(app, filename="secret_key"):
sys.exit(2)


def register_plugin(app: Flask):
def register_plugins(app: Flask):
"""
Register a FlexMeasures plugin as Blueprint.
Register FlexMeasures plugins as Blueprints.
This is configured by the config setting FLEXMEASURES_PLUGIN_PATHS.
Assumptions:
- Your plugin folder contains an __init__.py file.
- Your plugin folders contains an __init__.py file.
- In this init, you define a Blueprint object called <plugin folder>_bp
We'll refer to the plugin with the name of your plugin folder.
TODO: Support multiple plugins when we have multiple accounts per server.
We'll refer to the plugins with the name of your plugin folders (last part of tthe path).
"""
plugin_path = app.config.get("FLEXMEASURES_PLUGIN_PATH", "")
if plugin_path:
plugin_paths = app.config.get("FLEXMEASURES_PLUGIN_PATHS", "")
if not isinstance(plugin_paths, list):
app.logger.warning(
f"The value of FLEXMEASURES_PLUGIN_PATHS is not a list: {plugin_paths}. Cannot install plugins ..."
)
return
for plugin_path in plugin_paths:
plugin_name = plugin_path.split("/")[-1]
if not os.path.exists(os.path.join(plugin_path, "__init__.py")):
app.logger.warning(
Expand Down
2 changes: 1 addition & 1 deletion flexmeasures/utils/config_defaults.py
Expand Up @@ -85,7 +85,7 @@ class Config(object):
# This setting contains the domain on which FlexMeasures runs
# and the first month when the domain was under the current owner's administration
FLEXMEASURES_HOSTS_AND_AUTH_START: dict = {"flexmeasures.io": "2021-01"}
FLEXMEASURES_PLUGIN_PATH: Optional[str] = None
FLEXMEASURES_PLUGIN_PATHS: List[str] = []
FLEXMEASURES_PROFILE_REQUESTS: bool = False
FLEXMEASURES_DB_BACKUP_PATH: str = "migrations/dumps"
FLEXMEASURES_LISTED_VIEWS: List[str] = [
Expand Down

1 comment on commit a50a92e

@Flix6x
Copy link
Contributor

@Flix6x Flix6x commented on a50a92e Apr 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Please sign in to comment.