Mercurial > piecrust2
annotate piecrust/plugins/base.py @ 848:7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
These are loose `.py` files inside of the `plugins` folder of a website.
They're loaded along with other normal (packaged) plugins.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Thu, 27 Apr 2017 20:54:29 -0700 |
parents | bf9f4e55f751 |
children | 8f8bbb2e70e1 |
rev | line source |
---|---|
848
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
1 import os.path |
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
2 import sys |
303
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
3 import logging |
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
4 import importlib |
848
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
5 import importlib.util |
303
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
6 |
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
7 |
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
8 logger = logging.getLogger(__name__) |
0 | 9 |
10 | |
11 class PieCrustPlugin(object): | |
12 def getFormatters(self): | |
13 return [] | |
14 | |
15 def getTemplateEngines(self): | |
16 return [] | |
17 | |
18 def getDataProviders(self): | |
19 return [] | |
20 | |
21 def getProcessors(self): | |
22 return [] | |
23 | |
24 def getImporters(self): | |
25 return [] | |
26 | |
27 def getCommands(self): | |
28 return [] | |
29 | |
3
f485ba500df3
Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents:
1
diff
changeset
|
30 def getCommandExtensions(self): |
f485ba500df3
Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents:
1
diff
changeset
|
31 return [] |
f485ba500df3
Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents:
1
diff
changeset
|
32 |
0 | 33 def getBakerAssistants(self): |
34 return [] | |
35 | |
3
f485ba500df3
Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents:
1
diff
changeset
|
36 def getSources(self): |
f485ba500df3
Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents:
1
diff
changeset
|
37 return [] |
f485ba500df3
Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents:
1
diff
changeset
|
38 |
711
ab5c6a8ae90a
bake: Replace hard-coded taxonomy support with "generator" system.
Ludovic Chabant <ludovic@chabant.com>
parents:
613
diff
changeset
|
39 def getPageGenerators(self): |
ab5c6a8ae90a
bake: Replace hard-coded taxonomy support with "generator" system.
Ludovic Chabant <ludovic@chabant.com>
parents:
613
diff
changeset
|
40 return [] |
ab5c6a8ae90a
bake: Replace hard-coded taxonomy support with "generator" system.
Ludovic Chabant <ludovic@chabant.com>
parents:
613
diff
changeset
|
41 |
613
e2e955a3bb25
publish: Add publish command.
Ludovic Chabant <ludovic@chabant.com>
parents:
413
diff
changeset
|
42 def getPublishers(self): |
e2e955a3bb25
publish: Add publish command.
Ludovic Chabant <ludovic@chabant.com>
parents:
413
diff
changeset
|
43 return [] |
e2e955a3bb25
publish: Add publish command.
Ludovic Chabant <ludovic@chabant.com>
parents:
413
diff
changeset
|
44 |
0 | 45 def initialize(self, app): |
46 pass | |
47 | |
48 | |
49 class PluginLoader(object): | |
50 def __init__(self, app): | |
51 self.app = app | |
52 self._plugins = None | |
53 self._componentCache = {} | |
54 | |
55 @property | |
56 def plugins(self): | |
57 self._ensureLoaded() | |
58 return self._plugins | |
59 | |
60 def getFormatters(self): | |
312
10bb8e8600f5
plugins: Remove unused API endpoints.
Ludovic Chabant <ludovic@chabant.com>
parents:
306
diff
changeset
|
61 return self._getPluginComponents( |
413
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
62 'getFormatters', |
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
63 initialize=True, register_timer=True, |
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
64 order_key=lambda f: f.priority) |
0 | 65 |
66 def getTemplateEngines(self): | |
413
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
67 return self._getPluginComponents( |
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
68 'getTemplateEngines', |
803
bf9f4e55f751
rendering: Separate performance timers for renering segments and layouts.
Ludovic Chabant <ludovic@chabant.com>
parents:
711
diff
changeset
|
69 initialize=True, register_timer=True, |
bf9f4e55f751
rendering: Separate performance timers for renering segments and layouts.
Ludovic Chabant <ludovic@chabant.com>
parents:
711
diff
changeset
|
70 register_timer_suffixes=['_segment', '_layout']) |
0 | 71 |
72 def getDataProviders(self): | |
73 return self._getPluginComponents('getDataProviders') | |
74 | |
75 def getProcessors(self): | |
312
10bb8e8600f5
plugins: Remove unused API endpoints.
Ludovic Chabant <ludovic@chabant.com>
parents:
306
diff
changeset
|
76 return self._getPluginComponents( |
413
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
77 'getProcessors', |
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
78 initialize=True, register_timer=True, |
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
79 order_key=lambda p: p.priority) |
0 | 80 |
81 def getImporters(self): | |
82 return self._getPluginComponents('getImporters') | |
83 | |
84 def getCommands(self): | |
85 return self._getPluginComponents('getCommands') | |
86 | |
3
f485ba500df3
Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents:
1
diff
changeset
|
87 def getCommandExtensions(self): |
f485ba500df3
Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents:
1
diff
changeset
|
88 return self._getPluginComponents('getCommandExtensions') |
f485ba500df3
Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents:
1
diff
changeset
|
89 |
0 | 90 def getBakerAssistants(self): |
91 return self._getPluginComponents('getBakerAssistants') | |
92 | |
3
f485ba500df3
Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents:
1
diff
changeset
|
93 def getSources(self): |
f485ba500df3
Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents:
1
diff
changeset
|
94 return self._getPluginComponents('getSources') |
f485ba500df3
Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents:
1
diff
changeset
|
95 |
711
ab5c6a8ae90a
bake: Replace hard-coded taxonomy support with "generator" system.
Ludovic Chabant <ludovic@chabant.com>
parents:
613
diff
changeset
|
96 def getPageGenerators(self): |
ab5c6a8ae90a
bake: Replace hard-coded taxonomy support with "generator" system.
Ludovic Chabant <ludovic@chabant.com>
parents:
613
diff
changeset
|
97 return self._getPluginComponents('getPageGenerators') |
ab5c6a8ae90a
bake: Replace hard-coded taxonomy support with "generator" system.
Ludovic Chabant <ludovic@chabant.com>
parents:
613
diff
changeset
|
98 |
613
e2e955a3bb25
publish: Add publish command.
Ludovic Chabant <ludovic@chabant.com>
parents:
413
diff
changeset
|
99 def getPublishers(self): |
e2e955a3bb25
publish: Add publish command.
Ludovic Chabant <ludovic@chabant.com>
parents:
413
diff
changeset
|
100 return self._getPluginComponents('getPublishers') |
e2e955a3bb25
publish: Add publish command.
Ludovic Chabant <ludovic@chabant.com>
parents:
413
diff
changeset
|
101 |
0 | 102 def _ensureLoaded(self): |
103 if self._plugins is not None: | |
104 return | |
105 | |
1
aaa8fb7c8918
Re-arranged modules to reduce dependencies to builtin stuff.
Ludovic Chabant <ludovic@chabant.com>
parents:
0
diff
changeset
|
106 from piecrust.plugins.builtin import BuiltInPlugin |
0 | 107 self._plugins = [BuiltInPlugin()] |
108 | |
306
7122976bc751
plugins: Fix crash for sites that don't specify a `site/plugins` setting.
Ludovic Chabant <ludovic@chabant.com>
parents:
305
diff
changeset
|
109 to_install = self.app.config.get('site/plugins') |
7122976bc751
plugins: Fix crash for sites that don't specify a `site/plugins` setting.
Ludovic Chabant <ludovic@chabant.com>
parents:
305
diff
changeset
|
110 if to_install: |
413
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
111 for name in to_install: |
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
112 plugin = self._loadPlugin(name) |
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
113 self._plugins.append(plugin) |
0 | 114 |
115 for plugin in self._plugins: | |
116 plugin.initialize(self.app) | |
117 | |
303
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
118 def _loadPlugin(self, plugin_name): |
848
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
119 mod_name = 'piecrust_%s' % plugin_name |
303
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
120 try: |
848
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
121 # Import from the current environment. |
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
122 mod = importlib.import_module(mod_name) |
305
9ae23409d6e9
plugins: Change how plugins are loaded. Add a `plugins` command.
Ludovic Chabant <ludovic@chabant.com>
parents:
303
diff
changeset
|
123 except ImportError as ex: |
848
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
124 mod = None |
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
125 |
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
126 if mod is None: |
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
127 # Import as a loose Python file from the plugins dir. |
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
128 pfile = os.path.join(self.app.plugins_dir, plugin_name + '.py') |
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
129 if os.path.isfile(pfile): |
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
130 spec = importlib.util.spec_from_file_location(plugin_name, |
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
131 pfile) |
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
132 mod = importlib.util.module_from_spec(spec) |
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
133 spec.loader.exec_module(mod) |
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
134 sys.modules[mod_name] = mod |
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
135 |
7d83b9484b98
plugins: Add support for "ad-hoc" local plugins.
Ludovic Chabant <ludovic@chabant.com>
parents:
803
diff
changeset
|
136 if mod is None: |
305
9ae23409d6e9
plugins: Change how plugins are loaded. Add a `plugins` command.
Ludovic Chabant <ludovic@chabant.com>
parents:
303
diff
changeset
|
137 logger.error("Failed to load plugin '%s'." % plugin_name) |
9ae23409d6e9
plugins: Change how plugins are loaded. Add a `plugins` command.
Ludovic Chabant <ludovic@chabant.com>
parents:
303
diff
changeset
|
138 logger.error(ex) |
303
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
139 return |
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
140 |
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
141 plugin_class = getattr(mod, '__piecrust_plugin__', None) |
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
142 if plugin_class is None: |
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
143 logger.error("Plugin '%s' doesn't specify any " |
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
144 "`__piecrust_plugin__` class." % plugin_name) |
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
145 return |
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
146 |
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
147 try: |
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
148 plugin = plugin_class() |
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
149 except Exception as ex: |
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
150 logger.error("Failed to create plugin '%s': %s" % |
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
151 (plugin_name, ex)) |
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
152 return |
5dbab01daaba
plugins: First pass for a working plugin loader functionality.
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
153 |
413
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
154 return plugin |
0 | 155 |
413
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
156 def _getPluginComponents(self, name, *, |
803
bf9f4e55f751
rendering: Separate performance timers for renering segments and layouts.
Ludovic Chabant <ludovic@chabant.com>
parents:
711
diff
changeset
|
157 initialize=False, |
bf9f4e55f751
rendering: Separate performance timers for renering segments and layouts.
Ludovic Chabant <ludovic@chabant.com>
parents:
711
diff
changeset
|
158 register_timer=False, |
bf9f4e55f751
rendering: Separate performance timers for renering segments and layouts.
Ludovic Chabant <ludovic@chabant.com>
parents:
711
diff
changeset
|
159 register_timer_suffixes=None, |
413
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
160 order_key=None): |
0 | 161 if name in self._componentCache: |
162 return self._componentCache[name] | |
163 | |
164 all_components = [] | |
165 for plugin in self.plugins: | |
166 plugin_components = getattr(plugin, name)() | |
167 all_components += plugin_components | |
413
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
168 |
0 | 169 if initialize: |
170 for comp in plugin_components: | |
171 comp.initialize(self.app) | |
172 | |
413
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
173 if register_timer: |
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
174 for comp in plugin_components: |
803
bf9f4e55f751
rendering: Separate performance timers for renering segments and layouts.
Ludovic Chabant <ludovic@chabant.com>
parents:
711
diff
changeset
|
175 if not register_timer_suffixes: |
bf9f4e55f751
rendering: Separate performance timers for renering segments and layouts.
Ludovic Chabant <ludovic@chabant.com>
parents:
711
diff
changeset
|
176 self.app.env.registerTimer(comp.__class__.__name__) |
bf9f4e55f751
rendering: Separate performance timers for renering segments and layouts.
Ludovic Chabant <ludovic@chabant.com>
parents:
711
diff
changeset
|
177 else: |
bf9f4e55f751
rendering: Separate performance timers for renering segments and layouts.
Ludovic Chabant <ludovic@chabant.com>
parents:
711
diff
changeset
|
178 for s in register_timer_suffixes: |
bf9f4e55f751
rendering: Separate performance timers for renering segments and layouts.
Ludovic Chabant <ludovic@chabant.com>
parents:
711
diff
changeset
|
179 self.app.env.registerTimer( |
bf9f4e55f751
rendering: Separate performance timers for renering segments and layouts.
Ludovic Chabant <ludovic@chabant.com>
parents:
711
diff
changeset
|
180 comp.__class__.__name__ + s) |
413
eacf0a3afd0c
internal: Register performance timers for plugin components.
Ludovic Chabant <ludovic@chabant.com>
parents:
312
diff
changeset
|
181 |
7
343d08ef5668
More PieCrust 3 fixes, and a couple of miscellaneous bug fixes.
Ludovic Chabant <ludovic@chabant.com>
parents:
3
diff
changeset
|
182 if order_key is not None: |
343d08ef5668
More PieCrust 3 fixes, and a couple of miscellaneous bug fixes.
Ludovic Chabant <ludovic@chabant.com>
parents:
3
diff
changeset
|
183 all_components.sort(key=order_key) |
0 | 184 |
185 self._componentCache[name] = all_components | |
186 return all_components | |
187 |