klenwell information services : CocktailNapkin2012

2012 Cocktail Napkin

return to SpecialCocktailNapkin

PyWell: A Python Tutorial
PywellInterpreter

jQuery Cookie Plugin with Internet Explorer 6
It appears that including the path parameter when setting a cookie with the jQuery cookie plugin in IE6 does not work:
var cookie_name = "foo";
var cookie_value = "bar";
var cookie_path = "/some/valid/path";

// does not work in IE6
$.cookie(cookie_name, cookie_value, {path: cookie_path});

// works in IE6
$.cookie(cookie_name, cookie_value);

Was not tested with any other version of IE. Worked as expected in later versions of Firefox and Chrome that I had installed.

Wasn't sure if this warranted a bug report (yes, I have to target IE6) so I figured I just drop it here. Maybe move it to my blog at some point.

Euler #9 in Ruby
http://projecteuler.net/problem=9
=begin

    http://projecteuler.net/problem=9
   
    A Pythagorean triplet is a set of three natural numbers, a < b < c,
    for which,
            a2 + b2 = c2

    For example, 32 + 42 = 9 + 16 = 25 = 52.

    There exists exactly one Pythagorean triplet for which a + b + c = 1000.
    Find the product abc.

=end


#
# Test Case / Solution
#
def test_case
    sum = 3 + 4 + 5
    expected = 3 * 4 * 5
   
    a, b, c = find_first_triplet(sum)
    product = a * b * c
   
    raise "%s != expected %s" % [product , expected] unless product  == expected
    puts "test case successful"
end


def solution
    sum = 1000
    a, b, c = find_first_triplet(sum)
    puts "a, b, c: %d, %d, %d" % [a,b,c]
    a * b * c
end


#
# Support Code
#
def find_first_triplet(sum)
    a = get_max_a(sum)
    b, c = 0, 0
   
    while a > 0
        b = a + 1
        c = sum - (a + b)
        while b < c:
            c = sum - (a + b)
            if is_pythagorean(a, b, c)
                return a, b, c
            end
            b += 1
        end
        a -=1
    end
end


def is_pythagorean(a, b, c)
    a**2 + b**2 == c**2
end


def get_max_a(abc_sum)
    mean = abc_sum / 3
    c = mean
    b = c - 1
    a = c - 2
    deque = [c, b, a]
   
    while deque.inject{|sum,x| sum + x } < abc_sum
        n = deque.shift
        n += 1
        deque.push(n)
    end
   
    deque.min
end


#
# Test Code
#
def test_get_max_a
    cases = [
        [1000, 332],
        [12, 3]
    ]
   
    cases.each do |abc_sum, expected|
        a_max = get_max_a(abc_sum)
        raise "%s != expected %s" % [a_max , expected] unless a_max  == expected
        puts "test_get_max_a successful"
    end
end


#
# Main
#
test_get_max_a
test_case
puts solution


Euler #7 in Ruby
http://projecteuler.net/problem=7
=begin

    http://projecteuler.net/problem=7
   
    By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see
    that the 6th prime is 13.

    What is the 10 001st prime number?

=end


#
# Test Case / Solution
#
def test_case
    index = 6
    expected = 13
   
    prime = get_prime_number(index)
   
    raise "%s != expected %s" % [prime, expected] unless prime == expected
    puts "test case successful"
end


def solution
    index = 10001
    get_prime_number(index)
end


#
# Support Code
#
def get_prime_number(index)
    at = 0
    last_prime = 1
   
   
    while at < index:
        last_prime = get_next_prime(last_prime)
        at += 1
        #puts at
    end
   
    return last_prime
end


def get_next_prime(last_prime)
    found = false
    n = last_prime
   
    while ! found
        n += 1
        if is_prime(n)
            found = true
        end
    end
   
    return n
end


def is_prime(number)
    limit = number / 2
   
     2.upto(limit) do |n|
        if number % n == 0
            return false
        end
    end
   
    true
end


def erosthanes_incremental_sieve(limit)
    # http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes#Incremental_sieve
    lower = 2
    batch_size = 1000
    primes = []
   
    while primes.length < limit
        upper = lower + batch_size
        sieved = erosthanes_sieve(lower, upper, primes)
        primes += sieved
        lower = upper
    end
   
    primes[limit]
