Skip to content

Commit f448b61

Browse files
fix: Plugins are still loaded when running tests (#719)
* fix: defer plugin entrypoint loading until runtime Fixes #713 * Lazy-load plugins when listing them Keep plugin entrypoints from loading at module import time, but preserve the existing behavior of get_plugins() by loading entrypoints the first time plugins are listed outside tests. --------- Co-authored-by: Simon Willison <swillison@gmail.com>
1 parent 733a674 commit f448b61

4 files changed

Lines changed: 43 additions & 4 deletions

File tree

sqlite_utils/cli.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
NoTable,
1717
quote_identifier,
1818
)
19-
from sqlite_utils.plugins import pm, get_plugins
19+
from sqlite_utils.plugins import ensure_plugins_loaded, pm, get_plugins
2020
from sqlite_utils.utils import maximize_csv_field_size_limit
2121
from sqlite_utils import recipes
2222
import textwrap
@@ -3412,6 +3412,7 @@ def plugins_list():
34123412
click.echo(json.dumps(get_plugins(), indent=2))
34133413

34143414

3415+
ensure_plugins_loaded()
34153416
pm.hook.register_commands(cli=cli)
34163417
cli.add_command(migrate)
34173418

sqlite_utils/db.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
Tuple,
4242
)
4343
import uuid
44-
from sqlite_utils.plugins import pm
44+
from sqlite_utils.plugins import ensure_plugins_loaded, pm
4545

4646
try:
4747
iterdump = importlib.import_module("sqlite_dump").iterdump
@@ -401,6 +401,7 @@ def __init__(
401401
self._registered_functions: set = set()
402402
self.use_counts_table = use_counts_table
403403
if execute_plugins:
404+
ensure_plugins_loaded()
404405
pm.hook.prepare_connection(conn=self.conn)
405406
self.strict = strict
406407

sqlite_utils/plugins.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,19 @@
66

77
pm: pluggy.PluginManager = pluggy.PluginManager("sqlite_utils")
88
pm.add_hookspecs(hookspecs)
9+
_plugins_loaded = False
910

10-
if not getattr(sys, "_called_from_test", False):
11-
# Only load plugins if not running tests
11+
12+
def ensure_plugins_loaded() -> None:
13+
global _plugins_loaded
14+
if _plugins_loaded or getattr(sys, "_called_from_test", False):
15+
return
1216
pm.load_setuptools_entrypoints("sqlite_utils")
17+
_plugins_loaded = True
1318

1419

1520
def get_plugins() -> List[Dict[str, Union[str, List[str]]]]:
21+
ensure_plugins_loaded()
1622
plugins: List[Dict[str, Union[str, List[str]]]] = []
1723
plugin_to_distinfo = dict(pm.list_plugin_distinfo())
1824
for plugin in pm.get_plugins():

tests/test_plugins.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import click
33
import importlib
44
import pytest
5+
import sys
56
from sqlite_utils import cli, Database, hookimpl, plugins
67

78

@@ -16,6 +17,36 @@ def _supports_pragma_function_list():
1617
db.close()
1718

1819

20+
def test_get_plugins_loads_setuptools_entrypoints_once(monkeypatch):
21+
calls = []
22+
monkeypatch.delattr(sys, "_called_from_test", raising=False)
23+
monkeypatch.setattr(plugins, "_plugins_loaded", False)
24+
monkeypatch.setattr(
25+
plugins.pm,
26+
"load_setuptools_entrypoints",
27+
lambda group: calls.append(group) or 0,
28+
)
29+
30+
plugins.get_plugins()
31+
plugins.get_plugins()
32+
33+
assert calls == ["sqlite_utils"]
34+
35+
36+
def test_get_plugins_does_not_load_setuptools_entrypoints_in_tests(monkeypatch):
37+
calls = []
38+
monkeypatch.setattr(sys, "_called_from_test", True, raising=False)
39+
monkeypatch.setattr(plugins, "_plugins_loaded", False)
40+
monkeypatch.setattr(
41+
plugins.pm,
42+
"load_setuptools_entrypoints",
43+
lambda group: calls.append(group) or 0,
44+
)
45+
46+
assert plugins.get_plugins() == []
47+
assert calls == []
48+
49+
1950
def test_register_commands():
2051
importlib.reload(cli)
2152
assert plugins.get_plugins() == []

0 commit comments

Comments
 (0)