definite-sdk 0.1.9__py3-none-any.whl → 0.1.12__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.
definite_sdk/client.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import os
2
2
  from typing import Optional
3
3
 
4
+ import requests
4
5
  from definite_sdk.integration import DefiniteIntegrationStore
5
6
  from definite_sdk.message import DefiniteMessageClient
6
7
  from definite_sdk.secret import DefiniteSecretStore
@@ -66,6 +67,55 @@ class DefiniteClient:
66
67
 
67
68
  return DefiniteSqlClient(self.api_key, self.api_url)
68
69
 
70
+ def attach_ducklake(self, alias: str = "lake") -> str:
71
+ """Generates SQL statements to attach DuckLake to a DuckDB connection.
72
+
73
+ This method fetches the team's DuckLake integration credentials and generates
74
+ the necessary SQL statements to create a GCS secret and attach DuckLake.
75
+
76
+ Args:
77
+ alias: The alias name for the attached DuckLake database (default: "lake")
78
+
79
+ Returns:
80
+ str: SQL statements to execute for attaching DuckLake
81
+
82
+ Example:
83
+ >>> client = DefiniteClient(os.environ["DEFINITE_API_KEY"])
84
+ >>> sql = client.attach_ducklake()
85
+ >>> conn.execute(sql)
86
+ """
87
+ # Fetch DuckLake integration details
88
+ response = requests.get(
89
+ f"{self.api_url}/v1/api/integration/DuckLake",
90
+ headers={"Authorization": f"Bearer {self.api_key}"},
91
+ )
92
+ response.raise_for_status()
93
+ dl_integration = response.json()
94
+
95
+ # Generate SQL statements
96
+ create_secret_sql = f"""CREATE SECRET (
97
+ TYPE gcs,
98
+ KEY_ID '{dl_integration['gcs_access_key_id']}',
99
+ SECRET '{dl_integration['gcs_secret_access_key']}'
100
+ );"""
101
+
102
+ # Build PostgreSQL connection string
103
+ pg_conn_str = (
104
+ f"postgresql://{dl_integration['pg_user']}:"
105
+ f"{dl_integration['pg_password']}@"
106
+ f"{dl_integration['pg_host']}:"
107
+ f"{dl_integration['pg_port']}/"
108
+ f"{dl_integration['pg_database']}"
109
+ )
110
+
111
+ attach_sql = (
112
+ f"ATTACH 'ducklake:postgres:{pg_conn_str}' AS {alias} "
113
+ f"(DATA_PATH 'gs://{dl_integration['gcs_bucket_path']}', "
114
+ f"METADATA_SCHEMA '{dl_integration['pg_schema']}');"
115
+ )
116
+
117
+ return f"{create_secret_sql}\n\n{attach_sql}"
118
+
69
119
  # Alias methods for consistency
70
120
  def kv_store(self, name: str) -> DefiniteKVStore:
71
121
  """Alias for get_kv_store."""
definite_sdk/sql.py CHANGED
@@ -1,4 +1,4 @@
1
- from typing import Any, Dict, List, Optional, Union
1
+ from typing import Any, Dict, Optional
2
2
 
3
3
  import requests
4
4
 
@@ -31,7 +31,9 @@ class DefiniteSqlClient:
31
31
  ... "timeDimensions": [{"dimension": "sales.date", "granularity": "month"}],
32
32
  ... "limit": 1000
33
33
  ... }
34
- >>> result = sql_client.execute_cube_query(cube_query, integration_id="my_cube_integration")
34
+ >>> result = sql_client.execute_cube_query(
35
+ ... cube_query, integration_id="my_cube_integration"
36
+ ... )
35
37
  >>> print(result)
36
38
  """
37
39
 
@@ -46,11 +48,7 @@ class DefiniteSqlClient:
46
48
  self._api_key = api_key
47
49
  self._sql_url = api_url + SQL_ENDPOINT
48
50
 
49
- def execute(
50
- self,
51
- sql: str,
52
- integration_id: Optional[str] = None
53
- ) -> Dict[str, Any]:
51
+ def execute(self, sql: str, integration_id: Optional[str] = None) -> Dict[str, Any]:
54
52
  """
55
53
  Executes a SQL query against a database integration.
56
54
 
@@ -69,7 +67,7 @@ class DefiniteSqlClient:
69
67
  >>> result = sql_client.execute("SELECT COUNT(*) FROM users")
70
68
  >>> print(result)
71
69
  """
72
- payload = {"sql": sql}
70
+ payload: Dict[str, Any] = {"sql": sql}
73
71
  if integration_id:
74
72
  payload["integration_id"] = integration_id
75
73
 
@@ -82,9 +80,12 @@ class DefiniteSqlClient:
82
80
  return response.json()
83
81
 
84
82
  def execute_cube_query(
85
- self,
86
- cube_query: Dict[str, Any],
87
- integration_id: Optional[str] = None
83
+ self,
84
+ cube_query: Dict[str, Any],
85
+ integration_id: Optional[str] = None,
86
+ persist: bool = True,
87
+ invalidate: bool = False,
88
+ raw: bool = False,
88
89
  ) -> Dict[str, Any]:
89
90
  """
90
91
  Executes a Cube query against a Cube integration.
@@ -93,6 +94,9 @@ class DefiniteSqlClient:
93
94
  cube_query (Dict[str, Any]): The Cube query in JSON format.
94
95
  integration_id (Optional[str]): The Cube integration ID to query against.
95
96
  If not provided, the default integration will be used.
97
+ persist (bool): Whether to persist the query result to the cache.
98
+ invalidate (bool): Whether to invalidate the cached result.
99
+ raw (bool): Whether to return raw/unformatted cube results.
96
100
 
97
101
  Returns:
98
102
  Dict[str, Any]: The query result as returned by the API.
@@ -106,21 +110,38 @@ class DefiniteSqlClient:
106
110
  ... "measures": ["sales.total_amount"],
107
111
  ... "timeDimensions": [{
108
112
  ... "dimension": "sales.date",
109
- ... "granularity": "month"
113
+ ... "granularity": "month",
110
114
  ... }],
111
115
  ... "limit": 1000
112
116
  ... }
113
- >>> result = sql_client.execute_cube_query(cube_query, "my_cube_integration")
117
+ >>> result = sql_client.execute_cube_query(
118
+ ... cube_query, "my_cube_integration"
119
+ ... )
114
120
  >>> print(result)