end


def erosthanes_sieve(lower, upper, primes)
    # an exercise for the reader
end


#
# Main
#
test_case
puts solution


Python Sorting Problem
see Pastebin20120829

Google APIs Client Library for Python
Fabric DB Backup
from fabric.api import env, settings, run, local, get, put, lcd
from fabric.contrib.files import exists as remote_file_exists
from os.path import exists as local_file_exists, join as pathjoin

#
# Globals
#
DB_NAME = "klenwell"
DUMP_FILE = "%s-db.bz2" % (DB_NAME)
DUMP_PATH = pathjoin("/tmp", DUMP_FILE)
LOCAL_DEST = "/home/klenwell/hg/klenwell/data"

env.roledefs = {
    'local': ['localhost'],
    'remote': ['root@dbserver']
}
   
   
#
# Commands
#
def backup():
    mysql_dump_db()
    transfer_backup_file()
    save_to_repository()
    cleanup()

def test_host():
    echo("running `hostname -f` on host %s" % (env.host), 3)
    run("hostname -f")
   

#
# Tasks
#
def mysql_dump_db():
    cmd_f = "mysqldump %(db_name)s | bzip2 > %(dump_path)s"
    run(cmd_f % dict(db_name=DB_NAME, dump_path=DUMP_PATH))        
    assert remote_file_exists(DUMP_PATH), "dumped sql file not found"
   
def transfer_backup_file():
    get(DUMP_PATH, LOCAL_DEST)    
    assert local_file_exists(pathjoin(LOCAL_DEST, DUMP_FILE))

def save_to_repository():
    with lcd(LOCAL_DEST):
        local("hg commit -m 'backing up wiki db'")
        local("hg push")        
   
def cleanup():
    pass


Wikka Upgrade
WikkaUpgradeCore

WorkFlowy
https://workflowy.com/shared/82012321-4ce7-c039-6593-b0c5abf976f4/

WikkaRegistrationRecaptcha
Replaces UserSettingsRecaptcha

Font Ready (JS / PlayN)
The Problem

Solutions?
http://stackoverflow.com/a/6678869/1093087
https://developers.google.com/webfonts/docs/webfont_loader

<!DOCTYPE html PUBLIC "-W3CDTD XHTML 1.1EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

<head>
<title>webfont example</title>

<!-- Google AJAX Libraries API -->
<script src="http://www.google.com/jsapi">
<script>
google.load("jquery", "1.4.2");
google.load("webfont", "1");

WebFontConfig = {
google: {
families: [ 'Droid+Sans::latin' ]
},
loading: function() {
$("#status").text("loading fonts");
},
fontloading: function(DroidSans, n) {
$("#status").text("loading Droid Sans font");
$("#target").text("sans-serif");
},
fontactive: function(DroidSans, n) {
$("#status").text("Droid Sans is active");
$("#target").text("Droid Sans");
},
fontinactive: function(DroidSans, n) {
$("#status").text("Droid Sans is inactive");
}
};

google.setOnLoadCallback(function() {
WebFont.load(WebFontConfig);
});
</script>

<style type="text/css">
.wf-loading h1 {
font-family: sans-serif;
font-style:italic;
color: #999;
font-size: 16px;
}
.wf-inactive h1 {
font-family: sans-serif;
color:red;
font-size: 20px;
}
.wf-active h1 {
font-family: 'Droid Sans', sans-serif;
color:green;
font-size: 24px;
}
</style>

</head>

<body>
<h1 id="target">a web-load font</h1>
<pre>status: <span id="status">init</span></pre>
</body>

</html>


New Yorker Digital
To switch from print to digital version of New Yorker, call 800-873-8201

Vision Radius
visionRadius = r.radius + (court.radius * r.vision / 100.0)
focusPt = r.pt
maxScore = 0

for pt in visionRadiusPts:
    if not pt in court:
        continue
    score = getScore(pt)
    if score > maxScore:
        maxScore = score
        focusPt = pt
       
return focusPt


Lazy Sampling
import random, time, math

def get_options(num):
    return list(range(num))
   
def sort_options(options):
    return sorted(options, reverse=True)
       
