<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Sean Gillies (Posts about software engineering)</title><link>https://sgillies.net/</link><description></description><atom:link href="https://sgillies.net/tags/software-engineering.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Sun, 31 Dec 2023 01:26:22 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Box hugger no more</title><link>https://sgillies.net/2013/07/25/box-hugger-no-more.html</link><dc:creator>Sean Gillies</dc:creator><description>&lt;p&gt;I've been using zc.buildout for years now to build the Pleiades infrastructure
in a replicable way, and it's served the project well. The process of setting
up a production environment has been this:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;ssh in to production&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;git clone &lt;a class="reference external" href="https://github.com/isawnyu/pleiades3-buildout"&gt;https://github.com/isawnyu/pleiades3-buildout&lt;/a&gt; $HOME&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;cd $HOME&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;virtualenv&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;bin/python bootstrap.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;bin/buildout install zope2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;bin/buildout&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy database to $HOME/var&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Symlink $HOME to pleiades-production&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;supervisor restart all&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The buildout script yields a database server, multiple app servers, an nginx
load balancer, and Varnish caching proxy. Subsequent minor site releases are
just a matter of pulling buildout configuration files and re-running step 6.
Buildout is repeatable and, with care, idempotent. But the other steps are less
repeatable and more manual. That I use screen to keep that shell alive shows exactly
how much manual intervention is required.  Although I've automated half the
process, I've been the kind of devops person &lt;a class="reference external" href="http://www.subbu.org/blog/2013/04/code-the-infra"&gt;Subbu Allamaraju calls a "box
hugger"&lt;/a&gt;. Subbu says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Two steps to cure box hugging – first, internalize the idea that the box
you’ve just finished setting up meticulously is going to burst into flames
the very next minute, second treat operations the same way as you would treat
software development.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I'm well on the second step: all the Pleiades buildout configuration is version
controlled, if not fully tested. But the first step, not so much.&lt;/p&gt;
&lt;p&gt;I'm using a new project to reform my ways and be much less of a box hugger. To
internalize the ephemeral nature of servers, I'm teaching myself to
provision and configure &lt;a class="reference external" href="http://www.vagrantup.com/"&gt;Vagrant&lt;/a&gt; VMs with
&lt;a class="reference external" href="http://www.ansibleworks.com/tech/"&gt;Ansible&lt;/a&gt;. My goal is to be able to
deploy this project's sites to their production server using only Ansible,
never logging in at all. Having no database in this project (it's all based on
XML, on GitHub) makes this goal easier to hit. And it turns out that setting up
Solr isn't going to be too tough, either. Thanks to this &lt;a class="reference external" href="https://github.com/eosrei/ansible-multi-solr"&gt;ansible-multi-solr
project&lt;/a&gt; I've learned to write
my own very basic &lt;a class="reference external" href="https://github.com/srophe/srp-solr-server"&gt;Solr and Tomcat playbook&lt;/a&gt;. With just two commands&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code console"&gt;&lt;a id="rest_code_57d00d7cb58546a089b51724d0d82190-1" name="rest_code_57d00d7cb58546a089b51724d0d82190-1" href="https://sgillies.net/2013/07/25/box-hugger-no-more.html#rest_code_57d00d7cb58546a089b51724d0d82190-1"&gt;&lt;/a&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;vagrant up
&lt;a id="rest_code_57d00d7cb58546a089b51724d0d82190-2" name="rest_code_57d00d7cb58546a089b51724d0d82190-2" href="https://sgillies.net/2013/07/25/box-hugger-no-more.html#rest_code_57d00d7cb58546a089b51724d0d82190-2"&gt;&lt;/a&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;ansible-playbook setup.yml -k -i setup_hosts
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and a short wait, I get a running Solr instance at &lt;a class="reference external" href="http://192.168.35.10:8983/solr/"&gt;http://192.168.35.10:8983/solr/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I'm late to the party, I know, but Vagrant is killer. I'm also using it to test
packaging and installation of Shapely and Fiona. I believe it was Whit Morris
who directed me to Vagrant. Thanks, Whit!&lt;/p&gt;
&lt;p&gt;I've used neither Chef or Puppet and chose Ansible because it's Python, uses
familiar stuff like SSH and JSON, and because the playbook concept is
a reasonable leap for me from Buildout. I'm enjoying it very much and hope to
be able to contribute something to the project in time.&lt;/p&gt;
&lt;p&gt;Thanks, Subbu, for providing the impetus I needed to make the leap from box
hugging! I really would rather be developing than deploying and administering,
and feel like I'm beginning to get a grip on the tools that will make that
possible.&lt;/p&gt;
&lt;section id="comments"&gt;
&lt;h2&gt;Comments&lt;/h2&gt;
&lt;section id="re-box-hugger-no-more"&gt;
&lt;h3&gt;Re: Box hugger no more&lt;/h3&gt;
&lt;p&gt;Author: &lt;a class="reference external" href="https://sgillies.net/2013/07/25/twitter.com/mweisman"&gt;Michael Weisman&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Throw jenkins and a few lines of bash in there and you can have production or dev servers auto deploy on git commits to specific branches using the same ansible scripts you use with vagrant for local dev!&lt;/p&gt;&lt;/section&gt;
&lt;section id="re-box-hugger-no-more-1"&gt;
&lt;h3&gt;Re: Box hugger no more&lt;/h3&gt;
&lt;p&gt;Author: Sean&lt;/p&gt;
&lt;p&gt;Yes, sky's the limit! I didn't realize you were Ansible users at OpenGeo.&lt;/p&gt;&lt;/section&gt;
&lt;section id="re-box-hugger-no-more-2"&gt;
&lt;h3&gt;Re: Box hugger no more&lt;/h3&gt;
&lt;p&gt;Author: &lt;a class="reference external" href="http://www.recurse.ca"&gt;Kenshi&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There is Salt Stack, which is also Python and gaining a lot of traction. &lt;a href="http://saltstack.com/community.html"&gt;http://saltstack.com/community.html&lt;/a&gt;&lt;/p&gt;&lt;/section&gt;
&lt;/section&gt;</description><category>programming</category><category>software engineering</category><category>work</category><guid>https://sgillies.net/2013/07/25/box-hugger-no-more.html</guid><pubDate>Thu, 25 Jul 2013 06:00:00 GMT</pubDate></item><item><title>Pleiades software reuse</title><link>https://sgillies.net/2012/03/26/pleiades-software-reuse.html</link><dc:creator>Sean Gillies</dc:creator><description>&lt;p&gt;Yesterday I read Melissa Terras &lt;a class="reference external" href="http://melissaterras.blogspot.co.uk/2012/03/on-making-use-and-reuse-in-digital.html"&gt;On Making, Use and Reuse in Digital Humanities&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;That's right. The code we made is now in use by another institution, to do
their own transcription project. Hurrah!&lt;/p&gt;
&lt;p&gt;It was always our aim in Transcribe Bentham to provide the code to others: it
was a key part of our project proposal. But you always have to wonder if that
is going to happen. Its the kind of thing that everyone writes in project
proposals. And whilst lots of people talk about making things in Digital
Humanities, and whether or not you have to make things to be a Digital
Humanist, we've shied away - as a community - from the spectre of reuse: who
takes our code and reappropriates it once we are done? How can we demonstrate
impact through the things we've built being utilised beyond just us and
- quite frankly - our mates?&lt;/p&gt;
&lt;p&gt;So I'm happy as larry that the code we developed, and the system we have
built, is both useful to us, but is now useful to others. I'm not sure how
much I want to prod the sleeping monster that is general code reuse in
Digital Humanities... dont draw attention to our deficiencies!&lt;/p&gt;
&lt;p&gt;But I would be delighted if anyone else could point me to examples where code
and systems in Digital Humanities were repurposed beyond their original
project, just as we would wish?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I was unable to persuade Recaptcha to let me leave a comment and
congratulations on Melissa's blog, so am writing a brief post here. &lt;em&gt;TL;DR
Transcribe Bentham: congrats! My own horn: toot! toot!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To my knowledge, no one has set up another instance of Pleiades as a gazetteer.
But code written for Pleiades gets reused more and more widely the further down
in our stack you look. I designed it to be modular and reusable – a stack of
tools, not a single tool – so I'd be disappointed if that wasn't the case. I'll
explain how it works for us.&lt;/p&gt;
&lt;p&gt;Pleiades uses the Plone (and Zope) web application framework. Our Plone
products and packages have taken on a life of their own as the &lt;a class="reference external" href="http://www.coactivate.org/projects/collectivegeo/summary"&gt;collective.geo&lt;/a&gt; project.
&lt;a class="reference external" href="http://iwlearn.net/iw-projects/basin_view.html"&gt;IW:LEARN&lt;/a&gt; is a good example
of a collective.geo site. Contributions to collective.geo by almost 20 other
people have been making Pleiades better. And this is just the start of our
reuse story.&lt;/p&gt;
&lt;p&gt;Pleiades and collective.geo Zope and Plone packages are based on Python GIS
packages spun off from Pleiades such as Shapely, Rtree, and Geojson. At PyCon
a couple of weeks ago, I ran into a lot of Shapely users. I saw it mentioned on
slides in talks and on posters in the poster session. Famous web and geography
hackers even write about using Shapely &lt;a class="reference external" href="http://pleiades.stoa.org/Members/sgillies/news-items/praise-for-pleiades-spin-off-software"&gt;from time to time&lt;/a&gt;.
Shapely feature-wise, Pleiades now &lt;a class="reference external" href="http://pleiades.stoa.org/Members/sgillies/news-items/pleiades-spin-offs-shapely"&gt;gets as much back from others as we give
out&lt;/a&gt;.
This is a fantastic position to be in.&lt;/p&gt;
&lt;p&gt;Digging deeper in the stack, I've contributed (&lt;a class="reference external" href="http://www.ohloh.net/p/geos/contributors"&gt;as "sgillies"&lt;/a&gt;) to the development of GEOS as
part of my work on Pleiades, so Pleiades has thereby played a tiny role in
making thousands of open source GIS programs and web sites more spatially
capable. A Python protocol for sharing geospatial data that we invented for
Pleiades has been implemented rather widely in GIS software. Anywhere you see
&lt;code class="docutils literal"&gt;__geo_interface__&lt;/code&gt; and &lt;code class="docutils literal"&gt;shape()&lt;/code&gt; or &lt;code class="docutils literal"&gt;asShape()&lt;/code&gt;, or programmers &lt;a class="reference external" href="http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//000v00000153000000"&gt;sharing
data as GeoJSON-like Python mappings&lt;/a&gt;,
that's the impact of Pleiades. The &lt;a class="reference external" href="http://geojson.org"&gt;GeoJSON format&lt;/a&gt;
itself has some of its roots in Pleiades.&lt;/p&gt;
&lt;p&gt;Even if no one ever sets up another Pleiades site, we're having a significant
impact on GIS software and systems, even on big time GIS software being used
for Spatial Humanities work. The keys to having a similar impact are, in my mind, 1)
modularization and generalization to increase the number of potential users and
contributors, and 2) a policy of open sourcing from day zero instead of open
sourcing after completion of the project – and after people have lost interest
and moved on to other software.&lt;/p&gt;
&lt;section id="comments"&gt;
&lt;h2&gt;Comments&lt;/h2&gt;
&lt;section id="open-sourcing-from-day-zero"&gt;
&lt;h3&gt;open sourcing from day zero&lt;/h3&gt;
&lt;p&gt;Author: &lt;a class="reference external" href="http://iwlearn.net/"&gt;Christian Ledermann&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;+1&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Release often, release early. It is important to let the community know what you are up to, though it might feel a little embarrassing to make unfinished buggy alpha code available to the public it has big advantages. E.g. when I released the alpha of collective.geo.index the UI was unfinished and ugly, not one of my priorities. It would probably still be unfinished and ugly if it was not for David who gave the UI some TLC just days after the initial announcement.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Thank you very much for your hard work and your great products :)&lt;/p&gt;&lt;/section&gt;
&lt;/section&gt;</description><category>community</category><category>digital humanities</category><category>programming</category><category>software engineering</category><category>work</category><guid>https://sgillies.net/2012/03/26/pleiades-software-reuse.html</guid><pubDate>Mon, 26 Mar 2012 06:00:00 GMT</pubDate></item><item><title>Simple and reusable spatial queries</title><link>https://sgillies.net/2009/12/18/simple-and-reusable-spatial-queries.html</link><dc:creator>Sean Gillies</dc:creator><description>&lt;p&gt;Quoting &lt;a class="reference external" href="http://www.spatiallyadjusted.com/2009/12/16/the-google-maps-data-api-and-google-fusion-api-news/"&gt;James Fee&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;First we’ve got new functionality in the Google Maps Data API.  First off you
can now perform geospatial and attribution queries on data stored on Google’s
MyMap.  Now of course this isn’t paleo-type spatial queries, just simple
stuff that solve 80% of all queries you’d need to complete.  Simple web apps
need not fancy complicated APIs and clearly Google is the master of this.  So
upload your data into Google’s My Maps and then query it to display on a
Google Maps application.  Simple and sweet.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is also sweet from an engineering perspective. Yes, simple bounding box or
radius search are "only" "80-20 rule" features, but at the same time are also
features that power users are going to use almost 100 percent of the time for a
lot of tasks. In other words: highly reusable features. Let's say you want to select features of a collection that are
contained within another feature. You could build up a result set by iterating
over each feature in the collection no matter where it is and evaluate
containment with the filtering feature for every single one of them. Better yet
would be to first eliminate candidate features that aren't even in the same
ballpark as the filtering feature by using an indexed bounding box search. This
is the default mode of operation for newer functions in PostGIS, for example,
like &lt;a class="reference external" href="http://postgis.org/documentation/manual-svn/ST_Contains.html"&gt;ST_Contains&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This function call will automatically include a bounding box comparison that
will make use of any indexes that are available on the geometries. To avoid
index use, use the function _ST_Contains.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(By the way, nice new docs there, PostGIS people!) Simple indexed search is the initial boost to more interesting queries. Indexed
operations are best provided by the map data collections themselves. Higher
order processing, some of which can be done in parallel, can be left to other
resources or services. This is, of course (except for the parallel
considerations), the premise of the OGC's &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Web_Processing_Service"&gt;Web Processing Service&lt;/a&gt;, but taken
to an extreme where a WFS provides only bounding box and attribute filtering
and the WPS does everything else. A familiar pattern, but I'd be surprised if a
future Google spatial data processing platform wasn't as different from OGC WPS
as the maps data API is from WFS.&lt;/p&gt;</description><category>architecture</category><category>software engineering</category><category>web</category><category>work</category><guid>https://sgillies.net/2009/12/18/simple-and-reusable-spatial-queries.html</guid><pubDate>Fri, 18 Dec 2009 07:00:00 GMT</pubDate></item><item><title>Unofficial Python GIS SIG</title><link>https://sgillies.net/2009/09/30/unofficial-python-gis-sig.html</link><dc:creator>Sean Gillies</dc:creator><description>&lt;p&gt;There was a discussion on the GIS-Python list that made me think that there ought to be a discussion group that helps developers communicate across projects, share good ideas, and generally improve Python's GIS story, much like the Python &lt;a class="reference external" href="http://www.python.org/community/sigs/current/web-sig/"&gt;Web-SIG&lt;/a&gt; list does for web software developers. Please help spread word of the &lt;a class="reference external" href="http://groups.google.com/group/python-gis-sig"&gt;Unofficial Python GIS SIG&lt;/a&gt;.&lt;/p&gt;
&lt;section id="comments"&gt;
&lt;h2&gt;Comments&lt;/h2&gt;
&lt;section id="re-unofficial-python-gis-sig"&gt;
&lt;h3&gt;Re: Unofficial Python GIS SIG&lt;/h3&gt;
&lt;p&gt;Author: Timmie&lt;/p&gt;
&lt;p&gt;It's a great idea!&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;I added this to the OSGEO wiki at&lt;/p&gt;&lt;a href="http://wiki.osgeo.org/wiki/OSGeo_Python_Library#Communication"&gt;OSGeo Python Library&lt;/a&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Will you advertise it on the mailing list of GRASS, QGIS, gvSIG, Mapfish, featureserver/tilecache?&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Keep on!&lt;/p&gt;&lt;/section&gt;
&lt;section id="re-unofficial-python-gis-sig-1"&gt;
&lt;h3&gt;Re: Unofficial Python GIS SIG&lt;/h3&gt;
&lt;p&gt;Author: Sean&lt;/p&gt;
&lt;p&gt;I'm not a subscriber to those particular lists and am counting on others to spread the word. The MapFish developers are on board already.&lt;/p&gt;&lt;/section&gt;
&lt;/section&gt;</description><category>architecture</category><category>community</category><category>programming</category><category>python</category><category>software engineering</category><category>work</category><guid>https://sgillies.net/2009/09/30/unofficial-python-gis-sig.html</guid><pubDate>Wed, 30 Sep 2009 06:00:00 GMT</pubDate></item><item><title>On web sanity</title><link>https://sgillies.net/2009/09/07/on-web-sanity.html</link><dc:creator>Sean Gillies</dc:creator><description>&lt;p&gt;Stefan Tilkov, who has written an excellent &lt;a class="reference external" href="http://www.infoq.com/articles/rest-introduction"&gt;REST introduction&lt;/a&gt; and an analysis of &lt;a class="reference external" href="http://www.infoq.com/articles/rest-anti-patterns"&gt;REST anti-patterns&lt;/a&gt; has some criticism for enterprise web apps that &lt;a class="reference external" href="http://www.innoq.com/blog/st/2009/09/the_web_in_the_enterprise.html"&gt;applies&lt;/a&gt; equally well to "GeoWeb" apps:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In other words: Many web frameworks, especially those within the Java space, try to support the development of desktop applications that are delivered over the Web as opposed to “web sites”, and I believe this idea is deeply flawed: Any Web application should be measured against the criteria that are used to judge web sites.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think this goes for the "GeoWeb" too. We're delivering too much desktop GIS over the web. It's a point made also by Brian Noyle &lt;a class="reference external" href="http://briannoyle.wordpress.com/2009/07/03/useability-and-the-geoweb-part-1-of/"&gt;here&lt;/a&gt;, though I see Flex, Silverlight, .NET, and MVC as parts of the problem, not the solution.&lt;/p&gt;
&lt;section id="comments"&gt;
&lt;h2&gt;Comments&lt;/h2&gt;
&lt;section id="re-on-web-sanity"&gt;
&lt;h3&gt;Re: On web sanity&lt;/h3&gt;
&lt;p&gt;Author: Tim Bowden&lt;/p&gt;
&lt;p&gt;Those links are great thanks Sean.  I'm developing a desktop app replacement on the web atm, and that material has clarified some of the issues I've been mulling over.  I probably won't get it all right this time around, but I'll certainly get closer than I was going to get.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;I've previously looked briefly at the idea of RESTful apps, but not in any great detail or real understanding.  Now I am, and it's certainly an interesting journey.  The app I'm replacing is definitely very much in the traditional desktop space (with a legacy stretching back all the way from its DOS roots; think reverse engineering very old and poorly documented binary data formats).  It doesn't *look* like a candidate to be a 'website' type app, as opposed to a 'desktop app on the web'.  The requirements *seem* to point that way, that is until you dissect it bit by bit using a RESTful scalpel.  I'm not sure how far I'm going to be able to push this model, either because of limitations in my skill and understanding or limitations in the RESTful model, but I'm keen to see where I can go with this.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;It's a good thing this is a relatively simple app, as using a RESTful scalpel for the first time isn't so easy.  Old mental models of what desktop apps should look like and how they should behave keep getting in the way.  I've still not gone very far on this journey (I've not tried implementing any of this yet; next step!), but so far every issue seems to have been answered by sharpening my RESTful scalpel a little more.  I think one of the hardest ideas to come to terms with is the idea of “hypermedia as the engine of application state”.  All those 'client side' data structures start to melt into very ephemeral constructions.  Implementing that is going to be an interesting experience for sure.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Sean, keep pushing the REST barrow.  I'm very much a novice, but from my perspective so far, it *seems* to be a winner, despite the mental difficulty of overcoming deeply ingrained ideas from the desktop environment.  Hopefully I'll not be too shell shocked when I come out the other side!&lt;/p&gt;&lt;/section&gt;
&lt;/section&gt;</description><category>architecture</category><category>software engineering</category><category>web</category><category>work</category><guid>https://sgillies.net/2009/09/07/on-web-sanity.html</guid><pubDate>Mon, 07 Sep 2009 06:00:00 GMT</pubDate></item><item><title>Plugins for Shapely</title><link>https://sgillies.net/2009/02/19/plugins-for-shapely.html</link><dc:creator>Sean Gillies</dc:creator><description>&lt;p&gt;I haven't started working on any pure Python (for App Engine) geometry predicates or operators, or any other alternatives to GEOS, but I've begun to make it possible. All GEOS dependency is being moved to its own shapely.geos module, which will be the default plugin provider for Shapely's new plugin framework.&lt;/p&gt;
&lt;p&gt;The framework defines a few interfaces (geometry compiling or checking provider, area and length provider, bounds provider, etc) and entry points. When a geometry is asked to compute its bounds, for example, it delegates to a provider that has been wired up to the geometry factory on import. Here's a peek at how the default providers are registered in Shapely's setup.py:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code python"&gt;&lt;a id="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-1" name="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-1" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_2f8a135d4aa44dc08577b37fd133f1b9-1"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;a id="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-2" name="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-2" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_2f8a135d4aa44dc08577b37fd133f1b9-2"&gt;&lt;/a&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Shapely'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-3" name="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-3" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_2f8a135d4aa44dc08577b37fd133f1b9-3"&gt;&lt;/a&gt;      &lt;span class="n"&gt;version&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'1.1.0'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-4" name="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-4" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_2f8a135d4aa44dc08577b37fd133f1b9-4"&gt;&lt;/a&gt;      &lt;span class="o"&gt;...&lt;/span&gt;
&lt;a id="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-5" name="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-5" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_2f8a135d4aa44dc08577b37fd133f1b9-5"&gt;&lt;/a&gt;      &lt;span class="n"&gt;entry_points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;a id="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-6" name="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-6" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_2f8a135d4aa44dc08577b37fd133f1b9-6"&gt;&lt;/a&gt;&lt;span class="s2"&gt;          [shapely.geometry]&lt;/span&gt;
&lt;a id="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-7" name="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-7" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_2f8a135d4aa44dc08577b37fd133f1b9-7"&gt;&lt;/a&gt;&lt;span class="s2"&gt;          geometryChecker=shapely.geos.geometry:geometryChecker&lt;/span&gt;
&lt;a id="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-8" name="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-8" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_2f8a135d4aa44dc08577b37fd133f1b9-8"&gt;&lt;/a&gt;&lt;span class="s2"&gt;          metricProperties=shapely.geos.metrics:metricProperties&lt;/span&gt;
&lt;a id="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-9" name="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-9" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_2f8a135d4aa44dc08577b37fd133f1b9-9"&gt;&lt;/a&gt;&lt;span class="s2"&gt;          geometryProperties=shapely.geos.topology:geometryProperties&lt;/span&gt;
&lt;a id="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-10" name="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-10" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_2f8a135d4aa44dc08577b37fd133f1b9-10"&gt;&lt;/a&gt;&lt;span class="s2"&gt;          """&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-11" name="rest_code_2f8a135d4aa44dc08577b37fd133f1b9-11" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_2f8a135d4aa44dc08577b37fd133f1b9-11"&gt;&lt;/a&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And in shapely.geometry, the providers are activated with a function:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code python"&gt;&lt;a id="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-1" name="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-1" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-1"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;a id="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-2" name="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-2" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-2"&gt;&lt;/a&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Shapely&amp;gt;=1.1.0'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-3" name="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-3" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-3"&gt;&lt;/a&gt;
&lt;a id="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-4" name="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-4" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-4"&gt;&lt;/a&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;geo&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;asShape&lt;/span&gt;
&lt;a id="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-5" name="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-5" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-5"&gt;&lt;/a&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;point&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="n"&gt;asPoint&lt;/span&gt;
&lt;a id="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-6" name="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-6" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-6"&gt;&lt;/a&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;linestring&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LineString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;asLineString&lt;/span&gt;
&lt;a id="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-7" name="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-7" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-7"&gt;&lt;/a&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;polygon&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Polygon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;asPolygon&lt;/span&gt;
&lt;a id="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-8" name="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-8" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-8"&gt;&lt;/a&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;multipoint&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MultiPoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;asMultiPoint&lt;/span&gt;
&lt;a id="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-9" name="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-9" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-9"&gt;&lt;/a&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;multilinestring&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MultiLineString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;asMultiLineString&lt;/span&gt;
&lt;a id="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-10" name="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-10" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-10"&gt;&lt;/a&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;multipolygon&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MultiPolygon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;asMultiPolygon&lt;/span&gt;
&lt;a id="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-11" name="rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-11" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_21b2d60dc74e4b4cbb35ec1cfcda701d-11"&gt;&lt;/a&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;collection&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GeometryCollection&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Users can override the default GEOS providers by writing and installing (with setuptools) new packages that provide the same named end points, and "using" those at run time:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code python"&gt;&lt;a id="rest_code_64041a5ec32449a2bf0602a196c36dd3-1" name="rest_code_64041a5ec32449a2bf0602a196c36dd3-1" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_64041a5ec32449a2bf0602a196c36dd3-1"&gt;&lt;/a&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;shapely&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;geometry&lt;/span&gt;
&lt;a id="rest_code_64041a5ec32449a2bf0602a196c36dd3-2" name="rest_code_64041a5ec32449a2bf0602a196c36dd3-2" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_64041a5ec32449a2bf0602a196c36dd3-2"&gt;&lt;/a&gt;&lt;span class="n"&gt;geometry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'MyGeometry'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_64041a5ec32449a2bf0602a196c36dd3-3" name="rest_code_64041a5ec32449a2bf0602a196c36dd3-3" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_64041a5ec32449a2bf0602a196c36dd3-3"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;a id="rest_code_64041a5ec32449a2bf0602a196c36dd3-4" name="rest_code_64041a5ec32449a2bf0602a196c36dd3-4" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_64041a5ec32449a2bf0602a196c36dd3-4"&gt;&lt;/a&gt;
&lt;a id="rest_code_64041a5ec32449a2bf0602a196c36dd3-5" name="rest_code_64041a5ec32449a2bf0602a196c36dd3-5" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_64041a5ec32449a2bf0602a196c36dd3-5"&gt;&lt;/a&gt;&lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;geometry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_64041a5ec32449a2bf0602a196c36dd3-6" name="rest_code_64041a5ec32449a2bf0602a196c36dd3-6" href="https://sgillies.net/2009/02/19/plugins-for-shapely.html#rest_code_64041a5ec32449a2bf0602a196c36dd3-6"&gt;&lt;/a&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# calls on provider defined by MyGeometry package&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In theory, this makes it possible to a write an application using Shapely that can run on either C Python, Jython, or IronPython using the appropriate backend for the platform, as long as setuptools and pkg_resources work. I've read that they will in the next Jython release. IronPython seems to be a little farther behind. In practice, the plugin framework is helping to improve the testability and quality of Shapely's code.&lt;/p&gt;
&lt;section id="comments"&gt;
&lt;h2&gt;Comments&lt;/h2&gt;
&lt;section id="re-plugins-for-shapely"&gt;
&lt;h3&gt;Re: Plugins for Shapely&lt;/h3&gt;
&lt;p&gt;Author: brent&lt;/p&gt;
&lt;p&gt;thanks sean. very cool.&lt;/p&gt;&lt;p&gt;for those who didnt know about setuptools entry points, this is a good intro:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lucumr.pocoo.org/blogarchive/setuptools-plugins"&gt;http://lucumr.pocoo.org/blogarchive/setuptools-plugins&lt;/a&gt;&lt;/p&gt;&lt;/section&gt;
&lt;/section&gt;</description><category>python</category><category>software engineering</category><category>the lab</category><category>work</category><guid>https://sgillies.net/2009/02/19/plugins-for-shapely.html</guid><pubDate>Thu, 19 Feb 2009 07:00:00 GMT</pubDate></item><item><title>In order to form a more perfect union</title><link>https://sgillies.net/2009/01/23/in-order-to-form-a-more-perfect-union.html</link><dc:creator>Sean Gillies</dc:creator><description>&lt;p&gt;Paul Ramsey on GEOS 3.1 and PostGIS 1.4 &lt;a class="reference external" href="http://blog.cleverelephant.ca/2009/01/must-faster-unions-in-postgis-14.html"&gt;improvements&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here's a less contrived result, the 3141 counties in the United States. Using the old ST_Union(), the union takes 42 seconds. Using the new ST_Union() (coming in PostGIS 1.4.0) the union takes 3.7 seconds.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now that's change we can believe in.&lt;/p&gt;
&lt;section id="comments"&gt;
&lt;h2&gt;Comments&lt;/h2&gt;
&lt;section id="re-in-order-to-form-a-more-perfect-union"&gt;
&lt;h3&gt;Re: In order to form a more perfect union&lt;/h3&gt;
&lt;p&gt;Author: Guillaume&lt;/p&gt;
Yes, we can !&lt;/section&gt;
&lt;/section&gt;</description><category>software engineering</category><category>work</category><guid>https://sgillies.net/2009/01/23/in-order-to-form-a-more-perfect-union.html</guid><pubDate>Fri, 23 Jan 2009 07:00:00 GMT</pubDate></item><item><title>Mocking GEOS</title><link>https://sgillies.net/2009/01/20/mocking-geos.html</link><dc:creator>Sean Gillies</dc:creator><description>&lt;p&gt;My use of mocks isn't as sophisticated as &lt;a class="reference external" href="http://blog.davebouwman.net/Default.aspx"&gt;Dave's&lt;/a&gt;, perhaps, but I stumbled onto a simple testing pattern that might be useful to other Python geospatial/GIS developers who are wrapping C libs using ctypes.&lt;/p&gt;
&lt;p&gt;Consider Shapely: it wraps the GEOS library, the quality and accuracy of which we take as a given (though not blindly, because I do contribute fixes and enhancements to GEOS). The predicates and topological functions of GEOS are called from within Python descriptors, classes that perform argument validation and handle GEOS errors. For Shapely, I'm testing these descriptors, the GEOS wrappers, not GEOS itself. What pair of geometries would I have to pass to GEOSDisjoint (for example) in order to get the return value of 2 that signifies an error? Even if known, they might be subject to issues of numerical precision, or be sensitive to changes in GEOS. I'd rather not fuss with this. Instead, I want some function to stand in for GEOSDisjoint and friends, one that takes 2 arguments and has very predictable return values in the range (0, 1, 2). A function like libc's strcmp():&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code python"&gt;&lt;a id="rest_code_2c57c66320304ce390a6ccf61cabf166-1" name="rest_code_2c57c66320304ce390a6ccf61cabf166-1" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_2c57c66320304ce390a6ccf61cabf166-1"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;ctypes&lt;/span&gt;
&lt;a id="rest_code_2c57c66320304ce390a6ccf61cabf166-2" name="rest_code_2c57c66320304ce390a6ccf61cabf166-2" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_2c57c66320304ce390a6ccf61cabf166-2"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;libc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctypes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CDLL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'libc.dylib'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# this is OS X&lt;/span&gt;
&lt;a id="rest_code_2c57c66320304ce390a6ccf61cabf166-3" name="rest_code_2c57c66320304ce390a6ccf61cabf166-3" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_2c57c66320304ce390a6ccf61cabf166-3"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;libc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_2c57c66320304ce390a6ccf61cabf166-4" name="rest_code_2c57c66320304ce390a6ccf61cabf166-4" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_2c57c66320304ce390a6ccf61cabf166-4"&gt;&lt;/a&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;a id="rest_code_2c57c66320304ce390a6ccf61cabf166-5" name="rest_code_2c57c66320304ce390a6ccf61cabf166-5" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_2c57c66320304ce390a6ccf61cabf166-5"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;libc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\1&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_2c57c66320304ce390a6ccf61cabf166-6" name="rest_code_2c57c66320304ce390a6ccf61cabf166-6" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_2c57c66320304ce390a6ccf61cabf166-6"&gt;&lt;/a&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;a id="rest_code_2c57c66320304ce390a6ccf61cabf166-7" name="rest_code_2c57c66320304ce390a6ccf61cabf166-7" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_2c57c66320304ce390a6ccf61cabf166-7"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;libc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\2&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_2c57c66320304ce390a6ccf61cabf166-8" name="rest_code_2c57c66320304ce390a6ccf61cabf166-8" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_2c57c66320304ce390a6ccf61cabf166-8"&gt;&lt;/a&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Meaningless, but handy, isomorphism between strcmp() and GEOS binary operations in hand, a generic wrapper for GEOS can be fully tested like this:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code python"&gt;&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-1" name="rest_code_124cfbf6ff064bf58334b082560bda75-1" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-1"&gt;&lt;/a&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;ctypes&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-2" name="rest_code_124cfbf6ff064bf58334b082560bda75-2" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-2"&gt;&lt;/a&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-3" name="rest_code_124cfbf6ff064bf58334b082560bda75-3" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-3"&gt;&lt;/a&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-4" name="rest_code_124cfbf6ff064bf58334b082560bda75-4" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-4"&gt;&lt;/a&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;shapely&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;predicates&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-5" name="rest_code_124cfbf6ff064bf58334b082560bda75-5" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-5"&gt;&lt;/a&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-6" name="rest_code_124cfbf6ff064bf58334b082560bda75-6" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-6"&gt;&lt;/a&gt;&lt;span class="n"&gt;BN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;libc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strcmp&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-7" name="rest_code_124cfbf6ff064bf58334b082560bda75-7" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-7"&gt;&lt;/a&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-8" name="rest_code_124cfbf6ff064bf58334b082560bda75-8" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-8"&gt;&lt;/a&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompMockGeom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-9" name="rest_code_124cfbf6ff064bf58334b082560bda75-9" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-9"&gt;&lt;/a&gt;    &lt;span class="c1"&gt;# Values chosen with libc.strcmp in mind&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-10" name="rest_code_124cfbf6ff064bf58334b082560bda75-10" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-10"&gt;&lt;/a&gt;    &lt;span class="n"&gt;vals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\1&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\2&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-11" name="rest_code_124cfbf6ff064bf58334b082560bda75-11" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-11"&gt;&lt;/a&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-12" name="rest_code_124cfbf6ff064bf58334b082560bda75-12" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-12"&gt;&lt;/a&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_geom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctypes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c_char_p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vals&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-13" name="rest_code_124cfbf6ff064bf58334b082560bda75-13" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-13"&gt;&lt;/a&gt;    &lt;span class="n"&gt;comp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;predicates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BinaryPredicate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-14" name="rest_code_124cfbf6ff064bf58334b082560bda75-14" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-14"&gt;&lt;/a&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-15" name="rest_code_124cfbf6ff064bf58334b082560bda75-15" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-15"&gt;&lt;/a&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BinaryPredicateAttributeTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-16" name="rest_code_124cfbf6ff064bf58334b082560bda75-16" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-16"&gt;&lt;/a&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-17" name="rest_code_124cfbf6ff064bf58334b082560bda75-17" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-17"&gt;&lt;/a&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_bin_false&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-18" name="rest_code_124cfbf6ff064bf58334b082560bda75-18" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-18"&gt;&lt;/a&gt;        &lt;span class="n"&gt;g1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CompMockGeom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-19" name="rest_code_124cfbf6ff064bf58334b082560bda75-19" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-19"&gt;&lt;/a&gt;        &lt;span class="n"&gt;g2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CompMockGeom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-20" name="rest_code_124cfbf6ff064bf58334b082560bda75-20" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-20"&gt;&lt;/a&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;comp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-21" name="rest_code_124cfbf6ff064bf58334b082560bda75-21" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-21"&gt;&lt;/a&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-22" name="rest_code_124cfbf6ff064bf58334b082560bda75-22" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-22"&gt;&lt;/a&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_bin_true&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-23" name="rest_code_124cfbf6ff064bf58334b082560bda75-23" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-23"&gt;&lt;/a&gt;        &lt;span class="n"&gt;g1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CompMockGeom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-24" name="rest_code_124cfbf6ff064bf58334b082560bda75-24" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-24"&gt;&lt;/a&gt;        &lt;span class="n"&gt;g2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CompMockGeom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-25" name="rest_code_124cfbf6ff064bf58334b082560bda75-25" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-25"&gt;&lt;/a&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;comp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-26" name="rest_code_124cfbf6ff064bf58334b082560bda75-26" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-26"&gt;&lt;/a&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-27" name="rest_code_124cfbf6ff064bf58334b082560bda75-27" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-27"&gt;&lt;/a&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_bin_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-28" name="rest_code_124cfbf6ff064bf58334b082560bda75-28" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-28"&gt;&lt;/a&gt;        &lt;span class="n"&gt;g1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CompMockGeom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-29" name="rest_code_124cfbf6ff064bf58334b082560bda75-29" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-29"&gt;&lt;/a&gt;        &lt;span class="n"&gt;g2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CompMockGeom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_124cfbf6ff064bf58334b082560bda75-30" name="rest_code_124cfbf6ff064bf58334b082560bda75-30" href="https://sgillies.net/2009/01/20/mocking-geos.html#rest_code_124cfbf6ff064bf58334b082560bda75-30"&gt;&lt;/a&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;predicates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PredicateError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;g1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;comp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;g2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;section id="comments"&gt;
&lt;h2&gt;Comments&lt;/h2&gt;
&lt;section id="re-mocking-geos"&gt;
&lt;h3&gt;Re: Mocking GEOS&lt;/h3&gt;
&lt;p&gt;Author: &lt;a class="reference external" href="https://sgillies.net/2009/01/20/ajfowler.wordpress.com"&gt;ajfowler&lt;/a&gt;&lt;/p&gt;
Hi,

Unrelated to this post, but I came across one of your old blog posts about web-mapping accessibility.  Is this topic off of your radar now?

aj&lt;/section&gt;
&lt;section id="re-mocking-geos-1"&gt;
&lt;h3&gt;Re: Mocking GEOS&lt;/h3&gt;
&lt;p&gt;Author: Sean&lt;/p&gt;
Yes, but it looks like it's on yours. What's up with web map accessibility?&lt;/section&gt;
&lt;section id="re-mocking-geos-2"&gt;
&lt;h3&gt;Re: Mocking GEOS&lt;/h3&gt;
&lt;p&gt;Author: &lt;a class="reference external" href="http://ajfowler.wordpress.com/"&gt;ajfowler&lt;/a&gt;&lt;/p&gt;
Well I'm looking into creating a text description of a map. There aren't a lot of resources out there, but I'm avidly searching.&lt;/section&gt;
&lt;/section&gt;</description><category>programming</category><category>python</category><category>software engineering</category><category>the lab</category><category>work</category><guid>https://sgillies.net/2009/01/20/mocking-geos.html</guid><pubDate>Tue, 20 Jan 2009 07:00:00 GMT</pubDate></item><item><title>I can has Python and GIS environments?</title><link>https://sgillies.net/2008/12/23/i-can-has-python-and-gis-environments.html</link><dc:creator>Sean Gillies</dc:creator><description>&lt;p&gt;I've spent this short week tuning up my new laptop's development environment, and a side effect of this work is a new build system for replicable, isolated Python, GIS, and image/raster processing environments. &lt;a class="reference external" href="http://github.com/sgillies/ichpage/tree/master"&gt;Ichpage&lt;/a&gt; replaces &lt;a class="reference external" href="http://sgillies.net/blog/638/replicable-python-geoprocessing-environments/"&gt;Gdawg&lt;/a&gt; on my machine. It supplies:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GDAL (osgeo.gdal, etc)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;geojson&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;geopy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;keytree&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;lxml&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Numpy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PIL&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PyProj&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rtree&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Shapely&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and their various library dependencies (libgdal, libgeos_c, libspatialindex, libxml2, libxslt). To get started, clone or get the &lt;a class="reference external" href="http://github.com/sgillies/ichpage/tarball/master"&gt;tarball&lt;/a&gt;, cd into the directory, and execute:&lt;/p&gt;
&lt;pre class="literal-block"&gt;$ virtualenv .
$ source ./bin/activate
(ichpage)$ python bootstrap.py
(ichpage)$ buildout
(ichpage)$ . ./setenv
(ichpage)$ labpy
&amp;gt;&amp;gt;&amp;gt; from osgeo import gdal
&amp;gt;&amp;gt;&amp;gt; from shapely.geometry import Point
...&lt;/pre&gt;
&lt;p&gt;To do tasks include linking the GDAL utilities into the environment's bin directory, adding WorldMill, perhaps adding matplotlib. For now, it's a way for me to manage C libs while I develop Shapely and Rtree, and perhaps useful to other geospatial Python developers.&lt;/p&gt;
&lt;section id="comments"&gt;
&lt;h2&gt;Comments&lt;/h2&gt;
&lt;section id="re-i-can-has-python-and-gis-environments"&gt;
&lt;h3&gt;Re: I can has Python and GIS environments?&lt;/h3&gt;
&lt;p&gt;Author: &lt;a class="reference external" href="http://schwehr.org"&gt;Kurt&lt;/a&gt;&lt;/p&gt;
keytree?&lt;/section&gt;
&lt;section id="re-i-can-has-python-and-gis-environments-1"&gt;
&lt;h3&gt;Re: I can has Python and GIS environments?&lt;/h3&gt;
&lt;p&gt;Author: Sean&lt;/p&gt;
&lt;a href="http://sgillies.net/blog/750/keytree/"&gt;Keytree&lt;/a&gt; is a little KML helper for use with Python ElementTree APIs.&lt;/section&gt;
&lt;/section&gt;</description><category>python</category><category>software engineering</category><category>the lab</category><category>work</category><guid>https://sgillies.net/2008/12/23/i-can-has-python-and-gis-environments.html</guid><pubDate>Tue, 23 Dec 2008 07:00:00 GMT</pubDate></item><item><title>Preserving first-generation web/GIS projects</title><link>https://sgillies.net/2008/12/22/preserving-first-generation-webgis-projects.html</link><dc:creator>Sean Gillies</dc:creator><description>&lt;p&gt;Check out this interesting &lt;a class="reference external" href="http://journal.code4lib.org/articles/685"&gt;article&lt;/a&gt; about the &lt;a class="reference external" href="http://herbarium.lsa.umich.edu/website/michflora/onlinemaps.html"&gt;reanimation&lt;/a&gt; of an orphaned plant database and its associated ArcIMS instance. The analysis of the issues is sound. I disagree, of course, with their conclusion that ArcIMS is something worth learning and deploying in 2008, and this raises in my mind another issue that the authors did not identify: is not the project's data and its provenance the thing that is most important to preserve? Must the interface cruft around it be preserved in anything other than an archived form, if at all? The ArcIMS user interface and the species database &lt;a class="reference external" href="http://quod.lib.umich.edu/cgi/b/broker/test/datamgr"&gt;browser&lt;/a&gt; are no kind of programmable web APIs; it's unlikely any other application would be broken by a switch to some free web mapping framework or modern search interface.&lt;/p&gt;
&lt;p&gt;Now there's a question: switch to what? If this story is just the beginning, and bigger boxes of used, discarded, but potentially useful first-generation web/GIS projects end up in the laps of librarians, a turnkey (and open source, naturally) ArcIMS to MapServer/MapGuide migration tool might be a handy thing. I wouldn't be surprised if such a thing existed. Its authors might want to consider pitching it to GIS librarians in higher education.&lt;/p&gt;
&lt;section id="comments"&gt;
&lt;h2&gt;Comments&lt;/h2&gt;
&lt;section id="re-preserving-first-generation-web-gis-projects"&gt;
&lt;h3&gt;Re: Preserving first-generation web/GIS projects&lt;/h3&gt;
&lt;p&gt;Author: &lt;a class="reference external" href="http://www.jasonbirch.com/nodes/"&gt;Jason Birch&lt;/a&gt;&lt;/p&gt;
That's just freaking bizarre.  I was lying in bed last night thinking about whether it would be hard to write an AXL to MapGuide XML transformation.&lt;/section&gt;
&lt;section id="re-preserving-first-generation-web-gis-projects-1"&gt;
&lt;h3&gt;Re: Preserving first-generation web/GIS projects&lt;/h3&gt;
&lt;p&gt;Author: &lt;a class="reference external" href="http://www.spatiallyadjusted.com/"&gt;James Fee&lt;/a&gt;&lt;/p&gt;
Wow, deploy ArcIMS in 2008/2009.  This is why ESRI can't kill ArcIMS, folks still want to use the darn thing.  As much as Jack can get up on stage and basically say the thing is depreciated, people still refuse to listen.  Of course part of the problem is ESRI is willing to continue selling licenses to people to deploy it, but I suppose in a higher ed setting site licenses abound and they could have easily gone with the ESRI RESTful API if they wanted to stay ESRI.&lt;/section&gt;
&lt;/section&gt;</description><category>software engineering</category><category>work</category><guid>https://sgillies.net/2008/12/22/preserving-first-generation-webgis-projects.html</guid><pubDate>Mon, 22 Dec 2008 07:00:00 GMT</pubDate></item></channel></rss>