FlowFX

Queen - Live at LIVE AID 1985

Does it get any better?

DreamHost is awesome!

There are many crappy hosting providers. In fact, almost all of them are crappy.

Almost.

DreamHost is awesome!

In their standard shared-hosting plan they provide:

(to be continued…)

They do offer domain registration as well, but I prefer using Hover for this. In cases where everything else is on DreamHost, I just switch the domain's name servers to the DreamHost name servers. And it just works.

By now, I recommend DreamHost to everyone who asks, especially to all my clients.

List comprehensions for physicists

A list comprehension provides a compact way of mapping a list to another list by applying a function to each of the elements of the list.

From "Dive Into Python 3"

Yeah. Well. Talk English to me! Please.

Until recently I had no clue what list comprehensions do or how to use them or what they're good for. Reading Dive Into Python 3 about two years ago, without much prior programming knowledge, maybe wasn't the best idea I ever had.

Today I know quite a bit more about programming in general and about Python in particular. Still, list comprehensions kept eluding me until I read From List Comprehensions to Generator Expressions by the inventor of Python himself, Guido van Rossum.

In this article, he starts by showing how lists are stated in mathematics. As a physicist, an expression like

$$ \{ x \in \mathbf{N}\ |\ x < 10 \} $$

is perfectly clear to me. It's the set of all natural numbers that are smaller than 10, i.e.:

$$ \{1, 2, 3, 4, 5, 6, 7, 8, 9\} $$

depending on your preference of zero being a natural number or not.

A python list of these integers would be:

[0,1,2,3,4,5,6,7,8,9]

Und suddenly, everything became clear to me.

[f(x) for x in S if P(x)]

is the list of the function values $f(x)$ of all $x$ in the set $\mathbf{S}$ that fulfill the condition $\mathbf{P}$.

Using a Python list comprehension, the first mathematical expression above reads:

[x for x in N if x < 10]

Of course, this list is not possible, because $\mathbf{N}$ is infinite.

The function value $f(x)$ is very handy as well. The set of the squares of all integers between 1 and 4:

$$ \{ y\ |\ y = x^{2}; x \in \mathbf{N}; 0 < x < 5 \} $$

expressed via a list comprehension is:

[x**2 for x in [1,2,3,4]]

Looking at list comprehensions in mathematical terms helped me understand them. It's a great example of one and the same idea expressed differently in different fields and thus more or less understandable by people in that field.

Run Selenium from PyCharm

In order to run the Selenium WebDriver from within PyCharm, you need to explicitly add the path of the browser driver executable.

It is in fact not necessary to add the PyCharm Selenium plugin.

My PyTest fixture for the Selenium browser now looks like this:

from selenium import webdriver
import pytest

@pytest.fixture(scope="session")
def browser():
    browser = webdriver.PhantomJS(executable_path="/usr/local/bin/phantomjs",
                                  desired_capabilities={
                                  'phantomjs.page.settings.loadImages': 'false',
                                  })
    browser.implicitly_wait(3)

    yield browser

    browser.quit()

I'm using PhantomJS as a headless browser because it is way faster than Firefox or Chrome. I wish I could disable all loading of CSS files.

Update 2017-01-18

Putting the explicit path to the browser driver executable into the test fixture causes problems when I run the same test on Snap CI. A better solution is to add the directory of the (PhantomJS) executable into PyCharm itself.

In my PyCharm Community Edition 2016.2 I go to Run >> Edit Configurations…, select the run configuration that runs my functional test and put

PATH=/usr/local/bin/

into Environment variabls. That's all. Now PyCharm finds the executable of PhantomJS in that directory and I can remove the executable_path line from the fixture.

I do not know why PyCharm doesn't just import the $PATH from my shell.

Disable CSRF validation when unit-testing a Flask app!

In my current Flask project, I wanted to test a view method that includes a form with a POST request. But it wouldn't work.

The view method looks something like this:

# views.py
@tennis.route('/tournaments/add', methods=['GET', 'POST'])
def add_tournament():
    form = AddTournamentForm()
    
    if form.validate_on_submit():
        t = Tournament(name=form.name.data)
        db.session.add(t)
        db.session.commit()
        
        flash('A tournament was added to the database.')
        return redirect(url_for('tennis.index'))

    return render_template('tennis/add_tournament.html',
                       form=form)

Flask-Testing provides a TestCase class with several useful assert methods. So the test would look like this:

# test_views.py  
from flask_testing import TestCase

class TestTennisViews(TestCase):    
    […]   
      
    def test_tennis_add_tournament(self):
        # WHEN submitting correct form data to the add_tournament view
        r = self.client.post('/tennis/tournaments/add',
                             data=dict(
                                 name='Chicharito Open',
                             ))
    
        # THEN it redirects to the tennis overview page
        self.assertRedirects(r,'/tennis/')
        # and it shows a message
        self.assertMessageFlashed('A tournament was added to the database.')
        # and there is a tournament in the database
        assert Tournament.query.count() > 0
        # and it has the correct tournament
        t = Tournament.query.first()
        assert t.name == 'Chicharito Open'

assertRedirects checks if the status code is 301 or 302. In my tests, it was always 200, and the test failed. Of course, nothing was added to the database, either.

I googled a lot, without success. I tried all combinations of the following keywords, among others:

flask
unit test
wtforms
POST request
testing

The solution hit me when taking a break (it works!). It lies in the form.validate_on_submit() part of the view function. validate_on_submit() does two things:

  1. It validates the form fields according to the validators specified in the form definition.
  2. It validates a CSRF token.

Guess what: there is no CSRF token generated when executing a POST request directly in the test.

The solution is easy, as FLASK-WTF provides a configuration option to disable CSRF:

# config.py

[…]

class TestingConfig(Config):
    TESTING = True
    WTF_CSRF_ENABLED = False
    
    […]
    
class FunctionalTestingConfig(TestingConfig)
    WTF_CSRF_ENABLED = False

Of course, only disable CSRF in your test configuration! I created a separate configuration for my functional tests, so that CSRF is enabled in those. When using the browser with Selenium, the CSRF token is provided by the WTForms form on the web page.