I have had this never-ending question regarding how to run a Python Script to make updates to Versioned data.
How can I enter an Edit Session, on a pre-existing version, complete the edit session, review the changes, then reconcile and post WITHOUT causing a schema lock.
For some background, the below script is not in it's entirety:
I have created a database connection that is pointing to the intended, pre-existing version. The update cursor reads and updates a feature class using the above database connection. The update cursor completes successfully, updating correctly.
It is intended that the user will then manually review the changes, if the changes are good, reconcile and post. If bad, delete the version (I need a better process for this as well).
The Problem:
If the user enters an ArcMap Editor Toolbar Edit Session post update, checks everything, reconciles and posts. It works, no locks. Then, if you run the tool again, SystemError: error return without exception set. If I go to the Version Manager to view current locks, there is a lock on that version even after successful rec/post.
How does one prevent this lock from occurring. The python editing process is not documented in depth enough, and does not touch on how the delta tables are affected (I have tried to research the ArcObjects docs, which are mostly copied and pasted into arcpy). Why would I have schema locks if I am editing in one toolset vs. the other, but they're taking place after operations? I have tried many workarounds, numerous times, yet I am clearly missing something.
<SPAN class="comment token">## Editor Class</SPAN>
<SPAN class="string token">"""
https://gis.stackexchange.com/a/158627
"""</SPAN>
<SPAN class="keyword token">def</SPAN> <SPAN class="token function">find_ws</SPAN><SPAN class="punctuation token">(</SPAN>path<SPAN class="punctuation token">,</SPAN> ws_type<SPAN class="operator token">=</SPAN><SPAN class="string token">''</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN>
<SPAN class="string token">"""finds a valid workspace path for an arcpy.da.Editor() Session
Required:
path -- path to features or workspace
Optional:
ws_type -- option to find specific workspace type (FileSystem|LocalDatabase|RemoteDatabase)
"""</SPAN>
<SPAN class="comment token"># try original path first</SPAN>
<SPAN class="keyword token">if</SPAN> os<SPAN class="punctuation token">.</SPAN>sep <SPAN class="operator token">not</SPAN> <SPAN class="keyword token">in</SPAN> path<SPAN class="punctuation token">:</SPAN>
path <SPAN class="operator token">=</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>Describe<SPAN class="punctuation token">(</SPAN>path<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">.</SPAN>catalogPath
desc <SPAN class="operator token">=</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>Describe<SPAN class="punctuation token">(</SPAN>path<SPAN class="punctuation token">)</SPAN>
<SPAN class="keyword token">if</SPAN> hasattr<SPAN class="punctuation token">(</SPAN>desc<SPAN class="punctuation token">,</SPAN> <SPAN class="string token">'workspaceType'</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN>
<SPAN class="keyword token">if</SPAN> ws_type <SPAN class="operator token">and</SPAN> ws_type <SPAN class="operator token">==</SPAN> desc<SPAN class="punctuation token">.</SPAN>workspaceType<SPAN class="punctuation token">:</SPAN>
<SPAN class="keyword token">return</SPAN> path
<SPAN class="keyword token">elif</SPAN> <SPAN class="operator token">not</SPAN> ws_type<SPAN class="punctuation token">:</SPAN>
<SPAN class="keyword token">return</SPAN> path
<SPAN class="comment token"># search until finding a valid workspace</SPAN>
SPLIT <SPAN class="operator token">=</SPAN> filter<SPAN class="punctuation token">(</SPAN>None<SPAN class="punctuation token">,</SPAN> path<SPAN class="punctuation token">.</SPAN>split<SPAN class="punctuation token">(</SPAN>os<SPAN class="punctuation token">.</SPAN>sep<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="keyword token">if</SPAN> path<SPAN class="punctuation token">.</SPAN>startswith<SPAN class="punctuation token">(</SPAN><SPAN class="string token">'\\\\'</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN>
SPLIT<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN> <SPAN class="operator token">=</SPAN> r<SPAN class="string token">'\\{0}'</SPAN><SPAN class="punctuation token">.</SPAN>format<SPAN class="punctuation token">(</SPAN>SPLIT<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="comment token"># find valid workspace</SPAN>
<SPAN class="keyword token">for</SPAN> i <SPAN class="keyword token">in</SPAN> xrange<SPAN class="punctuation token">(</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">,</SPAN> len<SPAN class="punctuation token">(</SPAN>SPLIT<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN>
sub_dir <SPAN class="operator token">=</SPAN> os<SPAN class="punctuation token">.</SPAN>sep<SPAN class="punctuation token">.</SPAN>join<SPAN class="punctuation token">(</SPAN>SPLIT<SPAN class="punctuation token">[</SPAN><SPAN class="punctuation token">:</SPAN><SPAN class="operator token">-</SPAN>i<SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN>
desc <SPAN class="operator token">=</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>Describe<SPAN class="punctuation token">(</SPAN>sub_dir<SPAN class="punctuation token">)</SPAN>
<SPAN class="keyword token">if</SPAN> hasattr<SPAN class="punctuation token">(</SPAN>desc<SPAN class="punctuation token">,</SPAN> <SPAN class="string token">'workspaceType'</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN>
<SPAN class="keyword token">if</SPAN> ws_type <SPAN class="operator token">and</SPAN> ws_type <SPAN class="operator token">==</SPAN> desc<SPAN class="punctuation token">.</SPAN>workspaceType<SPAN class="punctuation token">:</SPAN>
<SPAN class="keyword token">return</SPAN> sub_dir
<SPAN class="keyword token">elif</SPAN> <SPAN class="operator token">not</SPAN> ws_type<SPAN class="punctuation token">:</SPAN>
<SPAN class="keyword token">return</SPAN> sub_dir
<SPAN class="keyword token">class</SPAN> <SPAN class="token class-name">EditorUpdateCursor</SPAN><SPAN class="punctuation token">(</SPAN>object<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN>
<SPAN class="string token">"""Wrapper class for arcpy.da.UpdateCursor to automatically
implement editing (required for versioned data, and data with
geometric networks, topologies, network datasets, and relationship
classes"""</SPAN>
<SPAN class="keyword token">def</SPAN> <SPAN class="token function">__init__</SPAN><SPAN class="punctuation token">(</SPAN>self<SPAN class="punctuation token">,</SPAN> <SPAN class="operator token">*</SPAN>args<SPAN class="punctuation token">,</SPAN> <SPAN class="operator token">**</SPAN>kwargs<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN>
<SPAN class="string token">"""init wrapper class for update cursor Supported args:
in_table, field_names, where_clause=None, spatial_reference=None
explode_to_points=False, sql_clause=(None, None)"""</SPAN>
self<SPAN class="punctuation token">.</SPAN>args <SPAN class="operator token">=</SPAN> args
self<SPAN class="punctuation token">.</SPAN>kwargs <SPAN class="operator token">=</SPAN> kwargs
self<SPAN class="punctuation token">.</SPAN>edit <SPAN class="operator token">=</SPAN> None
<SPAN class="keyword token">def</SPAN> <SPAN class="token function">__enter__</SPAN><SPAN class="punctuation token">(</SPAN>self<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN>
ws <SPAN class="operator token">=</SPAN> None
<SPAN class="keyword token">if</SPAN> self<SPAN class="punctuation token">.</SPAN>args<SPAN class="punctuation token">:</SPAN>
ws <SPAN class="operator token">=</SPAN> find_ws<SPAN class="punctuation token">(</SPAN>self<SPAN class="punctuation token">.</SPAN>args<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="keyword token">elif</SPAN> <SPAN class="string token">'in_table'</SPAN> <SPAN class="keyword token">in</SPAN> self<SPAN class="punctuation token">.</SPAN>kwargs<SPAN class="punctuation token">:</SPAN>
ws <SPAN class="operator token">=</SPAN> find_ws<SPAN class="punctuation token">(</SPAN>self<SPAN class="punctuation token">.</SPAN>kwargs<SPAN class="punctuation token">[</SPAN><SPAN class="string token">'in_table'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN>
self<SPAN class="punctuation token">.</SPAN>edit <SPAN class="operator token">=</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>da<SPAN class="punctuation token">.</SPAN>Editor<SPAN class="punctuation token">(</SPAN>ws<SPAN class="punctuation token">)</SPAN>
self<SPAN class="punctuation token">.</SPAN>edit<SPAN class="punctuation token">.</SPAN>startEditing<SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN>
self<SPAN class="punctuation token">.</SPAN>edit<SPAN class="punctuation token">.</SPAN>startOperation<SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="keyword token">return</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>da<SPAN class="punctuation token">.</SPAN>UpdateCursor<SPAN class="punctuation token">(</SPAN><SPAN class="operator token">*</SPAN>self<SPAN class="punctuation token">.</SPAN>args<SPAN class="punctuation token">,</SPAN> <SPAN class="operator token">**</SPAN>self<SPAN class="punctuation token">.</SPAN>kwargs<SPAN class="punctuation token">)</SPAN>
<SPAN class="keyword token">def</SPAN> <SPAN class="token function">__exit__</SPAN><SPAN class="punctuation token">(</SPAN>self<SPAN class="punctuation token">,</SPAN> type<SPAN class="punctuation token">,</SPAN> value<SPAN class="punctuation token">,</SPAN> traceback<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN>
<SPAN class="keyword token">if</SPAN> traceback <SPAN class="keyword token">is</SPAN> None<SPAN class="punctuation token">:</SPAN>
self<SPAN class="punctuation token">.</SPAN>edit<SPAN class="punctuation token">.</SPAN>stopOperation<SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN>
self<SPAN class="punctuation token">.</SPAN>edit<SPAN class="punctuation token">.</SPAN>stopEditing<SPAN class="punctuation token">(</SPAN><SPAN class="token boolean">True</SPAN><SPAN class="punctuation token">)</SPAN>
self<SPAN class="punctuation token">.</SPAN>edit <SPAN class="operator token">=</SPAN> None
<SPAN class="keyword token">else</SPAN><SPAN class="punctuation token">:</SPAN>
self<SPAN class="punctuation token">.</SPAN>edit<SPAN class="punctuation token">.</SPAN>abortOperation<SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN>
self<SPAN class="punctuation token">.</SPAN>edit<SPAN class="punctuation token">.</SPAN>stopEditing<SPAN class="punctuation token">(</SPAN><SPAN class="token boolean">False</SPAN><SPAN class="punctuation token">)</SPAN>
self<SPAN class="punctuation token">.</SPAN>edit <SPAN class="operator token">=</SPAN> None
<SPAN class="comment token">## Update Logic</SPAN>
<SPAN class="keyword token">if</SPAN> updatedStructuresCount <SPAN class="operator token">></SPAN> <SPAN class="number token">0</SPAN><SPAN class="punctuation token">:</SPAN>
arcpy<SPAN class="punctuation token">.</SPAN>AddMessage<SPAN class="punctuation token">(</SPAN><SPAN class="string token">'\nPole Numbers are being updated...'</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="keyword token">for</SPAN> structure <SPAN class="keyword token">in</SPAN> structureDict<SPAN class="punctuation token">:</SPAN>
where <SPAN class="operator token">=</SPAN> <SPAN class="string token">"""GLOBALID = '{}'"""</SPAN><SPAN class="punctuation token">.</SPAN>format<SPAN class="punctuation token">(</SPAN>structure<SPAN class="punctuation token">)</SPAN>
<SPAN class="keyword token">with</SPAN> editUpdCursor<SPAN class="punctuation token">.</SPAN>EditorUpdateCursor<SPAN class="punctuation token">(</SPAN>strPath<SPAN class="punctuation token">,</SPAN> <SPAN class="punctuation token">[</SPAN><SPAN class="string token">'POLENUMBER'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">,</SPAN> where<SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">as</SPAN> cursor<SPAN class="punctuation token">:</SPAN>
<SPAN class="keyword token">for</SPAN> row <SPAN class="keyword token">in</SPAN> cursor<SPAN class="punctuation token">:</SPAN>
newPoleNum <SPAN class="operator token">=</SPAN> structureDict<SPAN class="punctuation token">.</SPAN>get<SPAN class="punctuation token">(</SPAN>structure<SPAN class="punctuation token">)</SPAN>
row<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN> <SPAN class="operator token">=</SPAN> newPoleNum
cursor<SPAN class="punctuation token">.</SPAN>updateRow<SPAN class="punctuation token">(</SPAN>row<SPAN class="punctuation token">)</SPAN>
arcpy<SPAN class="punctuation token">.</SPAN>AddMessage<SPAN class="punctuation token">(</SPAN><SPAN class="string token">'Pole Numbers update complete...'</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>