TSC Datasource Management: All Methods
Every data source operation on the site — list, inspect, download, publish, refresh, update, rotate credentials, delete — from one script instead of a hundred clicks.
Why it matters
Data sources are where Tableau sites rot: refreshes fail silently, connection credentials expire, nobody knows which extract feeds which dashboard. TSC's datasources endpoint is ten methods that replace the clicking — and once you can enumerate and modify every data source programmatically, stale-content audits, credential rotation, and bulk migrations stop being projects and become scripts.
Write a Python CLI using tableauserverclient and argparse with subcommands for Tableau data source operations: `list` (with optional --name-contains, --project, and --tag filters via RequestOptions), `inspect <id>` (details plus populated connections), `download <id>` (backup, with --no-extract for speed), `publish <path> --project <name> --mode CreateNew|Overwrite`, `refresh <id>` (trigger and poll the job to completion), `update <id> --owner|--certified --note`, `rotate <id>` (update connection credentials from environment variables), and `delete <id>`. Authenticate with a PAT from environment variables. Every destructive subcommand (publish --mode Overwrite, rotate, delete) requires a --confirm flag and supports --dry-run that prints what would change instead of doing it.
Step 1 — datasources.get — List & Filter Data Sources
datasources.get — List & Filter Data Sources
List every datasource on your site and filter with RequestOptions + Filter (name, project, tags, owner, certification).
Name Contains is handy for quick, broad matches (e.g., 'Sales'). Combine multiple filters for precise results.with server.auth.sign_in(tableau_auth):
ro = TSC.RequestOptions()
ro.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.Contains, 'Sales'))
all_datasources, pagination_item = server.datasources.get(ro)
print([ds.name for ds in all_datasources])Step 2 — datasources.get_by_id — Fetch a Specific Datasource
datasources.get_by_id — Fetch a Specific Datasource
Each datasource has a unique ID; fetch it to access full details like project, owner, and certification note.
with server.auth.sign_in(tableau_auth):
datasource = server.datasources.get_by_id('YOUR-DATASOURCE-ID')
print(datasource.name, datasource.project_name, datasource.owner_id)Step 3 — datasources.populate_connections — See Connection Details
datasources.populate_connections — See Connection Details
Datasource objects do not include connection info by default. Populate to view server address, DB name, and connection type.
with server.auth.sign_in(tableau_auth):
ds = server.datasources.get_by_id('YOUR-DATASOURCE-ID')
server.datasources.populate_connections(ds)
for conn in ds.connections:
print(conn.connection_type, conn.server_address, conn.dbname)Step 4 — datasources.download — Save a Datasource File
datasources.download — Save a Datasource File
Download a local copy to inspect structure or keep a backup. You can exclude extracts for faster downloads.
with server.auth.sign_in(tableau_auth):
path = server.datasources.download('YOUR-DATASOURCE-ID', include_extract=False)
print(f'Downloaded to {path}')Step 5 — datasources.publish — Publish a New Datasource
datasources.publish — Publish a New Datasource
Publish a new datasource or update an existing one. Provide a valid file path and target project.
CreateNew (new item), Overwrite (replace), Append (for compatible extract schemas).with server.auth.sign_in(tableau_auth):
project_id = 'YOUR-PROJECT-ID'
file_path = r'C:\\path\\to\\WorldIndicators.hyper'
new_ds_item = TSC.DatasourceItem(project_id, name='WorldIndicators')
new_ds = server.datasources.publish(new_ds_item, file_path, TSC.Server.PublishMode.CreateNew)
print(new_ds.name, new_ds.id)Step 6 — datasources.refresh — Run an On-Demand Extract Refresh
datasources.refresh — Run an On-Demand Extract Refresh
Trigger a refresh now instead of waiting for the schedule. Returns a job you can track.
with server.auth.sign_in(tableau_auth):
ds = server.datasources.get_by_id('YOUR-DATASOURCE-ID')
job = server.datasources.refresh(ds)
print('Refresh job started:', job.id)Step 7 — datasources.update — Update Metadata
datasources.update — Update Metadata
Modify metadata like owner, description, and certification settings, then push changes.
certified only after validation; include a clear certification_note for auditors.with server.auth.sign_in(tableau_auth):
ds = server.datasources.get_by_id('YOUR-DATASOURCE-ID')
ds.certified = True
ds.certification_note = 'Validated by BI team'
updated = server.datasources.update(ds)
print(updated.certified, updated.certification_note)Step 8 — datasources.update_connection — Rotate or Edit Connection Credentials
datasources.update_connection — Rotate or Edit Connection Credentials
Populate connections, change fields, then apply with update_connection.
with server.auth.sign_in(tableau_auth):
ds = server.datasources.get_by_id('YOUR-DATASOURCE-ID')
server.datasources.populate_connections(ds)
conn = ds.connections[0]
conn.server_address = 'new-db-host'
conn.username = 'newuser'
conn.password = 'newpass'
updated_conn = server.datasources.update_connection(ds, conn)
print(updated_conn.server_address, updated_conn.username)Step 9 — datasources.update_hyper_data — Modify Rows in Live-to-Hyper Datasources
datasources.update_hyper_data — Modify Rows in Live-to-Hyper Datasources
Push row-level updates into a published Hyper datasource (REST API 3.13+). Prepare a Hyper payload file with your changes.
# Example using pantab or Hyper API to build payload.hyper, then:
with server.auth.sign_in(tableau_auth):
ds = server.datasources.get_by_id('YOUR-DATASOURCE-ID')
actions = [{ 'action': 'insert', 'table': {'schema': 'public', 'name': 'region_sales'} }]
job = server.datasources.update_hyper_data(ds, request_id='unique-req-001', actions=actions, payload='payload.hyper')
print('Update job started:', job.id)Step 10 — datasources.delete — Permanently Remove a Datasource
datasources.delete — Permanently Remove a Datasource
Deletes a datasource permanently. Double-check the ID before running this—there is no undo.
with server.auth.sign_in(tableau_auth):
server.datasources.delete('YOUR-DATASOURCE-ID')
print('Datasource deleted.')Got what you came for? Mark the stop and the line fills in beneath you.