Can someone tell me why this python toolbox is throwing a "parameters need repair" error?

765
7
Jump to solution
09-17-2021 01:49 PM
EricEagle
Occasional Contributor III

Unfortunately, programming python toolboxes is not very well documented by Esri.  I can't find any good examples anywhere of what a fully, completed toolbox with validation and source code should look like.  It also seems like "parameters" and "messages" behave as magic arcpy variables that don't need to be expressly instantiated; I'm having trouble finding explicit guidance/documentation on that.

 

Either way, could someone who has done this take a look at my code and help me understand why it's failing?

The validation code works just fine, but every time I run it, it yields the somewhat cryptic error 000820: The parameters need repair.

 

 

 

import arcpy

class Toolbox(object):
    def __init__(self):
        self.label = "ToolboxTest"
        self.alias = ""
        self.tools = [DummyTool]


class DummyTool(object):
    def __init__(self):
        self.label = "DummyTool"
        self.description = "A dummy tool"
        self.canRunInBackground = False

    def getParameterInfo(self):
        p = arcpy.mp.ArcGISProject('CURRENT')
        m = p.activeMap

        param0 = arcpy.Parameter(
            displayName="Choice One",
            name="input_choice_1",
            datatype="GPLayer",
            parameterType="Required",
            direction="Input"
        )

        poly_list = [] # list only polygon feature layers
        for lyr in m.listLayers():
            desc = arcpy.Describe(lyr)
            if desc.dataType == "FeatureLayer":
                if desc.shapeType == "Polygon":
                    poly_list.append(lyr.name)
        param0.filter.type = "ValueList"
        param0.filter.list = poly_list

        params = [param0]
        return params

    def isLicensed(self):
        return True

    def updateParameters(self, parameters):
        pass

    def updateMessages(self, parameters):
        return True

    def execute(self, parameters, messages):
        # All I want to do here is just access
        # the parameter value and report some
        # facts about it for testing
        self.updateParameters(parameters)
        
        lyr = parameters[0].value
        d = arcpy.Describe(lyr)
        arcpy.AddMessage(d.name)
        arcpy.AddMessage(d.dataType)
        arcpy.AddMessage(d.shapeType)

 

 

 

Tags (2)
0 Kudos
2 Solutions

Accepted Solutions
DonMorrison1
Occasional Contributor II

I was able to get it to work by changing the data type of the input variable from GPLayer to GPString.  I have no idea why, but this is typical with toolbox programming in that you just have to keep trying things until you find something that works.  I guess in a way it makes sense since you really are just setting it to a string and not a layer object. On line 28 you also have to initialize the variable (eg poly_list = []). Good luck on your tool, the fun is just beginning ;)

View solution in original post

JohannesLindner
Regular Contributor

Sorry, I should have tested it...

It works with datatype GPFeatureLayer and not setting the filter type.

I edited the post above accordingly for future reference.


Have a great day!
Johannes

View solution in original post

7 Replies
DonMorrison1
Occasional Contributor II

I was able to get it to work by changing the data type of the input variable from GPLayer to GPString.  I have no idea why, but this is typical with toolbox programming in that you just have to keep trying things until you find something that works.  I guess in a way it makes sense since you really are just setting it to a string and not a layer object. On line 28 you also have to initialize the variable (eg poly_list = []). Good luck on your tool, the fun is just beginning ;)

View solution in original post

EricEagle
Occasional Contributor III

Hi Don, your suggestion worked, (and I did instantiate the list, I just failed to put it in the example) but this part:

this is typical with toolbox programming in that you just have to keep trying things until you find something that works

is what is so frustrating.... show me the book I'll buy it, or tell me which class to attend and I'll register for it - it's the poking around in the dark that is so maddening!!

 

Still this did work so thanks :)

0 Kudos
JohannesLindner
Regular Contributor

You could do it like this:

 

class DummyTool
    def getParameterInfo(self):
        param0 = arcpy.Parameter(
            displayName="Choice One",
            name="input_choice_1",
            datatype="GPFeatureLayer",
            parameterType="Required",
            direction="Input"
        )
        param0.filter.list = ["Polygon"]

        params = [param0]
        return params

 


Have a great day!
Johannes
EricEagle
Occasional Contributor III

Hi @JohannesLindner that just gives me one option in the parameter drop-down called "Polygon."  What I'm looking for is a filter list of only the Polygon type feature layers

0 Kudos
JohannesLindner
Regular Contributor

Sorry, I should have tested it...

It works with datatype GPFeatureLayer and not setting the filter type.

I edited the post above accordingly for future reference.


Have a great day!
Johannes

View solution in original post

HannesZiegler
Esri Contributor

Hi EricEagle,

 

There is a bug in your code at line 28, where you did not set polylist to any value. Set this to an empty list and your code works for me.

 

 

poly_list = []  # list only polygon feature layers

 

 

 

Alternative Solution

*Edit* JohannesLinder beat me to this solution while I was writing this out =D. I'll leave it below here anyways:

You can accomplish what you are trying to do more concisely by changing dataType to "GPFeatureLayer". You can then choose a "Featureclass" filter type. Note that the default filter type for GPFeatureLayer is "Featureclass", so there is actually no need to explicitly specify this as in the example below. You can safely omit the line param0.filter.type = "Featureclass". 

 

 

 

 

param0 = arcpy.Parameter(
            displayName="Choice One",
            name="input_choice_1",
            datatype="GPFeatureLayer",
            parameterType="Required",
            direction="Input"
        )
param0.filter.type = "Featureclass"
param0.filter.list = ["Polygon"]

 

 

 

Here it is in action:

HannesZiegler_0-1632153766104.png

Also note that you won't be able to do the same with the GPLayer data type. The reason GPLayer doesn't have a data filter type is because GPLayer is for any Layer (which includes tables, raster, etc.) and GPFeatureLayer is explicitly only the subset of Layers with features (Feature Class, Shapefile).

More Info

You can find this in the doc here.

There's an example of a fully fleshed out Python toolbox here, though it doesn't cover your exact case (it'd be difficult to cover every case in the doc).

Also, check out recent presentations on creating toolboxes here, where parts of this topic are covered (haven't watched this one in a while, it might not cover your exact use case but might provide some more insights).

Hope this helps!

EricEagle
Occasional Contributor III

@HannesZieglerVery helpful - thanks for all the resources.  In the original code, I did instantiate the poly_list variable, but I wrote this on another network and messed up when retyping it here.

I really like the ability that toolboxes give me to maintain 100% of my code in git and not having to worry about updating/moving around .tbx files.  It's not practical for every case but feels like a lot cleaner way to work.

0 Kudos