Python environments! w/ virtualenv, virtualenvwrapper, pythonbrew

I will be speaking at the Python Houston meetup. The topic will be over virtualenv, virtualenvwrapper, and pythonbrew. The slides are below.

Sleep and Wake Scripting OSX

There have been many times where I thought to myself — I wish my computer would do X when it goes to sleep and Y when it wakes up. There are many applications for this, some include:

  • Mounting an SSH filesystem depending on WiFi connection
  • Have the computer greet you and dismiss you (very nerdy)
  • Disconnect/Kill some application that always hangs on sleep
  • Move files from one folder to another
  • Tweet

So how is this nerdy matter accomplished? It’s actually pretty trivial. Familiar with bash? Then you’re on the way to sleep/wake success!

Installing Sleepwatcher

Head over to http://www.bernhard-baehr.de/ and download a copy of Sleepwatcher 2.2. The installation instructions are pretty simple:

$ sudo mkdir -p /usr/local/sbin /usr/local/share/man/man8
$ sudo cp ~/Desktop/sleepwatcher_2.2/sleepwatcher /usr/local/sbin
$ sudo cp ~/Desktop/sleepwatcher_2.2/sleepwatcher.8 /usr/local/share/man/man8

Once installed, run it in daemon mode:

$ /usr/local/sbin/sleepwatcher -d --sleep /path/to/your/sleepscript --wakeup /path/to/your/wakeupscript

If testing is needed run it in verbose mode:

$ /usr/local/sbin/sleepwatcher --verbose --sleep /path/to/your/sleepscript --wakeup /path/to/your/wakeupscript

A simple hello/goodbye script

Now that sleepwatcher is installed, let’s make the computer say Welcome back, <yourname> on wake and Goodbye on sleep. Two files are needed for this:

  • sleepscript – script that runs when the computer sleeps
  • wakescript – script that runs when the computer wakes

The scripts can be placed anywhere but the standard place would be to place them in /Users/<username>/bin. The bin folder should contain:

  • /Users/<username>/bin/sleepscript
  • /Users/<username>/bin/wakescript

The scripts should contain:

Sleep Script

function say_goodbye {
	say -v Vicki "goodbye"
}
say_goodbye

Wake Script

function say_hello {
	say -v Vicki "Welcome back, username"
}
say_hello

Make sure to chmod the scripts to 775. Next, launch the daemon to test:

$ /usr/local/sbin/sleepwatcher -d --sleep /Users/<username>/bin/sleepscript --wakeup /Users/<username>/bin/wakescript

Demo

Here is a video demo showing my Macbook Air saying “Welcome back” and “Goodbye”. 1337!

Happy Coding!

IPv6: Biting the bullet

With IPv4 on the verge of being all used up and its successor IPv6 still in the distance, most companies are going to require massive code, infrastructure, and database changes. But hey, you get 2^128 IP addresses! That’s enough to move this planet for the next 200 years (a wild guess).

IPv4 vs. IPv6

So what’s the difference? IPv4 has 32 bits which means it’s possible to have 4,294,967,296 or 4.2 billion IP addresses. The new and hopefully improved IPv6 has 128 bits. While 32 vs 128 might not seem like a lot as a decimal number, IPv6 boasts a whopping 3.40282367 × 10^38 IP addresses. Lets expand that:

340,282,367,000,000,000,000,000,000,000,000,000,000 (WTF?!)

I don’t even know what that is?! A quick lookup in Google tells me this is 340 undecillion IP address. Hopefully this is enough to last us a while before we have to invest in yet another infrastructure change. So what does an IPv6 address look like? Traditional IPv4 looks like this:

192.168.1.100

The standard 4 octets above form a binary number totaling 32 bits. IPv6 is separated by colons and contains 8 groups of 16 bits in hexadecimal, hence the 128 bits. A typical IPv6 address:

0891:a783:804f:8c8d:033a:2ae2:16dc:b1ea

In it’s compressed form (removing the leading zeros) it looks like:

891:a783:804f:8c8d:33a:2ae2:16dc:b1ea

You can find more on how to compress IPv6 at wikipedia. Let’s focus on storing these suckers in the database.

Storing IPv6 Addresses

I am only going to focus on MySQL because that’s what I have been using, but there are two data types used to store IPv4 and IPv6 addresses in the same field (there are more, these are most common):

  • VARCHAR(39) – 39 characters allowing for both full IPv4 and IPv6 addresses to be stored
  • VARBINARY(16) – binary data up to 16 bytes or 128 bits

Both are suitable but have different use cases. If you want to only store the IP for simple whois lookups, DNS checks, mapping, or for presentation (UI) then VARCHAR is the way to go. Need to perform range operations (from xxx bits to xxx bits) on the data? VARBINARY is your friend. Plus, binary is cool.

Storing an ip address in VARBINARY is pretty trivial. This simple insert statement will do the trick:

INSERT INTO hosts (ip_address) VALUES (INET6_PTON('your_ip_address'));

Or an update statement:

UPDATE hosts SET ip_address = INET6_PTON('your_ip_address');

Storage is simple, unless you want to make it complex, but sticking to the KISS principle usually works best. The package for INET6_PTON is developed and maintained by Watchmouse. I haven’t been successful in getting the package to work in OSX, but hopefully I’ll have that resolved soon and post an update. In ubuntu, like always, it’s cake. In MySQL 5.6+ the packages are built-in.

IPv6 in Code

Now that IPv6 is ready to go on the database side, how do we validate before entering data? I’m going to explain this in server side code. If you need javascript validation, try Beaugunderson’s IPv6 Library. It works in both browser and Nodejs.

Let’s start with Python. Using a package called IPy we can test some IP addresses like so:

>>> import IPy
>>> ip = IPy.IP('0891:a783:804f:8c8d:033a:2ae2:16dc:b1ea')
>>> ip.version()
6
>>> ip = IPy.IP('0891:a783:804f:8c8d:033a:2ae2:16dc:b1ea/128')
>>> ip.version()
6
>>> ip = IPy.IP('192.168.1.100')
>>> ip.version()
4
>>> ip = IPy.IP('thisipisnotvalid')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/glenbot/.virtualenv/blogtests/lib/python2.7/site-packages/IPy.py", line 230, in __init__
    (self.ip, parsedVersion) = parseAddress(ip)
  File "/Users/glenbot/.virtualenv/blogtests/lib/python2.7/site-packages/IPy.py", line 1164, in parseAddress
    ret = long(ipstr, 10)
ValueError: invalid literal for long() with base 10: 'thisipisnotvalid'

Notice that it throws an exception when an IP is invalid. To test validation, writing a simple function will do the trick:

from IPy import IP

def ip_is_valid(ip_address):
    try:
        ip = IP(ip_address)
        return True
    except:
        return False

def get_version(ip_address):
    if ip_is_valid(ip_address):
        return IP(ip_address).version()
    return None

Validation in PHP is built-in. Using the filter_var function we can accomplish validation:

$is_ipv4 = filter_var($ip_address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
$is_ipv6 = filter_var($ip_address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);

if ($is_ipv6) {
    // do something here
}

if ($is_ipv4) {
    // do something here
}

This will not validate IP addresses with a prefix notation ex. 0891:a783:804f:8c8d:033a:2ae2:16dc:b1ea/128. For this, the PEAR IPv6 package is needed. In reality you could just split out the /128 but using the package is probably the safe route.

$net_ipv4  = new Net_IPv4();
$net_ipv6  = new Net_IPv6();

$is_ipv4 = !PEAR::isError($net_ipv4->parseAddress($ip_addr));
$is_ipv6 = $net_ipv6->checkIPv6($ip_addr);

if ($is_ipv6) {
    // do something here
}

if ($is_ipv4) {
    // do something here
}

Happily Ever After …

Hopefully this will get you started on your journey towards becoming an IPv4/6 validating Pirate! It’s somewhat trivial and biting the bullet now will definitely pay off. Happy coding!

Fork me on GitHub