From 60ca95e9b2a93493c8fa9f48dc3c2001a8ee3925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Tue, 30 Sep 2014 23:20:22 +0200 Subject: [PATCH] Started documenting plugin types and their API --- docs/conf.py | 2 +- docs/plugins/developing.rst | 19 ++++++ docs/plugins/index.rst | 15 ++--- src/octoprint/plugin/types.py | 123 ++++++++++++++++++++++++++++++++++ 4 files changed, 150 insertions(+), 9 deletions(-) create mode 100644 docs/plugins/developing.rst diff --git a/docs/conf.py b/docs/conf.py index 73af7be0..638144fa 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -30,7 +30,7 @@ year_current = date.today().year # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.todo', 'sphinxcontrib.httpdomain'] +extensions = ['sphinx.ext.todo', 'sphinx.ext.autodoc', 'sphinxcontrib.httpdomain'] todo_include_todos = True # Add any paths that contain templates here, relative to this directory. diff --git a/docs/plugins/developing.rst b/docs/plugins/developing.rst new file mode 100644 index 00000000..3213c6ad --- /dev/null +++ b/docs/plugins/developing.rst @@ -0,0 +1,19 @@ +.. _sec-plugins-developing: + +****************** +Developing Plugins +****************** + +.. todo:: + + A section on how to develop plugins yourself, including a tutorial creating an exemplary plugin as well as + a documentation of the plugin API, will be added in the near future. + +.. _sec-plugins-developing-types: + +Available plugin types +====================== + +.. automodule:: octoprint.plugin.types + :members: + :undoc-members: diff --git a/docs/plugins/index.rst b/docs/plugins/index.rst index c71261c2..bd085f73 100644 --- a/docs/plugins/index.rst +++ b/docs/plugins/index.rst @@ -4,13 +4,12 @@ Plugins Documentation ##################### -.. contents:: - Starting with OctoPrint 1.2.0, there's now a plugin system in place which allows to individually extend OctoPrint's functionality. Right now plugins can be used to extend OctoPrint's settings dialog, to execute specific tasks on server startup and -shutdown or to provide custom (API) endpoints with special functionality. More plugin types are planned for the future. +shutdown, to provide custom (API) endpoints with special functionality, to react on system events or to add support for +additional slicers. More plugin types are planned for the future. .. _sec-plugins-installation: @@ -50,12 +49,12 @@ Currently there's no such thing as a centralized plugin repository for available Plugins may be found in the lists provided in `the OctoPrint wiki `_ and on the `OctoPrint organization Github page `_. -.. _sec-plugins-developing: - Developing Plugins ================== -.. todo:: +Please see the following sub topics for information on how to develop your own OctoPrint plugins. - A section on how to develop plugins yourself, including a tutorial creating an exemplatory plugin as well as - a documentation of the plugin API, will be added in the near future. +.. toctree:: + :maxdepth: 2 + + developing.rst diff --git a/src/octoprint/plugin/types.py b/src/octoprint/plugin/types.py index f1403916..ccfde57e 100644 --- a/src/octoprint/plugin/types.py +++ b/src/octoprint/plugin/types.py @@ -10,23 +10,104 @@ from .core import Plugin class StartupPlugin(Plugin): + """ + The ``StartupPlugin`` allows hooking into the startup of OctoPrint. It can be used to start up additional services + on or just after the startup of the server. + """ + def on_startup(self, host, port): + """ + Called just before the server is actually launched. Plugins get supplied with the ``host`` and ``port`` the server + will listen on. Note that the ``host`` may be ``0.0.0.0`` if it will listen on all interfaces, so you can't just + blindly use this for constructing publicly reachable URLs. Also note that when this method is called, the server + is not actually up yet and none of your plugin's APIs or blueprints will be reachable yet. If you need to be + externally reachable, use ``on_after_startup`` instead or additionally. + + :param host: the host the server will listen on, may be ``0.0.0.0`` + :param port: the port the server will listen on + """ + pass def on_after_startup(self): + """ + Called just after launch of the server, so when the listen loop is actually running already. + """ + pass class ShutdownPlugin(Plugin): + """ + The ``ShutdownPlugin`` allows hooking into the shutdown of OctoPrint. It's usually used in conjunction with the + ``StartupPlugin`` mixin, to cleanly shut down additional services again that where started by the ``StartupPlugin`` + part of the plugin. + """ + def on_shutdown(self): + """ + Called upon the imminent shutdown of OctoPrint. + """ pass class AssetPlugin(Plugin): + """ + The ``AssetPlugin`` mixin allows plugins to define additional static assets such as Javascript or CSS files to + be automatically embedded into the pages delivered by the server to be used within the client sided part of + the plugin. + + A typical usage of the ``AssetPlugin`` functionality is to embed a custom view model to be used on the settings page + of a ``SettingsPlugin``. + """ + def get_asset_folder(self): + """ + Defines the folder where the plugin stores its static assets as defined in ``get_assets``. Usually an + implementation such as + + .. code-block:: python + + def get_asset_folder(self): + import os + return os.path.join(os.path.dirname(os.path.realpath(__file__)), "static") + + should be sufficient here. This way, assets can be put into a sub folder ``static`` in the plugin directory. + + :return: the absolute path to the folder where the plugin stores its static assets + """ return None def get_assets(self): + """ + Defines the static assets the plugin offers. The following asset types are recognized and automatically + imported at the appropriate places to be available: + + js + Javascript files, such as additional view models + css + CSS files with additional styles, will be embedded into delivered pages when not running in LESS mode. + less + LESS files with additional styles, will be embedded into delivered pages when running in LESS mode. + + The expected format to be returned is a dictionary mapping one or more of these keys to a list of files of that + type, the files being represented as relative paths from the asset folder as defined via ``get_asset_folder``. + Example: + + .. code-block:: python + + def get_assets(self): + return dict( + js=['js/my_file.js', 'js/my_other_file.js'], + css=['css/my_styles.css'], + less=['less/my_styles.less'] + ) + + The assets will be made available by OctoPrint under the URL ``/plugin_assets//``, with + ``plugin_name`` being the plugin's name and ``path`` being the path as defined in the asset dictionary. + + :return: a dictionary describing the static assets to publish for the plugin + """ return [] @@ -50,7 +131,49 @@ class SimpleApiPlugin(Plugin): class BlueprintPlugin(Plugin): + """ + The ``BlueprintPlugin`` mixin allows plugins to define their own full fledged endpoints for whatever purpose, + be it a more sophisticated API than what is possible via the ``SimpleApiPlugin`` or a custom web frontend. + + The mechanism at work here is `Flask's `_ own `Blueprint mechanism `_. + + Your plugin should define a blueprint like this: + + .. code-block:: python + + template_folder = os.path.join(os.path.dirname(os.path.realpath(__file__)), "templates") + blueprint = flask.Blueprint("plugin.myplugin", __name__, template_folder=template_folder) + + Use your blueprint just like any other Flask blueprint for defining your own endpoints, e.g. + + .. code-block:: python + + @blueprint.route("/echo", methods=["GET"]) + def myEcho(): + if not "text" in flask.request.values: + return flask.make_response("Expected a text to echo back.", 400) + return flask.request.values["text"] + + Your blueprint will be published by OctoPrint under the URL ``/plugin//``, so the above example + would be reachable under ``/plugin/myplugin/echo`` (given that you named your plugin "myplugin"). You'll be able + to create URLs via ``url_for`` under the prefix that you've chosen when constructing your blueprint, ``plugin.myplugin`` + in the above example: + + .. code-block:: python + + flask.url_for("plugin.myplugin.echo") # will return "/plugin/myplugin/echo" + + OctoPrint Blueprint plugins should always follow the naming scheme ``plugin.`` here + to avoid conflicts. + """ + def get_blueprint(self): + """ + Retrieves the blueprint as defined by your plugin. + + :return: the blueprint ready to be registered with Flask + """ + return None