Validator error with lists and set values

1174
2
Jump to solution
11-21-2019 06:29 AM
AlanDodson
New Contributor III

I have some simple ArcPy script tool validator code that is giving me grief. I am using desktop at 10.3.1. I'm open to whatever help can be offered to get this to work as intended.

I have two parameters for my script tool. The first is the type of product to be created, the second is the scale of the product. Digital Map / No scale required are the default values defined in the Tool Validator code.

If it is a paper product, the user selects the appropriate scale from the drop-down list. The problem I can't solve is that if the user changes the value in parameter 0 to paper map, the list of scales becomes available but the value is still the default ("No scale required") so an error is thrown because that option is not in the scale list. The error clears when I select the scale from the list, but I want only those choices available and obviously don't want the error to appear at all.

Likewise if I then change parameter 0 back to Digital Map the "No scale required" value appears but the error message is thrown again because that value is not in the scale list, which is somehow still appearing. There is no way to clear the error at this point.

I'd really appreciate help with how to get these different combinations to appear and change as intended without any errors. If they pick Paper, only the scales appear. If they switch back to Digital, only the "No scale required" value appears. And so on. I can't guarantee the user's behaviour so I'd like for it to be bulletproof.

import arcpy
class ToolValidator(object):

  def __init__(self):
    self.params = arcpy.GetParameterInfo()

  def initializeParameters(self):
    # Define the list of product types the user can choose from
    self.params[0].filter.list = ["Digital Map", "Paper Map"]
    self.params[0].value = "Digital Map"  
    return

  def updateParameters(self):
    if self.params[0].value == "Digital Map":
        self.params[1].value = "No scale required"                
    if self.params[0].value == "Paper Map":
        self.params[1].filter.list = ["1:10,000", "1:25,000"]
    return

  def updateMessages(self):
    return‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
1 Solution

Accepted Solutions
RandyBurton
MVP Alum

Try the following for the tool validator:

import arcpy
class ToolValidator(object):

  def __init__(self):
    self.params = arcpy.GetParameterInfo()

  def initializeParameters(self):
    return

  def updateParameters(self):

    if self.params[0].value == None:
        self.params[0].value = "Digital Map"
    if self.params[0].valueAsText == "Digital Map":
        self.params[1].filter.list = ["No scale required"]
    else:
        self.params[1].filter.list = ["1:10,000", "1:25,000"]
    if self.params[1].value not in self.params[1].filter.list:
        self.params[1].value = self.params[1].filter.list[0]

    return

  def updateMessages(self):
    return‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

For testing, I used Desktop 10.5.  I set the script tool parameters as type string, and populated the map type filter with the digital or paper map options.  I did not set the filter list for the map scale.

I find it a little easier to use a Python toolbox.  You don't have to go to the properties dialog box to edit a tool validator; everything fits into one script.  My test version:

import arcpy

class Toolbox(object):
    def __init__(self):
        self.label = "Toolbox"
        self.alias = ""
        self.tools = [Tool]

class Tool(object):
    def __init__(self):
        self.label = "Tool"
        self.description = ""
        self.canRunInBackground = False

    def getParameterInfo(self):

        MapType = arcpy.Parameter(
            displayName="Map Type",
            name="MapType",
            datatype="String",
            parameterType="Required",
            direction="Input")
        MapType.filter.list = ["Digital Map", "Paper Map"]
        MapType.value = "Digital Map"

        MapScale = arcpy.Parameter(
            displayName="Map Scale",
            name="MapScale",
            datatype="String",
            parameterType="Required",
            direction="Input")
        MapScale.filter.list = ["No scale required"]
        MapScale.value = "No scale required"

        params = [MapType, MapScale]
        return params

    def isLicensed(self):
        return True

    def updateParameters(self, parameters):
        """Modify the values and properties of parameters before internal
        validation is performed.  This method is called whenever a parameter
        has been changed."""

        if parameters[0].valueAsText == "Digital Map":
            parameters[1].filter.list = ["No scale required"]
        else:
            parameters[1].filter.list = ["1:10,000", "1:25,000"]
        if parameters[1].value not in parameters[1].filter.list:
            parameters[1].value = parameters[1].filter.list[0]
        
        return

    def updateMessages(self, parameters):
        return

    def execute(self, parameters, messages):
        """The source code of the tool."""
        return‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Hope this helps.