121
+
122
+ >>> # To get raw/unformatted results:
123
+ >>> raw_result = sql_client.execute_cube_query(
124
+ ... cube_query, "my_cube_integration", raw=True
125
+ ... )
126
+ >>> print(raw_result)
115
127
  """
116
- payload = {"cube_query": cube_query}
128
+ payload: Dict[str, Any] = {"cube_query": cube_query}
117
129
  if integration_id:
118
130
  payload["integration_id"] = integration_id
131
+ if persist:
132
+ payload["persist"] = persist
133
+ if invalidate:
134
+ payload["invalidate"] = invalidate
135
+
136
+ # Build URL with query parameters
137
+ url = self._sql_url
138
+ if raw:
139
+ url += "?raw=true"
119
140
 
120
141
  response = requests.post(
121
- self._sql_url,
142
+ url,
122
143
  json=payload,
123
144
  headers={"Authorization": "Bearer " + self._api_key},
124
145
  )
125
146
  response.raise_for_status()
126
- return response.json()
147
+ return response.json()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: definite-sdk
3
- Version: 0.1.9
3
+ Version: 0.1.12
4
4
  Summary: Definite SDK for Python
5
5
  License: MIT
6
6
  Author: Definite
@@ -59,6 +59,7 @@ client = DefiniteClient("YOUR_API_KEY")
59
59
  - **Integration Store**: Read-only access to integration configurations
60
60
  - **Messaging**: Send messages through various channels (Slack, and more coming soon)
61
61
  - **dlt Integration**: Run dlt pipelines with automatic state persistence to Definite
62
+ - **DuckLake Integration**: Easy attachment of your team's DuckLake to DuckDB connections
62
63
  - **DuckDB Support**: Automatic discovery and connection to team's DuckDB integrations
63
64
 
64
65
  ## Basic Usage
@@ -231,6 +232,39 @@ pipeline.run(orders())
231
232
  last_cursor = pipeline.get_state("orders")
232
233
  ```
233
234
 
235
+ ### DuckLake Integration
236
+
237
+ Attach your team's DuckLake to a DuckDB connection for seamless data access:
238
+
239
+ ```python
240
+ import duckdb
241
+ from definite_sdk import DefiniteClient
242
+
243
+ # Initialize the client
244
+ client = DefiniteClient("YOUR_API_KEY")
245
+
246
+ # Connect to DuckDB and attach DuckLake
247
+ conn = duckdb.connect()
248
+ conn.execute(client.attach_ducklake())
249
+
250
+ # Now you can use DuckLake tables
251
+ conn.execute("CREATE SCHEMA IF NOT EXISTS lake.my_schema;")
252
+ conn.execute("CREATE OR REPLACE TABLE lake.my_schema.users AS SELECT * FROM df")
253
+
254
+ # Query your DuckLake data
255
+ result = conn.sql("SELECT * FROM lake.my_schema.users").df()
256
+ ```
257
+
258
+ You can also specify a custom alias for the attached DuckLake:
259
+
260
+ ```python
261
+ # Attach with custom alias
262
+ conn.execute(client.attach_ducklake(alias="warehouse"))
263
+
264
+ # Use the custom alias
265
+ conn.execute("SELECT * FROM warehouse.my_schema.users")
266
+ ```
267
+
234
268
  ### DuckDB Integration Discovery
235
269
 
236
270
  ```python
@@ -1,13 +1,13 @@
1
1
  definite_sdk/__init__.py,sha256=Y3GwfDOkpWt6EILoZ7PRT7nXuoVnk0zHrNOPHlkEHS4,604
2
- definite_sdk/client.py,sha256=2wRrFFwMMeGfP5riaEGhCLk1OiyBsJj_uMqFb3hIooY,3199
2
+ definite_sdk/client.py,sha256=mpXFpJVmK3JVYsNrn7f4bzqlxMbIsS3meRu3XMiXWZ4,5075
3
3
  definite_sdk/dlt.py,sha256=JC-S1jd6zqnpGSnvk9kYb8GQ1IPZRd1zVKTVYAbeA4w,7188
4
4
  definite_sdk/integration.py,sha256=v15QIpWm3eAZr-cmavfA39LXTjpskEEQ2SM_TBV4E1U,3395
5
5
  definite_sdk/message.py,sha256=I3qx2v9gIcC9NZyr5zEp_Seft8clRoER4WeUbAaDiFc,6549
6
6
  definite_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  definite_sdk/secret.py,sha256=3wvEnTZ946hOxJBdB29dxvppwJ0x-TJV_LxRcXGqtis,2503
8
- definite_sdk/sql.py,sha256=K5cPXM7B60Fzd8CyI-B4rXwK7hLpLT1Z8XZSZJjSogQ,3878
8
+ definite_sdk/sql.py,sha256=o2ume-S7__wp8hMBy2aC6dmGYV4s-IXMlMAyEuyAP84,4705
9
9
  definite_sdk/store.py,sha256=7VYvROIrlWyM_ZX3LpqWWAfVLNDm0XMccMLv6qi9id8,5575
10
- definite_sdk-0.1.9.dist-info/LICENSE,sha256=jMd7PtwNWiMoGIDgFutC1v4taO69W9SRZLKe9o470Vk,1064
11
- definite_sdk-0.1.9.dist-info/METADATA,sha256=jZfdfG0EFt7kfN6HpbSCnAzhZHBrEy7SV7WKH-K0LVU,8196
12
- definite_sdk-0.1.9.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
13
- definite_sdk-0.1.9.dist-info/RECORD,,
10
+ definite_sdk-0.1.12.dist-info/LICENSE,sha256=jMd7PtwNWiMoGIDgFutC1v4taO69W9SRZLKe9o470Vk,1064
11
+ definite_sdk-0.1.12.dist-info/METADATA,sha256=mR32ZrkWtX_q7BBMF6dtE2f2lHicy2SBo1lkMxOTFto,9136
12
+ definite_sdk-0.1.12.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
13
+ definite_sdk-0.1.12.dist-info/RECORD,,