Creating example plugin.

This commit is contained in:
Roland 2019-10-15 12:28:31 -06:00
parent f6bdf3a3ec
commit 2e10a06a38
No known key found for this signature in database
GPG key ID: 9D6DBD3ACF11AB93
10 changed files with 195 additions and 1 deletions

View file

@ -0,0 +1,3 @@
from wrolpi.plugins.example_plugin.api import APIRoot
from wrolpi.plugins.example_plugin.main import PRETTY_NAME, init_parser, import_settings_config, save_settings_config
from wrolpi.plugins.example_plugin.web import ClientRoot, set_plugins, LINK

View file

@ -0,0 +1,43 @@
"""
These are the API methods for your plugin. It will be accessed through the key you set in user_plugins.py. These
should return JSON, if anything. These will be required to be accessed through a cherrypy.dispatch.MethodDispatcher(),
which means the request will be routed by the HTTP method you use. For example, the video plugin:
PUT /api/videos/settings
will be routed to videos.api.APIRoot.settings.PUT
Required: APIRoot
"""
import json
import cherrypy
from dictorm import DictDB
from wrolpi.plugins.example_plugin.common import hello
from wrolpi.tools import setup_tools
setup_tools()
# Do not change the name of this class, it is expected by wrolpi.web
class APIRoot(object):
def __init__(self):
self.settings = SettingsAPI()
@cherrypy.expose
class SettingsAPI(object):
@cherrypy.tools.db()
def GET(self, db: DictDB):
# curl http://127.0.0.1:8080/api/example_plugin/settings
return json.dumps({'hello': hello()})
@cherrypy.tools.db()
def POST(self, db: DictDB, **form_data):
# curl -X POST -d arg=val http://127.0.0.1:8080/api/example_plugin/settings
with db.transaction(commit=True):
return json.dumps({'hello': hello(), 'form_data': form_data})

View file

@ -0,0 +1,7 @@
"""
This module should contain any functions you will use in more than one module.
"""
def hello():
return 'world'

View file

@ -0,0 +1,52 @@
#! /usr/bin/env python3
"""
This module will be the entry-point for your plugin. The wrolpi.main will expect these basic functions to be here. Add
onto them to build your plugin.
Required: PRETTY_NAME, init_parser, main
"""
import argparse
import logging
from wrolpi.plugins.example_plugin.common import hello
from wrolpi.tools import setup_tools
# Pretty Name will be displayed when your plugin is linked to in the UI
PRETTY_NAME = 'Example Plugin'
logger = logging.getLogger('wrolpi')
setup_tools()
def init_parser(sub_commands):
# This function is called by WROLPI's main() function during startup, use it to setup your
# command-line arguments. If you don't have any, put a "pass" here
download_parser = sub_commands.add_parser('example_plugin')
# Add your own arguments
download_parser.add_argument('-a', '--asdf', action='store_true', default=False, help='Asdf')
def main(args):
# This function will be called when the parsers you defined above are passed via the command-line.
if args.sub_commands and 'example_plugin' in args.sub_commands:
print(f'hello {hello()}!')
return 0
def import_settings_config():
# If you build a config, it will be imported on startup here
pass
def save_settings_config():
# This could be called by the command-line to save the DB settings to a config.
pass
if __name__ == '__main__':
# If run directly, we'll make our own parser in the same form that wrolpi.main does
parser = argparse.ArgumentParser()
sub_commands = parser.add_subparsers(title='sub-commands', dest='sub_commands')
init_parser(sub_commands)
args = parser.parse_args()
main(args)

View file

@ -0,0 +1,18 @@
{# This is built off the main base.html. Please keep this, the plugin shouldn't be drastically different. #}
{% extends 'wrolpi/templates/base.html' %}
{% set title=title or 'Your Example Plugin Title' %} {# The title on the browser tab #}
{% block body %}
<h1>Example plugin!</h1>
<p>Hello {{ hello }}!</p>
<a href="/api/example_plugin/settings">GET Settings</a>
<hr>
<form method="post" action="/api/example_plugin/settings">
Arg: <input class="form-control" name="arg" type="text" />
<br>
<button class="btn btn-primary" type="submit">POST Settings</button>
</form>
{% endblock %}

View file

@ -0,0 +1,24 @@
"""
This will test your code (you're going to test your code, right?). Here are some simple tests.
Keep your tests simple! Don't test things like the full HTML of an endpoint, what if the base.html is changed out from
under you?
"""
import unittest
from wrolpi.common import get_db_context
from wrolpi.plugins.example_plugin.api import APIRoot
from wrolpi.plugins.example_plugin.common import hello
from wrolpi.test.common import test_db_wrapper
class TestAPI(unittest.TestCase):
def test_hello(self):
self.assertEqual(hello(), 'world')
@test_db_wrapper
def test_get(self):
api = APIRoot()
with get_db_context() as (db_conn, db):
self.assertEqual(api.settings.GET(db), '{"hello": "world"}')

View file

@ -0,0 +1,9 @@
-- noinspection SqlNoDataSourceInspectionForFile
-- Create the tables for plugin here. Don't step on any other plugin's tables! This will be applied during the DB
-- build/initialization.
CREATE TABLE example_plugin
(
id SERIAL PRIMARY KEY
);

View file

@ -0,0 +1,33 @@
"""
These are the UI classes for your plugin. They should all return a rendered HTML template from Jinja2. These methods
should NEVER make changes to the DB, do that in your API methods.
Required: LINK, PLUGINS, set_plugins, ClientRoot
"""
import cherrypy
from dictorm import DictDB
from wrolpi.common import env
from wrolpi.plugins.example_plugin.common import hello
# This is your link suffix. It will be used to link to your web classes here.
LINK = 'example_plugin'
# This will be set once all plugins are loaded
PLUGINS = None
def set_plugins(plugins):
global PLUGINS
PLUGINS = plugins
class ClientRoot(object):
@cherrypy.expose
@cherrypy.tools.db()
def index(self, db: DictDB):
# curl http://127.0.0.1:8080/example_plugin
template = env.get_template('wrolpi/plugins/example_plugin/templates/index.html')
html = template.render(hello=hello(), plugins=PLUGINS)
return html

View file

@ -1,13 +1,18 @@
"""
This document contains all plugins that will be loaded and linked to in the navbar. Add to the
This module contains all plugins that will be loaded and linked to in the navbar. Add to the
plugins object below when adding a new plugin.
You can uncomment the "example_plugin" lines below to explore building your own plugin!
"""
from collections import OrderedDict
from wrolpi.plugins import videos
from wrolpi.plugins import example_plugin
PLUGINS = OrderedDict(
videos=videos,
example_plugin=example_plugin,
)
# Share this list of plugins with every plugin