<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><description>Dabblings in the webs and suchlike.</description><title>/usr/share</title><generator>Tumblr (3.0; @usrshare)</generator><link>http://usrshare.net/</link><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/usrshare" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="usrshare" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://tumblr.superfeedr.com/" /><item><title>A Fairly Low Ceremony Method for Modularizing Django Settings</title><description>&lt;div class="updates"&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Updates&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;No longer wrapping modules in &lt;code&gt;def require&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;pkgutil&lt;/code&gt; and &lt;code&gt;inspect&lt;/code&gt; to get module names and constants&lt;/li&gt;
&lt;/ul&gt;&lt;div class="end-updates"&gt;&lt;/div&gt;

&lt;p&gt;Every time I need to add anything to settings.py in Django, I find myself spending a good minute trying to find a logical place to put it. But it&amp;#8217;s always the same. I give up, put it somewhere arbitrary, and move on feeling cheapened, dirty, and defeated. &lt;em&gt;There must be a better way&amp;#8230;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://code.djangoproject.com/wiki/SplitSettings"&gt;This&lt;/a&gt; wiki page provides a ton of examples that get very close. They let you override settings per environment, but you&amp;#8217;re still arbitrarily placing unrelated settings together. I&amp;#8217;d like something more modular. Today I worked out a method that is very modular and includes all the perks of the above examples at the cost of a small bit of ceremony.&lt;/p&gt;

&lt;p&gt;For reference, take a look at the &lt;a href="https://github.com/samiconductor/modularsettings/tree/master/modularsettings/settings"&gt;&lt;em&gt;updated&lt;/em&gt; example project settings&lt;/a&gt;. The gist of it is moving settings into it&amp;#8217;s own package, importing all settings in &lt;code&gt;__init__.py&lt;/code&gt;, and placing specific settings into aptly named modules.&lt;/p&gt;

&lt;div class="updates"&gt;&lt;/div&gt;

&lt;p&gt;Version 2.0&lt;/p&gt;

&lt;pre class="brush: py"&gt;
import inspect
import pkgutil


for _, module_name, _ in pkgutil.walk_packages(__path__):
    module = __import__(module_name, globals(), locals(), [])
    for var_name, val in inspect.getmembers(module):
        if var_name.isupper():
            locals().update({var_name: val})
&lt;/pre&gt;

&lt;p&gt;This version improves on the first by getting module names using &lt;code&gt;pkgutil.walk_packages&lt;/code&gt; which means you can put settings in packages now too.&lt;/p&gt;

&lt;p&gt;Also, instead of setting up the secrets, paths, and environment in here and passing them via &lt;code&gt;require&lt;/code&gt; I let the settings modules import the settings they need.&lt;/p&gt;

&lt;pre class="brush: py"&gt;
import os

import env
import paths
import secrets


if env.DEV_ENV:
    database_dir = os.path.join(paths.BASE_PATH, 'databases')

    if not os.path.exists(database_dir):
        os.mkdir(database_dir)

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(database_dir, 'sqlite3'),
        }
    }
else:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'USER': secrets.DATABASE_USER,
            'PASSWORD': secrets.DATABASE_PASSWORD,
            'HOST': secrets.DATABASE_HOST,
            'PORT': secrets.DATABASE_PORT,
        }
    }
&lt;/pre&gt;

&lt;p&gt;Instead of &lt;code&gt;import from&lt;/code&gt; I just import the modules directly and grab the settings from them. This makes things a bit more explicit and ensures the imported settings don&amp;#8217;t get added twice in &lt;code&gt;__init__.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Extending settings is exactly the same as version 1.0:&lt;/p&gt;

&lt;pre class="brush: py"&gt;
import env


INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Uncomment the next line to enable the admin:
    # 'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
)

if env.DEV_ENV:
    INSTALLED_APPS += (
        'debug_toolbar',
    )
&lt;/pre&gt;

&lt;p&gt;So in this version we&amp;#8217;ve cleaned up &lt;code&gt;__init__.py&lt;/code&gt; quite a bit and removed the ceremony from the settings modules. This is exactly what I wanted from the get go and I&amp;#8217;m pretty stinkin happy with it.&lt;/p&gt;

