From c4135eb962dbf05c5b1644e2ed437272eec8894d Mon Sep 17 00:00:00 2001 From: Lan <53841803+lanlooker@users.noreply.github.com> Date: Thu, 17 Jun 2021 02:36:22 +0900 Subject: [PATCH] feat(New Python Examples): Adding 2 new Python examples (#701) * new examples (python) Hi team, I am submitting two new examples using Python, as part of the "reduce contact rate" effort. I'd appreciate your comment and review so I can improve on my future code snippets. Thank you * Add in the readme file * Update README.md * Update README.md * Update transfer_all_schedules.py take out PII email addresses * Update transfer_all_schedules.py --- examples/python/README.md | 19 ++++- examples/python/add_contents_to_favorite.py | 80 +++++++++++++++++++++ examples/python/transfer_all_schedules.py | 76 ++++++++++++++++++++ 3 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 examples/python/add_contents_to_favorite.py create mode 100644 examples/python/transfer_all_schedules.py diff --git a/examples/python/README.md b/examples/python/README.md index 22f596b90..2d07cdbfa 100644 --- a/examples/python/README.md +++ b/examples/python/README.md @@ -2,20 +2,33 @@ You can find Python language examples in this folder. -## Connection management +## Connection Management - [Test a specified connection](test_connection.py) -## Manage Dashboards +## Content Access Management + +- [Add a board or dashboard to Favorites for a list of users](add_contents_to_favorite.py) + +## Dashboards Management - [Soft delete dashboard](soft_delete_dashboard.py) -## Manage Render Tasks +## Render Tasks Management - [Download dashboard tile in specified format](download_tile.py) - [Download look in specified format](download_look.py) - [Generate and download dashboard PDFs](download_dashboard_pdf.py) +## Schedules Management + +- [Transfer all schedules of a user to another user](transfer_all_schedules.py) + ## User Management - [Disable all active user sessions](logout_all_users.py) + + + + + diff --git a/examples/python/add_contents_to_favorite.py b/examples/python/add_contents_to_favorite.py new file mode 100644 index 000000000..fb558ac2d --- /dev/null +++ b/examples/python/add_contents_to_favorite.py @@ -0,0 +1,80 @@ +""" +The purpose of this script is to add a specific Dashboard or Board to "Favorites" +for a list of users, which may help new users discover useful Looker contents quicker and easier. + +The script contains two functions (add_boards_to_users and add_dashboards_to_users) that are similar +in logic and execution. Example function calls are placed at the end of the script. + +Author: Lan +Last modified: June 16, 2021 +""" + +import looker_sdk + +sdk = looker_sdk.init40() + +def add_boards_to_users(board_id: int, users_id: list): + + """ Add a specific board to the "Favorite" contents for a list of user + + Args: + board_id (int): id of a Looker board (https://company.looker.com/boards/id) + users_id (list): a list of users id (int) in the form of a native Python list + + Returns: "Successfully added!" (str) + + Raises: N/A (does not explicitly raise an exception); Looker SDK will raise an error. + """ + + content_metadata_id = sdk.board(board_id=board_id)['content_metadata_id'] + + """An admin can not update the list of favorite contents for users, + so sdk.auth.login_user() and sdk.auth.logout() are called to sudo as each user to call `create_content_favorite()""" + for i in users_id: + sdk.auth.login_user(i) + params = {} + params["user_id"] = i + params["content_metadata_id"] = content_metadata_id + sdk.create_content_favorite(params) + sdk.auth.logout() + + print("Successfully added!") + + + +""" The logic for `add_dashboards_to_users` is the same, except that `dashboard_id` is a string (because LookML dashboard id is a string). +Also, we are using `sdk.dashboard()` to retrieve `content_metadata_id`""" + + +def add_dashboards_to_users(dashboard_id: str, users_id: list): + + """ Add a specific dashboard to the list of favorite contents for a list of user + + Args: + dashboard_id (str): id of a Looker dashboard (https://company.looker.com/dashboards/id) + users_id (list): a list of users id in the form of a native Python list + + Returns: "Successfully added!" (str) + + Raises: N/A (does not explicitly raise an exception); Looker SDK will raise an error. + """ + + content_metadata_id = sdk.dashboard(dashboard_id=dashboard_id)['content_metadata_id'] + + """An admin can not update the list of favorite contents for users, + sdk.auth.login_user() and `sdk.auth.logout()` are called to sudo as each user to call `create_content_favorite()""" + for i in users_id: + sdk.auth.login_user(i) + params = {} + params["user_id"] = i + params["content_metadata_id"] = content_metadata_id + sdk.create_content_favorite(params) + sdk.auth.logout() + + print("Successfully added!") + + + +# Call the functions +add_boards_to_users(board_id = 1, users_id = [1]) +add_dashboards_to_users(dashboard_id = "string", users_id = [1]) \ No newline at end of file diff --git a/examples/python/transfer_all_schedules.py b/examples/python/transfer_all_schedules.py new file mode 100644 index 000000000..836365e6e --- /dev/null +++ b/examples/python/transfer_all_schedules.py @@ -0,0 +1,76 @@ +""" +This script transfers all schedules of a user to a different user using their email addreseses as parameter. +The script may come in handy when a user leaves an organization, and Looker admins have to re-assign all of +their existing schedules to a new user. + +The script is using customized if/else conditions to check for edge cases (i.e. if email addresses are associated +with existing Looker users, if a user has any schedules, etc.) before reading data and calling the functions. + +Author: Lan +Last modified: June 16, 2021 +""" +import looker_sdk + +sdk = looker_sdk.init40() + +def find_user_id(email: str): + + """ Given an email address, find the corresponding Looker user id + Args: email (str) + Returns: the Looker user id associated with the email addresses (int) + Raises: N/A (does not explicitly raise an exception) + """ + user_id = sdk.search_users(email=email) + + """ Customized logic block to check if an email address is associated with a Looker user""" + if len(user_id) == 0: + return 'There is no user associated with this email' + else: + return user_id[0]['id'] + + +def find_schedules(user_id: int): + + """ Return all schedules of a particular user id + Args: user_id (int) + Returns: all schedules of a particular user: result = {'name_of_schedule_plan': id_of_schedule_plan} + Raises: N/A (does not explicitly raise an exception) + """ + result = {} + schedule_plans = sdk.all_scheduled_plans(user_id=user_id) + for i in schedule_plans: + result[i['name']] = i['id'] + return result + + +def update_owner(current_owner_email: str, new_owner_email: str): + + """ Transfer all schedules of `foo@looker.com` to `bar@looker.com` + Args: current_owner_email (str), new_owner_email (str) + Returns: None (a warning message or a success message will be printed to console) + Raises: customized warning messages in if/else block + """ + current_owner_id = find_user_id(current_owner_email) + new_owner_id = find_user_id(new_owner_email) + + """ This block is executed to check if email addresses provided are associated with two Looker users """ + + if type(new_owner_id) != int and type(new_owner_id) != int: + print("The email addresses for both the current owner and the new owner are not associated with any Looker user id") + + elif type(current_owner_id) != int: + print("The email address for the current owner is not associated with any Looker user id") + + elif type(new_owner_id) != int: + print("The email address for the new owner is not associated with any Looker user id") + + else: + body = {} + body['user_id'] = new_owner_id + find = find_schedules(current_owner_id) + for i in find.values(): + sdk.update_scheduled_plan(i,body) + print("Successfully transfer all schedules of " + current_owner_email + " to " + new_owner_email) + +# Call the function +update_owner('foo@looker.com', 'bar@looker.com')