Skip to content

Commit

Permalink
Merge branch 'microsoft:main' into cross_region
Browse files Browse the repository at this point in the history
  • Loading branch information
MitchSS authored Dec 16, 2024
2 parents dd8c55a + 299381e commit 9b88466
Show file tree
Hide file tree
Showing 11 changed files with 344 additions and 60 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Semantic Link Labs

[![PyPI version](https://badge.fury.io/py/semantic-link-labs.svg)](https://badge.fury.io/py/semantic-link-labs)
[![Read The Docs](https://readthedocs.org/projects/semantic-link-labs/badge/?version=0.8.9&style=flat)](https://readthedocs.org/projects/semantic-link-labs/)
[![Read The Docs](https://readthedocs.org/projects/semantic-link-labs/badge/?version=0.8.10&style=flat)](https://readthedocs.org/projects/semantic-link-labs/)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Downloads](https://static.pepy.tech/badge/semantic-link-labs)](https://pepy.tech/project/semantic-link-labs)

Expand Down Expand Up @@ -116,6 +116,7 @@ An even better way to ensure the semantic-link-labs library is available in your
2. Select your newly created environment within the 'Environment' drop down in the navigation bar at the top of the notebook

## Version History
* [0.8.10](https://github.com/microsoft/semantic-link-labs/releases/tag/0.8.10) (December 16, 2024)
* [0.8.9](https://github.com/microsoft/semantic-link-labs/releases/tag/0.8.9) (December 4, 2024)
* [0.8.8](https://github.com/microsoft/semantic-link-labs/releases/tag/0.8.8) (November 28, 2024)
* [0.8.7](https://github.com/microsoft/semantic-link-labs/releases/tag/0.8.7) (November 27, 2024)
Expand Down
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
project = 'semantic-link-labs'
copyright = '2024, Microsoft and community'
author = 'Microsoft and community'
release = '0.8.9'
release = '0.8.10'

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ name="semantic-link-labs"
authors = [
{ name = "Microsoft Corporation" },
]
version="0.8.9"
version="0.8.10"
description="Semantic Link Labs for Microsoft Fabric"
readme="README.md"
requires-python=">=3.10,<3.12"
Expand Down
8 changes: 8 additions & 0 deletions src/sempy_labs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
create_vnet_gateway,
update_vnet_gateway,
update_on_premises_gateway,
bind_semantic_model_to_gateway,
)

from sempy_labs._authentication import (
Expand Down Expand Up @@ -205,6 +206,8 @@
list_lakehouses,
list_sql_endpoints,
update_item,
list_server_properties,
list_semantic_model_errors,
)
from sempy_labs._helper_functions import (
convert_to_friendly_case,
Expand All @@ -230,6 +233,7 @@
get_capacity_id,
get_capacity_name,
resolve_capacity_name,
get_tenant_id,
)
from sempy_labs._model_bpa_bulk import (
run_model_bpa_bulk,
Expand Down Expand Up @@ -458,4 +462,8 @@
"update_vnet_gateway",
"update_on_premises_gateway",
"get_semantic_model_definition",
"get_tenant_id",
"list_server_properties",
"bind_semantic_model_to_gateway",
"list_semantic_model_errors",
]
33 changes: 31 additions & 2 deletions src/sempy_labs/_authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,13 @@ def from_azure_key_vault(

return cls(credential)

def __call__(self, audience: Literal["pbi", "storage"] = "pbi") -> str:
def __call__(
self, audience: Literal["pbi", "storage", "azure", "graph"] = "pbi"
) -> str:
"""
Parameters
----------
audience : Literal["pbi", "storage"] = "pbi") -> str
audience : Literal["pbi", "storage", "azure", "graph"] = "pbi") -> str
Literal if it's for PBI/Fabric API call or OneLake/Storage Account call.
"""
if audience == "pbi":
Expand All @@ -104,5 +106,32 @@ def __call__(self, audience: Literal["pbi", "storage"] = "pbi") -> str:
).token
elif audience == "storage":
return self.credential.get_token("https://storage.azure.com/.default").token
elif audience == "azure":
return self.credential.get_token(
"https://management.azure.com/.default"
).token
elif audience == "graph":
return self.credential.get_token(
"https://graph.microsoft.com/.default"
).token
else:
raise NotImplementedError


def _get_headers(
token_provider: str, audience: Literal["pbi", "storage", "azure", "graph"] = "azure"
):
"""
Generates headers for an API request.
"""

token = token_provider(audience=audience)

headers = {"Authorization": f"Bearer {token}"}

if audience == "graph":
headers["ConsistencyLevel"] = "eventual"
else:
headers["Content-Type"] = "application/json"

return headers
46 changes: 46 additions & 0 deletions src/sempy_labs/_gateways.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
pagination,
_is_valid_uuid,
resolve_capacity_id,
resolve_workspace_name_and_id,
resolve_dataset_name_and_id,
)
from uuid import UUID
import sempy_labs._icons as icons
Expand Down Expand Up @@ -437,3 +439,47 @@ def update_vnet_gateway(
raise FabricHTTPException(response)

print(f"{icons.green_dot} The '{gateway}' has been updated accordingly.")


def bind_semantic_model_to_gateway(
dataset: str | UUID, gateway: str | UUID, workspace: Optional[str | UUID] = None
):
"""
Binds the specified dataset from the specified workspace to the specified gateway.
This is a wrapper function for the following API: `Datasets - Bind To Gateway In Group <https://learn.microsoft.com/rest/api/power-bi/datasets/bind-to-gateway-in-group>`_.
Parameters
----------
dataset : str | UUID
The name or ID of the semantic model.
gateway : str | UUID
The name or ID of the gateway.
workspace : str | UUID, default=None
The Fabric workspace name.
Defaults to None which resolves to the workspace of the attached lakehouse
or if no lakehouse attached, resolves to the workspace of the notebook.
"""

(workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
(dataset_name, dataset_id) = resolve_dataset_name_and_id(
dataset, workspace=workspace_id
)

gateway_id = _resolve_gateway_id(gateway)
payload = {
"gatewayObjectId": gateway_id,
}

client = fabric.FabricRestClient()
response = client.post(
f"/v1.0/myorg/groups/{workspace_id}/datasets/{dataset_id}/Default.BindToGateway",
json=payload,
)

if response.status_code != 200:
raise FabricHTTPException(response)

print(
f"{icons.green_dot} The '{dataset_name}' semantic model within the '{workspace_name}' workspace has been binded to the '{gateway_id}' gateway."
)
59 changes: 32 additions & 27 deletions src/sempy_labs/_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,43 +277,48 @@ def commit_to_git(
workspace, workspace_id = resolve_workspace_name_and_id(workspace)

gs = get_git_status(workspace=workspace)
workspace_head = gs["Workspace Head"].iloc[0]
if not gs.empty:
workspace_head = gs["Workspace Head"].iloc[0]

if item_ids is None:
commit_mode = "All"
else:
commit_mode = "Selective"
if item_ids is None:
commit_mode = "All"
else:
commit_mode = "Selective"

if isinstance(item_ids, str):
item_ids = [item_ids]
if isinstance(item_ids, str):
item_ids = [item_ids]

request_body = {
"mode": commit_mode,
"workspaceHead": workspace_head,
"comment": comment,
}
request_body = {
"mode": commit_mode,
"workspaceHead": workspace_head,
"comment": comment,
}

if item_ids is not None:
request_body["items"] = [{"objectId": item_id} for item_id in item_ids]
if item_ids is not None:
request_body["items"] = [{"objectId": item_id} for item_id in item_ids]

client = fabric.FabricRestClient()
response = client.post(
f"/v1/workspaces/{workspace_id}/git/commitToGit",
json=request_body,
)
client = fabric.FabricRestClient()
response = client.post(
f"/v1/workspaces/{workspace_id}/git/commitToGit",
json=request_body,
)

if response.status_code not in [200, 202]:
raise FabricHTTPException(response)
if response.status_code not in [200, 202]:
raise FabricHTTPException(response)

lro(client, response)
lro(client=client, response=response, return_status_code=True)

if commit_mode == "All":
print(
f"{icons.green_dot} All items within the '{workspace}' workspace have been committed to Git."
)
if commit_mode == "All":
print(
f"{icons.green_dot} All items within the '{workspace}' workspace have been committed to Git."
)
else:
print(
f"{icons.green_dot} The {item_ids} items within the '{workspace}' workspace have been committed to Git."
)
else:
print(
f"{icons.green_dot} The {item_ids} items ithin the '{workspace}' workspace have been committed to Git."
f"{icons.info} Git already up to date: no modified items found within the '{workspace}' workspace."
)


Expand Down
30 changes: 24 additions & 6 deletions src/sempy_labs/_helper_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -780,13 +780,19 @@ def get_capacity_id(workspace: Optional[str] = None) -> UUID:
The capacity Id.
"""

workspace = fabric.resolve_workspace_name(workspace)
filter_condition = urllib.parse.quote(workspace)
dfW = fabric.list_workspaces(filter=f"name eq '{filter_condition}'")
if len(dfW) == 0:
raise ValueError(f"{icons.red_dot} The '{workspace}' does not exist'.")
if workspace is None:
capacity_id = _get_x_id(name="trident.capacity.id")
else:

workspace = fabric.resolve_workspace_name(workspace)
filter_condition = urllib.parse.quote(workspace)
dfW = fabric.list_workspaces(filter=f"name eq '{filter_condition}'")
if len(dfW) == 0:
raise ValueError(f"{icons.red_dot} The '{workspace}' does not exist'.")

capacity_id = dfW["Capacity Id"].iloc[0]

return dfW["Capacity Id"].iloc[0]
return capacity_id


def get_capacity_name(workspace: Optional[str] = None) -> str:
Expand Down Expand Up @@ -1371,3 +1377,15 @@ def _is_valid_uuid(
return True
except ValueError:
return False


def _get_fabric_context_setting(name: str):

from synapse.ml.internal_utils.session_utils import get_fabric_context

return get_fabric_context().get(name)


def get_tenant_id():

_get_fabric_context_setting(name="trident.tenant.id")
Loading

0 comments on commit 9b88466

Please sign in to comment.