python - 16.10.2005 - 13.1.2006

Django Paste - Ian ist starting to integrate Django with paste (and paste deploy). I for one will most definitely try to support that, so his list of related tickets is already down by one. Paste deploy might even be taken as the future default FCGI/SCGI solution - because it uses the same FLUP lib, it is as capable as my scripts, but due to the structure of Paste, installation should be much easier (and might even be standard in the future with Python hosters).

MoinMoin Release 1.5 - hui, das neue MoinMoin sieht ja richtig slick aus.

code.enthought.com - Enthought Tool Suite - recht interessant klingende GUI-Bibliothek, die auf WxPython aufsetzt und noch komfortablere Anwendungserstellung ermöglicht. Besonders interessant der Einsatz des "Traits"-Konzeptes für die automatische Erstellung von Oberflächen.

Codeville - und noch eine Versionsverwaltung, diese ist in Python geschrieben und adressiert speziell das Problem der Merge-Algorithmen.

cucumber2: an object-relational mapping system for Python and PostgreSQL - ein weiterer ORM für Python. Besonderheit hier: PostgreSQL Tabellenvererbung wird benutzt, um die Übergänge zwischen Objekten und Klassen einfacher zu gestalten. Dadurch aber auch nicht auf andere Datenbanken portierbar.

LGT: Lightweight Game Toolkit for Python - besonders interessant die NanoThreads (Coroutinen für Python), das EventNet (erweiterte Eventprogrammierung) und Gherkin (eine Alternative zu Pickle/Marshal). Zu NanoThreads und EventNet gibt es mit FibraNet jetzt auch einen erweiterten Nachfolger (der von LGT losgelöst ist).

Webstemmer - HTML-Grabber der aufgrund des Layouts den eigentlichen Kerntext von Websites extrahiert.

simple_json 1.0 - Alternative zu json.py mit weniger Macken (dafür einem Soziopathen als Programmierer - aber man kann eben nicht alles haben. In diesem Fall ist funktionierender Code jedenfalls wichtiger als freundlicher Umgangston).

Dejavu - Trac - ein weiterer ORM für Python. Dieser zeichnet sich durch absurde Klassennamen aus (Arena, Sandbox, Units ...)

appscript - Python als Alternative zu AppleScript. Also Applikations-Steuerung über die AppleScript Schnittstellen direkt aus Python Programmen heraus.

Generische Funktionen mit Python

PEAK bietet ja seit geraumer Zeit generische Funktionen ala CLOS für Python an. Ich wollte immer mal damit rumspielen, aber lange Zeit war es ja einfach nur Bestandteil von PyProtocols, und die Installation etwas haarig. Seit September diesen Jahres ist es aber ausgekoppelt und sehr viel einfacher zu installieren. Also hab ich mich mal draufgestürzt.

Und ich muss sagen: wow. Was Phillip J. Eby da geleistet hat ist wirklich fantastisch. Die Integration in Python (funktioniert ab Python 2.3 - er hat einfach eine eigene Implementierung von Dekoratoren für Python 2.3 erfunden) ist super, auch wenn natürlich das eine oder andere etwas gewöhnungsbedürftig ist.

Ein kleines Beispiel:

import dispatch

[dispatch.generic()]
def anton(a,b):
 "handle two objects"

[anton.when('isinstance(a,int) and isinstance(b,int)')]
def anton(a,b):
 return a+b

[anton.when('isinstance(a,str) and isinstance(b,str)')]
def anton(a,b):
 return a+b

[anton.when('isinstance(a,str) and isinstance(b,int)')]
def anton(a,b):
 return a*b

[anton.when('isinstance(a,int) and isinstance(b,str)')]
def anton(a,b):
 return b*a

[anton.before('True')]
def anton(a,b):
 print type(a), type(b)

