npx skills add ...
npx skills add microsoft/semantic-link-labs --skill tom-operations
npx skills add microsoft/semantic-link-labs --skill tom-operations
Guide for working with the TOM (Tabular Object Model) wrapper. Use this when modifying semantic models programmatically.
This skill covers working with the TOM wrapper in Semantic Link Labs for programmatic semantic model management.
Use this skill when you need to:
The TOM wrapper provides a Pythonic interface to the Tabular Object Model (TOM), which is the object model for Analysis Services semantic models.
| File | Purpose |
|---|---|
src/sempy_labs/tom/__init__.py | Module exports |
src/sempy_labs/tom/_model.py | TOMWrapper class implementation |
with statement - changes are saved on exitservice_principal_authentication context| Method | Returns |
|---|---|
all_columns() | All columns in all tables |
all_calculated_columns() | All calculated columns |
all_calculated_tables() | All calculated tables |
all_calculation_groups() | All calculation groups |
all_measures() | All measures |
all_partitions() | All partitions |
all_hierarchies() | All hierarchies |
all_levels() | All hierarchy levels |
all_calculation_items() | All calculation items |
all_functions() | All user-defined functions |
The TOMWrapper class includes many helper methods for common operations:
The TOMWrapper also supports Azure Analysis Services:
with statement)readonly=True when only reading metadataall_measures(), etc.) for efficient traversal| Resource | URL |
|---|---|
| TOM Reference | Microsoft Docs |
| Sample Notebook | Tabular Object Model.ipynb |
| API Documentation | ReadTheDocs |
with connect_semantic_model(dataset, workspace=workspace) as tom:
# Access the model
model = tom.model
# Get dataset info
dataset_id = tom._dataset_id
dataset_name = tom._dataset_name
workspace_id = tom._workspace_id
workspace_name = tom._workspace_name
# Check compatibility level
compat_level = tom._compat_levelwith connect_semantic_model(dataset, workspace=workspace) as tom:
# List all measures
for measure in tom.all_measures():
print(f"Table: {measure.Parent.Name}, Measure: {measure.Name}")
# List all columns
for column in tom.all_columns():
print(f"Table: {column.Table.Name}, Column: {column.Name}, Type: {column.DataType}")
# List all partitions
for partition in tom.all_partitions():
print(f"Table: {partition.Table.Name}, Partition: {partition.Name}")with connect_semantic_model(dataset, workspace=workspace) as tom:
for table in tom.model.Tables:
print(f"Table: {table.Name}")
print(f" Description: {table.Description}")
print(f" Is Hidden: {table.IsHidden}")with connect_semantic_model(dataset, workspace=workspace) as tom:
for column in tom.all_columns():
print(f"Column: {column.Name}")
print(f" Table: {column.Table.Name}")
print(f" Data Type: {column.DataType}")
print(f" Is Hidden: {column.IsHidden}")with connect_semantic_model(dataset, workspace=workspace) as tom:
for measure in tom.all_measures():
print(f"Measure: {measure.Name}")
print(f" Table: {measure.Parent.Name}")
print(f" Expression: {measure.Expression}")
print(f" Format String: {measure.FormatString}")with connect_semantic_model(dataset, workspace=workspace) as tom:
for rel in tom.model.Relationships:
print(f"From: {rel.FromTable.Name}[{rel.FromColumn.Name}]")
print(f"To: {rel.ToTable.Name}[{rel.ToColumn.Name}]")
print(f"Cross Filter: {rel.CrossFilteringBehavior}")with connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:
measure = tom.model.Tables["Sales"].Measures["Revenue"]
measure.Description = "Total revenue"
measure.FormatString = "$#,##0.00"
measure.DisplayFolder = "Financial Metrics"with connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:
column = tom.model.Tables["Date"].Columns["Month"]
column.IsHidden = False
column.Description = "Calendar month"
column.SortByColumn = tom.model.Tables["Date"].Columns["MonthNumber"]with connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:
table = tom.model.Tables["Sales"]
table.Description = "Sales transactions"
table.IsHidden = Falseimport Microsoft.AnalysisServices.Tabular as TOM
with connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:
table = tom.model.Tables["Sales"]
new_measure = TOM.Measure()
new_measure.Name = "Total Sales"
new_measure.Expression = "SUM(Sales[Amount])"
new_measure.FormatString = "$#,##0.00"
new_measure.Description = "Sum of all sales amounts"
table.Measures.Add(new_measure)import Microsoft.AnalysisServices.Tabular as TOM
with connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:
table = tom.model.Tables["Products"]
calc_column = TOM.Column()
calc_column.Name = "Profit Margin"
calc_column.Type = TOM.ColumnType.Calculated
calc_column.Expression = "[Revenue] - [Cost]"
calc_column.DataType = TOM.DataType.Decimal
table.Columns.Add(calc_column)import Microsoft.AnalysisServices.Tabular as TOM
with connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:
from_column = tom.model.Tables["Sales"].Columns["ProductKey"]
to_column = tom.model.Tables["Products"].Columns["ProductKey"]
relationship = TOM.SingleColumnRelationship()
relationship.Name = f"{from_column.Table.Name}_{to_column.Table.Name}"
relationship.FromColumn = from_column
relationship.ToColumn = to_column
relationship.CrossFilteringBehavior = TOM.CrossFilteringBehavior.OneDirection
tom.model.Relationships.Add(relationship)with connect_semantic_model(dataset, workspace=workspace) as tom:
# List all measures
df = tom.list_measures()
# List all columns
df = tom.list_columns()
# List all relationships
df = tom.list_relationships()
# List all partitions
df = tom.list_partitions()with connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:
# Add measure
tom.add_measure(
table_name="Sales",
measure_name="Total Sales",
expression="SUM(Sales[Amount])",
format_string="$#,##0.00"
)
# Add calculated column
tom.add_calculated_column(
table_name="Products",
column_name="Margin",
expression="[Revenue] - [Cost]"
)with connect_semantic_model(dataset, readonly=False, workspace=workspace) as tom:
# Update measure expression
tom.update_measure(
table_name="Sales",
measure_name="Total Sales",
expression="SUMX(Sales, Sales[Quantity] * Sales[Price])"
)from sempy_labs import service_principal_authentication
from sempy_labs.tom import connect_semantic_model
# Using Service Principal
with service_principal_authentication(
tenant_id="...",
client_id="...",
client_secret="..."
):
with connect_semantic_model(
dataset="My Model",
readonly=False,
workspace="My Workspace"
) as tom:
# Operations use Service Principal credentials
for measure in tom.all_measures():
print(measure.Name)with connect_semantic_model(
dataset="MyDatabase",
workspace="asazure://westus2.asazure.windows.net/myserver",
readonly=True
) as tom:
for table in tom.model.Tables:
print(table.Name)from sempy.fabric.exceptions import FabricHTTPException
try:
with connect_semantic_model(
dataset="My Model",
readonly=False,
workspace="My Workspace"
) as tom:
# Modifications...
pass
except FabricHTTPException as e:
print(f"API error: {e}")
except Exception as e:
print(f"Error: {e}")
# Changes NOT saved due to exception