Coverage for openhcs/textual_tui/services/window_service.py: 0.0%

25 statements  

« prev     ^ index     » next       coverage.py v7.10.3, created at 2025-08-14 05:57 +0000

1"""Window service to break circular imports between widgets and windows.""" 

2 

3from typing import Any, Callable, List, Optional, Type 

4from pathlib import Path 

5from textual.css.query import NoMatches 

6 

7from openhcs.constants.constants import Backend 

8from openhcs.textual_tui.services.file_browser_service import SelectionMode 

9from openhcs.core.path_cache import PathCacheKey 

10 

11 

12class WindowService: 

13 """Service to handle window creation and management, breaking circular imports.""" 

14 

15 def __init__(self, app): 

16 self.app = app 

17 

18 async def open_file_browser( 

19 self, 

20 file_manager, 

21 initial_path: Path, 

22 backend: Backend = Backend.DISK, 

23 title: str = "Select Directory", 

24 mode: str = "load", # "load" or "save" 

25 selection_mode: SelectionMode = SelectionMode.DIRECTORIES_ONLY, 

26 filter_extensions: Optional[List[str]] = None, 

27 default_filename: str = "", 

28 cache_key: Optional[PathCacheKey] = None, 

29 on_result_callback: Optional[Callable] = None, 

30 caller_id: str = "unknown", 

31 enable_multi_selection: bool = False, 

32 ): 

33 """Open file browser window without circular imports.""" 

34 # Lazy import to avoid circular dependency 

35 from openhcs.textual_tui.windows.file_browser_window import ( 

36 open_file_browser_window, BrowserMode 

37 ) 

38 

39 browser_mode = BrowserMode.SAVE if mode == "save" else BrowserMode.LOAD 

40 

41 return await open_file_browser_window( 

42 app=self.app, 

43 file_manager=file_manager, 

44 initial_path=initial_path, 

45 backend=backend, 

46 title=title, 

47 mode=browser_mode, 

48 selection_mode=selection_mode, 

49 filter_extensions=filter_extensions, 

50 default_filename=default_filename, 

51 cache_key=cache_key, 

52 on_result_callback=on_result_callback, 

53 caller_id=caller_id, 

54 enable_multi_selection=enable_multi_selection, 

55 ) 

56 

57 async def open_config_window( 

58 self, 

59 config_class: Type, 

60 current_config: Any, 

61 on_save_callback: Optional[Callable] = None 

62 ): 

63 """ 

64 Open config window with separate config_class and current_config parameters. 

65 

66 Supports both GlobalPipelineConfig (global) and PipelineConfig (per-orchestrator). 

67 """ 

68 try: 

69 window = self.app.query_one(ConfigWindow) 

70 window.open_state = True 

71 except NoMatches: 

72 window = ConfigWindow( 

73 config_class=config_class, 

74 current_config=current_config, 

75 on_save_callback=on_save_callback 

76 ) 

77 await self.app.mount(window) 

78 window.open_state = True 

79 return window 

80 

81 async def open_multi_orchestrator_config( 

82 self, 

83 orchestrators: List, 

84 on_save_callback: Optional[Callable] = None 

85 ): 

86 """Open multi-orchestrator config window without circular imports.""" 

87 # Lazy import to avoid circular dependency 

88 from openhcs.textual_tui.windows.multi_orchestrator_config_window import ( 

89 show_multi_orchestrator_config 

90 ) 

91 

92 return await show_multi_orchestrator_config( 

93 app=self.app, 

94 orchestrators=orchestrators, 

95 on_save_callback=on_save_callback 

96 )