瀏覽代碼

first commit

db_access
Andrea Papotti 13 年之前
當前提交
247d2303b2
共有 22 個檔案被更改,包括 2078 行新增0 行删除
  1. +54
    -0
      cgi/cgi_test.py
  2. +49
    -0
      cgi/cgi_wrapper.py
  3. +13
    -0
      cgi/template1.tmpl
  4. +8
    -0
      config.py
  5. +8
    -0
      config.py.example
  6. +46
    -0
      controllers/demo.py
  7. +20
    -0
      controllers/demo/due.py
  8. +13
    -0
      deco.py
  9. +58
    -0
      dispatch_wsgi.py
  10. +1
    -0
      externals/access.log
  11. +1
    -0
      externals/error.log
  12. +1
    -0
      externals/etc_apache2_sites-available_nanowsgi
  13. +1
    -0
      externals/sei_framework_python.txt
  14. +13
    -0
      nanowsgi.wpr
  15. +665
    -0
      nanowsgi.wpu
  16. +116
    -0
      router.py
  17. +37
    -0
      static/.htaccess
  18. 二進制
     
  19. +21
    -0
      static/index.html
  20. 二進制
     
  21. +917
    -0
      template.py
  22. +36
    -0
      test_mysql.py

+ 54
- 0
cgi/cgi_test.py 查看文件

@@ -0,0 +1,54 @@
#!/usr/bin/python
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-

#
# in caso di traceback mostra una pagina più leggibile
#
import cgitb
cgitb.enable()

#
# import librerie utilizzate
#
import os
import cgi

print "Content-type: text/html"
print

#
# variabili d'ambiente (dall' OS)
#
print "<h3>ambiente</h3>"
keys = os.environ.keys()
keys.sort()



for k in keys:
print "%s = %s<br>\n" % ( k, str( os.environ[k] ) )

#
# pagina di provenienza (utile per rilevare direct link da altri siti)
#
print
print
print "<h3>pagina di provenienza</h3>"
print os.environ.get( 'HTTP_REFERER', '' )


#
# parametri della richiesta HTTP
#
print
print
print "<h3>parametri form</h3>"
form = cgi.FieldStorage( keep_blank_values=1 ) # non omettere i parametri senza valori

keys = form.keys()
keys.sort()

for k in keys:
print "%s = %s<br>\n" % ( k, str( form.getvalue( k, None ) ) )



+ 49
- 0
cgi/cgi_wrapper.py 查看文件

@@ -0,0 +1,49 @@
#!/usr/bin/python
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-


###############################################################################
##
##
## WRAPPER CGI PER IL NOSTRO FRAMEWORK WSGI
##
##
##
## !!! DA USARE SOLO INTERNAMENTE! __MAI__ IN AMBIENTE DI PRODUZIONE !!!
##
## - performance misere
## - inizializza tutto l'ambiente ad ogni richiesta
## - mostra parte del codice sorgente in caso di errori ( password, dati, ... )
##
##
###############################################################################


#
# in caso di traceback mostra una pagina più leggibile
#
import cgitb
cgitb.enable()

#
# libreria standard WSGI
#
import wsgiref.handlers

#
# importa il dispatcher WSGI ( si trova in ../ )
#
import sys

wsgilib = '/'.join( __file__.split('/')[:-2] )

if wsgilib not in sys.path:
sys.path.insert(0, wsgilib)

import dispatch_wsgi as mywsgi

#
# Magia!
#
if __name__ == '__main__':
wsgiref.handlers.CGIHandler().run( mywsgi.application )

+ 13
- 0
cgi/template1.tmpl 查看文件

@@ -0,0 +1,13 @@

il valore di v1 è {{= v1 }}
<br>
mentre il valore di v2 è {{= v2 }}
<br>
questo è il risultato di un loop che genera 10 valori casuali:<br>
{{ import random }}
{{ for x in range( 10 ): }}
<div style='background-color:{{ = random.choice( ('#fcc','yellow','#ccc','cyan',) ) }};'>
{{= random.randint( 10, 100 ) }}
</div>
{{ pass }}


+ 8
- 0
config.py 查看文件

@@ -0,0 +1,8 @@
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-

config = {
'MYSQL_HOST': 'localhost',
'MYSQL_USER': 'corso',
'MYSQL_PASSWORD': 'pwdcorso',
'MYSQL_DB': 'mywiki',
}

+ 8
- 0
config.py.example 查看文件

@@ -0,0 +1,8 @@
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-

config = {
'MYSQL_HOST': 'your_mysql_server_name_or_ip_address',
'MYSQL_USER': 'your_mysql_username',
'MYSQL_PASSWORD': 'your_mysql_password',
'MYSQL_DB': 'your_mysql_db',
}

+ 46
- 0
controllers/demo.py 查看文件

@@ -0,0 +1,46 @@
#!/usr/bin/python
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-

#
# esempio minimo di controller WSGI
#
def application( environ, start_response ):
start_response( '200 OK', [('content-type', 'text/html')] )
return [ 'Greetings from demo' ]

#
# funzioni specializzate per GET e POST.
# _se_ presenti hanno la precedenza rispetto ad 'application'
#
def get( environ, start_response ):
import template

start_response( '200 OK', [('content-type', 'text/html; charset=utf-8')] )

return [ template.render(
content='''
Greetings from demo (GET)<br>
{% for i in range(a): %}
{% = i %}<br>
{% pass %}
<br>
<span style='font-size:10px;'>(questo contenuto è generato da un template)</span>
''',

context=dict(a=5),

delimiters=( '{%', '%}' )
)
]

def post( environ, start_response ):
start_response( '200 OK', [('content-type', 'text/html')] )
return [ 'Greetings from demo (POST)' ]



"""
@template( 'hello_world.tmpl' )
def render( environ ):
return { 'v1': 100, 'cube':lambda x: x**3 }
"""

+ 20
- 0
controllers/demo/due.py 查看文件

@@ -0,0 +1,20 @@
#!/usr/bin/python
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-

import deco # decoratori
import traceback

#
# esempio minimo di controller WSGI
#
@deco.template( 'template1.tmpl' )
def application( environ, start_response ):

try:
html = environ['template']( context=dict( v1=1, v2='pippo') )
except:
html = "<pre>" + traceback.format_exc() + "</pre>"

start_response( '200 OK', [('content-type', 'text/html; charset=utf-8')] )

return [ html ]

+ 13
- 0
deco.py 查看文件

@@ -0,0 +1,13 @@
#!/usr/bin/python
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-

import template as tmpl
from functools import partial

def template( filename=None ):
def real_decorator( wsgi_application ):
def wrapper( environ, start_response ):
environ[ 'template' ] = partial( tmpl.render, filename=filename )
return wsgi_application( environ, start_response )
return wrapper
return real_decorator

+ 58
- 0
dispatch_wsgi.py 查看文件

@@ -0,0 +1,58 @@
#!/usr/bin/python
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-


#
# aggiungiamo la directory corrente al path (se non presente)
#
import sys
wsgilib = '/'.join( __file__.split('/')[:-1] )
if wsgilib not in sys.path:
sys.path.insert(0, wsgilib)

#
# importazione handler
#
from router import WSGIRouter, WSGISmartRouter

#
# index: esempio minimo di applicazione WSGI (pagina iniziale)
#
def index( environ, start_response ):
start_response( '200 OK', [('content-type', 'text/html')] )
return [ 'Index was here' ]

#
# hello: esempio minimo di applicazione WSGI
#
def hello( environ, start_response ):
start_response( '200 OK', [('content-type', 'text/html')] )
return [ 'Simon says: Hello world!' ]

