Source code for objectstate.global_config

"""
Generic global configuration context management.

Provides thread-local storage for global configuration state.
This is used as the base context for all lazy configuration resolution.

DUAL THREAD-LOCAL PATTERN:
- _saved_global_config_contexts: SAVED config (what descendants/compiler see)
- _live_global_config_contexts: LIVE config (what UI sees during editing)

Default behavior: UI uses LIVE (sees unsaved edits)
Explicit override: Compilation uses SAVED (via use_live_global=False)
"""

import threading
from typing import Dict, Type, Optional, Any


# Dual thread-local storage: saved (for descendants/compiler) and live (for UI editing)
_saved_global_config_contexts: Dict[Type, threading.local] = {}
_live_global_config_contexts: Dict[Type, threading.local] = {}


[docs] def set_saved_global_config(config_type: Type, config_instance: Any) -> None: """Set SAVED global config (what descendants/compiler see). Called when: - App startup loads cached config - User SAVES GlobalPipelineConfig in ConfigWindow - Tests set up saved state Args: config_type: The config type to set config_instance: The SAVED config instance """ if config_type not in _saved_global_config_contexts: _saved_global_config_contexts[config_type] = threading.local() _saved_global_config_contexts[config_type].value = config_instance
[docs] def set_live_global_config(config_type: Type, config_instance: Any) -> None: """Set LIVE global config (what UI sees during editing). Called when: - User types in GlobalPipelineConfig field (every keystroke) - UI needs to show live preview of unsaved changes Args: config_type: The config type to set config_instance: The LIVE (unsaved) config instance """ if config_type not in _live_global_config_contexts: _live_global_config_contexts[config_type] = threading.local() _live_global_config_contexts[config_type].value = config_instance
[docs] def get_saved_global_config(config_type: Type) -> Optional[Any]: """Get SAVED global config (what descendants/compiler see). Args: config_type: The config type to retrieve Returns: Saved config instance or None """ context = _saved_global_config_contexts.get(config_type) return getattr(context, 'value', None) if context else None
[docs] def get_live_global_config(config_type: Type) -> Optional[Any]: """Get LIVE global config (what UI sees during editing). Args: config_type: The config type to retrieve Returns: Live config instance or None """ context = _live_global_config_contexts.get(config_type) return getattr(context, 'value', None) if context else None
[docs] def set_current_global_config(config_type: Type, config_instance: Any, *, caller_context: str = None) -> None: """DEPRECATED: Use set_saved_global_config() or set_live_global_config() explicitly. For backward compatibility, this sets BOTH saved and live. """ set_saved_global_config(config_type, config_instance) set_live_global_config(config_type, config_instance)
[docs] def set_global_config_for_editing(config_type: Type, config_instance: Any) -> None: """Set global config for editing (sets BOTH saved and live). Use this for app startup and initial setup. For live editing updates, use set_live_global_config(). For saving, use set_saved_global_config(). Args: config_type: The config type to set config_instance: The config instance to set """ set_saved_global_config(config_type, config_instance) set_live_global_config(config_type, config_instance)
[docs] def get_current_global_config(config_type: Type, use_live: bool = True) -> Optional[Any]: """Get current global config. Args: config_type: The config type to retrieve use_live: If True (default), return LIVE config (UI sees unsaved edits). If False, return SAVED config (compiler sees saved values). Returns: Config instance or None """ if use_live: return get_live_global_config(config_type) else: return get_saved_global_config(config_type)