Coverage for nexusLIMS/tui/apps/instruments/app.py: 100%

29 statements  

« prev     ^ index     » next       coverage.py v7.11.3, created at 2026-03-24 05:23 +0000

1""" 

2Instrument Management TUI Application. 

3 

4Provides an interactive terminal UI for CRUD operations on the NexusLIMS 

5instruments database. 

6""" 

7 

8from pathlib import Path 

9 

10from sqlmodel import Session, create_engine 

11 

12from nexusLIMS import config 

13from nexusLIMS.tui.apps.instruments.screens import InstrumentListScreen 

14from nexusLIMS.tui.common.base_app import BaseNexusApp 

15 

16 

17class InstrumentManagerApp(BaseNexusApp): 

18 """ 

19 TUI application for managing NexusLIMS instruments. 

20 

21 Provides: 

22 - List view of all instruments 

23 - Add new instruments 

24 - Edit existing instruments 

25 - Delete instruments (with confirmation) 

26 - Theme switching 

27 - Help screen 

28 

29 Parameters 

30 ---------- 

31 db_path : pathlib.Path | None 

32 Path to the database file. If provided, overrides NX_DB_PATH from config. 

33 If None, uses the value from config.settings.NX_DB_PATH. 

34 """ 

35 

36 def __init__(self, db_path: Path | None = None, **kwargs): 

37 """Initialize the instrument manager app.""" 

38 self._db_path = db_path 

39 super().__init__(**kwargs) 

40 

41 @property 

42 def db_path(self) -> Path: 

43 """Get the database path (override or from config).""" 

44 return ( 

45 self._db_path if self._db_path is not None else config.settings.NX_DB_PATH 

46 ) 

47 

48 def on_mount(self) -> None: 

49 """Set up the app and show instrument list.""" 

50 # If custom db_path provided, create custom session 

51 if self._db_path is not None: 

52 try: 

53 engine = create_engine( 

54 f"sqlite:///{self._db_path}", 

55 connect_args={"check_same_thread": False}, 

56 ) 

57 self.db_session = Session(engine) 

58 except Exception as e: 

59 self.show_error(f"Database connection failed: {e}") 

60 return 

61 

62 # Call parent on_mount (which creates default db_session if not set) 

63 super().on_mount() 

64 

65 # Set title with database path 

66 self.title = f"NexusLIMS Instrument Manager - {self.db_path}" 

67 

68 # Push the list screen as the main screen 

69 self.push_screen(InstrumentListScreen()) 

70 

71 def get_app_name(self) -> str: 

72 """Get application name for help screen.""" 

73 return "NexusLIMS Instrument Manager" 

74 

75 def get_keybindings(self) -> list[tuple[str, str]]: 

76 """Get app-specific keybindings for help screen.""" 

77 base_bindings = super().get_keybindings() 

78 

79 app_bindings = [ 

80 ("a", "Add new instrument"), 

81 ("e / Enter", "Edit selected instrument"), 

82 ("d", "Delete selected instrument"), 

83 ("r", "Refresh instrument list"), 

84 ("s", "Cycle sort column (press repeatedly to change column/direction)"), 

85 ("/", "Focus filter/search bar"), 

86 ("↑↓", "Navigate instrument list"), 

87 ("Click column header", "Sort by that column (click again to reverse)"), 

88 ("Double click instrument row", "Edit that instrument's data"), 

89 ] 

90 

91 return app_bindings + base_bindings