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 |
from sempy_labs.tom import connect_semantic_model
# Read-only connection
with connect_semantic_model(
dataset="My Semantic Model",
readonly=True,
workspace="My Workspace"
) as tom:
# Read model metadata
for measure in tom.all_measures():
print(f"Measure: {measure.Name}")
# Read-write connection (requires XMLA read/write enabled)
with connect_semantic_model(
dataset="My Semantic Model",
readonly=False,
workspace="My Workspace"
) as tom:
# Modify model
measure = tom.model.Tables["Sales"].Measures["Revenue"]
measure.Description = "Total revenue in USD"
# Changes are saved when context exits
with statement - changes are saved on exitservice_principal_authentication contextwith 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_level
| 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 |
with 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 = False
import 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)
The TOMWrapper class includes many helper methods for common operations:
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)
The TOMWrapper also supports Azure Analysis Services:
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)
with statement)readonly=True when only reading metadataall_measures(), etc.) for efficient traversalfrom sempy.fabric.exceptions import FabricHTTPException