<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>http://dancallahan.info/</id>
  <title>DanCallahan.info</title>
  <updated>2013-01-21T19:18:21Z</updated>
  <link rel="alternate" href="http://dancallahan.info/" />
  
  <author>
    <name>Dan Callahan</name>
    <uri>http://dancallahan.info</uri>
  </author>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/Dancallahaninfo" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="dancallahaninfo" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <id>tag:dancallahan.info,2013-01-21:/journal/password-managers-not-enough/</id>
    <title type="html">Password Managers are not Enough</title>
    <published>2013-01-21T19:18:21Z</published>
    <updated>2013-01-21T19:18:21Z</updated>
    <link rel="alternate" href="http://dancallahan.info/journal/password-managers-not-enough/" />
    <content type="html">&lt;p&gt;We’re expected to create and remember unique passwords for every website. To do
so with memory alone is unthinkable, but tools — notebooks, spreadsheets, and
password managers — are rarely used and offer imperfect reprieve.&lt;/p&gt;

&lt;p&gt;Because passwords rarely change, a single compromise can grant months or years
of fraudulent access to an account. Such breaches are distressingly common:
LinkedIn, Yahoo, Blizzard, eHarmony, Last.fm, Formspring, Billabong, and NVIDIA
all suffered exposures in 2012.&lt;/p&gt;

&lt;p&gt;The collateral damage is much greater: users are at risk everywhere those
passwords were re-used.&lt;/p&gt;

&lt;p&gt;Would better tools — better password managers — help? No. Password managers
can only mitigate collateral damage. They can’t improve site security, nor can
they affect the longevity of passwords. Thus, the passwords themselves are the
problem, and they should be managed only insofar as they cannot be eliminated
altogether.&lt;/p&gt;

&lt;p&gt;To abolish passwords, web developers must support alternative login mechanisms.
Facebook Connect, Sign in with Twitter, and OpenID are the most prominent
replacements for traditional login systems, but they’re far from ideal. Each
requires compromising user experience, prospective audience, visitor privacy, or
data ownership.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://login.persona.org"&gt;Mozilla Persona&lt;/a&gt; is an attempt to find a better balance. It gets rid
of per-site passwords, works on all major browsers, and can be used by anyone
with an email address. There’s no lock in, and it’s dead simple to implement.
If you’re a user, please ask your favorite sites to support Persona. If you’re
a developer, please consider &lt;a href="https://developer.mozilla.org/en-US/docs/Persona"&gt;adding support today&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Should you have questions or need help integrating Persona into your site,
please do not hesitate to contact me.&lt;/p&gt;</content>
    <summary type="html">We have to kill the password.</summary>
  </entry>
  <entry>
    <id>tag:dancallahan.info,2012-04-02:/journal/introducing-mockmyid/</id>
    <title type="html">Introducing MockMyId.com</title>
    <published>2012-04-02T14:29:47Z</published>
    <updated>2012-04-02T14:29:47Z</updated>
    <link rel="alternate" href="http://dancallahan.info/journal/introducing-mockmyid/" />
    <content type="html">&lt;p&gt;As a exercise, I recently built my own BrowserID Identity Provider (IdP), also
known as a “Primary.” I didn’t want to actually deal with emails or an account
database, so I decided to create an IdP that would happily hand out
credentials to anyone that asked. Such an IdP would be useful for testing or
demoing sites that rely on BrowserID, since it allows for the creation of new
identities on demand.&lt;/p&gt;

&lt;p&gt;Thus, &lt;a href="http://mockmyid.com"&gt;MockMyId.com&lt;/a&gt; was born. You can log into any
BrowserID Relying Party with &lt;code&gt;anything_you_want@mockmyid.com&lt;/code&gt;, and it should
Just Work. Try it out at &lt;a href="http://myfavoritebeer.org/"&gt;My Favorite Beer&lt;/a&gt;! The
code is on &lt;a href="https://github.com/callahad/mockmyid"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="Building+MockMyID"&gt;Building MockMyID&lt;/h2&gt;

