# Tool validator value list append doesn't work?

463
9
03-28-2014 02:15 PM
by
Occasional Contributor
Hi Folks,

if you put the following code into a script tool 'toolValidator' class 'updateParameters' method, it only puts 'fee' in the list (no error is thrown).
self.params[0].filter.list = ['fee'] self.params[0].filter.list.append('foo')

The documentation says the 'list' filter property is a Python list.  My question is, why can't I append?  (The examples in the documentation all hard code the list... which makes me wonder if the authors know about this problem but didn't have time to fix it).

Thanks!
Tags (3)
1 Solution

Accepted Solutions
Regular Contributor II
Each time you request filter.list, it gives you a new copy of the list. You need to do this:
self.params[0].filter.list = ['fee'] self.params[0].filter.list += ['foo']

or

self.params[0].filter.list = ['fee'] fl = self.params[0].filter.list = ['fee'] fl += ['foo'] self.params[0].filter.list = fl
9 Replies
Regular Contributor
Huh... I thought that would have worked as well.  I'll try to dig into it and what gives.
Regular Contributor II
Each time you request filter.list, it gives you a new copy of the list. You need to do this:
self.params[0].filter.list = ['fee'] self.params[0].filter.list += ['foo']

or

self.params[0].filter.list = ['fee'] fl = self.params[0].filter.list = ['fee'] fl += ['foo'] self.params[0].filter.list = fl
by
Occasional Contributor
So, in effect, it's an immutable list?
Regular Contributor II
The Python list reflects the state of an underlying list on a C++ object at the time it was requested. It does not alter the state of that C++ list when you manipulate the Python list, the filter.list setter implementation does.
by
Occasional Contributor
Okay, thanks.  So I guess in Python terms, it may be useful to think of the filter list as a tuple instead of a list, since that's more like how it behaves.

I didn't realize there's a forum for Python questions now.  Should have posted this over there.

But I do have an additional question, in case you guys are still following this�?�

From inside the ToolValidator, can we access the property that stores the path of the script to which a script tool is pointing?

I'd like to set the default value of an input data file based on its relative path to the script.   An acceptable alternative for me would be to detect the location of the toolbox containing the script tool.  But the following return empty strings inside the ToolValidator class:

os.getcwd
sys.argv[0]
os.path.abspath(__file__)
inspect.getfile(inspect.currentframe())
Regular Contributor II
From inside a validator __file__ will be set to the full path of the TBX file (plus some extra information, it'll look like C:\pth\to\mytools.tbx#MyScriptTool.updateParameters). There isn't a way to get to the path of the script tool it wraps, though.
by
Occasional Contributor
Nice!  At least we can get the toolbox path from that.

Thanks.
by
Occasional Contributor
Okay here's some more puzzling behavior inside the ToolValidator class.  If I select a valid workspace for params[0] that has no rasters in it, ListRasters returns an empty list []
BUT self.params[1].value is set to 'fee'!

def updateParameters(self):
arcpy.env.workspace = self.params[0].value
rasts = arcpy.ListRasters()
if rasts:
self.params[1].value = 'fee'
else:
self.params[1].value = 'foo'
return


In Python, an empty list is false.

>>> arcpy.env.workspace = 'C:\noRastersDir'
>>> rasts = arcpy.ListRasters()
>>> rasts
[]
>>> if rasts:
...  print 'a'
... else:
...  print 'b'
...
b

But yet, it's evaluated as True inside the ToolValidator.

Why?

And more ominously, what other Python code isn't going to work as expected!!?
Regular Contributor
You can also use sys.path[0]:
tbxLoc = sys.path[0]

But, as Jason says, you can't get the path to the script in Validator.