1 Reply Latest reply: Feb 28, 2013 7:50 AM by curtvprice

    Listbox patterns or how do you string dependent inpu parameters in updateParametes()?

    blekros
      GPers,

      Having given up on ModelBuilder and Script Tools due to repeated Arc Desktop crashes, I have arrived down at the bare-metal:   the promising Python Toolbox.

      I'm trying to write a tool that allows the user choose the workspace, then select from a specific set of feature classes, then automatically fill a dropdown of filtered subtypes for the selected feature.

      This immediately presents the following problems:
      What datatype to set for the parameters?  Should I make them all string instead of Workspace, feature class, etc
      Is there an enumeration for the arcpy parameter datatypes so I don't have to type the bloody things and spell them correctly?
      How to detect the appropriate change-events?
      Should I set parameterDependencies() for any of them?
      What is the actual datatype of arcpy.Parameter.value?  a describe object?  a string? type (arcpy.Parameter.value) merely returns "property"
      Is there an arcpy.mapping dialog box that can display a table control?
      For coded picklists, like subtypes, what is the strategy for picking the value, yet returning the code so it can be used in a SQL expression?   The best I've seen is a list expansion with a value matching criteria.   Can this be handled if the argument were defined as a Field Info instead?

      Thus far, this is all I've been able to muster with no success:

      import arcpy
      
      
      class Toolbox(object):
          def __init__(self):
              """Define the toolbox (the name of the toolbox is the name of the
              .pyt file)."""
              self.label = "Toolbox"
              self.alias = ""
      
              # List of tool classes associated with this toolbox
              self.tools = [FeaturesBySubtype]
      
      
      class AbstractTool(object):
          def __init__(self):
              """Define the tool (tool name is the name of the class)."""
              self.label = "Tool"
              self.description = ""
              self.canRunInBackground = False
      
          def getParameterInfo(self):
              """Define parameter definitions"""
              params = None
              return params
      
          def isLicensed(self):
              """Set whether tool is licensed to execute."""
              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."""
              return
      
          def updateMessages(self, parameters):
              """Modify the messages created by internal validation for each tool
              parameter.  This method is called after internal validation."""
              return
      
          def execute(self, parameters, messages):
              """The source code of the tool."""
              return
      
      class FeaturesBySubtype(AbstractTool):
          def __init__(self):
              self.label = "Query Features By Subtype"
              self.description = "Return all the features of the specified subtype for the specified feature class"
              self.canRunInBackground = True
      
          def getParameterInfo(self):
              p1 = arcpy.Parameter(
                  displayName="Workspace",
                  name="in_workspace",
                  datatype="Workspace",
                  parameterType="Required",
                  direction="Input")
      
              p2 = arcpy.Parameter(
                  displayName="Feature Class",
                  name="in_featureclass",
                  datatype="Feature Class",
                  parameterType="Required",
                  direction="Input")
      
              p3 = arcpy.Parameter(
                  displayName="Subtype",
                  name="in_subtype",
                  datatype="string",
                  parameterType="Required",
                  direction="Input")
      
              p4 = arcpy.Parameter(
                  displayName="Output Table",
                  name="out_resulttable",
                  datatype="Table View",
                  parameterType="Required",
                  direction="Output")
              
              params = [p1,p2,p3,p4]
              return params
          
      
          def updateParameters(self, parameters):
              if parameters[0].value:
                  arcpy.env.workspace=parameters[0].value
                  
              for a_parm in parameters:
                  if a_parm.altered and not(a_parm.hasBeenValidated):
                     a_parm.setWarningMessage(str.format('Parameter modified {0}', a_parm.name)  )
              parameters[1].filter.list=['Fuse','Switch']
              st = arcpy.da.ListSubtypes('Fuse')
              parameters[2].filter.type='ValueList'
              parameters[2].filter.list = st.values()
              return
          
          
          def execute(self, parameters, messages):
              arcpy.AddMessage(parameters)
              
              tableList = [parameters[1].value]
              
              fc_descr = arcpy.Describe ( parameters[1].value)
              subtype_field = fc_descr.subtypeFieldName
              
              whereClause = str.format("{0}={1}",subtype_field,parameters[2].value)
              lyrName = "QueryOutput"
              
              arcpy.AddMessage(whereClause)
              # Make Query Table...
              arcpy.MakeQueryTable_management(tableList, lyrName, None, None, None, whereClause)
           
              # Print the total rows
              arcpy.AddMessage( arcpy.GetCount_management(lyrName))
           
      
              return    
        • Re: How do you string dependent input parameters in updateParameters?
          curtvprice
          Having given up on ModelBuilder and Script Tools due to repeated Arc Desktop crashes, I have arrived down at the bare-metal: the promising Python Toolbox.


          Hate to tell you Brad, but I've found .pyt to be pretty unstable compared to script toolboxes until you have enough experience to get the syntax exactly right. Also, if you were doing things with script tool validation etc that was crashing ArcMap, the same validation code will crash ArcMap just as effectively.  As far as I can tell, the tbx is simply a slightly different implementation of the same framework used in the pyt file. You do have a little more control with value table parameters than the tbx property sheets support.  (Maybe an Esri person can chime in, as I haven't gotten into that yet.) 

          What datatype to set for the parameters? Should I make them all string instead of Workspace, feature class, etc
          Is there an enumeration for the arcpy parameter datatypes so I don't have to type the bloody things and spell them correctly?
          How to detect the appropriate change-events?


          This is the same as it is with the validation code for tbx script tools. For datatypes that have string representation like Field, you can generate picklists as strings and then apply them to a filter. ".value" is the arcpy data type you have set it to be (that may or may not have an easy string representation you can use. Depends on the data type).
          Arc 10.1 Help:

          '>Understanding validation in script tools

          Customizing tool behavior in a Python toolbox

          So far I haven't been convinced to abandon the .tbx format in my work because 1) the tbx can store tool documentation inside the file and a .pyt doc hangs out in parallel .xml files, 2) I have 10.0 users to support, and 3) I am one of those lazy people  that likes it when someone does my work for me with property sheet interfaces so I don't have to write the code myself. (OK, I'll come clean, the folks that implemented the tbx properties are far better Python programmers than me.)

          Honestly if you're getting started with Python toolboxes, I feel the best approach to start with is to make a good old fashioned tbx script tool with validation set up for you from the script tool's property sheets (and maybe a little of your own in the Validation tab), then convert to a pyt using this conversion tool.

          Once you've done this you'll have auto-generated code to start with so you can get familiar with how it works with your particular application.