fleet-python 0.2.69b3__py3-none-any.whl → 0.2.70__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.

Potentially problematic release.


This version of fleet-python might be problematic. Click here for more details.

@@ -1,263 +0,0 @@
1
- """Unit tests for SQLiteResource dual-mode functionality."""
2
-
3
- import pytest
4
- import tempfile
5
- import sqlite3
6
- import os
7
- from fleet.resources.sqlite import SQLiteResource
8
- from fleet.instance.models import (
9
- Resource as ResourceModel,
10
- ResourceType,
11
- ResourceMode,
12
- QueryResponse,
13
- DescribeResponse,
14
- )
15
-
16
-
17
- class TestSQLiteResourceDirectMode:
18
- """Test SQLiteResource in direct (local file) mode."""
19
-
20
- @pytest.fixture
21
- def temp_db(self):
22
- """Create a temporary SQLite database for testing."""
23
- fd, path = tempfile.mkstemp(suffix=".db")
24
- os.close(fd)
25
-
26
- # Initialize with test data
27
- conn = sqlite3.connect(path)
28
- cursor = conn.cursor()
29
- cursor.execute("""
30
- CREATE TABLE users (
31
- id INTEGER PRIMARY KEY,
32
- name TEXT NOT NULL,
33
- email TEXT,
34
- age INTEGER
35
- )
36
- """)
37
- cursor.execute(
38
- "INSERT INTO users (id, name, email, age) VALUES (?, ?, ?, ?)",
39
- (1, "Alice", "alice@example.com", 30),
40
- )
41
- cursor.execute(
42
- "INSERT INTO users (id, name, email, age) VALUES (?, ?, ?, ?)",
43
- (2, "Bob", "bob@example.com", 25),
44
- )
45
- conn.commit()
46
- conn.close()
47
-
48
- yield path
49
-
50
- # Cleanup
51
- if os.path.exists(path):
52
- os.remove(path)
53
-
54
- @pytest.fixture
55
- def resource(self, temp_db):
56
- """Create a SQLiteResource in direct mode."""
57
- resource_model = ResourceModel(
58
- name="test_db",
59
- type=ResourceType.db,
60
- mode=ResourceMode.rw,
61
- )
62
- return SQLiteResource(resource_model, client=None, db_path=temp_db)
63
-
64
- def test_mode_property(self, resource):
65
- """Test that mode property returns 'direct'."""
66
- assert resource.mode == "direct"
67
-
68
- def test_query_select(self, resource):
69
- """Test SELECT query in direct mode."""
70
- response = resource.query("SELECT * FROM users ORDER BY id")
71
-
72
- assert response.success is True
73
- assert response.columns == ["id", "name", "email", "age"]
74
- assert len(response.rows) == 2
75
- # Rows can be either tuples or lists depending on the implementation
76
- assert list(response.rows[0]) == [1, "Alice", "alice@example.com", 30]
77
- assert list(response.rows[1]) == [2, "Bob", "bob@example.com", 25]
78
-
79
- def test_query_with_params(self, resource):
80
- """Test query with parameters."""
81
- response = resource.query("SELECT * FROM users WHERE id = ?", [1])
82
-
83
- assert response.success is True
84
- assert len(response.rows) == 1
85
- assert response.rows[0][1] == "Alice"
86
-
87
- def test_exec_insert(self, resource):
88
- """Test INSERT operation in direct mode."""
89
- response = resource.exec(
90
- "INSERT INTO users (id, name, email, age) VALUES (?, ?, ?, ?)",
91
- [3, "Charlie", "charlie@example.com", 35],
92
- )
93
-
94
- assert response.success is True
95
- assert response.rows_affected == 1
96
- assert response.last_insert_id == 3
97
-
98
- # Verify the insert
99
- check = resource.query("SELECT * FROM users WHERE id = 3")
100
- assert len(check.rows) == 1
101
- assert check.rows[0][1] == "Charlie"
102
-
103
- def test_exec_update(self, resource):
104
- """Test UPDATE operation in direct mode."""
105
- response = resource.exec("UPDATE users SET age = ? WHERE id = ?", [31, 1])
106
-
107
- assert response.success is True
108
- assert response.rows_affected == 1
109
-
110
- # Verify the update
111
- check = resource.query("SELECT age FROM users WHERE id = 1")
112
- assert check.rows[0][0] == 31
113
-
114
- def test_exec_delete(self, resource):
115
- """Test DELETE operation in direct mode."""
116
- response = resource.exec("DELETE FROM users WHERE id = ?", [2])
117
-
118
- assert response.success is True
119
- assert response.rows_affected == 1
120
-
121
- # Verify the delete
122
- check = resource.query("SELECT * FROM users")
123
- assert len(check.rows) == 1
124
-
125
- def test_describe(self, resource):
126
- """Test describe() in direct mode."""
127
- response = resource.describe()
128
-
129
- assert response.success is True
130
- assert response.resource_name == "test_db"
131
- assert len(response.tables) == 1
132
-
133
- table = response.tables[0]
134
- assert table.name == "users"
135
- assert table.sql is not None
136
- assert len(table.columns) == 4
137
-
138
- # Check column details
139
- columns = {col["name"]: col for col in table.columns}
140
- assert "id" in columns
141
- assert columns["id"]["primary_key"] is True
142
- assert "name" in columns
143
- assert columns["name"]["notnull"] is True
144
-
145
- def test_table_query_builder(self, resource):
146
- """Test table() query builder in direct mode."""
147
- users = resource.table("users").all()
148
-
149
- assert len(users) == 2
150
- assert users[0]["name"] == "Alice"
151
- assert users[1]["name"] == "Bob"
152
-
153
- def test_query_builder_eq(self, resource):
154
- """Test query builder eq() filter."""
155
- user = resource.table("users").eq("name", "Alice").first()
156
-
157
- assert user is not None
158
- assert user["name"] == "Alice"
159
- assert user["email"] == "alice@example.com"
160
-
161
- def test_query_builder_count(self, resource):
162
- """Test query builder count()."""
163
- count = resource.table("users").count()
164
- assert count == 2
165
-
166
- count_filtered = resource.table("users").eq("age", 30).count()
167
- assert count_filtered == 1
168
-
169
- def test_query_builder_where(self, resource):
170
- """Test query builder where() with multiple conditions."""
171
- users = resource.table("users").where(age=25).all()
172
-
173
- assert len(users) == 1
174
- assert users[0]["name"] == "Bob"
175
-
176
- def test_query_builder_limit(self, resource):
177
- """Test query builder limit()."""
178
- users = resource.table("users").limit(1).all()
179
-
180
- assert len(users) == 1
181
-
182
- def test_query_error_handling(self, resource):
183
- """Test error handling for invalid queries."""
184
- response = resource.query("SELECT * FROM nonexistent_table")
185
-
186
- assert response.success is False
187
- assert response.error is not None
188
- assert "nonexistent_table" in response.error.lower() or "no such table" in response.error.lower()
189
-
190
-
191
- class TestSQLiteResourceHTTPMode:
192
- """Test SQLiteResource in HTTP (remote) mode."""
193
-
194
- @pytest.fixture
195
- def mock_client(self, mocker):
196
- """Create a mock HTTP client."""
197
- return mocker.Mock()
198
-
199
- @pytest.fixture
200
- def resource(self, mock_client):
201
- """Create a SQLiteResource in HTTP mode."""
202
- resource_model = ResourceModel(
203
- name="remote_db",
204
- type=ResourceType.db,
205
- mode=ResourceMode.rw,
206
- )
207
- return SQLiteResource(resource_model, client=mock_client, db_path=None)
208
-
209
- def test_mode_property(self, resource):
210
- """Test that mode property returns 'http'."""
211
- assert resource.mode == "http"
212
-
213
- def test_query_http(self, resource, mock_client, mocker):
214
- """Test that query() calls HTTP client."""
215
- # Mock the HTTP response
216
- mock_response = mocker.Mock()
217
- mock_response.json.return_value = {
218
- "success": True,
219
- "columns": ["id", "name"],
220
- "rows": [[1, "Alice"]],
221
- "message": "Query successful",
222
- }
223
- mock_client.request.return_value = mock_response
224
-
225
- response = resource.query("SELECT * FROM users")
226
-
227
- # Verify HTTP client was called
228
- mock_client.request.assert_called_once()
229
- call_args = mock_client.request.call_args
230
- assert call_args[0][0] == "POST"
231
- assert "/query" in call_args[0][1]
232
-
233
- # Verify response
234
- assert response.success is True
235
- assert response.columns == ["id", "name"]
236
-
237
- def test_describe_http(self, resource, mock_client, mocker):
238
- """Test that describe() calls HTTP client."""
239
- # Mock the HTTP response
240
- mock_response = mocker.Mock()
241
- mock_response.json.return_value = {
242
- "success": True,
243
- "resource_name": "remote_db",
244
- "tables": [],
245
- "message": "Schema retrieved",
246
- }
247
- mock_client.request.return_value = mock_response
248
-
249
- response = resource.describe()
250
-
251
- # Verify HTTP client was called
252
- mock_client.request.assert_called_once()
253
- call_args = mock_client.request.call_args
254
- assert call_args[0][0] == "GET"
255
- assert "/describe" in call_args[0][1]
256
-
257
- # Verify response
258
- assert response.success is True
259
- assert response.resource_name == "remote_db"
260
-
261
-
262
- if __name__ == "__main__":
263
- pytest.main([__file__, "-v"])
@@ -1,117 +0,0 @@
1
- """Verification tests for SQLite shared memory behavior.
2
-
3
- These tests verify how SQLite's shared memory databases work to ensure
4
- our implementation assumptions are correct.
5
- """
6
-
7
- import sqlite3
8
- import pytest
9
-
10
-
11
- def test_plain_memory_no_sharing():
12
- """Verify that plain :memory: databases don't share data."""
13
- conn1 = sqlite3.connect(':memory:')
14
- conn1.execute("CREATE TABLE test (id INT)")
15
- conn1.execute("INSERT INTO test VALUES (1)")
16
-
17
- # Second connection to :memory: creates a SEPARATE database
18
- conn2 = sqlite3.connect(':memory:')
19
-
20
- with pytest.raises(sqlite3.OperationalError, match="no such table"):
21
- conn2.execute("SELECT * FROM test")
22
-
23
- conn1.close()
24
- conn2.close()
25
-
26
-
27
- def test_shared_memory_uri_sharing():
28
- """Verify that shared memory URIs DO share data."""
29
- conn1 = sqlite3.connect('file:testdb?mode=memory&cache=shared', uri=True)
30
- conn1.execute("CREATE TABLE test (id INT)")
31
- conn1.execute("INSERT INTO test VALUES (1)")
32
- conn1.commit() # Commit so other connections can see changes
33
-
34
- # Second connection to same URI shares the database
35
- conn2 = sqlite3.connect('file:testdb?mode=memory&cache=shared', uri=True)
36
- result = conn2.execute("SELECT * FROM test").fetchall()
37
-
38
- assert result == [(1,)]
39
-
40
- conn1.close()
41
- conn2.close()
42
-
43
-
44
- def test_different_namespaces_isolated():
45
- """Verify that different shared memory namespaces are isolated."""
46
- conn1 = sqlite3.connect('file:db1?mode=memory&cache=shared', uri=True)
47
- conn1.execute("CREATE TABLE test (id INT)")
48
- conn1.execute("INSERT INTO test VALUES (1)")
49
-
50
- conn2 = sqlite3.connect('file:db2?mode=memory&cache=shared', uri=True)
51
-
52
- # db2 should not have the test table from db1
53
- with pytest.raises(sqlite3.OperationalError, match="no such table"):
54
- conn2.execute("SELECT * FROM test")
55
-
56
- conn1.close()
57
- conn2.close()
58
-
59
-
60
- def test_data_lost_when_all_connections_close():
61
- """Verify that shared memory data is lost when all connections close."""
62
- conn1 = sqlite3.connect('file:tempdb?mode=memory&cache=shared', uri=True)
63
- conn1.execute("CREATE TABLE test (id INT)")
64
- conn1.execute("INSERT INTO test VALUES (1)")
65
- conn1.commit() # Commit so other connections can see changes
66
-
67
- conn2 = sqlite3.connect('file:tempdb?mode=memory&cache=shared', uri=True)
68
- result = conn2.execute("SELECT * FROM test").fetchall()
69
- assert result == [(1,)]
70
-
71
- # Close all connections
72
- conn1.close()
73
- conn2.close()
74
-
75
- # Open new connection - database is recreated empty
76
- conn3 = sqlite3.connect('file:tempdb?mode=memory&cache=shared', uri=True)
77
-
78
- with pytest.raises(sqlite3.OperationalError, match="no such table"):
79
- conn3.execute("SELECT * FROM test")
80
-
81
- conn3.close()
82
-
83
-
84
- def test_anchor_connection_keeps_data_alive():
85
- """Verify that keeping one connection open preserves the data."""
86
- # Create anchor connection
87
- anchor = sqlite3.connect('file:persistent?mode=memory&cache=shared', uri=True)
88
- # Drop table if it exists from a previous test run
89
- anchor.execute("DROP TABLE IF EXISTS test")
90
- anchor.execute("CREATE TABLE test (id INT)")
91
- anchor.execute("INSERT INTO test VALUES (1)")
92
- anchor.commit() # Commit so other connections can see changes
93
-
94
- # Open and close other connections
95
- conn1 = sqlite3.connect('file:persistent?mode=memory&cache=shared', uri=True)
96
- result = conn1.execute("SELECT * FROM test").fetchall()
97
- assert result == [(1,)]
98
- conn1.close()
99
-
100
- # Even after conn1 closes, data is still there because anchor is open
101
- conn2 = sqlite3.connect('file:persistent?mode=memory&cache=shared', uri=True)
102
- result = conn2.execute("SELECT * FROM test").fetchall()
103
- assert result == [(1,)]
104
- conn2.close()
105
-
106
- # Close anchor
107
- anchor.close()
108
-
109
- # Now data is gone
110
- conn3 = sqlite3.connect('file:persistent?mode=memory&cache=shared', uri=True)
111
- with pytest.raises(sqlite3.OperationalError, match="no such table"):
112
- conn3.execute("SELECT * FROM test")
113
- conn3.close()
114
-
115
-
116
- if __name__ == "__main__":
117
- pytest.main([__file__, "-v"])