Extending Albert using Python
This page focuses on the practical aspects of extending Albert using Python and its peculiarities. To get an overview of the API refer to the general extension section.
Writing Python plugins
An Albert Python plugin is a Python module having an interface defined in the Albert stub file. At runtime the stub file is written to your user Python plugin directory, where it serves as inline documentation and coding assistance in your IDE while development.
A minimal trigger query handler plugin:
from albert import *
md_iid = '3.0'
md_version = '1.0'
md_name = 'My plugin'
md_description = 'Does things'
class Plugin(PluginInstance, TriggerQueryHandler):
def __init__(self):
PluginInstance.__init__(self)
TriggerQueryHandler.__init__(self)
def handleTriggerQuery(self, query):
# query.add(StandardItem(…))
Next, skim through the Python stub file. For reference see the official plugins. In case of questions see the C++ API.
Plugin directories
Python plugin directories are the directories at python/plugins
relative to the app data directories.
- xdg:
~/.local/share/albert/python/plugins
/usr/local/share/albert/python/plugins
/usr/share/albert/python/plugins
- macOS:
~/Library/Application Support/Albert/python/plugins
/Library/Application Support/Albert/python/plugins
$BUNDLE_PATH/Contents/PlugIns/python/plugins
Technical notes and limitations
- Due to the different type systems, multiple virtual inheritance of extension interfaces is not supported. However, multiple extensions can be added by reimplementing
albert.PluginInstance.extensions()
. - Python plugin execution is subject to the Python Global Interpreter Lock (GIL). This means that only one thread can execute Python code at a time. This can become a problem for parallelization of queries or multithreaded global queries. Long running handlers will introduce noticeable lags. Do not block execution in your query handlers, especially not in
handleGlobalQuery
. If you can, useIndexQueryHandler
instead, which performs the handling in C++ space. - PyBind11 method resolution does not support mixin behavior. Usually this should not be much of a problem, but there is one prevalent use case: Reusing
id
,name
anddescription
of thePluginInstance
class for yourExtension
. For the sake of minimal boilerplate the mixin behavior is emulated for these methods. I.e. if you inheritPluginInstance
and anyExtension
, you do not have to reimplement these methods.