Strange Tool Validation Behaviour

1106
4
10-31-2016 12:01 AM
GinoMellino
Occasional Contributor

Hello,

I have a custom python script and tool which is designed to allow a user to select and zoom to a locality. Param[0] is a feature layer (containing locality boundaries) and param[1] is a multi value list which is populated from a field in the selected feature layer in param[0]. If I open the MXD and open the tool the localities in param[1] populate perfectly. If I use the tool to select a particular locality and zoom to it the script will run perfectly. However, if I then reopen the tool to use it again the only value which will be populated in param[1] is the locality value I used when I previously ran the tool and not all the locality values. I cannot get this to reset until I close the MXD and open it fresh again. 

The validation code is attached. Can anyone please tell me what I am doing wrong? I am sure it is something terribly simple which I am not seeing...

Cheers, 

Gino

0 Kudos
4 Replies
GinoMellino
Occasional Contributor

FYI I decided to hard-code the featurelayers path into the validation code and it works fine. I still cannot explain the behaviour in my previous post. 

0 Kudos
DanPatterson_Retired
MVP Emeritus

strange... if a hard-code path works then perhaps the full path to file isn't being grabbed.

One useful tip to exploit if your data are in a location relative to the running script/tool is

path = sys.argv[0]

data = path + "/DataFolder/some.gdb/something

so data refers now to the location of the something you are looking for since it is in a gdb in a folder relative to the location of the running script

GinoMellino
Occasional Contributor

Thanks Dan. Yep, I don't know why it does this, I would think it if it works the first time it should have reference to the layer set correctly, not sure why it would lose it after the first run?

This tool is designed to work with layers in a particular MXD so in this instance I just grabbed the layer from the TOC and used its datasource property as the input. Will keep your suggestion in mind when I need to reference the script folder however 🙂

Cheers, 

Gino

0 Kudos
curtvprice
MVP Esteemed Contributor

I'm wondering if using {} instead of [] for the list is an issue or whether in the end the set is being converted to a list by arcpy so it's no issue. ({} delineates a set [] delineates a list.)  

As for Dan's comment about the local path. There are two options: os.path.dirname(sys.argv[0]) or os.path.dirname(__file__).  Which is best depends on what you need -- usually __file__.

See: Difference between __file__ and sys.argv[0] (StackOverflow)

(In .tbx script tool validation code __file__ will be the path to the function - packed in the tbx file using a relative link syntax: u'C:\\test\\Toolbox.tbx#Script_z.InitializeParameters.py', sys.argv[0] will just give you an empty string as I would guess the validation code is being run with execfile().)

One more thing about path - maybe you instead want the path to the mxd? (Don't forget to import os at the top of your validatino code.)

here = os.path.dirname(arcpy.mapping.MapDocument("CURRENT").filePath‍)

Back to your original question: I would remove the if statement in the initialize code to make sure it always at least attempts to run. 

  def initializeParameters(self):
    """Refine the properties of a tool's parameters.  This method is
    called when the tool is opened."""

    try:
        self.params[1].filter.list = sorted(
            [row[0] for row in arcpy.da.SearchCursor(
                self.params[0].value, "ADMINAREANAME") if row[0]])
    except:
        pass‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Gino's attached .py snippet is pretty short so I am including it here:

import arcpy


class ToolValidator(object):
  """Class for validating a tool's parameter values and controlling
  the behavior of the tool's dialog."""

  def __init__(self):
    """Setup arcpy and the list of tool parameters."""
    self.params = arcpy.GetParameterInfo()

  def initializeParameters(self):
    """Refine the properties of a tool's parameters.  This method is
    called when the tool is opened."""

    if self.params[0].value:
        self.params[1].filter.list = sorted(
            {row[0] for row in arcpy.da.SearchCursor(
                self.params[0].value, "ADMINAREANAME") if row[0]})

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

    if self.params[0].altered:
        if self.params[0].value:
            self.params[1].filter.list = sorted(
                {row[0] for row in arcpy.da.SearchCursor(
                    self.params[0].value, "ADMINAREANAME") if row[0]})

    return

  def updateMessages(self):
    """Modify the messages created by internal validation for each tool
    parameter.  This method is called after internal validation."""
    return
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos