duckrun 0.2.9.dev1__tar.gz → 0.2.9.dev3__tar.gz
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.
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/PKG-INFO +1 -1
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/duckrun/__init__.py +1 -1
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/duckrun/auth.py +9 -0
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/duckrun/core.py +2 -2
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/duckrun/semantic_model.py +54 -19
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/duckrun.egg-info/PKG-INFO +1 -1
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/pyproject.toml +1 -1
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/LICENSE +0 -0
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/README.md +0 -0
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/duckrun/files.py +0 -0
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/duckrun/lakehouse.py +0 -0
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/duckrun/runner.py +0 -0
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/duckrun/stats.py +0 -0
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/duckrun/writer.py +0 -0
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/duckrun.egg-info/SOURCES.txt +0 -0
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/duckrun.egg-info/dependency_links.txt +0 -0
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/duckrun.egg-info/requires.txt +0 -0
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/duckrun.egg-info/top_level.txt +0 -0
- {duckrun-0.2.9.dev1 → duckrun-0.2.9.dev3}/setup.cfg +0 -0
@@ -123,6 +123,12 @@ def get_fabric_api_token() -> Optional[str]:
|
|
123
123
|
Returns:
|
124
124
|
Fabric API token string or None if authentication fails
|
125
125
|
"""
|
126
|
+
# Check if we already have a cached Fabric API token
|
127
|
+
fabric_token_env = os.environ.get("FABRIC_API_TOKEN")
|
128
|
+
if fabric_token_env:
|
129
|
+
print("✅ Using cached Fabric API token")
|
130
|
+
return fabric_token_env
|
131
|
+
|
126
132
|
print("🔐 Getting Fabric API token...")
|
127
133
|
|
128
134
|
# Try Fabric notebook environment first
|
@@ -130,6 +136,7 @@ def get_fabric_api_token() -> Optional[str]:
|
|
130
136
|
import notebookutils # type: ignore
|
131
137
|
print("📓 Microsoft Fabric notebook detected - using notebookutils")
|
132
138
|
token = notebookutils.credentials.getToken("pbi")
|
139
|
+
os.environ["FABRIC_API_TOKEN"] = token
|
133
140
|
print("✅ Fabric API token obtained!")
|
134
141
|
return token
|
135
142
|
except ImportError:
|
@@ -158,6 +165,7 @@ def get_fabric_api_token() -> Optional[str]:
|
|
158
165
|
print("🔐 Trying Azure CLI for Fabric API...")
|
159
166
|
credential = AzureCliCredential()
|
160
167
|
token_obj = credential.get_token("https://api.fabric.microsoft.com/.default")
|
168
|
+
os.environ["FABRIC_API_TOKEN"] = token_obj.token
|
161
169
|
print("✅ Fabric API token obtained via Azure CLI!")
|
162
170
|
return token_obj.token
|
163
171
|
except Exception as cli_error:
|
@@ -167,6 +175,7 @@ def get_fabric_api_token() -> Optional[str]:
|
|
167
175
|
credential = InteractiveBrowserCredential()
|
168
176
|
|
169
177
|
token_obj = credential.get_token("https://api.fabric.microsoft.com/.default")
|
178
|
+
os.environ["FABRIC_API_TOKEN"] = token_obj.token
|
170
179
|
print("✅ Fabric API token obtained!")
|
171
180
|
return token_obj.token
|
172
181
|
|
@@ -727,8 +727,8 @@ class Duckrun:
|
|
727
727
|
|
728
728
|
# Call the deployment function (DirectLake only)
|
729
729
|
return deploy_semantic_model(
|
730
|
-
|
731
|
-
|
730
|
+
workspace_name_or_id=self.workspace,
|
731
|
+
lakehouse_name_or_id=self.lakehouse_name,
|
732
732
|
schema_name=self.schema,
|
733
733
|
dataset_name=dataset_name,
|
734
734
|
bim_url=bim_url,
|
@@ -43,31 +43,66 @@ class FabricRestClient:
|
|
43
43
|
return response
|
44
44
|
|
45
45
|
|
46
|
-
def get_workspace_id(
|
47
|
-
"""Get workspace ID by name"""
|
46
|
+
def get_workspace_id(workspace_name_or_id, client):
|
47
|
+
"""Get workspace ID by name or validate if already a GUID"""
|
48
|
+
import re
|
49
|
+
|
50
|
+
# Check if input is already a GUID
|
51
|
+
guid_pattern = re.compile(r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$', re.IGNORECASE)
|
52
|
+
if guid_pattern.match(workspace_name_or_id):
|
53
|
+
# It's already a GUID, verify it exists
|
54
|
+
try:
|
55
|
+
response = client.get(f"/v1/workspaces/{workspace_name_or_id}")
|
56
|
+
workspace_name = response.json().get('displayName', workspace_name_or_id)
|
57
|
+
print(f"✓ Found workspace: {workspace_name}")
|
58
|
+
return workspace_name_or_id
|
59
|
+
except:
|
60
|
+
raise ValueError(f"Workspace with ID '{workspace_name_or_id}' not found")
|
61
|
+
|
62
|
+
# It's a name, search for it
|
48
63
|
response = client.get("/v1/workspaces")
|
49
64
|
workspaces = response.json().get('value', [])
|
50
65
|
|
51
|
-
workspace_match = next((ws for ws in workspaces if ws.get('displayName') ==
|
66
|
+
workspace_match = next((ws for ws in workspaces if ws.get('displayName') == workspace_name_or_id), None)
|
52
67
|
if not workspace_match:
|
53
|
-
raise ValueError(f"Workspace '{
|
68
|
+
raise ValueError(f"Workspace '{workspace_name_or_id}' not found")
|
54
69
|
|
55
70
|
workspace_id = workspace_match['id']
|
56
|
-
print(f"✓ Found workspace: {
|
71
|
+
print(f"✓ Found workspace: {workspace_name_or_id}")
|
57
72
|
return workspace_id
|
58
73
|
|
59
74
|
|
60
|
-
def get_lakehouse_id(
|
61
|
-
"""Get lakehouse ID by name"""
|
75
|
+
def get_lakehouse_id(lakehouse_name_or_id, workspace_id, client):
|
76
|
+
"""Get lakehouse ID by name or validate if already a GUID"""
|
77
|
+
import re
|
78
|
+
|
79
|
+
# Check if input is already a GUID
|
80
|
+
guid_pattern = re.compile(r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$', re.IGNORECASE)
|
81
|
+
if guid_pattern.match(lakehouse_name_or_id):
|
82
|
+
# It's already a GUID, verify it exists
|
83
|
+
try:
|
84
|
+
response = client.get(f"/v1/workspaces/{workspace_id}/lakehouses")
|
85
|
+
items = response.json().get('value', [])
|
86
|
+
lakehouse_match = next((item for item in items if item.get('id') == lakehouse_name_or_id), None)
|
87
|
+
if lakehouse_match:
|
88
|
+
lakehouse_name = lakehouse_match.get('displayName', lakehouse_name_or_id)
|
89
|
+
print(f"✓ Found lakehouse: {lakehouse_name}")
|
90
|
+
return lakehouse_name_or_id
|
91
|
+
else:
|
92
|
+
raise ValueError(f"Lakehouse with ID '{lakehouse_name_or_id}' not found")
|
93
|
+
except Exception as e:
|
94
|
+
raise ValueError(f"Lakehouse with ID '{lakehouse_name_or_id}' not found: {e}")
|
95
|
+
|
96
|
+
# It's a name, search for it
|
62
97
|
response = client.get(f"/v1/workspaces/{workspace_id}/lakehouses")
|
63
98
|
items = response.json().get('value', [])
|
64
99
|
|
65
|
-
lakehouse_match = next((item for item in items if item.get('displayName') ==
|
100
|
+
lakehouse_match = next((item for item in items if item.get('displayName') == lakehouse_name_or_id), None)
|
66
101
|
if not lakehouse_match:
|
67
|
-
raise ValueError(f"Lakehouse '{
|
102
|
+
raise ValueError(f"Lakehouse '{lakehouse_name_or_id}' not found")
|
68
103
|
|
69
104
|
lakehouse_id = lakehouse_match['id']
|
70
|
-
print(f"✓ Found lakehouse: {
|
105
|
+
print(f"✓ Found lakehouse: {lakehouse_name_or_id}")
|
71
106
|
return lakehouse_id
|
72
107
|
|
73
108
|
|
@@ -266,14 +301,14 @@ def create_dataset_from_bim(dataset_name, bim_content, workspace_id, client):
|
|
266
301
|
raise Exception(f"Operation timed out")
|
267
302
|
|
268
303
|
|
269
|
-
def deploy_semantic_model(
|
304
|
+
def deploy_semantic_model(workspace_name_or_id, lakehouse_name_or_id, schema_name, dataset_name,
|
270
305
|
bim_url, wait_seconds=5):
|
271
306
|
"""
|
272
307
|
Deploy a semantic model using DirectLake mode.
|
273
308
|
|
274
309
|
Args:
|
275
|
-
|
276
|
-
|
310
|
+
workspace_name_or_id: Name or GUID of the target workspace
|
311
|
+
lakehouse_name_or_id: Name or GUID of the lakehouse
|
277
312
|
schema_name: Schema name (e.g., 'dbo', 'staging')
|
278
313
|
dataset_name: Name for the semantic model
|
279
314
|
bim_url: URL to the BIM file
|
@@ -295,7 +330,7 @@ def deploy_semantic_model(workspace_name, lakehouse_name, schema_name, dataset_n
|
|
295
330
|
try:
|
296
331
|
# Step 1: Get workspace ID
|
297
332
|
print("\n[Step 1/6] Getting workspace information...")
|
298
|
-
workspace_id = get_workspace_id(
|
333
|
+
workspace_id = get_workspace_id(workspace_name_or_id, client)
|
299
334
|
|
300
335
|
# Step 2: Check if dataset exists
|
301
336
|
print(f"\n[Step 2/6] Checking if dataset '{dataset_name}' exists...")
|
@@ -320,7 +355,7 @@ def deploy_semantic_model(workspace_name, lakehouse_name, schema_name, dataset_n
|
|
320
355
|
|
321
356
|
# Step 3: Get lakehouse ID
|
322
357
|
print(f"\n[Step 3/6] Finding lakehouse...")
|
323
|
-
lakehouse_id = get_lakehouse_id(
|
358
|
+
lakehouse_id = get_lakehouse_id(lakehouse_name_or_id, workspace_id, client)
|
324
359
|
|
325
360
|
# Step 4: Download and update BIM
|
326
361
|
print("\n[Step 4/6] Downloading and configuring BIM file...")
|
@@ -346,8 +381,8 @@ def deploy_semantic_model(workspace_name, lakehouse_name, schema_name, dataset_n
|
|
346
381
|
print("🎉 Deployment Completed!")
|
347
382
|
print("=" * 70)
|
348
383
|
print(f"Dataset: {dataset_name}")
|
349
|
-
print(f"Workspace: {
|
350
|
-
print(f"Lakehouse: {
|
384
|
+
print(f"Workspace: {workspace_name_or_id}")
|
385
|
+
print(f"Lakehouse: {lakehouse_name_or_id}")
|
351
386
|
print(f"Schema: {schema_name}")
|
352
387
|
print("=" * 70)
|
353
388
|
|
@@ -359,8 +394,8 @@ def deploy_semantic_model(workspace_name, lakehouse_name, schema_name, dataset_n
|
|
359
394
|
print("=" * 70)
|
360
395
|
print(f"Error: {str(e)}")
|
361
396
|
print("\n💡 Troubleshooting:")
|
362
|
-
print(f" - Verify workspace '{
|
363
|
-
print(f" - Verify lakehouse '{
|
397
|
+
print(f" - Verify workspace '{workspace_name_or_id}' exists")
|
398
|
+
print(f" - Verify lakehouse '{lakehouse_name_or_id}' exists")
|
364
399
|
print(f" - Ensure tables exist in '{schema_name}' schema")
|
365
400
|
print(f" - Check tables are in Delta format")
|
366
401
|
print("=" * 70)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|