duckrun 0.2.18.dev2__py3-none-any.whl → 0.2.18.dev3__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 duckrun might be problematic. Click here for more details.

duckrun/core.py CHANGED
@@ -1188,7 +1188,7 @@ class Duckrun(WorkspaceOperationsMixin):
1188
1188
  - URL: "https://raw.githubusercontent.com/.../model.bim"
1189
1189
  - Local file: "model.bim"
1190
1190
  - Workspace/Model: "workspace_name/model_name"
1191
- dataset_name: Name for the semantic model (default: source model name if workspace/model format, else lakehouse_schema)
1191
+ dataset_name: Name for the semantic model (default: schema name)
1192
1192
  wait_seconds: Seconds to wait for permission propagation (default: 5)
1193
1193
 
1194
1194
  Returns:
@@ -1197,14 +1197,14 @@ class Duckrun(WorkspaceOperationsMixin):
1197
1197
  Examples:
1198
1198
  dr = Duckrun.connect("My Workspace/My Lakehouse.lakehouse/dbo")
1199
1199
 
1200
+ # Deploy with schema name as dataset name (dbo)
1201
+ dr.deploy("https://github.com/.../model.bim")
1202
+
1200
1203
  # Deploy from workspace/model (uses same name by default)
1201
1204
  dr.deploy("Source Workspace/Source Model") # Creates "Source Model"
1202
1205
 
1203
1206
  # Deploy with custom name
1204
- dr.deploy("Source Workspace/Source Model", dataset_name="Sales Model Copy")
1205
-
1206
- # Deploy from URL or local file
1207
- dr.deploy("https://raw.githubusercontent.com/.../model.bim", dataset_name="My Model")
1207
+ dr.deploy("https://github.com/.../model.bim", dataset_name="Sales Model")
1208
1208
  """
1209
1209
  from .semantic_model import deploy_semantic_model
1210
1210
 
@@ -1216,9 +1216,9 @@ class Duckrun(WorkspaceOperationsMixin):
1216
1216
  if len(parts) == 2:
1217
1217
  dataset_name = parts[1] # Use the model name
1218
1218
  else:
1219
- dataset_name = f"{self.lakehouse_name}_{self.schema}"
1219
+ dataset_name = self.schema # Use schema name
1220
1220
  else:
1221
- dataset_name = f"{self.lakehouse_name}_{self.schema}"
1221
+ dataset_name = self.schema # Use schema name
1222
1222
 
1223
1223
  # Call the deployment function (DirectLake only)
1224
1224
  return deploy_semantic_model(
duckrun/semantic_model.py CHANGED
@@ -135,6 +135,8 @@ def refresh_dataset(dataset_name, workspace_id, client, dataset_id=None):
135
135
  For DirectLake models, performs a two-step refresh:
136
136
  1. clearValues - Purges data from memory
137
137
  2. full - Reframes data from Delta tables
138
+
139
+ If a refresh is already in progress, waits for it to complete before starting a new one.
138
140
  """
139
141
 
140
142
  # If dataset_id not provided, look it up by name
@@ -145,6 +147,46 @@ def refresh_dataset(dataset_name, workspace_id, client, dataset_id=None):
145
147
  powerbi_url = f"https://api.powerbi.com/v1.0/myorg/datasets/{dataset_id}/refreshes"
146
148
  headers = client._get_headers()
147
149
 
150
+ # Check for in-progress refreshes
151
+ print(" Checking for in-progress refreshes...")
152
+ try:
153
+ status_response = requests.get(f"{powerbi_url}?$top=1", headers=headers)
154
+ if status_response.status_code == 200:
155
+ refreshes = status_response.json().get('value', [])
156
+ if refreshes:
157
+ latest_refresh = refreshes[0]
158
+ status = latest_refresh.get('status')
159
+ if status in ['InProgress', 'Unknown']:
160
+ refresh_id = latest_refresh.get('requestId')
161
+ print(f" ⚠️ Found in-progress refresh (ID: {refresh_id})")
162
+ print(f" Waiting for current refresh to complete...")
163
+
164
+ # Wait for the in-progress refresh to complete
165
+ max_wait_attempts = 60
166
+ for attempt in range(max_wait_attempts):
167
+ time.sleep(5)
168
+ check_response = requests.get(f"{powerbi_url}/{refresh_id}", headers=headers)
169
+ if check_response.status_code == 200:
170
+ current_status = check_response.json().get('status')
171
+
172
+ if current_status == 'Completed':
173
+ print(f" ✓ Previous refresh completed")
174
+ break
175
+ elif current_status == 'Failed':
176
+ print(f" ⚠️ Previous refresh failed, continuing with new refresh")
177
+ break
178
+ elif current_status == 'Cancelled':
179
+ print(f" ⚠️ Previous refresh was cancelled, continuing with new refresh")
180
+ break
181
+
182
+ if attempt % 6 == 0:
183
+ print(f" Still waiting... (status: {current_status})")
184
+ else:
185
+ print(f" ⚠️ Timeout waiting for previous refresh, will attempt new refresh anyway")
186
+ except Exception as e:
187
+ print(f" ⚠️ Could not check refresh status: {e}")
188
+ print(f" Continuing with refresh attempt...")
189
+
148
190
  # Step 1: clearValues - Purge data from memory
149
191
  print(" Step 1: Clearing values from memory...")
150
192
  clearvalues_payload = {
@@ -158,9 +200,45 @@ def refresh_dataset(dataset_name, workspace_id, client, dataset_id=None):
158
200
  response = requests.post(powerbi_url, headers=headers, json=clearvalues_payload)
159
201
 
160
202
  if response.status_code in [200, 202]:
161
- print(" ✓ Clear values completed")
203
+ # For 202, monitor the clearValues operation
204
+ if response.status_code == 202:
205
+ location = response.headers.get('Location')
206
+ if location:
207
+ clear_refresh_id = location.split('/')[-1]
208
+ print(" ✓ Clear values initiated, monitoring progress...")
209
+
210
+ max_attempts = 60
211
+ for attempt in range(max_attempts):
212
+ time.sleep(2)
213
+
214
+ status_url = f"https://api.powerbi.com/v1.0/myorg/datasets/{dataset_id}/refreshes/{clear_refresh_id}"
215
+ status_response = requests.get(status_url, headers=headers)
216
+ status_response.raise_for_status()
217
+ status = status_response.json().get('status')
218
+
219
+ if status == 'Completed':
220
+ print(f" ✓ Clear values completed")
221
+ break
222
+ elif status == 'Failed':
223
+ error = status_response.json().get('serviceExceptionJson', '')
224
+ raise Exception(f"Clear values failed: {error}")
225
+ elif status == 'Cancelled':
226
+ raise Exception("Clear values was cancelled")
227
+
228
+ if attempt % 10 == 0 and attempt > 0:
229
+ print(f" Clear values status: {status}...")
230
+ else:
231
+ raise Exception(f"Clear values timed out")
232
+ else:
233
+ print(" ✓ Clear values completed")
162
234
  else:
163
- response.raise_for_status()
235
+ # Provide detailed error message
236
+ try:
237
+ error_details = response.json()
238
+ error_message = error_details.get('error', {}).get('message', response.text)
239
+ raise Exception(f"Clear values failed with status {response.status_code}: {error_message}")
240
+ except (json.JSONDecodeError, ValueError):
241
+ response.raise_for_status()
164
242
 
165
243
  # Step 2: full refresh - Reframe data from Delta tables
166
244
  print(" Step 2: Full refresh to reframe data...")
@@ -175,7 +253,7 @@ def refresh_dataset(dataset_name, workspace_id, client, dataset_id=None):
175
253
  response = requests.post(powerbi_url, headers=headers, json=full_payload)
176
254
 
177
255
  if response.status_code in [200, 202]:
178
- print(f"✓ Refresh initiated")
256
+ print(f" ✓ Refresh initiated")
179
257
 
180
258
  # For 202, get the refresh_id from the Location header
181
259
  if response.status_code == 202:
@@ -207,7 +285,13 @@ def refresh_dataset(dataset_name, workspace_id, client, dataset_id=None):
207
285
 
208
286
  raise Exception(f"Refresh timed out")
209
287
  else:
210
- response.raise_for_status()
288
+ # Provide detailed error message
289
+ try:
290
+ error_details = response.json()
291
+ error_message = error_details.get('error', {}).get('message', response.text)
292
+ raise Exception(f"Refresh request failed with status {response.status_code}: {error_message}")
293
+ except (json.JSONDecodeError, ValueError):
294
+ response.raise_for_status()
211
295
 
212
296
 
213
297
  def download_bim_from_github(url_or_path):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: duckrun
3
- Version: 0.2.18.dev2
3
+ Version: 0.2.18.dev3
4
4
  Summary: Helper library for Fabric Python using duckdb, arrow and delta_rs (orchestration, queries, etc.)
5
5
  Author: mim
6
6
  License: MIT
@@ -1,15 +1,15 @@
1
1
  duckrun/__init__.py,sha256=vqv_bJjHjrrXGs8Zyxuy-GKTCyJlZ5z3npPQgE9ipBY,355
2
2
  duckrun/auth.py,sha256=EMaf-L2zeNOjbHOT97xYxfZNfWo4WrwrU1h3vBQTgEc,9624
3
- duckrun/core.py,sha256=tWLFOSVZHoJ0r5YJaj0lG1s_kehiIrnxPMrQQIcyh94,68367
3
+ duckrun/core.py,sha256=irIepj0d-4J7Er5YeQIaOZQuycBYQ1FSNmTEBgaGVm4,68270
4
4
  duckrun/files.py,sha256=Fvdjg3DyHJzIVzKo8M_j-eGz4zU61lOB38Y_onbQJkI,10137
5
5
  duckrun/lakehouse.py,sha256=j--Z3zo8AOWt1GF9VzRosmmTAy6ey2D0LVubti58twU,14109
6
6
  duckrun/notebook.py,sha256=SzdKTpvzHiWMrvg7mCd3DN6R4gU_6Gm7gfkuETzylaE,12103
7
7
  duckrun/runner.py,sha256=NGVyerJA44UP2umRdndfL0fuFM_gdOZmuJUz-PLOFf0,13461
8
- duckrun/semantic_model.py,sha256=X3VKdo4BehAg681Ucq7fzB2KPY2mwPLbfIZqI5Gbqp4,30377
8
+ duckrun/semantic_model.py,sha256=kc-g97A-Lbsa1H89EtumZTUPmGYN2uXhspGbG6ZuG2M,35049
9
9
  duckrun/stats.py,sha256=qvWnPk2P8Ob_tzaiNfdQmUQqMVq2FWv3EgArE7hPl44,15482
10
10
  duckrun/writer.py,sha256=wIsU77DSj4J7d9_bIhvk6AbC51uUrLW0e6pcSPQOY1c,9424
11
- duckrun-0.2.18.dev2.dist-info/licenses/LICENSE,sha256=-DeQQwdbCbkB4507ZF3QbocysB-EIjDtaLexvqRkGZc,1083
12
- duckrun-0.2.18.dev2.dist-info/METADATA,sha256=JpewTO7QqHrdUn_G3Lz-1jxFifVyBxj9lNX_Qodhe2A,20807
13
- duckrun-0.2.18.dev2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
14
- duckrun-0.2.18.dev2.dist-info/top_level.txt,sha256=BknMEwebbUHrVAp3SC92ps8MPhK7XSYsaogTvi_DmEU,8
15
- duckrun-0.2.18.dev2.dist-info/RECORD,,
11
+ duckrun-0.2.18.dev3.dist-info/licenses/LICENSE,sha256=-DeQQwdbCbkB4507ZF3QbocysB-EIjDtaLexvqRkGZc,1083
12
+ duckrun-0.2.18.dev3.dist-info/METADATA,sha256=tGhjPWM7NxHEQQbBp_PkSWNamMXJwJ92Ns8Qfse8TXs,20807
13
+ duckrun-0.2.18.dev3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
14
+ duckrun-0.2.18.dev3.dist-info/top_level.txt,sha256=BknMEwebbUHrVAp3SC92ps8MPhK7XSYsaogTvi_DmEU,8
15
+ duckrun-0.2.18.dev3.dist-info/RECORD,,