Show a custom tool's description in the tool search results of the Geoprocessing pane

1250
6
09-20-2021 01:58 AM
MattHowe
Occasional Contributor

I have a custom toolbox (.tbx) added to my favourites and so to find a specific tool within the toolbox, I 'd search (Tools > Favorites > [Type tool name] and then hopefully see the description of the tool in the results display but doesn't seem to display the metadata. Let's say I have a tool called 'Create Raster Extent Polygon' and I enter 'extent' in the search to get the result I need. It doesn't seem to display the tool description even though I have added information in all of the fields in the metadata page of the custom tool. Is there a way to show the tool description for custom tools similar to the inbuilt Esri ones? (See image for the custom tool example and the Esri tool that shows a nice tool description).

ToolDesc.PNG

0 Kudos
6 Replies
David_Brooks
MVP Regular Contributor

@MattHowe , do you know, that's so strange, i've been trying to work this one out, but it might be a bug. If you create a model or script in ArcMap, and edit the Summary field in the metadata, the description appears in tools and models. Also, all my old models made in ArcMap with a summary filled out display correctly in Pro. But i've just tried to make a new model/script in both ArcMap and Pro and none of the summaries appear below the tool in the search menu in Pro, but they appear in ArcMap in the Toolhelp sidebar.


David
..Maps with no limits..
JohannesLindner
MVP Frequent Contributor

It works for me...

JohannesLindner_0-1632132194664.png

 


Have a great day!
Johannes
0 Kudos
David_Brooks
MVP Regular Contributor

@JohannesLindner which version of Pro are you using, and which Metadata standard?

@MattHowe have you tried a brand new toolbox in Pro? Just wandering if you're using a toolbox previously created in ArcMap?


David
..Maps with no limits..
0 Kudos
David_Brooks
MVP Regular Contributor

Scratch that, i just tried with a brand new toolbox, created a blank script and edited the Summary in item description, and nothing.


David
..Maps with no limits..
0 Kudos
MattHowe
Occasional Contributor

Yeah I tried exactly the same thing and the description didn't show in the search results. Interested to see what @JohannesLindner reports back with re the metadata standard.

0 Kudos
JohannesLindner
MVP Frequent Contributor

Sooooo....

I use the default metadata option, which seems to be "Item description".

JohannesLindner_0-1632138532990.png

 

Like you, I just tried creating a new python toolbox, editing the metadata of the default tool and searching for that tool. Didn't work:

JohannesLindner_1-1632140774937.png

 

 

Then I remembered: For my work, I programmed quite a few tools (e.g. input forms). Because the tools were in constant development, I didn't want to manually edit the metadata each time I changed some parameters. So I created a custom Parameter class and gave the Tool class some extra attributes and wrote a function that creates the tool help files automatically.

 

def Parameter(*args, **kwargs):
    """Wrapper for `arcpy.Parameter` which allows for a custom attribute `description`.

    I can't just inherit from `arcpy.Parameter`, because arcpy is a wrapper for C classes and when I tried, it didn't work as expected. Using a wrapper class and forwarding all the methods and attributes would be too cumbersome. That's why this is a function that returns an `arcpy.Parameter`, using python's dynamic typing to add a custom attribute (which does noting in the underlying C code).
    """
    try:
        desc = kwargs["description"]
        del kwargs["description"]
    except KeyError:
        desc = ""
    p = arcpy.Parameter(*args, **kwargs)
    p.description = desc 
    return p

 

 

 

# Toolbox.pyt
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.canRunInBackground = False

        # attributes for automatically creating the metadata
        self.description = "This is a test tool."
        self.usage = "You can't do anything with this tool."
        self.search_keys = ["test", "another_tag"]

    def getParameterInfo(self):
        """Define parameter definitions"""
        params = [
##            arcpy.Parameter(name="parameter", displayName="Parameter", datatype="GPString", parameterType="Optional", direction="Input"),
            Parameter(name="parameter", displayName="Parameter", datatype="GPString", parameterType="Optional", direction="Input", description="This parameter does nothing."),
            ]
        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




