tableauserverclient 0.31__py3-none-any.whl → 0.33__py3-none-any.whl

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 (54) hide show
  1. tableauserverclient/__init__.py +74 -4
  2. tableauserverclient/_version.py +3 -3
  3. tableauserverclient/config.py +16 -4
  4. tableauserverclient/models/__init__.py +100 -37
  5. tableauserverclient/models/connection_item.py +4 -2
  6. tableauserverclient/models/database_item.py +6 -0
  7. tableauserverclient/models/datasource_item.py +18 -6
  8. tableauserverclient/models/favorites_item.py +7 -7
  9. tableauserverclient/models/flow_item.py +6 -6
  10. tableauserverclient/models/groupset_item.py +53 -0
  11. tableauserverclient/models/interval_item.py +27 -14
  12. tableauserverclient/models/job_item.py +18 -2
  13. tableauserverclient/models/linked_tasks_item.py +102 -0
  14. tableauserverclient/models/permissions_item.py +53 -5
  15. tableauserverclient/models/project_item.py +4 -3
  16. tableauserverclient/models/reference_item.py +5 -0
  17. tableauserverclient/models/tableau_auth.py +22 -23
  18. tableauserverclient/models/tableau_types.py +9 -7
  19. tableauserverclient/models/virtual_connection_item.py +77 -0
  20. tableauserverclient/server/__init__.py +83 -8
  21. tableauserverclient/server/endpoint/__init__.py +69 -28
  22. tableauserverclient/server/endpoint/auth_endpoint.py +3 -3
  23. tableauserverclient/server/endpoint/custom_views_endpoint.py +66 -5
  24. tableauserverclient/server/endpoint/databases_endpoint.py +21 -18
  25. tableauserverclient/server/endpoint/datasources_endpoint.py +115 -35
  26. tableauserverclient/server/endpoint/endpoint.py +53 -20
  27. tableauserverclient/server/endpoint/favorites_endpoint.py +1 -1
  28. tableauserverclient/server/endpoint/fileuploads_endpoint.py +2 -2
  29. tableauserverclient/server/endpoint/flow_runs_endpoint.py +45 -5
  30. tableauserverclient/server/endpoint/flows_endpoint.py +43 -16
  31. tableauserverclient/server/endpoint/groups_endpoint.py +85 -31
  32. tableauserverclient/server/endpoint/groupsets_endpoint.py +127 -0
  33. tableauserverclient/server/endpoint/jobs_endpoint.py +74 -7
  34. tableauserverclient/server/endpoint/linked_tasks_endpoint.py +45 -0
  35. tableauserverclient/server/endpoint/metadata_endpoint.py +3 -3
  36. tableauserverclient/server/endpoint/metrics_endpoint.py +1 -1
  37. tableauserverclient/server/endpoint/projects_endpoint.py +50 -18
  38. tableauserverclient/server/endpoint/resource_tagger.py +135 -3
  39. tableauserverclient/server/endpoint/tables_endpoint.py +19 -16
  40. tableauserverclient/server/endpoint/users_endpoint.py +40 -1
  41. tableauserverclient/server/endpoint/views_endpoint.py +97 -10
  42. tableauserverclient/server/endpoint/virtual_connections_endpoint.py +173 -0
  43. tableauserverclient/server/endpoint/workbooks_endpoint.py +97 -45
  44. tableauserverclient/server/pager.py +46 -46
  45. tableauserverclient/server/query.py +62 -33
  46. tableauserverclient/server/request_factory.py +192 -49
  47. tableauserverclient/server/request_options.py +4 -2
  48. tableauserverclient/server/server.py +13 -6
  49. {tableauserverclient-0.31.dist-info → tableauserverclient-0.33.dist-info}/METADATA +15 -16
  50. {tableauserverclient-0.31.dist-info → tableauserverclient-0.33.dist-info}/RECORD +54 -48
  51. {tableauserverclient-0.31.dist-info → tableauserverclient-0.33.dist-info}/WHEEL +1 -1
  52. {tableauserverclient-0.31.dist-info → tableauserverclient-0.33.dist-info}/LICENSE +0 -0
  53. {tableauserverclient-0.31.dist-info → tableauserverclient-0.33.dist-info}/LICENSE.versioneer +0 -0
  54. {tableauserverclient-0.31.dist-info → tableauserverclient-0.33.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,102 @@
1
+ import datetime as dt
2
+ from typing import List, Optional
3
+
4
+ from defusedxml.ElementTree import fromstring
5
+
6
+ from tableauserverclient.datetime_helpers import parse_datetime
7
+ from tableauserverclient.models.schedule_item import ScheduleItem
8
+
9
+
10
+ class LinkedTaskItem:
11
+ def __init__(self) -> None:
12
+ self.id: Optional[str] = None
13
+ self.num_steps: Optional[int] = None
14
+ self.schedule: Optional[ScheduleItem] = None
15
+
16
+ @classmethod
17
+ def from_response(cls, resp: bytes, namespace) -> List["LinkedTaskItem"]:
18
+ parsed_response = fromstring(resp)
19
+ return [
20
+ cls._parse_element(x, namespace)
21
+ for x in parsed_response.findall(".//t:linkedTasks[@id]", namespaces=namespace)
22
+ ]
23
+
24
+ @classmethod
25
+ def _parse_element(cls, xml, namespace) -> "LinkedTaskItem":
26
+ task = cls()
27
+ task.id = xml.get("id")
28
+ task.num_steps = int(xml.get("numSteps"))
29
+ task.schedule = ScheduleItem.from_element(xml, namespace)[0]
30
+ return task
31
+
32
+
33
+ class LinkedTaskStepItem:
34
+ def __init__(self) -> None:
35
+ self.id: Optional[str] = None
36
+ self.step_number: Optional[int] = None
37
+ self.stop_downstream_on_failure: Optional[bool] = None
38
+ self.task_details: List[LinkedTaskFlowRunItem] = []
39
+
40
+ @classmethod
41
+ def from_task_xml(cls, xml, namespace) -> List["LinkedTaskStepItem"]:
42
+ return [cls._parse_element(x, namespace) for x in xml.findall(".//t:linkedTaskSteps[@id]", namespace)]
43
+
44
+ @classmethod
45
+ def _parse_element(cls, xml, namespace) -> "LinkedTaskStepItem":
46
+ step = cls()
47
+ step.id = xml.get("id")
48
+ step.step_number = int(xml.get("stepNumber"))
49
+ step.stop_downstream_on_failure = string_to_bool(xml.get("stopDownstreamTasksOnFailure"))
50
+ step.task_details = LinkedTaskFlowRunItem._parse_element(xml, namespace)
51
+ return step
52
+
53
+
54
+ class LinkedTaskFlowRunItem:
55
+ def __init__(self) -> None:
56
+ self.flow_run_id: Optional[str] = None
57
+ self.flow_run_priority: Optional[int] = None
58
+ self.flow_run_consecutive_failed_count: Optional[int] = None
59
+ self.flow_run_task_type: Optional[str] = None
60
+ self.flow_id: Optional[str] = None
61
+ self.flow_name: Optional[str] = None
62
+
63
+ @classmethod
64
+ def _parse_element(cls, xml, namespace) -> List["LinkedTaskFlowRunItem"]:
65
+ all_tasks = []
66
+ for flow_run in xml.findall(".//t:flowRun[@id]", namespace):
67
+ task = cls()
68
+ task.flow_run_id = flow_run.get("id")
69
+ task.flow_run_priority = int(flow_run.get("priority"))
70
+ task.flow_run_consecutive_failed_count = int(flow_run.get("consecutiveFailedCount"))
71
+ task.flow_run_task_type = flow_run.get("type")
72
+ flow = flow_run.find(".//t:flow[@id]", namespace)
73
+ task.flow_id = flow.get("id")
74
+ task.flow_name = flow.get("name")
75
+ all_tasks.append(task)
76
+
77
+ return all_tasks
78
+
79
+
80
+ class LinkedTaskJobItem:
81
+ def __init__(self) -> None:
82
+ self.id: Optional[str] = None
83
+ self.linked_task_id: Optional[str] = None
84
+ self.status: Optional[str] = None
85
+ self.created_at: Optional[dt.datetime] = None
86
+
87
+ @classmethod
88
+ def from_response(cls, resp: bytes, namespace) -> "LinkedTaskJobItem":
89
+ parsed_response = fromstring(resp)
90
+ job = cls()
91
+ job_xml = parsed_response.find(".//t:linkedTaskJob[@id]", namespaces=namespace)
92
+ if job_xml is None:
93
+ raise ValueError("No linked task job found in response")
94
+ job.id = job_xml.get("id")
95
+ job.linked_task_id = job_xml.get("linkedTaskId")
96
+ job.status = job_xml.get("status")
97
+ job.created_at = parse_datetime(job_xml.get("createdAt"))
98
+ return job
99
+
100
+
101
+ def string_to_bool(s: str) -> bool:
102
+ return s.lower() == "true"
@@ -3,10 +3,11 @@ from typing import Dict, List, Optional
3
3
 
4
4
  from defusedxml.ElementTree import fromstring
5
5
 
6
- from .exceptions import UnknownGranteeTypeError, UnpopulatedPropertyError
7
- from .group_item import GroupItem
8
- from .reference_item import ResourceReference
9
- from .user_item import UserItem
6
+ from tableauserverclient.models.exceptions import UnknownGranteeTypeError, UnpopulatedPropertyError
7
+ from tableauserverclient.models.group_item import GroupItem
8
+ from tableauserverclient.models.groupset_item import GroupSetItem
9
+ from tableauserverclient.models.reference_item import ResourceReference
10
+ from tableauserverclient.models.user_item import UserItem
10
11
 
11
12
  from tableauserverclient.helpers.logging import logger
12
13
 
@@ -45,7 +46,7 @@ class Permission:
45
46
  return "<Enum Capability: AddComment | ChangeHierarchy | ChangePermission ... (17 more) >"
46
47
 
47
48
 
48
- class PermissionsRule(object):
49
+ class PermissionsRule:
49
50
  def __init__(self, grantee: ResourceReference, capabilities: Dict[str, str]) -> None:
50
51
  self.grantee = grantee
51
52
  self.capabilities = capabilities
@@ -53,6 +54,51 @@ class PermissionsRule(object):
53
54
  def __repr__(self):
54
55
  return "<PermissionsRule grantee={}, capabilities={}>".format(self.grantee, self.capabilities)
55
56
 
57
+ def __eq__(self, other: object) -> bool:
58
+ if not hasattr(other, "grantee") or not hasattr(other, "capabilities"):
59
+ return False
60
+ return self.grantee == other.grantee and self.capabilities == other.capabilities
61
+
62
+ def __and__(self, other: "PermissionsRule") -> "PermissionsRule":
63
+ if self.grantee != other.grantee:
64
+ raise ValueError("Cannot AND two permissions rules with different grantees")
65
+
66
+ if self.capabilities == other.capabilities:
67
+ return self
68
+
69
+ capabilities = set((*self.capabilities.keys(), *other.capabilities.keys()))
70
+ new_capabilities = {}
71
+ for capability in capabilities:
72
+ if (self.capabilities.get(capability), other.capabilities.get(capability)) == (
73
+ Permission.Mode.Allow,
74
+ Permission.Mode.Allow,
75
+ ):
76
+ new_capabilities[capability] = Permission.Mode.Allow
77
+ elif Permission.Mode.Deny in (self.capabilities.get(capability), other.capabilities.get(capability)):
78
+ new_capabilities[capability] = Permission.Mode.Deny
79
+
80
+ return PermissionsRule(self.grantee, new_capabilities)
81
+
82
+ def __or__(self, other: "PermissionsRule") -> "PermissionsRule":
83
+ if self.grantee != other.grantee:
84
+ raise ValueError("Cannot OR two permissions rules with different grantees")
85
+
86
+ if self.capabilities == other.capabilities:
87
+ return self
88
+
89
+ capabilities = set((*self.capabilities.keys(), *other.capabilities.keys()))
90
+ new_capabilities = {}
91
+ for capability in capabilities:
92
+ if Permission.Mode.Allow in (self.capabilities.get(capability), other.capabilities.get(capability)):
93
+ new_capabilities[capability] = Permission.Mode.Allow
94
+ elif (self.capabilities.get(capability), other.capabilities.get(capability)) == (
95
+ Permission.Mode.Deny,
96
+ Permission.Mode.Deny,
97
+ ):
98
+ new_capabilities[capability] = Permission.Mode.Deny
99
+
100
+ return PermissionsRule(self.grantee, new_capabilities)
101
+
56
102
  @classmethod
57
103
  def from_response(cls, resp, ns=None) -> List["PermissionsRule"]:
58
104
  parsed_response = fromstring(resp)
@@ -97,6 +143,8 @@ class PermissionsRule(object):
97
143
  grantee = UserItem.as_reference(grantee_id)
98
144
  elif grantee_type == "group":
99
145
  grantee = GroupItem.as_reference(grantee_id)
146
+ elif grantee_type == "groupSet":
147
+ grantee = GroupSetItem.as_reference(grantee_id)
100
148
  else:
101
149
  raise UnknownGranteeTypeError("No support for grantee type of {}".format(grantee_type))
102
150
 
@@ -4,8 +4,8 @@ from typing import List, Optional
4
4
 
5
5
  from defusedxml.ElementTree import fromstring
6
6
 
7
- from .exceptions import UnpopulatedPropertyError
8
- from .property_decorators import property_is_enum, property_not_empty
7
+ from tableauserverclient.models.exceptions import UnpopulatedPropertyError
8
+ from tableauserverclient.models.property_decorators import property_is_enum, property_not_empty
9
9
 
10
10
 
11
11
  class ProjectItem(object):
@@ -34,6 +34,7 @@ class ProjectItem(object):
34
34
  self.content_permissions: Optional[str] = content_permissions
35
35
  self.parent_id: Optional[str] = parent_id
36
36
  self._samples: Optional[bool] = samples
37
+ self._owner_id: Optional[str] = None
37
38
 
38
39
  self._permissions = None
39
40
  self._default_workbook_permissions = None
@@ -119,7 +120,7 @@ class ProjectItem(object):
119
120
 
120
121
  @owner_id.setter
121
122
  def owner_id(self, value: str) -> None:
122
- raise NotImplementedError("REST API does not currently support updating project owner.")
123
+ self._owner_id = value
123
124
 
124
125
  def is_default(self):
125
126
  return self.name.lower() == "default"
@@ -8,6 +8,11 @@ class ResourceReference(object):
8
8
 
9
9
  __repr__ = __str__
10
10
 
11
+ def __eq__(self, other: object) -> bool:
12
+ if not hasattr(other, "id") or not hasattr(other, "tag_name"):
13
+ return False
14
+ return (self.id == other.id) and (self.tag_name == other.tag_name)
15
+
11
16
  @property
12
17
  def id(self):
13
18
  return self._id
@@ -1,16 +1,20 @@
1
1
  import abc
2
+ from typing import Dict, Optional
2
3
 
3
4
 
4
5
  class Credentials(abc.ABC):
5
- def __init__(self, site_id=None, user_id_to_impersonate=None):
6
+ def __init__(self, site_id: Optional[str] = None, user_id_to_impersonate: Optional[str] = None) -> None:
6
7
  self.site_id = site_id or ""
7
8
  self.user_id_to_impersonate = user_id_to_impersonate or None
8
9
 
9
10
  @property
10
11
  @abc.abstractmethod
11
- def credentials(self):
12
- credentials = "Credentials can be username/password, Personal Access Token, or JWT"
13
- +"This method returns values to set as an attribute on the credentials element of the request"
12
+ def credentials(self) -> Dict[str, str]:
13
+ credentials = (
14
+ "Credentials can be username/password, Personal Access Token, or JWT"
15
+ "This method returns values to set as an attribute on the credentials element of the request"
16
+ )
17
+ return {"key": "value"}
14
18
 
15
19
  @abc.abstractmethod
16
20
  def __repr__(self):
@@ -28,10 +32,9 @@ def deprecate_site_attribute():
28
32
 
29
33
  # The traditional auth type: username/password
30
34
  class TableauAuth(Credentials):
31
- def __init__(self, username, password, site=None, site_id=None, user_id_to_impersonate=None):
32
- if site is not None:
33
- deprecate_site_attribute()
34
- site_id = site
35
+ def __init__(
36
+ self, username: str, password: str, site_id: Optional[str] = None, user_id_to_impersonate: Optional[str] = None
37
+ ) -> None:
35
38
  super().__init__(site_id, user_id_to_impersonate)
36
39
  if password is None:
37
40
  raise TabError("Must provide a password when using traditional authentication")
@@ -39,7 +42,7 @@ class TableauAuth(Credentials):
39
42
  self.username = username
40
43
 
41
44
  @property
42
- def credentials(self):
45
+ def credentials(self) -> Dict[str, str]:
43
46
  return {"name": self.username, "password": self.password}
44
47
 
45
48
  def __repr__(self):
@@ -49,20 +52,16 @@ class TableauAuth(Credentials):
49
52
  uid = ""
50
53
  return f"<Credentials username={self.username} password=redacted (site={self.site_id}{uid})>"
51
54
 
52
- @property
53
- def site(self):
54
- deprecate_site_attribute()
55
- return self.site_id
56
-
57
- @site.setter
58
- def site(self, value):
59
- deprecate_site_attribute()
60
- self.site_id = value
61
-
62
55
 
63
56
  # A Tableau-generated Personal Access Token
64
57
  class PersonalAccessTokenAuth(Credentials):
65
- def __init__(self, token_name, personal_access_token, site_id=None, user_id_to_impersonate=None):
58
+ def __init__(
59
+ self,
60
+ token_name: str,
61
+ personal_access_token: str,
62
+ site_id: Optional[str] = None,
63
+ user_id_to_impersonate: Optional[str] = None,
64
+ ) -> None:
66
65
  if personal_access_token is None or token_name is None:
67
66
  raise TabError("Must provide a token and token name when using PAT authentication")
68
67
  super().__init__(site_id=site_id, user_id_to_impersonate=user_id_to_impersonate)
@@ -70,7 +69,7 @@ class PersonalAccessTokenAuth(Credentials):
70
69
  self.personal_access_token = personal_access_token
71
70
 
72
71
  @property
73
- def credentials(self):
72
+ def credentials(self) -> Dict[str, str]:
74
73
  return {
75
74
  "personalAccessTokenName": self.token_name,
76
75
  "personalAccessTokenSecret": self.personal_access_token,
@@ -89,14 +88,14 @@ class PersonalAccessTokenAuth(Credentials):
89
88
 
90
89
  # A standard JWT generated specifically for Tableau
91
90
  class JWTAuth(Credentials):
92
- def __init__(self, jwt: str, site_id=None, user_id_to_impersonate=None):
91
+ def __init__(self, jwt: str, site_id: Optional[str] = None, user_id_to_impersonate: Optional[str] = None) -> None:
93
92
  if jwt is None:
94
93
  raise TabError("Must provide a JWT token when using JWT authentication")
95
94
  super().__init__(site_id, user_id_to_impersonate)
96
95
  self.jwt = jwt
97
96
 
98
97
  @property
99
- def credentials(self):
98
+ def credentials(self) -> Dict[str, str]:
100
99
  return {"jwt": self.jwt}
101
100
 
102
101
  def __repr__(self):
@@ -1,11 +1,12 @@
1
1
  from typing import Union
2
2
 
3
- from .datasource_item import DatasourceItem
4
- from .flow_item import FlowItem
5
- from .project_item import ProjectItem
6
- from .view_item import ViewItem
7
- from .workbook_item import WorkbookItem
8
- from .metric_item import MetricItem
3
+ from tableauserverclient.models.datasource_item import DatasourceItem
4
+ from tableauserverclient.models.flow_item import FlowItem
5
+ from tableauserverclient.models.project_item import ProjectItem
6
+ from tableauserverclient.models.view_item import ViewItem
7
+ from tableauserverclient.models.workbook_item import WorkbookItem
8
+ from tableauserverclient.models.metric_item import MetricItem
9
+ from tableauserverclient.models.virtual_connection_item import VirtualConnectionItem
9
10
 
10
11
 
11
12
  class Resource:
@@ -18,12 +19,13 @@ class Resource:
18
19
  Metric = "metric"
19
20
  Project = "project"
20
21
  View = "view"
22
+ VirtualConnection = "virtualConnection"
21
23
  Workbook = "workbook"
22
24
 
23
25
 
24
26
  # resource types that have permissions, can be renamed, etc
25
27
  # todo: refactoring: should actually define TableauItem as an interface and let all these implement it
26
- TableauItem = Union[DatasourceItem, FlowItem, MetricItem, ProjectItem, ViewItem, WorkbookItem]
28
+ TableauItem = Union[DatasourceItem, FlowItem, MetricItem, ProjectItem, ViewItem, WorkbookItem, VirtualConnectionItem]
27
29
 
28
30
 
29
31
  def plural_type(content_type: Resource) -> str:
@@ -0,0 +1,77 @@
1
+ import datetime as dt
2
+ import json
3
+ from typing import Callable, Dict, Iterable, List, Optional
4
+ from xml.etree.ElementTree import Element
5
+
6
+ from defusedxml.ElementTree import fromstring
7
+
8
+ from tableauserverclient.datetime_helpers import parse_datetime
9
+ from tableauserverclient.models.connection_item import ConnectionItem
10
+ from tableauserverclient.models.exceptions import UnpopulatedPropertyError
11
+ from tableauserverclient.models.permissions_item import PermissionsRule
12
+
13
+
14
+ class VirtualConnectionItem:
15
+ def __init__(self, name: str) -> None:
16
+ self.name = name
17
+ self.created_at: Optional[dt.datetime] = None
18
+ self.has_extracts: Optional[bool] = None
19
+ self._id: Optional[str] = None
20
+ self.is_certified: Optional[bool] = None
21
+ self.updated_at: Optional[dt.datetime] = None
22
+ self.webpage_url: Optional[str] = None
23
+ self._connections: Optional[Callable[[], Iterable[ConnectionItem]]] = None
24
+ self.project_id: Optional[str] = None
25
+ self.owner_id: Optional[str] = None
26
+ self.content: Optional[Dict[str, dict]] = None
27
+ self.certification_note: Optional[str] = None
28
+
29
+ def __str__(self) -> str:
30
+ return f"{self.__class__.__qualname__}(name={self.name})"
31
+
32
+ def __repr__(self) -> str:
33
+ return f"<{self!s}>"
34
+
35
+ def _set_permissions(self, permissions):
36
+ self._permissions = permissions
37
+
38
+ @property
39
+ def id(self) -> Optional[str]:
40
+ return self._id
41
+
42
+ @property
43
+ def permissions(self) -> List[PermissionsRule]:
44
+ if self._permissions is None:
45
+ error = "Workbook item must be populated with permissions first."
46
+ raise UnpopulatedPropertyError(error)
47
+ return self._permissions()
48
+
49
+ @property
50
+ def connections(self) -> Iterable[ConnectionItem]:
51
+ if self._connections is None:
52
+ raise AttributeError("connections not populated. Call populate_connections() first.")
53
+ return self._connections()
54
+
55
+ @classmethod
56
+ def from_response(cls, response: bytes, ns: Dict[str, str]) -> List["VirtualConnectionItem"]:
57
+ parsed_response = fromstring(response)
58
+ return [cls.from_xml(xml, ns) for xml in parsed_response.findall(".//t:virtualConnection[@name]", ns)]
59
+
60
+ @classmethod
61
+ def from_xml(cls, xml: Element, ns: Dict[str, str]) -> "VirtualConnectionItem":
62
+ v_conn = cls(xml.get("name", ""))
63
+ v_conn._id = xml.get("id", None)
64
+ v_conn.webpage_url = xml.get("webpageUrl", None)
65
+ v_conn.created_at = parse_datetime(xml.get("createdAt", None))
66
+ v_conn.updated_at = parse_datetime(xml.get("updatedAt", None))
67
+ v_conn.is_certified = string_to_bool(s) if (s := xml.get("isCertified", None)) else None
68
+ v_conn.certification_note = xml.get("certificationNote", None)
69
+ v_conn.has_extracts = string_to_bool(s) if (s := xml.get("hasExtracts", None)) else None
70
+ v_conn.project_id = p.get("id", None) if ((p := xml.find(".//t:project[@id]", ns)) is not None) else None
71
+ v_conn.owner_id = o.get("id", None) if ((o := xml.find(".//t:owner[@id]", ns)) is not None) else None
72
+ v_conn.content = json.loads(c.text or "{}") if ((c := xml.find(".//t:content", ns)) is not None) else None
73
+ return v_conn
74
+
75
+
76
+ def string_to_bool(s: str) -> bool:
77
+ return s.lower() in ["true", "1", "t", "y", "yes"]
@@ -1,16 +1,91 @@
1
1
  # These two imports must come first
2
- from .request_factory import RequestFactory
3
- from .request_options import (
2
+ from tableauserverclient.server.request_factory import RequestFactory
3
+ from tableauserverclient.server.request_options import (
4
4
  CSVRequestOptions,
5
5
  ExcelRequestOptions,
6
6
  ImageRequestOptions,
7
7
  PDFRequestOptions,
8
8
  RequestOptions,
9
9
  )
10
+ from tableauserverclient.server.filter import Filter
11
+ from tableauserverclient.server.sort import Sort
12
+ from tableauserverclient.server.server import Server
13
+ from tableauserverclient.server.pager import Pager
14
+ from tableauserverclient.server.endpoint.exceptions import NotSignedInError
10
15
 
11
- from .filter import Filter
12
- from .sort import Sort
13
- from .endpoint import *
14
- from .server import Server
15
- from .pager import Pager
16
- from .endpoint.exceptions import NotSignedInError
16
+ from tableauserverclient.server.endpoint import (
17
+ Auth,
18
+ CustomViews,
19
+ DataAccelerationReport,
20
+ DataAlerts,
21
+ Databases,
22
+ Datasources,
23
+ QuerysetEndpoint,
24
+ MissingRequiredFieldError,
25
+ Endpoint,
26
+ Favorites,
27
+ Fileuploads,
28
+ FlowRuns,
29
+ Flows,
30
+ FlowTasks,
31
+ Groups,
32
+ Jobs,
33
+ Metadata,
34
+ Metrics,
35
+ Projects,
36
+ Schedules,
37
+ ServerInfo,
38
+ ServerResponseError,
39
+ Sites,
40
+ Subscriptions,
41
+ Tables,
42
+ Tasks,
43
+ Users,
44
+ Views,
45
+ Webhooks,
46
+ Workbooks,
47
+ )
48
+
49
+ __all__ = [
50
+ "RequestFactory",
51
+ "CSVRequestOptions",
52
+ "ExcelRequestOptions",
53
+ "ImageRequestOptions",
54
+ "PDFRequestOptions",
55
+ "RequestOptions",
56
+ "Filter",
57
+ "Sort",
58
+ "Server",
59
+ "Pager",
60
+ "NotSignedInError",
61
+ "Auth",
62
+ "CustomViews",
63
+ "DataAccelerationReport",
64
+ "DataAlerts",
65
+ "Databases",
66
+ "Datasources",
67
+ "QuerysetEndpoint",
68
+ "MissingRequiredFieldError",
69
+ "Endpoint",
70
+ "Favorites",
71
+ "Fileuploads",
72
+ "FlowRuns",
73
+ "Flows",
74
+ "FlowTasks",
75
+ "Groups",
76
+ "Jobs",
77
+ "Metadata",
78
+ "Metrics",
79
+ "Projects",
80
+ "Schedules",
81
+ "ServerInfo",
82
+ "ServerResponseError",
83
+ "Sites",
84
+ "Subscriptions",
85
+ "Tables",
86
+ "Tasks",
87
+ "Users",
88
+ "Views",
89
+ "Webhooks",
90
+ "Workbooks",
91
+ ]
@@ -1,28 +1,69 @@
1
- from .auth_endpoint import Auth
2
- from .custom_views_endpoint import CustomViews
3
- from .data_acceleration_report_endpoint import DataAccelerationReport
4
- from .data_alert_endpoint import DataAlerts
5
- from .databases_endpoint import Databases
6
- from .datasources_endpoint import Datasources
7
- from .endpoint import Endpoint, QuerysetEndpoint
8
- from .exceptions import ServerResponseError, MissingRequiredFieldError
9
- from .favorites_endpoint import Favorites
10
- from .fileuploads_endpoint import Fileuploads
11
- from .flow_runs_endpoint import FlowRuns
12
- from .flows_endpoint import Flows
13
- from .flow_task_endpoint import FlowTasks
14
- from .groups_endpoint import Groups
15
- from .jobs_endpoint import Jobs
16
- from .metadata_endpoint import Metadata
17
- from .metrics_endpoint import Metrics
18
- from .projects_endpoint import Projects
19
- from .schedules_endpoint import Schedules
20
- from .server_info_endpoint import ServerInfo
21
- from .sites_endpoint import Sites
22
- from .subscriptions_endpoint import Subscriptions
23
- from .tables_endpoint import Tables
24
- from .tasks_endpoint import Tasks
25
- from .users_endpoint import Users
26
- from .views_endpoint import Views
27
- from .webhooks_endpoint import Webhooks
28
- from .workbooks_endpoint import Workbooks
1
+ from tableauserverclient.server.endpoint.auth_endpoint import Auth
2
+ from tableauserverclient.server.endpoint.custom_views_endpoint import CustomViews
3
+ from tableauserverclient.server.endpoint.data_acceleration_report_endpoint import DataAccelerationReport
4
+ from tableauserverclient.server.endpoint.data_alert_endpoint import DataAlerts
5
+ from tableauserverclient.server.endpoint.databases_endpoint import Databases
6
+ from tableauserverclient.server.endpoint.datasources_endpoint import Datasources
7
+ from tableauserverclient.server.endpoint.endpoint import Endpoint, QuerysetEndpoint
8
+ from tableauserverclient.server.endpoint.exceptions import ServerResponseError, MissingRequiredFieldError
9
+ from tableauserverclient.server.endpoint.favorites_endpoint import Favorites
10
+ from tableauserverclient.server.endpoint.fileuploads_endpoint import Fileuploads
11
+ from tableauserverclient.server.endpoint.flow_runs_endpoint import FlowRuns
12
+ from tableauserverclient.server.endpoint.flows_endpoint import Flows
13
+ from tableauserverclient.server.endpoint.flow_task_endpoint import FlowTasks
14
+ from tableauserverclient.server.endpoint.groups_endpoint import Groups
15
+ from tableauserverclient.server.endpoint.groupsets_endpoint import GroupSets
16
+ from tableauserverclient.server.endpoint.jobs_endpoint import Jobs
17
+ from tableauserverclient.server.endpoint.linked_tasks_endpoint import LinkedTasks
18
+ from tableauserverclient.server.endpoint.metadata_endpoint import Metadata
19
+ from tableauserverclient.server.endpoint.metrics_endpoint import Metrics
20
+ from tableauserverclient.server.endpoint.projects_endpoint import Projects
21
+ from tableauserverclient.server.endpoint.schedules_endpoint import Schedules
22
+ from tableauserverclient.server.endpoint.server_info_endpoint import ServerInfo
23
+ from tableauserverclient.server.endpoint.sites_endpoint import Sites
24
+ from tableauserverclient.server.endpoint.subscriptions_endpoint import Subscriptions
25
+ from tableauserverclient.server.endpoint.tables_endpoint import Tables
26
+ from tableauserverclient.server.endpoint.resource_tagger import Tags
27
+ from tableauserverclient.server.endpoint.tasks_endpoint import Tasks
28
+ from tableauserverclient.server.endpoint.users_endpoint import Users
29
+ from tableauserverclient.server.endpoint.views_endpoint import Views
30
+ from tableauserverclient.server.endpoint.virtual_connections_endpoint import VirtualConnections
31
+ from tableauserverclient.server.endpoint.webhooks_endpoint import Webhooks
32
+ from tableauserverclient.server.endpoint.workbooks_endpoint import Workbooks
33
+
34
+ __all__ = [
35
+ "Auth",
36
+ "CustomViews",
37
+ "DataAccelerationReport",
38
+ "DataAlerts",
39
+ "Databases",
40
+ "Datasources",
41
+ "QuerysetEndpoint",
42
+ "MissingRequiredFieldError",
43
+ "Endpoint",
44
+ "Favorites",
45
+ "Fileuploads",
46
+ "FlowRuns",
47
+ "Flows",
48
+ "FlowTasks",
49
+ "Groups",
50
+ "GroupSets",
51
+ "Jobs",
52
+ "LinkedTasks",
53
+ "Metadata",
54
+ "Metrics",
55
+ "Projects",
56
+ "Schedules",
57
+ "ServerInfo",
58
+ "ServerResponseError",
59
+ "Sites",
60
+ "Subscriptions",
61
+ "Tables",
62
+ "Tags",
63
+ "Tasks",
64
+ "Users",
65
+ "Views",
66
+ "VirtualConnections",
67
+ "Webhooks",
68
+ "Workbooks",
69
+ ]
@@ -4,9 +4,9 @@ import warnings
4
4
 
5
5
  from defusedxml.ElementTree import fromstring
6
6
 
7
- from .endpoint import Endpoint, api
8
- from .exceptions import ServerResponseError
9
- from ..request_factory import RequestFactory
7
+ from tableauserverclient.server.endpoint.endpoint import Endpoint, api
8
+ from tableauserverclient.server.endpoint.exceptions import ServerResponseError
9
+ from tableauserverclient.server.request_factory import RequestFactory
10
10
 
11
11
  from tableauserverclient.helpers.logging import logger
12
12