New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Documentation #7
Conversation
Api documentation updated, let me know if I should add something more to it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job 👍 It's mainly syntactical mistakes, but the documentation looks great!
docs/source/index.rst
Outdated
Creating a plugin | ||
----------------- | ||
|
||
Creating a plugin is simple. First of all you need to create a class for your plugin inheriting from Plugin:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we also mention the file names? Does it play an important role? Like plugin.py
, setup.py
, etc. If not, nvm!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A folder structure would also be useful. If I start creating the plugin now for example, just by reading the doc, I have no idea how to structure the code you mentioned 😉
docs/source/index.rst
Outdated
Current plugin | ||
-------------- | ||
|
||
Very useful feature of Flask-PluginEngine is a ``current_plugin`` global value. It's a proxy to currently active plugin. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Very useful feature of Flask-PluginEngine is a the..."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"It's a proxy to the currently active plugin."
docs/source/index.rst
Outdated
Example plugin functionality | ||
---------------------------- | ||
|
||
Now let's give our plugin some functionality to show how you can use the plugin. In this example we will render plugin's template from our application. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Now let's give our plugin some functionality to show how you can use the plugin it. In this example we will render the plugin's template from our application."
docs/source/index.rst
Outdated
|
||
Now let's give our plugin some functionality to show how you can use the plugin. In this example we will render plugin's template from our application. | ||
|
||
Let's create the templates folder with a simple Jinja template. For example displaying plugin's title and description:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Let's create the templates folder with a simple Jinja template . For example displaying to display for example the plugin's title and description"
docs/source/index.rst
Outdated
<div>{{ plugin.description }}</div> | ||
{% endblock %} | ||
|
||
If you documented plugin's class now you can access it as a ``name`` and ``description`` class properties. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am afraid I don't understand what this means.
docs/source/index.rst
Outdated
--------------------------------- | ||
|
||
To understand the possibilities of Flask-PluginEngine we will create a Jinja template, where we will list all the plugins we are using. | ||
Let's create two templates, the base one (base.html), for example:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd reword it a bit to:
"Let's create two templates, base.html
and index.html
: " and add comments above each code block below, like this:
{# base.html #}
<!DOCTYPE html>
<html lang="en">
<head>
...
{# index.html #}
<!DOCTYPE html>
<html lang="en">
<head>
...
docs/source/index.rst
Outdated
def hello(): | ||
return render_template('index.html', plugins=active_plugins) | ||
|
||
Now what we also should do is register the blueprints of all our plugins, for instance:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Now what we should also do is to register the blueprints of all our plugins..."
docs/source/index.rst
Outdated
if __name__ == "__main__": | ||
app.run() | ||
|
||
Now when we will go to the index page of our application we will be able to access plugin's template. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Now, when we will go to the index page of our application we will be able to can access the plugin's template."
docs/source/index.rst
Outdated
|
||
Now when we will go to the index page of our application we will be able to access plugin's template. | ||
|
||
You can find the application in the source code in example folder. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"You can find the source code of the application in the example folder"
docs/source/index.rst
Outdated
|
||
.. classmethod:: title() | ||
|
||
Plugin's title from the docstring |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this supposed to be fetched automatically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be, but due to the decorator problem I had to write it
Updated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well done! 🎉
docs/source/index.rst
Outdated
| setup.py | ||
| | ||
└───templates | ||
| index.html |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This directory tree is a bit confusing IMO, what about this?
plugin
├── example_plugin.py
├── setup.py
└── templates
└── index.html
docs/source/index.rst
Outdated
from flask_pluginengine import Plugin | ||
|
||
class ExamplePlugin(Plugin): | ||
"""ExamplePlugin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The docstring here should be indented.
docs/source/index.rst
Outdated
<div>{{ plugin.description }}</div> | ||
{% endblock %} | ||
|
||
Notice that the template extends a base.html. We are going to use the application's base template. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
base.html
docs/source/index.rst
Outdated
|
||
@plugin_blueprint.route('/plugin') | ||
def hello_plugin(): | ||
return render_template('example_plugin:index.html', plugin=current_plugin) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation.
docs/source/index.rst
Outdated
|
||
@app.route("/") | ||
def hello(): | ||
return render_template('index.html', plugins=active_plugins) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation.
docs/source/index.rst
Outdated
Now what we should also do is to register the blueprints of all our plugins, for instance:: | ||
|
||
for plugin in active_plugins: | ||
with plugin.plugin_context(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation.
docs/source/index.rst
Outdated
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<title>Title</title> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps it would look better "Flask-PluginEngine example" or similar?
docs/source/index.rst
Outdated
if __name__ == "__main__": | ||
app.run() | ||
|
||
Now when we go to the index page of our application we can access the plugin's template. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it's worth to mention here that you can also go to /plugin
and access the template of the plugin itself via its blueprint so that you prove that the stuff implemented in the plugin can be used.
docs/source/index.rst
Outdated
|
||
Now when we go to the index page of our application we can access the plugin's template. | ||
|
||
You can find the source code of the application in the example folder. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd appreciate here a link to the example folder.
docs/source/index.rst
Outdated
active_plugins = plugin_engine.get_active_plugins(app=app).values() | ||
|
||
|
||
Example application functionality |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I started reading this section I didn't know where to write the fragments of code explained and I struggled a bit until I check the example folder. In my opinion would be useful here to either explain that the plugin will be in a separated folder and the app itself in a different one or show again a directory tree pointing where the code in this section should be written in.
Updated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't find anything else :) Great job ! Nice guide which is easy to understand ;)
docs/source/index.rst
Outdated
@@ -26,17 +26,29 @@ You can install Flask-PluginEngine with the following command:: | |||
Creating a plugin | |||
----------------- | |||
|
|||
Creating a plugin is simple. First of all you need to create a class for your plugin inheriting from Plugin:: | |||
Creating a plugin is simple. First of all you need to create necessary files: file for your plugin code (in our case: ``example_plugin.py``), ``setup.py`` and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there should be a coma : First of all, you need ..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work, just have a few suggestions!
docs/source/index.rst
Outdated
Creating a plugin | ||
----------------- | ||
|
||
Creating a plugin is simple. First of all you need to create necessary files: file for your plugin code (in our case: ``example_plugin.py``), ``setup.py`` and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"create the necessary files: a file for [...] and a templates
folder"
docs/source/index.rst
Outdated
Just an example plugin | ||
""" | ||
|
||
Second, you need to fill the ``setup.py``. It's important to define a proper entry point to plugin's class. For example:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"point to the plugin's class"
docs/source/index.rst
Outdated
def hello_plugin(): | ||
return render_template('example_plugin:index.html', plugin=current_plugin) | ||
|
||
We can render any plugin template inside our application specifying the name of the plugin before the template name in ``render_template`` function, like above. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"in the render_template
function"
docs/source/index.rst
Outdated
return render_template('example_plugin:index.html', plugin=current_plugin) | ||
|
||
We can render any plugin template inside our application specifying the name of the plugin before the template name in ``render_template`` function, like above. | ||
We are also passing a current_plugin object to the template. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add double backticks around current_plugin
.
docs/source/index.rst
Outdated
Minimal application setup | ||
------------------------- | ||
|
||
To create a Flask application using Flask-PluginEngine we need to define it as ``PluginFlask`` application:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"as a PluginFlask
application"
docs/source/index.rst
Outdated
|
||
if __name__ == "__main__": | ||
app.run() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would maybe mention that PluginFlask
is just a regular Flask
application object with some added plugin magic. It should be already quite clear, however.
docs/source/index.rst
Outdated
name='Example-Plugin', | ||
version='0.0.1', | ||
py_modules=['example_plugin'], | ||
entry_points={'example': {'example_plugin = example_plugin:ExamplePlugin'}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would mention that example
is the namespace we're going to use below, in the application's config.
docs/source/index.rst
Outdated
plugin_engine.load_plugins(app) | ||
|
||
Then, we can access the loaded plugins by calling the :func:`get_active_plugins` method, which will return a dictionary containing the active plugins. | ||
To check if all of the plugins were loaded correctly we can also call the :func:`get_failed_plugins` method that will return a dictionary with plugins that failed to load:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would perhaps move the part about get_failed_plugins
below the example. It's a bit confusing to have an example that doesn't refer to it.
Updated |
Would it make sense to split the docs into multiple pages? When you want to write a plugin for some application you probably don't care about how to use this extension in your own app. OTOH, an application should have its own documentation on how to write plugins for it. |
docs/source/index.rst
Outdated
|
||
The Plugin instance used by the current app | ||
|
||
.. classmethod:: title() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it show up as title()
or title
in the docs? Because it's a class-level property and using ()
wouldn't work for obvious reasons ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just checked and it indeed shows up wrong.
example/app/app.py
Outdated
app.register_blueprint(plugin.get_blueprint()) | ||
|
||
|
||
@app.route("/") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
single quotes
example/app/app.py
Outdated
return render_template('index.html', plugins=active_plugins) | ||
|
||
|
||
if __name__ == "__main__": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
single quotes
flask_pluginengine/plugin.py
Outdated
@@ -119,12 +119,14 @@ def instance(cls): | |||
@classproperty | |||
@classmethod | |||
def title(cls): | |||
"""Plugin's title from the docstring""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"""The title of the plugin.
Automatically retrieved from the docstring of the plugin class.
"""
flask_pluginengine/plugin.py
Outdated
parts = trim_docstring(cls.__doc__).split('\n', 1) | ||
return parts[0].strip() | ||
|
||
@classproperty | ||
@classmethod | ||
def description(cls): | ||
"""Plugin's description from the docstring""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"""The description of the plugin.
Automatically retrieved from the docstring of the plugin class.
"""
Updated |
API documentation is still WIP but it would be great if you could already check the installation, setup and example usage steps if they make sense.