#
# fallback: mostra tutti i parametri disponibili all'applicazione WSGI
#
def fallback( environ, start_response ):
from pprint import pformat
start_response( '200 OK', [('Content-Type', 'text/html')] )
return [
'-- EMBEDDED MODE --' if not environ.get('mod_wsgi.process_group','') else '-- DAEMON MODE --',
'<form method="POST"><input type="submit"/></form>',
pformat( environ, width=132 ).replace('\n','<br>\n'),
]

#
# definiamo gli handler per le url che vogliamo servire
#
from test_mysql import simple_mysql

handlers = (
( r'/', index ),
( r'/hello', hello ),
( r'/mysql', simple_mysql ),
)

#
# !!! mod_wsgi richiede che la nostra applicazione si chiami 'application'
#
application = WSGISmartRouter( handlers, fallback, cont_dir='controllers' )

+ 1
- 0
externals/access.log 查看文件

@@ -0,0 +1 @@
/var/log/apache2/access.log

+ 1
- 0
externals/error.log 查看文件

@@ -0,0 +1 @@
/var/log/apache2/error.log

+ 1
- 0
externals/etc_apache2_sites-available_nanowsgi 查看文件

@@ -0,0 +1 @@
/etc/apache2/sites-available/nanowsgi

+ 1
- 0
externals/sei_framework_python.txt 查看文件

@@ -0,0 +1 @@
http://www.infoworld.com/d/application-development/pillars-python-six-python-web-frameworks-compared-169442?page=0,1

+ 13
- 0
nanowsgi.wpr 查看文件

@@ -0,0 +1,13 @@
#!wing
#!version=4.0
##################################################################
# Wing IDE project file #
##################################################################
[project attributes]
proj.directory-list = [{'dirloc': loc('.'),
'excludes': (),
'filter': '*',
'include_hidden': False,
'recursive': True,
'watch_for_changes': True}]
proj.file-type = 'shared'

+ 665
- 0
nanowsgi.wpu 查看文件

@@ -0,0 +1,665 @@
#!wing
#!version=4.0
##################################################################
# Wing IDE project file : User-specific branch #
##################################################################
[user attributes]
console.id-seed = 2
console.toolbox = [{'autosave': False,
'ctype': ('cmd',
'tail -f /var/log/apache2/error.log'),
'env': ('project',
['']),
'id': 'cmd-1',
'io_encoding': None,
'key_binding': '',
'line_mode': True,
'pseudo_tty': True,
'pypath': ('project',
''),
'raise_panel': True,
'rundir': ('project',
''),
'title': 'apache error log'}]
guimgr.overall-gui-state = {'windowing-policy': 'combined-window',
'windows': [{'name': 'T8mo9t3gr2UfAuntANdsFb69OL'\
'cVmlgL',
'size-state': '',
'type': 'dock',
'view': {'area': 'tall',
'constraint': None,
'current_pages': [1,
2],
'full-screen': False,
'notebook_display': 'tabs only',
'notebook_percent': 0.41268292682926833,
'override_title': None,
'pagelist': [('debug-stack',
'tall',
1,
{'codeline-mode': 'below'}),
('debug-io',
'tall',
0,
{'attrib-starts': [],
'first-line': 0,
'folded-linenos': [],
'sel-line': 0,
'sel-line-start': 0,
'selection_end': 0,
'selection_start': 0}),
('indent',
'tall',
2,
{}),
('project',
'tall',
0,
{'tree-state': {'file-sort-method': 'by name',
'list-files-first': False,
'tree-states': {'deep': {'column-widths': None,
'expanded-nodes': [(0,),
(1,),
(2,),
(3,)],
'selected-nodes': [(3,
3)],
'top-node': (0,)}},
'tree-style': 'deep'}}),
('refactoring',
'tall',
0,
{}),
('snippets',
'tall',
0,
{'tree-states': {'__all__': [],
u'c': [],
u'django': [],
u'html': [],
u'py': []}}),
('source-assistant',
'tall',
2,
{'docstring-during-complete': False,
'wrap-lines': True}),
('browser',
'tall',
0,
{'all_tree_states': {u'By Module': {'column-w'\
'idths': [1.0],
'expanded-nodes': [],
'selected-nodes': [],
'top-node': None}},
'browse_mode': u'By Module',
'follow-selection': False,
'sort_mode': 'Alphabetically',
'visibility_options': {u'Derived Classes': False,
u'Imported': False,
u'Modules': True}})],
'primary_view_state': {'area': 'wide',
'constraint': None,
'current_pages': [6],
'notebook_display': 'normal',
'notebook_percent': 0.39739413680781754,
'override_title': None,
'pagelist': [('bookmarks',
'wide',
1,
{}),
('debug-breakpoints',
'wide',
0,
{'tree-state': []}),
('debug-probe',
'wide',
2,
{'attrib-starts': [],
'first-line': 0,
'folded-linenos': [],
'history': {None: [],
u'file:/home/joshua/CIA/PROJECTS/oeseo/iniezione24/importer.py': [''\
'fields\n',
'eval( fields)\n',
'parse_month( value )\n'],
u'file:/home/joshua/CIA/PROJECTS/quake time machine/ingv_grabber.py': [''\
'query\n',
'print query\n'],
u'file:/home/joshua/CIA/PROJECTS/scribd/scribd_grabber.py': [''\
'value.split()\n',
'path.exists( fname)\n',
'path.isfile( fname )\n',
"fcontent[ fcontent.find('('): ]\n",
"fcontent[ fcontent.find('['): ]\n",
"print fcontent[ fcontent.find('['): ]\n",
"print fcontent[ fcontent.find('['):-4 ]\n",
"print fcontent[ fcontent.find('['):-3]\n",
"print fcontent[ fcontent.find('[')+1:-3]\n",
'fcontent\n',
"json.loads( fcontent[ fcontent.find('[')+1:-3] )\n",
"print json.loads( fcontent[ fcontent.find('[')+1:-3] )\n",
"jcontent.encode('utf-8')\n",
'self.rawdata\n',
"self.rawdata += jcontent.encode('utf-8')\n",
'len( self.rawdata )\n',
'econtent\n'],
u'file:/home/joshua/Desktop/ir-audio.py': [''\
'type( data )\n',
'l\n',
'data\n',
'for c in data:\n print ord( c )\n\n',
'len( data )\n'],
u'file:/home/joshua/Projects/corso_python/decoratori.py': [''\
'time()\n',
't0\n'],
u'file:/home/joshua/Projects/corso_python/mille_code.py': [''\
'self.__obj_list\n',
'self\n',
'self.__class__\n',
'self.__class__.__init_code()\n',
'self.__class__.__init_code\n',
'self.__class__.\n',
'_Supermarket__init_code\n',
'self.__init_code\n',
'self.__code\n',
'self.__store\n',
'self.store\n',
'self.code\n',
'coda.len()\n'],
u'file:/media/Kindle/screensaver/renumber.py': [''\
'file_list\n']},
'sel-line': 4,
'sel-line-start': 46,
'selection_end': 46,
'selection_start': 46}),
('debug-exceptions',
'wide',
0,
{}),
('messages',
'wide',
2,
{'current-domain': 8}),
('debug-modules',
'wide',
1,
{}),
('os-command',
'wide',
1,
{'last-percent': 0.80000000000000004,
'toolbox-percent': 1.0,
'toolbox-tree-sel': 'cmd-1'}),
('python-shell',
'wide',
2,
{'attrib-starts': [],
'first-line': 4,
'folded-linenos': [],
'history': {None: ['import stat\n',
'imporet urllib2\n',
'import urllib2\n',
'INGV_PAGE = "http://cnt.rm.ingv.it/"\n',
'html = urllib2.urlopen(INGV_PAGE).read()\n',
'print html\n',
'import MySQLdb\n',
'x = ["<div class=\\"newpage\\" id=\\"page225\\" style=\\"width: 902'\
'px; height:1103px\\">\\n<div class=text_layer style=\\"z-index:2\\"'\
'><div class=ie_fix>\\n&nbsp;\\n<div class=\\"ff3\\" style=\\"font-s'\
'ize:231px\\">\\n<span class=a style=\\"left:172px;top:131px;word-sp'\
'acing:36px;letter-spacing:-12px\\">Chiss\xc3\x83 da quanto tempo s'\
'i era accorta che lui la stava</span><span class=a style=\\"left:17'\
'2px;top:361px;letter-spacing:-10px\\">osservando?</span><span class'\
'=a style=\\"left:172px;top:784px;word-spacing:18px;letter-spacing:-'\
'13px\\">- Siamo in due, direi. \xc3\xa2\xe2\x82\xac\xe2\x80\x9c Ris'\
'pose sulla difensiva, alzandosi</span><span class=a style=\\"left:1'\
'72px;top:1014px;word-spacing:33px;letter-spacing:-12px\\">e raggiun'\
'gendola sul balcone. \xc3\xa2\xe2\x82\xac\xe2\x80\x9c Eppure dovres'\
'ti essere</span><span class=a style=\\"left:172px;top:1244px;word-s'\
'pacing:6px;letter-spacing:-12px\\">stanca. Non riposi da due giorni'\
' almeno.</span><span class=a style=\\"left:172px;top:1667px;word-sp'\
'acing:6px;letter-spacing:-11px\\">- Non dormo mai molto, da un anno'\
' a questa parte. \xc3\xa2\xe2\x82\xac\xe2\x80\x9c\xc3\x82 </span><s'\
'pan class=a style=\\"left:172px;top:2090px;word-spacing:77px;letter'\
'-spacing:-13px\\">Il suo tono si fece all\xc3\xa2\xe2\x82\xac\xe2\x84'\
'\xa2improvviso fragile, da donna</span><span class=a style=\\"left:'\
'172px;top:2319px;letter-spacing:-15px\\">impaurita.</span><span cla'\
'ss=a style=\\"left:172px;top:2743px;word-spacing:8px;letter-spacing'\
':-11px\\">- Pensieri?</span><span class=a style=\\"left:172px;top:3'\
'166px;word-spacing:11px;letter-spacing:-12px\\">Si accorse quasi su'\
'bito di quanto fosse superficiale la sua</span><span class=a style='\
'\\"left:172px;top:3395px;word-spacing:37px;letter-spacing:-11px\\">'\
'domanda, che per\xc3\x83\xc2\xb2 parve aprire un varco tra le ferre'\
'e</span><span class=a style=\\"left:172px;top:3625px;word-spacing:7'\
'px;letter-spacing:-11px\\">difese di Sara.</span><span class=a styl'\
'e=\\"left:120px;top:4048px\\">\xc3\x82 \xc3\xa2\xe2\x82\xac\xe2\x80'\
'\x9c <span class=l11>I<span class=l8>n<span class=l style=\\"margin'\
'-left:-20px\\">c<span class=l7>u<span class=l style=\\"margin-left:'\
'-19px\\">b<span class=l8>i<span class=l style=\\"margin-left:-21px\\'\
'">.</span></span></span></span></span></span></span></span><span cl'\
'ass=a style=\\"left:172px;top:4471px;word-spacing:28px;letter-spaci'\
'ng:-12px\\">Lei lo guard\xc3\x83\xc2\xb2. Sembrava che avesse vogli'\
'a di parlare e</span><span class=a style=\\"left:172px;top:4701px;w'\
'ord-spacing:7px;letter-spacing:-11px\\">che si stesse domandando se'\
' lui fosse la persona adatta.</span><span class=a style=\\"left:172'\
'px;top:5124px;word-spacing:48px;letter-spacing:-12px\\">Robert non '\
'disse nulla, Sara stava seguendo il filo di</span></div>\\n</div>\\'\
'n</div>\\n<div class=image_layer style=\\"z-index: 1\\">\\n<div cla'\
'ss=ie_fix>\\n<img class=\\"absimg\\" style=\\"left:18px;top:18px;wi'\
'dth:863px;height:1064px;clip:rect(1px 862px 1063px 1px)\\" orig=\\"'\
'http://html.scribd.com/7ushlvstz41l2q4u/images/225-35c233193a.jpg\\'\
'"/>\\n</div>\\n</div>\\n</div>\\n\\n"]\n',
'x\n',
'print x\n',
'len( x )\n',
'x.length\n',
'x.size()\n',
'dir( x )\n',
'y = x\n',
'y.sort\n',
'y.sort()\n',
'y = x[0]\n',
'y\n',
'print y\n',
'"%05d" % 42\n',
'"%05d" % 42.5\n',
'"%05f" % 42.5\n',
'"%05.3f" % 42.5\n',
'"%05.1f" % 42.5\n',
'"%05.1f" % 42.545\n',
'"%05.1f" % 42.567\n',
'"%5.1f" % 42.567\n',
'"%9.1f" % 42.567\n',
'"%9.7f" % 42.567\n',
'"%9.9f" % 42.567\n',
'"%-9.9f" % 42.567\n',
'"%5f" % 1.234567\n',
'"%5f" % 1.23456789\n',
'"%5.2f" % 1.23456789\n',
'"%7.2f" % 1.23456789\n',
"'%f' % 12.34567\n",
"'%0f' % 12.34567\n",
"'%3f' % 12.34567\n",
"'%3f' % 12.345678\n",
'345678\n\n',
"'%1.3f' % 12.345678\n",
"'%1.3f' % 435243512.345678\n",
"'%.3f' % 435243512.345678\n",
"'%.3f' % 12.345678\n",
"'%4.3f' % 12.345678\n",
"'%-4.3f' % 12.345678\n",
"'%4.2f' % 12.345678\n",
"'%.2f' % 12.345678\n",
"'%.-2f' % 12.345678\n",
"'%10.2f' % 12.345678\n",
"'%-10.2f' % 12.345678\n",
'"%-8s" % "loremipsum"\n',
'"%8s" % "loremipsum"\n',
'"%4s" % "loremipsum"\n',
'"%-4s" % "loremipsum"\n',
'"%-40s" % "loremipsum"\n',
'"%40s" % "loremipsum"\n',
'"%-5s" % "loremipsum"\n',
'"%-.5s" % "loremipsum"\n',
'"%.5s" % "loremipsum"\n',
'"%10.5s" % "loremipsum"\n',
'"%-10.5s" % "loremipsum"\n',
'2.56**5\n',
"giorni = \"\"\"\n Lunedi Martedi Mercoledi\n Giovedi Venerdi "\
"Sabato\n Domenica\n \"\"\".split()\n\nfor i, g in enumerate( "\
"giorni ):\n print \"il\", i+1, \"^ giorno e' un\", g\n\n",
'giorni\n',
'help( len )\n',
'a = 1\n',
'b = 2\n',
'a, b = b,a\n',
'print a, b\n',
'34\n',
'x = 34\n',
"x=input('valore di x ')\n",
'pippo\n',
'x = pippo\n',
'a = [ 1, 2, 3, 4 ]\n',
'len( a )\n',
'a[5] = 7\n',
'a.insert(0, 7)\n',
'a.insert(-1, 17)\n',
'a[::-1].insert(0,44)\n',
'a\n',
'import paste\n',
'import webob\n',
'import sys\n',
'sys.argv()\n',
'sys.argv\n',
'*sys.argv\n',
"\"{0}\".format( 'hello' )\n",
"\"{0}\".format( ['hello'] )\n",
"\"{0}\".format( *['hello'] )\n",
"*['hello']\n",
'None()\n',
'import subprocess\n',
'p = Popen( "ls -lR", stdin = PIPE )\n',
'p = subprocess.Popen( "ls -lR", stdin = PIPE )\n',
'p = subprocess.Popen( "ls -lR", stdin = subprocess.PIPE )\n',
'import re\n']},
'sel-line': 3,
'sel-line-start': 130,
'selection_end': 130,
'selection_start': 130}),
('interactive-search',
'wide',
0,
{'fScope': {'fFileSetName': u'All Source Files',
'fLocation': None,
'fRecursive': True,
'fType': 'project-files'},
'fSearchSpec': {'fEndPos': None,
'fIncludeLinenos': True,
'fInterpretBackslashes': False,
'fMatchCase': False,
'fOmitBinary': True,
'fRegexFlags': 46,
'fReplaceText': u"po'",
'fReverse': False,
'fSearchText': u'po"',
'fStartPos': 0,
'fStyle': 'text',
'fWholeWords': False,
'fWrap': True},
'fUIOptions': {'fAutoBackground': True,
'fFilePrefix': 'short-file',
'fFindAfterReplace': True,
'fInSelection': False,
'fIncremental': True,
'fReplaceOnDisk': False,
'fShowFirstMatch': False,
'fShowLineno': True,
'fShowReplaceWidgets': True},
'replace-entry-expanded': False,
'search-entry-expanded': False}),
('batch-search',
'wide',
0,
{'fScope': {'fFileSetName': u'All Source Files',
'fLocation': None,
'fRecursive': True,
'fType': 'current-file'},
'fSearchSpec': {'fEndPos': None,
'fIncludeLinenos': True,
'fInterpretBackslashes': False,
'fMatchCase': False,
'fOmitBinary': True,
'fRegexFlags': 38,
'fReplaceText': u'\\1',
'fReverse': False,
'fSearchText': u'__([^(]+?[^_ ])',
'fStartPos': 0,
'fStyle': 'regex',
'fWholeWords': False,
'fWrap': True},
'fUIOptions': {'fAutoBackground': True,
'fFilePrefix': 'short-file',
'fFindAfterReplace': True,
'fInSelection': False,
'fIncremental': True,
'fReplaceOnDisk': False,
'fShowFirstMatch': False,
'fShowLineno': True,
'fShowReplaceWidgets': True},
'replace-entry-expanded': False,
'search-entry-expanded': False}),
('debug-data',
'wide',
0,
{}),
('testing',
'wide',
0,
{'added-files': [],
'filter': '',
'recent-filters': None,
'sort-order': 'alpha'}),
('debug-watch',
'wide',
0,
{'node-states': [('eval',
'attrs')],
'tree-state': {'column-widths': [0.4008515815085158,
0.59914841849148415],
'expanded-nodes': [(0,)],
'selected-nodes': [],
'top-node': (0,)}})],
'primary_view_state': {'editor_states': {'bookmarks': ([[loc('../corso_python/www/wsgi/wsgi_test.py'),
{'attrib-starts': [],
'first-line': 0,
'folded-linenos': [],
'sel-line': 0,
'sel-line-start': 0,
'selection_end': 148,
'selection_start': 0},
1352922666.5966339],
[loc('../corso_python/www/wsgi/sqlpooler.py'),
{'attrib-starts': [('WSGISqlPoolMySQL',
4)],
'first-line': 0,
'folded-linenos': [21,
34,
67,
80],
'sel-line': 7,
'sel-line-start': 268,
'selection_end': 275,
'selection_start': 275},
1352922666.8889589],
[loc('../corso_python/www/static/index.html'),
{'attrib-starts': [],
'first-line': 0,
'folded-linenos': [],
'sel-line': 4,
'sel-line-start': 68,
'selection_end': 78,
'selection_start': 78},
1352922667.347193],
[loc('../corso_python/www/static/dispatch_wsgi.py'),
{'attrib-starts': [],
'first-line': 37,
'folded-linenos': [],
'sel-line': 51,
'sel-line-start': 1203,
'selection_end': 1249,
'selection_start': 1217},
1352922667.6854961],
[loc('../corso_python/www/static/dispatch_fcgi.py'),
{'attrib-starts': [],
'first-line': 25,
'folded-linenos': [],
'sel-line': 41,
'sel-line-start': 913,
'selection_end': 945,
'selection_start': 913},
1352922668.0699551],
[loc('../corso_python/www/static/.htaccess'),
{'attrib-starts': [],
'first-line': 34,
'folded-linenos': [],
'sel-line': 54,
'sel-line-start': 1157,
'selection_end': 1157,
'selection_start': 1157},
1352922668.490283],
[loc('../corso_python/www/protected/info_handler.py'),
{'attrib-starts': [('info',
22)],
'first-line': 0,
'folded-linenos': [],
'sel-line': 34,
'sel-line-start': 1127,
'selection_end': 1151,
'selection_start': 1127},
1352922668.901685],
[loc('../corso_python/www/protected/hello_handler.py'),
{'attrib-starts': [('hello',
18)],
'first-line': 0,
'folded-linenos': [],
'sel-line': 46,
'sel-line-start': 1148,
'selection_end': 1213,
'selection_start': 1153},
1352922669.3464761],
[loc('../corso_python/www/protected/fallback_handler.py'),
{'attrib-starts': [],
'first-line': 0,
'folded-linenos': [],
'sel-line': 3,
'sel-line-start': 81,
'selection_end': 108,
'selection_start': 81},
1352922669.920784],
[loc('../corso_python/www/cgi/dispatch_cgi.py'),
{'attrib-starts': [],
'first-line': 0,
'folded-linenos': [],
'sel-line': 5,
'sel-line-start': 162,
'selection_end': 164,
'selection_start': 164},
1352922670.2010989],
[loc('../corso_python/www/apache_config.txt'),
{'attrib-starts': [],
'first-line': 6,
'folded-linenos': [],
'sel-line': 16,
'sel-line-start': 467,
'selection_end': 499,
'selection_start': 499},
1352922670.649184],
(loc('controllers/demo.py'),
{'attrib-starts': [('get',
14)],
'first-line': 17,
'folded-linenos': [],
'sel-line': 27,
'sel-line-start': 805,
'selection_end': 811,
'selection_start': 811},
1352970566.1362541),
(loc('static/index.html'),
{'attrib-starts': [],
'first-line': 0,
'folded-linenos': [],
'sel-line': 11,
'sel-line-start': 315,
'selection_end': 315,
'selection_start': 315},
1352970992.829721),
(loc('controllers/demo.py'),
{'attrib-starts': [('get',
14)],
'first-line': 17,
'folded-linenos': [],
'sel-line': 27,
'sel-line-start': 805,
'selection_end': 811,
'selection_start': 811},
1352971019.481142),
(loc('dispatch_wsgi.py'),
{'attrib-starts': [],
'first-line': 31,
'folded-linenos': [],
'sel-line': 0,
'sel-line-start': 0,
'selection_end': 0,
'selection_start': 0},
1352971025.356674),
(loc('static/index.html'),
{'attrib-starts': [],
'first-line': 0,
'folded-linenos': [],
'sel-line': 10,
'sel-line-start': 268,
'selection_end': 318,
'selection_start': 318},
1352971029.3790801),
(loc('dispatch_wsgi.py'),
{'attrib-starts': [],
'first-line': 31,
'folded-linenos': [],
'sel-line': 0,
'sel-line-start': 0,
'selection_end': 0,
'selection_start': 0},
1352971052.15623),
(loc('static/index.html'),
{'attrib-starts': [],
'first-line': 0,
'folded-linenos': [],
'sel-line': 9,
'sel-line-start': 209,
'selection_end': 240,
'selection_start': 235},
1352971058.338448),
(loc('dispatch_wsgi.py'),
{'attrib-starts': [],
'first-line': 31,
'folded-linenos': [],
'sel-line': 0,
'sel-line-start': 0,
'selection_end': 0,
'selection_start': 0},
1352971071.333266),
[loc('static/index.html'),
{'attrib-starts': [],
'first-line': 0,
'folded-linenos': [],
'sel-line': 9,
'sel-line-start': 209,
'selection_end': 240,
'selection_start': 235},
1352971072.960921]],
19),
'current-loc': loc('static/index.html'),
'editor-states': {loc('controllers/demo.py'): {'attrib-starts': [('g'\
'et',
14)],
'first-line': 17,
'folded-linenos': [],
'sel-line': 27,
'sel-line-start': 805,
'selection_end': 811,
'selection_start': 811},
loc('dispatch_wsgi.py'): {'attrib-starts': [],
'first-line': 31,
'folded-linenos': [],
'sel-line': 0,
'sel-line-start': 0,
'selection_end': 0,
'selection_start': 0},
loc('static/index.html'): {'attrib-starts': [],
'first-line': 0,
'folded-linenos': [],
'sel-line': 11,
'sel-line-start': 335,
'selection_end': 394,
'selection_start': 394}},
'has-focus': True},
'open_files': [u'controllers/demo.py',
u'dispatch_wsgi.py',
u'static/index.html']},
'saved_notebook_display': None,
'split_percents': {0: 0.33189122373300373},
'splits': 1,
'tab_location': 'top',
'user_data': {}},
'saved_notebook_display': None,
'split_percents': {0: 0.7046688382193268},
'splits': 2,
'tab_location': 'left',
'user_data': {}},
'window-alloc': (38,
40,
1322,
964)}]}
guimgr.recent-documents = [loc('static/index.html'),
loc('dispatch_wsgi.py'),
loc('controllers/demo.py')]

