| @@ -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" | |||||
| # | |||||
| # 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 "<h3>pagina di provenienza</h3>" | |||||
| print os.environ.get( 'HTTP_REFERER', '' ) | |||||
| # | |||||
| # parametri della richiesta HTTP | |||||
| # | |||||
| 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 ) ) ) | |||||
| @@ -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 ) | |||||
| @@ -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 }} | |||||
| @@ -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', | |||||
| } | |||||
| @@ -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', | |||||
| } | |||||
| @@ -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 } | |||||
| """ | |||||
| @@ -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 ] | |||||
| @@ -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 | |||||
| @@ -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' ) | |||||
| @@ -0,0 +1 @@ | |||||
| /var/log/apache2/access.log | |||||
| @@ -0,0 +1 @@ | |||||
| /var/log/apache2/error.log | |||||
| @@ -0,0 +1 @@ | |||||
| /etc/apache2/sites-available/nanowsgi | |||||
| @@ -0,0 +1 @@ | |||||
| http://www.infoworld.com/d/application-development/pillars-python-six-python-web-frameworks-compared-169442?page=0,1 | |||||
| @@ -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' | |||||
| @@ -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 \\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')] | |||||
| @@ -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'] ] | |||||
| @@ -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] | |||||
| @@ -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 © 2012, Alchimie Digitali S.r.l. | |||||
| </div> | |||||
| </body> | |||||
| </htm> | |||||
| @@ -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("'", "'") | |||||
| 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() | |||||
| @@ -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() | |||||