Validation is everything that happens before a tool's OK button is pushed. When creating your own custom tools, validation allows you to customize how parameters respond and interact to values and each other. Validation is performed with a block of Python code that is used to control tool behavior.
To learn more about validation, see Understanding validation in script tools.
In a Python toolbox, every tool parameter has an associated Parameter object with properties and methods that are useful in tool validation. In a Python toolbox, parameters are defined in the getParameterInfo method of the tool class. The behavior of those parameters, and how they interact with each other and inputs, is validated according to the updateParameters method of the tool class.
Accessing the tool parameters
Parameter objects form the foundation of how parameters are defined and interact in a Python toolbox. The standard practice is to create the list of parameters in the tool class' getParameterInfo method, as shown in the code below.
def getParameterInfo(self):
#Define parameter definitions
# First parameter
param0 = arcpy.Parameter(
displayName="Input Features",
name="in_features",
datatype="GPFeatureLayer",
parameterType="Required",
direction="Input")
return [param0]
For more about defining parameters in a Python toolbox, see Defining parameters in a Python toolbox.
Parameter object
Methods
Method name | Usage description |
---|---|
setErrorMessage(message:string) | Marks the parameter as having an error (a red X) with the supplied message. Tools do not execute if any of the parameters have an error. |
setWarningMessage(message:string) | Marks the parameter as having a warning (a yellow triangle) with the supplied message. Unlike errors, tools do execute with warning messages. |
setIDMessage(messageType: string, messageID: string, {AddArgument1}, {AddArgument2}) | Allows you to set a system message. The arguments are the same as the AddIDMessage function. |
clearMessage() | Clears out any message text and sets the status to informative (no error or warning). |
hasError() | Returns true if the parameter contains an error. |
hasWarning() | Returns true if the parameter contains a warning. |
isInputValueDerived() | Returns true if the tool is being validated inside a Model and the input value is the output of another tool in the model. |
Properties
Property name | Read/Write | Value(s) | Description |
---|---|---|---|
name | Read-only | String | The parameter name. |
direction | Read-only | String: "Input", "Output" | Input/Output direction of the parameter. |
datatype | Read-only | String | For a list of parameter data types, see Defining parameter data types in a Python toolbox. |
parameterType | Read-only | String: "Required", "Optional", "Derived" | The parameter type. |
parameterDependencies | Read/write | Python list | A list of indexes of each dependent parameter. |
value | Read/write | Value object | The value of the parameter. |
defaultEnvironmentName | Read-only | String | The default environment setting. |
enabled | Read/write | Boolean | False if the parameter is unavailable. |
altered | Read-only | Boolean | True if the user has modified the value. |
hasBeenValidated | Read-only | Boolean | True if the internal validation routine has checked the parameter. |
category | Read/write | String | The category of the parameter. |
schema | Read-only | Schema object | The schema of the output dataset. |
filter | Read-only | Filter object | The filter to apply to values in the parameter. |
symbology | Read/write | String | The path to a layer file (.lyrx) used for drawing the output. |
message | Read-only | String | The message to be displayed to the user. See setErrorMessage and setWarningMessage above. |
Although many Parameter object properties are read/write, most of these properties can only be set or modified when you initially create or modify the object. Several properties, including name, displayName, datatype, direction, and parameterType, establish the characteristics of a tool and cannot be modified during validation methods (such as updateMessages and updateParameters).
parameterDependencies
You typically set parameter dependencies for use by the Schema object. There are two cases where the dependencies may already be set in the getParameterInfo method of the tool.
- For an output dataset parameter whose type is Derived, the dependency is the index of the parameter from which to derive the output.
- For certain input data types, the dependency is the index of the parameter containing the information used by the control, as shown in the table below.
Input data type | Dependent data type | Description |
---|---|---|
Field or SQL Expression | Table | The table containing the fields. |
INFO Item or INFO Expression | INFO Table | The INFO table containing the items. |
Coverage Feature Class | Coverage | The coverage containing features. |
Area Units or Linear Units | GeoDataset | A geographic dataset used to determine the default units. |
Coordinate System | Workspace | A workspace used to determine the default coordinate system. |
Network Analyst Hierarchy Settings | Network Dataset | The network dataset containing hierarchy information. |
Geostatistical Value Table | Geostatistical Layer | The analysis layer containing tables. |
Network Travel Mode | Network Data Source, Network Dataset, Network Dataset Layer | List of travel modes. |
Dependencies are typically set in the getParameterInfo method:
def getParameterInfo(self):
#Define parameter definitions
# First parameter
param0 = arcpy.Parameter(
displayName="Input Features",
name="in_features",
datatype="GPFeatureLayer",
parameterType="Required",
direction="Input")
# Second parameter
param1 = arcpy.Parameter(
displayName="Sinuosity Field",
name="sinuosity_field",
datatype="Field",
parameterType="Optional",
direction="Input")
param1.value = "sinuosity"
# Third parameter
param2 = arcpy.Parameter(
displayName="Output Features",
name="out_features",
datatype="GPFeatureLayer",
parameterType="Derived",
direction="Output")
param2.parameterDependencies = [param0.name]
param2.schema.clone = True
params = [param0, param1, param2]
return params
value
This is the value of the parameter that the user entered or you set programmatically. You can set the value in the getParameterInfo method, in which case it serves as the initial default value for the parameter. You can also set the value in updateParameters in response to user input as shown below.
def updateParameters(self, parameters):
# Set the default distance threshold to 1/100 of the larger of the width
# or height of the extent of the input features. Do not set if there is no
# input dataset yet, or the user has set a specific distance (Altered is true).
#
if parameters[0].valueAsText:
if not parameters[6].altered:
extent = arcpy.Describe(parameters[0]).extent
if extent.width > extent.height:
parameters[6].value = extent.width / 100
else:
parameters[6].value = extent.height / 100
return
A parameter's value property returns an object, unless the parameter isn't populated, in which case the value returns None. To safeguard against a parameter not being populated, use an if check prior to using its value.
The code snippet below tests whether the value is equal to the string "Get Spatial Weights From File". This test works because the parameter data type is a string.
# If the option to use a weights file is selected, enable the
# parameter for specifying the file, otherwise disable it
if parameters[3].value: # check that parameter has a value
if parameters[3].value == "Get Spatial Weights From File":
parameters[8].enabled = True
else:
parameters[8].enabled = False
As a Value object does not support string manipulation, use the Value object's value property whenever a string is to be manipulated or parsed. The code sample uses the os.path.dirname method to return the directory from a dataset.
if parameters[0].value:
workspace = os.path.dirname(parameters[0].value.value)
Note:
With the exception of Describe, don't use methods that take a catalog path, such as ListFields, in validation. The dataset may not exist when your tool is validated in ModelBuilder, and the method may fail or give unexpected results.
In the specific case of ListFields, the Describe object's fields property will provide the equivalent information.
Note:
Don't set a parameter value in updateMessages() since the value will not be validated by the internal validation routine.
altered
altered is true if the value of a parameter is changed—by entering an output path, for example. Once a parameter has been altered, it remains altered until the user empties (blanks out) the value, in which case it returns to being unaltered. Programmatically changing a value with validation code will change the altered state. That is, if you set a value for a parameter, the altered state of the parameter will be updated.
altered is used to determine whether you can change the value of a parameter. As an example, suppose a tool has a feature class parameter and a keyword parameter. If the feature class contains points or polygons, the keywords are RED, GREEN, and BLUE, and if lines, ORANGE, YELLOW, PURPLE, and WHITE.
Suppose the user enters a point feature class. If the keyword parameter is unaltered, you set the value to RED, since it's the default value.
If a line feature class is entered, you set the default value to ORANGE as long as the keyword parameter is unaltered.
However, if the keyword parameter has been altered by the user (that is, the keyword is set to GREEN), you should not reset the keyword—the user has made their choice (GREEN) and you don't know their intention—they may change the feature class so that GREEN is valid or they may change the keyword (to PURPLE, for example). Since GREEN isn't a member of the set of keywords you created for lines, internal validate flags the parameter an error. The user has two options at this point: change the input feature class or change the keyword.
if not parameters[2].altered:
parameters[2].value = "POINT"
hasBeenValidated
hasBeenValidated is false if a parameter's value has been modified by the user since the last time updateParameters and internal validate were called. Once internal validate has been called, geoprocessing automatically sets hasBeenValidated to true for every parameter.
hasBeenValidated is used to determine whether the user has changed a value since the last call to updateParameters. You can use this information in deciding whether to do your own checking of the parameter.
def updateParameters(self, parameters):
# Set the default distance threshold to 1/100 of the larger of the width
# or height of the extent of the input features. Do not set if there is no
# input dataset yet, or the user has set a specific distance.
#
if parameters[0].valueAsText:
if parameters[6].hasBeenValidated:
extent = arcpy.Describe(parameters[0]).extent
if extent.width > extent.height:
parameters[6].value = extent.width / 100
else:
parameters[6].value = extent.height / 100
return