View solution in original post

2 Replies
RandyBurton
MVP Alum

Try the following for the tool validator:

import arcpy
class ToolValidator(object):

  def __init__(self):
    self.params = arcpy.GetParameterInfo()

  def initializeParameters(self):
    return

  def updateParameters(self):

    if self.params[0].value == None:
        self.params[0].value = "Digital Map"
    if self.params[0].valueAsText == "Digital Map":
        self.params[1].filter.list = ["No scale required"]
    else:
        self.params[1].filter.list = ["1:10,000", "1:25,000"]
    if self.params[1].value not in self.params[1].filter.list:
        self.params[1].value = self.params[1].filter.list[0]

    return

  def updateMessages(self):
    return‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

For testing, I used Desktop 10.5.  I set the script tool parameters as type string, and populated the map type filter with the digital or paper map options.  I did not set the filter list for the map scale.

I find it a little easier to use a Python toolbox.  You don't have to go to the properties dialog box to edit a tool validator; everything fits into one script.  My test version:

import arcpy

class Toolbox(object):
    def __init__(self):
        self.label = "Toolbox"
        self.alias = ""
        self.tools = [Tool]

class Tool(object):
    def __init__(self):
        self.label = "Tool"
        self.description = ""
        self.canRunInBackground = False

    def getParameterInfo(self):

        MapType = arcpy.Parameter(
            displayName="Map Type",
            name="MapType",
            datatype="String",
            parameterType="Required",
            direction="Input")
        MapType.filter.list = ["Digital Map", "Paper Map"]
        MapType.value = "Digital Map"

        MapScale = arcpy.Parameter(
            displayName="Map Scale",
            name="MapScale",
            datatype="String",
            parameterType="Required",
            direction="Input")
        MapScale.filter.list = ["No scale required"]
        MapScale.value = "No scale required"

        params = [MapType, MapScale]
        return params

    def isLicensed(self):
        return True

    def updateParameters(self, parameters):
        """Modify the values and properties of parameters before internal
        validation is performed.  This method is called whenever a parameter
        has been changed."""

        if parameters[0].valueAsText == "Digital Map":
            parameters[1].filter.list = ["No scale required"]
        else:
            parameters[1].filter.list = ["1:10,000", "1:25,000"]
        if parameters[1].value not in parameters[1].filter.list:
            parameters[1].value = parameters[1].filter.list[0]
        
        return

    def updateMessages(self, parameters):
        return

    def execute(self, parameters, messages):
        """The source code of the tool."""
        return‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Hope this helps.

AlanDodson
New Contributor III

Based on Randy Burton‌ 's reply, I used the following code in the validator which does exactly what I want.  Thanks Randy!

import arcpy
class ToolValidator(object):

  def __init__(self):
    self.params = arcpy.GetParameterInfo()

  def initializeParameters(self):
    self.params[0].filter.list = ["Digital Map", "Paper Map"]
    self.params[0].value = "Digital Map"     
    return

  def updateParameters(self):
    if self.params[0].value == None:
      self.params[0].value = "Digital Map"
    if self.params[0].valueAsText == "Digital Map":
      self.params[1].filter.list = ["Not applicable"]
      self.params[1].value = "Not applicable"
      self.params[1].enabled = False    
    else:
      self.params[1].filter.list = ["1:10,000", "1:25,000"]
    if self.params[1].value not in self.params[1].filter.list:
      self.params[1].value = self.params[1].filter.list[0]
      self.params[1].enabled = True
    return

  def updateMessages(self):
    return‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos