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:

  • unlimited webspace
  • unlimited MySQL databases
  • unlimited email accounts
  • unlimited user accounts
    • with separate web spaces
    • with SSH access
  • free LetsEncrypt SSL certificates for every domain and subdomain
  • up-to-date PHP and MySQL versions
  • excellent and friendly customer support

(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.

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.

Testing Bootstrap select dropdown field with Selenium (Python)

I am building a Flask app that uses the Bootstrap CSS framework. Forms fields are generated with WTForms via the Flask-WTF extension.

One of my forms includes a select field:

<div class="form-group ">
    <label class="control-label" for="surface">Surface</label>

    <select class="form-control" id="surface" name="surface">
        <option value="clay">Clay</option>
        <option value="hard">Hard</option>
        <option value="grass">Grass</option>
    </select>
</div>

My functional tests with Selenium went fine until I changed the desired test value from the default ("Clay") to a different option ("Hard"). (duh!!) So I knew I did something wrong and looked for the correct way to choose an option from a select field.

All the tests use the Selenium WebDriver.

from selenium import webdriver

browser = webdriver.Firefox()

How it doesn't work

Via Google and Stackoverflow I found several possible solutions, none of which worked for me.
 My favorite one uses the Selenium Webdriver Select class:

from selenium.webdriver.support.ui import Select

select = Select(browser.find_element_by_id('surface'))
select.select_by_visible_text("Hard")
select.click()

Then there are solutions using the find_element_by_xpath method:

option = browser.find_element_by_xpath("//select[@id='surface']/option[@value='hard']")
option.click()

or find_element_by_css_selector:

option = browser.find_element_by_css_selector("select#surface > option[value='hard']")
option.click()

and one other looking for the option fields:

dropdown = browser.find_element_by_id('surface')
for option in dropdown.find_elements_by_tag_name('option'):
    if option.text == 'Hard':
        option.click()
        break

Apparently, Bootstrap does not play with Selenium. Or whatever.


How it does works

I don't remember where I got the idea to my solution, but it's simple and obvious. It selects the dropdown menu, and then types in the text that I want to click. Then hits enter and voilá, the desired option is selected.

from selenium.webdriver.common.keys import Keys

dropdown = browser.find_element_by_id('surface')
dropdown.send_keys('Hard')
dropdown.send_keys(Keys.ENTER)

If you have a better way to select an option in a Bootstrap select field with the Selenium WebDriver, then please tell me!

serving society

Dude. I service society by rocking! I'm out there on the front lines, liberating people with my music. Rockin' ain't no walk in the park, lady!

Jack Black in "School of Rock"

Tolle Dinge in Deutschland

Im Juli waren wir auf Deutschlandbesuch. Dort sind mir natürlich viele gute Dinge aufgefallen. Gute Dinge, die es teilweise nur dort gibt, und sicher nicht in Mexiko:

  • Sauberes und leckeres Wasser direkt aus der Leitung
  • Lecker Brötchen
  • Filterkaffee
  • Lecker Bier
  • Döner Kebap
  • Stille
  • Waldwege
  • Sofortwarme Duschen
  • Lecker Brot
  • Lecker Kuchen
  • Bier auf der Straße trinken
  • Öffentliche Mülleimer
  • Zwiebelmett

Was es nicht gibt:

  • Essensstände im Park