Python toolbox doesn't want to refresh

6611
4
Jump to solution
06-15-2015 01:39 PM
CharlesGasse1
New Contributor

Hi, i got a problem with my python toolbox.

First, i have a toolbar (test_addin) with 3 buttons:

toolbar.png

Button1 will activate Button2 and deactivate himself. Same thing for Button2.

"Go" will start a tool in a python toolbox.

This tool have a parameter object with a defaut value set to "1" or "2" depending on which button is activated.

The problem is: when i execute the tool, it work one time, but when i try to activate the other button, and then rerun the tool,

the defaut value for the parameter is not refreshing. I have to refresh the python toolbox manually to make it work.

Is there a way to make this work automatically?

Tank you!

Charles

-------------------------------------------

Toolbar:

import arcpy
import pythonaddins

class ButtonClass1(object):
    """Implementation for test_addin.button1 (Button)"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):
        button1.enabled = False
        button2.enabled = True
        gobutton.enabled = True

class ButtonClass2(object):
    """Implementation for test_addin.button2 (Button)"""
    def __init__(self):
        self.enabled = False
        self.checked = False
    def onClick(self):
        button2.enabled = False
        button1.enabled = True
        gobutton.enabled = True

class GoClass3(object):
    """Implementation for test_addin.gobutton (Button)"""
    def __init__(self):
        self.enabled = False
        self.checked = False
    def onClick(self):
        tbx = r"V:\mes documents\ArcGIS\AddIns\test\Install\Toolbox.pyt"
        tool = "Tool"
        arcpy.RefreshCatalog(tbx)
        pythonaddins.GPToolDialog(tbx, tool)



python toolbox:

import arcpy
import test_addin

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 = [Tool]


class Tool(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"""
        reload(test_addin)
        # First parameter
        param0 = arcpy.Parameter(
            displayName="Active button",
            name="button",
            datatype="String",
            parameterType="Required",
            direction="Input")

        if test_addin.button1.enabled == True:
            param0.value = "1"
        if test_addin.button2.enabled == True:
            param0.value = "2"

        params = [param0]
        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."""
        arcpy.AddWarning(parameters[0].valueAsText)
        return

        









0 Kudos
1 Solution

Accepted Solutions
Luke_Pinner
MVP Regular Contributor

I think ArcGIS might only load the toolbox once to improve performance.  I workaround this by making a temporary copy of the toolbox every time I want to call it.

import os, sys
import glob
import shutil
import tempfile
import threading
import time

import arcpy, pythonaddins

class Button(object):
    # ...
    def onClick(self):
        GPToolDialog('path/to/toolbox.pyt', 'ToolName')

def GPToolDialog(toolbox, tool):
    """
         * Workaround for NIM089253 - "TypeError: GPToolDialog() takes at most 1 argument (2 given)
           http://support.esri.com/en/bugs/nimbus/TklNMDg5MjUz
         * Workaround for defaults only refreshing on first run - copy the pyt (and xml docs)
           which forces Arc to reload it every time.
    """
    tmpdir = tempfile.mkdtemp(prefix='toolbox')
    tmpfile = os.path.join(tmpdir,os.path.basename(toolbox))
    docs=glob.glob(toolbox[:-4]+'*.xml')
    shutil.copy(toolbox,tmpdir)
    for doc in docs:shutil.copy(doc,tmpdir)
    try:
        result=pythonaddins.GPToolDialog(tmpfile,tool)
    except TypeError:
        pass
    finally:
        #Give ArcMap time to load the toolbox before it gets cleaned up
        threading.Thread(target=rm, args = (tmpdir,3)).start()
        return None

def rm(d, wait=1):
    time.sleep(wait)
    try: shutil.rmtree(d)
    except: pass

View solution in original post

4 Replies
Luke_Pinner
MVP Regular Contributor

I think ArcGIS might only load the toolbox once to improve performance.  I workaround this by making a temporary copy of the toolbox every time I want to call it.

import os, sys
import glob
import shutil
import tempfile
import threading
import time

import arcpy, pythonaddins

class Button(object):
    # ...
    def onClick(self):
        GPToolDialog('path/to/toolbox.pyt', 'ToolName')

def GPToolDialog(toolbox, tool):
    """
         * Workaround for NIM089253 - "TypeError: GPToolDialog() takes at most 1 argument (2 given)
           http://support.esri.com/en/bugs/nimbus/TklNMDg5MjUz
         * Workaround for defaults only refreshing on first run - copy the pyt (and xml docs)
           which forces Arc to reload it every time.
    """
    tmpdir = tempfile.mkdtemp(prefix='toolbox')
    tmpfile = os.path.join(tmpdir,os.path.basename(toolbox))
    docs=glob.glob(toolbox[:-4]+'*.xml')
    shutil.copy(toolbox,tmpdir)
    for doc in docs:shutil.copy(doc,tmpdir)
    try:
        result=pythonaddins.GPToolDialog(tmpfile,tool)
    except TypeError:
        pass
    finally:
        #Give ArcMap time to load the toolbox before it gets cleaned up
        threading.Thread(target=rm, args = (tmpdir,3)).start()
        return None

def rm(d, wait=1):
    time.sleep(wait)
    try: shutil.rmtree(d)
    except: pass

GraemeBrowning
Occasional Contributor III

I was just coming to the same conclusion i.e. that "ArcGIS might only load the toolbox once", and searching for a workaround to how to load my GPToolDialog with default values read from an ASCII file, after calling it from a Python AddIn tool that selects a feature and writes its attributes to that ASCII file, when I found your post.

Your workaround works for me!

If I have the ArcMap Python window open I see some errors (see below) go by but none stop it working.  I'm just recording the errors here, and not looking for help with them.

Traceback (most recent call last):

  File "C:\Users\Graeme\AppData\Local\ESRI\Desktop10.3\AssemblyCache\{15302DB5-BF1B-4509-B327-85E2E8476653}\WSAAddIn_addin.py", line 82, in onMouseDownMap

    GPToolDialog(PythonTBX, "GrossPollutantTrap")

  File "C:\Users\Graeme\AppData\Local\ESRI\Desktop10.3\AssemblyCache\{15302DB5-BF1B-4509-B327-85E2E8476653}\WSAAddIn_addin.py", line 35, in GPToolDialog

    threading.Thread(target=rm, args = (tmpdir,3)).start()

  File "C:\Python27\ArcGIS10.3\Lib\threading.py", line 687, in __init__

    self.__daemonic = self._set_daemon()

  File "C:\Python27\ArcGIS10.3\Lib\threading.py", line 711, in _set_daemon

    return current_thread().daemon

  File "C:\Python27\ArcGIS10.3\Lib\threading.py", line 1160, in currentThread

    return _active[_get_ident()]

TypeError: GPToolDialog() takes at most 1 argument (2 given)

0 Kudos
Luke_Pinner
MVP Regular Contributor

Hmmm, that's what the "tryexcept TypeError:" handler is supposed to silence, and it does for me on 10.2.2. I remember from GISSE that you're on 10.3.  The bug # I referenced in the code suggests adding `print " "` to the except clause.

0 Kudos
GraemeBrowning
Occasional Contributor III

I tried using

print ""

in place of

pass

in the except clause but it had no effect.

At the moment this is embedded in an application that works so I'm happy to ignore the error.  If I get a chance I'll try and extract a simpler test case and pursue further at another time.

I am using 10.3.1.

0 Kudos