samples: credential helper, pagination fixes, and new jobs/subscriptions samples - #1843
Open
jacalata wants to merge 4 commits into
Open
samples: credential helper, pagination fixes, and new jobs/subscriptions samples#1843jacalata wants to merge 4 commits into
jacalata wants to merge 4 commits into
Conversation
Introduces samples/_shared.py with resolve_credentials(args), which fills missing sign-in values from env vars (TABLEAU_SERVER, TABLEAU_TOKEN_NAME, etc.) or a .env-style file, and falls back to interactive getpass so secrets never touch shell history. CLI args still work for CI use. Wires the new helper into login.py, publish_workbook.py, and publish_datasource.py to establish the pattern; the remaining samples still accept the same CLI args and continue to work as before. Addresses #1551 item 1.
Several samples called `server.<endpoint>.get()` and named the result `all_workbooks`, `all_datasources`, etc. This only returns the first page (default 100 items); if the item of interest was not on that page it was silently missed and the sample failed with a "not found" message. Replace those calls with `TSC.Pager(server.<endpoint>)` so every page is walked. Where a total count was being displayed we still make one plain `.get()` up front so the total_available field is available without paging through the whole site twice. Also corrects an unrelated typo in getting_started/3_hello_universe.py where the "workbooks" section actually queried datasources. Addresses #1551 item 2 (and #1531).
The existing samples cover workbooks, datasources, schedules, extracts,
projects, users, groups, favorites, and webhooks, but there was no
sample for two frequently asked-about endpoints:
* list_jobs.py -- lists background jobs (extract refreshes, publishes,
flow runs, etc.), demonstrating the .filter() queryset with
date/status/type filters and the wait_for_job helper.
* manage_subscriptions.py -- list/create/delete site subscriptions,
demonstrating the SubscriptionItem + Target pattern and paginated
listing with TSC.Pager.
Both samples use the new samples/_shared.py credential resolver so the
sign-in pattern matches the rest of the samples.
Addresses #1551 item 3.
Restore -t for --site, -u for --username, -p for --password; drop short flags on --token-name and --token-value. This matches tabcmd's canonical short flags in tabcmd/execution/parent_parser.py so users running both tools have one convention to remember. The initial refactor picked new short flags without noticing that the old samples/login.py already followed tabcmd's convention (-p was --password, -t was --site). Reassigning -p to --token-name meant `python login.py -p <password>` silently sent the password as a token name. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Updates the samples/ scripts to demonstrate safer credential handling, correct pagination patterns, and add new examples for jobs and subscriptions, without changing the core tableauserverclient library.
Changes:
- Introduces
samples/_shared.pyhelpers for common CLI args plus credential resolution from CLI/env/.env/interactive prompt. - Fixes several samples that used
.get()(first page only) by switching toTSC.Pager(...)(or iterable QuerySet) to traverse full result sets. - Adds new sample scripts for listing background jobs and managing subscriptions.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| samples/_shared.py | New shared credential + argparse helpers used by multiple samples |
| samples/login.py | Uses shared helpers; updates login flow to avoid secrets on CLI |
| samples/publish_workbook.py | Uses shared helpers; fixes project discovery to page through projects |
| samples/publish_datasource.py | Uses shared helpers; removes ad-hoc env reading and debug overrides |
| samples/refresh_tasks.py | Pages through tasks via TSC.Pager instead of first-page .get() |
| samples/move_workbook_sites.py | Pages through sites via TSC.Pager instead of first-page .get() |
| samples/update_workbook_data_freshness_policy.py | Uses TSC.Pager to list all workbooks |
| samples/extracts.py | Uses TSC.Pager to list all workbooks |
| samples/explore_workbook.py | Uses TSC.Pager for projects/workbooks/custom views paging correctness |
| samples/explore_webhooks.py | Uses TSC.Pager to list all webhooks |
| samples/explore_favorites.py | Uses TSC.Pager to list all workbooks/datasources |
| samples/explore_datasource.py | Uses TSC.Pager for projects/datasources paging correctness |
| samples/getting_started/3_hello_universe.py | Fixes incorrect endpoint (workbooks vs datasources) |
| samples/list_jobs.py | New sample demonstrating jobs listing/filtering and wait-for-job |
| samples/manage_subscriptions.py | New sample demonstrating list/create/delete subscriptions with paging |
Suppressed comments (3)
samples/publish_workbook.py:34
add_common_arguments()already reserves-ufor--username, so reusing-uhere causes argparse to raise a conflicting option error and the script won’t start.
group = parser.add_mutually_exclusive_group(required=False)
group.add_argument("--thumbnails-user-id", "-u", help="User ID to use for thumbnails")
group.add_argument("--thumbnails-group-id", "-g", help="Group ID to use for thumbnails")
samples/_shared.py:133
- This claims a
.envfile next to the sample is loaded automatically, but the implementation only checks the current working directory. If users runpython samples/<script>.pyfrom the repo root,samples/.envwill be ignored.
# Load `.env` file if one is requested or available.
env_file = getattr(args, "env_file", None)
if env_file:
_load_env_file(Path(env_file))
else:
default_env = Path.cwd() / ".env"
if default_env.is_file():
_load_env_file(default_env)
samples/_shared.py:149
resolve_credentialswill callinput()/getpass.getpass()even when stdin is not a TTY, which can hang non-interactive runs despite the docstring saying prompts happen only when stdin is a terminal.
if not allow_prompt:
return
# Prompt for what's still missing. We only prompt for the pieces we
# actually need: server URL, and one of token or username/password.
if not getattr(args, "server", None):
args.server = input("Tableau server URL: ").strip()
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+101
to
+102
| create_p.add_argument("--attach-image", action="store_true", default=True, help="Attach a PNG snapshot (default).") | ||
| create_p.add_argument("--attach-pdf", action="store_true", default=False, help="Also attach a PDF snapshot.") |
| @@ -2,91 +2,50 @@ | |||
| # This script demonstrates how to log in to Tableau Server Client. | |||
| # | |||
| # To run the script, you must have installed Python 3.7 or later. | |||
| # # Wait for a specific job to finish. | ||
| # python samples/list_jobs.py --wait <job_id> | ||
| # | ||
| # To run the script, you must have installed Python 3.9 or later. |
| # # Delete an existing subscription. | ||
| # python samples/manage_subscriptions.py delete --id <subscription_id> | ||
| # | ||
| # To run the script, you must have installed Python 3.9 or later. |
Comment on lines
+43
to
+48
| """Add the sign-in and logging arguments used by every sample. | ||
|
|
||
| Kept in sync with the historical inline definitions so no existing | ||
| command line breaks. All arguments are optional -- missing values | ||
| are pulled from the environment or prompted for interactively. | ||
| """ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1551.
Motivation
#1551 flagged three concerns with
samples/: credentials always on thecommand line, several samples using
.get()where they meant to page,and no examples for background jobs or subscriptions. Each of the three
gets one commit for reviewability.
Behavior change
Samples only -- no library changes. Users running the sample scripts
directly will see:
Credentials.
samples/_shared.pyaddsresolve_credentials(args)which fills missing sign-in values from env vars
(
TABLEAU_SERVER,TABLEAU_TOKEN_NAME, etc.), a plain.envfile, orgetpass.getpass(), in that precedence order. CLI args continue towork for CI use. Wired into
login.py,publish_workbook.py, andpublish_datasource.pyto establish the pattern; other samples leftalone to keep the diff surgical. Stdlib only, no new deps.
Short flags on the shared helper match tabcmd's canonical set:
-s--server,-t--site,-u--username,-p--password,-l--logging-level.--token-nameand--token-valueare long-only.An earlier iteration of this PR reassigned
-pto--token-name; thatwas corrected before merge -- see 54e51f5.
Pagination fixes. Several samples called
server.<endpoint>.get()and named the resultall_workbooks, whichonly returns the first page (default 100). Replaces those with
TSC.Pager(...)so every page is walked. Where a total count wasdisplayed we still
.get()once to grabtotal_available; that meansone extra request but preserves the count line.
Also fixes an unrelated bug in
getting_started/3_hello_universe.pywhere the "workbooks" section actually queried datasources.
New samples.
list_jobs.py-- background jobs (extract refreshes, publishes,flow runs) with
.filter()queryset API +wait_for_jobmanage_subscriptions.py-- list/create/delete subscriptions withSubscriptionItem/Targetand paginated listingNot exhaustive on coverage -- data alerts, metrics, tables, databases,
virtual connections still have no dedicated sample. Left for follow-up.
Test plan
samples/ has no automated tests; each check below is manual.
python samples/login.py --helpshows the new flags with updated help textTABLEAU_TOKEN_NAME/TABLEAU_TOKEN_VALUEin env and runningpython samples/login.py -s <server>signs in with no secrets on the CLIpython samples/list_jobs.py --hours 24lists recent jobs;--wait <job_id>blocks until completionpython samples/manage_subscriptions.py listprints existing subs;create+deleteround-trips cleanlyexplore_datasource.py,explore_workbook.py,extracts.py,update_workbook_data_freshness_policy.py, andpublish_workbook.pyreturns correct behavior on a >100-item site🤖 Generated with Claude Code