Skip to content
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

populate_connections doesn't fetch datasource_id #1536

Open
LuigiCerone opened this issue Nov 21, 2024 · 7 comments
Open

populate_connections doesn't fetch datasource_id #1536

LuigiCerone opened this issue Nov 21, 2024 · 7 comments
Labels

Comments

@LuigiCerone
Copy link

LuigiCerone commented Nov 21, 2024

Describe the bug

Hi,

I'm encountering an issue with the Tableau Python client. Specifically, the datasource_id is missing from the ConnectionItem object.

Here’s the scenario: after retrieving a datasource by id, I populate its connections, but the ConnectionItem objects lack the datasource information.

From reviewing the source code:

url = f"{self.baseurl}/{datasource_item.id}/connections"

it seems the REST method being used by the module is: GET /api/api-version/sites/site-id/datasources/datasource-id/connections.

According to the official documentation, this method does not appear to return datasource information.

Versions

  • Tableau Cloud 2024.3
  • Python version: 3.11.0
  • TSC library version: 0.34

To Reproduce

import os
import tableauserverclient as TSC

token_name = 'my_token'
token_value = os.environ['TABLEAU_TOKEN']
tableau_site = 'my-site-it'
tableau_server = 'https://eu-west-1a.online.tableau.com'
datasource_id = 'REPLACE_ME'


def main():
    tableau_auth = TSC.PersonalAccessTokenAuth(token_name, token_value, site_id=tableau_site)
    server = TSC.Server(tableau_server, use_server_version=True)
    with server.auth.sign_in(tableau_auth):
        ds = server.datasources.get_by_id(datasource_id)
        server.datasources.populate_connections(ds)

        # This will fail
        assert ds.connections[0].datasource_id


if __name__ == '__main__':
    main()

Results

connections[0].datasource_id is None, data is not fetched from the REST API.

Thanks :)

@jacalata jacalata added the bug label Nov 22, 2024
@jacalata
Copy link
Contributor

Yes, that's a bug. We can populate the id from the datasource information we already have, I can add that.

@LuigiCerone
Copy link
Author

Hello @jacalata, thanks for your reply. That sounds great!
If you'd like, I can work on that, but I'm not entirely sure what your idea is. Could you clarify?

Regarding the ConnectionItem class, since its properties don't have setter methods, what's your idea?

If I'm not mistaken, there are only two factory methods that directly process the XML response from the API:

def from_response(cls, resp, ns) -> list["ConnectionItem"]:

It seems that the API doesn't return this information.

Would it be okay to add a setter method like this to the ConnectionItem class?

    @property.setter
    def datasource_id(self, datasource_id) -> None:
        self._datasource_id = datasource_id

@jorwoods
Copy link
Contributor

@LuigiCerone what are you expecting that datasource_id to be? The id of the datasource on which you called populate_connections? Or an upstream datasource that the connection pulls data from?

@LuigiCerone
Copy link
Author

LuigiCerone commented Nov 22, 2024

Hello @jorwoods

The id of the datasource on which you called populate_connections?

This

@jorwoods
Copy link
Contributor

jorwoods commented Nov 24, 2024

@LuigiCerone can you help me understand what this enables beyond using the id or datasource object you already have?

@jacalata I propose we remove the datasource_id and name from the connection item entirely. Theoretically a breaking change but since it's never been populated, usage should be basically non-existent. My thinking is:

  1. If we're going to wire up datasource id and name, then we should also do workbook_id and name.
  2. Different names breaks symmetry.
  3. Having different names for the originating object means the users script would have to know the type of the originating object.
  4. Different names means we have two null attributes all of the time, that cannot be populated in a way that makes any sense.
  5. With these non-settable properties removed, there is nothing preventing the user from adding their own custom attributes to the object, named whatever they so choose.

@LuigiCerone
Copy link
Author

@LuigiCerone can you help me understand what this enables beyond using the id or datasource object you already have?

The issue regarding the missing datasource value within the collection came up because I was trying to update the hyper data via the API using the method:

job = server.datasources.(
    ds.connections[0],
    request_id=request_id,
    actions=actions,
    payload=payload
)

Inside update_hyper_data implementation there is this:

elif isinstance(datasource_or_connection_item, ConnectionItem):
datasource_id = datasource_or_connection_item.datasource_id
connection_id = datasource_or_connection_item.id
url = f"{self.baseurl}/{datasource_id}/connections/{connection_id}/data"

which fails with the aformentioned problem.

jorwoods added a commit to jorwoods/server-client-python that referenced this issue Nov 25, 2024
Closes tableau#1536

Populates the datasource id and name on the `ConnectionItem`s
as they return.
jorwoods added a commit to jorwoods/server-client-python that referenced this issue Nov 25, 2024
Closes tableau#1536

Populates the datasource id and name on the `ConnectionItem`s
as they return.
@jorwoods
Copy link
Contributor

Based on the legitimate and internal usage of the datasource_id, I withdraw my proposal of removing those attributes. I submitted a PR to carry through the datasource id and name.

jacalata pushed a commit that referenced this issue Nov 27, 2024
Closes #1536

Populates the datasource id and name on the `ConnectionItem`s
as they return.

Co-authored-by: Jordan Woods <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants