Play Your Way to Flexbox Mastery

Projects at work have brought me back to front end web development. And reminded me what a pain it can be to position elements where you want them. I admit, for just a minute, I was tempted to use a table. Instead I used a Flexbox layout. While Flexbox is still a W3C draft, the CSS commands are supported by most modern browsers (according to Can I Use). If your users aren't using IE or old Android you are probably safe using it.

There are several excellent tutorials on Flexbox, such as this one by css-tricks.com. But if you are feeling a bit more playful check out these games that will keep you entertained while learning the basics of Flexbox layout.

Flexbox Froggy

Flexbox Froggy gives you a pond, some lillypads, and some frogs and ask you to get the frogs on the correctly colored pads. It starts of easy and adds commands as you progress through the 24 levels of play.

For example Level 19 has you using flex-direction and flex-wrap to go from this:

/images/flexbox_froggy_19start.thumbnail.png

to this:

/images/flexbox_froggy_19end.thumbnail.png

Flexbox Defense

If you are feeling a bit more aggressive, or maybe you're colorblind and the frogs all look the same to you, give Flexbox Defense a try. This spin on a classic tower defense game teaches you the key aspects of Flexbox layout while you blast dangerous purple circles with your turrets. Each of the 12 levels starts with a tutorial on the concept you'll need to make it past the level.

/images/flexbox_defense_1end.thumbnail.png

CSS Diner

Enjoying the mix of learning and fun? Need a little CSS selector practice? Checkout CSS Diner. It will teach you to use CSS classes, ids, and pseudo-selectors.

/images/css_diner_13start.thumbnail.png

Missing Dependencies When Installing Python Packages With Pip

Pip is the best way to install Python packages. It handles most of the pain of tracking down dependencies and installing everything. And usually it does it quite well. But some packages require various libraries to be installed and available on the system. When these libraries are missing the installation will fail.

The pip error messages can be overwhelming (there are a lot of them), but the info you need to fix the problem is there if you know where to look for it. In this case let's take a look at the errors I received when trying to install Scrapy into a new virtualenv. I'm on a recent-ish version of Debian Linux. I happen to be in Python 2.7 as Scrapy is still at 95% tests passing for Python 3 at the time of this writing.

Working in my new virtualenv I started by trying to install Scrapy.

pip install scrapy

Things start out well with the usual download, unpack, and install.

Downloading/unpacking scrapy
Downloading Scrapy-1.0.5-py2-none-any.whl (291kB): 291kB downloaded
Downloading/unpacking cssselect>=0.9 (from scrapy)
Downloading cssselect-0.9.1.tar.gz
Running setup.py (path:/tmp/pip-build-pETEoF/cssselect/setup.py) egg_info for package cssselect

And then we hit a snag. After a bit we run into an error with building some of the dependencies. This cascades and we end up with a slew of errors. This is where it gets a bit overwhelming. But we can zero in on the error to see exactly what we're missing.

Building wheels for collected packages: cryptography, cffi
Running setup.py bdist_wheel for cryptography ... error
Complete output from command /home/joshua/.virtualenvs/scrapycars/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-85Mdmv/cryptography/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" bdist_wheel -d /tmp/tmp6bFspgpip-wheel- --python-tag cp27:
Package libffi was not found in the pkg-config search path.
Perhaps you should add the directory containing `libffi.pc'
to the PKG_CONFIG_PATH environment variable
No package 'libffi' found

This error gets repeated multiple times (I don't know why, but I have it five times in a row) and then gets followed by a bunch of other output.

The key here really is that we are missing the libffi package. This package 'allows code written in one language to call code written in another language'. A search for 'debian libffi' showed me that I could install the libffi-dev package.

sudo apt-get install libffi-dev

With this package installed I then installed Scrapy without errors.

The Fix

  1. Don't panic.
  2. Start at the top-most error (others may be caused by the first error).
  3. Search for and install your missing package.
  4. Pip install again.
  5. Repeat as necessary.

But It Works Outside My VirtualEnv

You may find yourself with dependency errors in a virtualenv, but you didn't get any errors when you pip installed from your system Python installation. How can that be? Well, mostly likely you already had the package installed. When you run pip install again it doesn't throw up errors if the package is already installed.

The package may have been installed as part of the distribution and didn't need the missing package as part of its build. Or you may have had the missing package installed at one time and it was removed in the interim.

Deploying A WSGI Application On WebFaction

I've been using WebFaction since April 2010 as my webhost. Many of those projects are written in Python and use WSGI. Most often they will be a Flask app of some kind.

Creating The Application

WebFaction has their own custom control panel. We'll use the control panel to provision the application on their servers. This part isn't hard, but it is unique to WebFaction. See their docs for how to create an application, connect it to a domain, and create the website.

The key thing when creating the application is to set the App category to mod_wsgi and then pick the appropriate Python version.

/images/webfaction_wsgi_app.thumbnail.png

Using a VirtualEnv

You can use a virtualenv on WebFaction just like you would in your development environment. The benefits are basically the same: separation of package versions between projects, reproducibility between deployments, a general feeling of smugness.

If you are using virtualenvs you'll want virtualenvwrapper. You'll need to install that yourself. I followed the steps in this excellent post.

Once that is done create a new virtualenv:

mkvirtualenv yourvirtualenv

I prefer to use only packages in my virtualenv. You can use global packages if you like, but you run the risk of upgrading a dependency for one project that breaks another. To use only virtualenv packages you create an empty file called sitecustomize.py in your virtualenv's lib/pythonx.y directory.

Next you want to install the packages required by your project. To get that list pip is your friend. From your development environment:

pip freeze > requirements.txt

Now transfer that server to your host and use it to install the packages:

pip install -r requirements.txt

Updating index.py

When your application was created an index.py file was automatically created within the htdocs directory. This file needs to be edited to activate your virtualenv and to set some paths needed by WSGI.

As an example:

import sys

activate_this='/home/yourAccountName/.virtualenvs/yourVirtualEnvName/bin/activate_this.py'
execfile(activate_this, dict(__file__=activate_this))

sys.path.append('/home/yourAccountName/webapps/yourApp/htdocs')

from main import app as application

You will of course replace the paths withe ones to your account's virtualenvs and application directories.

The last line is the statement that starts your application. In my case I have a main.py file that handles starting the app.

Updating httpd.conf

The last file that needs to be edited is the Apache httpd.conf file. It is found in the applications apache2/conf directory. Edit the file to add the following:

WSGIPythonPath /home/yourAccountName/webapps/yourApp/htdocs/
WSGIScriptAlias / /home/yourAccountName/webapps/yourApp/htdocs/index.py

<Directory /home/yourAccountName/webapps/yourApp/htdocs/>
    AddHandler wsgi-script .py
    RewriteEngine on
    RewriteBase /
    WSGIScriptReloading on
</Directory>

This will work if your app is running at the root domain or a subdomain. If you are running in a subdirectory you have some more work to do. But for now, this will remove the .py from the path and give you the kind of URLs you are probably expecting.

Deploy Files and Restart Apache

If you haven't already, now is a good time to move your code to the server. I use mercurial to do this, but you can do it via git, FTP, or whatever method is convenient for you.

Once everything is in place restart Apache so it sees the configuration changes.

apache2/bin/restart

Victory

At this point you should be able to pull up your app in the browser and see it in all its glory.