Ziel ist es, a) in einem Modul oder Packet mehr als eine Bottle Applikationen verwalten zu können und b) mehrere Bottle Apps konfliktfrei in einem Serverprozess laufen zu lassen.
Punkt a) habe ich schon seit einiger Zeit vorbereitet. app() oder default_app() kennt ihr ja. Diese Funktion liefert ein WSGI-Funktionsobjekt zurück.
In Wirklichkeit ist app() allerdings ein Stack, der mehrere Bottle() Instanzen halten kann und der Rückgabewert ist der jeweils oberste Eintrag auf dem Stack. Mit app.push() und app.pop() kann man den Stack manipulieren.
Eine Bottle() Instanz dient übrigens nicht nur als WSGI Schnittstelle, sondern hat z.B. auch sämtliche Routen in sich gespeichert.
Es ist also jetzt schon möglich, die ganzen Aufrufe von @route() in eine separate Bottle Applikation um zu leiten, da @route(), genau wie die meisten anderen Module-Level Funktionen, intern auf app() zurück greift um die jeweils aktuelle Bottle() Instanz zu bekommen. Man kann also Module schreiben, die App-Objekte erzeugen, ohne mit anderen Modulen in Konflikt zu treten.
Code: Alles auswählen
from bottle import route, app
app.push()
@route('/')
def index()
return 'MyApp'
myapp = app.pop()
Punkt b) ist etwas schwieriger. Ich erzähle einfach mal, was mir vor schwebt:
Die neue Funktion bottle.mount(app, path) soll ermöglichen, eine separate Bottle Applikation (eventuell auch eine normale WSGI app) unter einem bestimmten Pfad einzubinden.
Code: Alles auswählen
bottle.mount(admin_app, '/admin')
Die Funktion bottle.merge(newapp, path) funktioniert ähnlich, nur dass die beiden Module miteinander verschmolzen werden. Alle Routen von newapp werden so verändert, das sie mit dem neuen Pfad beginnen. Dieser kann auch leer sein, was die beiden Apps komplett vermixen würde. PATH_INFO oder SCRIPT_PATH werden dabei nicht verändert. So ein Merge ist später schneller, da nur ein Router verwendet wird, allerdings auch nicht mehr rückgängig zu machen, wohingegen Mounts auch dynamisch wieder ausgehängt werden können.
Beide Funktionen könne außerdem einen Modulnamen als String im ersten Parameter verarbeiten. Dann wird mit app.push() und app.pop() gearbeitet und das benannte Modul mit __import__ geladen.
Soweit der Plan. Gibt es Szenarien, die damit nicht lösbar sind? Habt ihr andere Vorschläge oder Ideen?