+ 116
- 0
router.py 查看文件

@@ -0,0 +1,116 @@
#!/usr/bin/python
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-

import re
import imp
import os

class WSGIRouter(object):
""" parse http uri and call the proper handler (controller in MVC terms)
"""
def __init__( self, handlers=(), fallback=None ):
""" handlers = list of tuples in the form ( regex, handler )
groups in regex are passed to handlers within environ['router.args']

fallback = if defined, is the default handler to be called if no
regex in 'handlers' matches
"""
self.handlers = handlers
self.fallback = fallback

def __call__( self, environ, start_response ):
#
# search form matching handler
#
for regex, handler in self.handlers:
match = re.match( '^' + regex + '$', environ['SCRIPT_URL'])
if match:
environ['router.args'] = match.groups()
return handler( environ, start_response )

#
# use fallback ( if defined )
#
if self.fallback:
environ['router.args'] = [
token for token in environ['SCRIPT_URL'].split('/') if token ]
return self.fallback( environ, start_response )

#
# last resort
#
start_response( '202 Accepted', [('Content-Type', 'text/plain')] )
return [ "WSGIRouter: I have no route for '%s'" % environ['SCRIPT_URL'] ]

class WSGISmartRouter(object):
""" like WSGIRouter, but before calling fallback handler,
searches in 'cont_dir' folder for a file matching the url.

uri = http://<server[:port]>/lorem/ipsum/dolor/sit

handler: environ['router.args']:

any handler matching in handlers - capture groups -
<cont_dir>/lorem/ipsum/dolor/sit ()
<cont_dir>/lorem/ipsum/dolor ('sit')
<cont_dir>/lorem/ipsum ('dolor','sit')
<cont_dir>/lorem ('ipsum','dolor','sit')
fallback ('lorem','ipsum','dolor','sit')
"""
def __init__( self, handlers=(), fallback=None, cont_dir='.' ):
self.handlers = handlers
self.fallback = fallback
self.cont_dir = os.path.normpath( os.path.join( os.path.split(__file__)[0], cont_dir ) ) + '/'

def __call__( self, environ, start_response ):
#
# search form matching handler
#
for regex, handler in self.handlers:
match = re.match( '^' + regex + '$', environ['SCRIPT_URL'])
if match:
environ['router.args'] = match.groups()
return handler( environ, start_response )

#
# search in filesystem for matching file
#
tokens = [ token for token in environ['SCRIPT_URL'].split('/') if token ]

#for idx in range( 1, len( tokens ) + 1 ): # from shortest path to longest one
# from longest path to shortest one
for idx in range( len( tokens ) , 0, -1 ):
module = os.path.normpath( self.cont_dir + '/'.join( tokens[:idx] ) + '.py' )
args = tokens[idx:]

try:
handler = imp.load_source( 'application', module )
environ['router.args'] = args

if environ['REQUEST_METHOD'] == 'GET' and hasattr( handler, 'get' ):
# FIXME: forse è meglio eseguire QUI la start_response
# e compilare il template (solo per GET e POST)
return handler.get( environ, start_response )

elif environ['REQUEST_METHOD'] == 'POST' and hasattr( handler, 'post' ):
return handler.post( environ, start_response )

elif hasattr( handler, 'application' ):
return handler.application( environ, start_response )

except IOError:
# not found! Better luck next time...
pass

#
# use fallback ( if defined )
#
if self.fallback:
environ['router.args'] = tokens
return self.fallback( environ, start_response )

#
# last resort
#
start_response( '202 Accepted', [('Content-Type', 'text/plain')] )
return [ "WSGISmartRouter: I have no route for '%s'" % environ['SCRIPT_URL'] ]

+ 37
- 0
static/.htaccess 查看文件

@@ -0,0 +1,37 @@
RewriteEngine On # Turn on the rewriting engine
RewriteBase /


####################
RewriteRule ^/?$ /index


###############################################################################
## ##
## CGI WRAPPER PER WSGI ##
## ##
############################

##
## qualunque richiesta non statica viene passata a cgi/cgi_wrapper.py
##
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^(/.*)+cgi_wrapper.py/?
RewriteRule ^(.*)$ cgi/cgi_wrapper.py/$1 [QSA,L]



###############################################################################
## ##
## WSGI PURO ##
## ##
#################

##
## qualunque richiesta non statica viene passata a /dispatch_wsgi.py
##
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /dispatch_wsgi/$1 [QSA,L]


二進制
查看文件


+ 21
- 0
static/index.html 查看文件

@@ -0,0 +1,21 @@
<!doctype html>
<html>
<head>
<title>nanoWSGI</title>
</head>
<body>
<img src="/logo.png" alt="" width="540" height="160">
<h1>Elenco funzioni disponibili</h1>
<ul>
<li><a href="/">test index page</a></li>
<li><a href="/hello">test simple page (hello world)</a></li>
<li><a href="/mysql">test MYSQL access</a></li>
<li><a href="/demo">test autorouting</a></li>
<li><a href="/demo/due">test autorouting (longest path possible)</a></li>
</ul>
<div style="position:fixed; bottom:0; right:0;">
<img src="/favicon.ico" style="vertical-align: middle;">
nanoWSGI &copy; 2012, Alchimie Digitali S.r.l.
</div>
</body>
</htm>

二進制
查看文件


+ 917
- 0
template.py 查看文件

@@ -0,0 +1,917 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
This file is part of the web2py Web Framework (Copyrighted, 2007-2011).
License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html)

Author: Thadeus Burgess

Contributors:

- Thank you to Massimo Di Pierro for creating the original gluon/template.py
- Thank you to Jonathan Lundell for extensively testing the regex on Jython.
- Thank you to Limodou (creater of uliweb) who inspired the block-element support for web2py.
"""

import os
import cgi
import logging
from re import compile, sub, escape, DOTALL
try:
import cStringIO as StringIO
except:
from io import StringIO

try:
# have web2py
from restricted import RestrictedError
from globals import current
except ImportError:
# do not have web2py
current = None

def RestrictedError(a, b, c):
logging.error(str(a) + ':' + str(b) + ':' + str(c))
return RuntimeError


class Node(object):
"""
Basic Container Object
"""
def __init__(self, value=None, pre_extend=False):
self.value = value
self.pre_extend = pre_extend

def __str__(self):
return str(self.value)


class SuperNode(Node):
def __init__(self, name='', pre_extend=False):
self.name = name
self.value = None
self.pre_extend = pre_extend

def __str__(self):
if self.value:
return str(self.value)
else:
# raise SyntaxError("Undefined parent block ``%s``. \n" % self.name + "You must define a block before referencing it.\nMake sure you have not left out an ``{{end}}`` tag." )
return ''

def __repr__(self):
return "%s->%s" % (self.name, self.value)


def output_aux(node, blocks):
# If we have a block level
# If we can override this block.
# Override block from vars.
# Else we take the default
# Else its just a string
return (blocks[node.name].output(blocks)
if node.name in blocks else
node.output(blocks)) \
if isinstance(node, BlockNode) \
else str(node)


class BlockNode(Node):
"""
Block Container.

This Node can contain other Nodes and will render in a hierarchical order
of when nodes were added.

ie::

{{ block test }}
This is default block test
{{ end }}
"""
def __init__(self, name='', pre_extend=False, delimiters=('{{', '}}')):
"""
name - Name of this Node.
"""
self.nodes = []
self.name = name
self.pre_extend = pre_extend
self.left, self.right = delimiters

def __repr__(self):
lines = ['%sblock %s%s' % (self.left, self.name, self.right)]
lines += [str(node) for node in self.nodes]
lines.append('%send%s' % (self.left, self.right))
return ''.join(lines)

def __str__(self):
"""
Get this BlockNodes content, not including child Nodes
"""
return ''.join(str(node) for node in self.nodes
if not isinstance(node, BlockNode))

def append(self, node):
"""
Add an element to the nodes.

Keyword Arguments

- node -- Node object or string to append.
"""
if isinstance(node, str) or isinstance(node, Node):
self.nodes.append(node)
else:
raise TypeError("Invalid type; must be instance of ``str`` or ``BlockNode``. %s" % node)

def extend(self, other):
"""
Extend the list of nodes with another BlockNode class.

Keyword Arguments

- other -- BlockNode or Content object to extend from.
"""
if isinstance(other, BlockNode):
self.nodes.extend(other.nodes)
else:
raise TypeError(
"Invalid type; must be instance of ``BlockNode``. %s" % other)

def output(self, blocks):
"""
Merges all nodes into a single string.
blocks -- Dictionary of blocks that are extending
from this template.
"""
return ''.join(output_aux(node, blocks) for node in self.nodes)


class Content(BlockNode):
"""
Parent Container -- Used as the root level BlockNode.

Contains functions that operate as such.
"""
def __init__(self, name="ContentBlock", pre_extend=False):
"""
Keyword Arguments

name -- Unique name for this BlockNode
"""
self.name = name
self.nodes = []
self.blocks = {}
self.pre_extend = pre_extend

def __str__(self):
return ''.join(output_aux(node, self.blocks) for node in self.nodes)

def _insert(self, other, index=0):
"""
Inserts object at index.
"""
if isinstance(other, (str, Node)):
self.nodes.insert(index, other)
else:
raise TypeError(
"Invalid type, must be instance of ``str`` or ``Node``.")

def insert(self, other, index=0):
"""
Inserts object at index.

You may pass a list of objects and have them inserted.
"""
if isinstance(other, (list, tuple)):
# Must reverse so the order stays the same.
other.reverse()
for item in other:
self._insert(item, index)
else:
self._insert(other, index)

def append(self, node):
"""
Adds a node to list. If it is a BlockNode then we assign a block for it.
"""
if isinstance(node, (str, Node)):
self.nodes.append(node)
if isinstance(node, BlockNode):
self.blocks[node.name] = node
else:
raise TypeError("Invalid type, must be instance of ``str`` or ``BlockNode``. %s" % node)

def extend(self, other):
"""
Extends the objects list of nodes with another objects nodes
"""
if isinstance(other, BlockNode):
self.nodes.extend(other.nodes)
self.blocks.update(other.blocks)
else:
raise TypeError(
"Invalid type; must be instance of ``BlockNode``. %s" % other)

def clear_content(self):
self.nodes = []


class TemplateParser(object):

default_delimiters = ('{{', '}}')
r_tag = compile(r'(\{\{.*?\}\})', DOTALL)

r_multiline = compile(r'(""".*?""")|(\'\'\'.*?\'\'\')', DOTALL)

# These are used for re-indentation.
# Indent + 1
re_block = compile('^(elif |else:|except:|except |finally:).*$', DOTALL)

# Indent - 1
re_unblock = compile('^(return|continue|break|raise)( .*)?$', DOTALL)
# Indent - 1
re_pass = compile('^pass( .*)?$', DOTALL)

def __init__(self, text,
name="ParserContainer",
context=dict(),
path='views/',
writer='response.write',
lexers={},
delimiters=('{{', '}}'),
_super_nodes = [],
):
"""
text -- text to parse
context -- context to parse in
path -- folder path to templates
writer -- string of writer class to use
lexers -- dict of custom lexers to use.
delimiters -- for example ('{{','}}')
_super_nodes -- a list of nodes to check for inclusion
this should only be set by "self.extend"
It contains a list of SuperNodes from a child
template that need to be handled.
"""

# Keep a root level name.
self.name = name
# Raw text to start parsing.
self.text = text
# Writer to use (refer to the default for an example).
# This will end up as
# "%s(%s, escape=False)" % (self.writer, value)
self.writer = writer

# Dictionary of custom name lexers to use.
if isinstance(lexers, dict):
self.lexers = lexers
else:
self.lexers = {}

# Path of templates
self.path = path
# Context for templates.
self.context = context

# allow optional alternative delimiters
self.delimiters = delimiters
if delimiters != self.default_delimiters:
escaped_delimiters = (escape(delimiters[0]),
escape(delimiters[1]))
self.r_tag = compile(r'(%s.*?%s)' % escaped_delimiters, DOTALL)
elif hasattr(context.get('response', None), 'delimiters'):
if context['response'].delimiters != self.default_delimiters:
escaped_delimiters = (
escape(context['response'].delimiters[0]),
escape(context['response'].delimiters[1]))
self.r_tag = compile(r'(%s.*?%s)' % escaped_delimiters,
DOTALL)

# Create a root level Content that everything will go into.
self.content = Content(name=name)

# Stack will hold our current stack of nodes.
# As we descend into a node, it will be added to the stack
# And when we leave, it will be removed from the stack.
# self.content should stay on the stack at all times.
self.stack = [self.content]

# This variable will hold a reference to every super block
# that we come across in this template.
self.super_nodes = []

# This variable will hold a reference to the child
# super nodes that need handling.
self.child_super_nodes = _super_nodes

# This variable will hold a reference to every block
# that we come across in this template
self.blocks = {}

# Begin parsing.
self.parse(text)

def to_string(self):
"""
Return the parsed template with correct indentation.

