semantic-link-labs 0.10.0__py3-none-any.whl → 0.11.0__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 (95) hide show
  1. {semantic_link_labs-0.10.0.dist-info → semantic_link_labs-0.11.0.dist-info}/METADATA +9 -6
  2. {semantic_link_labs-0.10.0.dist-info → semantic_link_labs-0.11.0.dist-info}/RECORD +95 -87
  3. sempy_labs/__init__.py +11 -1
  4. sempy_labs/_a_lib_info.py +2 -0
  5. sempy_labs/_capacities.py +2 -0
  6. sempy_labs/_connections.py +11 -0
  7. sempy_labs/_dashboards.py +9 -4
  8. sempy_labs/_data_pipelines.py +5 -0
  9. sempy_labs/_dataflows.py +284 -17
  10. sempy_labs/_daxformatter.py +80 -0
  11. sempy_labs/_delta_analyzer_history.py +4 -1
  12. sempy_labs/_deployment_pipelines.py +4 -0
  13. sempy_labs/_documentation.py +3 -0
  14. sempy_labs/_environments.py +10 -1
  15. sempy_labs/_eventhouses.py +12 -5
  16. sempy_labs/_eventstreams.py +11 -3
  17. sempy_labs/_external_data_shares.py +8 -2
  18. sempy_labs/_gateways.py +26 -5
  19. sempy_labs/_git.py +11 -0
  20. sempy_labs/_graphQL.py +10 -3
  21. sempy_labs/_helper_functions.py +62 -10
  22. sempy_labs/_job_scheduler.py +54 -7
  23. sempy_labs/_kql_databases.py +11 -2
  24. sempy_labs/_kql_querysets.py +11 -3
  25. sempy_labs/_list_functions.py +17 -45
  26. sempy_labs/_managed_private_endpoints.py +11 -2
  27. sempy_labs/_mirrored_databases.py +17 -3
  28. sempy_labs/_mirrored_warehouses.py +9 -3
  29. sempy_labs/_ml_experiments.py +11 -3
  30. sempy_labs/_ml_models.py +11 -3
  31. sempy_labs/_model_bpa_rules.py +2 -0
  32. sempy_labs/_mounted_data_factories.py +12 -8
  33. sempy_labs/_notebooks.py +6 -3
  34. sempy_labs/_refresh_semantic_model.py +1 -0
  35. sempy_labs/_semantic_models.py +107 -0
  36. sempy_labs/_spark.py +7 -0
  37. sempy_labs/_sql_endpoints.py +208 -0
  38. sempy_labs/_sqldatabase.py +13 -4
  39. sempy_labs/_tags.py +5 -1
  40. sempy_labs/_user_delegation_key.py +2 -0
  41. sempy_labs/_variable_libraries.py +3 -1
  42. sempy_labs/_warehouses.py +13 -3
  43. sempy_labs/_workloads.py +3 -0
  44. sempy_labs/_workspace_identity.py +3 -0
  45. sempy_labs/_workspaces.py +14 -1
  46. sempy_labs/admin/__init__.py +2 -0
  47. sempy_labs/admin/_activities.py +6 -5
  48. sempy_labs/admin/_apps.py +31 -31
  49. sempy_labs/admin/_artifacts.py +8 -3
  50. sempy_labs/admin/_basic_functions.py +5 -0
  51. sempy_labs/admin/_capacities.py +39 -28
  52. sempy_labs/admin/_datasets.py +51 -51
  53. sempy_labs/admin/_domains.py +17 -1
  54. sempy_labs/admin/_external_data_share.py +8 -2
  55. sempy_labs/admin/_git.py +14 -9
  56. sempy_labs/admin/_items.py +15 -2
  57. sempy_labs/admin/_reports.py +64 -65
  58. sempy_labs/admin/_shared.py +7 -1
  59. sempy_labs/admin/_tags.py +5 -0
  60. sempy_labs/admin/_tenant.py +5 -2
  61. sempy_labs/admin/_users.py +9 -3
  62. sempy_labs/admin/_workspaces.py +88 -0
  63. sempy_labs/directlake/_dl_helper.py +2 -0
  64. sempy_labs/directlake/_generate_shared_expression.py +2 -0
  65. sempy_labs/directlake/_get_directlake_lakehouse.py +2 -4
  66. sempy_labs/directlake/_get_shared_expression.py +2 -0
  67. sempy_labs/directlake/_guardrails.py +2 -0
  68. sempy_labs/directlake/_update_directlake_model_lakehouse_connection.py +5 -3
  69. sempy_labs/directlake/_warm_cache.py +1 -0
  70. sempy_labs/graph/_groups.py +22 -7
  71. sempy_labs/graph/_teams.py +7 -2
  72. sempy_labs/graph/_users.py +1 -0
  73. sempy_labs/lakehouse/_blobs.py +1 -0
  74. sempy_labs/lakehouse/_get_lakehouse_tables.py +88 -27
  75. sempy_labs/lakehouse/_helper.py +2 -0
  76. sempy_labs/lakehouse/_lakehouse.py +38 -5
  77. sempy_labs/lakehouse/_livy_sessions.py +2 -1
  78. sempy_labs/lakehouse/_shortcuts.py +7 -1
  79. sempy_labs/migration/_direct_lake_to_import.py +2 -0
  80. sempy_labs/mirrored_azure_databricks_catalog/__init__.py +15 -0
  81. sempy_labs/mirrored_azure_databricks_catalog/_discover.py +213 -0
  82. sempy_labs/mirrored_azure_databricks_catalog/_refresh_catalog_metadata.py +45 -0
  83. sempy_labs/report/_download_report.py +2 -1
  84. sempy_labs/report/_generate_report.py +2 -0
  85. sempy_labs/report/_paginated.py +2 -0
  86. sempy_labs/report/_report_bpa.py +110 -122
  87. sempy_labs/report/_report_bpa_rules.py +2 -0
  88. sempy_labs/report/_report_functions.py +7 -0
  89. sempy_labs/report/_reportwrapper.py +86 -48
  90. sempy_labs/theme/__init__.py +12 -0
  91. sempy_labs/theme/_org_themes.py +96 -0
  92. sempy_labs/tom/_model.py +702 -35
  93. {semantic_link_labs-0.10.0.dist-info → semantic_link_labs-0.11.0.dist-info}/WHEEL +0 -0
  94. {semantic_link_labs-0.10.0.dist-info → semantic_link_labs-0.11.0.dist-info}/licenses/LICENSE +0 -0
  95. {semantic_link_labs-0.10.0.dist-info → semantic_link_labs-0.11.0.dist-info}/top_level.txt +0 -0
