fleet-python 0.2.68__py3-none-any.whl → 0.2.69b2__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.
- fleet/_async/client.py +163 -6
- fleet/_async/instance/client.py +19 -4
- fleet/_async/resources/sqlite.py +150 -1
- fleet/_async/tasks.py +5 -2
- fleet/client.py +163 -6
- fleet/instance/client.py +20 -5
- fleet/resources/sqlite.py +143 -1
- fleet/tasks.py +5 -2
- {fleet_python-0.2.68.dist-info → fleet_python-0.2.69b2.dist-info}/METADATA +1 -1
- {fleet_python-0.2.68.dist-info → fleet_python-0.2.69b2.dist-info}/RECORD +16 -13
- tests/test_instance_dispatch.py +607 -0
- tests/test_sqlite_resource_dual_mode.py +263 -0
- tests/test_sqlite_shared_memory_behavior.py +117 -0
- {fleet_python-0.2.68.dist-info → fleet_python-0.2.69b2.dist-info}/WHEEL +0 -0
- {fleet_python-0.2.68.dist-info → fleet_python-0.2.69b2.dist-info}/licenses/LICENSE +0 -0
- {fleet_python-0.2.68.dist-info → fleet_python-0.2.69b2.dist-info}/top_level.txt +0 -0
fleet/resources/sqlite.py
CHANGED
|
@@ -675,17 +675,97 @@ class SyncQueryBuilder:
|
|
|
675
675
|
|
|
676
676
|
|
|
677
677
|
class SQLiteResource(Resource):
|
|
678
|
-
def __init__(
|
|
678
|
+
def __init__(
|
|
679
|
+
self,
|
|
680
|
+
resource: ResourceModel,
|
|
681
|
+
client: Optional["SyncWrapper"] = None,
|
|
682
|
+
db_path: Optional[str] = None,
|
|
683
|
+
):
|
|
679
684
|
super().__init__(resource)
|
|
680
685
|
self.client = client
|
|
686
|
+
self.db_path = db_path
|
|
687
|
+
self._mode = "direct" if db_path else "http"
|
|
688
|
+
|
|
689
|
+
@property
|
|
690
|
+
def mode(self) -> str:
|
|
691
|
+
"""Return the mode of this resource: 'direct' (local file) or 'http' (remote API)."""
|
|
692
|
+
return self._mode
|
|
681
693
|
|
|
682
694
|
def describe(self) -> DescribeResponse:
|
|
683
695
|
"""Describe the SQLite database schema."""
|
|
696
|
+
if self._mode == "direct":
|
|
697
|
+
return self._describe_direct()
|
|
698
|
+
else:
|
|
699
|
+
return self._describe_http()
|
|
700
|
+
|
|
701
|
+
def _describe_http(self) -> DescribeResponse:
|
|
702
|
+
"""Describe database schema via HTTP API."""
|
|
684
703
|
response = self.client.request(
|
|
685
704
|
"GET", f"/resources/sqlite/{self.resource.name}/describe"
|
|
686
705
|
)
|
|
687
706
|
return DescribeResponse(**response.json())
|
|
688
707
|
|
|
708
|
+
def _describe_direct(self) -> DescribeResponse:
|
|
709
|
+
"""Describe database schema from local file or in-memory database."""
|
|
710
|
+
try:
|
|
711
|
+
# Check if we need URI mode (for shared memory databases)
|
|
712
|
+
use_uri = 'mode=memory' in self.db_path
|
|
713
|
+
conn = sqlite3.connect(self.db_path, uri=use_uri)
|
|
714
|
+
cursor = conn.cursor()
|
|
715
|
+
|
|
716
|
+
# Get all tables
|
|
717
|
+
cursor.execute(
|
|
718
|
+
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'"
|
|
719
|
+
)
|
|
720
|
+
table_names = [row[0] for row in cursor.fetchall()]
|
|
721
|
+
|
|
722
|
+
tables = []
|
|
723
|
+
for table_name in table_names:
|
|
724
|
+
# Get table info
|
|
725
|
+
cursor.execute(f"PRAGMA table_info({table_name})")
|
|
726
|
+
columns = cursor.fetchall()
|
|
727
|
+
|
|
728
|
+
# Get CREATE TABLE SQL
|
|
729
|
+
cursor.execute(
|
|
730
|
+
f"SELECT sql FROM sqlite_master WHERE type='table' AND name=?",
|
|
731
|
+
(table_name,)
|
|
732
|
+
)
|
|
733
|
+
sql_row = cursor.fetchone()
|
|
734
|
+
create_sql = sql_row[0] if sql_row else ""
|
|
735
|
+
|
|
736
|
+
table_schema = {
|
|
737
|
+
"name": table_name,
|
|
738
|
+
"sql": create_sql,
|
|
739
|
+
"columns": [
|
|
740
|
+
{
|
|
741
|
+
"name": col[1],
|
|
742
|
+
"type": col[2],
|
|
743
|
+
"notnull": bool(col[3]),
|
|
744
|
+
"default_value": col[4],
|
|
745
|
+
"primary_key": col[5] > 0,
|
|
746
|
+
}
|
|
747
|
+
for col in columns
|
|
748
|
+
],
|
|
749
|
+
}
|
|
750
|
+
tables.append(table_schema)
|
|
751
|
+
|
|
752
|
+
conn.close()
|
|
753
|
+
|
|
754
|
+
return DescribeResponse(
|
|
755
|
+
success=True,
|
|
756
|
+
resource_name=self.resource.name,
|
|
757
|
+
tables=tables,
|
|
758
|
+
message="Schema retrieved from local file",
|
|
759
|
+
)
|
|
760
|
+
except Exception as e:
|
|
761
|
+
return DescribeResponse(
|
|
762
|
+
success=False,
|
|
763
|
+
resource_name=self.resource.name,
|
|
764
|
+
tables=None,
|
|
765
|
+
error=str(e),
|
|
766
|
+
message=f"Failed to describe database: {str(e)}",
|
|
767
|
+
)
|
|
768
|
+
|
|
689
769
|
def query(self, query: str, args: Optional[List[Any]] = None) -> QueryResponse:
|
|
690
770
|
return self._query(query, args, read_only=True)
|
|
691
771
|
|
|
@@ -695,6 +775,15 @@ class SQLiteResource(Resource):
|
|
|
695
775
|
def _query(
|
|
696
776
|
self, query: str, args: Optional[List[Any]] = None, read_only: bool = True
|
|
697
777
|
) -> QueryResponse:
|
|
778
|
+
if self._mode == "direct":
|
|
779
|
+
return self._query_direct(query, args, read_only)
|
|
780
|
+
else:
|
|
781
|
+
return self._query_http(query, args, read_only)
|
|
782
|
+
|
|
783
|
+
def _query_http(
|
|
784
|
+
self, query: str, args: Optional[List[Any]] = None, read_only: bool = True
|
|
785
|
+
) -> QueryResponse:
|
|
786
|
+
"""Execute query via HTTP API."""
|
|
698
787
|
request = QueryRequest(query=query, args=args, read_only=read_only)
|
|
699
788
|
response = self.client.request(
|
|
700
789
|
"POST",
|
|
@@ -703,6 +792,59 @@ class SQLiteResource(Resource):
|
|
|
703
792
|
)
|
|
704
793
|
return QueryResponse(**response.json())
|
|
705
794
|
|
|
795
|
+
def _query_direct(
|
|
796
|
+
self, query: str, args: Optional[List[Any]] = None, read_only: bool = True
|
|
797
|
+
) -> QueryResponse:
|
|
798
|
+
"""Execute query directly on local SQLite file or in-memory database."""
|
|
799
|
+
try:
|
|
800
|
+
# Check if we need URI mode (for shared memory databases)
|
|
801
|
+
use_uri = 'mode=memory' in self.db_path
|
|
802
|
+
conn = sqlite3.connect(self.db_path, uri=use_uri)
|
|
803
|
+
cursor = conn.cursor()
|
|
804
|
+
|
|
805
|
+
# Execute the query
|
|
806
|
+
if args:
|
|
807
|
+
cursor.execute(query, args)
|
|
808
|
+
else:
|
|
809
|
+
cursor.execute(query)
|
|
810
|
+
|
|
811
|
+
# For write operations, commit the transaction
|
|
812
|
+
if not read_only:
|
|
813
|
+
conn.commit()
|
|
814
|
+
|
|
815
|
+
# Get column names if available
|
|
816
|
+
columns = [desc[0] for desc in cursor.description] if cursor.description else []
|
|
817
|
+
|
|
818
|
+
# Fetch results for SELECT queries
|
|
819
|
+
rows = []
|
|
820
|
+
rows_affected = 0
|
|
821
|
+
last_insert_id = None
|
|
822
|
+
|
|
823
|
+
if cursor.description: # SELECT query
|
|
824
|
+
rows = cursor.fetchall()
|
|
825
|
+
else: # INSERT/UPDATE/DELETE
|
|
826
|
+
rows_affected = cursor.rowcount
|
|
827
|
+
last_insert_id = cursor.lastrowid if cursor.lastrowid else None
|
|
828
|
+
|
|
829
|
+
conn.close()
|
|
830
|
+
|
|
831
|
+
return QueryResponse(
|
|
832
|
+
success=True,
|
|
833
|
+
columns=columns if columns else None,
|
|
834
|
+
rows=rows if rows else None,
|
|
835
|
+
rows_affected=rows_affected if rows_affected > 0 else None,
|
|
836
|
+
last_insert_id=last_insert_id,
|
|
837
|
+
message="Query executed successfully",
|
|
838
|
+
)
|
|
839
|
+
except Exception as e:
|
|
840
|
+
return QueryResponse(
|
|
841
|
+
success=False,
|
|
842
|
+
columns=None,
|
|
843
|
+
rows=None,
|
|
844
|
+
error=str(e),
|
|
845
|
+
message=f"Query failed: {str(e)}",
|
|
846
|
+
)
|
|
847
|
+
|
|
706
848
|
def table(self, table_name: str) -> SyncQueryBuilder:
|
|
707
849
|
"""Create a query builder for the specified table."""
|
|
708
850
|
return SyncQueryBuilder(self, table_name)
|
fleet/tasks.py
CHANGED
|
@@ -286,8 +286,11 @@ def verifier_from_string(
|
|
|
286
286
|
# Remove lines like: @verifier(key="...")
|
|
287
287
|
cleaned_code = re.sub(r"@verifier\([^)]*\)\s*\n", "", verifier_func)
|
|
288
288
|
# Also remove the verifier import if present
|
|
289
|
-
|
|
290
|
-
cleaned_code = re.sub(r"import.*verifier
|
|
289
|
+
# Use MULTILINE flag to match beginning of lines with ^
|
|
290
|
+
cleaned_code = re.sub(r"^from fleet\.verifiers.*import.*verifier.*$\n?", "", cleaned_code, flags=re.MULTILINE)
|
|
291
|
+
cleaned_code = re.sub(r"^from fleet import verifier.*$\n?", "", cleaned_code, flags=re.MULTILINE)
|
|
292
|
+
cleaned_code = re.sub(r"^import fleet\.verifiers.*$\n?", "", cleaned_code, flags=re.MULTILINE)
|
|
293
|
+
cleaned_code = re.sub(r"^import fleet$\n?", "", cleaned_code, flags=re.MULTILINE)
|
|
291
294
|
|
|
292
295
|
# Create a globals namespace with all required imports
|
|
293
296
|
exec_globals = globals().copy()
|
|
@@ -23,30 +23,30 @@ examples/quickstart.py,sha256=1VT39IRRhemsJgxi0O0gprdpcw7HB4pYO97GAYagIcg,3788
|
|
|
23
23
|
examples/test_cdp_logging.py,sha256=AkCwQCgOTQEI8w3v0knWK_4eXMph7L9x07wj9yIYM10,2836
|
|
24
24
|
fleet/__init__.py,sha256=yC4HIcbtPAPOgI0lLri3l8nbXkNee9JOihKAc7SXYkY,4201
|
|
25
25
|
fleet/base.py,sha256=bc-340sTpq_DJs7yQ9d2pDWnmJFmA1SwDB9Lagvqtb4,9182
|
|
26
|
-
fleet/client.py,sha256=
|
|
26
|
+
fleet/client.py,sha256=HPBKsGeWuLoBXFmEdZuLz04aYDKmg0_eYSgQ2-O4tNg,39521
|
|
27
27
|
fleet/config.py,sha256=uY02ZKxVoXqVDta-0IMWaYJeE1CTXF_fA9NI6QUutmU,319
|
|
28
28
|
fleet/exceptions.py,sha256=fUmPwWhnT8SR97lYsRq0kLHQHKtSh2eJS0VQ2caSzEI,5055
|
|
29
29
|
fleet/global_client.py,sha256=frrDAFNM2ywN0JHLtlm9qbE1dQpnQJsavJpb7xSR_bU,1072
|
|
30
30
|
fleet/models.py,sha256=GUL61DOD4XDT588T1a-EV7R1kh1w4q_JRLnX1rEI5ek,13911
|
|
31
|
-
fleet/tasks.py,sha256=
|
|
31
|
+
fleet/tasks.py,sha256=TWKenYlIJ8eo8TjMkTwfNL7ZRFgopnRXTCclPBMufgE,18281
|
|
32
32
|
fleet/types.py,sha256=L4Y82xICf1tzyCLqhLYUgEoaIIS5h9T05TyFNHSWs3s,652
|
|
33
33
|
fleet/_async/__init__.py,sha256=5oOTmh16UsPWL2gDKKWkj2j5WGNeUhMzbQFWjX21jsc,8310
|
|
34
34
|
fleet/_async/base.py,sha256=oisVTQsx0M_yTmyQJc3oij63uKZ97MHz-xYFsWXxQE8,9202
|
|
35
|
-
fleet/_async/client.py,sha256=
|
|
35
|
+
fleet/_async/client.py,sha256=xjDlAFWYez1SHKcUnYw-iLQsQ3gEeKiWw3qDX9gnNHs,40029
|
|
36
36
|
fleet/_async/exceptions.py,sha256=fUmPwWhnT8SR97lYsRq0kLHQHKtSh2eJS0VQ2caSzEI,5055
|
|
37
37
|
fleet/_async/global_client.py,sha256=4WskpLHbsDEgWW7hXMD09W-brkp4euy8w2ZJ88594rQ,1103
|
|
38
38
|
fleet/_async/models.py,sha256=-3xv2QyoHsvYcWmdKLf9Z93md8XB17DBeJCxdRCB3bo,13571
|
|
39
|
-
fleet/_async/tasks.py,sha256=
|
|
39
|
+
fleet/_async/tasks.py,sha256=C3t15WXfAn_DY5UXtf4S27OoAs4U61GO1LirWFHr7AM,18327
|
|
40
40
|
fleet/_async/env/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
41
|
fleet/_async/env/client.py,sha256=Qv0QiW--ZMAMnz_IPYbYtokGP08x4PvSmkwde8rPCNk,2093
|
|
42
42
|
fleet/_async/instance/__init__.py,sha256=PtmJq8J8bh0SOQ2V55QURz5GJfobozwtQoqhaOk3_tI,515
|
|
43
43
|
fleet/_async/instance/base.py,sha256=3qUBuUR8OVS36LzdP6KyZzngtwPKYO09HoY6Ekxp-KA,1625
|
|
44
|
-
fleet/_async/instance/client.py,sha256=
|
|
44
|
+
fleet/_async/instance/client.py,sha256=Nrnoez4J3UnbSJoOfDw8vwb00p_A5RNOy9ROwUE4B_4,6838
|
|
45
45
|
fleet/_async/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
46
|
fleet/_async/resources/base.py,sha256=UfrenxUqcpL8SgYGOo8o8HgRvv2-ZO5G2Cdo91ofEdg,664
|
|
47
47
|
fleet/_async/resources/browser.py,sha256=oldoSiymJ1lJkADhpUG81ViOBDNyppX1jSoEwe9-W94,1369
|
|
48
48
|
fleet/_async/resources/mcp.py,sha256=TLEsLiFhfVfZFs0Fu_uDPm-h4FPdvqgQblYqs-PTHhc,1720
|
|
49
|
-
fleet/_async/resources/sqlite.py,sha256=
|
|
49
|
+
fleet/_async/resources/sqlite.py,sha256=zRTbqW0qLt8EO9UTIxtcbrmwPV3cGK3rCaX1oSFsd_E,33036
|
|
50
50
|
fleet/_async/verifiers/__init__.py,sha256=1WTlCNq4tIFbbXaQu5Bf2WppZq0A8suhtZbxMTSOwxI,465
|
|
51
51
|
fleet/_async/verifiers/bundler.py,sha256=Sq0KkqEhM5Ng2x8R6Z4puXvQ8FMlEO7D3-ldBLktPi4,26205
|
|
52
52
|
fleet/_async/verifiers/verifier.py,sha256=IiHX028s6ux0kb2FR0Z5zJangl_IDh6cemXsUN2ktUU,14152
|
|
@@ -54,13 +54,13 @@ fleet/env/__init__.py,sha256=sSjD6vk8LzC_pxoXuRc8-ACqeX4PLm1FBWnWxpOhUS8,812
|
|
|
54
54
|
fleet/env/client.py,sha256=l2vI_BBrSXmyk2un3F1-QDcL-iv2OdBxTdYOdOioF0Q,1881
|
|
55
55
|
fleet/instance/__init__.py,sha256=CyWUkbGAK-DBPw4DC4AnCW-MqqheGhZMA5QSRVu-ws4,479
|
|
56
56
|
fleet/instance/base.py,sha256=OYqzBwZFfTX9wlBGSG5gljqj98NbiJeKIfFJ3uj5I4s,1587
|
|
57
|
-
fleet/instance/client.py,sha256=
|
|
57
|
+
fleet/instance/client.py,sha256=MUUkMV5i0-DPK8awBpRYfc3wy8kVq7IGQ_Re7td1e60,6639
|
|
58
58
|
fleet/instance/models.py,sha256=ZTiue0YOuhuwX8jYfJAoCzGfqjLqqXRLqK1LVFhq6rQ,4183
|
|
59
59
|
fleet/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
60
60
|
fleet/resources/base.py,sha256=AXZzT0_yWHkT497q3yekfr0xsD4cPGMCC6y7C43TIkk,663
|
|
61
61
|
fleet/resources/browser.py,sha256=hRNM0YMsVQUAraZGNi_B-KXxLpuddy4ntoEDFSw7czU,1295
|
|
62
62
|
fleet/resources/mcp.py,sha256=c6O4vVJnXANuHMGMe4IPxgp4zBEbFaGm6_d9e6j8Myc,1695
|
|
63
|
-
fleet/resources/sqlite.py,sha256=
|
|
63
|
+
fleet/resources/sqlite.py,sha256=BZE31mMOuRIT0vB4ppy6bO-QczmlYytHQkgo9nCZIew,31837
|
|
64
64
|
fleet/verifiers/__init__.py,sha256=GntS8qc3xv8mm-cku1t3xjvOll5jcc5FuiVqQgR4Y6Q,458
|
|
65
65
|
fleet/verifiers/bundler.py,sha256=Sq0KkqEhM5Ng2x8R6Z4puXvQ8FMlEO7D3-ldBLktPi4,26205
|
|
66
66
|
fleet/verifiers/code.py,sha256=A1i_UabZspbyj1awzKVQ_HRxgMO3fU7NbkxYyTrp7So,48
|
|
@@ -69,12 +69,15 @@ fleet/verifiers/decorator.py,sha256=nAP3O8szXu7md_kpwpz91hGSUNEVLYjwZQZTkQlV1DM,
|
|
|
69
69
|
fleet/verifiers/parse.py,sha256=qz9AfJrTbjlg-LU-lE8Ciqi7Yt2a8-cs17FdpjTLhMk,8550
|
|
70
70
|
fleet/verifiers/sql_differ.py,sha256=TqTLWyK3uOyLbitT6HYzYEzuSFC39wcyhgk3rcm__k8,6525
|
|
71
71
|
fleet/verifiers/verifier.py,sha256=_lcxXVm8e0xRrK2gNJy9up7pW1zOkPRY5n5lQ85S8jg,14197
|
|
72
|
-
fleet_python-0.2.
|
|
72
|
+
fleet_python-0.2.69b2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
73
73
|
scripts/fix_sync_imports.py,sha256=X9fWLTpiPGkSHsjyQUDepOJkxOqw1DPj7nd8wFlFqLQ,8368
|
|
74
74
|
scripts/unasync.py,sha256=vWVQxRWX8SRZO5cmzEhpvnG_REhCWXpidIGIpWmEcvI,696
|
|
75
75
|
tests/__init__.py,sha256=Re1SdyxH8NfyL1kjhi7SQkGP1mYeWB-D6UALqdIMd8I,35
|
|
76
|
+
tests/test_instance_dispatch.py,sha256=CvU4C3LBIqsYZdEsEFfontGjyxAZfVYyXnGwxyIvXOc,23065
|
|
77
|
+
tests/test_sqlite_resource_dual_mode.py,sha256=Mh8jBd-xsIGDYFsOACKKK_5DXMUYlFFS7W-jaY6AjG4,8734
|
|
78
|
+
tests/test_sqlite_shared_memory_behavior.py,sha256=fKx_1BmLS3b8x-9pMgjMycpnaHWY8P-2ZuXEspx6Sbw,4082
|
|
76
79
|
tests/test_verifier_from_string.py,sha256=Lxi3TpFHFb-hG4-UhLKZJkqo84ax9YJY8G6beO-1erM,13581
|
|
77
|
-
fleet_python-0.2.
|
|
78
|
-
fleet_python-0.2.
|
|
79
|
-
fleet_python-0.2.
|
|
80
|
-
fleet_python-0.2.
|
|
80
|
+
fleet_python-0.2.69b2.dist-info/METADATA,sha256=uUc9gJCTRFAIXetYKsETKq-P62QdGF35_wjxDjSYMcw,3306
|
|
81
|
+
fleet_python-0.2.69b2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
82
|
+
fleet_python-0.2.69b2.dist-info/top_level.txt,sha256=qb1zIbtEktyhRFZdqVytwg54l64qtoZL0wjHB4bUg3c,29
|
|
83
|
+
fleet_python-0.2.69b2.dist-info/RECORD,,
|