Coverage for src/qdrant_loader/config/sources.py: 81%
59 statements
« prev ^ index » next coverage.py v7.8.2, created at 2025-06-04 05:50 +0000
« prev ^ index » next coverage.py v7.8.2, created at 2025-06-04 05:50 +0000
1"""Sources configuration.
3This module defines the configuration for all data sources, including Git repositories,
4Confluence spaces, Jira projects, and public documentation.
5"""
7from typing import TYPE_CHECKING, Any
8from pydantic import BaseModel, ConfigDict, Field
10from qdrant_loader.config.source_config import SourceConfig
11from qdrant_loader.config.types import SourceType
13# Use TYPE_CHECKING to avoid circular imports at runtime
14if TYPE_CHECKING:
15 from qdrant_loader.connectors.confluence.config import ConfluenceSpaceConfig
16 from qdrant_loader.connectors.git.config import GitRepoConfig
17 from qdrant_loader.connectors.jira.config import JiraProjectConfig
18 from qdrant_loader.connectors.localfile.config import LocalFileConfig
19 from qdrant_loader.connectors.publicdocs.config import PublicDocsSourceConfig
22def _get_connector_config_classes():
23 """Lazy import connector config classes to avoid circular dependencies."""
24 from qdrant_loader.connectors.confluence.config import ConfluenceSpaceConfig
25 from qdrant_loader.connectors.git.config import GitRepoConfig
26 from qdrant_loader.connectors.jira.config import JiraProjectConfig
27 from qdrant_loader.connectors.localfile.config import LocalFileConfig
28 from qdrant_loader.connectors.publicdocs.config import PublicDocsSourceConfig
30 return {
31 "PublicDocsSourceConfig": PublicDocsSourceConfig,
32 "GitRepoConfig": GitRepoConfig,
33 "ConfluenceSpaceConfig": ConfluenceSpaceConfig,
34 "JiraProjectConfig": JiraProjectConfig,
35 "LocalFileConfig": LocalFileConfig,
36 }
39class SourcesConfig(BaseModel):
40 """Configuration for all available data sources."""
42 publicdocs: dict[str, Any] = Field(
43 default_factory=dict, description="Public documentation sources"
44 )
45 git: dict[str, Any] = Field(
46 default_factory=dict, description="Git repository sources"
47 )
48 confluence: dict[str, Any] = Field(
49 default_factory=dict, description="Confluence space sources"
50 )
51 jira: dict[str, Any] = Field(
52 default_factory=dict, description="Jira project sources"
53 )
54 localfile: dict[str, Any] = Field(
55 default_factory=dict, description="Local file sources"
56 )
58 model_config = ConfigDict(arbitrary_types_allowed=False, extra="forbid")
60 def __init__(self, **data):
61 """Initialize SourcesConfig with proper connector config objects."""
62 # Convert dictionaries to proper config objects
63 processed_data = {}
65 for field_name, field_value in data.items():
66 if field_name in [
67 "publicdocs",
68 "git",
69 "confluence",
70 "jira",
71 "localfile",
72 ] and isinstance(field_value, dict):
73 processed_data[field_name] = self._convert_source_configs(
74 field_name, field_value
75 )
76 else:
77 processed_data[field_name] = field_value
79 super().__init__(**processed_data)
81 def _convert_source_configs(self, source_type: str, configs: dict) -> dict:
82 """Convert dictionary configs to proper config objects."""
83 config_classes = _get_connector_config_classes()
84 converted = {}
86 for name, config_data in configs.items():
87 if isinstance(config_data, dict):
88 # Get the appropriate config class
89 if source_type == "publicdocs":
90 config_class = config_classes["PublicDocsSourceConfig"]
91 elif source_type == "git":
92 config_class = config_classes["GitRepoConfig"]
93 elif source_type == "confluence":
94 config_class = config_classes["ConfluenceSpaceConfig"]
95 elif source_type == "jira":
96 config_class = config_classes["JiraProjectConfig"]
97 elif source_type == "localfile":
98 config_class = config_classes["LocalFileConfig"]
99 else:
100 # Unknown source type, keep as dict
101 converted[name] = config_data
102 continue
104 # Create the config object - let validation errors propagate
105 try:
106 converted[name] = config_class(**config_data)
107 except (ImportError, AttributeError, TypeError) as e:
108 # Only catch import/type errors, not validation errors
109 # These indicate missing dependencies or code issues
110 converted[name] = config_data
111 # Let ValidationError and other Pydantic errors propagate
112 else:
113 # Already a config object or other type
114 converted[name] = config_data
116 return converted
118 def get_source_config(self, source_type: str, source: str) -> SourceConfig | None:
119 """Get the configuration for a specific source.
121 Args:
122 source_type: Type of the source (publicdocs, git, confluence, jira)
123 source: Name of the specific source configuration
125 Returns:
126 Optional[BaseModel]: The source configuration if it exists, None otherwise
127 """
128 source_dict = getattr(self, source_type, {})
129 return source_dict.get(source)
131 def to_dict(self) -> dict:
132 """Convert the configuration to a dictionary."""
133 return {
134 SourceType.PUBLICDOCS: {
135 name: config.model_dump() if hasattr(config, "model_dump") else config
136 for name, config in self.publicdocs.items()
137 },
138 SourceType.GIT: {
139 name: config.model_dump() if hasattr(config, "model_dump") else config
140 for name, config in self.git.items()
141 },
142 SourceType.CONFLUENCE: {
143 name: config.model_dump() if hasattr(config, "model_dump") else config
144 for name, config in self.confluence.items()
145 },
146 SourceType.JIRA: {
147 name: config.model_dump() if hasattr(config, "model_dump") else config
148 for name, config in self.jira.items()
149 },
150 SourceType.LOCALFILE: {
151 name: config.model_dump() if hasattr(config, "model_dump") else config
152 for name, config in self.localfile.items()
153 },
154 }