Used to make it easier to port to python3.
"""
return self.reindent(str(self.content))

def __str__(self):
"Make sure str works exactly the same as python 3"
return self.to_string()

def __unicode__(self):
"Make sure str works exactly the same as python 3"
return self.to_string()

def reindent(self, text):
"""
Reindents a string of unindented python code.
"""

# Get each of our lines into an array.
lines = text.split('\n')

# Our new lines
new_lines = []

# Keeps track of how many indents we have.
# Used for when we need to drop a level of indentation
# only to reindent on the next line.
credit = 0

# Current indentation
k = 0

#################
# THINGS TO KNOW
#################

# k += 1 means indent
# k -= 1 means unindent
# credit = 1 means unindent on the next line.

for raw_line in lines:
line = raw_line.strip()

# ignore empty lines
if not line:
continue

# If we have a line that contains python code that
# should be unindented for this line of code.
# and then reindented for the next line.
if TemplateParser.re_block.match(line):
k = k + credit - 1

# We obviously can't have a negative indentation
k = max(k, 0)

# Add the indentation!
new_lines.append(' ' * (4 * k) + line)

# Bank account back to 0 again :(
credit = 0

# If we are a pass block, we obviously de-dent.
if TemplateParser.re_pass.match(line):
k -= 1

# If we are any of the following, de-dent.
# However, we should stay on the same level
# But the line right after us will be de-dented.
# So we add one credit to keep us at the level
# while moving back one indentation level.
if TemplateParser.re_unblock.match(line):
credit = 1
k -= 1

# If we are an if statement, a try, or a semi-colon we
# probably need to indent the next line.
if line.endswith(':') and not line.startswith('#'):
k += 1

# This must come before so that we can raise an error with the
# right content.
new_text = '\n'.join(new_lines)

if k > 0:
self._raise_error('missing "pass" in view', new_text)
elif k < 0:
self._raise_error('too many "pass" in view', new_text)

return new_text

def _raise_error(self, message='', text=None):
"""
Raise an error using itself as the filename and textual content.
"""
raise RestrictedError(self.name, text or self.text, message)

def _get_file_text(self, filename):
"""
Attempt to open ``filename`` and retrieve its text.

This will use self.path to search for the file.
"""

# If they didn't specify a filename, how can we find one!
if not filename.strip():
self._raise_error('Invalid template filename')

# Allow Views to include other views dynamically
context = self.context
if current and not "response" in context:
context["response"] = getattr(current, 'response', None)

# Get the filename; filename looks like ``"template.html"``.
# We need to eval to remove the quotes and get the string type.
filename = eval(filename, context)

# Get the path of the file on the system.
filepath = self.path and os.path.join(self.path, filename) or filename

# try to read the text.
try:
fileobj = open(filepath, 'rb')
text = fileobj.read()
fileobj.close()
except IOError:
self._raise_error('Unable to open included view file: ' + filepath)

return text

def include(self, content, filename):
"""
Include ``filename`` here.
"""
text = self._get_file_text(filename)

t = TemplateParser(text,
name=filename,
context=self.context,
path=self.path,
writer=self.writer,
delimiters=self.delimiters)

content.append(t.content)

def extend(self, filename):
"""
Extend ``filename``. Anything not declared in a block defined by the
parent will be placed in the parent templates ``{{include}}`` block.
"""
text = self._get_file_text(filename)

# Create out nodes list to send to the parent
super_nodes = []
# We want to include any non-handled nodes.
super_nodes.extend(self.child_super_nodes)
# And our nodes as well.
super_nodes.extend(self.super_nodes)

t = TemplateParser(text,
name=filename,
context=self.context,
path=self.path,
writer=self.writer,
delimiters=self.delimiters,
_super_nodes=super_nodes)

# Make a temporary buffer that is unique for parent
# template.
buf = BlockNode(
name='__include__' + filename, delimiters=self.delimiters)
pre = []

# Iterate through each of our nodes
for node in self.content.nodes:
# If a node is a block
if isinstance(node, BlockNode):
# That happens to be in the parent template
if node.name in t.content.blocks:
# Do not include it
continue

if isinstance(node, Node):
# Or if the node was before the extension
# we should not include it
if node.pre_extend:
pre.append(node)
continue

# Otherwise, it should go int the
# Parent templates {{include}} section.
buf.append(node)
else:
buf.append(node)

# Clear our current nodes. We will be replacing this with
# the parent nodes.
self.content.nodes = []

t_content = t.content

# Set our include, unique by filename
t_content.blocks['__include__' + filename] = buf

# Make sure our pre_extended nodes go first
t_content.insert(pre)

# Then we extend our blocks
t_content.extend(self.content)

# Work off the parent node.
self.content = t_content

def parse(self, text):

# Basically, r_tag.split will split the text into
# an array containing, 'non-tag', 'tag', 'non-tag', 'tag'
# so if we alternate this variable, we know
# what to look for. This is alternate to
# line.startswith("{{")
in_tag = False
extend = None
pre_extend = True

# Use a list to store everything in
# This is because later the code will "look ahead"
# for missing strings or brackets.
ij = self.r_tag.split(text)
# j = current index
# i = current item
stack = self.stack
for j in range(len(ij)):
i = ij[j]

if i:
if not stack:
self._raise_error('The "end" tag is unmatched, please check if you have a starting "block" tag')

# Our current element in the stack.
top = stack[-1]

if in_tag:
line = i

# Get rid of '{{' and '}}'
line = line[2:-2].strip()

# This is bad juju, but let's do it anyway
if not line:
continue

# We do not want to replace the newlines in code,
# only in block comments.
def remove_newline(re_val):
# Take the entire match and replace newlines with
# escaped newlines.
return re_val.group(0).replace('\n', '\\n')

# Perform block comment escaping.
# This performs escaping ON anything
# in between """ and """
line = sub(TemplateParser.r_multiline,
remove_newline,
line)

if line.startswith('='):
# IE: {{=response.title}}
name, value = '=', line[1:].strip()
else:
v = line.split(' ', 1)
if len(v) == 1:
# Example
# {{ include }}
# {{ end }}
name = v[0]
value = ''
else:
# Example
# {{ block pie }}
# {{ include "layout.html" }}
# {{ for i in range(10): }}
name = v[0]
value = v[1]

# This will replace newlines in block comments
# with the newline character. This is so that they
# retain their formatting, but squish down to one
# line in the rendered template.

# First check if we have any custom lexers
if name in self.lexers:
# Pass the information to the lexer
# and allow it to inject in the environment

# You can define custom names such as
# '{{<<variable}}' which could potentially
# write unescaped version of the variable.
self.lexers[name](parser=self,
value=value,
top=top,
stack=stack)

elif name == '=':
# So we have a variable to insert into
# the template
buf = "\n%s(%s)" % (self.writer, value)
top.append(Node(buf, pre_extend=pre_extend))

elif name == 'block' and not value.startswith('='):
# Make a new node with name.
node = BlockNode(name=value.strip(),
pre_extend=pre_extend,
delimiters=self.delimiters)

# Append this node to our active node
top.append(node)

# Make sure to add the node to the stack.
# so anything after this gets added
# to this node. This allows us to
# "nest" nodes.
stack.append(node)

elif name == 'end' and not value.startswith('='):
# We are done with this node.

# Save an instance of it
self.blocks[top.name] = top

# Pop it.
stack.pop()

elif name == 'super' and not value.startswith('='):
# Get our correct target name
# If they just called {{super}} without a name
# attempt to assume the top blocks name.
if value:
target_node = value
else:
target_node = top.name

# Create a SuperNode instance
node = SuperNode(name=target_node,
pre_extend=pre_extend)

# Add this to our list to be taken care of
self.super_nodes.append(node)

# And put in in the tree
top.append(node)

elif name == 'include' and not value.startswith('='):
# If we know the target file to include
if value:
self.include(top, value)

# Otherwise, make a temporary include node
# That the child node will know to hook into.
else:
include_node = BlockNode(
name='__include__' + self.name,
pre_extend=pre_extend,
delimiters=self.delimiters)
top.append(include_node)

elif name == 'extend' and not value.startswith('='):
# We need to extend the following
# template.
extend = value
pre_extend = False

else:
# If we don't know where it belongs
# we just add it anyways without formatting.
if line and in_tag:

# Split on the newlines >.<
tokens = line.split('\n')

# We need to look for any instances of
# for i in range(10):
# = i
# pass
# So we can properly put a response.write() in place.
continuation = False
len_parsed = 0
for k, token in enumerate(tokens):

token = tokens[k] = token.strip()
len_parsed += len(token)

if token.startswith('='):
if token.endswith('\\'):
continuation = True
tokens[k] = "\n%s(%s" % (
self.writer, token[1:].strip())
else:
tokens[k] = "\n%s(%s)" % (
self.writer, token[1:].strip())
elif continuation:
tokens[k] += ')'
continuation = False

buf = "\n%s" % '\n'.join(tokens)
top.append(Node(buf, pre_extend=pre_extend))

else:
# It is HTML so just include it.
buf = "\n%s(%r, escape=False)" % (self.writer, i)
top.append(Node(buf, pre_extend=pre_extend))

# Remember: tag, not tag, tag, not tag
in_tag = not in_tag

# Make a list of items to remove from child
to_rm = []

# Go through each of the children nodes
for node in self.child_super_nodes:
# If we declared a block that this node wants to include
if node.name in self.blocks:
# Go ahead and include it!
node.value = self.blocks[node.name]
# Since we processed this child, we don't need to
# pass it along to the parent
to_rm.append(node)

# Remove some of the processed nodes
for node in to_rm:
# Since this is a pointer, it works beautifully.
# Sometimes I miss C-Style pointers... I want my asterisk...
self.child_super_nodes.remove(node)

# If we need to extend a template.
if extend:
self.extend(extend)

# We need this for integration with gluon


def parse_template(filename,
path='views/',
context=dict(),
lexers={},
delimiters=('{{', '}}')
):
"""
filename can be a view filename in the views folder or an input stream
path is the path of a views folder
context is a dictionary of symbols used to render the template
"""

# First, if we have a str try to open the file
if isinstance(filename, str):
try:
fp = open(os.path.join(path, filename), 'rb')
text = fp.read()
fp.close()
except IOError:
raise RestrictedError(filename, '', 'Unable to find the file')
else:
text = filename.read()

# Use the file contents to get a parsed template and return it.
return str(TemplateParser(text, context=context, path=path, lexers=lexers, delimiters=delimiters))


def get_parsed(text):
"""
Returns the indented python code of text. Useful for unit testing.

