All Projects → ashleysommer → sanic-plugin-toolkit

ashleysommer / sanic-plugin-toolkit

Licence: MIT license
Easily create Plugins for Sanic!

Programming Languages

python
139335 projects - #7 most used programming language
Makefile
30231 projects
HTML
75241 projects

Projects that are alternatives of or similar to sanic-plugin-toolkit

sanic-mongodb-extension
MongoDB with μMongo support for Sanic framework
Stars: ✭ 25 (-48.98%)
Mutual labels:  extension, sanic
nautilus-pdf-tools
Tools to work with PDF files from Nautilus
Stars: ✭ 16 (-67.35%)
Mutual labels:  extension
ctx
🍭Ctx (Context) 是一个服务模块化上下文框架。
Stars: ✭ 38 (-22.45%)
Mutual labels:  context
auto-click-auto-fill
Auto Click Auto Fill on any web page
Stars: ✭ 111 (+126.53%)
Mutual labels:  extension
contextual
🌈 Generate your Ecto contexts using this macro and eliminate boilerplate
Stars: ✭ 18 (-63.27%)
Mutual labels:  context
PDL
php dynamic library (PDL)
Stars: ✭ 13 (-73.47%)
Mutual labels:  extension
react-combine-contexts
🚀Use multiple React Contexts without pain.
Stars: ✭ 23 (-53.06%)
Mutual labels:  context
go-csync
Golang: contex-aware synchronization primitives (mutex).
Stars: ✭ 27 (-44.9%)
Mutual labels:  context
Funky
Funky is a functional utility library written in Objective-C.
Stars: ✭ 41 (-16.33%)
Mutual labels:  extension
laravel-react-spa
A Laravel-React SPA starter project template.
Stars: ✭ 94 (+91.84%)
Mutual labels:  context
TwitchPotPlayer
Extensions for PotPlayer to watch Twitch streams without streamlinks or any crap.
Stars: ✭ 159 (+224.49%)
Mutual labels:  extension
react-generate-context
A helper function for reducing React Context boilerplate
Stars: ✭ 24 (-51.02%)
Mutual labels:  context
github-toc
📖 Browser extension that adds a table of contents to GitHub repos, wikis and gists.
Stars: ✭ 71 (+44.9%)
Mutual labels:  extension
sanic-admin
sanic-admin is a command line tool for automatically restarting sanic.
Stars: ✭ 15 (-69.39%)
Mutual labels:  sanic
hackbar
A browser extension for Penetration Testing
Stars: ✭ 131 (+167.35%)
Mutual labels:  extension
react-context-global-store
A simple global store based on React context
Stars: ✭ 22 (-55.1%)
Mutual labels:  context
multi-ctx
Multiple Spring Contexts Showcase
Stars: ✭ 16 (-67.35%)
Mutual labels:  context
save-text-to-file-firefox
Firefox addon that saves highlighted text to a file.
Stars: ✭ 87 (+77.55%)
Mutual labels:  extension
browser-extension
Official LISTEN.moe browser extension
Stars: ✭ 23 (-53.06%)
Mutual labels:  extension
spreadsheet
Yii2 extension for export to Excel
Stars: ✭ 79 (+61.22%)
Mutual labels:  extension

Sanic Plugin Toolkit

Build Status Latest Version Supported Python versions License

Welcome to the Sanic Plugin Toolkit.

The Sanic Plugin Toolkit (SPTK) is a lightweight python library aimed at making it as simple as possible to build plugins for the Sanic Async HTTP Server.

The SPTK provides a SanicPlugin python base object that your plugin can build upon. It is set up with all of the basic functionality that the majority of Sanic Plugins will need.

A SPTK Sanic Plugin is implemented in a similar way to Sanic Blueprints. You can use convenience decorators to set up all of the routes, middleware, exception handlers, and listeners your plugin uses in the same way you would a blueprint, and any Application developer can import your plugin and register it into their application.

The Sanic Plugin Toolkit is more than just a Blueprints-like system for Plugins. It provides an enhanced middleware system, and manages Context objects.

Notice: Please update to SPTK v0.90.1 if you need compatibility with Sanic v21.03+.

The Enhanced Middleware System

The Middleware system in the Sanic Plugin Toolkit both builds upon and extends the native Sanic middleware system. Rather than simply having two middleware queues ('request', and 'response'), the middleware system in SPF uses five additional queues.

  • Request-Pre: These middleware run before the application's own request middleware.
  • Request-Post: These middleware run after the application's own request middleware.
  • Response-Pre: These middleware run before the application's own response middleware.
  • Response-Post: These middleware run after the application's own response middleware.
  • Cleanup: These middleware run after all of the above middleware, and are run after a response is sent, and are run even if response is None.

