Coverage for openhcs/processing/backends/lib_registry/registry_service.py: 89.6%
40 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-04 02:09 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-04 02:09 +0000
1"""
2Registry Service - Clean function discovery and metadata access.
4Provides unified access to all registry implementations with automatic discovery.
5Follows OpenHCS generic solution principle - automatically adapts to new registries.
6"""
8import logging
9from typing import Dict, List, Optional, Type
10from .unified_registry import LibraryRegistryBase, FunctionMetadata, LIBRARY_REGISTRIES
12logger = logging.getLogger(__name__)
15class RegistryService:
16 """
17 Clean service for registry discovery and function metadata access.
19 Automatically discovers all registry implementations and provides
20 unified access to their functions with caching.
21 """
23 _metadata_cache: Optional[Dict[str, FunctionMetadata]] = None
25 @classmethod
26 def get_all_functions_with_metadata(cls) -> Dict[str, FunctionMetadata]:
27 """Get unified metadata for all functions from all registries."""
28 if cls._metadata_cache is not None:
29 logger.debug(f"🎯 REGISTRY SERVICE: Using cached metadata ({len(cls._metadata_cache)} functions)")
30 return cls._metadata_cache
32 logger.debug("🎯 REGISTRY SERVICE: Discovering functions from all registries...")
33 all_functions = {}
35 # Registries auto-discovered on first access to LIBRARY_REGISTRIES
36 registry_classes = list(LIBRARY_REGISTRIES.values())
37 logger.debug(f"🎯 REGISTRY SERVICE: Found {len(registry_classes)} registered library registries")
39 # Load functions from each registry
40 for registry_class in registry_classes:
41 try:
42 registry_instance = registry_class()
44 # Skip if library not available
45 if not registry_instance.is_library_available():
46 logger.warning(f"Library {registry_instance.library_name} not available, skipping")
47 continue
49 # Get functions from this registry (with caching)
50 logger.debug(f"🎯 REGISTRY SERVICE: Calling _load_or_discover_functions for {registry_instance.library_name}")
51 functions = registry_instance._load_or_discover_functions()
52 logger.debug(f"🎯 REGISTRY SERVICE: Retrieved {len(functions)} {registry_instance.library_name} functions")
54 # Use composite keys to prevent function name collisions between backends
55 # Format: "backend:function_name" (e.g., "torch:stack_percentile_normalize")
56 for func_name, metadata in functions.items():
57 composite_key = f"{registry_instance.library_name}:{func_name}"
58 all_functions[composite_key] = metadata
60 except Exception as e:
61 logger.warning(f"Failed to load registry {registry_class.__name__}: {e}")
62 continue
64 logger.info(f"Total functions discovered: {len(all_functions)}")
65 cls._metadata_cache = all_functions
66 return all_functions
70 @classmethod
71 def clear_metadata_cache(cls) -> None:
72 """Clear cached metadata to force re-discovery."""
73 cls._metadata_cache = None
74 logger.info("Registry metadata cache cleared")
77# Backward compatibility aliases
78FunctionRegistryService = RegistryService
79get_all_functions_with_metadata = RegistryService.get_all_functions_with_metadata
80clear_metadata_cache = RegistryService.clear_metadata_cache