77into entries of :data:`datalab.config.OTHER_PLUGINS_PATHLIST` and verifies
88that :func:`datalab.plugins.discover_plugins` actually finds plugin modules
99placed in those directories.
10+
11+ The parsing function is tested directly (without reloading
12+ ``datalab.config``) to avoid corrupting global singletons (``Conf``,
13+ ``PluginRegistry``, the ``PluginBase`` metaclass) shared with the rest of
14+ the test session.
1015"""
1116
1217# guitest: skip
1318
1419from __future__ import annotations
1520
16- import importlib
1721import os
1822import sys
1923import textwrap
2024from pathlib import Path
2125
2226import pytest
2327
28+ from datalab import config as config_mod
29+ from datalab import plugins as plugins_mod
2430
25- def _reload_config (monkeypatch : pytest .MonkeyPatch , env_value : str | None ) -> object :
26- """Reload ``datalab.config`` with a controlled ``DATALAB_PLUGINS`` value."""
27- if env_value is None :
28- monkeypatch .delenv ("DATALAB_PLUGINS" , raising = False )
29- else :
30- monkeypatch .setenv ("DATALAB_PLUGINS" , env_value )
31- import datalab .config as config_mod
3231
33- return importlib .reload (config_mod )
32+ def test_env_var_unset_leaves_default_paths () -> None :
33+ """When the env var is empty/unset, the path list is left untouched."""
34+ pathlist : list [str ] = ["/initial/path" ]
35+ env_paths : list [str ] = []
3436
37+ config_mod .parse_datalab_plugins_env_var (None , pathlist , env_paths )
38+ config_mod .parse_datalab_plugins_env_var ("" , pathlist , env_paths )
3539
36- def test_env_var_unset_leaves_default_paths (monkeypatch : pytest .MonkeyPatch ) -> None :
37- """When the env var is unset, the default plugin path list is unchanged."""
38- config_mod = _reload_config (monkeypatch , None )
39- assert config_mod .OTHER_PLUGINS_PATHLIST # at least the bundled directory
40+ assert pathlist == ["/initial/path" ]
41+ assert env_paths == []
4042
4143
42- def test_env_var_adds_existing_directories (
43- monkeypatch : pytest .MonkeyPatch , tmp_path : Path
44- ) -> None :
45- """Existing directories listed in the env var are appended to the path list."""
44+ def test_env_var_adds_existing_directories (tmp_path : Path ) -> None :
45+ """Existing directories listed in the env var are appended to both lists."""
4646 dir1 = tmp_path / "plugins_a"
4747 dir2 = tmp_path / "plugins_b"
4848 dir1 .mkdir ()
4949 dir2 .mkdir ()
5050 env_value = os .pathsep .join ([str (dir1 ), str (dir2 )])
5151
52- config_mod = _reload_config (monkeypatch , env_value )
53- paths = [os .path .normpath (p ) for p in config_mod .OTHER_PLUGINS_PATHLIST ]
54- assert os .path .normpath (str (dir1 )) in paths
55- assert os .path .normpath (str (dir2 )) in paths
52+ pathlist : list [str ] = []
53+ env_paths : list [str ] = []
54+ config_mod .parse_datalab_plugins_env_var (env_value , pathlist , env_paths )
55+
56+ expected = [os .path .normpath (str (dir1 )), os .path .normpath (str (dir2 ))]
57+ assert [os .path .normpath (p ) for p in pathlist ] == expected
58+ assert [os .path .normpath (p ) for p in env_paths ] == expected
5659
5760
5861def test_env_var_skips_missing_directories (
59- monkeypatch : pytest . MonkeyPatch , tmp_path : Path , caplog : pytest .LogCaptureFixture
62+ tmp_path : Path , caplog : pytest .LogCaptureFixture
6063) -> None :
61- """Missing directories are skipped silently and a warning is logged."""
64+ """Missing directories are skipped and a warning is logged."""
6265 existing = tmp_path / "exists"
6366 existing .mkdir ()
6467 missing = tmp_path / "does_not_exist"
6568 env_value = os .pathsep .join ([str (existing ), str (missing ), " " ])
6669
70+ pathlist : list [str ] = []
71+ env_paths : list [str ] = []
6772 with caplog .at_level ("WARNING" , logger = "datalab.config" ):
68- config_mod = _reload_config ( monkeypatch , env_value )
73+ config_mod . parse_datalab_plugins_env_var ( env_value , pathlist , env_paths )
6974
70- paths = [os .path .normpath (p ) for p in config_mod . OTHER_PLUGINS_PATHLIST ]
75+ paths = [os .path .normpath (p ) for p in pathlist ]
7176 assert os .path .normpath (str (existing )) in paths
7277 assert os .path .normpath (str (missing )) not in paths
7378 assert any ("does_not_exist" in r .message for r in caplog .records )
@@ -76,7 +81,12 @@ def test_env_var_skips_missing_directories(
7681def test_discover_plugins_finds_module_in_env_dir (
7782 monkeypatch : pytest .MonkeyPatch , tmp_path : Path
7883) -> None :
79- """``datalab_*`` module in a ``DATALAB_PLUGINS`` directory is discovered."""
84+ """A ``datalab_*`` module in an env-var directory is discovered.
85+
86+ ``OTHER_PLUGINS_PATHLIST`` is mutated in-place (and restored after) to
87+ avoid reloading ``datalab.config`` or ``datalab.plugins``, which would
88+ invalidate the ``PluginBase`` metaclass and break later tests.
89+ """
8090 plugin_dir = tmp_path / "extra_plugins"
8191 plugin_dir .mkdir ()
8292 plugin_name = "datalab_envvar_discovery_probe"
@@ -91,22 +101,22 @@ def test_discover_plugins_finds_module_in_env_dir(
91101 encoding = "utf-8" ,
92102 )
93103
94- monkeypatch .setenv ("DATALAB_PLUGINS" , str (plugin_dir ))
95- # Ensure config picks up the env var, then reload plugins module so it
96- # imports the refreshed OTHER_PLUGINS_PATHLIST.
97- importlib .reload (importlib .import_module ("datalab.config" ))
98- plugins_mod = importlib .reload (importlib .import_module ("datalab.plugins" ))
99-
100- # Make sure plugins are enabled for discovery
101- from datalab .config import Conf
102-
103- monkeypatch .setattr (Conf .main .plugins_enabled , "get" , lambda * a , ** kw : True )
104-
104+ extra_path = str (plugin_dir )
105+ config_mod .OTHER_PLUGINS_PATHLIST .append (extra_path )
106+ sys .modules .pop (plugin_name , None )
105107 try :
108+ # Ensure plugins are considered enabled regardless of user config
109+ monkeypatch .setattr (
110+ config_mod .Conf .main .plugins_enabled , "get" , lambda * a , ** kw : True
111+ )
106112 modules = plugins_mod .discover_plugins ()
107113 discovered_names = {m .__name__ for m in modules }
108114 assert plugin_name in discovered_names
109115 finally :
116+ try :
117+ config_mod .OTHER_PLUGINS_PATHLIST .remove (extra_path )
118+ except ValueError :
119+ pass
110120 sys .modules .pop (plugin_name , None )
111121
112122
0 commit comments