1
|
|
|
""" |
2
|
|
|
TableauHyperApiExtraLogic - a Tableau Server Client wrapper |
3
|
|
|
|
4
|
|
|
This library facilitates publishing data source to Tableau Server |
5
|
|
|
""" |
6
|
|
|
# package to ensure communication with Tableau Server |
7
|
|
|
import tableauserverclient as tsc |
8
|
|
|
# Path manager |
9
|
|
|
from pathlib import Path |
10
|
|
|
|
11
|
|
|
|
12
|
|
|
class TableauServerCommunicator: |
13
|
|
|
req_opts = tsc.RequestOptions(pagesize=1000) |
14
|
|
|
tableau_server = None |
15
|
|
|
|
16
|
|
|
def connect_to_tableau_server(self, local_logger, timmer, connection_details): |
17
|
|
|
timmer.start() |
18
|
|
|
local_logger.debug('I am about to connect to the Tableau Server with URL: ' |
19
|
|
|
+ connection_details['Tableau Server'] + ' and the Site ' |
20
|
|
|
+ connection_details['Tableau Site'] + ' using the Username ' |
21
|
|
|
+ connection_details['Username']) |
22
|
|
|
self.tableau_server = tsc.Server(connection_details['Tableau Server'], True) |
23
|
|
|
tableau_auth = tsc.TableauAuth(connection_details['Username'], |
24
|
|
|
connection_details['Password'], |
25
|
|
|
connection_details['Tableau Site']) |
26
|
|
|
self.tableau_server.auth.sign_in(tableau_auth) |
27
|
|
|
local_logger.debug('Connection to the Tableau Server has been established successfully!') |
28
|
|
|
timmer.stop() |
29
|
|
|
|
30
|
|
|
def disconnect_from_tableau_server(self, local_logger, timmer): |
31
|
|
|
timmer.start() |
32
|
|
|
self.tableau_server.auth.sign_out() |
33
|
|
|
local_logger.debug('The connection to the Tableau Server has been terminated!') |
34
|
|
|
timmer.stop() |
35
|
|
|
|
36
|
|
|
@staticmethod |
37
|
|
|
def get_project_relevancy(relevant_projects_to_filter, filtering_type, current_project): |
38
|
|
|
relevant = 0 |
39
|
|
|
if filtering_type == 'JustOnesMentioned': |
40
|
|
|
if current_project.name.replace(chr(8211), chr(45)) in relevant_projects_to_filter: |
41
|
|
|
relevant = 1 |
42
|
|
|
elif filtering_type == 'OnesMentionedMarked': |
43
|
|
|
relevant = 2 |
44
|
|
|
elif filtering_type == 'All': |
45
|
|
|
relevant = 99 |
46
|
|
|
return relevant |
47
|
|
|
|
48
|
|
|
@staticmethod |
49
|
|
|
def is_publishing_possible(local_logger, relevant_project_name, relevant_project_ids): |
50
|
|
|
publish_possible = False |
51
|
|
|
int_found_projects = len(relevant_project_ids) |
52
|
|
|
if int_found_projects == 0: |
53
|
|
|
local_logger.error('No project with provided name "' + relevant_project_name |
54
|
|
|
+ '" has been found') |
55
|
|
|
local_logger.debug('No publishing action will take place!') |
56
|
|
|
local_logger.debug('Check your input parameter values for accuracy and try again!') |
57
|
|
|
elif int_found_projects > 1: |
58
|
|
|
local_logger.error(f'There are {str(int_found_projects)} projects with provided name "' |
59
|
|
|
+ relevant_project_name + ' but a unique identifier is expected') |
60
|
|
|
local_logger.debug('No publishing action will take place!') |
61
|
|
|
local_logger.info('Check your input parameter values for accuracy and try again!') |
62
|
|
|
else: |
63
|
|
|
publish_possible = True |
64
|
|
|
local_logger.info(f'A single project identifier was found "' + relevant_project_ids[0] |
65
|
|
|
+ '" so I will proceed with publishing provided file there') |
66
|
|
|
local_logger.info('Stay tuned for the confirmation') |
67
|
|
|
return publish_possible |
68
|
|
|
|
69
|
|
|
def load_tableau_project_ids(self, local_logger, timmer, relevant_projects_to_filter, |
70
|
|
|
str_filtering_type): |
71
|
|
|
timmer.start() |
72
|
|
|
project_items, pagination_item = self.tableau_server.projects.get(req_options=self.req_opts) |
73
|
|
|
local_logger.info('Reading list of all projects available has been completed') |
74
|
|
|
local_logger.info(str(len(project_items)) + ' projects were found') |
75
|
|
|
timmer.stop() |
76
|
|
|
timmer.start() |
77
|
|
|
dictionary_project_ids = [] |
78
|
|
|
project_counter = 0 |
79
|
|
|
for project_current in project_items: |
80
|
|
|
relevant = self.get_project_relevancy(relevant_projects_to_filter, |
81
|
|
|
str_filtering_type, |
82
|
|
|
project_current) |
83
|
|
|
if relevant >= 1: |
84
|
|
|
dictionary_project_ids.append(project_counter) |
85
|
|
|
dictionary_project_ids[project_counter] = project_current.id |
86
|
|
|
project_counter = project_counter + 1 |
87
|
|
|
local_logger.info('Retaining the projects according to filtering type provided ("' |
88
|
|
|
+ str_filtering_type + '") has been completed') |
89
|
|
|
local_logger.info(str(len(dictionary_project_ids)) + ' projects were retained') |
90
|
|
|
timmer.stop() |
91
|
|
|
return dictionary_project_ids |
92
|
|
|
|
93
|
|
|
def publish_data_source_to_tableau_server(self, local_logger, timmer, publish_details): |
94
|
|
|
timmer.start() |
95
|
|
|
local_logger.info('About to start publishing') |
96
|
|
|
data_source_name = Path(publish_details['Tableau Extract File']).name\ |
97
|
|
|
.replace('.hyper', '') + " Extract" |
98
|
|
|
project_data_source = tsc.DatasourceItem(publish_details['Project ID'], data_source_name) |
99
|
|
|
self.tableau_server.datasources.publish(project_data_source, |
100
|
|
|
publish_details['Tableau Extract File'], |
101
|
|
|
publish_details['Publishing Mode']) |
102
|
|
|
local_logger.info('Publishing has finished with success!') |
103
|
|
|
timmer.stop() |
104
|
|
|
|