semantic-link-labs 0.8.9__py3-none-any.whl → 0.8.11__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 semantic-link-labs might be problematic. Click here for more details.

Files changed (76) hide show
  1. {semantic_link_labs-0.8.9.dist-info → semantic_link_labs-0.8.11.dist-info}/METADATA +5 -2
  2. {semantic_link_labs-0.8.9.dist-info → semantic_link_labs-0.8.11.dist-info}/RECORD +76 -75
  3. sempy_labs/__init__.py +14 -2
  4. sempy_labs/_authentication.py +31 -2
  5. sempy_labs/_clear_cache.py +39 -37
  6. sempy_labs/_connections.py +13 -13
  7. sempy_labs/_data_pipelines.py +20 -20
  8. sempy_labs/_dataflows.py +27 -28
  9. sempy_labs/_dax.py +41 -47
  10. sempy_labs/_environments.py +26 -23
  11. sempy_labs/_eventhouses.py +16 -15
  12. sempy_labs/_eventstreams.py +16 -15
  13. sempy_labs/_external_data_shares.py +18 -20
  14. sempy_labs/_gateways.py +57 -11
  15. sempy_labs/_generate_semantic_model.py +100 -71
  16. sempy_labs/_git.py +134 -67
  17. sempy_labs/_helper_functions.py +199 -145
  18. sempy_labs/_job_scheduler.py +92 -0
  19. sempy_labs/_kql_databases.py +16 -15
  20. sempy_labs/_kql_querysets.py +16 -15
  21. sempy_labs/_list_functions.py +281 -120
  22. sempy_labs/_managed_private_endpoints.py +19 -17
  23. sempy_labs/_mirrored_databases.py +51 -48
  24. sempy_labs/_mirrored_warehouses.py +5 -4
  25. sempy_labs/_ml_experiments.py +16 -15
  26. sempy_labs/_ml_models.py +15 -14
  27. sempy_labs/_model_bpa.py +27 -25
  28. sempy_labs/_model_bpa_bulk.py +3 -3
  29. sempy_labs/_model_dependencies.py +60 -28
  30. sempy_labs/_notebooks.py +73 -39
  31. sempy_labs/_one_lake_integration.py +23 -26
  32. sempy_labs/_query_scale_out.py +67 -64
  33. sempy_labs/_refresh_semantic_model.py +47 -42
  34. sempy_labs/_spark.py +33 -32
  35. sempy_labs/_sql.py +12 -9
  36. sempy_labs/_translations.py +10 -7
  37. sempy_labs/_vertipaq.py +34 -31
  38. sempy_labs/_warehouses.py +22 -21
  39. sempy_labs/_workspace_identity.py +11 -10
  40. sempy_labs/_workspaces.py +40 -33
  41. sempy_labs/admin/__init__.py +4 -0
  42. sempy_labs/admin/_basic_functions.py +44 -12
  43. sempy_labs/admin/_external_data_share.py +3 -3
  44. sempy_labs/admin/_items.py +4 -4
  45. sempy_labs/admin/_scanner.py +7 -5
  46. sempy_labs/directlake/_directlake_schema_compare.py +18 -14
  47. sempy_labs/directlake/_directlake_schema_sync.py +18 -12
  48. sempy_labs/directlake/_dl_helper.py +36 -32
  49. sempy_labs/directlake/_generate_shared_expression.py +10 -9
  50. sempy_labs/directlake/_get_directlake_lakehouse.py +16 -13
  51. sempy_labs/directlake/_get_shared_expression.py +4 -3
  52. sempy_labs/directlake/_guardrails.py +12 -6
  53. sempy_labs/directlake/_list_directlake_model_calc_tables.py +15 -9
  54. sempy_labs/directlake/_show_unsupported_directlake_objects.py +16 -10
  55. sempy_labs/directlake/_update_directlake_model_lakehouse_connection.py +35 -31
  56. sempy_labs/directlake/_update_directlake_partition_entity.py +34 -31
  57. sempy_labs/directlake/_warm_cache.py +87 -65
  58. sempy_labs/lakehouse/_get_lakehouse_columns.py +10 -8
  59. sempy_labs/lakehouse/_get_lakehouse_tables.py +10 -9
  60. sempy_labs/lakehouse/_lakehouse.py +17 -13
  61. sempy_labs/lakehouse/_shortcuts.py +42 -23
  62. sempy_labs/migration/_create_pqt_file.py +16 -11
  63. sempy_labs/migration/_refresh_calc_tables.py +16 -10
  64. sempy_labs/report/_download_report.py +9 -8
  65. sempy_labs/report/_generate_report.py +40 -44
  66. sempy_labs/report/_paginated.py +9 -9
  67. sempy_labs/report/_report_bpa.py +13 -9
  68. sempy_labs/report/_report_functions.py +80 -91
  69. sempy_labs/report/_report_helper.py +8 -4
  70. sempy_labs/report/_report_list_functions.py +24 -13
  71. sempy_labs/report/_report_rebind.py +17 -16
  72. sempy_labs/report/_reportwrapper.py +41 -33
  73. sempy_labs/tom/_model.py +117 -38
  74. {semantic_link_labs-0.8.9.dist-info → semantic_link_labs-0.8.11.dist-info}/LICENSE +0 -0
  75. {semantic_link_labs-0.8.9.dist-info → semantic_link_labs-0.8.11.dist-info}/WHEEL +0 -0
  76. {semantic_link_labs-0.8.9.dist-info → semantic_link_labs-0.8.11.dist-info}/top_level.txt +0 -0
sempy_labs/_model_bpa.py CHANGED
@@ -10,9 +10,10 @@ from sempy_labs._helper_functions import (
10
10
  create_relationship_name,
11
11
  save_as_delta_table,
12
12
  resolve_workspace_capacity,
13
- resolve_dataset_id,
13
+ resolve_dataset_name_and_id,
14
14
  get_language_codes,
15
15
  _get_max_run_id,
16
+ resolve_workspace_name_and_id,
16
17
  )
17
18
  from sempy_labs.lakehouse import get_lakehouse_tables, lakehouse_attached
18
19
  from sempy_labs.tom import connect_semantic_model
@@ -23,11 +24,12 @@ import sempy_labs._icons as icons
23
24
  from pyspark.sql.functions import col, flatten
24
25
  from pyspark.sql.types import StructType, StructField, StringType
25
26
  import os
27
+ from uuid import UUID
26
28
 
27
29
 
28
30
  @log
29
31
  def run_model_bpa(
30
- dataset: str,
32
+ dataset: str | UUID,
31
33
  rules: Optional[pd.DataFrame] = None,
32
34
  workspace: Optional[str] = None,
33
35
  export: bool = False,
@@ -41,12 +43,12 @@ def run_model_bpa(
41
43
 
42
44
  Parameters
43
45
  ----------
44
- dataset : str
45
- Name of the semantic model.
46
+ dataset : str | uuid.UUID
47
+ Name or ID of the semantic model.
46
48
  rules : pandas.DataFrame, default=None
47
49
  A pandas dataframe containing rules to be evaluated.
48
- workspace : str, default=None
49
- The Fabric workspace name.
50
+ workspace : str | uuid.UUID, default=None
51
+ The Fabric workspace name or ID.
50
52
  Defaults to None which resolves to the workspace of the attached lakehouse
51
53
  or if no lakehouse attached, resolves to the workspace of the notebook.
52
54
  export : bool, default=False
@@ -105,28 +107,27 @@ def run_model_bpa(
105
107
  if language is not None:
106
108
  language = map_language(language, language_list)
107
109
 
108
- workspace = fabric.resolve_workspace_name(workspace)
110
+ (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
111
+ (dataset_name, dataset_id) = resolve_dataset_name_and_id(
112
+ dataset, workspace=workspace_id
113
+ )
109
114
 
110
115
  if language is not None and language not in language_list:
111
116
  print(
112
117
  f"{icons.yellow_dot} The '{language}' language code is not in our predefined language list. Please file an issue and let us know which language code you are using: https://github.com/microsoft/semantic-link-labs/issues/new?assignees=&labels=&projects=&template=bug_report.md&title=."
113
118
  )
114
119
 
115
- if extended:
116
- icons.sll_tags.append("ModelBPAExtended")
117
- with connect_semantic_model(
118
- dataset=dataset, workspace=workspace, readonly=False
119
- ) as tom:
120
- tom.set_vertipaq_annotations()
121
-
122
120
  with connect_semantic_model(
123
- dataset=dataset, workspace=workspace, readonly=True
121
+ dataset=dataset_id, workspace=workspace_id, readonly=True
124
122
  ) as tom:
125
123
 
124
+ if extended:
125
+ tom.set_vertipaq_annotations()
126
+
126
127
  # Do not run BPA for models with no tables
127
128
  if tom.model.Tables.Count == 0:
128
129
  print(
129
- f"{icons.warning} The '{dataset}' semantic model within the '{workspace}' workspace has no tables and therefore there are no valid BPA results."
130
+ f"{icons.warning} The '{dataset_name}' semantic model within the '{workspace_name}' workspace has no tables and therefore there are no valid BPA results."
130
131
  )
131
132
  finalDF = pd.DataFrame(
132
133
  columns=[
@@ -140,7 +141,9 @@ def run_model_bpa(
140
141
  ]
141
142
  )
142
143
  else:
143
- dep = get_model_calc_dependencies(dataset=dataset, workspace=workspace)
144
+ dep = get_model_calc_dependencies(
145
+ dataset=dataset_id, workspace=workspace_id
146
+ )
144
147
 
145
148
  def translate_using_po(rule_file):
146
149
  current_dir = os.path.dirname(os.path.abspath(__file__))
@@ -386,20 +389,19 @@ def run_model_bpa(
386
389
  runId = max_run_id + 1
387
390
 
388
391
  now = datetime.datetime.now()
389
- dfD = fabric.list_datasets(workspace=workspace, mode="rest")
390
- dfD_filt = dfD[dfD["Dataset Name"] == dataset]
392
+ dfD = fabric.list_datasets(workspace=workspace_id, mode="rest")
393
+ dfD_filt = dfD[dfD["Dataset Id"] == dataset_id]
391
394
  configured_by = dfD_filt["Configured By"].iloc[0]
392
- capacity_id, capacity_name = resolve_workspace_capacity(workspace=workspace)
395
+ capacity_id, capacity_name = resolve_workspace_capacity(workspace=workspace_id)
393
396
  dfExport["Capacity Name"] = capacity_name
394
397
  dfExport["Capacity Id"] = capacity_id
395
- dfExport["Workspace Name"] = workspace
396
- dfExport["Workspace Id"] = fabric.resolve_workspace_id(workspace)
397
- dfExport["Dataset Name"] = dataset
398
- dfExport["Dataset Id"] = resolve_dataset_id(dataset, workspace)
398
+ dfExport["Workspace Name"] = workspace_name
399
+ dfExport["Workspace Id"] = workspace_id
400
+ dfExport["Dataset Name"] = dataset_name
401
+ dfExport["Dataset Id"] = dataset_id
399
402
  dfExport["Configured By"] = configured_by
400
403
  dfExport["Timestamp"] = now
401
404
  dfExport["RunId"] = runId
402
- dfExport["Configured By"] = configured_by
403
405
  dfExport["RunId"] = dfExport["RunId"].astype("int")
404
406
 
405
407
  dfExport = dfExport[list(icons.bpa_schema.keys())]
@@ -119,16 +119,16 @@ def run_model_bpa_bulk(
119
119
  dfD_filt = dfD[~dfD["Dataset Name"].isin(skip_models)]
120
120
 
121
121
  if len(dfD_filt) > 0:
122
- for i2, r2 in dfD_filt.iterrows():
122
+ for _, r2 in dfD_filt.iterrows():
123
+ dataset_id = r2["Dataset Id"]
123
124
  dataset_name = r2["Dataset Name"]
124
125
  config_by = r2["Configured By"]
125
- dataset_id = r2["Dataset Id"]
126
126
  print(
127
127
  f"{icons.in_progress} Collecting Model BPA stats for the '{dataset_name}' semantic model within the '{wksp}' workspace."
128
128
  )
129
129
  try:
130
130
  bpa_df = run_model_bpa(
131
- dataset=dataset_name,
131
+ dataset=dataset_id,
132
132
  workspace=wksp,
133
133
  language=language,
134
134
  return_dataframe=True,
@@ -1,25 +1,30 @@
1
1
  import sempy.fabric as fabric
2
2
  import pandas as pd
3
- from sempy_labs._helper_functions import format_dax_object_name
3
+ from sempy_labs._helper_functions import (
4
+ format_dax_object_name,
5
+ resolve_dataset_name_and_id,
6
+ resolve_workspace_name_and_id,
7
+ )
4
8
  import sempy_labs._icons as icons
5
9
  from typing import Any, Dict, Optional
6
10
  from anytree import Node, RenderTree
7
11
  from sempy._utils._log import log
12
+ from uuid import UUID
8
13
 
9
14
 
10
15
  @log
11
16
  def get_measure_dependencies(
12
- dataset: str, workspace: Optional[str] = None
17
+ dataset: str | UUID, workspace: Optional[str | UUID] = None
13
18
  ) -> pd.DataFrame:
14
19
  """
15
20
  Shows all dependencies for all measures in a semantic model.
16
21
 
17
22
  Parameters
18
23
  ----------
19
- dataset : str
20
- Name of the semantic model.
21
- workspace : str, default=None
22
- The Fabric workspace name.
24
+ dataset : str | uuid.UUID
25
+ Name or ID of the semantic model.
26
+ workspace : str | uuid.UUID, default=None
27
+ The Fabric workspace name or ID.
23
28
  Defaults to None which resolves to the workspace of the attached lakehouse
24
29
  or if no lakehouse attached, resolves to the workspace of the notebook.
25
30
 
@@ -29,8 +34,6 @@ def get_measure_dependencies(
29
34
  Shows all dependencies for all measures in the semantic model.
30
35
  """
31
36
 
32
- workspace = fabric.resolve_workspace_name(workspace)
33
-
34
37
  dep = fabric.evaluate_dax(
35
38
  dataset=dataset,
36
39
  workspace=workspace,
@@ -139,17 +142,18 @@ def get_measure_dependencies(
139
142
 
140
143
  @log
141
144
  def get_model_calc_dependencies(
142
- dataset: str, workspace: Optional[str] = None
145
+ dataset: str | UUID,
146
+ workspace: Optional[str] = None,
143
147
  ) -> pd.DataFrame:
144
148
  """
145
149
  Shows all dependencies for all objects in a semantic model.
146
150
 
147
151
  Parameters
148
152
  ----------
149
- dataset : str
150
- Name of the semantic model.
151
- workspace : str, default=None
152
- The Fabric workspace name.
153
+ dataset : str | uuid.UUID
154
+ Name or ID of the semantic model.
155
+ workspace : str | uuid.UUID, default=None
156
+ The Fabric workspace name or ID.
153
157
  Defaults to None which resolves to the workspace of the attached lakehouse
154
158
  or if no lakehouse attached, resolves to the workspace of the notebook.
155
159
 
@@ -159,7 +163,6 @@ def get_model_calc_dependencies(
159
163
  Shows all dependencies for all objects in the semantic model.
160
164
  """
161
165
 
162
- workspace = fabric.resolve_workspace_name(workspace)
163
166
  dep = fabric.evaluate_dax(
164
167
  dataset=dataset,
165
168
  workspace=workspace,
@@ -187,12 +190,24 @@ def get_model_calc_dependencies(
187
190
  dep["Referenced Table"], dep["Referenced Object"]
188
191
  )
189
192
  dep["Parent Node"] = dep["Object Name"]
193
+
190
194
  # Initialize dependency DataFrame with 'Done' status
191
195
  df = dep.copy()
192
196
  objs = {"Measure", "Calc Column", "Calculation Item", "Calc Table"}
193
197
  df["Done"] = (
194
198
  df["Referenced Object Type"].apply(lambda x: x not in objs).astype(bool)
195
199
  )
200
+
201
+ # Set to track visited dependencies to prevent circular references
202
+ visited = set(
203
+ zip(
204
+ df["Full Object Name"],
205
+ df["Referenced Full Object Name"],
206
+ df["Object Type"],
207
+ df["Referenced Object Type"],
208
+ )
209
+ )
210
+
196
211
  # Expand dependencies iteratively
197
212
  while not df["Done"].all():
198
213
  incomplete_rows = df[df["Done"] == False]
@@ -206,11 +221,24 @@ def get_model_calc_dependencies(
206
221
  # Expand dependencies and update 'Done' status as needed
207
222
  new_rows = []
208
223
  for _, dependency in dep_filt.iterrows():
224
+ # Check if the dependency has already been visited
225
+ dependency_pair = (
226
+ row["Full Object Name"],
227
+ dependency["Referenced Full Object Name"],
228
+ row["Object Type"],
229
+ dependency["Referenced Object Type"],
230
+ )
231
+ if dependency_pair in visited:
232
+ continue # Skip already visited dependencies
233
+
234
+ visited.add(dependency_pair) # Mark as visited
235
+
209
236
  is_done = dependency["Referenced Object Type"] not in objs
210
237
  new_row = {
211
238
  "Table Name": row["Table Name"],
212
239
  "Object Name": row["Object Name"],
213
240
  "Object Type": row["Object Type"],
241
+ "Expression": row["Expression"],
214
242
  "Referenced Table": dependency["Referenced Table"],
215
243
  "Referenced Object": dependency["Referenced Object"],
216
244
  "Referenced Object Type": dependency["Referenced Object Type"],
@@ -222,7 +250,14 @@ def get_model_calc_dependencies(
222
250
  "Parent Node": row["Referenced Object"],
223
251
  }
224
252
  new_rows.append(new_row)
225
- df = pd.concat([df, pd.DataFrame(new_rows)], ignore_index=True)
253
+
254
+ if new_rows:
255
+ new_rows_df = pd.DataFrame(new_rows)
256
+ new_rows_df = new_rows_df.dropna(
257
+ axis=1, how="all"
258
+ ) # Drop empty columns
259
+ df = pd.concat([df, new_rows_df], ignore_index=True)
260
+
226
261
  df.loc[df.index == row.name, "Done"] = True
227
262
  # Finalize DataFrame and yield result
228
263
  df = df.drop(columns=["Done"])
@@ -232,39 +267,36 @@ def get_model_calc_dependencies(
232
267
 
233
268
  @log
234
269
  def measure_dependency_tree(
235
- dataset: str, measure_name: str, workspace: Optional[str] = None
270
+ dataset: str | UUID, measure_name: str, workspace: Optional[str | UUID] = None
236
271
  ):
237
272
  """
238
273
  Prints a measure dependency tree of all dependent objects for a measure in a semantic model.
239
274
 
240
275
  Parameters
241
276
  ----------
242
- dataset : str
243
- Name of the semantic model.
277
+ dataset : str | uuid.UUID
278
+ Name or ID of the semantic model.
244
279
  measure_name : str
245
280
  Name of the measure.
246
- workspace : str, default=None
247
- The Fabric workspace name.
281
+ workspace : str | uuid.UUID, default=None
282
+ The Fabric workspace name or ID.
248
283
  Defaults to None which resolves to the workspace of the attached lakehouse
249
284
  or if no lakehouse attached, resolves to the workspace of the notebook.
250
-
251
- Returns
252
- -------
253
-
254
285
  """
255
286
 
256
- workspace = fabric.resolve_workspace_name(workspace)
287
+ (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
288
+ (dataset_name, dataset_id) = resolve_dataset_name_and_id(dataset, workspace_id)
257
289
 
258
- dfM = fabric.list_measures(dataset=dataset, workspace=workspace)
290
+ dfM = fabric.list_measures(dataset=dataset_id, workspace=workspace_id)
259
291
  dfM_filt = dfM[dfM["Measure Name"] == measure_name]
260
292
 
261
293
  if len(dfM_filt) == 0:
262
294
  print(
263
- f"{icons.red_dot} The '{measure_name}' measure does not exist in the '{dataset}' semantic model in the '{workspace}' workspace."
295
+ f"{icons.red_dot} The '{measure_name}' measure does not exist in the '{dataset_name}' semantic model in the '{workspace_name}' workspace."
264
296
  )
265
297
  return
266
298
 
267
- md = get_measure_dependencies(dataset, workspace)
299
+ md = get_measure_dependencies(dataset_id, workspace_id)
268
300
  df_filt = md[md["Object Name"] == measure_name]
269
301
 
270
302
  # Create a dictionary to hold references to nodes
sempy_labs/_notebooks.py CHANGED
@@ -10,10 +10,49 @@ from sempy_labs._helper_functions import (
10
10
  _decode_b64,
11
11
  )
12
12
  from sempy.fabric.exceptions import FabricHTTPException
13
+ import os
14
+ from uuid import UUID
15
+
16
+ _notebook_prefix = "notebook-content."
17
+
18
+
19
+ def _get_notebook_definition_base(
20
+ notebook_name: str, workspace: Optional[str | UUID] = None
21
+ ) -> pd.DataFrame:
22
+
23
+ (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
24
+ item_id = fabric.resolve_item_id(
25
+ item_name=notebook_name, type="Notebook", workspace=workspace_id
26
+ )
27
+ client = fabric.FabricRestClient()
28
+ response = client.post(
29
+ f"v1/workspaces/{workspace_id}/notebooks/{item_id}/getDefinition",
30
+ )
31
+
32
+ result = lro(client, response).json()
33
+
34
+ return pd.json_normalize(result["definition"]["parts"])
35
+
36
+
37
+ def _get_notebook_type(
38
+ notebook_name: str, workspace: Optional[str | UUID] = None
39
+ ) -> str:
40
+
41
+ df_items = _get_notebook_definition_base(
42
+ notebook_name=notebook_name, workspace=workspace
43
+ )
44
+
45
+ file_path = df_items[df_items["path"].str.startswith(_notebook_prefix)][
46
+ "path"
47
+ ].iloc[0]
48
+
49
+ _, file_extension = os.path.splitext(file_path)
50
+
51
+ return file_extension[1:]
13
52
 
14
53
 
15
54
  def get_notebook_definition(
16
- notebook_name: str, workspace: Optional[str] = None, decode: bool = True
55
+ notebook_name: str, workspace: Optional[str | UUID] = None, decode: bool = True
17
56
  ) -> str:
18
57
  """
19
58
  Obtains the notebook definition.
@@ -24,8 +63,8 @@ def get_notebook_definition(
24
63
  ----------
25
64
  notebook_name : str
26
65
  The name of the notebook.
27
- workspace : str, default=None
28
- The name of the workspace.
66
+ workspace : str | uuid.UUID, default=None
67
+ The name or ID of the workspace.
29
68
  Defaults to None which resolves to the workspace of the attached lakehouse
30
69
  or if no lakehouse attached, resolves to the workspace of the notebook.
31
70
  decode : bool, default=True
@@ -38,18 +77,10 @@ def get_notebook_definition(
38
77
  The notebook definition.
39
78
  """
40
79
 
41
- (workspace, workspace_id) = resolve_workspace_name_and_id(workspace)
42
- item_id = fabric.resolve_item_id(
43
- item_name=notebook_name, type="Notebook", workspace=workspace
44
- )
45
- client = fabric.FabricRestClient()
46
- response = client.post(
47
- f"v1/workspaces/{workspace_id}/notebooks/{item_id}/getDefinition",
80
+ df_items = _get_notebook_definition_base(
81
+ notebook_name=notebook_name, workspace=workspace
48
82
  )
49
-
50
- result = lro(client, response).json()
51
- df_items = pd.json_normalize(result["definition"]["parts"])
52
- df_items_filt = df_items[df_items["path"] == "notebook-content.py"]
83
+ df_items_filt = df_items[df_items["path"].str.startswith(_notebook_prefix)]
53
84
  payload = df_items_filt["payload"].iloc[0]
54
85
 
55
86
  if decode:
@@ -64,7 +95,7 @@ def import_notebook_from_web(
64
95
  notebook_name: str,
65
96
  url: str,
66
97
  description: Optional[str] = None,
67
- workspace: Optional[str] = None,
98
+ workspace: Optional[str | UUID] = None,
68
99
  overwrite: bool = False,
69
100
  ):
70
101
  """
@@ -82,16 +113,15 @@ def import_notebook_from_web(
82
113
  description : str, default=None
83
114
  The description of the notebook.
84
115
  Defaults to None which does not place a description.
85
- workspace : str, default=None
86
- The name of the workspace.
116
+ workspace : str | uuid.UUID, default=None
117
+ The name or ID of the workspace.
87
118
  Defaults to None which resolves to the workspace of the attached lakehouse
88
119
  or if no lakehouse attached, resolves to the workspace of the notebook.
89
120
  overwrite : bool, default=False
90
121
  If set to True, overwrites the existing notebook in the workspace if it exists.
91
122
  """
92
123
 
93
- if workspace is None:
94
- workspace = fabric.resolve_workspace_name(workspace)
124
+ (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
95
125
 
96
126
  # Fix links to go to the raw github file
97
127
  starting_text = "https://github.com/"
@@ -111,24 +141,26 @@ def import_notebook_from_web(
111
141
  create_notebook(
112
142
  name=notebook_name,
113
143
  notebook_content=response.content,
114
- workspace=workspace,
144
+ workspace=workspace_id,
115
145
  description=description,
116
146
  )
117
147
  elif len(dfI_filt) > 0 and overwrite:
118
- update_notebook_definition(
119
- name=notebook_name, notebook_content=response.content, workspace=workspace
120
- )
148
+ print(f"{icons.info} Overwrite of notebooks is currently not supported.")
149
+ # update_notebook_definition(
150
+ # name=notebook_name, notebook_content=response.content, workspace=workspace
151
+ # )
121
152
  else:
122
153
  raise ValueError(
123
- f"{icons.red_dot} The '{notebook_name}' already exists within the '{workspace}' workspace and 'overwrite' is set to False."
154
+ f"{icons.red_dot} The '{notebook_name}' already exists within the '{workspace_name}' workspace and 'overwrite' is set to False."
124
155
  )
125
156
 
126
157
 
127
158
  def create_notebook(
128
159
  name: str,
129
160
  notebook_content: str,
161
+ type: str = "py",
130
162
  description: Optional[str] = None,
131
- workspace: Optional[str] = None,
163
+ workspace: Optional[str | UUID] = None,
132
164
  ):
133
165
  """
134
166
  Creates a new notebook with a definition within a workspace.
@@ -139,16 +171,18 @@ def create_notebook(
139
171
  The name of the notebook to be created.
140
172
  notebook_content : str
141
173
  The Jupyter notebook content (not in Base64 format).
174
+ type : str, default="py"
175
+ The notebook type.
142
176
  description : str, default=None
143
177
  The description of the notebook.
144
178
  Defaults to None which does not place a description.
145
- workspace : str, default=None
146
- The name of the workspace.
179
+ workspace : str | uuid.UUID, default=None
180
+ The name or ID of the workspace.
147
181
  Defaults to None which resolves to the workspace of the attached lakehouse
148
182
  or if no lakehouse attached, resolves to the workspace of the notebook.
149
183
  """
150
184
 
151
- (workspace, workspace_id) = resolve_workspace_name_and_id(workspace)
185
+ (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
152
186
  client = fabric.FabricRestClient()
153
187
  notebook_payload = base64.b64encode(notebook_content)
154
188
 
@@ -158,7 +192,7 @@ def create_notebook(
158
192
  "format": "ipynb",
159
193
  "parts": [
160
194
  {
161
- "path": "notebook-content.py",
195
+ "path": f"{_notebook_prefix}.{type}",
162
196
  "payload": notebook_payload,
163
197
  "payloadType": "InlineBase64",
164
198
  }
@@ -173,12 +207,12 @@ def create_notebook(
173
207
  lro(client, response, status_codes=[201, 202])
174
208
 
175
209
  print(
176
- f"{icons.green_dot} The '{name}' notebook was created within the '{workspace}' workspace."
210
+ f"{icons.green_dot} The '{name}' notebook was created within the '{workspace_name}' workspace."
177
211
  )
178
212
 
179
213
 
180
214
  def update_notebook_definition(
181
- name: str, notebook_content: str, workspace: Optional[str] = None
215
+ name: str, notebook_content: str, workspace: Optional[str | UUID] = None
182
216
  ):
183
217
  """
184
218
  Updates an existing notebook with a new definition.
@@ -189,26 +223,26 @@ def update_notebook_definition(
189
223
  The name of the notebook to be updated.
190
224
  notebook_content : str
191
225
  The Jupyter notebook content (not in Base64 format).
192
- workspace : str, default=None
193
- The name of the workspace.
226
+ workspace : str | uuid.UUID, default=None
227
+ The name or ID of the workspace.
194
228
  Defaults to None which resolves to the workspace of the attached lakehouse
195
229
  or if no lakehouse attached, resolves to the workspace of the notebook.
196
230
  """
197
231
 
198
- (workspace, workspace_id) = resolve_workspace_name_and_id(workspace)
232
+ (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
199
233
  client = fabric.FabricRestClient()
200
234
  notebook_payload = base64.b64encode(notebook_content)
201
235
  notebook_id = fabric.resolve_item_id(
202
- item_name=name, type="Notebook", workspace=workspace
236
+ item_name=name, type="Notebook", workspace=workspace_id
203
237
  )
204
238
 
239
+ type = _get_notebook_type(notebook_name=name, workspace=workspace_id)
240
+
205
241
  request_body = {
206
- "displayName": name,
207
242
  "definition": {
208
- "format": "ipynb",
209
243
  "parts": [
210
244
  {
211
- "path": "notebook-content.py",
245
+ "path": f"{_notebook_prefix}.{type}",
212
246
  "payload": notebook_payload,
213
247
  "payloadType": "InlineBase64",
214
248
  }
@@ -224,5 +258,5 @@ def update_notebook_definition(
224
258
  lro(client, response, return_status_code=True)
225
259
 
226
260
  print(
227
- f"{icons.green_dot} The '{name}' notebook was updated within the '{workspace}' workspace."
261
+ f"{icons.green_dot} The '{name}' notebook was updated within the '{workspace_name}' workspace."
228
262
  )