<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="https://www.w3.org/2005/Atom">
  <channel>
    <title>Josh Werts</title>
    <link>https://joshwerts.com/</link>
    <description>Recent content on Josh Werts</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Fri, 23 Mar 2018 13:41:03 -0400</lastBuildDate>
    <atom:link href="https://joshwerts.com/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Monkey-patching the ESRI JSAPI to mock services</title>
      <link>https://joshwerts.com/blog/2018/03/23/monkey-patching-the-esri-jsapi-to-mock-services/</link>
      <pubDate>Fri, 23 Mar 2018 13:41:03 -0400</pubDate>
      
      <guid>https://joshwerts.com/blog/2018/03/23/monkey-patching-the-esri-jsapi-to-mock-services/</guid>
      <description>

&lt;p&gt;Lately I&amp;rsquo;ve been working on a project where I&amp;rsquo;m unable to access the client&amp;rsquo;s ArcGIS Server services
directly and don&amp;rsquo;t have the data/environment to publish locally.  Working directly on the server is slow and I wanted a way to mock in a few services just to get started on some UI elements.  There are some online services that help w/ mocking HTTP calls, but I didn&amp;rsquo;t really want to put the data out there in the cloud&amp;hellip;.&lt;/p&gt;

&lt;p&gt;So how about some &lt;strong&gt;monkey-patching&lt;/strong&gt;?&lt;/p&gt;

&lt;h3 id=&#34;concept:58365f17369855609e8a0624874f7e55&#34;&gt;Concept&lt;/h3&gt;

