refactor: introduce RouteContext for route dependency registration

This commit is contained in:
Dariusz L
2026-08-01 23:09:51 +02:00
parent 4815cee748
commit 6ff887f004
9 changed files with 96 additions and 8 deletions
+48
View File
@@ -0,0 +1,48 @@
"""Dependency container shared by route registration modules."""
from collections.abc import Mapping
from dataclasses import dataclass
from types import MappingProxyType
from typing import Any
@dataclass(frozen=True, slots=True)
class RouteContext:
"""Immutable, read-only collection of dependencies used by API routes."""
_values: Mapping[str, Any]
def __post_init__(self):
object.__setattr__(
self,
"_values",
MappingProxyType(dict(self._values)),
)
@classmethod
def from_namespaces(
cls,
*namespaces: Mapping[str, Any],
) -> "RouteContext":
"""Build a context, with later namespaces taking precedence."""
values = {}
for namespace in namespaces:
values.update(namespace)
return cls(values)
def get(self, key: str, default: Any = None) -> Any:
"""Return a dependency or the supplied default when it is optional."""
return self._values.get(key, default)
def require(self, key: str) -> Any:
"""Return a dependency or fail with a descriptive configuration error."""
try:
return self._values[key]
except KeyError as exc:
raise KeyError(f"Missing route dependency: {key}") from exc
def __contains__(self, key: str) -> bool:
return key in self._values
def __len__(self) -> int:
return len(self._values)
+4 -1
View File
@@ -1,6 +1,9 @@
"""Directories route registration."""
def register_directory_routes(context):
from .context import RouteContext
def register_directory_routes(context: RouteContext):
TEMPLATE_KEY_ALIASES = context.get('TEMPLATE_KEY_ALIASES')
asyncio = context.get('asyncio')
dedupe_local_base_directories = context.get('dedupe_local_base_directories')
+4 -1
View File
@@ -1,6 +1,9 @@
"""Downloads route registration."""
def register_download_routes(context):
from .context import RouteContext
def register_download_routes(context: RouteContext):
Aria2InstallError = context.get('Aria2InstallError')
UnsafeUrlError = context.get('UnsafeUrlError')
asyncio = context.get('asyncio')
+4 -1
View File
@@ -1,6 +1,9 @@
"""Metadata route registration."""
def register_metadata_routes(context):
from .context import RouteContext
def register_metadata_routes(context: RouteContext):
asyncio = context.get('asyncio')
audit_metadata_sizes = context.get('audit_metadata_sizes')
build_missing_local_metadata = context.get('build_missing_local_metadata')
+4 -1
View File
@@ -1,6 +1,9 @@
"""Model Info route registration."""
def register_model_info_routes(context):
from .context import RouteContext
def register_model_info_routes(context: RouteContext):
UnsafeUrlError = context.get('UnsafeUrlError')
asyncio = context.get('asyncio')
build_civarchive_custom_result = context.get('build_civarchive_custom_result')
+2 -1
View File
@@ -20,6 +20,7 @@ from ..path_utils import (
get_model_resolver_sidecar_path,
get_safe_model_resolver_sidecar_path,
)
from .context import RouteContext
def register_routes(self):
@@ -240,7 +241,7 @@ def register_routes(self):
)
register_base_model_routes(routes, web, json_api_endpoint)
route_context = {**globals(), **locals()}
route_context = RouteContext.from_namespaces(globals(), locals())
register_workflow_routes(route_context)
register_metadata_routes(route_context)
register_loaded_model_routes(route_context)
+4 -1
View File
@@ -1,6 +1,9 @@
"""Search route registration."""
def register_search_routes(context):
from .context import RouteContext
def register_search_routes(context: RouteContext):
CivArchiveSearchError = context.get('CivArchiveSearchError')
asyncio = context.get('asyncio')
build_search_result = context.get('build_search_result')
+5 -2
View File
@@ -1,6 +1,9 @@
"""Workflow and loaded-model route registration."""
def register_workflow_routes(context):
from .context import RouteContext
def register_workflow_routes(context: RouteContext):
FileManagerError = context.get('FileManagerError')
FileManagerUnavailableError = context.get('FileManagerUnavailableError')
MODEL_RESOLVER_METADATA_SCHEMA = context.get('MODEL_RESOLVER_METADATA_SCHEMA')
@@ -914,7 +917,7 @@ def register_workflow_routes(context):
cancel_message="Stopping hash calculation..."
)
def register_loaded_model_routes(context):
def register_loaded_model_routes(context: RouteContext):
adapt_custom_node_loaded_model = context.get('adapt_custom_node_loaded_model')
asyncio = context.get('asyncio')
get_filename_from_path = context.get('get_filename_from_path')
+21
View File
@@ -245,6 +245,27 @@ class TestRefactoringTargets(unittest.IsolatedAsyncioTestCase):
self.assertEqual(node_mod._version_sort_key("v1.10.2-beta"), (1, 10, 2))
self.assertEqual(node_mod._version_sort_key("unknown"), ())
def test_route_context_merges_namespaces_and_validates_required_values(self):
context_module = importlib.import_module(
"comfyui-model-resolver.core.routes.context"
)
values = {"shared": "first", "left": 1}
context = context_module.RouteContext.from_namespaces(
values,
{"shared": "second", "right": 2},
)
values["left"] = 99
self.assertEqual(context.get("shared"), "second")
self.assertEqual(context.get("left"), 1)
self.assertEqual(context.get("missing"), None)
self.assertEqual(context.get("missing", "fallback"), "fallback")
self.assertEqual(context.require("right"), 2)
self.assertIn("right", context)
self.assertEqual(len(context), 3)
with self.assertRaisesRegex(KeyError, "Missing route dependency: missing"):
context.require("missing")
def test_project_version_info_reports_remote_update(self):
version_module = importlib.import_module("comfyui-model-resolver.core.version")
network_module = importlib.import_module("comfyui-model-resolver.core.network_utils")