After returning to work after my summer holidays, I was told that a Python script which we use very frequently had stopped working. The relevant part of the script uploads objects to ArcGIS Online of various types, including File Geodatabases, using Folder.add().
As mentioned in the documentation this function is supposed to return a concurrent.futures.Future object and nothing else. In the past this was true. However what has started to happen is that if the object added is a File Geodatabase it now returns some kind of Job object instead, of a type which I haven't seen documented. (type() names it as arcgis.gis._impl._content_manager.folder.core.Job.) Whether this happens to other types I don't know, I haven't investigated this beyond what our script does.
Crucially, this Job object lacks the done() method which breaks both my script and the sample code on the linked documentation page, although result() still works on it. I was able to fix my script after I discovered that the Job object contained a property called futures. But now I need to have code to detect the type returned, since it varies depending on the type of object added.
I haven't found this change documented anywhere, so I'm not sure what's going on, if this is an intentional change that was not documented or a bug. But whatever it is, it broke scripts that we rely on and it was not easy to fix due to the lack of documentation.
Hi @IsakL You're right, the documentation is not accurate. This has been addressed and will be available in the next release. The server returning a job and the Python API has begun taking advantage of that. The `folder.core.Job` object that is now being returned has the `result` method which will return the added `Item`.
item_props = ItemProperties(
title="new_shapefile_item",
item_type=ItemTypeEnum.SHAPEFILE.value,
tags=["tag1"],
snippet="Demo item added from Python API",
)
add_job = folder.add(
item_properties=item_props, file=r"E:\data\some_lines.zip"
)
print(type(add_job))
print(add_job.result())
# >>> <class 'arcgis.gis._impl._content_manager.folder.core.Job'>
# >>> <Item title:"new_shapefile_item" type:Shapefile owner:my_username>
Thank you for the information. Is there an equivalent to done() for the Job class? Preferably something that works the same for either type so we don't have to detect which type is being returned. This is what broke my script, right now I have it checking which type and then I do list(job.futures)[0].done(), not sure if that's the intended way though.
Also, does the Job class have a documentation page? I wasn't able to find one, not for that particular Job anyway.
@IsakL The documentation page will be updated with samples. The `ContentManger.folder.core.Job` class will have a result method.
# Usage Example: Getting item resulting from a job
from arcgis.gis import GIS, ItemTypeEnum, ItemProperties
gis = GIS(profile="your_online_profile")
csv_file_path = "/path/to/your/data.csv"
new_data_item_job = gis_folder.add(
item_properties=ItemProperties(
title="new_source_csv_item",
item_type=ItemTypeEnum.CSV,
snippet="A new csv item.",
description="CSV data item added through a folder add.",
tags=["csv_item", "gis_data"]
),
file=csv_file_path
)
if not new_data_item_job.done():
print("... job processing...")
else:
csv_item = new_data_item_job.result()
csv_item
<Item title:"new_source_csv_item" type:CSV owner:online_data_owner>
Thank you for the response. I'll wait for the documentation to be updated if nothing else but my question was about .done() not .result().
From your provided sample (which seems to be the same one from the documentation that I based my code on):if not new_data_item_job.done():
if not new_data_item_job.done():
This line is what caused my issue. This throws an exception when the returned object is a `ContentManger.folder.core.Job` rather than a Future. There doesn't seem to be a done() method in the Job class. Hopefully the updated documentation addresses this.