[GIS] Understanding updateParameters and updateMessages interaction in Python Toolbox

arcpypython-toolbox

I have been developing a Python toolbox which consists of 6 parameters. I have received immense amounts of help on this through StackExchange through the following posts:

How to Determine if a Layer is a Point

How to Change a Parameter Type from Optional to Required

I must say, you guys rock! I'm getting close to finishing up this toolbox and have yet again hit another wall.

For one of my parameters, I would like to throw a warning to the user if it is not a point shapefile. The main purpose of this tool is to label point shapefiles, so if they enter a polygon, that's going to potentially be a whole lot of labels showing on one map (at least for polygon shapefiles that I deal with). For some reason, the only way for the warning to appear correctly is for my updateParameters and updateMessages functions to consist of the following:

    def updateParameters(self, parameters):

    describe = arcpy.Describe(parameters[0].value)
    if describe.shapeType not in ('Point', 'Multipoint)':
        parameters[0].setWarningMessage('This is not a point feature class')
    else:
        parameters[0].clearMessage()    

    if parameters[2].value == True:
        parameters[3].enabled = True
        parameters[4].enabled = True
        parameters[5].enabled = True

    else:       
        parameters[3].enabled = False
        parameters[4].enabled = False
        parameters[5].enabled = False       

    return

def updateMessages(self, parameters):

    if parameters[0] != None:
        describe = arcpy.Describe(parameters[0].value)
        if describe.shapeType not in ('Point', 'Multipoint'):
            parameters[0].setWarningMessage('This is not a point shapefile. Labeling is not recommended.')
        else:
            parameters[0].clearMessage()

    return 

I can feed in a polygon shapefile and the warning appears and everything runs as it should. However, if I comment out the first 5 lines of the updateParameters method (the portion that checks if its a point and which also appears to be redundant), then my toolbox initially appears to have a bunch of errors with it once I open it:

enter image description here

enter image description here

My guess is that this has something to do with the order of validation that is performed for the tool. However, once I feed in a shapefile into the tool, all of the errors go away and the tool runs fine. So I have my tool working, just not in the way that I want it to since (a) I don't want to include a piece of code that I feel is redundant and (b) I shouldn't have error flags all over the place with the initial state of my tool.

Best Answer

Update: You can just use filters for this and not bother with tool validation code: See Defining parameters in a Python toolbox use a filter (Applying filters to parameters section). There is a filter type for Feature Classes, against which you can specify Point and Multipoint geometry types.

Update 2: If you'd like to customize the filter behavior to change its message and make it a warning instead of an error to enter a non-point feature class, you can use updateMessages to do this:

def updateMessages(self, parameters):
  if parameters[0].hasError and parameters[0].message == 'ERROR 000366: Invalid geometry type':
     parameters[0].clearMessage()
     parameters[0].setWarningMessage('This is not a point shapefile. Labeling is not recommended.')
  return

Original post:

Looks like you just need to consistently guard against the first parameter being empty, so that Describe is not called when it is.

For example:

def updateParameters(self, parameters):
  if parameters[0].value:
    describe = arcpy.Describe(parameters[0].value)
    if describe.shapeType not in ('Point', 'Multipoint)':
      parameters[0].setWarningMessage('This is not a point feature class')
    else:
      parameters[0].clearMessage()
    if parameters[2].value == True:
      parameters[3].enabled = True
      parameters[4].enabled = True
      parameters[5].enabled = True
    else:
      parameters[3].enabled = False
      parameters[4].enabled = False
      parameters[5].enabled = False
  return

def updateMessages(self, parameters):
  if parameters[0].value:
    describe = arcpy.Describe(parameters[0].value)
    if describe.shapeType not in ('Point', 'Multipoint'):
      parameters[0].setWarningMessage('This is not a point shapefile. Labeling is not recommended.')
    else:
      parameters[0].clearMessage()
  return