Dieses kleine Beispiel liefert einfach eine Funktion namens 'anton', welche auf Basis der Parametertypen unterschiedlichen Code ausführt. Das Beispiel ist natürlich völlig sinnfrei, zeigt aber einige wichtige Eigenschaften von generischen Funktionen:

  • generische Funktionen sind - anders als klassische Objekt/Klassenmethoden - nicht an irgendwelche Klassen oder Objekte fest gebunden. Statt dessen werden sie über ihre Parametertypen ausgewählt.
  • Parametertypen müssen demnach definiert werden - im Regelfall passiert das über eine Minisprache, mit der die Bedingungen der Auswahl formuliert werden. Das ist auch der einzige syntaktische Teil der mir nicht so gut gefällt: die Bedingungen werden als String abgelegt. Allerdings ist die Integration sehr gut, man erhält saubere Syntaxfehler schon beim Laden.
  • eine generische Funktion kann mit beliebigen Bedingungen überladen werden - nicht nur der erste Parameter ist entscheidend. Bedingungen können übrigens auch auf Basis von Werten entscheidungen treffen - jeder beliebige Python-Ausdruck kann dort verwendet werden.
  • mit Methodenkombinationen (Methoden sind hier die konkreten Ausprägungen einer generischen Funktion) kann man eine Methode vor oder nach ihrem Aufruf modifizieren, ohne an den Code selber ranzukommen. Das Beispiel benutzt eine before-Methode die immer (deshalb das 'True') herangezogen wird, um Debugging-Output zu erzeugen. Natürlich kann man bei before/after Methoden jederzeit auch Bedingungen benutzen, um sich auf spezifische Ausprägungen des Aufrufs der generischen Funktion zu hängen - womit generische Funktionen ein vollwertiges Event-System sind.

Ein recht guter Artikel über RuleDispatch (das generische Funktionen Paket) gibt es bei Developerworks.

Das Beispiel zeigt übrigens die Python 2.3 Syntax für Dekoratoren. Mit Python 2.4 kann natürlich auch die @-Syntax benutzt werden. Ein Nachteil soll nicht verschwiegen werden: die Definition von generischen Funktionen und ihren Methoden ist nicht interaktiv möglich - jedenfalls nicht mit der Python 2.3 Syntax. Leider muss man da generell mit externen Definitionen in Dateien arbeiten.

RuleDispatch wird definitiv einen Platz in meinem Werkzeugkasten finden - die Syntax ist einfach genug, die Möglichkeiten hingegen sind gigantisch. Als Eventsystem schlägt es an Flexibilität jedes andere System und als generelle Möglichkeit der Strukturierung des Codes kommt es sehr nah an CLOS heran. Schade, das Django sich vermutlich auf PyDispatch ausrichten wird - RuleDispatch würde meiner Meinung nach wesentlich besser passen (da viele Aspekte in Django als Dispatch auf mehrere Parametertypen geschrieben werden könnten).

Is Rails a DSL? What is a DSL, and is it possible in Python? - Domain Specific Languages - eine recht brauchbare Beschreibung und Betrachtung der Situation in Python und Ruby.

Python Cheese Shop : python-fastcgi 1.0 - FastCGI Implementation die auf der OpenMarket FastCGI C Bibliothek aufbaut und daher deutlich schneller als reine Python-Lösungen ist.

Python OpenID 1.0.1 Released — OpenID Enabled - OpenID Client und Server in Python. Müsste ich mir mal angucken, könnte ja recht interessant für Kommentarfunktionen sein.

How-To Guide for Descriptors - eine sehr gute Erklärung, wie in Python die Properties funktionieren und was es mit den magic methods get , set und del auf sich hat (und wie getattribute da mitspielt).

jacobian.org : Django performance tips - Jacob, einer der Dango Core-Devs schreibt über Performance-Tuning für Django Applikationen. Deckt sich stark mit meinen Erfahrungen.

SystemExit und exception handlers

Immer wieder gerne genommen: SystemExit. Eine Python-Exception, die viele nicht kennen. Das besondere an dieser Exception: sie ist kein Fehler. Sie tritt auch nicht unerwartet auf. Sie wird nämlich einfach von sys.exit ausgelöst. Die Idee dahinter ist, das man so im dynamischen Ablauf eine Ende-Bearbeitung einhängen kann (z.B. irgendwelche Dateibereinigungen), ohne sich in globale Exitbearbeitung einzuklinken (mit all den Problemen die das hat).

Das Problem ist jetzt, das viele Programme und Bibliotheken einen globalen Exception-Handler installieren. Einen, der jeden Fehler abfängt und hübsch formatiert per Mail verschickt, irgendwo logged oder ähnliches. Mache ich auch ständig. Geht auch klasse - ausser wenn man in seinem Programm tatsächlich mal explizit ein vorzeitiges Ende einleiten will. Dann klappt da garnix mehr - denn man erhält entsprechende Fehler für einen Nicht-Fehler.

Besonders kritisch wird das ganze im Zusammenhang mit mehreren Prozessen. Wenn man nämlich im Laufenden Betrieb einen Prozess anstartet, will man diesen auch beenden, ohne das eventueller nachgelagerter Code ausgeführt wird. Am besten sieht man das an einem Beispielprogramm:

import signal
import os

try:
 pid = os.fork()
 if pid:
 print "Elternprozess", os.getpid()
 else:
 print "Kindprozess", os.getpid()
 sys.exit(0)
except:
 print 'Fehler aufgetreten in Prozess', os.getpid()

print "Das darf nur der Elternprozess ausführen", os.getpid()

Dieser Code hat einfach einen globalen Fehlerbehandler, der Fehler recht unspezifisch abfängt. Innerhalb des Codes wird ein paralleler Prozess mit fork gestartet. Dadurch, das SystemExit wie alle anderen Exceptions behandelt wird, wird aber der Kindprozess nicht korrekt beendet - ein Prozess kopiert den gesamten Zustand des Elternprozesses, inklusive Rücksprungadressen, offene Fehlerbehandlungen, Dateien, Datenbankverbindungen und so weiter.

Das ist natürlich fatal - denn hier wird ja sys.exit abgefangen. Es gibt also eine Fehlermeldung für den ganz normalen sys.exit(0) Aufruf. Und noch schlimmer: da SystemExit nicht extra behandelt wird, gehts danach normal weiter - und der Kindprozess rennt in Code für den Elternprozess rein. Code läuft also doppelt, was unter Umständen kritische Ergebnisse haben kann.

Wenn man den ganzen Stack an Software voll kontrollieren kann, ist die Lösung einfach:

import signal
import os

try:
 pid = os.fork()
 if pid:
 print "Elternprozess", os.getpid()
 else:
 print "Kindprozess", os.getpid()
 sys.exit(0)
except SystemExit:
 raise
except:
 print 'Fehler aufgetreten in Prozess', os.getpid()

print "Das darf nur der Elternprozess ausführen", os.getpid()

Dadurch wird einfach der SystemExit neu geworfen - also neu ausgelöst - ohne eine Meldung zu machen. Im Regelfall wird dann die Standardbehandlung von Python zuschlagen und den SystemExit in eine normale Beendigung umsetzen.

Was aber machen, wenn man mehrere gestapelte Varianten des falschen Fehlerhandlings hat? Ich hab sowas zum Beispiel bei Django und FLUP (dem FCGI/SCGI Server für Python). In Django hab ich es geändert, dann hat der Fehler im FLUP zugeschlagen. Was macht man dann?

Die Lösung ist ein wenig brutaler:

import signal
import os

try:
 pid = os.fork()
 if pid:
 print "Elternprozess", os.getpid()
 else:
 print "Kindprozess", os.getpid()
 os.kill(os.getpid(), signal.SIGTERM)
except:
 print 'Fehler aufgetreten in Prozess', os.getpid()

print "Das darf nur der Elternprozess ausführen", os.getpid()

Letzten Endes begeht der Prozess einfach Selbstmord - er schickt sich selber ein SIGTERM, also ein Beendigungssignal. Das gleich, das man normalerweise von der Shell schicken würde. Allerdings muss man dann sicherstellen, das alle eventuell nötigen Nachbereinigungen entweder schon gemacht sind, oder dann in einer SIGKILL Behandlungsroutine laufen - sonst hat man unter Umständen Problemen (z.B. sollten Datenbanktransaktionen schon commited sein).

Auch bei dieser Lösung muss man aufpassen, das nicht irgendwelche offenen Resourcen den Prozess blockieren - sonst produziert man unter Umständen Zombiprozesse. Oftmals ist es daher besser für solches Multiprozessing einen Verwaltungsprozess sehr viel früher im System zu starten - ausserhalb der Fehlerbehandlungskette - und diesen dann zu benutzen um Bearbeitungsprozesse zu starten. Allerdings hat das dann den Nachteil, das diese solcherart gestarteten Prozesse nicht die Umgebung des Elternprozess erben. Man muss daher dann in der Regel mehr Vorbereitungen treffen, um die gewünschten Aktionen auszuführen. Einen ähnlichen Ansatz verfolgt übrigens Apache - dort werden die Prozesse aus einem sehr frühen Basiszustand heraus erzeugt, so das sie möglichst Resourcenfrei daherkommen.

