Show Navigation | Hide Navigation
You are here:
Geoprocessing > Automating your work with scripts > Creating script tools

Programming a ToolValidator class

Release 9.3
Last modified June 3, 2010
E-mail This Topic Printable Version Give Us Feedback

Print all topics in : "Creating script tools"


Related Topics

Note: This topic was updated for 9.3.1.

For an overview of the ToolValidator class and use of parameter methods, see Customizing script tool behavior.


Parameter object


Accessing the tool parameters


Every tool parameter has an associated parameter object with properties and methods that are useful in tool validation. Parameters are contained in a Python list. The standard practice is to create the list of parameters in the ToolValidator class __init__ method, as shown in the code below.

def __init__(self):
  import arcgisscripting as ARC
  self.GP = ARC.create(9.3)
  self.params = self.GP.getParameterInfo()


You can also access parameters in your script (as opposed to the ToolValidator class) as follows:

  import arcgisscripting
  gp = arcgisscripting.create()
  params = gp.getParameterInfo()


The only reason to access the parameter list within a script is to set the symbology property.
Learn more about setting symbology in scripts

Order of parameters


A tool's parameters and their order are defined in the Parameters tab of the tool's properties, as illustrated below.

Parameters and their order

NOTE: The list of parameters is 0-based, so the first parameter is at position zero in the list. So, to access the third parameter



p3 = self.params[2]



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 method.
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 property

String Parameter name as defined on the Parameters tab of the tool's properties.
Direction
Read only property

String: "nput, Output Input/Output direction of the parameter as defined on the Parameters tab of the tool's properties.
Datatype
Read only property

String Data type as defined on the Parameters tab of the tool's properties.
ParameterType
Read only property

String: Required, Optional, Derived Type as defined on the Parameters tab of the tool's properties.
ParameterDependencies
Read/write property

Python List A list of indexes of each dependent parameter.
Value
Read/write property

Value object The value of the parameter.
DefaultEnvironmentName
Read only property

String Environment as defined on the Parameters tab of the tool's properties.
Enabled
Read/write property

Boolean False if the parameter is dimmed (unavailable).
Altered
Read only property

Boolean True if the user has modified the value.
HasBeenValidated
Read only property

Boolean True if the internal validation routine has checked the parameter.
Category
Read/write property

String The category of the parameter.
Schema
Read only property

GP Schema object The schema of the output dataset.
Filter
Read only property

GP Filter object The filter to apply to values in the parameter.
Symbology
Read/write property

String The pathname to a layer file (.lyr) used for drawing the output.
Message
Read only property

String The message to be displayed to the user. See SetErrorMessage() and SetWarningMessage() above.

Some code examples are shown below. For other coding examples, see Customizing script tool behavior.

ToolValidator properties versus script tool properties



A parameter's default value, filter, symbology, and dependencies can be set in both the Parameters tab of the script tool's properties dialog and in the ToolValidator class, as illustrated below.

Overlap of parameter properties

Properties you set in ToolValidator always override those set in the script tool properties dialog box. For example, if you set the default value of a parameter to BLUE in the script tool properties dialog box and reset it to RED in initializeParameters(), the default value is RED. Once initializeParameters() has been called, the script tool properties dialog box will display RED as the default value. If you (or your users) get into the situation where the changes you make to one of these four parameter properties in the script's properties dialog box do not get saved, it is probably because the property is overridden within the ToolValidator class.

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 Parameters tab of the tool's properties.


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

Dependencies are typically set in the initializeParameters() method:
def initializeParameters(self):
  # Set the dependencies for the output and its schema properties
  #
  self.params[2].ParameterDependencies = [0, 1]



Value



This is the value of the parameter that the user entered or you set programmatically. You can set the value in initializeParameters(), in which case it serves as the initial default value for the parameter. You can also set values in updateParameters() in response to user input (click here for an example).
Don't set a parameter value in updateMessages() since the value will not be validated by the internal validation routine.
A value is an object that has a string representation. 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 self.params[3].Value == "Get Spatial Weights From File":
      self.params[8].Enabled = True
  else:
      self.params[8].Enabled = False


