Hi Guys,
I have a table in a view and I bind its Data property via a Tag History binding using an expression. The expression simply returns an array which I have as a custom property on the table.
In the table startup event, I construct an array which I write to the custom property I have on the table. Problem I’m having is this array builds up, that is it contains the last data I wrote to it along with the new data every time I launch it. What I want to do is clear the array every time the component launches before writing fresh data to it.
Any ideas?
Can you post your startup script?
Sure, here it is. Basically all I’m doing is getting all the tags under a path to show Tag History for them. The path is passed in by different devices.
def runAction(self):
"""
Method that will run whenever the selected event fires.
Arguments:
self: A reference to the component that is invoking this function.
"""
devicePath = self.view.params.basePath
items = []
allTags = []
allTags = tags.browseTags(devicePath,filter = {'tagType':'AtomicTag'})
for itag in allTags:
items.append({'path':itag,'alias':itag,'aggregate':'LastValue'})
self.custom.key = items
Hmm, it looks like you’re already constructing the array from blank and is replacing the existing custom property value. Are you seeing that the custom.key property value keeps its old items from the previous run and your new items are being appended onto it? Or am i misunderstanding your question?
Yes that is exactly what it is doing. It keeps the results from the previous run and then adds the new results so basically it’s doubling in length every time. I assumed if you set it to a new value to it it would overwrite the old contents but it doesn’t. I even tried adding the line custom.key = [] at the beginning of the script to see if that would zero it out everytime the script ran.
Ok it’s officially driven me up the wall 
Are we 100% certain that the tags.browseTags
invocation is not the cause? I just tried this locally using system.tag.browse()
and everything worked fine. I suspect that project library is not clearing out an internal array and is then supplying the duplicated array. You could verify this if you print the length of the allTags
variable immediately after it’s been assigned a value.
Not sure, I took that code off the User Manual for Recursive browse and simply added a list to return. The code is below. Granted I couldn’t for the life of me work out how to return the results from the recursive browse function listed in the manual so I copied off someone who posted it in the forum 
def browseTags(path, filter, rtResult=[]):
# First, browse for anything that can have children (Folders and UDTs, generally)
results = system.tag.browse(path)
for branch in results.getResults():
if branch['hasChildren']:
# If something has a child node, then call this function again so we can search deeper.
# Include the filter, so newer instances of this call will have the same filter.
browseTags(branch['fullPath'], filter)
# Call this function again at the current path, but apply the filter.
results = system.tag.browse(path, filter)
for result in results.getResults():
# Here's where you'd want to do something more useful. For now we print.
#print result['fullPath']
if str(result['fullPath']).find('_types') == -1:
rtResult.append(result['fullPath'])
return rtResult
Yeah, that function doesn’t work well and does append onto itself due to Python stuff…
Replace this:
def browseTags(path, filter, rtResult=[]):
with this
def browseTags(path, filter, rtResult=None):
if rtResult is None: rtResult = []
Basically, if you define a mutable object as the default argument in a function and you mutate it in the function, then Python keeps this in memory and doesn’t wipe it on the next function call.
2 Likes
Genius, that did the trick. Just to add to that, in order to make it work for a recursive function I had to explicitly set rtResult in the subsequent call.
for branch in results.getResults():
if branch['hasChildren']:
# If something has a child node, then call this function again so we can search deeper.
# Include the filter, so newer instances of this call will have the same filter.
browseTags(branch['fullPath'], filter, rtResult) <----
I must say, this should be made much easier to do. Hopefully down the track you can simply pass in a path with a wildcard and retrieve all the tags beneath that path.
The old tag browse function in 7 had it, and the recursive argument is actually still there in the new v8 function, but it has some issues currently so it’s currently undocumented. It’ll be back at some stage I assume