<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Python Toolbox Use Cases - altered, hasBeenValidated, valueAsText in ArcGIS Pro Questions</title>
    <link>https://community.esri.com/t5/arcgis-pro-questions/python-toolbox-use-cases-altered-hasbeenvalidated/m-p/1327127#M72906</link>
    <description>&lt;P&gt;The way I do it is to&amp;nbsp;check if &lt;FONT face="courier new,courier"&gt;parameter.altered and not parameter.hasBeenValidated&lt;/FONT&gt;. From the &lt;A href="https://pro.arcgis.com/en/pro-app/latest/arcpy/geoprocessing_and_python/customizing-tool-behavior-in-a-python-toolbox.htm" target="_self"&gt;help&lt;/A&gt;:&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;P&gt;&lt;STRONG&gt;altered&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;altered&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;is true if the value of a parameter is changed... Once a parameter has been altered,&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;&lt;STRONG&gt;it remains altered&lt;/STRONG&gt;&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;until the user empties (blanks out) the value, in which case it returns to being unaltered.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;BLOCKQUOTE&gt;&lt;P&gt;&lt;STRONG&gt;hasBeenValidated&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;hasBeenValidated&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;is false if a parameter's value has been modified by the user since the last time&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;updateParameters&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;and internal validate were called. Once internal validate has been called, geoprocessing automatically sets&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;hasBeenValidated&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;to true for every parameter.&lt;/P&gt;&lt;P&gt;hasBeenValidated&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;&lt;STRONG&gt;is used to determine whether the user has changed a value since the last call to&lt;/STRONG&gt;&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;updateParameters.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;Re your questions:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;Altered is has the user changed the value (see above) and yes you can have&amp;nbsp;&lt;STRONG&gt;altered&amp;nbsp;and&amp;nbsp;UNvalidated&lt;/STRONG&gt;.&amp;nbsp;&lt;/LI&gt;&lt;LI&gt;After a value is changed, internal (basic ArcGIS) validation happens which doesn't change "&lt;FONT face="courier new,courier"&gt;hasBeenValidated&lt;/FONT&gt;", then &lt;FONT face="courier new,courier"&gt;UpdateParameters&lt;/FONT&gt; is called.&lt;/LI&gt;&lt;LI&gt;&lt;FONT face="courier new,courier"&gt;valueAsText&lt;/FONT&gt;/&lt;FONT face="courier new,courier"&gt;value&lt;/FONT&gt; is if you need to access the actual value of the parameter (as an object or as text) e.g. to check it or to use it for something else - for example to populate a filter list&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Something like:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="python"&gt;  def updateParameters(self):
      """Modify the values and properties of parameters before internal
      validation is performed.  This method is called whenever a parameter
      has been changed."""

      if self.params[0].altered and not self.params[0].hasBeenValidated:
          etc... &lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Sun, 10 Sep 2023 22:13:56 GMT</pubDate>
    <dc:creator>Luke_Pinner</dc:creator>
    <dc:date>2023-09-10T22:13:56Z</dc:date>
    <item>
      <title>Python Toolbox Use Cases - altered, hasBeenValidated, valueAsText</title>
      <link>https://community.esri.com/t5/arcgis-pro-questions/python-toolbox-use-cases-altered-hasbeenvalidated/m-p/1327123#M72905</link>
      <description>&lt;P&gt;1) I've read the docs ( &lt;A href="https://pro.arcgis.com/en/pro-app/latest/arcpy/geoprocessing_and_python/customizing-tool-behavior-in-a-python-toolbox.htm" target="_self"&gt;customize tool behavior&lt;/A&gt; )&lt;/P&gt;&lt;P&gt;2) I've received excellent feedback in a related post ( &lt;A href="https://community.esri.com/t5/python-questions/constructing-the-toolvalidator-class-to-validate/m-p/1277598" target="_self"&gt;related post&lt;/A&gt; )&lt;/P&gt;&lt;P&gt;3) And followed similar workflow examples ( &lt;A href="https://community.esri.com/t5/arcgis-pro-questions/arcpy-parameter-for-arcgis-pro-document/td-p/1039453" target="_self"&gt;Arcpy paramaters example&lt;/A&gt; )&lt;/P&gt;&lt;P&gt;My observation is that people use `&lt;STRONG&gt;param.valueAsText&lt;/STRONG&gt;&amp;nbsp;for some reason as validation that a parameter has been entered.&amp;nbsp; Others mix and match &lt;STRONG&gt;param.altered&lt;/STRONG&gt; for a similiar purpose.&amp;nbsp; While others use &lt;STRONG&gt;hasBeenValidated&lt;/STRONG&gt;.&amp;nbsp; Reposting this example from the ESRI docs -&amp;nbsp;&lt;STRONG&gt;1)&lt;/STRONG&gt; above:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="python"&gt;def updateParameters(self, parameters):
    # Set the default distance threshold to 1/100 of the larger of the width
    #  or height of the extent of the input features.  Do not set if there is no 
    #  input dataset yet, or the user has set a specific distance (Altered is true).
    #
    if parameters[0].valueAsText:
        if not parameters[6].altered:
            extent = arcpy.Describe(parameters[0]).extent
        if extent.width &amp;gt; extent.height:
            parameters[6].value = extent.width / 100
        else:
            parameters[6].value = extent.height / 100

    return&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Why not do this:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="python"&gt;def updateParameters(self, parameters):
    if parameters[0].altered:
        if not parameters[6].altered:
            #continue&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;U&gt;My questions in relation to this example are:&lt;/U&gt;&lt;/P&gt;&lt;P&gt;1. What is the difference between&amp;nbsp;&lt;STRONG&gt;altered&amp;nbsp;&lt;/STRONG&gt;and&amp;nbsp;&lt;STRONG&gt;hasBeenValidated&lt;/STRONG&gt; and can a paramaters be &lt;STRONG&gt;UNaltered&lt;/STRONG&gt;&amp;nbsp;and &lt;STRONG&gt;validated&amp;nbsp;&lt;/STRONG&gt;and&amp;nbsp;&lt;STRONG&gt;altered&amp;nbsp;&lt;/STRONG&gt;and &lt;STRONG&gt;UNvalidated&lt;/STRONG&gt;.&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;2. When does validation occur?&amp;nbsp;&lt;/P&gt;&lt;P&gt;3. Is&amp;nbsp;&lt;STRONG&gt;valueAsText/value&lt;/STRONG&gt; just a syntactically awkward way of checking if a paramater has been set?&amp;nbsp; (I understand we can assign new values with this property)&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;3. when to use&amp;nbsp;&lt;STRONG&gt;value&lt;/STRONG&gt; vs.&amp;nbsp;&lt;STRONG&gt;valueAsText -&amp;nbsp;&lt;/STRONG&gt;i.e.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="python"&gt;if param[0].&amp;lt;value or valueAsText:
    # do something&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;My guess is that&amp;nbsp;&lt;STRONG&gt;valueAsText/value&lt;/STRONG&gt; is way overused and due to sparse documentation people made their Python Toolboxes work by misusing these properties.&amp;nbsp; Hence my attempt to clarify my understanding.&lt;/P&gt;&lt;P&gt;Thanks,&lt;/P&gt;&lt;P&gt;Zach&lt;/P&gt;</description>
      <pubDate>Sun, 10 Sep 2023 18:05:18 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcgis-pro-questions/python-toolbox-use-cases-altered-hasbeenvalidated/m-p/1327123#M72905</guid>
      <dc:creator>ZacharyUhlmann1</dc:creator>
      <dc:date>2023-09-10T18:05:18Z</dc:date>
    </item>
    <item>
      <title>Re: Python Toolbox Use Cases - altered, hasBeenValidated, valueAsText</title>
      <link>https://community.esri.com/t5/arcgis-pro-questions/python-toolbox-use-cases-altered-hasbeenvalidated/m-p/1327127#M72906</link>
      <description>&lt;P&gt;The way I do it is to&amp;nbsp;check if &lt;FONT face="courier new,courier"&gt;parameter.altered and not parameter.hasBeenValidated&lt;/FONT&gt;. From the &lt;A href="https://pro.arcgis.com/en/pro-app/latest/arcpy/geoprocessing_and_python/customizing-tool-behavior-in-a-python-toolbox.htm" target="_self"&gt;help&lt;/A&gt;:&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;P&gt;&lt;STRONG&gt;altered&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;altered&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;is true if the value of a parameter is changed... Once a parameter has been altered,&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;&lt;STRONG&gt;it remains altered&lt;/STRONG&gt;&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;until the user empties (blanks out) the value, in which case it returns to being unaltered.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;BLOCKQUOTE&gt;&lt;P&gt;&lt;STRONG&gt;hasBeenValidated&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;hasBeenValidated&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;is false if a parameter's value has been modified by the user since the last time&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;updateParameters&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;and internal validate were called. Once internal validate has been called, geoprocessing automatically sets&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;hasBeenValidated&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;to true for every parameter.&lt;/P&gt;&lt;P&gt;hasBeenValidated&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;&lt;STRONG&gt;is used to determine whether the user has changed a value since the last call to&lt;/STRONG&gt;&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;updateParameters.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;Re your questions:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;Altered is has the user changed the value (see above) and yes you can have&amp;nbsp;&lt;STRONG&gt;altered&amp;nbsp;and&amp;nbsp;UNvalidated&lt;/STRONG&gt;.&amp;nbsp;&lt;/LI&gt;&lt;LI&gt;After a value is changed, internal (basic ArcGIS) validation happens which doesn't change "&lt;FONT face="courier new,courier"&gt;hasBeenValidated&lt;/FONT&gt;", then &lt;FONT face="courier new,courier"&gt;UpdateParameters&lt;/FONT&gt; is called.&lt;/LI&gt;&lt;LI&gt;&lt;FONT face="courier new,courier"&gt;valueAsText&lt;/FONT&gt;/&lt;FONT face="courier new,courier"&gt;value&lt;/FONT&gt; is if you need to access the actual value of the parameter (as an object or as text) e.g. to check it or to use it for something else - for example to populate a filter list&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Something like:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="python"&gt;  def updateParameters(self):
      """Modify the values and properties of parameters before internal
      validation is performed.  This method is called whenever a parameter
      has been changed."""

      if self.params[0].altered and not self.params[0].hasBeenValidated:
          etc... &lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 10 Sep 2023 22:13:56 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcgis-pro-questions/python-toolbox-use-cases-altered-hasbeenvalidated/m-p/1327127#M72906</guid>
      <dc:creator>Luke_Pinner</dc:creator>
      <dc:date>2023-09-10T22:13:56Z</dc:date>
    </item>
    <item>
      <title>Re: Python Toolbox Use Cases - altered, hasBeenValidated, valueAsText</title>
      <link>https://community.esri.com/t5/arcgis-pro-questions/python-toolbox-use-cases-altered-hasbeenvalidated/m-p/1327535#M72939</link>
      <description>&lt;P&gt;Hi Luke,&lt;/P&gt;&lt;P&gt;I almost tagged you on this post, as you seem to be the Resident Python Toolbox Expert on the forum.&amp;nbsp; That makes...more sense.&amp;nbsp; If you get time (no rush) perhaps you can use my below example as an example to point out anything I did wrong, inefficient, redundant, etc.&amp;nbsp; It's based off of your Python Toolbox sample code chunk on this post -&amp;nbsp;&lt;A href="ttps://community.esri.com/t5/arcgis-pro-questions/arcpy-parameter-for-arcgis-pro-document/td-p/1039453" target="_self"&gt;arcpy-parameter-for-arcgis-pro-document&lt;/A&gt;&amp;nbsp;.&amp;nbsp; There the guy was accessing layouts from a project via arcpy.mp.ArcGISProject(&amp;lt;project_name&amp;gt;). Mine has one extra wrinkle.&amp;nbsp; I am cascading the variable&amp;nbsp;&lt;STRONG&gt;project_name&lt;/STRONG&gt;&amp;nbsp;to &lt;STRONG&gt;map_name&lt;/STRONG&gt; to&amp;nbsp;&lt;STRONG&gt;layer_name,&amp;nbsp;&lt;/STRONG&gt;ultimately updating the CIM of a layer in the &lt;STRONG&gt;execute&amp;nbsp;&lt;/STRONG&gt;method.&amp;nbsp; It works (took awhile).&amp;nbsp;&lt;EM&gt;Note that I am truncating the execute codeblock for brevity. But first here is the toolbox look:&lt;/EM&gt;&lt;/P&gt;&lt;P&gt;&lt;EM&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2023-09-11 172734.jpg" style="width: 400px;"&gt;&lt;img src="https://community.esri.com/t5/image/serverpage/image-id/80386iAF8615CCB7B21973/image-size/medium?v=v2&amp;amp;px=400" role="button" title="Screenshot 2023-09-11 172734.jpg" alt="Screenshot 2023-09-11 172734.jpg" /&gt;&lt;/span&gt;&lt;/EM&gt;&lt;/P&gt;&lt;LI-CODE lang="python"&gt;import pandas as pd

class ToolBox(object):
    def __init__(self):
        '''
        Define the toolbox (name of the toolbox is name of .pyt file).
        '''
        self.label = "Color Ramp Toolbox"
        self.alias = "Color Ramp Toolbox"
        self.tools = [color_ramp_from_csv]
class color_ramp_from_csv(object):
    '''
    classifies color ramp from csv.  Note that user must classify color ramp simply with number \
    of classes initially prior to running
    '''

    def __init__(self):
        self.label = "format_color_ramp"
        self.description = "specify breaks, colors and labels for color ramps of rasters"
        self.canRunInBackground = False

    def getParameterInfo(self):
        '''
        Define parameter defitions
        '''
        param0 = arcpy.Parameter(
            displayName="Current Pro-Document",
            name="currentProDocument",
            datatype="GPBoolean",
            parameterType="Optional",
            direction="Input")

        param1 = arcpy.Parameter(
            displayName="Other Pro-Document",
            name="otherProDocument",
            datatype="DEFile",
            parameterType="Optional",
            direction="Input")
        param1.filter.list = ['aprx']
        param2 = arcpy.Parameter(
            displayName="map",
            name="map",
            datatype="GPString",
            parameterType="Required",
            direction="Input")
        param3 = arcpy.Parameter(
            displayName="layer",
            name="layer",
            datatype="GPString",
            parameterType="Required",
            direction="Input")
        parameters = [param0,param1,param2,param3]
        return parameters
    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.
        '''
        if parameters[1].altered and not parameters[1].hasBeenValidated:
            parameters[0].value=False
            parameters[2].value=None
            parameters[2].filter.list=[]
            prodoc = parameters[1].valueAsText
            prodoc_selected = True
        elif parameters[0].altered and not parameters[0].hasBeenValidated:
            parameters[1].value=None
            parameters[2].value=None
            parameters[2].filter.list=[]
            prodoc='current'
            prodoc_selected=True
        else:
            prodoc_selected  = False
        if prodoc_selected:
            project=arcpy.mp.ArcGISProject(prodoc)
            map_list = [m.name for m in project.listMaps()]
            parameters[2].value=None
            parameters[2].filter.list=map_list
            parameters[3].value = None
            parameters[3].filter.list = []
        if parameters[2].altered and not parameters[2].hasBeenValidated:
            if parameters[0].value is not None:
                prodoc = 'current'
            elif parameters[1].value is not None:
                prodoc = parameters[1].valueAsText
            project = arcpy.mp.ArcGISProject(prodoc)
            map_name = parameters[2].valueAsText
            map_object = project.listMaps(map_name)[0]
            layer_list = [l.name for l in map_object.listLayers()]
            parameters[3].filter.list=layer_list
        return parameters

    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."""
        if parameters[0].value is not None:
            prodoc = 'current'
        elif parameters[1].value is not None:
            prodoc = parameters[1].valueAsText
        project_name=prodoc
        layer_name = parameters[3].valueAsText
        map_name = parameters[2].valueAsText

        p = arcpy.mp.ArcGISProject(project_name)
        m = p.listMaps(map_name)[0]
        l = m.listLayers(layer_name)[0]&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;As I said, it functions well but perhaps I missed or misused some conditions in my&amp;nbsp;&lt;STRONG&gt;if&amp;nbsp;&lt;/STRONG&gt;statements.&amp;nbsp; I understand that&amp;nbsp;&lt;STRONG&gt;altered&lt;/STRONG&gt; property is re-assigned every time a parameter is changed and that&amp;nbsp;&lt;STRONG&gt;hasBeenValidated&lt;/STRONG&gt; relates to non-internal ArcGIS validation related to&amp;nbsp;&lt;STRONG&gt;updateParameters&lt;/STRONG&gt; method.&amp;nbsp; However I still don't understand WHEN&amp;nbsp;&lt;STRONG&gt;hasBeenValidated&amp;nbsp;&lt;/STRONG&gt;is checked.&amp;nbsp; ex) Drop down, select parameter1,&amp;nbsp;&lt;STRONG&gt;altered&lt;/STRONG&gt; is assigned but nothing is validated?&amp;nbsp; So when does validation occur?&lt;/P&gt;&lt;P&gt;In regards to the&amp;nbsp;&lt;STRONG&gt;value&amp;nbsp;&lt;/STRONG&gt;and&amp;nbsp;&lt;STRONG&gt;valueAsText&lt;/STRONG&gt; confusion, it seems that there are loads of examples of people using it INSTEAD OF&amp;nbsp;&lt;STRONG&gt;hasBeenValidated&amp;nbsp;&lt;/STRONG&gt;or &lt;STRONG&gt;altered.&lt;/STRONG&gt;&amp;nbsp; For instance the OP in the post I referenced above, does this (line 44):&lt;/P&gt;&lt;LI-CODE lang="python"&gt; def updateParameters(self, parameters):
        if parameters[0].value:
            p0Val = parameters[0].valueAsText&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;Couldn't it be&lt;/P&gt;&lt;LI-CODE lang="python"&gt; def updateParameters(self, parameters):
        if parameters[0].altered:
            p0Val = parameters[0].valueAsText&lt;/LI-CODE&gt;&lt;P&gt;?&amp;nbsp; &amp;nbsp;Thanks for sharing your knowledge...&lt;/P&gt;&lt;P&gt;Zach&lt;/P&gt;</description>
      <pubDate>Mon, 11 Sep 2023 23:29:30 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcgis-pro-questions/python-toolbox-use-cases-altered-hasbeenvalidated/m-p/1327535#M72939</guid>
      <dc:creator>ZacharyUhlmann1</dc:creator>
      <dc:date>2023-09-11T23:29:30Z</dc:date>
    </item>
  </channel>
</rss>

