<?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/"
	>

<channel>
	<title>Ian Bicking: a blog</title>
	<atom:link href="http://blog.ianbicking.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.ianbicking.org</link>
	<description></description>
	<pubDate>Sat, 23 May 2009 02:35:58 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>WebOb decorator</title>
		<link>http://blog.ianbicking.org/2009/05/22/webob-decorator/</link>
		<comments>http://blog.ianbicking.org/2009/05/22/webob-decorator/#comments</comments>
		<pubDate>Sat, 23 May 2009 02:35:58 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Python]]></category>

		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=122</guid>
		<description><![CDATA[
Lately I&#8217;ve been writing a few applications (e.g., PickyWiki and a revisiting a request-tracking application VaingloriousEye), and I usually use no framework at all.  Pylons would be a natural choice, but given that I am comfortable with all the components, I find myself inclined to assemble the pieces myself.
In the process I keep writing [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>Lately I&#8217;ve been writing a few applications (e.g., <a class="reference external" href="http://pickywiki.org">PickyWiki</a> and a revisiting a request-tracking application <a class="reference external" href="http://svn.pythonpaste.org/Paste/VaingloriousEye/trunk">VaingloriousEye</a>), and I usually use no framework at all.  <a class="reference external" href="http://pylonshq.com">Pylons</a> would be a natural choice, but given that I am comfortable with all the components, I find myself inclined to assemble the pieces myself.</p>
<p>In the process I keep writing bits of code to make WSGI applications from simple <a class="reference external" href="http://pythonpaste.org/webob/">WebOb</a> -based request/response cycles.  The simplest form looks like this:</p>
<pre class="literal-block">
from webob import Request, Response, exc

def wsgiwrap(func):
    def wsgi_app(environ, start_response):
        req = Request(environ)
        try:
            resp = func(req)
        except exc.HTTPException, e:
            resp = e
        return resp(environ, start_response)
    return wsgi_app

&#64;wsgiwrap
def hello_world(req):
    return Response('Hi %s!' % (req.POST.get('name', 'You')))
</pre>
<p>But each time I&#8217;d write it, I change things slightly, implementing more or less features.  For instance, <a class="reference external" href="http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/">handling methods</a>, or coercing other responses, or handling middleware.</p>
<p>Having implemented several of these (and <a class="reference external" href="http://svn.pythonpaste.org/Paste/WebOb/contrib">reading other people&#8217;s implementations</a>) I decided I wanted WebOb to include a kind of reference implementation.  But I don&#8217;t like to include anything in WebOb unless I&#8217;m sure I can get it <em>right</em>, so I&#8217;d really like feedback.  (There&#8217;s been some <a class="reference external" href="http://groups.google.com/group/paste-users/browse_thread/thread/7346e75940413f46">less than positive feedback</a>, but I trudge on.)</p>
<p>My implementation is in a <a class="reference external" href="http://svn.pythonpaste.org/Paste/WebOb/branches/ianb-decorator-experiment">WebOb branch</a>, primarily in <a class="reference external" href="http://svn.pythonpaste.org/Paste/WebOb/branches/ianb-decorator-experiment/webob/dec.py">webob.dec</a> (along with some <a class="reference external" href="http://svn.pythonpaste.org/Paste/WebOb/branches/ianb-decorator-experiment/tests/test_dec.txt">doctests</a>).</p>
<p>The most prominent way this is different from the example I gave is that it doesn&#8217;t change the function signature, instead it adds an attribute <tt class="docutils literal"><span class="pre">.wsgi_app</span></tt> which is WSGI application associated with the function.  My goal with this is that the decorator isn&#8217;t intrusive.  Here&#8217;s the case where I&#8217;ve been bothered:</p>
<pre class="literal-block">
class MyClass(object):
    &#64;wsgiwrap
    def form(self, req):
        return Response(form_html...)

    &#64;wsgiwrap
    def form_post(self, req):
        handle submission
</pre>
<p>OK, that&#8217;s fine, then I add validation:</p>
<pre class="literal-block">
&#64;wsgiwrap
def form_post(self, req):
    if req not valid:
        return self.form
    handle submission
</pre>
<p>This still works, because the decorator allows you to return <em>any</em> WSGI application, not just a WebOb Response object.  But that&#8217;s not helpful, because I need errors&#8230;</p>
<pre class="literal-block">
&#64;wsgiwrap
def form_post(self, req):
    if req not valid:
        return self.form(req, errors)
    handle submission
</pre>
<p>That is, I want to have an option argument to the <tt class="docutils literal"><span class="pre">form</span></tt> method that passes in errors.  But I can&#8217;t do this with the traditional <tt class="docutils literal"><span class="pre">wsgiwrap</span></tt> decorator, instead I have to refactor the code to have a third method that both <tt class="docutils literal"><span class="pre">form</span></tt> and <tt class="docutils literal"><span class="pre">form_post</span></tt> use.  Of course, there&#8217;s more than one way to address this issue, but this is the technique I like.</p>
<p>The one other notable feature is that you can also make middleware:</p>
<pre class="literal-block">
&#64;wsgify.middleware
def cap_middleware(req, app):
    resp = app(req)
    resp.body = resp.body.upper()
    return resp

capped_app = cap_middleware(some_wsgi_app)
</pre>
<p>Otherwise, for some reason I&#8217;ve found myself putting an inordinate amount of time into <tt class="docutils literal"><span class="pre">__repr__</span></tt>.  Why I&#8217;ve done this I cannot say.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2009/05/22/webob-decorator/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Treating configuration values as templates</title>
		<link>http://blog.ianbicking.org/2009/04/20/treating-configuration-values-as-templates/</link>
		<comments>http://blog.ianbicking.org/2009/04/20/treating-configuration-values-as-templates/#comments</comments>
		<pubDate>Mon, 20 Apr 2009 06:11:43 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=116</guid>
		<description><![CDATA[
A while back I described fassembler and one of the things I liked in it is how the configuration works.  It uses a conventional declarative INI-style but also allows arbitrary code, so that defaults can be based on each other.
Here&#8217;s a basic example of a default configuration:

[some_app]
port_offset = 10
port = {{int(section.DEFAULT['base_port'])+int(port_offset)}}

Then if another configuration [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>A while back I <a class="reference external" href="http://blog.ianbicking.org/2008/06/19/my-experience-writing-a-build-system/">described fassembler</a> and one of the things I liked in it is how the configuration works.  It uses a conventional declarative INI-style but also allows arbitrary code, so that defaults can be based on each other.</p>
<p>Here&#8217;s a basic example of a default configuration:</p>
<pre class="literal-block">
[some_app]
port_offset = 10
port = {{int(section.DEFAULT['base_port'])+int(port_offset)}}
</pre>
<p>Then if another configuration file defines <tt class="docutils literal"><span class="pre">base_port</span></tt> then this will all resolve.  You can do this in Python, but you don&#8217;t get sections, and you have to define everything in just the right order.  So while <tt class="docutils literal"><span class="pre">base_port</span></tt> will probably be defined in a deployment-specific configuration, it has to be defined before these other derivative settings are defined.  On the other hand, you want deployment-specific configuration to take precedence&#8230; so there&#8217;s really no good ordering.</p>
<p>Anyway, the implementation really isn&#8217;t that hard.  I use <a class="reference external" href="http://pythonpaste.org/tempita/">Tempita</a> as the templating language because, well, I wrote it, and because it&#8217;s simple and appropriate for small strings.  For the configuration parsing, <a class="reference external" href="http://docs.python.org/library/configparser.html">ConfigParser</a> will do.</p>
<p>Here&#8217;s what the basic code looks like in ConfigParser:</p>
<pre class="literal-block">
from ConfigParser import ConfigParser
from tempita import Template

class TempitaConfigParser(ConfigParser):

    def _interpolate(self, section, option, rawval, vars):
        ns = _Namespace(self, section, vars)
        tmpl = Template(rawval, name='%s.%s' % (section, option))
        value = tmpl.substitute(ns)
        return value
</pre>
<p>Actually instead of using <tt class="docutils literal"><span class="pre">tempita.Template</span></tt>, we could just do <tt class="docutils literal"><span class="pre">eval(rawval,</span> <span class="pre">{},</span> <span class="pre">ns)</span></tt>, it would just require a lot more quoting (every value would have to be a valid Python expression).  Either with that or Tempita the implementation of <tt class="docutils literal"><span class="pre">_Namespace</span></tt> will look the same.</p>
<p>Here&#8217;s a simple implementation:</p>
<pre class="literal-block">
from UserDict import DictMixin

class _Namespace(DictMixin):
    def __init__(self, config, section, vars):
        self.config = config
        self.section = section
        self.vars = vars

    def __getitem__(self, key):
        if key == 'section':
            return _Section(self)
        if self.config.has_option(self.section, key):
            return self.config.get(self.section, key)
        if vars and key in self.vars:
            return self.vars[key]
        raise KeyError(key)

   def __setitem__(self, key, value):
       if self.vars is None:
           self.vars = {key: value}
       else:
           self.vars[key] = value
</pre>
<p>We&#8217;ve introduced a magic variable <tt class="docutils literal"><span class="pre">section</span></tt>, which is used to refer to other sections.  It looks like this:</p>
<pre class="literal-block">
class _Section(object):
    def __init__(self, namespace):
        self._namespace = namespace

    def __getattr__(self, attr):
        if attr.startswith('_'):
            raise AttributeError(attr)
        return _Namespace(self._namespace.config, attr,     self._namespace.vars)
</pre>
<p>With these I think you get many of the benefits of using Python code as your configuration format, while still having the benefits of a more declarative approach to configuration, one that allows for forward and backward references.</p>
<p>A full implementation has several more things than I show here, but you can see the full example <a class="reference external" href="http://svn.colorstudy.com/home/ianb/recipes/evalconfig.py">in my recipes</a>.  It also has an example of using <a class="reference external" href="http://pythonpaste.org/initools/">INITools</a> instead of ConfigParser to give more accurate filenames and line numbers when there is an exception, while otherwise using the same interface.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2009/04/20/treating-configuration-values-as-templates/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Woonerf and Python</title>
		<link>http://blog.ianbicking.org/2009/01/16/woonerf-and-python/</link>
		<comments>http://blog.ianbicking.org/2009/01/16/woonerf-and-python/#comments</comments>
		<pubDate>Fri, 16 Jan 2009 19:09:26 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=109</guid>
		<description><![CDATA[
At TOPP there&#8217;s a lot of traffic discussion, since a substantial portion of the organization is dedicated to Livable Streets initiatives.  One of the traffic ideas people have gotten excited about is Woonerf.  This is a Dutch traffic planning idea.  In areas where there&#8217;s the intersection of lots of kinds of traffic [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>At <a class="reference external" href="http://topp.openplans.org/">TOPP</a> there&#8217;s a lot of traffic discussion, since a substantial portion of the organization is dedicated to <a class="reference external" href="http://www.livablestreets.com/">Livable Streets</a> initiatives.  One of the traffic ideas people have gotten excited about is <a class="reference external" href="http://www.livablestreets.com/streetswiki/woonerf">Woonerf</a>.  This is a Dutch traffic planning idea.  In areas where there&#8217;s the intersection of lots of kinds of traffic (car, pedestrian, bike, destinations and through traffic) you have to deal with the contention for the streets.  Traditionally this is approached as a complicated system of rules and right-of-ways.  There&#8217;s spaces for each mode of transportation, lights to say which is allowed to go when (with lots of red and green arrows), crosswalk islands, concrete barriers, and so on.</p>
<p>A problem with this is that a person can only pay attention to so many things at a time.  As the number of traffic controls increases, the controls themselves dominate your attention.  It&#8217;s based on the ideal that so long as everyone pays attention tothe controls, they don&#8217;t have to pay attention to each other.  Of course, if there&#8217;s a circumstance the controls don&#8217;t take into account then people will deviate (for instance, crossing somewhere other than the crosswalk, or getting in the wrong lane for a turn, or the simple existance of a bike is usually unaccounted for).  If all attention is on the controls, and everyone trusts that the controls are being obeyed, these deviations can lead to accidents.  This can create a negative feedback cycle where the controls become increasingly complex to try to take into account every possibility, with the addition of things like <a class="reference external" href="http://en.wikipedia.org/wiki/Jersey_barriers">Jersey barriers</a> to exclude deviant traffic.  At least in the U.S., and especially in the suburbs or in complex intersections, this feeling of an overcontrolled and restricted traffic plan is common.</p>
<p><img align="right" alt="Copenhagen retail street" class="align-right" src="/wp-content/uploads/images/Copenhagen_retail_street.jpg" /></p>
<p>So: Woonerf.  This is an extreme reaction to traffic controls.  An intersection designed with the principles of Woonerf eschews all controls.  This includes even things like curbs and signage.  It removes most cues about behavior, and specifically of the concept of &quot;right of way&quot;.  Every person entering the intersection must view it as a <em>negotiation</em>.  The use of eye contact, body language, and hand signals determines who takes the right of way.  In this way all kinds of traffic are peers, regardless of destination or mode of transport.  Also each person must focus on where they are right now, and not where they will be a minute from now; they must stay engaged.</p>
<hr class="docutils" />
<img align="left" alt="Code as Jersey Barrier" class="align-left" src="/wp-content/uploads/images/code-based-jersey-barrier.jpg" /></p>
<p>So, I was reading a critique of Python where someone was saying how they missed public/private/protected distinctions on attributes and methods.  And it occurred to me: Python&#8217;s object model is like Woonerf.</p>
<p>Python does not enforce rules about what you must and must not do.  There are cues, like leading underscores, the <tt class="docutils literal"><span class="pre">__magic_method__</span></tt> naming pattern, or at the module level there&#8217;s <tt class="docutils literal"><span class="pre">__all__</span></tt>.  But there are no curbs, you won&#8217;t even feel the slightest bump when you access a &quot;private&quot; attribute on an instance.</p>
<p>This can lead to conflicts.  For example, during discussions on installation, some people will argue for creating requirements like <tt class="docutils literal"><span class="pre">&quot;SomeLibrary&gt;=1.0,&lt;2.0&quot;</span></tt>, with the expectation that while version 2.0 doesn&#8217;t exist, so long as you install something in the 1.x line it will maintain compatibility with your application.  This is an unrealistic expectation.  Do you and the library maintainer have the same idea about what compatibility means?  What if you depend on something the maintainer considers a bug?</p>
<p>Practically, you can&#8217;t be sure that future versions of a library will work.  You also can&#8217;t be sure they won&#8217;t work; there&#8217;s nothing that <em>requires</em> the maintainer of the library to break your application with version 2.0.  This is where it becomes a negotiation.  If you decide to cross without a crosswalk (use a non-public API) then okay.  You just have to keep an eye out.  And library authors, whether they like it or not, need to consider the API-as-it-is-used as much as the API-they-have-defined.  In open source in particular, there are a lot of ways to achieve this communication.  We don&#8217;t use some third party (e.g., a QA team or language features) to enforce rules on both sides (there are no traffic controls), instead the communication is more flat, and speaks as much to <em>intentions</em> as <em>mechanisms</em>.  When someone asks &quot;how do I do X?&quot; a common response is: &quot;what are you trying to accomplish?&quot;  Often an answer to the second question makes the first question irrelevant.</p>
<p>Woonerf is great for small towns, for creating a humane space.  Is it right for big cities and streets, for busy people who want to get places fast, for trucking and industry?  I&#8217;m not sure, but probably not.  This is where a multi-paradigm approach is necessary.  Over time libraries have to harden, become more static, innovation should happen on top of them and not in the library.  Some times we create third party controls through interfaces (of <a class="reference external" href="http://wiki.zope.org/Interfaces/FrontPage">one kind</a> or <a class="reference external" href="http://www.python.org/dev/peps/pep-0333/">another</a>).  I suppose in this case there is a kind of negotiation about how we negotiate &#8212; there&#8217;s no one process for how to build negotiation-free foundations in Python.  But it&#8217;s best not to harden things you aren&#8217;t sure are right, and I&#8217;m pretty sure there&#8217;s no &quot;right&quot; at this very-human level of abstraction.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2009/01/16/woonerf-and-python/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Cultural Imperialism, Technology, and OLPC</title>
		<link>http://blog.ianbicking.org/2009/01/14/cultural-imperialism-technology-and-olpc/</link>
		<comments>http://blog.ianbicking.org/2009/01/14/cultural-imperialism-technology-and-olpc/#comments</comments>
		<pubDate>Thu, 15 Jan 2009 00:58:49 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
		
		<category><![CDATA[Non-technical]]></category>

		<category><![CDATA[OLPC]]></category>

		<category><![CDATA[Politics]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=89</guid>
		<description><![CDATA[
A couple posts have got me thinking about cultural imperialism lately: a post by Guido van Rossum about &#34;missionaries&#34; and OLPC not about OLPC at all, a post by Chris Hardie and a speech by Wade Davis.
Some of the questions raised: are we destroying cultures?  If so, what can we do about it?  [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>A couple posts have got me thinking about cultural imperialism lately: a <a class="reference external" href="http://neopythonic.blogspot.com/2008/11/bibles-or-computers-its-same-thing.html">post by Guido van Rossum about &quot;missionaries&quot; and OLPC</a> not about OLPC at all, <a class="reference external" href="http://www.chrishardie.com/blog/2008/10/failed-attempts-at-being-you.html">a post by Chris Hardie</a> and <a class="reference external" href="http://www.ted.com/index.php/talks/wade_davis_on_endangered_cultures.html">a speech by Wade Davis</a>.</p>
<p>Some of the questions raised: are we destroying cultures?  If so, what can we do about it?  Must we be hands off?  I will add these questions: is it patronizing to make these choices for other people, no matter how enlightened we try to be?  How much change is inevitable?  Can we help make the change positive instead of resisting change?</p>
<p>More specifically: what is the effect of <a class="reference external" href="http://laptop.org">OLPC</a> on cultures where it is introduced?  Especially small cultures, cultures that have been relatively isolated, cultures that are vulnerable.  The internet <a class="reference external" href="http://en.wikipedia.org/wiki/Quechua">Quechua</a> community is pretty slim, for example.  Introducing the internet into a community will lead the children to favor Spanish more strongly, and identify with that more dominant culture over their family and community culture.</p>
<p>Criticisms like Guido&#8217;s are common:</p>
<blockquote><p>
I&#8217;m not surprised that the pope is pleased by the OLPC program. The mentality from which it springs is the same mentality which in past centuries created the missionary programs. The idea is that we, the west, know what&#8217;s good for the rest of the world, and that we therefore must push our ideas onto the &quot;third world&quot; by means of the most advanced technology available. In past centuries, that was arguably the printing press, so we sent missionaries armed with stacks of bibles. These days, we have computers, so we send modern missionaries (of our western lifestyle, including consumerism, global warming, and credit default swaps) armed with computers.</p></blockquote>
<p>This kind of criticism is easy, because it doesn&#8217;t have any counterproposal.  It&#8217;s not saying much more than &quot;you all suck&quot; to the people involved.</p>
<p>Cultural imperialism is a genuine phenomena.  In an attempt to subjugate or assimilate, the dominant culture may explicitly and cynically enforce its cultural norms, through its religion, requiring all schools to operate in the dominant language, even going as far as <a class="reference external" href="http://en.wikipedia.org/wiki/Missionary_position">suggesting how we arrange ourselves during sex</a>.</p>
<p>But it&#8217;s not clear to me that what&#8217;s happening now is cultural imperialism.  It&#8217;s more market-oriented homogenization.  Food manufacturers don&#8217;t use high-fructose corn syrup because they want to make us fat &#8212; they just give us what we want, and they are enabling our latent tendency to become obese.  Similarly I think the way culture is spread currently encourages homogeneity, without explicit attempting to destroy culture.</p>
<p>This is where I think a protectionist stance &#8212; the idea we should just be hands-off &#8212; is patronizing.  People aren&#8217;t abandoning their cultures because they are stupid and they are being manipulated.  People make decisions, what they think is the best decision for themself and their families.  These decisions lead them to leave rural areas, learn the dominant language, try to conform through education, and even just lead them to enjoy a dominant culture which is often far more entertaining than a smaller and more traditional culture.</p>
<p>The irony is that once they&#8217;ve done this they&#8217;ve traded their position for a place in the bottom rung of the dominant society.  And it&#8217;s true that in many cases they&#8217;ve made these decisions because they&#8217;ve been forced out of their traditional life by political and legal systems they don&#8217;t understand.  But to blame it all on oppression is to be blind to the many concrete benefits of our modern world.  Corrugated metal roofs are simply superior to thatched roofs, and we can get all romantic about traditional building processes and material independence, but we do so from homes with roofs that don&#8217;t leak.  Leaking roofs are just objectively unpleasant.  And frankly people like TV, you don&#8217;t have to <em>tell</em> people to like TV, it just happens.</p>
<p>So I believe that assimilation pressure is natural and inevitable in our times.</p>
<p>What then of technology, of the internet and laptops?</p>
<p>I believe OLPC takes an important stance when it selects open source and open licensing for its content.  It is valuing freedom, but more importantly encouraging self-determination, trying to build up a user base that can act as peers in this project, not as simply receivers of first-world largess.  But it will be culturally disruptive.  And I&#8217;m okay with that.  In a patriarchal culture, giving girls access to this technology will be destructive to that power structure.  Yay!  I believe in the moral rightness of that one girl making her own choices, finding her own truths, more than I believe in the validity of the culture she was born into.  If you believe people should be able to make their own choices (so long as they are aware of the real consequence of their choices), then you must allow for them to choose to abandon their own cultures for something they find more appealing.  They might know better than you if that&#8217;s a good choice.  I think we all hope that instead they <em>transform</em> their own cultures, but that&#8217;s not our choice to make.</p>
<p>What I find unpleasant is if they leave a true identity to find themselves in a place of cultural subservience.  If they feel they can&#8217;t preserve the part of their culture they most value.  Perhaps because of discrimination they feel they must hide their past, or they build up a sense of self-loathing.  Perhaps they become isolated, unable to find peers that understand where they come from.  And perhaps there is no higher culture at all that they can use to exalt their understanding of the world &#8212; do they have a literature?  Do they have non-traditional music forms of their own?  Do they have a forum where people who share their perspective can have serious discussions?  Cultures aren&#8217;t destroyed so much as they are starved out of existence.</p>
<hr class="docutils" />
<p>I think assimilation is inevitable, and can be positive.  If we were all able to speak to each other, with some shared second or third language, I think the world would be a better place.  I&#8217;m not a Christian, but I&#8217;m not afraid of anyone knowing The Bible.  There&#8217;s no piece of culture that I would want to deny from anyone.  Each new song, each new book, each new idea&#8230; I believe they will all make you a better person, if only in a small way.</p>
<p>And on the internet our culture is cumulative.  There&#8217;s only so many hours of programming on TV or the radio, only so many pages in a newspaper.  On the internet the presence of one kind of culture does not exclude any other.  There&#8217;s room for a Quechua community as much of any other.  But the online Quechua community won&#8217;t have exclusive rights to its members like a traditional culture claims &#8212; children will live between cultures.</p>
<p>Cumulative culture is not a promise that anyone will care.  Languages can still die, cultures can still die, identities become forgotten.  If these smaller cultures are going to be preserved, they must adapt to the partially-assimilated status of their members.  There must be new art and new ideas and new identities.  This is why I believe in the laptop project, because it can enable the creation and sharing of these new ideas.  I think it will give smaller cultures a chance to survive &#8212; there&#8217;s no promises, literature doesn&#8217;t write itself, but maybe there is at least a chance.</p>
<p>This is also why I am more skeptical of mobile phones, audio devices, and any device that doesn&#8217;t actively enable content creation.  Mobile phones are not how culture is made.  It let&#8217;s people chat, consume information, communicate in a 12-key pidgin.  But the mobile phone user is not a peer in a world wide web of information.  The mobile phone user lives on a proprietary network, with a proprietary device, and while it perhaps it breaks down some hierarchies through disintermediation, it does so in a transient way.  The uptake is certainly faster, but the potential seems so much lower.</p>
<p>I don&#8217;t know if OLPC will be successful.  That&#8217;s as unclear now as ever.  But it&#8217;s trying to do the right thing, and I think it&#8217;s a better chance than most for maintaining or improving the richness of the worlds&#8217; culture.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2009/01/14/cultural-imperialism-technology-and-olpc/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Modern Web Design, I Renounce Thee!</title>
		<link>http://blog.ianbicking.org/2009/01/14/modern-web-design-i-renounce-thee/</link>
		<comments>http://blog.ianbicking.org/2009/01/14/modern-web-design-i-renounce-thee/#comments</comments>
		<pubDate>Wed, 14 Jan 2009 07:14:38 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
		
		<category><![CDATA[HTML]]></category>

		<category><![CDATA[Non-technical]]></category>

		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=96</guid>
		<description><![CDATA[
I&#8217;m not a designer, but I spend as much time looking at web pages as the next guy.  So I took interest when I came upon this post on font size by Wilson Miner, which in turn is inspired by the 100e2r (100% easy to read) standard by Oliver Reichenstein.
The basic idea is simple: [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>I&#8217;m not a designer, but I spend as much time looking at web pages as the next guy.  So I took interest when I came upon <a class="reference external" href="http://www.wilsonminer.com/posts/2008/oct/20/relative-readability/">this post on font size</a> by Wilson Miner, which in turn is inspired by the <a class="reference external" href="http://informationarchitects.jp/100e2r/">100e2r (100% easy to read) standard</a> by Oliver Reichenstein.</p>
<p>The basic idea is simple: we should have fonts at the &quot;default&quot; size, about 16px, no smaller.  This is about the size of text in print, read at a reasonable distance (typically closer up than a screen):</p>
<div align="center" class="align-center"><img alt="http://blog.ianbicking.org/wp-content/uploads/images/typesize_comparison2.jpg" class="align-center" src="http://blog.ianbicking.org/wp-content/uploads/images/typesize_comparison2.jpg" /></div>
<p>Also it calls out low-contrast color schemes, which I think are mostly passe, and I will not insult you, my reader, by suggesting you don&#8217;t entirely agree.  Because if you <em>don&#8217;t</em> agree, well, I&#8217;m afraid I&#8217;d have to use some strong words.</p>
<p>I think small fonts, low contrast, huge amounts of whitespace, are a side effect of the audience designers create for.</p>
<p>This makes me think of <a class="reference external" href="http://en.wikipedia.org/wiki/Modern_architecture">Modern Architecture</a>:</p>
<div align="center" class="align-center"><img alt="http://blog.ianbicking.org/wp-content/uploads/images/300px-seagram.jpg" class="align-center" src="http://blog.ianbicking.org/wp-content/uploads/images/300px-seagram.jpg" /></div>
<p>This is a form of architecture popular for skyscapers and other dramatic structures, with their soaring heights and other such dramatic adjectives.  These are buildings designed for someone looking at the building from five hundred feet away.  They are not designed for occupants.  But that&#8217;s okay, because the design isn&#8217;t sold to occupants, it is sold to people who look at the sketches and want to feel very dramatic.</p>
<p>Similarly, I think the design pattern of small fonts is something meant to appeal to shallow observation.  By deemphasizing the text itself, the design is accentuated.  Low-contrast text is even more obviously the domination of design over content.  And it may very well look more professional and visually pleasing.  But web design isn&#8217;t for making sites visually pleasing, it is for making the experience of the content more pleasing.  Sites exist for their content, not their design.</p>
<p>In 100e2r he also says <em>let your text breathe</em>.  You need whitespace.  If you <a class="reference external" href="http://blog.ianbicking.org/2009/01/14/modern-web-design-i-renounce-thee/">view my site directly</a>, you&#8217;ll notice I don&#8217;t have big white margins around my text.  When you come to my site, it&#8217;s to see my words, and that&#8217;s what I&#8217;m going to give you!  When I want to let my text <em>breathe</em> with lots of <em>whitespace</em> this is what I do:</p>
<div align="center" class="align-center"><img alt="http://blog.ianbicking.org/wp-content/uploads/images/500px-my-white-desktop.jpg" class="align-center" src="http://blog.ianbicking.org/wp-content/uploads/images/500px-my-white-desktop.jpg" /></div>
<p>Is a huge block of text hard to read?  It is.  And yeah, I&#8217;ve written articles like that.  But the solution?</p>
<div style="text-align: center"><b>WRITE BETTER</b></div>
<p>Similarly, it&#8217;s hard to read text if you don&#8217;t use paragraphs, but the solution isn&#8217;t to increase your line height until every line is like a paragraph of its own.</p>
<p>The solution to the drudgery of large swathes of text is:</p>
<ol class="arabic simple">
<li>Make your blocks of text smaller.</li>
<li>Use something other than paragraphs of text.</li>
</ol>
<p>Throw in a list.  Do some indentation.  Toss in even a stupid picture.  Personally I try to throw in code examples, because that&#8217;s how we roll on this blog.</p>
<p>That&#8217;s good writing, that&#8217;s content that is easy to read.  It&#8217;s not easy to write, and I&#8217;m sure I miss the mark more often than not.  But you can&#8217;t design your way to good content.  If you want to write like this, if you want to let the flow of your text reflect the flow of your ideas, you need <strong>room</strong>.  Huge margins don&#8217;t give you room.  They are a crutch for poor writing, and not even a good crutch.</p>
<p>So in conclusion: modern design be damned!</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2009/01/14/modern-web-design-i-renounce-thee/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Atompub as an alternative to WebDAV</title>
		<link>http://blog.ianbicking.org/2009/01/11/atompub-instead-o-webdav/</link>
		<comments>http://blog.ianbicking.org/2009/01/11/atompub-instead-o-webdav/#comments</comments>
		<pubDate>Sun, 11 Jan 2009 23:27:52 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
		
		<category><![CDATA[HTML]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=91</guid>
		<description><![CDATA[
I&#8217;ve been thinking about an import/export API for PickyWiki; I want something that&#8217;s sensible, and works well enough that it can be the basic for things like creating restorable snapshots, integration with version control systems, and being good at self-hosting documentation.
So far I&#8217;ve made a simple import/export system based on Atom.  You can export [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>I&#8217;ve been thinking about an import/export API for <a class="reference external" href="http://pickywiki.org">PickyWiki</a>; I want something that&#8217;s sensible, and works well enough that it can be the basic for things like creating restorable snapshots, integration with version control systems, and being good at self-hosting documentation.</p>
<p>So far I&#8217;ve made a simple import/export system based on Atom.  You can export the entire site as an Atom feed, and you can import Atom feeds.  But whole-site import/export isn&#8217;t enough for the tools I&#8217;d like to write on top of the API.</p>
<p><a class="reference external" href="http://en.wikipedia.org/wiki/WebDAV">WebDAV</a> would seem like a logical choice, as it lets you get and put resources.   But it&#8217;s not a great choice for a few reasons:</p>
<ul class="simple">
<li>It&#8217;s really hard to implement on the server.</li>
<li>Even clients are hard to implement.</li>
<li>It uses GET to get resources.  This is probably its most fatal flaw.  There is no CMS that I know of (except <a class="reference external" href="http://www.tiddlywiki.com/">maybe one</a>) where the thing you view the browser is the thing that you&#8217;d actually edit.  To work around this CMSes use User-Agent sniffing or an alternate URL space.</li>
<li>WebDAV is worried about &quot;collections&quot; (i.e., directories).  The web basically doesn&#8217;t know what &quot;collections&quot; are, it only knows paths, and paths are strings.</li>
<li>(In summary) WebDAV uses HTTP, but it is not <em>of the web</em>.</li>
</ul>
<p>I don&#8217;t want to invent something new though.  So I started thinking of Atom some more, and <a class="reference external" href="http://en.wikipedia.org/wiki/Atom_(standard)">Atompub</a>.</p>
<p>The first thought is how to fix the GET problem in WebDAV.  A web page isn&#8217;t an editable representation, but it&#8217;s pretty reasonable to put an editable representation into an Atom entry.  Clients won&#8217;t necessarily understand extensions and properties you might add to those entries, but I don&#8217;t see any way around that.  An entry might look like:</p>
<pre class="literal-block">
&lt;entry&gt;
  &lt;content type=&quot;html&quot;&gt;QUOTED HTML&lt;/content&gt;
  ... other normal metadata (title etc) ...
  &lt;privateprop:myproperty xmlns:privateprop=&quot;URL&quot; name=&quot;foo&quot; value=&quot;bar&quot; /&gt;
&lt;/entry&gt;
</pre>
<p>While there is special support for HTML, XHTML, and plain text in Atom, you can put any type of content in <tt class="docutils literal"><span class="pre">&lt;content&gt;</span></tt>, encoded in base64.</p>
<p>To find the editable representation, the browser page can point to it.  I imagine something like this:</p>
<pre class="literal-block">
&lt;link rel=&quot;alternate&quot; type=&quot;application/atom+xml; type=entry&quot;
 href=&quot;this-url?format=atom&quot;&gt;
</pre>
<p>The actual URL (in this example <tt class="docutils literal"><span class="pre">this-url?format=atom</span></tt>) can be pretty much anything.  My one worry is that this could be confused with feed detection, which looks like:</p>
<pre class="literal-block">
&lt;link rel=&quot;alternate&quot; type=&quot;application/atom+xml&quot;
 href=&quot;/atom.xml&quot;&gt;
</pre>
<p>The only difference is &quot;; type=entry&quot;, which I&#8217;m betting a lot of clients don&#8217;t pay attention to.</p>
<p>The Atom entries then can have an element:</p>
<pre class="literal-block">
&lt;link rel=&quot;edit&quot; href=&quot;this-url&quot; /&gt;
</pre>
<p>This is a location where you can PUT a new entry to update the resource.  You could allow the client to PUT directly over the old page, or use <tt class="docutils literal"><span class="pre">this-url?format=atom</span></tt> or whatever is convenient on the server-side.  Additionally, DELETE to the same URL would delete.</p>
<p>This handles updates and deletes, and single-page reads.  The next issue is creating pages.</p>
<p>Atompub makes creation fairly simple.  First you have to get the <a class="reference external" href="http://bitworking.org/projects/atom/rfc5023.html#appdocs">Atompub service document</a>.  This is a document with the type <tt class="docutils literal"><span class="pre">application/atomsvc+xml</span></tt> and it gives the collection URL.  <a class="reference external" href="http://wiki.whatwg.org/wiki/ServiceRelExtension">It&#8217;s suggested</a> you make this document discoverable like:</p>
<pre class="literal-block">
&lt;link rel=&quot;service&quot; type=&quot;application/atomsvc+xml&quot;
 href=&quot;/atomsvc.xml&quot;&gt;
</pre>
<p>This document then points to the &quot;collection&quot; URL, which for our purposes is where you create documents.  The service document would look like:</p>
<pre class="literal-block">
&lt;service xmlns=&quot;http://www.w3.org/2007/app&quot;
         xmlns:atom=&quot;http://www.w3.org/2005/Atom&quot;&gt;
  &lt;workspace&gt;
    &lt;atom:title&gt;SITE TITLE&lt;/atom:title&gt;
    &lt;collection href=&quot;/atomapi&quot;&gt;
      &lt;atom:title&gt;SITE TITLE&lt;/atom:title&gt;
      &lt;accept&gt;*/*&lt;/accept&gt;
      &lt;accept&gt;application/atom+xml;type=entry&lt;/accept&gt;
    &lt;/collection&gt;
  &lt;/workspace&gt;
&lt;/service&gt;
</pre>
<p>Basically this indicates that you can POST any media to <tt class="docutils literal"><span class="pre">/atomapi</span></tt> (both Atom entries, and things like images).</p>
<p>To create a page, a client then does a POST like:</p>
<pre class="literal-block">
POST /atomapi
Content-Type: application/atom+xml; type=entry
Slug: /page/path

&lt;entry xmlns=&quot;...&quot;&gt;...&lt;/entry&gt;
</pre>
<p>There&#8217;s an awkwardness here, that you can suggest (via the Slug header) what the URL for the new page is.  The client can find the actual URL of the new page from the Location header in the response. But the client can&#8217;t demand that the slug be respected (getting an error back if it is not), and there&#8217;s lots of use cases where the client doesn&#8217;t just want to <em>suggest</em> a path (for instance, other documents that are being created might rely on that path for links).</p>
<p>Also, &quot;slug&quot; implies&#8230; well, a slug.  That is, some path segment probably derived from the title.  There&#8217;s nothing stopping the client from putting a complete path in there, but it&#8217;s very likely to be misinterpreted (e.g. translating <tt class="docutils literal"><span class="pre">/page/path</span></tt> to <tt class="docutils literal"><span class="pre">/2009/01/pagepath</span></tt>).</p>
<p>Bug I digress.  Anyway, you can post every resource as an entry, base64-encoding the resource body, but Atompub also allows POSTing media directly.  When you do that, the server puts the media somewhere and creates a simple Atom entry for the media.  If you wanted to add properties to that entry, you&#8217;d edit the entry after creating it.</p>
<p>The last missing piece is how to get a list of all the pages on a site.  Atompub <em>does</em> have an answer for this: just <tt class="docutils literal"><span class="pre">GET</span> <span class="pre">/atomapi</span></tt> will give you an Atom feed, and for our purposes we can demand that the feed is complete (using paging so that any one page of the feed doesn&#8217;t get too big).  But this doesn&#8217;t seem like a good solution to me.  <a class="reference external" href="http://code.google.com/apis/gdata/overview.html">GData</a> specifies a useful set of queries to for feeds, but I&#8217;m not sure that this is very useful here; the kind of queries a client needs to do for this use case aren&#8217;t things GData was designed for.</p>
<p>The queries that seem most important to me are queries by page path (which allows some sense of &quot;collections&quot; without being formal) and by content type.  Also to allow incremental updates on the client side, filtering these queries by last-modified time (i.e., all pages created since I last looked).  Reporting queries (date of creation, update, author, last editor, and custom properties) of course <em>could</em> be useful, but don&#8217;t seem as directly applicable.</p>
<p>Also, often the client won&#8217;t want the complete Atom entry for the pages, but only a list of pages (maybe with minimal metadata).  I&#8217;m unsure about the validity of abbreviated Atom entries, but it seems like one solution.  Any Atom entry can have something like:</p>
<pre class="literal-block">
&lt;link rel=&quot;self&quot; type=&quot;application/atom+xml; type=entry&quot;
 href=&quot;url?format=atom&quot; /&gt;
</pre>
<p>This indicates where the entry exists, though it doesn&#8217;t suggest very forcefully that the actual entry is abbreviated.  Anyway, I could then imagine a feed like:</p>
<pre class="literal-block">
&lt;feed&gt;
  &lt;entry&gt;

    &lt;content type=&quot;some/content-type&quot; /&gt;
    &lt;link rel=&quot;self&quot; href=&quot;...&quot; /&gt;
    &lt;updated&gt;YYYYMMDDTHH:MM:SSZ&lt;/updated&gt;
  &lt;entry&gt;
  ...
&lt;/feed&gt;
</pre>
<p>This isn&#8217;t entirely valid, however &#8212; you can&#8217;t just have an empty <tt class="docutils literal"><span class="pre">&lt;content&gt;</span></tt> tag.  You can use a <tt class="docutils literal"><span class="pre">src</span></tt> attribute to use indirection for the content, and then add Yet Another URL for each page that points to its raw content.  But that&#8217;s just jumping through hoops.  This also seems like an opportunity to suggest that the entry is incomplete.</p>
<p>To actually construct these feeds, you need some way of getting the feed.  I suggest that another entry be added to the Atompub service document, something like:</p>
<pre class="literal-block">
&lt;cmsapi:feed href=&quot;URI-TEMPLATE&quot; /&gt;
</pre>
<p>That would be a <a class="reference external" href="http://bitworking.org/projects/URI-Templates/">URI Template</a> that accepted several known variables (though frustratingly, URI Templates aren&#8217;t properly standardized yet).  Things like:</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">content-type</span></tt>: the content type of the resource (allowing wildcards like <tt class="docutils literal"><span class="pre">image/*</span></tt>)</li>
<li><tt class="docutils literal"><span class="pre">container</span></tt>: a path to a container, i.e., <tt class="docutils literal"><span class="pre">/2007</span></tt> would match all pages in <tt class="docutils literal"><span class="pre">/2007/&#8230;</span></tt></li>
<li><tt class="docutils literal"><span class="pre">path-regex</span></tt>: some regular expression to match the paths</li>
<li><tt class="docutils literal"><span class="pre">last-modified</span></tt>: return all pages modified at the given date or later</li>
</ul>
<p>All parameters would be ANDed together.</p>
<p>So, open issues:</p>
<ul class="simple">
<li>How to strongly suggest a path when creating a resource (better than Slug)</li>
<li>How to rename (move) or copy a page (it&#8217;s easy enough to punt on copy, but I&#8217;d rather move by a <em>little</em> more formal than just recreating a resource in a new location and deleting the original)</li>
<li>How to represent abbreviated Atom entries</li>
</ul>
<p>With these resolved I think it&#8217;d be possible to create a much simpler API than WebDAV, and one that can be applied to existing applications much more easily.  (If you think there&#8217;s more missing, please comment.)</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2009/01/11/atompub-instead-o-webdav/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Avoiding Silos: &#8220;link&#8221; as a first-class object</title>
		<link>http://blog.ianbicking.org/2008/12/27/avoiding-silos-link-as-a-first-class-object/</link>
		<comments>http://blog.ianbicking.org/2008/12/27/avoiding-silos-link-as-a-first-class-object/#comments</comments>
		<pubDate>Sat, 27 Dec 2008 19:09:18 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
		
		<category><![CDATA[HTML]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Python]]></category>

		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/2008/12/27/avoiding-silos-link-as-a-first-class-object/</guid>
		<description><![CDATA[
One of the constant annoyances to me in web applications is the self-proclaimed need for those applications to know about everything and do everything, and only spotty ad hoc techniques for including things from other applications.
An example might be blog navigation or search, where you can only include data from the application itself.  Or [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>One of the constant annoyances to me in web applications is the self-proclaimed need for those applications to know about everything and do everything, and only spotty ad hoc techniques for including things from other applications.</p>
<p>An example might be blog navigation or search, where you can only include data from the application itself.  Or &quot;Recent Posts&quot; which can only show locally-produce posts.  What if I post something elsewhere?  I have to create some shoddy placeholder post to refer to it.  Bah!  Underlying this the data is usually structured in a specific way, with the HTML being a sort of artifact of the database, the markup transient and a slave to the database&#8217;s structure.</p>
<p>An example of this might be a recent post listing like:</p>
<pre class="literal-block">
&lt;ul&gt;
  for post in recent_posts:
    &lt;li&gt;
      &lt;a href=&quot;/post/{{post.year}}/{{post.month}}/{{post.slug}}&quot;&gt;
        {{post.title}}&lt;/a&gt;
    &lt;/li&gt;
&lt;/ul&gt;
</pre>
<p>There&#8217;s clearly no room for exceptions in this code.  I am thus proposing that any system like this should have the notion of a &quot;link&quot; as a first-class object.  The code should look like this:</p>
<pre class="literal-block">
&lt;ul&gt;
  for post in recent_posts:
    &lt;li&gt;
      {{post.link()}}
    &lt;/li&gt;
&lt;/ul&gt;
</pre>
<p>Just like with <a class="reference external" href="http://blog.ianbicking.org/2008/10/24/hypertext-driven-urls/">changing IDs to links</a> in service documents, the template doesn&#8217;t actually look any more complicated than it did before (simpler, even).  But now we can use simple object-oriented techniques to create first-class links.  The code might look like:</p>
<pre class="literal-block">
class Post(SomeORM):
    def url(self):
        if self.type == 'link':
            return self.body
        else:
            base = get_request().application_url
            return '%s/%s/%s/%s' % (
                base, self.year, self.month, self.slug)

    def link(self):
        return html('&lt;a href=&quot;%s&quot;&gt;%s&lt;/a&gt;') % (
            self.url(), self.title)
</pre>
<p>The addition of the <tt class="docutils literal"><span class="pre">.url()</span></tt> method has the obvious effect of making these offsite links work.  Using a <tt class="docutils literal"><span class="pre">.link()</span></tt> method has the added advantage of allowing things like HTML snippets to be inserted into the system (even though that is not implemented here).  By allowing arbitrary HTML in certain places you make it possible for people to extend the site in little ways &#8212; possibly adding markup to a title, or allowing an item in the list that actually contains two URLs (e.g., <tt class="docutils literal"><span class="pre">&lt;a</span> <span class="pre">href=&quot;url1&quot;&gt;Some</span> <span class="pre">Item&lt;/a&gt;</span> <span class="pre">(&lt;a</span> <span class="pre">href=&quot;url2&quot;&gt;via&lt;/a&gt;)</span></tt>).</p>
<p>In the context of Python I recommend making these into methods, not properties, because it allows you to later add keyword arguments to specialize the markup (like <tt class="docutils literal"><span class="pre">post.link(abbreviated=True)</span></tt>).</p>
<p>One negative aspect of this is that you cannot affect all the markup through the template alone, you may have to go into the Python code to change things.  Anyone have ideas for handling this problem?</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2008/12/27/avoiding-silos-link-as-a-first-class-object/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Javascript Status Message Display</title>
		<link>http://blog.ianbicking.org/2008/12/17/javascript-status-message-display/</link>
		<comments>http://blog.ianbicking.org/2008/12/17/javascript-status-message-display/#comments</comments>
		<pubDate>Wed, 17 Dec 2008 18:03:15 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
		
		<category><![CDATA[Javascript]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/2008/12/17/javascript-status-message-display/</guid>
		<description><![CDATA[
In a little wiki I&#8217;ve been playing with I&#8217;ve been trying out little ideas that I&#8217;ve had but haven&#8217;t had a place to actually implement them.  One is how notification messages work.  I&#8217;m sure other people have done the same thing, but I thought I&#8217;d describe it anyway.
A common pattern is to accept [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>In a <a class="reference external" href="http://www.bitbucket.org/ianb/pickywiki/">little wiki I&#8217;ve been playing with</a> I&#8217;ve been trying out little ideas that I&#8217;ve had but haven&#8217;t had a place to actually implement them.  One is how notification messages work.  I&#8217;m sure other people have done the same thing, but I thought I&#8217;d describe it anyway.</p>
<p>A <a class="reference external" href="http://blog.ianbicking.org/web-application-patterns-status-notification.html">common pattern</a> is to accept a POST request and then redirect the user to some page, setting a status message.  Typically the status message is either set in a cookie or in the session, then the standard template for the application has some code to check for a message and display it.</p>
<p>The problem with this is that this breaks all caching &#8212; at any time any page can have some message injected into it, basically for no reason at all.  So I thought: why not do the whole thing in Javascript?  The server will set a cookie, but only Javascript will read it.</p>
<p>The code goes like this; on the server (easily translated into any framework):</p>
<pre class="literal-block">
resp.set_cookie('flash_message', urllib.quote(msg))
</pre>
<p>I quote the message because it can contain characters unsafe for cookies, and URL quoting is a particularly easy quoting to apply.</p>
<p>Then I have this Javascript (using jQuery):</p>
<pre class="literal-block">
$(function () {
    // Anything in $(function...) is run on page load
    var flashMsg = readCookie('flash_message');
    if (flashMsg) {
        flashMsg = unescape(flashMsg);
        var el = $('&lt;div id=&quot;flash-message&quot;&gt;'+
          '&lt;div id=&quot;flash-message-close&quot;&gt;'+
          '&lt;a title=&quot;dismiss this message&quot; '+
          'id=&quot;flash-message-button&quot; href=&quot;#&quot;&gt;X&lt;/a&gt;&lt;/div&gt;'+
          flashMsg + '&lt;/div&gt;');
        $('a#flash-message-button', el).bind(
          'click', function () {
            $(this.parentNode.parentNode).remove();
        });
        $('#body').prepend(el);
        eraseCookie('flash_message');
    }
});
</pre>
<p>Note that I&#8217;ve decided to treat the flash message as HTML.  I don&#8217;t see a strong risk of injection attack in this case, though I must admit I&#8217;m a little unclear about what the normal policies are for cross-domain cookie setting.</p>
<p>I use <a class="reference external" href="http://www.quirksmode.org/js/cookies.html">these cookie functions</a> because oddly I can&#8217;t find cookie handling functions in jQuery.  It&#8217;s always weird to me how primitive <tt class="docutils literal"><span class="pre">document.cookie</span></tt> is.  Anyway, CSS looks like this:</p>
<pre class="literal-block">
#flash-message {
  margin: 0.5em;
  border: 2px solid #000;
  background-color: #9f9;
  -moz-border-radius: 4px;
  text-align: center;
}

#flash-message-close {
  float: right;
  font-size: 70%;
  margin: 2px;
}

a#flash-message-button {
  text-decoration: none;
  color: #000;
  border: 1px solid #9f9;
}

a#flash-message-button:hover {
  border: 1px solid #000;
  background-color: #009;
  color: #fff;
}
</pre>
<p>This doesn&#8217;t have non-Javascript fallback, but I think that&#8217;s okay.  This isn&#8217;t something that a spider would ever see (since spiders shouldn&#8217;t be submitting forms that result in update messages).  Accessible browsers generally implement Javascript so that&#8217;s also not particularly a problem, though there may be additional hints I could give in CSS or Javascript to help make this more readable (if there&#8217;s a message, it should probably be the first thing read on the page).</p>
<p>Another common component of pages that varies separate from the page itself is logged-in status, but that&#8217;s more heavily connected to your application.  Get both into Javascript and you might be able to turn caching way up on a lot of your pages.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2008/12/17/javascript-status-message-display/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Using pip Requirements</title>
		<link>http://blog.ianbicking.org/2008/12/16/using-pip-requirements/</link>
		<comments>http://blog.ianbicking.org/2008/12/16/using-pip-requirements/#comments</comments>
		<pubDate>Wed, 17 Dec 2008 01:30:21 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
		
		<category><![CDATA[Packaging]]></category>

		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/2008/12/16/using-pip-requirements/</guid>
		<description><![CDATA[
Following onto a set of recent posts (from James, me, then James again), Martijn Faassen wrote a description of Grok&#8217;s version management.  Our ideas are pretty close, but he&#8217;s using buildout, and I&#8217;ll describe out to do the same things with pip.
Here&#8217;s a kind of development workflow that I think works well:

A framework release [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>Following onto a set of recent posts (from <a class="reference external" href="http://www.b-list.org/weblog/2008/dec/14/packaging/">James</a>, <a class="reference external" href="http://blog.ianbicking.org/2008/12/14/a-few-corrections-to-on-packaging/">me</a>, then <a class="reference external" href="http://www.b-list.org/weblog/2008/dec/15/pip/">James again</a>), Martijn Faassen <a class="reference external" href="http://faassen.n--tree.net/blog/view/weblog/2008/12/16/0">wrote a description of Grok&#8217;s version management</a>.  Our ideas are pretty close, but he&#8217;s using buildout, and I&#8217;ll describe out to do the same things with pip.</p>
<p>Here&#8217;s a kind of development workflow that I think works well:</p>
<ul class="simple">
<li>A framework release is prepared.  Ideally there&#8217;s a buildbot that has been running (as <a class="reference external" href="http://pylonshq.com:8010/">Pylons has</a>, for example), so the integration has been running for a while.</li>
<li>People make sure there are released versions of all the important components.  If there are known conflicts between pieces, libraries and the framework update their <tt class="docutils literal"><span class="pre">install_requires</span></tt> in their <tt class="docutils literal"><span class="pre">setup.py</span></tt> files to make sure people don&#8217;t use conflicting pieces together.</li>
<li>Once everything has been released, there is a known set of packages that work together.  Using a buildbot maybe future versions will also work together, but they won&#8217;t necessarily work together with applications built on the framework.  And breakage can also occur regardless of a buildbot.</li>
<li>Also, people may have versions of libraries already installed, but just because they&#8217;ve installed something doesn&#8217;t mean they really mean to stay with an old version.  While known conflicts have been noted, there&#8217;s going to be lots of unknown conflicts and future conflicts.</li>
<li>When starting development with a framework, the developer would like to start with some known-good set, which is a set that can be developed by the framework developers, or potentially by any person.  For instance, if you extend a public framework with an internal framework (or even a public sub-framework like <a class="reference external" href="http://pinaxproject.com/">Pinax</a>) then the known-good set will be developed by a different set of people.</li>
<li>As an application is developed, the developer will add on other libraries, or use some of their own libraries.  Development will probably occur at the trunk/tip of several libraries as they are developed together.</li>
<li>A developer might upgrade the entire framework, or just upgrade one piece (for instance, to get a bug fix they are interested in, or follow a branch that has functionality they care about).  The developer doesn&#8217;t necessarily have the same notion of &quot;stable&quot; and &quot;released&quot; as the core framework developers have.</li>
<li>At the time of deployment the developer wants to make sure all the pieces are deployed together as they&#8217;ve tested them, and how they know them to work.  At any time, another developer may want to clone the same set of libraries.</li>
<li>After initial deployment, the developer may want to upgrade a single component, if only to test that an upgrade works, or if it resolves a bug.  They may test out combinations only to throw them away, and they don&#8217;t want to bump versions of libraries in order to deploy new combinations.</li>
</ul>
<p>This is the kind of development pattern that requirement files are meant to assist with.  They can provide a known-good set of packages.  Or they can provide a starting point for an active line of development.  Or they can provide a historical record of how something was put together.</p>
<p>The easy way to start a requirement file for pip is just to put the packages you know you want to work with.  For instance, we&#8217;ll call this <tt class="docutils literal"><span class="pre">project-start.txt</span></tt>:</p>
<pre class="literal-block">
Pylons
-e svn+http://mycompany/svn/MyApp/trunk#egg=MyApp
-e svn+http://mycompany/svn/MyLibrary/trunk#egg=MyLibrary
</pre>
<p>You can plug away for a while, and maybe you decide you want to freeze the file.  So you do:</p>
<pre class="literal-block">
$ pip freeze -r project-start.txt project-frozen.txt
</pre>
<p>By using <tt class="docutils literal"><span class="pre">-r</span> <span class="pre">project-start.txt</span></tt> you give <tt class="docutils literal"><span class="pre">pip</span> <span class="pre">freeze</span></tt> a template for it to start with.  From that, you&#8217;ll get <tt class="docutils literal"><span class="pre">project-frozen.txt</span></tt> that will look like:</p>
<pre class="literal-block">
Pylons==0.9.7
-e svn+http://mycompany/svn/MyApp/trunk&#64;1045#egg=MyApp
-e svn+http://mycompany/svn/MyLibrary/trunk&#64;1058#egg=MyLibrary

## The following requirements were added by pip --freeze:
Beaker==0.2.1
WebHelpers==0.9.1
nose==1.4
# Installing as editable to satisfy requirement INITools==0.2.1dev-r3488:
-e svn+http://svn.colorstudy.com/INITools/trunk&#64;3488#egg=INITools-0.2.1dev_r3488
</pre>
<p>At that point you might decide that you don&#8217;t care about the nose version, or you might have installed something from trunk when you could have used the last release.  So you go and adjust some things.</p>
<p>Martijn also asks: how do you have framework developers maintain one file, and then also have developers maintain their own lists for their projects?</p>
<p>You could start with a file like this for the framework itself.  Pylons for instance could ship with something like this.  To install Pylons you could then do:</p>
<pre class="literal-block">
$ pip -E MyProject install \\
&gt;    -r http://pylonshq.com/0.9.7-requirements.txt
</pre>
<p>You can also download that file yourself, add some comments, rename the file and add your project to it, and use that.  When you freeze the order of the packages and any comments will be preserved, so you can keep track of what changed.  Also it should be ameniable to source control, and diffs would be sensible.</p>
<p>You could also use indirection, creating a file like this for your project:</p>
<pre class="literal-block">
-r http://pylonshq.com/0.9.7-requirements.txt
-e svn+http://mycompany/svn/MyApp/trunk#egg=MyApp
-e svn+http://mycompany/svn/MyLibrary/trunk#egg=MyLibrary
</pre>
<p>That is, requirements files can refer to each other.  So if you want to maintain your own requirements file alongside the development of an upstream requirements file, you could do that.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2008/12/16/using-pip-requirements/feed/</wfw:commentRss>
		</item>
		<item>
		<title>A Few Corrections To &#8220;On Packaging&#8221;</title>
		<link>http://blog.ianbicking.org/2008/12/14/a-few-corrections-to-on-packaging/</link>
		<comments>http://blog.ianbicking.org/2008/12/14/a-few-corrections-to-on-packaging/#comments</comments>
		<pubDate>Sun, 14 Dec 2008 21:53:25 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
		
		<category><![CDATA[Packaging]]></category>

		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/2008/12/14/a-few-corrections-to-on-packaging/</guid>
		<description><![CDATA[
James Bennett recently wrote an article on Python packaging and installation, and Setuptools.  There&#8217;s a lot of issues, and writing up my thoughts could take a long time, but I thought at least I should correct some errors, specifically category errors.  Figuring out where all the pieces in Setuptools (and pip and virtualenv) [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p><a class="reference external" href="http://www.b-list.org/weblog/2008/dec/14/packaging/">James Bennett recently wrote an article on Python packaging and installation</a>, and Setuptools.  There&#8217;s a lot of issues, and writing up my thoughts could take a long time, but I thought at least I should correct some errors, specifically category errors.  Figuring out where all the pieces in Setuptools (and pip and virtualenv) fit <em>is</em> difficult, so I don&#8217;t blame James for making some mistakes, but in the interest of clarifying the discussion&#8230;</p>
<p>I will start with a kind of glossary:</p>
<dl class="docutils">
<dt>Distribution:</dt>
<dd>This is something-with-a-setup.py.  A tarball, zip, a checkout, etc.  Distributions have names; this is the name in <tt class="docutils literal"><span class="pre">setup(name=&quot;&#8230;&quot;)</span></tt> in the setup.py file.  They have some other metadata too (description, version, etc), and Setuptools adds to that metadata some.  Distutils doesn&#8217;t make it very easy to add to the metadata &#8212; it&#8217;ll whine a little about things it doesn&#8217;t know, but won&#8217;t do anything with that extra data.  Fixing this problem in Distutils is an important aspect of Setuptools, and part of what Distutils itself unsuitable as a basis for good library management.</dd>
<dt>package/module:</dt>
<dd>This is something you import.  It is not the same as a distribution, though usually a distribution will have the same name as a package.  In my own libraries I try to name the distribution with mixed case (like Paste) and the package with lower case (like paste).  Keeping the terminology straight here is <em>very</em> difficult; and usually it doesn&#8217;t matter, but sometimes it does.</dd>
<dt>Setuptools The Distribution:</dt>
<dd>This is what you install when you install Setuptools.  It includes several pieces that Phillip Eby wrote, that work together but are not strictly a single thing.</dd>
<dt>setuptools The Package:</dt>
<dd>This is what you get when you do <tt class="docutils literal"><span class="pre">import</span> <span class="pre">setuptools</span></tt>.  Setuptools largely works by monkeypatching distutils, so simply importing setuptools activates its functionality from then on.  This package is entirely focused on installation and package management, it is not something you should use at runtime (unless you are installing packages as your runtime, of course).</dd>
<dt>pkg_resources The Module:</dt>
<dd>This is also included in Setuptools The Distribution, and is for use at runtime.  This is a single module that provides the ability to query what distributions are installed, metadata about those distributions, information about the location where they are installed.  It also allows distributions to be &quot;activated&quot;.  A <em>distribution</em> can be available but not activated.  Activating a distribution means adding its location to <tt class="docutils literal"><span class="pre">sys.path</span></tt>, and probably you&#8217;ve noticed how long sys.path is when you use easy_install.  Almost everything that allows different libraries to be installed, or allows different versions of libraries, does it through some management of sys.path.  pkg_resources also allows for generic access to &quot;resources&quot; (i.e., non-code files), and let&#8217;s those resources be in zip files.  pkg_resources is safe to use, it doesn&#8217;t do any of the funny stuff that people get annoyed with.</dd>
<dt>easy_install:</dt>
<dd>This is also in Setuptools The Distribution.  The basic functionality it provides is that given a name, it can search for package with that distribution name, and also satisfying a version requirement.  It then downloads the package, installs it (using <tt class="docutils literal"><span class="pre">setup.py</span> <span class="pre">install</span></tt>, but with the setuptools monkeypatches in place).  After that, it checks the newly installed distribution to see if it requires any other libraries that aren&#8217;t yet installed, and if so it installs them.</dd>
<dt>Eggs the Distribution Format:</dt>
<dd>These are zip files that Setuptools creates when you run <tt class="docutils literal"><span class="pre">python</span> <span class="pre">setup.py</span> <span class="pre">bdist_egg</span></tt>.  Unlike a tarball, these can be binary packages, containing compiled modules, and generally contain .pyc files (which are portable across platforms, but not Python versions).  This format only includes files that will actually be installed; as a result it does not include doc files or <tt class="docutils literal"><span class="pre">setup.py</span></tt> itself.  All the metadata from <tt class="docutils literal"><span class="pre">setup.py</span></tt> that is needed for installation is put in files in a directory <tt class="docutils literal"><span class="pre">EGG-INFO</span></tt>.</dd>
<dt>Eggs the Installation Format:</dt>
<dd>Eggs the Distribution Format are a subset of the Installation Format.  That is, if you put an Egg zip file on the path, it is installed, no other process is necessary.  But the Installation Format is more general.  To have an egg installed, you either need something like <tt class="docutils literal"><span class="pre">DistroName-X.Y.egg/</span></tt> on the path, and then an <tt class="docutils literal"><span class="pre">EGG-INFO/</span></tt> directory under that with the metadata, or a path like <tt class="docutils literal"><span class="pre">DistroName.egg-info/</span></tt> with the metadata directly in that directory.  This metadata can exist anywhere, and doesn&#8217;t have to be directly alongside the actual Python code.  Egg directories are required for pkg_resources to activate and deactivate distributions, but otherwise they aren&#8217;t necessary.</dd>
<dt>pip:</dt>
<dd>This is an alternative to easy_install.  It works <em>somewhat</em> differently than easy_install, but not much.  Mostly it is <em>better</em> than easy_install, in that it has some extra features and is easier to use.  Unlike easy_install, it downloads all distributions up-front, and generates the metadata to read distribution and version requirements.  It uses Setuptools to generate this metadata from a setup.py file, and uses pkg_resources to parse this metadata.  It then installs packages <em>with the setuptools monkeypatches applied</em>.  It just happens to use an option <tt class="docutils literal"><span class="pre">python</span> <span class="pre">setup.py</span> <span class="pre">&#8211;single-version-externally-managed</span></tt>, which gets Setuptools to install packages in a more flat manner, with <tt class="docutils literal"><span class="pre">Distro.egg-info/</span></tt> directories alongside the package.  Pip installs eggs!  I&#8217;ve heard the many complaints about easy_install (and I&#8217;ve had many myself), but ultimately I think pip does well by just fixing a few small issues.  Pip is <em>not</em> a repudiation of Setuptools or the basic mechanisms that easy_install uses.</dd>
<dt>PoachEggs:</dt>
<dd>This is a defunct package that had some of the features of pip (particularly requirement files) but used easy_install for installation.  Don&#8217;t bother with this, it was just a bridge to get to pip.</dd>
<dt>virtualenv:</dt>
<dd>This is a little hack that creates isolated Python environments.  It&#8217;s based on <tt class="docutils literal"><span class="pre">virtual-python.py</span></tt>, which is something I wrote based on some documentation notes PJE wrote for Setuptools.  Basically virtualenv just creates a <tt class="docutils literal"><span class="pre">bin/python</span></tt> interpreter that has its own value of <tt class="docutils literal"><span class="pre">sys.prefix</span></tt>, but uses the system Python and standard library.  It also installs Setuptools to make it easier to bootstrap the environment (because bootstrapping Setuptools is itself a bit tedious).  I&#8217;ll add pip to it too sometime.  Using virtualenv you don&#8217;t have to worry about different library versions, because for any one environment you will probably only need one version of a library.  On any one <em>machine</em> you probably need different versions, which is why installing packages system-wide is problematic for most libraries.  (I&#8217;ve been meaning to write a post on why I think using system packaging for libraries is counter-productive, but that&#8217;ll wait for another time.)</dd>
</dl>
<hr class="docutils" />
<p>So&#8230; there&#8217;s the pieces involved, at least the ones I can remember now.  And I haven&#8217;t really discussed .pth files, entry points, sys.path trickery, site.py, distutils.cfg&#8230; sadly this is a complex state of affairs, but it was also complex before Setuptools.</p>
<p>There are a few things that I think people really dislike about Setuptools.</p>
<p>First, zip files.  Setuptools prefers zip files, for reasons that won&#8217;t mean much to you, and maybe are more historical than anything.  When a distribution doesn&#8217;t indicate if it is zip-safe, Setuptools looks at the code and sees if it uses <tt class="docutils literal"><span class="pre">__file__</span></tt>, an if not it presumes that the code is probably zip-safe.  The specific problem James cites is what appears to be a bug in Django, that Django looks for code and can&#8217;t traverse into zip files in the same way that Python itself can.  Setuptools didn&#8217;t itself add anything to Python to make it import zip files, that functionality was added to Python some time before.  The zipped eggs that Setuptools installs are using existing (standard!) Python functionality.</p>
<p>That said, I don&#8217;t think zipping libraries up is all that useful, and while it <em>should</em> work, it doesn&#8217;t always, and it makes code harder to inspect and understand.  So since it&#8217;s not that useful, I&#8217;ve disabled it when pip installs packages.  I also have had it disabled on my own system for years now, by creating a <tt class="docutils literal"><span class="pre">distutils.cfg</span></tt> file with <tt class="docutils literal"><span class="pre">[easy_install]</span> <span class="pre">zip_ok</span> <span class="pre">=</span> <span class="pre">False</span></tt> in it.  Sadly App Engine is forcing me to use zip files again, because of its absurdly small file limits&#8230; but that&#8217;s a different topic.  (There is an experimental <tt class="docutils literal"><span class="pre">pip</span> <span class="pre">zip</span></tt> command mostly intended for App Engine.)</p>
<p>Another pain point is version management with <tt class="docutils literal"><span class="pre">setup.py</span></tt> and Setuptools.  Indeed it is easy to get things messed up, and it is easy to piss people off by overspecifying, and sometimes things can get in a weird state for no good reason (often because of easy_install&#8217;s rather naive leap-before-you-look installation order).  Pip fixes that last point, but it also tries to suggest more constructive and less painful ways to manage other pieces.</p>
<p>Pip requirement files are an assertion of <strong>versions that work together</strong>.  setup.py requirements (the Setuptools requirements) should contain two things: <strong>1</strong>: all the libraries used by the distribution (without which there&#8217;s no way it&#8217;ll work) and <strong>2</strong>: exclusions of the versions of those libraries that are <strong>known not to work</strong>.  setup.py requirements should not be viewed as an assertion that by satisfying those requirements everything <em>will</em> work, just that it <em>might</em> work.  Only the end developer, testing the system together, can figure out if it really works.  Then pip gives you a way to record that working set (using <a class="reference external" href="http://pip.openplans.org/#freezing-requirements">pip freeze</a>), separate from any single distribution or library.</p>
<p>There&#8217;s also a lot of conflicts between Setuptools and package maintainers.  This is kind of a proxy war between developers and sysadmins, who have very different motivations.  It deserves a post of its own, but the conflicts are about more than just how Setuptools is implemented.</p>
<p>I&#8217;d love if there was a language-neutral library installation and management tool that really worked.  Linux system package managers are absolutely not that tool; frankly it is absurd to even consider them as an alternative.  So for now we do our best in our respective language communities.  If we&#8217;re going to move forward, we&#8217;ll have to acknowledge what&#8217;s come before, and the reasoning for it.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2008/12/14/a-few-corrections-to-on-packaging/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