The test in the above code would not work if the parameter data type is a feature class, or any value representing a dataset. Values that represent data on disk, such as feature classes and rasters, need to be converted to strings before doing string operations. The built-in Python function str() converts value objects to strings, as follows:

  if str(self.params[0].Value) == "E:\data\example.gdb\roads":


You only need to use the str() function for values with data types that represent datasets. For these types of values, the str() function returns the catalog path to the dataset. You don't need to use this function for other data types, such as long or linear unit, since these data types don't represent datasets and are automatically converted to strings.

NOTE: When using the geoprocessing describe method, never use the string representation of the value.



Incorrect (str function used)
  desc = self.GP.describe(str(self.params[0].Value))

Correct
  desc = self.GP.describe(self.params[0].Value)


You should not use the string representation for datasets (which yields the catalog path to the dataset) since the dataset may not exist—it may be a model variable, and the model has to be run before the dataset exists on disk. If you use the string representation for the dataset, describe may fail since the dataset may not yet exist on disk.

NOTE: Don't use geoprocessing object methods that take a catalog path, such as ListFields, in ToolValidator. The dataset may not exist when your tool is validated in ModelBuilder, and the method may fail. (In the case of ListFields, you can use the Describe Fields method instead.)



When you are testing strings for equivalence, you should use case-insensitive comparisons. The code below shows using the Python lower() function to lowercase the shape type of a feature class and comparing lowercase strings. (Alternatively, you can use the upper() function to compare uppercase strings.)

  fc = self.params[0].Value
  shapetype = self.GP.Describe(fc).ShapeType.lower()
    if shapetype == "point" or shapetype == "multipoint":



Altered