"""
return str(TemplateParser(text))


class DummyResponse():
def __init__(self):
self.body = StringIO.StringIO()

def write(self, data, escape=True):
if not escape:
self.body.write(str(data))
elif hasattr(data, 'as_html') and callable(data.as_html):
self.body.write(data.as_html())
else:
# make it a string
if not isinstance(data, (str, unicode)):
data = str(data)
elif isinstance(data, unicode):
data = data.encode('utf8', 'xmlcharrefreplace')
data = cgi.escape(data, True).replace("'", "&#x27;")
self.body.write(data)


class NOESCAPE():
"""
A little helper to avoid escaping.
"""
def __init__(self, text):
self.text = text

def xml(self):
return self.text

# And this is a generic render function.
# Here for integration with gluon.


def render(content="hello world",
stream=None,
filename=None,
path=None,
context={},
lexers={},
delimiters=('{{', '}}')
):
"""
>>> render()
'hello world'
>>> render(content='abc')
'abc'
>>> render(content='abc\\'')
"abc'"
>>> render(content='a"\\'bc')
'a"\\'bc'
>>> render(content='a\\nbc')
'a\\nbc'
>>> render(content='a"bcd"e')
'a"bcd"e'
>>> render(content="'''a\\nc'''")
"'''a\\nc'''"
>>> render(content="'''a\\'c'''")
"'''a\'c'''"
>>> render(content='{{for i in range(a):}}{{=i}}<br />{{pass}}', context=dict(a=5))
'0<br />1<br />2<br />3<br />4<br />'
>>> render(content='{%for i in range(a):%}{%=i%}<br />{%pass%}', context=dict(a=5),delimiters=('{%','%}'))
'0<br />1<br />2<br />3<br />4<br />'
>>> render(content="{{='''hello\\nworld'''}}")
'hello\\nworld'
>>> render(content='{{for i in range(3):\\n=i\\npass}}')
'012'
"""
# here to avoid circular Imports
try:
from globals import Response
except ImportError:
# Working standalone. Build a mock Response object.
Response = DummyResponse

# Add it to the context so we can use it.
if not 'NOESCAPE' in context:
context['NOESCAPE'] = NOESCAPE

# save current response class
if context and 'response' in context:
old_response_body = context['response'].body
context['response'].body = StringIO.StringIO()
else:
old_response_body = None
context['response'] = Response()

# If we don't have anything to render, why bother?
if not content and not stream and not filename:
raise SyntaxError("Must specify a stream or filename or content")

# Here for legacy purposes, probably can be reduced to
# something more simple.
close_stream = False
if not stream:
if filename:
stream = open(filename, 'rb')
close_stream = True
elif content:
stream = StringIO.StringIO(content)

# Execute the template.
code = str(TemplateParser(stream.read(
), context=context, path=path, lexers=lexers, delimiters=delimiters))
try:
exec(code) in context
except Exception:
# for i,line in enumerate(code.split('\n')): print i,line
raise

if close_stream:
stream.close()

# Returned the rendered content.
text = context['response'].body.getvalue()
if old_response_body is not None:
context['response'].body = old_response_body
return text


if __name__ == '__main__':
import doctest
doctest.testmod()

+ 36
- 0
test_mysql.py 查看文件

@@ -0,0 +1,36 @@
import MySQLdb
from config import config

def simple_mysql( environ, start_response ):
#
# collegamento al mysql
#
# for more options see:
# http://mysql-python.sourceforge.net/MySQLdb.html#introduction
conn = MySQLdb.connect(
host = config['MYSQL_HOST'],
user = config['MYSQL_USER'],
passwd = config['MYSQL_PASSWORD'],
db = config['MYSQL_DB']
)

#
# esecuzione query
#
cur = conn.cursor( MySQLdb.cursors.DictCursor )
cur.execute( 'SHOW tables;' )

#
# recupero record e generazione html
#

start_response( '200 OK', [('Content-Type', 'text/plain')] )

for record in cur.fetchall():
yield "\n" + str( record )

#
# chiusura connessione al mysql
#
conn.close()


Loading…
取消
儲存