semantic-link-labs 0.12.8__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.
Files changed (243) hide show
  1. semantic_link_labs-0.12.8.dist-info/METADATA +354 -0
  2. semantic_link_labs-0.12.8.dist-info/RECORD +243 -0
  3. semantic_link_labs-0.12.8.dist-info/WHEEL +5 -0
  4. semantic_link_labs-0.12.8.dist-info/licenses/LICENSE +21 -0
  5. semantic_link_labs-0.12.8.dist-info/top_level.txt +1 -0
  6. sempy_labs/__init__.py +606 -0
  7. sempy_labs/_a_lib_info.py +2 -0
  8. sempy_labs/_ai.py +437 -0
  9. sempy_labs/_authentication.py +264 -0
  10. sempy_labs/_bpa_translation/_model/_translations_am-ET.po +869 -0
  11. sempy_labs/_bpa_translation/_model/_translations_ar-AE.po +908 -0
  12. sempy_labs/_bpa_translation/_model/_translations_bg-BG.po +968 -0
  13. sempy_labs/_bpa_translation/_model/_translations_ca-ES.po +963 -0
  14. sempy_labs/_bpa_translation/_model/_translations_cs-CZ.po +943 -0
  15. sempy_labs/_bpa_translation/_model/_translations_da-DK.po +945 -0
  16. sempy_labs/_bpa_translation/_model/_translations_de-DE.po +988 -0
  17. sempy_labs/_bpa_translation/_model/_translations_el-GR.po +993 -0
  18. sempy_labs/_bpa_translation/_model/_translations_es-ES.po +971 -0
  19. sempy_labs/_bpa_translation/_model/_translations_fa-IR.po +933 -0
  20. sempy_labs/_bpa_translation/_model/_translations_fi-FI.po +942 -0
  21. sempy_labs/_bpa_translation/_model/_translations_fr-FR.po +994 -0
  22. sempy_labs/_bpa_translation/_model/_translations_ga-IE.po +967 -0
  23. sempy_labs/_bpa_translation/_model/_translations_he-IL.po +902 -0
  24. sempy_labs/_bpa_translation/_model/_translations_hi-IN.po +944 -0
  25. sempy_labs/_bpa_translation/_model/_translations_hu-HU.po +963 -0
  26. sempy_labs/_bpa_translation/_model/_translations_id-ID.po +946 -0
  27. sempy_labs/_bpa_translation/_model/_translations_is-IS.po +939 -0
  28. sempy_labs/_bpa_translation/_model/_translations_it-IT.po +986 -0
  29. sempy_labs/_bpa_translation/_model/_translations_ja-JP.po +846 -0
  30. sempy_labs/_bpa_translation/_model/_translations_ko-KR.po +839 -0
  31. sempy_labs/_bpa_translation/_model/_translations_mt-MT.po +967 -0
  32. sempy_labs/_bpa_translation/_model/_translations_nl-NL.po +978 -0
  33. sempy_labs/_bpa_translation/_model/_translations_pl-PL.po +962 -0
  34. sempy_labs/_bpa_translation/_model/_translations_pt-BR.po +962 -0
  35. sempy_labs/_bpa_translation/_model/_translations_pt-PT.po +957 -0
  36. sempy_labs/_bpa_translation/_model/_translations_ro-RO.po +968 -0
  37. sempy_labs/_bpa_translation/_model/_translations_ru-RU.po +964 -0
  38. sempy_labs/_bpa_translation/_model/_translations_sk-SK.po +952 -0
  39. sempy_labs/_bpa_translation/_model/_translations_sl-SL.po +950 -0
  40. sempy_labs/_bpa_translation/_model/_translations_sv-SE.po +942 -0
  41. sempy_labs/_bpa_translation/_model/_translations_ta-IN.po +976 -0
  42. sempy_labs/_bpa_translation/_model/_translations_te-IN.po +947 -0
  43. sempy_labs/_bpa_translation/_model/_translations_th-TH.po +924 -0
  44. sempy_labs/_bpa_translation/_model/_translations_tr-TR.po +953 -0
  45. sempy_labs/_bpa_translation/_model/_translations_uk-UA.po +961 -0
  46. sempy_labs/_bpa_translation/_model/_translations_zh-CN.po +804 -0
  47. sempy_labs/_bpa_translation/_model/_translations_zu-ZA.po +969 -0
  48. sempy_labs/_capacities.py +1198 -0
  49. sempy_labs/_capacity_migration.py +660 -0
  50. sempy_labs/_clear_cache.py +351 -0
  51. sempy_labs/_connections.py +610 -0
  52. sempy_labs/_dashboards.py +69 -0
  53. sempy_labs/_data_access_security.py +98 -0
  54. sempy_labs/_data_pipelines.py +162 -0
  55. sempy_labs/_dataflows.py +668 -0
  56. sempy_labs/_dax.py +501 -0
  57. sempy_labs/_daxformatter.py +80 -0
  58. sempy_labs/_delta_analyzer.py +467 -0
  59. sempy_labs/_delta_analyzer_history.py +301 -0
  60. sempy_labs/_dictionary_diffs.py +221 -0
  61. sempy_labs/_documentation.py +147 -0
  62. sempy_labs/_domains.py +51 -0
  63. sempy_labs/_eventhouses.py +182 -0
  64. sempy_labs/_external_data_shares.py +230 -0
  65. sempy_labs/_gateways.py +521 -0
  66. sempy_labs/_generate_semantic_model.py +521 -0
  67. sempy_labs/_get_connection_string.py +84 -0
  68. sempy_labs/_git.py +543 -0
  69. sempy_labs/_graphQL.py +90 -0
  70. sempy_labs/_helper_functions.py +2833 -0
  71. sempy_labs/_icons.py +149 -0
  72. sempy_labs/_job_scheduler.py +609 -0
  73. sempy_labs/_kql_databases.py +149 -0
  74. sempy_labs/_kql_querysets.py +124 -0
  75. sempy_labs/_kusto.py +137 -0
  76. sempy_labs/_labels.py +124 -0
  77. sempy_labs/_list_functions.py +1720 -0
  78. sempy_labs/_managed_private_endpoints.py +253 -0
  79. sempy_labs/_mirrored_databases.py +416 -0
  80. sempy_labs/_mirrored_warehouses.py +60 -0
  81. sempy_labs/_ml_experiments.py +113 -0
  82. sempy_labs/_model_auto_build.py +140 -0
  83. sempy_labs/_model_bpa.py +557 -0
  84. sempy_labs/_model_bpa_bulk.py +378 -0
  85. sempy_labs/_model_bpa_rules.py +859 -0
  86. sempy_labs/_model_dependencies.py +343 -0
  87. sempy_labs/_mounted_data_factories.py +123 -0
  88. sempy_labs/_notebooks.py +441 -0
  89. sempy_labs/_one_lake_integration.py +151 -0
  90. sempy_labs/_onelake.py +131 -0
  91. sempy_labs/_query_scale_out.py +433 -0
  92. sempy_labs/_refresh_semantic_model.py +435 -0
  93. sempy_labs/_semantic_models.py +468 -0
  94. sempy_labs/_spark.py +455 -0
  95. sempy_labs/_sql.py +241 -0
  96. sempy_labs/_sql_audit_settings.py +207 -0
  97. sempy_labs/_sql_endpoints.py +214 -0
  98. sempy_labs/_tags.py +201 -0
  99. sempy_labs/_translations.py +43 -0
  100. sempy_labs/_user_delegation_key.py +44 -0
  101. sempy_labs/_utils.py +79 -0
  102. sempy_labs/_vertipaq.py +1021 -0
  103. sempy_labs/_vpax.py +388 -0
  104. sempy_labs/_warehouses.py +234 -0
  105. sempy_labs/_workloads.py +140 -0
  106. sempy_labs/_workspace_identity.py +72 -0
  107. sempy_labs/_workspaces.py +595 -0
  108. sempy_labs/admin/__init__.py +170 -0
  109. sempy_labs/admin/_activities.py +167 -0
  110. sempy_labs/admin/_apps.py +145 -0
  111. sempy_labs/admin/_artifacts.py +65 -0
  112. sempy_labs/admin/_basic_functions.py +463 -0
  113. sempy_labs/admin/_capacities.py +508 -0
  114. sempy_labs/admin/_dataflows.py +45 -0
  115. sempy_labs/admin/_datasets.py +186 -0
  116. sempy_labs/admin/_domains.py +522 -0
  117. sempy_labs/admin/_external_data_share.py +100 -0
  118. sempy_labs/admin/_git.py +72 -0
  119. sempy_labs/admin/_items.py +265 -0
  120. sempy_labs/admin/_labels.py +211 -0
  121. sempy_labs/admin/_reports.py +241 -0
  122. sempy_labs/admin/_scanner.py +118 -0
  123. sempy_labs/admin/_shared.py +82 -0
  124. sempy_labs/admin/_sharing_links.py +110 -0
  125. sempy_labs/admin/_tags.py +131 -0
  126. sempy_labs/admin/_tenant.py +503 -0
  127. sempy_labs/admin/_tenant_keys.py +89 -0
  128. sempy_labs/admin/_users.py +140 -0
  129. sempy_labs/admin/_workspaces.py +236 -0
  130. sempy_labs/deployment_pipeline/__init__.py +23 -0
  131. sempy_labs/deployment_pipeline/_items.py +580 -0
  132. sempy_labs/directlake/__init__.py +57 -0
  133. sempy_labs/directlake/_autosync.py +58 -0
  134. sempy_labs/directlake/_directlake_schema_compare.py +120 -0
  135. sempy_labs/directlake/_directlake_schema_sync.py +161 -0
  136. sempy_labs/directlake/_dl_helper.py +274 -0
  137. sempy_labs/directlake/_generate_shared_expression.py +94 -0
  138. sempy_labs/directlake/_get_directlake_lakehouse.py +62 -0
  139. sempy_labs/directlake/_get_shared_expression.py +34 -0
  140. sempy_labs/directlake/_guardrails.py +96 -0
  141. sempy_labs/directlake/_list_directlake_model_calc_tables.py +70 -0
  142. sempy_labs/directlake/_show_unsupported_directlake_objects.py +90 -0
  143. sempy_labs/directlake/_update_directlake_model_lakehouse_connection.py +239 -0
  144. sempy_labs/directlake/_update_directlake_partition_entity.py +259 -0
  145. sempy_labs/directlake/_warm_cache.py +236 -0
  146. sempy_labs/dotnet_lib/dotnet.runtime.config.json +10 -0
  147. sempy_labs/environment/__init__.py +23 -0
  148. sempy_labs/environment/_items.py +212 -0
  149. sempy_labs/environment/_pubstage.py +223 -0
  150. sempy_labs/eventstream/__init__.py +37 -0
  151. sempy_labs/eventstream/_items.py +263 -0
  152. sempy_labs/eventstream/_topology.py +652 -0
  153. sempy_labs/graph/__init__.py +59 -0
  154. sempy_labs/graph/_groups.py +651 -0
  155. sempy_labs/graph/_sensitivity_labels.py +120 -0
  156. sempy_labs/graph/_teams.py +125 -0
  157. sempy_labs/graph/_user_licenses.py +96 -0
  158. sempy_labs/graph/_users.py +516 -0
  159. sempy_labs/graph_model/__init__.py +15 -0
  160. sempy_labs/graph_model/_background_jobs.py +63 -0
  161. sempy_labs/graph_model/_items.py +149 -0
  162. sempy_labs/lakehouse/__init__.py +67 -0
  163. sempy_labs/lakehouse/_blobs.py +247 -0
  164. sempy_labs/lakehouse/_get_lakehouse_columns.py +102 -0
  165. sempy_labs/lakehouse/_get_lakehouse_tables.py +274 -0
  166. sempy_labs/lakehouse/_helper.py +250 -0
  167. sempy_labs/lakehouse/_lakehouse.py +351 -0
  168. sempy_labs/lakehouse/_livy_sessions.py +143 -0
  169. sempy_labs/lakehouse/_materialized_lake_views.py +157 -0
  170. sempy_labs/lakehouse/_partitioning.py +165 -0
  171. sempy_labs/lakehouse/_schemas.py +217 -0
  172. sempy_labs/lakehouse/_shortcuts.py +440 -0
  173. sempy_labs/migration/__init__.py +35 -0
  174. sempy_labs/migration/_create_pqt_file.py +238 -0
  175. sempy_labs/migration/_direct_lake_to_import.py +105 -0
  176. sempy_labs/migration/_migrate_calctables_to_lakehouse.py +398 -0
  177. sempy_labs/migration/_migrate_calctables_to_semantic_model.py +148 -0
  178. sempy_labs/migration/_migrate_model_objects_to_semantic_model.py +533 -0
  179. sempy_labs/migration/_migrate_tables_columns_to_semantic_model.py +172 -0
  180. sempy_labs/migration/_migration_validation.py +71 -0
  181. sempy_labs/migration/_refresh_calc_tables.py +131 -0
  182. sempy_labs/mirrored_azure_databricks_catalog/__init__.py +15 -0
  183. sempy_labs/mirrored_azure_databricks_catalog/_discover.py +213 -0
  184. sempy_labs/mirrored_azure_databricks_catalog/_refresh_catalog_metadata.py +45 -0
  185. sempy_labs/ml_model/__init__.py +23 -0
  186. sempy_labs/ml_model/_functions.py +427 -0
  187. sempy_labs/report/_BPAReportTemplate.json +232 -0
  188. sempy_labs/report/__init__.py +55 -0
  189. sempy_labs/report/_bpareporttemplate/.pbi/localSettings.json +9 -0
  190. sempy_labs/report/_bpareporttemplate/.platform +11 -0
  191. sempy_labs/report/_bpareporttemplate/StaticResources/SharedResources/BaseThemes/CY24SU06.json +710 -0
  192. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/page.json +11 -0
  193. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/1b08bce3bebabb0a27a8/visual.json +191 -0
  194. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/2f22ddb70c301693c165/visual.json +438 -0
  195. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/3b1182230aa6c600b43a/visual.json +127 -0
  196. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/58577ba6380c69891500/visual.json +576 -0
  197. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/a2a8fa5028b3b776c96c/visual.json +207 -0
  198. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/adfd47ef30652707b987/visual.json +506 -0
  199. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/b6a80ee459e716e170b1/visual.json +127 -0
  200. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/ce3130a721c020cc3d81/visual.json +513 -0
  201. sempy_labs/report/_bpareporttemplate/definition/pages/92735ae19b31712208ad/page.json +8 -0
  202. sempy_labs/report/_bpareporttemplate/definition/pages/92735ae19b31712208ad/visuals/66e60dfb526437cd78d1/visual.json +112 -0
  203. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/page.json +11 -0
  204. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/07deb8bce824e1be37d7/visual.json +513 -0
  205. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0b1c68838818b32ad03b/visual.json +352 -0
  206. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0c171de9d2683d10b930/visual.json +37 -0
  207. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0efa01be0510e40a645e/visual.json +542 -0
  208. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/6bf2f0eb830ab53cc668/visual.json +221 -0
  209. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/88d8141cb8500b60030c/visual.json +127 -0
  210. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/a753273590beed656a03/visual.json +576 -0
  211. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/b8fdc82cddd61ac447bc/visual.json +127 -0
  212. sempy_labs/report/_bpareporttemplate/definition/pages/d37dce724a0ccc30044b/page.json +9 -0
  213. sempy_labs/report/_bpareporttemplate/definition/pages/d37dce724a0ccc30044b/visuals/ce8532a7e25020271077/visual.json +38 -0
  214. sempy_labs/report/_bpareporttemplate/definition/pages/pages.json +10 -0
  215. sempy_labs/report/_bpareporttemplate/definition/report.json +176 -0
  216. sempy_labs/report/_bpareporttemplate/definition/version.json +4 -0
  217. sempy_labs/report/_bpareporttemplate/definition.pbir +14 -0
  218. sempy_labs/report/_download_report.py +76 -0
  219. sempy_labs/report/_export_report.py +257 -0
  220. sempy_labs/report/_generate_report.py +427 -0
  221. sempy_labs/report/_paginated.py +76 -0
  222. sempy_labs/report/_report_bpa.py +354 -0
  223. sempy_labs/report/_report_bpa_rules.py +115 -0
  224. sempy_labs/report/_report_functions.py +581 -0
  225. sempy_labs/report/_report_helper.py +227 -0
  226. sempy_labs/report/_report_list_functions.py +110 -0
  227. sempy_labs/report/_report_rebind.py +149 -0
  228. sempy_labs/report/_reportwrapper.py +3100 -0
  229. sempy_labs/report/_save_report.py +147 -0
  230. sempy_labs/snowflake_database/__init__.py +10 -0
  231. sempy_labs/snowflake_database/_items.py +105 -0
  232. sempy_labs/sql_database/__init__.py +21 -0
  233. sempy_labs/sql_database/_items.py +201 -0
  234. sempy_labs/sql_database/_mirroring.py +79 -0
  235. sempy_labs/theme/__init__.py +12 -0
  236. sempy_labs/theme/_org_themes.py +129 -0
  237. sempy_labs/tom/__init__.py +3 -0
  238. sempy_labs/tom/_model.py +5977 -0
  239. sempy_labs/variable_library/__init__.py +19 -0
  240. sempy_labs/variable_library/_functions.py +403 -0
  241. sempy_labs/warehouse/__init__.py +28 -0
  242. sempy_labs/warehouse/_items.py +234 -0
  243. sempy_labs/warehouse/_restore_points.py +309 -0
