I'm using ArcMap 10.2.1 and Python 2.7.5.
I would like my updateParameters to enable and disable fields based on if a feature is a point or a polygon. If the point is selected then I need the measure. If the line is selected then I need the begin measure and the end measure. I am getting a similar error as coolDude when I open my tool in ArcMap.
There is an excellent discussion that almost answers my question posted here: Understanding updateParameters and updateMessages interaction in Python Toolbox?
The questioner (coolDude) had two related questions that also got very close to answering my question. However, the tool I am writing is comparing either two point features, a point and a line feature, or two line features.
The error suggest that my describe method is incorrect. Python developers, am I using the syntax incorrectly? I checked out my code in the console and I got the desired effect.
Here is my getParameterInfo method:
input_base_feature = arcpy.Parameter(displayName="Base Feature",
name="input_base_feature",
datatype="GPFeatureLayer",
parameterType="Required",
direction="Input")
params.append(input_base_feature)
input_base_id_field = arcpy.Parameter(displayName="Base Feature ID Field",
name="input_base_id_field",
datatype="Field",
parameterType="Required",
direction="Input")
input_base_id_field.parameterDependencies = [input_base_feature.name]
params.append(input_base_id_field)
input_base_measure_field = arcpy.Parameter(displayName="Base Feature Measure Field",
name="input_base_measure_field",
datatype="Field",
parameterType="Required",
direction="Input")
input_base_measure_field.parameterDependencies = [input_base_feature.name]
input_base_measure_field.filter.list = ['Float', 'Double']
params.append(input_base_measure_field)
input_base_begin_measure_field = arcpy.Parameter(displayName="Base Feature Begin Measure Field",
name="input_base_begin_measure_field",
datatype="Field",
parameterType="Required",
direction="Input")
input_base_begin_measure_field.parameterDependencies = [input_base_feature.name]
input_base_begin_measure_field.filter.list = ['Float', 'Double']
params.append(input_base_begin_measure_field)
input_base_end_measure_field = arcpy.Parameter(displayName="Base Feature End Measure Field",
name="input_base_end_measure_field",
datatype="Field",
parameterType="Required",
direction="Input")
input_base_end_measure_field.parameterDependencies = [input_base_feature.name]
input_base_end_measure_field.filter.list = ['Float', 'Double']
params.append(input_base_end_measure_field)
Further down in the code, I use the updateParameter method:
desc_base = arcpy.Describe(parameters[4].value)
if desc_base.shapeType == 'Point':
parameters[6].enabled = True,
parameters[6].parameterType = 'Required',
parameters[7].enabled = False,
parameters[7].parameterType = 'Optional',
parameters[8].enabled = False,
parameters[8].parameterType = 'Optional'
elif desc_base.shapeType == 'Polyline':
parameters[6].enabled = False,
parameters[6].parameterType = 'Optional',
parameters[7].enabled = True,
parameters[7].parameterType = 'Required',
parameters[8].enabled = True,
parameters[8].parameterType = 'Required'
else:
arcpy.AddMessage("Incorrect type for input_base_feature. Point or polyline features only.")
My guess is
desc_base = arcpy.Describe(parameters[4].value)
Is incorrect. The other error I get has to do with the line:
parameters[6].parameterType = 'Required',
I tried it without comments and I tried replacing the .value with .valueAsText and I got the same errors. Speaking of, here are the errors:
When I select a Centerline:
Traceback (most recent call last):
File "C:\Workspace\qcerator\src\eaglepyqc\toolboxes\check_for_overlaps.py",
line 147, in updateParameters desc_base = arcpy.Describe(parameters[4].value)
File "c:\program files (x86)\arcgis\desktop10.2\arcpy\arcpy\__init__.py",
line 1234, in Describe return gp.describe(value)
File "c:\program files (x86)\arcgis\desktop10.2\arcpy\arcpy\geoprocessing\_base.py",
line 374, in describe self._gp.Describe(*gp_fixargs(args, True)))
AttributeError: Object: Error in parsing arguments for Describe
When I select a Base Feature (line):
Traceback (most recent call last):
File "C:\Workspace\qcerator\src\eaglepyqc\toolboxes\check_for_overlaps.py",
line 153, in updateParameters parameters[8].enabled = False
TypeError: list indices must be integers, not tuple
When I select a Base feature (point):
Traceback (most recent call last):
File "C:\Workspace\qcerator\src\eaglepyqc\toolboxes\check_for_overlaps.py",
line 150, in updateParameters parameters[6].enabled = False
TypeError: list indices must be integers, not tuple
And finally, a screenshot of the toolbox so you can see the whole thing. I left out lines of code that sets up the Centerline and cross feature inputs for the sake of brevity.
Python Toolbox Tool
The reason I put in the lines with "required" or "optional" is I still get the green dots next to the grayed-out fields. Furthermore, the fields only get grayed-out if a polyline is selected. The if statement doesn't work if a point feature class is selected from the drop-down menu.
-
I realize I didn't address the errors in my question. I'm not sure how else to 'parse the arguments in Describe' other than put a .valueAsText behind parameters.keepaustinbeard– keepaustinbeard2015年04月20日 23:05:56 +00:00Commented Apr 20, 2015 at 23:05
-
A couple small things. 1) You can't change the parameterType dynamically. If it's required, it's required. You can however, make an parameter optional, and force an error message on the parameter to make sure it is corrected before the tool will be run. 2) arcpy message functions AddMessage, etc. are not for validation, there you need to use parameter methods like setErrorMessage, setWarningMessage.DWynne– DWynne2015年04月22日 19:11:16 +00:00Commented Apr 22, 2015 at 19:11
-
It's really hard to see what you're doing, there is only partial code so it is hard to recreate what you're seeing. But there is still a lot of noise in the code you have provided. Really, this question would benefit a lot if you simplified your tool down to the basic issue and then posted all relevant parts (getParameterInfo, updateParameters, and updateMessages).DWynne– DWynne2015年04月22日 19:18:02 +00:00Commented Apr 22, 2015 at 19:18
-
I will answer your request to clean up and simplify my example soon. I was diverted from this project and should return to it soon. Thank you for your guidance in the meantime!keepaustinbeard– keepaustinbeard2015年05月01日 20:42:04 +00:00Commented May 1, 2015 at 20:42
1 Answer 1
I was able to take the answer @DWynne gave me for Python Toolbox Error Messages and apply it to this problem. The issue of enabling/disabling ID, Begin and End Measure fields using updateParameters was a red herring. Instead, preventing the user from even selecting bad data (i.e. a polygon feature) could be handled using the updateMessages method.
def updateMessages(self, parameters):
"""
Definition needed for Python Toolbox.
"""
centerline_value = parameters[0].valueAsText
if centerline_value:
desc = arcpy.Describe(centerline_value)
if desc.shapeType != 'Polyline':
parameters[0].setErrorMessage('Only polylines are accepted')
# If the user selects a Base feature class instead of a table, this ensures only points and polylines are present.
base_compare = parameters[4].valueAsText
if base_compare:
desc = arcpy.Describe(base_compare)
if desc.datasettype in ['FeatureLayer', 'FeatureClass'] and desc.shapeType not in ['Point','Polyline']:
parameters[4].setErrorMessage('Only points, polylines and tables are accepted')
# If the user selects a Cross feature class instead of a table, this ensures only points and polylines are present.
cross_compare = parameters[9].valueAsText
if cross_compare:
desc = arcpy.Describe(cross_compare)
if desc.datasettype in ['FeatureLayer', 'FeatureClass'] and desc.shapeType not in ['Point','Polyline']:
parameters[9].setErrorMessage('Only points, polylines and tables are accepted')
return
Now I am able to display a message preventing the tool from running. I also added the additional functionality allowing a table (with route id, begin measure, and end measure fields) as a parameter for base and cross features.
Also, the errors I was receiving "AttributeError: Object: Error in parsing arguments for Describe" have to do with not checking the parameters as either:
desc = parameters[0].valueAsText
desc = parameters[0].value
desc = parameters[0].altered
desc = parameters[0].hasBeenValidated
If the parameter is checked, then I can go on to make .shapeType and .dataType boolean statements. There are more on ESRI's documentation but those are ones I've used before.
Side note: It is a matter of Pep-8 rule breaking preference if you want your lines to extend past 80 OR have an extra line of code. I prefer using the boolean AND instead of a nested if.