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
@@ -0,0 +1,541 @@
1
+ import sempy.fabric as fabric
2
+ from typing import Optional, List
3
+ from sempy._utils._log import log
4
+ import sempy_labs._icons as icons
5
+ from sempy.fabric.exceptions import FabricHTTPException
6
+ import requests
7
+ from sempy_labs._helper_functions import get_azure_token_credentials
8
+
9
+
10
+ def _add_sll_tag(payload, tags):
11
+
12
+ if tags is None:
13
+ payload["tags"] = {"SLL": 1}
14
+ else:
15
+ if "tags" not in payload:
16
+ payload["tags"] = tags
17
+ payload["tags"]["SLL"] = 1
18
+
19
+ return payload
20
+
21
+
22
+ @log
23
+ def create_fabric_capacity(
24
+ capacity_name: str,
25
+ azure_subscription_id: str,
26
+ key_vault_uri: str,
27
+ key_vault_tenant_id: str,
28
+ key_vault_client_id: str,
29
+ key_vault_client_secret: str,
30
+ resource_group: str,
31
+ region: str,
32
+ sku: str,
33
+ admin_members: str | List[str],
34
+ tags: Optional[dict] = None,
35
+ ):
36
+ """
37
+ This function creates a new Fabric capacity within an Azure subscription.
38
+
39
+ Parameters
40
+ ----------
41
+ capacity_name : str
42
+ Name of the Fabric capacity.
43
+ azure_subscription_id : str
44
+ The Azure subscription ID.
45
+ key_vault_uri : str
46
+ The name of the `Azure key vault <https://azure.microsoft.com/products/key-vault>`_ URI. Example: "https://<Key Vault Name>.vault.azure.net/"
47
+ key_vault_tenant_id : str
48
+ The name of the Azure key vault secret storing the Tenant ID.
49
+ key_vault_client_id : str
50
+ The name of the Azure key vault secret storing the Client ID.
51
+ key_vault_client_secret : str
52
+ The name of the Azure key vault secret storing the Client Secret.
53
+ resource_group : str
54
+ The name of the Azure resource group.
55
+ region : str
56
+ The name of the region in which the capacity will be created.
57
+ sku : str
58
+ The `sku size <https://azure.microsoft.com/pricing/details/microsoft-fabric/>`_ of the Fabric capacity.
59
+ admin_members : str | List[str]
60
+ The email address(es) of the admin(s) of the Fabric capacity.
61
+ tags: dict, default=None
62
+ Tag(s) to add to the capacity. Example: {'tagName': 'tagValue'}.
63
+ """
64
+
65
+ from azure.mgmt.resource import ResourceManagementClient
66
+
67
+ capacity_suffix = "fsku"
68
+
69
+ if isinstance(admin_members, str):
70
+ admin_members = [admin_members]
71
+
72
+ # list source: https://learn.microsoft.com/fabric/admin/region-availability
73
+ region_list = [
74
+ "Brazil South",
75
+ "North Europe",
76
+ "UAE North",
77
+ "South Africa North",
78
+ "Australia East",
79
+ "Canada Central",
80
+ "West Europe",
81
+ "Australia Southeast",
82
+ "Canada East",
83
+ "France Central",
84
+ "Central India",
85
+ "East US",
86
+ "Germany West Central",
87
+ "East Asia",
88
+ "East US 2",
89
+ "Norway East",
90
+ "Japan East",
91
+ "North Central US",
92
+ "Sweden Central",
93
+ "Korea Central",
94
+ "South Central US",
95
+ "Switzerland North",
96
+ "Southeast Asia",
97
+ "West US",
98
+ "Switzerland West",
99
+ "South India",
100
+ "West US 2",
101
+ "UK South",
102
+ "West US 3",
103
+ "UK West",
104
+ "brazilsouth",
105
+ "northeurope",
106
+ "uaenorth",
107
+ "southafricanorth",
108
+ "australiaeast",
109
+ "canadacentral",
110
+ "westeurope",
111
+ "australiasoutheast",
112
+ "canadaeast",
113
+ "francecentral",
114
+ "centralindia",
115
+ "eastus",
116
+ "germanywestcentral",
117
+ "eastasia",
118
+ "eastus2",
119
+ "norwayeast",
120
+ "japaneast",
121
+ "northcentralus",
122
+ "swedencentral",
123
+ "koreacentral",
124
+ "southcentralus",
125
+ "switzerlandnorth",
126
+ "southeastasia",
127
+ "westus",
128
+ "switzerlandwest",
129
+ "southindia",
130
+ "westus2",
131
+ "uksouth",
132
+ "westus3",
133
+ "ukwest",
134
+ ]
135
+
136
+ valid_regions = [
137
+ region for region in region_list if any(char.isupper() for char in region)
138
+ ]
139
+
140
+ if region not in region_list:
141
+ raise ValueError(
142
+ f"{icons.red_dot} Invalid region. Valid options: {valid_regions}."
143
+ )
144
+
145
+ azure_token, credential, headers = get_azure_token_credentials(
146
+ key_vault_uri=key_vault_uri,
147
+ key_vault_tenant_id=key_vault_tenant_id,
148
+ key_vault_client_id=key_vault_client_id,
149
+ key_vault_client_secret=key_vault_client_secret,
150
+ )
151
+
152
+ resource_client = ResourceManagementClient(credential, azure_subscription_id)
153
+
154
+ if resource_group is None:
155
+ for i in resource_client.resources.list(
156
+ "resourceType eq 'Microsoft.PowerBIDedicated/capacities'"
157
+ ):
158
+ if i.name == capacity_name.removesuffix(capacity_suffix):
159
+ resource_group = i.id.split("/")[4]
160
+ print(
161
+ f"{icons.yellow_dot} Override resource group flag detected for A SKUs - using the existing resource group '{resource_group}' for capacity '{capacity_name}'"
162
+ )
163
+ else:
164
+ # Attempt to get the resource group
165
+ try:
166
+ rg = resource_client.resource_groups.get(resource_group)
167
+ if rg.location != region:
168
+ print(
169
+ f"{icons.yellow_dot} The '{resource_group}' resource group exists, but in a different region."
170
+ )
171
+ except Exception:
172
+ # If the resource group does not exist, create it
173
+ print(
174
+ f"{icons.yellow_dot} The '{resource_group}' resource group does not exist."
175
+ )
176
+ print(
177
+ f"{icons.in_progress} Creating the '{resource_group}' resource group in the '{region}' region"
178
+ )
179
+ rg_result = resource_client.resource_groups.create_or_update(
180
+ resource_group, {"location": region}
181
+ )
182
+ print(
183
+ f"{icons.green_dot} Provisioned resource group with ID: {rg_result.id}"
184
+ )
185
+
186
+ payload = {
187
+ "properties": {"administration": {"members": admin_members}},
188
+ "sku": {"name": sku, "tier": "Fabric"},
189
+ "location": region,
190
+ }
191
+
192
+ payload = _add_sll_tag(payload, tags)
193
+
194
+ print(
195
+ f"{icons.in_progress} Creating the '{capacity_name}' capacity as an '{sku}' SKU within the '{region}' region..."
196
+ )
197
+
198
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Fabric/capacities/{capacity_name}?api-version={icons.azure_api_version}"
199
+
200
+ response = requests.put(url, headers=headers, json=payload)
201
+
202
+ if response.status_code not in [200, 201]:
203
+ raise FabricHTTPException(response)
204
+
205
+ print(
206
+ f"{icons.green_dot} Successfully created the '{capacity_name}' capacity within the '{region}' region."
207
+ )
208
+
209
+
210
+ def suspend_fabric_capacity(
211
+ capacity_name: str,
212
+ azure_subscription_id: str,
213
+ resource_group: str,
214
+ key_vault_uri: str,
215
+ key_vault_tenant_id: str,
216
+ key_vault_client_id: str,
217
+ key_vault_client_secret: str,
218
+ ):
219
+ """
220
+ This function suspends a Fabric capacity.
221
+
222
+ Parameters
223
+ ----------
224
+ capacity_name : str
225
+ Name of the Fabric capacity.
226
+ azure_subscription_id : str
227
+ The Azure subscription ID.
228
+ resource_group : str
229
+ The name of the Azure resource group.
230
+ key_vault_uri : str
231
+ The name of the `Azure key vault <https://azure.microsoft.com/products/key-vault>`_ URI. Example: "https://<Key Vault Name>.vault.azure.net/"
232
+ key_vault_tenant_id : str
233
+ The name of the Azure key vault secret storing the Tenant ID.
234
+ key_vault_client_id : str
235
+ The name of the Azure key vault secret storing the Client ID.
236
+ key_vault_client_secret : str
237
+ The name of the Azure key vault secret storing the Client Secret.
238
+ """
239
+ # https://learn.microsoft.com/en-us/rest/api/microsoftfabric/fabric-capacities/suspend?view=rest-microsoftfabric-2023-11-01&tabs=HTTP
240
+
241
+ azure_token, credential, headers = get_azure_token_credentials(
242
+ key_vault_uri=key_vault_uri,
243
+ key_vault_tenant_id=key_vault_tenant_id,
244
+ key_vault_client_id=key_vault_client_id,
245
+ key_vault_client_secret=key_vault_client_secret,
246
+ )
247
+
248
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Fabric/capacities/{capacity_name}/suspend?api-version={icons.azure_api_version}"
249
+
250
+ response = requests.post(url, headers=headers)
251
+
252
+ if response.status_code != 202:
253
+ raise FabricHTTPException(response)
254
+
255
+ print(f"{icons.green_dot} The '{capacity_name} capacity has been suspended.")
256
+
257
+
258
+ def resume_fabric_capacity(
259
+ capacity_name: str,
260
+ azure_subscription_id: str,
261
+ resource_group: str,
262
+ key_vault_uri: str,
263
+ key_vault_tenant_id: str,
264
+ key_vault_client_id: str,
265
+ key_vault_client_secret: str,
266
+ ):
267
+ """
268
+ This function resumes a Fabric capacity.
269
+
270
+ Parameters
271
+ ----------
272
+ capacity_name : str
273
+ Name of the Fabric capacity.
274
+ azure_subscription_id : str
275
+ The Azure subscription ID.
276
+ resource_group : str
277
+ The name of the Azure resource group.
278
+ key_vault_uri : str
279
+ The name of the `Azure key vault <https://azure.microsoft.com/products/key-vault>`_ URI. Example: "https://<Key Vault Name>.vault.azure.net/"
280
+ key_vault_tenant_id : str
281
+ The name of the Azure key vault secret storing the Tenant ID.
282
+ key_vault_client_id : str
283
+ The name of the Azure key vault secret storing the Client ID.
284
+ key_vault_client_secret : str
285
+ The name of the Azure key vault secret storing the Client Secret.
286
+ """
287
+
288
+ # https://learn.microsoft.com/en-us/rest/api/microsoftfabric/fabric-capacities/resume?view=rest-microsoftfabric-2023-11-01&tabs=HTTP
289
+
290
+ azure_token, credential, headers = get_azure_token_credentials(
291
+ key_vault_uri=key_vault_uri,
292
+ key_vault_tenant_id=key_vault_tenant_id,
293
+ key_vault_client_id=key_vault_client_id,
294
+ key_vault_client_secret=key_vault_client_secret,
295
+ )
296
+
297
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Fabric/capacities/{capacity_name}/resume?api-version={icons.azure_api_version}"
298
+
299
+ response = requests.post(url, headers=headers)
300
+
301
+ if response.status_code != 202:
302
+ raise FabricHTTPException(response)
303
+
304
+ print(f"{icons.green_dot} The '{capacity_name} capacity has been resumed.")
305
+
306
+
307
+ def delete_embedded_capacity(
308
+ capacity_name: str,
309
+ azure_subscription_id: str,
310
+ resource_group: str,
311
+ key_vault_uri: str,
312
+ key_vault_tenant_id: str,
313
+ key_vault_client_id: str,
314
+ key_vault_client_secret: str,
315
+ ):
316
+ """
317
+ This function deletes a Power BI Embedded capacity.
318
+
319
+ Parameters
320
+ ----------
321
+ capacity_name : str
322
+ Name of the Fabric capacity.
323
+ azure_subscription_id : str
324
+ The Azure subscription ID.
325
+ resource_group : str
326
+ The name of the Azure resource group.
327
+ key_vault_uri : str
328
+ The name of the `Azure key vault <https://azure.microsoft.com/products/key-vault>`_ URI. Example: "https://<Key Vault Name>.vault.azure.net/"
329
+ key_vault_tenant_id : str
330
+ The name of the Azure key vault secret storing the Tenant ID.
331
+ key_vault_client_id : str
332
+ The name of the Azure key vault secret storing the Client ID.
333
+ key_vault_client_secret : str
334
+ The name of the Azure key vault secret storing the Client Secret.
335
+ """
336
+
337
+ # https://learn.microsoft.com/en-us/rest/api/power-bi-embedded/capacities/delete?view=rest-power-bi-embedded-2021-01-01&tabs=HTTP
338
+
339
+ azure_token, credential, headers = get_azure_token_credentials(
340
+ key_vault_uri=key_vault_uri,
341
+ key_vault_tenant_id=key_vault_tenant_id,
342
+ key_vault_client_id=key_vault_client_id,
343
+ key_vault_client_secret=key_vault_client_secret,
344
+ )
345
+
346
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.PowerBIDedicated/capacities/{capacity_name}?api-version={icons.azure_api_version}"
347
+
348
+ response = requests.delete(url, headers=headers)
349
+
350
+ if response.status_code not in [200, 202]:
351
+ raise FabricHTTPException(response)
352
+
353
+ print(f"{icons.green_dot} The '{capacity_name} capacity has been deleted.")
354
+
355
+
356
+ def delete_premium_capacity(capacity_name: str):
357
+ """
358
+ This function deletes a Power BI Premium capacity.
359
+
360
+ Parameters
361
+ ----------
362
+ capacity_name : str
363
+ Name of the Fabric capacity.
364
+ """
365
+
366
+ dfC = fabric.list_capacities()
367
+
368
+ dfC_filt = dfC[dfC["Display Name"] == capacity_name]
369
+ if len(dfC_filt) == 0:
370
+ raise ValueError(
371
+ f"{icons.red_dot} The '{capacity_name}' capacity does not exist."
372
+ )
373
+ capacity_id = dfC_filt["Id"].iloc[0].upper()
374
+
375
+ client = fabric.FabricRestClient()
376
+ response = client.delete(f"capacities/{capacity_id}")
377
+
378
+ if response.status_code != 200:
379
+ raise FabricHTTPException(response)
380
+
381
+ print(f"{icons.green_dot} The '{capacity_name}' capacity has been deleted.")
382
+
383
+
384
+ def delete_fabric_capacity(
385
+ capacity_name: str,
386
+ azure_subscription_id: str,
387
+ resource_group: str,
388
+ key_vault_uri: str,
389
+ key_vault_tenant_id: str,
390
+ key_vault_client_id: str,
391
+ key_vault_client_secret: str,
392
+ ):
393
+ """
394
+ This function deletes a Fabric capacity.
395
+
396
+ Parameters
397
+ ----------
398
+ capacity_name : str
399
+ Name of the Fabric capacity.
400
+ azure_subscription_id : str
401
+ The Azure subscription ID.
402
+ resource_group : str
403
+ The name of the Azure resource group.
404
+ key_vault_uri : str
405
+ The name of the `Azure key vault <https://azure.microsoft.com/products/key-vault>`_ URI. Example: "https://<Key Vault Name>.vault.azure.net/"
406
+ key_vault_tenant_id : str
407
+ The name of the Azure key vault secret storing the Tenant ID.
408
+ key_vault_client_id : str
409
+ The name of the Azure key vault secret storing the Client ID.
410
+ key_vault_client_secret : str
411
+ The name of the Azure key vault secret storing the Client Secret.
412
+ """
413
+
414
+ # https://learn.microsoft.com/en-us/rest/api/microsoftfabric/fabric-capacities/delete?view=rest-microsoftfabric-2023-11-01&tabs=HTTP
415
+
416
+ azure_token, credential, headers = get_azure_token_credentials(
417
+ key_vault_uri=key_vault_uri,
418
+ key_vault_tenant_id=key_vault_tenant_id,
419
+ key_vault_client_id=key_vault_client_id,
420
+ key_vault_client_secret=key_vault_client_secret,
421
+ )
422
+
423
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Fabric/capacities/{capacity_name}?api-version={icons.azure_api_version}"
424
+
425
+ response = requests.delete(url, headers=headers)
426
+
427
+ if response.status_code != 202:
428
+ raise FabricHTTPException(response)
429
+
430
+ print(f"{icons.green_dot} The '{capacity_name} capacity has been deleted.")
431
+
432
+
433
+ def update_fabric_capacity(
434
+ capacity_name: str,
435
+ azure_subscription_id: str,
436
+ resource_group: str,
437
+ key_vault_uri: str,
438
+ key_vault_tenant_id: str,
439
+ key_vault_client_id: str,
440
+ key_vault_client_secret: str,
441
+ sku: Optional[str] = None,
442
+ admin_members: Optional[str | List[str]] = None,
443
+ tags: Optional[dict] = None,
444
+ ):
445
+ """
446
+ This function updates a Fabric capacity's properties.
447
+
448
+ Parameters
449
+ ----------
450
+ capacity_name : str
451
+ Name of the Fabric capacity.
452
+ azure_subscription_id : str
453
+ The Azure subscription ID.
454
+ resource_group : str
455
+ The name of the Azure resource group.
456
+ key_vault_uri : str
457
+ The name of the `Azure key vault <https://azure.microsoft.com/products/key-vault>`_ URI. Example: "https://<Key Vault Name>.vault.azure.net/"
458
+ key_vault_tenant_id : str
459
+ The name of the Azure key vault secret storing the Tenant ID.
460
+ key_vault_client_id : str
461
+ The name of the Azure key vault secret storing the Client ID.
462
+ key_vault_client_secret : str
463
+ The name of the Azure key vault secret storing the Client Secret.
464
+ sku : str, default=None
465
+ The `sku size <https://azure.microsoft.com/pricing/details/microsoft-fabric/>`_ of the Fabric capacity.
466
+ admin_members : str | List[str], default=None
467
+ The email address(es) of the admin(s) of the Fabric capacity.
468
+ tags : dict, default=None
469
+ Tag(s) to add to the capacity. Example: {'tagName': 'tagValue'}.
470
+
471
+ """
472
+
473
+ # https://learn.microsoft.com/en-us/rest/api/microsoftfabric/fabric-capacities/update?view=rest-microsoftfabric-2023-11-01&tabs=HTTP
474
+
475
+ if isinstance(admin_members, str):
476
+ admin_members = [admin_members]
477
+ if tags is not None and not isinstance(tags, dict):
478
+ raise ValueError(
479
+ f"{icons.red_dot} If specified, the 'tags' parameter must be a dictionary."
480
+ )
481
+
482
+ azure_token, credential, headers = get_azure_token_credentials(
483
+ key_vault_uri=key_vault_uri,
484
+ key_vault_tenant_id=key_vault_tenant_id,
485
+ key_vault_client_id=key_vault_client_id,
486
+ key_vault_client_secret=key_vault_client_secret,
487
+ )
488
+
489
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Fabric/capacities/{capacity_name}?api-version={icons.azure_api_version}"
490
+
491
+ payload = {}
492
+ if sku is not None:
493
+ payload["sku"] = {"name": sku, "tier": "Fabric"}
494
+ if admin_members is not None:
495
+ payload["properties"] = {"administration": {"members": [admin_members]}}
496
+
497
+ payload = _add_sll_tag(payload, tags)
498
+
499
+ if payload == {}:
500
+ raise ValueError(
501
+ f"{icons.warning} No parameters have been set to update the '{capacity_name}' capacity."
502
+ )
503
+
504
+ response = requests.patch(url, headers=headers, data=payload)
505
+
506
+ if response.status_code != 202:
507
+ raise FabricHTTPException(response)
508
+
509
+ print(
510
+ f"{icons.green_dot} The '{capacity_name} capacity has been updated accordingly."
511
+ )
512
+
513
+
514
+ def check_fabric_capacity_name_availablility(
515
+ capacity_name: str,
516
+ azure_subscription_id: str,
517
+ region: str,
518
+ key_vault_uri: str,
519
+ key_vault_tenant_id: str,
520
+ key_vault_client_id: str,
521
+ key_vault_client_secret: str,
522
+ ) -> bool:
523
+ # https://learn.microsoft.com/en-us/rest/api/microsoftfabric/fabric-capacities/check-name-availability?view=rest-microsoftfabric-2023-11-01&tabs=HTTP
524
+
525
+ azure_token, credential, headers = get_azure_token_credentials(
526
+ key_vault_uri=key_vault_uri,
527
+ key_vault_tenant_id=key_vault_tenant_id,
528
+ key_vault_client_id=key_vault_client_id,
529
+ key_vault_client_secret=key_vault_client_secret,
530
+ )
531
+
532
+ payload = {"name": capacity_name, "type": "Microsoft.Fabric/capacities"}
533
+
534
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/providers/Microsoft.Fabric/locations/{region}/checkNameAvailability?api-version={icons.azure_api_version}"
535
+
536
+ response = requests.post(url, headers=headers, data=payload)
537
+
538
+ if response.status_code != 202:
539
+ raise FabricHTTPException(response)
540
+
541
+ return bool(response.json().get("nameAvailable"))