From 55c5cf1ddea0c323bdda0b61ea5e2a50390c185a Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 12 Dec 2024 12:07:06 +0200 Subject: [PATCH 01/22] enabling multiple notebook suffixes --- src/sempy_labs/_notebooks.py | 56 +++++++++++++++++++++++++++--------- src/sempy_labs/tom/_model.py | 8 ++++-- 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/src/sempy_labs/_notebooks.py b/src/sempy_labs/_notebooks.py index b9d24222..41fc5950 100644 --- a/src/sempy_labs/_notebooks.py +++ b/src/sempy_labs/_notebooks.py @@ -10,6 +10,40 @@ _decode_b64, ) from sempy.fabric.exceptions import FabricHTTPException +import os + + +def _get_notebook_definition_base( + notebook_name: str, workspace: Optional[str] = None +) -> pd.DataFrame: + + (workspace, workspace_id) = resolve_workspace_name_and_id(workspace) + item_id = fabric.resolve_item_id( + item_name=notebook_name, type="Notebook", workspace=workspace + ) + client = fabric.FabricRestClient() + response = client.post( + f"v1/workspaces/{workspace_id}/notebooks/{item_id}/getDefinition", + ) + + result = lro(client, response).json() + + return pd.json_normalize(result["definition"]["parts"]) + + +def _get_notebook_type(notebook_name: str, workspace: Optional[str] = None) -> str: + + df_items = _get_notebook_definition_base( + notebook_name=notebook_name, workspace=workspace + ) + + file_path = df_items[df_items["path"].str.startswith("notebook-content")][ + "path" + ].iloc[0] + + _, file_extension = os.path.splitext(file_path) + + return file_extension[1:] def get_notebook_definition( @@ -38,17 +72,9 @@ def get_notebook_definition( The notebook definition. """ - (workspace, workspace_id) = resolve_workspace_name_and_id(workspace) - item_id = fabric.resolve_item_id( - item_name=notebook_name, type="Notebook", workspace=workspace + df_items = _get_notebook_definition_base( + notebook_name=notebook_name, workspace=workspace ) - client = fabric.FabricRestClient() - response = client.post( - f"v1/workspaces/{workspace_id}/notebooks/{item_id}/getDefinition", - ) - - result = lro(client, response).json() - df_items = pd.json_normalize(result["definition"]["parts"]) df_items_filt = df_items[df_items["path"] == "notebook-content.py"] payload = df_items_filt["payload"].iloc[0] @@ -127,6 +153,7 @@ def import_notebook_from_web( def create_notebook( name: str, notebook_content: str, + type: str = "py", description: Optional[str] = None, workspace: Optional[str] = None, ): @@ -139,6 +166,8 @@ def create_notebook( The name of the notebook to be created. notebook_content : str The Jupyter notebook content (not in Base64 format). + type : str, default="py" + The notebook type. description : str, default=None The description of the notebook. Defaults to None which does not place a description. @@ -158,7 +187,7 @@ def create_notebook( "format": "ipynb", "parts": [ { - "path": "notebook-content.py", + "path": f"notebook-content.{type}", "payload": notebook_payload, "payloadType": "InlineBase64", } @@ -202,13 +231,14 @@ def update_notebook_definition( item_name=name, type="Notebook", workspace=workspace ) + type = _get_notebook_type(notebook_name=name, workspace=workspace_id) + request_body = { "displayName": name, "definition": { - "format": "ipynb", "parts": [ { - "path": "notebook-content.py", + "path": f"notebook-content.{type}", "payload": notebook_payload, "payloadType": "InlineBase64", } diff --git a/src/sempy_labs/tom/_model.py b/src/sempy_labs/tom/_model.py index da36060b..d5ff4d00 100644 --- a/src/sempy_labs/tom/_model.py +++ b/src/sempy_labs/tom/_model.py @@ -4541,9 +4541,13 @@ def add_role_member(self, role_name: str, member: str | List[str]): rm.IdentityProvider = "AzureAD" rm.MemberName = m role.Members.Add(rm) - print(f"{icons.green_dot} '{m}' has been added as a member of the '{role_name}' role.") + print( + f"{icons.green_dot} '{m}' has been added as a member of the '{role_name}' role." + ) else: - print(f"{icons.yellow_dot} '{m}' is already a member in the '{role_name}' role.") + print( + f"{icons.yellow_dot} '{m}' is already a member in the '{role_name}' role." + ) def close(self): From 6134d73aefda930999f914e8cd262cbbfc8d0e56 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 12 Dec 2024 13:51:09 +0200 Subject: [PATCH 02/22] updated --- src/sempy_labs/_notebooks.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/sempy_labs/_notebooks.py b/src/sempy_labs/_notebooks.py index 41fc5950..f06ccded 100644 --- a/src/sempy_labs/_notebooks.py +++ b/src/sempy_labs/_notebooks.py @@ -12,6 +12,8 @@ from sempy.fabric.exceptions import FabricHTTPException import os +_notebook_prefix = "notebook-content." + def _get_notebook_definition_base( notebook_name: str, workspace: Optional[str] = None @@ -37,7 +39,7 @@ def _get_notebook_type(notebook_name: str, workspace: Optional[str] = None) -> s notebook_name=notebook_name, workspace=workspace ) - file_path = df_items[df_items["path"].str.startswith("notebook-content")][ + file_path = df_items[df_items["path"].str.startswith(_notebook_prefix)][ "path" ].iloc[0] @@ -75,7 +77,7 @@ def get_notebook_definition( df_items = _get_notebook_definition_base( notebook_name=notebook_name, workspace=workspace ) - df_items_filt = df_items[df_items["path"] == "notebook-content.py"] + df_items_filt = df_items[df_items["path"].str.startswith(_notebook_prefix)] payload = df_items_filt["payload"].iloc[0] if decode: @@ -187,7 +189,7 @@ def create_notebook( "format": "ipynb", "parts": [ { - "path": f"notebook-content.{type}", + "path": f"{_notebook_prefix}{type}", "payload": notebook_payload, "payloadType": "InlineBase64", } @@ -238,7 +240,7 @@ def update_notebook_definition( "definition": { "parts": [ { - "path": f"notebook-content.{type}", + "path": f"{_notebook_prefix}{type}", "payload": notebook_payload, "payloadType": "InlineBase64", } From 2132403a8d12b4cfbc243c38b70f955b747456ba Mon Sep 17 00:00:00 2001 From: Nick Hurt Date: Fri, 13 Dec 2024 09:39:23 +0000 Subject: [PATCH 03/22] Update _git.py (#320) * Update _git.py Fix LRO bug - no result is returned from a commit to git operation therefore added True boolean param to use status code instead. Added check to see whether any changes exist before calling commit operation and added message if no modified items found. Fixed small typo. * Update _git.py changed git status response empty check when making commit. changed green icon dot to info if nothing to commit --- src/sempy_labs/_git.py | 60 +++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/src/sempy_labs/_git.py b/src/sempy_labs/_git.py index 959df930..1de2fe2c 100644 --- a/src/sempy_labs/_git.py +++ b/src/sempy_labs/_git.py @@ -277,46 +277,52 @@ 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." ) + def update_from_git( remote_commit_hash: str, conflict_resolution_policy: str, From 6fe5fb7f1c09fef9db4755d65f02aebae42797c8 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 13 Dec 2024 14:17:43 +0200 Subject: [PATCH 04/22] added list_serverproperties --- src/sempy_labs/__init__.py | 2 ++ src/sempy_labs/_git.py | 1 - src/sempy_labs/_list_functions.py | 26 ++++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/sempy_labs/__init__.py b/src/sempy_labs/__init__.py index e0bf0dea..8a194149 100644 --- a/src/sempy_labs/__init__.py +++ b/src/sempy_labs/__init__.py @@ -205,6 +205,7 @@ list_lakehouses, list_sql_endpoints, update_item, + list_server_properties, ) from sempy_labs._helper_functions import ( convert_to_friendly_case, @@ -458,4 +459,5 @@ "update_vnet_gateway", "update_on_premises_gateway", "get_semantic_model_definition", + "list_server_properties", ] diff --git a/src/sempy_labs/_git.py b/src/sempy_labs/_git.py index 1de2fe2c..4e58078b 100644 --- a/src/sempy_labs/_git.py +++ b/src/sempy_labs/_git.py @@ -322,7 +322,6 @@ def commit_to_git( ) - def update_from_git( remote_commit_hash: str, conflict_resolution_policy: str, diff --git a/src/sempy_labs/_list_functions.py b/src/sempy_labs/_list_functions.py index f4157ccd..33c37ca6 100644 --- a/src/sempy_labs/_list_functions.py +++ b/src/sempy_labs/_list_functions.py @@ -1575,3 +1575,29 @@ def list_semantic_model_object_report_usage( final_df.reset_index(drop=True, inplace=True) return final_df + + +def list_server_properties(workspace: Optional[str | UUID] = None) -> pd.DataFrame: + + tom_server = fabric.create_tom_server(readonly=True, workspace=workspace) + + rows = [ + { + "Name": sp.Name, + "Value": sp.Value, + "Default Value": sp.DefaultValue, + "Is Read Only": sp.IsReadOnly, + "Requires Restart": sp.RequiresRestart, + "Units": sp.Units, + "Category": sp.Category, + } + for sp in tom_server.ServerProperties + ] + + tom_server.Dispose() + df = pd.DataFrame(rows) + + bool_cols = ["Is Read Only", "Requires Restart"] + df[bool_cols] = df[bool_cols].astype(bool) + + return df From 1df29ef64ebd5b2b04a8264e36b9f95c32074e93 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 13 Dec 2024 14:19:03 +0200 Subject: [PATCH 05/22] added help section --- src/sempy_labs/_list_functions.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/sempy_labs/_list_functions.py b/src/sempy_labs/_list_functions.py index 33c37ca6..3f67f532 100644 --- a/src/sempy_labs/_list_functions.py +++ b/src/sempy_labs/_list_functions.py @@ -1578,6 +1578,21 @@ def list_semantic_model_object_report_usage( def list_server_properties(workspace: Optional[str | UUID] = None) -> pd.DataFrame: + """ + Lists the `properties `_ of the Analysis Services instance. + + Parameters + ---------- + workspace : str, 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. + + Returns + ------- + pandas.DataFrame + A pandas dataframe showing a list of the server properties. + """ tom_server = fabric.create_tom_server(readonly=True, workspace=workspace) From 08f958e7e9ce8920ed0d5a7ac9479c3a7ac355ea Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 15 Dec 2024 10:03:13 +0200 Subject: [PATCH 06/22] remove update notebook support --- src/sempy_labs/_git.py | 1 - src/sempy_labs/_notebooks.py | 12 ++++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/sempy_labs/_git.py b/src/sempy_labs/_git.py index 1de2fe2c..4e58078b 100644 --- a/src/sempy_labs/_git.py +++ b/src/sempy_labs/_git.py @@ -322,7 +322,6 @@ def commit_to_git( ) - def update_from_git( remote_commit_hash: str, conflict_resolution_policy: str, diff --git a/src/sempy_labs/_notebooks.py b/src/sempy_labs/_notebooks.py index f06ccded..afcec7d6 100644 --- a/src/sempy_labs/_notebooks.py +++ b/src/sempy_labs/_notebooks.py @@ -143,9 +143,10 @@ def import_notebook_from_web( description=description, ) elif len(dfI_filt) > 0 and overwrite: - update_notebook_definition( - name=notebook_name, notebook_content=response.content, workspace=workspace - ) + print(f"{icons.info} Overwrite of notebooks is currently not supported.") + # update_notebook_definition( + # name=notebook_name, notebook_content=response.content, workspace=workspace + # ) else: raise ValueError( f"{icons.red_dot} The '{notebook_name}' already exists within the '{workspace}' workspace and 'overwrite' is set to False." @@ -189,7 +190,7 @@ def create_notebook( "format": "ipynb", "parts": [ { - "path": f"{_notebook_prefix}{type}", + "path": f"{_notebook_prefix}.{type}", "payload": notebook_payload, "payloadType": "InlineBase64", } @@ -236,11 +237,10 @@ def update_notebook_definition( type = _get_notebook_type(notebook_name=name, workspace=workspace_id) request_body = { - "displayName": name, "definition": { "parts": [ { - "path": f"{_notebook_prefix}{type}", + "path": f"{_notebook_prefix}.{type}", "payload": notebook_payload, "payloadType": "InlineBase64", } From ed8e6500daa5f25acfa6dcf98ba9ac76959f85fa Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 15 Dec 2024 10:08:21 +0200 Subject: [PATCH 07/22] change --- src/sempy_labs/_notebooks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sempy_labs/_notebooks.py b/src/sempy_labs/_notebooks.py index afcec7d6..4c24b99d 100644 --- a/src/sempy_labs/_notebooks.py +++ b/src/sempy_labs/_notebooks.py @@ -145,7 +145,7 @@ def import_notebook_from_web( elif len(dfI_filt) > 0 and overwrite: print(f"{icons.info} Overwrite of notebooks is currently not supported.") # update_notebook_definition( - # name=notebook_name, notebook_content=response.content, workspace=workspace + # name=notebook_name, notebook_content=response.content, workspace=workspace # ) else: raise ValueError( From efb02d122660846fd1bb5158cdf7a2e597268cf1 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 15 Dec 2024 10:13:54 +0200 Subject: [PATCH 08/22] change --- src/sempy_labs/_notebooks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sempy_labs/_notebooks.py b/src/sempy_labs/_notebooks.py index afcec7d6..4c24b99d 100644 --- a/src/sempy_labs/_notebooks.py +++ b/src/sempy_labs/_notebooks.py @@ -145,7 +145,7 @@ def import_notebook_from_web( elif len(dfI_filt) > 0 and overwrite: print(f"{icons.info} Overwrite of notebooks is currently not supported.") # update_notebook_definition( - # name=notebook_name, notebook_content=response.content, workspace=workspace + # name=notebook_name, notebook_content=response.content, workspace=workspace # ) else: raise ValueError( From 0960a44f0eebd57fdaaafe0481eb1ae6d5d728df Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 16 Dec 2024 07:44:55 +0200 Subject: [PATCH 09/22] added list_semantic_model_errors --- src/sempy_labs/__init__.py | 2 + src/sempy_labs/_list_functions.py | 69 +++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/src/sempy_labs/__init__.py b/src/sempy_labs/__init__.py index e0bf0dea..1acf7ff4 100644 --- a/src/sempy_labs/__init__.py +++ b/src/sempy_labs/__init__.py @@ -205,6 +205,7 @@ list_lakehouses, list_sql_endpoints, update_item, + list_semantic_model_errors, ) from sempy_labs._helper_functions import ( convert_to_friendly_case, @@ -458,4 +459,5 @@ "update_vnet_gateway", "update_on_premises_gateway", "get_semantic_model_definition", + "list_semantic_model_errors", ] diff --git a/src/sempy_labs/_list_functions.py b/src/sempy_labs/_list_functions.py index f4157ccd..54454274 100644 --- a/src/sempy_labs/_list_functions.py +++ b/src/sempy_labs/_list_functions.py @@ -1575,3 +1575,72 @@ def list_semantic_model_object_report_usage( final_df.reset_index(drop=True, inplace=True) return final_df + +def list_semantic_model_errors(dataset: str | UUID, workspace: Optional[str | UUID]) -> pd.DataFrame: + """ + Shows a list of a semantic model's errors and their error messages (if they exist). + + Parameters + ---------- + dataset : str | UUID + Name or ID of the semantic model. + workspace : str | UUID, default=None + The Fabric workspace name or ID. + Defaults to None which resolves to the workspace of the attached lakehouse + or if no lakehouse attached, resolves to the workspace of the notebook. + + Returns + ------- + pandas.DataFrame + A pandas dataframe showing a list of the errors and error messages for a given semantic model. + """ + + from sempy_labs.tom import connect_semantic_model + + (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace) + (dataset_name, dataset_id) = resolve_dataset_name_and_id( + dataset, workspace=workspace_id + ) + + error_rows = [] + + # Helper function to add a new error row + def add_error_row(object_type, table_name, object_name, error_message): + error_rows.append({ + "Object Type": object_type, + "Table Name": table_name, + "Object Name": object_name, + "Error Message": error_message, + }) + + with connect_semantic_model(dataset=dataset_id, workspace=workspace_id, readonly=True) as tom: + # Define mappings of TOM objects to object types and attributes + error_checks = [ + ("Column", tom.all_columns, lambda o: o.ErrorMessage), + ("Partition", tom.all_partitions, lambda o: o.ErrorMessage), + ("Partition - Data Coverage Expression", + tom.all_partitions, lambda o: o.DataCoverageDefinition.ErrorMessage if o.DataCoverageDefinition else ""), + ("Row Level Security", tom.all_rls, lambda o: o.ErrorMessage), + ("Calculation Item", tom.all_calculation_items, lambda o: o.ErrorMessage), + ("Measure", tom.all_measures, lambda o: o.ErrorMessage), + ("Measure - Detail Rows Expression", + tom.all_measures, lambda o: o.DetailRowsDefinition.ErrorMessage if o.DetailRowsDefinition else ""), + ("Measure - Format String Expression", + tom.all_measures, lambda o: o.FormatStringDefinition.ErrorMessage if o.FormatStringDefinition else ""), + ("Calculation Group - Multiple or Empty Selection Expression", + tom.all_calculation_groups, lambda o: o.CalculationGroup.MultipleOrEmptySelectionExpression.ErrorMessage + if o.CalculationGroup.MultipleOrEmptySelectionExpression else ""), + ("Calculation Group - No Selection Expression", + tom.all_calculation_groups, lambda o: o.CalculationGroup.NoSelectionExpression.ErrorMessage + if o.CalculationGroup.NoSelectionExpression else "") + ] + + # Iterate over all error checks + for object_type, getter, error_extractor in error_checks: + for obj in getter(): + error_message = error_extractor(obj) + if error_message: # Only add rows if there's an error message + add_error_row(object_type, obj.Parent.Name, obj.Name, error_message) + + # Create the DataFrame from collected rows + return pd.DataFrame(error_rows) \ No newline at end of file From b69da6372e5b41c3a9ee5d2fb3e342b846c28be8 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 16 Dec 2024 08:17:40 +0200 Subject: [PATCH 10/22] added get_tenant_id --- src/sempy_labs/__init__.py | 2 ++ src/sempy_labs/_helper_functions.py | 30 +++++++++++++++++++++++------ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/sempy_labs/__init__.py b/src/sempy_labs/__init__.py index e0bf0dea..5784e440 100644 --- a/src/sempy_labs/__init__.py +++ b/src/sempy_labs/__init__.py @@ -230,6 +230,7 @@ get_capacity_id, get_capacity_name, resolve_capacity_name, + get_tenant_id, ) from sempy_labs._model_bpa_bulk import ( run_model_bpa_bulk, @@ -458,4 +459,5 @@ "update_vnet_gateway", "update_on_premises_gateway", "get_semantic_model_definition", + "get_tenant_id", ] diff --git a/src/sempy_labs/_helper_functions.py b/src/sempy_labs/_helper_functions.py index 13edf392..336c8d01 100644 --- a/src/sempy_labs/_helper_functions.py +++ b/src/sempy_labs/_helper_functions.py @@ -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: @@ -1371,3 +1377,15 @@ def _is_valid_uuid( return True except ValueError: return False + + +def _get_x_id(name: str): + + from synapse.ml.internal_utils.session_utils import get_fabric_context + + return get_fabric_context().get(name) + + +def get_tenant_id(): + + _get_x_id(name='trident.tenant.id') From 59e9d7b954524fde4e2a327b3606afbbb5723cd7 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 16 Dec 2024 10:01:29 +0200 Subject: [PATCH 11/22] added bind_semantic_model_to_gateway --- src/sempy_labs/__init__.py | 2 ++ src/sempy_labs/_gateways.py | 39 +++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/sempy_labs/__init__.py b/src/sempy_labs/__init__.py index e0bf0dea..b6b14cbb 100644 --- a/src/sempy_labs/__init__.py +++ b/src/sempy_labs/__init__.py @@ -8,6 +8,7 @@ create_vnet_gateway, update_vnet_gateway, update_on_premises_gateway, + bind_semantic_model_to_gateway, ) from sempy_labs._authentication import ( @@ -458,4 +459,5 @@ "update_vnet_gateway", "update_on_premises_gateway", "get_semantic_model_definition", + "bind_semantic_model_to_gateway", ] diff --git a/src/sempy_labs/_gateways.py b/src/sempy_labs/_gateways.py index c8b95830..d43cea17 100644 --- a/src/sempy_labs/_gateways.py +++ b/src/sempy_labs/_gateways.py @@ -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 @@ -437,3 +439,40 @@ 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 `_. + + 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.") \ No newline at end of file From fdd5c6a246473a2a1640265528b0c41c70c2e57f Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 16 Dec 2024 10:01:45 +0200 Subject: [PATCH 12/22] black --- src/sempy_labs/_gateways.py | 15 +++++++++++---- src/sempy_labs/_notebooks.py | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/sempy_labs/_gateways.py b/src/sempy_labs/_gateways.py index d43cea17..03ebaa6c 100644 --- a/src/sempy_labs/_gateways.py +++ b/src/sempy_labs/_gateways.py @@ -441,7 +441,9 @@ def update_vnet_gateway( 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): +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. @@ -470,9 +472,14 @@ def bind_semantic_model_to_gateway(dataset: str | UUID, gateway: str | UUID, wor } client = fabric.FabricRestClient() - response = client.post(f'/v1.0/myorg/groups/{workspace_id}/datasets/{dataset_id}/Default.BindToGateway', json=payload) + 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.") \ No newline at end of file + + print( + f"{icons.green_dot} The '{dataset_name}' semantic model within the '{workspace_name}' workspace has been binded to the '{gateway_id}' gateway." + ) diff --git a/src/sempy_labs/_notebooks.py b/src/sempy_labs/_notebooks.py index 4c24b99d..afcec7d6 100644 --- a/src/sempy_labs/_notebooks.py +++ b/src/sempy_labs/_notebooks.py @@ -145,7 +145,7 @@ def import_notebook_from_web( elif len(dfI_filt) > 0 and overwrite: print(f"{icons.info} Overwrite of notebooks is currently not supported.") # update_notebook_definition( - # name=notebook_name, notebook_content=response.content, workspace=workspace + # name=notebook_name, notebook_content=response.content, workspace=workspace # ) else: raise ValueError( From 3ef9b9cd3a78d8a235a42aca559afc066f83fb9c Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 16 Dec 2024 15:55:07 +0200 Subject: [PATCH 13/22] updated name per comment --- src/sempy_labs/_helper_functions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sempy_labs/_helper_functions.py b/src/sempy_labs/_helper_functions.py index 336c8d01..cdf6d43a 100644 --- a/src/sempy_labs/_helper_functions.py +++ b/src/sempy_labs/_helper_functions.py @@ -1379,7 +1379,7 @@ def _is_valid_uuid( return False -def _get_x_id(name: str): +def _get_fabric_context_setting(name: str): from synapse.ml.internal_utils.session_utils import get_fabric_context @@ -1388,4 +1388,4 @@ def _get_x_id(name: str): def get_tenant_id(): - _get_x_id(name='trident.tenant.id') + _get_fabric_context_setting(name='trident.tenant.id') From ea7d94d637852abf847942f85fcdf4d923da614b Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 16 Dec 2024 16:01:14 +0200 Subject: [PATCH 14/22] updates per comment --- src/sempy_labs/_list_functions.py | 87 ++++++++++++++++++++++--------- src/sempy_labs/_notebooks.py | 2 +- 2 files changed, 62 insertions(+), 27 deletions(-) diff --git a/src/sempy_labs/_list_functions.py b/src/sempy_labs/_list_functions.py index 54454274..9bb2cb94 100644 --- a/src/sempy_labs/_list_functions.py +++ b/src/sempy_labs/_list_functions.py @@ -1576,7 +1576,10 @@ def list_semantic_model_object_report_usage( return final_df -def list_semantic_model_errors(dataset: str | UUID, workspace: Optional[str | UUID]) -> pd.DataFrame: + +def list_semantic_model_errors( + dataset: str | UUID, workspace: Optional[str | UUID] +) -> pd.DataFrame: """ Shows a list of a semantic model's errors and their error messages (if they exist). @@ -1604,35 +1607,61 @@ def list_semantic_model_errors(dataset: str | UUID, workspace: Optional[str | UU error_rows = [] - # Helper function to add a new error row - def add_error_row(object_type, table_name, object_name, error_message): - error_rows.append({ - "Object Type": object_type, - "Table Name": table_name, - "Object Name": object_name, - "Error Message": error_message, - }) - - with connect_semantic_model(dataset=dataset_id, workspace=workspace_id, readonly=True) as tom: + with connect_semantic_model( + dataset=dataset_id, workspace=workspace_id, readonly=True + ) as tom: # Define mappings of TOM objects to object types and attributes error_checks = [ ("Column", tom.all_columns, lambda o: o.ErrorMessage), ("Partition", tom.all_partitions, lambda o: o.ErrorMessage), - ("Partition - Data Coverage Expression", - tom.all_partitions, lambda o: o.DataCoverageDefinition.ErrorMessage if o.DataCoverageDefinition else ""), + ( + "Partition - Data Coverage Expression", + tom.all_partitions, + lambda o: ( + o.DataCoverageDefinition.ErrorMessage + if o.DataCoverageDefinition + else "" + ), + ), ("Row Level Security", tom.all_rls, lambda o: o.ErrorMessage), ("Calculation Item", tom.all_calculation_items, lambda o: o.ErrorMessage), ("Measure", tom.all_measures, lambda o: o.ErrorMessage), - ("Measure - Detail Rows Expression", - tom.all_measures, lambda o: o.DetailRowsDefinition.ErrorMessage if o.DetailRowsDefinition else ""), - ("Measure - Format String Expression", - tom.all_measures, lambda o: o.FormatStringDefinition.ErrorMessage if o.FormatStringDefinition else ""), - ("Calculation Group - Multiple or Empty Selection Expression", - tom.all_calculation_groups, lambda o: o.CalculationGroup.MultipleOrEmptySelectionExpression.ErrorMessage - if o.CalculationGroup.MultipleOrEmptySelectionExpression else ""), - ("Calculation Group - No Selection Expression", - tom.all_calculation_groups, lambda o: o.CalculationGroup.NoSelectionExpression.ErrorMessage - if o.CalculationGroup.NoSelectionExpression else "") + ( + "Measure - Detail Rows Expression", + tom.all_measures, + lambda o: ( + o.DetailRowsDefinition.ErrorMessage + if o.DetailRowsDefinition + else "" + ), + ), + ( + "Measure - Format String Expression", + tom.all_measures, + lambda o: ( + o.FormatStringDefinition.ErrorMessage + if o.FormatStringDefinition + else "" + ), + ), + ( + "Calculation Group - Multiple or Empty Selection Expression", + tom.all_calculation_groups, + lambda o: ( + o.CalculationGroup.MultipleOrEmptySelectionExpression.ErrorMessage + if o.CalculationGroup.MultipleOrEmptySelectionExpression + else "" + ), + ), + ( + "Calculation Group - No Selection Expression", + tom.all_calculation_groups, + lambda o: ( + o.CalculationGroup.NoSelectionExpression.ErrorMessage + if o.CalculationGroup.NoSelectionExpression + else "" + ), + ), ] # Iterate over all error checks @@ -1640,7 +1669,13 @@ def add_error_row(object_type, table_name, object_name, error_message): for obj in getter(): error_message = error_extractor(obj) if error_message: # Only add rows if there's an error message - add_error_row(object_type, obj.Parent.Name, obj.Name, error_message) + error_rows.append( + { + "Object Type": object_type, + "Table Name": obj.Parent.Name, + "Object Name": obj.Name, + "Error Message": error_message, + } + ) - # Create the DataFrame from collected rows - return pd.DataFrame(error_rows) \ No newline at end of file + return pd.DataFrame(error_rows) diff --git a/src/sempy_labs/_notebooks.py b/src/sempy_labs/_notebooks.py index 4c24b99d..afcec7d6 100644 --- a/src/sempy_labs/_notebooks.py +++ b/src/sempy_labs/_notebooks.py @@ -145,7 +145,7 @@ def import_notebook_from_web( elif len(dfI_filt) > 0 and overwrite: print(f"{icons.info} Overwrite of notebooks is currently not supported.") # update_notebook_definition( - # name=notebook_name, notebook_content=response.content, workspace=workspace + # name=notebook_name, notebook_content=response.content, workspace=workspace # ) else: raise ValueError( From 42a75d6fd659b71213dd1b725af6adfd988c5b72 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 16 Dec 2024 16:08:37 +0200 Subject: [PATCH 15/22] bind --- src/sempy_labs/_gateways.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sempy_labs/_gateways.py b/src/sempy_labs/_gateways.py index 03ebaa6c..08b904fc 100644 --- a/src/sempy_labs/_gateways.py +++ b/src/sempy_labs/_gateways.py @@ -483,3 +483,4 @@ def bind_semantic_model_to_gateway( print( f"{icons.green_dot} The '{dataset_name}' semantic model within the '{workspace_name}' workspace has been binded to the '{gateway_id}' gateway." ) + From 2fbb2e4b18b4c6ea243ba7e67f9d2163de7f43e1 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 16 Dec 2024 16:11:13 +0200 Subject: [PATCH 16/22] remove space --- src/sempy_labs/_gateways.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sempy_labs/_gateways.py b/src/sempy_labs/_gateways.py index 08b904fc..03ebaa6c 100644 --- a/src/sempy_labs/_gateways.py +++ b/src/sempy_labs/_gateways.py @@ -483,4 +483,3 @@ def bind_semantic_model_to_gateway( print( f"{icons.green_dot} The '{dataset_name}' semantic model within the '{workspace_name}' workspace has been binded to the '{gateway_id}' gateway." ) - From edd7e340241d8fb35dc923c718c6bbeaa2c0bed7 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 16 Dec 2024 17:39:47 +0200 Subject: [PATCH 17/22] update to 0.8.10 --- README.md | 3 ++- docs/source/conf.py | 2 +- pyproject.toml | 2 +- src/sempy_labs/_authentication.py | 33 +++++++++++++++++++++++++++-- src/sempy_labs/_helper_functions.py | 4 ++-- 5 files changed, 37 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8701e906..577f5876 100644 --- a/README.md +++ b/README.md @@ -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) @@ -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.9](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) diff --git a/docs/source/conf.py b/docs/source/conf.py index 86640c0b..cbee7399 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -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 diff --git a/pyproject.toml b/pyproject.toml index 9b921e0d..63e97bf7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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" diff --git a/src/sempy_labs/_authentication.py b/src/sempy_labs/_authentication.py index 340eecff..c1b37316 100644 --- a/src/sempy_labs/_authentication.py +++ b/src/sempy_labs/_authentication.py @@ -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": @@ -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 diff --git a/src/sempy_labs/_helper_functions.py b/src/sempy_labs/_helper_functions.py index cdf6d43a..2ff51e50 100644 --- a/src/sempy_labs/_helper_functions.py +++ b/src/sempy_labs/_helper_functions.py @@ -781,7 +781,7 @@ def get_capacity_id(workspace: Optional[str] = None) -> UUID: """ if workspace is None: - capacity_id = _get_x_id(name='trident.capacity.id') + capacity_id = _get_x_id(name="trident.capacity.id") else: workspace = fabric.resolve_workspace_name(workspace) @@ -1388,4 +1388,4 @@ def _get_fabric_context_setting(name: str): def get_tenant_id(): - _get_fabric_context_setting(name='trident.tenant.id') + _get_fabric_context_setting(name="trident.tenant.id") From 67fcf964f9e068238503e15888127392709eb0ce Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 16 Dec 2024 17:41:58 +0200 Subject: [PATCH 18/22] update to 0.8.10 --- README.md | 3 ++- docs/source/conf.py | 2 +- pyproject.toml | 2 +- src/sempy_labs/_authentication.py | 33 +++++++++++++++++++++++++++-- src/sempy_labs/_helper_functions.py | 4 ++-- 5 files changed, 37 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8701e906..577f5876 100644 --- a/README.md +++ b/README.md @@ -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) @@ -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.9](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) diff --git a/docs/source/conf.py b/docs/source/conf.py index 86640c0b..cbee7399 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -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 diff --git a/pyproject.toml b/pyproject.toml index 9b921e0d..63e97bf7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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" diff --git a/src/sempy_labs/_authentication.py b/src/sempy_labs/_authentication.py index 340eecff..c1b37316 100644 --- a/src/sempy_labs/_authentication.py +++ b/src/sempy_labs/_authentication.py @@ -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": @@ -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 diff --git a/src/sempy_labs/_helper_functions.py b/src/sempy_labs/_helper_functions.py index cdf6d43a..2ff51e50 100644 --- a/src/sempy_labs/_helper_functions.py +++ b/src/sempy_labs/_helper_functions.py @@ -781,7 +781,7 @@ def get_capacity_id(workspace: Optional[str] = None) -> UUID: """ if workspace is None: - capacity_id = _get_x_id(name='trident.capacity.id') + capacity_id = _get_x_id(name="trident.capacity.id") else: workspace = fabric.resolve_workspace_name(workspace) @@ -1388,4 +1388,4 @@ def _get_fabric_context_setting(name: str): def get_tenant_id(): - _get_fabric_context_setting(name='trident.tenant.id') + _get_fabric_context_setting(name="trident.tenant.id") From 4d7070791c94b98d00e1f9db33bbc26c9480d919 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 16 Dec 2024 17:42:05 +0200 Subject: [PATCH 19/22] update to 10 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 577f5876..35084f1f 100644 --- a/README.md +++ b/README.md @@ -116,7 +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.9](https://github.com/microsoft/semantic-link-labs/releases/tag/0.8.10) (December 16, 2024) +* [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) From 716fd318391a1275edd66d30de52d855e6f05337 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 16 Dec 2024 17:42:39 +0200 Subject: [PATCH 20/22] update to 10 --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 37e84c19..35084f1f 100644 --- a/README.md +++ b/README.md @@ -116,11 +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 -<<<<<<< HEAD * [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.10) (December 16, 2024) ->>>>>>> edd7e340241d8fb35dc923c718c6bbeaa2c0bed7 * [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) From 641b3db83864c9be2d6e656a7e493cec1602363c Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 16 Dec 2024 18:37:51 +0200 Subject: [PATCH 21/22] update scan help section --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 37e84c19..35084f1f 100644 --- a/README.md +++ b/README.md @@ -116,11 +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 -<<<<<<< HEAD * [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.10) (December 16, 2024) ->>>>>>> edd7e340241d8fb35dc923c718c6bbeaa2c0bed7 * [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) From 69b7ab2d6a441509f8323f09b6004c0bc33806e4 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 16 Dec 2024 18:37:57 +0200 Subject: [PATCH 22/22] update help --- src/sempy_labs/admin/_scanner.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sempy_labs/admin/_scanner.py b/src/sempy_labs/admin/_scanner.py index 84f56f09..a20720a0 100644 --- a/src/sempy_labs/admin/_scanner.py +++ b/src/sempy_labs/admin/_scanner.py @@ -16,12 +16,12 @@ def scan_workspaces( workspace: Optional[str | List[str] | UUID | List[UUID]] = None, ) -> dict: """ - Get the inventory and details of the tenant. + Gets the scan result for the specified scan. This is a wrapper function for the following APIs: - `Admin - WorkspaceInfo PostWorkspaceInfo `_. - `Admin - WorkspaceInfo GetScanStatus `_. - `Admin - WorkspaceInfo GetScanResult `_. + `Admin - WorkspaceInfo PostWorkspaceInfo `_. + `Admin - WorkspaceInfo GetScanStatus `_. + `Admin - WorkspaceInfo GetScanResult `_. Parameters ----------