0
# Plugin Development
1
2
The Indico plugin system provides a comprehensive framework for extending functionality through custom plugins. Plugins can add new features, integrate with external systems, customize user interfaces, and extend core application behavior while maintaining clean separation from the core codebase.
3
4
## Capabilities
5
6
### Base Plugin Class
7
8
The foundation class for all Indico plugins, providing configuration management, lifecycle hooks, and integration points.
9
10
```python { .api }
11
class IndicoPlugin:
12
"""
13
Base class for all Indico plugins.
14
15
Attributes:
16
- settings_form: WTForm class for plugin settings (requires configurable=True)
17
- default_settings: dict, default plugin settings
18
- default_event_settings: dict, default event-specific settings
19
- default_user_settings: dict, default user-specific settings
20
- acl_settings: set, settings which store ACLs
21
- configurable: bool, whether plugin should link to config page in admin interface
22
- category: PluginCategory, plugin category enum value
23
- strict_settings: bool, whether to use strict mode for settings
24
"""
25
26
configurable: bool = False
27
category: 'PluginCategory' = None
28
default_settings: dict = {}
29
default_event_settings: dict = {}
30
default_user_settings: dict = {}
31
acl_settings: set = set()
32
strict_settings: bool = True
33
34
def init(self):
35
"""
36
Called when plugin is loaded/initialized.
37
Override to perform plugin-specific initialization.
38
"""
39
40
def get_blueprints(self):
41
"""
42
Return blueprints to be registered on application.
43
44
Returns:
45
list: List of Flask blueprints to register
46
"""
47
48
def get_vars_js(self):
49
"""
50
Return dictionary with variables for vars.js file.
51
52
Returns:
53
dict: Variables to inject into JavaScript context
54
"""
55
56
def connect(self, signal, receiver, **kwargs):
57
"""
58
Connect signal to receiver function.
59
60
Parameters:
61
- signal: Signal to connect to
62
- receiver: Function to handle the signal
63
- **kwargs: Additional connection parameters
64
"""
65
66
def inject_bundle(self, name, view_class=None, subclasses=True, condition=None):
67
"""
68
Inject asset bundle into pages.
69
70
Parameters:
71
- name: str, bundle name
72
- view_class: Class to inject into (optional, None for all pages)
73
- subclasses: bool, whether to include subclasses
74
- condition: callable, condition for injection
75
"""
76
77
def template_hook(self, name, receiver, priority=50, markup=True):
78
"""
79
Register template hook function.
80
81
Parameters:
82
- name: str, hook name
83
- receiver: callable, hook function
84
- priority: int, hook priority (lower = earlier)
85
- markup: bool, whether receiver returns markup
86
"""
87
```
88
89
### Settings Management
90
91
Plugin settings are managed through proxy objects that provide access to different setting scopes.
92
93
```python { .api }
94
@property
95
def settings(self):
96
"""
97
SettingsProxy for plugin settings.
98
99
Returns:
100
SettingsProxy: Global plugin settings
101
"""
102
103
@property
104
def event_settings(self):
105
"""
106
EventSettingsProxy for event-specific settings.
107
108
Returns:
109
EventSettingsProxy: Event-specific plugin settings
110
"""
111
112
@property
113
def user_settings(self):
114
"""
115
UserSettingsProxy for user-specific settings.
116
117
Returns:
118
UserSettingsProxy: User-specific plugin settings
119
"""
120
```
121
122
### Plugin Categories
123
124
Enumeration defining the available plugin categories for organization and filtering.
125
126
```python { .api }
127
class PluginCategory:
128
"""Plugin category enumeration."""
129
130
search = "search"
131
synchronization = "synchronization"
132
payment = "payment"
133
importers = "importers"
134
videoconference = "videoconference"
135
other = "other"
136
```
137
138
### Plugin Blueprint
139
140
Specialized Flask blueprint class for plugins with proper context handling and static folder support.
141
142
```python { .api }
143
class IndicoPluginBlueprint:
144
"""
145
Blueprint class for plugins with proper context handling.
146
Extends Flask Blueprint with plugin-specific functionality.
147
"""
148
```
149
150
### Plugin Engine
151
152
The plugin management system that handles plugin loading, registration, and lifecycle management.
153
154
```python { .api }
155
plugin_engine: 'IndicoPluginEngine'
156
"""Plugin engine instance for managing plugins."""
157
```
158
159
### Utility Functions
160
161
Helper functions for plugin development and integration.
162
163
```python { .api }
164
def plugin_url_rule_to_js(endpoint):
165
"""
166
Convert plugin endpoint to JavaScript format.
167
168
Parameters:
169
- endpoint: str, plugin endpoint name
170
171
Returns:
172
str: JavaScript-compatible URL rule
173
"""
174
175
def url_for_plugin(endpoint, *targets, **values):
176
"""
177
Generate URLs for plugin endpoints.
178
179
Parameters:
180
- endpoint: str, plugin endpoint
181
- *targets: positional arguments for URL generation
182
- **values: keyword arguments for URL generation
183
184
Returns:
185
str: Generated URL
186
"""
187
188
def get_plugin_template_module(template_name, **context):
189
"""
190
Get plugin template module.
191
192
Parameters:
193
- template_name: str, template file name
194
- **context: template context variables
195
196
Returns:
197
Template module for rendering
198
"""
199
```
200
201
## Plugin Development Examples
202
203
### Basic Plugin Structure
204
205
```python
206
from indico.core.plugins import IndicoPlugin, PluginCategory
207
208
class MyPlugin(IndicoPlugin):
209
"""Example plugin demonstrating basic structure."""
210
211
# Plugin metadata
212
configurable = True
213
category = PluginCategory.other
214
215
# Default settings
216
default_settings = {
217
'enabled': True,
218
'api_key': '',
219
'timeout': 30
220
}
221
222
default_event_settings = {
223
'feature_enabled': False
224
}
225
226
def init(self):
227
"""Initialize plugin when loaded."""
228
super().init()
229
# Connect to signals
230
self.connect('event_created', self._on_event_created)
231
232
def get_blueprints(self):
233
"""Register plugin blueprints."""
234
from .blueprint import bp
235
return [bp]
236
237
def _on_event_created(self, event, **kwargs):
238
"""Handle event creation."""
239
if self.event_settings.get(event, 'feature_enabled'):
240
# Custom logic for new events
241
pass
242
```
243
244
### Plugin with Web Interface
245
246
```python
247
from flask import render_template, request
248
from indico.core.plugins import IndicoPluginBlueprint
249
250
# Blueprint definition
251
bp = IndicoPluginBlueprint('my_plugin', __name__)
252
253
@bp.route('/config')
254
def config():
255
"""Plugin configuration page."""
256
return render_template('my_plugin:config.html')
257
258
@bp.route('/api/data')
259
def api_data():
260
"""Plugin API endpoint."""
261
return {'status': 'ok', 'data': []}
262
```
263
264
### Plugin with Template Hooks
265
266
```python
267
def init(self):
268
"""Initialize plugin with template hooks."""
269
super().init()
270
271
# Add content to event pages
272
self.template_hook('event-header', self._inject_header_content)
273
274
# Add JavaScript variables
275
self.inject_bundle('plugin_js', 'events.display')
276
277
def _inject_header_content(self, event, **kwargs):
278
"""Inject content into event header."""
279
if self.event_settings.get(event, 'show_banner'):
280
return render_template('my_plugin:banner.html', event=event)
281
```
282
283
## Plugin Registration
284
285
Plugins are registered through Python entry points in the package configuration:
286
287
```toml
288
[project.entry-points."indico.plugins"]
289
my_plugin = "my_plugin:MyPlugin"
290
```