@@ -0,0 +1,516 @@
1
+ import pandas as pd
2
+ import os
3
+ import base64
4
+ from uuid import UUID
5
+ import sempy_labs._icons as icons
6
+ from typing import List, Literal, Optional
7
+ from sempy_labs._helper_functions import (
8
+ _is_valid_uuid,
9
+ _base_api,
10
+ _create_dataframe,
11
+ _update_dataframe_datatypes,
12
+ _mount,
13
+ )
14
+ from sempy._utils._log import log
15
+
16
+
17
+ @log
18
+ def resolve_user_id(user: str | UUID) -> UUID:
19
+ """
20
+ Resolves the user ID from the user principal name or ID.
21
+
22
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
23
+
24
+ Parameters
25
+ ----------
26
+ user : str | uuid.UUID
27
+ The user ID or user principal name.
28
+
29
+ Returns
30
+ -------
31
+ uuid.UUID
32
+ The user ID.
33
+ """
34
+
35
+ if _is_valid_uuid(user):
36
+ return user
37
+ else:
38
+ result = _base_api(request=f"users/{user}", client="graph").json()
39
+ return result.get("id")
40
+
41
+
42
+ @log
43
+ def get_user(user: str | UUID, show_manager: bool = False) -> pd.DataFrame:
44
+ """
45
+ Shows properties of a given user.
46
+
47
+ This is a wrapper function for the following API: `Get a user <https://learn.microsoft.com/graph/api/user-get>`_.
48
+
49
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
50
+
51
+ Parameters
52
+ ----------
53
+ user : str | uuid.UUID
54
+ The user ID or user principal name.
55
+ show_manager : bool, default=False
56
+ Whether to include the user's manager information.
57
+
58
+ Returns
59
+ -------
60
+ pandas.DataFrame
61
+ A pandas dataframe showing properties of a given user.
62
+ """
63
+
64
+ url = f"users/{user}?$select=id,userPrincipalName,displayName,mail,jobTitle,officeLocation,mobilePhone,businessPhones,preferredLanguage,surname,department"
65
+ if show_manager:
66
+ url += "&$expand=manager($select=displayName,id,mail,jobTitle)"
67
+
68
+ result = _base_api(request=url, client="graph").json()
69
+
70
+ new_data = {
71
+ "User Id": result.get("id"),
72
+ "User Principal Name": result.get("userPrincipalName"),
73
+ "User Name": result.get("displayName"),
74
+ "Mail": result.get("mail"),
75
+ "Job Title": result.get("jobTitle"),
76
+ "Office Location": result.get("officeLocation"),
77
+ "Mobile Phone": result.get("mobilePhone"),
78
+ "Business Phones": str(result.get("businessPhones")),
79
+ "Preferred Language": result.get("preferredLanguage"),
80
+ "Surname": result.get("surname"),
81
+ "Department": result.get("department"),
82
+ }
83
+ if show_manager:
84
+ manager = result.get("manager", {})
85
+ new_data |= {
86
+ "Manager Id": manager.get("id"),
87
+ "Manager Name": manager.get("displayName"),
88
+ "Manager Mail": manager.get("mail"),
89
+ "Manager Job Title": manager.get("jobTitle"),
90
+ }
91
+
92
+ return pd.DataFrame([new_data])
93
+
94
+
95
+ @log
96
+ def list_users(show_manager: bool = False) -> pd.DataFrame:
97
+ """
98
+ Shows a list of users and their properties.
99
+
100
+ This is a wrapper function for the following API: `List users <https://learn.microsoft.com/graph/api/user-list>`_.
101
+
102
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
103
+
104
+ Parameters
105
+ ----------
106
+ show_manager : bool, default=False
107
+ Whether to include the user's manager information.
108
+
109
+ Returns
110
+ -------
111
+ pandas.DataFrame
112
+ A pandas dataframe showing a list of users and their properties.
113
+ """
114
+
115
+ url = "users?$select=id,userPrincipalName,displayName,mail,jobTitle,officeLocation,mobilePhone,businessPhones,preferredLanguage,surname,department"
116
+ if show_manager:
117
+ url += "&$expand=manager($select=displayName,id,mail,jobTitle)"
118
+ result = _base_api(request=url, client="graph", uses_pagination=True)
119
+
120
+ columns = {
121
+ "User Id": "string",
122
+ "User Principal Name": "string",
123
+ "User Name": "string",
124
+ "Mail": "string",
125
+ "Job Title": "string",
126
+ "Office Location": "string",
127
+ "Mobile Phone": "string",
128
+ "Business Phones": "string",
129
+ "Preferred Language": "string",
130
+ "Surname": "string",
131
+ "Department": "string",
132
+ }
133
+
134
+ if show_manager:
135
+ columns.update(
136
+ {
137
+ "Manager Id": "string",
138
+ "Manager Name": "string",
139
+ "Manager Mail": "string",
140
+ "Manager Job Title": "string",
141
+ }
142
+ )
143
+
144
+ df = _create_dataframe(columns=columns)
145
+
146
+ rows = []
147
+ for r in result:
148
+ for v in r.get("value", []):
149
+ user_data = {
150
+ "User Id": v.get("id"),
151
+ "User Principal Name": v.get("userPrincipalName"),
152
+ "User Name": v.get("displayName"),
153
+ "Mail": v.get("mail"),
154
+ "Job Title": v.get("jobTitle"),
155
+ "Office Location": v.get("officeLocation"),
156
+ "Mobile Phone": v.get("mobilePhone"),
157
+ "Business Phones": str(v.get("businessPhones")),
158
+ "Preferred Language": v.get("preferredLanguage"),
159
+ "Surname": v.get("surname"),
160
+ "Department": v.get("department"),
161
+ }
162
+
163
+ if show_manager:
164
+ manager = v.get("manager", {})
165
+ user_data |= {
166
+ "Manager Id": manager.get("id"),
167
+ "Manager Name": manager.get("displayName"),
168
+ "Manager Mail": manager.get("mail"),
169
+ "Manager Job Title": manager.get("jobTitle"),
170
+ }
171
+
172
+ rows.append(user_data)
173
+
174
+ if rows:
175
+ df = pd.DataFrame(rows, columns=list(columns.keys()))
176
+ _update_dataframe_datatypes(dataframe=df, column_map=columns)
177
+
178
+ return df
179
+
180
+
181
+ @log
182
+ def send_mail(
183
+ user: UUID | str,
184
+ subject: str,
185
+ to_recipients: str | List[str],
186
+ content: str,
187
+ content_type: Literal["Text", "HTML"] = "Text",
188
+ cc_recipients: Optional[str | List[str]] = None,
189
+ bcc_recipients: Optional[str | List[str]] = None,
190
+ priority: Literal["Normal", "High", "Low"] = "Normal",
191
+ attachments: Optional[str | List[str]] = None,
192
+ ):
193
+ """
194
+ Sends an email to the specified recipients.
195
+
196
+ This is a wrapper function for the following API: `user: sendMail <https://learn.microsoft.com/graph/api/user-sendmail>`_.
197
+
198
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
199
+
200
+ Parameters
201
+ ----------
202
+ user : uuid.UUID | str
203
+ The user ID or user principal name.
204
+ subject : str
205
+ The email subject.
206
+ to_recipients : str | List[str]
207
+ The email address of the recipients.
208
+ content : str
209
+ The email content.
210
+ content_type : Literal["Text", "HTML"], default="Text"
211
+ The email content type. Options: "Text" or "HTML".
212
+ cc_recipients : str | List[str], default=None
213
+ The email address of the CC recipients.
214
+ bcc_recipients : str | List[str], default=None
215
+ The email address of the BCC recipients.
216
+ priority : Literal["Normal", "High", "Low"], default="Normal"
217
+ The email priority.
218
+ attachments : str | List[str], default=None
219
+ The abfss path or a list of the abfss paths of the attachments to include in the email.
220
+ """
221
+
222
+ content_type = "HTML" if content_type.lower() == "html" else "Text"
223
+
224
+ priority = priority.capitalize()
225
+ if priority not in ["Normal", "High", "Low"]:
226
+ raise ValueError(
227
+ f"{icons.red_dot} Invalid priority: {priority}. Options are: Normal, High, Low."
228
+ )
229
+
230
+ user_id = resolve_user_id(user=user)
231
+
232
+ if isinstance(to_recipients, str):
233
+ to_recipients = [to_recipients]
234
+
235
+ if isinstance(cc_recipients, str):
236
+ cc_recipients = [cc_recipients]
237
+
238
+ to_email_addresses = [
239
+ {"emailAddress": {"address": email}} for email in to_recipients
240
+ ]
241
+
242
+ cc_email_addresses = (
243
+ [{"emailAddress": {"address": email}} for email in cc_recipients]
244
+ if cc_recipients
245
+ else None
246
+ )
247
+ bcc_email_addresses = (
248
+ [{"emailAddress": {"address": email}} for email in bcc_recipients]
249
+ if bcc_recipients
250
+ else None
251
+ )
252
+
253
+ payload = {
254
+ "message": {
255
+ "subject": subject,
256
+ "body": {
257
+ "contentType": content_type,
258
+ "content": content,
259
+ },
260
+ "toRecipients": to_email_addresses,
261
+ "importance": priority,
262
+ },
263
+ }
264
+
265
+ if cc_email_addresses:
266
+ payload["message"]["ccRecipients"] = cc_email_addresses
267
+
268
+ if bcc_email_addresses:
269
+ payload["message"]["bccRecipients"] = bcc_email_addresses
270
+
271
+ # if follow_up_flag:
272
+ # payload["message"]["flag"] = {"flagStatus": "flagged"}
273
+
274
+ content_types = {
275
+ ".txt": "text/plain",
276
+ ".pdf": "application/pdf",
277
+ ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
278
+ ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
279
+ ".csv": "text/csv",
280
+ ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
281
+ ".jpg": "image/jpeg",
282
+ ".jpeg": "image/jpeg",
283
+ ".png": "image/png",
284
+ ".gif": "image/gif",
285
+ ".bmp": "image/bmp",
286
+ ".zip": "application/zip",
287
+ ".json": "application/json",
288
+ ".xml": "application/xml",
289
+ ".html": "text/html",
290
+ ".bim": "application/json",
291
+ ".pbix": "application/vnd.ms-powerbi.report",
292
+ ".pbip": "application/vnd.ms-powerbi.report",
293
+ ".pbit": "application/vnd.ms-powerbi.report",
294
+ ".vpax": "application/zip",
295
+ ".geojson": "application/geo+json",
296
+ }
297
+
298
+ def file_path_to_content_bytes(file_path):
299
+
300
+ path_parts = file_path.split("abfss://")[1].split("@")
301
+ workspace = path_parts[0]
302
+
303
+ rest = path_parts[1].split(".microsoft.com/")[1]
304
+ lakehouse, *file_parts = rest.split("/")
305
+ if lakehouse.endswith(".Lakehouse"):
306
+ lakehouse = lakehouse.removesuffix(".Lakehouse")
307
+ relative_path = os.path.join(*file_parts)
308
+
309
+ local_path = _mount(lakehouse, workspace)
310
+ full_path = os.path.join(local_path, relative_path)
311
+
312
+ with open(full_path, "rb") as file:
313
+ return base64.b64encode(file.read()).decode("utf-8")
314
+
315
+ if isinstance(attachments, str):
316
+ attachments = [attachments]
317
+ if attachments:
318
+ attachments_list = []
319
+ for attach_path in attachments:
320
+ content_bytes = file_path_to_content_bytes(attach_path)
321
+ file_extension = os.path.splitext(attach_path)[1]
322
+ content_type = content_types.get(file_extension)
323
+ if not content_type:
324
+ raise ValueError(
325
+ f"{icons.red_dot} Unsupported file type: {file_extension}. Supported types are: {', '.join(content_types.keys())}."
326
+ )
327
+ attachments_list.append(
328
+ {
329
+ "@odata.type": "#microsoft.graph.fileAttachment",
330
+ "name": attach_path.split("/")[-1],
331
+ "contentType": content_type,
332
+ "contentBytes": content_bytes,
333
+ }
334
+ )
335
+
336
+ # Add to payload
337
+ payload["message"]["attachments"] = attachments_list
338
+
339
+ _base_api(
340
+ request=f"users/{user_id}/sendMail",
341
+ client="graph",
342
+ status_codes=202,
343
+ payload=payload,
344
+ method="post",
345
+ )
346
+
347
+ printout = f"{icons.green_dot} The email has been sent to {to_recipients}"
348
+ if cc_recipients:
349
+ printout += f" and CCed to {cc_recipients}"
350
+ if bcc_recipients:
351
+ printout += f" and BCCed to {bcc_recipients}"
352
+ if attachments:
353
+ printout += f" with {len(attachments)} attachment(s)"
354
+ print(f"{printout}.")
355
+
356
+
357
+ @log
358
+ def create_user(
359
+ display_name: str,
360
+ user_principal_name: str,
361
+ mail_nickname: str,
362
+ password: str,
363
+ account_enabled: bool = True,
364
+ force_change_password_next_sign_in: bool = True,
365
+ ):
366
+ """
367
+ Creates a new user.
368
+
369
+ This is a wrapper function for the following API: `Create User <https://learn.microsoft.com/graph/api/user-post-users>`_.
370
+
371
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
372
+
373
+ Parameters
374
+ ----------
375
+ display_name : str
376
+ The name to display in the address book for the user.
377
+ user_principal_name : str
378
+ The user principal name (someuser@contoso.com).
379
+ mail_nickname : str
380
+ The mail alias for the user.
381
+ password : str
382
+ The initial password for the user.
383
+ account_enabled : bool, default=True
384
+ Whether the account is enabled. Default is True.
385
+ force_change_password_next_sign_in : bool, default=True
386
+ Whether the user must change their password on next sign-in. Default is True.
387
+ """
388
+
389
+ payload = {
390
+ "accountEnabled": account_enabled,
391
+ "displayName": display_name,
392
+ "mailNickname": mail_nickname,
393
+ "userPrincipalName": user_principal_name,
394
+ "passwordProfile": {
395
+ "forceChangePasswordNextSignIn": force_change_password_next_sign_in,
396
+ "password": password,
397
+ },
398
+ }
399
+
400
+ _base_api(
401
+ request="users",
402
+ client="graph",
403
+ status_codes=201,
404
+ payload=payload,
405
+ method="post",
406
+ )
407
+
408
+ print(f"{icons.green_dot} The '{display_name}' user has been created successfully.")
409
+
410
+
411
+ @log
412
+ def delete_user(user: str | UUID):
413
+ """
414
+ Deletes a user.
415
+
416
+ This is a wrapper function for the following API: `Delete User <https://learn.microsoft.com/graph/api/user-delete>`_.
417
+
418
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
419
+
420
+ Parameters
421
+ ----------
422
+ user : str | uuid.UUID
423
+ The user name or ID.
424
+ """
425
+
426
+ user_id = resolve_user_id(user)
427
+
428
+ _base_api(
429
+ request=f"users/{user_id}",
430
+ client="graph",
431
+ status_codes=204,
432
+ method="delete",
433
+ )
434
+
435
+ print(f"{icons.green_dot} The '{user}' user has been deleted successfully.")
436
+
437
+
438
+ @log
439
+ def update_user(
440
+ user: str | UUID,
441
+ display_name: Optional[str] = None,
442
+ user_principal_name: Optional[str] = None,
443
+ given_name: Optional[str] = None,
444
+ surname: Optional[str] = None,
445
+ job_title: Optional[str] = None,
446
+ mail_nickname: Optional[str] = None,
447
+ my_site: Optional[str] = None,
448
+ office_location: Optional[str] = None,
449
+ account_enabled: Optional[bool] = None,
450
+ ):
451
+ """
452
+ Updates a user's properties.
453
+
454
+ This is a wrapper function for the following API: `Update user <https://learn.microsoft.com/graph/api/user-update>`_.
455
+
456
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
457
+
458
+ Parameters
459
+ ----------
460
+ user : str | uuid.UUID
461
+ The user name or ID.
462
+ display_name : str, default=None
463
+ The name displayed in the address book for the user.
464
+ user_principal_name : str, default=None
465
+ The user principal name (UPN) of the user.
466
+ given_name : str, default=None
467
+ The given name (first name) of the user.
468
+ surname : str, default=None
469
+ The user's surname (family name or last name).
470
+ job_title : str, default=None
471
+ The user's job title.
472
+ mail_nickname : str, default=None
473
+ The mail alias for the user. This property must be specified when a user is created.
474
+ my_site : str, default=None
475
+ The URL for the user's personal site.
476
+ office_location : str, default=None
477
+ The office location in the user's place of business.
478
+ account_enabled : bool, default=None
479
+ Whether the account is enabled. If None, the property will not be updated.
480
+ """
481
+
482
+ user_id = resolve_user_id(user)
483
+
484
+ payload = {}
485
+ if display_name is not None:
486
+ payload["displayName"] = display_name
487
+ if mail_nickname is not None:
488
+ payload["mailNickname"] = mail_nickname
489
+ if user_principal_name is not None:
490
+ payload["userPrincipalName"] = user_principal_name
491
+ if given_name is not None:
492
+ payload["givenName"] = given_name
493
+ if job_title is not None:
494
+ payload["jobTitle"] = job_title
495
+ if my_site is not None:
496
+ payload["mySite"] = my_site
497
+ if office_location is not None:
498
+ payload["officeLocation"] = office_location
499
+ if surname is not None:
500
+ payload["surname"] = surname
501
+ if account_enabled is not None and isinstance(account_enabled, bool):
502
+ payload["accountEnabled"] = account_enabled
503
+
504
+ if not payload:
505
+ print(f"{icons.info} No properties to update.")
506
+ return
507
+
508
+ _base_api(
509
+ request=f"users/{user_id}",
510
+ client="graph",
511
+ status_codes=204,
512
+ payload=payload,
513
+ method="patch",
514
+ )
515
+
516
+ print(f"{icons.green_dot} The '{user}' user has been updated successfully.")
@@ -0,0 +1,15 @@
1
+ from ._items import (
2
+ list_graph_models,
3
+ execute_query,
4
+ get_queryable_graph_type,
5
+ )
6
+ from ._background_jobs import (
7
+ refresh_graph,
8
+ )
9
+
10
+ __all__ = [
11
+ "list_graph_models",
12
+ "execute_query",
13
+ "get_queryable_graph_type",
14
+ "refresh_graph",
15
+ ]
@@ -0,0 +1,63 @@
1
+ import pandas as pd
2
+ from uuid import UUID
3
+ from typing import Optional
4
+ from sempy._utils._log import log
5
+ from sempy_labs._helper_functions import (
6
+ _base_api,
7
+ resolve_item_name_and_id,
8
+ resolve_workspace_name_and_id,
9
+ )
10
+ import sempy_labs._icons as icons
11
+
12
+
13
+ @log
14
+ def refresh_graph(
15
+ graph_model: str | UUID, workspace: Optional[str | UUID] = None
16
+ ) -> pd.DataFrame:
17
+ """
18
+ Refreshes the graph model.
19
+
20
+ This is a wrapper function for the following API: `Background Jobs - Run On Demand Refresh Graph <https://learn.microsoft.com/rest/api/fabric/graphmodel/background-jobs/run-on-demand-refresh-graph>`_.
21
+
22
+ Parameters
23
+ ----------
24
+ graph_model : str | uuid.UUID
25
+ The graph model name or ID.
26
+ workspace : str | uuid.UUID, default=None
27
+ The Fabric workspace name or ID.
28
+ Defaults to None which resolves to the workspace of the attached lakehouse
29
+ or if no lakehouse attached, resolves to the workspace of the notebook.
30
+
31
+ Returns
32
+ -------
33
+ pandas.DataFrame
34
+ A pandas dataframe showing the result of the refresh operation.
35
+ """
36
+
37
+ (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
38
+ (item_name, item_id) = resolve_item_name_and_id(
39
+ item=graph_model, type="GraphModel", workspace=workspace_id
40
+ )
41
+
42
+ print(
43
+ f"{icons.in_progress} The refresh graph job for the '{item_name}' graph model within the '{workspace_name}' workspace has been initiated."
44
+ )
45
+
46
+ df = _base_api(
47
+ request=f"/v1/workspaces/{workspace_id}/GraphModels/{item_id}/jobs/instances?jobType=RefreshGraph",
48
+ method="post",
49
+ lro_return_df=True,
50
+ )
51
+ status = df["Status"].iloc[0]
52
+
53
+ if status == "Completed":
54
+ print(
55
+ f"{icons.green_dot} The refresh graph job for the '{item_name}' graph model within the '{workspace_name}' workspace has succeeded."
56
+ )
57
+ else:
58
+ print(status)
59
+ print(
60
+ f"{icons.red_dot} The refresh graph job for the '{item_name}' graph model within the '{workspace_name}' workspace has failed."
61
+ )
62
+
63
+ return df