2

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 Apr 20 '15 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 Apr 22 '15 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 Apr 22 '15 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 May 1 '15 at 20:42
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.