&lt;div class="end-updates"&gt;&lt;/div&gt;

&lt;p&gt;Version 1.0&lt;/p&gt;

&lt;pre class="brush: py; collapse: true"&gt;
import os

from secrets import *

SETTINGS_PATH = os.path.abspath(os.path.dirname(__file__))
PROJECT_PATH  = os.path.dirname(SETTINGS_PATH)
BASE_PATH     = os.path.dirname(PROJECT_PATH)

ENV      = os.getenv('DJANGO_ENVIRONMENT', 'development')
DEV_ENV  = ENV == 'development'
TEST_ENV = ENV == 'staging'
PROD_ENV = ENV == 'production'


def _constants(d):
    return dict((key, val) for key, val in d.items() if key.isupper())

for settings_file in [filename.rstrip('.py') for filename in os.listdir(SETTINGS_PATH)
        if not filename.endswith('.pyc') and filename not in ('__init__.py', 'secrets.py')]:

    module = __import__(settings_file, globals(), locals(), [])
    settings = module.require(**_constants(locals()))
    locals().update(_constants(settings))
&lt;/pre&gt;

&lt;p&gt;The first thing we do is import &lt;code&gt;secrets.py&lt;/code&gt;. This is where you&amp;#8217;ll put the &lt;code&gt;SECRET_KEY&lt;/code&gt;, database credentials, etc, and is the standard of the wiki examples. Next, we setup our project paths and the environment variable. But from here I stray from the norm a bit. Instead of importing a module based on the environment, I go ahead and import everything in the settings package (&lt;code&gt;listdir&lt;/code&gt; may not be the most elegant way to get each filename, let me know if there&amp;#8217;s a better approach).&lt;/p&gt;

&lt;p&gt;I quickly ran into a problem though. I want to use the secrets, project paths, and environment settings inside the imported modules. This is where the ceremony comes in. To get around this I wrap each settings module in a function I can call in &lt;code&gt;__init__.py&lt;/code&gt;, passing in the settings it needs like so:&lt;/p&gt;

&lt;pre class="brush: py; collapse: true;"&gt;
import os

def require(DEV_ENV, BASE_PATH, DATABASE_USER, DATABASE_PASSWORD,
        DATABASE_HOST, DATABASE_PORT, **kwargs):

    if DEV_ENV:
        database_dir = os.path.join(BASE_PATH, 'databases')

        if not os.path.exists(database_dir):
            os.mkdir(database_dir)

        DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.sqlite3',
                'NAME': os.path.join(database_dir, 'sqlite3'),
            }
        }
    else:
        DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.postgresql_psycopg2',
                'USER': DATABASE_USER,
                'PASSWORD': DATABASE_PASSWORD,
                'HOST': DATABASE_HOST,
                'PORT': DATABASE_PORT,
            }
        }

    return locals()
&lt;/pre&gt;

&lt;p&gt;So each module must &lt;code&gt;def require&lt;/code&gt; (hat tip to &lt;a href="http://requirejs.org/"&gt;RequireJS&lt;/a&gt;) with &lt;code&gt;**kwargs&lt;/code&gt; and &lt;code&gt;return locals()&lt;/code&gt;. Not too bad. Also, the above example shows another way in which I diverge from the wiki examples. Instead of overriding per environment, I just check the environment setting and drop in the correct setting. To extend settings per environment you would do the following:&lt;/p&gt;

&lt;pre class="brush: py; collapse: true"&gt;
def require(DEV_ENV, **kwargs):

    INSTALLED_APPS = (
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.sites',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        # Uncomment the next line to enable the admin:
        # 'django.contrib.admin',
        # Uncomment the next line to enable admin documentation:
        # 'django.contrib.admindocs',
    )

    if DEV_ENV:
        INSTALLED_APPS += (
            'debug_toolbar',
        )

    return locals()
&lt;/pre&gt;

&lt;p&gt;All in all, I feel like this is a step in the right direction. If the settings package crammed full of sparse modules makes you queazy, than stick with one of the wiki examples. But for me, the ability to drop in a &lt;code&gt;widgery.py&lt;/code&gt; module when I want to configure my widgery app is a breath of fresh air. Everything finally has a place.&lt;/p&gt;

