-
Notifications
You must be signed in to change notification settings - Fork 446
Adding pagination sample #72
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
Changes from all commits
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 |
|---|---|---|
| @@ -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: | ||
| current_item_list, last_pagination_item = self._load_next_page(current_item_list, last_pagination_item) | ||
|
|
||
| yield current_item_list.pop(0) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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() |
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.
You can just do
if not current_item_listbut I think the equality so 0 might make this case a little clearer so not a strong recommendation.