semantic-link-labs 0.9.11__py3-none-any.whl → 0.10.1__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.

@@ -0,0 +1,15 @@
1
+ from sempy_labs.mirrored_azure_databricks_catalog._refresh_catalog_metadata import (
2
+ refresh_catalog_metadata,
3
+ )
4
+ from sempy_labs.mirrored_azure_databricks_catalog._discover import (
5
+ discover_catalogs,
6
+ discover_schemas,
7
+ discover_tables,
8
+ )
9
+
10
+ __all__ = [
11
+ "refresh_catalog_metadata",
12
+ "discover_catalogs",
13
+ "discover_schemas",
14
+ "discover_tables",
15
+ ]
@@ -0,0 +1,209 @@
1
+ from uuid import UUID
2
+ from typing import Optional
3
+ from sempy_labs._helper_functions import (
4
+ resolve_workspace_id,
5
+ _base_api,
6
+ _create_dataframe,
7
+ )
8
+ import pandas as pd
9
+
10
+
11
+ def discover_catalogs(
12
+ databricks_workspace_connection_id: UUID,
13
+ workspace: Optional[str | UUID] = None,
14
+ max_results: Optional[int] = None,
15
+ ) -> pd.DataFrame:
16
+ """
17
+ Returns a list of catalogs from Unity Catalog.
18
+
19
+ This is a wrapper function for the following API: `Databricks Metadata Discovery - Discover Catalogs <https://learn.microsoft.comrest/api/fabric/mirroredazuredatabrickscatalog/databricks-metadata-discovery/discover-catalogs>`_.
20
+
21
+ Parameters
22
+ ----------
23
+ databricks_workspace_connection_id : uuid.UUID
24
+ The ID of the Databricks workspace connection.
25
+ workspace : str | uuid.UUID, default=None
26
+ The workspace name or ID.
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
+ max_results : int, default=None
30
+ The maximum number of results to return. If not specified, all results are returned.
31
+
32
+ Returns
33
+ -------
34
+ pandas.DataFrame
35
+ A pandas dataframe showing a list of catalogs from Unity Catalog.
36
+ """
37
+
38
+ workspace_id = resolve_workspace_id(workspace)
39
+
40
+ url = f"/v1/workspaces/{workspace_id}/azuredatabricks/catalogs?databricksWorkspaceConnectionId={databricks_workspace_connection_id}"
41
+ if max_results:
42
+ url += f"&maxResults={max_results}"
43
+
44
+ responses = _base_api(request=url, uses_pagination=True)
45
+
46
+ columns = {
47
+ "Catalog Name": "str",
48
+ "Catalog Full Name": "str",
49
+ "Catalog Type": "str",
50
+ "Storage Location": "str",
51
+ }
52
+
53
+ df = _create_dataframe(columns=columns)
54
+
55
+ dfs = []
56
+ for r in responses:
57
+ for i in r.get("value", []):
58
+ new_data = {
59
+ "Catalog Name": i.get("name"),
60
+ "Catalog Full Name": i.get("fullName"),
61
+ "Catalog Type": i.get("catalogType"),
62
+ "Storage Location": i.get("storageLocation"),
63
+ }
64
+
65
+ dfs.append(pd.DataFrame(new_data, index=[0]))
66
+
67
+ if dfs:
68
+ df = pd.concat(dfs, ignore_index=True)
69
+
70
+ return df
71
+
72
+
73
+ def discover_schemas(
74
+ catalog: str,
75
+ databricks_workspace_connection_id: UUID,
76
+ workspace: Optional[str | UUID] = None,
77
+ max_results: Optional[int] = None,
78
+ ) -> pd.DataFrame:
79
+ """
80
+ Returns a list of schemas in the given catalog from Unity Catalog.
81
+
82
+ This is a wrapper function for the following API: `Databricks Metadata Discovery - Discover Schemas <https://learn.microsoft.comrest/api/fabric/mirroredazuredatabrickscatalog/databricks-metadata-discovery/discover-schemas>`_.
83
+
84
+ Parameters
85
+ ----------
86
+ catalog : str
87
+ The name of the catalog.
88
+ databricks_workspace_connection_id : uuid.UUID
89
+ The ID of the Databricks workspace connection.
90
+ workspace : str | uuid.UUID, default=None
91
+ The workspace name or ID.
92
+ Defaults to None which resolves to the workspace of the attached lakehouse
93
+ or if no lakehouse attached, resolves to the workspace of the notebook.
94
+ max_results : int, default=None
95
+ The maximum number of results to return. If not specified, all results are returned.
96
+
97
+ Returns
98
+ -------
99
+ pandas.DataFrame
100
+ A pandas dataframe showing a list of schemas in the given catalog from Unity Catalog.
101
+ """
102
+
103
+ workspace_id = resolve_workspace_id(workspace)
104
+
105
+ url = f"/v1/workspaces/{workspace_id}/azuredatabricks/catalogs/{catalog}/schemas?databricksWorkspaceConnectionId={databricks_workspace_connection_id}"
106
+ if max_results:
107
+ url += f"&maxResults={max_results}"
108
+
109
+ responses = _base_api(request=url, uses_pagination=True)
110
+
111
+ columns = {
112
+ "Catalog Name": "str",
113
+ "Schema Name": "str",
114
+ "Schema Full Name": "str",
115
+ "Storage Location": "str",
116
+ }
117
+
118
+ df = _create_dataframe(columns=columns)
119
+
120
+ dfs = []
121
+ for r in responses:
122
+ for i in r.get("value", []):
123
+ new_data = {
124
+ "Catalog Name": catalog,
125
+ "Schema Name": i.get("name"),
126
+ "Schema Full Name": i.get("fullName"),
127
+ "Storage Location": i.get("storageLocation"),
128
+ }
129
+
130
+ dfs.append(pd.DataFrame(new_data, index=[0]))
131
+
132
+ if dfs:
133
+ df = pd.concat(dfs, ignore_index=True)
134
+
135
+ return df
136
+
137
+
138
+ def discover_tables(
139
+ catalog: str,
140
+ schema: str,
141
+ databricks_workspace_connection_id: UUID,
142
+ workspace: Optional[str | UUID] = None,
143
+ max_results: Optional[int] = None,
144
+ ) -> pd.DataFrame:
145
+ """
146
+ Returns a list of schemas in the given catalog from Unity Catalog.
147
+
148
+ This is a wrapper function for the following API: `Databricks Metadata Discovery - Discover Tables <https://learn.microsoft.comrest/api/fabric/mirroredazuredatabrickscatalog/databricks-metadata-discovery/discover-tables>`_.
149
+
150
+ Parameters
151
+ ----------
152
+ catalog : str
153
+ The name of the catalog.
154
+ schema : str
155
+ The name of the schema.
156
+ databricks_workspace_connection_id : uuid.UUID
157
+ The ID of the Databricks workspace connection.
158
+ workspace : str | uuid.UUID, default=None
159
+ The workspace name or ID.
160
+ Defaults to None which resolves to the workspace of the attached lakehouse
161
+ or if no lakehouse attached, resolves to the workspace of the notebook.
162
+ max_results : int, default=None
163
+ The maximum number of results to return. If not specified, all results are returned.
164
+
165
+ Returns
166
+ -------
167
+ pandas.DataFrame
168
+ A pandas dataframe showing a list of schemas in the given catalog from Unity Catalog.
169
+ """
170
+
171
+ workspace_id = resolve_workspace_id(workspace)
172
+
173
+ url = f"/v1/workspaces/{workspace_id}/azuredatabricks/catalogs/{catalog}/schemas/{schema}/tables?databricksWorkspaceConnectionId={databricks_workspace_connection_id}"
174
+ if max_results:
175
+ url += f"&maxResults={max_results}"
176
+
177
+ responses = _base_api(request=url, uses_pagination=True)
178
+
179
+ columns = {
180
+ "Catalog Name": "str",
181
+ "Schema Name": "str",
182
+ "Table Name": "str",
183
+ "Table Full Name": "str",
184
+ "Storage Location": "str",
185
+ "Table Type": "str",
186
+ "Data Source Format": "str",
187
+ }
188
+
189
+ df = _create_dataframe(columns=columns)
190
+
191
+ dfs = []
192
+ for r in responses:
193
+ for i in r.get("value", []):
194
+ new_data = {
195
+ "Catalog Name": catalog,
196
+ "Schema Name": schema,
197
+ "Table Name": i.get("name"),
198
+ "Table Full Name": i.get("fullName"),
199
+ "Storage Location": i.get("storageLocation"),
200
+ "Table Type": i.get("tableType"),
201
+ "Data Source Format": i.get("dataSourceFormat"),
202
+ }
203
+
204
+ dfs.append(pd.DataFrame(new_data, index=[0]))
205
+
206
+ if dfs:
207
+ df = pd.concat(dfs, ignore_index=True)
208
+
209
+ return df
@@ -0,0 +1,43 @@
1
+ from uuid import UUID
2
+ from typing import Optional
3
+ from sempy_labs._helper_functions import (
4
+ resolve_workspace_name_and_id,
5
+ resolve_item_name_and_id,
6
+ _base_api,
7
+ )
8
+ import sempy_labs._icons as icons
9
+
10
+
11
+ def refresh_catalog_metadata(
12
+ mirrored_azure_databricks_catalog: str | UUID,
13
+ workspace: Optional[str | UUID] = None,
14
+ ):
15
+ """
16
+ Refresh Databricks catalog metadata in mirroredAzureDatabricksCatalogs Item.
17
+
18
+ This is a wrapper function for the following API: `Refresh Metadata - Items RefreshCatalogMetadata <https://learn.microsoft.com/rest/api/fabric/mirroredazuredatabrickscatalog/refresh-metadata/items-refresh-catalog-metadata>`_.
19
+
20
+ Parameters
21
+ ----------
22
+ mirrored_azure_databricks_catalog : str | uuid.UUID
23
+ The name or ID of the mirrored Azure Databricks catalog.
24
+ workspace : str | uuie.UUID, default=None
25
+ The workspace name or ID.
26
+ Defaults to None which resolves to the workspace of the attached lakehouse
27
+ or if no lakehouse attached, resolves to the workspace of the notebook
28
+ """
29
+
30
+ (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
31
+ (catalog_name, catalog_id) = resolve_item_name_and_id(
32
+ mirrored_azure_databricks_catalog
33
+ )
34
+
35
+ _base_api(
36
+ request=f"/v1/workspaces/{workspace_id}/mirroredAzureDatabricksCatalogs/{catalog_id}/refreshCatalogMetadata",
37
+ method="post",
38
+ lro_return_status_code=True,
39
+ )
40
+
41
+ print(
42
+ f"{icons.green_dot} The '{catalog_name}' Databricks Catalog metadata within the '{workspace_name}' workspace has been refreshed."
43
+ )
@@ -3,6 +3,7 @@ from sempy_labs.report._save_report import (
3
3
  )
4
4
  from sempy_labs.report._reportwrapper import (
5
5
  ReportWrapper,
6
+ connect_report,
6
7
  )
7
8
  from sempy_labs.report._paginated import (
8
9
  get_report_datasources,
@@ -50,4 +51,5 @@ __all__ = [
50
51
  "get_report_datasources",
51
52
  "download_report",
52
53
  "save_report_as_pbip",
54
+ "connect_report",
53
55
  ]
@@ -1,14 +1,5 @@
1
- import sempy.fabric as fabric
2
- from typing import Tuple, Optional
3
- import sempy_labs._icons as icons
4
- import re
5
- import base64
6
- import json
7
1
  import requests
8
- from uuid import UUID
9
- from sempy_labs._helper_functions import (
10
- resolve_workspace_name_and_id,
11
- )
2
+ import sempy_labs._icons as icons
12
3
 
13
4
 
14
5
  vis_type_mapping = {
@@ -47,10 +38,9 @@ vis_type_mapping = {
47
38
  "decompositionTreeVisual": "Decomposition tree",
48
39
  "qnaVisual": "Q&A",
49
40
  "aiNarratives": "Narrative",
50
- "scorecard": "Metrics (Preview)",
41
+ "scorecard": "Goals (Preview)",
51
42
  "rdlVisual": "Paginated report",
52
43
  "cardVisual": "Card (new)",
53
- "advancedSlicerVisual": "Slicer (new)",
54
44
  "actionButton": "Button",
55
45
  "bookmarkNavigator": "Bookmark navigator",
56
46
  "image": "Image",
@@ -58,8 +48,33 @@ vis_type_mapping = {
58
48
  "pageNavigator": "Page navigator",
59
49
  "shape": "Shape",
60
50
  "Group": "Group",
51
+ "listSlicer": "List Slicer",
52
+ "advancedSlicerVisual": "Button Slicer",
53
+ "FlowVisual_C29F1DCC_81F5_4973_94AD_0517D44CC06A": "Power Automate for Power BI",
61
54
  }
62
55
 
56
+
57
+ def generate_visual_file_path(page_file_path: str, visual_id: str) -> str:
58
+
59
+ return page_file_path.split("/page.json")[0] + f"/visuals/{visual_id}.json"
60
+
61
+
62
+ def resolve_visual_type(visual_type: str) -> str:
63
+ vt_lower = visual_type.lower()
64
+
65
+ vis_map_lower = {k.lower(): v for k, v in vis_type_mapping.items()}
66
+ flipped_lower = {v.lower(): k for k, v in vis_type_mapping.items()}
67
+
68
+ if vt_lower in vis_map_lower:
69
+ resolved = vis_map_lower.get(vt_lower)
70
+ elif vt_lower in flipped_lower:
71
+ resolved = flipped_lower.get(vt_lower)
72
+ else:
73
+ raise ValueError(f"{icons.red_dot} Unknown visual type: {visual_type}")
74
+
75
+ return resolved
76
+
77
+
63
78
  page_type_mapping = {
64
79
  (320, 240): "Tooltip",
65
80
  (816, 1056): "Letter",
@@ -70,22 +85,6 @@ page_type_mapping = {
70
85
  page_types = ["Tooltip", "Letter", "4:3", "16:9"]
71
86
 
72
87
 
73
- def get_web_url(report: str, workspace: Optional[str | UUID] = None):
74
-
75
- (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
76
-
77
- dfR = fabric.list_reports(workspace=workspace_id)
78
- dfR_filt = dfR[dfR["Name"] == report]
79
-
80
- if len(dfR_filt) == 0:
81
- raise ValueError(
82
- f"{icons.red_dot} The '{report}' report does not exist within the '{workspace_name}' workspace."
83
- )
84
- web_url = dfR_filt["Web Url"].iloc[0]
85
-
86
- return web_url
87
-
88
-
89
88
  def populate_custom_visual_display_names():
90
89
 
91
90
  url = "https://catalogapi.azure.com/offers?api-version=2018-08-01-beta&storefront=appsource&$filter=offerType+eq+%27PowerBIVisuals%27"
@@ -128,106 +127,6 @@ def populate_custom_visual_display_names():
128
127
  vis_type_mapping[vizId] = displayName
129
128
 
130
129
 
131
- def resolve_page_name(self, page_name: str) -> Tuple[str, str, str]:
132
-
133
- dfP = self.list_pages()
134
- if any(r["Page Name"] == page_name for _, r in dfP.iterrows()):
135
- valid_page_name = page_name
136
- dfP_filt = dfP[dfP["Page Name"] == page_name]
137
- valid_display_name = dfP_filt["Page Display Name"].iloc[0]
138
- file_path = dfP_filt["File Path"].iloc[0]
139
- elif any(r["Page Display Name"] == page_name for _, r in dfP.iterrows()):
140
- valid_display_name = page_name
141
- dfP_filt = dfP[dfP["Page Display Name"] == page_name]
142
- valid_page_name = dfP_filt["Page Name"].iloc[0]
143
- file_path = dfP_filt["File Path"].iloc[0]
144
- else:
145
- raise ValueError(
146
- f"{icons.red_dot} Invalid page name. The '{page_name}' page does not exist in the '{self._report}' report within the '{self._workspace}' workspace."
147
- )
148
-
149
- return valid_page_name, valid_display_name, file_path
150
-
151
-
152
- def visual_page_mapping(self) -> Tuple[dict, dict]:
153
-
154
- page_mapping = {}
155
- visual_mapping = {}
156
- rd = self.rdef
157
- for _, r in rd.iterrows():
158
- file_path = r["path"]
159
- payload = r["payload"]
160
- if file_path.endswith("/page.json"):
161
- pattern_page = r"/pages/(.*?)/page.json"
162
- page_name = re.search(pattern_page, file_path).group(1)
163
- obj_file = base64.b64decode(payload).decode("utf-8")
164
- obj_json = json.loads(obj_file)
165
- page_id = obj_json.get("name")
166
- page_display = obj_json.get("displayName")
167
- page_mapping[page_name] = (page_id, page_display)
168
- for _, r in rd.iterrows():
169
- file_path = r["path"]
170
- payload = r["payload"]
171
- if file_path.endswith("/visual.json"):
172
- pattern_page = r"/pages/(.*?)/visuals/"
173
- page_name = re.search(pattern_page, file_path).group(1)
174
- visual_mapping[file_path] = (
175
- page_mapping.get(page_name)[0],
176
- page_mapping.get(page_name)[1],
177
- )
178
-
179
- return page_mapping, visual_mapping
180
-
181
-
182
- def resolve_visual_name(
183
- self, page_name: str, visual_name: str
184
- ) -> Tuple[str, str, str, str]:
185
- """
186
- Obtains the page name, page display name, and the file path for a given page in a report.
187
-
188
- Parameters
189
- ----------
190
- page_name : str
191
- The name of the page of the report - either the page name (GUID) or the page display name.
192
- visual_name : str
193
- The name of the visual of the report.
194
-
195
- Returns
196
- -------
197
- Tuple[str, str, str, str] Page name, page display name, visual name, file path from the report definition.
198
-
199
- """
200
-
201
- dfV = self.list_visuals()
202
- if any(
203
- (r["Page Name"] == page_name) & (r["Visual Name"] == visual_name)
204
- for _, r in dfV.iterrows()
205
- ):
206
- valid_page_name = page_name
207
- dfV_filt = dfV[
208
- (dfV["Page Name"] == page_name) & (dfV["Visual Name"] == visual_name)
209
- ]
210
- file_path = dfV_filt["File Path"].iloc[0]
211
- valid_display_name = dfV_filt["Page Display Name"].iloc[0]
212
- elif any(
213
- (r["Page Display Name"] == page_name) & (r["Visual Name"] == visual_name)
214
- for _, r in dfV.iterrows()
215
- ):
216
- valid_display_name = page_name
217
- dfV_filt = dfV[
218
- (dfV["Page Display Name"] == page_name)
219
- & (dfV["Visual Name"] == visual_name)
220
- ]
221
- file_path = dfV_filt["File Path"].iloc[0]
222
- valid_page_name = dfV_filt["Page Name"].iloc[0]
223
- else:
224
- raise ValueError(
225
- f"{icons.red_dot} Invalid page/visual name. The '{visual_name}' visual on the '{page_name}' page does not exist in the '{self._report}' report within the '{self._workspace}' workspace."
226
- )
227
-
228
- return valid_page_name, valid_display_name, visual_name, file_path
229
-
230
-
231
130
  def find_entity_property_pairs(data, result=None, keys_path=None):
232
131
 
233
132
  if result is None: