Coverage for src / qdrant_loader / cli / config_loader.py: 47%

73 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-18 04:48 +0000

1from __future__ import annotations 

2 

3from pathlib import Path 

4from typing import Any 

5 

6from click.exceptions import ClickException 

7 

8from qdrant_loader.config.state import DatabaseDirectoryError 

9from qdrant_loader.utils.logging import LoggingConfig 

10 

11 

12# Back-compat shim for tests that import _get_logger from cli.cli 

13def _get_logger(): 

14 return LoggingConfig.get_logger(__name__) 

15 

16 

17def setup_workspace(workspace_path: Path): 

18 try: 

19 from qdrant_loader.config.workspace import ( 

20 create_workspace_structure, 

21 ) 

22 from qdrant_loader.config.workspace import setup_workspace as _setup 

23 

24 create_workspace_structure(workspace_path) 

25 workspace_config = _setup(workspace_path) 

26 return workspace_config 

27 except ValueError as e: 

28 raise ClickException(str(e)) from e 

29 except Exception as e: # pragma: no cover - handled by CLI tests 

30 raise ClickException(f"Failed to setup workspace: {str(e)!s}") from e 

31 

32 

33def load_config_with_workspace( 

34 workspace_config: Any | None = None, 

35 config_path: Path | None = None, 

36 env_path: Path | None = None, 

37 skip_validation: bool = False, 

38) -> None: 

39 try: 

40 from qdrant_loader.config import initialize_config_with_workspace 

41 

42 if workspace_config: 

43 LoggingConfig.get_logger(__name__).debug( 

44 "Loading configuration in workspace mode" 

45 ) 

46 initialize_config_with_workspace( 

47 workspace_config, skip_validation=skip_validation 

48 ) 

49 else: 

50 LoggingConfig.get_logger(__name__).debug( 

51 "Loading configuration in traditional mode" 

52 ) 

53 load_config(config_path, env_path, skip_validation) 

54 except ClickException: 

55 raise 

56 except Exception as e: 

57 LoggingConfig.get_logger(__name__).error("config_load_failed", error=str(e)) 

58 # Lazy import to avoid slowing CLI startup 

59 from qdrant_loader.config.error_formatter import print_config_error 

60 

61 print_config_error(e) 

62 raise SystemExit(1) from e 

63 

64 

65def create_database_directory(path: Path) -> bool: 

66 try: 

67 abs_path = path.resolve() 

68 LoggingConfig.get_logger(__name__).info( 

69 "The database directory does not exist", path=str(abs_path) 

70 ) 

71 import click 

72 

73 if click.confirm("Would you like to create this directory?", default=True): 

74 abs_path.mkdir(parents=True, mode=0o755, exist_ok=True) 

75 LoggingConfig.get_logger(__name__).info("Created directory: %s", abs_path) 

76 return True 

77 return False 

78 except Exception as e: # pragma: no cover - interactive path 

79 raise ClickException(f"Failed to create directory: {str(e)!s}") from e 

80 

81 

82def load_config( 

83 config_path: Path | None = None, 

84 env_path: Path | None = None, 

85 skip_validation: bool = False, 

86) -> None: 

87 try: 

88 from qdrant_loader.config import initialize_config 

89 

90 if config_path is not None: 

91 if not config_path.exists(): 

92 LoggingConfig.get_logger(__name__).error( 

93 "config_not_found", path=str(config_path) 

94 ) 

95 raise ClickException(f"Config file not found: {str(config_path)!s}") 

96 initialize_config(config_path, env_path, skip_validation=skip_validation) 

97 return 

98 

99 default_config = Path("config.yaml") 

100 if default_config.exists(): 

101 initialize_config(default_config, env_path, skip_validation=skip_validation) 

102 return 

103 

104 raise ClickException( 

105 f"No config file found. Please specify a config file or create config.yaml in the current directory: {str(default_config)!s}" 

106 ) 

107 

108 except DatabaseDirectoryError as e: 

109 if skip_validation: 

110 return 

111 error_path = e.path 

112 abs_path = error_path.resolve() 

113 if not create_database_directory(abs_path): 

114 raise ClickException( 

115 "Database directory creation declined. Exiting." 

116 ) from e 

117 # After successful creation, initialize once using the original config_path if provided, 

118 # otherwise fall back to default config.yaml 

119 from qdrant_loader.config import initialize_config 

120 

121 target_config = config_path if config_path is not None else Path("config.yaml") 

122 initialize_config(target_config, env_path, skip_validation=skip_validation) 

123 except ClickException: 

124 raise 

125 except Exception as e: 

126 LoggingConfig.get_logger(__name__).error("config_load_failed", error=str(e)) 

127 # Lazy import to avoid slowing CLI startup 

128 from qdrant_loader.config.error_formatter import print_config_error 

129 

130 print_config_error(e) 

131 raise SystemExit(1) from e