&lt;blockquote&gt;&lt;p&gt;Note: The implementation details herein may be out of date! You should
always refer to &lt;a href="https://developer.mozilla.org/en/BrowserID/"&gt;MDN&lt;/a&gt; for
current information.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Once I settled on the idea of an approve-anything IdP, I got to thinking about
Mozilla’s use of NodeJS for the BrowserID project. Since I didn’t need to keep
the keypair secret, and I didn’t need to do any work on the backend, I decided
to try and implement everything client-side.&lt;/p&gt;

&lt;p&gt;So, where to start? I initially went to the &lt;a href="https://developer.mozilla.org/en/BrowserID"&gt;BrowserID page on
MDN&lt;/a&gt; but couldn’t find any
relevant information aside from “Development Tips” for becoming an IdP.
Unfortunately, the tips weren’t terribly useful since they presumed a lot of
pre-existing knowledge about the authentication flow.&lt;/p&gt;

&lt;p&gt;With MDN a bust, I headed over to the &lt;a href="https://wiki.mozilla.org/Identity/BrowserID"&gt;BrowserID
spec&lt;/a&gt; and skipped down to the
section on “Primary Authority Compliance,” where I learned that I only needed
three documents on my server: a support document at &lt;code&gt;/.well-known/browserid&lt;/code&gt;,
a page for authenticating users, and a page for creating new keys.&lt;/p&gt;

&lt;h3 id="The+Support+Document"&gt;The Support Document&lt;/h3&gt;

&lt;p&gt;First things first, I created a new json document at &lt;code&gt;/.well-known/browserid&lt;/code&gt;
and configured Nginx to serve it as &lt;code&gt;Content-Type: application/json&lt;/code&gt;. The
document just needed three keys, as per the spec: &lt;code&gt;public-key&lt;/code&gt;,
&lt;code&gt;authentication&lt;/code&gt;, and &lt;code&gt;provisioning&lt;/code&gt;. I stubbed out the &lt;code&gt;authetication&lt;/code&gt; and
&lt;code&gt;provisioning&lt;/code&gt; values and then turned to the &lt;code&gt;public-key&lt;/code&gt; field.&lt;/p&gt;

&lt;p&gt;The spec simply said that the key needs to be a “Public Key serialized as a
JSON object, as defined above.” I would’ve appreciated a link to the whole
“above” part, but it was easy enough to find the “Public Key” subsection under
the “Objects / Messages” header. Where to go from there, however, proved to be
a little more challenging. The spec mentions RSA keys and proffers a link to
&lt;a href="http://www.ietf.org/dyn/wg/charter/jose-charter"&gt;JOSE&lt;/a&gt;, the IETF’s Javascript
Object Signing and Encryption working group.&lt;/p&gt;

&lt;p&gt;Landing on the homepage of an IETF working group isn’t the most helpful, but I
found a link therein to the JSON Web Key (JWK) draft… which 404’d.
Thankfully, there’s a working link to the JWK spec at the bottom of the
BrowserID spec.&lt;/p&gt;

&lt;p&gt;The JWK spec mentioned RSA keys, so I generated a keypair using &lt;code&gt;openssl&lt;/code&gt; on
the command line and spent an hour or so working out how to encode the public
key as a JWK. It was only then that I noticed that the example in the JWK spec
looked nothing like the one in the BrowserID spec, and the one in the
BrowserID spec looked nothing like the one used at
&lt;a href="https://eyedee.me"&gt;eyedee.me&lt;/a&gt;, Lloyd’s proof-of-concept IdP. Awesome.&lt;/p&gt;

&lt;p&gt;At this point I gave up on the docs and fell back on the knowledge that Ben
Adida had been working on &lt;a href="https://github.com/mozilla/jwcrypto"&gt;jwcrypto&lt;/a&gt;, an
implementation of the various standards coming out of JOSE. I grepped through
the source, found the &lt;code&gt;RSAKey.readPublicKeyFromPEMString&lt;/code&gt; and
&lt;code&gt;RSAKey.readPrivateKeyFromPEMString&lt;/code&gt; functions, but wasn’t able to figure out
how to take those and serialize them back out to the JSON format.&lt;/p&gt;

