Writing plugins¶
A number of aspects of Jacquard are pluggable: the key ones right now being storage engines and directories.
You will probably want to write a directory plugin to interface with your database.
Directories¶
Declared in the directory_entries plugin group.
Declaring plugins¶
Plugin entry points (such as new directory engines) can be declared in one of two ways: simplified plugins, and setuptools plugins.
simplified plugins¶
Simplified plugins are declared in the Jacquard configuration file. To add, for instance, a directory engine called “my_directory_engine” which loads the Directory subclass MyDirectory from a Python module my_directory.py one would add:
[plugins:directory_engines]
my_directory_engine = my_directory:MyDirectory
This will look for my_directory.py anywhere on the Python path, which for Jacquard includes /etc/jacquard/plugins. This is the simplest way to add plugins.
setuptools plugins¶
For advanced use, or for plugins which are made for redistribution and/or installation through pip and PyPI, you can declare plugins via the standard Python entry_points mechanism.
Where this is normally used to declare entry points for command-line tools via the console_scripts group, in this case entry points are declared for the jacquard.directory_engines group.
Storage engines¶
Storage plugins can be added for new ways to store data, such as custom key/ value stores, or even a fast enough SQL database if you’re feeling particularly crazy.
Declared in the storage_engines plugin group.
API¶
-
class
jacquard.storage.base.
StorageEngine
(connection_string)[source]¶ Base storage engine class.
StorageEngine subclasses are required to be thread-safe.
-
begin_read_only
()[source]¶ Enter a new, read-only transaction.
May be overloaded for efficiency - by default, just calls begin().
-
commit
(changes, deletions)[source]¶ Commit transaction.
Writes to make are given in the two arguments: changes is a mapping of keys to their new string values, and deletions is an iterable of keys to remove entirely.
If optimistic locking or other transactional mechanisms fail, this can raise the Retry exception to request that the entire transaction be repeated.
-
decode_key
(key)[source]¶ Convert a given key for use in Jacquard.
This optional method must be implemented if encode_key is given, and must be its inverse.
The default implementation is the identity function.
-
encode_key
(key)[source]¶ Convert a given key for use in the storage engine.
This optional method is given for engine-specific encodings of keys - for instance, replacing slashes with the more idiomatic colons and prefix for the Redis backend. All keys entering the rest of the API are encoded.
The default implementation is the identity function.
-
get
(key)[source]¶ Get the current value corresponding with a given key.
Where there is no current value this must return None.
Only ever called in a transaction.
-
keys
()[source]¶ Get an iterable over all keys in the store.
This is only ever called in transactions.
-
rollback
()[source]¶ Roll back the current transaction without writing any changes.
This is used not only in exceptions but also when no writes were necessary after a transaction, so should ideally be fairly fast.
-
transaction
(read_only=False)[source]¶ Run a transactional sequence on this store.
This is (currently?) the main user API for StorageEngine. The context manager yields an object supporting the mutable mapping protocol in all its glory, which can be treated as if a dict in, say, the standard library’s shelve module.
When the context manager exits, the transaction is rolled back if there are no writes or if an exception is escaping.
Commits are allowed to raise the Retry exception and it is left to users of the API to deal with this. Retry is guaranteed not to be raised if the transaction was read-only.
-
Subcommands¶
Subcommand plugins add new subcommands to the jacquard command-line utility.
Declared in the commands plugin group.
Note
Due to current technical restrictions, simplified plugins cannot add subcommands—only setuptools plugins.
HTTP endpoints¶
HTTP endpoint plugins add new URL handlers for the HTTP API.
Declared in the http_endpoints plugin group.
API¶
-
class
jacquard.service.base.
Endpoint
(config)[source]¶ Base HTTP endpoint.
Subclasses must implement url and handle. url is a URL pattern in the standard Werkzeug/Flask form, and handle is the method which is actually called to dispatch the endpoint.
Instances have two states: bound and unbound. When the endpoint is loaded it is instantiated in an unbound state. Before it’s actually dispatched, the dispatcher calls bind which copies the endpoint to produce a bound version. Bound endpoints have context available in attributes: reverse and request.
-
bind
(request, reverse)[source]¶ Create bound version of this endpoint.
Clones with copy.copy and assigns instance.request and instance.reverse.
-
defaults
¶ Default values for URL parameters.
-
classmethod
handle
(**kwargs)[source]¶ Endpoint handler.
Any URL parameters are passed in as keyword arguments. This is only called on bound instances, so you can rely on self.request and friends existing.
Return JSON structures.
-
request
¶ Request this endpoint is handling.
-
url
¶ URL config, to be overridden in subclasses.
Takes the standard Werkzeug/Flask format. Examples:
- ‘/’
- ‘/foo/bar/bazz’
- ‘/foo/<user>’
- ‘/order/<id:int>’
Full documentation can be found in Werkzeug’s werkzeug.routing docs.
-