So as a plugin developer you can choose whether you need your middleware to be executed before or after the application's own middleware.

You can also assign a priority to each of your plugin's middleware so you can more precisely control the order in which your middleware is executed, especially when the application is using multiple plugins.

The Context Object Manager

One feature that many find missing from Sanic is a context object. SPF provides multiple context objects that can be used for different purposes.

  • A shared context: All plugins registered in the SPF have access to a shared, persistent context object, which anyone can read and write to.
  • A per-request context: All plugins get access to a shared temporary context object anyone can read and write to that is created at the start of a request, and deleted when a request is completed.
  • A per-plugin context: All plugins get their own private persistent context object that only that plugin can read and write to.
  • A per-plugin per-request context: All plugins get a temporary private context object that is created at the start of a request, and deleted when a request is completed.

Installation

Install the extension with using pip, or easy_install.

$ pip install -U sanic-plugin-toolkit

Usage

A simple plugin written using the Sanic Plugin Toolkit will look like this:

# Source: my_plugin.py
from sanic_plugin_toolkit import SanicPlugin
from sanic.response import text

class MyPlugin(SanicPlugin):
    def __init__(self, *args, **kwargs):
        super(MyPlugin, self).__init__(*args, **kwargs)
        # do pre-registration plugin init here.
        # Note, context objects are not accessible here.

    def on_registered(self, context, reg, *args, **kwargs):
        # do post-registration plugin init here
        # We have access to our context and the shared context now.
        context.my_private_var = "Private variable"
        shared = context.shared
        shared.my_shared_var = "Shared variable"

my_plugin = MyPlugin()

# You don't need to add any parameters to @middleware, for default behaviour
# This is completely compatible with native Sanic middleware behaviour
@my_plugin.middleware
def my_middleware(request)
    h = request.headers
    #Do request middleware things here

#You can tune the middleware priority, and add a context param like this
#Priority must be between 0 and 9 (inclusive). 0 is highest priority, 9 the lowest.
#If you don't specify an 'attach_to' parameter, it is a 'request' middleware
@my_plugin.middleware(priority=6, with_context=True)
def my_middleware2(request, context):
    context['test1'] = "test"
    print("Hello world")

#Add attach_to='response' to make this a response middleware
@my_plugin.middleware(attach_to='response', with_context=True)
def my_middleware3(request, response, context):
    # Do response middleware here
    return response

#Add relative='pre' to make this a response middleware run _before_ the
#application's own response middleware
@my_plugin.middleware(attach_to='response', relative='pre', with_context=True)
def my_middleware4(request, response, context):
    # Do response middleware here
    return response

#Add attach_to='cleanup' to make this run even when the Response is None.
#This queue is fired _after_ response is already sent to the client.
@my_plugin.middleware(attach_to='cleanup', with_context=True)
def my_middleware5(request, context):
    # Do per-request cleanup here.
    return None

#Add your plugin routes here. You can even choose to have your context passed in to the route.
@my_plugin.route('/test_plugin', with_context=True)
def t1(request, context):
    words = context['test1']
    return text('from plugin! {}'.format(words))

The Application developer can use your plugin in their code like this:

# Source: app.py
from sanic import Sanic
from sanic_plugin_toolkit import SanicPluginRealm
from sanic.response import text
import my_plugin

app = Sanic(__name__)
realm = SanicPluginRealm(app)
assoc = realm.register_plugin(my_plugin)

# ... rest of user app here

There is support for using a config file to define the list of plugins to load when SPF is added to an App.

# Source: sptk.ini
[plugins]
MyPlugin
AnotherPlugin=ExampleArg,False,KWArg1=True,KWArg2=33.3
# Source: app.py
app = Sanic(__name__)
app.config['SPTK_LOAD_INI'] = True
app.config['SPTK_INI_FILE'] = 'sptk.ini'
realm = SanicPluginRealm(app)

# We can get the assoc object from SPF, it is already registered
assoc = spf.get_plugin_assoc('MyPlugin')

Or if the developer prefers to do it the old way, (like the Flask way), they can still do it like this:

# Source: app.py
from sanic import Sanic
from sanic.response import text
from my_plugin import MyPlugin

app = Sanic(__name__)
# this magically returns your previously initialized instance
# from your plugin module, if it is named `my_plugin` or `instance`.
assoc = MyPlugin(app)

# ... rest of user app here

Contributing

Questions, comments or improvements? Please create an issue on Github

Credits

Ashley Sommer [email protected]

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].