tableau/server-client-python

AttributeError: 'NoneType' object has no attribute 'id'

naresh251 opened this issue · 3 comments

Describe the bug
A clear and concise description of what the bug is.

Versions
Details of your environment, including:

  • Tableau Online
  • Python version: 3.8
  • TSC library version 3.22

To Reproduce
Steps to reproduce the behavior. Please include a code snippet where possible.

# Name of the data source in tableau
datasource = sys.argv[1]
 
tableau_auth = tsc.PersonalAccessTokenAuth(
    token_name=personal_access_token_name,
    personal_access_token=personal_access_token_secret,
    site_id=site
)
server = tsc.Server(tableau_server, use_server_version=True)
server.auth.sign_in(tableau_auth)
 
# Get datasource id from datasource name
req_option = tsc.RequestOptions(pagesize=1000)
req_option.filter.update([tsc.Filter(tsc.RequestOptions.Field.Name, tsc.RequestOptions.Operator.Equals, datasource)])
all_datasources = list(tsc.Pager(server.datasources, req_option))
 
datasource_id = all_datasources[0].id
 
# Get 1000 tasks and then filter for only extract tasks under the datasource id of interest
# I don't believe you can filter tasks
all_extracts = list(tsc.Pager(server.tasks, tsc.RequestOptions(pagesize=1000)))
 
# The task type for incremental extracts is 'IncrementExtractTask' and full extracts is 'extractRefresh'
# The task type for incremental exrracts via Bridges is 'IncrementExtractViaBridgeTask'
extracts = [i for i in all_extracts if (i.target.id == datasource_id) and ('IncrementExtractViaBridgeTask' == i.task_type)]
 
incremental_extract_obj = extracts[0]
 
# Trigger the incremental extract associated with the datasource
update_xml = server.tasks.run(incremental_extract_obj)
job_id = xmltodict.parse(update_xml)['tsResponse']['job']['@id']
print(f"Refresh extract job {job_id} created")

Results
What are the results or error messages received?

D:\Python38>python.exe D:\Refresh-Scripts\TableauExtractIncRefTrigScript.py Tab_AggSCMDownload_V
Traceback (most recent call last):
  File "D:\Refresh-Scripts\TableauExtractIncRefTrigScript.py", line 35, in <module>
    extracts = [i for i in all_extracts if (i.target.id == datasource_id) and ('IncrementExtractViaBridgeTask' == i.task_type)]
  File "D:\Refresh-Scripts\TableauExtractIncRefTrigScript.py", line 35, in <listcomp>
    extracts = [i for i in all_extracts if (i.target.id == datasource_id) and ('IncrementExtractViaBridgeTask' == i.task_type)]
AttributeError: 'NoneType' object has no attribute 'id'

Hey @naresh251. I think you missed adding the backticks to make your code render as code in the issue. That said, I have a few thoughts on your issue:

Can you try changing:
extracts = [i for i in all_extracts if (i.target.id == datasource_id) and ('IncrementExtractViaBridgeTask' == i.task_type)]

to

extracts = [i for i in all_extracts if ('IncrementExtractViaBridgeTask' == i.task_type) and (i.target.id == datasource_id)]

Python implicitly does short-circuit evaluation, so if the first condition is False it never evaluates the second. In the code you provided, it is checking if the target.id == datasource_id before it checks if the task type is 'IncrementExtractViaBridgeTask'. By flipping the conditions around, it will check if the task type is correct before it tries to compare the target id, which may eliminate that NoneType error.

hey @jorwoods thanks for checking. Issue got fixed by condition i.target is not None.

extracts = [i for i in all_extracts if (i.target is not None and i.target.id == datasource_id) and ('IncrementExtractViaBridgeTask' == i.task_type)]

Closed as solved based on discussion above.