def create_tool_help_files():
    import os
    import datetime
    import xml.etree.cElementTree as ET

    today = datetime.datetime.now().strftime("%Y%m%d")

    for tool in Toolbox().tools:
        tool_instance = tool()

        metadata = ET.Element("metadata")
        dataIdInfo = ET.SubElement(metadata, "dataIdInfo")

        # ESRI metadata
        esri = ET.SubElement(metadata, "Esri")
        ET.SubElement(esri, "CreaDate").text = today
        ET.SubElement(esri, "CreaTime").text = today
        ET.SubElement(esri, "ArcGISFormat").text = "1.0"
        ET.SubElement(esri, "SyncOnce").text = "TRUE"
        ET.SubElement(esri, "ModDate").text = today
        ET.SubElement(esri, "ModTime").text = today
        scaleRange = ET.SubElement(esri, "scaleRange")
        ET.SubElement(scaleRange, "minScale").text = "150000000"
        ET.SubElement(scaleRange, "maxScale").text = "5000"

        # tool metadata
        toolMeta = ET.SubElement(metadata,
            "tool",
            xmlns = "",
            name = tool.__name__,
            displayname = tool_instance.label,
            toolboxalias = "")
        ET.SubElement(toolMeta, "arcToolboxHelpPath").text = "c:\\program files\\arcgis\\pro\\Resources\\Help\\gp"

        # Tags
        searchKeys = ET.SubElement(dataIdInfo, "searchKeys")
        tags = getattr(tool_instance, "search_keys", [])
        for t in tags:
            ET.SubElement(searchKeys, "keyword").text = str(t)
        # Summary und Usage
        summary = ET.SubElement(toolMeta, "summary").text = getattr(tool_instance, "description", "")
        usage = ET.SubElement(toolMeta, "usage").text = getattr(tool_instance, "usage", "")

        # parameter metadata
        paramMeta = ET.SubElement(toolMeta, "parameters")
        parameters = tool_instance.getParameterInfo()
        if parameters is None:
            parameters = []
        for p in parameters:
            param = ET.SubElement(paramMeta,
                "param",
                name = getattr(p, "name", ""),
                displayname = getattr(p, "displayName", ""),
                type = getattr(p, "parameterType", ""),
                direction = getattr(p, "direction", ""),
                datatype = getattr(p, "datatype", ""),
                expression = getattr(p, "name", ""))
            dialogReference = ET.SubElement(param, "dialogReference").text = getattr(p, "description", "n/a")

        # Credit
        idCredit = ET.SubElement(dataIdInfo, "idCredit").text = getattr(tool, "credit", "My employer\nMy Name\nMy mail address")

        # some more general metadata
        idCitation = ET.SubElement(dataIdInfo, "idCitation")
        resTitle = ET.SubElement(idCitation, "resTitle").text = getattr(tool, "label", "")
        distInfo = ET.SubElement(metadata, "distInfo")
        distributor = ET.SubElement(distInfo, "distributor")
        distorFormat = ET.SubElement(distributor, "distorFormat")
        ET.SubElement(distorFormat, "formatName").text = "ArcToolbox Tool"
        mdHrLv = ET.SubElement(metadata, "mdHrLv")
        ET.SubElement(mdHrLv, "ScopeCd ", value = "005")
        mdDateSt = ET.SubElement(metadata, "mdDateSt",Sync="TRUE").text = today

        # write XML
        directory = os.path.dirname(__file__)
        toolbox_label = os.path.basename(__file__).replace(".pyt", "")
        ET.ElementTree(metadata).write("{}.{}.pyt.xml".format(os.path.join(directory, toolbox_label), tool.__name__))


# execute the file from IDE to automatically create the tool metadata files
if __name__ == "__main__":
    create_tool_help_files()

 

 

And it works:

JohannesLindner_2-1632142830844.png

 

Please don't ask me why...


Have a great day!
Johannes
0 Kudos