&lt;p&gt;I eventually stumbled upon &lt;code&gt;jwk.KeyPair.generate&lt;/code&gt; and used that to create a
new JWK KeyPair, which I then dumped to JSON with the &lt;code&gt;toSimpleObject&lt;/code&gt; method
on the KeyPair’s &lt;code&gt;publicKey&lt;/code&gt; and &lt;code&gt;privateKey&lt;/code&gt; members. The output looked like
the public key on eyedee.me and not like the one in the JWK or BrowserID
specs, but it was at least a proper keypair! I dumped my old openssl-derived
keys and forged ahead with these new keys, plugging the public key into its
place in &lt;code&gt;.well-known/browserid&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now for the two other attributes: &lt;code&gt;authentication&lt;/code&gt; and &lt;code&gt;provisioning&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id="The+Authentication+Page"&gt;The Authentication Page&lt;/h3&gt;

&lt;p&gt;The “Identity Provisioning Flow” section of the spec was pretty
straightforward: The user agent tries to provision a new key by loading the
&lt;code&gt;provisioning&lt;/code&gt; URL in an invisible iframe, and if the user isn’t sufficiently
authenticated with the IdP, the provisioning page raises a provisioning
failure and the user gets taken to the &lt;code&gt;authentication&lt;/code&gt; page.&lt;/p&gt;

&lt;p&gt;Since MockMyID never requires any authentication, I just stubbed out a
&lt;a href="https://github.com/callahad/mockmyid/blob/master/public_html/browserid/sign_in.html"&gt;mostly-empty&lt;/a&gt;
HTML document and saved it at &lt;code&gt;/browserid/sign_in.html&lt;/code&gt;. No one should ever
see that page, but at least it won’t 404.&lt;/p&gt;

&lt;h3 id="The+Provisioning+Page"&gt;The Provisioning Page&lt;/h3&gt;

&lt;p&gt;The BrowserID Spec does a good job of outlining what needs to happen on the
provisioning page under the “Certifying Users” subheading, but there was a
bunch of useful information scattered in other sections. Everything starts
with a call to &lt;code&gt;navigator.id.beginProvisioning(callback)&lt;/code&gt;, with the callback
described as “a function that accepts an email address as parameter.” However,
under the “User-Agent Compliance” section, that same function is described as
needing to “accept parameters &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;cert_duration_s&lt;/code&gt;,” and it’s used in
this manner in the example in the “Identity Provisioning Flow” section earlier
in the document.&lt;/p&gt;

&lt;p&gt;If the user is properly authenticated (which is always true in mockmyid’s
case), the provisioning page then needs to call
&lt;code&gt;navigator.id.genKeyPair(callback)&lt;/code&gt; to request that the client generates a
keypair for the site to sign. If everything checks out the site is supposed to
build a signed Identity Certificate and pass that to
&lt;code&gt;navigator.id.registerCertificate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I stubbed out everything as per the example in the spec, but before diving
into generating signed certificates, I figured I should make sure that
everything else was at least set up properly. I added a self-signed SSL
certificate to Nginx and tried to log in at
&lt;a href="http://dev.myfavoritebeer.org/"&gt;dev.myfavoritebeer.org&lt;/a&gt;, which was mentioned
in the “IdP Developer Tips and Tricks” article on MDN. Watching the JavaScript
console, I saw an early problem: &lt;code&gt;navigator.id.beginProvisioning&lt;/code&gt; wasn’t
defined anywhere! Oops! From building a site that used BrowserID for
authentication, I knew about the &lt;code&gt;include.js&lt;/code&gt; file provided by browserid.org,
so I went and added that to a &lt;code&gt;script&lt;/code&gt; tag and tried again. Same problem.&lt;/p&gt;

&lt;p&gt;It turns out, &lt;code&gt;include.js&lt;/code&gt; doesn’t include definitions for provisioning stuff.
Rather, there’s another file at on browserid.org called &lt;code&gt;provisioning_api.js&lt;/code&gt;
that has all of that in it. I changed the &lt;code&gt;script&lt;/code&gt; tag and tried again.
Success! My callback was getting a key when I ran &lt;code&gt;navigator.id.genKeyPair&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;(It’s worth noting that, as per the Developer Tips, I wasn’t actually loading
the scripts from &lt;code&gt;browserid.org&lt;/code&gt;, but rather from &lt;code&gt;dev.diresworb.org&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;Now I just had to create the certificate and sign it. I started by typing out
a literal JSON structure similar to that in the example, but I couldn’t quite
figure out how to sign it. The spec just says that “when signed, [the
certificate] becomes a base64url-encoded data structure.” Helpful. From
looking at the JOSE stuff, there’s mention of “JSON Web Signatures,” but that
link is also broken. Googling turned up a working link, but given the
discrepancies I saw between the BrowserID and JWK specs, I ended up just going
straight to eyedee.me’s source.&lt;/p&gt;

&lt;p&gt;Therein I discovered the &lt;code&gt;sign&lt;/code&gt; method on &lt;code&gt;JWCert&lt;/code&gt; objects, and a simple
constructor for said objects. Sold! The only thing I needed to do was find a
way to actually have the jwcrypto libraries available client-side.
Fortunately, the readme notes that
“&lt;a href="https://github.com/substack/node-browserify"&gt;Browserify&lt;/a&gt; is used to bundle
it all up,” and the repo includes a convenient &lt;code&gt;build.sh&lt;/code&gt; script to create
&lt;code&gt;vepbundle.js&lt;/code&gt; with all of the crypto libraries concatenated together.&lt;/p&gt;

&lt;p&gt;After adding that to the head of my provisioning page, I was able to take the
rest of the flow from eyedee.me and have a mostly-complete IdP. Folks on IRC
had pointed me to the &lt;a href="https://github.com/mozilla/browserid/blob/dev/scripts/check_primary_support"&gt;check_primary_support
script&lt;/a&gt;
in the BrowserID repo, which reported an all-clear.&lt;/p&gt;

&lt;p&gt;I tried to log into &lt;a href="http://dev.myfavoritebeer.org"&gt;dev.myfavoritebeer.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It worked!&lt;/p&gt;

&lt;h3 id="Making+it+Work+in+Production"&gt;Making it Work in Production&lt;/h3&gt;

&lt;p&gt;Knowing that I had a functional IdP, I switched all of the &lt;code&gt;dev.diresworb.org&lt;/code&gt;
references over to &lt;code&gt;browserid.org&lt;/code&gt;, went to the standard
&lt;a href="http://myfavoritebeer.org"&gt;myfavoritebeer.org&lt;/a&gt; site, and… it failed. I got
the “this looks like a new email address!” login flow used with non-IdP
email addresses.&lt;/p&gt;

&lt;p&gt;Looking at the network flow, I saw request to
&lt;code&gt;https://browserid.org/wsapi/address_info?email=dan@mockmyid.com&lt;/code&gt; which
returned the JSON structure &lt;code&gt;{"type":"secondary","known":false}&lt;/code&gt;. Yet hitting
that same URL on &lt;code&gt;dev.diresworb.org&lt;/code&gt; showed the correct information:
&lt;code&gt;{"auth":"https://mockmyid.com/browserid/sign_in.html","prov":"https://mockmyid.com/browserid/provision.html","type":"primary"}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After scratching my head for a while, I realized that the production site
requires a properly signed SSL certificated, and thus my self-signed one just
wouldn’t do. The failure mode involved gracefully degrading the the
email-based verification workflow, but I would’ve appreciated it if either
&lt;code&gt;check_primary_support&lt;/code&gt; or the &lt;code&gt;wsapi&lt;/code&gt; call had given me some clue as to this
being a problem.&lt;/p&gt;

&lt;p&gt;Everything worked flawlessly after I installed a proper SSL certificate. I was
done!&lt;/p&gt;

&lt;p&gt;MockMyID is live, and you can use it right now.&lt;/p&gt;

&lt;h2 id="Next+Steps"&gt;Next Steps&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I would’ve really appreciated an abbreviated guide to building an IdP. The
Spec is nice, but there needs to be somewhere that we can say “Oh, and by
the way, we’ve totally built a JavaScript implementation of this part for
you.  It’s available over here.”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Explicitly pointing people to &lt;code&gt;check_primary_support&lt;/code&gt; and
&lt;code&gt;/wsapi/address_info&lt;/code&gt; would be useful.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I need to figure out what’s going on with the discrepancies between the
BrowserID spec and the JOSE specs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;I’ll be working on the documentation in the coming weeks, but I can’t do it
all alone! If you’re interested in improving the status quo, contributions are
always welcome on the &lt;a href="https://developer.mozilla.org/en/BrowserID/"&gt;BrowserID section of
MDN&lt;/a&gt;. It’s a wiki, so anyone can
help out!&lt;/p&gt;

&lt;h2 id="Resources"&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Lloyd’s &lt;a href="https://github.com/lloyd/eyedee.me"&gt;eyedee.me&lt;/a&gt;, the
proof-of-concept IdP; great for demonstrations and exploring the API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ozten’s &lt;a href="https://github.com/ozten/vinz-clortho"&gt;Vinz Clortho&lt;/a&gt;, an
LDAP-backed IdP, soon to become Mozilla.com’s internal IdP.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/callahad/mockmyid"&gt;MockMyID’s source code&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
    <summary type="html">Building a BrowserID Identity Provider</summary>
  </entry>
  <entry>
    <id>tag:dancallahan.info,2012-02-26:/journal/startup-employee-sanity-check/</id>
    <title type="html">A Startup Employee's Checklist for Tough Times</title>
    <published>2012-02-26T20:35:19Z</published>
    <updated>2012-02-26T20:35:19Z</updated>
    <link rel="alternate" href="http://dancallahan.info/journal/startup-employee-sanity-check/" />
    <content type="html">&lt;p&gt;Startups are, by their nature, risky endeavours. As an early-stage employee,
you’re often exposed to much of the same risk as the founders: namely, what
happens when the money simply isn’t there to make that month’s payroll?
There’s an enormous opportunity cost associated with sticking around once the
runway runs out, but leaving too soon may be foolhardy.&lt;/p&gt;

&lt;p&gt;When I faced the prospect of working through a “dry period” at a startup, I
had trouble finding clarity and direction. Answering the following questions,
and revisiting them periodically, was immensely helpful.&lt;/p&gt;

&lt;h2 id="The+Questions"&gt;The Questions&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;How long am I willing to work without pay?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How long can I work without pay?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What concessions do I need to make working without pay feasible?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What lifestyle changes should I make to ease working without pay?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To what degree can my employer extend its runway through cutting costs?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How confident am I that my employer will raise additional funding?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If my employer raises additional funding, how and when am I likely to be
compensated for my working without pay?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When is my apartment’s lease up for renewal?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under what terms can I extend my lease?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Should I extend my lease, find a new place, or move to another city or
region?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What job prospects are readily available?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What do I need to do in order to be ready to apply for them?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When should I start applying for them?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When should I start contacting people in my network in advance of
applying?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Or, to put it another way: What is my personal runway, how far down it am I
willing to go, and how likely is it to pay off in the end?&lt;/p&gt;</content>
    <summary type="html">A sanity check for when the money runs out.</summary>
  </entry>
  <entry>
    <id>tag:dancallahan.info,2012-01-15:/journal/python-flake8/</id>
    <title type="html">Useful Python Modules: Flake8</title>
    <published>2012-01-16T01:26:47Z</published>
    <updated>2012-01-16T01:26:47Z</updated>
    <link rel="alternate" href="http://dancallahan.info/journal/python-flake8/" />
    <content type="html">&lt;p&gt;This article is based on a presentation I gave at &lt;a href="http://python.mn/"&gt;PyMNtos&lt;/a&gt; in January, 2012.&lt;/p&gt;

&lt;p&gt;Every Pythonista should be familiar with &lt;a href="http://python.org/dev/peps/pep-0008/"&gt;PEP 8&lt;/a&gt;, Guido’s “Style Guide for
Python Code.” It’s a wonderful document that, should it be followed, ensures
that your code is stylistically consistent with code written by other
developers. Greater consistency is a huge win, since it makes everyone’s life
easier when interacting with your code.&lt;/p&gt;

&lt;p&gt;Amongst PEP 8’s many recommendations are things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use 4 spaces per indentation level.&lt;/li&gt;
&lt;li&gt;Separate top-level function and class definitions with two blank lines.&lt;/li&gt;
&lt;li&gt;Use spaces around arithmetic operators.&lt;/li&gt;
&lt;li&gt;Imports should usually be on separate lines.&lt;/li&gt;
&lt;li&gt;Limit all lines to a maximum of 79 characters.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;But how do you remember all of those? Enter: pep8.&lt;/p&gt;

&lt;h2 id="pep8:+A+Style+Checker+for+Python+Code"&gt;pep8: A Style Checker for Python Code&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;pep8&lt;/code&gt; script simply checks your code against PEP 8 and warns you about
inconsistencies. You can install it with &lt;code&gt;pip install pep8&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let’s look at a quick example. Check out the code below:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-python"&gt;import os, sys
from csv import *

def double(x):
    return x+x

def square(x):
    return x*x&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It’s simple, and it works, but the style is all wrong!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I have two imports, &lt;code&gt;os&lt;/code&gt; and &lt;code&gt;sys&lt;/code&gt;, on the same line.&lt;/li&gt;
&lt;li&gt;I only have one blank line in between function definitions.&lt;/li&gt;
&lt;li&gt;I don’t have any spaces around my &lt;code&gt;+&lt;/code&gt; and &lt;code&gt;*&lt;/code&gt; operators.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Let’s see what happens when I run it through &lt;code&gt;pep8&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-console"&gt;$ pep8 -r mymath.py
mymath.py:1:10: E401 multiple imports on one line
mymath.py:4:1: E302 expected 2 blank lines, found 1
mymath.py:5:13: E225 missing whitespace around operator
mymath.py:7:1: E302 expected 2 blank lines, found 1
mymath.py:8:13: E225 missing whitespace around operator&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Not only did it find those mistakes, but I can also use the &lt;code&gt;--show-pep8&lt;/code&gt;
option to get it to quote PEP 8 at me for each transgression!&lt;/p&gt;

&lt;p&gt;But what about other problems, like the fact that those useless imports are
there at all? That’s whare PyFlakes comes in.&lt;/p&gt;

&lt;h2 id="pyflakes:+An+Error+Checker+for+Python"&gt;pyflakes: An Error Checker for Python&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;pyflakes&lt;/code&gt; script reads your code and warns you about common sources of
errors. You can install it with &lt;code&gt;pip install pyflakes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Pyflakes catches things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unused imports and variables.&lt;/li&gt;
&lt;li&gt;Shadowed or clobbered names.&lt;/li&gt;
&lt;li&gt;Redefined functions.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Check it out:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-console"&gt;$ pyflakes mymath.py
mymath.py:1: 'sys' imported but unused
mymath.py:1: 'os' imported but unused
mymath.py:2: 'from csv import *' used; unable to detect undefined names&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Awesome!&lt;/p&gt;

&lt;p&gt;But what if I cared about style &lt;em&gt;and&lt;/em&gt; sources of error?&lt;/p&gt;

&lt;h2 id="flake8:+pep8+++pyflakes+++more"&gt;flake8: pep8 + pyflakes + more&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://ziade.org/"&gt;Tarek Ziadé&lt;/a&gt; wrote Flake8, which brings together pep8 and pyflakes in
one convenient standalone package. You don’t even need separate installations
of pep8 or pyflakes, since those come baked in to Flake8. You can install it
with &lt;code&gt;pip install flake8&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To these scripts, Tarek also added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Mercurial commit hook.&lt;/li&gt;
&lt;li&gt;A way to exempt files or lines from being checked.&lt;/li&gt;
&lt;li&gt;An optional cyclomatic complexity checker.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;(Cyclomatic complexity is a measure of your code’s “complexity,” derived
primarily from its degree of nesting and branching. Too much in any one
function, and the code is likely difficult to read, maintain, or reason about.)&lt;/p&gt;

&lt;p&gt;The output is what you might expect:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-console"&gt;$ flake8 mymath.py
mymath.py:1: 'sys' imported but unused
mymath.py:1: 'os' imported but unused
mymath.py:2: 'from csv import *' used; unable to detect undefined names
mymath.py:1:10: E401 multiple imports on one line
mymath.py:4:1: E302 expected 2 blank lines, found 1
mymath.py:5:13: E225 missing whitespace around operator
mymath.py:7:1: E302 expected 2 blank lines, found 1
mymath.py:8:13: E225 missing whitespace around operator&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But hey, that’s super useful! You should install it!&lt;/p&gt;

&lt;h2 id="Special+Bonus+Mention:+Syntastic:+Syntax+Checking+for+Vim"&gt;Special Bonus Mention: Syntastic: Syntax Checking for Vim&lt;/h2&gt;

&lt;p&gt;If you use Vim and like the ideas behind flake8, you should absolutely install
the &lt;a href="https://github.com/scrooloose/syntastic/"&gt;Syntastic&lt;/a&gt; plugin. When you save a file, Syntastic runs it through an
error checker and warns you about potential issues. For Python, it defaults to
using Flake8.&lt;/p&gt;

&lt;p&gt;Check out what happens when I try to save the &lt;code&gt;mymath.py&lt;/code&gt; script shown above:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://dancallahan.info/journal/python-flake8/syntastic-flake8.png" alt="Syntastic showing errors in a Vim session"&gt;&lt;/p&gt;

&lt;p&gt;Erroneous lines get highlighted, and the Location List gets filled with a
listing of all of the errors. Cool, right?&lt;/p&gt;

&lt;p&gt;What’s even better is that Syntastic is able to take advantage of syntax
checkers for a ton of languages, both mainstream and obscure. To wit, it
supports C, CoffeeScript, Go, Haskell, JavaScript, Puppet, Vala, and more.&lt;/p&gt;

&lt;h2 id="Resources"&gt;Resources&lt;/h2&gt;

&lt;p&gt;You can download a copy of &lt;a href="http://dancallahan.info/journal/python-flake8/python-flake8-Jan2012.pdf"&gt;the slides&lt;/a&gt; (PDF) that I used for my
presentation.&lt;/p&gt;

&lt;p&gt;You can also find links to the previously mentioned projects below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://python.org/dev/peps/pep-0008/"&gt;PEP 8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pypi.python.org/pypi/pep8"&gt;pep8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pypi.python.org/pypi/pyflakes"&gt;Pyflakes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pypi.python.org/pypi/flake8"&gt;Flake8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/scrooloose/syntastic/"&gt;Syntastic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
    <summary type="html">Simple static analysis. Presented at PyMNtos, January 2012.</summary>
  </entry>
  <entry>
    <id>tag:dancallahan.info,2011-12-31:/journal/go-concurrency-slides/</id>
    <title type="html">Go Concurrency Presentation Slides</title>
    <published>2011-12-31T16:21:17Z</published>
    <updated>2011-12-31T16:21:17Z</updated>
    <link rel="alternate" href="http://dancallahan.info/journal/go-concurrency-slides/" />
    <content type="html">&lt;p&gt;These resources were used when I presented on concurrency in the Go programming
language at &lt;a href="http://python.mn"&gt;PyMNtos&lt;/a&gt; in December, 2011.&lt;/p&gt;

&lt;p&gt;You can read my write up of the presentation in two parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="http://dancallahan.info/journal/go-overview/"&gt;An Overview of Go&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://dancallahan.info/journal/go-concurrency/"&gt;Concurrency in the Go Programmign Language&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;You can also download:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://dancallahan.info/journal/go-concurrency-slides/golang-concurrency-Dec2011.pdf"&gt;My Slides&lt;/a&gt; (PDF).&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://dancallahan.info/journal/go-concurrency-slides/golang-concurrency-code.tar.gz"&gt;Code Samples&lt;/a&gt; used in the presentation.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://dancallahan.info/journal/go-concurrency-slides/golang-concurrency-notes.tar.gz"&gt;My Presentation notes&lt;/a&gt;, in VimOutliner (plain text) format.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;If you have any questions, please get in touch!&lt;/p&gt;</content>
    <summary type="html">Supplemental. Presented at PyMNtos, December 2011.</summary>
  </entry>
</feed>