Altered is true if the user changed the value of a parameter—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 does not change the altered state. That is, if you set a default value for a parameter, the altered state of the parameter does not change.
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 they then enter a line feature class, 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 change may change 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 self.params[2].Altered:
      self.params[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 was called. Once internal validate has been called, geoprocessing automatically sets HasBeenValidated to true for every parameter.
HasBeenValidated is used to determine if 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.

# 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 if the input features have already been validated,
#  or the user has set a specific distance (Altered is true).
# 
import string
if self.params[0].Value and not self.params[0].HasBeenValidated:
  if not self.params[6].Altered: 
    extent = self.GP.Describe(self.params[0].Value).Extent
    width = extent.Width
    height = extent.Height
    if width > height:
      self.params[6].Value = width / 100
    else:
      self.params[6].Value = height / 100



Category



You can put parameters in different categories to minimize the size of the tool dialog. The Network Analyst tools use categories, as shown below.
Parameter categories

Since you can only set the category once, set it in initializeParameters(). Setting categories in updateParameters() has no effect. The code below shows putting parameters 4 and 5 into the Options category and parameters 6 and 7 into the Advanced category.

  def initializeParameters(self):
    self.params[4].Category = "Options"
    self.params[5].Category = "Options"
    self.params[6].Category = "Advanced"
    self.params[7].Category = "Advanced"


Categories are always shown after noncategorized parameters. Do not put required parameters into categories since the user may not see them.

Symbology



The symbology property associates a layer file (.lyr) with an output parameter.

params[2].symbology = r"E:\tools\extraction\ToolData\ClassByDist.lyr"

Learn more about output symbology


Schema object

Every output parameter of type feature class, table, raster, or workspace has a schema object. Only output feature classes, tables, rasters, and workspaces have a schema—other types do not. The schema object is created for you by geoprocessing. You access this schema through the parameter object and set the rules for describing the output of your tool. After you set the schema rules, and on return from the ToolValidator class, the geoprocessing internal validation code examines the rules you set and updates the description of the output.

To review, the flow of control is as follows:

  1. When the tool dialog is first opened, initializeParameters() is called. You set up the static rules (rules that don't change based on user input) for describing the output. No output description is created at this time since the user hasn't specified values for any of the parameters (unless you've provided default values).
  2. Once the user interacts with the tool dialog in any way, updateParameters() is called.
  3. updateParameters() can modify the schema object to account for dynamic behavior that can't be determined from the parameter dependencies (such as adding a new field like Add Field).
  4. After returning from updateParameters(), the internal validation routines are called and the rules found in the schema object are applied to update the description of the output data.
  5. updateMessages() is then called. You can examine the warning and error messages that internal validation may have created and modify them or add your own custom warning and error messages.
All Schema properties are read and write except for Type, which is read-only.



Property name Value(s)
Type String: Feature, Table, Raster , Container (for workspaces and feature datasets). (Read-only property.)
Clone Boolean
FeatureTypeRule String: AsSpecified, FirstDependency
FeatureType String: Simple, Annotation, Dimension
GeometryTypeRule String: Unknown, FirstDependency, Min, Max, AsSpecified
GeometryType String: Point, Multipoint, Polyline, Polygon
ExtentRule String: AsSpecified, FirstDependency, Intersection, Union, Environment
Extent Extent object
FieldsRule String: None, FirstDependency, FirstDependencyFIDsOnly, All, AllNoFIDs, AllFIDsOnly
AdditionalFields Python list of field objects
CellSizeRule String: AsSpecified, FirstDependency, Min, Max, Environment
Cellsize double
RasterRule String: FirstDependency, Min, Max, Integer, Float
RasterFormatRule String: Img, Grid
AdditionalChildren Python list of datasets to add to a workspace schema.


Using FirstDependency


Several of the rules can be set to FirstDependency, which means to use the value of the first parameter found in parameter dependency array set with parameter.ParameterDependencies. In the code example below, parameter 2 has two dependent parameters, 0 and 1, and the first dependency is parameter 0.
  # Set the dependencies for the output and its schema properties
  #
  self.params[2].ParameterDependencies = [0, 1]


If any dependent parameter is a multivalue (a list of values), the first value in the multivalue list is used.

Case insensitive


Schema object rules and methods take case-insensitive text strings. For example, "AsSpecified" and "asspecified" are equivalent.

Type


The Type property is read-only and is set by geoprocessing.

Clone


If true, you are instructing geoprocessing to make an exact copy (clone) of the description in the first dependent parameter. The default value is false. Typically, you set Clone to true in the initializeParameters() method. If the first dependent parameter is a multivalue (a list of values), the first value in the multivalue list is cloned.


After setting Clone to true, all rule-based methods, such as FeatureTypeRule, GeometryTypeRule, and ExtentRule, are set to FirstDependency.

The two code examples below do the equivalent work. Both examples are based on how the Clip tool creates the output schema.
Example 1: Explicitly setting all rules
  def initializeParameters(self):
    # Set the dependencies for the output and its schema properties
    #  The two input parameters are feature classes.
    #
    self.params[2].ParameterDependencies = [0, 1]

    # Feature type, geometry type, and fields all come from the first 
    #  dependency (parameter 0), the input features
    #
    self.params[2].Schema.FeatureTypeRule = "FirstDependency"
    self.params[2].Schema.GeometryTypeRule = "FirstDependency"
    self.params[2].Schema.FieldsRule = "FirstDependency"

    # The extent of the output is the intersection of the input features 
    #  and the clip features (parameter 1)
    #
    self.params[2].Schema.ExtentRule = "Intersection"

    return


Example 2: Using Clone to set rules to FirstDependency, then overriding the extent rule
  def initializeParameters(self):
    # Set the dependencies for the output and its schema properties
    #  The two input parameters are feature classes.
    #
    self.params[2].ParameterDependencies = [0, 1]
    self.params[2].Schema.Clone = True
    return

  def updateParameters(self):
    # The only property of the clone that changes is that the extent 
    #  of the output is the intersection of the input features 
    #  and the clip features (parameter 1)
    #
    self.params[2].Schema.ExtentRule = "Intersection"
    return



FeatureTypeRule


This setting determines the feature type of the output feature class. This rule has no affect on output rasters or tables.

Value Description
AsSpecified The feature type will be determined by the FeatureType property.
FirstDependency The feature type will be the same as the first parameter in the dependencies. If the first dependent parameter is a multivalue (a list of values), the first value in the multivalue list is used.


FeatureType


When the FeatureTypeRule is AsSpecified, the value in FeatureType is used to specify the feature type of the output.

Value Description
Simple The output will contain simple features. The geometry type of the features is specified with GeometryTypeRul.
Annotation The output will contain annotation features.
Dimension The output will contain dimension features.


GeometryTypeRule


This setting determines the geometry type (such as point or polygon) of the output feature class.

Value Description
Unknown This is the default setting. Typically, you should be able to determine the geometry type in updateParameters() based on the values of other parameters. You'd only set the rule to Unknown if you don't have enough information to determine the geometry type, such as in initializeParameters().
FirstDependency The geometry type is the same as the first dependent parameter. If the first dependent parameter is a multivalue (a list of values), the first value in the multivalue list is used.
Min, Max Examines the geometries of all dependent parameters and sets the output geometry type to the minimum or maximum type found. Min and Max are defined as follows:
Point and Multipoint = 0

Polyline = 1

Polygon = 2

So, if the dependent parameters were a point and polygon feature class, the minimum would be point and the maximum would be polygon.
AsSpecified The geometry type will be determined by the value of the GeometryType property.


GeometryType


Set this to the geometry type to use (either Point, Multipoint, Polyline, or Polygon) when GeometryTypeRule is AsSpecified.

ExtentRule



Value Description
AsSpecified The output extent will be specified in the Extent property.
FirstDependency The output extent is the same as the first dependent parameter. If the first dependent parameter is a multivalue (a list of values), the first value in the multivalue list is used.
Intersection The output extent will be the geometric intersection of all dependent parameters. (This is what the Clip tool uses, as shown below.)
Union The output extent will be the geometric union of all dependent parameters.
Environment The output extent will be calculated based on the output extent environment setting.

Example

    # The extent of the output is the intersection of the input features 
    #  and the clip features (the dependent parameters)
    #
    self.params[2].Schema.ExtentRule = "Intersection"



Extent


Set this to the extent to use when ExtentRule is AsSpecified. You can either set the extent with a space-delimited string or a Python list object with four values. The sequence is xmin, ymin, xmax, ymax.
Example
self.params[2].Schema.ExtentRule = "AsSpecified"
self.params[2].Schema.Extent = "123.32 435.8 987.3 567.9"


or using a Python list

xmin = 123.32
ymin = 435.8
xmax = 987.3
ext = [xmin, ymin, xmax, 567.9]
self.params[2].Schema.Extent = ext



FieldsRule


FieldsRule determines what fields will exist on the output feature class or table.

In the table below, FID stands for Feature ID, but actually refers to the ObjectID field found on every feature class or table.

Value Description
None No fields will be output except for the object ID.
FirstDependency Output fields will be the same as the first dependent parameter. If the first dependent parameter is a multivalue (a list of values), the first value in the multivalue list is used.
FirstDependencyFIDsOnly Only the ObjectID of the first dependent input will be written to the output.
All All fields in the list of dependent parameters will be output.
"llNoFIDs All fields except for the ObjectIDs will be written to the output.
"llFIDsOnly All ObjectID fields are written to the output, but no other fields from the inputs will be written.

Example of Clip using FieldsRule of FirstDependency
  def initializeParameters(self):
    # Set the dependencies for the output and its schema properties
    #  The two input parameters are feature classes.
    #
    self.params[2].ParameterDependencies = [0, 1]

    # Feature type, geometry type, and fields all come from the first 
    #  dependency (parameter 0), the input features
    #
    self.params[2].Schema.FeatureTypeRule = "FirstDependency"
    self.params[2].Schema.GeometryTypeRule = "FirstDependency"
    self.params[2].Schema.FieldsRule = "FirstDependency"

    # The extent of the output is the intersection of the input features 
    #  and the clip features (parameter 1)
    #
    self.params[2].Schema.ExtentRule = "Intersection"

    return



AdditionalFields


Besides the fields that are added by the application of the FieldsRule, you can add additional fields to the output. AdditionalFields takes a Python list of field objects.

View example of using AdditionalFields

CellSizeRule


This determines the cellsize of output rasters or grids.

Value Description
AsSpecified The output cellsize is specified in the CellSize property.
FirstDependency The cell size is calculated from the first dependent parameter. If the dependent parameter is a raster, then its cell size is used. For other types of dependent parameters, such as feature classes or feature datasets, the extent of the data is used to calculate a cell size.
If the first dependent parameter is a multivalue (a list of values), the first value in the multivalue list is used.
Min, Max Min means the output cell size is the smallest cell size of the dependent parameters. Max means it is the largest cell size of the dependent parameters.
"Environment" The output cel lsize is calculated based on the cell size environment setting.


CellSize


Set this to the cell size to use when CellSizeRule is AsSpecified.

RasterRule


This determines the data type—integer or float—contained in the output raster.

Value Description
FirstDependency The data type (integer or float) is the same as the first dependent parameter. If the first dependent parameter is a multivalue (a list of values), the first value in the multivalue list is used.
Min, Max Integer is considered smaller than float. For example, if there are two dependent parameters, one containing integers and the other containing floats, Min creates an integer output and Max creates a float output.
Integer The output raster contains integers (whole numbers).
Float The output raster contains floats (fractional numbers).


RasterFormatRule


This determines the output raster format, either Grid or Img. The default is Img, which is ERDAS IMAGINE format. Grid is ESRI's format.

Learn more about raster data formats

AdditionalChildren



A workspace is a container for datasets (features, tables, and rasters). These datasets are children of the workspace (think of the workspace as the parent). If your tool adds datasets to a new or existing workspace, you can update the description of the workspace by adding descriptions of the children. For example, you may have a tool that takes a list of feature classes (a multivalue), modifies them in some way, then writes the modified feature classes to an existing workspace. When the tool is used in ModelBuilder, the workspace is the derived output of the tool, and you may want to use this workspace as input to the Select Data tool. Select Data allows you to select a child dataset found in a container and use it as input to another tool.
The input to AdditionalChildren is one or more descriptions of the children. There are two forms of child descriptions:

Form Description
Geoprocessing value object A feature class, table, raster, dimension, or annotation value, as returned by the Value method; for example
inFeatures = self.params[0].Value



Python list object of the form [type, name, fields, extent, spatial reference] A Python list containing a description of the child to be added. Only the first two entries in the list, type and name, are required. The remaining arguments are optional.

When adding more than one child, you provide a list of child descriptions. If you're adding the children using the Python list object form, you'll create a list of lists for AdditionalChildren.
View examples of using Python lists and list of lists

The Python list form has five arguments, as described in the following table.

Argument Type Description
type required One of the following:
    Point
    Multipoint
    Polyline
    Polygon
    Table
    Raster
    Annotation
    Dimension
name required The name of the dataset. It can just be the base name of the dataset (streets) or the full catalog path ("E:\mydata\test.gdb\infrastructure\streets"). When a full catalog path is given, all but the base name (streets) is ignored.
fields optional A Python list of field objects. This contains the fields appearing on the child, if known.
extent optional A string or Python list containing the spatial extent of the child.
spatial reference optional A spatial reference object.

These arguments must be supplied in the order shown. To skip over an optional argument, use the Python keyword None or "#" (command line style).

Following are some examples of setting a workspace schema. The examples are based on a script tool that has the following arguments:


Parameter name Properties
0 Input feature class Feature class—Input
1 Input table Table—Input
2 Input workspace Workspace—Input (an existing workspace that contains the results of the tool).
3 Derived workspace Workspace—Derived output, obtained from Input_workspace. The schema of this workspace is modified to contain additional children.

The tool takes the input feature class and table, copies both to the workspace, adds a new field to the feature class, then creates a new polygon feature class in the workspace. (The actual work of the tool isn't important as it only serves to illustrate setting a workspace schema.) The code examples below build on one another, starting with simple usage of AdditionalChildren. If you choose to implement and test some of the code examples below, you can test the code using the model illustrated below.

Model used to view results of validation

In initializeParameters(), the output workspace is cloned from its dependent parameter (parameter 2). This dependency is set in the tool properties but can also be set in initializeParameters() to guard against someone removing the dependency in the tool's properties.

class ToolValidator:
  def __init__(self):
    import arcgisscripting as ARC
    self.GP = ARC.create(9.3)
    self.params = self.GP.getparameterinfo()

  def initializeParameters(self):
    self.params[3].ParameterDependencies = [2]  # input workspace
    self.params[3].Schema.Clone = True  # Copy all existing contents to output
    return


Example: Copy the two inputs (no modifications) to the output workspace:
  def updateParameters(self):
    inFC = self.params[0].Value     # input feature class
    inTable = self.params[1].Value  # input table
    inWS = self.params[2].Value     # input workspace
    if inFC and inTable and inWS:
      self.params[3].Schema.AdditionalChildren = [inFC, inTable]
    return


Example: The tool creates a new polygon feature class. The only properties known about this new feature class (when validating) are the name (SummaryPolygon) and type (polygon).

  children = []    # New empty list
  children.append(inFC)
  children.append(inTable)
  children.append(["polygon", "SummaryPolygon"])
  self.params[3].Schema.AdditionalChildren = children


Example: Add a field to the input feature class.

  # Create a field object with the name "Category" and type "Long"
  #
  newField = self.GP.CreateObject("Field")
  newField.Name = "Category"
  newField.Type = "Long"

  # Describe the input feature class in order to get its list of fields. The 9.3
  #  version of the geoprocessing object returns fields in a Python list, unlike
  #  previous versions, which returned fields in an enumerator.
  #
  desc = self.GP.Describe(inFC)
  fieldList = desc.Fields

  # Add the new field to the list
  #
  fieldList.append(newField)

  # Create a new child based on the input feature class, but with the 
  #  additional field added
  #
   newChild = [desc.ShapeType, desc.CatalogPath, fieldList,                   desc.Extent, desc.SpatialReference]

  # Now create our list of children and add to the schema
  #
  children = []
  children.append(newChild)
  children.append(inTable)
  children.append(["polygon", "SummaryPolygon"])
  self.params[3].Schema.AdditionalChildren = children


To create fields for SummaryPolygon (the new polygon feature class), create a list of field objects similar to the pattern shown in the above example.

Example: Multivalue input.
In this example, the first parameter is a mulitvalue of feature classes. Each feature class in the multivalue is copied to the derived workspace. A new field, ProjectID, is added to each of the copied feature classes.

# 0 - input features (multivalue)
# 1 - input workspace
# 2 - derived workspace

class ToolValidator:
  def __init__(self):
    import arcgisscripting as ARC
    self.GP = ARC.create(9.3)
    self.params = self.GP.getparameterinfo()

  def initializeParameters(self):
    self.params[2].ParameterDependencies = [1]
    self.params[2].Schema.Clone = True
    return

  def updateParameters(self):
    inVT = self.params[0].Value   # multivalue ValueTable
    inWS = self.params[1].Value   # WorkSpace

    # Add each feature class to the output workspace. In addition,
    #  add a new field "ProjectID" to each feature class
    #
    if inVT and inWS:
        rowCount = inVT.rowcount  # Number of rows in the MultiValue table
        children = []
        newField = self.GP.CreateObject("Field")
        newField.Name = "ProjectID"
        newField.Type = "Long"
        for row in range(0, rowCount):
            value = inVT.GetValue(row, 0)
            if value:
                d = self.GP.Describe(value)
                fieldList = d.Fields

                # Note -- not checking if field already exists
                #
                fieldList.append(newField)

                # Create new child with additional ProjectID field and
                #  add child to list of children
                #
                child = [d.shapetype, d.catalogpath, fieldList]
                children.append(child)            

        self.params[2].Schema.AdditionalChildren = children
    return

  def updateMessages(self):
    return



Filter object




The filter object allows you to specify the choices available to the user for a parameter. For example, you can set up a field filter that limits choices to just text fields. A filter does three jobs.



There are two ways to specify filters.



There are six kinds of filters, as shown in the table below.

Filter type Values
ValueList A list of string or numeric values. Used with String, Long, Double, and Boolean data types.
Range A minimum and maximum value. Used with Long and Double data types.
FeatureClass A list of allowable feature class types, specified with the values Point, Multipoint, Polyline, Polygon, MultiPatch, Sphere, Annotation, Dimension. More than one value can be supplied to the filter.
File A list of file suffixes. Example txt, e00, ditamap.
Field A list of allowable field types, specified by the values Short, Long, Single, Double, Text, Date, OID, Geometry, Blob, Raster, GUID, GlobalID, XML. More than one value can be supplied to the filter.
Workspace A list of allowable workspace types, specified by the values FileSystem, LocalDatabase, and RemoteDatabase. More than one value can be supplied.


Properties



Property Description
Type The type of filter (ValueList, Range, FeatureClass, File, Field, and Workspace). You can set the type of filter when dealing with Long and Double parameters (see note below). For other types of parameters, there is only one valid type of filter, so setting the type on these parameters is ignored. If you do not want to filter values, set the List property to an empty list.
List A Python list of values for the filter. If you do not want to filter values, set the List property to an empty list.


ValueList



ValueList for String parameters
For a string parameter, the list can contain any number of strings. Below is an example of setting the list of string values in initializeParameters. The parameter contains two choices, NEW_FORMAT and OLD_FORMAT.
  def initializeParameters(self):
    # Set the fixed list of "file format type" parameter choices and its
    #  default value
    #
    self.params[1].Filter.List = ["OLD_FORMAT", "NEW_FORMAT"]
    self.params[1].Value = "OLD_FORMAT"
    return


In the above example, you could have just as easily set the list of values in the Parameter tab of the tool's properties dialog. In fact, if you had set the list of values to something else (like OLD and NEW) in the tool's properties, these values would be replaced by OLD_FORMAT and NEW_FORMAT when initializeParameters() is called. The same is true for the default value—it can be set in the tool's properties dialog and then reset in ToolValidator.

NOTE: The list of values you provide in ToolValidator always replaces the values set in the tool's properties dialog. This behavior allows you to update the values based on other parameters.



Continuing with this example, the code below shows updateParameters() changing a list of values in another parameter based on whether the user chose OLD_FORMAT or NEW_FORMAT:

  def updateParameters(self):
    # Update the value list filter of the "feature type in file" parameter 
    #   depending on the "file format type" parameter.
    #
    if self.params[1].Value.upper() == "OLD_FORMAT":
      self.params[2].Filter.List = ["POINT", "LINE", "POLYGON"]
    elif self.params[1].Value.upper() == "NEW_FORMAT":
      self.params[2].Filter.List = ["POINT", "LINE", "POLYGON",                                     "POINT_WITH_ANNO",                                     "LINE_WITH_ANNO",                                     "POLYGON_WITH_ANNO"]

    # Provide default value for "feature type in file" parameter
    #
    if not self.params[2].Altered:
      self.params[2].Value = "POINT"


ValueList for Long and Double parameters
A Long or Double parameter can have a list of numeric values. The user can only choose or enter values that are in the list.

  # Set filter for a Long parameter
  #
  self.params[7].Filter.List = [10, 20, 30, 40, 50]

  # Set filter for a Double parameter
  #
  self.params[8].Filter.List = [10.0, 12.5, 15.0]


ValueList for Boolean parameters
There are two values for a Boolean parameter: the true value and false value. The true value is always the first value in the list.

  def initializeParameters(self):
    # Set the Boolean choice for including or excluding angles
    #
    self.params[6].Filter.List = ["ANGLE", "NO_ANGLE"]

    # Set the default value to false (no angle)
    #
    self.params[6].Value = "NO_ANGLE"
    return

  def updateParameters(self):
    # Enable angle format parameter if user wants angles
    #
    if self.params[6].Value.upper() == "ANGLE":
      self.params[7].Enabled = True



Range


A Long or Double parameter can have a Range filter. Range filters have two values, the minimum and maximum. The first value in the list is the minimum. The range is inclusive, meaning the minimum and maximum are valid choices.

  def initializeParameters(self)
    # Utility values must be between -10 and 10.
    #
    self.params[7].Filter.List = [-10, 10]



Setting filter type on long and double parameters




For Long and Double parameters, the default filter type is ValueList. If you want it to be a Range filter, set the filter type in initializeParameters(), as follows:

  def initializeParameters(self)
    # Set the 'score' value parameters to a range filter
    #
    self.params[7].Filter.Type = "Range"
    self.params[7].Filter.List = [-10, 10]


You can only set the filter type for Long and Double parameters.

FeatureClass


The example below shows setting the feature type of one input parameter based on the feature type of another input parameter.

  def updateParameters(self):
    # Set the input feature type of the second parameter based
    #  on the feature type of the first parameter.
    #
    if self.params[0].Value:
      desc = self.GP.describe(self.params[0].Value)
      feature_type = desc.ShapeType.lower()

      if feature_type == "polygon":
        self.params[1].Filter.List = ["point", "multipoint"]

      elif feature_type == "polyline":
        self.params[1].Filter.List = ["polygon"]

      elif feature_type == "point" or            feature_type == "multipoint":
        self.params[1].Filter.List = ["polyline"]

      else:
        self.params[1].Filter.List = []

    return



File


The file filter contains a list of file suffixes that a file can have, such as txt (simple text file) and csv (comma separated value). You can supply any text for a suffix—it doesn't have to be a suffix that ArcGIS recognizes. The suffix can be of any length and does not include the dot. The example below shows setting the filter for an input File parameter.

  def initializeParameters(self)
    # Set the input file type to our recognized options file suffixes
    #
    self.params[0].Filter.List = ["opt56", "opt57", "globalopt"]
    return



Field


The field filter defines the permissible field types. Values can be Short, Long, Single, Double, Text, Date, OID, Geometry, Blob, Raster, GUID, GlobalID, XML.

Display versus Internal name
There are four field types that have an internal name, shown in the table below.
Display name Internal name
Short SmallInteger
Long Integer
Float Single
Text String

When specifying a field filter, you can use either the display or internal name. That is, the following two lines of code are equivalent:

  self.params[1].Filter.List = ["short", "long", "float", "text"]
  self.params[1].Filter.List = ["smallinteger", "integer", "single", "string"]


If you supply the display name, such as "short", it is converted and stored in the filter as "SmallInteger." You should rarely need to access values in the field filter, but if you do, be aware that the internal name is stored. The code snippet below shows how to account for this:

  self.params[1].Filter.List = ["short", "long"]
  # 
  if self.params[1].Filter.List[0].lower() == "smallinteger":
    # do something


Setting a default field value

You may want to provide a default value for a field parameter. The way you do this is to loop through the fields on the input table and pick the first field that satisfies the filter, as follows:

  def initializeParameters(self):
    self.params[1].Filter.List = ["short", "long", "float", "double"]
    return

  def updateParameters(self):
    if self.params[0].Value and not self.params[1].Altered:
        self.params[1].Value = ""
        desc = self.GP.Describe(self.params[0].Value)
        fields = desc.Fields

        # Set default to the first field that matches our filter
        #
        for field in fields:
            fType = field.type.lower()
            if fType == "smallinteger" or                fType == "integer" or                fType == "single" or                fType == "double":
                self.params[1].Value = field.Name
                break
    return


NOTE: Do not use the geoprocessing ListFields method in ToolValidator. Instead, use the Describe method as shown above.


Learn more about using Describe versus ListFields

Workspace


The workspace filter specifies the types of input workspaces that are permissible. There are three values:



Please visit the Feedback page to comment or give suggestions on ArcGIS Desktop Help.
Copyright © Environmental Systems Research Institute, Inc.