semantic-link-labs 0.7.3__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 (60) hide show
  1. {semantic_link_labs-0.7.3.dist-info → semantic_link_labs-0.7.4.dist-info}/METADATA +14 -3
  2. {semantic_link_labs-0.7.3.dist-info → semantic_link_labs-0.7.4.dist-info}/RECORD +60 -44
  3. {semantic_link_labs-0.7.3.dist-info → semantic_link_labs-0.7.4.dist-info}/WHEEL +1 -1
  4. sempy_labs/__init__.py +63 -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/{_translations_ta-IN.po → _model/_translations_ta-IN.po} +26 -0
  36. sempy_labs/_bpa_translation/{_translations_te-IN.po → _model/_translations_te-IN.po} +24 -0
  37. sempy_labs/_bpa_translation/{_translations_th-TH.po → _model/_translations_th-TH.po} +24 -0
  38. sempy_labs/_bpa_translation/_model/_translations_tr-TR.po +925 -0
  39. sempy_labs/_bpa_translation/_model/_translations_uk-UA.po +933 -0
  40. sempy_labs/_bpa_translation/{_translations_zh-CN.po → _model/_translations_zh-CN.po} +116 -97
  41. sempy_labs/_bpa_translation/{_translations_zu-ZA.po → _model/_translations_zu-ZA.po} +25 -0
  42. sempy_labs/_capacities.py +541 -0
  43. sempy_labs/_connections.py +138 -0
  44. sempy_labs/_environments.py +156 -0
  45. sempy_labs/_helper_functions.py +146 -8
  46. sempy_labs/_icons.py +43 -0
  47. sempy_labs/_list_functions.py +35 -900
  48. sempy_labs/_model_bpa.py +8 -32
  49. sempy_labs/_notebooks.py +143 -0
  50. sempy_labs/_query_scale_out.py +28 -7
  51. sempy_labs/_spark.py +465 -0
  52. sempy_labs/_sql.py +35 -11
  53. sempy_labs/_translations.py +3 -0
  54. sempy_labs/_vertipaq.py +160 -99
  55. sempy_labs/_workspaces.py +294 -0
  56. sempy_labs/directlake/_directlake_schema_sync.py +1 -2
  57. sempy_labs/tom/_model.py +5 -1
  58. {semantic_link_labs-0.7.3.dist-info → semantic_link_labs-0.7.4.dist-info}/LICENSE +0 -0
  59. {semantic_link_labs-0.7.3.dist-info → semantic_link_labs-0.7.4.dist-info}/top_level.txt +0 -0
  60. /sempy_labs/_bpa_translation/{_translations_sv-SE.po → _model/_translations_sv-SE.po} +0 -0
