R: [Irgendwas über Mozart und Wien]. Mozart wohnte doch mal in Wien?

D: Zumindest behauptet Falco das.

R: Wer ist Falco?

D: Das ist dieser Sänger? Der »Rock Me Amadeus« gesungen hat? Falco? Der Österreicher? Falco? Der King of Pop? Falco?

R: Der mit der Sonnenbrille und der roten Jacke?

D: DAS IST HEINO. WAS IST FALSCH MIT DIR.

Widowfix Filter for Jinja2

So, if you are anything like me (or Max), you hate it when the last word of a paragraph is on its own. Mostly, you don’t really have a choice. But with the following Flask snippet, you do!

It doesn’t really matter where you put it. In most cases, I’ll have a utils.py file which contains these kind of things, but because you directly register the filter with the app object, the location is not important.

from yourapp.app import app
from jinja2 import Markup

def widowfix(value):
    value = escape(value)
    splitted = value.rsplit(' ', 1)
    return Markup(' '.join(splitted))

app.jinja_env.filters['widowfix'] = widowfix

What exactly happens here?

In the first line, we import our app. This is simple.

Then, we import Markup. It takes a string as a parameter and returns a Markup object that will be treated as “safe” by Jinja. This is important, because we don’t want the   to be escaped.

We create the widowfix function. It takes a value, escapes it, splits it at the last space and puts it back together, with a   as the glue.

Finally, we register that function as a new Jinja filter with the name widowfix.

To use it in your templates, simply write

{{ my_text|widowfix }}

The last space in the string will be replaced by a non-breaking space, so the last two words will always be right next to each other. No more widows!

Update

I got a tumblr message reminding me that it may be unsafe to just not escape the whole variable. (S/he actually called it “a security nightmare”. I don’t know about that, but at least it’s dramatic.)

Yes, you probably want to escape the variable before adding the &nbsp, so I added value = escape(value) to the function. Thanks, anon!

Aktuelles Python und zumindest akzeptables SQLite auf Uberspace verwenden

Ist das hier jetzt ein Programmierblog? Unfollow!

Die Arbeit an der neuen Lesetagebuch-Version geht gut voran. Ich habe eine Volltextsuche eingebaut (endlich!) und nutze dafür die coolen FTS3/4-Funktionen, die SQLite mitliefert und für die Peewee gute Anbindungen bietet.

Gestern Abend dachte ich, dass ich den bisherigen Code mal auf dem Uberspace, auf dem auch das aktuelle Lesetagebuch läuft, installieren sollte, damit ich sehen kann, ob das so klappt, und damit ich ein paar Testlinks an Freunde rausschicken kann.

Uberspace ist hervorragend, aber nicht immer cutting edge. Das ist okay, da sie sich ja nicht den ganzen Tag mit Updates und damit verbundenen Problemen rumschlagen wollen. Aber ich hätte halt schon gerne Python 3.4, und nicht nur 3.3. (Ich habe nicht mal einen guten Grund! Einfach aus Prinzip!)

Glücklicherweise geht das. Man kompiliert einfach alles selbst! Yolo!

(Die Anleitung folgt am Ende des Artikels, denn dann müsst ihr es nicht, wie ich, zweimal machen.)

Das Lesetagebuch lief dann auch irgendwann, und ich versuchte, etwas zu suchen. Dabei reichte mir Peewee einen SQLite-Error durch (Die Funktion matchinfo() konnte nicht gefunden werden), der daher rührte, dass die Standard-SQLite-Version bei Uberspace 3.6.20 ist, und diese Funktion tatsächlich einfach nicht mitbringt.

Das Uberspace-Wiki versteckt auf der Seite über Ruby die Information, dass in /package/host/localhost/sqlite-3 eine neuere Version bereitgestellt wird. (Und zwar 3.7.15.2. Immerhin!) Yay!

Ein paar Stunden googlen später fand ich bei StackOverflow (wo sonst!) die Informationen, die ich gesucht hatte: Wie man Python sagt, welches SQLite verwendet werden soll.

Dafür muss man zum Glück nur vier Environment-Variablen setzen:

$: export PATH=/package/host/localhost/sqlite-3.7.15.2/bin:$PATH
$: export LDFLAGS='-L/package/host/localhost/sqlite-3.7.15.2/lib'
$: export CPPFLAGS='-I/package/host/localhost/sqlite-3.7.15.2/include'
$: export LD_LIBRARY_PATH=/package/host/localhost/sqlite-3.7.15.2/lib:$LD_LIBRARY_PATH

Damit sagt ihr dem Python, das ihr gleich installieren werdet, wo es zuerst nach Libraries schauen soll, die es benutzt (zumindest, soweit ich das verstanden habe). Dadurch findet es zuerst die neue SQLite-Installation.

Jetzt zum eigentlichen Spaß: Python installieren. Sucht auf der Downloadseite für den Python-Sourcecode nach dem Release, das ihr haben wollt (im folgenden 3.4.1).

Dann laden wir das mal runter, entpacken es, gehen in den Ordner, werfen die Konfiguration an, kompilieren und installieren es:

$: wget https://www.python.org/ftp/python/3.4.1/Python-3.4.1.tgz
$: tar -xzf Python-3.4.1.tgz
$: cd Python-3.4.1
$: ./configure --prefix=/home/lstgbch (warten)
$: make (lange warten)
$: make install

Das --prefix=/home/lstgbch ist wichtig, damit es nicht versucht, Python global zu installieren (was im Uberspace natürlich nicht geht), sondern in euer Homeverzeichnis rein.

Jetzt könnt ihr python3.4 in die Befehlszeile eingeben, und dann kurz in der Python-Shell testen, ob alles so ist, wie wir es haben wollen:

Python 3.4.1 (default, Jul 22 2014, 16:37:47)
> > > import sqlite3
> > > sqlite3.sqlite_version
'3.7.15.2'

Falls eure Ausgabe nicht 3.7.15.2 sagt, hat irgendwas nicht geklappt. Versucht es einfach noch ein paarmal, ich habe Python bestimmt sechsmal kompiliert, bis es geklappt hat. Diese Anleitung ist insofern auch vor allem für mich selbst, damit ich beim nächsten Mal ein bisschen schneller bin.

Update

Okay, scheinbar sind die Informationen oben nicht absolut korrekt. Ich bin nicht mal mehr sicher, ob es wirklich einen Unterschied macht, dass man die LDFLAGS und die CPPFLAGS setzt. Denn, wie gesagt, das tat ich, und gerade startete ich eine neue Session und Python wollte wieder das alte SQLite benutzen.

Was ich jetzt aber weiß: Es reicht scheinbar aus, den LD_LIBRARY_PATH so zu setzen, wie oben beschrieben. (Ich bin nicht sicher, ob das nur funktioniert, wenn Python wie beschrieben kompiliert wurde, oder ob es allgemein funktionieren würde.)

Jedenfalls solltet ihr das, der Einfachheit halber, in eure .bash_profile packen:

$: export PATH=/package/host/localhost/sqlite-3.7.15.2/bin:$PATH:$HOME/bin
$: export LD_LIBRARY_PATH=/package/host/localhost/sqlite-3.7.15.2/lib:$LD_LIBRARY_PATH

Zusammen Verschwinden (Karpatenhund-Cover)

Eigentlich wollte ich nur ein bisschen Gitarre spielen, bevor ich ins Bett gehe, aber jetzt ist es zwei Uhr Nachts und ich habe plötzlich dieses Cover rumliegen.