From 8d254ccdc48a0df7160e5303ae2f589a9a88923d Mon Sep 17 00:00:00 2001 From: Bryant Howell Date: Tue, 7 Jan 2020 07:23:15 -0600 Subject: [PATCH 1/3] incremented to 5.1.1 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9b6ca90..e7ed9cf 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup( name='tableau_tools', python_requires='>=3.6', - version='5.1.0', + version='5.1.1', packages=['tableau_tools', 'tableau_tools.tableau_rest_api', 'tableau_tools.tableau_documents', 'tableau_tools.examples', 'tableau_tools.tableau_rest_api.methods'], url='https://github.com/bryantbhowell/tableau_tools', From 9dc235c4ceaf438b67ef49aa7e2d168cdfd747e7 Mon Sep 17 00:00:00 2001 From: Bryant Howell Date: Mon, 13 Jan 2020 13:15:55 -0600 Subject: [PATCH 2/3] Added logic to the packaged file saving to check for existing directories (mostly the 'data' directory), so that the cleanup doesn't remove anything that was already on disk --- tableau_documents/tableau_file.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tableau_documents/tableau_file.py b/tableau_documents/tableau_file.py index 7e96bb1..67ad7ee 100644 --- a/tableau_documents/tableau_file.py +++ b/tableau_documents/tableau_file.py @@ -417,14 +417,23 @@ def save_new_file(self, new_filename_no_extension: str): os.remove(self.packaged_filename) temp_directories_to_remove = {} - + # Store any directories that already existed, so you don't clean up exiting directory on disk + existing_directories = [] + all_in_working_dir = os.listdir() + for l in all_in_working_dir: + if (os.path.isdir(l)): + existing_directories.append(l) + # Now actually go through all the other files, extract them, put into the new ZIP file, then clean up if len(self.other_files) > 0: file_obj = open(self.orig_filename, 'rb') o_zf = zipfile.ZipFile(file_obj) for filename in self.other_files: self.log('Looking into additional files: {}'.format(filename)) - + lowest_level = filename.split('/') + # Only delete out if it didn't exist prior to saving out of the original ZIPfile + if lowest_level[0] not in existing_directories: + temp_directories_to_remove[lowest_level[0]] = True if self.file_replacement_map and filename in self.file_replacement_map: new_zf.write(self.file_replacement_map[filename], "/" + filename) # Delete from the data_file_replacement_map to reduce down to end @@ -434,8 +443,7 @@ def save_new_file(self, new_filename_no_extension: str): new_zf.write(filename) os.remove(filename) self.log('Removed file {}'.format(filename)) - lowest_level = filename.split('/') - temp_directories_to_remove[lowest_level[0]] = True + file_obj.close() # Loop through remaining files in data_file_replacement_map to just add From 3e82963df27e1970c0f129e2c34cf5a2ed928394 Mon Sep 17 00:00:00 2001 From: Bryant Howell Date: Fri, 24 Jan 2020 14:03:56 -0600 Subject: [PATCH 3/3] Updated README on a common exception pattern --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 410a696..8f7a6c7 100644 --- a/README.md +++ b/README.md @@ -345,6 +345,8 @@ You can get all of the values from the previous object, if it has been signed in Now any actions you take with t2 will be the same session to the Tableau Server as those taken with t1. This can also be very useful for multi-threaded programming, where you may want to clone instances of an object so that they don't interact with one another while doing things on different threads, but still use the same REST API session. ### 1.2 Basics and Querying +NOTE: If you get a "RecursionError: maximum recursion depth exceeded" Exception, it generally means that you are trying a method that does not exist. The most common reason for this with the TableauServerRest objects is when porting code over from TableauRestApiConnection objects. All methods except for lookups live under a sub-object (t.users.method()) in TableauServerRest, so if you put a method directly on the main object, it will try and search for it but error out. This issue can work the other way, if you try and use a sub-object under TableauRestApiConnection when it doesn't exist. + #### 1.2.0 ElementTree.Element XML Responses As mentioned in the 0 section, tableau_tools returns ElementTree.Element responses for any XML request. To know exactly what is available in any given object coming back from the Tableau REST API, you'll need to either consult the REST API Reference or convert to it something you can write to the console or a text file.