diff --git a/controllers/demo/due.py b/controllers/demo/due.py index 6652729..993fc44 100644 --- a/controllers/demo/due.py +++ b/controllers/demo/due.py @@ -3,12 +3,12 @@ from decorators import WSGITemplate # decoratore ( singleton ) -wsgit = WSGITemplate() +wsgitmpl = WSGITemplate() # # esempio minimo di controller WSGI # -@wsgit.template( 'template1.tmpl' ) +@wsgitmpl.template( 'template1.tmpl' ) def application( environ, start_response ): from pprint import pformat diff --git a/controllers/demo/sql.py b/controllers/demo/sql.py new file mode 100644 index 0000000..5eabd67 --- /dev/null +++ b/controllers/demo/sql.py @@ -0,0 +1,50 @@ +#!/usr/bin/python +# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*- + +from decorators import WSGIMySQL # decoratore ( singleton ) + +wsgisql = WSGIMySQL() + +# +# esempio minimo di controller WSGI +# +@wsgisql.db( 'mywiki', 'shoot' ) +def application( environ, start_response ): + + cur = environ['mysql.mywiki.cur'] + + # + # esecuzione query + # + cur.execute( 'SHOW tables;' ) + + # + # recupero record e generazione html + # + + start_response( '200 OK', [('content-type', 'text/html; charset=utf-8')] ) + + yield "

elenco tabelle presenti nel db mywiki

" + + for record in cur.fetchall(): + yield str( record ) + "
" + + # + # recupero secondo cursore + # + + cur2 = environ['mysql.shoot.cur'] + + # + # esecuzione query + # + cur2.execute( 'SHOW tables;' ) + + # + # recupero record e generazione html + # + + yield "

elenco tabelle presenti nel db shoot

" + + for record in cur2.fetchall(): + yield str( record ) + "
" diff --git a/decorators.py b/decorators.py index 866934c..d2294b4 100644 --- a/decorators.py +++ b/decorators.py @@ -36,41 +36,82 @@ class WSGIMySQL( object ): __metaclass__ = Singleton def __init__( self, dsn, *args ): + """ inizializza le connessioni a 1 o più database. + In caso di connessioni a databese multipli, + le connessioni sono identificate tramite ALIAS + o in mancanza di questo tramite DB + + ogni singolo dsn deve essere un dizionario con le chiavi: + - DB : nome del database + - HOST : host a cui connettersi + - USER : username da utilizzare per connettersi + - PASSWORD : password da utilizzare per connettersi + - ALIAS : (opzionale) identificativo della connessione + """ import MySQLdb - self.__dsn = dsn - self.__pool = [ self.__newconn() ] + # + # aggiungiamo il primo dsn in cima alla lista + # + args = list( args ) + args.insert( 0, dsn ) + + # + # creiamo il nostro dizionario di dizionari + # + self.__dsn = { dsndict.get( 'ALIAS', dsndict['DB'] ):dsndict for dsndict in args } + + # + # verifichiamo che non ci siano alias duplicati + # + if len( self.__dsn.keys() ) != len( args ): + raise Exception( "WSGIMySQL :: conflicting alias in dsn list" ) + + # + # tentiamo di creare la prima connessione verso TUTTI i dsn passati + # + + for alias, dsndict in self.__dsn.iteritems(): + dsndict['pool'] = [ self.__newconn( alias ) ] + self.__dict_cursor = MySQLdb.cursors.DictCursor - def __newconn( self ): + def __newconn( self, alias ): import MySQLdb return MySQLdb.connect( - host = self.__dsn["HOST"], - user = self.__dsn["USER"], - passwd = self.__dsn["PASSWORD"], - db = self.__dsn["DB"] + host = self.__dsn[ alias ]["HOST"], + user = self.__dsn[ alias ]["USER"], + passwd = self.__dsn[ alias ]["PASSWORD"], + db = self.__dsn[ alias ]["DB"] ) def db( self, *args ): def real_decorator( wsgi_application ): def wrapper( environ, start_response ): - try: - conn = self.__pool.pop( 0 ) - except IndexError: - conn = self.__newconn() + connections = [] + + for arg in args: + try: + conn = self.__dsn[ arg ]['pool'].pop( 0 ) + except IndexError: + conn = self.__newconn( arg ) + + connections.append( conn ) - cur = conn.cursor( self.__dict_cursor ) + cur = conn.cursor( self.__dict_cursor ) - environ['mysql.cur'] = cur + environ['mysql.' + arg + '.cur'] = cur try: for item in wsgi_application( environ, start_response ): yield item finally: - conn.commit() - self.__pool.append( conn ) + for arg in args: + conn = connections.pop(0) + conn.commit() + self.__dsn[ arg ]['pool'].append( conn ) return wrapper @@ -78,5 +119,9 @@ class WSGIMySQL( object ): def __del__( self ): - for conn in self.__pool: - conn.close() + # + # chiudiamo tutte le connessioni attualmente aperte + # + for dsndict in self.__dsn.items(): + for conn in dsndict['pool']: + conn.close() diff --git a/dispatch_wsgi.py b/dispatch_wsgi.py index fee191b..0681f63 100755 --- a/dispatch_wsgi.py +++ b/dispatch_wsgi.py @@ -21,12 +21,19 @@ WSGITemplate( basedir='views' ) # from decorators import WSGIMySQL WSGIMySQL( - dsn = dict( + dict( DB = "mywiki", HOST = "localhost", USER = "corso", PASSWORD = "pwdcorso" - ) + ), + dict( + DB = "shootout", + HOST = "localhost", + USER = "root", + PASSWORD = "server", + ALIAS = "shoot" + ), )