@@ -0,0 +1,156 @@
1
+ import sempy.fabric as fabric
2
+ import pandas as pd
3
+ import sempy_labs._icons as icons
4
+ from typing import Optional
5
+ from sempy_labs._helper_functions import (
6
+ resolve_workspace_name_and_id,
7
+ lro,
8
+ pagination,
9
+ )
10
+ from sempy.fabric.exceptions import FabricHTTPException
11
+
12
+
13
+ def create_environment(
14
+ environment: str, description: Optional[str] = None, workspace: Optional[str] = None
15
+ ):
16
+ """
17
+ Creates a Fabric environment.
18
+
19
+ Parameters
20
+ ----------
21
+ environment: str
22
+ Name of the environment.
23
+ description : str, default=None
24
+ A description of the environment.
25
+ workspace : str, default=None
26
+ The Fabric workspace name.
27
+ Defaults to None which resolves to the workspace of the attached lakehouse
28
+ or if no lakehouse attached, resolves to the workspace of the notebook.
29
+ """
30
+
31
+ (workspace, workspace_id) = resolve_workspace_name_and_id(workspace)
32
+
33
+ request_body = {"displayName": environment}
34
+
35
+ if description:
36
+ request_body["description"] = description
37
+
38
+ client = fabric.FabricRestClient()
39
+ response = client.post(
40
+ f"/v1/workspaces/{workspace_id}/environments", json=request_body
41
+ )
42
+
43
+ lro(client, response, status_codes=[201, 202])
44
+
45
+ print(
46
+ f"{icons.green_dot} The '{environment}' environment has been created within the '{workspace}' workspace."
47
+ )
48
+
49
+
50
+ def list_environments(workspace: Optional[str] = None) -> pd.DataFrame:
51
+ """
52
+ Shows the environments within a workspace.
53
+
54
+ Parameters
55
+ ----------
56
+ workspace : str, default=None
57
+ The Fabric workspace name.
58
+ Defaults to None which resolves to the workspace of the attached lakehouse
59
+ or if no lakehouse attached, resolves to the workspace of the notebook.
60
+
61
+ Returns
62
+ -------
63
+ pandas.DataFrame
64
+ A pandas dataframe showing the environments within a workspace.
65
+ """
66
+
67
+ df = pd.DataFrame(columns=["Environment Name", "Environment Id", "Description"])
68
+
69
+ (workspace, workspace_id) = resolve_workspace_name_and_id(workspace)
70
+
71
+ client = fabric.FabricRestClient()
72
+ response = client.get(f"/v1/workspaces/{workspace_id}/environments")
73
+ if response.status_code != 200:
74
+ raise FabricHTTPException(response)
75
+
76
+ responses = pagination(client, response)
77
+
78
+ for r in responses:
79
+ for v in r.get("value", []):
80
+ new_data = {
81
+ "Environment Name": v.get("displayName"),
82
+ "Environment Id": v.get("id"),
83
+ "Description": v.get("description"),
84
+ }
85
+ df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
86
+
87
+ return df
88
+
89
+
90
+ def delete_environment(environment: str, workspace: Optional[str] = None):
91
+ """
92
+ Deletes a Fabric environment.
93
+
94
+ Parameters
95
+ ----------
96
+ environment: str
97
+ Name of the environment.
98
+ workspace : str, default=None
99
+ The Fabric workspace name.
100
+ Defaults to None which resolves to the workspace of the attached lakehouse
101
+ or if no lakehouse attached, resolves to the workspace of the notebook.
102
+ """
103
+
104
+ from sempy_labs._helper_functions import resolve_environment_id
105
+
106
+ (workspace, workspace_id) = resolve_workspace_name_and_id(workspace)
107
+ environment_id = resolve_environment_id(
108
+ environment=environment, workspace=workspace
109
+ )
110
+
111
+ client = fabric.FabricRestClient()
112
+ response = client.delete(
113
+ f"/v1/workspaces/{workspace_id}/environments/{environment_id}"
114
+ )
115
+
116
+ if response.status_code != 200:
117
+ raise FabricHTTPException(response)
118
+
119
+ print(
120
+ f"{icons.green_dot} The '{environment}' environment within the '{workspace}' workspace has been deleted."
121
+ )
122
+
123
+
124
+ def publish_environment(environment: str, workspace: Optional[str] = None):
125
+ """
126
+ Publishes a Fabric environment.
127
+
128
+ Parameters
129
+ ----------
130
+ environment: str
131
+ Name of the environment.
132
+ workspace : str, default=None
133
+ The Fabric workspace name.
134
+ Defaults to None which resolves to the workspace of the attached lakehouse
135
+ or if no lakehouse attached, resolves to the workspace of the notebook.
136
+ """
137
+
138
+ # https://learn.microsoft.com/en-us/rest/api/fabric/environment/spark-libraries/publish-environment?tabs=HTTP
139
+
140
+ from sempy_labs._helper_functions import resolve_environment_id
141
+
142
+ (workspace, workspace_id) = resolve_workspace_name_and_id(workspace)
143
+ environment_id = resolve_environment_id(
144
+ environment=environment, workspace=workspace
145
+ )
146
+
147
+ client = fabric.FabricRestClient()
148
+ response = client.post(
149
+ f"/v1/workspaces/{workspace_id}/environments/{environment_id}/staging/publish"
150
+ )
151
+
152
+ lro(client, response)
153
+
154
+ print(
155
+ f"{icons.green_dot} The '{environment}' environment within the '{workspace}' workspace has been published."
156
+ )
@@ -6,7 +6,6 @@ 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
@@ -392,6 +391,7 @@ def save_as_delta_table(
392
391
  delta_table_name: str,
393
392
  write_mode: str,
394
393
  merge_schema: Optional[bool] = False,
394
+ schema: Optional[dict] = None,
395
395
  lakehouse: Optional[str] = None,
396
396
  workspace: Optional[str] = None,
397
397
  ):
@@ -408,6 +408,8 @@ def save_as_delta_table(
408
408
  The write mode for the save operation. Options: 'append', 'overwrite'.
409
409
  merge_schema : bool, default=False
410
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.
411
413
  lakehouse : str, default=None
412
414
  The Fabric lakehouse used by the Direct Lake semantic model.
413
415
  Defaults to None which resolves to the lakehouse attached to the notebook.
@@ -415,13 +417,22 @@ def save_as_delta_table(
415
417
  The Fabric workspace name.
416
418
  Defaults to None which resolves to the workspace of the attached lakehouse
417
419
  or if no lakehouse attached, resolves to the workspace of the notebook.
418
-
419
- Returns
420
- -------
421
- UUID
422
- The ID of the Power BI report.
423
420
  """
424
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
+
425
436
  if workspace is None:
426
437
  workspace_id = fabric.get_workspace_id()
427
438
  workspace = fabric.resolve_workspace_name(workspace_id)
@@ -450,9 +461,32 @@ def save_as_delta_table(
450
461
  )
451
462
 
452
463
  dataframe.columns = dataframe.columns.str.replace(" ", "_")
453
-
454
464
  spark = SparkSession.builder.getOrCreate()
455
- 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)
456
490
 
457
491
  filePath = create_abfss_path(
458
492
  lakehouse_id=lakehouse_id,
@@ -781,6 +815,37 @@ def resolve_capacity_name(capacity_id: Optional[UUID] = None) -> str:
781
815
  return dfC_filt["Display Name"].iloc[0]
782
816
 
783
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
+
784
849
  def retry(sleep_time: int, timeout_error_message: str):
785
850
  def decorator(func):
786
851
  @wraps(func)
@@ -883,6 +948,7 @@ class FabricTokenCredential(TokenCredential):
883
948
  ) -> AccessToken:
884
949
 
885
950
  from notebookutils import mssparkutils
951
+
886
952
  token = mssparkutils.credentials.getToken(scopes)
887
953
  access_token = AccessToken(token, 0)
888
954
 
@@ -910,3 +976,75 @@ def resolve_warehouse_id(warehouse: str, workspace: Optional[str]):
910
976
  )
911
977
 
912
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"]