<?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: Programmatically switch metadata source for a given layer in Python Questions</title>
    <link>https://community.esri.com/t5/python-questions/programmatically-switch-metadata-source-for-a/m-p/1575568#M73558</link>
    <description>&lt;P&gt;Actually, speaking of untested options and building on this:&lt;/P&gt;&lt;P&gt;I missed that&amp;nbsp;&lt;STRONG&gt;useSourceMetadata&lt;/STRONG&gt; property.&amp;nbsp; If you can set that on an active layer, then theoretically you should then be able to export that layer from the map as a LYRX file, right?&lt;/P&gt;&lt;P&gt;If the &lt;U&gt;untested&lt;/U&gt; assumptions above are correct (and if the useSourceMetadata property persists in an LYRX file), then theoretically you could run the code to import the data into a dummy map file, then re-export it back out as a LYRX file.&lt;/P&gt;&lt;P&gt;Try running Hayden's code, followed by calling &lt;A href="https://pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/save-to-layer-file.htm" target="_blank" rel="noopener"&gt;"Save Layer to File (Data Management)"&lt;/A&gt;&amp;nbsp; and passing it the resulting map layer.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;If we're both right, and a with a little luck, the end result would hopefully be a LYRX file that points to the source metadata.&amp;nbsp; I likely won't have time to test this for a few days, at least, but if either you is able before then, definitely report back with what you found.&lt;/P&gt;</description>
    <pubDate>Tue, 14 Jan 2025 19:54:49 GMT</pubDate>
    <dc:creator>MErikReedAugusta</dc:creator>
    <dc:date>2025-01-14T19:54:49Z</dc:date>
    <item>
      <title>Programmatically switch metadata source for a given layer</title>
      <link>https://community.esri.com/t5/python-questions/programmatically-switch-metadata-source-for-a/m-p/1575335#M73543</link>
      <description>&lt;P&gt;I have a simple question - I'd like to change the value of this dropdown box programmatically (in Python) for a large number of layers in a large number of layer files.&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="GIS_Weasel_0-1736866915379.png" style="width: 400px;"&gt;&lt;img src="https://community.esri.com/t5/image/serverpage/image-id/123329iAFF86EDBE3FC05AE/image-size/medium?v=v2&amp;amp;px=400" role="button" title="GIS_Weasel_0-1736866915379.png" alt="GIS_Weasel_0-1736866915379.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;The default setting for loading .lyr files into pro sets this to '&lt;STRONG&gt;Layer has its own metadata&lt;/STRONG&gt;'. This is also the case when loading programmatically via &lt;A href="https://pro.arcgis.com/en/pro-app/latest/arcpy/mapping/layerfile-class.htm" target="_self"&gt;LayerFile("uri-to-layer.lyr")&lt;/A&gt; I want to run a Python script to reset this to '&lt;STRONG&gt;Show metadata from data source (read-only)&lt;/STRONG&gt;', as is possible in the Pro UI.&lt;/P&gt;&lt;P&gt;All of the methods and mechanisms in the &lt;A href="https://pro.arcgis.com/en/pro-app/latest/arcpy/metadata/metadata-class.htm" target="_self"&gt;Metadata class&lt;/A&gt; seem to be based around the assumption I want to do something with metadata for this layer. I do not! I want to make it read-only and show users the metadata stored in our spatial database. But, &lt;EM&gt;Metadata.isReadOnly is&lt;/EM&gt; &lt;EM&gt;itself read only!&lt;/EM&gt;&lt;/P&gt;&lt;P&gt;I then intend to re-save them as .lyrx files.&lt;/P&gt;&lt;P&gt;Any suggestions welcome.&lt;/P&gt;</description>
      <pubDate>Tue, 14 Jan 2025 15:14:48 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/programmatically-switch-metadata-source-for-a/m-p/1575335#M73543</guid>
      <dc:creator>GIS_Weasel</dc:creator>
      <dc:date>2025-01-14T15:14:48Z</dc:date>
    </item>
    <item>
      <title>Re: Programmatically switch metadata source for a given layer</title>
      <link>https://community.esri.com/t5/python-questions/programmatically-switch-metadata-source-for-a/m-p/1575352#M73546</link>
      <description>&lt;P&gt;From my reading, this doesn't look to be currently possible.&amp;nbsp; You could&amp;nbsp;&lt;EM&gt;import&lt;/EM&gt; Metadata for a fossilized copy of the Metadata at the time you created the LYRX files, but that's the closest I think you can get.&amp;nbsp; Normally, this level of advanced editing is hiding in the CIM, but that seems just to point back to the regular Metadata class object, as you've found.&lt;/P&gt;&lt;P&gt;This probably warrants a post on the &lt;A href="https://community.esri.com/t5/python-ideas/idb-p/python-ideas" target="_blank" rel="noopener"&gt;Python Ideas Board&lt;/A&gt;.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;There's also the larger question, though, of the use-case here.&amp;nbsp; Is this something you'll have to regularly do and update, hence the desire for automation?&amp;nbsp; Or is it a one-and-done operation for most/all of the sources?&amp;nbsp; If it's the latter, you're probably better off setting aside time for the obnoxious labor of doing it manually.&lt;/P&gt;</description>
      <pubDate>Tue, 14 Jan 2025 15:37:03 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/programmatically-switch-metadata-source-for-a/m-p/1575352#M73546</guid>
      <dc:creator>MErikReedAugusta</dc:creator>
      <dc:date>2025-01-14T15:37:03Z</dc:date>
    </item>
    <item>
      <title>Re: Programmatically switch metadata source for a given layer</title>
      <link>https://community.esri.com/t5/python-questions/programmatically-switch-metadata-source-for-a/m-p/1575439#M73552</link>
      <description>&lt;P&gt;I believe you can kinda get around this by directly modifying the CIM definition of the layer once you import it:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="python"&gt;from pathlib import Path