&lt;p&gt;Here&amp;rsquo;s the basic concept - since nothing is really closed in JavaScript, we can intercept global functions, perform some action and then allow the function to continue as usual.  Here&amp;rsquo;s a simple example - let&amp;rsquo;s say we want to log the url of all XHR requests to the console:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// place this anonymous closure somewhere in your code before any service calls.
// could be in a script tag in index.html for instance.
(function (open) {

  // REPLACE the open function with a new function
  XMLHttpRequest.prototype.open = function (method, url, async, user, password) {

    // log out the url
    console.log(&#39;XHR request to: &#39;, url);

    // after we do our work, call the ORIGINAL open function so we continue normally.
    open.apply(this, arguments);
  };

  // pass the ORIGINAL function in as a parameter.
})(XMLHttpRequest.prototype.open);

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Example output in Chrome console:&lt;/strong&gt;&lt;br /&gt;
&lt;img src=&#34;https://joshwerts.com/img/xhr_logging.png&#34; alt=&#34;XHR logging in chrome console&#34; /&gt;&lt;/p&gt;

&lt;h3 id=&#34;featurelayer-xhr-example:58365f17369855609e8a0624874f7e55&#34;&gt;FeatureLayer (XHR) Example&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Some&lt;/em&gt; of the JSAPI uses XHR to pass queries.  For instance, this is an example of intercepting and mocking out service calls from a JSAPI 4.6 FeatureLayer.  In this case, we&amp;rsquo;re just checking the URL on each call and changing it to our JSON (which is simply previous ArcGIS Server calls saved out into .json files).  There are 3 steps here based on how ESRI has implemented the FeatureLayer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When the FeatureLayer is instantiated, a call is made to the endpoint w/ &lt;code&gt;f=json&lt;/code&gt; to retrieve the service&amp;rsquo;s schema.&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;At 4.x ESRI performs a &lt;code&gt;returnCountOnly&lt;/code&gt; call to get the total count of features.&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Then, the API tries to iterate through the objectIds with actual query calls to get all of the features, but we&amp;rsquo;re just returning a single response.  There&amp;rsquo;s a major gotcha here:  Make sure &lt;code&gt;&amp;quot;exceededTransferLimit&amp;quot;: false&lt;/code&gt; is set to &lt;code&gt;false&lt;/code&gt; in the json or the API will just keep iterating indefinitely trying to get all of the features.&lt;br /&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;(function (open) {
  XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
    if (url === &#39;https://server/arcgis/rest/services/myservice/MapServer/5?f=json&#39;) {
      console.log(&#39;open&#39;, method, url, async, user, password);
      url = &#39;https://localhost:8080/app/mocks/ags/my_ags_service_info.json&#39;;
    }

    if (url.indexOf(&#39;https://server/arcgis/rest/services/myservice/MapServer/5/query&#39;) &amp;gt; -1) {
      if (url.indexOf(&#39;returnCountOnly&#39;) &amp;gt; -1) {
        console.log(&#39;open&#39;, method, url, async, user, password);
        url = &#39;https://localhost:8080/app/mocks/ags/my_ags_service_5_values_count.json&#39;;
      } else {
        console.log(&#39;open&#39;, method, url, async, user, password);
        url = &#39;https://localhost:8080/app/mocks/ags/my_ags_service_5_values.json&#39;;
      }
    }
    open.apply(this, arguments);
  };
})(XMLHttpRequest.prototype.open);
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;querytask-jsonp-example:58365f17369855609e8a0624874f7e55&#34;&gt;QueryTask (jsonp) Example&lt;/h3&gt;

&lt;p&gt;Other parts of the API use jsonp instead of XHR to handle requests so we can&amp;rsquo;t intercept via XMLHttpRequest.  Here&amp;rsquo;s a slightly different approach to handle a &lt;code&gt;QueryTask.execute&lt;/code&gt; call by patching the class&amp;rsquo;s &lt;code&gt;execute&lt;/code&gt; function itself.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// NOTE: requires here are with a Webpack setup.
import QueryTask = require(&#39;esri/tasks/QueryTask&#39;);
import Point = require(&#39;esri/geometry/Point&#39;);
import FeatureSet = require(&#39;esri/tasks/support/FeatureSet&#39;);
import esriRequest = require(&#39;esri/request&#39;);

(function (execute) {
  QueryTask.prototype.execute = function (query, requestOptions?) {
    if (this.url.indexOf(&#39;https://server/arcgis/rest/services/myservice/MapServer/5?f=json&#39;) &amp;gt; -1) {

      // create a new Promise and do our own call to the local mocked json response.
      return new Promise((resolve, reject) =&amp;gt; {
        esriRequest(&#39;https://localhost:8080/app/mocks/ags/my_features.json&#39;).then(response =&amp;gt; {
          let featureSet = new FeatureSet(response.data);

          // In some cases geometries weren&#39;t correctly created and needed to fix.
          for (let f of featureSet.features) {
            f.geometry = new Point({
              x: f.geometry.x,
              y: f.geometry.y,
              spatialReference: {
                wkid: 4326
              }
            });
          }
          // resolve the promise with our mocked FeatureSet
          resolve(featureSet);
        }, error =&amp;gt; reject(error));
      });
    }
  }
  return execute.apply(this, arguments);
})(QueryTask.prototype.execute);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are probably better ways to accomplish this and I definitely wouldn&amp;rsquo;t suggest doing anything like this for a production app, but it can still be useful in some cases.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Group by query in a file geodatabase</title>
      <link>https://joshwerts.com/blog/2018/01/16/group-by-query-in-a-file-geodatabase/</link>
      <pubDate>Tue, 16 Jan 2018 13:51:36 -0500</pubDate>
      
      <guid>https://joshwerts.com/blog/2018/01/16/group-by-query-in-a-file-geodatabase/</guid>
      <description>&lt;p&gt;File geodatabase feature classes and tables lack some of the more advanced ability to query that a true relational database supports.  Sometimes these queries can be simulated with arcpy cursors; one good example is a SQL group by query.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typical SQL&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;SELECT field, count(*) from table group by field order by count(*) desc;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;In arcpy&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;from collections import Counter

def group_by_count(table_or_fc, fields):
    &amp;quot;&amp;quot;&amp;quot; Returns dictionary containing count of unique items &amp;quot;&amp;quot;&amp;quot;
    counter = Counter()
    with arcpy.da.SearchCursor(table_or_fc, fields) as curs:
        for row in curs:
            # no need to store as a tuple if only 1 field, just store the value
            if len(row) == 1:
                row = row[0]
            counter[row] += 1
    return counter


def group_by_count_formatted(table_or_fc, fields):
    &amp;quot;&amp;quot;&amp;quot; prints out counts of unique values &amp;quot;&amp;quot;&amp;quot;
    counter = group_by_count(table_or_fc, fields)
    # sort yields highest count records first (order by count(*) desc)
    for key, count in sorted(counter.items(), reverse=True, key=lambda item: item[1]):
        print(&amp;quot;{}: {:,}&amp;quot;.format(str(key), count))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Example usage in ArcMap Python console (single field)&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;&amp;gt;&amp;gt;&amp;gt; group_by_count(&#39;junctions&#39;, &#39;ImpedanceType&#39;)
Counter({u&#39;SmallStreet&#39;: 455145, u&#39;LargeStreet&#39;: 28714, u&#39;Stream&#39;: 9375, u&#39;RailRoad&#39;: 1742})

&amp;gt;&amp;gt;&amp;gt; group_by_count_formatted(&#39;junctions&#39;, &#39;ImpedanceType&#39;)
SmallStreet: 455,145
LargeStreet: 28,714
Stream: 9,375
RailRoad: 1,742
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Example usage in ArcMap Python console (multiple fields)&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;&amp;gt;&amp;gt;&amp;gt; group_by_count(&#39;junctions&#39;, [&#39;ImpedanceType&#39;, &#39;InfrastructureType&#39;])
Counter({(&#39;SmallStreet&#39;, &#39;New&#39;): 318834, (&#39;LargeStreet&#39;, &#39;New&#39;): 28710, (&#39;Stream&#39;, &#39;New&#39;): 18379, (&#39;Stream&#39;, &#39;Aerial&#39;): 5806, (&#39;RailRoad&#39;, &#39;New&#39;): 4043, (&#39;Stream&#39;, &#39;Underground&#39;): 3227, (&#39;RailRoad&#39;, &#39;Aerial&#39;): 1035, (&#39;RailRoad&#39;, &#39;Underground&#39;): 668})

&amp;gt;&amp;gt;&amp;gt; group_by_count_formatted(&#39;junctions&#39;, [&#39;ImpedanceType&#39;, &#39;InfrastructureType&#39;])
(&#39;SmallStreet&#39;, &#39;New&#39;): 318,834
(&#39;LargeStreet&#39;, &#39;New&#39;): 28,710
(&#39;Stream&#39;, &#39;New&#39;): 18,379
(&#39;Stream&#39;, &#39;Aerial&#39;): 5,806
(&#39;RailRoad&#39;, &#39;New&#39;): 4,043
(&#39;Stream&#39;, &#39;Underground&#39;): 3,227
(&#39;RailRoad&#39;, &#39;Aerial&#39;): 1,035
(&#39;RailRoad&#39;, &#39;Underground&#39;): 668
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These functions aren&amp;rsquo;t going to be as efficient as a SQL query, but they can be quite useful sometimes for ad-hoc data exploration - especially in the Arcmap/Pro console.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>ESRI Javascript API 4 with Angular 2 - Transition to Webpack</title>
      <link>https://joshwerts.com/blog/2017/01/08/esri-javascript-api-4-with-angular-2---transition-to-webpack/</link>
      <pubDate>Sun, 08 Jan 2017 14:21:52 -0500</pubDate>
      
      <guid>https://joshwerts.com/blog/2017/01/08/esri-javascript-api-4-with-angular-2---transition-to-webpack/</guid>
      <description>&lt;p&gt;Since my &lt;a href=&#34;https://joshwerts.com/blog/2016/05/17/esri-javascript-api-4-with-angular-2-and-typescript/&#34;&gt;first post&lt;/a&gt; on Angular 2 and the ESRI API, I&amp;rsquo;ve transitioned from SystemJS to Webpack which I&amp;rsquo;m enjoying thoroughly.&lt;/p&gt;

&lt;p&gt;Sample App w/ Webpack setup:&lt;br /&gt;
&lt;strong&gt;&lt;a href=&#34;https://joshwerts.com/angular2-esri-play&#34;&gt;Demo&lt;/a&gt;&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;&lt;a href=&#34;https://github.com/jwerts/angular2-esri-play&#34;&gt;Repo&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;IMO, Webpack has a few major advantages over SystemJS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Development build step is much faster and lite-server does not bog down with memory leaks (not sure why that happened with the SystemJS setup but lite-server got slower and slower until restarted).&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Webpack takes care of bundling code for you (everything expect the ESRI requires).&lt;br /&gt;

&lt;ul&gt;
&lt;li&gt;This setup also bundles each components&amp;rsquo; html and css in the main bundle.&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Feels like less of a hack to use with esri - simply require in each module and that&amp;rsquo;s it.  Setup is simply specifying ESRI as an &amp;ldquo;external&amp;rdquo;.  Nothing really special there and it just works.&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;No need for a grunt/gulp step to minimize, etc.  Webpack is pretty comprehensive.&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;This app is just a map with a custom coordinate display component (bottom left):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://joshwerts.com/img/map_w_coordinates.png&#34; alt=&#34;Coordinate component&#34; /&gt;&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve used a similar webpack configuration to this in a couple production apps over the last several months.  Unit testing w/ this setup and Typescript is finally starting to feel natural (instead of a large very verbose burden w/ es5).  I&amp;rsquo;ve found it fairly straightfoward to test domain classes and models w/ business logic where I feel you get the most bang for your buck from testing.  What I haven&amp;rsquo;t quite figured out yet is how to test components (and when it&amp;rsquo;s actually worth the effort).  This project contains a working test for the coordinate component&amp;hellip;  It works, but I&amp;rsquo;m not yet convinced it&amp;rsquo;s the best way to go about it.  Please comment if you have experience here!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coordinate Component test&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-ts&#34;&gt;import { TestBed, ComponentFixture } from &#39;@angular/core/testing&#39;;
import { DebugElement } from &#39;@angular/core&#39;;

import { CoordinateComponent } from &#39;./coordinate.component&#39;;

let fixture: ComponentFixture&amp;lt;CoordinateComponent&amp;gt;;
let component: CoordinateComponent;
let de: DebugElement;
let el: HTMLElement;
let $mapDiv;
let mapDivEl: Element;
beforeEach(() =&amp;gt; {
  // refine the test module by declaring the test component
  TestBed.configureTestingModule({
    declarations: [CoordinateComponent]
  });

  // create component and test fixture
  fixture = TestBed.createComponent(CoordinateComponent);
  el = fixture.nativeElement;

  // get test component from the fixture
  component = fixture.componentInstance;

  // add a div to the body
  $mapDiv = $(&#39;&amp;lt;div&amp;gt;&#39;, { id: &#39;mapDiv&#39; }).appendTo(&#39;body&#39;);
  mapDivEl = $mapDiv[0];

  // mock required MapView props/functions
  component.mapView = &amp;lt;any&amp;gt;{
    container: mapDivEl,
    toMap: (point) =&amp;gt; {
      return {
        longitude: 5,
        latitude: 10
      };
    },
    zoom: 7,
    scale: 500
  };

  // runs ngOnInit
  fixture.detectChanges();
});

describe(&#39;Coordinate&#39;, () =&amp;gt; {
  it(&#39;should update lat/long on mousemove&#39;, () =&amp;gt; {
    mapDivEl.dispatchEvent(new Event(&#39;mousemove&#39;, {
      bubbles: true,
      cancelable: true
    }));
    // pageX, pageY
    fixture.detectChanges();
    expect(el.querySelector(&#39;#longitude&#39;).innerHTML).toBe(&#39;5.000000&#39;);
    expect(el.querySelector(&#39;#latitude&#39;).innerHTML).toBe(&#39;10.000000&#39;);
    expect(el.querySelector(&#39;#zoom&#39;).innerHTML).toBe(&#39;7&#39;);
    expect(el.querySelector(&#39;#scale&#39;).innerHTML).toBe(&#39;500&#39;);
  });
});
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>FeatureClass from JSON</title>
      <link>https://joshwerts.com/blog/2016/10/14/featureclass-from-json/</link>
      <pubDate>Fri, 14 Oct 2016 10:07:44 -0400</pubDate>
      
      <guid>https://joshwerts.com/blog/2016/10/14/featureclass-from-json/</guid>
      <description>&lt;p&gt;I keep forgetting how to do this after several months pass by and it&amp;rsquo;s certainly not obvious&amp;hellip;&lt;/p&gt;

&lt;p&gt;ESRI provides a tool for converting JSON to FeatureClass but it requires reading the JSON from a .json file: &lt;a href=&#34;https://pro.arcgis.com/en/pro-app/tool-reference/conversion/json-to-features.htm&#34;&gt;JSON to Features&lt;/a&gt;.  That extra step of writing out and reading from a file just seems completely unnecessary.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s the alternative lesser known and not obvious way to do it:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;valid_featureset_json = \
&amp;quot;&amp;quot;&amp;quot;{
    &amp;quot;displayFieldName&amp;quot;: &amp;quot;&amp;quot;,
    &amp;quot;fieldAliases&amp;quot;: {
        &amp;quot;OBJECTID&amp;quot;: &amp;quot;OBJECTID&amp;quot;,
        &amp;quot;Description&amp;quot;: &amp;quot;Description&amp;quot;
    },
    &amp;quot;geometryType&amp;quot;: &amp;quot;esriGeometryPoint&amp;quot;,
    &amp;quot;spatialReference&amp;quot;: {
        &amp;quot;wkid&amp;quot;: 4326,
        &amp;quot;latestWkid&amp;quot;: 4326
    },
    &amp;quot;fields&amp;quot;: [
        {
            &amp;quot;name&amp;quot;: &amp;quot;OBJECTID&amp;quot;,
            &amp;quot;type&amp;quot;: &amp;quot;esriFieldTypeOID&amp;quot;,
            &amp;quot;alias&amp;quot;: &amp;quot;OBJECTID&amp;quot;
        },
        {
            &amp;quot;name&amp;quot;: &amp;quot;Description&amp;quot;,
            &amp;quot;type&amp;quot;: &amp;quot;esriFieldTypeString&amp;quot;,
            &amp;quot;alias&amp;quot;: &amp;quot;Description&amp;quot;,
            &amp;quot;length&amp;quot;: 50
        }
    ],
    &amp;quot;features&amp;quot;: [
        {
            &amp;quot;attributes&amp;quot;: {
                &amp;quot;OBJECTID&amp;quot;: 1,
                &amp;quot;Description&amp;quot;: &amp;quot;This is a test feature.&amp;quot;
            },
            &amp;quot;geometry&amp;quot;: {
                &amp;quot;x&amp;quot;: -123.80816799999991,
                &amp;quot;y&amp;quot;: 39.40451500000006
            }
        },
        {
            &amp;quot;attributes&amp;quot;: {
                &amp;quot;OBJECTID&amp;quot;: 2,
                &amp;quot;Description&amp;quot;: &amp;quot;This is aanother test feature.&amp;quot;
            },
            &amp;quot;geometry&amp;quot;: {
                &amp;quot;x&amp;quot;: -123.80816839299996,
                &amp;quot;y&amp;quot;: 39.404514814000095
            }
        }
    ]
}&amp;quot;&amp;quot;&amp;quot;

# convert to RecordSet object (should be able to use this most places FeatureSet would be called for)
record_set = arcpy.AsShape(valid_featureset_json, True)

# If you need a FeatureClass, just copy into one
output_fc = r&#39;in_memory\\output_fc&#39;
arcpy.management.CopyFeatures(record_set, output_fc)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that&amp;rsquo;s it!  No need to write the json to file.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Fun with Python Sets (and arcpy)</title>
      <link>https://joshwerts.com/blog/2016/07/21/fun-with-python-sets-and-arcpy/</link>
      <pubDate>Thu, 21 Jul 2016 17:38:05 -0400</pubDate>
      
      <guid>https://joshwerts.com/blog/2016/07/21/fun-with-python-sets-and-arcpy/</guid>
      <description>&lt;p&gt;I often forget about the Python &lt;code&gt;set&lt;/code&gt;, so this is a fun reminder to myself to keep it in mind.  Here&amp;rsquo;s a neat example of using a set for deleting fields.&lt;/p&gt;

&lt;p&gt;This function deletes all of the fields &lt;em&gt;except&lt;/em&gt; the ones you specify:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;def delete_all_fields_except(fc, keep_fields):
    &amp;quot;&amp;quot;&amp;quot; deletes all fields except those specfied as keep_fields &amp;quot;&amp;quot;&amp;quot; 
    # create set of all possible fields but exclude OBJECTID, SHAPE, etc.
    all_fields = set(f.name for f in arcpy.ListFields(fc) if not f.required)

    # get a list of fields in the featureclass but not in the list of fields to keep
    # using set.difference()
    
    delete_fields = list(all_fields.difference(keep_fields))
    
    # delete out all the fields
    arcpy.management.DeleteField(fc, delete_fields)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Usage:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;# Assume our feature class has the following fields:
print([f.name for f in arcpy.ListFields(fc)])
# [&#39;OBJECTID&#39;, &#39;Shape&#39;, &#39;field1&#39;, &#39;field2&#39;, &#39;field3&#39;, &#39;field4&#39;, &#39;field5&#39;]

keep_fields = [&#39;field1&#39;, &#39;field3&#39;]
delete_all_fields_except(fc, keep_fields)

print([f.name for f in arcpy.ListFields(fc)])
# [&#39;OBJECTID&#39;, &#39;Shape&#39;, &#39;field1&#39;, &#39;field3&#39;]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is pretty simple example and you could obviously accomplish this without using set, but set is more elegant and more efficient (probably doesn&amp;rsquo;t matter much here).  Perhaps I&amp;rsquo;ll update this post with more advanced usage now that this is here to remind me to think about sets!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>ESRI Javascript API 4 with Angular 2 and Typescript</title>
      <link>https://joshwerts.com/blog/2016/05/17/esri-javascript-api-4-with-angular-2-and-typescript/</link>
      <pubDate>Tue, 17 May 2016 20:23:08 -0400</pubDate>
      
      <guid>https://joshwerts.com/blog/2016/05/17/esri-javascript-api-4-with-angular-2-and-typescript/</guid>
      <description>

&lt;p&gt;&lt;strong&gt;Update 1/8/2017: &lt;/strong&gt;I&amp;rsquo;ve transitioned to Webpack since this post: &lt;a href=&#34;https://joshwerts.com/blog/2017/01/08/esri-javascript-api-4-with-angular-2---transition-to-webpack/&#34;&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This could really be a post about many things.&lt;/p&gt;

&lt;p&gt;First, I&amp;rsquo;m a believer in client-side MV*.  Second, I&amp;rsquo;m trying to incorporate better testing into my front-end JS code.  Angular seemed like a natural fit given these 2 primary objectives.  I&amp;rsquo;ve done a fair amount of work now with Angular 1 and the ESRI JSAPI 3.x library.  There have been some solid success here, but Dojo &lt;code&gt;require&lt;/code&gt; throughout the app and especially in unit tests have been a major headache.  You could perhaps mock all dependencies from ESRI in the unit tests or try to keep ESRI in it&amp;rsquo;s own untested sandbox, but both of these strategies seems better in theory than practice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Aside&lt;/strong&gt;: ESRI does not make any of this easy.  Sure, you can get it to work&amp;hellip; kind of&amp;hellip;. with a lot of headaches along the way.  It all boils down to Dojo.  Don&amp;rsquo;t get me wrong, the ESRI API does some amazing things and some of the new 4.0 features look incredibly promising (&lt;code&gt;.watch()&lt;/code&gt; is brilliant), but there&amp;rsquo;s really no solid reason why we&amp;rsquo;re still forced to use Dojo.&lt;/p&gt;

&lt;p&gt;Anyway, getting to what this post is really about&amp;hellip;.&lt;/p&gt;

&lt;h2 id=&#34;the-app:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;The App&lt;/h2&gt;

&lt;p&gt;&lt;a href=&#34;https://joshwerts.com/jsapi4-angular2&#34; target=&#34;_blank&#34; ____&gt;&lt;img src=&#34;https://joshwerts.com/img/jsapi4ang2_tests_liteserver_app.png&#34; alt=&#34;Full setup&#34; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://joshwerts.com/jsapi4-angular2/&#34;&gt;Live Demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From a high level view, the app simply adds points to the map and shows a list of those points with their geometry and &amp;ldquo;index&amp;rdquo; attribute.  Nothing too special - just there to test some concepts.  As an added bonus, the app is served through lite-server and constantly updates as you code.  Similarly, the unit tests run continuously.&lt;/p&gt;

&lt;p&gt;Building upon experimental work by &lt;a href=&#34;https://github.com/odoe/esrijs4-vm-angular2&#34;&gt;Rene Rubalcava&lt;/a&gt; and &lt;a href=&#34;https://github.com/tomwayson/angular2-esri-example&#34;&gt;Tom Wayson&lt;/a&gt;, I was able to get an Angular 2 app properly loading dojo dependencies both in the browser and in Karma tests.&lt;/p&gt;

&lt;p&gt;The app consists of a &amp;ldquo;model&amp;rdquo; (Angular service) to hold the points (or domain object of your choosing) - the thought being that business logic in this model would be testable without being concerned about the objects&amp;rsquo; relation to the map.  Ideally, this model wouldn&amp;rsquo;t contain ESRI dependencies, but with the JSAPI 4&amp;rsquo;s watch capabilities, it seems to make sense to use an &lt;code&gt;esri/core/Collection&lt;/code&gt; as the underlying data structure in the model.  Also ideally, we&amp;rsquo;d just have the collection in the model, but it seems the only way to achieve the map automagically updating is if we use the points from a GraphicsLayer (passing in our Collection as the graphics property to the GraphicsLayer constructor worked in 4.0beta3, but not in 4.0 final for some reason).&lt;/p&gt;

&lt;h3 id=&#34;pointsmodel-points-model-ts:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;PointsModel (points.model.ts)&lt;/h3&gt;

&lt;p&gt;So here&amp;rsquo;s our PointsModel (in Typescript).  We&amp;rsquo;ve simply wrapped a few &lt;code&gt;Collection&lt;/code&gt; methods and then we can add some additional business logic like &lt;code&gt;getIndexSum()&lt;/code&gt;.  &lt;code&gt;index&lt;/code&gt; is just a made up attribute for sake of testing.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-ts&#34;&gt;import { Injectable } from &#39;@angular/core&#39;;

import Graphic from &#39;esri/Graphic&#39;;
import GraphicsLayer from &#39;esri/layers/GraphicsLayer&#39;;
import Collection from &#39;esri/core/Collection&#39;;

@Injectable()
export class PointsModel {
  private points: Collection = new Collection();
  pointsLayer: GraphicsLayer;
  constructor() {
    this.pointsLayer = new GraphicsLayer();
    this.points = this.pointsLayer.graphics;
  }
  addPoint(pointGraphic: Graphic) {
    this.points.add(pointGraphic);
  }
  addPoints(pointsGraphics: Graphic[]) {
    this.points.addMany(pointsGraphics);
  }
  getPointGraphics() {
    return this.points;
  }
  clear() {
    this.points.removeAll();
  }
  getIndexSum() {
    let sum = 0;
    if (this.points !== null) {
      this.points.forEach(p =&amp;gt; sum += p.attributes.index);
    }
    return sum;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;attributecomponent-attribute-component-html:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;AttributeComponent (attribute.component.html)&lt;/h3&gt;

&lt;p&gt;When we add a point to the model, it not only shows up in the map, but also in the attribute list which is wired up through databinding:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;div&amp;gt;
  &amp;lt;h2&amp;gt;Points!&amp;lt;/h2&amp;gt;
  &amp;lt;p&amp;gt;Index Sum: {{pointsModel.getIndexSum()}}
  &amp;lt;ul&amp;gt;
    &amp;lt;li *ngFor=&amp;quot;let point of points.toArray()&amp;quot;&amp;gt;
      &amp;lt;span&amp;gt;{{point.attributes.index}} ({{point.geometry.x | number:&#39;.5-5&#39;}},{{point.geometry.y | number:&#39;.5-5&#39;}})&amp;lt;/span&amp;gt;
    &amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;mapservice-map-service-ts:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;MapService (map.service.ts)&lt;/h3&gt;

&lt;p&gt;Our map binding to our PointsModel (which is just a matter of adding pointsModel.pointsLayer (our GraphicsLayer) to the map):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-ts&#34;&gt;import { Injectable } from &#39;@angular/core&#39;;

import Map from &#39;esri/Map&#39;;
import GraphicsLayer from &#39;esri/layers/GraphicsLayer&#39;;

import { PointsModel } from &#39;./points.model&#39;;

@Injectable()
export class MapService {
  map: Map;
  pointGraphicsLayer: GraphicsLayer;
  constructor(pointsModel: PointsModel) {
    this.map = new Map({
      basemap: &#39;topo&#39;
    });
    this.map.add(pointsModel.pointsLayer);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;pointsmodel-tests-points-model-spec-ts:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;PointsModel Tests (points.model.spec.ts)&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-ts&#34;&gt;import { PointsModel } from &#39;./points.model&#39;;

import Graphic from &#39;esri/Graphic&#39;;
import Point from &#39;esri/geometry/Point&#39;;

describe(&#39;PointsModel tests&#39;, () =&amp;gt; {
  let mockPointGraphic = new Graphic({
    attributes: {
      index: 1
    },
    geometry: new Point({
      x: 1,
      y: 2,
      spatialReference: {
        wkid: 4326
      }
    })
  });

  let pointsModel;
  beforeEach(() =&amp;gt; {
    pointsModel = new PointsModel();
  });

  it(&#39;should contstruct it&#39;, () =&amp;gt; {
    expect(pointsModel).toBeDefined();
    expect(pointsModel.getPointGraphics()).toBeDefined();
  });

  describe(&#39;adding and removing points&#39;, () =&amp;gt; {
    it(&#39;should add a point to collection&#39;, () =&amp;gt; {
       pointsModel.addPoint(mockPointGraphic);
       pointsModel.addPoint(mockPointGraphic);
       expect(pointsModel.getPointGraphics().length).toEqual(2);
    });

    it(&#39;should add points to collection&#39;, () =&amp;gt; {
      pointsModel.addPoints([mockPointGraphic, mockPointGraphic]);
      expect(pointsModel.getPointGraphics().length).toEqual(2);
    });

    it(&#39;should clear points&#39;, () =&amp;gt; {
      pointsModel.addPoint(mockPointGraphic);
      pointsModel.addPoint(mockPointGraphic);
      pointsModel.clear();
      expect(pointsModel.getPointGraphics().length).toEqual(0);
    });
  });

  describe(&#39;calculations&#39;, () =&amp;gt; {
    it(&#39;should calculate the sum of the index attributes&#39;, () =&amp;gt; {
      pointsModel.addPoints([mockPointGraphic, mockPointGraphic]);
      let sum = pointsModel.getIndexSum();
      expect(sum).toEqual(2);
    });
  });

});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The nice thing here is that the tests didn&amp;rsquo;t balk at using the esri &lt;code&gt;Collection&lt;/code&gt; that must be imported into the PointsModel (&lt;strong&gt;this has been an incredibly difficult thing to do w/ Angular 1 / Dojo&lt;/strong&gt;).&lt;/p&gt;

&lt;h2 id=&#34;setup:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;Setup&lt;/h2&gt;

&lt;p&gt;Setup for this is non-trivial and is based heavily on &lt;a href=&#34;https://github.com/Esri/esri-system-js&#34;&gt;esri/esri-system-js&lt;/a&gt; along with custom configuration in the Karma configuration and loading of dependencies locally using the &lt;a href=&#34;https://github.com/Esri/arcgis-js-api&#34;&gt;esri bower jsapi repo&lt;/a&gt;.  In short, the esri-system-js loader loads &lt;strong&gt;ALL&lt;/strong&gt; esri dependencies at the start of the application so they&amp;rsquo;re available through import statements in Typescript files.  This was already figured out for the browser portion by Tom and Rene as referenced previously, so check out their repo&amp;rsquo;s for more information there.&lt;/p&gt;

&lt;p&gt;Getting it wired up for testing was a little more difficult but here are the key highlights.  Note that I&amp;rsquo;ve broken out some different configs for browser vs tests.&lt;/p&gt;

&lt;h3 id=&#34;dojoconfigtest-js:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;dojoConfigTest.js&lt;/h3&gt;

&lt;p&gt;Fairly standard setup for loading from a &lt;strong&gt;local&lt;/strong&gt; bower setup.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;(function(window) {
  // set up your dojoConfig
  window.dojoConfig = {
    baseUrl: &#39;app/node_modules/&#39;,
    deps: [&#39;app/main&#39;],
    packages: [
      &#39;app&#39;,
      &#39;dijit&#39;,
      &#39;dojo&#39;,
      &#39;dojox&#39;,
      &#39;dstore&#39;,
      &#39;dgrid&#39;,
      &#39;esri&#39;, {
        name: &#39;moment&#39;,
        location: &#39;moment&#39;,
        main: &#39;moment&#39;
      }
    ]
  };
});
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;karma-conf-js:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;karma.conf.js&lt;/h3&gt;

&lt;p&gt;These are the changes that were added to the karma.conf.js configuration included in the &lt;a href=&#34;https://github.com/angular/quickstart&#34;&gt;angular2 quick start repo&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;  ...

  files: [
    ... angular files, etc.
    // ********* esri load ***********
    // must be able to serve these files for dojo require
    // NOTE: karma gives a cryptic error when 
    // files can&#39;t be found  (msg || &amp;quot;&amp;quot;).replace is not a function
    { pattern: &#39;bower_components/dojo/**/*.*&#39;, included: false, watched: false },
    { pattern: &#39;bower_components/dojox/**/*.*&#39;, included: false, watched: false },
    { pattern: &#39;bower_components/dstore/**/*.*&#39;, included: false, watched: false },     
    { pattern: &#39;bower_components/dgrid/**/*.*&#39;, included: false, watched: false },
    
    { pattern: &#39;bower_components/dijit/**/*.*&#39;, included: false, watched: false },
    { pattern: &#39;bower_components/esri/**/*.*&#39;, included: false, watched: false },    
    { pattern: &#39;bower_components/moment/**/*.js&#39;, included: false, watched: false },   

    // load dojoConfig so dojo knows where to &amp;quot;require&amp;quot; modules from
    &#39;dojoConfigTest.js&#39;,
    
    // we need the actual dojo startup file for &amp;quot;requrire&amp;quot; to be defined
    &#39;bower_components/dojo/dojo.js&#39;,
    
    // load in esri&#39;s systemJs util
    &#39;node_modules/esri-system-js/dist/esriSystem.js&#39;,
    
    // load in our array of esri dependencies
    &#39;esriLoadConfig.js&#39;,
    
    // bootstrap in the modules using esri-system-js
    &#39;esriSystemLoadTest.js&#39;, 

    ... more angular files
]
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;esriloadconfig-js:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;esriLoadConfig.js&lt;/h3&gt;

&lt;p&gt;Contains &lt;strong&gt;ALL&lt;/strong&gt; esri modules required by the application:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;(function(window) {
  window.esriLoadConfig = {
      modules: [
      &#39;esri/Map&#39;,
      &#39;esri/views/MapView&#39;,
      &#39;esri/core/Collection&#39;,
      &#39;esri/layers/GraphicsLayer&#39;,
      &#39;esri/Graphic&#39;,
      &#39;esri/geometry/Point&#39;,
      &#39;esri/geometry/SpatialReference&#39;,
      &#39;esri/symbols/SimpleMarkerSymbol&#39;,
      &#39;esri/Color&#39;
    ]
  };
}(window))
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;esrisystemloadtest-js:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;esriSystemLoadTest.js&lt;/h3&gt;

&lt;p&gt;Called by Karma to pre-load the esri modules before the tests run.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// load esri modules needed by this application
// into a System.js module called esri
start = performance.now();
esriSystem.register(esriLoadConfig.modules, function () {
  end = performance.now();
  time = end - start;
  console.log(&#39;Loaded esri modules&#39;, time / 1000.0);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;esrisystemloadbrowser-js:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;esriSystemLoadBrowser.js&lt;/h3&gt;

&lt;p&gt;Used in the browser code (called from index.html) to load in the esri modules AND bootstrap the application once those modules are available.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// load esri modules needed by this application
// into a System.js module called esri
console.log(&amp;quot;Loading esri modules: &amp;quot;, esriLoadConfig.modules);
start = performance.now();
esriSystem.register(esriLoadConfig.modules, function () {
  // then bootstrap application
  end = performance.now();
  time = end - start;
  console.log(&#39;Loaded esri modules&#39;, time / 1000.0);
  System.import(&#39;app/main&#39;).then(function () {
    console.log(&#39;app/main imported&#39;);
  }, function (error) {
    console.log(&amp;quot;System import error:&amp;quot;, error);
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;conclusion:9b18d3a8a2156557610aadbdfb7d2ee2&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;&lt;del&gt;This is &lt;strong&gt;highly experimental&lt;/strong&gt; and there&amp;rsquo;s &lt;strong&gt;a lot of moving parts&lt;/strong&gt;, but it&amp;rsquo;s nice to know this is possible.&lt;/del&gt; This is getting closer to production quality.  I&amp;rsquo;ve left out a lot but the full repo&amp;rsquo;s here:&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://github.com/jwerts/jsapi4-angular2&#34;&gt;https://github.com/jwerts/jsapi4-angular2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There will likely be updates to the repo as I continue to explore this concept (and learn Angular 2&amp;hellip; and learn Typescript).&lt;/p&gt;

&lt;p&gt;It could really benefit from a final build process.  Note that I&amp;rsquo;ve used CDN for most dependencies in index.html for the gh-pages demo to avoid loading local bower and node dependencies to Github.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Edit 2016-06-16:&lt;/strong&gt; Updated Angular to &lt;strong&gt;2.0.0.RC2&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Edit 2016-06-24:&lt;/strong&gt; Updated Angular to &lt;strong&gt;2.0.0.RC3&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Edit 2016-07-05:&lt;/strong&gt; Updated Angular to &lt;strong&gt;2.0.0.RC4&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Edit 2016-07-07:&lt;/strong&gt; Updated to use &lt;strong&gt;esri-system-js 1.0 beta&lt;/strong&gt; which now preserves esri module names and works correctly with Typescript arcgis-js-api typings.&lt;br /&gt;
&lt;strong&gt;Edit 2016-09-22:&lt;/strong&gt; Updated Angular to &lt;strong&gt;2.0.0 final&lt;/strong&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>arcpy: Efficient Geometry Creation</title>
      <link>https://joshwerts.com/blog/2016/02/04/arcpy-efficient-geometry-creation/</link>
      <pubDate>Thu, 04 Feb 2016 15:10:09 -0500</pubDate>
      
      <guid>https://joshwerts.com/blog/2016/02/04/arcpy-efficient-geometry-creation/</guid>
      <description>

&lt;p&gt;Sometimes every second counts&amp;hellip; and even if it doesn&amp;rsquo;t, it&amp;rsquo;s still interesting to see the quirks of a familiar library.&lt;/p&gt;

&lt;p&gt;It turns out that object creation can be somewhat expensive (especially when you&amp;rsquo;re talking about Python &amp;ndash;&amp;gt; ArcObjects &amp;ndash;&amp;gt; COM).  With arcpy (and underlying ArcObjects), there are some objects which can be reused to gain some efficiency.&lt;/p&gt;

&lt;p&gt;An interesting example is simply creating a polyline from a pair of points.&lt;/p&gt;

&lt;h2 id=&#34;example-creating-a-2-point-polyline:a6ccf97ec21661e841aba6ff978f1848&#34;&gt;Example: Creating a 2 point polyline&lt;/h2&gt;

&lt;h3 id=&#34;simplest-form:a6ccf97ec21661e841aba6ff978f1848&#34;&gt;Simplest form:&lt;/h3&gt;

&lt;p&gt;In its simplest form, you may write:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;def create_line_simple(point1_x_and_y, point2_x_and_y, spatial_ref):
    &amp;quot;&amp;quot;&amp;quot; creates polyline from pair of (x,y) tuples &amp;quot;&amp;quot;&amp;quot;
    start_point = arcpy.Point(*point1_x_and_y)
    end_point = arcpy.Point(*point2_x_and_y)
    array = arcpy.Array([start_point, end_point])
    polyline = arcpy.Polyline(array, spatial_ref)
    return polyline

# Usage:
polyline = create_line_simple((-81.60, 36.20), (-81.70, 36.30), arcpy.SpatialReference(4326))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There&amp;rsquo;s nothing wrong with this code.  In fact, if you&amp;rsquo;re only creating a few polylines, stop here.  It&amp;rsquo;s readable and gets the job done.&lt;/p&gt;

&lt;h3 id=&#34;a-little-more-efficient:a6ccf97ec21661e841aba6ff978f1848&#34;&gt;A little more efficient:&lt;/h3&gt;

&lt;p&gt;However, if you&amp;rsquo;re creating thousands of polylines, some time can be saved by reusing arcpy.Point objects.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;# modules scoped private variables
_start_point = arcpy.Point()
_end_point = arcpy.Point()

def create_line_reuse_points(point1_x_and_y, point2_x_and_y, spatial_ref):
    &amp;quot;&amp;quot;&amp;quot; creates polyline from pair of (x,y) tuples &amp;quot;&amp;quot;&amp;quot;
    _start_point.X, _start_point.Y = point1_x_and_y
    _end_point.X, _end_point.Y = point2_x_and_y
    array = arcpy.Array([_start_point, _end_point])
    polyline = arcpy.Polyline(array, spatial_ref)
    return polyline
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this case, we&amp;rsquo;re creating 2 module scoped points only once and then setting the X and Y properties on those points.  The arcpy.Polyline constructor reads X and Y from those points, but it doesn&amp;rsquo;t maintain a reference to the points.  Setting properties on the existing objects is a bit more efficient than creating new objects every time and since references aren&amp;rsquo;t maintained to those objects, we&amp;rsquo;re safe from a memory perspective.&lt;/p&gt;

&lt;h3 id=&#34;even-more-efficient:a6ccf97ec21661e841aba6ff978f1848&#34;&gt;Even more efficient:&lt;/h3&gt;

&lt;p&gt;Why not go ahead and reuse the arcpy.Array as well?  Once again, arcpy.Polyline() only reads data from the array and doesn&amp;rsquo;t maintain a reference.  Make sure to removeAll() from array to clean up.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;# modules scoped private variables
_start_point = arcpy.Point()
_end_point = arcpy.Point()
_array = arcpy.Array()

def create_line_reuse_points_array(point1_x_and_y, point2_x_and_y, spatial_ref):
    &amp;quot;&amp;quot;&amp;quot; creates polyline from pair of (x,y) tuples &amp;quot;&amp;quot;&amp;quot;
    _start_point.X, _start_point.Y = point1_x_and_y
    _end_point.X, _end_point.Y = point2_x_and_y
    _array.add(_start_point)
    _array.add(_end_point)
    polyline = arcpy.Polyline(_array, spatial_ref)
    _array.removeAll()
    return polyline
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;how-much-more-efficient-is-this-approach:a6ccf97ec21661e841aba6ff978f1848&#34;&gt;How much more efficient is this approach?&lt;/h2&gt;

&lt;p&gt;Here are the results (in seconds) for creating 100,000 polylines with each function (Python 3.4.1 w/ ArcGIS Pro on Core i7-4712HQ):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Create line simple:
0:00:21.071529

Create line reuse points:
0:00:17.813275

Create line reuse points and array:
0:00:16.277035
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Is it a huge difference?  Not really.  But if you have a process that creates a large amount of geometries, it&amp;rsquo;s worth considering reusing a few objects.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s the full test script to produce the above results:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import arcpy
from datetime import datetime as dt


def time_me(n):
    &amp;quot;&amp;quot;&amp;quot; decorator to print total time to run function n number of times &amp;quot;&amp;quot;&amp;quot;
    def time_me_decorator(f):
        def wrapper(*args):
            start = dt.now()
            for _ in range(n):
                f(*args)
            print(dt.now() - start)
        return wrapper
    return time_me_decorator


REPETITIONS = 100000

######## Simple Case

@time_me(REPETITIONS)
def create_line_simple(point1_x_and_y, point2_x_and_y, spatial_ref):
    &amp;quot;&amp;quot;&amp;quot; creates polyline from pair of (x,y) tuples &amp;quot;&amp;quot;&amp;quot;
    start_point = arcpy.Point(*point1_x_and_y)
    end_point = arcpy.Point(*point2_x_and_y)
    array = arcpy.Array([start_point, end_point])
    polyline = arcpy.Polyline(array, spatial_ref)
    return polyline


######## Reuses the point objects

# modules scoped private functions
_start_point = arcpy.Point()
_end_point = arcpy.Point()

@time_me(REPETITIONS)
def create_line_reuse_points(point1_x_and_y, point2_x_and_y, spatial_ref):
    &amp;quot;&amp;quot;&amp;quot; creates polyline from pair of (x,y) tuples &amp;quot;&amp;quot;&amp;quot;
    _start_point.X, _start_point.Y = point1_x_and_y
    _end_point.X, _end_point.Y = point2_x_and_y
    array = arcpy.Array([_start_point, _end_point])
    polyline = arcpy.Polyline(array, spatial_ref)
    return polyline


######## Reuses the point and array objects

# modules scoped private functions
_start_point = arcpy.Point()
_end_point = arcpy.Point()
_array = arcpy.Array()

@time_me(REPETITIONS)
def create_line_reuse_points_array(point1_x_and_y, point2_x_and_y, spatial_ref):
    &amp;quot;&amp;quot;&amp;quot; creates polyline from pair of (x,y) tuples &amp;quot;&amp;quot;&amp;quot;
    _start_point.X, _start_point.Y = point1_x_and_y
    _end_point.X, _end_point.Y = point2_x_and_y
    _array.add(_start_point)
    _array.add(_end_point)
    polyline = arcpy.Polyline(_array, spatial_ref)
    _array.removeAll()
    return polyline


# Run our tests
if __name__ == &amp;quot;__main__&amp;quot;:
    WGS_84 = arcpy.SpatialReference(4326)
    POINT1 = (-81.674525, 36.216630)
    POINT2 = (-81.675351, 36.213886)

    print(&amp;quot;Create line simple:&amp;quot;)
    create_line_simple(POINT1, POINT2, WGS_84)
    print(&amp;quot;&amp;quot;)

    print(&amp;quot;Create line reuse points:&amp;quot;)
    create_line_reuse_points(POINT1, POINT2, WGS_84)
    print(&amp;quot;&amp;quot;)

    print(&amp;quot;Create line reuse points and array:&amp;quot;)
    create_line_reuse_points_array(POINT1, POINT2, WGS_84)
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Octopress to Hexo to Hugo</title>
      <link>https://joshwerts.com/blog/2015/12/10/octopress-to-hexo-to-hugo/</link>
      <pubDate>Thu, 10 Dec 2015 18:17:49 -0500</pubDate>
      
      <guid>https://joshwerts.com/blog/2015/12/10/octopress-to-hexo-to-hugo/</guid>
      <description>

&lt;p&gt;This blog post is really just to say &lt;strong&gt;&amp;ldquo;Wow! Hugo is freakin&amp;rsquo; awesome!&amp;rdquo;&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&#34;a-href-http-octopress-org-octopress-a:955d799df0aa29831b7762c00172d370&#34;&gt;&lt;a href=&#34;https://octopress.org/&#34;&gt;Octopress&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;&lt;img src=&#34;https://joshwerts.com/img/octopress.png&#34; alt=&#34;Octopress&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Octopress definitely got the job done and introduced me to static blog generators, but I had no real desire to learn Ruby and lately with Windows 10, I&amp;rsquo;ve booted up to Linux less and less (yes, Windows 10 really is pretty good - if only it had a bash terminal).  Installing Ruby on Windows just wasn&amp;rsquo;t something I wanted to bother with.  Also, if I wanted to change the underlying templates, it just seemed more complicated than it really needed to be and I couldn&amp;rsquo;t find the time or motivation to really bother changing the default template much.&lt;/p&gt;

&lt;p&gt;&lt;br/&gt;&lt;/p&gt;

&lt;h2 id=&#34;a-href-https-hexo-io-hexo-a:955d799df0aa29831b7762c00172d370&#34;&gt;&lt;a href=&#34;https://hexo.io/&#34;&gt;Hexo&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;&lt;img src=&#34;https://joshwerts.com/img/hexo.png&#34; alt=&#34;Hexo&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Soooooooo&amp;hellip; the next logical step seemed to be Hexo.  NodeJS - easy enough on Windows and I&amp;rsquo;ve done a little node development here and there so here we go.  Somehow this just seemed a bit kludgy too.  It&amp;rsquo;s a decent enough project, but just didn&amp;rsquo;t quite feel right.&lt;/p&gt;

&lt;p&gt;&lt;br/&gt;&lt;/p&gt;

&lt;h2 id=&#34;a-href-https-gohugo-io-hugo-a:955d799df0aa29831b7762c00172d370&#34;&gt;&lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;&lt;img src=&#34;https://joshwerts.com/img/hugo.jpg&#34; alt=&#34;Hugo&#34; /&gt;&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve been looking for excuses to learn Go, so on a whim, googled static blog generators and Go.  I&amp;rsquo;m yet to really learn any Go from using Hugo (other than perusing the code), but still it&amp;rsquo;s nice to know it&amp;rsquo;s there if I need to dig through source to figure out what&amp;rsquo;s up or want to dive deeper and contribute to the project.&lt;/p&gt;

&lt;p&gt;At any rate, Hugo &lt;em&gt;just feels right.&lt;/em&gt;  Not only was I able to migrate my existing blog fairly quickly, but it was not only easy, but also &lt;em&gt;fun&lt;/em&gt; to start hacking on an existing theme.&lt;/p&gt;

&lt;p&gt;Reasons I love Hugo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installation is just a matter of adding a .exe to your PATH and your good to go.  Can&amp;rsquo;t argue with that.&lt;/li&gt;
&lt;li&gt;Good documentation - was fairly easy to get started (one hint though: you need to specify a theme or it will seem like it&amp;rsquo;s failing silently)&lt;/li&gt;
&lt;li&gt;Go templates seem mostly straightforward and powerful&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SPEED&lt;/strong&gt; - this wasn&amp;rsquo;t really a criteria for me since this blog is pretty small but with Hugo&amp;rsquo;s speed (100ms to generate this blog) along with its &lt;strong&gt;built-in live reload&lt;/strong&gt;, development is easy and fun.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This blog is currently running off a moderately modified &lt;a href=&#34;https://github.com/digitalcraftsman/hugo-steam-theme&#34;&gt;Steam&lt;/a&gt; theme.  Development is fun enough that hopefully it will continue to evolve (in other words, I don&amp;rsquo;t feel like I&amp;rsquo;m &lt;em&gt;fighting the framework&lt;/em&gt; with Hugo).&lt;/p&gt;

&lt;p&gt;I also found these resources especially helpful for migration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://nathanleclaire.com/blog/2014/12/22/migrating-to-hugo-from-octopress/&#34;&gt;https://nathanleclaire.com/blog/2014/12/22/migrating-to-hugo-from-octopress/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/tutorials/github-pages-blog/&#34;&gt;https://gohugo.io/tutorials/github-pages-blog/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Feature Service applyEdits on Multiple Layers</title>
      <link>https://joshwerts.com/blog/2015/11/10/feature-service-applyedits-on-multiple-layers/</link>
      <pubDate>Tue, 10 Nov 2015 13:09:37 -0500</pubDate>
      
      <guid>https://joshwerts.com/blog/2015/11/10/feature-service-applyedits-on-multiple-layers/</guid>
      <description>

&lt;p&gt;If you&amp;rsquo;ve worked with any of the esri web API&amp;rsquo;s over the last several years, chances are you&amp;rsquo;ve used a Feature Service to edit an SDE feature class at some point.  Using the web API&amp;rsquo;s, the obvious way to do this would be to construct a &lt;a href=&#34;https://developers.arcgis.com/javascript/jsapi/featurelayer-amd.html&#34;&gt;FeatureLayer&lt;/a&gt; and call its &lt;a href=&#34;https://developers.arcgis.com/javascript/jsapi/featurelayer-amd.html#applyedits&#34;&gt;applyEdits&lt;/a&gt; method.  In reality, this is just a wrapper around the ArcGIS Server REST API&amp;rsquo;s applyEdits endpoint on an individual service layer.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Example:&lt;/em&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;https://[host]/arcgis/rest/services/[folder]/[service]/[layerid]/FeatureServer/applyEdits
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But what happens if you want to applyEdits to multiple layers within the Feature Service instead of just one layer?  You&amp;rsquo;ve got a few standard API options after constructing multiple feature layers:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Call applyEdits on each FeatureLayer with &lt;a href=&#34;https://dojotoolkit.org/api/?qs=1.10/dojo/promise/all&#34;&gt;dojo/promise/all&lt;/a&gt;:&lt;/em&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// construct FeatureLayers
flayer1 = new FeatureLayer(&amp;quot;https://MyServer/arcgis/rest/services/MyServiceFolder/MyService/0&amp;quot;);
flayer2 = new FeatureLayer(&amp;quot;https://MyServer/arcgis/rest/services/MyServiceFolder/MyService/1&amp;quot;);

// call applyEdits
var deferred1 = flayer.applyEdits(adds1, deletes1, updates1);
var deferred2 = flayer.applyEdits(adds2, deletes2, updates2);

// use dojo/All to respond to success or failure when both operations finish
all([deferred1, deferred2]).then(function(results) {
  // Do something with results.
  // Note that you&#39;ll still need to check each edit in each layer for &amp;quot;success&amp;quot;
}, function(error) {
  // uh oh, one of them failed.  
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;Chain promises for each FeatureLayer:&lt;/em&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// construct FeatureLayers
flayer1 = new FeatureLayer(&amp;quot;https://MyServer/arcgis/rest/services/MyServiceFolder/MyService/0&amp;quot;);
flayer2 = new FeatureLayer(&amp;quot;https://MyServer/arcgis/rest/services/MyServiceFolder/MyService/1&amp;quot;);

// call applyEdits
flayer.applyEdits(adds1, deletes1, updates1).then(function(result1) {
  // do something with result
  // Note that you&#39;ll still need to check each edit for &amp;quot;success&amp;quot;
  flayer2.applyEdits(adds2, deletes2, updates2).then(function(result2) {
    // do something with result
    // Note that you&#39;ll still need to check each edit for &amp;quot;success&amp;quot;
  }, function(error) {
    // flayer 2 error
  });
}, function(error) {
  // flayer 1 error
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Either of these options would work, but what if the 2 layer edits depended on each other?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Usually when I&amp;rsquo;m editing multiple layers at once, they have some sort of relation to each other.  This may or may not be defined in the database, but at any rate - if one edit fails, I&amp;rsquo;d really like the other edit to also fail so we don&amp;rsquo;t end up with an inconsistency in the database.  Additionally, wouldn&amp;rsquo;t it be nice to only send one request to the server, especially when there&amp;rsquo;s many layers?&lt;/p&gt;

&lt;h3 id=&#34;one-request-to-rule-them-all:49c8eba68da4672c57330404ff0b31cc&#34;&gt;One Request to Rule Them All&lt;/h3&gt;

&lt;p&gt;It turns out that the ArcGIS Server REST API also has an &lt;a href=&#34;https://resources.arcgis.com/en/help/rest/apiref/fsserviceedits.html&#34;&gt;applyEdits&lt;/a&gt; endpoint on the Feature Service itself - it&amp;rsquo;s just not wrapped in the web API&amp;rsquo;s.&lt;/p&gt;

&lt;p&gt;This makes it possible to send multiple edits in a single request AND make sure nothing gets stored on any layers if any one of the layer edits fails.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s nothing in the ESRI web API&amp;rsquo;s that directly hit this endpoint, so I give to you: FeatureService.js.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;bower install featureservice-esri-jsapi
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;usage:49c8eba68da4672c57330404ff0b31cc&#34;&gt;Usage:&lt;/h4&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;var package_path = window.location.pathname.substring(0, window.location.pathname.lastIndexOf(&#39;/&#39;));
var dojoConfig = {
  async: true,
  packages: [
    {
      name: &#39;feature-service&#39;,
      location: package_path + &#39;/js/lib/bower_components/featureservice-esri-jsapi/dist&#39;,
      main: &#39;FeatureService.min&#39;
    }
  ]
};

require(
  [
    &#39;feature-service&#39;
  ], function(FeatureService) {
    &#39;use strict&#39;;

    var service = new FeatureService(&amp;quot;https://[server]/arcgis/rest/MyService&amp;quot;);
    var edits = [
      {
        id: 2,  // id of layer in service
        adds: [
          addGraphic
        ],
        updates: [
          updateGraphic
        ],
        deletes: [
          1, 2  // just objectids of features to delete.
        ]
      },
      {
        id: 5,  // id of layer in service
        adds: [
          someGraphic,
          anotherGraphic,
          yetAnotherGraphic
        ]
      }
    ];

    var deferred = service.applyEdits(edits);
    deferred.then(function(result) {
      // result is an array
      // each array value contains an object with layer id and objectids of successful edits:
      /*
      [
        {
          id: int id of feature service layer
          adds: [oid, oid, oid, ...],
          updates: [oid, oid oid, ...],
          deletes: [oid, oid, oid, ...]
        },
        ...
      ]
      */
      // layer 2 results
      console.log(result[0].id);
      console.log(result[0].adds);
      console.log(result[0].updates);
      console.log(result[0].deletes);

      // layer 5 results
      console.log(result[1].id);
      console.log(result[1].adds);
      console.log(result[1].updates);
      console.log(result[1].deletes);

    }, function(error) {
      /* error callback can be called for 2 reasons
        1. Regular service faults (server 500 error, etc)
        2. One or more of the edits failed (but server still responded with 200)

        In case 1, the error is a standard esri error object with code and message.
        In case 2, the error is an object with code (200) and message plus an additional
        errors property which contains an array of error objects.
        Error object contains code, description, and id (layer id).
      */
      // case 2
      if (error.code === 200) {
        for (var i; i&amp;lt;error.errors.length; i++) {
          var err = error.errors[i];
          console.log(err.id);
          console.log(err.code);
          console.log(err.description);
        }
      }
    });
});

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Currently only the applyEdits endpoint is implemented, but this is really the most useful.  There are a couple of personal design decisions here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The service always sends rollbackOnFailure as true.  This seems to be the most likely use case.&lt;/li&gt;
&lt;li&gt;If any single edit fails, the fault handler is triggered.  This is different from the jsapi&amp;rsquo;s FeatureLayer, where even if there&amp;rsquo;s a failure, it will still trigger the success handler and you have to check each result for failures.  This class does it for you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you find this useful, please leave a comment or feel free to fork!&lt;br /&gt;
&lt;a href=&#34;https://github.com/jwerts/featureservice-esri-jsapi.git&#34;&gt;https://github.com/jwerts/featureservice-esri-jsapi.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a side note, this could have been a separate post on &lt;em&gt;&amp;ldquo;Unit testing esri Javascript API services with Karma/Mocha/Chai/Sinon&amp;rdquo;&lt;/em&gt;.  Perhaps in the future&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>arcpy.Project in_memory Featureclass</title>
      <link>https://joshwerts.com/blog/2015/09/10/arcpy-dot-project-in-memory-featureclass</link>
      <pubDate>Thu, 10 Sep 2015 00:00:00 +0000</pubDate>
      
      <guid>https://joshwerts.com/blog/2015/09/10/arcpy-dot-project-in-memory-featureclass</guid>
      <description>&lt;p&gt;It&amp;rsquo;s inevitable that you eventually run into this error when scripting with arcpy (arcpy.Project_management):
&lt;a href=&#34;https://help.arcgis.com/en%20/arcgisdesktop/10.0/help/index.html#//00vp0000000m000944.htm&#34;&gt;https://help.arcgis.com/en%20/arcgisdesktop/10.0/help/index.html#//00vp0000000m000944.htm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The standard project tool does not support in_memory workspaces.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s the workaround - we just create a new featureclass using the source featureclass as a template and then exploit the spatial_reference parameter of arcpy.da.SearchCursor to project on the fly while inserting into the new featureclass.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Function:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;from os.path import split
import arcpy

# create destination feature class using the source as a template to establish schema
# and set destination spatial reference
def project(source_fc, out_projected_fc, spatial_reference):
  &amp;quot;&amp;quot;&amp;quot; projects source_fc to out_projected_fc using cursors (supports in_memory workspace) &amp;quot;&amp;quot;&amp;quot;
  path, name = split(out_projected_fc)
  arcpy.management.CreateFeatureclass(path, name,
                                      arcpy.Describe(source_fc).shapeType,
                                      template=source_fc,
                                      spatial_reference=spatial_reference)

  # specify copy of all fields from source to destination
  fields = [&amp;quot;Shape@&amp;quot;] + [f.name for f in arcpy.ListFields(source_fc) if not f.required]

  # project source geometries on the fly while inserting to destination featureclass
  with arcpy.da.SearchCursor(source_fc, fields, spatial_reference=spatial_reference) as source_curs, \
       arcpy.da.InsertCursor(out_projected_fc, fields) as ins_curs:
      for row in source_curs:
        ins_curs.insertRow(row)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;# assume we&#39;ve already created this somewhere
source_fc = r&amp;quot;in_memory/source_fc&amp;quot;

# destination featureclass to be created
out_projected_fc = r&amp;quot;in_memory/projected_source_fc&amp;quot;

# destination projection
web_mercator = arcpy.SpatialReference(102100)

project(source_fc, out_projected_fc, web_mercator)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Edit 2016-02-04:&lt;/strong&gt; Changed to function per suggestion by &lt;a href=&#34;https://github.com/andygarfield&#34;&gt;Andy Garfield&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Debugging Server Object Extensions (SOEs) in Style</title>
      <link>https://joshwerts.com/blog/2015/04/12/debugging-server-object-extensions-soe-in-style/</link>
      <pubDate>Sun, 12 Apr 2015 00:00:00 +0000</pubDate>
      
      <guid>https://joshwerts.com/blog/2015/04/12/debugging-server-object-extensions-soe-in-style/</guid>
      <description>

&lt;p&gt;Server Object Extensions (SOEs) can be incredibly powerful, but they can also be a pain to debug.&lt;/p&gt;

&lt;h4 id=&#34;typical-workflow:2143b7784ee121ce40ff096ceffe4741&#34;&gt;Typical workflow:&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Rebuild solution&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Open ArcGIS Manager in browser -&amp;gt; Site -&amp;gt; Extensions -&amp;gt; Update Extension by selecting .soe file.&lt;/li&gt;
&lt;li&gt;Restart all of the services that depended on the SOE.&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Attach Visual Studio to process.&lt;br /&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Steps 2 &amp;amp; 3 are the really annoying ones, but they can be automated!&lt;/p&gt;

&lt;p&gt;It turns out this is really a post about REST and Python.&lt;/p&gt;

&lt;p&gt;When you update an SOE through the ArcGIS Manager app (&lt;a href=&#34;https://localhost/arcgis/manager&#34;&gt;https://localhost/arcgis/manager&lt;/a&gt;), the web application is actually making calls to ArcGIS Server REST admin endpoints.&lt;/p&gt;

&lt;h3 id=&#34;automate-with-python:2143b7784ee121ce40ff096ceffe4741&#34;&gt;Automate with Python&lt;/h3&gt;

&lt;p&gt;I&amp;rsquo;ll cut to the chase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;See the full script here:&lt;/strong&gt;&lt;br /&gt;
&lt;a href=&#34;https://github.com/jwerts/soe-updater&#34;&gt;https://github.com/jwerts/soe-updater&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Usage (simply run from command line after rebuilding SOE solution):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;C:\Projects\_General\_Code\soe-updater&amp;gt;python update_soe.py

Retrieving token...
Retrieved: oUK04q-J8ORWDUrSWGPfq8zAU29u3q5_YZ79ZvcFZx8kFneOMb5Z2Y2Yf19
Uploading SOE...
Uploaded: ibd792bae-a986-4861-8ac3-c16d42f4d610
Updating SOE...
Updated!
Starting services...
Starting service_folder/service.MapServer
Started!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Your SOE will be updated and services restarted.  You can re-attach to the service processes or if you&amp;rsquo;re using &lt;code&gt;System.Diagnostics.Debugger.Launch();&lt;/code&gt; in your &lt;code&gt;Init()&lt;/code&gt; function, you&amp;rsquo;ll automatically be greeted with the dialog to attach your process once the script finishes and the services restart.&lt;/p&gt;

&lt;p&gt;&lt;br/&gt;&lt;br/&gt;
Now a little explanation of what&amp;rsquo;s going on&amp;hellip;&lt;/p&gt;

&lt;h3 id=&#34;rest-api-calls:2143b7784ee121ce40ff096ceffe4741&#34;&gt;REST API Calls&lt;/h3&gt;

&lt;h4 id=&#34;generate-token:2143b7784ee121ce40ff096ceffe4741&#34;&gt;Generate token&lt;/h4&gt;

&lt;p&gt;Because we&amp;rsquo;re going to automate this, we need a preliminary step.  We&amp;rsquo;ll generate a token that can be passed to subsequent steps.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;https://localhost/arcgis/rest/tokens
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;upload-the-soe:2143b7784ee121ce40ff096ceffe4741&#34;&gt;Upload the SOE&lt;/h4&gt;

&lt;p&gt;The .soe file that gets generated after building in Visual Studio is uploaded to ArcGIS Server and returns an itemID.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;https://localhost/arcgis/admin/uploads/upload
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;update-the-soe:2143b7784ee121ce40ff096ceffe4741&#34;&gt;Update the SOE&lt;/h4&gt;

&lt;p&gt;Another call references the uploaded .soe through the itemID and updates the extension.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;https://localhost/arcgis/admin/services/types/extensions/update
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;restart-services:2143b7784ee121ce40ff096ceffe4741&#34;&gt;Restart services&lt;/h4&gt;

&lt;p&gt;After the SOE is updated, all services that use it are stopped and must be restarted.  This can also be accomplished through REST calls:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;https://localhost/arcgis/admin/services/[service_folder]/[service_name]/start
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These calls are all pretty straightford to automate in a Python script using the requests library (&lt;a href=&#34;https://docs.python-requests.org/en/latest/&#34;&gt;https://docs.python-requests.org/en/latest/&lt;/a&gt;).&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>arcpy.da Cursors and Readability Part 2</title>
      <link>https://joshwerts.com/blog/2014/12/21/arcpy-dot-da-cursors-and-readability-part-2/</link>
      <pubDate>Sun, 21 Dec 2014 00:00:00 +0000</pubDate>
      
      <guid>https://joshwerts.com/blog/2014/12/21/arcpy-dot-da-cursors-and-readability-part-2/</guid>
      <description>

&lt;p&gt;arcpy.da cursors provide the simplest data structure by default (tuples).  Python generators provide a pretty neat way of customizing these cursors to increase readability.&lt;/p&gt;

&lt;h3 id=&#34;searchcursor:ab62167d7f5279dad4a62ae177204a76&#34;&gt;SearchCursor:&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Return &lt;code&gt;dict&lt;/code&gt; instead of tuple:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;def rows_as_dicts(cursor):
  &amp;quot;&amp;quot;&amp;quot; returns rows as dicts (does not maintain field order) &amp;quot;&amp;quot;&amp;quot;
  colnames = cursor.fields
  for row in cursor:
    yield dict(zip(colnames, row))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Usage&lt;/strong&gt; (note the cursor is wrapped with the generator):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;total_cost_by_name = {}
with arcpy.da.SearchCursor(costs_table, [&amp;quot;name&amp;quot;, &amp;quot;unit_cost&amp;quot;, &amp;quot;quantity&amp;quot;]) as curs:
  for row in rows_as_dicts(curs):
    total_cost_by_name[row[&amp;quot;name&amp;quot;]] = row[&amp;quot;unit_cost&amp;quot;] * row[&amp;quot;quantity&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If using with an update cursor, you&amp;rsquo;ll want to use an OrderedDict so the field/value order is maintained.  You&amp;rsquo;ll also need to the use &lt;code&gt;dict.values()&lt;/code&gt; to pass an ordered tuple back into Cursor.updateRow.&lt;/p&gt;

&lt;h3 id=&#34;updatecursor:ab62167d7f5279dad4a62ae177204a76&#34;&gt;UpdateCursor:&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Return &lt;code&gt;collections.OrderedDict&lt;/code&gt; instead of tuple:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import collections
def rows_as_ordered_dicts(cursor):
  &amp;quot;&amp;quot;&amp;quot; returns rows as collections.OrderedDict &amp;quot;&amp;quot;&amp;quot;
  colnames = cursor.fields
  for row in cursor:
    yield collections.OrderedDict(zip(colnames, row))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Usage&lt;/strong&gt; (updating):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;with arcpy.da.UpdateCursor(costs_table, [&amp;quot;unit_cost&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;total_cost&amp;quot;]) as curs:
  for row in rows_as_ordered_dicts(curs):
    row[&amp;quot;total_cost&amp;quot;] = row[&amp;quot;unit_cost&amp;quot;] * row[&amp;quot;quantity&amp;quot;]

    # call .values() to convert back to tuple
    # if we didn&#39;t use OrderedDict, the values would be in random order.
    curs.updateRow( row.values() )
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>arcpy.da Cursors and Readability Part 1</title>
      <link>https://joshwerts.com/blog/2014/08/07/arcpy-dot-da-cursors/</link>
      <pubDate>Thu, 07 Aug 2014 00:00:00 +0000</pubDate>
      
      <guid>https://joshwerts.com/blog/2014/08/07/arcpy-dot-da-cursors/</guid>
      <description>

&lt;p&gt;The arcpy.da cursors (ie: arcpy.da.SearchCursor) are far and away better than the regular cursors (ie: arcpy.SearchCursor).  They&amp;rsquo;re more pythonic, incredibly flexible, faster, and allow context management (with).  However, their straight-out-of-the-box-use may be a little hard to read and maintain.&lt;/p&gt;

&lt;h3 id=&#34;fun-with-tuples:dc138d3f5428a0342b5c02b02f9dbdd9&#34;&gt;Fun with Tuples&lt;/h3&gt;

&lt;p&gt;arcpy.da cursors return tuples (instead of objects that feel too much like writing ArcObjects).&lt;/p&gt;

&lt;h4 id=&#34;good:dc138d3f5428a0342b5c02b02f9dbdd9&#34;&gt;Good:&lt;/h4&gt;

&lt;p&gt;It&amp;rsquo;s perfectly valid to use tuple indexes to access the fields:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;total_cost_by_name = {}
with arcpy.da.SearchCursor(costs_table, [&amp;quot;name&amp;quot;, &amp;quot;unit_cost&amp;quot;, &amp;quot;quantity&amp;quot;]) as curs:
    for row in curs:
        total_cost_by_name[row[0]] = row[1] * row[2]
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;better:dc138d3f5428a0342b5c02b02f9dbdd9&#34;&gt;Better:&lt;/h4&gt;

&lt;p&gt;This works fine, but the intent of our calculation is not really clear without some mental mapping.  How about this?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;total_cost_by_name = {}
with arcpy.da.SearchCursor(costs_table, [&amp;quot;name&amp;quot;, &amp;quot;unit_cost&amp;quot;, &amp;quot;quantity&amp;quot;]) as curs:
    for row in curs:
        name = row[0]
        unit_cost = row[1]
        quantity = row[2]

        total_cost_by_name[name] = unit_cost * quantity
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The intent in the calculation is much more clear here, but we&amp;rsquo;ve gained a lot of verbosity that is perhaps unnecessary.&lt;/p&gt;

&lt;h4 id=&#34;best:dc138d3f5428a0342b5c02b02f9dbdd9&#34;&gt;Best:&lt;/h4&gt;

&lt;p&gt;Of course, you could set the variables all on one line &lt;code&gt;name, unit_cost, quantity = row[0], row[1], row[2]&lt;/code&gt;, but even better would be to take advantage of python&amp;rsquo;s tuple unpacking:  &lt;code&gt;name, unit_cost, quantity = row&lt;/code&gt;.  Taking that one step further, why not unpack every tuple as it&amp;rsquo;s iterated over.  Now we have a process that is both concise and highly readable:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;total_cost_by_name = {}
with arcpy.da.SearchCursor(costs_table, [&amp;quot;name&amp;quot;, &amp;quot;unit_cost&amp;quot;, &amp;quot;quantity&amp;quot;]) as curs:
    for name, unit_cost, quantity in curs:
        total_cost_by_name[name] = unit_cost * quantity
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now what if we want to update a total cost field in the featureclass using an UpdateCursor instead?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;with arcpy.da.UpdateCursor(costs_table, [&amp;quot;unit_cost&amp;quot;, &amp;quot;quantity&amp;quot;, &amp;quot;total_cost&amp;quot;]) as curs:
    for unit_cost, quantity, total_cost in curs:
        total_cost = unit_cost * quantity
        curs.updateRow( (unit_cost, quantity, total_cost) )
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Python: Recursion with Lists</title>
      <link>https://joshwerts.com/blog/2014/06/28/python-recursion-with-lists/</link>
      <pubDate>Sat, 28 Jun 2014 00:00:00 +0000</pubDate>
      
      <guid>https://joshwerts.com/blog/2014/06/28/python-recursion-with-lists/</guid>
      <description>

&lt;p&gt;I rarely find use cases for recursion in my every day work, but every once in a while, there&amp;rsquo;s a problem that comes up where I instantly think: &amp;ldquo;Recursion!&amp;rdquo; (typically followed by an equal mix of excitement and dread).&lt;/p&gt;

&lt;p&gt;I often try to get away from GIS related programming when I&amp;rsquo;m not at work.  With limited free time, Python&amp;rsquo;s the perfect language to focus on fundamentals without getting bogged down with other concerns.&lt;/p&gt;

&lt;p&gt;Recursion is challenging enough already but I find it even more difficult to wrap my head around when the end result is intended to be a list.  I love nested functions (and closure) in Python (as long as it doesn&amp;rsquo;t get out of hand) and think it works well in this case to provide the expected simple interface to a function despite the fact that recursion is being used internally.&lt;/p&gt;

&lt;p&gt;Most of the code I write for work is proprietary and can&amp;rsquo;t be posted here, so here&amp;rsquo;s a classic problem I&amp;rsquo;ve been playing around with simply for learning purposes.&lt;/p&gt;

&lt;h4 id=&#34;code:092771151d81b7b7fd50670c6e2e1500&#34;&gt;Code:&lt;/h4&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;def prime_factors(x):
    &amp;quot;&amp;quot;&amp;quot; returns all prime factors of x
    ex:  prime_factors(21) = [3,7]
    ex:  prime_factors(24) = [2,2,2,3]
    &amp;quot;&amp;quot;&amp;quot;

    def get_first_prime(y):
        &amp;quot;&amp;quot;&amp;quot; returns first prime of y &amp;quot;&amp;quot;&amp;quot;
        # 0 and 1 are not prime, start with 2
        i = 2

        while i &amp;lt;= y:
            if y % i == 0:
                return i
            i += 1

    def get_primes(y, primes):
        &amp;quot;&amp;quot;&amp;quot; Recursively appends primes of y
            ex:  prime_factors(24) = [2,2,2,3]

            24
           /  \
          2    12
              /  \
             2    6
                 / \
                2   3

        Appends end nodes of tree as it recurses down.
        &amp;quot;&amp;quot;&amp;quot;
        first_prime = get_first_prime(y)
        primes.append(first_prime)

        if y == first_prime:
            return

        else:
            # Number is not prime and can be divided further.
            # Divide by the first prime (left node)
            # to get the next test value (right node)
            get_primes(y / first_prime, primes)


    primes = []
    if x &amp;gt;= 2:
        get_primes(x, primes)

    return primes
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;usage:092771151d81b7b7fd50670c6e2e1500&#34;&gt;Usage:&lt;/h4&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;&amp;gt;&amp;gt;&amp;gt; prime_factors(24)
[2, 2, 2, 3]
&amp;gt;&amp;gt;&amp;gt; prime_factors(13595)
[5, 7, 13, 29]
&amp;gt;&amp;gt;&amp;gt; prime_factors(23049820394)
[2, 89, 139, 181, 5147]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The list &lt;code&gt;primes&lt;/code&gt; is passed by reference into the recursive function and simply appended to throughout the operation to keep track of the values.  There is no actual return value from the function.&lt;/p&gt;

&lt;p&gt;This could be difficult to follow if the end user used: &lt;code&gt;get_primes(y, primes) -&amp;gt; void&lt;/code&gt; directly but since it&amp;rsquo;s wrapped in a simpler interface:  &lt;code&gt;prime_factors(x) -&amp;gt; primes&lt;/code&gt;, the end result is a returned list as expected.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>arcpy: Reorder Fields</title>
      <link>https://joshwerts.com/blog/2014/04/17/arcpy-reorder-fields/</link>
      <pubDate>Thu, 17 Apr 2014 00:00:00 +0000</pubDate>
      
      <guid>https://joshwerts.com/blog/2014/04/17/arcpy-reorder-fields/</guid>
      <description>&lt;p&gt;Here&amp;rsquo;s another handy function for re-ordering fields in a feature class.  Like the &lt;code&gt;rename_fields&lt;/code&gt; function previously posted, it recreates the existing field mappings and modifies as necessary.  The output is a new feature class with fields in the order specified.&lt;/p&gt;

&lt;p&gt;The only caveat is that required fields always get pushed to the front (so the featureclass will start with OBJECTID, Shape, rest of fields&amp;hellip;).  After required fields are out of the way, the rest of the fields are added in the order specified in the &lt;code&gt;field_order&lt;/code&gt; list.  If any fields are missing, they are added to the end of the feature class.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import arcpy

def reorder_fields(table, out_table, field_order, add_missing=True):
    &amp;quot;&amp;quot;&amp;quot;
    Reorders fields in input featureclass/table
    :table:         input table (fc, table, layer, etc)
    :out_table:     output table (fc, table, layer, etc)
    :field_order:   order of fields (objectid, shape not necessary)
    :add_missing:   add missing fields to end if True (leave out if False)
    -&amp;gt; path to output table
    &amp;quot;&amp;quot;&amp;quot;
    existing_fields = arcpy.ListFields(table)
    existing_field_names = [field.name for field in existing_fields]

    existing_mapping = arcpy.FieldMappings()
    existing_mapping.addTable(table)

    new_mapping = arcpy.FieldMappings()

    def add_mapping(field_name):
        mapping_index = existing_mapping.findFieldMapIndex(field_name)

        # required fields (OBJECTID, etc) will not be in existing mappings
        # they are added automatically
        if mapping_index != -1:
            field_map = existing_mapping.fieldMappings[mapping_index]
            new_mapping.addFieldMap(field_map)

    # add user fields from field_order
    for field_name in field_order:
        if field_name not in existing_field_names:
            raise Exception(&amp;quot;Field: {0} not in {1}&amp;quot;.format(field_name, table))

        add_mapping(field_name)

    # add missing fields at end
    if add_missing:
        missing_fields = [f for f in existing_field_names if f not in field_order]
        for field_name in missing_fields:
            add_mapping(field_name)

    # use merge with single input just to use new field_mappings
    arcpy.Merge_management(table, out_table, new_mapping)
    return out_table
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;new_field_order = [&amp;quot;field2&amp;quot;, &amp;quot;field3&amp;quot;, &amp;quot;field1&amp;quot;]
reorder_fields(in_fc, out_fc, new_field_order)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&amp;rsquo;ve tested this in 10.1.1+ - it may work in 10.0 as well and should work with any license level.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>