Hello everyone,
I have a .pyt toolbox which runs correctly in the ArcGIS Pro 3.5 environment but fails when the tool is hosted on ArcGIS Enterprise 11.3. The tool uses arcpy and the arcgis api for python to retrieve a hosted webmap, included layers and hosted layout, all of which are available to all users within the organization.
The tool uses gis = GIS("home") when run inside of ArcGIS Pro. However, when run in a hosted environment, I receive the the following errors:
{"error":{"code":499,"message":"Token Required","details":[]}}
RuntimeError: Failed to create layer from service at https://portal_url.com/gisweb/rest/services/Hosted/feature_layer/FeatureServer/1.\n"
I assume this is related to user authentication/credentials, but I cannot figure out how to properly pass credentials when hosting. Should I be using keyring to do so? If so, what is the proper way of setting it up? Does the .pyt toolbox need to be run from the server machine in ArcGIS Pro, or can it be run on my local computer?
Below is the execute() portion of the .pyt toolbox. Any insights you may have into how to properly pass API credentials when hosting a .pyt toolbox on enterprise would be greatly appreciated.
"""
def execute(self, parameters, messages):
parcel_apn = parameters[0].valueAsText
output_pdf = parameters[1].valueAsText
web_map_id = "a4373271ba30412939sh23201h8h282"
layout_id = "btheh82hek930jj3932429je9302030"
attributes = ["SHAPE@", "apn", "property_name"]
parcels = [parcel_apn]
gis = GIS("home")
webmap_item = gis.content.get(web_map_id)
arcpy.AddMessage(webmap_item)
web_map_json = webmap_item.get_data()
arcpy.AddMessage("")
arcpy.AddMessage("")
pretty_json = json.dumps(web_map_json, indent=4)
arcpy.AddMessage(pretty_json)
web_map_json.update(json.loads('''{"mapOptions" : { "extent" : { "xmin":6787761, "ymin":2073010, "xmax":6787762, "ymax":2073011, "spatialReference" : { "wkid" : 6418 } }}}'''))
pagx_path = os.path.join(arcpy.env.scratchFolder, "Report.pagx")
layout_item = gis.content.get(layout_id)
layout_item.download(pagx_path)
result = arcpy.mp.ConvertWebMapToArcGISProject(json.dumps(web_map_json), template_pagx=fr"{pagx_path}\Property_Report_1.pagx")
aprx = result.ArcGISProject
map = aprx.listMaps("Web Map")[0]
layer = map.listLayers("Properties")[0]
layout = aprx.listLayouts("Property Report")[0]
map_frame = layout.listElements("MAPFRAME_ELEMENT", "Property Map Frame")[0]
arcpy.AddMessage(map_frame.name)
property_name_text = layout.listElements("TEXT_ELEMENT", "Property Name")[0]
apn_text = layout.listElements("TEXT_ELEMENT", "APN")[0]
for parcel in parcels:
arcpy.management.SelectLayerByAttribute(layer, "NEW_SELECTION", where_clause=f"apn = '{parcel}'")
with arcpy.da.SearchCursor(layer, attributes, where_clause=f"apn = '{parcel}'") as cursor:
for row in cursor:
extent = row[0].extent
apn = row[1]
property_name = row[2]
# Get Parcel Layer Extent and Pad it by 20-Percent in the Active Map Frame
pad = 0.20
width_pad = extent.width * pad
height_pad = extent.height * pad
new_xmin = (extent.XMin - width_pad)
new_xmax = (extent.XMax + width_pad)
new_ymin = (extent.YMin - height_pad)
new_ymax = (extent.YMax + height_pad)
padded_extent = arcpy.Extent(new_xmin, new_ymin, new_xmax, new_ymax, spatial_reference=extent.spatialReference)
map_frame.camera.setExtent(padded_extent)
property_name_text.text = f"{property_name}"
apn_text.text = f"APN: {apn}"
layer.definitionQuery = f"APN = '{parcel}'"
layout.exportToPDF(output_pdf)
return
"""
When you run this in ArcGIS Pro Geoprocessing pane the toolbox script is pulling your credentials from your ArcGIS Pro login by using: gis = GIS("home") . I'm not familiar with the login functionality on the Enterprise side when passing "home". You may need to enter user credentials to run in enterprise: https://developers.arcgis.com/python/latest/guide/working-with-different-authentication-schemes/#:~:...
Do you happen to have MFA setup in your Enterprise?
Hi Ben, we do not have MFA setup in our Enterprise.
Ok
@BlakeFulkerson does the code at the link below work for you after customizing to make your portal url, username, and password?