mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
First working prototype of plugins, refs #14
Uses pluggy: https://pluggy.readthedocs.io/ Two example plugins - an uppercase template filter and a convert_units() SQL function.
This commit is contained in:
parent
efbb4e8337
commit
f2720b0c6b
5 changed files with 47 additions and 1 deletions
|
|
@ -1 +1,3 @@
|
||||||
from datasette.version import __version_info__, __version__ # noqa
|
from datasette.version import __version_info__, __version__ # noqa
|
||||||
|
from .hookspecs import hookimpl # noqa
|
||||||
|
from .hookspecs import hookspec # noqa
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import jinja2
|
||||||
import hashlib
|
import hashlib
|
||||||
import time
|
import time
|
||||||
import pint
|
import pint
|
||||||
|
import pluggy
|
||||||
import traceback
|
import traceback
|
||||||
from .utils import (
|
from .utils import (
|
||||||
Filters,
|
Filters,
|
||||||
|
|
@ -38,6 +39,7 @@ from .utils import (
|
||||||
urlsafe_components,
|
urlsafe_components,
|
||||||
validate_sql_select,
|
validate_sql_select,
|
||||||
)
|
)
|
||||||
|
from . import hookspecs
|
||||||
from .version import __version__
|
from .version import __version__
|
||||||
|
|
||||||
app_root = Path(__file__).parent.parent
|
app_root = Path(__file__).parent.parent
|
||||||
|
|
@ -49,6 +51,13 @@ connections = threading.local()
|
||||||
ureg = pint.UnitRegistry()
|
ureg = pint.UnitRegistry()
|
||||||
|
|
||||||
|
|
||||||
|
pm = pluggy.PluginManager('datasette')
|
||||||
|
pm.add_hookspecs(hookspecs)
|
||||||
|
import datasette.plugin_demo
|
||||||
|
pm.register(datasette.plugin_demo)
|
||||||
|
pm.load_setuptools_entrypoints('datasette')
|
||||||
|
|
||||||
|
|
||||||
class DatasetteError(Exception):
|
class DatasetteError(Exception):
|
||||||
def __init__(self, message, title=None, error_dict=None, status=500, template=None):
|
def __init__(self, message, title=None, error_dict=None, status=500, template=None):
|
||||||
self.message = message
|
self.message = message
|
||||||
|
|
@ -1100,6 +1109,7 @@ class Datasette:
|
||||||
conn.enable_load_extension(True)
|
conn.enable_load_extension(True)
|
||||||
for extension in self.sqlite_extensions:
|
for extension in self.sqlite_extensions:
|
||||||
conn.execute("SELECT load_extension('{}')".format(extension))
|
conn.execute("SELECT load_extension('{}')".format(extension))
|
||||||
|
pm.hook.prepare_connection(conn=conn)
|
||||||
|
|
||||||
def inspect(self):
|
def inspect(self):
|
||||||
if not self._inspect:
|
if not self._inspect:
|
||||||
|
|
@ -1226,6 +1236,7 @@ class Datasette:
|
||||||
self.jinja_env.filters['quote_plus'] = lambda u: urllib.parse.quote_plus(u)
|
self.jinja_env.filters['quote_plus'] = lambda u: urllib.parse.quote_plus(u)
|
||||||
self.jinja_env.filters['escape_sqlite'] = escape_sqlite
|
self.jinja_env.filters['escape_sqlite'] = escape_sqlite
|
||||||
self.jinja_env.filters['to_css_class'] = to_css_class
|
self.jinja_env.filters['to_css_class'] = to_css_class
|
||||||
|
pm.hook.prepare_jinja2_environment(env=self.jinja_env)
|
||||||
app.add_route(IndexView.as_view(self), '/<as_json:(\.jsono?)?$>')
|
app.add_route(IndexView.as_view(self), '/<as_json:(\.jsono?)?$>')
|
||||||
# TODO: /favicon.ico and /-/static/ deserve far-future cache expires
|
# TODO: /favicon.ico and /-/static/ deserve far-future cache expires
|
||||||
app.add_route(favicon, '/favicon.ico')
|
app.add_route(favicon, '/favicon.ico')
|
||||||
|
|
|
||||||
15
datasette/hookspecs.py
Normal file
15
datasette/hookspecs.py
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
from pluggy import HookimplMarker
|
||||||
|
from pluggy import HookspecMarker
|
||||||
|
|
||||||
|
hookspec = HookspecMarker('datasette')
|
||||||
|
hookimpl = HookimplMarker('datasette')
|
||||||
|
|
||||||
|
|
||||||
|
@hookspec
|
||||||
|
def prepare_connection(conn):
|
||||||
|
"Modify SQLite connection in some way e.g. register custom SQL functions"
|
||||||
|
|
||||||
|
|
||||||
|
@hookspec
|
||||||
|
def prepare_jinja2_environment(env):
|
||||||
|
"Modify Jinja2 template environment e.g. register custom template tags"
|
||||||
17
datasette/plugin_demo.py
Normal file
17
datasette/plugin_demo.py
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
from datasette import hookimpl
|
||||||
|
import pint
|
||||||
|
|
||||||
|
ureg = pint.UnitRegistry()
|
||||||
|
|
||||||
|
|
||||||
|
@hookimpl
|
||||||
|
def prepare_jinja2_environment(env):
|
||||||
|
env.filters['uppercase'] = lambda u: u.upper()
|
||||||
|
|
||||||
|
|
||||||
|
@hookimpl
|
||||||
|
def prepare_connection(conn):
|
||||||
|
def convert_units(amount, from_, to_):
|
||||||
|
"select convert_units(100, 'm', 'ft');"
|
||||||
|
return (amount * ureg(from_)).to(to_).to_tuple()[0]
|
||||||
|
conn.create_function('convert_units', 3, convert_units)
|
||||||
3
setup.py
3
setup.py
|
|
@ -28,7 +28,8 @@ setup(
|
||||||
'Sanic==0.7.0',
|
'Sanic==0.7.0',
|
||||||
'Jinja2==2.10',
|
'Jinja2==2.10',
|
||||||
'hupper==1.0',
|
'hupper==1.0',
|
||||||
'pint==0.8.1'
|
'pint==0.8.1',
|
||||||
|
'pluggy>=0.1.0,<1.0',
|
||||||
],
|
],
|
||||||
entry_points='''
|
entry_points='''
|
||||||
[console_scripts]
|
[console_scripts]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue