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/resources/sqlite.py CHANGED
@@ -675,17 +675,97 @@ class SyncQueryBuilder:
675
675
 
676
676
 
677
677
  class SQLiteResource(Resource):
678
- def __init__(self, resource: ResourceModel, client: "SyncWrapper"):
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
- cleaned_code = re.sub(r"from fleet import.*verifier.*\n", "", cleaned_code)
290
- cleaned_code = re.sub(r"import.*verifier.*\n", "", cleaned_code)
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()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fleet-python
3
- Version: 0.2.68
3
+ Version: 0.2.69b2
4
4
  Summary: Python SDK for Fleet environments
5
5
  Author-email: Fleet AI <nic@fleet.so>
6
6
  License: Apache-2.0
@@ -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=niWdLmALTmLXHMnIZ4PEwyU6T28dxvtDXeLf-0DS_DE,33868
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=iwwvN2o1IWT-9zxmAMBHfT12rfX2Hm0DkfUlrPTs298,17956
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=ien5Xs1s4EetFAFExq7Vp_25lN2aVqEQyyDhYy3SJ00,34353
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=8d65DBMhmHNaLer1FhttUWK4WLS1SU5Hx9_nALMwM4Y,18002
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=kcrmLZciQxvPSfTtbEq5LIbhscwDHg6WIiNcPyM4L9w,6085
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=up_umepfyX9PDFsnmEMJLjsj7bLa6a3wizZOgMGkK1Q,27409
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=XM_Qmd7pUzC3-dCMTh6orTEsGeWJXbKueBlvcWcSUuI,5897
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=bR6d1zYQ4cMAlmZIJ7jqmY9-N-GokXaDhUyGKTWHsfY,26811
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.68.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
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.68.dist-info/METADATA,sha256=3OtKPA7XpF59sT-kEEUPKEdBFJp8GLVStE5kZJLJP84,3304
78
- fleet_python-0.2.68.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
79
- fleet_python-0.2.68.dist-info/top_level.txt,sha256=qb1zIbtEktyhRFZdqVytwg54l64qtoZL0wjHB4bUg3c,29
80
- fleet_python-0.2.68.dist-info/RECORD,,
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,,