<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Andrew Brookins</title>
	<atom:link href="http://andrewbrookins.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://andrewbrookins.com</link>
	<description>software engineering, the nature of good and evil, etc.</description>
	<lastBuildDate>Mon, 20 May 2013 04:57:16 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.1</generator>
		<item>
		<title>Wrap Comments and Text to Column Width in IntelliJ Editors</title>
		<link>http://andrewbrookins.com/tech/wrap-comments-and-text-to-column-width-in-intellij-editors/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=wrap-comments-and-text-to-column-width-in-intellij-editors</link>
		<comments>http://andrewbrookins.com/tech/wrap-comments-and-text-to-column-width-in-intellij-editors/#comments</comments>
		<pubDate>Mon, 20 May 2013 04:57:16 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[technology]]></category>

		<guid isPermaLink="false">http://andrewbrookins.com/?p=957</guid>
		<description><![CDATA[One of the small annoyances I found after switching to IntelliJ text editors recently was that the editor won&#8217;t reformat selected text to your chosen column width. Annoying, for Vim and Emacs users! I corrected this by writing my first IntelliJ plugin: Wrap to Column, which is a port of a different plugin I wrote [...]]]></description>
			<content:encoded><![CDATA[<p>One of the small annoyances I found after switching to IntelliJ text editors recently was that the editor won&#8217;t reformat selected text to your chosen column width. Annoying, for Vim and Emacs users!</p>
<p>I corrected this by writing my first IntelliJ plugin: <a href="http://plugins.jetbrains.com/plugin/?phpStorm&amp;pluginId=7234">Wrap to Column</a>, which is a port of <a href="https://github.com/abrookins/WrapCode">a different plugin I wrote</a> for the same feature in Sublime Text 2.</p>
<p>My &#8220;Wrap to column&#8221; command wraps selected text or the current line to the column width you&#8217;ve configured for the project. The goal is to match the functionality of Vim&#8217;s &#8220;reformat lines&#8221; (<code>gq</code>) command and &#8220;fill paragraph&#8221; in Emacs.</p>
<p>Just so you know, there <em>is</em> a &#8220;fill paragraph&#8221; command in IntelliJ &#8212; something they added in recent months &#8212; but I&#8217;ve not been able to get it to do anything but merge all selected text into a single line that is longer than my column width setting. After filing bug reports and sending emails, I gave up and wrote the feature myself, since I&#8217;d already done so one before.</p>
<p>If you end up using it, drop me a line or comment on the plugin page if it&#8217;s working for you. I could use more testers!</p>
]]></content:encoded>
			<wfw:commentRss>http://andrewbrookins.com/tech/wrap-comments-and-text-to-column-width-in-intellij-editors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Build an In-Memory Proximity Search Web Service with Python, SciPy and Heroku</title>
		<link>http://andrewbrookins.com/tech/build-an-in-memory-proximity-search-web-service-with-python-scipy-and-heroku/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=build-an-in-memory-proximity-search-web-service-with-python-scipy-and-heroku</link>
		<comments>http://andrewbrookins.com/tech/build-an-in-memory-proximity-search-web-service-with-python-scipy-and-heroku/#comments</comments>
		<pubDate>Mon, 29 Apr 2013 16:53:57 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[technology]]></category>

		<guid isPermaLink="false">http://andrewbrookins.com/?p=924</guid>
		<description><![CDATA[In this post I&#8217;m going to look at a concrete example of building an in-memory proximity (aka, nearest neighbor) search web service using Python, SciPy and Heroku. Later we can speculate on use cases for this approach as opposed to a geo-aware database. Define Our Terms So, let&#8217;s define our terms: In-memory: The web service [...]]]></description>
			<content:encoded><![CDATA[<p>In this post I&#8217;m going to look at a concrete example of building an in-memory proximity (aka, nearest neighbor) search web service using Python, SciPy and Heroku.</p>
<p>Later we can speculate on use cases for this approach as opposed to a geo-aware database.</p>
<h1>Define Our Terms</h1>
<p>So, let&#8217;s define our terms:</p>
<ul>
<li>In-memory: The web service process contains the data we will query.</li>
<li>Proximity search: Given a latitude/longitude coordinate, return a set of results within a fixed distance from that location. Also called nearest neighbor search, closest point search, etc. I prefer &#8220;proximity search.&#8221;</li>
<li>Web service: This will be a JSON web service.</li>
<li>Python: We&#8217;ll use Python 2.7.</li>
<li>SciPy: We&#8217;ll use a C component of SciPy to do the search, namely <code>scipy.spatial.cKDTree</code>.</li>
<li>Heroku: We&#8217;ll deploy the project on Heroku using a custom Python build-pack to install SciPy.</li>
</ul>
<h1>The Example Project</h1>
<p>All of the code I&#8217;ll discuss and quote is available in <a href="https://github.com/abrookins/siren">an example project on Github</a>.</p>
<p>The proximity search that the example performs looks up statistics (nothing fancy now, just sums) about crimes that occurred in Portland, Oregon near a given location.</p>
<p>Also, a <strong>warning</strong>: this is by no means an attempt at production-ready code.</p>
<h1>The Secret Sauce: SciPy&#8217;s K-D Tree</h1>
<p>The fastest way to do a proximity search lookup in Python that I could find was SciPy&#8217;s implementation of a k-d tree. For more information, check the <a href="http://en.wikipedia.org/wiki/K-d_tree">Wikipedia article</a>.</p>
<p>In short, a k-d tree is a binary space partitioning tree, and SciPy&#8217;s C implementation is pretty fast. Here are <a href="http://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.cKDTree.html#scipy.spatial.cKDTree">the docs for the code we&#8217;ll use</a>.</p>
<p>The class is pretty simple. According to the docs, we load in some data and get a <code>query</code> method that we can use to perform a nearest-neighbor search.</p>
<h1>Building the Proximity Search</h1>
<p>So, let&#8217;s look at some example code that loads up the k-d tree. Then we&#8217;ll look at code that performs the query.</p>
<p>I&#8217;ve simplified part of a class I used in the example project to do this. The source is <a href="https://github.com/abrookins/siren/blob/master/siren/crime_tracker.py">available on GitHub</a>.</p>
<p>Here&#8217;s a Gist of the code we&#8217;ll look at first:</p>
<p><script src="https://gist.github.com/abrookins/5478445.js"></script></p>
<p>We have an <code>__init__</code> method that creates a <code>self.crimes</code> object.</p>
<p>Let&#8217;s assume this code loads a file that contains crime data tagged with Mercator coordinates  into a dict whose keys are coordinates and values are an array of crimes that occurred at that location. (Presumably you also have a file of geo-tagged data that you wish to offer a proximity search web service for.)</p>
<p>On <a href="https://gist.github.com/abrookins/5478445#file-gistfile1-py-L13">line 13</a> we create the k-d tree of crime locations. What we&#8217;re doing here is taking the coordinates of all known crimes (not the crime objects &#8212; just the coordinates, which are stored as keys in the <code>self.crimes</code> dict) and passing them into the <code>scipy.spatial.cKDTree</code> constructor. The <code>cKDTree</code> builds an index of the coordinates.</p>
<p>Next we have a <code>get_points_nearby</code> method that performs the nearest-neighbor(s) query against the k-d tree. The call to <code>query</code> is on <a href="https://gist.github.com/abrookins/5478445#file-gistfile1-py-L24">line 24</a>.</p>
<p>We sent a coordinate into <code>query</code> and we get back a tuple containing the distances and indices of nearest neighbors within the maximum distance that we supplied (in this case, 1/2 a mile).</p>
<p>That&#8217;s the meat of the proximity search, just passing the buck to SciPy &#8212; we now have our coordinates and we can look up in <code>self.crimes</code> the actual crime data that map to those coordinates.</p>
<h1>Creating the Web Service</h1>
<p>Assuming your source data is already in latitude and longitude form, you can already use <code>cKDTree</code> in the fashion we&#8217;ve looked at to do proximity search. Now we just need to wrap it up as a web service.</p>
<p>The following is an example using Flask because it&#8217;s a pretty easy framework to deploy to Heroku. I&#8217;ve edited it to remove only a couple of lines from <a href="https://github.com/abrookins/siren/blob/master/siren/__init__.py">the real file</a>.</p>
<p><script src="https://gist.github.com/abrookins/5479607.js"></script></p>
<p>This file defines two web services, one available at <code>/crimes/stats/&lt;longitude&gt;,&lt;latitude&gt;</code> and one at <code>/crimes/&lt;longitude&gt;,&lt;latitude&gt;</code>.</p>
<p>Assuming that the <code>PortlandCrimeTracker</code> object is capable of giving us back sums by category for crimes discovered near a coordinate, the rest of the work done in these services is ceremony: <code>get_point</code> tries to obtain a coordinate from the current request, and if it fails, causes Flask to return a 400 status code for the request. Meanwhile, <code>get_crimes</code> passes a valid coordinate and any GET parameters found in the request to <code>PortlandCrimeTracker.get_crimes_nearby</code>, which returns data on crimes near the coordinate.</p>
<h1>Deploying SciPy on Heroku</h1>
<p>The trick to deploying SciPy on Heroku is using a custom buildpack. Fortunately, someone already creating one of these for this purpose. Some details about using it are available in <a href="http://stackoverflow.com/a/10632272">this Stack Overflow comment</a>.</p>
<p>I <a href="https://github.com/abrookins/heroku-buildpack-python">forked the buildpack</a> for the sole purpose of pointing all of the repo URLs at my GitHub account.</p>
<h1>Performance</h1>
<p>Deploying this code onto Heroku with a free account (1 dyno) using no cache, Gunicorn and two workers got me an average of 98 requests per second after around 6000 requests.</p>
<h1>Why not PostGIS?</h1>
<p>Well, for one, to have fun!</p>
<p>I like the idea of doing an in-memory search more than storing geo-data in a database when the dataset is frozen or it changes at regular and predictable intervals. So, I wouldn&#8217;t use this for an application that made user-entered locations searchable. In that case I would probably use PostGIS.</p>
<p>That said, we swapped a PostGIS dependency for a SciPy dependency, and with Heroku that turns out to be less than straightforward to deploy.</p>
]]></content:encoded>
			<wfw:commentRss>http://andrewbrookins.com/tech/build-an-in-memory-proximity-search-web-service-with-python-scipy-and-heroku/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Revisiting Umberto Eco&#8217;s Future of the Book</title>
		<link>http://andrewbrookins.com/tech/the-present-of-books/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=the-present-of-books</link>
		<comments>http://andrewbrookins.com/tech/the-present-of-books/#comments</comments>
		<pubDate>Sun, 25 Nov 2012 19:32:45 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[books]]></category>
		<category><![CDATA[technology]]></category>

		<guid isPermaLink="false">http://andrewbrookins.com/?p=906</guid>
		<description><![CDATA[In 2003 Umberto Eco gave a talk at the opening of the Bibliotheca Alexandrina titled, &#8220;Vegetal and mineral memory: The future of books&#8221; that is interesting to reread now, 9 years later. His goal in the talk was to break apart the fear people had back then about &#8220;the future of books.&#8221; He split this [...]]]></description>
			<content:encoded><![CDATA[<p>In 2003 Umberto Eco gave a talk at the opening of the Bibliotheca Alexandrina titled, <a href="http://weekly.ahram.org.eg/2003/665/bo3.htm">&#8220;Vegetal and mineral memory: The future of books&#8221;</a> that is interesting to reread now, 9 years later.</p>
<p>His goal in the talk was to break apart the fear people had back then about &#8220;the future of books.&#8221; He split this into the future of the physical artifact &#8212; the bound book &#8212; and what people usually read in them: novels, reference texts, etc.</p>
<p>In 2003, I remember thinking that his opinion that the novel as a form would stick around seemed quaint and wrong because of the internet and the rise of story-based video games. &#8220;Hypertext&#8221; seemed more appropriate to the future than the old frozen novel. However, Eco&#8217;s argument that the computer would never become popular for consuming stories, not as popular as books, anyway, because of how uncomfortable it is on the eyes to read a computer screen, seemed right. Books would live, while the novel was going out, I thought. So what was left in the middle, except the death of the novel?</p>
<p>In 2013, I&#8217;ve come to think the opposite. Now, I agree with Eco that nothing can replace the novel, precisely for the reasons he gave in his talk, the most important of which is that the novel mirrors human reality. The past is frozen &#8212; that is the source of all tragedy, isn&#8217;t it? We can&#8217;t change what happens. Novels communicate with us on this level. In video games and in the theoretical (because none have been done well, right?) &#8220;hypertext&#8221; novel, the reader may choose what happens, and more importantly the reader is always free to do things over. That isn&#8217;t what life is like. You may be able to try again, but maybe not. Much like a novel, we can only analyze and learn from the past. I&#8217;m also surprised while the novel is as alive to me as ever, perhaps even more than in 2003, electronic books are now breaking the bounds of what Eco must have imagined they could be. Reading ebooks is now enjoyable, convenient and becoming more and more affordable every fiscal quarter. Yes, the experience is not the same as with physical books: there is no &#8220;used&#8221; ebook for purchase; we cannot easily give them to friends after reading (though this has changed a bit and is becoming easier); we never own them. Still, just as CDs and tapes have fallen away, there are many benefits to digital books, enough that I prefer them over physical books &#8212; something I thought impossible in 2003.</p>
<p>So I look forward to reading Eco&#8217;s talk again in 2022 or 2023 (maybe let&#8217;s make it a round 10 year check-in).</p>
]]></content:encoded>
			<wfw:commentRss>http://andrewbrookins.com/tech/the-present-of-books/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using IPython Notebook with Django</title>
		<link>http://andrewbrookins.com/python/using-ipython-notebook-with-django/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-ipython-notebook-with-django</link>
		<comments>http://andrewbrookins.com/python/using-ipython-notebook-with-django/#comments</comments>
		<pubDate>Thu, 30 Aug 2012 17:28:52 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[python django]]></category>

		<guid isPermaLink="false">http://andrewbrookins.com/?p=856</guid>
		<description><![CDATA[IPython has a relatively new featured called the &#8220;Notebook,&#8221; which improves on the traditional terminal shell in many ways. Notebook launches a web-based shell to an IPython session that has some very, very handy features, like the ability to save, edit and delete &#8220;notebooks&#8221; of code that are each comprised of organized cells of Python, [...]]]></description>
			<content:encoded><![CDATA[<p>IPython has a relatively new featured called the &#8220;Notebook,&#8221; which improves on the traditional terminal shell in many ways.</p>
<p>Notebook launches a web-based shell to an IPython session that has some very, very handy features, like the ability to save, edit and delete &#8220;notebooks&#8221; of code that are each comprised of organized cells of Python, text or Markdown. You can move the cells around, developing code interactively with documentation and notes to yourself, displaying anything that a browser could render: images, HTML, etc.</p>
<p>But! You can&#8217;t run a Django shell using notebook.</p>
<h2>With Django Extensions</h2>
<p>The latest version of the <a href="https://github.com/django-extensions/django-extensions" title="Django Extensions" target="_blank">Django Extensions</a> app on Github has support for using the <code>shell_plus</code> command with Notebook. If you&#8217;re up to date, you should be able to use the following command to run a Django shell with Notebook:</p>
<p><code>$ ./manage.py shell_plus --notebook</code></p>
<h2>Without Django Extensions</h2>
<p>If you&#8217;d rather not use the Django Extensions app, you can load an IPython extension that performs the imports that an IPython session needs to run Django.</p>
<p>I&#8217;ve packaged up such an extension (very simple) that you can install from by executing this command from within IPython:</p>
<p><script src="https://gist.github.com/3553617.js?file=gistfile1.py"></script></p>
<p>This will download the <code>django_notebook.py</code> module into <code>~/.ipython/extensions/django_notebook.py</code>. (The file merely attempts to load Django whenever you start IPython, unless an ImportError occurs.)</p>
<p>After installing the extension, add it to your IPython RC file. This is probably at <code>~/.ipython/profile_default/ipython_config.py</code>. If you don&#8217;t have one, you can use this command to create one with IPython (from the terminal shell, not within IPython):</p>
<p><code>$ ipython profile create</code></p>
<p>Then edit the created (or existing) <code>ipython_config.py</code> file and add the following line somewhere after the line <code>c = get_config()</code>:</p>
<p><script src="https://gist.github.com/3553655.js?file=gistfile1.py"></script></p>
<p>(Or just append <code>'django_notebook'</code> to the existing extensions list if it exists.)</p>
<p>Now you should be able to run <code>ipython notebook</code> from within a Django project and have access to all of the Django and project-related modules.</p>
]]></content:encoded>
			<wfw:commentRss>http://andrewbrookins.com/python/using-ipython-notebook-with-django/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Set an ImageField path in Django manually</title>
		<link>http://andrewbrookins.com/tech/set-the-path-to-an-imagefield-in-django-manually/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=set-the-path-to-an-imagefield-in-django-manually</link>
		<comments>http://andrewbrookins.com/tech/set-the-path-to-an-imagefield-in-django-manually/#comments</comments>
		<pubDate>Thu, 23 Aug 2012 19:42:37 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[technology]]></category>

		<guid isPermaLink="false">http://andrewbrookins.com/?p=857</guid>
		<description><![CDATA[Apparently this is a confusing topic. Let&#8217;s say you have a Django model with an ImageField and some existing media files, and you&#8217;d like to connect the files to the ImageField. This is relatively painless and doesn&#8217;t require you to use the save() method on the ImageField. If you only want to set an ImageField [...]]]></description>
			<content:encoded><![CDATA[<p>Apparently this is a confusing topic. Let&#8217;s say you have a Django model with an ImageField and some existing media files, and you&#8217;d like to connect the files to the ImageField. This is relatively painless and doesn&#8217;t require you to use the <code>save()</code> method on the ImageField.</p>
<p>If you only want to set an ImageField to point to an existing file, assign a string containing the path <em>relative to <code>settings.MEDIA_ROOT</code></em> to the field. E.g.:</p>
<p><script src="https://gist.github.com/3440646.js?file=gistfile1.py"></script></p>
<p>This works as of (and possibly before) Django 1.3.</p>
<p>Note a couple of things:</p>
<p>Setting the path ignores your <code>upload_to</code> value. You have to prefix your string with that value yourself.</p>
<p>Again, you don&#8217;t have to call <code>save()</code> on the ImageField &#8212; just the model instance. There are some StackOverflow posts that advise going the route of calling <code>save()</code> on the ImageField, which requires you to open a file descriptor, etc. This isn&#8217;t necessary, will end up copying the file, and ignores any prefixed paths, resulting in a path that is always, in my testing, <code>settings.MEDIA_ROOT/filename.jpeg</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://andrewbrookins.com/tech/set-the-path-to-an-imagefield-in-django-manually/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Go: How to Get the Directory of the Current File</title>
		<link>http://andrewbrookins.com/tech/golang-get-directory-of-the-current-file/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=golang-get-directory-of-the-current-file</link>
		<comments>http://andrewbrookins.com/tech/golang-get-directory-of-the-current-file/#comments</comments>
		<pubDate>Sat, 19 May 2012 22:10:38 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[technology]]></category>

		<guid isPermaLink="false">http://andrewbrookins.com/?p=831</guid>
		<description><![CDATA[In Python I often use the __file__ constant to get the directory of the current file (e.g., os.path.dirname(os.path.realpath(__file__))). While writing a Go app recently, I found that there wasn&#8217;t an immediately obvious (or searchable, even with &#8220;golang&#8221;) equivalent. But in the annals of the golong-nuts mailing list I eventually found out about runtime.Caller(). This returns [...]]]></description>
			<content:encoded><![CDATA[<p>In Python I often use the <code>__file__</code> constant to get the directory of the current file (e.g., <code>os.path.dirname(os.path.realpath(__file__))</code>). While writing a Go app recently, I found that there wasn&#8217;t an immediately obvious (or searchable, even with &#8220;golang&#8221;) equivalent.</p>
<p>But in the annals of the golong-nuts mailing list I eventually found out about <code>runtime.Caller()</code>. This returns a few details about the current goroutine&#8217;s stack, including the file path.</p>
<p>The context of my problem was opening a data file in a shared package. What I cooked up was:</p>
<p><script src="https://gist.github.com/2732551.js?file=gistfile1.go"></script></p>
<p>Sending <code>1</code> to <code>runtime.Caller</code> identifies the caller of <code>runtime.Caller</code> as the stack frame to return details about. So you you get info about the file your method is in. Check <a href="http://golang.org/pkg/runtime/#Caller">the docs</a> for more in-depth coverage.</p>
<p>It&#8217;s not quite as elegant as <code>__file__</code> but it works.</p>
]]></content:encoded>
			<wfw:commentRss>http://andrewbrookins.com/tech/golang-get-directory-of-the-current-file/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Run Django Unit Tests in a Sublime Text 2 Build System</title>
		<link>http://andrewbrookins.com/tech/run-django-unit-tests-in-a-sublime-text-2-build-system/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=run-django-unit-tests-in-a-sublime-text-2-build-system</link>
		<comments>http://andrewbrookins.com/tech/run-django-unit-tests-in-a-sublime-text-2-build-system/#comments</comments>
		<pubDate>Tue, 28 Feb 2012 17:11:20 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[technology]]></category>

		<guid isPermaLink="false">http://andrewbrookins.com/?p=820</guid>
		<description><![CDATA[With the dev builds of Sublime Text 2, you can easily set up a build system that runs Django unit tests. You do this by adding a build system to your Sublime Text 2 project file for the Django project. I&#8217;ll include an example project file in this post that runs manage.py test --noinput as [...]]]></description>
			<content:encoded><![CDATA[<p>With the dev builds of Sublime Text 2, you can easily set up a build system that runs Django unit tests. You do this by adding a build system to your Sublime Text 2 project file for the Django project.</p>
<p>I&#8217;ll include an example project file in this post that runs <code>manage.py test --noinput</code> as the build command. In order for this to work with the current implementation of build systems, the project file must add the Django project dir and the virtualenv&#8217;s site-packages directory to the <code>PYTHONPATH</code>.</p>
<p>Note a couple of things:</p>
<ul>
<li>In the project file, ${project_path} refers to the directory in which the project file exists: I created mine in the virtual env directory (the directory with the bin/ and lib/ directores for the virtualenv). For more info on other possible substitutions see <a href="http://sublimetext.info/docs/en/reference/build_systems.html">the docs</a> (note that I couldn&#8217;t get substitutions to work in the &#8220;env&#8221; dictionary)</li>
<li>My placeholder text <code>django_project_dir</code> stands for the directory that contains your Django project files inside of the virtualenv</li>
<li>This doesn&#8217;t use the <code>python</code> binary in your virtualenv &#8212; so your mileage may vary </li>
</ul>
<p>One final thing to note is that I&#8217;ve added the <code>lib/python2.7</code> directory as a folder in the project file. This is not related to the build system. It simply includes libraries in my &#8220;Find in File&#8230;&#8221; searches, allowing me to easily search for, e.g., Django classes and usages alongside my own. (SublimeRope is also a helpful tool for exploring.)</p>
<p>Anyway, here is the example project file:</p>
<p><script src="https://gist.github.com/1933635.js?file=gistfile1.json"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://andrewbrookins.com/tech/run-django-unit-tests-in-a-sublime-text-2-build-system/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python: How to tell what class a decorated method is in at runtime</title>
		<link>http://andrewbrookins.com/tech/how-to-get-the-name-of-the-class-of-a-decorated-method-in-python/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=how-to-get-the-name-of-the-class-of-a-decorated-method-in-python</link>
		<comments>http://andrewbrookins.com/tech/how-to-get-the-name-of-the-class-of-a-decorated-method-in-python/#comments</comments>
		<pubDate>Wed, 22 Feb 2012 21:01:23 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[technology]]></category>

		<guid isPermaLink="false">http://andrewbrookins.com/?p=808</guid>
		<description><![CDATA[When profiling a Python app, it&#8217;s helpful to have a decorator that wraps functions and reports details about their performance. Assuming you are doing this to report some metric about the function, you&#8217;ll want the decorator to work with both bound and unbound functions (IE, regular functions and methods of a class), and if the [...]]]></description>
			<content:encoded><![CDATA[<p>When profiling a Python app, it&#8217;s helpful to have a decorator that wraps functions and reports details about their performance. Assuming you are doing this to report some metric about the function, you&#8217;ll want the decorator to work with both bound and unbound functions (IE, regular functions and methods of a class), and if the decorator wraps a method, you&#8217;ll probably want to know the name of the class the method belongs to.</p>
<p>There is only one way (<em>update</em>: two ways) I&#8217;ve found to do this. They both involve the <code>inspect</code> module. (There are obvious ways to do it that don&#8217;t work with decorators.)</p>
<p>You can&#8217;t assume that the first argument in a function always refers to its class because that would break in the case that the function was not a method. However, the strong convention in Python is to name the first argument of methods &#8216;self&#8217;. Relying on this convention, we can easily tell if a function includes such an argument with the <code>inspect</code> module.</p>
<p>The <code>inspect</code> module&#8217;s <code>getcallargs</code> function will map the parameter names from a function&#8217;s signature to its arguments. Given a function <code>fn</code> that your decorator wraps, you can call <code>inspect.getcallargs(fn, *args)</code> at runtime and discover that the first positional argument is the &#8216;self&#8217; parameter defined in the method&#8217;s signature!</p>
<p>Now, the use of &#8216;self&#8217; is such a strong Pythonic convention that it&#8217;s good enough in most cases to use the presence of such a parameter in a function to know that it&#8217;s a bound function (again, a class method), and you can then inspect the &#8216;self&#8217; argument for its class using <code>__class__.__name__</code>.</p>
<p>Here is an example decorator that will print out the class name of a decorated bound function:</p>
<p><script src="https://gist.github.com/1887230.js?file=gistfile1.py"></script></p>
<p><em>Update</em>: In Python 2.6, which does not include <code>inspect.getcallargs</code>, you can use <code>inspect.getargspec</code> to similar effect:</p>
<p><script src="https://gist.github.com/1893856.js?file=gistfile1.py"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://andrewbrookins.com/tech/how-to-get-the-name-of-the-class-of-a-decorated-method-in-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Make Sublime Text 2 More like Vim: Wrap Code, Go To Last Edit, Jump Back, and More</title>
		<link>http://andrewbrookins.com/tech/make-sublime-text-2-more-like-vim-wrap-code-goto-last-edit-and-more/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=make-sublime-text-2-more-like-vim-wrap-code-goto-last-edit-and-more</link>
		<comments>http://andrewbrookins.com/tech/make-sublime-text-2-more-like-vim-wrap-code-goto-last-edit-and-more/#comments</comments>
		<pubDate>Thu, 19 Jan 2012 14:16:46 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[technology]]></category>

		<guid isPermaLink="false">http://andrewbrookins.com/?p=776</guid>
		<description><![CDATA[I&#8217;ve been trying out Sublime Text 2 as a replacement for Vim. While I enjoy using it and I experienced the &#8220;Wow, this does 90% of what Vim does&#8221; moment, I kept a running list of all the features in the remaining 10% that I relied on every day. These included: Better code wrapping (gq) [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been trying out Sublime Text 2 as a replacement for Vim. While I enjoy using it and I experienced the &#8220;Wow, this does 90% of what Vim does&#8221; moment, I kept a running list of all the features in the remaining 10% that I relied on every day.</p>
<p>These included:</p>
<ul>
<li>Better code wrapping (<code>gq</code>)</li>
<li>Go to last edit (<code>'.</code>)</li>
<li>Go to file in Ack search output</li>
<li>Display full path to current file (<code>:echo expand('%:p')&lt;CR&gt;</code>)</li>
<li>Jumping back and forward through files</li>
</ul>
<p>However, Sublime Text 2 has a great Python API and I was able to whip up plugins for these tasks that perform just as well as in Vim. <em>Update</em>: I also found the navigationHistory plugin, which does a pretty good job of back/forward jumps.</p>
<p>Note: The following plugins are not verified to work with Sublime Text 3. If you&#8217;d like to contribute to updating them for ST 3, <a href="http://www.gofundme.com/2qtxgg">you can do so here</>.</p>
<h2>Better code wrapping</h2>
<p>Vim&#8217;s reformat text command (<code>gq</code>) can take multiple paragraphs and text in comments and flow them to the current textwidth setting. Some people don&#8217;t care about this, but I prefer to keep lines of code less than 80 characters wide, so I can open multiple files side-by-side. (Also, Pep-8.)</p>
<p>Sublime Text 2 had a &#8220;wrap&#8221; feature, but it failed to intelligently wrap comments, it joined separate paragraphs together and it wouldn&#8217;t reflow selected text (only the paragraph around the cursor).</p>
<p>The plugin I wrote creates a Wrap Code command (mapped to <code>gq</code> in Vintage mode) that works reasonably on commented lines of code (and uncommented lines), multiple paragraphs and selected text, thanks to the <code>codewrap.py</code> module written by Nir Soffer.</p>
<p><a href="https://github.com/abrookins/WrapCode">Download the WrapCode plugin on Github.</a></p>
<h2>Go to the last edit</h2>
<p>I&#8217;m used to typing <code>'.</code> in a buffer in Vim to move the cursor to the last edit. Great feature. Totally underrated.</p>
<p>If you use Vintage mode in Sublime Text 2, you&#8217;ll quickly discover that this command does nothing &#8212; worse than nothing, in fact, as it seems to refocus your cursor somewhere other than the text of the buffer, forcing you to use your mouse to recover.</p>
<p>While I couldn&#8217;t bind my plugin to the <code>'.</code> command without forking Vintage mode, I bound it to <code>Super+'</code> and it works the same as Vim&#8217;s.</p>
<p><a href="https://github.com/abrookins/GotoLastEdit">Download the GotoLastEdit plugin on Github.</a></p>
<h2>Easily open search results</h2>
<p>Another thing I missed about Vim was its Ack plugin. The &#8220;Find in Files&#8221; feature of Sublime Text 2 is great, but it didn&#8217;t provide an easy way to quickly open a file listed in the search results via the keyboard (you can double-click on a line to open it, though).</p>
<p>So I wrote a plugin that, in a Search Results window, allows you to do one of the following via the keyboard:</p>
<ul>
<li>On a &#8220;matched&#8221; line in the search output, open its file at the line of the match</li>
<li>On a file path in the search output (without a line number), open the file in a new tab</li>
</ul>
<p><a href="https://github.com/abrookins/OpenSearchResult">Download the OpenSearchResult plugin on Github.</a></p>
<h2>Display full path to file in status bar</h2>
<p>I use Vim in OS X&#8217;s full screen mode, with no tabs or status line. Working this way, I don&#8217;t have reference to the path of the current file. Of course, I know the name of the file because I usually typed it, but sometimes the full path is important; e.g., if I have two Mercurial branches of the same code in different directories.</p>
<p>So, I have a command mapped to <code>,F</code> that displays the full path. Then it silently goes away after a moment. I love that command.</p>
<p>I couldn&#8217;t find an ideal way to implement this in Sublime Text 2, other than to create a command that would toggle displaying the path to the current file in the status bar. It works well enough for me, however.</p>
<p><a href="https://github.com/abrookins/FilenameStatus">Download the FilenameStatus plugin on Github.</a></p>
<h2>Jumping back and forward</h2>
<p>One of Vim&#8217;s most awesome features is Control-O/Control-I to jump back and forward &#8212; maybe I can generalize to say that <em>all</em> of Vim&#8217;s jump commands are part of its &#8220;killer app&#8221; status.</p>
<p>Sublime Text 2 doesn&#8217;t have a feature like this, but someone on the internet has packaged a version of Martin Aspelli&#8217;s <code>navigationHistory</code> plugin, which comes close.</p>
<p><a href="https://github.com/marram/sublime-navigation-history">Download the navigationHistory plugin on Github.</a></p>
<h2>Installing the plugins</h2>
<p>You install these plugins the same way as other Sublime Text 2 plugins, by downloading the files and dropping them into the Packages directory.</p>
<p>See <a href="http://sublimetext.info/docs/en/extensibility/plugins.html">this documentation</a> for more details if you need additional help installing plugins.</p>
<p>The default key bindings are intended for Vintage mode and are oriented for OS X.</p>
]]></content:encoded>
			<wfw:commentRss>http://andrewbrookins.com/tech/make-sublime-text-2-more-like-vim-wrap-code-goto-last-edit-and-more/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sharp Edges: Protecting Ourselves from Digital Publishing</title>
		<link>http://andrewbrookins.com/tech/sharp-edges-protecting-ourselves-from-digital-publishing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sharp-edges-protecting-ourselves-from-digital-publishing</link>
		<comments>http://andrewbrookins.com/tech/sharp-edges-protecting-ourselves-from-digital-publishing/#comments</comments>
		<pubDate>Sat, 07 Jan 2012 19:42:11 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[books]]></category>
		<category><![CDATA[technology]]></category>

		<guid isPermaLink="false">http://andrewbrookins.com/?p=731</guid>
		<description><![CDATA[Nicholas Carr wrote in a recent article that he considered the ability of publishers to change text after they had released it &#8220;insidious&#8221; and a &#8220;bane&#8221; of digital publishing &#8212; specifically, if such changes are made in response to market research. I agree that there is a challenge inherent in the new ease with which [...]]]></description>
			<content:encoded><![CDATA[<p>Nicholas Carr wrote in a recent article that he considered the ability of publishers to change text after they had released it &#8220;insidious&#8221; and a &#8220;bane&#8221; of digital publishing &#8212; specifically, if such changes are made in response to market research.</p>
<p>I agree that there is a challenge inherent in the new ease with which publishers may release versions of a text, but the challenge I see is different than the one Carr suggested. Data about the chapters that readers skip and areas that cause people to abandon their reading will only help publishers create better, more relevant content, just as this data has helped web site authors do the same. It is our response, as readers, to the possibility of frequent (and silent) revisions to text that I worry about.</p>
<h2>Movable Text</h2>
<p>As a summary of the key difference between print and electronic publishing, Carr described electronic publishing as having replaced Gutenberg&#8217;s movable type with &#8220;movable text.&#8221; For centuries, once set and printed, the text of a book remained the same. Today, with web sites and now ebooks, publishers may change the text at any time, introducing multiple divergent copies or, if the distribution method supports it, even changing the copy you are reading as you read it.</p>
<p>Carr wrote about the downside of this change that,</p>
<blockquote><p>The promise of stronger sales and profits will make it hard to resist tinkering with a book … adding a few choice words here, trimming a chapter there, maybe giving a key character a quick makeover.</p></blockquote>
<p>&#8211; <a href="http://online.wsj.com/article/SB10001424052970203893404577098343417771160.html" target="_blank">Books That Are Never Done Being Written</a></p>
<p>What is wrong with this? While some readers may finish every book they start, I have dismissed dozens of books in my life, at various points in their stories, after having read one too many missteps of voice or plot, or simply because I was bored. Life is short. There are more books to read than I have time for. So why should I read a poorly written book, and what do I care for the &#8220;shape&#8221; of a book (to quote Carr quoting Updike) if I can&#8217;t connect with it?</p>
<p>Creators and publishers who release work on the internet can get faster and more in-depth feedback from consumers than in traditional publishing &#8212; not just through comments but through analytics about a reader&#8217;s behavior. Analytics can show what people look for in a text and different ways they respond (e.g., most people stopped reading on page two). As anyone who has written a blog or maintained a web site will know, this information is extremely valuable as way of testing what people want to read and what they don&#8217;t.</p>
<p>The same will now be true for books. As readers, our reactions to books, not just the fact that we purchased them but more intimate details like how long we lingered on a page and where we stopped reading (if it wasn&#8217;t the end), will place us in tighter feedback loops with authors. How is this a &#8220;bane&#8221;?</p>
<h2>Authentic Text</h2>
<p>What <em>is</em> wrong with this model is that we must change our idea of the persistence and security of human knowledge to fit it. We have to create new mechanisms to ensure the authenticity of texts. There are measures we can take to accomplish this:</p>
<ul>
<li>Creators should have control over changes made to their works, to protect themselves from publishers introducing alterations based on sales data.</li>
<li>Readers should have access to all released versions of a text. Each authorized edition of a text should have its own ID that is registered with a trusted authority. And if the publisher releases a new version of a book that is already on our ebook readers, we ought to have the right to approve whether or not we update to it.</li>
<li>A trusted organization of the public good should house a copy of each version of released texts, to reduce the chance that individuals, companies and governments can alter or destroy the source files.</li>
</ul>
<p>In the traditional publishing model, a printed edition of a work with an ISBN is a &#8220;known good&#8221; source copy. It is authorized by someone. Multiple editions of a book may exist, but as readers and historians we can examine our authorized copies of these editions. We can protect them.</p>
<p>As we move toward using and relying on digital text, we must develop new means of protecting the authenticity of this information. The bane &#8212; the sharp edge &#8212; of &#8220;movable text&#8221; is not the ease with which we may change our books after we publish them. It is that our mechanisms for protecting ourselves from such change are outdated.</p>
]]></content:encoded>
			<wfw:commentRss>http://andrewbrookins.com/tech/sharp-edges-protecting-ourselves-from-digital-publishing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using apc
Database Caching 9/15 queries in 0.002 seconds using apc
Object Caching 669/780 objects using apc

 Served from: andrewbrookins.com @ 2013-05-19 23:38:10 by W3 Total Cache -->