definite-sdk 0.1.15__py3-none-any.whl → 0.1.16__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 +22 -26
- definite_sdk/integration.py +59 -46
- {definite_sdk-0.1.15.dist-info → definite_sdk-0.1.16.dist-info}/METADATA +1 -1
- {definite_sdk-0.1.15.dist-info → definite_sdk-0.1.16.dist-info}/RECORD +6 -6
- {definite_sdk-0.1.15.dist-info → definite_sdk-0.1.16.dist-info}/WHEEL +1 -1
- {definite_sdk-0.1.15.dist-info → definite_sdk-0.1.16.dist-info}/licenses/LICENSE +0 -0
definite_sdk/client.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from typing import Optional
|
|
3
3
|
|
|
4
|
-
import requests
|
|
5
4
|
from definite_sdk.integration import DefiniteIntegrationStore
|
|
6
5
|
from definite_sdk.message import DefiniteMessageClient
|
|
7
6
|
from definite_sdk.secret import DefiniteSecretStore
|
|
@@ -73,6 +72,7 @@ class DefiniteClient:
|
|
|
73
72
|
This method fetches the team's DuckLake integration credentials and generates
|
|
74
73
|
the necessary SQL statements to create a GCS secret and attach DuckLake.
|
|
75
74
|
|
|
75
|
+
|
|
76
76
|
Args:
|
|
77
77
|
alias: The alias name for the attached DuckLake database (default: "lake")
|
|
78
78
|
|
|
@@ -85,42 +85,38 @@ class DefiniteClient:
|
|
|
85
85
|
>>> conn.execute(sql)
|
|
86
86
|
"""
|
|
87
87
|
# Fetch DuckLake integration details
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
integrations_client = self.get_integration_store()
|
|
89
|
+
integrations = integrations_client.list_integrations(
|
|
90
|
+
integration_type="ducklake"
|
|
91
|
+
)
|
|
92
|
+
if len(integrations) == 0:
|
|
93
|
+
raise Exception(
|
|
94
|
+
"DuckLake integration not found. Please make sure one is"
|
|
95
|
+
"created for your team at https://ui.definite.app/settings/integrations"
|
|
92
96
|
)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
except requests.exceptions.HTTPError as e:
|
|
96
|
-
if response.status_code == 404:
|
|
97
|
-
raise ValueError(
|
|
98
|
-
"DuckLake integration not found. Please ensure you have a DuckLake integration "
|
|
99
|
-
"configured in your Definite account at https://ui.definite.app"
|
|
100
|
-
) from e
|
|
101
|
-
else:
|
|
102
|
-
raise
|
|
97
|
+
|
|
98
|
+
integration = integrations.pop()
|
|
103
99
|
|
|
104
100
|
# Generate SQL statements
|
|
105
101
|
create_secret_sql = f"""CREATE SECRET (
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
);"""
|
|
102
|
+
TYPE gcs,
|
|
103
|
+
KEY_ID '{integration["gcs_access_key_id"]}',
|
|
104
|
+
SECRET '{integration["gcs_secret_access_key"]}'
|
|
105
|
+
);"""
|
|
110
106
|
|
|
111
107
|
# Build PostgreSQL connection string
|
|
112
108
|
pg_conn_str = (
|
|
113
|
-
f"postgresql://{
|
|
114
|
-
f"{
|
|
115
|
-
f"{
|
|
116
|
-
f"{
|
|
117
|
-
f"{
|
|
109
|
+
f"postgresql://{integration['pg_user']}:"
|
|
110
|
+
f"{integration['pg_password']}@"
|
|
111
|
+
f"{integration['pg_host']}:"
|
|
112
|
+
f"{integration['pg_port']}/"
|
|
113
|
+
f"{integration['pg_database']}"
|
|
118
114
|
)
|
|
119
115
|
|
|
120
116
|
attach_sql = (
|
|
121
117
|
f"ATTACH 'ducklake:postgres:{pg_conn_str}' AS {alias} "
|
|
122
|
-
f"(DATA_PATH 'gs://{
|
|
123
|
-
f"METADATA_SCHEMA '{
|
|
118
|
+
f"(DATA_PATH 'gs://{integration['gcs_bucket_path']}', "
|
|
119
|
+
f"METADATA_SCHEMA '{integration['pg_schema']}');"
|
|
124
120
|
)
|
|
125
121
|
|
|
126
122
|
return f"{create_secret_sql}\n\n{attach_sql}"
|
definite_sdk/integration.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Dict, List, Optional, cast
|
|
2
2
|
|
|
3
3
|
import requests
|
|
4
4
|
|
|
5
|
-
INTEGRATION_ENDPOINT = "/v1/api/
|
|
5
|
+
INTEGRATION_ENDPOINT = "/v1/api/integrations"
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class DefiniteIntegrationStore:
|
|
@@ -27,23 +27,42 @@ class DefiniteIntegrationStore:
|
|
|
27
27
|
api_key (str): The API key for authorization.
|
|
28
28
|
"""
|
|
29
29
|
self._api_key = api_key
|
|
30
|
-
self.
|
|
31
|
-
|
|
32
|
-
def list_integrations(
|
|
30
|
+
self._integrations_url = api_url + INTEGRATION_ENDPOINT
|
|
31
|
+
|
|
32
|
+
def list_integrations(
|
|
33
|
+
self,
|
|
34
|
+
*,
|
|
35
|
+
integration_type: Optional[str] = None,
|
|
36
|
+
category: Optional[str] = None,
|
|
37
|
+
) -> List[Dict]:
|
|
33
38
|
"""
|
|
34
39
|
Lists all integrations in the store.
|
|
35
40
|
|
|
41
|
+
Args:
|
|
42
|
+
integration_type (str): Optional type filter
|
|
43
|
+
category (str): Optional category filter
|
|
44
|
+
|
|
36
45
|
Returns:
|
|
37
46
|
Iterator[str]: An iterator of integrations.
|
|
38
47
|
"""
|
|
48
|
+
params = {}
|
|
49
|
+
if integration_type:
|
|
50
|
+
params |= {"type": integration_type}
|
|
51
|
+
if category:
|
|
52
|
+
params |= {"category": category}
|
|
53
|
+
|
|
39
54
|
response = requests.get(
|
|
40
|
-
self.
|
|
55
|
+
self._integrations_url,
|
|
56
|
+
params=params,
|
|
41
57
|
headers={"Authorization": "Bearer " + self._api_key},
|
|
42
58
|
)
|
|
43
59
|
response.raise_for_status()
|
|
44
|
-
|
|
60
|
+
cursor_page = response.json()
|
|
61
|
+
integrations = cursor_page.get("data", [])
|
|
62
|
+
details = [i.get("details", {}) for i in integrations]
|
|
63
|
+
return cast(List[Dict], details)
|
|
45
64
|
|
|
46
|
-
def get_integration(self, name: str) ->
|
|
65
|
+
def get_integration(self, name: str) -> Dict:
|
|
47
66
|
"""
|
|
48
67
|
Retrieves an integration by name.
|
|
49
68
|
|
|
@@ -54,13 +73,19 @@ class DefiniteIntegrationStore:
|
|
|
54
73
|
str: The value of the integration.
|
|
55
74
|
"""
|
|
56
75
|
response = requests.get(
|
|
57
|
-
self.
|
|
76
|
+
self._integrations_url,
|
|
77
|
+
params={"name": name, "limit": 1},
|
|
58
78
|
headers={"Authorization": "Bearer " + self._api_key},
|
|
59
79
|
)
|
|
60
80
|
response.raise_for_status()
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
81
|
+
cursor_page = response.json()
|
|
82
|
+
integrations = cursor_page.get("data", [])
|
|
83
|
+
if len(integrations) == 0:
|
|
84
|
+
raise Exception(f"Integration with name {name} not found")
|
|
85
|
+
integration = integrations[0]
|
|
86
|
+
return integration.get("details", {})
|
|
87
|
+
|
|
88
|
+
def get_integration_by_id(self, integration_id: str) -> Dict:
|
|
64
89
|
"""
|
|
65
90
|
Retrieves an integration by ID.
|
|
66
91
|
|
|
@@ -71,47 +96,35 @@ class DefiniteIntegrationStore:
|
|
|
71
96
|
dict: The integration details.
|
|
72
97
|
"""
|
|
73
98
|
response = requests.get(
|
|
74
|
-
self.
|
|
99
|
+
self._integrations_url,
|
|
100
|
+
params={"id": integration_id, "limit": 1},
|
|
75
101
|
headers={"Authorization": "Bearer " + self._api_key},
|
|
76
102
|
)
|
|
77
103
|
response.raise_for_status()
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
104
|
+
cursor_page = response.json()
|
|
105
|
+
integrations = cursor_page.get("data", [])
|
|
106
|
+
if len(integrations) == 0:
|
|
107
|
+
raise Exception(f"Integration with ID {integration_id} not found")
|
|
108
|
+
integration = integrations[0]
|
|
109
|
+
return integration.get("details", {})
|
|
110
|
+
|
|
111
|
+
def lookup_duckdb_integration(self) -> Dict:
|
|
81
112
|
"""
|
|
82
113
|
Look up the team's DuckDB integration.
|
|
83
114
|
|
|
84
|
-
Note: Currently, the API only returns extractor (source) integrations.
|
|
85
|
-
Destination integrations like DuckDB are not yet exposed through this endpoint.
|
|
86
|
-
This method is provided for future compatibility when the API is updated.
|
|
87
|
-
|
|
88
115
|
Returns:
|
|
89
116
|
Optional[Tuple[str, str]]: Tuple of (integration_id, connection_uri)
|
|
90
117
|
if found, None if no DuckDB integration exists.
|
|
91
118
|
"""
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
for integration in integrations:
|
|
105
|
-
integration_type = integration.get("integration_type", "").lower()
|
|
106
|
-
if integration_type == "duckdb" and integration.get("active", True):
|
|
107
|
-
integration_id = integration.get("id")
|
|
108
|
-
# Connection URI might be in config or connection_string field
|
|
109
|
-
connection_uri = (
|
|
110
|
-
integration.get("connection_string")
|
|
111
|
-
or integration.get("config", {}).get("database_path")
|
|
112
|
-
or integration.get("config", {}).get("connection_string")
|
|
113
|
-
)
|
|
114
|
-
if integration_id and connection_uri:
|
|
115
|
-
return (integration_id, connection_uri)
|
|
116
|
-
|
|
117
|
-
return None
|
|
119
|
+
response = requests.get(
|
|
120
|
+
self._integrations_url,
|
|
121
|
+
params={"type": "duckdb", "limit": 1},
|
|
122
|
+
headers={"Authorization": "Bearer " + self._api_key},
|
|
123
|
+
)
|
|
124
|
+
response.raise_for_status()
|
|
125
|
+
cursor_page = response.json()
|
|
126
|
+
integrations = cursor_page.get("data", [])
|
|
127
|
+
if len(integrations) == 0:
|
|
128
|
+
raise Exception("Integration with type `duckdb` not found")
|
|
129
|
+
integration = integrations[0]
|
|
130
|
+
return integration.get("details", {})
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
definite_sdk/__init__.py,sha256=pzw1-eWBcD5mvWRxbo59dMUU8Wue4zNsdDYK0Pj1hXQ,606
|
|
2
|
-
definite_sdk/client.py,sha256=
|
|
2
|
+
definite_sdk/client.py,sha256=iI1CXPMW1jtIFIPcNT2V4Ley7VqHIzEimmGO2biXZkM,5203
|
|
3
3
|
definite_sdk/dlt.py,sha256=JC-S1jd6zqnpGSnvk9kYb8GQ1IPZRd1zVKTVYAbeA4w,7188
|
|
4
|
-
definite_sdk/integration.py,sha256=
|
|
4
|
+
definite_sdk/integration.py,sha256=oSQz9ojgnCch5CFWEC02nTwNmM6Y-w5-LKz0na4xLOQ,4163
|
|
5
5
|
definite_sdk/message.py,sha256=k5TpAoPYSqK_w7ZOphnDz4ntTMmsYVNfG5ROCg6oqxg,6504
|
|
6
6
|
definite_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
definite_sdk/secret.py,sha256=3wvEnTZ946hOxJBdB29dxvppwJ0x-TJV_LxRcXGqtis,2503
|
|
8
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.
|
|
11
|
-
definite_sdk-0.1.
|
|
12
|
-
definite_sdk-0.1.
|
|
13
|
-
definite_sdk-0.1.
|
|
10
|
+
definite_sdk-0.1.16.dist-info/METADATA,sha256=828vrMGBYuQZlClISEXcYLfKfVUa8pdRqwaS_ufSa4c,9209
|
|
11
|
+
definite_sdk-0.1.16.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
12
|
+
definite_sdk-0.1.16.dist-info/licenses/LICENSE,sha256=jMd7PtwNWiMoGIDgFutC1v4taO69W9SRZLKe9o470Vk,1064
|
|
13
|
+
definite_sdk-0.1.16.dist-info/RECORD,,
|
|
File without changes
|