-
Notifications
You must be signed in to change notification settings - Fork 14
mypy: enable checking untyped code #367
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: development
Are you sure you want to change the base?
Changes from all commits
63f1ae1
112654e
4457b1e
4677e5c
408ce05
5cee61e
a2a11ae
a1f0948
3837652
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -13,7 +13,7 @@ | |||
| from tabcmd.execution.localize import _ | ||||
| from tabcmd.execution.logger_config import log | ||||
|
|
||||
| from typing import Dict, Any | ||||
| from typing import Dict, Any, Optional | ||||
|
|
||||
|
|
||||
| class Session: | ||||
|
|
@@ -28,31 +28,31 @@ class Session: | |||
| PASSWORD_CRED_TYPE = "password" | ||||
|
|
||||
| def __init__(self): | ||||
| self.username = None | ||||
| self.username: Optional[str] = None | ||||
| # we don't store the password | ||||
| self.user_id = None | ||||
| self.auth_token = None | ||||
| self.token_name = None | ||||
| self.token_value = None | ||||
| self.password_file = None | ||||
| self.token_file = None | ||||
| self.site_name = None # The site name, e.g 'alpodev' | ||||
| self.site_id = None # The site id, e.g 'abcd-1234-1234-1244-1234' | ||||
| self.server_url = None | ||||
| self.last_command = None # for when we have to renew the session then re-try | ||||
| self.last_login_using = None | ||||
|
|
||||
| self.no_prompt = False | ||||
| self.certificate = None | ||||
| self.no_certcheck = False | ||||
| self.no_proxy = False | ||||
| self.proxy = None | ||||
| self.timeout = None | ||||
|
|
||||
| self.logging_level = "info" | ||||
| self.user_id: Optional[str] = None | ||||
| self.auth_token: Optional[str] = None | ||||
| self.token_name: Optional[str] = None | ||||
| self.token_value: Optional[str] = None | ||||
| self.password_file: Optional[str] = None | ||||
| self.token_file: Optional[str] = None | ||||
| self.site_name: Optional[str] = None # The site name, e.g 'alpodev' | ||||
| self.site_id: Optional[str] = None # The site id, e.g 'abcd-1234-1234-1244-1234' | ||||
| self.server_url: Optional[str] = None | ||||
| self.last_command: Optional[str] = None # for when we have to renew the session then re-try | ||||
| self.last_login_using: Optional[str] = None | ||||
|
|
||||
| self.no_prompt: bool = False | ||||
| self.certificate: Optional[str] = None | ||||
| self.no_certcheck: bool = False | ||||
| self.no_proxy: bool = False | ||||
| self.proxy: Optional[str] = None | ||||
| self.timeout: Optional[int] = None | ||||
|
|
||||
| self.logging_level: str = "info" | ||||
| self.logger = log(__name__, self.logging_level) # instantiate here mostly for tests | ||||
| self._read_from_json() | ||||
| self.tableau_server = None # this one is an object that doesn't get persisted in the file | ||||
| self.tableau_server: Optional[TSC.Server] = None # this one is an object that doesn't get persisted in the file | ||||
|
|
||||
| # called before we connect to the server | ||||
| # generally, we don't want to overwrite stored data with nulls | ||||
|
|
@@ -201,6 +201,10 @@ def _open_connection_with_opts(self) -> TSC.Server: | |||
| return tableau_server | ||||
|
|
||||
| def _verify_server_connection_unauthed(self): | ||||
| if not self.tableau_server: | ||||
| Errors.exit_with_error(self.logger, "No server connection available") | ||||
|
|
||||
| assert self.tableau_server is not None # Type hint for mypy | ||||
| try: | ||||
| self.tableau_server.use_server_version() | ||||
| except requests.exceptions.ReadTimeout as timeout_error: | ||||
|
|
@@ -222,7 +226,12 @@ def _create_new_connection(self) -> TSC.Server: | |||
| try: | ||||
| self.tableau_server = self._open_connection_with_opts() | ||||
| except Exception as e: | ||||
| Errors.exit_with_error(self.logger, "Failed to connect to server", e) | ||||
| Errors.exit_with_error(self.logger, "Failed to connect to server", exception=e) | ||||
|
|
||||
| if not self.tableau_server: | ||||
| Errors.exit_with_error(self.logger, "Failed to create server connection") | ||||
|
|
||||
| assert self.tableau_server is not None # Type hint for mypy | ||||
|
Comment on lines
+231
to
+234
|
||||
| return self.tableau_server | ||||
|
|
||||
| def _read_existing_state(self): | ||||
|
|
@@ -246,7 +255,7 @@ def _print_server_info(self): | |||
| def _validate_existing_signin(self): | ||||
| # when do these two messages show up? self.logger.info(_("session.auto_site_login")) | ||||
| try: | ||||
| if self.tableau_server and self.tableau_server.is_signed_in(): | ||||
| if self.tableau_server and self.tableau_server.is_signed_in() and self.user_id: | ||||
| server_user = self.tableau_server.users.get_by_id(self.user_id).name | ||||
| if not self.username: | ||||
| self.logger.info("Fetched user details from server") | ||||
|
|
@@ -261,8 +270,12 @@ def _validate_existing_signin(self): | |||
|
|
||||
| # server connection created, not yet logged in | ||||
| def _sign_in(self, tableau_auth) -> TSC.Server: | ||||
| self.logger.debug(_("session.login") + self.server_url) | ||||
| if not self.tableau_server: | ||||
| Errors.exit_with_error(self.logger, "No server connection available for sign in") | ||||
|
|
||||
| self.logger.debug(_("session.login") + (self.server_url or "")) | ||||
| self.logger.debug(_("listsites.output").format("", self.username or self.token_name, self.site_name)) | ||||
| assert self.tableau_server is not None # Type hint for mypy | ||||
|
||||
| assert self.tableau_server is not None # Type hint for mypy |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ | |
| from tabcmd.commands.constants import Errors | ||
| from tabcmd.commands.server import Server | ||
| from tabcmd.execution.localize import _ | ||
| RequestOptionsType = TSC.ExcelRequestOptions | TSC.CSVRequestOptions | TSC.PDFRequestOptions | TSC.ImageRequestOptions | ||
|
|
||
|
|
||
| class DatasourcesAndWorkbooks(Server): | ||
|
|
@@ -13,7 +14,7 @@ class DatasourcesAndWorkbooks(Server): | |
| """ | ||
|
|
||
| def __init__(self, args): | ||
| super().__init__(args) | ||
| pass | ||
|
Comment on lines
16
to
+17
|
||
|
|
||
| @staticmethod | ||
| def get_view_url_from_names(wb_name, view_name): | ||
|
|
@@ -62,7 +63,7 @@ def get_ds_by_content_url(logger, server, datasource_content_url) -> TSC.Datasou | |
| return matching_datasources[0] | ||
|
|
||
| @staticmethod | ||
| def apply_values_from_url_params(logger, request_options: TSC.RequestOptions, url) -> None: | ||
| def apply_values_from_url_params(logger, request_options: RequestOptionsType, url) -> None: | ||
| logger.debug(url) | ||
| try: | ||
| if "?" in url: | ||
|
|
@@ -86,7 +87,7 @@ def apply_values_from_url_params(logger, request_options: TSC.RequestOptions, ur | |
|
|
||
| # this is called from within from_url_params, for each view_filter value | ||
| @staticmethod | ||
| def apply_encoded_filter_value(logger, request_options, value): | ||
| def apply_encoded_filter_value(logger, request_options: RequestOptionsType, value): | ||
| # the REST API doesn't appear to have the option to disambiguate with "Parameters.<fieldname>" | ||
| value = value.replace("Parameters.", "") | ||
| # the filter values received from the url are already url encoded. tsc will encode them again. | ||
|
|
@@ -99,7 +100,7 @@ def apply_encoded_filter_value(logger, request_options, value): | |
| # from apply_options, which expects an un-encoded input, | ||
| # or from apply_url_params via apply_encoded_filter_value which decodes the input | ||
| @staticmethod | ||
| def apply_filter_value(logger, request_options: TSC.RequestOptions, value: str) -> None: | ||
| def apply_filter_value(logger, request_options: RequestOptionsType, value: str) -> None: | ||
| logger.debug("handling filter param {}".format(value)) | ||
| data_filter = value.split("=") | ||
| # we should export the _DataExportOptions class from tsc | ||
|
|
@@ -108,7 +109,7 @@ def apply_filter_value(logger, request_options: TSC.RequestOptions, value: str) | |
| # this is called from within from_url_params, for each param value | ||
| # expects either ImageRequestOptions or PDFRequestOptions | ||
| @staticmethod | ||
| def apply_options_in_url(logger, request_options: TSC.RequestOptions, value: str) -> None: | ||
| def apply_options_in_url(logger, request_options: RequestOptionsType, value: str) -> None: | ||
| logger.debug("handling url option {}".format(value)) | ||
| setting = value.split("=") | ||
| if len(setting) != 2: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| import os | ||
|
|
||
| import tableauserverclient as TSC | ||
| from uuid import UUID | ||
|
|
||
| from tabcmd.commands.constants import Errors | ||
|
|
@@ -14,7 +15,7 @@ class DatasourcesWorkbooksAndViewsUrlParser(Server): | |
| """ | ||
|
|
||
| def __init__(self, args): | ||
| super().__init__(args) | ||
| pass | ||
|
Comment on lines
17
to
+18
|
||
|
|
||
| @staticmethod | ||
| def get_view_url_from_names(wb_name, view_name): | ||
|
|
@@ -179,12 +180,12 @@ def get_url_item_and_item_type_from_view_url(logger, url, server): | |
|
|
||
| @staticmethod | ||
| def get_content_and_server_content_type_from_url(logger, server, view_content_url, custom_view_id): | ||
| item = DatasourcesAndWorkbooks.get_view_by_content_url(logger, server, view_content_url) | ||
| item: TSC.ViewItem | TSC.CustomViewItem = DatasourcesAndWorkbooks.get_view_by_content_url(logger, server, view_content_url) | ||
| server_content_type = server.views | ||
|
|
||
| if custom_view_id: | ||
| custom_view_item = DatasourcesAndWorkbooks.get_custom_view_by_id(logger, server, custom_view_id) | ||
| if custom_view_item.view.id != item.id: | ||
| custom_view_item: TSC.CustomViewItem = DatasourcesAndWorkbooks.get_custom_view_by_id(logger, server, custom_view_id) | ||
| if not custom_view_item.view or custom_view_item.view.id != item.id: | ||
| Errors.exit_with_error(logger, "Invalid custom view URL provided") | ||
| server_content_type = server.custom_views | ||
| item = custom_view_item | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -13,6 +13,7 @@ | |||||
| pagesize = TSC.PDFRequestOptions.PageType # type alias for brevity | ||||||
| pageorientation = TSC.PDFRequestOptions.Orientation | ||||||
| imageresolution = TSC.ImageRequestOptions.Resolution | ||||||
| RequestOptionsType = TSC.ExcelRequestOptions | TSC.CSVRequestOptions | TSC.PDFRequestOptions | TSC.ImageRequestOptions | ||||||
|
||||||
| ImageResolutionStandard = "standard" | ||||||
|
|
||||||
|
|
||||||
|
|
@@ -81,9 +82,9 @@ def define_args(export_parser): | |||||
| it to a file. This command can also export just the data used for a view_name | ||||||
| """ | ||||||
|
|
||||||
| @staticmethod | ||||||
| def run_command(args): | ||||||
| logger = log(__class__.__name__, args.logging_level) | ||||||
| @classmethod | ||||||
| def run_command(cls, args): | ||||||
| logger = log(cls.__name__, args.logging_level) | ||||||
| logger.debug(_("tabcmd.launching")) | ||||||
| session = Session() | ||||||
| server = session.create_session(args, logger) | ||||||
|
|
@@ -97,7 +98,7 @@ def run_command(args): | |||||
| if not view_content_url and not wb_content_url: | ||||||
| view_example = "/workbook_name/view_name" | ||||||
| message = "{} [{}]".format( | ||||||
| _("export.errors.requires_workbook_view_param").format(__class__.__name__), view_example | ||||||
| _("export.errors.requires_workbook_view_param").format("ExportCommand"), view_example | ||||||
|
||||||
| _("export.errors.requires_workbook_view_param").format("ExportCommand"), view_example | |
| _("export.errors.requires_workbook_view_param").format(cls.__name__), view_example |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,9 +33,9 @@ def define_args(publish_parser): | |
| set_append_replace_option(group) | ||
| set_parent_project_arg(group) | ||
|
|
||
| @staticmethod | ||
| def run_command(args): | ||
| logger = log(__class__.__name__, args.logging_level) | ||
| @classmethod | ||
| def run_command(cls, args): | ||
| logger = log(cls.__name__, args.logging_level) | ||
| logger.debug(_("tabcmd.launching")) | ||
| session = Session() | ||
| server = session.create_session(args, logger) | ||
|
|
@@ -50,22 +50,24 @@ def run_command(args): | |
| project_id = dest_project.id | ||
| except Exception as exc: | ||
| logger.error(exc.__str__()) | ||
| Errors.exit_with_error(logger, _("publish.errors.server_resource_not_found"), exc) | ||
| Errors.exit_with_error(logger, _("publish.errors.server_resource_not_found"), exception=exc) | ||
|
|
||
| publish_mode = PublishCommand.get_publish_mode(args, logger) | ||
|
|
||
| connection = TSC.models.ConnectionItem() | ||
| connection: TSC.models.ConnectionItem | None = None | ||
| if args.db_username: | ||
| connection = TSC.models.ConnectionItem() | ||
| connection.connection_credentials = TSC.models.ConnectionCredentials( | ||
| args.db_username, args.db_password, embed=args.save_db_password | ||
| ) | ||
| elif args.oauth_username: | ||
| connection = TSC.models.ConnectionItem() | ||
| connection.connection_credentials = TSC.models.ConnectionCredentials( | ||
| args.oauth_username, None, embed=False, oauth=args.save_oauth | ||
| ) | ||
| else: | ||
| logger.debug("No db-username or oauth-username found in command") | ||
| connection = None | ||
| logger.debug("No db-username or oauth-username found in command") | ||
|
Comment on lines
+57
to
+70
|
||
|
|
||
| if connection: | ||
| connections = list() | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The exit_with_error call is made before the assert statement. Since exit_with_error calls sys.exit(1) which terminates the program, the assert on line 207 will never be reached if self.tableau_server is None. The assert is dead code in this case. Consider either removing the assert or restructuring to check the condition differently.