def select_opt(options, skill):
    prob = skill / 100.0
    sampled_opts = []
    for o in options:
        if random.random() < prob:
            sampled_opts.append(o)
        if len(sampled_opts) > 10:
            break
    return random.choice(sampled_opts[:10])

def select_old(options, skill):
    size = int(round(1.0 * (len(options) * skill / 100.0)))
    opts = random.sample(options, size)
    opts = sorted(opts, reverse=True)
    return random.choice(opts[:10])
   
def selecti(options, skill):
    limit = (100 - skill) * 10
    sp = skill / 100.0
    prob = sp
   
    sampled_opts = []
    for o in options:
        if random.random() < prob:
            sampled_opts.append(o)
        if len(sampled_opts) > limit:
            break
    return random.choice(sampled_opts)

 
def sim(f, skill=50):
    runs = 1000
    options = sort_options(get_options(1000))
   
    selections = []
    for n in range(runs):
        selected = f(options, skill)
        selections.append(selected)
       
    avg_selection = 1.0 * sum(selections) / len(selections)
    print """
skill: %d
avg: %.2f
max: %d
min: %d"
"" % (skill, avg_selection, max(selections), min(selections))
   
   
if __name__ == "__main__":    
    sim(selecti,99)
    sim(selecti,66)
    sim(selecti,33)
   
    skill = 75
    s0 = time.time()
    sim(select_old,skill)
    s1 = time.time() - s0
    print "old complete: %0.5fs" % (s1)    
   
    s0 = time.time()
    sim(select_opt,skill)
    s2 = time.time() - s0
    opt = s1 / s2
    print "opt complete: %0.5fs (%.1fx as fast)" % (s2, opt)
   
    s0 = time.time()
    sim(selecti,skill)
    s3 = time.time() - s0
    opt = s1 / s3
    print "i complete: %0.5fs (%.1fx as fast)" % (s3, opt)    


String Data Structures (for when your JSON lib is a PITA)
)( - 1:a,b,c,d )( 2:a,b,c,d )( 3:a-b-c-d
][ - 1:a,b,c,d )( 2:a,b,c,d )( 3:a-b-c-d ][ 1:a,b,c,d )( 2:a,b,c,d )( 3:a-b-c-d ][ 1:a,b,c,d )( 2:a,b,c,d )( 3:a-b-c-d
}{ - 1:a,b,c,d )( 2:a,b,c,d )( 3:a-b-c-d ][ 1:a,b,c,d )( 2:a,b,c,d )( 3:a-b-c-d ][ 1:a,b,c,d )( 2:a,b,c,d )( 3:a-b-c-d }{ 1:a,b,c,d )( 2:a,b,c,d )( 3:a-b-c-d ][ 1:a,b,c,d )( 2:a,b,c,d )( 3:a-b-c-d ][ 1:a,b,c,d )( 2:a,b,c,d )( 3:a-b-c-d


init not found try passing init=bootargs
  • On Asus EEE Netbook
  • To Fix

atta dict!
"""
    ref: http://news.ycombinator.com/item?id=3881341
"
""
from collections import defaultdict
from pprint import pprint
import pdb

class attrdict(defaultdict):
    def __getattr__(self, key): return self[key]
    def __setattr__(self, key, val): self[key]=val

def tree(): return attrdict(tree)

ca = tree()
ca.orange.santa_ana = 92704
ca.orange.anaheim = 92807

pprint(ca)

pdb.set_trace()


matplotlib custom color sequence
"""
    A series of circle with custom colormap (red to green)
   
    USAGE
    python .dev/colormap.py
   
    REFERENCES:
    http://matplotlib.sourceforge.net/api/artist_api.html#matplotlib.patches.Circle
    http://www.scipy.org/Cookbook/Matplotlib/Show_colormaps
    http://stackoverflow.com/questions/9215658/plot-a-circle-with-pyplot
    http://stackoverflow.com/a/9544600/1093087
"
""

import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from matplotlib import cm
from numpy import arange
import math

SOLID = 'solid'
GREY = (.75,.75,.75)

clamp = lambda v: min(max(0, v), 1)

def main():
    # simulate a smartphone
    h, w = 15.0/8.0, 51.0/16.0
    hpx, wpx = 480.0, 800.0
    dpi = math.sqrt(hpx*wpx) / math.sqrt(h*w)
   
    # or my laptop
    lhpx, lwpx = 1600.0, 900.0
    lhw = 17.3
    ldpi = math.sqrt(lhpx*lwpx) / math.sqrt(lhw)
   
    # set up color map
    colors = cm.gist_rainbow(arange(200))
    rg_map = ListedColormap(colors[:100], 'red-green')
    colors = rg_map.colors    
   
    # circle params
    minR, maxR = 4,8
    x,y = 2,0
   
    # build image
    fig = plt.Figure(figsize=(w,h), dpi=dpi)
    for n in range(0,100,3):  
        radius = minR + ((maxR-minR) * (n/100.0))
        x += maxR
        pt = (x,y)
        x += maxR + 4
       
        r = clamp(1 - (.66*n / 100.0))
        g = clamp(0 + (1.0*n / 100.0))
        b = 0

        # alternately, using a colormap
        #ci = math.floor((n/100.0)*len(colors))
        #rgba = colors[ci]
        #r,g,b = map(lambda n: int(round(n*255)), [v for v in rgba[:3]])

        # circle and edge
        c = plt.Circle(pt, radius, color=(r,g,b))
        o = plt.Circle(pt, maxR, fill=False, lw=1, ls=SOLID, edgecolor=GREY)

        plt.axes().add_artist(c)
        plt.axes().add_artist(o)
        print (pt, radius), (r,g,b)
       
        # label a few
        if (n/3) % 11 == 0:
            rv,gv,bv = map(lambda n: int(round(n*255)), [v for v in (r,g,b)])
            label = 'RGB: (%d,%d,%d)' % (rv,gv,bv)
            plt.axes().annotate(label, (x-radius, n+minR+12), size=12)
       
    plt.axes().set_xlim((0,wpx), auto=False)
    plt.axes().set_ylim((-hpx/2,hpx/2), auto=False)
    plt.axes().set_aspect('equal')
    plt.show()
       

def example():
    """source: http://stackoverflow.com/a/9216646/1093087"""
    circle1=plt.Circle((0,0),.2,color='r')
    circle2=plt.Circle((.5,.5),.2,color='b')
    circle3=plt.Circle((1,1),.2,color='g',clip_on=False)

    fig = plt.gcf()
    fig.gca().add_artist(circle1)
    fig.gca().add_artist(circle2)
    fig.gca().add_artist(circle3)

    plt.show()

main()


Soup Request Test
#!/usr/bin/python

"""
    proto.py

    PURPOSE
    Prototyping gyro (requests experiment).
   
   
    USAGE
    $ venv/bin/python dev/gyro/tests/dev/proto.py

   
    NOTES
    Uses requests, beautifulsoup


    REFERENCES
    http://docs.python-requests.org/en/latest/user/quickstart/#make-a-get-request
    http://www.crummy.com/software/BeautifulSoup/bs3/documentation.html#Quick%20Start
"
""
#
# IMPORTS
#
# Python Imports
import unittest, sys, os, time
from os.path import (abspath, dirname, join as pathjoin, exists)
from datetime import(datetime, date, timedelta)
from random import (choice, sample)
import pdb
import re

# External Imports
import requests
from BeautifulSoup import BeautifulSoup as soup, Tag, NavigableString

# Extend sys.path
PROJECT_PATH = abspath(pathjoin(dirname(__file__), '../..'))

# Project Imports




#
# MODULE PARAMETERS
#



# Exception Classes
class NullException(Exception): pass


#
# Test Class
#
class PrototypeTest(unittest.TestCase):
   
    data_dir = pathjoin(PROJECT_PATH, 'test/data')
   
    #
    # Harness
    #
    def setUp(self):
        pass
       
    def tearDown(self):
        pass

       
    #
    # New Methods
    #
   
   
   
    #
    # Unit Tests
    #
   
   
   
    #
    # Dev Tests
    #
    def testLastPageGoogleNoOmissions(self):
        url = "http://www.google.com/search"
        query = "hello world"
        start_at = 990
       
        #
        # REQUESTS
        #
        # prepare
        payload = dict(
            q = query,
            hl = "en",
            start = start_at,
            filter = 0
        )
       
        # get
        site = requests.get(url, params=payload)        
        raw = site.content
       
        # test
        needle = "to show you the most relevant results"
        self.assertFalse(needle in raw)
        self.assertTrue("Page 100" in raw)
       
        #
        # SOUP
        #
        # parser
        html = soup(site.content)
        results_block = html.findAll("li", { "class" : "g" })
        last_result = results_block[-1]
       
        # parse last result
        links = last_result.findAll("a")
        result_link = links[0].get("href")
        result_url = result_link.split('/url?q=')[1].split('&')[0]
        print result_url
       
        # test request
        self.assertTrue(results_block)
       
        # interact
        time.sleep(2)              
   
    def testLastPageGoogleOmitted(self):
        url = "http://www.google.com/search"
        query = "python language"
        start_at = 990
       
        #
        # REQUESTS
        #
        # prepare
        payload = dict(
            q = query,
            hl = "en",
            start = start_at
        )
       
        # get
        site = requests.get(url, params=payload)        
        raw = site.content
       
        # test
        needle = "to show you the most relevant results"
        self.assertTrue(needle in raw)
       
        #
        # SOUP
        #
        # parser
        html = soup(site.content)
        results_block = html.findAll("li", { "class" : "g" })
        last_result = results_block[-1]
       
        # parse last result
        links = last_result.findAll("a")
        result_link = links[0].get("href")
        result_url = result_link.split('/url?q=')[1].split('&')[0]
        print result_url
       
        # test request
        self.assertTrue(results_block)
       
        # interact
        #import pdb; pdb.set_trace()
       
        # don't arouse suspicion
        time.sleep(2)
       
   
    def testBeautifulSoup(self):
        """parse my special wiki page"""
        url = "http://localhost/wikka/Gyro"
        site = requests.get(url)
        html = soup(site.content)
       
        # these work
        haystack = html.find("h3", { "id" : "hn_Haystack" })
        needle = html.find(text=re.compile('a beautiful needle'))
       
        # these don't work
        nostack = html.find("h4", { "id" : "hn_Haystack" })     # wrong tag
        noneedle = html.findAll(text="a beautiful needle")
       
        self.assertEqual(type(haystack), Tag)
        self.assertEqual(type(needle), NavigableString)
        self.assertFalse(nostack)
        self.assertFalse(noneedle)
        self.assertTrue("a beautiful needle" in str(html))
        self.assertTrue("a beautiful needle" in str(needle))
       
   
    def testRequests(self):
        """pull my wiki"""
        url = "http://localhost/wikka/Gyro"
        site = requests.get(url)
        self.assertTrue(site.ok)
        self.assertTrue("a beautiful needle" in site.content)
   

   
    #
    # Smoke Tests
    #
    def testInstance(self):
        self.assertTrue(isinstance(self, unittest.TestCase))



#
# Main
#
if __name__ == "__main__":
    mod = sys.modules[globals()['__name__']]
    suite = unittest.TestLoader().loadTestsFromModule(mod)
    unittest.TextTestRunner(verbosity=2).run(suite)


Programming Collective Intelligence
Source code: http://blog.kiwitobes.com/?p=44

Install gevent to virtualenv Directory
mirnazim.org
stackoverflow.com
groups.google.com
# set up virtual env
source bin/activate

# install gevent
sudo apt-get install libevent-dev
export C_INCLUDE_PATH=/usr/include:/usr/local/include:/opt/local/include
pip install greenlet
pip install gevent


Python Temp Files
Simple case:
import tempfile
...
temp_file_name = tempfile.NamedTemporaryFile().name
f = open(temp_file_name)


Write to temp file:
file_contents = """hello world"""
temp_file = tempfile.NamedTemporaryFile()
temp_file.write(file_contents)
temp_file.seek(0)
f = open(temp_file.name)


Getting Setup with Virtualenv
http://mirnazim.org/writings/python-ecosystem-introduction/
# Install pip and virtualenv
sudo apt-get install python-pip python-dev build-essential 
sudo pip install pip --upgrade
sudo pip install virtualenv

# Setup a virtualenv
mkdir venv
virtualenv --distribute --no-site-packages venv

# Run from virtualenv
venv/bin/python
venv/bin/python myscript.py

# To activate/deactivate env
source bin/activate
(venv)$ deactivate


Draw Circle to Canvas in PlayN
Stack Overflow Question: http://stackoverflow.com/questions/9478065/

GWT Plugin for Eclipse
Problem: http://stackoverflow.com/questions/8363560
Solution: http://askubuntu.com/questions/49557#94341

Install Eclipse with ADT Plugin on Ubuntu 11.10
Ask Ubuntu
Pastebin20120223
http://stackoverflow.com/questions/9426715
related?
possible solution?

Color Maps
http://matplotlib.sourceforge.net/examples/api/colorbar_only.html
http://matplotlib.sourceforge.net/examples/pylab_examples/show_colormaps.html
RdYlGn

Installing Ubuntu 11.10 on HP G71310US
HP Pavilion g7-1310us Intel Core i3-2350M Notebook
Chose Ubuntu 11.10 64-Bit
Needed to deal with black screen issue detailed here
  • See How to enable kernel options on the livecd (before install)
  • Choose nomodeset (x will appear next to it)
  • Then select Install Ubuntu
  • After installation, need to follow direction for temporarily and then permanently modifying grub config with nomodeset flag. Hold down shift on boot to get to grub config.
  • On IRC chat, ludwin01 suggested 10.04 lts version did not have this problem. I'm working around it for now with grub flag.
  • My Ubuntu Forum post on issue: http://ubuntuforums.org/showthread.php?p=11695329#post11695329
  • AskUbuntu Post: http://askubuntu.com/questions/105651/

Python Inheritance
class Reveal(object):
    def __repr__(self):
        return "<%s %s>" % (self.__class__.__name__, self.__dict__)

class Yin(Reveal):
    def __init__(self, yin=100):
        self.yin = yin
        self.lightness = True
        self.darkness = False
        self.balance = False


class Yan(Reveal):
    def __init__(self, yan=100):
        self.yan = yan
        self.lightness = False
        self.darkness = True
        self.balance = False

class YinYan(Yin, Yan):
    def __init__(self, yin, yan):
        Yin.__init__(self, yin)
        Yan.__init__(self, yan)
        self.balance = True


yin = Yin(50)
yan = Yan(50)
yinyan = YinYan(50, 50)

print yin
print yan
print yinyan

# Prints
<Yin {'balance': False, 'yin': 50, 'lightness': True, 'darkness': False}>
<Yan {'balance': False, 'yan': 50, 'lightness': False, 'darkness': True}>
<YinYan {'balance': True, 'yin': 50, 'lightness': False, 'darkness': True, 'yan': 50}>


Send Email through Gmail with Python
"""
    Send an email programmatically through Gmail.

    REFERENCES
    http://snippets.dzone.com/posts/show/757
    http://www.nixtutor.com/linux/send-mail-through-gmail-with-python/
    http://stackoverflow.com/questions/399129/#comment8985407_399240
"
""
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders
import os
from os.path import abspath, dirname, join

SMTP_SERVER = 'smtp.gmail.com:587'
SMTP_USER   = 'USER@gmail.com'
SMTP_PASS   = 'PASS'
EMAIL_FROM  = 'USER <%s>' % (SMTP_USER)

def send_gmail(to, subject, text, files=[]):
    assert type(to) == list
    assert type(files) == list
    from_ = EMAIL_FROM

    msg = MIMEMultipart()
    msg['From'] = EMAIL_FROM
    msg['To'] = COMMASPACE.join(to)
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject

    msg.attach( MIMEText(text) )

    for file in files:
        part = MIMEBase('application', "octet-stream")
        part.set_payload( open(file,"rb").read() )
        Encoders.encode_base64(part)
        part.add_header('Content-Disposition', 'attachment; filename="%s"'
                       % os.path.basename(file))
        msg.attach(part)

    smtp = smtplib.SMTP(SMTP_SERVER)
    #smtp.set_debuglevel(1)
    smtp.ehlo()    # apparently this is required in python 2.5
    smtp.starttls()
    smtp.login(SMTP_USER, SMTP_PASS)
    smtp.sendmail(from_, to, msg.as_string() )
    smtp.close()


def test_email():
    to = 'YOUR_RECEPIENT@some_domain.com'
    subject = "Python Gmail Test"
    text = 'This is simply a test.'
    send_gmail([to], subject, text)
    print 'simple test complete'


Method Decorator
def check_some_flag(method):
    def wrapper(self, *args, **kwargs):
        if not self.some_flag:
            raise Exception("some_flag not set")
        else:
            result = method(self, *args, **kwargs)
            return result
    return wrapper


Find Equation for Set of Points
python find roots of equation
>>> import numpy
>>> x = [1,50,99]
>>> y = [2,1,0.5]
>>> a,b,c = numpy.polyfit(x,y,2)
>>> f = lambda x: a*x**2 + b*x + c
>>> f(1)
2.0
>>> f(20)
1.5528946272386506
>>> f(50)
1.0000000000000002
>>> f(90)
0.55435235318617249
>>> f(100)
0.49500208246563937
>>> f(99)
0.5


Verizon Opt-Out Site: http://www.vzw.com/myprivacy

Somewhat Improved Wikka Installer Routine
Diff for wikka.php:
diff -r c8f8537f5e21 -r 4e091af5eacf php/wikka/wikka.php
--- a/php/wikka/wikka.php	Tue Jan 17 10:01:24 2012 -0800
+++ b/php/wikka/wikka.php	Tue Jan 17 11:43:38 2012 -0800
@@ -509,11 +509,15 @@
 
 /**
  * Compare versions, start installer if necessary.
+ * Wait to start installer below if this is an upgrade so we can limit access
+ * to admin users.
  */
-if (!isset($wakkaConfig['wakka_version'])) $wakkaConfig['wakka_version'] = 0;
-if ($wakkaConfig['wakka_version'] !== WAKKA_VERSION)
-{
-	/**
+$is_new_install = ! isset($wakkaConfig['wakka_version']);
+$is_upgrade = $wakkaConfig['wakka_version'] !== WAKKA_VERSION;
+
+if ( $is_new_install ) {
+    $wakkaConfig['wakka_version'] = 0;
+    /**
 	 * Start installer.
 	 *
 	 * Data entered by the user is submitted in $_POST, next action for the
@@ -590,6 +594,7 @@
 	exit;
 }
 
+
 /**
  * Save session ID
  */
@@ -611,6 +616,39 @@
 }
 
 /**
+ * Check for upgrade. If so an user is admin, show setup page, else show
+ * a maintenance message to all other visitors.
+ */
+$is_admin = $wakka->IsAdmin($user);
+$at_install_step = ($_GET['installAction'] == 'writeconfig') && (isset($_POST['config']));
+$upgrade_allowed = $is_admin || $at_install_step;
+
+if ( $is_upgrade && $upgrade_allowed ) {
+	$installAction = 'default';
+	if (isset($_GET['installAction'])) $installAction = trim($_GET['installAction']);	#312
+	if (file_exists('setup'.DIRECTORY_SEPARATOR.'header.php'))
+	include('setup'.DIRECTORY_SEPARATOR.'header.php'); else print '<em class="error">'.ERROR_SETUP_HEADER_MISSING.'</em>'; #89
+	if
+	(file_exists('setup'.DIRECTORY_SEPARATOR.$installAction.'.php'))
+	include('setup'.DIRECTORY_SEPARATOR.$installAction.'.php'); else print '<em class="error">'.ERROR_SETUP_FILE_MISSING.'</em>'; #89
+	if (file_exists('setup'.DIRECTORY_SEPARATOR.'footer.php'))
+	include('setup'.DIRECTORY_SEPARATOR.'footer.php'); else print '<em class="error">'.ERROR_SETUP_FOOTER_MISSING.'</em>'; #89
+	exit;
+}
+elseif ( $is_upgrade && $_GET['install_help'] ) {
+    print "<h2> POST,GET, SESSION variables</h2>";
+    print '<pre>';
+    var_dump($_POST);
+    var_dump($_GET);
+    var_dump($_SESSION);
+    print '</pre>';
+}
+elseif ( $is_upgrade ) {
+    die('<h2>Site Undergoing Temporary Maintenance</h2><h4>Please check back shortly.</h4>');
+}
+
+
+/**
  * Run the engine.
  */
 if (!isset($handler)) $handler='';


IKEA Stand-Up Desks
http://news.ycombinator.com/item?id=3442809
http://www.ikea.com/us/en/catalog/products/00115992/
http://www.ikea.com/us/en/catalog/products/60111123/