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,149 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from uuid import UUID
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from sempy._utils._log import log
|
|
5
|
+
from sempy_labs._helper_functions import (
|
|
6
|
+
_base_api,
|
|
7
|
+
_create_dataframe,
|
|
8
|
+
resolve_item_id,
|
|
9
|
+
resolve_workspace_id,
|
|
10
|
+
resolve_item_name_and_id,
|
|
11
|
+
resolve_workspace_name_and_id,
|
|
12
|
+
)
|
|
13
|
+
import sempy_labs._icons as icons
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@log
|
|
17
|
+
def list_graph_models(workspace: Optional[str | UUID] = None) -> pd.DataFrame:
|
|
18
|
+
"""
|
|
19
|
+
Shows the graph models within a workspace.
|
|
20
|
+
|
|
21
|
+
This is a wrapper function for the following API: `Items - List Graph Models <https://learn.microsoft.com/rest/api/fabric/graphmodel/items/list-graph-models>`_.
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
workspace : str | uuid.UUID, default=None
|
|
26
|
+
The Fabric 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
|
+
|
|
30
|
+
Returns
|
|
31
|
+
-------
|
|
32
|
+
pandas.DataFrame
|
|
33
|
+
A pandas dataframe showing the graph models within a workspace.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
columns = {
|
|
37
|
+
"Graph Model Name": "string",
|
|
38
|
+
"Graph Model Id": "string",
|
|
39
|
+
"Description": "string",
|
|
40
|
+
"OneLake Root Path": "string",
|
|
41
|
+
}
|
|
42
|
+
df = _create_dataframe(columns=columns)
|
|
43
|
+
|
|
44
|
+
workspace_id = resolve_workspace_id(workspace)
|
|
45
|
+
|
|
46
|
+
responses = _base_api(
|
|
47
|
+
request=f"/v1/workspaces/{workspace_id}/GraphModels",
|
|
48
|
+
uses_pagination=True,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
rows = []
|
|
52
|
+
for r in responses:
|
|
53
|
+
for v in r.get("value", []):
|
|
54
|
+
rows.append(
|
|
55
|
+
{
|
|
56
|
+
"Graph Model Name": v.get("displayName"),
|
|
57
|
+
"Graph Model Id": v.get("id"),
|
|
58
|
+
"Description": v.get("description"),
|
|
59
|
+
"OneLake Root Path": v.get("properties", {}).get("oneLakeRootPath"),
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
if rows:
|
|
64
|
+
df = pd.DataFrame(rows, columns=list(columns.keys()))
|
|
65
|
+
|
|
66
|
+
return df
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@log
|
|
70
|
+
def execute_query(
|
|
71
|
+
graph_model: str | UUID, query: str, workspace: Optional[str | UUID] = None
|
|
72
|
+
) -> dict:
|
|
73
|
+
"""
|
|
74
|
+
Executes a query on the specified graph model.
|
|
75
|
+
|
|
76
|
+
This is a wrapper function for the following API: `Items - ExecuteQuery <https://learn.microsoft.com/rest/api/fabric/graphmodel/items/execute-query(preview)>`_.
|
|
77
|
+
|
|
78
|
+
Parameters
|
|
79
|
+
----------
|
|
80
|
+
graph_model : str | uuid.UUID
|
|
81
|
+
The graph model name or ID.
|
|
82
|
+
query : str
|
|
83
|
+
The query string.
|
|
84
|
+
workspace : str | uuid.UUID, default=None
|
|
85
|
+
The Fabric workspace name or ID.
|
|
86
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
87
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
88
|
+
|
|
89
|
+
Returns
|
|
90
|
+
-------
|
|
91
|
+
dict
|
|
92
|
+
The response from the API.
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
(workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
|
|
96
|
+
(item_name, item_id) = resolve_item_name_and_id(
|
|
97
|
+
item=graph_model, type="GraphModel", workspace=workspace_id
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
payload = {
|
|
101
|
+
"query": query,
|
|
102
|
+
}
|
|
103
|
+
response = _base_api(
|
|
104
|
+
request=f"/v1/workspaces/{workspace_id}/GraphModels/{item_id}/executeQuery?preview=True",
|
|
105
|
+
method="post",
|
|
106
|
+
payload=payload,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
print(
|
|
110
|
+
f"{icons.green_dot} Executed query on Graph Model '{item_name}' in workspace '{workspace_name}' successfully."
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
return response.json()
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@log
|
|
117
|
+
def get_queryable_graph_type(
|
|
118
|
+
graph_model: str | UUID, workspace: Optional[str | UUID] = None
|
|
119
|
+
) -> dict:
|
|
120
|
+
"""
|
|
121
|
+
Gets the current queryable graph type.
|
|
122
|
+
|
|
123
|
+
This is a wrapper function for the following API: `Items - GetQueryableGraphType <https://learn.microsoft.com/rest/api/fabric/graphmodel/items/get-queryable-graph-type(preview)>`_.
|
|
124
|
+
|
|
125
|
+
Parameters
|
|
126
|
+
----------
|
|
127
|
+
graph_model : str | uuid.UUID
|
|
128
|
+
The graph model name or ID.
|
|
129
|
+
workspace : str | uuid.UUID, default=None
|
|
130
|
+
The Fabric workspace name or ID.
|
|
131
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
132
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
133
|
+
|
|
134
|
+
Returns
|
|
135
|
+
-------
|
|
136
|
+
dict
|
|
137
|
+
A dictionary showing the current queryable graph type.
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
workspace_id = resolve_workspace_id(workspace)
|
|
141
|
+
item_id = resolve_item_id(
|
|
142
|
+
item=graph_model, type="GraphModel", workspace=workspace_id
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
response = _base_api(
|
|
146
|
+
request=f"/v1/workspaces/{workspace_id}/GraphModels/{item_id}/getQueryableGraphType?preview=True"
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
return response.json()
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from ._get_lakehouse_columns import (
|
|
2
|
+
get_lakehouse_columns,
|
|
3
|
+
)
|
|
4
|
+
from ._get_lakehouse_tables import (
|
|
5
|
+
get_lakehouse_tables,
|
|
6
|
+
)
|
|
7
|
+
from ._lakehouse import (
|
|
8
|
+
lakehouse_attached,
|
|
9
|
+
optimize_lakehouse_tables,
|
|
10
|
+
vacuum_lakehouse_tables,
|
|
11
|
+
run_table_maintenance,
|
|
12
|
+
list_lakehouses,
|
|
13
|
+
)
|
|
14
|
+
from ._shortcuts import (
|
|
15
|
+
# create_shortcut,
|
|
16
|
+
create_shortcut_onelake,
|
|
17
|
+
delete_shortcut,
|
|
18
|
+
reset_shortcut_cache,
|
|
19
|
+
list_shortcuts,
|
|
20
|
+
)
|
|
21
|
+
from ._blobs import (
|
|
22
|
+
recover_lakehouse_object,
|
|
23
|
+
list_blobs,
|
|
24
|
+
)
|
|
25
|
+
from ._livy_sessions import (
|
|
26
|
+
list_livy_sessions,
|
|
27
|
+
)
|
|
28
|
+
from ._helper import (
|
|
29
|
+
is_v_ordered,
|
|
30
|
+
delete_lakehouse,
|
|
31
|
+
update_lakehouse,
|
|
32
|
+
load_table,
|
|
33
|
+
)
|
|
34
|
+
from ._materialized_lake_views import (
|
|
35
|
+
refresh_materialized_lake_views,
|
|
36
|
+
)
|
|
37
|
+
from ._schemas import (
|
|
38
|
+
list_schemas,
|
|
39
|
+
schema_exists,
|
|
40
|
+
is_schema_enabled,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
__all__ = [
|
|
44
|
+
"get_lakehouse_columns",
|
|
45
|
+
"get_lakehouse_tables",
|
|
46
|
+
"lakehouse_attached",
|
|
47
|
+
"optimize_lakehouse_tables",
|
|
48
|
+
# create_shortcut,
|
|
49
|
+
"create_shortcut_onelake",
|
|
50
|
+
"delete_shortcut",
|
|
51
|
+
"vacuum_lakehouse_tables",
|
|
52
|
+
"reset_shortcut_cache",
|
|
53
|
+
"run_table_maintenance",
|
|
54
|
+
"list_shortcuts",
|
|
55
|
+
"recover_lakehouse_object",
|
|
56
|
+
"list_blobs",
|
|
57
|
+
"list_livy_sessions",
|
|
58
|
+
"is_v_ordered",
|
|
59
|
+
"delete_lakehouse",
|
|
60
|
+
"update_lakehouse",
|
|
61
|
+
"load_table",
|
|
62
|
+
"refresh_materialized_lake_views",
|
|
63
|
+
"list_lakehouses",
|
|
64
|
+
"list_schemas",
|
|
65
|
+
"schema_exists",
|
|
66
|
+
"is_schema_enabled",
|
|
67
|
+
]
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
from sempy_labs._helper_functions import (
|
|
2
|
+
resolve_workspace_id,
|
|
3
|
+
resolve_lakehouse_id,
|
|
4
|
+
_xml_to_dict,
|
|
5
|
+
_create_dataframe,
|
|
6
|
+
_update_dataframe_datatypes,
|
|
7
|
+
)
|
|
8
|
+
from sempy._utils._log import log
|
|
9
|
+
from uuid import UUID
|
|
10
|
+
from typing import Optional, List
|
|
11
|
+
import sempy_labs._icons as icons
|
|
12
|
+
import xml.etree.ElementTree as ET
|
|
13
|
+
import pandas as pd
|
|
14
|
+
from sempy.fabric.exceptions import FabricHTTPException
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@log
|
|
18
|
+
def _request_blob_api(
|
|
19
|
+
request: str,
|
|
20
|
+
method: str = "get",
|
|
21
|
+
payload: Optional[dict] = None,
|
|
22
|
+
status_codes: int | List[int] = 200,
|
|
23
|
+
uses_pagination: bool = False,
|
|
24
|
+
):
|
|
25
|
+
|
|
26
|
+
import requests
|
|
27
|
+
import notebookutils
|
|
28
|
+
from sempy.fabric.exceptions import FabricHTTPException
|
|
29
|
+
|
|
30
|
+
if isinstance(status_codes, int):
|
|
31
|
+
status_codes = [status_codes]
|
|
32
|
+
|
|
33
|
+
token = notebookutils.credentials.getToken("storage")
|
|
34
|
+
|
|
35
|
+
headers = {
|
|
36
|
+
"Authorization": f"Bearer {token}",
|
|
37
|
+
"Content-Type": "application/xml",
|
|
38
|
+
"x-ms-version": "2025-05-05",
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
base_url = "https://onelake.blob.fabric.microsoft.com/"
|
|
42
|
+
full_url = f"{base_url}{request}"
|
|
43
|
+
results = []
|
|
44
|
+
|
|
45
|
+
while True:
|
|
46
|
+
response = requests.request(
|
|
47
|
+
method.upper(),
|
|
48
|
+
full_url,
|
|
49
|
+
headers=headers,
|
|
50
|
+
data=payload if method.lower() != "get" else None,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
if response.status_code not in status_codes:
|
|
54
|
+
raise FabricHTTPException(response)
|
|
55
|
+
|
|
56
|
+
if not uses_pagination:
|
|
57
|
+
return response
|
|
58
|
+
|
|
59
|
+
# Parse XML to find blobs and NextMarker
|
|
60
|
+
root = ET.fromstring(response.content)
|
|
61
|
+
results.append(root)
|
|
62
|
+
|
|
63
|
+
next_marker = root.findtext(".//NextMarker")
|
|
64
|
+
if not next_marker:
|
|
65
|
+
break # No more pages
|
|
66
|
+
|
|
67
|
+
# Append the marker to the original request (assuming query string format)
|
|
68
|
+
delimiter = "&" if "?" in request else "?"
|
|
69
|
+
full_url = f"{base_url}{request}{delimiter}marker={next_marker}"
|
|
70
|
+
|
|
71
|
+
return results
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@log
|
|
75
|
+
def list_blobs(
|
|
76
|
+
lakehouse: Optional[str | UUID] = None,
|
|
77
|
+
workspace: Optional[str | UUID] = None,
|
|
78
|
+
container: Optional[str] = None,
|
|
79
|
+
) -> pd.DataFrame:
|
|
80
|
+
"""
|
|
81
|
+
Returns a list of blobs for a given lakehouse.
|
|
82
|
+
|
|
83
|
+
This function leverages the following API: `List Blobs <https://learn.microsoft.com/rest/api/storageservices/list-blobs?tabs=microsoft-entra-id>`_.
|
|
84
|
+
|
|
85
|
+
Parameters
|
|
86
|
+
----------
|
|
87
|
+
lakehouse : str | uuid.UUID, default=None
|
|
88
|
+
The Fabric lakehouse name or ID.
|
|
89
|
+
Defaults to None which resolves to the lakehouse attached to the notebook.
|
|
90
|
+
workspace : str | uuid.UUID, default=None
|
|
91
|
+
The Fabric workspace name or ID used by the lakehouse.
|
|
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
|
+
container : str, default=None
|
|
95
|
+
The container name to list blobs from. If None, lists all blobs in the lakehouse.
|
|
96
|
+
Valid values are "Tables" or "Files". If not specified, the function will list all blobs in the lakehouse.
|
|
97
|
+
|
|
98
|
+
Returns
|
|
99
|
+
-------
|
|
100
|
+
pandas.DataFrame
|
|
101
|
+
A pandas dataframe showing a list of blobs in the lakehouse.
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
workspace_id = resolve_workspace_id(workspace)
|
|
105
|
+
lakehouse_id = resolve_lakehouse_id(lakehouse, workspace_id)
|
|
106
|
+
|
|
107
|
+
if container is None:
|
|
108
|
+
path_prefix = f"{workspace_id}/{lakehouse_id}"
|
|
109
|
+
else:
|
|
110
|
+
if container not in ["Tables", "Files"]:
|
|
111
|
+
raise ValueError(
|
|
112
|
+
f"{icons.red_dot} Invalid container '{container}' within the file_path parameter. Expected 'Tables' or 'Files'."
|
|
113
|
+
)
|
|
114
|
+
path_prefix = f"{workspace_id}/{lakehouse_id}/{container}"
|
|
115
|
+
|
|
116
|
+
columns = {
|
|
117
|
+
"Blob Name": "str",
|
|
118
|
+
"Is Deleted": "bool",
|
|
119
|
+
"Deletion Id": "str",
|
|
120
|
+
"Creation Time": "datetime",
|
|
121
|
+
"Expiry Time": "datetime",
|
|
122
|
+
"Etag": "str",
|
|
123
|
+
"Resource Type": "str",
|
|
124
|
+
"Content Length": "int",
|
|
125
|
+
"Content Type": "str",
|
|
126
|
+
"Content Encoding": "str",
|
|
127
|
+
"Content Language": "str",
|
|
128
|
+
"Content CRC64": "str",
|
|
129
|
+
"Content MD5": "str",
|
|
130
|
+
"Cache Control": "str",
|
|
131
|
+
"Content Disposition": "str",
|
|
132
|
+
"Blob Type": "str",
|
|
133
|
+
"Access Tier": "str",
|
|
134
|
+
"Access Tier Inferred": "str",
|
|
135
|
+
"Server Encrypted": "bool",
|
|
136
|
+
"Deleted Time": "str",
|
|
137
|
+
"Remaining Retention Days": "str",
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
df = _create_dataframe(columns=columns)
|
|
141
|
+
|
|
142
|
+
url = f"{path_prefix}?restype=container&comp=list&include=deleted"
|
|
143
|
+
|
|
144
|
+
responses = _request_blob_api(
|
|
145
|
+
request=url,
|
|
146
|
+
uses_pagination=True,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
rows = []
|
|
150
|
+
for root in responses:
|
|
151
|
+
response_json = _xml_to_dict(root)
|
|
152
|
+
|
|
153
|
+
blobs = (
|
|
154
|
+
response_json.get("EnumerationResults", {}).get("Blobs", {}).get("Blob", [])
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
if isinstance(blobs, dict):
|
|
158
|
+
blobs = [blobs]
|
|
159
|
+
|
|
160
|
+
for blob in blobs:
|
|
161
|
+
p = blob.get("Properties", {})
|
|
162
|
+
rows.append(
|
|
163
|
+
{
|
|
164
|
+
"Blob Name": blob.get("Name"),
|
|
165
|
+
"Is Deleted": blob.get("Deleted", False),
|
|
166
|
+
"Deletion Id": blob.get("DeletionId"),
|
|
167
|
+
"Creation Time": p.get("Creation-Time"),
|
|
168
|
+
"Expiry Time": p.get("Expiry-Time"),
|
|
169
|
+
"Etag": p.get("Etag"),
|
|
170
|
+
"Resource Type": p.get("ResourceType"),
|
|
171
|
+
"Content Length": p.get("Content-Length"),
|
|
172
|
+
"Content Type": p.get("Content-Type"),
|
|
173
|
+
"Content Encoding": p.get("Content-Encoding"),
|
|
174
|
+
"Content Language": p.get("Content-Language"),
|
|
175
|
+
"Content CRC64": p.get("Content-CRC64"),
|
|
176
|
+
"Content MD5": p.get("Content-MD5"),
|
|
177
|
+
"Cache Control": p.get("Cache-Control"),
|
|
178
|
+
"Content Disposition": p.get("Content-Disposition"),
|
|
179
|
+
"Blob Type": p.get("BlobType"),
|
|
180
|
+
"Access Tier": p.get("AccessTier"),
|
|
181
|
+
"Access Tier Inferred": p.get("AccessTierInferred"),
|
|
182
|
+
"Server Encrypted": p.get("ServerEncrypted"),
|
|
183
|
+
"Deleted Time": p.get("DeletedTime"),
|
|
184
|
+
"Remaining Retention Days": p.get("RemainingRetentionDays"),
|
|
185
|
+
}
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
if rows:
|
|
189
|
+
df = pd.DataFrame(rows, columns=list(columns.keys()))
|
|
190
|
+
_update_dataframe_datatypes(dataframe=df, column_map=columns)
|
|
191
|
+
|
|
192
|
+
return df
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
@log
|
|
196
|
+
def recover_lakehouse_object(
|
|
197
|
+
file_path: str,
|
|
198
|
+
lakehouse: Optional[str | UUID] = None,
|
|
199
|
+
workspace: Optional[str | UUID] = None,
|
|
200
|
+
):
|
|
201
|
+
"""
|
|
202
|
+
Recovers an object (i.e. table, file, folder) in a lakehouse from a deleted state. Only `soft-deleted objects <https://learn.microsoft.com/fabric/onelake/onelake-disaster-recovery#soft-delete-for-onelake-files>`_ can be recovered (deleted for less than 7 days).
|
|
203
|
+
|
|
204
|
+
Parameters
|
|
205
|
+
----------
|
|
206
|
+
file_path : str
|
|
207
|
+
The file path of the object to restore. For example: "Tables/my_delta_table".
|
|
208
|
+
lakehouse : str | uuid.UUID, default=None
|
|
209
|
+
The Fabric lakehouse name or ID.
|
|
210
|
+
Defaults to None which resolves to the lakehouse attached to the notebook.
|
|
211
|
+
workspace : str | uuid.UUID, default=None
|
|
212
|
+
The Fabric workspace name or ID used by the lakehouse.
|
|
213
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
214
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
215
|
+
"""
|
|
216
|
+
|
|
217
|
+
workspace_id = resolve_workspace_id(workspace)
|
|
218
|
+
lakehouse_id = resolve_lakehouse_id(lakehouse, workspace_id)
|
|
219
|
+
|
|
220
|
+
blob_name = f"{lakehouse_id}/{file_path}"
|
|
221
|
+
|
|
222
|
+
container = file_path.split("/")[0]
|
|
223
|
+
if container not in ["Tables", "Files"]:
|
|
224
|
+
raise ValueError(
|
|
225
|
+
f"{icons.red_dot} Invalid container '{container}' within the file_path parameter. Expected 'Tables' or 'Files'."
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
# Undelete the blob
|
|
229
|
+
print(f"{icons.in_progress} Attempting to recover the '{blob_name}' blob...")
|
|
230
|
+
|
|
231
|
+
try:
|
|
232
|
+
_request_blob_api(
|
|
233
|
+
request=f"{workspace_id}/{lakehouse_id}/{file_path}?comp=undelete",
|
|
234
|
+
method="put",
|
|
235
|
+
)
|
|
236
|
+
print(
|
|
237
|
+
f"{icons.green_dot} The '{blob_name}' blob recover attempt was successful."
|
|
238
|
+
)
|
|
239
|
+
except FabricHTTPException as e:
|
|
240
|
+
if e.status_code == 404:
|
|
241
|
+
print(
|
|
242
|
+
f"{icons.warning} The '{blob_name}' blob was not found. No action taken."
|
|
243
|
+
)
|
|
244
|
+
else:
|
|
245
|
+
print(
|
|
246
|
+
f"{icons.red_dot} An error occurred while recovering the '{blob_name}' blob: {e}"
|
|
247
|
+
)
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import re
|
|
3
|
+
from sempy_labs._helper_functions import (
|
|
4
|
+
format_dax_object_name,
|
|
5
|
+
resolve_workspace_name_and_id,
|
|
6
|
+
resolve_lakehouse_name_and_id,
|
|
7
|
+
_create_dataframe,
|
|
8
|
+
_get_delta_table,
|
|
9
|
+
_pure_python_notebook,
|
|
10
|
+
)
|
|
11
|
+
from typing import Optional
|
|
12
|
+
from sempy._utils._log import log
|
|
13
|
+
from uuid import UUID
|
|
14
|
+
import sempy_labs._icons as icons
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@log
|
|
18
|
+
def get_lakehouse_columns(
|
|
19
|
+
lakehouse: Optional[str | UUID] = None, workspace: Optional[str | UUID] = None
|
|
20
|
+
) -> pd.DataFrame:
|
|
21
|
+
"""
|
|
22
|
+
Shows the tables and columns of a lakehouse and their respective properties. This function can be executed in either a PySpark or pure Python notebook. Note that data types may show differently when using PySpark vs pure Python.
|
|
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
|
+
lakehouse : str | uuid.UUID, default=None
|
|
29
|
+
The Fabric lakehouse name or ID.
|
|
30
|
+
Defaults to None which resolves to the lakehouse attached to the notebook.
|
|
31
|
+
lakehouse_workspace : str | uuid.UUID, default=None
|
|
32
|
+
The Fabric workspace name or ID used by the lakehouse.
|
|
33
|
+
Defaults to None which resolves to the workspace of the attached lakehouse
|
|
34
|
+
or if no lakehouse attached, resolves to the workspace of the notebook.
|
|
35
|
+
|
|
36
|
+
Returns
|
|
37
|
+
-------
|
|
38
|
+
pandas.DataFrame
|
|
39
|
+
Shows the tables/columns within a lakehouse and their properties.
|
|
40
|
+
"""
|
|
41
|
+
from ._get_lakehouse_tables import get_lakehouse_tables
|
|
42
|
+
|
|
43
|
+
columns = {
|
|
44
|
+
"Workspace Name": "string",
|
|
45
|
+
"Lakehouse Name": "string",
|
|
46
|
+
"Table Name": "string",
|
|
47
|
+
"Column Name": "string",
|
|
48
|
+
"Full Column Name": "string",
|
|
49
|
+
"Data Type": "string",
|
|
50
|
+
}
|
|
51
|
+
df = _create_dataframe(columns=columns)
|
|
52
|
+
|
|
53
|
+
(workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
|
|
54
|
+
(lakehouse_name, lakehouse_id) = resolve_lakehouse_name_and_id(
|
|
55
|
+
lakehouse=lakehouse, workspace=workspace_id
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
tables = get_lakehouse_tables(
|
|
59
|
+
lakehouse=lakehouse_id, workspace=workspace_id, extended=False, count_rows=False
|
|
60
|
+
)
|
|
61
|
+
tables_filt = tables[tables["Format"] == "delta"]
|
|
62
|
+
|
|
63
|
+
def add_column_metadata(table_name, col_name, data_type):
|
|
64
|
+
new_rows.append(
|
|
65
|
+
{
|
|
66
|
+
"Workspace Name": workspace_name,
|
|
67
|
+
"Lakehouse Name": lakehouse_name,
|
|
68
|
+
"Table Name": table_name,
|
|
69
|
+
"Column Name": col_name,
|
|
70
|
+
"Full Column Name": format_dax_object_name(table_name, col_name),
|
|
71
|
+
"Data Type": data_type,
|
|
72
|
+
}
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
new_rows = []
|
|
76
|
+
|
|
77
|
+
for _, r in tables_filt.iterrows():
|
|
78
|
+
table_name = r["Table Name"]
|
|
79
|
+
path = r["Location"]
|
|
80
|
+
|
|
81
|
+
if _pure_python_notebook():
|
|
82
|
+
from deltalake import DeltaTable
|
|
83
|
+
|
|
84
|
+
table_schema = DeltaTable(path).schema()
|
|
85
|
+
|
|
86
|
+
for field in table_schema.fields:
|
|
87
|
+
col_name = field.name
|
|
88
|
+
match = re.search(r'"(.*?)"', str(field.type))
|
|
89
|
+
if not match:
|
|
90
|
+
raise ValueError(
|
|
91
|
+
f"{icons.red_dot} Could not find data type for column {col_name}."
|
|
92
|
+
)
|
|
93
|
+
data_type = match.group(1)
|
|
94
|
+
add_column_metadata(table_name, col_name, data_type)
|
|
95
|
+
else:
|
|
96
|
+
delta_table = _get_delta_table(path=path)
|
|
97
|
+
table_df = delta_table.toDF()
|
|
98
|
+
|
|
99
|
+
for col_name, data_type in table_df.dtypes:
|
|
100
|
+
add_column_metadata(table_name, col_name, data_type)
|
|
101
|
+
|
|
102
|
+
return pd.concat([df, pd.DataFrame(new_rows)], ignore_index=True)
|