from arcpy.mp import LayerFile, ArcGISProject
from arcpy._mp import Map, Layer # Hidden mp types

from arcpy.cim import CIMDefinition # All CIM types support the useSourceMetadata property

def get_map(project: ArcGISProject, map_name: str) -&amp;gt; Map:
    return project.listMaps(map_name)[0]

def set_metadata_readonly(project: ArcGISProject, layerfiles: list[str], output_map: str | None=None):
    """Adds layerfiles to a map then sets the useSourceMetadata property to True.
    
    Parameters:
        project (ArcGISProject): The project to add the layers to.
        layerfiles (list[str]): The list of layerfiles to add to the map.
        output_map (Optional[str]): The name of the map to add the layers to. (default is first map in project)
    """
    for layer_path in layerfiles:
        # Set Up LayerFile object
        lyrpath =  Path(layer_path)
        lyr = LayerFile(str(lyrpath))
        
        # Add Layer to top of map
        target_map = get_map(project, output_map)
        target_map.addLayer(lyr, add_position="TOP")
        
        # Get the new layer
        new_layer: Layer = target_map.listLayers()[0]
        
        # Get CIM definition for new layer
        new_layer_cim: CIMDefinition = new_layer.getDefinition("V3")
        
        # Set CIM useSourceMetadata to True
        new_layer_cim.useSourceMetadata = True
        
        # Update CIM definition
        new_layer.setDefinition(new_layer_cim)
            
def main():
    ## Implement your script here
    return

if __name__ == "__main__":
    main()&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;This won't set that property in the layerfile itself, but it will make sure that once the layer is added to a target map/project that the &lt;STRONG&gt;useSourceMetadata&lt;/STRONG&gt; CIM property is set to &lt;STRONG&gt;True&lt;/STRONG&gt;.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;NOTE:&lt;/P&gt;&lt;P&gt;You will need to .save() the ArcGISProject in your implementation, or the edits will be dropped.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;This is also untested, so if you still can't get it to work by directly modifying the CIM definition of the layer, creating an Ideas post as per &lt;a href="https://community.esri.com/t5/user/viewprofilepage/user-id/569244"&gt;@MErikReedAugusta&lt;/a&gt; 's suggestion is the best bet.&lt;/P&gt;</description>
      <pubDate>Tue, 14 Jan 2025 16:54:58 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/programmatically-switch-metadata-source-for-a/m-p/1575439#M73552</guid>
      <dc:creator>HaydenWelch</dc:creator>
      <dc:date>2025-01-14T16:54:58Z</dc:date>
    </item>
    <item>
      <title>Re: Programmatically switch metadata source for a given layer</title>
      <link>https://community.esri.com/t5/python-questions/programmatically-switch-metadata-source-for-a/m-p/1575568#M73558</link>
      <description>&lt;P&gt;Actually, speaking of untested options and building on this:&lt;/P&gt;&lt;P&gt;I missed that&amp;nbsp;&lt;STRONG&gt;useSourceMetadata&lt;/STRONG&gt; property.&amp;nbsp; If you can set that on an active layer, then theoretically you should then be able to export that layer from the map as a LYRX file, right?&lt;/P&gt;&lt;P&gt;If the &lt;U&gt;untested&lt;/U&gt; assumptions above are correct (and if the useSourceMetadata property persists in an LYRX file), then theoretically you could run the code to import the data into a dummy map file, then re-export it back out as a LYRX file.&lt;/P&gt;&lt;P&gt;Try running Hayden's code, followed by calling &lt;A href="https://pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/save-to-layer-file.htm" target="_blank" rel="noopener"&gt;"Save Layer to File (Data Management)"&lt;/A&gt;&amp;nbsp; and passing it the resulting map layer.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;If we're both right, and a with a little luck, the end result would hopefully be a LYRX file that points to the source metadata.&amp;nbsp; I likely won't have time to test this for a few days, at least, but if either you is able before then, definitely report back with what you found.&lt;/P&gt;</description>
      <pubDate>Tue, 14 Jan 2025 19:54:49 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/programmatically-switch-metadata-source-for-a/m-p/1575568#M73558</guid>
      <dc:creator>MErikReedAugusta</dc:creator>
      <dc:date>2025-01-14T19:54:49Z</dc:date>
    </item>
    <item>
      <title>Re: Programmatically switch metadata source for a given layer</title>
      <link>https://community.esri.com/t5/python-questions/programmatically-switch-metadata-source-for-a/m-p/1575740#M73563</link>
      <description>&lt;P&gt;Thanks lads. CIM was the solution.&lt;/P&gt;&lt;P&gt;I just need one and done on this, but digging through group layers in several hundred files wasn't especially appealing!&lt;/P&gt;&lt;P&gt;Included a functional example below (no, it's not pretty, but it works).&lt;/P&gt;&lt;LI-CODE lang="python"&gt;# Script to resave lyr files as lyrx
# Plan:
# Send a folder location
# Walk through each folder and open lyr file (into new map? Or reuse a single map?)
# Modify to use metadata from source
# Save lyrx with same name in same folder structrure

# https://pro.arcgis.com/en/pro-app/latest/arcpy/data-access/walk.htm
# https://pro.arcgis.com/en/pro-app/latest/arcpy/mapping/python-cim-access.htm
# https://pro.arcgis.com/en/pro-app/latest/arcpy/mapping/layer-class.htm
# https://pro.arcgis.com/en/pro-app/latest/arcpy/metadata/metadata-class.htm

import arcpy
import logging
import os
from arcpy._mp import Layer # Hidden mp types
from arcpy.cim import CIMDefinition # All CIM types support the useSourceMetadata property

workspace = "H:/Data/ESRI"
layerfiles = []
projectLocation = r'C:\Users\user\Documents\ArcGIS\Projects\MyProject\MyProject.aprx'
mapName = "Map"
outputLocation = r'C:\Users\user\Desktop\Layerfiles'

# Configure the logging system
logging.basicConfig(
    filename = os.path.join(outputLocation, "updateLyrsToLyrx.log"),
    level = logging.DEBUG,
    format = "%(asctime)s - %(levelname)s - %(message)s"
)

# Recursive function to step through group layers
def updateMetadataForLayer(layer: Layer):

   # dump to log
   logging.info("updateMetadataForLayer: " + layer.name)

   # Recurse through groups
   if layer.isGroupLayer:
      for subLayer in layer.listLayers():
         updateMetadataForLayer(subLayer)
   
   # Get CIM definition for new layer
   new_layer_cim: CIMDefinition = layer.getDefinition("V3")
   
   # Set CIM useSourceMetadata to True
   new_layer_cim.useSourceMetadata = True
   
   # Update CIM definition
   layer.setDefinition(new_layer_cim)

# Main entry point, uses global variables
def updateLyrsToLyrx():

   ## Walk the directory to find all layer files
   walk = arcpy.da.Walk(workspace, topdown=True)

   # Load a project
   p = arcpy.mp.ArcGISProject(projectLocation)

   # Use the default "Map"
   map = p.listMaps(mapName)[0]

   for dirpath, dirnames, filenames in walk:

      for filename in filenames:

         if (filename.find(".lyr") != -1) and (filename.find(".lyrx") == -1): # Only operate on layer files, excluding lyrx

            # full filename
            layerFilePath = os.path.join(dirpath, filename)
            
            # dump to log
            logging.info("Found: " + layerFilePath)

            # Add this layer to the map
            lyrFile = arcpy.mp.LayerFile(layerFilePath)
            
            # Retain the list
            list_of_added_maplayers = map.addLayer(lyrFile)
            
            # Loop through every added layers, catch errors and log failures
            for added_layer in list_of_added_maplayers:
               try:
                  updateMetadataForLayer(added_layer)
               except:
                  # Log &amp;amp; fall through - save layer as lyrx anyway - check errored files later
                  logging.error('Unable to update metadata for: ' + added_layer.name)

            # Grab the first, or root, layer
            firstLayer = list_of_added_maplayers[0]

            # subfolder path - trim the workspace
            folderPath = os.path.dirname(layerFilePath[len(workspace):])

            # find the filename
            filename = os.path.splitext(os.path.basename(layerFilePath))[0]

            # new output location
            outputFolderPath = os.path.join(outputLocation + folderPath)

            # create output folders if necessary
            os.makedirs(outputFolderPath, exist_ok=True)

            # Now we've updated the layer, flaky save a copy as lyrx (lol)
            firstLayer.saveACopy(os.path.join(outputFolderPath, filename + ".lyrx"))

def main():
   ## Implement your script here
   updateLyrsToLyrx()
   return

if __name__ == "__main__":
   main()&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Again, thanks for taking the time to reply. Much appreciated &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 15 Jan 2025 11:54:29 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/programmatically-switch-metadata-source-for-a/m-p/1575740#M73563</guid>
      <dc:creator>GIS_Weasel</dc:creator>
      <dc:date>2025-01-15T11:54:29Z</dc:date>
    </item>
  </channel>
</rss>