sempy_labs/_tags.py CHANGED
@@ -10,8 +10,10 @@ import pandas as pd
10
10
  from typing import Optional, List
11
11
  from uuid import UUID
12
12
  import sempy_labs._icons as icons
13
+ from sempy._utils._log import log
13
14
 
14
15
 
16
+ @log
15
17
  def list_tags() -> pd.DataFrame:
16
18
  """
17
19
  Shows a list of all the tenant's tags.
@@ -39,7 +41,6 @@ def list_tags() -> pd.DataFrame:
39
41
  )
40
42
 
41
43
  dfs = []
42
-
43
44
  for r in responses:
44
45
  for v in r.get("value", []):
45
46
  new_data = {
@@ -55,6 +56,7 @@ def list_tags() -> pd.DataFrame:
55
56
  return df
56
57
 
57
58
 
59
+ @log
58
60
  def resolve_tags(tags: str | List[str]) -> List[str]:
59
61
  """
60
62
  Resolves the tags to a list of strings.
@@ -92,6 +94,7 @@ def resolve_tags(tags: str | List[str]) -> List[str]:
92
94
  return tag_list
93
95
 
94
96
 
97
+ @log
95
98
  def apply_tags(
96
99
  item: str | UUID,
97
100
  type: str,
@@ -143,6 +146,7 @@ def apply_tags(
143
146
  )
144
147
 
145
148
 
149
+ @log
146
150
  def unapply_tags(
147
151
  item: str | UUID,
148
152
  type: str,
@@ -4,8 +4,10 @@ from sempy_labs._helper_functions import (
4
4
  )
5
5
  from datetime import datetime, timedelta, timezone
6
6
  import xml.etree.ElementTree as ET
7
+ from sempy._utils._log import log
7
8
 
8
9
 
10
+ @log
9
11
  def get_user_delegation_key():
10
12
  """
11
13
  Gets a key that can be used to sign a user delegation SAS (shared access signature). A user delegation SAS grants access to Azure Blob Storage resources by using Microsoft Entra credentials.
@@ -1,5 +1,4 @@
1
1
  from sempy_labs._helper_functions import (
2
- resolve_workspace_name_and_id,
3
2
  resolve_workspace_id,
4
3
  _base_api,
5
4
  _create_dataframe,
@@ -9,8 +8,10 @@ from sempy_labs._helper_functions import (
9
8
  import pandas as pd
10
9
  from typing import Optional
11
10
  from uuid import UUID
11
+ from sempy._utils._log import log
12
12
 
13
13
 
14
+ @log
14
15
  def list_variable_libraries(workspace: Optional[str | UUID] = None) -> pd.DataFrame:
15
16
  """
16
17
  Shows the variable libraries within a workspace.
@@ -68,6 +69,7 @@ def list_variable_libraries(workspace: Optional[str | UUID] = None) -> pd.DataFr
68
69
  return df
69
70
 
70
71
 
72
+ @log
71
73
  def delete_variable_library(
72
74
  variable_library: str | UUID, workspace: Optional[str | UUID] = None
73
75
  ):
sempy_labs/_warehouses.py CHANGED
@@ -4,13 +4,16 @@ from sempy_labs._helper_functions import (
4
4
  _create_dataframe,
5
5
  _update_dataframe_datatypes,
6
6
  delete_item,
7
+ resolve_workspace_id,
7
8
  )
8
9
  import pandas as pd
9
10
  from typing import Optional
10
11
  import sempy_labs._icons as icons
11
12
  from uuid import UUID
13
+ from sempy._utils._log import log
12
14
 
13
15
 
16
+ @log
14
17
  def create_warehouse(
15
18
  warehouse: str,
16
19
  description: Optional[str] = None,
@@ -68,6 +71,7 @@ def create_warehouse(
68
71
  return result.get("id")
69
72
 
70
73
 
74
+ @log
71
75
  def list_warehouses(workspace: Optional[str | UUID] = None) -> pd.DataFrame:
72
76
  """
73
77
  Shows the warehouses within a workspace.
@@ -99,7 +103,7 @@ def list_warehouses(workspace: Optional[str | UUID] = None) -> pd.DataFrame:
99
103
  }
100
104
  df = _create_dataframe(columns=columns)
101
105
 
102
- (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
106
+ workspace_id = resolve_workspace_id(workspace)
103
107
 
104
108
  responses = _base_api(
105
109
  request=f"/v1/workspaces/{workspace_id}/warehouses",
@@ -107,6 +111,7 @@ def list_warehouses(workspace: Optional[str | UUID] = None) -> pd.DataFrame:
107
111
  client="fabric_sp",
108
112
  )
109
113
 
114
+ dfs = []
110
115
  for r in responses:
111
116
  for v in r.get("value", []):
112
117
  prop = v.get("properties", {})
@@ -119,13 +124,16 @@ def list_warehouses(workspace: Optional[str | UUID] = None) -> pd.DataFrame:
119
124
  "Created Date": prop.get("createdDate"),
120
125
  "Last Updated Time": prop.get("lastUpdatedTime"),
121
126
  }
122
- df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
127
+ dfs.append(pd.DataFrame(new_data, index=[0]))
123
128
 
124
- _update_dataframe_datatypes(dataframe=df, column_map=columns)
129
+ if dfs:
130
+ df = pd.concat(dfs, ignore_index=True)
131
+ _update_dataframe_datatypes(dataframe=df, column_map=columns)
125
132
 
126
133
  return df
127
134
 
128
135
 
136
+ @log
129
137
  def delete_warehouse(name: str | UUID, workspace: Optional[str | UUID] = None):
130
138
  """
131
139
  Deletes a Fabric warehouse.
@@ -145,6 +153,7 @@ def delete_warehouse(name: str | UUID, workspace: Optional[str | UUID] = None):
145
153
  delete_item(item=name, type="Warehouse", workspace=workspace)
146
154
 
147
155
 
156
+ @log
148
157
  def get_warehouse_tables(
149
158
  warehouse: str | UUID, workspace: Optional[str | UUID] = None
150
159
  ) -> pd.DataFrame:
@@ -180,6 +189,7 @@ def get_warehouse_tables(
180
189
  return df
181
190
 
182
191
 
192
+ @log
183
193
  def get_warehouse_columns(
184
194
  warehouse: str | UUID, workspace: Optional[str | UUID] = None
185
195
  ) -> pd.DataFrame:
sempy_labs/_workloads.py CHANGED
@@ -7,8 +7,10 @@ from sempy_labs._helper_functions import (
7
7
  _create_dataframe,
8
8
  )
9
9
  from uuid import UUID
10
+ from sempy._utils._log import log
10
11
 
11
12
 
13
+ @log
12
14
  def list_workloads(capacity: str | UUID, **kwargs) -> pd.DataFrame:
13
15
  """
14
16
  Returns the current state of the specified capacity workloads.
@@ -59,6 +61,7 @@ def list_workloads(capacity: str | UUID, **kwargs) -> pd.DataFrame:
59
61
  return df
60
62
 
61
63
 
64
+ @log
62
65
  def patch_workload(
63
66
  capacity: str | UUID,
64
67
  workload_name: str,
@@ -5,8 +5,10 @@ from sempy_labs._helper_functions import (
5
5
  from typing import Optional
6
6
  import sempy_labs._icons as icons
7
7
  from uuid import UUID
8
+ from sempy._utils._log import log
8
9
 
9
10
 
11
+ @log
10
12
  def provision_workspace_identity(workspace: Optional[str | UUID] = None):
11
13
  """
12
14
  Provisions a workspace identity for a workspace.
@@ -38,6 +40,7 @@ def provision_workspace_identity(workspace: Optional[str | UUID] = None):
38
40
  )
39
41
 
40
42
 
43
+ @log
41
44
  def deprovision_workspace_identity(workspace: Optional[str | UUID] = None):
42
45
  """
43
46
  Deprovisions a workspace identity for a workspace.
sempy_labs/_workspaces.py CHANGED
@@ -8,8 +8,10 @@ from sempy_labs._helper_functions import (
8
8
  _create_dataframe,
9
9
  )
10
10
  from uuid import UUID
11
+ from sempy._utils._log import log
11
12
 
12
13
 
14
+ @log
13
15
  def delete_user_from_workspace(
14
16
  email_address: str, workspace: Optional[str | UUID] = None
15
17
  ):
@@ -42,6 +44,7 @@ def delete_user_from_workspace(
42
44
  )
43
45
 
44
46
 
47
+ @log
45
48
  def update_workspace_user(
46
49
  email_address: str,
47
50
  role_name: str,
@@ -102,6 +105,7 @@ def update_workspace_user(
102
105
  )
103
106
 
104
107
 
108
+ @log
105
109
  def list_workspace_users(workspace: Optional[str | UUID] = None) -> pd.DataFrame:
106
110
  """
107
111
  A list of all the users of a workspace and their roles.
@@ -140,6 +144,7 @@ def list_workspace_users(workspace: Optional[str | UUID] = None) -> pd.DataFrame
140
144
  client="fabric_sp",
141
145
  )
142
146
 
147
+ dfs = []
143
148
  for r in responses:
144
149
  for v in r.get("value", []):
145
150
  p = v.get("principal", {})
@@ -150,11 +155,15 @@ def list_workspace_users(workspace: Optional[str | UUID] = None) -> pd.DataFrame
150
155
  "Role": v.get("role"),
151
156
  "Email Address": p.get("userDetails", {}).get("userPrincipalName"),
152
157
  }
153
- df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
158
+ dfs.append(pd.DataFrame(new_data, index=[0]))
159
+
160
+ if dfs:
161
+ df = pd.concat(dfs, ignore_index=True)
154
162
 
155
163
  return df
156
164
 
157
165
 
166
+ @log
158
167
  def add_user_to_workspace(
159
168
  email_address: str,
160
169
  role_name: str,
@@ -213,6 +222,7 @@ def add_user_to_workspace(
213
222
  )
214
223
 
215
224
 
225
+ @log
216
226
  def assign_workspace_to_capacity(
217
227
  capacity: str | UUID,
218
228
  workspace: Optional[str | UUID] = None,
@@ -255,6 +265,7 @@ def assign_workspace_to_capacity(
255
265
  )
256
266
 
257
267
 
268
+ @log
258
269
  def unassign_workspace_from_capacity(workspace: Optional[str | UUID] = None):
259
270
  """
260
271
  Unassigns a workspace from its assigned capacity.
@@ -284,6 +295,7 @@ def unassign_workspace_from_capacity(workspace: Optional[str | UUID] = None):
284
295
  )
285
296
 
286
297
 
298
+ @log
287
299
  def list_workspace_role_assignments(
288
300
  workspace: Optional[str | UUID] = None,
289
301
  ) -> pd.DataFrame:
@@ -337,6 +349,7 @@ def list_workspace_role_assignments(
337
349
  return df
338
350
 
339
351
 
352
+ @log
340
353
  def delete_workspace(workspace: Optional[str | UUID] = None):
341
354
  """
342
355
  Deletes a workspace.
@@ -6,6 +6,7 @@ from sempy_labs.admin._workspaces import (
6
6
  add_user_to_workspace,
7
7
  delete_user_from_workspace,
8
8
  restore_deleted_workspace,
9
+ list_orphaned_workspaces,
9
10
  )
10
11
  from sempy_labs.admin._artifacts import (
11
12
  list_unused_artifacts,
@@ -139,6 +140,7 @@ __all__ = [
139
140
  "add_user_to_workspace",
140
141
  "delete_user_from_workspace",
141
142
  "restore_deleted_workspace",
143
+ "list_orphaned_workspaces",
142
144
  "list_capacity_users",
143
145
  "list_user_subscriptions",
144
146
  "list_report_subscriptions",
@@ -107,6 +107,8 @@ def list_activity_events(
107
107
 
108
108
  responses = _base_api(request=url, client="fabric_sp", uses_pagination=True)
109
109
 
110
+ dfs = []
111
+
110
112
  for r in responses:
111
113
  if return_dataframe:
112
114
  for i in r.get("activityEventEntities", []):
@@ -150,17 +152,16 @@ def list_activity_events(
150
152
  "Consumption Method": i.get("ConsumptionMethod"),
151
153
  "Artifact Kind": i.get("ArtifactKind"),
152
154
  }
153
- df = pd.concat(
154
- [df, pd.DataFrame(new_data, index=[0])],
155
- ignore_index=True,
156
- )
155
+ dfs.append(pd.DataFrame(new_data, index=[0]))
157
156
  else:
158
157
  response_json["activityEventEntities"].extend(
159
158
  r.get("activityEventEntities")
160
159
  )
161
160
 
162
161
  if return_dataframe:
163
- _update_dataframe_datatypes(dataframe=df, column_map=columns)
162
+ if dfs:
163
+ df = pd.concat(dfs, ignore_index=True)
164
+ _update_dataframe_datatypes(dataframe=df, column_map=columns)
164
165
  return df
165
166
  else:
166
167
  return response_json
sempy_labs/admin/_apps.py CHANGED
@@ -9,8 +9,10 @@ from sempy_labs._helper_functions import (
9
9
  )
10
10
  from uuid import UUID
11
11
  import sempy_labs._icons as icons
12
+ from sempy._utils._log import log
12
13
 
13
14
 
15
+ @log
14
16
  def list_apps(
15
17
  top: Optional[int] = 1000,
16
18
  skip: Optional[int] = None,
@@ -56,26 +58,25 @@ def list_apps(
56
58
  url = _build_url(url, params)
57
59
  response = _base_api(request=url, client="fabric_sp")
58
60
 
59
- rows = []
61
+ dfs = []
60
62
  for v in response.json().get("value", []):
61
- rows.append(
62
- {
63
- "App Name": v.get("name"),
64
- "App Id": v.get("id"),
65
- "Description": v.get("description"),
66
- "Published By": v.get("publishedBy"),
67
- "Last Update": v.get("lastUpdate"),
68
- }
69
- )
70
-
71
- if rows:
72
- df = pd.DataFrame(rows, columns=list(columns.keys()))
73
-
74
- _update_dataframe_datatypes(dataframe=df, column_map=columns)
63
+ new_data = {
64
+ "App Name": v.get("name"),
65
+ "App Id": v.get("id"),
66
+ "Description": v.get("description"),
67
+ "Published By": v.get("publishedBy"),
68
+ "Last Update": v.get("lastUpdate"),
69
+ }
70
+ dfs.append(pd.DataFrame(new_data, index=[0]))
71
+
72
+ if dfs:
73
+ df = pd.concat(dfs, ignore_index=True)
74
+ _update_dataframe_datatypes(dataframe=df, column_map=columns)
75
75
 
76
76
  return df
77
77
 
78
78
 
79
+ @log
79
80
  def _resolve_app_id(app: str | UUID) -> str:
80
81
  if _is_valid_uuid(app):
81
82
  return app
@@ -87,6 +88,7 @@ def _resolve_app_id(app: str | UUID) -> str:
87
88
  return df_filt["App Id"].iloc[0]
88
89
 
89
90
 
91
+ @log
90
92
  def list_app_users(app: str | UUID) -> pd.DataFrame:
91
93
  """
92
94
  Shows a list of users that have access to the specified app.
@@ -122,22 +124,20 @@ def list_app_users(app: str | UUID) -> pd.DataFrame:
122
124
  url = f"/v1.0/myorg/admin/apps/{app_id}/users"
123
125
  response = _base_api(request=url, client="fabric_sp")
124
126
 
125
- rows = []
127
+ dfs = []
126
128
  for v in response.json().get("value", []):
127
- rows.append(
128
- {
129
- "User Name": v.get("displayName"),
130
- "Email Address": v.get("emailAddress"),
131
- "App User Access Right": v.get("appUserAccessRight"),
132
- "Identifier": v.get("identifier"),
133
- "Graph Id": v.get("graphId"),
134
- "Principal Type": v.get("principalType"),
135
- }
136
- )
137
-
138
- if rows:
139
- df = pd.DataFrame(rows, columns=list(columns.keys()))
140
-
141
- _update_dataframe_datatypes(dataframe=df, column_map=columns)
129
+ new_data = {
130
+ "User Name": v.get("displayName"),
131
+ "Email Address": v.get("emailAddress"),
132
+ "App User Access Right": v.get("appUserAccessRight"),
133
+ "Identifier": v.get("identifier"),
134
+ "Graph Id": v.get("graphId"),
135
+ "Principal Type": v.get("principalType"),
136
+ }
137
+ dfs.append(pd.DataFrame(new_data, index=[0]))
138
+
139
+ if dfs:
140
+ df = pd.concat(dfs, ignore_index=True)
141
+ _update_dataframe_datatypes(dataframe=df, column_map=columns)
142
142
 
143
143
  return df
@@ -9,8 +9,10 @@ from sempy_labs.admin._basic_functions import (
9
9
  _create_dataframe,
10
10
  _update_dataframe_datatypes,
11
11
  )
12
+ from sempy._utils._log import log
12
13
 
13
14
 
15
+ @log
14
16
  def list_unused_artifacts(workspace: Optional[str | UUID] = None) -> pd.DataFrame:
15
17
  """
16
18
  Returns a list of datasets, reports, and dashboards that have not been used within 30 days for the specified workspace.
@@ -25,7 +27,7 @@ def list_unused_artifacts(workspace: Optional[str | UUID] = None) -> pd.DataFram
25
27
  A pandas dataframe showing a list of datasets, reports, and dashboards that have not been used within 30 days for the specified workspace.
26
28
  """
27
29
 
28
- (workspace_name, workspace_id) = _resolve_workspace_name_and_id(workspace)
30
+ (_, workspace_id) = _resolve_workspace_name_and_id(workspace)
29
31
 
30
32
  columns = {
31
33
  "Artifact Name": "string",
@@ -44,6 +46,7 @@ def list_unused_artifacts(workspace: Optional[str | UUID] = None) -> pd.DataFram
44
46
  uses_pagination=True,
45
47
  )
46
48
 
49
+ dfs = []
47
50
  for r in responses:
48
51
  for i in r.get("unusedArtifactEntities", []):
49
52
  new_data = {
@@ -55,8 +58,10 @@ def list_unused_artifacts(workspace: Optional[str | UUID] = None) -> pd.DataFram
55
58
  "Last Accessed Date Time": i.get("lastAccessedDateTime"),
56
59
  }
57
60
 
58
- df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
61
+ dfs.append(pd.DataFrame(new_data, index=[0]))
59
62
 
60
- _update_dataframe_datatypes(dataframe=df, column_map=columns)
63
+ if dfs:
64
+ df = pd.concat(dfs, ignore_index=True)
65
+ _update_dataframe_datatypes(dataframe=df, column_map=columns)
61
66
 
62
67
  return df
@@ -249,6 +249,7 @@ def unassign_workspaces_from_capacity(
249
249
  )
250
250
 
251
251
 
252
+ @log
252
253
  def list_modified_workspaces(
253
254
  modified_since: Optional[str] = None,
254
255
  exclude_inactive_workspaces: Optional[bool] = False,
@@ -298,6 +299,7 @@ def list_modified_workspaces(
298
299
  return df
299
300
 
300
301
 
302
+ @log
301
303
  def list_workspace_access_details(
302
304
  workspace: Optional[Union[str, UUID]] = None,
303
305
  ) -> pd.DataFrame:
@@ -350,6 +352,7 @@ def list_workspace_access_details(
350
352
  return df
351
353
 
352
354
 
355
+ @log
353
356
  def _resolve_workspace_name(workspace_id: Optional[UUID] = None) -> str:
354
357
  from sempy_labs._helper_functions import _get_fabric_context_setting
355
358
  from sempy.fabric.exceptions import FabricHTTPException
@@ -372,6 +375,7 @@ def _resolve_workspace_name(workspace_id: Optional[UUID] = None) -> str:
372
375
  return workspace_name
373
376
 
374
377
 
378
+ @log
375
379
  def _resolve_workspace_name_and_id(
376
380
  workspace: str | UUID,
377
381
  ) -> Tuple[str, UUID]:
@@ -397,6 +401,7 @@ def _resolve_workspace_name_and_id(
397
401
  return workspace_name, workspace_id
398
402
 
399
403
 
404
+ @log
400
405
  def list_workspace_users(workspace: Optional[str | UUID] = None) -> pd.DataFrame:
401
406
  """
402
407
  Shows a list of users that have access to the specified workspace.
@@ -13,6 +13,7 @@ from sempy_labs._helper_functions import (
13
13
  )
14
14
 
15
15
 
16
+ @log
16
17
  def patch_capacity(capacity: str | UUID, tenant_key_id: UUID):
17
18
  """
18
19
  Changes specific capacity information. Currently, this API call only supports changing the capacity's encryption key.
@@ -44,6 +45,7 @@ def patch_capacity(capacity: str | UUID, tenant_key_id: UUID):
44
45
  )
45
46
 
46
47
 
48
+ @log
47
49
  def _resolve_capacity_name_and_id(
48
50
  capacity: str | UUID,
49
51
  ) -> Tuple[str, UUID]:
@@ -58,6 +60,7 @@ def _resolve_capacity_name_and_id(
58
60
  return capacity_name, capacity_id
59
61
 
60
62
 
63
+ @log
61
64
  def _resolve_capacity_id(
62
65
  capacity: str | UUID,
63
66
  ) -> UUID:
@@ -76,6 +79,7 @@ def _resolve_capacity_id(
76
79
  return capacity_id
77
80
 
78
81
 
82
+ @log
79
83
  def _list_capacities_meta() -> pd.DataFrame:
80
84
  """
81
85
  Shows the a list of capacities and their properties. This function is the admin version.
@@ -102,6 +106,7 @@ def _list_capacities_meta() -> pd.DataFrame:
102
106
  request="/v1.0/myorg/admin/capacities", client="fabric_sp", uses_pagination=True
103
107
  )
104
108
 
109
+ dfs = []
105
110
  for r in responses:
106
111
  for i in r.get("value", []):
107
112
  new_data = {
@@ -112,11 +117,15 @@ def _list_capacities_meta() -> pd.DataFrame:
112
117
  "State": i.get("state"),
113
118
  "Admins": [i.get("admins", [])],
114
119
  }
115
- df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
120
+ dfs.append(pd.DataFrame(new_data, index=[0]))
121
+
122
+ if dfs:
123
+ df = pd.concat(dfs, ignore_index=True)
116
124
 
117
125
  return df
118
126
 
119
127
 
128
+ @log
120
129
  def get_capacity_assignment_status(
121
130
  workspace: Optional[str | UUID] = None,
122
131
  ) -> pd.DataFrame:
@@ -178,6 +187,7 @@ def get_capacity_assignment_status(
178
187
  return df
179
188
 
180
189
 
190
+ @log
181
191
  def get_capacity_state(capacity: Optional[str | UUID] = None):
182
192
  """
183
193
  Gets the state of a capacity.
@@ -248,6 +258,7 @@ def list_capacities(
248
258
  request="/v1.0/myorg/admin/capacities", client="fabric_sp", uses_pagination=True
249
259
  )
250
260
 
261
+ dfs = []
251
262
  for r in responses:
252
263
  for i in r.get("value", []):
253
264
  new_data = {
@@ -258,7 +269,10 @@ def list_capacities(
258
269
  "State": i.get("state"),
259
270
  "Admins": [i.get("admins", [])],
260
271
  }
261
- df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
272
+ dfs.append(pd.DataFrame(new_data, index=[0]))
273
+
274
+ if dfs:
275
+ df = pd.concat(dfs, ignore_index=True)
262
276
 
263
277
  if capacity is not None:
264
278
  if _is_valid_uuid(capacity):
@@ -269,6 +283,7 @@ def list_capacities(
269
283
  return df
270
284
 
271
285
 
286
+ @log
272
287
  def list_capacity_users(capacity: str | UUID) -> pd.DataFrame:
273
288
  """
274
289
  Shows a list of users that have access to the specified workspace.
@@ -288,7 +303,7 @@ def list_capacity_users(capacity: str | UUID) -> pd.DataFrame:
288
303
  A pandas dataframe showing a list of users that have access to the specified workspace.
289
304
  """
290
305
 
291
- (capacity_name, capacity_id) = _resolve_capacity_name_and_id(capacity)
306
+ (_, capacity_id) = _resolve_capacity_name_and_id(capacity)
292
307
 
293
308
  columns = {
294
309
  "User Name": "string",
@@ -307,25 +322,23 @@ def list_capacity_users(capacity: str | UUID) -> pd.DataFrame:
307
322
  request=f"/v1.0/myorg/admin/capacities/{capacity_id}/users", client="fabric_sp"
308
323
  )
309
324
 
310
- rows = []
325
+ dfs = []
311
326
  for v in response.json().get("value", []):
312
- rows.append(
313
- {
314
- "User Name": v.get("displayName"),
315
- "Email Address": v.get("emailAddress"),
316
- "Capacity User Access Right": v.get("capacityUserAccessRight"),
317
- "Identifier": v.get("identifier"),
318
- "Graph Id": v.get("graphId"),
319
- "Principal Type": v.get("principalType"),
320
- "User Type": v.get("userType"),
321
- "Profile": v.get("profile"),
322
- }
323
- )
324
-
325
- if rows:
326
- df = pd.DataFrame(rows, columns=list(columns.keys()))
327
+ new_data = {
328
+ "User Name": v.get("displayName"),
329
+ "Email Address": v.get("emailAddress"),
330
+ "Capacity User Access Right": v.get("capacityUserAccessRight"),
331
+ "Identifier": v.get("identifier"),
332
+ "Graph Id": v.get("graphId"),
333
+ "Principal Type": v.get("principalType"),
334
+ "User Type": v.get("userType"),
335
+ "Profile": v.get("profile"),
336
+ }
337
+ dfs.append(pd.DataFrame(new_data, index=[0]))
327
338
 
328
- _update_dataframe_datatypes(dataframe=df, column_map=columns)
339
+ if dfs:
340
+ df = pd.concat(dfs, ignore_index=True)
341
+ _update_dataframe_datatypes(dataframe=df, column_map=columns)
329
342
 
330
343
  return df
331
344
 
@@ -419,11 +432,10 @@ def get_refreshables(
419
432
 
420
433
  url = _build_url(url, params)
421
434
 
422
- responses = _base_api(request=url, client="fabric_sp")
435
+ response = _base_api(request=url, client="fabric_sp")
423
436
 
424
- refreshables = []
425
-
426
- for i in responses.json().get("value", []):
437
+ dfs = []
438
+ for i in response.json().get("value", []):
427
439
  last_refresh = i.get("lastRefresh", {})
428
440
  refresh_schedule = i.get("refreshSchedule", {})
429
441
  new_data = {
@@ -461,11 +473,10 @@ def get_refreshables(
461
473
  "Refresh Schedule Notify Option": refresh_schedule.get("notifyOption"),
462
474
  "Configured By": i.get("configuredBy"),
463
475
  }
476
+ dfs.append(pd.DataFrame(new_data, index=[0]))
464
477
 
465
- refreshables.append(new_data)
466
-
467
- if len(refreshables) > 0:
468
- df = pd.DataFrame(refreshables)
478
+ if dfs:
479
+ df = pd.concat(dfs, ignore_index=True)
469
480
  _update_dataframe_datatypes(dataframe=df, column_map=columns)
470
481
 
471
482
  return df