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.
Files changed (364) hide show
  1. {tableauserverclient-0.28 → tableauserverclient-0.30}/PKG-INFO +2 -2
  2. {tableauserverclient-0.28 → tableauserverclient-0.30}/contributing.md +1 -2
  3. {tableauserverclient-0.28 → tableauserverclient-0.30}/pyproject.toml +1 -1
  4. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/getting_started/3_hello_universe.py +4 -8
  5. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/_version.py +3 -3
  6. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/config.py +1 -1
  7. tableauserverclient-0.30/tableauserverclient/helpers/headers.py +17 -0
  8. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/helpers/strings.py +0 -2
  9. tableauserverclient-0.30/tableauserverclient/models/interval_item.py +268 -0
  10. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/project_item.py +0 -3
  11. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/schedule_item.py +27 -9
  12. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/task_item.py +18 -16
  13. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/datasources_endpoint.py +3 -0
  14. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/endpoint.py +9 -47
  15. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/flows_endpoint.py +3 -0
  16. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/tasks_endpoint.py +18 -12
  17. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/workbooks_endpoint.py +6 -3
  18. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/request_factory.py +11 -7
  19. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/request_options.py +40 -0
  20. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient.egg-info/PKG-INFO +2 -2
  21. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient.egg-info/SOURCES.txt +5 -0
  22. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient.egg-info/requires.txt +1 -1
  23. tableauserverclient-0.30/test/assets/schedule_get_daily_id.xml +11 -0
  24. tableauserverclient-0.30/test/assets/schedule_get_hourly_id.xml +11 -0
  25. tableauserverclient-0.30/test/assets/schedule_get_monthly_id.xml +11 -0
  26. tableauserverclient-0.30/test/assets/tasks_without_schedule.xml +12 -0
  27. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_datasource.py +11 -0
  28. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_endpoint.py +8 -5
  29. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_flow.py +10 -0
  30. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_schedule.py +50 -2
  31. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_task.py +12 -1
  32. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_workbook.py +9 -0
  33. tableauserverclient-0.28/tableauserverclient/models/interval_item.py +0 -202
  34. {tableauserverclient-0.28 → tableauserverclient-0.30}/CHANGELOG.md +0 -0
  35. {tableauserverclient-0.28 → tableauserverclient-0.30}/CONTRIBUTORS.md +0 -0
  36. {tableauserverclient-0.28 → tableauserverclient-0.30}/LICENSE +0 -0
  37. {tableauserverclient-0.28 → tableauserverclient-0.30}/LICENSE.versioneer +0 -0
  38. {tableauserverclient-0.28 → tableauserverclient-0.30}/MANIFEST.in +0 -0
  39. {tableauserverclient-0.28 → tableauserverclient-0.30}/README.md +0 -0
  40. {tableauserverclient-0.28 → tableauserverclient-0.30}/docs/README.md +0 -0
  41. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/add_default_permission.py +0 -0
  42. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/create_extract_task.py +0 -0
  43. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/create_group.py +0 -0
  44. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/create_project.py +0 -0
  45. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/create_schedules.py +0 -0
  46. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/explore_datasource.py +0 -0
  47. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/explore_favorites.py +0 -0
  48. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/explore_site.py +0 -0
  49. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/explore_webhooks.py +0 -0
  50. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/explore_workbook.py +0 -0
  51. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/export.py +0 -0
  52. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/extracts.py +0 -0
  53. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/filter_sort_groups.py +0 -0
  54. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/filter_sort_projects.py +0 -0
  55. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/getting_started/1_hello_server.py +0 -0
  56. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/getting_started/2_hello_site.py +0 -0
  57. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/initialize_server.py +0 -0
  58. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/kill_all_jobs.py +0 -0
  59. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/list.py +0 -0
  60. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/login.py +0 -0
  61. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/metadata_query.py +0 -0
  62. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/move_workbook_projects.py +0 -0
  63. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/move_workbook_sites.py +0 -0
  64. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/name.txt +0 -0
  65. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/pagination_sample.py +0 -0
  66. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/publish_datasource.py +0 -0
  67. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/publish_workbook.py +0 -0
  68. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/query_permissions.py +0 -0
  69. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/refresh.py +0 -0
  70. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/refresh_tasks.py +0 -0
  71. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/set_refresh_schedule.py +0 -0
  72. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/smoke_test.py +0 -0
  73. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/update_connection.py +0 -0
  74. {tableauserverclient-0.28 → tableauserverclient-0.30}/samples/update_datasource_data.py +0 -0
  75. {tableauserverclient-0.28 → tableauserverclient-0.30}/setup.cfg +0 -0
  76. {tableauserverclient-0.28 → tableauserverclient-0.30}/setup.py +0 -0
  77. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/__init__.py +0 -0
  78. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/datetime_helpers.py +0 -0
  79. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/exponential_backoff.py +0 -0
  80. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/filesys_helpers.py +0 -0
  81. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/helpers/__init__.py +0 -0
  82. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/helpers/logging.py +0 -0
  83. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/__init__.py +0 -0
  84. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/column_item.py +0 -0
  85. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/connection_credentials.py +0 -0
  86. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/connection_item.py +0 -0
  87. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/custom_view_item.py +0 -0
  88. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/data_acceleration_report_item.py +0 -0
  89. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/data_alert_item.py +0 -0
  90. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/database_item.py +0 -0
  91. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/datasource_item.py +0 -0
  92. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/dqw_item.py +0 -0
  93. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/exceptions.py +0 -0
  94. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/favorites_item.py +0 -0
  95. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/fileupload_item.py +0 -0
  96. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/flow_item.py +0 -0
  97. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/flow_run_item.py +0 -0
  98. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/group_item.py +0 -0
  99. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/job_item.py +0 -0
  100. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/metric_item.py +0 -0
  101. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/pagination_item.py +0 -0
  102. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/permissions_item.py +0 -0
  103. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/property_decorators.py +0 -0
  104. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/reference_item.py +0 -0
  105. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/revision_item.py +0 -0
  106. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/server_info_item.py +0 -0
  107. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/site_item.py +0 -0
  108. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/subscription_item.py +0 -0
  109. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/table_item.py +0 -0
  110. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/tableau_auth.py +0 -0
  111. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/tableau_types.py +0 -0
  112. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/tag_item.py +0 -0
  113. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/target.py +0 -0
  114. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/user_item.py +0 -0
  115. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/view_item.py +0 -0
  116. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/webhook_item.py +0 -0
  117. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/models/workbook_item.py +0 -0
  118. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/namespace.py +0 -0
  119. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/py.typed +0 -0
  120. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/__init__.py +0 -0
  121. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/__init__.py +0 -0
  122. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/auth_endpoint.py +0 -0
  123. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/custom_views_endpoint.py +0 -0
  124. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/data_acceleration_report_endpoint.py +0 -0
  125. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/data_alert_endpoint.py +0 -0
  126. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/databases_endpoint.py +0 -0
  127. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/default_permissions_endpoint.py +0 -0
  128. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/dqw_endpoint.py +0 -0
  129. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/exceptions.py +0 -0
  130. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/favorites_endpoint.py +0 -0
  131. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/fileuploads_endpoint.py +0 -0
  132. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/flow_runs_endpoint.py +0 -0
  133. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/groups_endpoint.py +0 -0
  134. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/jobs_endpoint.py +0 -0
  135. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/metadata_endpoint.py +0 -0
  136. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/metrics_endpoint.py +0 -0
  137. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/permissions_endpoint.py +0 -0
  138. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/projects_endpoint.py +0 -0
  139. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/resource_tagger.py +0 -0
  140. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/schedules_endpoint.py +0 -0
  141. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/server_info_endpoint.py +0 -0
  142. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/sites_endpoint.py +0 -0
  143. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/subscriptions_endpoint.py +0 -0
  144. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/tables_endpoint.py +0 -0
  145. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/users_endpoint.py +0 -0
  146. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/views_endpoint.py +0 -0
  147. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/endpoint/webhooks_endpoint.py +0 -0
  148. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/exceptions.py +0 -0
  149. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/filter.py +0 -0
  150. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/pager.py +0 -0
  151. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/query.py +0 -0
  152. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/server.py +0 -0
  153. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient/server/sort.py +0 -0
  154. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient.egg-info/dependency_links.txt +0 -0
  155. {tableauserverclient-0.28 → tableauserverclient-0.30}/tableauserverclient.egg-info/top_level.txt +0 -0
  156. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/__init__.py +0 -0
  157. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/_utils.py +0 -0
  158. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/Data/Tableau Samples/World Indicators.tde +0 -0
  159. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/Data/user_details.csv +0 -0
  160. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/Data/usernames.csv +0 -0
  161. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/RESTAPISample Image.png +0 -0
  162. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/Sample View Image.png +0 -0
  163. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/World Indicators.hyper +0 -0
  164. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/auth_sign_in.xml +0 -0
  165. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/auth_sign_in_error.xml +0 -0
  166. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/auth_sign_in_impersonate.xml +0 -0
  167. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/custom_view_get.xml +0 -0
  168. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/custom_view_get_id.xml +0 -0
  169. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/custom_view_update.xml +0 -0
  170. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/data_acceleration_report.xml +0 -0
  171. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/data_alerts_add_user.xml +0 -0
  172. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/data_alerts_get.xml +0 -0
  173. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/data_alerts_get_by_id.xml +0 -0
  174. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/data_alerts_update.xml +0 -0
  175. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/database_get.xml +0 -0
  176. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/database_populate_permissions.xml +0 -0
  177. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/database_update.xml +0 -0
  178. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_add_tags.xml +0 -0
  179. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_connection_update.xml +0 -0
  180. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_data_update.xml +0 -0
  181. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_get.xml +0 -0
  182. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_get_by_id.xml +0 -0
  183. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_get_empty.xml +0 -0
  184. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_populate_connections.xml +0 -0
  185. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_populate_permissions.xml +0 -0
  186. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_publish.xml +0 -0
  187. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_publish_async.xml +0 -0
  188. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_refresh.xml +0 -0
  189. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_revision.xml +0 -0
  190. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/datasource_update.xml +0 -0
  191. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/dqw_by_content_type.xml +0 -0
  192. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/favorites_add_datasource.xml +0 -0
  193. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/favorites_add_project.xml +0 -0
  194. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/favorites_add_view.xml +0 -0
  195. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/favorites_add_workbook.xml +0 -0
  196. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/favorites_get.xml +0 -0
  197. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/fileupload_append.xml +0 -0
  198. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/fileupload_initialize.xml +0 -0
  199. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_get.xml +0 -0
  200. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_get_by_id.xml +0 -0
  201. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_populate_connections.xml +0 -0
  202. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_populate_permissions.xml +0 -0
  203. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_publish.xml +0 -0
  204. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_refresh.xml +0 -0
  205. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_runs_get.xml +0 -0
  206. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_runs_get_by_id.xml +0 -0
  207. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_runs_get_by_id_failed.xml +0 -0
  208. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_runs_get_by_id_inprogress.xml +0 -0
  209. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/flow_update.xml +0 -0
  210. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_add_user.xml +0 -0
  211. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_create.xml +0 -0
  212. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_create_ad.xml +0 -0
  213. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_create_async.xml +0 -0
  214. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_get.xml +0 -0
  215. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_populate_users.xml +0 -0
  216. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_populate_users_empty.xml +0 -0
  217. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_update.xml +0 -0
  218. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_update_async.xml +0 -0
  219. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/group_users_added.xml +0 -0
  220. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/job_get.xml +0 -0
  221. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/job_get_by_id.xml +0 -0
  222. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/job_get_by_id_failed.xml +0 -0
  223. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/job_get_by_id_failed_workbook.xml +0 -0
  224. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/job_get_by_id_inprogress.xml +0 -0
  225. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metadata_paged_1.json +0 -0
  226. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metadata_paged_2.json +0 -0
  227. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metadata_paged_3.json +0 -0
  228. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metadata_query_error.json +0 -0
  229. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metadata_query_expected_dict.dict +0 -0
  230. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metadata_query_success.json +0 -0
  231. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metrics_get.xml +0 -0
  232. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metrics_get_by_id.xml +0 -0
  233. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/metrics_update.xml +0 -0
  234. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/populate_csv.csv +0 -0
  235. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/populate_pdf.pdf +0 -0
  236. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/project_content_permission.xml +0 -0
  237. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/project_create.xml +0 -0
  238. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/project_get.xml +0 -0
  239. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/project_populate_permissions.xml +0 -0
  240. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/project_populate_workbook_default_permissions.xml +0 -0
  241. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/project_update.xml +0 -0
  242. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/project_update_datasource_default_permissions.xml +0 -0
  243. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/queryset_slicing_page_1.xml +0 -0
  244. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/queryset_slicing_page_2.xml +0 -0
  245. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/request_option_filter_equals.xml +0 -0
  246. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/request_option_filter_name_in.xml +0 -0
  247. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/request_option_filter_tags_in.xml +0 -0
  248. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/request_option_page_number.xml +0 -0
  249. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/request_option_page_size.xml +0 -0
  250. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/request_option_pagination.xml +0 -0
  251. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/request_option_slicing_queryset.xml +0 -0
  252. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_add_datasource.xml +0 -0
  253. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_add_flow.xml +0 -0
  254. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_add_workbook.xml +0 -0
  255. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_add_workbook_with_warnings.xml +0 -0
  256. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_create_daily.xml +0 -0
  257. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_create_hourly.xml +0 -0
  258. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_create_monthly.xml +0 -0
  259. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_create_weekly.xml +0 -0
  260. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_get.xml +0 -0
  261. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_get_by_id.xml +0 -0
  262. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_get_empty.xml +0 -0
  263. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/schedule_update.xml +0 -0
  264. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/server_info_25.xml +0 -0
  265. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/server_info_404.xml +0 -0
  266. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/server_info_auth_info.xml +0 -0
  267. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/server_info_get.xml +0 -0
  268. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/site_create.xml +0 -0
  269. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/site_get.xml +0 -0
  270. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/site_get_by_id.xml +0 -0
  271. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/site_get_by_name.xml +0 -0
  272. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/site_update.xml +0 -0
  273. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/subscription_create.xml +0 -0
  274. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/subscription_get.xml +0 -0
  275. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/subscription_get_by_id.xml +0 -0
  276. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/table_get.xml +0 -0
  277. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/table_update.xml +0 -0
  278. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/tasks_create_extract_task.xml +0 -0
  279. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/tasks_no_workbook_or_datasource.xml +0 -0
  280. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/tasks_run_now_response.xml +0 -0
  281. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/tasks_with_dataacceleration_task.xml +0 -0
  282. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/tasks_with_datasource.xml +0 -0
  283. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/tasks_with_workbook.xml +0 -0
  284. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/tasks_with_workbook_and_datasource.xml +0 -0
  285. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/user_add.xml +0 -0
  286. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/user_add_favorite.xml +0 -0
  287. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/user_get.xml +0 -0
  288. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/user_get_by_id.xml +0 -0
  289. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/user_get_empty.xml +0 -0
  290. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/user_populate_groups.xml +0 -0
  291. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/user_populate_workbooks.xml +0 -0
  292. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/user_update.xml +0 -0
  293. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/view_add_tags.xml +0 -0
  294. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/view_get.xml +0 -0
  295. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/view_get_id.xml +0 -0
  296. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/view_get_usage.xml +0 -0
  297. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/view_populate_permissions.xml +0 -0
  298. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/view_update_permissions.xml +0 -0
  299. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/webhook_create.xml +0 -0
  300. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/webhook_create_request.xml +0 -0
  301. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/webhook_get.xml +0 -0
  302. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_add_tags.xml +0 -0
  303. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_get.xml +0 -0
  304. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_get_by_id.xml +0 -0
  305. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_get_by_id_personal.xml +0 -0
  306. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_get_empty.xml +0 -0
  307. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_get_invalid_date.xml +0 -0
  308. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_get_page_1.xml +0 -0
  309. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_get_page_2.xml +0 -0
  310. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_get_page_3.xml +0 -0
  311. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_populate_connections.xml +0 -0
  312. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_populate_permissions.xml +0 -0
  313. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_populate_views.xml +0 -0
  314. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_populate_views_usage.xml +0 -0
  315. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_publish.xml +0 -0
  316. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_publish_async.xml +0 -0
  317. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_refresh.xml +0 -0
  318. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_revision.xml +0 -0
  319. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_update.xml +0 -0
  320. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/assets/workbook_update_permissions.xml +0 -0
  321. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/http/test_http_requests.py +0 -0
  322. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/models/_models.py +0 -0
  323. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/models/test_repr.py +0 -0
  324. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/request_factory/__init__.py +0 -0
  325. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/request_factory/test_datasource_requests.py +0 -0
  326. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/request_factory/test_workbook_requests.py +0 -0
  327. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_auth.py +0 -0
  328. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_connection_.py +0 -0
  329. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_custom_view.py +0 -0
  330. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_data_acceleration_report.py +0 -0
  331. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_dataalert.py +0 -0
  332. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_database.py +0 -0
  333. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_datasource_model.py +0 -0
  334. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_dqw.py +0 -0
  335. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_exponential_backoff.py +0 -0
  336. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_favorites.py +0 -0
  337. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_filesys_helpers.py +0 -0
  338. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_fileuploads.py +0 -0
  339. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_filter.py +0 -0
  340. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_flowruns.py +0 -0
  341. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_group.py +0 -0
  342. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_group_model.py +0 -0
  343. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_job.py +0 -0
  344. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_metadata.py +0 -0
  345. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_metrics.py +0 -0
  346. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_pager.py +0 -0
  347. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_project.py +0 -0
  348. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_project_model.py +0 -0
  349. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_regression_tests.py +0 -0
  350. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_request_option.py +0 -0
  351. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_requests.py +0 -0
  352. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_server_info.py +0 -0
  353. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_site.py +0 -0
  354. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_site_model.py +0 -0
  355. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_sort.py +0 -0
  356. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_subscription.py +0 -0
  357. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_table.py +0 -0
  358. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_tableauauth_model.py +0 -0
  359. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_user.py +0 -0
  360. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_user_model.py +0 -0
  361. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_view.py +0 -0
  362. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_webhook.py +0 -0
  363. {tableauserverclient-0.28 → tableauserverclient-0.30}/test/test_workbook_model.py +0 -0
  364. {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.28
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.6
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.6', # latest as at 7/31/23
18
+ 'urllib3==2.0.7', # latest as at 7/31/23
19
19
  ]
20
20
  requires-python = ">=3.7"
21
21
  classifiers = [
@@ -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.metrics.get()
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
- if __name__ == "__main__":
96
- main()
90
+
91
+ if __name__ == "__main__":
92
+ main()
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2023-10-04T00:33:03-0700",
11
+ "date": "2024-01-19T11:30:24-0800",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "72eb3c8500193e4f20defa20c8a6f8bbf34b2f43",
15
- "version": "0.28"
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
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
@@ -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)]
@@ -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"]:
@@ -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
- return DailyInterval(start_time)
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
- interval_occurrence, interval_value = interval.pop()
272
+ converted_intervals = []
261
273
 
262
- # We use fractional hours for the two minute-based intervals.
263
- # Need to convert to hours from minutes here
264
- if interval_occurrence == IntervalItem.Occurrence.Minutes:
265
- interval_value = float(interval_value) / 60
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, interval_value)
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
- interval_occurrence, interval_value = interval.pop()
275
- return MonthlyInterval(start_time, interval_value)
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):
@@ -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
- if len(schedule_item_list) >= 1:
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
- self.async_response = e
90
- finally:
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=0
99
- ) -> Optional["Response"]:
100
- try:
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: