From 4a037e952d92882f41d201038d5d76153997deaa Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Tue, 14 Feb 2023 17:47:11 -0800 Subject: [PATCH 1/6] make imports absolute was: "from ..models import x" now: "from tableauserverclient.models import x" this will make it easier to split them into properly independent modules --- tableauserverclient/__init__.py | 39 +------------- tableauserverclient/models/__init__.py | 2 + tableauserverclient/models/datasource_item.py | 2 +- tableauserverclient/models/dqw_item.py | 2 +- tableauserverclient/models/flow_item.py | 7 +-- tableauserverclient/models/flow_run_item.py | 2 +- tableauserverclient/models/group_item.py | 2 +- tableauserverclient/models/job_item.py | 2 +- tableauserverclient/models/metric_item.py | 2 +- .../models/property_decorators.py | 2 +- tableauserverclient/models/revision_item.py | 2 +- tableauserverclient/models/schedule_item.py | 2 +- tableauserverclient/models/task_item.py | 2 +- tableauserverclient/models/user_item.py | 12 ++--- tableauserverclient/models/view_item.py | 2 +- tableauserverclient/models/workbook_item.py | 2 +- tableauserverclient/server/__init__.py | 52 +------------------ .../data_acceleration_report_endpoint.py | 2 +- .../server/endpoint/data_alert_endpoint.py | 3 +- .../server/endpoint/databases_endpoint.py | 3 +- .../server/endpoint/datasources_endpoint.py | 44 +++++++++------- .../endpoint/default_permissions_endpoint.py | 4 +- .../server/endpoint/dqw_endpoint.py | 3 +- .../server/endpoint/endpoint.py | 6 +-- .../server/endpoint/favorites_endpoint.py | 8 +-- .../server/endpoint/fileuploads_endpoint.py | 4 +- .../server/endpoint/flow_runs_endpoint.py | 4 +- .../server/endpoint/flows_endpoint.py | 8 +-- .../server/endpoint/groups_endpoint.py | 3 +- .../server/endpoint/jobs_endpoint.py | 4 +- .../server/endpoint/metrics_endpoint.py | 5 +- .../server/endpoint/permissions_endpoint.py | 6 +-- .../server/endpoint/projects_endpoint.py | 3 +- .../server/endpoint/resource_tagger.py | 4 +- .../server/endpoint/schedules_endpoint.py | 3 +- .../server/endpoint/server_info_endpoint.py | 2 +- .../server/endpoint/sites_endpoint.py | 3 +- .../server/endpoint/subscriptions_endpoint.py | 3 +- .../server/endpoint/tables_endpoint.py | 3 +- .../server/endpoint/tasks_endpoint.py | 3 +- .../server/endpoint/users_endpoint.py | 9 ++-- .../server/endpoint/views_endpoint.py | 2 +- .../server/endpoint/webhooks_endpoint.py | 4 +- .../server/endpoint/workbooks_endpoint.py | 25 +++------ tableauserverclient/server/request_factory.py | 19 +------ tableauserverclient/server/request_options.py | 2 +- test/test_workbook.py | 7 +-- 47 files changed, 112 insertions(+), 223 deletions(-) diff --git a/tableauserverclient/__init__.py b/tableauserverclient/__init__.py index 212540d84..03e484372 100644 --- a/tableauserverclient/__init__.py +++ b/tableauserverclient/__init__.py @@ -1,43 +1,6 @@ from ._version import get_versions from .namespace import NEW_NAMESPACE as DEFAULT_NAMESPACE -from .models import ( - BackgroundJobItem, - ColumnItem, - ConnectionCredentials, - ConnectionItem, - DQWItem, - DailyInterval, - DataAlertItem, - DatabaseItem, - DatasourceItem, - FlowItem, - FlowRunItem, - GroupItem, - HourlyInterval, - IntervalItem, - JobItem, - MetricItem, - MonthlyInterval, - PaginationItem, - Permission, - PermissionsRule, - PersonalAccessTokenAuth, - ProjectItem, - RevisionItem, - ScheduleItem, - SiteItem, - SubscriptionItem, - TableItem, - TableauAuth, - Target, - TaskItem, - UnpopulatedPropertyError, - UserItem, - ViewItem, - WebhookItem, - WeeklyInterval, - WorkbookItem, -) +from .models import * from .server import ( CSVRequestOptions, ExcelRequestOptions, diff --git a/tableauserverclient/models/__init__.py b/tableauserverclient/models/__init__.py index 58e5ed6d1..a7b025fda 100644 --- a/tableauserverclient/models/__init__.py +++ b/tableauserverclient/models/__init__.py @@ -10,6 +10,7 @@ from .favorites_item import FavoriteItem from .flow_item import FlowItem from .flow_run_item import FlowRunItem +from .fileupload_item import FileuploadItem from .group_item import GroupItem from .interval_item import ( IntervalItem, @@ -31,6 +32,7 @@ from .table_item import TableItem from .tableau_auth import Credentials, TableauAuth, PersonalAccessTokenAuth from .tableau_types import Resource, TableauItem, plural_type +from .tag_item import TagItem from .target import Target from .task_item import TaskItem from .user_item import UserItem diff --git a/tableauserverclient/models/datasource_item.py b/tableauserverclient/models/datasource_item.py index 4a7a74c4b..ced008506 100644 --- a/tableauserverclient/models/datasource_item.py +++ b/tableauserverclient/models/datasource_item.py @@ -11,7 +11,7 @@ property_is_enum, ) from .tag_item import TagItem -from ..datetime_helpers import parse_datetime +from tableauserverclient.datetime_helpers import parse_datetime if TYPE_CHECKING: from .permissions_item import PermissionsRule diff --git a/tableauserverclient/models/dqw_item.py b/tableauserverclient/models/dqw_item.py index 2baecee09..ada041481 100644 --- a/tableauserverclient/models/dqw_item.py +++ b/tableauserverclient/models/dqw_item.py @@ -1,6 +1,6 @@ from defusedxml.ElementTree import fromstring -from ..datetime_helpers import parse_datetime +from tableauserverclient.datetime_helpers import parse_datetime class DQWItem(object): diff --git a/tableauserverclient/models/flow_item.py b/tableauserverclient/models/flow_item.py index 18f0ecae2..1f153bd78 100644 --- a/tableauserverclient/models/flow_item.py +++ b/tableauserverclient/models/flow_item.py @@ -7,12 +7,7 @@ from .exceptions import UnpopulatedPropertyError from .property_decorators import property_not_nullable from .tag_item import TagItem -from ..datetime_helpers import parse_datetime - -if TYPE_CHECKING: - import datetime - -from typing import List, Optional, TYPE_CHECKING, Set +from tableauserverclient.datetime_helpers import parse_datetime if TYPE_CHECKING: import datetime diff --git a/tableauserverclient/models/flow_run_item.py b/tableauserverclient/models/flow_run_item.py index ce859a65b..a457f51a2 100644 --- a/tableauserverclient/models/flow_run_item.py +++ b/tableauserverclient/models/flow_run_item.py @@ -3,7 +3,7 @@ from defusedxml.ElementTree import fromstring -from ..datetime_helpers import parse_datetime +from tableauserverclient.datetime_helpers import parse_datetime if TYPE_CHECKING: from datetime import datetime diff --git a/tableauserverclient/models/group_item.py b/tableauserverclient/models/group_item.py index eb03b1b5d..128f151cf 100644 --- a/tableauserverclient/models/group_item.py +++ b/tableauserverclient/models/group_item.py @@ -8,7 +8,7 @@ from .user_item import UserItem if TYPE_CHECKING: - from ..server import Pager + from tableauserverclient.server import Pager class GroupItem(object): diff --git a/tableauserverclient/models/job_item.py b/tableauserverclient/models/job_item.py index a7490e705..650db38c5 100644 --- a/tableauserverclient/models/job_item.py +++ b/tableauserverclient/models/job_item.py @@ -3,7 +3,7 @@ from defusedxml.ElementTree import fromstring from .flow_run_item import FlowRunItem -from ..datetime_helpers import parse_datetime +from tableauserverclient.datetime_helpers import parse_datetime if TYPE_CHECKING: import datetime diff --git a/tableauserverclient/models/metric_item.py b/tableauserverclient/models/metric_item.py index a54d1e30e..b650c0656 100644 --- a/tableauserverclient/models/metric_item.py +++ b/tableauserverclient/models/metric_item.py @@ -1,5 +1,5 @@ import xml.etree.ElementTree as ET -from ..datetime_helpers import parse_datetime +from tableauserverclient.datetime_helpers import parse_datetime from .property_decorators import property_is_boolean, property_is_datetime from .tag_item import TagItem from typing import List, Optional, TYPE_CHECKING, Set diff --git a/tableauserverclient/models/property_decorators.py b/tableauserverclient/models/property_decorators.py index 2d7e01557..4e6697433 100644 --- a/tableauserverclient/models/property_decorators.py +++ b/tableauserverclient/models/property_decorators.py @@ -2,7 +2,7 @@ import re from functools import wraps -from ..datetime_helpers import parse_datetime +from tableauserverclient.datetime_helpers import parse_datetime def property_is_enum(enum_type): diff --git a/tableauserverclient/models/revision_item.py b/tableauserverclient/models/revision_item.py index 600d73168..6696fb550 100644 --- a/tableauserverclient/models/revision_item.py +++ b/tableauserverclient/models/revision_item.py @@ -2,7 +2,7 @@ from defusedxml.ElementTree import fromstring -from ..datetime_helpers import parse_datetime +from tableauserverclient.datetime_helpers import parse_datetime if TYPE_CHECKING: from datetime import datetime diff --git a/tableauserverclient/models/schedule_item.py b/tableauserverclient/models/schedule_item.py index 828034d23..7408707c3 100644 --- a/tableauserverclient/models/schedule_item.py +++ b/tableauserverclient/models/schedule_item.py @@ -16,7 +16,7 @@ property_not_nullable, property_is_int, ) -from ..datetime_helpers import parse_datetime +from tableauserverclient.datetime_helpers import parse_datetime Interval = Union[HourlyInterval, DailyInterval, WeeklyInterval, MonthlyInterval] diff --git a/tableauserverclient/models/task_item.py b/tableauserverclient/models/task_item.py index 32299a853..30cac8626 100644 --- a/tableauserverclient/models/task_item.py +++ b/tableauserverclient/models/task_item.py @@ -2,7 +2,7 @@ from .schedule_item import ScheduleItem from .target import Target -from ..datetime_helpers import parse_datetime +from tableauserverclient.datetime_helpers import parse_datetime class TaskItem(object): diff --git a/tableauserverclient/models/user_item.py b/tableauserverclient/models/user_item.py index 032841dc7..059b18f4f 100644 --- a/tableauserverclient/models/user_item.py +++ b/tableauserverclient/models/user_item.py @@ -1,10 +1,8 @@ -import io -import logging -import xml.etree.ElementTree as ET from datetime import datetime -from enum import IntEnum - from defusedxml.ElementTree import fromstring +from enum import IntEnum +import io +import xml.etree.ElementTree as ET from .exceptions import UnpopulatedPropertyError from .property_decorators import ( @@ -12,12 +10,12 @@ property_not_empty, ) from .reference_item import ResourceReference -from ..datetime_helpers import parse_datetime +from tableauserverclient.datetime_helpers import parse_datetime from typing import Dict, List, Optional, TYPE_CHECKING, Tuple if TYPE_CHECKING: - from ..server.pager import Pager + from tableauserverclient.server import Pager class UserItem(object): diff --git a/tableauserverclient/models/view_item.py b/tableauserverclient/models/view_item.py index 01635349b..65ce6b858 100644 --- a/tableauserverclient/models/view_item.py +++ b/tableauserverclient/models/view_item.py @@ -5,7 +5,7 @@ from .exceptions import UnpopulatedPropertyError from .tag_item import TagItem -from ..datetime_helpers import parse_datetime +from tableauserverclient.datetime_helpers import parse_datetime if TYPE_CHECKING: from datetime import datetime diff --git a/tableauserverclient/models/workbook_item.py b/tableauserverclient/models/workbook_item.py index 6d9a21b6b..9ecc8b42e 100644 --- a/tableauserverclient/models/workbook_item.py +++ b/tableauserverclient/models/workbook_item.py @@ -14,7 +14,7 @@ ) from .tag_item import TagItem from .view_item import ViewItem -from ..datetime_helpers import parse_datetime +from tableauserverclient.datetime_helpers import parse_datetime if TYPE_CHECKING: diff --git a/tableauserverclient/server/__init__.py b/tableauserverclient/server/__init__.py index 84d118a2e..bcea2604e 100644 --- a/tableauserverclient/server/__init__.py +++ b/tableauserverclient/server/__init__.py @@ -10,56 +10,8 @@ from .filter import Filter from .sort import Sort -from ..models import ( - BackgroundJobItem, - ColumnItem, - ConnectionItem, - DQWItem, - DataAlertItem, - DatabaseItem, - DatasourceItem, - FlowItem, - FlowRunItem, - GroupItem, - JobItem, - PaginationItem, - Permission, - PermissionsRule, - ProjectItem, - RevisionItem, - ScheduleItem, - SiteItem, - SubscriptionItem, - TableItem, - TableauAuth, - TaskItem, - UserItem, - ViewItem, - WebhookItem, - WorkbookItem, - TableauItem, - Resource, - plural_type, -) -from .endpoint import ( - Auth, - DataAlerts, - Datasources, - Endpoint, - Groups, - Projects, - Schedules, - Sites, - Tables, - Users, - Views, - Workbooks, - Subscriptions, - ServerResponseError, - MissingRequiredFieldError, - Flows, - Favorites, -) +from ..models import * +from .endpoint import * from .server import Server from .pager import Pager from .exceptions import NotSignedInError diff --git a/tableauserverclient/server/endpoint/data_acceleration_report_endpoint.py b/tableauserverclient/server/endpoint/data_acceleration_report_endpoint.py index f972c0d60..28e5495c5 100644 --- a/tableauserverclient/server/endpoint/data_acceleration_report_endpoint.py +++ b/tableauserverclient/server/endpoint/data_acceleration_report_endpoint.py @@ -3,7 +3,7 @@ from .default_permissions_endpoint import _DefaultPermissionsEndpoint from .endpoint import api, Endpoint from .permissions_endpoint import _PermissionsEndpoint -from ...models.data_acceleration_report_item import DataAccelerationReportItem +from tableauserverclient.models import DataAccelerationReportItem logger = logging.getLogger("tableau.endpoint.data_acceleration_report") diff --git a/tableauserverclient/server/endpoint/data_alert_endpoint.py b/tableauserverclient/server/endpoint/data_alert_endpoint.py index 8929f8c6a..5af4e0464 100644 --- a/tableauserverclient/server/endpoint/data_alert_endpoint.py +++ b/tableauserverclient/server/endpoint/data_alert_endpoint.py @@ -2,7 +2,8 @@ from .endpoint import api, Endpoint from .exceptions import MissingRequiredFieldError -from .. import RequestFactory, DataAlertItem, PaginationItem, UserItem +from tableauserverclient.server import RequestFactory +from tableauserverclient.models import DataAlertItem, PaginationItem, UserItem logger = logging.getLogger("tableau.endpoint.dataAlerts") diff --git a/tableauserverclient/server/endpoint/databases_endpoint.py b/tableauserverclient/server/endpoint/databases_endpoint.py index aa9d73f18..2522ef53e 100644 --- a/tableauserverclient/server/endpoint/databases_endpoint.py +++ b/tableauserverclient/server/endpoint/databases_endpoint.py @@ -5,7 +5,8 @@ from .endpoint import api, Endpoint from .exceptions import MissingRequiredFieldError from .permissions_endpoint import _PermissionsEndpoint -from .. import RequestFactory, DatabaseItem, TableItem, PaginationItem, Resource +from tableauserverclient.server import RequestFactory +from tableauserverclient.models import DatabaseItem, TableItem, PaginationItem, Resource logger = logging.getLogger("tableau.endpoint.databases") diff --git a/tableauserverclient/server/endpoint/datasources_endpoint.py b/tableauserverclient/server/endpoint/datasources_endpoint.py index 9df7edfc8..95b8b3b82 100644 --- a/tableauserverclient/server/endpoint/datasources_endpoint.py +++ b/tableauserverclient/server/endpoint/datasources_endpoint.py @@ -1,40 +1,49 @@ import cgi import copy -import io import json import logging +import io import os + from contextlib import closing from pathlib import Path -from typing import ( - List, - Mapping, - Optional, - Sequence, - Tuple, - TYPE_CHECKING, - Union, -) +from typing import List, Mapping, Optional, Sequence, Tuple, TYPE_CHECKING, Union + +if TYPE_CHECKING: + from tableauserverclient.server import Server + from tableauserverclient.models import PermissionsRule + from .schedules_endpoint import AddResponse from .dqw_endpoint import _DataQualityWarningEndpoint from .endpoint import QuerysetEndpoint, api, parameter_added_in from .exceptions import InternalServerError, MissingRequiredFieldError from .permissions_endpoint import _PermissionsEndpoint from .resource_tagger import _ResourceTagger -from .. import RequestFactory, DatasourceItem, PaginationItem, ConnectionItem, RequestOptions -from ..query import QuerySet -from ...filesys_helpers import ( + +from tableauserverclient.server import RequestFactory, RequestOptions +from tableauserverclient.filesys_helpers import ( to_filename, make_download_path, get_file_type, get_file_object_size, ) -from ...models import ConnectionCredentials, RevisionItem -from ...models.job_item import JobItem +from tableauserverclient.models import ( + ConnectionCredentials, + ConnectionItem, + DatasourceItem, + JobItem, + RevisionItem, + PaginationItem, +) +io_types = (io.BytesIO, io.BufferedReader) io_types_r = (io.BytesIO, io.BufferedReader) io_types_w = (io.BytesIO, io.BufferedWriter) +FilePath = Union[str, os.PathLike] +FileObject = Union[io.BufferedReader, io.BytesIO] +PathOrFile = Union[FilePath, FileObject] + # The maximum size of a file that can be published in a single request is 64MB FILESIZE_LIMIT = 1024 * 1024 * 64 # 64MB @@ -42,11 +51,6 @@ logger = logging.getLogger("tableau.endpoint.datasources") -if TYPE_CHECKING: - from ..server import Server - from ...models import PermissionsRule - from .schedules_endpoint import AddResponse - FilePath = Union[str, os.PathLike] FileObjectR = Union[io.BufferedReader, io.BytesIO] FileObjectW = Union[io.BufferedWriter, io.BytesIO] diff --git a/tableauserverclient/server/endpoint/default_permissions_endpoint.py b/tableauserverclient/server/endpoint/default_permissions_endpoint.py index 66fc23d49..b0d16efaf 100644 --- a/tableauserverclient/server/endpoint/default_permissions_endpoint.py +++ b/tableauserverclient/server/endpoint/default_permissions_endpoint.py @@ -2,8 +2,8 @@ from .endpoint import Endpoint from .exceptions import MissingRequiredFieldError -from .. import RequestFactory -from ...models import DatabaseItem, PermissionsRule, ProjectItem, plural_type, Resource +from tableauserverclient.server import RequestFactory +from tableauserverclient.models import DatabaseItem, PermissionsRule, ProjectItem, plural_type, Resource from typing import TYPE_CHECKING, Callable, List, Optional, Sequence, Union if TYPE_CHECKING: diff --git a/tableauserverclient/server/endpoint/dqw_endpoint.py b/tableauserverclient/server/endpoint/dqw_endpoint.py index ff1637721..96cb7c5f9 100644 --- a/tableauserverclient/server/endpoint/dqw_endpoint.py +++ b/tableauserverclient/server/endpoint/dqw_endpoint.py @@ -2,7 +2,8 @@ from .endpoint import Endpoint from .exceptions import MissingRequiredFieldError -from .. import RequestFactory, DQWItem +from tableauserverclient.server import RequestFactory +from tableauserverclient.models import DQWItem logger = logging.getLogger(__name__) diff --git a/tableauserverclient/server/endpoint/endpoint.py b/tableauserverclient/server/endpoint/endpoint.py index b1a42b20c..0dbd8cfc2 100644 --- a/tableauserverclient/server/endpoint/endpoint.py +++ b/tableauserverclient/server/endpoint/endpoint.py @@ -3,7 +3,7 @@ from packaging.version import Version from functools import wraps from xml.etree.ElementTree import ParseError -from typing import Any, Callable, Dict, Optional, TYPE_CHECKING, Mapping +from typing import Any, Callable, Dict, Optional, TYPE_CHECKING from .exceptions import ( ServerResponseError, @@ -11,8 +11,8 @@ NonXMLResponseError, EndpointUnavailableError, ) -from ..query import QuerySet -from ... import helpers, get_versions +from tableauserverclient.server.query import QuerySet +from tableauserverclient import helpers, get_versions if TYPE_CHECKING: from ..server import Server diff --git a/tableauserverclient/server/endpoint/favorites_endpoint.py b/tableauserverclient/server/endpoint/favorites_endpoint.py index 19199c5a0..5105b3bf4 100644 --- a/tableauserverclient/server/endpoint/favorites_endpoint.py +++ b/tableauserverclient/server/endpoint/favorites_endpoint.py @@ -1,10 +1,8 @@ import logging from .endpoint import Endpoint, api -from .. import RequestFactory -from ...models import FavoriteItem - -logger = logging.getLogger("tableau.endpoint.favorites") +from tableauserverclient.server import RequestFactory +from tableauserverclient.models import FavoriteItem from typing import Optional, TYPE_CHECKING @@ -12,6 +10,8 @@ from ...models import DatasourceItem, FlowItem, ProjectItem, UserItem, ViewItem, WorkbookItem from ..request_options import RequestOptions +logger = logging.getLogger("tableau.endpoint.favorites") + class Favorites(Endpoint): @property diff --git a/tableauserverclient/server/endpoint/fileuploads_endpoint.py b/tableauserverclient/server/endpoint/fileuploads_endpoint.py index 3df8ee4d5..9a8e9560d 100644 --- a/tableauserverclient/server/endpoint/fileuploads_endpoint.py +++ b/tableauserverclient/server/endpoint/fileuploads_endpoint.py @@ -1,8 +1,8 @@ import logging from .endpoint import Endpoint, api -from .. import RequestFactory -from ...models.fileupload_item import FileuploadItem +from tableauserverclient.server import RequestFactory +from tableauserverclient.models import FileuploadItem # For when a datasource is over 64MB, break it into 5MB(standard chunk size) chunks CHUNK_SIZE = 1024 * 1024 * 5 # 5MB diff --git a/tableauserverclient/server/endpoint/flow_runs_endpoint.py b/tableauserverclient/server/endpoint/flow_runs_endpoint.py index 62f910dea..3bca93a7f 100644 --- a/tableauserverclient/server/endpoint/flow_runs_endpoint.py +++ b/tableauserverclient/server/endpoint/flow_runs_endpoint.py @@ -3,8 +3,8 @@ from .endpoint import QuerysetEndpoint, api from .exceptions import FlowRunFailedException, FlowRunCancelledException -from .. import FlowRunItem, PaginationItem -from ...exponential_backoff import ExponentialBackoffTimer +from tableauserverclient.models import FlowRunItem, PaginationItem +from tableauserverclient.exponential_backoff import ExponentialBackoffTimer logger = logging.getLogger("tableau.endpoint.flowruns") diff --git a/tableauserverclient/server/endpoint/flows_endpoint.py b/tableauserverclient/server/endpoint/flows_endpoint.py index 5b182111b..be5b81674 100644 --- a/tableauserverclient/server/endpoint/flows_endpoint.py +++ b/tableauserverclient/server/endpoint/flows_endpoint.py @@ -8,18 +8,18 @@ from typing import Iterable, List, Optional, TYPE_CHECKING, Tuple, Union from .dqw_endpoint import _DataQualityWarningEndpoint -from .endpoint import Endpoint, QuerysetEndpoint, api +from .endpoint import QuerysetEndpoint, api from .exceptions import InternalServerError, MissingRequiredFieldError from .permissions_endpoint import _PermissionsEndpoint from .resource_tagger import _ResourceTagger -from .. import RequestFactory, FlowItem, PaginationItem, ConnectionItem -from ...filesys_helpers import ( +from tableauserverclient.models import FlowItem, PaginationItem, ConnectionItem, JobItem +from tableauserverclient.server import RequestFactory +from tableauserverclient.filesys_helpers import ( to_filename, make_download_path, get_file_type, get_file_object_size, ) -from ...models.job_item import JobItem io_types_r = (io.BytesIO, io.BufferedReader) io_types_w = (io.BytesIO, io.BufferedWriter) diff --git a/tableauserverclient/server/endpoint/groups_endpoint.py b/tableauserverclient/server/endpoint/groups_endpoint.py index 289ccdb11..ba5b6649b 100644 --- a/tableauserverclient/server/endpoint/groups_endpoint.py +++ b/tableauserverclient/server/endpoint/groups_endpoint.py @@ -2,7 +2,8 @@ from .endpoint import QuerysetEndpoint, api from .exceptions import MissingRequiredFieldError -from .. import RequestFactory, GroupItem, UserItem, PaginationItem, JobItem +from tableauserverclient.server import RequestFactory +from tableauserverclient.models import GroupItem, UserItem, PaginationItem, JobItem from ..pager import Pager logger = logging.getLogger("tableau.endpoint.groups") diff --git a/tableauserverclient/server/endpoint/jobs_endpoint.py b/tableauserverclient/server/endpoint/jobs_endpoint.py index 6b709efad..dd210d990 100644 --- a/tableauserverclient/server/endpoint/jobs_endpoint.py +++ b/tableauserverclient/server/endpoint/jobs_endpoint.py @@ -2,9 +2,9 @@ from .endpoint import QuerysetEndpoint, api from .exceptions import JobCancelledException, JobFailedException -from .. import JobItem, BackgroundJobItem, PaginationItem +from tableauserverclient.models import JobItem, BackgroundJobItem, PaginationItem from ..request_options import RequestOptionsBase -from ...exponential_backoff import ExponentialBackoffTimer +from tableauserverclient.exponential_backoff import ExponentialBackoffTimer logger = logging.getLogger("tableau.endpoint.jobs") diff --git a/tableauserverclient/server/endpoint/metrics_endpoint.py b/tableauserverclient/server/endpoint/metrics_endpoint.py index fba2632a4..8443726cd 100644 --- a/tableauserverclient/server/endpoint/metrics_endpoint.py +++ b/tableauserverclient/server/endpoint/metrics_endpoint.py @@ -3,11 +3,10 @@ from .permissions_endpoint import _PermissionsEndpoint from .dqw_endpoint import _DataQualityWarningEndpoint from .resource_tagger import _ResourceTagger -from .. import RequestFactory, PaginationItem -from ...models.metric_item import MetricItem +from tableauserverclient.server import RequestFactory +from tableauserverclient.models import MetricItem, PaginationItem import logging -import copy from typing import List, Optional, TYPE_CHECKING, Tuple diff --git a/tableauserverclient/server/endpoint/permissions_endpoint.py b/tableauserverclient/server/endpoint/permissions_endpoint.py index e3e9af2a6..e50e32945 100644 --- a/tableauserverclient/server/endpoint/permissions_endpoint.py +++ b/tableauserverclient/server/endpoint/permissions_endpoint.py @@ -1,12 +1,12 @@ import logging -from .. import RequestFactory, PermissionsRule +from tableauserverclient.server import RequestFactory +from tableauserverclient.models import TableauItem, PermissionsRule from .endpoint import Endpoint from .exceptions import MissingRequiredFieldError -from ...models import TableauItem -from typing import Optional, Callable, TYPE_CHECKING, List, Union +from typing import Callable, TYPE_CHECKING, List, Optional, Union logger = logging.getLogger(__name__) diff --git a/tableauserverclient/server/endpoint/projects_endpoint.py b/tableauserverclient/server/endpoint/projects_endpoint.py index 7ccdcd775..440940606 100644 --- a/tableauserverclient/server/endpoint/projects_endpoint.py +++ b/tableauserverclient/server/endpoint/projects_endpoint.py @@ -4,7 +4,8 @@ from .endpoint import QuerysetEndpoint, api, XML_CONTENT_TYPE from .exceptions import MissingRequiredFieldError from .permissions_endpoint import _PermissionsEndpoint -from .. import RequestFactory, RequestOptions, ProjectItem, PaginationItem, Resource +from tableauserverclient.server import RequestFactory, RequestOptions +from tableauserverclient.models import ProjectItem, PaginationItem, Resource from typing import List, Optional, Tuple, TYPE_CHECKING diff --git a/tableauserverclient/server/endpoint/resource_tagger.py b/tableauserverclient/server/endpoint/resource_tagger.py index d5bc4dccb..18c38798e 100644 --- a/tableauserverclient/server/endpoint/resource_tagger.py +++ b/tableauserverclient/server/endpoint/resource_tagger.py @@ -4,8 +4,8 @@ from .endpoint import Endpoint from .exceptions import EndpointUnavailableError, ServerResponseError -from .. import RequestFactory -from ...models.tag_item import TagItem +from tableauserverclient.server import RequestFactory +from tableauserverclient.models import TagItem logger = logging.getLogger("tableau.endpoint.resource_tagger") diff --git a/tableauserverclient/server/endpoint/schedules_endpoint.py b/tableauserverclient/server/endpoint/schedules_endpoint.py index 65a55bcb6..b98362972 100644 --- a/tableauserverclient/server/endpoint/schedules_endpoint.py +++ b/tableauserverclient/server/endpoint/schedules_endpoint.py @@ -6,7 +6,8 @@ from .endpoint import Endpoint, api, parameter_added_in from .exceptions import MissingRequiredFieldError -from .. import RequestFactory, PaginationItem, ScheduleItem, TaskItem +from tableauserverclient.server import RequestFactory +from tableauserverclient.models import PaginationItem, ScheduleItem, TaskItem logger = logging.getLogger("tableau.endpoint.schedules") AddResponse = namedtuple("AddResponse", ("result", "error", "warnings", "task_created")) diff --git a/tableauserverclient/server/endpoint/server_info_endpoint.py b/tableauserverclient/server/endpoint/server_info_endpoint.py index 943aabee6..d9611736a 100644 --- a/tableauserverclient/server/endpoint/server_info_endpoint.py +++ b/tableauserverclient/server/endpoint/server_info_endpoint.py @@ -6,7 +6,7 @@ ServerInfoEndpointNotFoundError, EndpointUnavailableError, ) -from ...models import ServerInfoItem +from tableauserverclient.models import ServerInfoItem logger = logging.getLogger("tableau.endpoint.server_info") diff --git a/tableauserverclient/server/endpoint/sites_endpoint.py b/tableauserverclient/server/endpoint/sites_endpoint.py index 67d7db209..a4c765484 100644 --- a/tableauserverclient/server/endpoint/sites_endpoint.py +++ b/tableauserverclient/server/endpoint/sites_endpoint.py @@ -3,7 +3,8 @@ from .endpoint import Endpoint, api from .exceptions import MissingRequiredFieldError -from .. import RequestFactory, SiteItem, PaginationItem +from tableauserverclient.server import RequestFactory +from tableauserverclient.models import SiteItem, PaginationItem logger = logging.getLogger("tableau.endpoint.sites") diff --git a/tableauserverclient/server/endpoint/subscriptions_endpoint.py b/tableauserverclient/server/endpoint/subscriptions_endpoint.py index 6b929524e..a81a2fbf0 100644 --- a/tableauserverclient/server/endpoint/subscriptions_endpoint.py +++ b/tableauserverclient/server/endpoint/subscriptions_endpoint.py @@ -2,7 +2,8 @@ from .endpoint import Endpoint, api from .exceptions import MissingRequiredFieldError -from .. import RequestFactory, SubscriptionItem, PaginationItem +from tableauserverclient.server import RequestFactory +from tableauserverclient.models import SubscriptionItem, PaginationItem logger = logging.getLogger("tableau.endpoint.subscriptions") diff --git a/tableauserverclient/server/endpoint/tables_endpoint.py b/tableauserverclient/server/endpoint/tables_endpoint.py index e41ab07ca..e51f885d7 100644 --- a/tableauserverclient/server/endpoint/tables_endpoint.py +++ b/tableauserverclient/server/endpoint/tables_endpoint.py @@ -4,7 +4,8 @@ from .endpoint import api, Endpoint from .exceptions import MissingRequiredFieldError from .permissions_endpoint import _PermissionsEndpoint -from .. import RequestFactory, TableItem, ColumnItem, PaginationItem +from tableauserverclient.server import RequestFactory +from tableauserverclient.models import TableItem, ColumnItem, PaginationItem from ..pager import Pager logger = logging.getLogger("tableau.endpoint.tables") diff --git a/tableauserverclient/server/endpoint/tasks_endpoint.py b/tableauserverclient/server/endpoint/tasks_endpoint.py index a70480b91..b903ac634 100644 --- a/tableauserverclient/server/endpoint/tasks_endpoint.py +++ b/tableauserverclient/server/endpoint/tasks_endpoint.py @@ -2,7 +2,8 @@ from .endpoint import Endpoint, api from .exceptions import MissingRequiredFieldError -from .. import TaskItem, PaginationItem, RequestFactory +from tableauserverclient.models import TaskItem, PaginationItem +from tableauserverclient.server import RequestFactory logger = logging.getLogger("tableau.endpoint.tasks") diff --git a/tableauserverclient/server/endpoint/users_endpoint.py b/tableauserverclient/server/endpoint/users_endpoint.py index 3faf4d173..5a9c74619 100644 --- a/tableauserverclient/server/endpoint/users_endpoint.py +++ b/tableauserverclient/server/endpoint/users_endpoint.py @@ -1,16 +1,13 @@ import copy import logging -import os -from typing import List, Optional, Tuple, Union +from typing import List, Optional, Tuple from .endpoint import QuerysetEndpoint, api from .exceptions import MissingRequiredFieldError, ServerResponseError -from .. import RequestFactory, RequestOptions, UserItem, WorkbookItem, PaginationItem, GroupItem +from tableauserverclient.server import RequestFactory, RequestOptions +from tableauserverclient.models import UserItem, WorkbookItem, PaginationItem, GroupItem from ..pager import Pager -# duplicate defined in workbooks_endpoint -FilePath = Union[str, os.PathLike] - logger = logging.getLogger("tableau.endpoint.users") diff --git a/tableauserverclient/server/endpoint/views_endpoint.py b/tableauserverclient/server/endpoint/views_endpoint.py index 06cc08349..c060298ba 100644 --- a/tableauserverclient/server/endpoint/views_endpoint.py +++ b/tableauserverclient/server/endpoint/views_endpoint.py @@ -5,7 +5,7 @@ from .exceptions import MissingRequiredFieldError from .permissions_endpoint import _PermissionsEndpoint from .resource_tagger import _ResourceTagger -from .. import ViewItem, PaginationItem +from tableauserverclient.models import ViewItem, PaginationItem logger = logging.getLogger("tableau.endpoint.views") diff --git a/tableauserverclient/server/endpoint/webhooks_endpoint.py b/tableauserverclient/server/endpoint/webhooks_endpoint.py index b28f3e5f1..69a958988 100644 --- a/tableauserverclient/server/endpoint/webhooks_endpoint.py +++ b/tableauserverclient/server/endpoint/webhooks_endpoint.py @@ -1,8 +1,8 @@ import logging from .endpoint import Endpoint, api -from .. import RequestFactory -from ...models import WebhookItem, PaginationItem +from tableauserverclient.server import RequestFactory +from tableauserverclient.models import WebhookItem, PaginationItem logger = logging.getLogger("tableau.endpoint.webhooks") diff --git a/tableauserverclient/server/endpoint/workbooks_endpoint.py b/tableauserverclient/server/endpoint/workbooks_endpoint.py index 8cca4150a..a240f483b 100644 --- a/tableauserverclient/server/endpoint/workbooks_endpoint.py +++ b/tableauserverclient/server/endpoint/workbooks_endpoint.py @@ -5,29 +5,21 @@ import os from contextlib import closing from pathlib import Path -from typing import ( - List, - Optional, - Sequence, - Tuple, - TYPE_CHECKING, - Union, -) from .endpoint import QuerysetEndpoint, api, parameter_added_in from .exceptions import InternalServerError, MissingRequiredFieldError -from ...helpers import redact_xml from .permissions_endpoint import _PermissionsEndpoint from .resource_tagger import _ResourceTagger -from .. import RequestFactory, WorkbookItem, ConnectionItem, ViewItem, PaginationItem -from ...filesys_helpers import ( + +from tableauserverclient.filesys_helpers import ( to_filename, make_download_path, get_file_type, get_file_object_size, ) -from ...models.job_item import JobItem -from ...models.revision_item import RevisionItem +from tableauserverclient.helpers import redact_xml +from tableauserverclient.models import WorkbookItem, ConnectionItem, ViewItem, PaginationItem, JobItem, RevisionItem +from tableauserverclient.server import RequestFactory from typing import ( List, @@ -39,10 +31,9 @@ ) if TYPE_CHECKING: - from ..server import Server - from ..request_options import RequestOptions - from .. import DatasourceItem - from ...models.connection_credentials import ConnectionCredentials + from tableauserverclient.server import Server + from tableauserverclient.server.request_options import RequestOptions + from tableauserverclient.models import DatasourceItem, ConnectionCredentials from .schedules_endpoint import AddResponse io_types_r = (io.BytesIO, io.BufferedReader) diff --git a/tableauserverclient/server/request_factory.py b/tableauserverclient/server/request_factory.py index 720eb4085..fb8e057ad 100644 --- a/tableauserverclient/server/request_factory.py +++ b/tableauserverclient/server/request_factory.py @@ -1,29 +1,12 @@ -from os import name import xml.etree.ElementTree as ET from typing import Any, Dict, Iterable, List, Optional, Tuple, TYPE_CHECKING from requests.packages.urllib3.fields import RequestField from requests.packages.urllib3.filepost import encode_multipart_formdata -from tableauserverclient.models.metric_item import MetricItem - -from ..models import ConnectionCredentials -from ..models import ConnectionItem -from ..models import DataAlertItem -from ..models import FlowItem -from ..models import ProjectItem -from ..models import SiteItem -from ..models import SubscriptionItem -from ..models import TaskItem, UserItem, GroupItem, PermissionsRule, FavoriteItem -from ..models import WebhookItem +from tableauserverclient.models import * if TYPE_CHECKING: - from ..models import SubscriptionItem - from ..models import DataAlertItem - from ..models import FlowItem - from ..models import ConnectionItem - from ..models import SiteItem - from ..models import ProjectItem from tableauserverclient.server import Server diff --git a/tableauserverclient/server/request_options.py b/tableauserverclient/server/request_options.py index f4ed8fd3c..baedd74de 100644 --- a/tableauserverclient/server/request_options.py +++ b/tableauserverclient/server/request_options.py @@ -1,4 +1,4 @@ -from ..models.property_decorators import property_is_int +from tableauserverclient.models.property_decorators import property_is_int import logging logger = logging.getLogger("tableau.request_options") diff --git a/test/test_workbook.py b/test/test_workbook.py index 2e5de9369..772dcbdb0 100644 --- a/test/test_workbook.py +++ b/test/test_workbook.py @@ -1,20 +1,15 @@ import os import re import requests_mock -import tableauserverclient as TSC import tempfile import unittest -import xml.etree.ElementTree as ET - from defusedxml.ElementTree import fromstring from io import BytesIO from pathlib import Path import tableauserverclient as TSC from tableauserverclient.datetime_helpers import format_datetime -from tableauserverclient.models.group_item import GroupItem -from tableauserverclient.models.permissions_item import PermissionsRule -from tableauserverclient.models.user_item import UserItem +from tableauserverclient.models import UserItem, GroupItem, PermissionsRule from tableauserverclient.server.endpoint.exceptions import InternalServerError from tableauserverclient.server.request_factory import RequestFactory from ._utils import asset From f740e12a6b4c2caa7bd4dd76eeab29635ea6eaf5 Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Tue, 14 Feb 2023 18:57:59 -0800 Subject: [PATCH 2/6] IntelliJ optimize imports also some manual work, to find places where imports are unnecessarily hidden behind if TYPE_CHECKING TODO: split out code into a new module for interface code like Pagination that needs to be referred to by both server and models. Goal: zero direct imports between models and server. --- tableauserverclient/models/__init__.py | 2 +- tableauserverclient/models/connection_item.py | 8 ++--- tableauserverclient/models/data_alert_item.py | 20 ++++------- tableauserverclient/models/datasource_item.py | 36 +++++++------------ tableauserverclient/models/flow_item.py | 28 +++++++-------- tableauserverclient/models/flow_run_item.py | 19 ++++------ tableauserverclient/models/job_item.py | 36 +++++++++---------- tableauserverclient/models/metric_item.py | 15 ++++---- .../models/permissions_item.py | 12 +++---- tableauserverclient/models/project_item.py | 3 +- tableauserverclient/models/revision_item.py | 10 +++--- tableauserverclient/models/schedule_item.py | 2 +- tableauserverclient/models/site_item.py | 1 + tableauserverclient/models/tableau_types.py | 14 ++++---- tableauserverclient/models/tag_item.py | 3 +- tableauserverclient/models/task_item.py | 2 +- tableauserverclient/models/user_item.py | 12 +++---- tableauserverclient/models/view_item.py | 24 ++++++------- tableauserverclient/models/workbook_item.py | 33 ++++++----------- 19 files changed, 114 insertions(+), 166 deletions(-) diff --git a/tableauserverclient/models/__init__.py b/tableauserverclient/models/__init__.py index a7b025fda..4b817f865 100644 --- a/tableauserverclient/models/__init__.py +++ b/tableauserverclient/models/__init__.py @@ -8,9 +8,9 @@ from .dqw_item import DQWItem from .exceptions import UnpopulatedPropertyError from .favorites_item import FavoriteItem +from .fileupload_item import FileuploadItem from .flow_item import FlowItem from .flow_run_item import FlowRunItem -from .fileupload_item import FileuploadItem from .group_item import GroupItem from .interval_item import ( IntervalItem, diff --git a/tableauserverclient/models/connection_item.py b/tableauserverclient/models/connection_item.py index ed7733076..3b2255a3b 100644 --- a/tableauserverclient/models/connection_item.py +++ b/tableauserverclient/models/connection_item.py @@ -1,11 +1,9 @@ -from typing import TYPE_CHECKING, List, Optional +from typing import List, Optional + from defusedxml.ElementTree import fromstring from .connection_credentials import ConnectionCredentials -if TYPE_CHECKING: - from tableauserverclient.models.connection_credentials import ConnectionCredentials - class ConnectionItem(object): def __init__(self): @@ -18,7 +16,7 @@ def __init__(self): self.server_address: Optional[str] = None self.server_port: Optional[str] = None self.username: Optional[str] = None - self.connection_credentials: Optional["ConnectionCredentials"] = None + self.connection_credentials: Optional[ConnectionCredentials] = None @property def datasource_id(self) -> Optional[str]: diff --git a/tableauserverclient/models/data_alert_item.py b/tableauserverclient/models/data_alert_item.py index 3882d14eb..65be233e3 100644 --- a/tableauserverclient/models/data_alert_item.py +++ b/tableauserverclient/models/data_alert_item.py @@ -1,4 +1,5 @@ -from typing import List, Optional, TYPE_CHECKING +from datetime import datetime +from typing import List, Optional from defusedxml.ElementTree import fromstring @@ -8,15 +9,6 @@ property_is_boolean, ) -if TYPE_CHECKING: - from datetime import datetime - - -from typing import List, Optional, TYPE_CHECKING - -if TYPE_CHECKING: - from datetime import datetime - class DataAlertItem(object): class Frequency: @@ -30,8 +22,8 @@ def __init__(self): self._id: Optional[str] = None self._subject: Optional[str] = None self._creatorId: Optional[str] = None - self._createdAt: Optional["datetime"] = None - self._updatedAt: Optional["datetime"] = None + self._createdAt: Optional[datetime] = None + self._updatedAt: Optional[datetime] = None self._frequency: Optional[str] = None self._public: Optional[bool] = None self._owner_id: Optional[str] = None @@ -90,11 +82,11 @@ def recipients(self) -> List[str]: return self._recipients or list() @property - def createdAt(self) -> Optional["datetime"]: + def createdAt(self) -> Optional[datetime]: return self._createdAt @property - def updatedAt(self) -> Optional["datetime"]: + def updatedAt(self) -> Optional[datetime]: return self._updatedAt @property diff --git a/tableauserverclient/models/datasource_item.py b/tableauserverclient/models/datasource_item.py index ced008506..b84006f06 100644 --- a/tableauserverclient/models/datasource_item.py +++ b/tableauserverclient/models/datasource_item.py @@ -1,31 +1,21 @@ import copy +import datetime import xml.etree.ElementTree as ET -from typing import Dict, List, Optional, Set, Tuple, TYPE_CHECKING +from typing import Dict, List, Optional, Set, Tuple from defusedxml.ElementTree import fromstring +from tableauserverclient.datetime_helpers import parse_datetime +from .connection_item import ConnectionItem from .exceptions import UnpopulatedPropertyError +from .permissions_item import PermissionsRule from .property_decorators import ( property_not_nullable, property_is_boolean, property_is_enum, ) +from .revision_item import RevisionItem from .tag_item import TagItem -from tableauserverclient.datetime_helpers import parse_datetime - -if TYPE_CHECKING: - from .permissions_item import PermissionsRule - from .connection_item import ConnectionItem - from .revision_item import RevisionItem - import datetime - -from typing import Dict, List, Optional, Set, Tuple, TYPE_CHECKING, Union - -if TYPE_CHECKING: - from .permissions_item import PermissionsRule - from .connection_item import ConnectionItem - from .revision_item import RevisionItem - import datetime class DatasourceItem(object): @@ -64,23 +54,23 @@ def __init__(self, project_id: str, name: Optional[str] = None) -> None: return None @property - def ask_data_enablement(self) -> Optional["DatasourceItem.AskDataEnablement"]: + def ask_data_enablement(self) -> Optional[AskDataEnablement]: return self._ask_data_enablement @ask_data_enablement.setter @property_is_enum(AskDataEnablement) - def ask_data_enablement(self, value: Optional["DatasourceItem.AskDataEnablement"]): + def ask_data_enablement(self, value: Optional[AskDataEnablement]): self._ask_data_enablement = value @property - def connections(self) -> Optional[List["ConnectionItem"]]: + def connections(self) -> Optional[List[ConnectionItem]]: if self._connections is None: error = "Datasource item must be populated with connections first." raise UnpopulatedPropertyError(error) return self._connections() @property - def permissions(self) -> Optional[List["PermissionsRule"]]: + def permissions(self) -> Optional[List[PermissionsRule]]: if self._permissions is None: error = "Project item must be populated with permissions first." raise UnpopulatedPropertyError(error) @@ -91,7 +81,7 @@ def content_url(self) -> Optional[str]: return self._content_url @property - def created_at(self) -> Optional["datetime.datetime"]: + def created_at(self) -> Optional[datetime.datetime]: return self._created_at @property @@ -162,7 +152,7 @@ def description(self, value: str): self._description = value @property - def updated_at(self) -> Optional["datetime.datetime"]: + def updated_at(self) -> Optional[datetime.datetime]: return self._updated_at @property @@ -179,7 +169,7 @@ def webpage_url(self) -> Optional[str]: return self._webpage_url @property - def revisions(self) -> List["RevisionItem"]: + def revisions(self) -> List[RevisionItem]: if self._revisions is None: error = "Datasource item must be populated with revisions first." raise UnpopulatedPropertyError(error) diff --git a/tableauserverclient/models/flow_item.py b/tableauserverclient/models/flow_item.py index 1f153bd78..f9a7b963b 100644 --- a/tableauserverclient/models/flow_item.py +++ b/tableauserverclient/models/flow_item.py @@ -1,38 +1,36 @@ import copy +import datetime import xml.etree.ElementTree as ET -from typing import List, Optional, TYPE_CHECKING, Set +from typing import List, Optional, Set from defusedxml.ElementTree import fromstring +from tableauserverclient.datetime_helpers import parse_datetime +from .connection_item import ConnectionItem +from .dqw_item import DQWItem from .exceptions import UnpopulatedPropertyError +from .permissions_item import Permission from .property_decorators import property_not_nullable from .tag_item import TagItem -from tableauserverclient.datetime_helpers import parse_datetime - -if TYPE_CHECKING: - import datetime - from .connection_item import ConnectionItem - from .permissions_item import Permission - from .dqw_item import DQWItem class FlowItem(object): def __init__(self, project_id: str, name: Optional[str] = None) -> None: self._webpage_url: Optional[str] = None - self._created_at: Optional["datetime.datetime"] = None + self._created_at: Optional[datetime.datetime] = None self._id: Optional[str] = None self._initial_tags: Set[str] = set() self._project_name: Optional[str] = None - self._updated_at: Optional["datetime.datetime"] = None + self._updated_at: Optional[datetime.datetime] = None self.name: Optional[str] = name self.owner_id: Optional[str] = None self.project_id: str = project_id self.tags: Set[str] = set() self.description: Optional[str] = None - self._connections = None - self._permissions = None - self._data_quality_warnings = None + self._connections: Optional[ConnectionItem] = None + self._permissions: Optional[Permission] = None + self._data_quality_warnings: Optional[DQWItem] = None @property def connections(self): @@ -53,7 +51,7 @@ def webpage_url(self) -> Optional[str]: return self._webpage_url @property - def created_at(self) -> Optional["datetime.datetime"]: + def created_at(self) -> Optional[datetime.datetime]: return self._created_at @property @@ -89,7 +87,7 @@ def project_name(self) -> Optional[str]: return self._project_name @property - def updated_at(self) -> Optional["datetime.datetime"]: + def updated_at(self) -> Optional[datetime.datetime]: return self._updated_at def _set_connections(self, connections): diff --git a/tableauserverclient/models/flow_run_item.py b/tableauserverclient/models/flow_run_item.py index a457f51a2..12281f4f8 100644 --- a/tableauserverclient/models/flow_run_item.py +++ b/tableauserverclient/models/flow_run_item.py @@ -1,26 +1,19 @@ import itertools -from typing import Dict, List, Optional, Type, TYPE_CHECKING +from datetime import datetime +from typing import Dict, List, Optional, Type from defusedxml.ElementTree import fromstring from tableauserverclient.datetime_helpers import parse_datetime -if TYPE_CHECKING: - from datetime import datetime - -from typing import Dict, List, Optional, Type, TYPE_CHECKING - -if TYPE_CHECKING: - from datetime import datetime - class FlowRunItem(object): def __init__(self) -> None: self._id: str = "" self._flow_id: Optional[str] = None self._status: Optional[str] = None - self._started_at: Optional["datetime"] = None - self._completed_at: Optional["datetime"] = None + self._started_at: Optional[datetime] = None + self._completed_at: Optional[datetime] = None self._progress: Optional[str] = None self._background_job_id: Optional[str] = None @@ -37,11 +30,11 @@ def status(self) -> Optional[str]: return self._status @property - def started_at(self) -> Optional["datetime"]: + def started_at(self) -> Optional[datetime]: return self._started_at @property - def completed_at(self) -> Optional["datetime"]: + def completed_at(self) -> Optional[datetime]: return self._completed_at @property diff --git a/tableauserverclient/models/job_item.py b/tableauserverclient/models/job_item.py index 650db38c5..5a2636246 100644 --- a/tableauserverclient/models/job_item.py +++ b/tableauserverclient/models/job_item.py @@ -1,12 +1,10 @@ -from typing import List, Optional, TYPE_CHECKING +import datetime +from typing import List, Optional from defusedxml.ElementTree import fromstring -from .flow_run_item import FlowRunItem from tableauserverclient.datetime_helpers import parse_datetime - -if TYPE_CHECKING: - import datetime +from .flow_run_item import FlowRunItem class JobItem(object): @@ -25,16 +23,16 @@ def __init__( id_: str, job_type: str, progress: str, - created_at: "datetime.datetime", - started_at: Optional["datetime.datetime"] = None, - completed_at: Optional["datetime.datetime"] = None, + created_at: datetime.datetime, + started_at: Optional[datetime.datetime] = None, + completed_at: Optional[datetime.datetime] = None, finish_code: int = 0, notes: Optional[List[str]] = None, mode: Optional[str] = None, workbook_id: Optional[str] = None, datasource_id: Optional[str] = None, flow_run: Optional[FlowRunItem] = None, - updated_at: Optional["datetime.datetime"] = None, + updated_at: Optional[datetime.datetime] = None, ): self._id = id_ self._type = job_type @@ -63,15 +61,15 @@ def progress(self) -> str: return self._progress @property - def created_at(self) -> "datetime.datetime": + def created_at(self) -> datetime.datetime: return self._created_at @property - def started_at(self) -> Optional["datetime.datetime"]: + def started_at(self) -> Optional[datetime.datetime]: return self._started_at @property - def completed_at(self) -> Optional["datetime.datetime"]: + def completed_at(self) -> Optional[datetime.datetime]: return self._completed_at @property @@ -116,7 +114,7 @@ def flow_run(self, value): self._flow_run = value @property - def updated_at(self) -> Optional["datetime.datetime"]: + def updated_at(self) -> Optional[datetime.datetime]: return self._updated_at def __repr__(self): @@ -185,14 +183,14 @@ class Status: def __init__( self, id_: str, - created_at: "datetime.datetime", + created_at: datetime.datetime, priority: int, job_type: str, status: str, title: Optional[str] = None, subtitle: Optional[str] = None, - started_at: Optional["datetime.datetime"] = None, - ended_at: Optional["datetime.datetime"] = None, + started_at: Optional[datetime.datetime] = None, + ended_at: Optional[datetime.datetime] = None, ): self._id = id_ self._type = job_type @@ -223,15 +221,15 @@ def type(self) -> str: return self._type @property - def created_at(self) -> "datetime.datetime": + def created_at(self) -> datetime.datetime: return self._created_at @property - def started_at(self) -> Optional["datetime.datetime"]: + def started_at(self) -> Optional[datetime.datetime]: return self._started_at @property - def ended_at(self) -> Optional["datetime.datetime"]: + def ended_at(self) -> Optional[datetime.datetime]: return self._ended_at @property diff --git a/tableauserverclient/models/metric_item.py b/tableauserverclient/models/metric_item.py index b650c0656..4adc73fa8 100644 --- a/tableauserverclient/models/metric_item.py +++ b/tableauserverclient/models/metric_item.py @@ -1,11 +1,10 @@ import xml.etree.ElementTree as ET +from datetime import datetime +from typing import List, Optional, Set + from tableauserverclient.datetime_helpers import parse_datetime from .property_decorators import property_is_boolean, property_is_datetime from .tag_item import TagItem -from typing import List, Optional, TYPE_CHECKING, Set - -if TYPE_CHECKING: - from datetime import datetime class MetricItem(object): @@ -14,8 +13,8 @@ def __init__(self, name: Optional[str] = None): self._name: Optional[str] = name self._description: Optional[str] = None self._webpage_url: Optional[str] = None - self._created_at: Optional["datetime"] = None - self._updated_at: Optional["datetime"] = None + self._created_at: Optional[datetime] = None + self._updated_at: Optional[datetime] = None self._suspended: Optional[bool] = None self._project_id: Optional[str] = None self._project_name: Optional[str] = None @@ -53,7 +52,7 @@ def webpage_url(self) -> Optional[str]: return self._webpage_url @property - def created_at(self) -> Optional["datetime"]: + def created_at(self) -> Optional[datetime]: return self._created_at @created_at.setter @@ -62,7 +61,7 @@ def created_at(self, value: "datetime") -> None: self._created_at = value @property - def updated_at(self) -> Optional["datetime"]: + def updated_at(self) -> Optional[datetime]: return self._updated_at @updated_at.setter diff --git a/tableauserverclient/models/permissions_item.py b/tableauserverclient/models/permissions_item.py index 74b167e9d..3bdc63092 100644 --- a/tableauserverclient/models/permissions_item.py +++ b/tableauserverclient/models/permissions_item.py @@ -1,18 +1,16 @@ import logging import xml.etree.ElementTree as ET +from typing import Dict, List, Optional from defusedxml.ElementTree import fromstring + from .exceptions import UnknownGranteeTypeError, UnpopulatedPropertyError from .group_item import GroupItem +from .reference_item import ResourceReference from .user_item import UserItem logger = logging.getLogger("tableau.models.permissions_item") -from typing import Dict, List, Optional, TYPE_CHECKING - -if TYPE_CHECKING: - from .reference_item import ResourceReference - class Permission: class Mode: @@ -43,7 +41,7 @@ class Capability: class PermissionsRule(object): - def __init__(self, grantee: "ResourceReference", capabilities: Dict[str, str]) -> None: + def __init__(self, grantee: ResourceReference, capabilities: Dict[str, str]) -> None: self.grantee = grantee self.capabilities = capabilities @@ -80,7 +78,7 @@ def from_response(cls, resp, ns=None) -> List["PermissionsRule"]: return rules @staticmethod - def _parse_grantee_element(grantee_capability_xml: ET.Element, ns: Optional[Dict[str, str]]) -> "ResourceReference": + def _parse_grantee_element(grantee_capability_xml: ET.Element, ns: Optional[Dict[str, str]]) -> ResourceReference: """Use Xpath magic and some string splitting to get the right object type from the xml""" # Get the first element in the tree with an 'id' attribute diff --git a/tableauserverclient/models/project_item.py b/tableauserverclient/models/project_item.py index a8430bfd0..18931dbdf 100644 --- a/tableauserverclient/models/project_item.py +++ b/tableauserverclient/models/project_item.py @@ -1,13 +1,12 @@ import logging import xml.etree.ElementTree as ET +from typing import List, Optional from defusedxml.ElementTree import fromstring from .exceptions import UnpopulatedPropertyError from .property_decorators import property_is_enum, property_not_empty -from typing import List, Optional - class ProjectItem(object): class ContentPermissions: diff --git a/tableauserverclient/models/revision_item.py b/tableauserverclient/models/revision_item.py index 6696fb550..a0e6a1bd5 100644 --- a/tableauserverclient/models/revision_item.py +++ b/tableauserverclient/models/revision_item.py @@ -1,12 +1,10 @@ -from typing import List, Optional, TYPE_CHECKING +from datetime import datetime +from typing import List, Optional from defusedxml.ElementTree import fromstring from tableauserverclient.datetime_helpers import parse_datetime -if TYPE_CHECKING: - from datetime import datetime - class RevisionItem(object): def __init__(self): @@ -15,7 +13,7 @@ def __init__(self): self._revision_number: Optional[str] = None self._current: Optional[bool] = None self._deleted: Optional[bool] = None - self._created_at: Optional["datetime"] = None + self._created_at: Optional[datetime] = None self._user_id: Optional[str] = None self._user_name: Optional[str] = None @@ -40,7 +38,7 @@ def deleted(self) -> Optional[bool]: return self._deleted @property - def created_at(self) -> Optional["datetime"]: + def created_at(self) -> Optional[datetime]: return self._created_at @property diff --git a/tableauserverclient/models/schedule_item.py b/tableauserverclient/models/schedule_item.py index 7408707c3..54e4badbe 100644 --- a/tableauserverclient/models/schedule_item.py +++ b/tableauserverclient/models/schedule_item.py @@ -4,6 +4,7 @@ from defusedxml.ElementTree import fromstring +from tableauserverclient.datetime_helpers import parse_datetime from .interval_item import ( IntervalItem, HourlyInterval, @@ -16,7 +17,6 @@ property_not_nullable, property_is_int, ) -from tableauserverclient.datetime_helpers import parse_datetime Interval = Union[HourlyInterval, DailyInterval, WeeklyInterval, MonthlyInterval] diff --git a/tableauserverclient/models/site_item.py b/tableauserverclient/models/site_item.py index e6bc3af24..813e812af 100644 --- a/tableauserverclient/models/site_item.py +++ b/tableauserverclient/models/site_item.py @@ -2,6 +2,7 @@ import xml.etree.ElementTree as ET from defusedxml.ElementTree import fromstring + from .property_decorators import ( property_is_enum, property_is_boolean, diff --git a/tableauserverclient/models/tableau_types.py b/tableauserverclient/models/tableau_types.py index 6ed77318f..9649c7ed9 100644 --- a/tableauserverclient/models/tableau_types.py +++ b/tableauserverclient/models/tableau_types.py @@ -1,13 +1,11 @@ -from tableauserverclient.models.database_item import DatabaseItem -from tableauserverclient.models.datasource_item import DatasourceItem -from tableauserverclient.models.flow_item import FlowItem -from tableauserverclient.models.project_item import ProjectItem -from tableauserverclient.models.table_item import TableItem -from tableauserverclient.models.view_item import ViewItem -from tableauserverclient.models.workbook_item import WorkbookItem - from typing import Union +from .datasource_item import DatasourceItem +from .flow_item import FlowItem +from .project_item import ProjectItem +from .view_item import ViewItem +from .workbook_item import WorkbookItem + class Resource: Database = "database" diff --git a/tableauserverclient/models/tag_item.py b/tableauserverclient/models/tag_item.py index f7568ae45..afa0a0762 100644 --- a/tableauserverclient/models/tag_item.py +++ b/tableauserverclient/models/tag_item.py @@ -1,5 +1,6 @@ -from typing import Set import xml.etree.ElementTree as ET +from typing import Set + from defusedxml.ElementTree import fromstring diff --git a/tableauserverclient/models/task_item.py b/tableauserverclient/models/task_item.py index 30cac8626..159869b07 100644 --- a/tableauserverclient/models/task_item.py +++ b/tableauserverclient/models/task_item.py @@ -1,8 +1,8 @@ from defusedxml.ElementTree import fromstring +from tableauserverclient.datetime_helpers import parse_datetime from .schedule_item import ScheduleItem from .target import Target -from tableauserverclient.datetime_helpers import parse_datetime class TaskItem(object): diff --git a/tableauserverclient/models/user_item.py b/tableauserverclient/models/user_item.py index 059b18f4f..dd705d326 100644 --- a/tableauserverclient/models/user_item.py +++ b/tableauserverclient/models/user_item.py @@ -1,18 +1,18 @@ -from datetime import datetime -from defusedxml.ElementTree import fromstring -from enum import IntEnum import io import xml.etree.ElementTree as ET +from datetime import datetime +from enum import IntEnum +from typing import Dict, List, Optional, TYPE_CHECKING, Tuple +from defusedxml.ElementTree import fromstring + +from tableauserverclient.datetime_helpers import parse_datetime from .exceptions import UnpopulatedPropertyError from .property_decorators import ( property_is_enum, property_not_empty, ) from .reference_item import ResourceReference -from tableauserverclient.datetime_helpers import parse_datetime - -from typing import Dict, List, Optional, TYPE_CHECKING, Tuple if TYPE_CHECKING: from tableauserverclient.server import Pager diff --git a/tableauserverclient/models/view_item.py b/tableauserverclient/models/view_item.py index 65ce6b858..b9bef903a 100644 --- a/tableauserverclient/models/view_item.py +++ b/tableauserverclient/models/view_item.py @@ -1,21 +1,19 @@ import copy -from typing import Callable, Generator, Iterator, List, Optional, Set, TYPE_CHECKING +from datetime import datetime +from typing import Callable, Iterator, List, Optional, Set from defusedxml.ElementTree import fromstring +from tableauserverclient.datetime_helpers import parse_datetime from .exceptions import UnpopulatedPropertyError +from .permissions_item import PermissionsRule from .tag_item import TagItem -from tableauserverclient.datetime_helpers import parse_datetime - -if TYPE_CHECKING: - from datetime import datetime - from .permissions_item import PermissionsRule class ViewItem(object): def __init__(self) -> None: self._content_url: Optional[str] = None - self._created_at: Optional["datetime"] = None + self._created_at: Optional[datetime] = None self._id: Optional[str] = None self._image: Optional[Callable[[], bytes]] = None self._initial_tags: Set[str] = set() @@ -28,9 +26,9 @@ def __init__(self) -> None: self._excel: Optional[Callable[[], Iterator[bytes]]] = None self._total_views: Optional[int] = None self._sheet_type: Optional[str] = None - self._updated_at: Optional["datetime"] = None + self._updated_at: Optional[datetime] = None self._workbook_id: Optional[str] = None - self._permissions: Optional[Callable[[], List["PermissionsRule"]]] = None + self._permissions: Optional[Callable[[], List[PermissionsRule]]] = None self.tags: Set[str] = set() def _set_preview_image(self, preview_image): @@ -53,7 +51,7 @@ def content_url(self) -> Optional[str]: return self._content_url @property - def created_at(self) -> Optional["datetime"]: + def created_at(self) -> Optional[datetime]: return self._created_at @property @@ -119,7 +117,7 @@ def total_views(self): return self._total_views @property - def updated_at(self) -> Optional["datetime"]: + def updated_at(self) -> Optional[datetime]: return self._updated_at @property @@ -127,13 +125,13 @@ def workbook_id(self) -> Optional[str]: return self._workbook_id @property - def permissions(self) -> List["PermissionsRule"]: + def permissions(self) -> List[PermissionsRule]: if self._permissions is None: error = "View item must be populated with permissions first." raise UnpopulatedPropertyError(error) return self._permissions() - def _set_permissions(self, permissions: Callable[[], List["PermissionsRule"]]) -> None: + def _set_permissions(self, permissions: Callable[[], List[PermissionsRule]]) -> None: self._permissions = permissions @classmethod diff --git a/tableauserverclient/models/workbook_item.py b/tableauserverclient/models/workbook_item.py index 9ecc8b42e..9e1168e6d 100644 --- a/tableauserverclient/models/workbook_item.py +++ b/tableauserverclient/models/workbook_item.py @@ -1,35 +1,22 @@ import copy +import datetime import uuid import xml.etree.ElementTree as ET -from typing import Callable, Dict, List, Optional, Set, TYPE_CHECKING +from typing import Callable, Dict, List, Optional, Set from defusedxml.ElementTree import fromstring +from tableauserverclient.datetime_helpers import parse_datetime +from .connection_item import ConnectionItem from .exceptions import UnpopulatedPropertyError from .permissions_item import PermissionsRule from .property_decorators import ( - property_not_nullable, property_is_boolean, property_is_data_acceleration_config, ) +from .revision_item import RevisionItem from .tag_item import TagItem from .view_item import ViewItem -from tableauserverclient.datetime_helpers import parse_datetime - - -if TYPE_CHECKING: - from .connection_item import ConnectionItem - from .permissions_item import PermissionsRule - import datetime - from .revision_item import RevisionItem - -from typing import Dict, List, Optional, Set, TYPE_CHECKING, Union - -if TYPE_CHECKING: - from .connection_item import ConnectionItem - from .permissions_item import PermissionsRule - import datetime - from .revision_item import RevisionItem class WorkbookItem(object): @@ -66,14 +53,14 @@ def __init__(self, project_id: str, name: Optional[str] = None, show_tabs: bool return None @property - def connections(self) -> List["ConnectionItem"]: + def connections(self) -> List[ConnectionItem]: if self._connections is None: error = "Workbook item must be populated with connections first." raise UnpopulatedPropertyError(error) return self._connections() @property - def permissions(self) -> List["PermissionsRule"]: + def permissions(self) -> List[PermissionsRule]: if self._permissions is None: error = "Workbook item must be populated with permissions first." raise UnpopulatedPropertyError(error) @@ -88,7 +75,7 @@ def webpage_url(self) -> Optional[str]: return self._webpage_url @property - def created_at(self) -> Optional["datetime.datetime"]: + def created_at(self) -> Optional[datetime.datetime]: return self._created_at @property @@ -146,7 +133,7 @@ def size(self): return self._size @property - def updated_at(self) -> Optional["datetime.datetime"]: + def updated_at(self) -> Optional[datetime.datetime]: return self._updated_at @property @@ -176,7 +163,7 @@ def data_acceleration_config(self, value): self._data_acceleration_config = value @property - def revisions(self) -> List["RevisionItem"]: + def revisions(self) -> List[RevisionItem]: if self._revisions is None: error = "Workbook item must be populated with revisions first." raise UnpopulatedPropertyError(error) From 99dcb86afe5ba492414c1b2087e7dc12e4ac4fee Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Wed, 15 Feb 2023 19:53:09 -0800 Subject: [PATCH 3/6] format --- tableauserverclient/server/server.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tableauserverclient/server/server.py b/tableauserverclient/server/server.py index 18957c1f3..cdc23dd9b 100644 --- a/tableauserverclient/server/server.py +++ b/tableauserverclient/server/server.py @@ -150,9 +150,7 @@ def _get_legacy_version(self): info_xml = fromstring(response.content) except ParseError as parseError: logger.info(parseError) - logger.info( - "Could not read server version info. The server may not be running or configured." - ) + logger.info("Could not read server version info. The server may not be running or configured.") return self.version prod_version = info_xml.find(".//product_version").text version = _PRODUCT_TO_REST_VERSION.get(prod_version, "2.1") # 2.1 From e1ace7bbed3104d653a024876fa6add64ff9c429 Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Thu, 16 Feb 2023 14:15:02 -0800 Subject: [PATCH 4/6] fix variable references --- tableauserverclient/server/server.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tableauserverclient/server/server.py b/tableauserverclient/server/server.py index cdc23dd9b..f287afbc3 100644 --- a/tableauserverclient/server/server.py +++ b/tableauserverclient/server/server.py @@ -107,8 +107,8 @@ def __init__(self, server_address, use_server_version=False, http_options=None, def validate_connection_settings(self): try: Endpoint(self).set_parameters(self._http_options, None, None, None, None) - if not server_address.startswith("http://") and not server_address.startswith("https://"): - self._server_address = "http://" + self._server_address + if not self._server_address.startswith("http://") and not self._server_address.startswith("https://"): + self._server_address = "http://" + self.server_address self._session.prepare_request(requests.Request("GET", url=self._server_address, params=self._http_options)) except Exception as req_ex: raise ValueError("Server connection settings not valid", req_ex) @@ -149,8 +149,8 @@ def _get_legacy_version(self): try: info_xml = fromstring(response.content) except ParseError as parseError: - logger.info(parseError) - logger.info("Could not read server version info. The server may not be running or configured.") + self.logger.info(parseError) + self.logger.info("Could not read server version info. The server may not be running or configured.") return self.version prod_version = info_xml.find(".//product_version").text version = _PRODUCT_TO_REST_VERSION.get(prod_version, "2.1") # 2.1 @@ -164,7 +164,7 @@ def _determine_highest_version(self): except ServerInfoEndpointNotFoundError: version = self._get_legacy_version() except BaseException as e: - logger.info("Could not get version info from server, guessing {}".format(e.__class__)) + self.logger.info("Could not get version info from server, guessing {}".format(e.__class__)) version = self._get_legacy_version() self.version = old_version @@ -176,7 +176,7 @@ def use_server_version(self): def use_highest_version(self): self.use_server_version() - logger.info("use use_server_version instead", DeprecationWarning) + self.logger.info("use use_server_version instead", DeprecationWarning) def check_at_least_version(self, target: str): server_version = Version(self.version or "0.0") From 227060fbbae0654aeed562b64432341c6953ce4f Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Thu, 16 Feb 2023 17:28:59 -0800 Subject: [PATCH 5/6] fix mock for tests --- tableauserverclient/models/server_info_item.py | 2 +- test/http/test_http_requests.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tableauserverclient/models/server_info_item.py b/tableauserverclient/models/server_info_item.py index 350ae3a0d..bcc1ce738 100644 --- a/tableauserverclient/models/server_info_item.py +++ b/tableauserverclient/models/server_info_item.py @@ -38,7 +38,7 @@ def from_response(cls, resp, ns): try: parsed_response = fromstring(resp) except xml.etree.ElementTree.ParseError as error: - warnings.warn("Unexpected response for ServerInfo: {}".format(resp)) + print("Unexpected response for ServerInfo: {}".format(resp)) return cls("Unknown", "Unknown", "Unknown") product_version_tag = parsed_response.find(".//t:productVersion", namespaces=ns) rest_api_version_tag = parsed_response.find(".//t:restApiVersion", namespaces=ns) diff --git a/test/http/test_http_requests.py b/test/http/test_http_requests.py index 23eab9c98..ce845502d 100644 --- a/test/http/test_http_requests.py +++ b/test/http/test_http_requests.py @@ -11,6 +11,8 @@ def mocked_requests_get(*args, **kwargs): class MockResponse: def __init__(self, status_code): + self.headers = {} + self.encoding = None self.content = ( "" "" From e864a67cc88989023468363f3f181f3662fcf772 Mon Sep 17 00:00:00 2001 From: Jac Date: Thu, 16 Feb 2023 17:41:22 -0800 Subject: [PATCH 6/6] Update code-coverage.yml don't really need multi-OS runs here --- .github/workflows/code-coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml index d393a06d5..6d74c5c38 100644 --- a/.github/workflows/code-coverage.yml +++ b/.github/workflows/code-coverage.yml @@ -10,7 +10,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [ubuntu-latest] python-version: ['3.10'] runs-on: ${{ matrix.os }}