semantic-link-labs 0.7.2__py3-none-any.whl → 0.7.4__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 (82) hide show
  1. {semantic_link_labs-0.7.2.dist-info → semantic_link_labs-0.7.4.dist-info}/METADATA +15 -3
  2. semantic_link_labs-0.7.4.dist-info/RECORD +134 -0
  3. {semantic_link_labs-0.7.2.dist-info → semantic_link_labs-0.7.4.dist-info}/WHEEL +1 -1
  4. sempy_labs/__init__.py +120 -24
  5. sempy_labs/_bpa_translation/{_translations_am-ET.po → _model/_translations_am-ET.po} +22 -0
  6. sempy_labs/_bpa_translation/{_translations_ar-AE.po → _model/_translations_ar-AE.po} +24 -0
  7. sempy_labs/_bpa_translation/_model/_translations_bg-BG.po +938 -0
  8. sempy_labs/_bpa_translation/_model/_translations_ca-ES.po +934 -0
  9. sempy_labs/_bpa_translation/{_translations_cs-CZ.po → _model/_translations_cs-CZ.po} +179 -157
  10. sempy_labs/_bpa_translation/{_translations_da-DK.po → _model/_translations_da-DK.po} +24 -0
  11. sempy_labs/_bpa_translation/{_translations_de-DE.po → _model/_translations_de-DE.po} +77 -52
  12. sempy_labs/_bpa_translation/{_translations_el-GR.po → _model/_translations_el-GR.po} +25 -0
  13. sempy_labs/_bpa_translation/{_translations_es-ES.po → _model/_translations_es-ES.po} +67 -43
  14. sempy_labs/_bpa_translation/{_translations_fa-IR.po → _model/_translations_fa-IR.po} +24 -0
  15. sempy_labs/_bpa_translation/_model/_translations_fi-FI.po +915 -0
  16. sempy_labs/_bpa_translation/{_translations_fr-FR.po → _model/_translations_fr-FR.po} +83 -57
  17. sempy_labs/_bpa_translation/{_translations_ga-IE.po → _model/_translations_ga-IE.po} +25 -0
  18. sempy_labs/_bpa_translation/{_translations_he-IL.po → _model/_translations_he-IL.po} +23 -0
  19. sempy_labs/_bpa_translation/{_translations_hi-IN.po → _model/_translations_hi-IN.po} +24 -0
  20. sempy_labs/_bpa_translation/{_translations_hu-HU.po → _model/_translations_hu-HU.po} +25 -0
  21. sempy_labs/_bpa_translation/_model/_translations_id-ID.po +918 -0
  22. sempy_labs/_bpa_translation/{_translations_is-IS.po → _model/_translations_is-IS.po} +25 -0
  23. sempy_labs/_bpa_translation/{_translations_it-IT.po → _model/_translations_it-IT.po} +25 -0
  24. sempy_labs/_bpa_translation/{_translations_ja-JP.po → _model/_translations_ja-JP.po} +21 -0
  25. sempy_labs/_bpa_translation/_model/_translations_ko-KR.po +823 -0
  26. sempy_labs/_bpa_translation/_model/_translations_mt-MT.po +937 -0
  27. sempy_labs/_bpa_translation/{_translations_nl-NL.po → _model/_translations_nl-NL.po} +80 -56
  28. sempy_labs/_bpa_translation/{_translations_pl-PL.po → _model/_translations_pl-PL.po} +101 -76
  29. sempy_labs/_bpa_translation/{_translations_pt-BR.po → _model/_translations_pt-BR.po} +25 -0
  30. sempy_labs/_bpa_translation/{_translations_pt-PT.po → _model/_translations_pt-PT.po} +25 -0
  31. sempy_labs/_bpa_translation/_model/_translations_ro-RO.po +939 -0
  32. sempy_labs/_bpa_translation/{_translations_ru-RU.po → _model/_translations_ru-RU.po} +25 -0
  33. sempy_labs/_bpa_translation/_model/_translations_sk-SK.po +925 -0
  34. sempy_labs/_bpa_translation/_model/_translations_sl-SL.po +922 -0
  35. sempy_labs/_bpa_translation/_model/_translations_sv-SE.po +914 -0
  36. sempy_labs/_bpa_translation/{_translations_ta-IN.po → _model/_translations_ta-IN.po} +26 -0
  37. sempy_labs/_bpa_translation/{_translations_te-IN.po → _model/_translations_te-IN.po} +24 -0
  38. sempy_labs/_bpa_translation/{_translations_th-TH.po → _model/_translations_th-TH.po} +24 -0
  39. sempy_labs/_bpa_translation/_model/_translations_tr-TR.po +925 -0
  40. sempy_labs/_bpa_translation/_model/_translations_uk-UA.po +933 -0
  41. sempy_labs/_bpa_translation/{_translations_zh-CN.po → _model/_translations_zh-CN.po} +116 -97
  42. sempy_labs/_bpa_translation/{_translations_zu-ZA.po → _model/_translations_zu-ZA.po} +25 -0
  43. sempy_labs/_capacities.py +541 -0
  44. sempy_labs/_clear_cache.py +298 -3
  45. sempy_labs/_connections.py +138 -0
  46. sempy_labs/_dataflows.py +130 -0
  47. sempy_labs/_deployment_pipelines.py +171 -0
  48. sempy_labs/_environments.py +156 -0
  49. sempy_labs/_generate_semantic_model.py +148 -27
  50. sempy_labs/_git.py +380 -0
  51. sempy_labs/_helper_functions.py +203 -8
  52. sempy_labs/_icons.py +43 -0
  53. sempy_labs/_list_functions.py +170 -1012
  54. sempy_labs/_model_bpa.py +90 -112
  55. sempy_labs/_model_bpa_bulk.py +3 -1
  56. sempy_labs/_model_bpa_rules.py +788 -800
  57. sempy_labs/_notebooks.py +143 -0
  58. sempy_labs/_query_scale_out.py +28 -7
  59. sempy_labs/_spark.py +465 -0
  60. sempy_labs/_sql.py +120 -0
  61. sempy_labs/_translations.py +3 -1
  62. sempy_labs/_vertipaq.py +160 -99
  63. sempy_labs/_workspace_identity.py +66 -0
  64. sempy_labs/_workspaces.py +294 -0
  65. sempy_labs/directlake/__init__.py +2 -0
  66. sempy_labs/directlake/_directlake_schema_compare.py +1 -2
  67. sempy_labs/directlake/_directlake_schema_sync.py +1 -2
  68. sempy_labs/directlake/_dl_helper.py +4 -7
  69. sempy_labs/directlake/_generate_shared_expression.py +85 -0
  70. sempy_labs/directlake/_show_unsupported_directlake_objects.py +1 -2
  71. sempy_labs/lakehouse/_get_lakehouse_tables.py +7 -3
  72. sempy_labs/migration/_migrate_calctables_to_lakehouse.py +5 -0
  73. sempy_labs/migration/_migrate_calctables_to_semantic_model.py +5 -0
  74. sempy_labs/migration/_migrate_model_objects_to_semantic_model.py +6 -2
  75. sempy_labs/migration/_migrate_tables_columns_to_semantic_model.py +6 -5
  76. sempy_labs/migration/_migration_validation.py +6 -0
  77. sempy_labs/report/_report_functions.py +21 -42
  78. sempy_labs/report/_report_rebind.py +5 -0
  79. sempy_labs/tom/_model.py +95 -52
  80. semantic_link_labs-0.7.2.dist-info/RECORD +0 -111
  81. {semantic_link_labs-0.7.2.dist-info → semantic_link_labs-0.7.4.dist-info}/LICENSE +0 -0
  82. {semantic_link_labs-0.7.2.dist-info → semantic_link_labs-0.7.4.dist-info}/top_level.txt +0 -0
sempy_labs/_git.py ADDED
@@ -0,0 +1,380 @@
1
+ import sempy.fabric as fabric
2
+ import pandas as pd
3
+ import sempy_labs._icons as icons
4
+ from typing import Optional, List
5
+ from sempy_labs._helper_functions import (
6
+ resolve_workspace_name_and_id,
7
+ lro,
8
+ )
9
+ from sempy.fabric.exceptions import FabricHTTPException
10
+
11
+
12
+ def connect_workspace_to_git(
13
+ organization_name: str,
14
+ project_name: str,
15
+ repository_name: str,
16
+ branch_name: str,
17
+ directory_name: str,
18
+ git_provider_type: str = "AzureDevOps",
19
+ workspace: Optional[str] = None,
20
+ ):
21
+ """
22
+ Connects a workspace to a git repository.
23
+
24
+ Parameters
25
+ ----------
26
+ organization_name : str
27
+ The organization name.
28
+ project_name : str
29
+ The project name.
30
+ repository_name : str
31
+ The repository name.
32
+ branch_name : str
33
+ The branch name.
34
+ directory_name : str
35
+ The directory name.
36
+ git_provider_type : str, default="AzureDevOps"
37
+ A `Git provider type <https://learn.microsoft.com/rest/api/fabric/core/git/connect?tabs=HTTP#gitprovidertype>`_.
38
+ workspace : str, default=None
39
+ The Fabric workspace name.
40
+ Defaults to None which resolves to the workspace of the attached lakehouse
41
+ or if no lakehouse attached, resolves to the workspace of the notebook.
42
+ """
43
+
44
+ # https://learn.microsoft.com/en-us/rest/api/fabric/core/git/connect?tabs=HTTP
45
+
46
+ workspace, workspace_id = resolve_workspace_name_and_id(workspace)
47
+
48
+ request_body = {
49
+ "gitProviderDetails": {
50
+ "organizationName": organization_name,
51
+ "projectName": project_name,
52
+ "gitProviderType": git_provider_type,
53
+ "repositoryName": repository_name,
54
+ "branchName": branch_name,
55
+ "directoryName": directory_name,
56
+ }
57
+ }
58
+
59
+ client = fabric.FabricRestClient()
60
+ response = client.post(
61
+ f"/v1/workspaces/{workspace_id}/git/connect", json=request_body
62
+ )
63
+ if response.status_code != 200:
64
+ raise FabricHTTPException(response)
65
+
66
+ print(
67
+ f"{icons.green_dot} The '{workspace}' workspace has been connected to the '{project_name}' Git project within the '{repository_name}' repository."
68
+ )
69
+
70
+
71
+ def disconnect_workspace_from_git(workspace: Optional[str] = None):
72
+ """
73
+ Disconnects a workpsace from a git repository.
74
+
75
+ Parameters
76
+ ----------
77
+ workspace : str, default=None
78
+ The Fabric workspace name.
79
+ Defaults to None which resolves to the workspace of the attached lakehouse
80
+ or if no lakehouse attached, resolves to the workspace of the notebook.
81
+ """
82
+
83
+ # https://learn.microsoft.com/en-us/rest/api/fabric/core/git/disconnect?tabs=HTTP
84
+
85
+ workspace, workspace_id = resolve_workspace_name_and_id(workspace)
86
+
87
+ client = fabric.FabricRestClient()
88
+ response = client.post(f"/v1/workspaces/{workspace_id}/git/disconnect")
89
+ if response.status_code != 200:
90
+ raise FabricHTTPException(response)
91
+
92
+ print(
93
+ f"{icons.green_dot} The '{workspace}' workspace has been disconnected from Git."
94
+ )
95
+
96
+
97
+ def get_git_status(workspace: Optional[str] = None) -> pd.DataFrame:
98
+ """
99
+ Obtains the Git status of items in the workspace, that can be committed to Git.
100
+
101
+ Parameters
102
+ ----------
103
+ workspace : str, default=None
104
+ The Fabric workspace name.
105
+ Defaults to None which resolves to the workspace of the attached lakehouse
106
+ or if no lakehouse attached, resolves to the workspace of the notebook.
107
+
108
+ Returns
109
+ -------
110
+ pandas.DataFrame
111
+ A pandas dataframe showing the Git status of items in the workspace.
112
+ """
113
+
114
+ # https://learn.microsoft.com/en-us/rest/api/fabric/core/git/get-status?tabs=HTTP
115
+
116
+ workspace, workspace_id = resolve_workspace_name_and_id(workspace)
117
+
118
+ df = pd.DataFrame(
119
+ columns=[
120
+ "Workspace Head",
121
+ "Remote Commit Hash",
122
+ "Object ID",
123
+ "Logical ID",
124
+ "Item Type",
125
+ "Item Name",
126
+ "Workspace Change",
127
+ "Remote Change",
128
+ "Conflict Type",
129
+ ]
130
+ )
131
+
132
+ client = fabric.FabricRestClient()
133
+ response = client.get(f"/v1/workspaces/{workspace_id}/git/status")
134
+
135
+ if response not in [200, 202]:
136
+ raise FabricHTTPException(response)
137
+
138
+ result = lro(client, response).json()
139
+
140
+ for v in result.get("value", []):
141
+ changes = v.get("changes", [])
142
+ item_metadata = changes.get("itemMetadata", {})
143
+ item_identifier = item_metadata.get("itemIdentifier", {})
144
+
145
+ new_data = {
146
+ "Workspace Head": v.get("workspaceHead"),
147
+ "Remote Commit Hash": v.get("remoteCommitHash"),
148
+ "Object ID": item_identifier.get("objectId"),
149
+ "Logical ID": item_identifier.get("logicalId"),
150
+ "Item Type": item_metadata.get("itemType"),
151
+ "Item Name": item_metadata.get("displayName"),
152
+ "Remote Change": changes.get("remoteChange"),
153
+ "Workspace Change": changes.get("workspaceChange"),
154
+ "Conflict Type": changes.get("conflictType"),
155
+ }
156
+ df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
157
+
158
+ return df
159
+
160
+
161
+ def get_git_connection(workspace: Optional[str] = None) -> pd.DataFrame:
162
+ """
163
+ Obtains the Git status of items in the workspace, that can be committed to Git.
164
+
165
+ Parameters
166
+ ----------
167
+ workspace : str, default=None
168
+ The Fabric workspace name.
169
+ Defaults to None which resolves to the workspace of the attached lakehouse
170
+ or if no lakehouse attached, resolves to the workspace of the notebook.
171
+
172
+ Returns
173
+ -------
174
+ pandas.DataFrame
175
+ A pandas dataframe showing the Git status of items in the workspace.
176
+ """
177
+
178
+ # https://learn.microsoft.com/en-us/rest/api/fabric/core/git/get-status?tabs=HTTP
179
+
180
+ workspace, workspace_id = resolve_workspace_name_and_id(workspace)
181
+
182
+ df = pd.DataFrame(
183
+ columns=[
184
+ "Organization Name",
185
+ "Project Name",
186
+ "Git Provider Type",
187
+ "Repository Name",
188
+ "Branch Name",
189
+ "Directory Name",
190
+ "Workspace Head",
191
+ "Last Sync Time",
192
+ "Git Connection State",
193
+ ]
194
+ )
195
+
196
+ client = fabric.FabricRestClient()
197
+ response = client.get(f"/v1/workspaces/{workspace_id}/git/connection")
198
+
199
+ if response.status_code != 200:
200
+ raise FabricHTTPException(response)
201
+
202
+ for v in response.json().get("value", []):
203
+ provider_details = v.get("gitProviderDetails", {})
204
+ sync_details = v.get("gitSyncDetails", {})
205
+ new_data = {
206
+ "Organization Name": provider_details.get("organizationName"),
207
+ "Project Name": provider_details.get("projectName"),
208
+ "Git Provider Type": provider_details.get("gitProviderType"),
209
+ "Repository Name": provider_details.get("repositoryName"),
210
+ "Branch Name": provider_details.get("branchName"),
211
+ "Directory Name": provider_details.get("directoryName"),
212
+ "Workspace Head": sync_details.get("head"),
213
+ "Last Sync Time": sync_details.get("lastSyncTime"),
214
+ "Git Conneciton State": v.get("gitConnectionState"),
215
+ }
216
+ df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
217
+
218
+ return df
219
+
220
+
221
+ def initialize_git_connection(workspace: Optional[str] = None):
222
+ """
223
+ Initializes a connection for a workspace that is connected to Git.
224
+
225
+ Parameters
226
+ ----------
227
+ workspace : str, default=None
228
+ The Fabric workspace name.
229
+ Defaults to None which resolves to the workspace of the attached lakehouse
230
+ or if no lakehouse attached, resolves to the workspace of the notebook.
231
+ """
232
+
233
+ # https://learn.microsoft.com/en-us/rest/api/fabric/core/git/initialize-connection?tabs=HTTP
234
+
235
+ workspace, workspace_id = resolve_workspace_name_and_id(workspace)
236
+
237
+ client = fabric.FabricRestClient()
238
+ response = client.post(f"/v1/workspaces/{workspace_id}/git/initializeConnection")
239
+
240
+ if response not in [200, 202]:
241
+ raise FabricHTTPException(response)
242
+
243
+ lro(client, response)
244
+
245
+ print(
246
+ f"{icons.green_dot} The '{workspace}' workspace git connection has been initialized."
247
+ )
248
+
249
+
250
+ def commit_to_git(
251
+ comment: str, item_ids: str | List[str] = None, workspace: Optional[str] = None
252
+ ):
253
+ """
254
+ Commits all or a selection of items within a workspace to Git.
255
+
256
+ Parameters
257
+ ----------
258
+ comment : str
259
+ The Git commit comment.
260
+ item_ids : str | List[str], default=None
261
+ A list of item Ids to commit to Git.
262
+ Defaults to None which commits all items to Git.
263
+ workspace : str, default=None
264
+ The Fabric workspace name.
265
+ Defaults to None which resolves to the workspace of the attached lakehouse
266
+ or if no lakehouse attached, resolves to the workspace of the notebook.
267
+ """
268
+
269
+ # https://learn.microsoft.com/en-us/rest/api/fabric/core/git/commit-to-git?tabs=HTTP
270
+
271
+ workspace, workspace_id = resolve_workspace_name_and_id(workspace)
272
+
273
+ gs = get_git_status(workspace=workspace)
274
+ workspace_head = gs["Workspace Head"].iloc[0]
275
+
276
+ if item_ids is None:
277
+ commit_mode = "All"
278
+ else:
279
+ commit_mode = "Selective"
280
+
281
+ if isinstance(item_ids, str):
282
+ item_ids = [item_ids]
283
+
284
+ request_body = {
285
+ "mode": commit_mode,
286
+ "workspaceHead": workspace_head,
287
+ "comment": comment,
288
+ }
289
+
290
+ if item_ids is not None:
291
+ request_body["items"] = [{"objectId": item_id} for item_id in item_ids]
292
+
293
+ client = fabric.FabricRestClient()
294
+ response = client.post(
295
+ f"/v1/workspaces/{workspace_id}/git/commitToGit",
296
+ json=request_body,
297
+ )
298
+
299
+ if response.status_code not in [200, 202]:
300
+ raise FabricHTTPException(response)
301
+
302
+ lro(client, response)
303
+
304
+ if commit_mode == "All":
305
+ print(
306
+ f"{icons.green_dot} All items within the '{workspace}' workspace have been committed to Git."
307
+ )
308
+ else:
309
+ print(
310
+ f"{icons.green_dot} The {item_ids} items ithin the '{workspace}' workspace have been committed to Git."
311
+ )
312
+
313
+
314
+ def update_from_git(
315
+ remote_commit_hash: str,
316
+ conflict_resolution_policy: str,
317
+ workspace_head: Optional[str] = None,
318
+ allow_override: Optional[bool] = False,
319
+ workspace: Optional[str] = None,
320
+ ):
321
+ """
322
+ Updates the workspace with commits pushed to the connected branch.
323
+
324
+ Parameters
325
+ ----------
326
+ workspace_head : str
327
+ Full SHA hash that the workspace is synced to. This value may be null only after Initialize Connection.
328
+ In other cases, the system will validate that the given value is aligned with the head known to the system.
329
+ remove_commit_hash : str
330
+ Remote full SHA commit hash.
331
+ confilict_resolution_policy : str
332
+ The `conflict resolution policy <https://learn.microsoft.com/rest/api/fabric/core/git/update-from-git?tabs=HTTP#conflictresolutionpolicy>`_.
333
+ allow_override : bool, default=False
334
+ workspace : str, default=None
335
+ The Fabric workspace name.
336
+ Defaults to None which resolves to the workspace of the attached lakehouse
337
+ or if no lakehouse attached, resolves to the workspace of the notebook.
338
+ """
339
+
340
+ # https://learn.microsoft.com/en-us/rest/api/fabric/core/git/update-from-git?tabs=HTTP
341
+
342
+ workspace, workspace_id = resolve_workspace_name_and_id(workspace)
343
+
344
+ conflict_resolution_policies = ["PreferWorkspace", "PreferRemote"]
345
+ if "remote" in conflict_resolution_policies.lower():
346
+ conflict_resolution_policies = "PreferRemote"
347
+ elif "workspace" in conflict_resolution_policies.lower():
348
+ conflict_resolution_policies = "PreferWorkspace"
349
+
350
+ if conflict_resolution_policy not in conflict_resolution_policies:
351
+ raise ValueError(
352
+ f"{icons.red_dot} Invalid conflict resolution policy. Valid options: {conflict_resolution_policies}."
353
+ )
354
+
355
+ request_body = {}
356
+ request_body["remoteCommitHash"] = remote_commit_hash
357
+ request_body["conflictResolution"] = {
358
+ "conflictResolutionType": "Workspace",
359
+ "conflictResolutionPolicy": conflict_resolution_policy,
360
+ }
361
+
362
+ if workspace_head is not None:
363
+ request_body["workspaceHead"] = workspace_head
364
+ if allow_override is not None:
365
+ request_body["options"] = {"allowOverrideItems": allow_override}
366
+
367
+ client = fabric.FabricRestClient()
368
+ response = client.post(
369
+ f"/v1/workspaces/{workspace_id}/git/updateFromGit",
370
+ json=request_body,
371
+ )
372
+
373
+ if response.status_code not in [200, 202]:
374
+ raise FabricHTTPException(response)
375
+
376
+ lro(client, response)
377
+
378
+ print(
379
+ f"{icons.green_dot} The '{workspace}' workspace has been updated with commits pushed to the connected branch."
380
+ )
@@ -6,12 +6,12 @@ import pandas as pd
6
6
  from functools import wraps
7
7
  import datetime
8
8
  import time
9
- from pyspark.sql import SparkSession
10
9
  from typing import Optional, Tuple, List
11
10
  from uuid import UUID
12
11
  import sempy_labs._icons as icons
13
12
  from sempy.fabric.exceptions import FabricHTTPException
14
13
  import urllib.parse
14
+ from azure.core.credentials import TokenCredential, AccessToken
15
15
 
16
16
 
17
17
  def create_abfss_path(
@@ -391,6 +391,7 @@ def save_as_delta_table(
391
391
  delta_table_name: str,
392
392
  write_mode: str,
393
393
  merge_schema: Optional[bool] = False,
394
+ schema: Optional[dict] = None,
394
395
  lakehouse: Optional[str] = None,
395
396
  workspace: Optional[str] = None,
396
397
  ):
@@ -407,6 +408,8 @@ def save_as_delta_table(
407
408
  The write mode for the save operation. Options: 'append', 'overwrite'.
408
409
  merge_schema : bool, default=False
409
410
  Merges the schemas of the dataframe to the delta table.
411
+ schema : dict, default=None
412
+ A dictionary showing the schema of the columns and their data types.
410
413
  lakehouse : str, default=None
411
414
  The Fabric lakehouse used by the Direct Lake semantic model.
412
415
  Defaults to None which resolves to the lakehouse attached to the notebook.
@@ -414,13 +417,22 @@ def save_as_delta_table(
414
417
  The Fabric workspace name.
415
418
  Defaults to None which resolves to the workspace of the attached lakehouse
416
419
  or if no lakehouse attached, resolves to the workspace of the notebook.
417
-
418
- Returns
419
- -------
420
- UUID
421
- The ID of the Power BI report.
422
420
  """
423
421
 
422
+ from pyspark.sql import SparkSession
423
+ from pyspark.sql.types import (
424
+ StringType,
425
+ IntegerType,
426
+ FloatType,
427
+ DateType,
428
+ StructType,
429
+ StructField,
430
+ BooleanType,
431
+ LongType,
432
+ DoubleType,
433
+ TimestampType,
434
+ )
435
+
424
436
  if workspace is None:
425
437
  workspace_id = fabric.get_workspace_id()
426
438
  workspace = fabric.resolve_workspace_name(workspace_id)
@@ -449,9 +461,32 @@ def save_as_delta_table(
449
461
  )
450
462
 
451
463
  dataframe.columns = dataframe.columns.str.replace(" ", "_")
452
-
453
464
  spark = SparkSession.builder.getOrCreate()
454
- spark_df = spark.createDataFrame(dataframe)
465
+
466
+ type_mapping = {
467
+ "string": StringType(),
468
+ "str": StringType(),
469
+ "integer": IntegerType(),
470
+ "int": IntegerType(),
471
+ "float": FloatType(),
472
+ "date": DateType(),
473
+ "bool": BooleanType(),
474
+ "boolean": BooleanType(),
475
+ "long": LongType(),
476
+ "double": DoubleType(),
477
+ "timestamp": TimestampType(),
478
+ }
479
+
480
+ if schema is None:
481
+ spark_df = spark.createDataFrame(dataframe)
482
+ else:
483
+ schema_map = StructType(
484
+ [
485
+ StructField(column_name, type_mapping[data_type], True)
486
+ for column_name, data_type in schema.items()
487
+ ]
488
+ )
489
+ spark_df = spark.createDataFrame(dataframe, schema_map)
455
490
 
456
491
  filePath = create_abfss_path(
457
492
  lakehouse_id=lakehouse_id,
@@ -780,6 +815,37 @@ def resolve_capacity_name(capacity_id: Optional[UUID] = None) -> str:
780
815
  return dfC_filt["Display Name"].iloc[0]
781
816
 
782
817
 
818
+ def resolve_capacity_id(capacity_name: Optional[str] = None) -> UUID:
819
+ """
820
+ Obtains the capacity Id for a given capacity name.
821
+
822
+ Parameters
823
+ ----------
824
+ capacity_name : str, default=None
825
+ The capacity name.
826
+ Defaults to None which resolves to the capacity id of the workspace of the attached lakehouse
827
+ or if no lakehouse attached, resolves to the capacity name of the workspace of the notebook.
828
+
829
+ Returns
830
+ -------
831
+ UUID
832
+ The capacity Id.
833
+ """
834
+
835
+ if capacity_name is None:
836
+ return get_capacity_id()
837
+
838
+ dfC = fabric.list_capacities()
839
+ dfC_filt = dfC[dfC["Display Name"] == capacity_name]
840
+
841
+ if len(dfC_filt) == 0:
842
+ raise ValueError(
843
+ f"{icons.red_dot} The '{capacity_name}' capacity does not exist."
844
+ )
845
+
846
+ return dfC_filt["Id"].iloc[0]
847
+
848
+
783
849
  def retry(sleep_time: int, timeout_error_message: str):
784
850
  def decorator(func):
785
851
  @wraps(func)
@@ -853,3 +919,132 @@ def pagination(client, response):
853
919
  continuation_uri = response_json.get("continuationUri")
854
920
 
855
921
  return responses
922
+
923
+
924
+ def resolve_deployment_pipeline_id(deployment_pipeline: str) -> UUID:
925
+
926
+ from sempy_labs._deployment_pipelines import list_deployment_pipelines
927
+
928
+ dfP = list_deployment_pipelines()
929
+ dfP_filt = dfP[dfP["Deployment Pipeline Name"] == deployment_pipeline]
930
+ if len(dfP_filt) == 0:
931
+ raise ValueError(
932
+ f"{icons.red_dot} The '{deployment_pipeline}' deployment pipeline is not valid."
933
+ )
934
+ deployment_pipeline_id = dfP_filt["Deployment Pipeline Id"].iloc[0]
935
+
936
+ return deployment_pipeline_id
937
+
938
+
939
+ class FabricTokenCredential(TokenCredential):
940
+
941
+ def get_token(
942
+ self,
943
+ scopes: str,
944
+ claims: Optional[str] = None,
945
+ tenant_id: Optional[str] = None,
946
+ enable_cae: Optional[bool] = False,
947
+ **kwargs: any,
948
+ ) -> AccessToken:
949
+
950
+ from notebookutils import mssparkutils
951
+
952
+ token = mssparkutils.credentials.getToken(scopes)
953
+ access_token = AccessToken(token, 0)
954
+
955
+ return access_token
956
+
957
+
958
+ def get_adls_client(account_name):
959
+
960
+ from azure.storage.filedatalake import DataLakeServiceClient
961
+
962
+ account_url = f"https://{account_name}.dfs.core.windows.net"
963
+
964
+ service_client = DataLakeServiceClient(
965
+ account_url, credential=FabricTokenCredential()
966
+ )
967
+
968
+ return service_client
969
+
970
+
971
+ def resolve_warehouse_id(warehouse: str, workspace: Optional[str]):
972
+
973
+ workspace = fabric.resolve_workspace_name(workspace)
974
+ warehouse_id = fabric.resolve_item_id(
975
+ item_name=warehouse, type="Warehouse", workspace=workspace
976
+ )
977
+
978
+ return warehouse_id
979
+
980
+
981
+ def get_language_codes(languages: str | List[str]):
982
+
983
+ if isinstance(languages, str):
984
+ languages = [languages]
985
+
986
+ for i, lang in enumerate(languages):
987
+ for k, v in icons.language_map.items():
988
+ if v == lang.capitalize():
989
+ languages[i] = k
990
+ break
991
+
992
+ return languages
993
+
994
+
995
+ def resolve_environment_id(environment: str, workspace: Optional[str] = None) -> UUID:
996
+ """
997
+ Obtains the environment Id for a given environment.
998
+
999
+ Parameters
1000
+ ----------
1001
+ environment: str
1002
+ Name of the environment.
1003
+ workspace : str, default=None
1004
+ The Fabric workspace name.
1005
+ Defaults to None which resolves to the workspace of the attached lakehouse
1006
+ or if no lakehouse attached, resolves to the workspace of the notebook.
1007
+ """
1008
+
1009
+ from sempy_labs._environments import list_environments
1010
+
1011
+ (workspace, workspace_id) = resolve_workspace_name_and_id(workspace)
1012
+
1013
+ dfE = list_environments(workspace=workspace)
1014
+ dfE_filt = dfE[dfE["Environment Name"] == environment]
1015
+ if len(dfE_filt) == 0:
1016
+ raise ValueError(
1017
+ f"{icons.red_dot} The '{environment}' environment does not exist within the '{workspace}' workspace."
1018
+ )
1019
+
1020
+ return dfE_filt["Environment Id"].iloc[0]
1021
+
1022
+
1023
+ def get_azure_token_credentials(
1024
+ key_vault_uri: str,
1025
+ key_vault_tenant_id: str,
1026
+ key_vault_client_id: str,
1027
+ key_vault_client_secret: str,
1028
+ ) -> Tuple[str, str, dict]:
1029
+
1030
+ from notebookutils import mssparkutils
1031
+ from azure.identity import ClientSecretCredential
1032
+
1033
+ tenant_id = mssparkutils.credentials.getSecret(key_vault_uri, key_vault_tenant_id)
1034
+ client_id = mssparkutils.credentials.getSecret(key_vault_uri, key_vault_client_id)
1035
+ client_secret = mssparkutils.credentials.getSecret(
1036
+ key_vault_uri, key_vault_client_secret
1037
+ )
1038
+
1039
+ credential = ClientSecretCredential(
1040
+ tenant_id=tenant_id, client_id=client_id, client_secret=client_secret
1041
+ )
1042
+
1043
+ token = credential.get_token("https://management.azure.com/.default").token
1044
+
1045
+ headers = {
1046
+ "Authorization": f"Bearer {token}",
1047
+ "Content-Type": "application/json",
1048
+ }
1049
+
1050
+ return token, credential, headers
sempy_labs/_icons.py CHANGED
@@ -31,3 +31,46 @@ model_bpa_name = "ModelBPA"
31
31
  report_bpa_name = "ReportBPA"
32
32
  severity_mapping = {warning: "Warning", error: "Error", info: "Info"}
33
33
  special_characters = ['"', "/", '"', ":", "|", "<", ">", "*", "?", "'", "!"]
34
+
35
+ language_map = {
36
+ "it-IT": "Italian",
37
+ "es-ES": "Spanish",
38
+ "he-IL": "Hebrew",
39
+ "pt-PT": "Portuguese",
40
+ "zh-CN": "Chinese",
41
+ "fr-FR": "French",
42
+ "da-DK": "Danish",
43
+ "cs-CZ": "Czech",
44
+ "de-DE": "German",
45
+ "el-GR": "Greek",
46
+ "fa-IR": "Persian",
47
+ "ga-IE": "Irish",
48
+ "hi-IN": "Hindi",
49
+ "hu-HU": "Hungarian",
50
+ "is-IS": "Icelandic",
51
+ "ja-JP": "Japanese",
52
+ "nl-NL": "Dutch",
53
+ "pl-PL": "Polish",
54
+ "pt-BR": "Portuguese",
55
+ "ru-RU": "Russian",
56
+ "te-IN": "Telugu",
57
+ "ta-IN": "Tamil",
58
+ "th-TH": "Thai",
59
+ "zu-ZA": "Zulu",
60
+ "am-ET": "Amharic",
61
+ "ar-AE": "Arabic",
62
+ "sv-SE": "Swedish",
63
+ "ko-KR": "Korean",
64
+ "id-ID": "Indonesian",
65
+ "mt-MT": "Maltese",
66
+ "ro-RO": "Romanian",
67
+ "sk-SK": "Slovak",
68
+ "sl-SL": "Slovenian",
69
+ "tr-TR": "Turkish",
70
+ "uk-UA": "Ukrainian",
71
+ "bg-BG": "Bulgarian",
72
+ "ca-ES": "Catalan",
73
+ "fi-FI": "Finnish",
74
+ }
75
+ workspace_roles = ["Admin", "Member", "Viewer", "Contributor"]
76
+ principal_types = ["App", "Group", "None", "User"]