Skip to content

docs: consolidate auth samples into a single samples/login.py - #1877

Draft
jacalata wants to merge 2 commits into
developmentfrom
jac/auth-from-env-sample
Draft

docs: consolidate auth samples into a single samples/login.py#1877
jacalata wants to merge 2 commits into
developmentfrom
jac/auth-from-env-sample

Conversation

@jacalata

Copy link
Copy Markdown
Contributor

Motivation

samples/login.py was the canonical auth demo but only partially covered the credential-loading space: argparse-driven, with get_env fallback for a few PAT fields, an odd hardcoded server.version = "3.19" pin after sign-in, and a getpass.getpass("Personal Access Token: ") fallback nobody's going to actually use (PATs are 40-char random strings). Env-var loading for basic auth wasn't there at all.

Rather than ship a second sample alongside (originally samples/auth_from_env.py in an earlier commit on this branch), this PR consolidates: one sample, three credential sources, clear precedence.

Behavior change

Rewritten samples/login.py:

  • Three credential sources compose in precedence order: CLI args > TABLEAU_* env vars > interactive password prompt (with --interactive).
  • Env vars are TABLEAU_-prefixed to avoid collision with generic shell variables like USERNAME (which Windows sets automatically to the OS user account). Pre-change get_env was reading bare SERVER / SITE / TOKEN_NAME / TOKEN_VALUE; those are renamed to TABLEAU_SERVER etc. Users relying on the bare names need to update — noted.
  • New --interactive flag prompts for a missing password via getpass. Requires a TTY — raises ValueError if stdin is redirected (pipe, file, non-interactive CI) so the failure mode is loud rather than hanging on stdin. PATs are never prompted for.
  • New --api-version CLI flag + TABLEAU_API_VERSION env var replace the previous unconditional server.version = "3.19" pin. Default now is use_server_version=True (auto-negotiate); the pin is opt-in.
  • New helpers resolve_credentials(args) and build_server_and_auth(args) split the resolution/construction steps from the sign-in step. Callers who want to control the sign-in scope themselves (with server.auth.sign_in(auth): ...) can use build_server_and_auth and skip sample_connect_to_server.
  • Kept function names sample_define_common_options, sample_connect_to_server, set_up_and_log_in, and get_env so any external references keep working. Grepped samples/ and test/: nothing else in-repo imports them, confirmed.
  • Removed the getpass.getpass("Personal Access Token: ") fallback — dead weight, no one types 40-char PATs.

Testing Run

  • python -c "from samples.login import sample_define_common_options, sample_connect_to_server, set_up_and_log_in, resolve_credentials, build_server_and_auth, get_env" — all names importable.
  • python samples/login.py with no args and no env — argparse succeeds, then build_server_and_auth raises the "Server URL is required" ValueError cleanly.
  • No other samples/ or test/ file imports from login.py. Verified via grep for each of the public names.
  • No unit tests for samples/ in this repo (grepped test/ for from samples); none added.
  • black and mypy clean via pre-commit.

Merge the previously-separate samples/auth_from_env.py into samples/login.py
so there is one canonical demo of how to sign in to Tableau Server. The
consolidated sample now supports three credential sources composed in
precedence order: CLI args, TABLEAU_* env vars, and (with --interactive)
a getpass password prompt. Env-var names are TABLEAU_-prefixed to avoid
collision with generic shell vars like USERNAME (which Windows sets
automatically for the current OS user).

Public helpers on samples/login.py:
  - sample_define_common_options(parser)   -- unchanged name; adds
    --interactive and --api-version.
  - get_env(key, default=None)             -- unchanged name.
  - resolve_credentials(args)              -- new; CLI -> env -> prompt.
  - build_server_and_auth(args)            -- new; returns (Server, Auth)
    without signing in, replacing load_from_env's return shape.
  - sample_connect_to_server(args)         -- unchanged name; now calls
    resolve_credentials + build_server_and_auth then signs in.
  - set_up_and_log_in()                    -- unchanged main entry.

Removes the "Personal Access Token:" getpass fallback in
sample_connect_to_server -- nobody wants to type a 40-character random
string; a missing PAT half now raises the partial-credentials error.
The password getpass prompt is likewise gated on --interactive rather
than triggering silently on a missing --password.

Env-var rename (breaks anyone relying on the pre-change bare names in
login.py::get_env calls, though no other sample called those helpers):
  SERVER      -> TABLEAU_SERVER
  SITE        -> TABLEAU_SITE
  TOKEN_NAME  -> TABLEAU_TOKEN_NAME
  TOKEN_VALUE -> TABLEAU_TOKEN

samples/auth_from_env.py is deleted; its load_from_env() shape is now
available as resolve_credentials(args) + build_server_and_auth(args).
The README subsection is retained but points at samples/login.py and
documents the three-source precedence.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown

Coverage

Coverage Report
FileStmtsMissCoverMissing
tableauserverclient
   __init__.py50100% 
   config.py150100% 
   datetime_helpers.py2511 96%
   exponential_backoff.py200100% 
   filesys_helpers.py310100% 
   namespace.py2533 88%
tableauserverclient/bin
   __init__.py20100% 
   _version.py358212212 41%
tableauserverclient/helpers
   __init__.py10100% 
   logging.py20100% 
   strings.py3111 97%
tableauserverclient/models
   __init__.py460100% 
   collection_item.py4177 83%
   column_item.py553232 42%
   connection_credentials.py351111 69%
   connection_item.py941414 85%
   custom_view_item.py1442121 85%
   data_acceleration_report_item.py5411 98%
   data_alert_item.py15844 97%
   data_freshness_policy_item.py1551515 90%
   database_item.py2073636 83%
   datasource_item.py3001212 96%
   dqw_item.py10455 95%
   exceptions.py40100% 
   extensions_item.py13244 97%
   extract_item.py4444 91%
   favorites_item.py6988 88%
   fileupload_item.py190100% 
   flow_item.py1491010 93%
   flow_run_item.py710100% 
   group_item.py8966 93%
   groupset_item.py4977 86%
   interval_item.py1823232 82%
   job_item.py1921010 95%
   linked_tasks_item.py7911 99%
   location_item.py2922 93%
   metric_item.py1291313 90%
   oidc_item.py6333 95%
   pagination_item.py3411 97%
   permissions_item.py1111212 89%
   project_item.py2073131 85%
   property_decorators.py1001818 82%
   reference_item.py2622 92%
   revision_item.py5911 98%
   schedule_item.py20966 97%
   server_info_item.py3777 81%
   site_item.py6361313 98%
   subscription_item.py10122 98%
   table_item.py1191818 85%
   tableau_auth.py612525 59%
   tableau_types.py2711 96%
   tag_item.py150100% 
   target.py60100% 
   task_item.py5622 96%
   user_item.py3381717 95%
   view_item.py2201616 93%
   virtual_connection_item.py6488 88%
   webhook_item.py6911 99%
   workbook_item.py3621616 96%
tableauserverclient/server
   __init__.py90100% 
   exceptions.py40100% 
   filter.py2911 97%
   pager.py3311 97%
   query.py1431515 90%
   request_factory.py1335195195 85%
   request_options.py38655 99%
   server.py1882323 88%
   sort.py60100% 
tableauserverclient/server/endpoint
   __init__.py350100% 
   auth_endpoint.py731010 86%
   custom_views_endpoint.py1521212 92%
   data_acceleration_report_endpoint.py210100% 
   data_alert_endpoint.py942323 76%
   databases_endpoint.py1113030 73%
   datasources_endpoint.py3233333 90%
   default_permissions_endpoint.py4433 93%
   dqw_endpoint.py451616 64%
   endpoint.py2612525 90%
   exceptions.py7966 92%
   extensions_endpoint.py310100% 
   favorites_endpoint.py942222 77%
   fileuploads_endpoint.py510100% 
   flow_runs_endpoint.py6299 85%
   flow_task_endpoint.py2122 90%
   flows_endpoint.py1985353 73%
   groups_endpoint.py12699 93%
   groupsets_endpoint.py7277 90%
   jobs_endpoint.py6799 87%
   linked_tasks_endpoint.py370100% 
   metadata_endpoint.py881414 84%
   metrics_endpoint.py5566 89%
   oidc_endpoint.py4211 98%
   permissions_endpoint.py4433 93%
   projects_endpoint.py1782424 87%
   resource_tagger.py1273535 72%
   schedules_endpoint.py1191111 91%
   server_info_endpoint.py361010 72%
   sites_endpoint.py1302727 79%
   subscriptions_endpoint.py561414 75%
   tables_endpoint.py1103636 67%
   tasks_endpoint.py6366 90%
   users_endpoint.py17077 96%
   views_endpoint.py15099 94%
   virtual_connections_endpoint.py1131010 91%
   webhooks_endpoint.py5499 83%
   workbooks_endpoint.py3382222 93%
TOTAL12068142588% 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant