Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions 79 samples/pagination_sample.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
####
# This script demonstrates how to use pagination item that is returned as part
# of many of the .get() method calls.
#
# This script will iterate over every workbook that exists on the server using the
# pagination item to fetch additional pages as needed.
#
# While this sample uses workbook, this same technique will work with any of the .get() methods that return
# a pagination item
####

import argparse
import getpass
import logging
import os.path

import tableauserverclient as TSC


class pagination_generator(object):
""" This class returns a generator that will iterate over all of the results.

server is the server object that will be used when calling the callback. It will be passed
to the callback on each iteration

Callback is expected to take a server object and a request options and return two values, an array of results,
and the pagination item from the current call. This will be used to build subsequent requests.
"""

def __init__(self, fetch_more):
self._fetch_more = fetch_more

def __call__(self):
current_item_list, last_pagination_item = self._fetch_more(None) # Prime the generator
count = 0

while count < last_pagination_item.total_available:
if len(current_item_list) == 0:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just do if not current_item_list but I think the equality so 0 might make this case a little clearer so not a strong recommendation.

current_item_list, last_pagination_item = self._load_next_page(current_item_list, last_pagination_item)

yield current_item_list.pop(0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has to rebuild the list every time, only popping from the end is O(1).

I don't know if it matters that much here, if we decide it does some options:

  1. make current_item_list a deque
  2. pop from the end which would reverse the order from when w get the response but maybe it doesn't matter

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think for the sample, I'm going to leave it as is, but replace this once I implement the larger effort.

count += 1

def _load_next_page(self, current_item_list, last_pagination_item):
next_page = last_pagination_item.page_number + 1
opts = TSC.RequestOptions(pagenumber=next_page, pagesize=last_pagination_item.page_size)
current_item_list, last_pagination_item = self._fetch_more(opts)
return current_item_list, last_pagination_item


def main():

parser = argparse.ArgumentParser(description='Return a list of all of the workbooks on your server')
parser.add_argument('--server', '-s', required=True, help='server address')
parser.add_argument('--username', '-u', required=True, help='username to sign into server')
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: ")

# Set logging level based on user input, or error by default
logging_level = getattr(logging, args.logging_level.upper())
logging.basicConfig(level=logging_level)

# SIGN IN

tableau_auth = TSC.TableauAuth(args.username, password)
server = TSC.Server(args.server)

with server.auth.sign_in(tableau_auth):
generator = pagination_generator(server.workbooks.get)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like we talked about ... this should take the options object so that we can support filters. I know I mentioned the optional additional arguments in case a get method takes more than just options but for now, you probably don't need to add this. Let's put the "paginator" in our server directory so that is it is a supported utility and then that will simplify our code. Would like Ben to comment on the name.

print("Your server contains the following workbooks:\n")
for wb in generator():
print(wb.name)

if __name__ == '__main__':
main()
Morty Proxy This is a proxified and sanitized view of the page, visit original site.