tableau / server-client-python

A Python library for the Tableau Server REST API
https://tableau.github.io/server-client-python/
MIT License
661 stars 421 forks source link

Workbooks,download fails for Tableau Server v.2023.1.7 #1312

Closed ElenasemDA closed 9 months ago

ElenasemDA commented 1 year ago

Describe the bug Workbooks.download fails with an error in regard to 'filename'. Versions: Tableau Server 2023.1.7 (API 3.19), tableauserverclient-0.14.1, python 3.7.9 (tested also: Tableau Server 2023.1.7 (API 3.19), tableauserverclient-0.28, python 3.9.13)

To Reproduce server_int = TSC.Server("https://yousite",use_server_version = True) tableau_auth_int = TSC.TableauAuth("username", "password", site_id='sitename')

with server_int.auth.sign_in(tableau_auth_int):

workbook= server_int.workbooks.get_by_id('fca33a9a-0139-41b9-b1e7-841a92bf5f92')
wkbk=workbook.name
print(workbook.name)        
print(workbook.id)
file_path = server_int.workbooks.download('fca33a9a-0139-41b9-b1e7-841a92bf5f92')
print("\nDownloaded the file to {0}.".format(file_path))

Results WorkbookName fca33a9a-0139-41b9-b1e7-841a92bf5f92

KeyError Traceback (most recent call last) ~\AppData\Local\Temp\1\ipykernel_7340\2448852531.py in 5 print(workbook.name) 6 print(workbook.id) ----> 7 file_path = server_int.workbooks.download('fca33a9a-0139-41b9-b1e7-841a92bf5f92') 8 print("\nDownloaded the file to {0}.".format(file_path))

E:\Anaconda3\envs\Tableau_analytics\lib\site-packages\tableauserverclient\server\endpoint\endpoint.py in wrapper(self, *args, kwargs) 290 def wrapper(self, *args, *kwargs): 291 self.parent_srv.assert_at_least_version(version, self.class.name) --> 292 return func(self, args, kwargs) 293 294 return wrapper

E:\Anaconda3\envs\Tableau_analytics\lib\site-packages\tableauserverclient\server\endpoint\endpoint.py in wrapper(self, *args, *kwargs) 332 error = "{!r} not available in {}, it will be ignored. Added in {}".format(p, server_ver, min_ver) 333 warnings.warn(error) --> 334 return func(self, args, **kwargs) 335 336 return wrapper

E:\Anaconda3\envs\Tableau_analytics\lib\site-packages\tableauserverclient\server\endpoint\endpoint.py in wrapper(self, *args, *kwargs) 332 error = "{!r} not available in {}, it will be ignored. Added in {}".format(p, server_ver, min_ver) 333 warnings.warn(error) --> 334 return func(self, args, **kwargs) 335 336 return wrapper

E:\Anaconda3\envs\Tableau_analytics\lib\site-packages\tableauserverclient\server\endpoint\workbooks_endpoint.py in download(self, workbook_id, filepath, include_extract, no_extract) 182 no_extract: Optional[bool] = None, 183 ) -> str: --> 184 return self.download_revision(workbook_id, None, filepath, include_extract, no_extract) 185 186 # Get all views of workbook

E:\Anaconda3\envs\Tableau_analytics\lib\site-packages\tableauserverclient\server\endpoint\endpoint.py in wrapper(self, *args, kwargs) 290 def wrapper(self, *args, *kwargs): 291 self.parent_srv.assert_at_least_version(version, self.class.name) --> 292 return func(self, args, kwargs) 293 294 return wrapper

E:\Anaconda3\envs\Tableau_analytics\lib\site-packages\tableauserverclient\server\endpoint\workbooks_endpoint.py in download_revision(self, workbook_id, revision_number, filepath, include_extract, no_extract) 488 return_path = filepath 489 else: --> 490 filename = to_filename(os.path.basename(params["filename"])) 491 download_path = make_download_path(filepath, filename) 492 with open(download_path, "wb") as f:

KeyError: 'filename'

NOTE: Be careful not to post user names, passwords, auth tokens or any other private or sensitive information.

hersh-gupta commented 1 year ago

