Python Toolbox – Applying Error Messages to Prevent Tool from Running with Bad Parameters

arcpypythonpython-toolbox

This is a continuation of my question here: Point and Polyline I tried making this question easier to follow.

My tool accepts two main parameters – a continuous centerline and a table (or a feature class with an attribute table) with polyline features including route ID and measures. If the user chooses a table, I cannot check to see if the table has polylines. I'm going to trust that they are loading the correct data. However, I CAN check to see if the feature class is a polyline or not.

I have tried to do this in updateParameter with a filter. I think I have the wrong idea of how it works though:

def updateParameters(self, parameters):
    """
    I am not convinced that this even needs to be here. I've considered using a 
    checkbox instead.
    """
    if parameters[2].altered and parameters[2].hasBeenValidated:
        if parameters[2].dataType == 'Feature':
            parameters[2].filter.list = 'Polyline'
    return

In my unit testing, I've been able to select a point feature and it fails (good). When I run this in ArcMap, it accepts points (bad) and runs without errors. I want to be able to have an error message appear in the toolbox window and prevent the user from clicking ok.

My updateMessages looks like this:

def updateMessages(self, parameters):
    """
    For instances where a feature class is inputted for param2 and it is a point feature class
    The messaging should prevent the tool from running. 
    """
    # Error in parsing arguments for Describe
    if parameters[0].altered and parameters[0].hasBeenValidated:
        desc = arcpy.Describe(parameters[0].valueAsText)
        if desc.shapeType not in 'Polyline':
            arcpy.AddError("{0} has the wrong data type.")
            raise arcpy.ExecuteError
    if parameters[2].altered and parameters[2].hasBeenValidated:
        desc = arcpy.Describe(parameters[2].valueAsText)
        if desc.datatype == 'Feature' and desc.shapeType not in 'Polyline':
            arcpy.AddError("{2} has the wrong data type.")
            raise arcpy.ExecuteError
    return

I took half of this code straight from ESRI's documentation Writing Messages in Scripts

I might as well show you the getParameterInfo so you have the whole picture:

def getParameterInfo(self):
    """
    Define parameter definitions
    """
    params = list()
    param0 = arcpy.Parameter(displayName="Centerline Layer",
                                       name="param0",
                                       datatype="GPFeatureLayer",
                                       parameterType="Required",
                                       direction="Input")
    param0.filter.list = ['Polyline']
    params.append(param0)
    param1 = arcpy.Parameter(displayName="Centerline ID",
                                                      name="param1",
                                                      datatype="Field",
                                                      parameterType="Required",
                                                      direction="Input")
    param1.parameterDependencies = [param0.name]
    params.append(param1)

    param2 = arcpy.Parameter(displayName="Polyline Compare",
                                           name="param2",
                                           datatype="GPTableView", # table or attribute table
                                           parameterType="Required",
                                           direction="Input")
    params.append(param2)

    param3 = arcpy.Parameter(displayName="Polyline Compare ID",
                                                          name="param3",
                                                          datatype="Field",
                                                          parameterType="Required",
                                                          direction="Input")
    param3.parameterDependencies = [param2.name]
    params.append(param3)

    return params

As you can see, the Centerline (param0) was easier to do. I just included it in the code so that it would still create an error if it is called. I could put a error statement in the execute method like this:

desc = arcpy.Describe(param0.value)
if desc.shapeType != 'Polyline':
    raise arcpy.ExecuteError("Incorrect Data Type: Select a polyline.")
desc = arcpy.Describe(param2.value)
if desc.dataType == 'Feature Class' and desc.shapeType != 'Polyline':
    raise arcpy.ExecuteError("Incorrect Data Type: Select a polyline.")

Right now the error messages just do not appear. I have looked through every relevant post tagged python toolbox. This one needs an answer too! Anyone in the Stack able to help with this one?

Best Answer

One thing to remember, all actions that involve the parameter should be off the parameter object; so use parameters[n].setErrorMessage(msg) instead of arcpy.AddError(msg). AddError is used to add error messages into the tool execution messages, setErrorMessage is to add an error to the parameter that will block the tool from executing. So you also don't need to raise any exceptions.

A couple other issues, and something like the below should do what you've described.

def updateMessages(self, parameters):
    """Modify the messages created by internal validation for each tool
    parameter.  This method is called after internal validation."""

    polyline_compare = parameters[2].valueAsText
    if polyline_compare:
        desc = arcpy.Describe(polyline_compare)
        if desc.datasettype in ['FeatureClass', 'FeatureLayer']:
            if desc.shapetype != 'Polyline':
                parameters[2].setErrorMessage('Only polylines and tables are accepted')

    return
Related Question