or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-commands.mdindex.mdplugin-development.mdtesting-utilities.md

plugin-development.mddocs/

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

```