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.
- semantic_link_labs-0.12.8.dist-info/METADATA +354 -0
- semantic_link_labs-0.12.8.dist-info/RECORD +243 -0
- semantic_link_labs-0.12.8.dist-info/WHEEL +5 -0
- semantic_link_labs-0.12.8.dist-info/licenses/LICENSE +21 -0
- semantic_link_labs-0.12.8.dist-info/top_level.txt +1 -0
- sempy_labs/__init__.py +606 -0
- sempy_labs/_a_lib_info.py +2 -0
- sempy_labs/_ai.py +437 -0
- sempy_labs/_authentication.py +264 -0
- sempy_labs/_bpa_translation/_model/_translations_am-ET.po +869 -0
- sempy_labs/_bpa_translation/_model/_translations_ar-AE.po +908 -0
- sempy_labs/_bpa_translation/_model/_translations_bg-BG.po +968 -0
- sempy_labs/_bpa_translation/_model/_translations_ca-ES.po +963 -0
- sempy_labs/_bpa_translation/_model/_translations_cs-CZ.po +943 -0
- sempy_labs/_bpa_translation/_model/_translations_da-DK.po +945 -0
- sempy_labs/_bpa_translation/_model/_translations_de-DE.po +988 -0
- sempy_labs/_bpa_translation/_model/_translations_el-GR.po +993 -0
- sempy_labs/_bpa_translation/_model/_translations_es-ES.po +971 -0
- sempy_labs/_bpa_translation/_model/_translations_fa-IR.po +933 -0
- sempy_labs/_bpa_translation/_model/_translations_fi-FI.po +942 -0
- sempy_labs/_bpa_translation/_model/_translations_fr-FR.po +994 -0
- sempy_labs/_bpa_translation/_model/_translations_ga-IE.po +967 -0
- sempy_labs/_bpa_translation/_model/_translations_he-IL.po +902 -0
- sempy_labs/_bpa_translation/_model/_translations_hi-IN.po +944 -0
- sempy_labs/_bpa_translation/_model/_translations_hu-HU.po +963 -0
- sempy_labs/_bpa_translation/_model/_translations_id-ID.po +946 -0
- sempy_labs/_bpa_translation/_model/_translations_is-IS.po +939 -0
- sempy_labs/_bpa_translation/_model/_translations_it-IT.po +986 -0
- sempy_labs/_bpa_translation/_model/_translations_ja-JP.po +846 -0
- sempy_labs/_bpa_translation/_model/_translations_ko-KR.po +839 -0
- sempy_labs/_bpa_translation/_model/_translations_mt-MT.po +967 -0
- sempy_labs/_bpa_translation/_model/_translations_nl-NL.po +978 -0
- sempy_labs/_bpa_translation/_model/_translations_pl-PL.po +962 -0
- sempy_labs/_bpa_translation/_model/_translations_pt-BR.po +962 -0
- sempy_labs/_bpa_translation/_model/_translations_pt-PT.po +957 -0
- sempy_labs/_bpa_translation/_model/_translations_ro-RO.po +968 -0
- sempy_labs/_bpa_translation/_model/_translations_ru-RU.po +964 -0
- sempy_labs/_bpa_translation/_model/_translations_sk-SK.po +952 -0
- sempy_labs/_bpa_translation/_model/_translations_sl-SL.po +950 -0
- sempy_labs/_bpa_translation/_model/_translations_sv-SE.po +942 -0
- sempy_labs/_bpa_translation/_model/_translations_ta-IN.po +976 -0
- sempy_labs/_bpa_translation/_model/_translations_te-IN.po +947 -0
- sempy_labs/_bpa_translation/_model/_translations_th-TH.po +924 -0
- sempy_labs/_bpa_translation/_model/_translations_tr-TR.po +953 -0
- sempy_labs/_bpa_translation/_model/_translations_uk-UA.po +961 -0
- sempy_labs/_bpa_translation/_model/_translations_zh-CN.po +804 -0
- sempy_labs/_bpa_translation/_model/_translations_zu-ZA.po +969 -0
- sempy_labs/_capacities.py +1198 -0
- sempy_labs/_capacity_migration.py +660 -0
- sempy_labs/_clear_cache.py +351 -0
- sempy_labs/_connections.py +610 -0
- sempy_labs/_dashboards.py +69 -0
- sempy_labs/_data_access_security.py +98 -0
- sempy_labs/_data_pipelines.py +162 -0
- sempy_labs/_dataflows.py +668 -0
- sempy_labs/_dax.py +501 -0
- sempy_labs/_daxformatter.py +80 -0
- sempy_labs/_delta_analyzer.py +467 -0
- sempy_labs/_delta_analyzer_history.py +301 -0
- sempy_labs/_dictionary_diffs.py +221 -0
- sempy_labs/_documentation.py +147 -0
- sempy_labs/_domains.py +51 -0
- sempy_labs/_eventhouses.py +182 -0
- sempy_labs/_external_data_shares.py +230 -0
- sempy_labs/_gateways.py +521 -0
- sempy_labs/_generate_semantic_model.py +521 -0
- sempy_labs/_get_connection_string.py +84 -0
- sempy_labs/_git.py +543 -0
- sempy_labs/_graphQL.py +90 -0
- sempy_labs/_helper_functions.py +2833 -0
- sempy_labs/_icons.py +149 -0
- sempy_labs/_job_scheduler.py +609 -0
- sempy_labs/_kql_databases.py +149 -0
- sempy_labs/_kql_querysets.py +124 -0
- sempy_labs/_kusto.py +137 -0
- sempy_labs/_labels.py +124 -0
- sempy_labs/_list_functions.py +1720 -0
- sempy_labs/_managed_private_endpoints.py +253 -0
- sempy_labs/_mirrored_databases.py +416 -0
- sempy_labs/_mirrored_warehouses.py +60 -0
- sempy_labs/_ml_experiments.py +113 -0
- sempy_labs/_model_auto_build.py +140 -0
- sempy_labs/_model_bpa.py +557 -0
- sempy_labs/_model_bpa_bulk.py +378 -0
- sempy_labs/_model_bpa_rules.py +859 -0
- sempy_labs/_model_dependencies.py +343 -0
- sempy_labs/_mounted_data_factories.py +123 -0
- sempy_labs/_notebooks.py +441 -0
- sempy_labs/_one_lake_integration.py +151 -0
- sempy_labs/_onelake.py +131 -0
- sempy_labs/_query_scale_out.py +433 -0
- sempy_labs/_refresh_semantic_model.py +435 -0
- sempy_labs/_semantic_models.py +468 -0
- sempy_labs/_spark.py +455 -0
- sempy_labs/_sql.py +241 -0
- sempy_labs/_sql_audit_settings.py +207 -0
- sempy_labs/_sql_endpoints.py +214 -0
- sempy_labs/_tags.py +201 -0
- sempy_labs/_translations.py +43 -0
- sempy_labs/_user_delegation_key.py +44 -0
- sempy_labs/_utils.py +79 -0
- sempy_labs/_vertipaq.py +1021 -0
- sempy_labs/_vpax.py +388 -0
- sempy_labs/_warehouses.py +234 -0
- sempy_labs/_workloads.py +140 -0
- sempy_labs/_workspace_identity.py +72 -0
- sempy_labs/_workspaces.py +595 -0
- sempy_labs/admin/__init__.py +170 -0
- sempy_labs/admin/_activities.py +167 -0
- sempy_labs/admin/_apps.py +145 -0
- sempy_labs/admin/_artifacts.py +65 -0
- sempy_labs/admin/_basic_functions.py +463 -0
- sempy_labs/admin/_capacities.py +508 -0
- sempy_labs/admin/_dataflows.py +45 -0
- sempy_labs/admin/_datasets.py +186 -0
- sempy_labs/admin/_domains.py +522 -0
- sempy_labs/admin/_external_data_share.py +100 -0
- sempy_labs/admin/_git.py +72 -0
- sempy_labs/admin/_items.py +265 -0
- sempy_labs/admin/_labels.py +211 -0
- sempy_labs/admin/_reports.py +241 -0
- sempy_labs/admin/_scanner.py +118 -0
- sempy_labs/admin/_shared.py +82 -0
- sempy_labs/admin/_sharing_links.py +110 -0
- sempy_labs/admin/_tags.py +131 -0
- sempy_labs/admin/_tenant.py +503 -0
- sempy_labs/admin/_tenant_keys.py +89 -0
- sempy_labs/admin/_users.py +140 -0
- sempy_labs/admin/_workspaces.py +236 -0
- sempy_labs/deployment_pipeline/__init__.py +23 -0
- sempy_labs/deployment_pipeline/_items.py +580 -0
- sempy_labs/directlake/__init__.py +57 -0
- sempy_labs/directlake/_autosync.py +58 -0
- sempy_labs/directlake/_directlake_schema_compare.py +120 -0
- sempy_labs/directlake/_directlake_schema_sync.py +161 -0
- sempy_labs/directlake/_dl_helper.py +274 -0
- sempy_labs/directlake/_generate_shared_expression.py +94 -0
- sempy_labs/directlake/_get_directlake_lakehouse.py +62 -0
- sempy_labs/directlake/_get_shared_expression.py +34 -0
- sempy_labs/directlake/_guardrails.py +96 -0
- sempy_labs/directlake/_list_directlake_model_calc_tables.py +70 -0
- sempy_labs/directlake/_show_unsupported_directlake_objects.py +90 -0
- sempy_labs/directlake/_update_directlake_model_lakehouse_connection.py +239 -0
- sempy_labs/directlake/_update_directlake_partition_entity.py +259 -0
- sempy_labs/directlake/_warm_cache.py +236 -0
- sempy_labs/dotnet_lib/dotnet.runtime.config.json +10 -0
- sempy_labs/environment/__init__.py +23 -0
- sempy_labs/environment/_items.py +212 -0
- sempy_labs/environment/_pubstage.py +223 -0
- sempy_labs/eventstream/__init__.py +37 -0
- sempy_labs/eventstream/_items.py +263 -0
- sempy_labs/eventstream/_topology.py +652 -0
- sempy_labs/graph/__init__.py +59 -0
- sempy_labs/graph/_groups.py +651 -0
- sempy_labs/graph/_sensitivity_labels.py +120 -0
- sempy_labs/graph/_teams.py +125 -0
- sempy_labs/graph/_user_licenses.py +96 -0
- sempy_labs/graph/_users.py +516 -0
- sempy_labs/graph_model/__init__.py +15 -0
- sempy_labs/graph_model/_background_jobs.py +63 -0
- sempy_labs/graph_model/_items.py +149 -0
- sempy_labs/lakehouse/__init__.py +67 -0
- sempy_labs/lakehouse/_blobs.py +247 -0
- sempy_labs/lakehouse/_get_lakehouse_columns.py +102 -0
- sempy_labs/lakehouse/_get_lakehouse_tables.py +274 -0
- sempy_labs/lakehouse/_helper.py +250 -0
- sempy_labs/lakehouse/_lakehouse.py +351 -0
- sempy_labs/lakehouse/_livy_sessions.py +143 -0
- sempy_labs/lakehouse/_materialized_lake_views.py +157 -0
- sempy_labs/lakehouse/_partitioning.py +165 -0
- sempy_labs/lakehouse/_schemas.py +217 -0
- sempy_labs/lakehouse/_shortcuts.py +440 -0
- sempy_labs/migration/__init__.py +35 -0
- sempy_labs/migration/_create_pqt_file.py +238 -0
- sempy_labs/migration/_direct_lake_to_import.py +105 -0
- sempy_labs/migration/_migrate_calctables_to_lakehouse.py +398 -0
- sempy_labs/migration/_migrate_calctables_to_semantic_model.py +148 -0
- sempy_labs/migration/_migrate_model_objects_to_semantic_model.py +533 -0
- sempy_labs/migration/_migrate_tables_columns_to_semantic_model.py +172 -0
- sempy_labs/migration/_migration_validation.py +71 -0
- sempy_labs/migration/_refresh_calc_tables.py +131 -0
- sempy_labs/mirrored_azure_databricks_catalog/__init__.py +15 -0
- sempy_labs/mirrored_azure_databricks_catalog/_discover.py +213 -0
- sempy_labs/mirrored_azure_databricks_catalog/_refresh_catalog_metadata.py +45 -0
- sempy_labs/ml_model/__init__.py +23 -0
- sempy_labs/ml_model/_functions.py +427 -0
- sempy_labs/report/_BPAReportTemplate.json +232 -0
- sempy_labs/report/__init__.py +55 -0
- sempy_labs/report/_bpareporttemplate/.pbi/localSettings.json +9 -0
- sempy_labs/report/_bpareporttemplate/.platform +11 -0
- sempy_labs/report/_bpareporttemplate/StaticResources/SharedResources/BaseThemes/CY24SU06.json +710 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/page.json +11 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/1b08bce3bebabb0a27a8/visual.json +191 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/2f22ddb70c301693c165/visual.json +438 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/3b1182230aa6c600b43a/visual.json +127 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/58577ba6380c69891500/visual.json +576 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/a2a8fa5028b3b776c96c/visual.json +207 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/adfd47ef30652707b987/visual.json +506 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/b6a80ee459e716e170b1/visual.json +127 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/ce3130a721c020cc3d81/visual.json +513 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/92735ae19b31712208ad/page.json +8 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/92735ae19b31712208ad/visuals/66e60dfb526437cd78d1/visual.json +112 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/page.json +11 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/07deb8bce824e1be37d7/visual.json +513 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0b1c68838818b32ad03b/visual.json +352 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0c171de9d2683d10b930/visual.json +37 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0efa01be0510e40a645e/visual.json +542 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/6bf2f0eb830ab53cc668/visual.json +221 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/88d8141cb8500b60030c/visual.json +127 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/a753273590beed656a03/visual.json +576 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/b8fdc82cddd61ac447bc/visual.json +127 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/d37dce724a0ccc30044b/page.json +9 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/d37dce724a0ccc30044b/visuals/ce8532a7e25020271077/visual.json +38 -0
- sempy_labs/report/_bpareporttemplate/definition/pages/pages.json +10 -0
- sempy_labs/report/_bpareporttemplate/definition/report.json +176 -0
- sempy_labs/report/_bpareporttemplate/definition/version.json +4 -0
- sempy_labs/report/_bpareporttemplate/definition.pbir +14 -0
- sempy_labs/report/_download_report.py +76 -0
- sempy_labs/report/_export_report.py +257 -0
- sempy_labs/report/_generate_report.py +427 -0
- sempy_labs/report/_paginated.py +76 -0
- sempy_labs/report/_report_bpa.py +354 -0
- sempy_labs/report/_report_bpa_rules.py +115 -0
- sempy_labs/report/_report_functions.py +581 -0
- sempy_labs/report/_report_helper.py +227 -0
- sempy_labs/report/_report_list_functions.py +110 -0
- sempy_labs/report/_report_rebind.py +149 -0
- sempy_labs/report/_reportwrapper.py +3100 -0
- sempy_labs/report/_save_report.py +147 -0
- sempy_labs/snowflake_database/__init__.py +10 -0
- sempy_labs/snowflake_database/_items.py +105 -0
- sempy_labs/sql_database/__init__.py +21 -0
- sempy_labs/sql_database/_items.py +201 -0
- sempy_labs/sql_database/_mirroring.py +79 -0
- sempy_labs/theme/__init__.py +12 -0
- sempy_labs/theme/_org_themes.py +129 -0
- sempy_labs/tom/__init__.py +3 -0
- sempy_labs/tom/_model.py +5977 -0
- sempy_labs/variable_library/__init__.py +19 -0
- sempy_labs/variable_library/_functions.py +403 -0
- sempy_labs/warehouse/__init__.py +28 -0
- sempy_labs/warehouse/_items.py +234 -0
- sempy_labs/warehouse/_restore_points.py +309 -0
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
from typing import Optional, List, Union, Tuple
|
|
2
|
+
from uuid import UUID
|
|
3
|
+
import sempy_labs._icons as icons
|
|
4
|
+
from sempy_labs._helper_functions import (
|
|
5
|
+
_is_valid_uuid,
|
|
6
|
+
_build_url,
|
|
7
|
+
_base_api,
|
|
8
|
+
_create_dataframe,
|
|
9
|
+
)
|
|
10
|
+
from sempy._utils._log import log
|
|
11
|
+
import numpy as np
|
|
12
|
+
import pandas as pd
|
|
13
|
+
from dateutil.parser import parse as dtparser
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@log
|
|
17
|
+
def list_workspaces(
|
|
18
|
+
capacity: Optional[str | UUID] = None,
|
|
19
|
+
workspace: Optional[str | UUID] = None,
|
|
20
|
+
workspace_state: Optional[str] = None,
|
|
21
|
+
workspace_type: Optional[str] = None,
|
|
22
|
+
**kwargs,
|
|
23
|
+
) -> pd.DataFrame:
|
|
24
|
+
"""
|
|
25
|
+
Lists workspaces for the organization. This function is the admin version of list_workspaces.
|
|
26
|
+
|
|
27
|
+
This is a wrapper function for the following API: `Workspaces - List Workspaces - REST API (Admin) <https://learn.microsoft.com/en-us/rest/api/fabric/admin/workspaces/list-workspaces>`_.
|
|
28
|
+
|
|
29
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
30
|
+
|
|
31
|
+
Parameters
|
|
32
|
+
----------
|
|
33
|
+
capacity : str | uuid.UUID, default=None
|
|
34
|
+
Returns only the workspaces in the specified Capacity.
|
|
35
|
+
workspace : str | uuid.UUID, default=None
|
|
36
|
+
Returns the workspace with the specific name.
|
|
37
|
+
workspace_state : str, default=None
|
|
38
|
+
Return only the workspace with the requested state. You can find the possible states in `Workspace States <https://learn.microsoft.com/en-us/rest/api/fabric/admin/workspaces/list-workspaces?tabs=HTTP#workspacestate>`_.
|
|
39
|
+
workspace_type : str, default=None
|
|
40
|
+
Return only the workspace of the specific type. You can find the possible types in `Workspace Types <https://learn.microsoft.com/en-us/rest/api/fabric/admin/workspaces/list-workspaces?tabs=HTTP#workspacetype>`_.
|
|
41
|
+
|
|
42
|
+
Returns
|
|
43
|
+
-------
|
|
44
|
+
pandas.DataFrame
|
|
45
|
+
A pandas dataframe showing a list of workspaces for the organization.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
from sempy_labs.admin._capacities import _resolve_capacity_name_and_id
|
|
49
|
+
|
|
50
|
+
if "filter" in kwargs:
|
|
51
|
+
print(
|
|
52
|
+
"The 'filter' parameter has been deprecated. Please remove this parameter from the function going forward."
|
|
53
|
+
)
|
|
54
|
+
del kwargs["filter"]
|
|
55
|
+
|
|
56
|
+
if "top" in kwargs:
|
|
57
|
+
print(
|
|
58
|
+
"The 'top' parameter has been deprecated. Please remove this parameter from the function going forward."
|
|
59
|
+
)
|
|
60
|
+
del kwargs["top"]
|
|
61
|
+
|
|
62
|
+
if "skip" in kwargs:
|
|
63
|
+
print(
|
|
64
|
+
"The 'skip' parameter has been deprecated. Please remove this parameter from the function going forward."
|
|
65
|
+
)
|
|
66
|
+
del kwargs["skip"]
|
|
67
|
+
|
|
68
|
+
columns = {
|
|
69
|
+
"Id": "string",
|
|
70
|
+
"Name": "string",
|
|
71
|
+
"State": "string",
|
|
72
|
+
"Type": "string",
|
|
73
|
+
"Capacity Id": "string",
|
|
74
|
+
}
|
|
75
|
+
df = _create_dataframe(columns=columns)
|
|
76
|
+
|
|
77
|
+
url = "/v1/admin/workspaces"
|
|
78
|
+
params = {}
|
|
79
|
+
|
|
80
|
+
if capacity is not None:
|
|
81
|
+
params["capacityId"] = _resolve_capacity_name_and_id(capacity)[1]
|
|
82
|
+
|
|
83
|
+
if workspace is not None and not _is_valid_uuid(workspace):
|
|
84
|
+
params["name"] = workspace
|
|
85
|
+
|
|
86
|
+
if workspace_state is not None:
|
|
87
|
+
params["state"] = workspace_state
|
|
88
|
+
|
|
89
|
+
if workspace_type is not None:
|
|
90
|
+
params["type"] = workspace_type
|
|
91
|
+
|
|
92
|
+
url = _build_url(url, params)
|
|
93
|
+
|
|
94
|
+
responses = _base_api(request=url, client="fabric_sp", uses_pagination=True)
|
|
95
|
+
workspaces = []
|
|
96
|
+
|
|
97
|
+
for r in responses:
|
|
98
|
+
workspaces = workspaces + r.get("workspaces", [])
|
|
99
|
+
|
|
100
|
+
if len(workspaces) > 0:
|
|
101
|
+
df = pd.DataFrame(workspaces)
|
|
102
|
+
df.rename(
|
|
103
|
+
columns={
|
|
104
|
+
"id": "Id",
|
|
105
|
+
"name": "Name",
|
|
106
|
+
"state": "State",
|
|
107
|
+
"type": "Type",
|
|
108
|
+
"capacityId": "Capacity Id",
|
|
109
|
+
},
|
|
110
|
+
inplace=True,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
df["Capacity Id"] = df["Capacity Id"].str.lower()
|
|
114
|
+
|
|
115
|
+
if workspace is not None and _is_valid_uuid(workspace):
|
|
116
|
+
df = df[df["Id"] == workspace.lower()]
|
|
117
|
+
|
|
118
|
+
return df
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@log
|
|
122
|
+
def assign_workspaces_to_capacity(
|
|
123
|
+
source_capacity: Optional[str | UUID] = None,
|
|
124
|
+
target_capacity: Optional[str | UUID] = None,
|
|
125
|
+
workspace: Optional[str | List[str] | UUID | List[UUID]] = None,
|
|
126
|
+
):
|
|
127
|
+
"""
|
|
128
|
+
Assigns a workspace to a capacity. This function is the admin version.
|
|
129
|
+
|
|
130
|
+
This is a wrapper function for the following API: `Admin - Capacities AssignWorkspacesToCapacity <https://learn.microsoft.com/rest/api/power-bi/admin/capacities-assign-workspaces-to-capacity>`_.
|
|
131
|
+
|
|
132
|
+
Parameters
|
|
133
|
+
----------
|
|
134
|
+
source_capacity : str | uuid.UUID, default=None
|
|
135
|
+
The name of the source capacity. If the Workspace is not specified, this is parameter mandatory.
|
|
136
|
+
target_capacity : str | uuid.UUID, default=None
|
|
137
|
+
The name of the target capacity.
|
|
138
|
+
workspace : str | List[str] | uuid.UUID | List[uuid.UUID], default=None
|
|
139
|
+
The name or ID of the workspace(s).
|
|
140
|
+
Defaults to None which resolves to migrating all workspaces within the source capacity to the target capacity.
|
|
141
|
+
"""
|
|
142
|
+
from sempy_labs.admin._capacities import _resolve_capacity_name_and_id
|
|
143
|
+
|
|
144
|
+
if target_capacity is None:
|
|
145
|
+
raise ValueError(
|
|
146
|
+
f"{icons.red_dot} The parameter 'target_capacity' is mandatory."
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
if source_capacity is None and workspace is None:
|
|
150
|
+
raise ValueError(
|
|
151
|
+
f"{icons.red_dot} The parameters 'source_capacity' or 'workspace' needs to be specified."
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
if workspace is None:
|
|
155
|
+
source_capacity_id = _resolve_capacity_name_and_id(source_capacity)[1]
|
|
156
|
+
dfW = list_workspaces(capacity=source_capacity_id)
|
|
157
|
+
workspaces = dfW["Id"].tolist()
|
|
158
|
+
else:
|
|
159
|
+
if isinstance(workspace, str) or isinstance(workspace, UUID):
|
|
160
|
+
workspace = [workspace]
|
|
161
|
+
if source_capacity is None:
|
|
162
|
+
dfW = list_workspaces()
|
|
163
|
+
else:
|
|
164
|
+
source_capacity_id = _resolve_capacity_name_and_id(source_capacity)[1]
|
|
165
|
+
dfW = list_workspaces(capacity=source_capacity_id)
|
|
166
|
+
|
|
167
|
+
# Extract names and IDs that are mapped in dfW
|
|
168
|
+
workspaces_names = dfW[dfW["Name"].isin(workspace)]["Name"].tolist()
|
|
169
|
+
workspaces_ids = dfW[dfW["Id"].isin(workspace)]["Id"].tolist()
|
|
170
|
+
|
|
171
|
+
# Combine IDs into the final workspaces list
|
|
172
|
+
workspaces = workspaces_ids + dfW[dfW["Name"].isin(workspace)]["Id"].tolist()
|
|
173
|
+
|
|
174
|
+
# Identify unmapped workspaces
|
|
175
|
+
unmapped_workspaces = [
|
|
176
|
+
item
|
|
177
|
+
for item in workspace
|
|
178
|
+
if item not in workspaces_names and item not in workspaces_ids
|
|
179
|
+
]
|
|
180
|
+
|
|
181
|
+
if len(workspace) != len(workspaces):
|
|
182
|
+
raise ValueError(
|
|
183
|
+
f"{icons.red_dot} The following workspaces are invalid or not found in source capacity: {unmapped_workspaces}."
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
target_capacity_id = _resolve_capacity_name_and_id(target_capacity)[1]
|
|
187
|
+
|
|
188
|
+
workspaces = np.array(workspaces)
|
|
189
|
+
batch_size = 999
|
|
190
|
+
for i in range(0, len(workspaces), batch_size):
|
|
191
|
+
batch = workspaces[i : i + batch_size].tolist()
|
|
192
|
+
payload = {
|
|
193
|
+
"capacityMigrationAssignments": [
|
|
194
|
+
{
|
|
195
|
+
"targetCapacityObjectId": target_capacity_id.upper(),
|
|
196
|
+
"workspacesToAssign": batch,
|
|
197
|
+
}
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
_base_api(
|
|
202
|
+
request="/v1.0/myorg/admin/capacities/AssignWorkspaces",
|
|
203
|
+
method="post",
|
|
204
|
+
payload=payload,
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
print(
|
|
208
|
+
f"{icons.green_dot} The workspaces have been assigned to the '{target_capacity}' capacity. A total of {len(workspaces)} were moved."
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
@log
|
|
213
|
+
def unassign_workspaces_from_capacity(
|
|
214
|
+
workspaces: str | List[str] | UUID | List[UUID],
|
|
215
|
+
):
|
|
216
|
+
"""
|
|
217
|
+
Unassigns workspace(s) from their capacity.
|
|
218
|
+
|
|
219
|
+
This is a wrapper function for the following API: `Admin - Capacities UnassignWorkspacesFromCapacity <https://learn.microsoft.com/rest/api/power-bi/admin/capacities-unassign-workspaces-from-capacity>`_.
|
|
220
|
+
|
|
221
|
+
Parameters
|
|
222
|
+
----------
|
|
223
|
+
workspaces : str | List[str] | uuid.UUID | List[uuid.UUID]
|
|
224
|
+
The workspace name(s) or ID(s).
|
|
225
|
+
"""
|
|
226
|
+
if isinstance(workspaces, str):
|
|
227
|
+
workspaces = [workspaces]
|
|
228
|
+
|
|
229
|
+
dfW = list_workspaces()
|
|
230
|
+
workspacesIds = dfW[dfW["Name"].isin(workspaces)]["Id"].tolist()
|
|
231
|
+
workspacesIds = workspacesIds + dfW[dfW["Id"].isin(workspaces)]["Id"].tolist()
|
|
232
|
+
|
|
233
|
+
if len(workspacesIds) != len(workspaces):
|
|
234
|
+
raise ValueError(
|
|
235
|
+
f"{icons.red_dot} Some of the workspaces provided are not valid."
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
payload = {"workspacesToUnassign": workspacesIds}
|
|
239
|
+
_base_api(
|
|
240
|
+
request="/v1.0/myorg/admin/capacities/UnassignWorkspaces",
|
|
241
|
+
method="post",
|
|
242
|
+
payload=payload,
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
print(
|
|
246
|
+
f"{icons.green_dot} A total of {len(workspacesIds)} workspaces have been unassigned."
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
@log
|
|
251
|
+
def list_modified_workspaces(
|
|
252
|
+
modified_since: Optional[str] = None,
|
|
253
|
+
exclude_inactive_workspaces: Optional[bool] = False,
|
|
254
|
+
exclude_personal_workspaces: Optional[bool] = False,
|
|
255
|
+
) -> pd.DataFrame:
|
|
256
|
+
"""
|
|
257
|
+
Gets a list of workspace IDs in the organization.
|
|
258
|
+
|
|
259
|
+
This is a wrapper function for the following API: `Admin - WorkspaceInfo GetModifiedWorkspaces <https://learn.microsoft.com/rest/api/power-bi/admin/workspace-info-get-modified-workspaces>`_.
|
|
260
|
+
|
|
261
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
262
|
+
|
|
263
|
+
Parameters
|
|
264
|
+
----------
|
|
265
|
+
modified_since : str, default=None
|
|
266
|
+
Last modified date (must be in ISO compliant UTC format). Example: "2024-11-02T05:51:30" or "2024-11-02T05:51:30.0000000Z".
|
|
267
|
+
exclude_inactive_workspaces : bool, default=False
|
|
268
|
+
Whether to exclude inactive workspaces.
|
|
269
|
+
exclude_personal_workspaces : bool, default=False
|
|
270
|
+
Whether to exclude personal workspaces.
|
|
271
|
+
|
|
272
|
+
Returns
|
|
273
|
+
-------
|
|
274
|
+
pandas.DataFrame
|
|
275
|
+
A pandas dataframe showing a list of workspace IDs in the organization.
|
|
276
|
+
"""
|
|
277
|
+
params = {}
|
|
278
|
+
url = "/v1.0/myorg/admin/workspaces/modified"
|
|
279
|
+
|
|
280
|
+
if modified_since is not None:
|
|
281
|
+
modified_since_dt = dtparser(modified_since)
|
|
282
|
+
params["modifiedSince"] = (
|
|
283
|
+
f"{modified_since_dt.isoformat(timespec='microseconds')}0Z"
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
if exclude_inactive_workspaces is not None:
|
|
287
|
+
params["excludeInActiveWorkspaces"] = exclude_inactive_workspaces
|
|
288
|
+
|
|
289
|
+
if exclude_personal_workspaces is not None:
|
|
290
|
+
params["excludePersonalWorkspaces"] = exclude_personal_workspaces
|
|
291
|
+
|
|
292
|
+
url = _build_url(url, params)
|
|
293
|
+
response = _base_api(request=url, client="fabric_sp")
|
|
294
|
+
|
|
295
|
+
df = pd.DataFrame(response.json()).rename(columns={"id": "Workspace Id"})
|
|
296
|
+
|
|
297
|
+
return df
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
@log
|
|
301
|
+
def list_workspace_access_details(
|
|
302
|
+
workspace: Optional[Union[str, UUID]] = None,
|
|
303
|
+
) -> pd.DataFrame:
|
|
304
|
+
"""
|
|
305
|
+
Shows a list of users (including groups and Service Principals) that have access to the specified workspace.
|
|
306
|
+
|
|
307
|
+
This is a wrapper function for the following API: `Workspaces - List Workspace Access Details <https://learn.microsoft.com/rest/api/fabric/admin/workspaces/list-workspace-access-details>`_.
|
|
308
|
+
|
|
309
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
310
|
+
|
|
311
|
+
Parameters
|
|
312
|
+
----------
|
|
313
|
+
workspace : str | uuid.UUID, default=None
|
|
314
|
+
The workspace name or ID.
|
|
315
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
316
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
317
|
+
|
|
318
|
+
Returns
|
|
319
|
+
-------
|
|
320
|
+
pandas.DataFrame
|
|
321
|
+
A pandas dataframe showing a list of users (including groups and Service Principals) that have access to the specified workspace.
|
|
322
|
+
"""
|
|
323
|
+
(workspace_name, workspace_id) = _resolve_workspace_name_and_id(workspace)
|
|
324
|
+
|
|
325
|
+
columns = {
|
|
326
|
+
"User Id": "string",
|
|
327
|
+
"User Name": "string",
|
|
328
|
+
"User Type": "string",
|
|
329
|
+
"Workspace Name": "string",
|
|
330
|
+
"Workspace Id": "string",
|
|
331
|
+
"Workspace Role": "string",
|
|
332
|
+
}
|
|
333
|
+
df = _create_dataframe(columns=columns)
|
|
334
|
+
|
|
335
|
+
response = _base_api(
|
|
336
|
+
request=f"/v1/admin/workspaces/{workspace_id}/users", client="fabric_sp"
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
rows = []
|
|
340
|
+
for v in response.json().get("accessDetails", []):
|
|
341
|
+
rows.append(
|
|
342
|
+
{
|
|
343
|
+
"User Id": v.get("principal", {}).get("id"),
|
|
344
|
+
"User Name": v.get("principal", {}).get("displayName"),
|
|
345
|
+
"User Type": v.get("principal", {}).get("type"),
|
|
346
|
+
"Workspace Name": workspace_name,
|
|
347
|
+
"Workspace Id": workspace_id,
|
|
348
|
+
"Workspace Role": v.get("workspaceAccessDetails", {}).get(
|
|
349
|
+
"workspaceRole"
|
|
350
|
+
),
|
|
351
|
+
}
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
if rows:
|
|
355
|
+
df = pd.DataFrame(rows, columns=list(columns.keys()))
|
|
356
|
+
|
|
357
|
+
return df
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
@log
|
|
361
|
+
def _resolve_workspace_name(workspace_id: Optional[UUID] = None) -> str:
|
|
362
|
+
from sempy_labs._helper_functions import _get_fabric_context_setting
|
|
363
|
+
from sempy.fabric.exceptions import FabricHTTPException
|
|
364
|
+
|
|
365
|
+
if workspace_id is None:
|
|
366
|
+
workspace_id = _get_fabric_context_setting(name="trident.workspace.id")
|
|
367
|
+
|
|
368
|
+
try:
|
|
369
|
+
workspace_name = (
|
|
370
|
+
_base_api(
|
|
371
|
+
request=f"/v1/admin/workspaces/{workspace_id}", client="fabric_sp"
|
|
372
|
+
)
|
|
373
|
+
.json()
|
|
374
|
+
.get("name")
|
|
375
|
+
)
|
|
376
|
+
except FabricHTTPException:
|
|
377
|
+
raise ValueError(
|
|
378
|
+
f"{icons.red_dot} The '{workspace_id}' workspace was not found."
|
|
379
|
+
)
|
|
380
|
+
return workspace_name
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
@log
|
|
384
|
+
def _resolve_workspace_name_and_id(
|
|
385
|
+
workspace: str | UUID,
|
|
386
|
+
) -> Tuple[str, UUID]:
|
|
387
|
+
|
|
388
|
+
from sempy_labs._helper_functions import _get_fabric_context_setting
|
|
389
|
+
|
|
390
|
+
if workspace is None:
|
|
391
|
+
workspace_id = _get_fabric_context_setting(name="trident.workspace.id")
|
|
392
|
+
workspace_name = _resolve_workspace_name(workspace_id)
|
|
393
|
+
elif _is_valid_uuid(workspace):
|
|
394
|
+
workspace_id = workspace
|
|
395
|
+
workspace_name = _resolve_workspace_name(workspace_id)
|
|
396
|
+
else:
|
|
397
|
+
dfW = list_workspaces(workspace=workspace)
|
|
398
|
+
if not dfW.empty:
|
|
399
|
+
workspace_name = dfW["Name"].iloc[0]
|
|
400
|
+
workspace_id = dfW["Id"].iloc[0]
|
|
401
|
+
else:
|
|
402
|
+
raise ValueError(
|
|
403
|
+
f"{icons.red_dot} The '{workspace}' workspace was not found."
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
return workspace_name, workspace_id
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
@log
|
|
410
|
+
def list_workspace_users(workspace: Optional[str | UUID] = None) -> pd.DataFrame:
|
|
411
|
+
"""
|
|
412
|
+
Shows a list of users that have access to the specified workspace.
|
|
413
|
+
|
|
414
|
+
This is a wrapper function for the following API: `Admin - Groups GetGroupUsersAsAdmin <https://learn.microsoft.com/rest/api/power-bi/admin/groups-get-group-users-as-admin>`_.
|
|
415
|
+
|
|
416
|
+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
417
|
+
|
|
418
|
+
Parameters
|
|
419
|
+
----------
|
|
420
|
+
workspace : str | uuid.UUID, default=None
|
|
421
|
+
The workspace name or ID.
|
|
422
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
423
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
424
|
+
|
|
425
|
+
Returns
|
|
426
|
+
-------
|
|
427
|
+
pandas.DataFrame
|
|
428
|
+
A pandas dataframe showing a list of users that have access to the specified workspace.
|
|
429
|
+
"""
|
|
430
|
+
|
|
431
|
+
(workspace_name, workspace_id) = _resolve_workspace_name_and_id(workspace)
|
|
432
|
+
|
|
433
|
+
columns = {
|
|
434
|
+
"User Name": "string",
|
|
435
|
+
"Email Address": "string",
|
|
436
|
+
"Group User Access Right": "string",
|
|
437
|
+
"Identifier": "string",
|
|
438
|
+
"Graph Id": "string",
|
|
439
|
+
"Principal Type": "string",
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
df = _create_dataframe(columns=columns)
|
|
443
|
+
|
|
444
|
+
url = f"/v1.0/myorg/admin/groups/{workspace_id}/users"
|
|
445
|
+
response = _base_api(request=url, client="fabric_sp")
|
|
446
|
+
|
|
447
|
+
rows = []
|
|
448
|
+
for v in response.json().get("value", []):
|
|
449
|
+
rows.append(
|
|
450
|
+
{
|
|
451
|
+
"User Name": v.get("displayName"),
|
|
452
|
+
"Email Address": v.get("emailAddress"),
|
|
453
|
+
"Group User Access Right": v.get("groupUserAccessRight"),
|
|
454
|
+
"Identifier": v.get("identifier"),
|
|
455
|
+
"Graph Id": v.get("graphId"),
|
|
456
|
+
"Principal Type": v.get("principalType"),
|
|
457
|
+
}
|
|
458
|
+
)
|
|
459
|
+
|
|
460
|
+
if rows:
|
|
461
|
+
df = pd.DataFrame(rows, columns=list(columns.keys()))
|
|
462
|
+
|
|
463
|
+
return df
|