semantic-link-labs 0.8.0__py3-none-any.whl → 0.8.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of semantic-link-labs might be problematic. Click here for more details.

Files changed (47) hide show
  1. {semantic_link_labs-0.8.0.dist-info → semantic_link_labs-0.8.1.dist-info}/METADATA +39 -7
  2. {semantic_link_labs-0.8.0.dist-info → semantic_link_labs-0.8.1.dist-info}/RECORD +47 -37
  3. sempy_labs/__init__.py +70 -51
  4. sempy_labs/_ai.py +0 -2
  5. sempy_labs/_capacity_migration.py +1 -2
  6. sempy_labs/_data_pipelines.py +118 -0
  7. sempy_labs/_documentation.py +144 -0
  8. sempy_labs/_eventhouses.py +118 -0
  9. sempy_labs/_eventstreams.py +118 -0
  10. sempy_labs/_generate_semantic_model.py +3 -3
  11. sempy_labs/_git.py +3 -3
  12. sempy_labs/_helper_functions.py +116 -26
  13. sempy_labs/_icons.py +21 -0
  14. sempy_labs/_kql_databases.py +134 -0
  15. sempy_labs/_kql_querysets.py +124 -0
  16. sempy_labs/_list_functions.py +12 -425
  17. sempy_labs/_mirrored_warehouses.py +50 -0
  18. sempy_labs/_ml_experiments.py +122 -0
  19. sempy_labs/_ml_models.py +120 -0
  20. sempy_labs/_model_auto_build.py +0 -4
  21. sempy_labs/_model_bpa.py +9 -11
  22. sempy_labs/_model_bpa_bulk.py +8 -7
  23. sempy_labs/_model_dependencies.py +26 -18
  24. sempy_labs/_notebooks.py +5 -16
  25. sempy_labs/_query_scale_out.py +2 -2
  26. sempy_labs/_refresh_semantic_model.py +7 -19
  27. sempy_labs/_spark.py +10 -10
  28. sempy_labs/_vertipaq.py +16 -18
  29. sempy_labs/_warehouses.py +132 -0
  30. sempy_labs/_workspaces.py +0 -3
  31. sempy_labs/admin/_basic_functions.py +92 -10
  32. sempy_labs/admin/_domains.py +1 -1
  33. sempy_labs/directlake/_directlake_schema_sync.py +1 -1
  34. sempy_labs/directlake/_dl_helper.py +32 -16
  35. sempy_labs/directlake/_guardrails.py +7 -7
  36. sempy_labs/directlake/_update_directlake_partition_entity.py +1 -1
  37. sempy_labs/directlake/_warm_cache.py +1 -1
  38. sempy_labs/lakehouse/_get_lakehouse_tables.py +3 -3
  39. sempy_labs/lakehouse/_lakehouse.py +3 -2
  40. sempy_labs/migration/_migrate_calctables_to_lakehouse.py +5 -0
  41. sempy_labs/report/_generate_report.py +1 -1
  42. sempy_labs/report/_report_bpa.py +13 -3
  43. sempy_labs/report/_reportwrapper.py +14 -16
  44. sempy_labs/tom/_model.py +261 -24
  45. {semantic_link_labs-0.8.0.dist-info → semantic_link_labs-0.8.1.dist-info}/LICENSE +0 -0
  46. {semantic_link_labs-0.8.0.dist-info → semantic_link_labs-0.8.1.dist-info}/WHEEL +0 -0
  47. {semantic_link_labs-0.8.0.dist-info → semantic_link_labs-0.8.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,132 @@
1
+ import sempy.fabric as fabric
2
+ from sempy_labs._helper_functions import (
3
+ resolve_workspace_name_and_id,
4
+ pagination,
5
+ lro,
6
+ )
7
+ import pandas as pd
8
+ from typing import Optional
9
+ import sempy_labs._icons as icons
10
+ from sempy.fabric.exceptions import FabricHTTPException
11
+
12
+
13
+ def create_warehouse(
14
+ warehouse: str, description: Optional[str] = None, workspace: Optional[str] = None
15
+ ):
16
+ """
17
+ Creates a Fabric warehouse.
18
+
19
+ Parameters
20
+ ----------
21
+ warehouse: str
22
+ Name of the warehouse.
23
+ description : str, default=None
24
+ A description of the warehouse.
25
+ workspace : str, default=None
26
+ The Fabric workspace name.
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
+
31
+ (workspace, workspace_id) = resolve_workspace_name_and_id(workspace)
32
+
33
+ request_body = {"displayName": warehouse}
34
+
35
+ if description:
36
+ request_body["description"] = description
37
+
38
+ client = fabric.FabricRestClient()
39
+ response = client.post(
40
+ f"/v1/workspaces/{workspace_id}/warehouses/", json=request_body
41
+ )
42
+
43
+ lro(client, response, status_codes=[201, 202])
44
+
45
+ print(
46
+ f"{icons.green_dot} The '{warehouse}' warehouse has been created within the '{workspace}' workspace."
47
+ )
48
+
49
+
50
+ def list_warehouses(workspace: Optional[str] = None) -> pd.DataFrame:
51
+ """
52
+ Shows the warehouses within a workspace.
53
+
54
+ Parameters
55
+ ----------
56
+ workspace : str, default=None
57
+ The Fabric workspace name.
58
+ Defaults to None which resolves to the workspace of the attached lakehouse
59
+ or if no lakehouse attached, resolves to the workspace of the notebook.
60
+
61
+ Returns
62
+ -------
63
+ pandas.DataFrame
64
+ A pandas dataframe showing the warehouses within a workspace.
65
+ """
66
+
67
+ df = pd.DataFrame(
68
+ columns=[
69
+ "Warehouse Name",
70
+ "Warehouse Id",
71
+ "Description",
72
+ "Connection Info",
73
+ "Created Date",
74
+ "Last Updated Time",
75
+ ]
76
+ )
77
+
78
+ (workspace, workspace_id) = resolve_workspace_name_and_id(workspace)
79
+
80
+ client = fabric.FabricRestClient()
81
+ response = client.get(f"/v1/workspaces/{workspace_id}/warehouses")
82
+ if response.status_code != 200:
83
+ raise FabricHTTPException(response)
84
+
85
+ responses = pagination(client, response)
86
+
87
+ for r in responses:
88
+ for v in r.get("value", []):
89
+ prop = v.get("properties", {})
90
+
91
+ new_data = {
92
+ "Warehouse Name": v.get("displayName"),
93
+ "Warehouse Id": v.get("id"),
94
+ "Description": v.get("description"),
95
+ "Connection Info": prop.get("connectionInfo"),
96
+ "Created Date": prop.get("createdDate"),
97
+ "Last Updated Time": prop.get("lastUpdatedTime"),
98
+ }
99
+ df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
100
+
101
+ return df
102
+
103
+
104
+ def delete_warehouse(name: str, workspace: Optional[str] = None):
105
+ """
106
+ Deletes a Fabric warehouse.
107
+
108
+ Parameters
109
+ ----------
110
+ name: str
111
+ Name of the warehouse.
112
+ workspace : str, default=None
113
+ The Fabric workspace name.
114
+ Defaults to None which resolves to the workspace of the attached lakehouse
115
+ or if no lakehouse attached, resolves to the workspace of the notebook.
116
+ """
117
+
118
+ (workspace, workspace_id) = resolve_workspace_name_and_id(workspace)
119
+
120
+ item_id = fabric.resolve_item_id(
121
+ item_name=name, type="Warehouse", workspace=workspace
122
+ )
123
+
124
+ client = fabric.FabricRestClient()
125
+ response = client.delete(f"/v1/workspaces/{workspace_id}/warehouses/{item_id}")
126
+
127
+ if response.status_code != 200:
128
+ raise FabricHTTPException(response)
129
+
130
+ print(
131
+ f"{icons.green_dot} The '{name}' warehouse within the '{workspace}' workspace has been deleted."
132
+ )
sempy_labs/_workspaces.py CHANGED
@@ -22,9 +22,6 @@ def delete_user_from_workspace(email_address: str, workspace: Optional[str] = No
22
22
  The name of the workspace.
23
23
  Defaults to None which resolves to the workspace of the attached lakehouse
24
24
  or if no lakehouse attached, resolves to the workspace of the notebook.
25
-
26
- Returns
27
- -------
28
25
  """
29
26
 
30
27
  (workspace, workspace_id) = resolve_workspace_name_and_id(workspace)
@@ -3,7 +3,10 @@ from typing import Optional, List, Union
3
3
  from uuid import UUID
4
4
  import sempy_labs._icons as icons
5
5
  from sempy.fabric.exceptions import FabricHTTPException
6
- from sempy_labs._helper_functions import resolve_workspace_name_and_id, pagination
6
+ from sempy_labs._helper_functions import (
7
+ resolve_workspace_name_and_id,
8
+ pagination,
9
+ )
7
10
  import datetime
8
11
  import numpy as np
9
12
  import pandas as pd
@@ -387,7 +390,7 @@ def revoke_external_data_share(
387
390
 
388
391
 
389
392
  def list_capacities_delegated_tenant_settings(
390
- return_dataframe: Optional[bool] = True,
393
+ return_dataframe: bool = True,
391
394
  ) -> Optional[pd.DataFrame | dict]:
392
395
  """
393
396
  Returns list of tenant setting overrides that override at the capacities.
@@ -477,11 +480,11 @@ def list_capacities_delegated_tenant_settings(
477
480
 
478
481
 
479
482
  def scan_workspaces(
480
- data_source_details: Optional[bool] = False,
481
- dataset_schema: Optional[bool] = False,
482
- dataset_expressions: Optional[bool] = False,
483
- lineage: Optional[bool] = False,
484
- artifact_users: Optional[bool] = False,
483
+ data_source_details: bool = False,
484
+ dataset_schema: bool = False,
485
+ dataset_expressions: bool = False,
486
+ lineage: bool = False,
487
+ artifact_users: bool = False,
485
488
  workspace: Optional[str | List[str]] = None,
486
489
  ) -> dict:
487
490
 
@@ -519,6 +522,16 @@ def scan_workspaces(
519
522
 
520
523
 
521
524
  def list_datasets() -> pd.DataFrame:
525
+ """
526
+ Shows a list of datasets for the organization.
527
+
528
+ Returns
529
+ -------
530
+ pandas.DataFrame
531
+ A pandas dataframe showing a list of datasets for the organization.
532
+ """
533
+
534
+ # https://learn.microsoft.com/en-us/rest/api/power-bi/admin/datasets-get-datasets-as-admin
522
535
 
523
536
  df = pd.DataFrame(
524
537
  columns=[
@@ -544,8 +557,7 @@ def list_datasets() -> pd.DataFrame:
544
557
  ]
545
558
  )
546
559
 
547
- client = fabric.FabricRestClient()
548
-
560
+ client = fabric.PowerBIRestClient()
549
561
  response = client.get("/v1.0/myorg/admin/datasets")
550
562
 
551
563
  if response.status_code != 200:
@@ -600,6 +612,25 @@ def list_datasets() -> pd.DataFrame:
600
612
  def list_item_access_details(
601
613
  item_name: str, type: str, workspace: Optional[str] = None
602
614
  ) -> pd.DataFrame:
615
+ """
616
+ Returns a list of users (including groups and service principals) and lists their workspace roles.
617
+
618
+ Parameters
619
+ ----------
620
+ item_name : str
621
+ Name of the Fabric item.
622
+ type : str
623
+ Type of Fabric item.
624
+ workspace : str, default=None
625
+ The Fabric workspace name.
626
+ Defaults to None which resolves to the workspace of the attached lakehouse
627
+ or if no lakehouse attached, resolves to the workspace of the notebook.
628
+
629
+ Returns
630
+ -------
631
+ pandas.DataFrame
632
+ A pandas dataframe showing a list of users (including groups and service principals) and lists their workspace roles.
633
+ """
603
634
 
604
635
  # https://learn.microsoft.com/en-us/rest/api/fabric/admin/items/list-item-access-details?tabs=HTTP
605
636
 
@@ -652,6 +683,19 @@ def list_item_access_details(
652
683
  def list_access_entities(
653
684
  user_email_address: str,
654
685
  ) -> pd.DataFrame:
686
+ """
687
+ Shows a list of permission details for Fabric and PowerBI items the specified user can access.
688
+
689
+ Parameters
690
+ ----------
691
+ user_email_address : str
692
+ The user's email address.
693
+
694
+ Returns
695
+ -------
696
+ pandas.DataFrame
697
+ A pandas dataframe showing a list of permission details for Fabric and PowerBI items the specified user can access.
698
+ """
655
699
 
656
700
  # https://learn.microsoft.com/en-us/rest/api/fabric/admin/users/list-access-entities?tabs=HTTP
657
701
 
@@ -691,8 +735,23 @@ def list_access_entities(
691
735
  def list_workspace_access_details(
692
736
  workspace: Optional[Union[str, UUID]] = None
693
737
  ) -> pd.DataFrame:
738
+ """
739
+ Shows a list of users (including groups and Service Principals) that have access to the specified workspace.
694
740
 
695
- # https://learn.microsoft.com/en-us/rest/api/fabric/admin/items/list-items?tabs=HTTP
741
+ Parameters
742
+ ----------
743
+ workspace : str, default=None
744
+ The Fabric workspace name.
745
+ Defaults to None which resolves to the workspace of the attached lakehouse
746
+ or if no lakehouse attached, resolves to the workspace of the notebook.
747
+
748
+ Returns
749
+ -------
750
+ pandas.DataFrame
751
+ A pandas dataframe showing a list of users (including groups and Service Principals) that have access to the specified workspace.
752
+ """
753
+
754
+ # https://learn.microsoft.com/en-us/rest/api/fabric/admin/workspaces/list-workspace-access-details?tabs=HTTP
696
755
 
697
756
  workspace_name = fabric.resolve_workspace_name(workspace)
698
757
  workspace_id = fabric.resolve_workspace_id(workspace_name)
@@ -732,6 +791,29 @@ def list_items(
732
791
  state: Optional[str] = None,
733
792
  type: Optional[str] = None,
734
793
  ) -> pd.DataFrame:
794
+ """
795
+ Shows a list of active Fabric and PowerBI items.
796
+
797
+ Parameters
798
+ ----------
799
+ capacity_name : str, default=None
800
+ The capacity name.
801
+ workspace : str, default=None
802
+ The Fabric workspace name.
803
+ Defaults to None which resolves to the workspace of the attached lakehouse
804
+ or if no lakehouse attached, resolves to the workspace of the notebook.
805
+ state : str, default=None
806
+ The item state.
807
+ type : str, default=None
808
+ The item type.
809
+
810
+ Returns
811
+ -------
812
+ pandas.DataFrame
813
+ A pandas dataframe showing a list of active Fabric and Power BI items.
814
+ """
815
+
816
+ # https://learn.microsoft.com/en-us/rest/api/fabric/admin/items/list-items?tabs=HTTP
735
817
 
736
818
  url = "/v1/admin/items?"
737
819
 
@@ -30,7 +30,7 @@ def resolve_domain_id(domain_name: str) -> UUID:
30
30
  return dfL_filt["Domain ID"].iloc[0]
31
31
 
32
32
 
33
- def list_domains(non_empty_only: Optional[bool] = False) -> pd.DataFrame:
33
+ def list_domains(non_empty_only: bool = False) -> pd.DataFrame:
34
34
  """
35
35
  Shows a list of domains.
36
36
 
@@ -12,7 +12,7 @@ import sempy_labs._icons as icons
12
12
  def direct_lake_schema_sync(
13
13
  dataset: str,
14
14
  workspace: Optional[str] = None,
15
- add_to_model: Optional[bool] = False,
15
+ add_to_model: bool = False,
16
16
  **kwargs,
17
17
  ):
18
18
  """
@@ -5,7 +5,11 @@ from typing import Optional, List, Union, Tuple
5
5
  from uuid import UUID
6
6
  import sempy_labs._icons as icons
7
7
  from sempy._utils._log import log
8
- from sempy_labs._helper_functions import retry, resolve_dataset_id
8
+ from sempy_labs._helper_functions import (
9
+ retry,
10
+ resolve_dataset_id,
11
+ resolve_lakehouse_name,
12
+ )
9
13
 
10
14
 
11
15
  def check_fallback_reason(
@@ -28,16 +32,17 @@ def check_fallback_reason(
28
32
  pandas.DataFrame
29
33
  The tables in the semantic model and their fallback reason.
30
34
  """
35
+ from sempy_labs.tom import connect_semantic_model
31
36
 
32
37
  workspace = fabric.resolve_workspace_name(workspace)
33
38
 
34
- dfP = fabric.list_partitions(dataset=dataset, workspace=workspace)
35
- dfP_filt = dfP[dfP["Mode"] == "DirectLake"]
36
-
37
- if len(dfP_filt) == 0:
38
- raise ValueError(
39
- f"{icons.red_dot} The '{dataset}' semantic model is not in Direct Lake. This function is only applicable to Direct Lake semantic models."
40
- )
39
+ with connect_semantic_model(
40
+ dataset=dataset, workspace=workspace, readonly=True
41
+ ) as tom:
42
+ if not tom.is_direct_lake():
43
+ raise ValueError(
44
+ f"{icons.red_dot} The '{dataset}' semantic model is not in Direct Lake. This function is only applicable to Direct Lake semantic models."
45
+ )
41
46
 
42
47
  df = fabric.evaluate_dax(
43
48
  dataset=dataset,
@@ -73,8 +78,9 @@ def generate_direct_lake_semantic_model(
73
78
  workspace: Optional[str] = None,
74
79
  lakehouse: Optional[str] = None,
75
80
  lakehouse_workspace: Optional[str] = None,
76
- overwrite: Optional[bool] = False,
77
- refresh: Optional[bool] = True,
81
+ schema: str = "dbo",
82
+ overwrite: bool = False,
83
+ refresh: bool = True,
78
84
  ):
79
85
  """
80
86
  Dynamically generates a Direct Lake semantic model based on tables in a Fabric lakehouse.
@@ -96,23 +102,32 @@ def generate_direct_lake_semantic_model(
96
102
  The Fabric workspace in which the lakehouse resides.
97
103
  Defaults to None which resolves to the workspace of the attached lakehouse
98
104
  or if no lakehouse attached, resolves to the workspace of the notebook.
105
+ schema : str, default="dbo"
106
+ The schema used for the lakehouse.
99
107
  overwrite : bool, default=False
100
108
  If set to True, overwrites the existing semantic model if it already exists.
101
109
  refresh: bool, default=True
102
110
  If True, refreshes the newly created semantic model after it is created.
103
-
104
- Returns
105
- -------
106
111
  """
107
112
 
108
113
  from sempy_labs.lakehouse import get_lakehouse_tables, get_lakehouse_columns
109
- from sempy_labs import create_blank_semantic_model, refresh_semantic_model
110
- from sempy_labs.tom import connect_semantic_model
111
114
  from sempy_labs.directlake import get_shared_expression
115
+ from sempy_labs.tom import connect_semantic_model
116
+ from sempy_labs._generate_semantic_model import create_blank_semantic_model
117
+ from sempy_labs._refresh_semantic_model import refresh_semantic_model
112
118
 
113
119
  if isinstance(lakehouse_tables, str):
114
120
  lakehouse_tables = [lakehouse_tables]
115
121
 
122
+ workspace = fabric.resolve_workspace_name(workspace)
123
+ if lakehouse_workspace is None:
124
+ lakehouse_workspace = workspace
125
+ if lakehouse is None:
126
+ lakehouse_id = fabric.get_lakehouse_id()
127
+ lakehouse_workspace_id = fabric.get_workspace_id()
128
+ lakehouse_workspace = fabric.resolve_workspace_name(lakehouse_workspace_id)
129
+ lakehouse = resolve_lakehouse_name(lakehouse_id, lakehouse_workspace)
130
+
116
131
  dfLT = get_lakehouse_tables(lakehouse=lakehouse, workspace=lakehouse_workspace)
117
132
 
118
133
  # Validate lakehouse tables
@@ -158,7 +173,7 @@ def generate_direct_lake_semantic_model(
158
173
 
159
174
  for t in lakehouse_tables:
160
175
  tom.add_table(name=t)
161
- tom.add_entity_partition(table_name=t, entity_name=t)
176
+ tom.add_entity_partition(table_name=t, entity_name=t, schema_name=schema)
162
177
  dfLC_filt = dfLC[dfLC["Table Name"] == t]
163
178
  for i, r in dfLC_filt.iterrows():
164
179
  lakeCName = r["Column Name"]
@@ -212,6 +227,7 @@ def get_direct_lake_source(
212
227
  response = client.post(
213
228
  "metadata/relations/upstream?apiVersion=3", json=request_body
214
229
  )
230
+
215
231
  artifacts = response.json().get("artifacts", [])
216
232
  sql_id, sql_object_name, sql_workspace_id, artifact_type = None, None, None, None
217
233
 
@@ -7,10 +7,7 @@ import sempy_labs._icons as icons
7
7
  def get_direct_lake_guardrails() -> pd.DataFrame:
8
8
  """
9
9
  Shows the guardrails for when Direct Lake semantic models will fallback to Direct Query
10
- based on Microsoft's `online documentation <https://learn.microsoft.com/power-bi/enterprise/directlake-overview>`_.
11
-
12
- Parameters
13
- ----------
10
+ based on Microsoft's `online documentation <https://learn.microsoft.com/power-bi/enterprise/directlake-overview>`_.
14
11
 
15
12
  Returns
16
13
  -------
@@ -21,9 +18,12 @@ def get_direct_lake_guardrails() -> pd.DataFrame:
21
18
  url = "https://learn.microsoft.com/power-bi/enterprise/directlake-overview"
22
19
 
23
20
  tables = pd.read_html(url)
24
- df = tables[0]
25
- df["Fabric SKUs"] = df["Fabric SKUs"].str.split("/")
26
- df = df.explode("Fabric SKUs", ignore_index=True)
21
+ for df in tables:
22
+ first_column_name = df.columns[0]
23
+ if first_column_name.startswith("Fabric"):
24
+ df[first_column_name] = df[first_column_name].str.split("/")
25
+ df = df.explode(first_column_name, ignore_index=True)
26
+ break
27
27
 
28
28
  return df
29
29
 
@@ -100,7 +100,7 @@ def add_table_to_direct_lake_semantic_model(
100
100
  dataset: str,
101
101
  table_name: str,
102
102
  lakehouse_table_name: str,
103
- refresh: Optional[bool] = True,
103
+ refresh: bool = True,
104
104
  workspace: Optional[str] = None,
105
105
  ):
106
106
  """
@@ -15,7 +15,7 @@ import sempy_labs._icons as icons
15
15
  def warm_direct_lake_cache_perspective(
16
16
  dataset: str,
17
17
  perspective: str,
18
- add_dependencies: Optional[bool] = False,
18
+ add_dependencies: bool = False,
19
19
  workspace: Optional[str] = None,
20
20
  ) -> pd.DataFrame:
21
21
  """
@@ -24,9 +24,9 @@ from sempy.fabric.exceptions import FabricHTTPException
24
24
  def get_lakehouse_tables(
25
25
  lakehouse: Optional[str] = None,
26
26
  workspace: Optional[str] = None,
27
- extended: Optional[bool] = False,
28
- count_rows: Optional[bool] = False,
29
- export: Optional[bool] = False,
27
+ extended: bool = False,
28
+ count_rows: bool = False,
29
+ export: bool = False,
30
30
  ) -> pd.DataFrame:
31
31
  """
32
32
  Shows the tables of a lakehouse and their respective properties. Option to include additional properties relevant to Direct Lake guardrails.
@@ -1,9 +1,7 @@
1
1
  import sempy.fabric as fabric
2
2
  from tqdm.auto import tqdm
3
- from pyspark.sql import SparkSession
4
3
  from sempy_labs._helper_functions import resolve_lakehouse_name
5
4
  from typing import List, Optional, Union
6
- import sempy_labs._icons as icons
7
5
  from sempy._utils._log import log
8
6
 
9
7
 
@@ -16,6 +14,7 @@ def lakehouse_attached() -> bool:
16
14
  bool
17
15
  Returns True if a lakehouse is attached to the notebook.
18
16
  """
17
+ from pyspark.sql import SparkSession
19
18
 
20
19
  spark = SparkSession.builder.getOrCreate()
21
20
  lakeId = spark.conf.get("trident.lakehouse.id")
@@ -49,6 +48,7 @@ def optimize_lakehouse_tables(
49
48
  or if no lakehouse attached, resolves to the workspace of the notebook.
50
49
  """
51
50
 
51
+ from pyspark.sql import SparkSession
52
52
  from sempy_labs.lakehouse._get_lakehouse_tables import get_lakehouse_tables
53
53
  from delta import DeltaTable
54
54
 
@@ -107,6 +107,7 @@ def vacuum_lakehouse_tables(
107
107
  The default retention period is 168 hours (7 days) unless manually configured via table properties.
108
108
  """
109
109
 
110
+ from pyspark.sql import SparkSession
110
111
  from sempy_labs.lakehouse._get_lakehouse_tables import get_lakehouse_tables
111
112
  from delta import DeltaTable
112
113
 
@@ -8,6 +8,7 @@ from sempy_labs._helper_functions import (
8
8
  resolve_lakehouse_id,
9
9
  create_abfss_path,
10
10
  retry,
11
+ generate_guid,
11
12
  )
12
13
  from sempy_labs.tom import connect_semantic_model
13
14
  from pyspark.sql import SparkSession
@@ -343,6 +344,8 @@ def migrate_field_parameters(
343
344
 
344
345
  tbl = TOM.Table()
345
346
  tbl.Name = tName
347
+ tbl.LineageTag = generate_guid()
348
+ tbl.SourceLineageTag = generate_guid()
346
349
  tbl.Partitions.Add(par)
347
350
 
348
351
  columns = ["Value1", "Value2", "Value3"]
@@ -352,6 +355,8 @@ def migrate_field_parameters(
352
355
  col.Name = colName
353
356
  col.SourceColumn = "[" + colName + "]"
354
357
  col.DataType = TOM.DataType.String
358
+ col.LineageTag = generate_guid()
359
+ col.SourceLineageTag = generate_guid()
355
360
 
356
361
  tbl.Columns.Add(col)
357
362
 
@@ -313,7 +313,7 @@ def _create_report(
313
313
  dataset: str,
314
314
  dataset_workspace: Optional[str] = None,
315
315
  report_workspace: Optional[str] = None,
316
- update_if_exists: Optional[bool] = False,
316
+ update_if_exists: bool = False,
317
317
  ):
318
318
 
319
319
  from sempy_labs.report import report_rebind
@@ -14,6 +14,7 @@ from sempy_labs._helper_functions import (
14
14
  from sempy_labs.lakehouse import get_lakehouse_tables, lakehouse_attached
15
15
  import sempy_labs._icons as icons
16
16
  from IPython.display import display, HTML
17
+ import sempy_labs.report._report_helper as helper
17
18
 
18
19
 
19
20
  @log
@@ -22,8 +23,8 @@ def run_report_bpa(
22
23
  rules: Optional[pd.DataFrame] = None,
23
24
  workspace: Optional[str] = None,
24
25
  # language: Optional[str] = None,
25
- export: Optional[bool] = False,
26
- return_dataframe: Optional[bool] = False,
26
+ export: bool = False,
27
+ return_dataframe: bool = False,
27
28
  ):
28
29
  """
29
30
  Displays an HTML visualization of the results of the Best Practice Analyzer scan for a report.
@@ -50,6 +51,7 @@ def run_report_bpa(
50
51
  """
51
52
 
52
53
  rpt = ReportWrapper(report=report, workspace=workspace)
54
+
53
55
  dfCV = rpt.list_custom_visuals()
54
56
  dfP = rpt.list_pages()
55
57
  dfRF = rpt.list_report_filters()
@@ -57,6 +59,12 @@ def run_report_bpa(
57
59
  dfRF["Table Name"], dfRF["Object Name"]
58
60
  )
59
61
  dfPF = rpt.list_page_filters()
62
+ # Convert back to dataframe
63
+ # if isinstance(dfPF, pd.io.formats.style.Styler):
64
+ # dfPF = dfPF.data
65
+ # if isinstance(dfP, pd.io.formats.style.Styler):
66
+ # dfP = dfP.data
67
+
60
68
  dfPF["Filter Object"] = (
61
69
  dfPF["Page Display Name"]
62
70
  + " : "
@@ -134,7 +142,9 @@ def run_report_bpa(
134
142
  df_output["Severity"] = row["Severity"]
135
143
  df_output["Description"] = row["Description"]
136
144
  df_output["URL"] = row["URL"]
137
- df_output["Report URL"] = rpt._get_web_url()
145
+ df_output["Report URL"] = helper.get_web_url(
146
+ report=report, workspace=workspace
147
+ )
138
148
 
139
149
  page_mapping_dict = dfP.set_index("Page Display Name")["Page URL"].to_dict()
140
150