mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-04 14:25:08 +00:00
refactor(plugins): split PluginStoreManager into mixins (#659)
* refactor(plugins): split PluginStoreManager into mixins src/plugin_system/store_manager.py (2,977 lines) keeps the class, its shared state, locks, the uninstall registry, directory lookup and uninstall; its methods are split by area into: - store_registry.py (_RegistryMixin): registry, GitHub metadata, search, manifest validation - store_install.py (_InstallMixin): install paths and dependencies - store_update.py (_UpdateMixin): updates, rollback, local git state Pure move: all 56 members are byte-identical (checked with ast) and the assembled class has exactly the same attributes as before (checked at runtime). PluginStoreManager is imported from store_manager.py as before. Tests that patched shared modules (subprocess, requests, tempfile, shutil) through store_manager now reach them through the module whose code they exercise; a source-text contract test reads all store_*.py modules. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: annotate findings the split moved into new store modules subprocess imports and a list-form git clone (no shell), and the config template's placeholder token string -- existing code that Codacy reported as new because it moved. Annotated with the repo's nosec/nosemgrep style. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: annotate the default-branch git clone the split moved Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -210,7 +210,11 @@ class TestStandaloneBackupContract:
|
||||
from src.plugin_system import plugin_dirs
|
||||
assert plugin_dirs.BACKUP_MARKER == '.standalone-backup-'
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
sm_text = (root / "src/plugin_system/store_manager.py").read_text(encoding="utf-8")
|
||||
# PluginStoreManager's methods are spread over store_manager.py and
|
||||
# its store_*.py mixins.
|
||||
sm_text = "".join(
|
||||
p.read_text(encoding="utf-8")
|
||||
for p in sorted((root / "src/plugin_system").glob("store_*.py")))
|
||||
assert "{BACKUP_MARKER}preinstall" in sm_text
|
||||
assert "{BACKUP_MARKER}migrating" in sm_text
|
||||
assert plugin_dirs.is_ignored_dir_name(
|
||||
|
||||
@@ -42,8 +42,8 @@ def _run(tmp_path, move_side_effect=None):
|
||||
return path
|
||||
|
||||
with patch.object(sm, '_http_get_with_retries', return_value=_response(_zip_bytes())), \
|
||||
patch('src.plugin_system.store_manager.tempfile.mkdtemp', side_effect=tracking_mkdtemp), \
|
||||
patch('src.plugin_system.store_manager.shutil.move', side_effect=move_side_effect):
|
||||
patch('src.plugin_system.store_install.tempfile.mkdtemp', side_effect=tracking_mkdtemp), \
|
||||
patch('src.plugin_system.store_install.shutil.move', side_effect=move_side_effect):
|
||||
ok = sm._install_via_download('https://example.invalid/demo.zip', plugins_dir / 'demo')
|
||||
return ok, created
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ def test_github_network_failure_logs_a_warning_not_an_error(caplog):
|
||||
from src.plugin_system.store_manager import PluginStoreManager
|
||||
with TemporaryDirectory() as tmp:
|
||||
sm = PluginStoreManager(plugins_dir=tmp)
|
||||
with patch("src.plugin_system.store_manager.requests.get",
|
||||
with patch("src.plugin_system.store_registry.requests.get",
|
||||
side_effect=requests.ConnectionError("offline")), \
|
||||
caplog.at_level(logging.WARNING):
|
||||
info = sm._get_github_repo_info("https://github.com/owner/repo")
|
||||
|
||||
@@ -468,7 +468,7 @@ class TestGitPullGate:
|
||||
import src
|
||||
monkeypatch.setattr(src, '__version__', '3.2.0')
|
||||
monkeypatch.setattr(
|
||||
'src.plugin_system.store_manager.subprocess.run', fail_stash)
|
||||
'src.plugin_system.store_update.subprocess.run', fail_stash)
|
||||
assert mgr.update_plugin('gitplug') is False
|
||||
|
||||
assert self._head(work) == before, "must not pull what it cannot undo"
|
||||
@@ -496,7 +496,7 @@ class TestGitPullGate:
|
||||
import src
|
||||
monkeypatch.setattr(src, '__version__', '3.2.0')
|
||||
monkeypatch.setattr(
|
||||
'src.plugin_system.store_manager.subprocess.run', fail_reset)
|
||||
'src.plugin_system.store_update.subprocess.run', fail_reset)
|
||||
assert mgr.update_plugin('gitplug') is False
|
||||
|
||||
logged = ' '.join(str(c) for c in mgr.logger.error.call_args_list)
|
||||
|
||||
@@ -157,7 +157,7 @@ class TestGitInfoCache(unittest.TestCase):
|
||||
|
||||
def test_cache_hits_avoid_subprocess_calls(self):
|
||||
with patch(
|
||||
"src.plugin_system.store_manager.subprocess.run",
|
||||
"src.plugin_system.store_update.subprocess.run",
|
||||
side_effect=self._fake_subprocess_run,
|
||||
) as mock_run:
|
||||
first = self.sm._get_local_git_info(self.plugin_path)
|
||||
@@ -174,7 +174,7 @@ class TestGitInfoCache(unittest.TestCase):
|
||||
|
||||
def test_cache_invalidates_on_head_mtime_change(self):
|
||||
with patch(
|
||||
"src.plugin_system.store_manager.subprocess.run",
|
||||
"src.plugin_system.store_update.subprocess.run",
|
||||
side_effect=self._fake_subprocess_run,
|
||||
) as mock_run:
|
||||
self.sm._get_local_git_info(self.plugin_path)
|
||||
@@ -229,7 +229,7 @@ class TestGitInfoCache(unittest.TestCase):
|
||||
return result
|
||||
|
||||
with patch(
|
||||
"src.plugin_system.store_manager.subprocess.run",
|
||||
"src.plugin_system.store_update.subprocess.run",
|
||||
side_effect=fake_subprocess_run,
|
||||
):
|
||||
first = self.sm._get_local_git_info(self.plugin_path)
|
||||
@@ -284,7 +284,7 @@ class TestGitInfoCache(unittest.TestCase):
|
||||
return result
|
||||
|
||||
with patch(
|
||||
"src.plugin_system.store_manager.subprocess.run",
|
||||
"src.plugin_system.store_update.subprocess.run",
|
||||
side_effect=fake_subprocess_run,
|
||||
):
|
||||
first = self.sm._get_local_git_info(self.plugin_path)
|
||||
@@ -442,7 +442,7 @@ class TestStaleOnErrorFallbacks(unittest.TestCase):
|
||||
self.sm.cache_timeout = 1 # force re-fetch
|
||||
|
||||
import requests as real_requests
|
||||
with patch("src.plugin_system.store_manager.requests.get",
|
||||
with patch("src.plugin_system.store_registry.requests.get",
|
||||
side_effect=real_requests.ConnectionError("boom")):
|
||||
result = self.sm._get_github_repo_info("https://github.com/owner/repo")
|
||||
self.assertEqual(result["stars"], 42)
|
||||
@@ -472,7 +472,7 @@ class TestStaleOnErrorFallbacks(unittest.TestCase):
|
||||
call_count["n"] += 1
|
||||
raise real_requests.ConnectionError("boom")
|
||||
|
||||
with patch("src.plugin_system.store_manager.requests.get", side_effect=counting_get):
|
||||
with patch("src.plugin_system.store_registry.requests.get", side_effect=counting_get):
|
||||
first = self.sm._get_github_repo_info("https://github.com/owner/repo")
|
||||
self.assertEqual(first["stars"], 99)
|
||||
self.assertEqual(call_count["n"], 1)
|
||||
@@ -505,7 +505,7 @@ class TestStaleOnErrorFallbacks(unittest.TestCase):
|
||||
call_count["n"] += 1
|
||||
return rate_limited
|
||||
|
||||
with patch("src.plugin_system.store_manager.requests.get", side_effect=counting_get):
|
||||
with patch("src.plugin_system.store_registry.requests.get", side_effect=counting_get):
|
||||
self.sm._get_github_repo_info("https://github.com/owner/repo")
|
||||
self.assertEqual(call_count["n"], 1)
|
||||
self.sm._get_github_repo_info("https://github.com/owner/repo")
|
||||
@@ -523,7 +523,7 @@ class TestStaleOnErrorFallbacks(unittest.TestCase):
|
||||
self.sm.commit_cache_timeout = 1 # force re-fetch
|
||||
|
||||
import requests as real_requests
|
||||
with patch("src.plugin_system.store_manager.requests.get",
|
||||
with patch("src.plugin_system.store_registry.requests.get",
|
||||
side_effect=real_requests.ConnectionError("boom")):
|
||||
result = self.sm._get_latest_commit_info(
|
||||
"https://github.com/owner/repo", branch="main"
|
||||
@@ -553,7 +553,7 @@ class TestStaleOnErrorFallbacks(unittest.TestCase):
|
||||
not_found = MagicMock()
|
||||
not_found.status_code = 404
|
||||
not_found.text = "Not Found"
|
||||
with patch("src.plugin_system.store_manager.requests.get", return_value=not_found):
|
||||
with patch("src.plugin_system.store_registry.requests.get", return_value=not_found):
|
||||
result = self.sm._get_latest_commit_info(
|
||||
"https://github.com/owner/repo", branch="main"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user