tableauserverclient 0.28__tar.gz → 0.30__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tableauserverclient-0.28 → tableauserverclient-0.30}/PKG-INFO +2 -2
- {tableauserverclient-0.28 → tableauserverclient-0.30}/contributing.md +1 -2
- {tableauserverclient-0.28 → tableauserverclient-0.30}/pyproject.toml +1 -1
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/getting_started/3_hello_universe.py +4 -8
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/_version.py +3 -3
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/config.py +1 -1
- tableauserverclient-0.30/tableauserverclient/helpers/headers.py +17 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/helpers/strings.py +0 -2
- tableauserverclient-0.30/tableauserverclient/models/interval_item.py +268 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/project_item.py +0 -3
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/schedule_item.py +27 -9
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/task_item.py +18 -16
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/datasources_endpoint.py +3 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/endpoint.py +9 -47
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/flows_endpoint.py +3 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/tasks_endpoint.py +18 -12
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/workbooks_endpoint.py +6 -3
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/request_factory.py +11 -7
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/request_options.py +40 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient.egg-info/PKG-INFO +2 -2
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient.egg-info/SOURCES.txt +5 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient.egg-info/requires.txt +1 -1
- tableauserverclient-0.30/test/assets/schedule_get_daily_id.xml +11 -0
- tableauserverclient-0.30/test/assets/schedule_get_hourly_id.xml +11 -0
- tableauserverclient-0.30/test/assets/schedule_get_monthly_id.xml +11 -0
- tableauserverclient-0.30/test/assets/tasks_without_schedule.xml +12 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_datasource.py +11 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_endpoint.py +8 -5
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_flow.py +10 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_schedule.py +50 -2
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_task.py +12 -1
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_workbook.py +9 -0
- tableauserverclient-0.28/tableauserverclient/models/interval_item.py +0 -202
- {tableauserverclient-0.28 → tableauserverclient-0.30}/CHANGELOG.md +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/CONTRIBUTORS.md +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/LICENSE +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/LICENSE.versioneer +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/MANIFEST.in +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/README.md +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/docs/README.md +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/add_default_permission.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/create_extract_task.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/create_group.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/create_project.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/create_schedules.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/explore_datasource.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/explore_favorites.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/explore_site.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/explore_webhooks.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/explore_workbook.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/export.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/extracts.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/filter_sort_groups.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/filter_sort_projects.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/getting_started/1_hello_server.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/getting_started/2_hello_site.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/initialize_server.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/kill_all_jobs.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/list.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/login.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/metadata_query.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/move_workbook_projects.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/move_workbook_sites.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/name.txt +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/pagination_sample.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/publish_datasource.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/publish_workbook.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/query_permissions.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/refresh.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/refresh_tasks.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/set_refresh_schedule.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/smoke_test.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/update_connection.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/update_datasource_data.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/setup.cfg +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/setup.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/__init__.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/datetime_helpers.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/exponential_backoff.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/filesys_helpers.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/helpers/__init__.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/helpers/logging.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/__init__.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/column_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/connection_credentials.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/connection_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/custom_view_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/data_acceleration_report_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/data_alert_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/database_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/datasource_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/dqw_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/exceptions.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/favorites_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/fileupload_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/flow_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/flow_run_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/group_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/job_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/metric_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/pagination_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/permissions_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/property_decorators.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/reference_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/revision_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/server_info_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/site_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/subscription_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/table_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/tableau_auth.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/tableau_types.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/tag_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/target.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/user_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/view_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/webhook_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/workbook_item.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/namespace.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/py.typed +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/__init__.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/__init__.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/auth_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/custom_views_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/data_acceleration_report_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/data_alert_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/databases_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/default_permissions_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/dqw_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/exceptions.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/favorites_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/fileuploads_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/flow_runs_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/groups_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/jobs_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/metadata_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/metrics_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/permissions_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/projects_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/resource_tagger.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/schedules_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/server_info_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/sites_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/subscriptions_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/tables_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/users_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/views_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/webhooks_endpoint.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/exceptions.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/filter.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/pager.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/query.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/server.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/sort.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient.egg-info/dependency_links.txt +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient.egg-info/top_level.txt +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/__init__.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/_utils.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/Data/Tableau Samples/World Indicators.tde +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/Data/user_details.csv +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/Data/usernames.csv +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/RESTAPISample Image.png +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/Sample View Image.png +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/World Indicators.hyper +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/auth_sign_in.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/auth_sign_in_error.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/auth_sign_in_impersonate.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/custom_view_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/custom_view_get_id.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/custom_view_update.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/data_acceleration_report.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/data_alerts_add_user.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/data_alerts_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/data_alerts_get_by_id.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/data_alerts_update.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/database_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/database_populate_permissions.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/database_update.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_add_tags.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_connection_update.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_data_update.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_get_by_id.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_get_empty.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_populate_connections.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_populate_permissions.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_publish.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_publish_async.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_refresh.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_revision.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_update.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/dqw_by_content_type.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/favorites_add_datasource.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/favorites_add_project.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/favorites_add_view.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/favorites_add_workbook.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/favorites_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/fileupload_append.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/fileupload_initialize.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_get_by_id.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_populate_connections.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_populate_permissions.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_publish.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_refresh.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_runs_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_runs_get_by_id.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_runs_get_by_id_failed.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_runs_get_by_id_inprogress.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_update.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_add_user.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_create.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_create_ad.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_create_async.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_populate_users.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_populate_users_empty.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_update.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_update_async.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_users_added.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/job_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/job_get_by_id.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/job_get_by_id_failed.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/job_get_by_id_failed_workbook.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/job_get_by_id_inprogress.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metadata_paged_1.json +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metadata_paged_2.json +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metadata_paged_3.json +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metadata_query_error.json +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metadata_query_expected_dict.dict +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metadata_query_success.json +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metrics_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metrics_get_by_id.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metrics_update.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/populate_csv.csv +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/populate_pdf.pdf +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/project_content_permission.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/project_create.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/project_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/project_populate_permissions.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/project_populate_workbook_default_permissions.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/project_update.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/project_update_datasource_default_permissions.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/queryset_slicing_page_1.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/queryset_slicing_page_2.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/request_option_filter_equals.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/request_option_filter_name_in.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/request_option_filter_tags_in.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/request_option_page_number.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/request_option_page_size.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/request_option_pagination.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/request_option_slicing_queryset.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_add_datasource.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_add_flow.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_add_workbook.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_add_workbook_with_warnings.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_create_daily.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_create_hourly.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_create_monthly.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_create_weekly.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_get_by_id.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_get_empty.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_update.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/server_info_25.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/server_info_404.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/server_info_auth_info.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/server_info_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/site_create.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/site_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/site_get_by_id.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/site_get_by_name.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/site_update.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/subscription_create.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/subscription_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/subscription_get_by_id.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/table_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/table_update.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/tasks_create_extract_task.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/tasks_no_workbook_or_datasource.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/tasks_run_now_response.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/tasks_with_dataacceleration_task.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/tasks_with_datasource.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/tasks_with_workbook.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/tasks_with_workbook_and_datasource.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/user_add.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/user_add_favorite.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/user_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/user_get_by_id.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/user_get_empty.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/user_populate_groups.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/user_populate_workbooks.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/user_update.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/view_add_tags.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/view_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/view_get_id.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/view_get_usage.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/view_populate_permissions.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/view_update_permissions.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/webhook_create.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/webhook_create_request.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/webhook_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_add_tags.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_get.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_get_by_id.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_get_by_id_personal.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_get_empty.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_get_invalid_date.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_get_page_1.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_get_page_2.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_get_page_3.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_populate_connections.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_populate_permissions.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_populate_views.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_populate_views_usage.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_publish.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_publish_async.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_refresh.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_revision.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_update.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_update_permissions.xml +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/http/test_http_requests.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/models/_models.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/models/test_repr.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/request_factory/__init__.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/request_factory/test_datasource_requests.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/request_factory/test_workbook_requests.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_auth.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_connection_.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_custom_view.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_data_acceleration_report.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_dataalert.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_database.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_datasource_model.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_dqw.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_exponential_backoff.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_favorites.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_filesys_helpers.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_fileuploads.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_filter.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_flowruns.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_group.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_group_model.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_job.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_metadata.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_metrics.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_pager.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_project.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_project_model.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_regression_tests.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_request_option.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_requests.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_server_info.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_site.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_site_model.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_sort.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_subscription.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_table.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_tableauauth_model.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_user.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_user_model.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_view.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_webhook.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_workbook_model.py +0 -0
- {tableauserverclient-0.28 → tableauserverclient-0.30}/versioneer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: tableauserverclient
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.30
|
|
4
4
|
Summary: A Python module for working with the Tableau Server REST API.
|
|
5
5
|
Author-email: Tableau <github@tableau.com>
|
|
6
6
|
License: The MIT License (MIT)
|
|
@@ -40,7 +40,7 @@ License-File: LICENSE.versioneer
|
|
|
40
40
|
Requires-Dist: defusedxml>=0.7.1
|
|
41
41
|
Requires-Dist: packaging>=23.1
|
|
42
42
|
Requires-Dist: requests>=2.31
|
|
43
|
-
Requires-Dist: urllib3==2.0.
|
|
43
|
+
Requires-Dist: urllib3==2.0.7
|
|
44
44
|
Provides-Extra: test
|
|
45
45
|
Requires-Dist: argparse; extra == "test"
|
|
46
46
|
Requires-Dist: black==23.7; extra == "test"
|
|
@@ -10,8 +10,7 @@ Contribution can include, but are not limited to, any of the following:
|
|
|
10
10
|
* Fix an Issue/Bug
|
|
11
11
|
* Add/Fix documentation
|
|
12
12
|
|
|
13
|
-
Contributions must follow the guidelines outlined on the [Tableau Organization](http://tableau.github.io/) page, though filing an issue or requesting
|
|
14
|
-
a feature do not require the CLA.
|
|
13
|
+
Contributions must follow the guidelines outlined on the [Tableau Organization](http://tableau.github.io/) page, though filing an issue or requesting a feature do not require the CLA.
|
|
15
14
|
|
|
16
15
|
## Issues and Feature Requests
|
|
17
16
|
|
|
@@ -15,7 +15,7 @@ dependencies = [
|
|
|
15
15
|
'defusedxml>=0.7.1', # latest as at 7/31/23
|
|
16
16
|
'packaging>=23.1', # latest as at 7/31/23
|
|
17
17
|
'requests>=2.31', # latest as at 7/31/23
|
|
18
|
-
'urllib3==2.0.
|
|
18
|
+
'urllib3==2.0.7', # latest as at 7/31/23
|
|
19
19
|
]
|
|
20
20
|
requires-python = ">=3.7"
|
|
21
21
|
classifiers = [
|
{tableauserverclient-0.28 → tableauserverclient-0.30}/samples/getting_started/3_hello_universe.py
RENAMED
|
@@ -62,11 +62,6 @@ def main():
|
|
|
62
62
|
print("{} jobs".format(pagination.total_available))
|
|
63
63
|
print(jobs[0])
|
|
64
64
|
|
|
65
|
-
metrics, pagination = server.metrics.get()
|
|
66
|
-
if metrics:
|
|
67
|
-
print("{} metrics".format(pagination.total_available))
|
|
68
|
-
print(metrics[0])
|
|
69
|
-
|
|
70
65
|
schedules, pagination = server.schedules.get()
|
|
71
66
|
if schedules:
|
|
72
67
|
print("{} schedules".format(pagination.total_available))
|
|
@@ -82,7 +77,7 @@ def main():
|
|
|
82
77
|
print("{} webhooks".format(pagination.total_available))
|
|
83
78
|
print(webhooks[0])
|
|
84
79
|
|
|
85
|
-
users, pagination = server.
|
|
80
|
+
users, pagination = server.users.get()
|
|
86
81
|
if users:
|
|
87
82
|
print("{} users".format(pagination.total_available))
|
|
88
83
|
print(users[0])
|
|
@@ -92,5 +87,6 @@ def main():
|
|
|
92
87
|
print("{} groups".format(pagination.total_available))
|
|
93
88
|
print(groups[0])
|
|
94
89
|
|
|
95
|
-
|
|
96
|
-
|
|
90
|
+
|
|
91
|
+
if __name__ == "__main__":
|
|
92
|
+
main()
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "
|
|
11
|
+
"date": "2024-01-19T11:30:24-0800",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "0.
|
|
14
|
+
"full-revisionid": "f84d7d5302344f0a4ac369c501b122931ae7e79e",
|
|
15
|
+
"version": "0.30"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -7,7 +7,7 @@ BYTES_PER_MB = 1024 * 1024
|
|
|
7
7
|
# For when a datasource is over 64MB, break it into 5MB(standard chunk size) chunks
|
|
8
8
|
CHUNK_SIZE_MB = 5 * 10 # 5MB felt too slow, upped it to 50
|
|
9
9
|
|
|
10
|
-
DELAY_SLEEP_SECONDS =
|
|
10
|
+
DELAY_SLEEP_SECONDS = 0.1
|
|
11
11
|
|
|
12
12
|
# The maximum size of a file that can be published in a single request is 64MB
|
|
13
13
|
FILESIZE_LIMIT_MB = 64
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from copy import deepcopy
|
|
2
|
+
from urllib.parse import unquote_plus
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def fix_filename(params):
|
|
6
|
+
if "filename*" not in params:
|
|
7
|
+
return params
|
|
8
|
+
|
|
9
|
+
params = deepcopy(params)
|
|
10
|
+
filename = params["filename*"]
|
|
11
|
+
prefix = "UTF-8''"
|
|
12
|
+
if filename.startswith(prefix):
|
|
13
|
+
filename = filename[len(prefix) :]
|
|
14
|
+
|
|
15
|
+
params["filename"] = unquote_plus(filename)
|
|
16
|
+
del params["filename*"]
|
|
17
|
+
return params
|
{tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/helpers/strings.py
RENAMED
|
@@ -9,8 +9,6 @@ from typing import TypeVar
|
|
|
9
9
|
T = TypeVar("T", str, bytes)
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
# usage: _redact_any_type("<xml workbook password= cooliothesecond>")
|
|
13
|
-
# -> b"<xml workbook password =***************">
|
|
14
12
|
def _redact_any_type(xml: T, sensitive_word: T, replacement: T, encoding=None) -> T:
|
|
15
13
|
try:
|
|
16
14
|
root = fromstring(xml)
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
from .property_decorators import property_is_valid_time, property_not_nullable
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class IntervalItem(object):
|
|
5
|
+
class Frequency:
|
|
6
|
+
Hourly = "Hourly"
|
|
7
|
+
Daily = "Daily"
|
|
8
|
+
Weekly = "Weekly"
|
|
9
|
+
Monthly = "Monthly"
|
|
10
|
+
|
|
11
|
+
class Occurrence:
|
|
12
|
+
Minutes = "minutes"
|
|
13
|
+
Hours = "hours"
|
|
14
|
+
WeekDay = "weekDay"
|
|
15
|
+
MonthDay = "monthDay"
|
|
16
|
+
|
|
17
|
+
class Day:
|
|
18
|
+
Sunday = "Sunday"
|
|
19
|
+
Monday = "Monday"
|
|
20
|
+
Tuesday = "Tuesday"
|
|
21
|
+
Wednesday = "Wednesday"
|
|
22
|
+
Thursday = "Thursday"
|
|
23
|
+
Friday = "Friday"
|
|
24
|
+
Saturday = "Saturday"
|
|
25
|
+
LastDay = "LastDay"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class HourlyInterval(object):
|
|
29
|
+
def __init__(self, start_time, end_time, interval_value):
|
|
30
|
+
self.start_time = start_time
|
|
31
|
+
self.end_time = end_time
|
|
32
|
+
|
|
33
|
+
# interval should be a tuple, if it is not, assign as a tuple with single value
|
|
34
|
+
if isinstance(interval_value, tuple):
|
|
35
|
+
self.interval = interval_value
|
|
36
|
+
else:
|
|
37
|
+
self.interval = (interval_value,)
|
|
38
|
+
|
|
39
|
+
def __repr__(self):
|
|
40
|
+
return f"<{self.__class__.__name__} start={self.start_time} end={self.end_time} interval={self.interval}>"
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def _frequency(self):
|
|
44
|
+
return IntervalItem.Frequency.Hourly
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def start_time(self):
|
|
48
|
+
return self._start_time
|
|
49
|
+
|
|
50
|
+
@start_time.setter
|
|
51
|
+
@property_is_valid_time
|
|
52
|
+
@property_not_nullable
|
|
53
|
+
def start_time(self, value):
|
|
54
|
+
self._start_time = value
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def end_time(self):
|
|
58
|
+
return self._end_time
|
|
59
|
+
|
|
60
|
+
@end_time.setter
|
|
61
|
+
@property_is_valid_time
|
|
62
|
+
@property_not_nullable
|
|
63
|
+
def end_time(self, value):
|
|
64
|
+
self._end_time = value
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def interval(self):
|
|
68
|
+
return self._interval
|
|
69
|
+
|
|
70
|
+
@interval.setter
|
|
71
|
+
def interval(self, intervals):
|
|
72
|
+
VALID_INTERVALS = {0.25, 0.5, 1, 2, 4, 6, 8, 12, 24}
|
|
73
|
+
for interval in intervals:
|
|
74
|
+
# if an hourly interval is a string, then it is a weekDay interval
|
|
75
|
+
if isinstance(interval, str) and not interval.isnumeric() and not hasattr(IntervalItem.Day, interval):
|
|
76
|
+
error = "Invalid weekDay interval {}".format(interval)
|
|
77
|
+
raise ValueError(error)
|
|
78
|
+
|
|
79
|
+
# if an hourly interval is a number, it is an hours or minutes interval
|
|
80
|
+
if isinstance(interval, (int, float)) and float(interval) not in VALID_INTERVALS:
|
|
81
|
+
error = "Invalid interval {} not in {}".format(interval, str(VALID_INTERVALS))
|
|
82
|
+
raise ValueError(error)
|
|
83
|
+
|
|
84
|
+
self._interval = intervals
|
|
85
|
+
|
|
86
|
+
def _interval_type_pairs(self):
|
|
87
|
+
interval_type_pairs = []
|
|
88
|
+
for interval in self.interval:
|
|
89
|
+
# We use fractional hours for the two minute-based intervals.
|
|
90
|
+
# Need to convert to minutes from hours here
|
|
91
|
+
if interval in {0.25, 0.5}:
|
|
92
|
+
calculated_interval = int(interval * 60)
|
|
93
|
+
interval_type = IntervalItem.Occurrence.Minutes
|
|
94
|
+
|
|
95
|
+
interval_type_pairs.append((interval_type, str(calculated_interval)))
|
|
96
|
+
else:
|
|
97
|
+
# if the interval is a non-numeric string, it will always be a weekDay
|
|
98
|
+
if isinstance(interval, str) and not interval.isnumeric():
|
|
99
|
+
interval_type = IntervalItem.Occurrence.WeekDay
|
|
100
|
+
|
|
101
|
+
interval_type_pairs.append((interval_type, str(interval)))
|
|
102
|
+
# otherwise the interval is hours
|
|
103
|
+
else:
|
|
104
|
+
interval_type = IntervalItem.Occurrence.Hours
|
|
105
|
+
|
|
106
|
+
interval_type_pairs.append((interval_type, str(interval)))
|
|
107
|
+
|
|
108
|
+
return interval_type_pairs
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class DailyInterval(object):
|
|
112
|
+
def __init__(self, start_time, *interval_values):
|
|
113
|
+
self.start_time = start_time
|
|
114
|
+
self.interval = interval_values
|
|
115
|
+
|
|
116
|
+
def __repr__(self):
|
|
117
|
+
return f"<{self.__class__.__name__} start={self.start_time} interval={self.interval}>"
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def _frequency(self):
|
|
121
|
+
return IntervalItem.Frequency.Daily
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def start_time(self):
|
|
125
|
+
return self._start_time
|
|
126
|
+
|
|
127
|
+
@start_time.setter
|
|
128
|
+
@property_is_valid_time
|
|
129
|
+
@property_not_nullable
|
|
130
|
+
def start_time(self, value):
|
|
131
|
+
self._start_time = value
|
|
132
|
+
|
|
133
|
+
@property
|
|
134
|
+
def interval(self):
|
|
135
|
+
return self._interval
|
|
136
|
+
|
|
137
|
+
@interval.setter
|
|
138
|
+
def interval(self, intervals):
|
|
139
|
+
VALID_INTERVALS = {0.25, 0.5, 1, 2, 4, 6, 8, 12}
|
|
140
|
+
|
|
141
|
+
for interval in intervals:
|
|
142
|
+
# if an hourly interval is a string, then it is a weekDay interval
|
|
143
|
+
if isinstance(interval, str) and not interval.isnumeric() and not hasattr(IntervalItem.Day, interval):
|
|
144
|
+
error = "Invalid weekDay interval {}".format(interval)
|
|
145
|
+
raise ValueError(error)
|
|
146
|
+
|
|
147
|
+
# if an hourly interval is a number, it is an hours or minutes interval
|
|
148
|
+
if isinstance(interval, (int, float)) and float(interval) not in VALID_INTERVALS:
|
|
149
|
+
error = "Invalid interval {} not in {}".format(interval, str(VALID_INTERVALS))
|
|
150
|
+
raise ValueError(error)
|
|
151
|
+
|
|
152
|
+
self._interval = intervals
|
|
153
|
+
|
|
154
|
+
def _interval_type_pairs(self):
|
|
155
|
+
interval_type_pairs = []
|
|
156
|
+
for interval in self.interval:
|
|
157
|
+
# We use fractional hours for the two minute-based intervals.
|
|
158
|
+
# Need to convert to minutes from hours here
|
|
159
|
+
if interval in {0.25, 0.5}:
|
|
160
|
+
calculated_interval = int(interval * 60)
|
|
161
|
+
interval_type = IntervalItem.Occurrence.Minutes
|
|
162
|
+
|
|
163
|
+
interval_type_pairs.append((interval_type, str(calculated_interval)))
|
|
164
|
+
else:
|
|
165
|
+
# if the interval is a non-numeric string, it will always be a weekDay
|
|
166
|
+
if isinstance(interval, str) and not interval.isnumeric():
|
|
167
|
+
interval_type = IntervalItem.Occurrence.WeekDay
|
|
168
|
+
|
|
169
|
+
interval_type_pairs.append((interval_type, str(interval)))
|
|
170
|
+
# otherwise the interval is hours
|
|
171
|
+
else:
|
|
172
|
+
interval_type = IntervalItem.Occurrence.Hours
|
|
173
|
+
|
|
174
|
+
interval_type_pairs.append((interval_type, str(interval)))
|
|
175
|
+
|
|
176
|
+
return interval_type_pairs
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class WeeklyInterval(object):
|
|
180
|
+
def __init__(self, start_time, *interval_values):
|
|
181
|
+
self.start_time = start_time
|
|
182
|
+
self.interval = interval_values
|
|
183
|
+
|
|
184
|
+
def __repr__(self):
|
|
185
|
+
return f"<{self.__class__.__name__} start={self.start_time} interval={self.interval}>"
|
|
186
|
+
|
|
187
|
+
@property
|
|
188
|
+
def _frequency(self):
|
|
189
|
+
return IntervalItem.Frequency.Weekly
|
|
190
|
+
|
|
191
|
+
@property
|
|
192
|
+
def start_time(self):
|
|
193
|
+
return self._start_time
|
|
194
|
+
|
|
195
|
+
@start_time.setter
|
|
196
|
+
@property_is_valid_time
|
|
197
|
+
@property_not_nullable
|
|
198
|
+
def start_time(self, value):
|
|
199
|
+
self._start_time = value
|
|
200
|
+
|
|
201
|
+
@property
|
|
202
|
+
def interval(self):
|
|
203
|
+
return self._interval
|
|
204
|
+
|
|
205
|
+
@interval.setter
|
|
206
|
+
def interval(self, interval_values):
|
|
207
|
+
if not all(hasattr(IntervalItem.Day, day) for day in interval_values):
|
|
208
|
+
raise ValueError("Invalid week day defined " + str(interval_values))
|
|
209
|
+
|
|
210
|
+
self._interval = interval_values
|
|
211
|
+
|
|
212
|
+
def _interval_type_pairs(self):
|
|
213
|
+
return [(IntervalItem.Occurrence.WeekDay, day) for day in self.interval]
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
class MonthlyInterval(object):
|
|
217
|
+
def __init__(self, start_time, interval_value):
|
|
218
|
+
self.start_time = start_time
|
|
219
|
+
|
|
220
|
+
# interval should be a tuple, if it is not, assign as a tuple with single value
|
|
221
|
+
if isinstance(interval_value, tuple):
|
|
222
|
+
self.interval = interval_value
|
|
223
|
+
else:
|
|
224
|
+
self.interval = (interval_value,)
|
|
225
|
+
|
|
226
|
+
def __repr__(self):
|
|
227
|
+
return f"<{self.__class__.__name__} start={self.start_time} interval={self.interval}>"
|
|
228
|
+
|
|
229
|
+
@property
|
|
230
|
+
def _frequency(self):
|
|
231
|
+
return IntervalItem.Frequency.Monthly
|
|
232
|
+
|
|
233
|
+
@property
|
|
234
|
+
def start_time(self):
|
|
235
|
+
return self._start_time
|
|
236
|
+
|
|
237
|
+
@start_time.setter
|
|
238
|
+
@property_is_valid_time
|
|
239
|
+
@property_not_nullable
|
|
240
|
+
def start_time(self, value):
|
|
241
|
+
self._start_time = value
|
|
242
|
+
|
|
243
|
+
@property
|
|
244
|
+
def interval(self):
|
|
245
|
+
return self._interval
|
|
246
|
+
|
|
247
|
+
@interval.setter
|
|
248
|
+
def interval(self, interval_values):
|
|
249
|
+
# This is weird because the value could be a str or an int
|
|
250
|
+
# The only valid str is 'LastDay' so we check that first. If that's not it
|
|
251
|
+
# try to convert it to an int, if that fails because it's an incorrect string
|
|
252
|
+
# like 'badstring' we catch and re-raise. Otherwise we convert to int and check
|
|
253
|
+
# that it's in range 1-31
|
|
254
|
+
for interval_value in interval_values:
|
|
255
|
+
error = "Invalid interval value for a monthly frequency: {}.".format(interval_value)
|
|
256
|
+
|
|
257
|
+
if interval_value != "LastDay":
|
|
258
|
+
try:
|
|
259
|
+
if not (1 <= int(interval_value) <= 31):
|
|
260
|
+
raise ValueError(error)
|
|
261
|
+
except ValueError:
|
|
262
|
+
if interval_value != "LastDay":
|
|
263
|
+
raise ValueError(error)
|
|
264
|
+
|
|
265
|
+
self._interval = interval_values
|
|
266
|
+
|
|
267
|
+
def _interval_type_pairs(self):
|
|
268
|
+
return [(IntervalItem.Occurrence.MonthDay, self.interval)]
|
{tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/project_item.py
RENAMED
|
@@ -163,9 +163,6 @@ class ProjectItem(object):
|
|
|
163
163
|
attr,
|
|
164
164
|
permissions,
|
|
165
165
|
)
|
|
166
|
-
fetch_call = getattr(self, attr)
|
|
167
|
-
logging.getLogger().info({"type": attr, "value": fetch_call()})
|
|
168
|
-
return fetch_call()
|
|
169
166
|
|
|
170
167
|
@classmethod
|
|
171
168
|
def from_response(cls, resp, ns) -> List["ProjectItem"]:
|
{tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/schedule_item.py
RENAMED
|
@@ -254,25 +254,43 @@ class ScheduleItem(object):
|
|
|
254
254
|
interval.extend(interval_elem.attrib.items())
|
|
255
255
|
|
|
256
256
|
if frequency == IntervalItem.Frequency.Daily:
|
|
257
|
-
|
|
257
|
+
converted_intervals = []
|
|
258
|
+
|
|
259
|
+
for i in interval:
|
|
260
|
+
# We use fractional hours for the two minute-based intervals.
|
|
261
|
+
# Need to convert to hours from minutes here
|
|
262
|
+
if i[0] == IntervalItem.Occurrence.Minutes:
|
|
263
|
+
converted_intervals.append(float(i[1]) / 60)
|
|
264
|
+
elif i[0] == IntervalItem.Occurrence.Hours:
|
|
265
|
+
converted_intervals.append(float(i[1]))
|
|
266
|
+
else:
|
|
267
|
+
converted_intervals.append(i[1])
|
|
268
|
+
|
|
269
|
+
return DailyInterval(start_time, *converted_intervals)
|
|
258
270
|
|
|
259
271
|
if frequency == IntervalItem.Frequency.Hourly:
|
|
260
|
-
|
|
272
|
+
converted_intervals = []
|
|
261
273
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
274
|
+
for i in interval:
|
|
275
|
+
# We use fractional hours for the two minute-based intervals.
|
|
276
|
+
# Need to convert to hours from minutes here
|
|
277
|
+
if i[0] == IntervalItem.Occurrence.Minutes:
|
|
278
|
+
converted_intervals.append(float(i[1]) / 60)
|
|
279
|
+
elif i[0] == IntervalItem.Occurrence.Hours:
|
|
280
|
+
converted_intervals.append(i[1])
|
|
281
|
+
else:
|
|
282
|
+
converted_intervals.append(i[1])
|
|
266
283
|
|
|
267
|
-
return HourlyInterval(start_time, end_time,
|
|
284
|
+
return HourlyInterval(start_time, end_time, tuple(converted_intervals))
|
|
268
285
|
|
|
269
286
|
if frequency == IntervalItem.Frequency.Weekly:
|
|
270
287
|
interval_values = [i[1] for i in interval]
|
|
271
288
|
return WeeklyInterval(start_time, *interval_values)
|
|
272
289
|
|
|
273
290
|
if frequency == IntervalItem.Frequency.Monthly:
|
|
274
|
-
|
|
275
|
-
|
|
291
|
+
interval_values = [i[1] for i in interval]
|
|
292
|
+
|
|
293
|
+
return MonthlyInterval(start_time, tuple(interval_values))
|
|
276
294
|
|
|
277
295
|
@staticmethod
|
|
278
296
|
def _parse_element(schedule_xml, ns):
|
{tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/task_item.py
RENAMED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import List, Optional
|
|
3
|
+
|
|
1
4
|
from defusedxml.ElementTree import fromstring
|
|
2
5
|
|
|
3
6
|
from tableauserverclient.datetime_helpers import parse_datetime
|
|
4
|
-
from .schedule_item import ScheduleItem
|
|
5
|
-
from .target import Target
|
|
7
|
+
from tableauserverclient.models.schedule_item import ScheduleItem
|
|
8
|
+
from tableauserverclient.models.target import Target
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
class TaskItem(object):
|
|
@@ -19,14 +22,14 @@ class TaskItem(object):
|
|
|
19
22
|
|
|
20
23
|
def __init__(
|
|
21
24
|
self,
|
|
22
|
-
id_,
|
|
23
|
-
task_type,
|
|
24
|
-
priority,
|
|
25
|
-
consecutive_failed_count=0,
|
|
26
|
-
schedule_id=None,
|
|
27
|
-
schedule_item=None,
|
|
28
|
-
last_run_at=None,
|
|
29
|
-
target=None,
|
|
25
|
+
id_: str,
|
|
26
|
+
task_type: str,
|
|
27
|
+
priority: int,
|
|
28
|
+
consecutive_failed_count: int = 0,
|
|
29
|
+
schedule_id: Optional[str] = None,
|
|
30
|
+
schedule_item: Optional[ScheduleItem] = None,
|
|
31
|
+
last_run_at: Optional[datetime] = None,
|
|
32
|
+
target: Optional[Target] = None,
|
|
30
33
|
):
|
|
31
34
|
self.id = id_
|
|
32
35
|
self.task_type = task_type
|
|
@@ -37,14 +40,14 @@ class TaskItem(object):
|
|
|
37
40
|
self.last_run_at = last_run_at
|
|
38
41
|
self.target = target
|
|
39
42
|
|
|
40
|
-
def __repr__(self):
|
|
43
|
+
def __repr__(self) -> str:
|
|
41
44
|
return (
|
|
42
45
|
"<Task#{id} {task_type} pri({priority}) failed({consecutive_failed_count}) schedule_id({"
|
|
43
46
|
"schedule_id}) target({target})>".format(**self.__dict__)
|
|
44
47
|
)
|
|
45
48
|
|
|
46
49
|
@classmethod
|
|
47
|
-
def from_response(cls, xml, ns, task_type=Type.ExtractRefresh):
|
|
50
|
+
def from_response(cls, xml, ns, task_type=Type.ExtractRefresh) -> List["TaskItem"]:
|
|
48
51
|
parsed_response = fromstring(xml)
|
|
49
52
|
all_tasks_xml = parsed_response.findall(".//t:task/t:{}".format(task_type), namespaces=ns)
|
|
50
53
|
|
|
@@ -62,8 +65,7 @@ class TaskItem(object):
|
|
|
62
65
|
last_run_at_element = element.find(".//t:lastRunAt", namespaces=ns)
|
|
63
66
|
|
|
64
67
|
schedule_item_list = ScheduleItem.from_element(element, ns)
|
|
65
|
-
|
|
66
|
-
schedule_item = schedule_item_list[0]
|
|
68
|
+
schedule_item = next(iter(schedule_item_list), None)
|
|
67
69
|
|
|
68
70
|
# according to the Tableau Server REST API documentation,
|
|
69
71
|
# there should be only one of workbook or datasource
|
|
@@ -87,14 +89,14 @@ class TaskItem(object):
|
|
|
87
89
|
task_type,
|
|
88
90
|
priority,
|
|
89
91
|
consecutive_failed_count,
|
|
90
|
-
schedule_item.id,
|
|
92
|
+
schedule_item.id if schedule_item is not None else None,
|
|
91
93
|
schedule_item,
|
|
92
94
|
last_run_at,
|
|
93
95
|
target,
|
|
94
96
|
)
|
|
95
97
|
|
|
96
98
|
@staticmethod
|
|
97
|
-
def _translate_task_type(task_type):
|
|
99
|
+
def _translate_task_type(task_type: str) -> str:
|
|
98
100
|
if task_type in TaskItem._TASK_TYPE_MAPPING:
|
|
99
101
|
return TaskItem._TASK_TYPE_MAPPING[task_type]
|
|
100
102
|
else:
|
|
@@ -8,6 +8,8 @@ from contextlib import closing
|
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
from typing import List, Mapping, Optional, Sequence, Tuple, TYPE_CHECKING, Union
|
|
10
10
|
|
|
11
|
+
from tableauserverclient.helpers.headers import fix_filename
|
|
12
|
+
|
|
11
13
|
if TYPE_CHECKING:
|
|
12
14
|
from tableauserverclient.server import Server
|
|
13
15
|
from tableauserverclient.models import PermissionsRule
|
|
@@ -441,6 +443,7 @@ class Datasources(QuerysetEndpoint):
|
|
|
441
443
|
filepath.write(chunk)
|
|
442
444
|
return_path = filepath
|
|
443
445
|
else:
|
|
446
|
+
params = fix_filename(params)
|
|
444
447
|
filename = to_filename(os.path.basename(params["filename"]))
|
|
445
448
|
download_path = make_download_path(filepath, filename)
|
|
446
449
|
with open(download_path, "wb") as f:
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
from threading import Thread
|
|
2
|
-
from time import sleep
|
|
3
1
|
from tableauserverclient import datetime_helpers as datetime
|
|
4
2
|
|
|
5
|
-
import requests
|
|
6
3
|
from packaging.version import Version
|
|
7
4
|
from functools import wraps
|
|
8
5
|
from xml.etree.ElementTree import ParseError
|
|
@@ -76,58 +73,21 @@ class Endpoint(object):
|
|
|
76
73
|
# return explicitly for testing only
|
|
77
74
|
return parameters
|
|
78
75
|
|
|
79
|
-
def _blocking_request(self, method, url, parameters={}) -> Optional["Response"]:
|
|
80
|
-
self.async_response = None
|
|
76
|
+
def _blocking_request(self, method, url, parameters={}) -> Optional[Union["Response", Exception]]:
|
|
81
77
|
response = None
|
|
82
78
|
logger.debug("[{}] Begin blocking request to {}".format(datetime.timestamp(), url))
|
|
83
79
|
try:
|
|
84
80
|
response = method(url, **parameters)
|
|
85
|
-
self.async_response = response
|
|
86
81
|
logger.debug("[{}] Call finished".format(datetime.timestamp()))
|
|
87
82
|
except Exception as e:
|
|
88
83
|
logger.debug("Error making request to server: {}".format(e))
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if response and not self.async_response:
|
|
92
|
-
logger.debug("Request response not saved")
|
|
93
|
-
return None
|
|
94
|
-
logger.debug("[{}] Request complete".format(datetime.timestamp()))
|
|
95
|
-
return self.async_response
|
|
84
|
+
raise e
|
|
85
|
+
return response
|
|
96
86
|
|
|
97
87
|
def send_request_while_show_progress_threaded(
|
|
98
|
-
self, method, url, parameters={}, request_timeout=
|
|
99
|
-
) -> Optional["Response"]:
|
|
100
|
-
|
|
101
|
-
request_thread = Thread(target=self._blocking_request, args=(method, url, parameters))
|
|
102
|
-
request_thread.async_response = -1 # type:ignore # this is an invented attribute for thread comms
|
|
103
|
-
request_thread.start()
|
|
104
|
-
except Exception as e:
|
|
105
|
-
logger.debug("Error starting server request on separate thread: {}".format(e))
|
|
106
|
-
return None
|
|
107
|
-
seconds = 0
|
|
108
|
-
minutes = 0
|
|
109
|
-
sleep(1)
|
|
110
|
-
if self.async_response != -1:
|
|
111
|
-
# a quick return for any immediate responses
|
|
112
|
-
return self.async_response
|
|
113
|
-
while self.async_response == -1 and (request_timeout == 0 or seconds < request_timeout):
|
|
114
|
-
self.log_wait_time_then_sleep(minutes, seconds, url)
|
|
115
|
-
seconds = seconds + DELAY_SLEEP_SECONDS
|
|
116
|
-
if seconds >= 60:
|
|
117
|
-
seconds = 0
|
|
118
|
-
minutes = minutes + 1
|
|
119
|
-
return self.async_response
|
|
120
|
-
|
|
121
|
-
def log_wait_time_then_sleep(self, minutes, seconds, url):
|
|
122
|
-
logger.debug("{} Waiting....".format(datetime.timestamp()))
|
|
123
|
-
if seconds >= 60: # detailed log message ~every minute
|
|
124
|
-
if minutes % 5 == 0:
|
|
125
|
-
logger.info(
|
|
126
|
-
"[{}] Waiting ({} minutes so far) for request to {}".format(datetime.timestamp(), minutes, url)
|
|
127
|
-
)
|
|
128
|
-
else:
|
|
129
|
-
logger.debug("[{}] Waiting for request to {}".format(datetime.timestamp(), url))
|
|
130
|
-
sleep(DELAY_SLEEP_SECONDS)
|
|
88
|
+
self, method, url, parameters={}, request_timeout=None
|
|
89
|
+
) -> Optional[Union["Response", Exception]]:
|
|
90
|
+
return self._blocking_request(method, url, parameters)
|
|
131
91
|
|
|
132
92
|
def _make_request(
|
|
133
93
|
self,
|
|
@@ -151,7 +111,7 @@ class Endpoint(object):
|
|
|
151
111
|
# a request can, for stuff like publishing, spin for ages waiting for a response.
|
|
152
112
|
# we need some user-facing activity so they know it's not dead.
|
|
153
113
|
request_timeout = self.parent_srv.http_options.get("timeout") or 0
|
|
154
|
-
server_response: Optional["Response"] = self.send_request_while_show_progress_threaded(
|
|
114
|
+
server_response: Optional[Union["Response", Exception]] = self.send_request_while_show_progress_threaded(
|
|
155
115
|
method, url, parameters, request_timeout
|
|
156
116
|
)
|
|
157
117
|
logger.debug("[{}] Async request returned: received {}".format(datetime.timestamp(), server_response))
|
|
@@ -163,6 +123,8 @@ class Endpoint(object):
|
|
|
163
123
|
if server_response is None:
|
|
164
124
|
logger.debug("[{}] Request failed".format(datetime.timestamp()))
|
|
165
125
|
raise RuntimeError
|
|
126
|
+
if isinstance(server_response, Exception):
|
|
127
|
+
raise server_response
|
|
166
128
|
self._check_status(server_response, url)
|
|
167
129
|
|
|
168
130
|
loggable_response = self.log_response_safely(server_response)
|
|
@@ -7,6 +7,8 @@ from contextlib import closing
|
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
from typing import Iterable, List, Optional, TYPE_CHECKING, Tuple, Union
|
|
9
9
|
|
|
10
|
+
from tableauserverclient.helpers.headers import fix_filename
|
|
11
|
+
|
|
10
12
|
from .dqw_endpoint import _DataQualityWarningEndpoint
|
|
11
13
|
from .endpoint import QuerysetEndpoint, api
|
|
12
14
|
from .exceptions import InternalServerError, MissingRequiredFieldError
|
|
@@ -124,6 +126,7 @@ class Flows(QuerysetEndpoint):
|
|
|
124
126
|
filepath.write(chunk)
|
|
125
127
|
return_path = filepath
|
|
126
128
|
else:
|
|
129
|
+
params = fix_filename(params)
|
|
127
130
|
filename = to_filename(os.path.basename(params["filename"]))
|
|
128
131
|
download_path = make_download_path(filepath, filename)
|
|
129
132
|
with open(download_path, "wb") as f:
|