&lt;p&gt;Let me know what you think!&lt;/p&gt;</description><link>http://usrshare.net/post/28744449338</link><guid>http://usrshare.net/post/28744449338</guid><pubDate>Sat, 04 Aug 2012 23:20:00 -0500</pubDate><category>django</category><category>python</category></item><item><title>Sharefix vim plugin</title><description>&lt;a href="https://github.com/samiconductor/vim-sharefix"&gt;Sharefix vim plugin&lt;/a&gt;: &lt;p&gt;Have you ever wanted to keep your quickfixes available when running different commands and functions in vim? Now you can.&lt;/p&gt;</description><link>http://usrshare.net/post/24794511000</link><guid>http://usrshare.net/post/24794511000</guid><pubDate>Sat, 09 Jun 2012 23:42:00 -0500</pubDate><category>vim</category></item><item><title>Sass One Liners</title><description>&lt;a href="https://gist.github.com/2879838/9c14f8e04ab844dc3b1b32fcc7496cedb5040e0d"&gt;Sass One Liners&lt;/a&gt;: &lt;p&gt;I always have trouble remembering the syntax for linear gradients, especially the legacy webkit version. It would be nice if compass had a repl that you could execute compass’ &lt;a href="http://compass-style.org/reference/compass/css3/"&gt;CSS3 mixins and functions&lt;/a&gt; in and get the nicely prefixed properties out. Well it does!&lt;/p&gt;

&lt;pre class="brush: bash"&gt;compass interactive&lt;/pre&gt;

&lt;p&gt;Here we go:&lt;/p&gt;

&lt;pre class="brush: text"&gt;
&gt;&gt; background(linear-gradient(white, black))
background(linear-gradient(#ffffff, #000000))
&lt;/pre&gt;

&lt;p&gt;Ok, the colors were replaced at least. Let’s try the sass syntax for mixins:&lt;/p&gt;

&lt;pre class="brush: text"&gt;
&gt;&gt; +background(linear-gradient(white, black))
"+background(linear-gradient(#ffffff, #000000))"
&lt;/pre&gt;

&lt;p&gt;Thanks for quoting it, but no thanks. How about scss:&lt;/p&gt;

&lt;pre class="brush: text"&gt;
&gt;&gt; @import background(linear-gradient(white, black))
SyntaxError: Invalid CSS after "": expected expression (e.g. 1px, bold), was "@import backgro..."
&lt;/pre&gt;

&lt;p&gt;Alrighty, unless I’m missing something, the sass repl is pretty useless for compass extensions. There’s even an option for the sass command to run a repl with compass enabled:&lt;/p&gt;

&lt;pre class="brush: bash"&gt;sass -i --compass&lt;/pre&gt;

&lt;p&gt;Same results.&lt;/p&gt;

&lt;p&gt;So as a work around I wrote a &lt;a href="https://gist.github.com/2879838/9c14f8e04ab844dc3b1b32fcc7496cedb5040e0d"&gt;script&lt;/a&gt; to pipe in a line of sass to the sass command, compile it, and print the properties:&lt;/p&gt;

&lt;pre class="brush: text"&gt;
$ sass-cat -c "+background(linear-gradient(white, black))"
background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(100%, #000000));
background: -webkit-linear-gradient(#ffffff, #000000);
background: -moz-linear-gradient(#ffffff, #000000);
background: -o-linear-gradient(#ffffff, #000000);
background: -ms-linear-gradient(#ffffff, #000000);
background: linear-gradient(#ffffff, #000000);
&lt;/pre&gt;</description><link>http://usrshare.net/post/24535284623</link><guid>http://usrshare.net/post/24535284623</guid><pubDate>Wed, 06 Jun 2012 07:14:00 -0500</pubDate><category>sass</category><category>compass</category><category>bash</category></item><item><title>Prefetch Images With Javascript</title><description>&lt;p&gt;This one is an oldie but a goodie. If you ever need to swap out the src on an image tag you can prefetch images with javascript to make the swap instant after the page loads. All you need to do is create an image element in javascript and assign the url to the src. The browser will request the image immediately regardless of what you do with the image element. You can try this out in the network tab of your browser dev tools:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_m4lypjaGp81r25evb.png" alt="image prefetch in dev console"/&gt;&lt;/p&gt;

&lt;p&gt;Now you can assign the same url to an img tag in your html and the image will change immediately if it has finished loading in the background. You can also prefetch and swap out background images the same way.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://jsfiddle.net/samiconductor/TtBvU/"&gt;try it out in this fiddle&lt;/a&gt;&lt;/p&gt;</description><link>http://usrshare.net/post/23773320550</link><guid>http://usrshare.net/post/23773320550</guid><pubDate>Fri, 25 May 2012 21:55:00 -0500</pubDate><category>javascript</category></item><item><title>Vim Python Complete Function</title><description>&lt;p&gt;I finally found a nice complete function setup for python in vim. It&amp;#8217;s simply using &lt;a href="https://github.com/sontek/rope-vim"&gt;rope-vim&lt;/a&gt;&amp;#8217;s code assistance but there are a few settings you need to enable. I should note that I was clued in on rope and a ton of other great plugins through a &lt;a href="http://sontek.net/turning-vim-into-a-modern-python-ide"&gt;nice article&lt;/a&gt; by John Anderson on using vim as a python ide. You can follow his setup or I use &lt;a href="https://github.com/carlhuda/janus"&gt;janus&lt;/a&gt; so I dropped them into my janus folder as git submodules. The rope-vim plugin he suggests includes all the rope packages so you don&amp;#8217;t need to install them yourself.&lt;/p&gt;

&lt;p&gt;In the code assist section of &lt;code&gt;:h ropevim.txt&lt;/code&gt;, you&amp;#8217;ll see that you can set a few globals to have rope-vim handle completion:&lt;/p&gt;

&lt;pre class="brush: vim"&gt;
let g:ropevim_vim_completion=1
let g:ropevim_extended_complete=1
&lt;/pre&gt;

&lt;p&gt;The first setting makes the &lt;code&gt;RopeCodeAssistInsertMode&lt;/code&gt; function behave like a vim complete function, i.e. it display a popup menu when called. And the second adds useful bits of info to each completion: the location the completion came from &lt;code&gt;{'L': 'local', 'G': 'global', 'B': 'builtin', '': 'no scope available'}&lt;/code&gt;, it&amp;#8217;s type, and the first line of the doc string. It&amp;#8217;s pretty sweet!&lt;/p&gt;

&lt;p&gt;Other than that, you might want to remap the awkward default code assist mapping of alt+shift+comma (see the filetype commands of my &lt;a href="https://github.com/samiconductor/dotfiles/blob/master/vimrc.after"&gt;vimrc&lt;/a&gt; for an option). Also, if you&amp;#8217;ve never used rope before it will ask you to create or open a project each time. This stores a hidden ropeproject directory that caches info about your modules to make completions faster. It&amp;#8217;s slightly annoying to open each time but it&amp;#8217;s worth it for completions.&lt;/p&gt;

&lt;p&gt;And that&amp;#8217;s all there is to it!&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_m34gdsg0XN1r25evb.png" alt="vim python completion menu"/&gt;&lt;/p&gt;</description><link>http://usrshare.net/post/21898987184</link><guid>http://usrshare.net/post/21898987184</guid><pubDate>Fri, 27 Apr 2012 00:00:00 -0500</pubDate><category>vim</category><category>python</category></item><item><title>Bret Victor - Inventing on Principle</title><description>&lt;a href="http://vimeo.com/36579366"&gt;Bret Victor - Inventing on Principle&lt;/a&gt;: &lt;h4&gt;Summary&lt;/h4&gt;

&lt;p&gt;Devoting yourself to a principal isn’t confined to social services for example, you can take a stand on a principal in technology too. This transforms your view from ‘how can I turn this problem into a viable product?’ into ‘how can I prevent this problem from hindering myself and others?’.&lt;/p&gt;

&lt;p&gt;Finding your principal can take a while, but when you do, it will last a lifetime. Experience many things to see what pikes your interest or bugs your conscience and sooner than later, you’ll be able to sum up what drives you with a concise, guiding principal.&lt;/p&gt;</description><link>http://usrshare.net/post/17944938645</link><guid>http://usrshare.net/post/17944938645</guid><pubDate>Mon, 20 Feb 2012 08:02:06 -0600</pubDate><category>Web Dev</category></item><item><title>Web Art</title><description>&lt;p&gt;I recently read Paul Graham&amp;#8217;s essay &lt;em&gt;&lt;a href="http://www.paulgraham.com/hp.html"&gt;Hackers and Painters&lt;/a&gt;&lt;/em&gt; and it solidified a few reasons why I enjoy programming for the webs. Graham uses art as an analogy for different aspects of programming. A couple of his points stood out: That programming is not all theory and algorithms as most assume. And that dynamic languages are superior in that they lend themselves to the creative process.&lt;/p&gt;

&lt;p&gt;Part of the essay breaks down the misconception that hacking is applied computer science, which implies to program you must have crazy computational theories and algorithms constantly floating around your mind. Instead, Graham paints the picture that hacking is more like art. Programming languages are our brushes and paint and the screen is our canvas.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Along with composers, architects, and writes, what hackers and painters are trying to do is make good things.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is especially true of programming for the webs, which is where Graham is coming from. The web programmer is like a skilled craftsman. With an assortment of open source tools, he mashes up, duck tapes, and glues together the raw materials of the web: HTML, CSS, and Javascript. He is a maker and killer features are his commodity.&lt;/p&gt;

&lt;p&gt;The point is web programming is more hands on. Just because it involves computers doesn&amp;#8217;t mean it&amp;#8217;s all computer sciency. Sure, web programming can be complex. Just to get started, you have to learn three languages. You&amp;#8217;ll need a database at some point, which can involve mind bending queries and endless optimization. You&amp;#8217;ll need to use design patterns as your programs get massive. And a sea of acronyms and jargon awaits you on the horizon. But the problems you&amp;#8217;ll be solving are hardly theoretical. It&amp;#8217;s just a matter of practice, not nth power thinking.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;All the time I was in graduate school I had an uncomfortable feeling in the back of my mind that I ought to know more theory, and that it was very remiss of me to have forgotten all that stuff within three weeks of the final exam.&lt;/p&gt;
  
  &lt;p&gt;Now I realize I was mistaken. Hackers need to understand the theory of computation about as much as painters need to understand paint chemistry.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is comforting because my little mind has a lot of trouble grasping the abstract underpinnings of programming. Fortunately, all those problems are solved by someone else, which is why Graham was able to forget the theory and focus on more important things and why I can participate.&lt;/p&gt;

&lt;p&gt;Another point Graham makes is that languages are best served dynamic. Graham found his workflow consisted almost entirely of debugging. Instead of carefully planning out his programs on paper like he was taught in college, he started in an editor, building and debugging until he was satisfied.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;For a long time I felt bad about this, just as I once felt bad that I didn&amp;#8217;t hold my pencil the way they taught me to in elementary school. If I had only looked over at the other makers, the painters or the architects, I would have realized that there was a name for what I was doing: sketching.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;He goes on to say that the programming workflow should match other creative processes like writing and painting. Dynamic, interpreted languages lend themselves to this workflow quite nicely. They&amp;#8217;re high level and provide a lot of implicit functionality. Therefore you can express what you&amp;#8217;re thinking rather than placate the compiler with crufty boilerplate. And you can write and test bits and pieces as you go, just like sketching.&lt;/p&gt;

&lt;p&gt;The beauty of web programming is that it embraces dynamic interpreted languages. First of all, the browser interprets everything. I knew I loved web programming when I first learned HTML and CSS and could see immediate results with a page refresh. And Javascript is as dynamic as it gets. Second, the backend is language agnostic. As long as you eventually speak HTML, CSS, and JS, you can write your code in whatever you want (&lt;em&gt;Python!&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;To conclude, if you&amp;#8217;re interested in web development, don&amp;#8217;t let theory bog you down. Start by learning the tools while building projects. And if you&amp;#8217;re interested in programming in general, the web is a great place to be since it gives you the freedom to express your thoughts in the language of your choice.&lt;/p&gt;</description><link>http://usrshare.net/post/14353013949</link><guid>http://usrshare.net/post/14353013949</guid><pubDate>Sat, 17 Dec 2011 08:00:00 -0600</pubDate><category>Web Dev</category></item></channel></rss>