It looks like the filename header in the following was changed to filename*, throwing the error: https://github.com/tableau/server-client-python/blob/72eb3c8500193e4f20defa20c8a6f8bbf34b2f43/tableauserverclient/server/endpoint/workbooks_endpoint.py#L483-L495

DGordon-Placer commented 1 year ago

@hersh-gupta @ElenasemDA we have run into this issue as well. Any rough idea of how long things like this usually take to get resolved?

mendon26 commented 1 year ago

Any updates on this? We are facing the same issue.

hahu66 commented 1 year ago

Same issue here, after upgrading from 2023.1.5 to 2023.1.7 Looks like a change in Rest API version 3.19? There is no "filename" return in the 'params' set on line 484

File "C:\Program Files\Python38\lib\site-packages\tableauserverclient\server\endpoint\workbooks_endpoint.py", line 490, in download_revision filename = to_filename(os.path.basename(params["filename"])) KeyError: 'filename'

madreyg commented 1 year ago

Hello. We faced the same problem. We are looking forward to the fix.

DGordon-Placer commented 1 year ago

Update From our side, we did a test and upgraded our dev server to 2023.3.0 and it looks like the issue has been resolved. However, we've learnt from past experiences to never upgrade our production server to an 20XX.X.0 version as there are usually very buggy and cause more damage than they fix. We're going to wait till 2023.3.1 comes out.

galmarco commented 1 year ago

Any update on this issue? we are facing the same.

Soltis12 commented 12 months ago

Also getting this error. Awaiting a fix.

nir9696 commented 12 months ago

I'm also encountering this error. Looking forward to a resolution.

ManikandanUV commented 12 months ago

facing this same issue after our server upgrade. Please push a fix to the python client.

ElenasemDA commented 11 months ago

We use the snippet below instead of calling the server.workbooks.download (v.2023.1.7). Check if you can incorporate it to your processes.

with closing(server_int.workbooks.get_request(url, parameters={"stream": True})) as serverresponse: , params = cgi.parse_header(server_response.headers["Content-Disposition"]) if isinstance(ind_path, io_types_w): for chunk in server_response.iter_content(1024): # 1KB ind_path.write(chunk) return_path = ind_path else: filename = to_filename(os.path.basename(params["filename*"])) filename = filename.replace("UTF-8","").replace("+"," ") filename = filename.replace("28","(").replace("29",")") download_path = make_download_path(ind_path, filename) with open(download_path, "wb") as f: for chunk in server_response.iter_content(1024): # 1KB f.write(chunk) return_path = os.path.abspath(download_path)

nir9696 commented 11 months ago

We use the snippet below instead of calling the server.workbooks.download (v.2023.1.7). Check if you can incorporate it to your processes.

with closing(server_int.workbooks.get_request(url, parameters={"stream": True})) as serverresponse: , params = cgi.parse_header(server_response.headers["Content-Disposition"]) if isinstance(ind_path, io_types_w): for chunk in server_response.iter_content(1024): # 1KB ind_path.write(chunk) return_path = ind_path else: filename = to_filename(os.path.basename(params["filename*"])) filename = filename.replace("UTF-8","").replace("+"," ") filename = filename.replace("28","(").replace("29",")") download_path = make_download_path(ind_path, filename) with open(download_path, "wb") as f: for chunk in server_response.iter_content(1024): # 1KB f.write(chunk) return_path = os.path.abspath(download_path)

This is my workaround snippet. maybe you'll find it useful as well until the fix:

def _decode_filename(self, params):
    if 'filename*' in params:
        encoded_filename = params['filename*']
        if encoded_filename.startswith("UTF-8''"):
            encoded_filename = encoded_filename[
                               7:]  # strip off the "UTF-8''" prefix
        filename = urllib.parse.unquote_plus(
            encoded_filename)  # decode percent-encoded octets
    elif 'filename' in params:
        filename = params['filename']
    else:
        filename = None

    return filename

