diff --git a/datasette/app.py b/datasette/app.py index 731c3d13..3adb8925 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -1058,7 +1058,11 @@ class Datasette: filepath = os.path.join(self.plugins_dir, filename) with open(filepath) as f: mod = module_from_path(filepath, name=filename) - pm.register(mod) + try: + pm.register(mod) + except ValueError: + # Plugin already registered + pass def app_css_hash(self): if not hasattr(self, '_app_css_hash'): diff --git a/tests/fixtures.py b/tests/fixtures.py index 9889f2b4..38df8b00 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -15,12 +15,16 @@ def app_client(): conn = sqlite3.connect(filepath) conn.executescript(TABLES) os.chdir(os.path.dirname(filepath)) + plugins_dir = os.path.join(tmpdir, 'plugins') + os.mkdir(plugins_dir) + open(os.path.join(plugins_dir, 'my_plugin.py'), 'w').write(PLUGIN) ds = Datasette( [filepath], page_size=50, max_returned_rows=100, sql_time_limit_ms=20, metadata=METADATA, + plugins_dir=plugins_dir, ) ds.sqlite_functions.append( ('sleep', 1, lambda n: time.sleep(float(n))), @@ -90,6 +94,20 @@ METADATA = { } } +PLUGIN = ''' +from datasette import hookimpl +import pint + +ureg = pint.UnitRegistry() + + +@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) +''' TABLES = ''' CREATE TABLE simple_primary_key ( diff --git a/tests/test_api.py b/tests/test_api.py index 050359d3..21fc34bf 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -588,8 +588,10 @@ def test_row_foreign_key_tables(app_client): def test_unit_filters(app_client): - response = app_client.get('/test_tables/units.json?distance__lt=75km&frequency__gt=1kHz', - gather_request=False) + response = app_client.get( + '/test_tables/units.json?distance__lt=75km&frequency__gt=1kHz', + gather_request=False + ) assert response.status == 200 data = response.json @@ -598,3 +600,11 @@ def test_unit_filters(app_client): assert len(data['rows']) == 1 assert data['rows'][0][0] == 2 + + +def test_plugins_dir_plugin(app_client): + response = app_client.get( + "/test_tables.json?sql=select+convert_units(100%2C+'m'%2C+'ft')", + gather_request=False + ) + assert pytest.approx(328.0839) == response.json['rows'][0][0] diff --git a/tests/test_utils.py b/tests/test_utils.py index d71ecc60..3b3b8946 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -195,6 +195,7 @@ def test_temporary_docker_directory_uses_hard_link(): extra_options=None, branch=None, template_dir=None, + plugins_dir=None, static=[], ) as temp_docker: hello = os.path.join(temp_docker, 'hello') @@ -218,6 +219,7 @@ def test_temporary_docker_directory_uses_copy_if_hard_link_fails(mock_link): extra_options=None, branch=None, template_dir=None, + plugins_dir=None, static=[], ) as temp_docker: hello = os.path.join(temp_docker, 'hello')