Vampire - Erweiterung von mod_python, mit dem es etwas Entwicklerfreundlicher wird. Zum Beispiel kann es dann auch automatischen Code-Reload.

Commentary - Postit-Kommentare für Webseiten, ausgeführt als WSGI Middleware. Sehr interessant, könnte vor allem für Sourceviews oder ähnliches interessant sein, oder für längere Texte.

pyinotify - sehr schön, endlich ein brauchbarer Wrapper für die notify-Funktion in Linux. Damit können Python-Programme sich über Änderungen an Dateisystemen informieren lassen - ideal für Verzeichnismonitoring.

akismet.py - Python-Interface für den (zentralen) Akismet Spam Scanner.

Louie - ein neues Event-Dispatching-Modul für Python. Baut auf PyDispatcher auf.

SQLAlchemy README - ein weiterer ORM für Python, orientiert sich stark an SQL und bietet einiges an magischer Syntax. Faszinierend, wie gerade in diesem Bereich die Programmierer jedes Sprachfeature versuchen zu missbrauchen nur um nicht SQL schreiben zu müssen ...

Mal wieder was von der Bastelfront

Content-type: matter-transport/sentient-life-form - für die, die mal schnuppern wollen, wo es mit meinem Blog hingehen wird. Noch nicht ganz fertig, einige Bugs in meiner Software, ein paar Sachen warten auf Patches in Django, aber im grossen und ganzen bin ich schon ganz zufrieden.

Another OPML server...

Phil Pearson does it again - diesmal hat er den Community-Server für den OPML-Editor von Dave Winer in Python nachprogrammiert (damals hatte er ja den Radio Community Server nachgebaut, ein Projekt an dem ich auch zweitweilig beteiligt war). Jedenfalls kann man jetzt also auch seinen OPML-Editor auf die eigene Linux-Kiste veröffentlichen lassen, wenn man dort Python und SCGI zur Verfügung hat.

JobControl - Django Projects - Trac - ein einfaches Jobsteuerungssystem für Django, mit dem man Hintergrundjobs einstellen kann.

Weird Python 2.3 Bug

Also wirklich, manche Bugs die man jagt sind wirklich strange. Guckt euch einfach mal folgendes Python Script an:


 import re

r = re.compile('^', re.M)

src = '''<html> <head> <title>Logviewer</title> </head> <body> <div> <h1>Titel</h1> </div> <div> {{}}
 {% block content %}
 {% endblock %}
 </div> </body> </html> '''

for match in r.finditer(src):
 print match.start()

Sieht ja ganz harmlos aus - liefert einfach nur die Positionen der Newlines (ja, ich weiss, das macht man anders - der Source ist nicht von mir). Das Script hat unter Python 2.3 eine Endlosschleife auf dem letzten, abschließenden Newline. Nimmt man das raus (also pappt das """ direkt hinter das letzte Tag ohne Zeilenumbruch) funktioniert das Script. Unter Python 2.4 funktionieren beide Varianten. Und hinter sowas muss man dann herjagen ...

Ich brauch ja nicht extra zu betonen, das dieser kleine Schnipsel Code in einem grösseren Berg von Code versteckt war, oder?

Closures python,scheme,ruby - eine gute Erläuterung der etwas defekten Lookups für lexikalische Variablen in Python (jedenfalls wenn eine Zuweisung in einem Inner Scope beteiligt ist).

Routes 1.0 Released - das ist die Python-Version der URL-Routen aus Ruby-on-Rails. Sehr interessant, ich muss mich irgendwann mal dransetzen und gucken ob ich das nicht in Django als alternativen URL-Dispatcher einbauen kann.

Dejavu - Trac - ein weiterer Object-Relational-Mapper für Python. Klingt aber in Punkten ganz interessant.

Manches ärgert mich fürchterlich

Zum Beispiel, wenn Umlaute nicht sauber verarbeitet werden - wie bei dem pre_populate_from bei Django. Daher benutze ich das einfach nicht mehr in meinem CMSProject, sondern fülle den Slug einfach im _pre_save. Und lasse dann dort eine entsprechende Routine laufen. Wobei auch diese nicht wirklich perfekt ist, aber immerhin brauchbar ...

Und ja, das hier ist ein Testbeitrag für die Funktion um aus einem Titel mit Umlauten einen Slug zu machen.

sql relay ist ein SQL connection pool der verschiedenste Datenbanken bedienen kann und die Verbindungen von Clients zur Datenbank über einen zentralen Pool abwickelt. Ideal in Multi-Host-Umgebungen und wenn die Connecton-Last zu hoch ist (z.B. erzeugt Django pro Request eine Connection).

coverage ist ein Tool zur Erstellung von Coverage-Übersichten - also welche Teile eines Programms ausgeführt wurden und welche nicht. Sinnvoll als Ergänzung für unittests, damit man sicher ist, das die unittests auch alle Bereiche des Codes abdecken.

A Test Framework for Django

DjangoTesting is part of my DjangoStuff project and is the start of a testing framework for Django, modeled after the testing framework that Ruby on Rails provides. Currently only model tests are implemented, request/response tests are planned.

The testing framework is built solely on unittest and django, so you don't need additional modules (besides my DjangoStuff project, of course). It provides python-based fixture notations (fixtures are just python classes with attributes in a DATA subclass) and a basic command line utility to make use of those tests and fixtures.

Tests and fixtures are stored in applications and projects, so you can have application specific tests (especially usefull with generic applications) and project-level tests that will integrate stuff over several applications.

I think a good testing framework would really be important for Django applications, especially for applications that should be shared between projects. But I do think that a good testing framework needs some banging on, too - so I started it as a small subproject on my own. But if it grows into something useful, I will opt for inclusion into Django trunk.

Case/When/Otherwise for Django

If you have any evil plans for a switch statement for Django (hia rjwittams! ), you might want to look into my TagLib. There is a case/when/otherwise statement in there. It's quite easy to use:

{% case variable %}
{% when "value1" %}
{% endwhen %}
{% when "value2" %}
{% endwhen %}
{% otherwise %}
{% endotherwise %}
{% endcase %}

The reason for the tag structure is that the django template parser only looks for parameterless block-closing tags in the parsefor function and so you can't just pull an easy one like this:

{% if condition %}
{% elif condition %}
{% else %}
{% endif %}

You would have to copy over much from the template parser to get a parsefor that looks for a token with a tag and parameters to close the current block.

So I opted for the scoped tags approach where the "case" tag only sets up a context variable "case" and populates it with a dictionary with "value" and "fired" - with the latter one a trigger that can be fired by any "when" tag to prevent other "when" tags or the "otherwise" tag to fire themselves. A bit ugly, but working.

Adhoc-Organization in CM-Systems

Adhoc organization is what I named the basic design decisions for my new content management system (blog system, personal wiki, digital image shoebox - whatever). It's coming along nicely, even though up to now I only used it as a sample application to make use of my little tools from the DjangoStuff pseudo-project. And it still is one of the best ways to see how tagging or searching or the new calendar tag or other stuff is used.

But it's coming along so good that I think I will be able to change over some sites in the near future. The basic design decisions are somewhat documented in the linked document in my trac-wiki. The main objective for me is to get something that I can use as easy for image presentation as for text presentation and that allows me to really integrate both parts. So that articles really can consist of a multitude of media and text.

It's quite fun to work on a project where you tear down the model and rebuild part of it from time to time, or make major refactoring decisions that leave you with a broken heap of python-bullshit for a while

cucumber2 ist ein sehr interessanter Object-Relational-Mapper für Python und PostgreSQL, der unter anderem auch die Tabellenvererbung in PostgreSQL unterstützt.

Django Project - ein sehr nettes Webframework, welches ich bei mir hier einsetze.

"Fitting on" some framework

How do you know wether a framework fits your style of thinking? It's not as if you could just look into a mirror wether it suits you nicely, you need other ways to decide that. One way to decide it is productivity - how fast you get your project up and running.

But does that really tell you the whole story? What if the project would have been something completely different? Did you just hit the sweet spot of the framework? Where you just lucky?

One way to decide wether some framework, language or tool fits my style of working for me is to look at the basic abstractions this tool gives me. And to look how I can use them and how naturally they fit my thinking - do I stumble on problems, not immediately knowing what abstraction to use, what tool to pull? Or do things just fall in place?

I discovered quite early on that I am a bit uncommon in programming, in that I don't build my own abstractions and try to translate from them into what the language or framework gives me, but that I start to think directly in the abstractions and syntaxes given to me - but only if they match my way.

So that's for me the ultimate measurement of wether a framework really fits into my thinking: checking from time to time wether I try to do translations or wether stuff just flows. Reaching "the flow" is what it's all about for me nowadays.

So how does Django match up? Quite nicely. It really gives me what I need in most cases, there are only very few areas where "the flow" is broken, where I need to think around problems, start to do translations. One area is special behaviour of entry fields - this curently is done in Django with parameterized instances of predefined field classes. There is no really nice way to do subclassing, you end up copying code from other parts of the django source - definitely breaking "the flow".

But most other parts just fall into place: middleware for global management of the request-response span. Template loaders for - well - template loading (yes, it's not a big deal - but being able to write your own template loader really is helpfull). The urlpatterns -hey, that's really a cool idea, because of it's absolutely loose couplying you don't even try to model your urls after your code structure, but tend to design them. And that's how it should be.

Models just powerfull enough to really move the model-related functionality there (although the class MODULE stuff will make it even nicer, especially the kind of ugly module_globals thingy). It would be cool if model classes would support mixin classes, so that abstract apps could provide stuff that just would be referenced by users to add functionality. But you can solve many of those problems with generated classes - thanks to python introspection (although you need to know a bit about djangos model-magic).

Most complex stuff tends to go into template tags and generic views - my CMS project currently only has 3 view functions of it's own, the rest is abstracted away into generic views (for searching and tagging). Template tags could be a bit easier to write, especially the parser is too primitive - a library of helper functions for easy deconstructing the tag string would be good (hey, maybe I write one, the basics arealready in my SVN repository).

Template filters are a big of an ugly duckling - they don't see the request context, so they can't do much more than just take the incoming object and some constant parameters. I think they should get the context passed in, so that they could be a bit smarter, if needed (like allowing filters to resolve a parameter against the context).

Generic views are quite nice, too - even though I don't use the predefined ones that often. The main reason is that more often than not I end up in wrapping the generic views in some code that modifies their behaviour - and then it's quite often simpler to just roll my own. But they are great for first starts into areas, just tack them into your project and funcitonality is available. You can allways exchange them with your own view functions if you discover that you need to.

And the admin, the one thing that makes Django stand out in the crowd? In my first play-projects I loved it, in later ones I didn't use it (the Gallery doesn't need it), but with the CMS project I did the first one that makes really heavy use of it. And I have to say, I like it. It should get a bit more flexibility (the new_admin branch might help there, as it moves more stuff into templates, so they can be overridden), but overall it's really cool and usefull.

Two things, though, are definitely needed for the admin: full transaction support bound to request-response (ticket #9 in the django trac), because changing stuff and ending up with inconsistent tables is no fun. Like getting an exception because something broke in repr , so the log entry isn't written, but the object is written. Of course you don't notice it, go back, send again, end up with two objects and still no log message ...

The other thing that is needed: basic hooks for object-based authentication. Not a full blown ACL or anything like that, just some really simple hooks from the admin to the model that the user can define to tell the admin wether some object should be editable or should only be shown readonly. The main problem with the current solution is, it only handles full tables - you can't even tell the admin that some user can only work on the current site and can't change objects of other sites (my CMS project makes heavy use of the multi-site capability in Django - one admin server should manage multiple sites in one admin interface).

But all in all webapp building with Django is real fun. It's not only productive to me, it just feels natural to do things the Django way. So, yes, Django fits my thinking style. Seems to have hit home right on.

Markdown for Django

Django already includes a markdown filter (in contrib.markup), but I nonetheless rolled my own Markdown for Django mini-app. The main benefits are link integration with django models (by using generic model queries and get absolute url), a documentation generic view that handles language switching and a nice macro facility for markdown. Macros are a usefull way to extend markdown by writing Django template snippets that are called whenever the users calls the makro in his markdown source.

It was formerly part of the CMS project, but I think it's usefull in it's own and so much better put into the stuff pseudo-project.

Twisted Buch ist raus

Wer sein Hirn nicht so ohne weiteres in die verdrehte Welt von Twisted quetschen kann, dem hilft vielleicht Twisted Network Programming Essentials - ein neues Buch zu der wohl mächtigsten Internet-Protokoll-Plattfor für Python.

akaDAV - Lightweight WebDAV server and python module ist ein WebDAV Modul für Twisted. Damit kann man sich seinen eigenen WebDAV Server basteln. Könnte nütlich für mich sein, weil ich dann das Teil unter Userrechten laufen lassen kann, statt unter den Rechten des Webservers ...

python webdav server ist noch ein WebDAV Server für Python - seit 2000 nicht mehr aktualisiert, aber wenns funktioniert, könnte es reichen. Vielleicht verständlicher als Twisted-Code.

generic search service for Django

If your Django application needs searching capabilities, you can roll your own. Or you can use my generic search view. This provides a parser for queries and a search machinery that is suiteable for moderate database sizes. It provides an extensible google-like syntax.

The main problem is that django doesn't support OR query combinations and that it doesn't support "icontainsnot" queries. So the search engine does multiple selects to get one query. It starts with the longest search word and goes down in size from that result set, restricting it from one step to the next. But since it needs to keep the last result set in memory (at least the list of IDs), if your database contains too much rows, this might pose problems to your server (especially if the users do silly queries that produce large resultsets).

Maybe in future this will learn some optimizations to make it work better with larger databases, but it's quite fine as a search engine for your blog or standard content management systems.

very simple view functions

Sometimes you have a bunch of really simple view functions in your django project (yes, this is for your, bitprophet! ). View functions that are actually not more than just a render to response call - take a template, take some data from the request, stuff them in and render a response. It's rather boring to write them down and it breaks the DRY principle. So what to do? Write your own generic view.

from django.core.extensions \
 import render_to_response

def simple_view(request, template, **kwargs):
 return render_to_response(
 template, kwargs)

That's all. A simple and nice view function that just does that - render a template. It even can be fed with context variables from the urlpattern. Use it like this in your urlconf:

urlpatterns = patterns('',
(r'^page/(?P<arg>.*)/$', 'cool.simple_view',
 {'template': 'app/mytemplate'}),
)

That way a /page/foo/ view would be routed to the 'app/mytemplate' template with a context that just includes the variable 'arg' with the value 'foo'. And you never will need to write those simple_view functions again. For extra spices you could throw in a context_instance = DjangoContext(request) into the render to response call to even get the authenticated user and stuff like that from the request.

Module Hacking for Django

Django itself constructs model modules dynamically from your model classes. That's what I used in my first take at the abstract tagging application. Now I found a better way in the current version - I can modify the dynamic module myself quite easily, generate a dynamic model class and push that into the model module. What it actually does is just mimicking what happens when Python defines a class - most stuff is done by the meta.ModelBase metaclass in Django, anyway. I only had to add some module hacking stuff. Python introspection rules!

What this gives you is a much cleaner interface to create the tagrelation class for your model - just a function call, no silly subclassing or superfluous assignment. Everything happens as by magic.

It is magic.

Twisted Names muss ich mir mal angucken - ein DNS server in Python auf Twisted-Basis. Könnte ich ja auf DB-Benutzung umstricken, als Alternative zum PowerDNS.

Tagging with Django

Since the question about how to do tagging with Django shows up quite often, I have written a small solution to this problem: AbstractTagging. This is a generic application and generic views that give you a very simple solution to add tagging to any model you have in your django apps. It's currently used by me in my CMS project. The source is in the stuff project.

It was a bit weird to build, because I had to dynamically construct a base class you can subclass in your models - this is because of the magic in django.core.meta, where model classes are turned into modules. But the result is quite nice, I think.

call of the noodle

Da schreibt einer an einem Lisp-Compiler für Python-Bytecode - sehr interessant, da man damit die Python Libraries unter einem Lisp-Dialekt benutzen könnte. Mal schauen wenn der erste Release kommt, wie der Lisp-Dialekt aussehen wird und was für Features er abdecken wird. Mit Unterstützung für Lisp-Makros wäre es sehr interessant.

Using Django as a CMS

I am currently reworking one of my sites - Content-type: matter-transport/sentient-life-form. It was a Apache::MiniWiki based site before and is now in the transition to being a Django based site. The idea of the code for that site is to build a CMS based on Django that fully uses the Django admin. So the users should be able to do all management only in the admin, while the site itself behaves a bit like a Wiki. Autolinking, Autoediting of missing pages, Editlinks, Versioning (currently missing in the source) - all that should be done based on tools the Django admin provides.

This isn't for a full-blown site, though - the linked site is allmost empty, I never put much up there. It's more a project to dig deeper into the Django admin to see what it's like to work in it - so I know about that stuff when I start to build real projects.

The code itself is freely available - and there is already a nice thing in it. It's a template loader who pulls stuff from the database instead from the filesystem or from python eggs. It's "ticketed" at Django under #633, so it might make it into django.contrib some day.