# Download 1 workbook revision by revision number
@api(version="2.3")
def download_revision(
    self,
    workbook_id: str,
    revision_number: str,
    filepath: Optional[PathOrFileW] = None,
    include_extract: bool = True,
    no_extract: Optional[bool] = None,
) -> PathOrFileW:
    if not workbook_id:
        error = "Workbook ID undefined."
        raise ValueError(error)
    if revision_number is None:
        url = "{0}/{1}/content".format(self.baseurl, workbook_id)
    else:
        url = "{0}/{1}/revisions/{2}/content".format(self.baseurl, workbook_id, revision_number)

    if no_extract is False or no_extract is True:
        import warnings

        warnings.warn(
            "no_extract is deprecated, use include_extract instead.",
            DeprecationWarning,
        )
        include_extract = not no_extract

    if not include_extract:
        url += "?includeExtract=False"

    with closing(self.get_request(url, parameters={"stream": True})) as server_response:
        _, params = cgi.parse_header(server_response.headers["Content-Disposition"])
        if isinstance(filepath, io_types_w):
            for chunk in server_response.iter_content(1024):  # 1KB
                filepath.write(chunk)
            return_path = filepath
        else:
            filename = self._decode_filename(params)
            filename = to_filename(os.path.basename(filename))
            download_path = make_download_path(filepath, filename)
            with open(download_path, "wb") as f:
                for chunk in server_response.iter_content(1024):  # 1KB
                    f.write(chunk)
            return_path = os.path.abspath(download_path)

    logger.info(
        "Downloaded workbook revision {0} to {1} (ID: {2})".format(revision_number, return_path, workbook_id)
    )
    return return_path
hjwilliam commented 11 months ago

Same issue for us since upgrading to 2023.1.7 - looking forward to a fix.

PradeepDoddarangaiah commented 11 months ago

facing the same issue in 2023.1.7. Looking forward to a resolution.

rickymedrano commented 11 months ago

Faced the same issue. You can fix it by opening /{path/to/your/python-libraries}/site-packages/tableauserverclient/server/endpoint/workbooks_endpoint.py and on line 490 update: "...(params["filename"]))" to "...(params["filename*"]))" Workbooks should now download but they have "UTF-8" appended to beginning of their name so you can write some code to take care of that until they patch this issue. Will probably need to edit the datasources file as well to handle downloading datasources.

ManikandanUV commented 11 months ago

Our code uses both workbook endpoint and datasource endpoint, and is a mixture of upgraded as well as old version servers, so these are the changes I did to get it working for our usecase.

/venv/lib/python3.8/site-packages/tableauserverclient/server/endpoint/workbooks_endpoint.py

205             try:
206                 filename = to_filename(os.path.basename(params["filename*"]))
207                 filename = filename.replace("UTF-8","").replace("+"," ")
208             except KeyError:
209                 filename = to_filename(os.path.basename(params["filename"]))

venv/lib/python3.8/site-packages/tableauserverclient/server/endpoint/datasources_endpoint.py

161             try:
162                 filename = to_filename(os.path.basename(params["filename*"]))
163                 filename = filename.replace("UTF-8","").replace("+"," ")
164             except KeyError:
165                 filename = to_filename(os.path.basename(params["filename"]))
amarkoe2018 commented 11 months ago

We also are affected by this issue.

bcantoni commented 10 months ago

For anyone facing this issue, please try downloaded the new v0.29 release. It includes #1330 which should fix this.

SebMontreal06 commented 9 months ago

unfortunately, i get an issue with 0.29 to uploading datasources : 400011: Bad Request There was a problem publishing the file '17851:753240939c9444f4a364f54c39c26e3e-1:0'

jorwoods commented 9 months ago

@SebMontreal06 That is different than the problem being discussed in this issue. Please open a new issue.

SebMontreal06 commented 9 months ago

I create a support case for that

On Mon, Jan 22, 2024 at 2:41 PM jorwoods @.***> wrote:

@SebMontreal06 https://github.com/SebMontreal06 That is different than the problem being discussed in this issue. Please open a new issue.

— Reply to this email directly, view it on GitHub https://github.com/tableau/server-client-python/issues/1312#issuecomment-1904770500, or unsubscribe https://github.com/notifications/unsubscribe-auth/AENNTRR5XDQT2QVIVOWBXF3YP3FGLAVCNFSM6AAAAAA63RQWBSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSMBUG43TANJQGA . You are receiving this because you were mentioned.Message ID: @.***>

-- Regards

Sebastien Henry Tel : 737 205 9066 Mail : @.***

bcantoni commented 9 months ago

I'm going to resolve this one as closed/fixed now. If anyone is encountering problems like this after upgrading to v.030, please open a new issue with details.