diff --git a/datasette/app.py b/datasette/app.py index 052131d0..e263cc48 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -2,7 +2,6 @@ import asyncio import click import collections import hashlib -import importlib import itertools import os import sqlite3 @@ -14,7 +13,6 @@ from concurrent import futures from pathlib import Path from markupsafe import Markup -import pluggy from jinja2 import ChoiceLoader, Environment, FileSystemLoader, PrefixLoader from sanic import Sanic, response from sanic.exceptions import InvalidUsage, NotFound @@ -28,7 +26,6 @@ from .views.index import IndexView from .views.special import JsonDataView from .views.table import RowView, TableView -from . import hookspecs from .utils import ( InterruptedError, Results, @@ -40,26 +37,13 @@ from .utils import ( to_css_class ) from .inspect import inspect_hash, inspect_views, inspect_tables +from .plugins import pm from .version import __version__ -default_plugins = ( - "datasette.publish.heroku", - "datasette.publish.now", -) - app_root = Path(__file__).parent.parent connections = threading.local() -pm = pluggy.PluginManager("datasette") -pm.add_hookspecs(hookspecs) -pm.load_setuptools_entrypoints("datasette") - -# Load default plugins -for plugin in default_plugins: - mod = importlib.import_module(plugin) - pm.register(mod, plugin) - ConfigOption = collections.namedtuple( "ConfigOption", ("name", "default", "help") diff --git a/datasette/utils.py b/datasette/utils.py index 8ecd9025..29360b35 100644 --- a/datasette/utils.py +++ b/datasette/utils.py @@ -16,7 +16,6 @@ import shutil import urllib import numbers - # From https://www.sqlite.org/lang_keywords.html reserved_words = set(( 'abort action add after all alter analyze and as asc attach autoincrement ' diff --git a/datasette/views/base.py b/datasette/views/base.py index fbb9b173..f376c327 100644 --- a/datasette/views/base.py +++ b/datasette/views/base.py @@ -13,6 +13,7 @@ from sanic.exceptions import NotFound from sanic.views import HTTPMethodView from datasette import __version__ +from datasette.plugins import pm from datasette.utils import ( CustomJSONEncoder, InterruptedError, @@ -494,7 +495,6 @@ class BaseView(RenderMixin): for value in row: display_value = value # Let the plugins have a go - from datasette.app import pm plugin_value = pm.hook.render_cell(value=value) if plugin_value is not None: display_value = plugin_value diff --git a/datasette/views/table.py b/datasette/views/table.py index 654e60fa..ae71d33d 100644 --- a/datasette/views/table.py +++ b/datasette/views/table.py @@ -5,6 +5,7 @@ import jinja2 from sanic.exceptions import NotFound from sanic.request import RequestParameters +from datasette.plugins import pm from datasette.utils import ( CustomRow, Filters, @@ -22,7 +23,6 @@ from datasette.utils import ( urlsafe_components, value_as_boolean, ) - from .base import BaseView, DatasetteError, ureg LINK_WITH_LABEL = '{label} {id}' @@ -166,7 +166,11 @@ class RowTableShared(BaseView): # already shown in the link column. continue - if isinstance(value, dict): + # First let the plugins have a go + plugin_display_value = pm.hook.render_cell(value=value) + if plugin_display_value is not None: + display_value = plugin_display_value + elif isinstance(value, dict): # It's an expanded foreign key - display link to other row label = value["label"] value = value["value"] diff --git a/tests/fixtures.py b/tests/fixtures.py index 955b155d..ffacfa51 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -223,6 +223,8 @@ def extra_js_urls(): @hookimpl def render_cell(value): # Render {"href": "...", "label": "..."} as link + if not isinstance(value, str): + return None stripped = value.strip() if not stripped.startswith("{") and stripped.endswith("}"): return None @@ -230,6 +232,8 @@ def render_cell(value): data = json.loads(value) except ValueError: return None + if not isinstance(data, dict): + return None if set(data.keys()) != {"href", "label"}: return None href = data["href"] @@ -389,9 +393,12 @@ INSERT INTO "searchable_fts" (rowid, text1, text2, [name with . and spaces]) CREATE TABLE [select] ( [group] text, [having] text, - [and] text + [and] text, + [json] text +); +INSERT INTO [select] VALUES ('group', 'having', 'and', + '{"href": "http://example.com/", "label":"Example"}' ); -INSERT INTO [select] VALUES ('group', 'having', 'and'); CREATE TABLE infinity ( value REAL diff --git a/tests/test_api.py b/tests/test_api.py index 8f67a9eb..f76795fe 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -231,7 +231,7 @@ def test_database_page(app_client): ], }, }, { - 'columns': ['group', 'having', 'and'], + 'columns': ['group', 'having', 'and', 'json'], 'name': 'select', 'count': 1, 'hidden': False, @@ -599,6 +599,7 @@ def test_table_with_reserved_word_name(app_client): 'group': 'group', 'having': 'having', 'and': 'and', + 'json': '{"href": "http://example.com/", "label":"Example"}' }]