vector-inspector 0.3.6__py3-none-any.whl → 0.3.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vector_inspector/core/connections/chroma_connection.py +4 -1
- vector_inspector/core/connections/pgvector_connection.py +108 -93
- vector_inspector/core/connections/pinecone_connection.py +4 -0
- vector_inspector/core/connections/qdrant_connection.py +13 -0
- vector_inspector/core/provider_factory.py +97 -0
- vector_inspector/services/update_service.py +73 -0
- vector_inspector/ui/components/splash_window.py +14 -2
- vector_inspector/ui/components/update_details_dialog.py +47 -0
- vector_inspector/ui/controllers/__init__.py +1 -0
- vector_inspector/ui/controllers/connection_controller.py +177 -0
- vector_inspector/ui/main_window.py +148 -323
- vector_inspector/ui/main_window_shell.py +106 -0
- vector_inspector/ui/services/__init__.py +1 -0
- vector_inspector/ui/services/dialog_service.py +113 -0
- vector_inspector/ui/tabs.py +64 -0
- vector_inspector/ui/views/metadata_view.py +72 -0
- vector_inspector/utils/version.py +11 -4
- {vector_inspector-0.3.6.dist-info → vector_inspector-0.3.8.dist-info}/METADATA +27 -5
- {vector_inspector-0.3.6.dist-info → vector_inspector-0.3.8.dist-info}/RECORD +21 -12
- {vector_inspector-0.3.6.dist-info → vector_inspector-0.3.8.dist-info}/WHEEL +0 -0
- {vector_inspector-0.3.6.dist-info → vector_inspector-0.3.8.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"""Controller for managing connection lifecycle and threading."""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Optional
|
|
4
|
+
from PySide6.QtCore import QObject, Signal, QThread
|
|
5
|
+
from PySide6.QtWidgets import QMessageBox, QWidget
|
|
6
|
+
|
|
7
|
+
from vector_inspector.core.connection_manager import ConnectionManager, ConnectionState
|
|
8
|
+
from vector_inspector.core.connections.base_connection import VectorDBConnection
|
|
9
|
+
from vector_inspector.core.provider_factory import ProviderFactory
|
|
10
|
+
from vector_inspector.services.profile_service import ProfileService
|
|
11
|
+
from vector_inspector.ui.components.loading_dialog import LoadingDialog
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ConnectionThread(QThread):
|
|
15
|
+
"""Background thread for connecting to database."""
|
|
16
|
+
|
|
17
|
+
finished = Signal(bool, list, str) # success, collections, error_message
|
|
18
|
+
|
|
19
|
+
def __init__(self, connection: VectorDBConnection):
|
|
20
|
+
super().__init__()
|
|
21
|
+
self.connection = connection
|
|
22
|
+
|
|
23
|
+
def run(self):
|
|
24
|
+
"""Connect to database and get collections."""
|
|
25
|
+
try:
|
|
26
|
+
success = self.connection.connect()
|
|
27
|
+
if success:
|
|
28
|
+
collections = self.connection.list_collections()
|
|
29
|
+
self.finished.emit(True, collections, "")
|
|
30
|
+
else:
|
|
31
|
+
self.finished.emit(False, [], "Connection failed")
|
|
32
|
+
except Exception as e:
|
|
33
|
+
self.finished.emit(False, [], str(e))
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ConnectionController(QObject):
|
|
37
|
+
"""Controller for managing connection operations and lifecycle.
|
|
38
|
+
|
|
39
|
+
This handles:
|
|
40
|
+
- Creating connections from profiles
|
|
41
|
+
- Starting connection threads
|
|
42
|
+
- Handling connection results
|
|
43
|
+
- Managing loading dialogs
|
|
44
|
+
- Emitting signals for UI updates
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
connection_completed = Signal(
|
|
48
|
+
str, bool, list, str
|
|
49
|
+
) # connection_id, success, collections, error
|
|
50
|
+
|
|
51
|
+
def __init__(
|
|
52
|
+
self,
|
|
53
|
+
connection_manager: ConnectionManager,
|
|
54
|
+
profile_service: ProfileService,
|
|
55
|
+
parent: Optional[QWidget] = None,
|
|
56
|
+
):
|
|
57
|
+
super().__init__(parent)
|
|
58
|
+
self.connection_manager = connection_manager
|
|
59
|
+
self.profile_service = profile_service
|
|
60
|
+
self.parent_widget = parent
|
|
61
|
+
|
|
62
|
+
# State
|
|
63
|
+
self._connection_threads: Dict[str, ConnectionThread] = {}
|
|
64
|
+
self.loading_dialog = LoadingDialog("Loading...", parent)
|
|
65
|
+
|
|
66
|
+
def connect_to_profile(self, profile_id: str) -> bool:
|
|
67
|
+
"""Connect to a profile.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
profile_id: ID of the profile to connect to
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
True if connection initiated successfully, False otherwise
|
|
74
|
+
"""
|
|
75
|
+
profile_data = self.profile_service.get_profile_with_credentials(profile_id)
|
|
76
|
+
if not profile_data:
|
|
77
|
+
QMessageBox.warning(self.parent_widget, "Error", "Profile not found.")
|
|
78
|
+
return False
|
|
79
|
+
|
|
80
|
+
# Check connection limit
|
|
81
|
+
if self.connection_manager.get_connection_count() >= ConnectionManager.MAX_CONNECTIONS:
|
|
82
|
+
QMessageBox.warning(
|
|
83
|
+
self.parent_widget,
|
|
84
|
+
"Connection Limit",
|
|
85
|
+
f"Maximum number of connections ({ConnectionManager.MAX_CONNECTIONS}) reached. "
|
|
86
|
+
"Please close a connection first.",
|
|
87
|
+
)
|
|
88
|
+
return False
|
|
89
|
+
|
|
90
|
+
# Create connection
|
|
91
|
+
provider = profile_data["provider"]
|
|
92
|
+
config = profile_data["config"]
|
|
93
|
+
credentials = profile_data.get("credentials", {})
|
|
94
|
+
|
|
95
|
+
try:
|
|
96
|
+
# Create connection object using factory
|
|
97
|
+
connection = ProviderFactory.create(provider, config, credentials)
|
|
98
|
+
|
|
99
|
+
# Register with connection manager, using profile_id as connection_id for persistence
|
|
100
|
+
connection_id = self.connection_manager.create_connection(
|
|
101
|
+
name=profile_data["name"],
|
|
102
|
+
provider=provider,
|
|
103
|
+
connection=connection,
|
|
104
|
+
config=config,
|
|
105
|
+
connection_id=profile_data["id"],
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# Update state to connecting
|
|
109
|
+
self.connection_manager.update_connection_state(
|
|
110
|
+
connection_id, ConnectionState.CONNECTING
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Connect in background thread
|
|
114
|
+
thread = ConnectionThread(connection)
|
|
115
|
+
thread.finished.connect(
|
|
116
|
+
lambda success, collections, error: self._on_connection_finished(
|
|
117
|
+
connection_id, success, collections, error
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
self._connection_threads[connection_id] = thread
|
|
121
|
+
thread.start()
|
|
122
|
+
|
|
123
|
+
# Show loading dialog
|
|
124
|
+
self.loading_dialog.show_loading(f"Connecting to {profile_data['name']}...")
|
|
125
|
+
return True
|
|
126
|
+
|
|
127
|
+
except Exception as e:
|
|
128
|
+
QMessageBox.critical(
|
|
129
|
+
self.parent_widget, "Connection Error", f"Failed to create connection: {e}"
|
|
130
|
+
)
|
|
131
|
+
return False
|
|
132
|
+
|
|
133
|
+
def _on_connection_finished(
|
|
134
|
+
self, connection_id: str, success: bool, collections: list, error: str
|
|
135
|
+
):
|
|
136
|
+
"""Handle connection thread completion."""
|
|
137
|
+
self.loading_dialog.hide_loading()
|
|
138
|
+
|
|
139
|
+
# Clean up thread
|
|
140
|
+
thread = self._connection_threads.pop(connection_id, None)
|
|
141
|
+
if thread:
|
|
142
|
+
thread.wait() # Wait for thread to fully finish
|
|
143
|
+
thread.deleteLater()
|
|
144
|
+
|
|
145
|
+
if success:
|
|
146
|
+
# Update state to connected
|
|
147
|
+
self.connection_manager.update_connection_state(
|
|
148
|
+
connection_id, ConnectionState.CONNECTED
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# Mark connection as opened first (will show in UI)
|
|
152
|
+
self.connection_manager.mark_connection_opened(connection_id)
|
|
153
|
+
|
|
154
|
+
# Then update collections (UI item now exists to receive them)
|
|
155
|
+
self.connection_manager.update_collections(connection_id, collections)
|
|
156
|
+
else:
|
|
157
|
+
# Update state to error
|
|
158
|
+
self.connection_manager.update_connection_state(
|
|
159
|
+
connection_id, ConnectionState.ERROR, error
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
QMessageBox.warning(
|
|
163
|
+
self.parent_widget, "Connection Failed", f"Failed to connect: {error}"
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
# Remove the failed connection
|
|
167
|
+
self.connection_manager.close_connection(connection_id)
|
|
168
|
+
|
|
169
|
+
# Emit signal for UI updates
|
|
170
|
+
self.connection_completed.emit(connection_id, success, collections, error)
|
|
171
|
+
|
|
172
|
+
def cleanup(self):
|
|
173
|
+
"""Clean up connection threads on shutdown."""
|
|
174
|
+
for thread in list(self._connection_threads.values()):
|
|
175
|
+
if thread.isRunning():
|
|
176
|
+
thread.quit()
|
|
177
|
+
thread.wait(1000) # Wait up to 1 second
|