semantic-link-labs 0.9.3__py3-none-any.whl → 0.9.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.
- {semantic_link_labs-0.9.3.dist-info → semantic_link_labs-0.9.4.dist-info}/METADATA +9 -6
- {semantic_link_labs-0.9.3.dist-info → semantic_link_labs-0.9.4.dist-info}/RECORD +41 -31
- {semantic_link_labs-0.9.3.dist-info → semantic_link_labs-0.9.4.dist-info}/WHEEL +1 -1
- sempy_labs/__init__.py +27 -1
- sempy_labs/_capacity_migration.py +3 -2
- sempy_labs/_dax.py +17 -3
- sempy_labs/_delta_analyzer.py +279 -127
- sempy_labs/_eventhouses.py +70 -1
- sempy_labs/_generate_semantic_model.py +30 -9
- sempy_labs/_helper_functions.py +30 -1
- sempy_labs/_job_scheduler.py +226 -2
- sempy_labs/_list_functions.py +40 -16
- sempy_labs/_model_bpa.py +15 -0
- sempy_labs/_model_bpa_rules.py +12 -2
- sempy_labs/_semantic_models.py +117 -0
- sempy_labs/_sql.py +73 -6
- sempy_labs/_sqldatabase.py +227 -0
- sempy_labs/admin/__init__.py +49 -8
- sempy_labs/admin/_activities.py +166 -0
- sempy_labs/admin/_apps.py +143 -0
- sempy_labs/admin/_basic_functions.py +32 -652
- sempy_labs/admin/_capacities.py +250 -0
- sempy_labs/admin/_datasets.py +184 -0
- sempy_labs/admin/_domains.py +1 -1
- sempy_labs/admin/_items.py +3 -1
- sempy_labs/admin/_reports.py +165 -0
- sempy_labs/admin/_scanner.py +0 -1
- sempy_labs/admin/_shared.py +74 -0
- sempy_labs/admin/_tenant.py +489 -0
- sempy_labs/directlake/_dl_helper.py +0 -1
- sempy_labs/directlake/_update_directlake_partition_entity.py +6 -0
- sempy_labs/graph/_teams.py +1 -1
- sempy_labs/graph/_users.py +9 -1
- sempy_labs/lakehouse/_shortcuts.py +28 -15
- sempy_labs/report/__init__.py +3 -1
- sempy_labs/report/_download_report.py +4 -1
- sempy_labs/report/_export_report.py +272 -0
- sempy_labs/report/_report_functions.py +9 -261
- sempy_labs/tom/_model.py +278 -29
- {semantic_link_labs-0.9.3.dist-info → semantic_link_labs-0.9.4.dist-info}/LICENSE +0 -0
- {semantic_link_labs-0.9.3.dist-info → semantic_link_labs-0.9.4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from uuid import UUID
|
|
3
|
+
import sempy_labs._icons as icons
|
|
4
|
+
from typing import Optional, Tuple
|
|
5
|
+
from sempy._utils._log import log
|
|
6
|
+
from sempy_labs._helper_functions import (
|
|
7
|
+
_base_api,
|
|
8
|
+
_create_dataframe,
|
|
9
|
+
_update_dataframe_datatypes,
|
|
10
|
+
_is_valid_uuid,
|
|
11
|
+
get_capacity_id,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def patch_capacity(capacity: str | UUID, tenant_key_id: UUID):
|
|
16
|
+
"""
|
|
17
|
+
Changes specific capacity information. Currently, this API call only supports changing the capacity's encryption key.
|
|
18
|
+
|
|
19
|
+
This is a wrapper function for the following API: `Admin - Patch Capacity As Admin <https://learn.microsoft.com/rest/api/power-bi/admin/patch-capacity-as-admin>`_.
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
capacity : str | uuid.UUID
|
|
24
|
+
The name or ID of the capacity.
|
|
25
|
+
tenant_key_id : str
|
|
26
|
+
The ID of the encryption key.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
(capacity_name, capacity_id) = _resolve_capacity_name_and_id(capacity)
|
|
30
|
+
|
|
31
|
+
payload = {
|
|
32
|
+
"tenantKeyId": tenant_key_id,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
_base_api(
|
|
36
|
+
request=f"/v1.0/myorg/admin/capacities/{capacity_id}",
|
|
37
|
+
method="patch",
|
|
38
|
+
payload=payload,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
print(
|
|
42
|
+
f"{icons.green_dot} The capacity '{capacity_name}' has been successfully patched."
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _resolve_capacity_name_and_id(
|
|
47
|
+
capacity: str | UUID,
|
|
48
|
+
) -> Tuple[str, UUID]:
|
|
49
|
+
|
|
50
|
+
dfC = list_capacities(capacity=capacity)
|
|
51
|
+
if dfC.empty:
|
|
52
|
+
raise ValueError(f"{icons.red_dot} The '{capacity}' capacity was not found.")
|
|
53
|
+
|
|
54
|
+
capacity_name = dfC["Capacity Name"].iloc[0]
|
|
55
|
+
capacity_id = dfC["Capacity Id"].iloc[0]
|
|
56
|
+
|
|
57
|
+
return capacity_name, capacity_id
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _list_capacities_meta() -> pd.DataFrame:
|
|
61
|
+
"""
|
|
62
|
+
Shows the a list of capacities and their properties. This function is the admin version.
|
|
63
|
+
|
|
64
|
+
This is a wrapper function for the following API: `Admin - Get Capacities As Admin <https://learn.microsoft.com/rest/api/power-bi/admin/get-capacities-as-admin>`_.
|
|
65
|
+
|
|
66
|
+
Returns
|
|
67
|
+
-------
|
|
68
|
+
pandas.DataFrame
|
|
69
|
+
A pandas dataframe showing the capacities and their properties
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
columns = {
|
|
73
|
+
"Capacity Id": "string",
|
|
74
|
+
"Capacity Name": "string",
|
|
75
|
+
"Sku": "string",
|
|
76
|
+
"Region": "string",
|
|
77
|
+
"State": "string",
|
|
78
|
+
"Admins": "string",
|
|
79
|
+
}
|
|
80
|
+
df = _create_dataframe(columns=columns)
|
|
81
|
+
|
|
82
|
+
responses = _base_api(
|
|
83
|
+
request="/v1.0/myorg/admin/capacities", client="fabric_sp", uses_pagination=True
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
for r in responses:
|
|
87
|
+
for i in r.get("value", []):
|
|
88
|
+
new_data = {
|
|
89
|
+
"Capacity Id": i.get("id").lower(),
|
|
90
|
+
"Capacity Name": i.get("displayName"),
|
|
91
|
+
"Sku": i.get("sku"),
|
|
92
|
+
"Region": i.get("region"),
|
|
93
|
+
"State": i.get("state"),
|
|
94
|
+
"Admins": [i.get("admins", [])],
|
|
95
|
+
}
|
|
96
|
+
df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
|
|
97
|
+
|
|
98
|
+
return df
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def get_capacity_assignment_status(
|
|
102
|
+
workspace: Optional[str | UUID] = None,
|
|
103
|
+
) -> pd.DataFrame:
|
|
104
|
+
"""
|
|
105
|
+
Gets the status of the assignment-to-capacity operation for the specified workspace.
|
|
106
|
+
|
|
107
|
+
This is a wrapper function for the following API: `Capacities - Groups CapacityAssignmentStatus <https://learn.microsoft.com/rest/api/power-bi/capacities/groups-capacity-assignment-status>`_.
|
|
108
|
+
|
|
109
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
110
|
+
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
workspace : str | uuid.UUID, default=None
|
|
114
|
+
The workspace name or ID.
|
|
115
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
116
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
117
|
+
|
|
118
|
+
Returns
|
|
119
|
+
-------
|
|
120
|
+
pandas.DataFrame
|
|
121
|
+
A pandas dataframe showing the status of the assignment-to-capacity operation for the specified workspace.
|
|
122
|
+
"""
|
|
123
|
+
from sempy_labs.admin._basic_functions import _resolve_workspace_name_and_id
|
|
124
|
+
|
|
125
|
+
(workspace_name, workspace_id) = _resolve_workspace_name_and_id(workspace)
|
|
126
|
+
|
|
127
|
+
columns = {
|
|
128
|
+
"Status": "string",
|
|
129
|
+
"Activity Id": "string",
|
|
130
|
+
"Start Time": "datetime",
|
|
131
|
+
"End Time": "datetime",
|
|
132
|
+
"Capacity Id": "string",
|
|
133
|
+
"Capacity Name": "string",
|
|
134
|
+
}
|
|
135
|
+
df = _create_dataframe(columns=columns)
|
|
136
|
+
|
|
137
|
+
response = _base_api(
|
|
138
|
+
request=f"/v1.0/myorg/groups/{workspace_id}/CapacityAssignmentStatus",
|
|
139
|
+
client="fabric_sp",
|
|
140
|
+
)
|
|
141
|
+
v = response.json()
|
|
142
|
+
capacity_id = v.get("capacityId")
|
|
143
|
+
|
|
144
|
+
(capacity_name, capacity_id) = _resolve_capacity_name_and_id(capacity=capacity_id)
|
|
145
|
+
|
|
146
|
+
new_data = {
|
|
147
|
+
"Status": v.get("status"),
|
|
148
|
+
"Activity Id": v.get("activityId"),
|
|
149
|
+
"Start Time": v.get("startTime"),
|
|
150
|
+
"End Time": v.get("endTime"),
|
|
151
|
+
"Capacity Id": capacity_id,
|
|
152
|
+
"Capacity Name": capacity_name,
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
df = pd.concat([df, pd.DataFrame([new_data])], ignore_index=True)
|
|
156
|
+
|
|
157
|
+
_update_dataframe_datatypes(dataframe=df, column_map=columns)
|
|
158
|
+
|
|
159
|
+
return df
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def get_capacity_state(capacity: Optional[str | UUID] = None):
|
|
163
|
+
"""
|
|
164
|
+
Gets the state of a capacity.
|
|
165
|
+
|
|
166
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
167
|
+
|
|
168
|
+
Parameters
|
|
169
|
+
----------
|
|
170
|
+
capacity : str | uuid.UUID, default=None
|
|
171
|
+
The capacity name or ID.
|
|
172
|
+
Defaults to None which resolves to the capacity of the attached lakehouse
|
|
173
|
+
or if no lakehouse is attached, resolves to the workspace of the notebook.
|
|
174
|
+
|
|
175
|
+
Returns
|
|
176
|
+
-------
|
|
177
|
+
str
|
|
178
|
+
The capacity state.
|
|
179
|
+
"""
|
|
180
|
+
|
|
181
|
+
df = list_capacities()
|
|
182
|
+
|
|
183
|
+
if capacity is None:
|
|
184
|
+
capacity = get_capacity_id()
|
|
185
|
+
if _is_valid_uuid(capacity):
|
|
186
|
+
df_filt = df[df["Capacity Id"] == capacity]
|
|
187
|
+
else:
|
|
188
|
+
df_filt = df[df["Capacity Name"] == capacity]
|
|
189
|
+
|
|
190
|
+
if df_filt.empty:
|
|
191
|
+
raise ValueError(f"{icons.red_dot} The capacity '{capacity}' was not found.")
|
|
192
|
+
|
|
193
|
+
return df_filt["State"].iloc[0]
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
@log
|
|
197
|
+
def list_capacities(
|
|
198
|
+
capacity: Optional[str | UUID] = None,
|
|
199
|
+
) -> pd.DataFrame:
|
|
200
|
+
"""
|
|
201
|
+
Shows the a list of capacities and their properties.
|
|
202
|
+
|
|
203
|
+
This is a wrapper function for the following API: `Admin - Get Capacities As Admin <https://learn.microsoft.com/rest/api/power-bi/admin/get-capacities-as-admin>`_.
|
|
204
|
+
|
|
205
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
206
|
+
|
|
207
|
+
Parameters
|
|
208
|
+
----------
|
|
209
|
+
capacity : str | uuid.UUID, default=None
|
|
210
|
+
The capacity name or ID to filter. If None, all capacities are returned.
|
|
211
|
+
|
|
212
|
+
Returns
|
|
213
|
+
-------
|
|
214
|
+
pandas.DataFrame
|
|
215
|
+
A pandas dataframe showing the capacities and their properties.
|
|
216
|
+
"""
|
|
217
|
+
|
|
218
|
+
columns = {
|
|
219
|
+
"Capacity Id": "string",
|
|
220
|
+
"Capacity Name": "string",
|
|
221
|
+
"Sku": "string",
|
|
222
|
+
"Region": "string",
|
|
223
|
+
"State": "string",
|
|
224
|
+
"Admins": "string",
|
|
225
|
+
}
|
|
226
|
+
df = _create_dataframe(columns=columns)
|
|
227
|
+
|
|
228
|
+
responses = _base_api(
|
|
229
|
+
request="/v1.0/myorg/admin/capacities", client="fabric_sp", uses_pagination=True
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
for r in responses:
|
|
233
|
+
for i in r.get("value", []):
|
|
234
|
+
new_data = {
|
|
235
|
+
"Capacity Id": i.get("id").lower(),
|
|
236
|
+
"Capacity Name": i.get("displayName"),
|
|
237
|
+
"Sku": i.get("sku"),
|
|
238
|
+
"Region": i.get("region"),
|
|
239
|
+
"State": i.get("state"),
|
|
240
|
+
"Admins": [i.get("admins", [])],
|
|
241
|
+
}
|
|
242
|
+
df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
|
|
243
|
+
|
|
244
|
+
if capacity is not None:
|
|
245
|
+
if _is_valid_uuid(capacity):
|
|
246
|
+
df = df[df["Capacity Id"] == capacity.lower()]
|
|
247
|
+
else:
|
|
248
|
+
df = df[df["Capacity Name"] == capacity]
|
|
249
|
+
|
|
250
|
+
return df
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from typing import Optional
|
|
3
|
+
from sempy_labs._helper_functions import (
|
|
4
|
+
_build_url,
|
|
5
|
+
_base_api,
|
|
6
|
+
_create_dataframe,
|
|
7
|
+
_update_dataframe_datatypes,
|
|
8
|
+
_is_valid_uuid,
|
|
9
|
+
)
|
|
10
|
+
from uuid import UUID
|
|
11
|
+
import sempy_labs._icons as icons
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def list_datasets(
|
|
15
|
+
top: Optional[int] = None,
|
|
16
|
+
filter: Optional[str] = None,
|
|
17
|
+
skip: Optional[int] = None,
|
|
18
|
+
) -> pd.DataFrame:
|
|
19
|
+
"""
|
|
20
|
+
Shows a list of datasets for the organization.
|
|
21
|
+
|
|
22
|
+
This is a wrapper function for the following API: `Admin - Datasets GetDatasetsAsAdmin <https://learn.microsoft.com/rest/api/power-bi/admin/datasets-get-datasets-as-admin>`_.
|
|
23
|
+
|
|
24
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
top : int, default=None
|
|
29
|
+
Returns only the first n results.
|
|
30
|
+
filter : str, default=None
|
|
31
|
+
Returns a subset of a results based on Odata filter query parameter condition.
|
|
32
|
+
skip : int, default=None
|
|
33
|
+
Skips the first n results.
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
pandas.DataFrame
|
|
38
|
+
A pandas dataframe showing a list of datasets for the organization.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
columns = {
|
|
42
|
+
"Dataset Id": "string",
|
|
43
|
+
"Dataset Name": "string",
|
|
44
|
+
"Web URL": "string",
|
|
45
|
+
"Add Rows API Enabled": "bool",
|
|
46
|
+
"Configured By": "string",
|
|
47
|
+
"Is Refreshable": "bool",
|
|
48
|
+
"Is Effective Identity Required": "bool",
|
|
49
|
+
"Is Effective Identity Roles Required": "bool",
|
|
50
|
+
"Target Storage Mode": "string",
|
|
51
|
+
"Created Date": "datetime",
|
|
52
|
+
"Content Provider Type": "string",
|
|
53
|
+
"Create Report Embed URL": "string",
|
|
54
|
+
"QnA Embed URL": "string",
|
|
55
|
+
"Upstream Datasets": "string",
|
|
56
|
+
"Users": "string",
|
|
57
|
+
"Is In Place Sharing Enabled": "bool",
|
|
58
|
+
"Workspace Id": "string",
|
|
59
|
+
"Auto Sync Read Only Replicas": "bool",
|
|
60
|
+
"Max Read Only Replicas": "int",
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
df = _create_dataframe(columns=columns)
|
|
64
|
+
|
|
65
|
+
params = {}
|
|
66
|
+
url = "/v1.0/myorg/admin/datasets"
|
|
67
|
+
|
|
68
|
+
if top is not None:
|
|
69
|
+
params["$top"] = top
|
|
70
|
+
|
|
71
|
+
if filter is not None:
|
|
72
|
+
params["$filter"] = filter
|
|
73
|
+
|
|
74
|
+
if skip is not None:
|
|
75
|
+
params["$skip"] = skip
|
|
76
|
+
|
|
77
|
+
url = _build_url(url, params)
|
|
78
|
+
response = _base_api(request=url, client="fabric_sp")
|
|
79
|
+
|
|
80
|
+
rows = []
|
|
81
|
+
for v in response.json().get("value", []):
|
|
82
|
+
rows.append(
|
|
83
|
+
{
|
|
84
|
+
"Dataset Id": v.get("id"),
|
|
85
|
+
"Dataset Name": v.get("name"),
|
|
86
|
+
"Web URL": v.get("webUrl"),
|
|
87
|
+
"Add Rows API Enabled": v.get("addRowsAPIEnabled"),
|
|
88
|
+
"Configured By": v.get("configuredBy"),
|
|
89
|
+
"Is Refreshable": v.get("isRefreshable"),
|
|
90
|
+
"Is Effective Identity Required": v.get("isEffectiveIdentityRequired"),
|
|
91
|
+
"Is Effective Identity Roles Required": v.get(
|
|
92
|
+
"isEffectiveIdentityRolesRequired"
|
|
93
|
+
),
|
|
94
|
+
"Target Storage Mode": v.get("targetStorageMode"),
|
|
95
|
+
"Created Date": pd.to_datetime(v.get("createdDate")),
|
|
96
|
+
"Content Provider Type": v.get("contentProviderType"),
|
|
97
|
+
"Create Report Embed URL": v.get("createReportEmbedURL"),
|
|
98
|
+
"QnA Embed URL": v.get("qnaEmbedURL"),
|
|
99
|
+
"Upstream Datasets": v.get("upstreamDatasets", []),
|
|
100
|
+
"Users": v.get("users", []),
|
|
101
|
+
"Is In Place Sharing Enabled": v.get("isInPlaceSharingEnabled"),
|
|
102
|
+
"Workspace Id": v.get("workspaceId"),
|
|
103
|
+
"Auto Sync Read Only Replicas": v.get("queryScaleOutSettings", {}).get(
|
|
104
|
+
"autoSyncReadOnlyReplicas"
|
|
105
|
+
),
|
|
106
|
+
"Max Read Only Replicas": v.get("queryScaleOutSettings", {}).get(
|
|
107
|
+
"maxReadOnlyReplicas"
|
|
108
|
+
),
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
if rows:
|
|
113
|
+
df = pd.DataFrame(rows, columns=list(columns.keys()))
|
|
114
|
+
|
|
115
|
+
_update_dataframe_datatypes(dataframe=df, column_map=columns)
|
|
116
|
+
|
|
117
|
+
return df
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _resolve_dataset_id(dataset: str | UUID) -> str:
|
|
121
|
+
if _is_valid_uuid(dataset):
|
|
122
|
+
return dataset
|
|
123
|
+
else:
|
|
124
|
+
df = list_datasets()
|
|
125
|
+
df_filt = df[df["Dataset Name"] == dataset]
|
|
126
|
+
if df_filt.empty:
|
|
127
|
+
raise ValueError(f"{icons.red_dot} The '{dataset}' dataset does not exist.")
|
|
128
|
+
return df_filt["Dataset Id"].iloc[0]
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def list_dataset_users(dataset: str | UUID) -> pd.DataFrame:
|
|
132
|
+
"""
|
|
133
|
+
Shows a list of users that have access to the specified dataset.
|
|
134
|
+
|
|
135
|
+
This is a wrapper function for the following API: `Admin - Datasets GetDatasetUsersAsAdmin <https://learn.microsoft.com/rest/api/power-bi/admin/datasets-get-dataset-users-as-admin>`_.
|
|
136
|
+
|
|
137
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
138
|
+
|
|
139
|
+
Parameters
|
|
140
|
+
----------
|
|
141
|
+
dataset : str | uuid.UUID
|
|
142
|
+
The name or ID of the dataset.
|
|
143
|
+
|
|
144
|
+
Returns
|
|
145
|
+
-------
|
|
146
|
+
pandas.DataFrame
|
|
147
|
+
A pandas dataframe showing a list of users that have access to the specified dataset.
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
dataset_id = _resolve_dataset_id(dataset)
|
|
151
|
+
|
|
152
|
+
columns = {
|
|
153
|
+
"User Name": "string",
|
|
154
|
+
"Email Address": "string",
|
|
155
|
+
"Dataset User Access Right": "string",
|
|
156
|
+
"Identifier": "string",
|
|
157
|
+
"Graph Id": "string",
|
|
158
|
+
"Principal Type": "string",
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
df = _create_dataframe(columns=columns)
|
|
162
|
+
|
|
163
|
+
url = f"/v1.0/myorg/admin/datasets/{dataset_id}/users"
|
|
164
|
+
response = _base_api(request=url, client="fabric_sp")
|
|
165
|
+
|
|
166
|
+
rows = []
|
|
167
|
+
for v in response.json().get("value", []):
|
|
168
|
+
rows.append(
|
|
169
|
+
{
|
|
170
|
+
"User Name": v.get("displayName"),
|
|
171
|
+
"Email Address": v.get("emailAddress"),
|
|
172
|
+
"Dataset User Access Right": v.get("datasetUserAccessRight"),
|
|
173
|
+
"Identifier": v.get("identifier"),
|
|
174
|
+
"Graph Id": v.get("graphId"),
|
|
175
|
+
"Principal Type": v.get("principalType"),
|
|
176
|
+
}
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
if rows:
|
|
180
|
+
df = pd.DataFrame(rows, columns=list(columns.keys()))
|
|
181
|
+
|
|
182
|
+
_update_dataframe_datatypes(dataframe=df, column_map=columns)
|
|
183
|
+
|
|
184
|
+
return df
|
sempy_labs/admin/_domains.py
CHANGED
|
@@ -319,7 +319,7 @@ def assign_domain_workspaces_by_capacities(
|
|
|
319
319
|
The capacity names.
|
|
320
320
|
"""
|
|
321
321
|
|
|
322
|
-
from sempy_labs.admin import list_capacities
|
|
322
|
+
from sempy_labs.admin._capacities import list_capacities
|
|
323
323
|
|
|
324
324
|
if "domain_name" in kwargs:
|
|
325
325
|
domain = kwargs["domain_name"]
|
sempy_labs/admin/_items.py
CHANGED
|
@@ -3,9 +3,11 @@ from typing import Optional, Tuple
|
|
|
3
3
|
from uuid import UUID
|
|
4
4
|
import sempy_labs._icons as icons
|
|
5
5
|
from sempy_labs.admin._basic_functions import (
|
|
6
|
-
_resolve_capacity_name_and_id,
|
|
7
6
|
_resolve_workspace_name_and_id,
|
|
8
7
|
)
|
|
8
|
+
from sempy_labs.admin._capacities import (
|
|
9
|
+
_resolve_capacity_name_and_id,
|
|
10
|
+
)
|
|
9
11
|
from sempy_labs._helper_functions import (
|
|
10
12
|
_is_valid_uuid,
|
|
11
13
|
_build_url,
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from typing import Optional
|
|
3
|
+
from sempy_labs._helper_functions import (
|
|
4
|
+
_base_api,
|
|
5
|
+
_create_dataframe,
|
|
6
|
+
_update_dataframe_datatypes,
|
|
7
|
+
_is_valid_uuid,
|
|
8
|
+
)
|
|
9
|
+
from uuid import UUID
|
|
10
|
+
import sempy_labs._icons as icons
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def list_reports(
|
|
14
|
+
top: Optional[int] = None,
|
|
15
|
+
skip: Optional[int] = None,
|
|
16
|
+
filter: Optional[str] = None,
|
|
17
|
+
) -> pd.DataFrame:
|
|
18
|
+
"""
|
|
19
|
+
Shows a list of reports for the organization.
|
|
20
|
+
|
|
21
|
+
This is a wrapper function for the following API: `Admin - Reports GetReportsAsAdmin <https://learn.microsoft.com/rest/api/power-bi/admin/reports-get-reports-as-admin>`_.
|
|
22
|
+
|
|
23
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
top : int, default=None
|
|
28
|
+
Returns only the first n results.
|
|
29
|
+
skip : int, default=None
|
|
30
|
+
Skips the first n results.
|
|
31
|
+
filter : str, default=None
|
|
32
|
+
Returns a subset of a results based on Odata filter query parameter condition.
|
|
33
|
+
|
|
34
|
+
Returns
|
|
35
|
+
-------
|
|
36
|
+
pandas.DataFrame
|
|
37
|
+
A pandas dataframe showing a list of reports for the organization.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
columns = {
|
|
41
|
+
"Report Id": "string",
|
|
42
|
+
"Report Name": "string",
|
|
43
|
+
"Type": "string",
|
|
44
|
+
"Web URL": "string",
|
|
45
|
+
"Embed URL": "string",
|
|
46
|
+
"Dataset Id": "string",
|
|
47
|
+
"Created Date": "datetime_coerce",
|
|
48
|
+
"Modified Date": "datetime_coerce",
|
|
49
|
+
"Created By": "string",
|
|
50
|
+
"Modified By": "string",
|
|
51
|
+
"Sensitivity Label Id": "string",
|
|
52
|
+
"Users": "string",
|
|
53
|
+
"Subscriptions": "string",
|
|
54
|
+
"Workspace Id": "string",
|
|
55
|
+
"Report Flags": "int",
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
df = _create_dataframe(columns=columns)
|
|
59
|
+
|
|
60
|
+
url = "/v1.0/myorg/admin/reports?"
|
|
61
|
+
if top is not None:
|
|
62
|
+
url += f"$top={top}&"
|
|
63
|
+
if skip is not None:
|
|
64
|
+
url += f"$skip={skip}&"
|
|
65
|
+
if filter is not None:
|
|
66
|
+
url += f"$filter={filter}&"
|
|
67
|
+
|
|
68
|
+
url.rstrip("$").rstrip("?")
|
|
69
|
+
response = _base_api(request=url, client="fabric_sp")
|
|
70
|
+
rows = []
|
|
71
|
+
|
|
72
|
+
for v in response.json().get("value", []):
|
|
73
|
+
rows.append(
|
|
74
|
+
{
|
|
75
|
+
"Report Id": v.get("id"),
|
|
76
|
+
"Report Name": v.get("name"),
|
|
77
|
+
"Type": v.get("reportType"),
|
|
78
|
+
"Web URL": v.get("webUrl"),
|
|
79
|
+
"Embed URL": v.get("embedUrl"),
|
|
80
|
+
"Dataset Id": v.get("datasetId"),
|
|
81
|
+
"Created Date": v.get("createdDateTime"),
|
|
82
|
+
"Modified Date": v.get("modifiedDateTime"),
|
|
83
|
+
"Created By": v.get("createdBy"),
|
|
84
|
+
"Modified By": v.get("modifiedBy"),
|
|
85
|
+
"Sensitivity Label Id": v.get("sensitivityLabel", {}).get("labelId"),
|
|
86
|
+
"Users": v.get("users"),
|
|
87
|
+
"Subscriptions": v.get("subscriptions"),
|
|
88
|
+
"Workspace Id": v.get("workspaceId"),
|
|
89
|
+
"Report Flags": v.get("reportFlags"),
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
if rows:
|
|
94
|
+
df = pd.DataFrame(rows, columns=list(columns.keys()))
|
|
95
|
+
|
|
96
|
+
_update_dataframe_datatypes(dataframe=df, column_map=columns)
|
|
97
|
+
|
|
98
|
+
return df
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _resolve_report_id(report: str | UUID) -> str:
|
|
102
|
+
if _is_valid_uuid(report):
|
|
103
|
+
return report
|
|
104
|
+
else:
|
|
105
|
+
df = list_reports()
|
|
106
|
+
df_filt = df[df["Report Name"] == report]
|
|
107
|
+
if df_filt.empty:
|
|
108
|
+
raise ValueError(f"{icons.red_dot} The '{report}' report does not exist.")
|
|
109
|
+
return df_filt["Report Id"].iloc[0]
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def list_report_users(report: str | UUID) -> pd.DataFrame:
|
|
113
|
+
"""
|
|
114
|
+
Shows a list of users that have access to the specified report.
|
|
115
|
+
|
|
116
|
+
This is a wrapper function for the following API: `Admin - Reports GetDatasetUsersAsAdmin <https://learn.microsoft.com/rest/api/power-bi/admin/datasets-get-report-users-as-admin>`_.
|
|
117
|
+
|
|
118
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
119
|
+
|
|
120
|
+
Parameters
|
|
121
|
+
----------
|
|
122
|
+
report : str | uuid.UUID
|
|
123
|
+
The name or ID of the report.
|
|
124
|
+
|
|
125
|
+
Returns
|
|
126
|
+
-------
|
|
127
|
+
pandas.DataFrame
|
|
128
|
+
A pandas dataframe showing a list of users that have access to the specified report.
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
report_id = _resolve_report_id(report)
|
|
132
|
+
|
|
133
|
+
columns = {
|
|
134
|
+
"User Name": "string",
|
|
135
|
+
"Email Address": "string",
|
|
136
|
+
"Report User Access Right": "string",
|
|
137
|
+
"Identifier": "string",
|
|
138
|
+
"Graph Id": "string",
|
|
139
|
+
"Principal Type": "string",
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
df = _create_dataframe(columns=columns)
|
|
143
|
+
|
|
144
|
+
url = f"/v1.0/myorg/admin/reports/{report_id}/users"
|
|
145
|
+
response = _base_api(request=url, client="fabric_sp")
|
|
146
|
+
|
|
147
|
+
rows = []
|
|
148
|
+
for v in response.json().get("value", []):
|
|
149
|
+
rows.append(
|
|
150
|
+
{
|
|
151
|
+
"User Name": v.get("displayName"),
|
|
152
|
+
"Email Address": v.get("emailAddress"),
|
|
153
|
+
"Report User Access Right": v.get("reportUserAccessRight"),
|
|
154
|
+
"Identifier": v.get("identifier"),
|
|
155
|
+
"Graph Id": v.get("graphId"),
|
|
156
|
+
"Principal Type": v.get("principalType"),
|
|
157
|
+
}
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
if rows:
|
|
161
|
+
df = pd.DataFrame(rows, columns=list(columns.keys()))
|
|
162
|
+
|
|
163
|
+
_update_dataframe_datatypes(dataframe=df, column_map=columns)
|
|
164
|
+
|
|
165
|
+
return df
|
sempy_labs/admin/_scanner.py
CHANGED
|
@@ -2,7 +2,6 @@ import sempy.fabric as fabric
|
|
|
2
2
|
from typing import Optional, List
|
|
3
3
|
from uuid import UUID
|
|
4
4
|
from sempy.fabric.exceptions import FabricHTTPException
|
|
5
|
-
import numpy as np
|
|
6
5
|
import time
|
|
7
6
|
import sempy_labs._icons as icons
|
|
8
7
|
from sempy_labs.admin._basic_functions import list_workspaces
|