def generate_report(view_name, filepath): # site_id = site to log into, do not specify for default site tableau_auth = TSC.PersonalAccessTokenAuth("Slack API Token", token, site_id="") server = TSC.Server(server_url, use_server_version=True) # The new endpoint was introduced in Version 2.5 server.version = "2.5" with server.auth.sign_in(tableau_auth): # Query for the view that we want an image of req_option = TSC.RequestOptions() req_option.filter.add( TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.Equals, view_name)) all_views, pagination_item = server.views.get(req_option) if not all_views: raise LookupError("View with the specified name was not found.") view_item = all_views[0] max_age = 1 if not max_age: max_age = 1 image_req_option = TSC.ImageRequestOptions( imageresolution=TSC.ImageRequestOptions.Resolution.High, maxage=max_age) server.views.populate_image(view_item, image_req_option) # Write file to local /tmp with open("/tmp/view_{0}.png".format(filepath), "wb") as image_file: image_file.write(view_item.image)
class TableauServerConnection: FILE_PATH = os.path.dirname(Tests.__file__) username = os.getenv('USERNAME') password = os.getenv('PASSWORD') server_url = os.getenv('SERVER_URL') tableau_auth = TSC.TableauAuth('mll25', 'BobRoss1125!') server = TSC.Server('https://casanalyticsp01.cas.org/') # Current server version : 3.3 server.use_server_version() req_option = TSC.RequestOptions(pagesize=1000) csv_req_option = TSC.CSVRequestOptions() image_req_option = TSC.ImageRequestOptions(imageresolution=TSC.ImageRequestOptions.Resolution.High) image_req_option.vf('Country', 'AUSTRALIA') csv_req_option.vf('Country','AUSTRALIA') with server.auth.sign_in(tableau_auth): all_workbooks, pagination_item = server.workbooks.get() wfound = [workbook for workbook in all_workbooks if workbook.name == 'Enterprise Success Dashboard LIVE'] # pprint(vars(wfound[0])) wconnect = server.workbooks.get_by_id('94d2abea-bced-46d1-831c-edce132b2864') server.workbooks.populate_views(wconnect) vfound = [view for view in wconnect.views if len(view.name) > 0] view_item = vfound[21] server.views.populate_csv(view_item, csv_req_option) with open(f'{FILE_PATH}/CCDAus.csv', 'wb') as f: if os.path.exists(f): os.remove(f) f.write(b''.join(view_item.csv))
def test_populate_image_high_resolution(self): with open(POPULATE_PREVIEW_IMAGE, 'rb') as f: response = f.read() with requests_mock.mock() as m: m.get(self.baseurl + '/d79634e1-6063-4ec9-95ff-50acbf609ff5/image?resolution=high', content=response) single_view = TSC.ViewItem() single_view._id = 'd79634e1-6063-4ec9-95ff-50acbf609ff5' req_option = TSC.ImageRequestOptions(imageresolution=TSC.ImageRequestOptions.Resolution.High) self.server.views.populate_image(single_view, req_option) self.assertEqual(response, single_view.image)
def download_view_image(resource_name, server_url=None, username=None, password=None, path=None, server=None, resolution="high"): """ Download a view as image Parameters: resource_name -- name of the resource to download - REQUIRED path -- path of the resource to download to (current working directory by default) server_url -- the url of the server to connect with username -- username of the user to authenticate with password -- password of the user to authenticate with server -- the server object if authenticated previosly resolution -- resultion of image ('low'/'medium'/'high') Return value(s): path -- path of the downlaoded image Exception(s): NameError -- if resolution is invalid """ # check if the either all the necessary credentials or the server object are there and authenticate if necessary server = check_credentials_authenticate(username, password, server) # get id resource_id, resource_object = get_resource_id("view", resource_name, project_name=None, server=server) print(resource_id, resource_object) # request for high resolution if resolution == 'high': imageresolution = TSC.ImageRequestOptions.Resolution.High # request for medium resolution elif resolution == 'medium': imageresolution = TSC.ImageRequestOptions.Resolution.Medium # request for low resolution elif resolution == 'low': imageresolution = TSC.ImageRequestOptions.Resolution.Low else: raise NameError("Invalid resolution '{}'".format(resolution)) # make request image_req_option = TSC.ImageRequestOptions(imageresolution) server.views.populate_image(resource_object, image_req_option) # write to disk if path is None: path = os.getcwd() + "/" + resource_object.name + ".jpeg" with open(path, "wb") as image_file: image_file.write(resource_object.image) return (path)
def test_populate_image_with_options(self) -> None: with open(POPULATE_PREVIEW_IMAGE, "rb") as f: response = f.read() with requests_mock.mock() as m: m.get( self.baseurl + "/d79634e1-6063-4ec9-95ff-50acbf609ff5/image?resolution=high&maxAge=10", content=response) single_view = TSC.ViewItem() single_view._id = "d79634e1-6063-4ec9-95ff-50acbf609ff5" req_option = TSC.ImageRequestOptions( imageresolution=TSC.ImageRequestOptions.Resolution.High, maxage=10) self.server.views.populate_image(single_view, req_option) self.assertEqual(response, single_view.image)
def export_view_as_image(self, image_file_path: str, view_id: str, filters: list = []): image_req_option = TSC.ImageRequestOptions( imageresolution=TSC.ImageRequestOptions.Resolution.High) for filter in filters: image_req_option.vf(filter.get('filter_name'), filter.get('filter_value')) with self.server.auth.sign_in(self.tableau_auth): for view_item in TSC.Pager(self.server.views): if view_item.id == view_id: self.server.views.populate_image( view_item, req_options=image_req_option) with open(image_file_path, 'wb') as f: f.write(view_item.image) break self.server.auth.sign_out()
def CSV_ImageRequest(server, tableau_auth, csv_filename, end_file_directory, WorkbookName, DashboardName, UserEmail): with server.auth.sign_in(tableau_auth): folderExplore.TableauFolderViews(server) req_option1 = TSC.RequestOptions() req_option1.filter.add( TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.Equals, DashboardName)) req_option2 = TSC.RequestOptions() req_option2.filter.add( TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.Equals, WorkbookName)) all_views_filtered, views_items1 = server.views.get(req_option1) all_workbooks_filtered, workbooks_items1 = server.workbooks.get( req_option2) view_i, workbook_i = folderExplore.checkMatch(all_views_filtered, views_items1, all_workbooks_filtered, workbooks_items1) with open(csv_filename) as csv_file: csv_reader = csv.reader(csv_file, delimiter=',') line_count = 0 for row in csv_reader: if line_count == 0: num_col = len(row) column_header = row print("\n {}".format(column_header)) line_count += 1 else: if (row[1] == "PNG" or row[1] == "JPG"): # view item is the dashboard view. view_item = all_views_filtered[view_i] image_req_option = TSC.ImageRequestOptions( imageresolution=TSC.ImageRequestOptions.Resolution. High) # Assumes col 0,1,2 are imageName, FileType, and Email respectively for iter_ in range(3, num_col): # column_header[iter_] takes the nth item across in column header, # row header [iter_] takes the same nth item acrpss in the row # pases it to like this: # image_req_option.vf( Color By , 2) # image_req_option.vf( Bubble Color, 1) # image_req_option.vf( Sales Channel, Channel1) if (row[iter_] == "All"): image_req_option.view_filters.clear() break else: image_req_option.vf(column_header[iter_], row[iter_]) server.views.populate_image(view_item, image_req_option) image_filepath = view_item.name with open( end_file_directory + "/" + image_filepath + row[0] + "." + row[1], "wb") as image_file: image_file.write(view_item.image) elif (row[1] == "PDF"): view_item = all_views_filtered[view_i] pdf_req_option = TSC.PDFRequestOptions( page_type=TSC.PDFRequestOptions.PageType.A4, orientation=TSC.PDFRequestOptions.Orientation. Portrait) # Assumes col 0,1,2 are imageName, FileType, and Email respectively for iter_ in range(3, num_col): if (row[iter_] == "All"): pdf_req_option.view_filters.clear() break else: pdf_req_option.vf(column_header[iter_], row[iter_]) server.views.populate_pdf(view_item, pdf_req_option) pdf_name = view_item.name with open( end_file_directory + "/" + pdf_name + row[0] + "." + row[1], "wb") as pdf_file: pdf_file.write(view_item.pdf) # full_path = end_file_directory + "/" + pdf_name + row[0] + "." + row[1] # emailScript.email_singlePDF(row[2], full_path, row[0], UserEmail) print(row) line_count += 1 print(f'Processed {line_count} lines.') server.auth.sign_out()
def execute(self): process_start_time = time.process_time() try: tableau_auth = TSC.TableauAuth( args.u, password, site_id=self.site_view.site.content_url) server = TSC.Server(self.site_view.server.server_address) server.add_http_options({'verify': False}) server.version = APIVERSION makePath(self.getOutputFilePathBase()) with server.auth.sign_in(tableau_auth): if self.render_type == 'png': # TSC something image_req_option = TSC.ImageRequestOptions( imageresolution=TSC.ImageRequestOptions.Resolution. High, maxage=0) # now make the request, but only at or after the specified time while datetime.now() < self.start_timestamp: time.sleep(.05) self.start_time = time.strftime( '%Y-%m-%d %H:%M:%S.') + getCurrentMicrosecondsStr() process_start_time = time.process_time( ) # reset the timer so we get the most accurate duration server.views.populate_image(self.site_view.view, image_req_option) with open(self.getOutputFilePath(), "wb") as file_to_write: file_to_write.write(self.site_view.view.image) elif self.render_type == 'csv': csv_req_option = TSC.ImageRequestOptions( maxage=0) # CSVRequestOption does not support "maxage" # now make the request, but only at or after the specified time while datetime.now() < self.start_timestamp: time.sleep(.05) self.start_time = time.strftime( '%Y-%m-%d %H:%M:%S.') + getCurrentMicrosecondsStr() process_start_time = time.process_time( ) # reset the timer so we get the most accurate duration server.views.populate_csv(self.site_view.view, csv_req_option) with open(self.getOutputFilePath(), "wb") as file_to_write: file_to_write.writelines(self.site_view.view.csv) else: raise RuntimeError( f'Invalid render_type provided, {self.render_type}') if os.path.isfile(self.getOutputFilePath()): self.succeeded = True except Exception as e: self.error_text = f'Error rendering to {self.render_type}: {e}, {sys.exc_info()}' raise e finally: self.is_complete = True self.duration = time.process_time() - process_start_time if os.path.isfile(self.getOutputFilePath()): self.filesize = os.stat(self.getOutputFilePath()).st_size self.filepath = self.getOutputFilePath() else: self.error_text += f'File {self.getOutputFilePath()} is missing.'
def main(): parser = argparse.ArgumentParser( description='Download pdf file of snapshot(s) of a tableau dashboard.') parser.add_argument('--server', '-s', required=True, help='server address') parser.add_argument('--token-name', '-tn', required=True, help='user token name') parser.add_argument('--token-secret', '-ts', required=True, help='user token secret') parser.add_argument('--view-name', '-v', required=True, help='name of dashboard view') parser.add_argument('--csv', '-csv', required=False, help='csv dataframe of filters/parameters') parser.add_argument('--filepath', '-f', required=True, help='filepath to save the pdf file returned') args = parser.parse_args() #signs user into server using token access tableau_auth = TSC.PersonalAccessTokenAuth(args.token_name, args.token_secret, '') server = TSC.Server(args.server, use_server_version=True) server.auth.sign_in(tableau_auth) #query for the view that we want an image of with server.auth.sign_in(tableau_auth): req_option = TSC.RequestOptions() req_option.filter.add( TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.Equals, args.view_name)) all_views, pagination_item = server.views.get(req_option) if not all_views: raise LookupError("View with the specified name was not found.") view_item = all_views[0] #adds filter/parameters to the view if .csv included in argument if args.csv is not None: filters = pd.read_csv(args.csv) path_names = [0] * filters.shape[0] for i, j in filters.iterrows(): image_req_option = TSC.ImageRequestOptions( imageresolution=TSC.ImageRequestOptions.Resolution.High) for col in filters.columns: image_req_option.vf(col, str(j[col]).replace(', ', ',')) server.views.populate_image(view_item, image_req_option) #temporarily saves each view as separate .png files with open('py_img_%i.png' % i, "wb") as image_file: image_file.write(view_item.image) path_names[i] = ('py_img_%i.png' % i) #takes a snapshot of the default view, when .csv not included else: image_req_option = TSC.ImageRequestOptions( imageresolution=TSC.ImageRequestOptions.Resolution.High) server.views.populate_image(view_item, image_req_option) #temporarily saves view as .png with open('py_img_0.png', "wb") as image_file: image_file.write(view_item.image) path_names = ['py_img_0.png'] #converts mode to remove alpha channel to allow .pdf conversion for path in path_names: img = Image.open(path) if img.mode == 'RGBA': img.convert('RGB').save(path) #save images as single .pdf with open(args.filepath, "wb") as f: f.write(img2pdf.convert(path_names)) #removes temporary .png file(s) from folder for path in path_names: os.remove(path)
req_option = TSC.RequestOptions() req_option.filter.add( TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.Equals, 'Sales Potential')) # Also note the server.views - this references a specific folder that I knew the dashboard was in (see printout for # more clarification) all_views, pagination_item = server.views.get(req_option) # This is unecessary, but sometimes useful print(all_views) print(pagination_item) view_item = all_views[0] print(view_item) image_req_option = TSC.ImageRequestOptions( imageresolution=TSC.ImageRequestOptions.Resolution.High) print('Populating image') server.views.populate_image(view_item, image_req_option) print('Got image') image_filepath = 'TableauDashboardImage.png' with open(image_filepath, "wb") as image_file: image_file.write(view_item.image) server.auth.sign_out()
def Tableau2Slack(): try: # Import Tableau environment variables load_dotenv() # EXAMPLE VALUES: tabAccount = os.getenv('tabAcct') # [email protected] tabPass = os.getenv('tabPwd') # password tabDomain = os.getenv('tabDomain') # site-id tabServer = os.getenv('tabServer') # https://10ay.online.tableau.com tabView = os.getenv('tabView') # InvestorUpdate tabPath = os.getenv('tabPath') # ./InvestorUpdate.png # For further explanation of Tableau environment variables visit: # https://tableau.github.io/server-client-python/docs/api-ref#tableauauth-class # Full list of Tableau Online Server Domains for tabServer variable: # https://help.tableau.com/current/online/en-us/to_keep_data_fresh.htm#safelist print("Talking to Tableau...\n") tableau_auth = TSC.TableauAuth(tabAccount, tabPass, tabDomain) server = TSC.Server(tabServer) # Searching Tableau Online account for the View we declared in env variables with server.auth.sign_in(tableau_auth): server.use_server_version() req_option = TSC.RequestOptions() req_option.filter.add( TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.Equals, tabView)) all_views, pagination_item = server.views.get(req_option) # Error catching for bad View names if not all_views: raise LookupError( "View with the specified name was not found.") view_item = all_views[0] # Force refresh of screenshot if cached image more than one hour old max_age = '1' if not max_age: max_age = '1' image_req_option = TSC.ImageRequestOptions( imageresolution=TSC.ImageRequestOptions.Resolution.High, maxage=max_age) server.views.populate_image(view_item, image_req_option) # Save bytes as image with open(tabPath, "wb") as image_file: image_file.write(view_item.image) print("Tableau image successfully saved to {0}".format(tabPath), '\n') try: # Upload and send customized Slack message # Import Slack environment variables load_dotenv() # EXAMPLE VALUES: slackBotToken = os.getenv( 'slackBotToken') # xoxb-1111111111-111111111-111111111 slackChannel = os.getenv('slackChannel') # #random # for further explanation of Slack environment variables visit: # https://slack.dev/python-slackclient/ # Preparing date to format filename and caption. Change "Sales Analytics" ect. to whatever you like. date = datetime.utcnow().strftime('%Y-%m-%d') utc_dt = datetime.now(timezone.utc) your_tz = pytz.timezone( 'US/Pacific') # Replace with your timezone to localize imagetitle = 'SalesUpdate_{}'.format( utc_dt.astimezone(your_tz).strftime('%Y-%m-%d_%I:%M%p_%Z')) caption = 'Sales Update as of {}'.format( utc_dt.astimezone(your_tz).strftime('%Y-%m-%d %I:%M%p %Z')) captionA = 'Sales Analytics Update' captionB = ' as of {}'.format( utc_dt.astimezone(your_tz).strftime('%Y-%m-%d %I:%M%p %Z')) captionC = ('\n\n*' + captionA + '*' + captionB) # Connect to Slack print("Talking to Slack...\n") sc = WebClient(slackBotToken) # Upload Tableau image to burner channel so that we can securely generate a URL from Tableau image. img = sc.files_upload( channels= '#tableau-test', # You will need to make this channel or another like it. file=tabPath, title=imagetitle, filetype='png') # Store private URL to post in message. url_private = img["file"]["url_private"] # Construct "builder" and "attachments" json payloads. blocksjson = [{ "type": "section", "text": { "type": "mrkdwn", "text": ":level_slider: Queuing up your Daily Dose of Data :control_knobs:" } }, { "type": "image", "image_url": "https://i.imgur.com/Eg4TjJq.png", "alt_text": "Nina Kravisualization" }, { "type": "context", "elements": [{ "type": "mrkdwn", "text": "Want to see more? <https://www.tableau.com/ Insert Your Link to All Dashboards Here>" }] }, { "type": "section", "text": { "type": "mrkdwn", "text": captionC } }] # Note: the use of "attachments" is a work around and may be deprecated in the future. attachmentsjson = [{ 'title': '', 'text': '', 'image_url': url_private, 'alt_text': caption }] # Post images with custom icon and username msg = sc.chat_postMessage( channel=slackChannel, icon_url='https://i.imgur.com/WpMvRvn.jpg', username='******', blocks=json.dumps(blocksjson), attachments=json.dumps(attachmentsjson)) # Remove the local image file once it is posted fileRemoval = '{0}'.format(tabPath) os.remove(fileRemoval) print('Removing image from local machine.') # Out of the box Slack error handling except SlackApiError as e: assert e.response["ok"] is False assert e.response["error"] print(f"Got an error: {e.response['error']}") # Tableau try statement error handling except: traceback.print_exc()
print( "\n -----------------Working on your Dashboard shapshot,please be patient and do not touch anything------------------------ \n") ##Taking the snapshot based on user input # Step 2: Query for the view that we want an image of req_option = TSC.RequestOptions() req_option.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.Equals, v)) all_views, pagination_item = server.views.get(req_option) if not all_views: raise LookupError("View with the specified name was not found.") view_item = all_views[0] max_age = args.maxage if not max_age: max_age = 1 image_req_option = TSC.ImageRequestOptions(imageresolution=TSC.ImageRequestOptions.Resolution.High, maxage=max_age) ##image_req_option.vf('project', temp200[e]) server.views.populate_image(view_item, image_req_option) logging.info('**** View Name/Dashboard Name:' + v) with open(save_image, "wb") as image_file: image_file.write(view_item.image) print("View image saved to {0}".format(save_image)) loc = (excel_book) wb = xlrd.open_workbook(loc) sheet = wb.sheet_by_index(0) sheet.cell_value(0, 0) print("Sending Mail to following User:") ##Fetching the data from the Excel file to send the particular user
def main(): parser = argparse.ArgumentParser(description='Query View Image From Server') parser.add_argument('--maxage', '-m', required=False, help='max age of the image in the cache in minutes.') parser.add_argument('--logging-level', '-l', choices=['debug', 'info', 'error'], default='error', help='desired logging level (set to error by default)') parser.add_argument('--Email_id', '-e', required=True, help='Email id to send snapshot') args = parser.parse_args() print("\n -----------------Working on your Dashboard shapshot,please be patient and do not touch anything------------------------ \n") user = "******" pwd1 = "***" # Set logging level based on user input, or error by default logging_level = getattr(logging, args.logging_level.upper()) logging.basicConfig(filename="C:/Users/sadiqmmo/PycharmProjects/untitled4/test.log", level=logging.INFO,format='%(asctime)s %(levelname)s - %(message)s', datefmt='%a, %d %b %Y %H:%M:%S') logging.info("Sign in Name:" + user) # Step 1: Sign in to server. site_id = "BI_EDM_Dev_QA" if not site_id: site_id = "" tableau_auth = TSC.TableauAuth(user, pwd1, site_id="BI_EDM_Dev_QA") server = TSC.Server(ser) # The new endpoint was introduced in Version 2.5 server.version = "2.5" with server.auth.sign_in(tableau_auth): req_option = TSC.RequestOptions() req_option.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.Equals, 'Run Summary')) all_views, pagination_item = server.views.get(req_option) if not all_views: raise LookupError("View with the specified name was not found.") view_item = all_views[0] max_age = args.maxage if not max_age: max_age = 1 image_req_option = TSC.ImageRequestOptions(imageresolution=TSC.ImageRequestOptions.Resolution.High, maxage=max_age) #image_req_option.vf('Parameter 1', 'PROPHUB') server.views.populate_image(view_item, image_req_option) logging.info('**** View Name/Dashboard Name:' + 'run') with open(save_image, "wb") as image_file: image_file.write(view_item.image) ##print("View image saved to {0}".format(save_image)) outlook = win32.Dispatch('outlook.application') mail = outlook.CreateItem(0) mail.To = args.Email_id mail.Subject = 'EDM RUN SUMMARY SNAPSHOT' Body = 'Message body' attachment = mail.Attachments.Add(attachment_location) attachment.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001F", "MyId1") body = "Dear" + " " + "Team" + ",""<br><br>" + "Please find the attached Latest Run run summary snapshot " + "<br><br> <img src=""cid:MyId1"" height=""700"" width=""1150"">" mail.HTMLBody = (body) mail.Send() print("\n -----------------Mail Send------------------------ \n")
def download_png(server, view_item): req_option_image = TSC.ImageRequestOptions(maxage=1) server.views.populate_image(view_item, req_option_image) return view_item.png
def main(): parser = argparse.ArgumentParser(description='Access to config.yml file') parser.add_argument('--config-file', '-c', default='config.yml', help='config file path. Default is config.yml') args = parser.parse_args() # Load yml config file try: with open(args.config_file, 'r') as ymlfile: cfg = yaml.load(ymlfile, Loader=yaml.FullLoader) except: raise if cfg['tableau_server']['password'] is None: password = getpass.getpass("Password: "******"-------- Starting checks for wb: {0} --------".format( wb.name)) # CHECK 1: Validate that the number of views in the wb doesn't exceed the max views threshold if len(wb.views) > int(cfg['performance_thresholds']['max_views']): print( "Number of Max Views exceeded {0} Rejecting workbook {1}". format(len(wb.views), wb.name)) reject_wb(wb, server, search_tags, cfg['tags']['reject_tag']) is_rejected = True # CHECK 2: render every view of the wb and validate against the maximum render time threshold for view in wb.views: if is_rejected: break print(" Evaluating: {0} ".format(view.name)) start_time = time.time() # We have a number of different types and functions for each different export type. # However, in this case what we want to do is just to populate the view without creating a physical file # Therefore, we just unroll simulate the rendering of an image that we can call by using getattr() # Note that we use image in order to be able to bypass the cache with the maxage parameter. view_req_option = TSC.ImageRequestOptions( imageresolution=TSC.ImageRequestOptions.Resolution.High, maxage=1) server.views.populate_image(view, view_req_option) getattr(view, "image") elapsed_time = time.time() - start_time print( "----render time in seconds --- {0}".format(elapsed_time)) # Validate the execution time against designated treshold to render view is_rejected = elapsed_time > int( cfg['performance_thresholds']['max_elapsed_time']) # if the wb is poor performant we tag it as rejected if is_rejected: print( "Maximum elapsed time exceeded {0} Rejecting workbook {1}" .format(elapsed_time, wb.name)) reject_wb(wb, server, search_tags, cfg['tags']['reject_tag'])
def main(): parser = argparse.ArgumentParser( description='Query View Image From Server') parser.add_argument('--server', '-s', required=True, help='server address') parser.add_argument('--site-id', '-si', required=False, help='content url for site the view is on') parser.add_argument('--username', '-u', required=True, help='username to sign into server') parser.add_argument('--view-name', '-v', required=True, help='name of view to download an image of') parser.add_argument('--filepath', '-f', required=True, help='filepath to save the image returned') parser.add_argument('--logging-level', '-l', choices=['debug', 'info', 'error'], default='error', help='desired logging level (set to error by default)') args = parser.parse_args() password = getpass.getpass("Password: "******"" tableau_auth = TSC.TableauAuth(args.username, password, site_id=site_id) server = TSC.Server(args.server) # The new endpoint was introduced in Version 2.5 server.version = "2.5" with server.auth.sign_in(tableau_auth): # Step 2: Query for the view that we want an image of req_option = TSC.RequestOptions() req_option.filter.add( TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.Equals, args.view_name)) all_views, pagination_item = server.views.get(req_option) if not all_views: raise LookupError("View with the specified name was not found.") view_item = all_views[0] # Step 3: Query the image endpoint and save the image to the specified location image_req_option = TSC.ImageRequestOptions( imageresolution=TSC.ImageRequestOptions.Resolution.High) server.views.populate_image(view_item, image_req_option) with open(args.filepath, "wb") as image_file: image_file.write(view_item.image) print("View image saved to {0}".format(args.filepath))
def main(): parser = argparse.ArgumentParser( description='Download image of a specified view.') # Common options; please keep those in sync across all samples parser.add_argument('--server', '-s', required=True, help='server address') parser.add_argument('--site', '-S', help='site name') parser.add_argument( '--token-name', '-p', required=True, help='name of the personal access token used to sign into the server') parser.add_argument( '--token-value', '-v', required=True, help='value of the personal access token used to sign into the server') parser.add_argument('--logging-level', '-l', choices=['debug', 'info', 'error'], default='error', help='desired logging level (set to error by default)') # Options specific to this sample parser.add_argument('--view-name', '-vn', required=True, help='name of view to download an image of') parser.add_argument('--filepath', '-f', required=True, help='filepath to save the image returned') parser.add_argument('--maxage', '-m', required=False, help='max age of the image in the cache in minutes.') args = parser.parse_args() # Set logging level based on user input, or error by default logging_level = getattr(logging, args.logging_level.upper()) logging.basicConfig(level=logging_level) # Step 1: Sign in to server. tableau_auth = TSC.PersonalAccessTokenAuth(args.token_name, args.token_value, site_id=args.site) server = TSC.Server(args.server, use_server_version=True) with server.auth.sign_in(tableau_auth): # Step 2: Query for the view that we want an image of req_option = TSC.RequestOptions() req_option.filter.add( TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.Equals, args.view_name)) all_views, pagination_item = server.views.get(req_option) if not all_views: raise LookupError("View with the specified name was not found.") view_item = all_views[0] max_age = args.maxage if not max_age: max_age = 1 image_req_option = TSC.ImageRequestOptions( imageresolution=TSC.ImageRequestOptions.Resolution.High, maxage=max_age) server.views.populate_image(view_item, image_req_option) with open(args.filepath, "wb") as image_file: image_file.write(view_item.image) print("View image saved to {0}".format(args.filepath))