您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 

171 行
5.4 KiB

  1. #!/usr/bin/python
  2. # -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
  3. ## all
  4. from singleton import Singleton
  5. ## WSGITemplate
  6. from template import render
  7. from functools import partial
  8. ## WSGIAuth
  9. import Cookie
  10. import hashlib
  11. import hmac
  12. md5 = lambda x : hashlib.md5( x ).hexdigest()
  13. sha1 = lambda key,value: hmac.new( key, value, hashlib.sha1 ).hexdigest()
  14. #------------------------------------------------------------------------------
  15. class WSGITemplate( object ):
  16. __metaclass__ = Singleton
  17. def __init__( self, basedir='' ):
  18. import os
  19. self.__basedir = os.path.normpath( os.path.join( os.path.split(__file__)[0], basedir ) ) + '/'
  20. self.__fallback_template = \
  21. "<h1> NO TEMPLATE DEFINED </h1>\n" \
  22. "{{ from pprint import pformat }}" \
  23. "<pre>{{ = pformat( { k:v for k,v in locals().iteritems() if k not in ('NOESCAPE','__builtins__','pformat','response') }, width=132 ) }}</pre>\n\n"
  24. def template( self, filename=None ):
  25. def real_decorator( wsgi_application ):
  26. def wrapper( environ, start_response ):
  27. if filename:
  28. environ[ 'template' ] = partial( render, filename=self.__basedir + filename )
  29. else:
  30. environ[ 'template' ] = partial( render, content=self.__fallback_template )
  31. return wsgi_application( environ, start_response )
  32. return wrapper
  33. return real_decorator
  34. class WSGIMySQL( object ):
  35. __metaclass__ = Singleton
  36. def __init__( self, dsn, *args ):
  37. """ inizializza le connessioni a 1 o più database.
  38. In caso di connessioni a databese multipli,
  39. le connessioni sono identificate tramite ALIAS
  40. o in mancanza di questo tramite DB
  41. ogni singolo dsn deve essere un dizionario con le chiavi:
  42. - DB : nome del database
  43. - HOST : host a cui connettersi
  44. - USER : username da utilizzare per connettersi
  45. - PASSWORD : password da utilizzare per connettersi
  46. - ALIAS : (opzionale) identificativo della connessione
  47. """
  48. import MySQLdb
  49. #
  50. # aggiungiamo il primo dsn in cima alla lista
  51. #
  52. args = list( args )
  53. args.insert( 0, dsn )
  54. #
  55. # creiamo il nostro dizionario di dizionari
  56. #
  57. self.__dsn = { dsndict.get( 'ALIAS', dsndict['DB'] ):dsndict for dsndict in args }
  58. #
  59. # verifichiamo che non ci siano alias duplicati
  60. #
  61. if len( self.__dsn.keys() ) != len( args ):
  62. raise Exception( "WSGIMySQL :: conflicting alias in dsn list" )
  63. #
  64. # tentiamo di creare la prima connessione verso TUTTI i dsn passati
  65. #
  66. for alias, dsndict in self.__dsn.iteritems():
  67. dsndict['pool'] = [ self.__newconn( alias ) ]
  68. self.__dict_cursor = MySQLdb.cursors.DictCursor
  69. def __newconn( self, alias ):
  70. import MySQLdb
  71. return MySQLdb.connect(
  72. host = self.__dsn[ alias ]["HOST"],
  73. user = self.__dsn[ alias ]["USER"],
  74. passwd = self.__dsn[ alias ]["PASSWORD"],
  75. db = self.__dsn[ alias ]["DB"]
  76. )
  77. def db( self, *args ):
  78. def real_decorator( wsgi_application ):
  79. def wrapper( environ, start_response ):
  80. connections = []
  81. for arg in args:
  82. try:
  83. conn = self.__dsn[ arg ]['pool'].pop( 0 )
  84. except IndexError:
  85. conn = self.__newconn( arg )
  86. connections.append( conn )
  87. cur = conn.cursor( self.__dict_cursor )
  88. environ['mysql.' + arg + '.cur'] = cur
  89. try:
  90. for item in wsgi_application( environ, start_response ):
  91. yield item
  92. finally:
  93. for arg in args:
  94. conn = connections.pop(0)
  95. conn.commit()
  96. self.__dsn[ arg ]['pool'].append( conn )
  97. return wrapper
  98. return real_decorator
  99. def __del__( self ):
  100. #
  101. # chiudiamo tutte le connessioni attualmente aperte
  102. #
  103. for dsndict in self.__dsn.items():
  104. for conn in dsndict['pool']:
  105. conn.close()
  106. class WSGISimpleAuth( object ):
  107. __metaclass__ = Singleton
  108. def __init__( self, secret_key, login_url=None, forbidden_url=None ):
  109. self.__secret_key = secret_key
  110. def auth( self, permission='', group='', p_g_mode='AND', p_mode='OR', g_mode='OR' ):
  111. def real_decorator( wsgi_application ):
  112. def wrapper( environ, start_response ):
  113. try:
  114. uuid = Cookie.SimpleCookie(environ["HTTP_COOKIE"])["uuid"].value
  115. except:
  116. uuid = None
  117. environ['auth.uuid'] = uuid
  118. def my_start_response( status, response_headers ):
  119. cookie = Cookie.SimpleCookie()
  120. cookie["uuid"] = uuid
  121. response_headers.append( ('Set-Cookie',cookie.OutputString()) )
  122. start_response( status, response_headers );
  123. for item in wsgi_application( environ, my_start_response ):
  124. yield item
  125. return wrapper
  126. return real_decorator
  127. # EOF