PKò¢*5¾‰fj?j?colubrid/application.pyc;ò £ŒõDc@sGdZdklZdklZlZlZdklZdk l Z dk l Z l Z dkZddd d d d d fZdefd„ƒYZdefd„ƒYZdefd„ƒYZdefd„ƒYZd efd„ƒYZd efd„ƒYZd efd„ƒYZd efd„ƒYZd efd„ƒYZdS(s Colubrid Base Applications ========================== This file provides a list of colubrid application. Each of them inherits form BaseApplication and implements a full WSGI compatible web application. If you like to add your own you _have_ to inherit from BaseApplication or the Request object wont work properly. Since colubrid 0.10 you don't have to use those base application objects. If you're looking for an example check out the `customapp.py` application in the example folder. (s generators(sRequestsResponseRequests RoutesRequest(s HttpResponse(s fix_slash(s HttpExceptions PageNotFoundNsBaseApplicationsRegexApplicationsResolveRegexApplicationsPathApplicationsObjectApplicationsWebpyApplicationsRoutesApplicationsRegexCompilerClasscBstZdZd„ZRS(s` Metaclass that automatically compiles regular expressions in the 'urls' attribute. cCs¹ti||||ƒ}t|dƒtjo|Snt|dƒ otdƒ‚ng}xG|i D]<}t |ƒ}t i|dƒ|d<|it|ƒƒqhW||_ |SdS(Nisurlss)Regex application without url definition.(stypes__new__sclssnamesbasessdctsresultshasattrs TypeErrors compiled_urlssurlssargsslistsrescompilesappendstuple(sclssnamesbasessdctsargss compiled_urlssresult((s2build/bdist.linux-i686/egg/colubrid/application.pys__new__#s   (s__name__s __module__s__doc__s__new__(((s2build/bdist.linux-i686/egg/colubrid/application.pysRegexCompilerClasss sRoutesMapperClasscBstZdZd„ZRS(s? Metaclass that automatically creates a Routes mapper. c Cs’ti||||ƒ} t|dƒtjo| Snt| dƒ otdƒ‚ndk l }|ƒ}h}h}xß| iD]Ô}|diddƒd}tt|dƒƒ} |d|| <| ||d HelloWorld.index() http://localhost/name/ --> HelloWorld.name('Nobody') http://localhost/name/Max --> HelloWorld.name('Max') http://localhost/admin/ --> AdminPanel.index() http://localhost/admin/login --> AdminPanel.login() cCsÊt|dƒ o td‚n|iiiddƒidƒ}|idƒ}|i } g}xi|D]a} | idƒo t‚nt| | tƒ}|tjo| o|i| ƒqÅqd|} qdWt}dk} | i| ƒo| idjo t}qTnOt| dtƒ}|tj o%t|d ƒ o t}n|} n tƒ‚|tjo t| d ƒo | i}n| i| ƒ\}}}}|tjo d }n t |ƒ}t |ƒd }||} t |ƒ}|o d }n|d jo|| jo t‚qcnI| |jo |jno!|tjo||j}qcn tƒ‚|tjo t}nt$|ii|ƒ| i%ƒ} t|d ƒo|i| _n| | |ŒSdS(sProcess a single request.sroots)ObjectApplication requires a root object.s PATH_INFOss/s_Nsindexs containeriiiÿÿÿÿsrequest('shasattrsselfsAttributeErrorsrequestsenvironsgetsstripspathssplitspartssrootshandlersargssparts startswiths PageNotFoundsgetattrsNonesnodesappends containersinspectsismethods__name__sFalsesindexsTrues getargspecs handler_argssvarargss_sdefaultsslensmax_lensmin_lenscur_lens fix_slashsim_classsparent(sselfscur_lensmax_lens handler_argssindexs containerspartssnodesargssparentsmin_lenshandlersinspectspartsvarargsspaths_sdefaults((s2build/bdist.linux-i686/egg/colubrid/application.pysprocess_request sh !                      (s__name__s __module__s__doc__sprocess_request(((s2build/bdist.linux-i686/egg/colubrid/application.pysObjectApplicationês cBstZdZeZd„ZRS(sY Application that uses Routes (http://routes.groovie.org/) to dispatch URLs. cs͇d†}ttˆƒi|||ƒˆiiidƒpd}ˆi i |ƒ}|t jo t ƒ‚nˆi|d}|iƒ}ˆi|_|ddjo |d=n|d=|||SdS(Ncstˆ|||ƒSdS(N(s RoutesRequestsselfsesssc(sesssc(sself(s2build/bdist.linux-i686/egg/colubrid/application.pyscreate_requestass PATH_INFOs/s controllersactionsindex(screate_requestssupersRoutesApplicationsselfs__init__senvironsstart_responsesrequestsgetspaths_routes_mappersmatchsNones PageNotFounds_routes_controllersshandlersim_classsapp(sselfsenvironsstart_responseshandlerspathscreate_requestsappsmatch((sselfs2build/bdist.linux-i686/egg/colubrid/application.pys__init__`s      (s__name__s __module__s__doc__sRoutesMapperClasss __metaclass__s__init__(((s2build/bdist.linux-i686/egg/colubrid/application.pysRoutesApplicationYs (s__doc__s __future__s generatorsscolubrid.requestsRequestsResponseRequests RoutesRequestscolubrid.responses HttpResponsescolubrid.utilss fix_slashscolubrid.exceptionss HttpExceptions PageNotFoundsres__all__stypesRegexCompilerClasssRoutesMapperClasssobjectsBaseApplicationsRegexApplicationsResolveRegexApplicationsWebpyApplicationsPathApplicationsObjectApplicationsRoutesApplication(sResolveRegexApplications__all__s HttpExceptionsBaseApplications PageNotFoundsRequestsRegexApplications fix_slashs RoutesRequestsresWebpyApplications generatorssRoutesMapperClasssObjectApplicationsRoutesApplications HttpResponsesPathApplicationsRegexCompilerClasssResponseRequest((s2build/bdist.linux-i686/egg/colubrid/application.pys?s     ! ,oPK#”*5§büücolubrid/response.py# -*- coding: utf-8 -*- """ Colubrid Response """ from __future__ import generators from colubrid.utils import HttpHeaders from colubrid.const import HTTP_STATUS_CODES from Cookie import SimpleCookie from datetime import datetime from time import gmtime __all__ = ('HttpResponse',) class HttpResponse(object): """ The Response object is used to collect the data to be written back to the HTTP client. """ def __init__(self, response=None, headers=None, status=200): if response is None: self.response = [] elif isinstance(response, basestring): self.response = [response] else: self.response = response if headers is None: self.headers = HttpHeaders([]) elif isinstance(headers, list): self.headers = HttpHeaders(headers) elif isinstance(headers, HttpHeaders): self.headers = headers else: raise TypeError('invalid header format') self.status = status self._cookies = None def __setitem__(self, name, value): self.headers[name] = value def __getitem__(self, name): self.headers.get(name) def __delitem__(self, name): del self.headers[name] def __contains__(self, name): return name in self.headers def __len__(self): if isinstance(self.response, list): length = 0 for item in self.response: length += len(item) return length try: return len(self.response) except: return 0 def write(self, d): if not isinstance(self.response, list): raise TypeError('read only or dynamic response object') elif isinstance(d, basestring): self.response.append(d) else: raise TypeError('str or unicode required') def set_cookie(self, key, value='', max_age=None, expires=None, path='/', domain=None, secure=None): if self._cookies is None: self._cookies = SimpleCookie() self._cookies[key] = value if not max_age is None: self._cookies[key]['max-age'] = max_age if not expires is None: if isinstance(expires, basestring): self._cookies[key]['expires'] = expires expires = None elif isinstance(expires, datetime): expires = expires.utctimetuple() elif not isinstance(expires, (int, long)): expires = gmtime(expires) else: raise ValueError('datetime or integer required') if not expires is None: now = gmtime() month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][now.tm_mon - 1] day = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'][expires.tm_wday] date = '%02d-%s-%s' % ( now.tm_mday, month, str(now.tm_year)[-2:] ) d = '%s, %s %02d:%02d:%02d GMT' % (day, date, now.tm_hour, now.tm_min, now.tm_sec) self._cookies[key]['expires'] = d if not path is None: self._cookies[key]['path'] = path if not domain is None: self._cookies[key]['domain'] = domain if not secure is None: self._cookies[key]['secure'] = secure def delete_cookie(self, key): if self._cookies is None: self._cookies = SimpleCookie() if not key in self._cookies: self._cookies[key] = '' self._cookies[key]['max-age'] = 0 def __call__(self, request): if not 'Content-Type' in self.headers: self.headers['Content-Type'] = 'text/html; charset=%s' % \ str(request.charset) headers = self.headers.get() if not self._cookies is None: for morsel in self._cookies.values(): headers.append(('Set-Cookie', morsel.output(header=''))) status = '%d %s' % (self.status, HTTP_STATUS_CODES.get(self.status, 'UNKNOWN')) request.start_response(status, headers) if self.response is None: yield '' elif isinstance(self.response, unicode): yield self.response.encode(request.charset) elif isinstance(self.response, str): yield self.response else: try: iterator = iter(self.response) except TypeError: raise TypeError('%r is not an valid response' % self.response) for line in iterator: if isinstance(line, unicode): yield line.encode(request.charset) elif isinstance(line, str): yield line else: raise TypeError('%r is not string or unicode' % line) PK)W4mÖE•È È colubrid/reloader.py# -*- coding: utf-8 -*- """ Reloader Module =============== Taken from django, which took it from cherrypy / paste """ # Portions copyright (c) 2004, CherryPy Team (team@cherrypy.org) # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # * Neither the name of the CherryPy Team nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import os import sys import thread import time RUN_RELOADER = True def reloader_thread(watch): """This thread watches Python and "watch" files and reloads the application if something changes.""" mtimes = {} win = sys.platform == 'win32' while RUN_RELOADER: for filename in [getattr(m, '__file__', '') for m in sys.modules.values()] + watch: if filename[-4:] in ('.pyo', '.pyc'): filename = filename[:-1] if not os.path.exists(filename): continue stat = os.stat(filename) mtime = stat.st_mtime if win: mtime -= stat.st_ctime if filename not in mtimes: mtimes[filename] = mtime continue if mtime != mtimes[filename]: sys.exit(3) # force reload time.sleep(1) def restart_with_reloader(): """Spawn a new Python interpreter with the same arguments as this one, but running the reloader thread.""" while True: args = [sys.executable] + sys.argv if sys.platform == 'win32': args = ['"%s"' % arg for arg in args] new_environ = os.environ.copy() new_environ['RUN_MAIN'] = 'true' exit_code = os.spawnve(os.P_WAIT, sys.executable, args, new_environ) if exit_code != 3: return exit_code def main(main_func, watch=[]): """Call this to initialize the reloader.""" if os.environ.get('RUN_MAIN') == 'true': thread.start_new_thread(main_func, ()) try: reloader_thread(watch) except KeyboardInterrupt: pass else: try: sys.exit(restart_with_reloader()) except KeyboardInterrupt: pass PK§pÄ4oÞݺ` ` colubrid/exceptions.py# -*- coding: utf-8 -*- """ Colubrid Exceptions =================== Since paste covers that too this is only a "redirection module". Because colubrid may change the error interface later it's better to use the mapped names instead of the paste.httpexceptions module. """ __all__ = ['PageNotFound', 'PageGone', 'AccessDenied', 'BadRequest', 'RequestTimeout', 'ServerError', 'HttpRedirect', 'HttpFound', 'HttpMoved'] ERROR_PAGE_TEMPLATE = """\ %(code)s %(title)s

%(title)s

%(msg)s
powered by colubrid %(version)s
""" class HttpException(Exception): """Base for HTTP exceptions. Not to be used directly.""" code = None title = None msg = '' headers = None def get_error_page(self): from colubrid.utils import get_version from cgi import escape return ERROR_PAGE_TEMPLATE % { 'code': self.code, 'title': escape(self.title), 'msg': escape(self.msg), 'version': get_version() } def get_headers(self): if not self.headers: return [] return self.headers[:] def __repr__(self): return '<%s %d>' % (self.__class__.__name__, self.code) class HttpMove(HttpException): """Automatically add a "Location:" header to the result.""" msg = 'The resource has been moved to %s.' def __init__(self, url): self.headers = [('Location', url)] if '%s' in self.msg: self.msg = self.msg % url class PageNotFound(HttpException): """HTTP 404.""" code = 404 title = 'Not Found' msg = 'The resource could not be found.' class PageGone(HttpException): """HTTP 410.""" code = 410 title = 'Gone' msg = ('This resource is no longer available. ' 'No forwarding address is given.') class AccessDenied(HttpException): """HTTP 403.""" code = 403 title = 'Forbidden' msg = 'Access was denied to this resource.' class BadRequest(HttpException): """HTTP 400.""" code = 400 title = 'Bad Request' msg = 'The server could not comply with the request since it is either '\ 'malformed or wtherwise incorrect.' class RequestTimeout(HttpException): """HTTP 408.""" code = 408 title = 'Request Timeout' msg = 'There was a conflict when trying to complete your request.' class ServerError(HttpException): """HTTP 500.""" code = 500 title = 'Internal Server Error' msg = 'The server has either erred or is inapable of performing '\ 'the requested operation.' class HttpRedirect(HttpMove): """HTTP 307.""" code = 307 title = 'Temporary Redirect' class HttpFound(HttpMove): """HTTP 302.""" code = 302 title = 'Found' msg = 'The resource was found at %s.' class HttpMoved(HttpMove): """HTTP 301.""" code = 301 title = 'Moved Permanently' PK%œ*5ý~¬r? ? colubrid/server.py# -*- coding: utf-8 -*- """ Colubrid Execute ================ Since the 0.10 version of colubrid this is only a small helper module which uses paster to serve the application. """ from __future__ import generators import sys import os from threading import Thread __all__ = ('execute', 'run_test', 'stop_test') class StaticExports(object): def __init__(self, app, exports): self.application = app self.exports = exports def serve_file(self, filename, start_response): from mimetypes import guess_type guessed_type = guess_type(filename) if guessed_type[0] is None: mime_type = 'text/plain' else: mime_type = guessed_type[0] start_response('200 OK', [('Content-Type', mime_type)]) fp = file(filename, 'rb') try: result = fp.read() finally: fp.close() return iter([result]) def __call__(self, environ, start_response): path_info = environ.get('PATH_INFO', '') for search_path, file_path in self.exports.iteritems(): if not search_path.endswith('/'): search_path += '/' if path_info.startswith(search_path): real_path = os.path.join(file_path, path_info[len(search_path):]) if os.path.exists(real_path) and os.path.isfile(real_path): return self.serve_file(real_path, start_response) return self.application(environ, start_response) def execute(app=None, debug=True, hostname='localhost', port=8080, reload=False, evalex=False): if app is None: frm = sys._getframe().f_back if not 'app' in frm.f_globals: raise RuntimeError('no application found') app = frm.f_globals['app'] if debug: from colubrid.debug import DebuggedApplication app = DebuggedApplication(app, evalex) try: from paste import httpserver run = lambda: httpserver.serve(app, host=hostname, port=str(port)) except ImportError: try: from BaseWSGIServer import WSGIServer run = WSGIServer(app, hostname, port).serve_forever except ImportError: try: from wsgiref.simple_server import make_server run = make_server(hostname, port, app).serve_forever except ImportError: run = None if run is None: raise RuntimeError('no standalone wsgi server found') if reload: from colubrid import reloader reloader.main(run) else: run() PKò¢*5Ý&1.f{f{colubrid/debug.pyc;ò öÄÿDc@sgdZdklZdkZdkZdkZdkZdkZdkZdk Z dk Z dk Z dk Z dk Z dkZdklZdklZdklZdZdZd„Zd d „Zeed „Zd „Zd efd„ƒYZdefd„ƒYZdefd„ƒYZdefd„ƒYZ defd„ƒYZ!defd„ƒYZ"dS(so Colubrid Debugging Module ========================= Adds debug support to colubrid applications. (s generatorsN(srandom(sStringIO(sescapes” function toggleBlock(handler) { if (handler.nodeName == 'H3') { var table = handler; do { table = table.nextSibling; if (typeof table == 'undefined') { return; } } while (table.nodeName != 'TABLE'); } else if (handler.nodeName == 'DT') { var parent = handler.parentNode; var table = parent.getElementsByTagName('TABLE')[0]; } var lines = table.getElementsByTagName("TR"); for (var i = 0; i < lines.length; i++) { var line = lines[i]; if (line.className == 'pre' || line.className == 'post') { line.style.display = (line.style.display == 'none') ? '' : 'none'; } else if (line.parentNode.parentNode.className == 'vars' || line.parentNode.parentNode.className == 'exec_code') { line.style.display = (line.style.display == 'none') ? '' : 'none'; var input = line.getElementsByTagName('TEXTAREA'); if (input.length) { input[0].focus(); } } } } function initTB() { var tb = document.getElementById('wsgi-traceback'); var handlers = tb.getElementsByTagName('H3'); for (var i = 0; i < handlers.length; i++) { toggleBlock(handlers[i]); handlers[i].setAttribute('onclick', 'toggleBlock(this)'); } handlers = tb.getElementsByTagName('DT'); for (var i = 0; i < handlers.length; i++) { toggleBlock(handlers[i]); handlers[i].setAttribute('onclick', 'toggleBlock(this)'); } var handlers = tb.getElementsByTagName('TEXTAREA'); for (var i = 0; i < handlers.length; i++) { var hid = handlers[i].getAttribute('id'); if (hid && hid.substr(0, 6) == 'input-') { var p = handlers[i].getAttribute('id').split('-'); handlers[i].onkeyup = makeEnter(p[1], p[2]); } } } AJAX_ACTIVEX = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0']; function ajaxConnect() { var con = null; try { con = new XMLHttpRequest(); } catch (e) { if (typeof AJAX_ACTIVEX == 'string') { con = new ActiveXObject(AJAX_ACTIVEX); } else { for (var i=0; i < AJAX_ACTIVEX.length; i++) { var axid = AJAX_ACTIVEX[i]; try { con = new ActiveXObject(axid); } catch (e) {} if (con) { AJAX_ACTIVEX = axid; break; } } } } return con; } function execCode(traceback, frame) { var input = document.getElementById('input-' + traceback + '-' + frame); var e = encodeURIComponent; var data = 'tb=' + e(traceback) + '&' + 'frame=' + e(frame) + '&' + 'code=' + e(input.value); writeToOutput(traceback, frame, '>>> ' + input.value); var con = ajaxConnect(); con.onreadystatechange = function() { if (con.readyState == 4 && con.status == 200) { writeToOutput(traceback, frame, con.responseText); input.focus(); input.value = ''; } }; con.open('GET', '__traceback__?' + data); con.send(data); } function makeEnter(traceback, frame) { return function(e) { var e = (e) ? e : window.event; var code = (e.keyCode) ? e.keyCode : e.which; if (code == 13) { var input = document.getElementById('input-' + traceback + '-' + frame); if (input.className == 'big') { if (input.value.substr(input.value.length - 2) != '\n\n') { return; } input.value = input.value.substr(0, input.value.length - 1); input.className = 'small'; } if (input.value == 'clear\n') { clearOutput(traceback, frame); input.value = ''; } else { execCode(traceback, frame); } } } } function writeToOutput(traceback, frame, text) { var output = document.getElementById('output-' + traceback + '-' + frame); if (text && text != '\n') { var node = document.createTextNode(text); output.appendChild(node); } } function clearOutput(traceback, frame) { var output = document.getElementById('output-' + traceback + '-' + frame); output.innerHTML = ''; } function toggleExtend(traceback, frame) { var input = document.getElementById('input-' + traceback + '-' + frame); input.className = (input.className == 'small') ? 'big' : 'small'; input.focus(); } function change_tb() { interactive = document.getElementById('interactive'); plain = document.getElementById('plain'); interactive.style.display = ((interactive.style.display == 'block') | (interactive.style.display == '')) ? 'none' : 'block'; plain.style.display = (plain.style.display == 'block') ? 'none' : 'block'; } sš body { font-size:0.9em; } * { margin:0; padding:0; } #wsgi-traceback { margin: 1em; border: 1px solid #5F9CC4; background-color: #F6F6F6; } .footer { margin: 1em; text-align: right; font-style: italic; } h1 { background-color: #3F7CA4; font-size:1.2em; color:#FFFFFF; padding:0.3em; margin:0 0 0.2em 0; } h2 { background-color:#5F9CC4; font-size:1em; color:#FFFFFF; padding:0.3em; margin:0.4em 0 0.2em 0; } h2.tb { cursor:pointer; } h3 { font-size:1em; cursor:pointer; } h3.fn { margin-top: 0.5em; } h3.fn:hover:before { content: "\21D2 "; } h3.indent { margin:0 0.7em 0 0.7em; font-weight:normal; } p.text { padding:0.1em 0.5em 0.1em 0.5em; } p.important { font-weight: bold; } div.frame { margin:0 1em 0 1em; } table.code { margin:0.5em 0.7em 0.3em 0.7em; background-color:#E0E0E0; width:100%; font-size:0.9em; border:1px solid #C9C9C9; border-collapse:collapse; } table.code td.lineno { width:42px; text-align:right; padding:0 5px 0 0; color:#444444; border-right:1px solid #888888; } table.code td.code { background-color:#EFEFEF; padding:0 0 0 5px; white-space:pre; } table.code tr.cur td.code { background-color: #FAFAFA; padding: 1px 0 1px 5px; white-space: pre; } pre.plain { margin:0.5em 1em 1em 1em; padding:0.5em; border:1px solid #999999; background-color: #FFFFFF; line-height: 120%; font-family: monospace; } table.exec_code { width:100%; margin:0 1em 0 1em; } table.exec_code td.input { width:100%; } table.exec_code textarea.small { width:100%; height:1.5em; border:1px solid #999999; } table.exec_code textarea.big { width:100%; height:5em; border:1px solid #999999; } table.exec_code input { height:1.5em; border:1px solid #999999; background-color:#FFFFFF; } table.exec_code td.extend { width:70px; padding:0 5px 0 5px; } table.exec_code td.output pre { font-family: monospace; white-space: pre-wrap; /* css-3 should we be so lucky... */ white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ white-space: -pre-wrap; /* Opera 4-6 ?? */ white-space: -o-pre-wrap; /* Opera 7 ?? */ word-wrap: break-word; /* Internet Explorer 5.5+ */ _white-space: pre; /* IE only hack to re-specify in addition to word-wrap */ } table.vars { margin:0 1.5em 0 1.5em; border-collapse:collapse; font-size: 0.9em; } table.vars td { font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; padding: 0.3em; border: 1px solid #ddd; vertical-align: top; background-color: white; } table.vars .name { font-style: italic; } table.vars .value { color: #555; } table.vars th { padding: 0.2em; border: 1px solid #ddd; background-color: #f2f2f2; text-align: left; } #plain { display: none; } dl dt { padding: 0.2em 0 0.2em 1em; font-weight: bold; cursor: pointer; background-color: #ddd; } dl dt:hover { background-color: #bbb; color: white; } dl dd { padding: 0 0 0 2em; background-color: #eee; } span.p-kw { font-weight:bold; } span.p-cmt { color:#8CBF83; } span.p-str { color:#DEA39B; } span.p-num { color:#D2A2D6; } span.p-op { color:#0000AA; } cCs!ttƒƒidƒdd!SdS(Nsbase64ii (sstrsrandomsencode(((s,build/bdist.linux-i686/egg/colubrid/debug.pysget_uid˜sicCs:|i} |iii} |ii}|ii i dƒ}| o/t i iti|ƒp ti|ƒƒ}n|dddfjo|d }n|ii i dƒ}|ii i dƒ}y7|tj o|i|ƒ}nt|ƒiƒ}Wn1d}ggf\} }ttf\} }n¦Xt|ƒ}|iƒ|i ƒ}t"d | |d ƒ} | |}y0|| d } || | d !} || |!}Wn)t&j ot} ggf} }nX| }hd |<d |<d |<d| <d| <d|<d| <d| <d|<d|<d|ssingleiis(ssyssstdoutspushscompilessscodesselfsglobalsslocalssexc_infosetypesvaluestbstb_nextsjoins tracebacksformat_exceptionsmsgswritesreleasesoutput(sselfssscodesvaluesmsgsetypesoutputstb((s,build/bdist.linux-i686/egg/colubrid/debug.pys exec_expr"s  (s__name__s __module__s__init__s exec_expr(((s,build/bdist.linux-i686/egg/colubrid/debug.pys EvalContexts s PythonParsercBs¬tZdZeidZeidZheid<eid<ei d<e i d<ei d<ei d<ed <ed siis(srescompiles open_tag_res close_tag_res open_tagsslinesslinestagsgroupsfinditersappendsreversesctagsotagsremove(slinessctags open_tagss open_tag_resotagstags close_tag_resline((s,build/bdist.linux-i686/egg/colubrid/debug.pyshtml_splitlines`s0   N(shtml_splitlinesslistsselfsoutsgetvalues splitlines(sselfshtml_splitlines((s,build/bdist.linux-i686/egg/colubrid/debug.pysget_html_output^s c Csx|\}}|\}} |i} |i||} | t |ƒ|_|t i tigjo|iidƒdSn| | jo|ii|i| | !ƒn|t it igjo| |_dSnt i|jo |t ijo t i}n.|t ijo ti|ƒo |i}n|ii|dƒ} |iid| ƒ|iit|ƒƒ|iidƒdS(Ns stxtss(ssrowsscolserowsecolsselfspossoldposslinessnewposslenstoktextstoktypestokensNEWLINEstokenizesNLsoutswritesrawsINDENTsDEDENTsLPARsOPsNAMEskeywords iskeywords_KEYWORDs_classessgetsclsnamesescape( sselfstoktypestoktexts.6s.8slinessrowsscolserowsecolsclsnamesoldpossnewpos((s,build/bdist.linux-i686/egg/colubrid/debug.pys__call__ys&       (s__name__s __module__s__doc__stokens NT_OFFSETs_KEYWORDs_TEXTsNUMBERsOPsSTRINGstokenizesCOMMENTsNAMEs ERRORTOKENs_classess__init__sparsesget_html_outputs__call__(((s,build/bdist.linux-i686/egg/colubrid/debug.pys PythonParser2s   `   s DebugRendercBsbtZd„Zd„Zd„Zd„Zd„Zd„Zd„Zd„Z d „Z d „Z RS( NcCs||_||_dS(N(scontextsselfscsevalex(sselfscontextsevalex((s,build/bdist.linux-i686/egg/colubrid/debug.pys__init__–s cCs5di|iƒ|iƒ|iƒ|iƒgƒSdS(Ns (sjoinsselfsheaders tracebacksrequest_informationsfooter(sself((s,build/bdist.linux-i686/egg/colubrid/debug.pysrenderšscCsÊdtdtdg}t|idƒo@t|iiƒ}t|ii ƒ}|d|d|g7}nt|idƒo<|d|ii d |ii d |ii d fg7}nd i |ƒSdS( Ns*s!s
sexception_types

%s

s

%s

s last_frames/

%s in %s, line %s

sfilenamesfunctionslinenos ( s JAVASCRIPTs STYLESHEETsdatashasattrsselfscsescapesexception_typestitlesexception_valuesexcs last_framesjoin(sselfsexcstitlesdata((s,build/bdist.linux-i686/egg/colubrid/debug.pysheader¢s<cCsd„}dg}|d}|tj o¥|d7}x5|dD])}|i|d||ƒƒ|d7}q?W|i|d||dƒƒ|d7}xR|d D])}|i|d ||ƒƒ|d7}qžWn|i|ddd ƒƒ|id ƒd i|ƒSdS(NcCs&did|d|d|gƒSdS(Nsss%is%s(sjoinsmodeslinenoscode(smodeslinenoscode((s,build/bdist.linux-i686/egg/colubrid/debug.pys render_line»ssscontext_linenois pre_contextsprescurs context_lines post_contextspostsSourcecode not availables
s (s render_linestmpsframeslinenosNoneslsappendsjoin(sselfsframestmpsls render_lineslineno((s,build/bdist.linux-i686/egg/colubrid/debug.pys render_codeºs$        cCsàt|tƒp-t|tƒpt|tƒp t|tƒo d|Snt|tƒp t|dƒo°|iƒ}|i ƒ| odSndg}x`|D]X\}}yt ti|ƒƒ}Wn d}nX|idt t|ƒƒ|fƒq¢W|idƒdi|ƒSnt|tƒo‚| odSnd g}xH|D]@}yt ti|ƒƒ}Wn d}nX|id |ƒqLW|idƒdi|ƒSnyt t|ƒƒ}Wn d}nXd |SdS( Ns>
%r
sitemss;
no data given
s8s?s:s
NameValue
%s%s
s ss"s0
%s
%s
(s isinstancesvars basestringsfloatsintslongsdictshasattrsitemsssortsresultskeysvaluesescapespprintspformatsvalsappendsreprsjoinslistsline(sselfsvarsvaluesvalsitemssresultskeysline((s,build/bdist.linux-i686/egg/colubrid/debug.pys var_tableÔsF@       '     cCs-dhdd<d|ii<d|<SdS(Ns
stargets#stb_uids frame_uid(sselfscstb_uidsuid(sselfsuid((s,build/bdist.linux-i686/egg/colubrid/debug.pysexec_code_table scCsUt|idƒ odSndg}|idƒxít|iiƒD]Ù\}}d|d|d|df|i |ƒg}|d o-|id i d |i |d ƒgƒƒn|i o |iio-|id i d |i|d ƒgƒƒn|idƒ|idi |ƒƒqEW|id i d|iƒgƒƒd i |ƒSdS(NsframesssQ

Traceback (click to switch to raw view)

A problem occurred in your Python WSGI application. Here is the sequence of function calls leading up to the error, in the order they occurred. Click on a header to show context lines.

s!
s

%s in %s

sfunctionsfilenamesvarss s.

⇒ local variables

s+

⇒ execute code

s frame_uids
(shasattrsselfscsresultsappends enumeratesframessnumsframes render_codeslinesjoins var_tablesevalexstb_uidsexec_code_tablesplain(sselfsnumsresultslinesframe((s,build/bdist.linux-i686/egg/colubrid/debug.pys tracebacks   . -- "cCs.t|idƒ odSnd|iiSdS(Nsplaintbss©

Here is the plain Python traceback for copy and paste:

%s
(shasattrsselfscsplaintb(sself((s,build/bdist.linux-i686/egg/colubrid/debug.pysplainDscCs‚dddg}t|idƒ o |d=nx@|iiD]2\}}|idt|ƒ|i |ƒfƒq;Wdi |ƒSdS(Ns

Request Data

s9

The following list contains all importants<request variables. Click on a header to expand the list.

sframesis
%s
%s
s ( sresultshasattrsselfscsreq_varsskeysinfosappendsescapes var_tablesjoin(sselfsinfosresultskey((s,build/bdist.linux-i686/egg/colubrid/debug.pysrequest_informationNs  *cCsAdidddt|idƒod|iipdgƒSdS(Ns s1s
s•splaintbss(sjoinshasattrsselfscsplaintb(sself((s,build/bdist.linux-i686/egg/colubrid/debug.pysfooter_s( s__name__s __module__s__init__srendersheaders render_codes var_tablesexec_code_tables tracebacksplainsrequest_informationsfooter(((s,build/bdist.linux-i686/egg/colubrid/debug.pys DebugRender”s     5  & sDebuggedApplicationcBs,tZdZed„Zd„Zd„ZRS(s Enables debugging support for a given application:: from colubrid.debug import DebuggedApplication from myapp import app app = DebuggedApplication(app) Or for a whole package:: app = DebuggedApplication("myapp:app") cCs„t|ƒ|_t|tƒ o ||_nKy"|iddƒ\|_|_Wn%t j o||_d|_nXh|_ dS(Ns:isapp( sboolsevalexsselfs isinstances applications basestringssplitsmoduleshandlers ValueErrors tracebacks(sselfs applicationsevalex((s,build/bdist.linux-i686/egg/colubrid/debug.pys__init__zs " ccs|io"|iddƒidƒidƒo«ti|dƒ}yK|i |dd}|dd} || } |d di d dƒ}Wnttfj oqÚX| i|ƒ}|d d d fgƒ|VdSnt}y‡t|dƒo|i||ƒ}n=t|idddgƒ}t||iƒ}|||ƒ}t|ƒ}x|D] } | VqXWWnuti |ƒt!i"ƒ}y d dfg} |d| ƒWnnX|i$|ƒ} t&|idƒ| |iƒVnXt|dƒo|i'ƒndS(Ns PATH_INFOss/s __traceback__s QUERY_STRINGstbisframescodes s200 OKs Content-Types text/plains applications text/htmls500 INTERNAL SERVER ERRORscolubrid.requestsclose((sselfsevalexsenvironsgetsstripsendswithscgisparse_qss parameterss tracebacksstbsframescontextsreplacescodes IndexErrorsKeyErrors exec_exprsresultsstart_responsesNonesappitershasattrs applications __import__smodulesgetattrshandlersappsiterslinesThreadedStreamsinstallssyssexc_infosheaderssget_debug_contexts debug_contexts debug_infosclose(sselfsenvironsstart_responsescodesappsmodulesresults parametersstbsframes debug_contextslinesheadersscontextsexc_infosappiter((s,build/bdist.linux-i686/egg/colubrid/debug.pys__call__†sH/      c CsX|\}} } | itj o | i} nditi|Œƒ}g} h}t}t iƒotƒ}h}|i|Dc@sRdZdkZdkZdkZdkZeZd„Zd„Zgd„Z dS(se Reloader Module =============== Taken from django, which took it from cherrypy / paste NcCs0h}tidj}xto xøgi}tiiƒD]}|t |ddƒƒq9~|D]¶}|dddfjo|d }nt ii|ƒ oq`nt i|ƒ}|i}|o||i8}n||jo|||<d?d@<dAdB<dCdD<dEdF<dGdH<dIdJ<dKdL<dMdN<dOdP<dQdR<dSdT<dUdV<dWdX<dYdZ<d[d\ %(code)s %(title)s

%(title)s

%(msg)s
powered by colubrid %(version)s
s HttpExceptioncBsAtZdZeZeZdZeZd„Zd„Z d„Z RS(s2Base for HTTP exceptions. Not to be used directly.scCsbdkl}dkl}thd|i<d||iƒ<d||iƒ<d|ƒ<SdS(N(s get_version(sescapescodestitlesmsgsversion( scolubrid.utilss get_versionscgisescapesERROR_PAGE_TEMPLATEsselfscodestitlesmsg(sselfs get_versionsescape((s1build/bdist.linux-i686/egg/colubrid/exceptions.pysget_error_page7s  cCs|i ogSn|iSdS(N(sselfsheaders(sself((s1build/bdist.linux-i686/egg/colubrid/exceptions.pys get_headersAs cCsd|ii|ifSdS(Ns<%s %d>(sselfs __class__s__name__scode(sself((s1build/bdist.linux-i686/egg/colubrid/exceptions.pys__repr__Fs( s__name__s __module__s__doc__sNonescodestitlesmsgsheaderssget_error_pages get_headerss__repr__(((s1build/bdist.linux-i686/egg/colubrid/exceptions.pys HttpException0s  sHttpMovecBstZdZdZd„ZRS(s5Automatically add a "Location:" header to the result.s"The resource has been moved to %s.cCs:d|fg|_d|ijo|i||_ndS(NsLocations%s(surlsselfsheaderssmsg(sselfsurl((s1build/bdist.linux-i686/egg/colubrid/exceptions.pys__init__Ns(s__name__s __module__s__doc__smsgs__init__(((s1build/bdist.linux-i686/egg/colubrid/exceptions.pysHttpMoveJs cBs tZdZdZdZdZRS(s HTTP 404.i”s Not Founds The resource could not be found.(s__name__s __module__s__doc__scodestitlesmsg(((s1build/bdist.linux-i686/egg/colubrid/exceptions.pys PageNotFoundTs cBs tZdZdZdZdZRS(s HTTP 410.išsGonesEThis resource is no longer available. No forwarding address is given.(s__name__s __module__s__doc__scodestitlesmsg(((s1build/bdist.linux-i686/egg/colubrid/exceptions.pysPageGone[s cBs tZdZdZdZdZRS(s HTTP 403.i“s Forbiddens#Access was denied to this resource.(s__name__s __module__s__doc__scodestitlesmsg(((s1build/bdist.linux-i686/egg/colubrid/exceptions.pys AccessDeniedcs cBs tZdZdZdZdZRS(s HTTP 400.is Bad RequestsaThe server could not comply with the request since it is either malformed or wtherwise incorrect.(s__name__s __module__s__doc__scodestitlesmsg(((s1build/bdist.linux-i686/egg/colubrid/exceptions.pys BadRequestjs cBs tZdZdZdZdZRS(s HTTP 408.i˜sRequest Timeouts:There was a conflict when trying to complete your request.(s__name__s __module__s__doc__scodestitlesmsg(((s1build/bdist.linux-i686/egg/colubrid/exceptions.pysRequestTimeoutrs cBs tZdZdZdZdZRS(s HTTP 500.iôsInternal Server ErrorsQThe server has either erred or is inapable of performing the requested operation.(s__name__s __module__s__doc__scodestitlesmsg(((s1build/bdist.linux-i686/egg/colubrid/exceptions.pys ServerErrorys cBstZdZdZdZRS(s HTTP 307.i3sTemporary Redirect(s__name__s __module__s__doc__scodestitle(((s1build/bdist.linux-i686/egg/colubrid/exceptions.pys HttpRedirects cBs tZdZdZdZdZRS(s HTTP 302.i.sFoundsThe resource was found at %s.(s__name__s __module__s__doc__scodestitlesmsg(((s1build/bdist.linux-i686/egg/colubrid/exceptions.pys HttpFound‡s cBstZdZdZdZRS(s HTTP 301.i-sMoved Permanently(s__name__s __module__s__doc__scodestitle(((s1build/bdist.linux-i686/egg/colubrid/exceptions.pys HttpMovedŽs N(s__doc__s__all__sERROR_PAGE_TEMPLATEs Exceptions HttpExceptionsHttpMoves PageNotFoundsPageGones AccessDenieds BadRequestsRequestTimeouts ServerErrors HttpRedirects HttpFounds HttpMoved( sPageGones HttpMoveds HttpRedirects__all__s HttpExceptionsHttpMovesRequestTimeouts PageNotFoundsERROR_PAGE_TEMPLATEs HttpFounds ServerErrors BadRequests AccessDenied((s1build/bdist.linux-i686/egg/colubrid/exceptions.pys? s! PKÏH'5ZX#&k&kcolubrid/debug.py# -*- coding: utf-8 -*- """ Colubrid Debugging Module ========================= Adds debug support to colubrid applications. """ from __future__ import generators import os import sys import re import traceback import keyword import token import tokenize import string import pprint import inspect import threading import cgi from random import random from cStringIO import StringIO from xml.sax.saxutils import escape JAVASCRIPT = r''' function toggleBlock(handler) { if (handler.nodeName == 'H3') { var table = handler; do { table = table.nextSibling; if (typeof table == 'undefined') { return; } } while (table.nodeName != 'TABLE'); } else if (handler.nodeName == 'DT') { var parent = handler.parentNode; var table = parent.getElementsByTagName('TABLE')[0]; } var lines = table.getElementsByTagName("TR"); for (var i = 0; i < lines.length; i++) { var line = lines[i]; if (line.className == 'pre' || line.className == 'post') { line.style.display = (line.style.display == 'none') ? '' : 'none'; } else if (line.parentNode.parentNode.className == 'vars' || line.parentNode.parentNode.className == 'exec_code') { line.style.display = (line.style.display == 'none') ? '' : 'none'; var input = line.getElementsByTagName('TEXTAREA'); if (input.length) { input[0].focus(); } } } } function initTB() { var tb = document.getElementById('wsgi-traceback'); var handlers = tb.getElementsByTagName('H3'); for (var i = 0; i < handlers.length; i++) { toggleBlock(handlers[i]); handlers[i].setAttribute('onclick', 'toggleBlock(this)'); } handlers = tb.getElementsByTagName('DT'); for (var i = 0; i < handlers.length; i++) { toggleBlock(handlers[i]); handlers[i].setAttribute('onclick', 'toggleBlock(this)'); } var handlers = tb.getElementsByTagName('TEXTAREA'); for (var i = 0; i < handlers.length; i++) { var hid = handlers[i].getAttribute('id'); if (hid && hid.substr(0, 6) == 'input-') { var p = handlers[i].getAttribute('id').split('-'); handlers[i].onkeyup = makeEnter(p[1], p[2]); } } } AJAX_ACTIVEX = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0']; function ajaxConnect() { var con = null; try { con = new XMLHttpRequest(); } catch (e) { if (typeof AJAX_ACTIVEX == 'string') { con = new ActiveXObject(AJAX_ACTIVEX); } else { for (var i=0; i < AJAX_ACTIVEX.length; i++) { var axid = AJAX_ACTIVEX[i]; try { con = new ActiveXObject(axid); } catch (e) {} if (con) { AJAX_ACTIVEX = axid; break; } } } } return con; } function execCode(traceback, frame) { var input = document.getElementById('input-' + traceback + '-' + frame); var e = encodeURIComponent; var data = 'tb=' + e(traceback) + '&' + 'frame=' + e(frame) + '&' + 'code=' + e(input.value); writeToOutput(traceback, frame, '>>> ' + input.value); var con = ajaxConnect(); con.onreadystatechange = function() { if (con.readyState == 4 && con.status == 200) { writeToOutput(traceback, frame, con.responseText); input.focus(); input.value = ''; } }; con.open('GET', '__traceback__?' + data); con.send(data); } function makeEnter(traceback, frame) { return function(e) { var e = (e) ? e : window.event; var code = (e.keyCode) ? e.keyCode : e.which; if (code == 13) { var input = document.getElementById('input-' + traceback + '-' + frame); if (input.className == 'big') { if (input.value.substr(input.value.length - 2) != '\n\n') { return; } input.value = input.value.substr(0, input.value.length - 1); input.className = 'small'; } if (input.value == 'clear\n') { clearOutput(traceback, frame); input.value = ''; } else { execCode(traceback, frame); } } } } function writeToOutput(traceback, frame, text) { var output = document.getElementById('output-' + traceback + '-' + frame); if (text && text != '\n') { var node = document.createTextNode(text); output.appendChild(node); } } function clearOutput(traceback, frame) { var output = document.getElementById('output-' + traceback + '-' + frame); output.innerHTML = ''; } function toggleExtend(traceback, frame) { var input = document.getElementById('input-' + traceback + '-' + frame); input.className = (input.className == 'small') ? 'big' : 'small'; input.focus(); } function change_tb() { interactive = document.getElementById('interactive'); plain = document.getElementById('plain'); interactive.style.display = ((interactive.style.display == 'block') | (interactive.style.display == '')) ? 'none' : 'block'; plain.style.display = (plain.style.display == 'block') ? 'none' : 'block'; } ''' STYLESHEET = ''' body { font-size:0.9em; } * { margin:0; padding:0; } #wsgi-traceback { margin: 1em; border: 1px solid #5F9CC4; background-color: #F6F6F6; } .footer { margin: 1em; text-align: right; font-style: italic; } h1 { background-color: #3F7CA4; font-size:1.2em; color:#FFFFFF; padding:0.3em; margin:0 0 0.2em 0; } h2 { background-color:#5F9CC4; font-size:1em; color:#FFFFFF; padding:0.3em; margin:0.4em 0 0.2em 0; } h2.tb { cursor:pointer; } h3 { font-size:1em; cursor:pointer; } h3.fn { margin-top: 0.5em; } h3.fn:hover:before { content: "\\21D2 "; } h3.indent { margin:0 0.7em 0 0.7em; font-weight:normal; } p.text { padding:0.1em 0.5em 0.1em 0.5em; } p.important { font-weight: bold; } div.frame { margin:0 1em 0 1em; } table.code { margin:0.5em 0.7em 0.3em 0.7em; background-color:#E0E0E0; width:100%; font-size:0.9em; border:1px solid #C9C9C9; border-collapse:collapse; } table.code td.lineno { width:42px; text-align:right; padding:0 5px 0 0; color:#444444; border-right:1px solid #888888; } table.code td.code { background-color:#EFEFEF; padding:0 0 0 5px; white-space:pre; } table.code tr.cur td.code { background-color: #FAFAFA; padding: 1px 0 1px 5px; white-space: pre; } pre.plain { margin:0.5em 1em 1em 1em; padding:0.5em; border:1px solid #999999; background-color: #FFFFFF; line-height: 120%; font-family: monospace; } table.exec_code { width:100%; margin:0 1em 0 1em; } table.exec_code td.input { width:100%; } table.exec_code textarea.small { width:100%; height:1.5em; border:1px solid #999999; } table.exec_code textarea.big { width:100%; height:5em; border:1px solid #999999; } table.exec_code input { height:1.5em; border:1px solid #999999; background-color:#FFFFFF; } table.exec_code td.extend { width:70px; padding:0 5px 0 5px; } table.exec_code td.output pre { font-family: monospace; white-space: pre-wrap; /* css-3 should we be so lucky... */ white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ white-space: -pre-wrap; /* Opera 4-6 ?? */ white-space: -o-pre-wrap; /* Opera 7 ?? */ word-wrap: break-word; /* Internet Explorer 5.5+ */ _white-space: pre; /* IE only hack to re-specify in addition to word-wrap */ } table.vars { margin:0 1.5em 0 1.5em; border-collapse:collapse; font-size: 0.9em; } table.vars td { font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; padding: 0.3em; border: 1px solid #ddd; vertical-align: top; background-color: white; } table.vars .name { font-style: italic; } table.vars .value { color: #555; } table.vars th { padding: 0.2em; border: 1px solid #ddd; background-color: #f2f2f2; text-align: left; } #plain { display: none; } dl dt { padding: 0.2em 0 0.2em 1em; font-weight: bold; cursor: pointer; background-color: #ddd; } dl dt:hover { background-color: #bbb; color: white; } dl dd { padding: 0 0 0 2em; background-color: #eee; } span.p-kw { font-weight:bold; } span.p-cmt { color:#8CBF83; } span.p-str { color:#DEA39B; } span.p-num { color:#D2A2D6; } span.p-op { color:#0000AA; } ''' def get_uid(): return str(random()).encode('base64')[3:11] def get_frame_info(tb, context_lines=7): """ Return a dict of informations about a given traceback. """ # line numbers / function / variables lineno = tb.tb_lineno function = tb.tb_frame.f_code.co_name variables = tb.tb_frame.f_locals # get filename fn = tb.tb_frame.f_globals.get('__file__') if not fn: fn = os.path.realpath(inspect.getsourcefile(tb) or inspect.getfile(tb)) if fn[-4:] in ('.pyc', '.pyo'): fn = fn[:-1] # module name modname = tb.tb_frame.f_globals.get('__name__') # get loader loader = tb.tb_frame.f_globals.get('__loader__') # sourcecode try: if not loader is None: source = loader.get_source(modname) else: source = file(fn).read() except: source = '' pre_context, post_context = [], [] context_line, context_lineno = None, None else: parser = PythonParser(source) parser.parse() parsed_source = parser.get_html_output() lbound = max(0, lineno - context_lines - 1) ubound = lineno + context_lines try: context_line = parsed_source[lineno - 1] pre_context = parsed_source[lbound:lineno - 1] post_context = parsed_source[lineno:ubound] except IndexError: context_line = None pre_context = post_context = [], [] context_lineno = lbound return { 'tb': tb, 'filename': fn, 'loader': loader, 'function': function, 'lineno': lineno, 'vars': variables, 'pre_context': pre_context, 'context_line': context_line, 'post_context': post_context, 'context_lineno': context_lineno, 'source': source } def debug_info(request, context=None, evalex=True): """ Return debug info for the request """ if context is None: context = Namespace() req_vars = [] for item in dir(request): attr = getattr(request, item) if not (item.startswith("_") or inspect.isroutine(attr)): req_vars.append((item, attr)) req_vars.sort() context.req_vars = req_vars return DebugRender(context, evalex).render() def get_current_thread(): return threading.currentThread() class Namespace(object): def __init__(self, **kwds): self.__dict__.update(kwds) class ThreadedStream(object): _orig = None def __init__(self): self._buffer = {} def install(cls, environ): if cls._orig or not environ['wsgi.multithread']: return cls._orig = sys.stdout sys.stdout = cls() install = classmethod(install) def can_interact(cls): return not cls._orig is None can_interact = classmethod(can_interact) def push(self): tid = get_current_thread() self._buffer[tid] = StringIO() def release(self): tid = get_current_thread() if tid in self._buffer: result = self._buffer[tid].getvalue() del self._buffer[tid] else: result = '' return result def write(self, d): tid = get_current_thread() if tid in self._buffer: self._buffer[tid].write(d) else: self._orig.write(d) class EvalContext(object): def __init__(self, frm): self.locals = frm.f_locals self.globals = frm.f_globals def exec_expr(self, s): sys.stdout.push() try: try: code = compile(s, '', 'single', 0, 1) exec code in self.globals, self.locals except: etype, value, tb = sys.exc_info() tb = tb.tb_next msg = ''.join(traceback.format_exception(etype, value, tb)) sys.stdout.write(msg) finally: output = sys.stdout.release() return output class PythonParser(object): """ Simple python sourcecode highlighter. Usage:: p = PythonParser(source) p.parse() for line in p.get_html_output(): print line """ _KEYWORD = token.NT_OFFSET + 1 _TEXT = token.NT_OFFSET + 2 _classes = { token.NUMBER: 'num', token.OP: 'op', token.STRING: 'str', tokenize.COMMENT: 'cmt', token.NAME: 'id', token.ERRORTOKEN: 'error', _KEYWORD: 'kw', _TEXT: 'txt', } def __init__(self, raw): self.raw = raw.expandtabs(8).strip() self.out = StringIO() def parse(self): self.lines = [0, 0] pos = 0 while 1: pos = string.find(self.raw, '\n', pos) + 1 if not pos: break self.lines.append(pos) self.lines.append(len(self.raw)) self.pos = 0 text = StringIO(self.raw) try: tokenize.tokenize(text.readline, self) except tokenize.TokenError: pass def get_html_output(self): """ Return line generator. """ def html_splitlines(lines): # this cool function was taken from trac. # http://projects.edgewall.com/trac/ open_tag_re = re.compile(r'<(\w+)(\s.*)?[^/]?>') close_tag_re = re.compile(r'') open_tags = [] for line in lines: for tag in open_tags: line = tag.group(0) + line open_tags = [] for tag in open_tag_re.finditer(line): open_tags.append(tag) open_tags.reverse() for ctag in close_tag_re.finditer(line): for otag in open_tags: if otag.group(1) == ctag.group(1): open_tags.remove(otag) break for tag in open_tags: line += '' % tag.group(1) yield line return list(html_splitlines(self.out.getvalue().splitlines())) def __call__(self, toktype, toktext, (srow,scol), (erow,ecol), line): oldpos = self.pos newpos = self.lines[srow] + scol self.pos = newpos + len(toktext) if toktype in [token.NEWLINE, tokenize.NL]: self.out.write('\n') return if newpos > oldpos: self.out.write(self.raw[oldpos:newpos]) if toktype in [token.INDENT, token.DEDENT]: self.pos = newpos return if token.LPAR <= toktype and toktype <= token.OP: toktype = token.OP elif toktype == token.NAME and keyword.iskeyword(toktext): toktype = self._KEYWORD clsname = self._classes.get(toktype, 'txt') self.out.write('' % clsname) self.out.write(escape(toktext)) self.out.write('') class DebugRender(object): def __init__(self, context, evalex): self.c = context self.evalex = evalex def render(self): return '\n'.join([ self.header(), self.traceback(), self.request_information(), self.footer() ]) def header(self): data = [ '' % JAVASCRIPT, '' % STYLESHEET, '
' ] if hasattr(self.c, 'exception_type'): title = escape(self.c.exception_type) exc = escape(self.c.exception_value) data += [ '

%s

' % title, '

%s

' % exc ] if hasattr(self.c, 'last_frame'): data += [ '

%s in %s, line %s

' % ( self.c.last_frame['filename'], self.c.last_frame['function'], self.c.last_frame['lineno']) ] return '\n'.join(data) def render_code(self, frame): def render_line(mode, lineno, code): return ''.join([ '' % mode, '%i' % lineno, '%s' % code ]) tmp = [''] lineno = frame['context_lineno'] if not lineno is None: lineno += 1 for l in frame['pre_context']: tmp.append(render_line('pre', lineno, l)) lineno += 1 tmp.append(render_line('cur', lineno, frame['context_line'])) lineno += 1 for l in frame['post_context']: tmp.append(render_line('post', lineno, l)) lineno += 1 else: tmp.append(render_line('cur', 1, 'Sourcecode not available')) tmp.append('
') return '\n'.join(tmp) def var_table(self, var): # simple data types if isinstance(var, basestring) or isinstance(var, float)\ or isinstance(var, int) or isinstance(var, long): return ('
%r' '
' % var) # dicts if isinstance(var, dict) or hasattr(var, 'items'): items = var.items() items.sort() # empty dict if not items: return ('
no data given' '
') result = [''] for key, value in items: try: val = escape(pprint.pformat(value)) except: val = '?' result.append('' % (escape(repr(key)), val)) result.append('
Name' 'Value
%s%s' '
') return '\n'.join(result) # lists if isinstance(var, list): # empty list if not var: return ('
no data given' '
') result = [''] for line in var: try: val = escape(pprint.pformat(line)) except: val = '?' result.append('' % (val)) result.append('
%s
') return '\n'.join(result) # unknown things try: value = escape(repr(var)) except: value = '?' return '
%s
' % value def exec_code_table(self, uid): return '''
''' % { 'target': '#', 'tb_uid': self.c.tb_uid, 'frame_uid': uid } def traceback(self): if not hasattr(self.c, 'frames'): return '' result = ['

Traceback (click to switch to raw view)

'] result.append('

A problem occurred in your Python WSGI' ' application. Here is the sequence of function calls leading up to' ' the error, in the order they occurred. Click on a header to show' ' context lines.

') for num, frame in enumerate(self.c.frames): line = [ '
' % num, '

%s in %s

' % (frame['function'], frame['filename']), self.render_code(frame), ] if frame['vars']: line.append('\n'.join([ '

⇒ local variables

', self.var_table(frame['vars']) ])) if self.evalex and self.c.tb_uid: line.append('\n'.join([ '

⇒ execute code

', self.exec_code_table(frame['frame_uid']) ])) line.append('
') result.append(''.join(line)) result.append('\n'.join([ '
', self.plain() ])) return '\n'.join(result) def plain(self): if not hasattr(self.c, 'plaintb'): return '' return '''

Here is the plain Python traceback for copy and paste:

\n%s
''' % self.c.plaintb def request_information(self): result = [ '

Request Data

', '

The following list contains all important', 'request variables. Click on a header to expand the list.

' ] if not hasattr(self.c, 'frames'): del result[0] for key, info in self.c.req_vars: result.append('
%s
%s
' % ( escape(key), self.var_table(info) )) return '\n'.join(result) def footer(self): return '\n'.join([ '', '
', '', hasattr(self.c, 'plaintb') and ('' % self.c.plaintb) or '', ]) class DebuggedApplication(object): """ Enables debugging support for a given application:: from colubrid.debug import DebuggedApplication from myapp import app app = DebuggedApplication(app) Or for a whole package:: app = DebuggedApplication("myapp:app") """ def __init__(self, application, evalex=True): self.evalex = bool(evalex) if not isinstance(application, basestring): self.application = application else: try: self.module, self.handler = application.split(':', 1) except ValueError: self.module = application self.handler = 'app' self.tracebacks = {} def __call__(self, environ, start_response): # exec code in open tracebacks if self.evalex and environ.get('PATH_INFO', '').strip('/').endswith('__traceback__'): parameters = cgi.parse_qs(environ['QUERY_STRING']) try: tb = self.tracebacks[parameters['tb'][0]] frame = parameters['frame'][0] context = tb[frame] code = parameters['code'][0].replace('\r','') except (IndexError, KeyError): pass else: result = context.exec_expr(code) start_response('200 OK', [('Content-Type', 'text/plain')]) yield result return appiter = None try: if hasattr(self, 'application'): result = self.application(environ, start_response) else: module = __import__(self.module, '', '', ['']) app = getattr(module, self.handler) result = app(environ, start_response) appiter = iter(result) for line in appiter: yield line except: ThreadedStream.install(environ) exc_info = sys.exc_info() try: headers = [('Content-Type', 'text/html')] start_response('500 INTERNAL SERVER ERROR', headers) except: pass debug_context = self.get_debug_context(exc_info) yield debug_info(environ.get('colubrid.request'), debug_context, self.evalex) if hasattr(appiter, 'close'): appiter.close() def get_debug_context(self, exc_info): exception_type, exception_value, tb = exc_info # skip first internal frame if not tb.tb_next is None: tb = tb.tb_next plaintb = ''.join(traceback.format_exception(*exc_info)) # load frames frames = [] frame_map = {} tb_uid = None if ThreadedStream.can_interact(): tb_uid = get_uid() frame_map = self.tracebacks[tb_uid] = {} # walk through frames and collect informations while tb is not None: if tb_uid: frame_uid = get_uid() frame_map[frame_uid] = EvalContext(tb.tb_frame) else: frame_uid = None frame = get_frame_info(tb) frame['frame_uid'] = frame_uid frames.append(frame) tb = tb.tb_next if exception_type.__module__ == "exceptions": extypestr = exception_type.__name__ else: extypestr = str(exception_type) return Namespace( exception_type = extypestr, exception_value = str(exception_value), frames = frames, last_frame = frames[-1], plaintb = plaintb, tb_uid = tb_uid, frame_map = frame_map ) PKEFn4ž‹Û›ÖÖcolubrid/const.py# -*- coding: utf-8 -*- """ Colubrid Constants """ HTTP_STATUS_CODES = { 100: 'CONTINUE', 101: 'SWITCHING PROTOCOLS', 102: 'PROCESSING', 200: 'OK', 201: 'CREATED', 202: 'ACCEPTED', 203: 'NON-AUTHORITATIVE INFORMATION', 204: 'NO CONTENT', 205: 'RESET CONTENT', 206: 'PARTIAL CONTENT', 207: 'MULTI STATUS', 300: 'MULTIPLE CHOICES', 301: 'MOVED PERMANENTLY', 302: 'FOUND', 303: 'SEE OTHER', 304: 'NOT MODIFIED', 305: 'USE PROXY', 306: 'RESERVED', 307: 'TEMPORARY REDIRECT', 400: 'BAD REQUEST', 401: 'UNAUTHORIZED', 402: 'PAYMENT REQUIRED', 403: 'FORBIDDEN', 404: 'NOT FOUND', 405: 'METHOD NOT ALLOWED', 406: 'NOT ACCEPTABLE', 407: 'PROXY AUTHENTICATION REQUIRED', 408: 'REQUEST TIMEOUT', 409: 'CONFLICT', 410: 'GONE', 411: 'LENGTH REQUIRED', 412: 'PRECONDITION FAILED', 413: 'REQUEST ENTITY TOO LARGE', 414: 'REQUEST-URI TOO LONG', 415: 'UNSUPPORTED MEDIA TYPE', 416: 'REQUESTED RANGE NOT SATISFIABLE', 417: 'EXPECTATION FAILED', 500: 'INTERNAL SERVER ERROR', 501: 'NOT IMPLEMENTED', 502: 'BAD GATEWAY', 503: 'SERVICE UNAVAILABLE', 504: 'GATEWAY TIMEOUT', 505: 'HTTP VERSION NOT SUPPORTED', 506: 'VARIANT ALSO VARIES', 507: 'INSUFFICIENT STORAGE', 510: 'NOT EXTENDED' } PKò¢*5;bÇÁ/$/$colubrid/request.pyc;ò B>Ec@sãdZdklZdklZlZlZlZdkl Z dk Z dk Z dk Z dk lZdklZdklZdklZd d fZd efd „ƒYZd ee fd „ƒYZd efd„ƒYZdS(s9 Colubrid Request Object ======================= (s generators(s MultiDictsMergedMultiDicts FieldStorages get_full_url(s HttpResponseN(squote(sMessage(sStringIO(s SimpleCookiesRequestsResponseRequestcBsàtZdZdd„Zd„Zd„Zd„Zd„Zd„Zd„Z d „Z d „Z d „Z d „Z eed dƒZee d dƒZ ee d dƒZ ee d dƒZ ee d dƒZ ee d dƒZ RS(sY The central Request object. It stores all data coming from the HTTP client. sutf-8cCsë||_||_||_t|iƒ|id<||d<|iiddƒ}| p|idƒ od|}n||id?s(s WSGIServer(s make_serversno standalone wsgi server found(sreloader(sappsNonessyss _getframesf_backsfrms f_globalss RuntimeErrorsdebugscolubrid.debugsDebuggedApplicationsevalexspastes httpserversruns ImportErrorsBaseWSGIServers WSGIServershostnamesports serve_foreverswsgiref.simple_servers make_serversreloadscolubridsreloadersmain( sappsdebugshostnamesportsreloadsevalexsDebuggedApplications httpserversruns make_servers WSGIServersfrmsreloader((sappshostnamesports httpservers-build/bdist.linux-i686/egg/colubrid/server.pysexecute2s6       (s__doc__s __future__s generatorsssyssoss threadingsThreads__all__sobjects StaticExportssNonesTruesFalsesexecute(sexecutesThreads__all__ssyss StaticExportss generatorssos((s-build/bdist.linux-i686/egg/colubrid/server.pys?s    !PK#”*5»°D!^^colubrid/request.py# -*- coding: utf-8 -*- """ Colubrid Request Object ======================= """ from __future__ import generators from colubrid.utils import MultiDict, MergedMultiDict, FieldStorage,\ get_full_url from colubrid.response import HttpResponse import posixpath import cgi import email from urllib import quote from email.Message import Message as MessageType from cStringIO import StringIO from Cookie import SimpleCookie __all__ = ('Request', 'ResponseRequest') class Request(object): """ The central Request object. It stores all data coming from the HTTP client. """ def __init__(self, environ, start_response, charset='utf-8'): self.charset = charset self.start_response = start_response self.environ = environ self.environ['REQUEST_URI'] = get_full_url(self.environ) # copy a reference to the request object # into the environ so wsgi middlewares # can communicate with it. environ['colubrid.request'] = self # get absolute path to script root = self.environ.get('SCRIPT_NAME', '/') if not root or not root.startswith('/'): root = '/' + root self.environ['SCRIPT_ROOT'] = root # get the full application request url = ''.join([ quote(self.environ['SCRIPT_NAME']), quote(self.environ.get('PATH_INFO', '')) ]) if not url.startswith('/'): url = '/' + url self.environ['APPLICATION_REQUEST'] = url def read(self, *args): if not hasattr(self, '_buffered_stream'): self._buffered_stream = StringIO(self.data) return self._buffered_stream.read(*args) def readline(self, *args): if not hasattr(self, '_buffered_stream'): self._buffered_stream = StringIO(self.data) return self._buffered_stream.readline(*args) def readlines(self, *args): while True: line = self.readline(*args) if not line: raise StopIteration() yield line def _load_post_data(self): self._data = '' if self.environ['REQUEST_METHOD'] == 'POST': maxlen = int(self.environ['CONTENT_LENGTH']) self._data = self.environ['wsgi.input'].read(maxlen) if self.environ.get('CONTENT_TYPE', '').startswith('multipart'): lines = ['Content-Type: %s' % self.environ.get('CONTENT_TYPE', '')] for key, value in self.environ.items(): if key.startswith('HTTP_'): lines.append('%s: %s' % (key, value)) raw = '\r\n'.join(lines) + '\r\n\r\n' + self._data msg = email.message_from_string(raw) self._post = MultiDict() self._files = MultiDict() for sub in msg.get_payload(): if not isinstance(sub, MessageType): continue name_dict = cgi.parse_header(sub['Content-Disposition'])[1] if 'filename' in name_dict: payload = sub.get_payload() filename = name_dict['filename'] if isinstance(payload, list) or not filename.strip(): continue filename = name_dict['filename'] #XXX: fixes stupid ie bug but can cause problems filename = filename[filename.rfind('\\') + 1:] if 'Content-Type' in sub: content_type = sub['Content-Type'] else: content_type = None s = FieldStorage(name_dict['name'], filename, content_type, payload) self._files.appendlist(name_dict['name'], s) else: value = sub.get_payload() if not self.charset is None: value = value.decode(self.charset, 'ignore') self._post.appendlist(name_dict['name'], value) else: d = cgi.parse_qs(self._data, True) if not self.charset is None: for key, value in d.iteritems(): d[key] = [i.decode(self.charset, 'ignore') for i in value] self._post = MultiDict(d) self._files = MultiDict() else: self._post = MultiDict() self._files = MultiDict() def args(self): if not hasattr(self, '_get'): query = cgi.parse_qs(self.environ.get('QUERY_STRING', ''), True) if not self.charset is None: for key, value in query.iteritems(): query[key] = [i.decode(self.charset, 'ignore') for i in value] self._get = MultiDict(query) return self._get def form(self): if not hasattr(self, '_post'): self._load_post_data() return self._post def values(self): if not hasattr(self, '_values'): self._values = MergedMultiDict(self.args, self.form) return self._values def files(self): if not hasattr(self, '_files'): self._load_post_data() return self._files def cookies(self): if not hasattr(self, '_cookie'): self._cookie = SimpleCookie() self._cookie.load(self.environ.get('HTTP_COOKIE', '')) return self._cookie def data(self): if not hasattr(self, '_data'): self._load_post_data() return self._data args = property(args, doc='url paramters') form = property(form, doc='form data') files = property(files, doc='submitted files') values = property(values, doc='url parameters and form data') cookies = property(cookies, doc='cookies') data = property(data, doc='raw value of input stream') class ResponseRequest(Request, HttpResponse): """ A Request that's a Response too. This way users can call request.write() etc. """ def __init__(self, environ, start_response, charset='utf-8'): Request.__init__(self, environ, start_response, charset) HttpResponse.__init__(self, [], [], 200) class RoutesRequest(Request): def __init__(self, app, environ, start_response, charset='utf-8'): super(RoutesRequest, self).__init__(environ, start_response, charset) self.app = app def link_to(self, __controller__, **kwargs): controller = self.app._controller_map.get(__controller__) root = self.environ['SCRIPT_ROOT'] link = self.app._routes_map.generate(controller, **kwargs) if link is None: return root return posixpath.join(root, link[1:]) PKò¢*5VDÆ®®colubrid/__init__.pyc;ò äWEc@sJdZdZdZdZdkTdklZdklZdk l Z dS( s5 Colubrid WSGI Toolkit --------------------- s0.10s,Armin Ronacher s BSD License(s*(sRequest(s HttpResponse(sexecuteN( s__doc__s __version__s __author__s __license__scolubrid.applicationscolubrid.requestsRequestscolubrid.responses HttpResponsescolubrid.serversexecute(sexecutes __license__sRequests __author__s HttpResponses __version__((s/build/bdist.linux-i686/egg/colubrid/__init__.pys?s  PKò¢*5þF›Õcolubrid/response.pyc;ò B>Ec@swdZdklZdklZdklZdklZdk l Z dk l Z dfZ de fd„ƒYZd S( s Colubrid Response (s generators(s HttpHeaders(sHTTP_STATUS_CODES(s SimpleCookie(sdatetime(sgmtimes HttpResponsecBsƒtZdZeedd„Zd„Zd„Zd„Zd„Zd„Z d„Z d eed eed „Z d „Z d „Z RS(sd The Response object is used to collect the data to be written back to the HTTP client. iÈcCsÅ|tjo g|_n*t|tƒo|g|_n ||_|tjotgƒ|_nMt|tƒot|ƒ|_n*t|tƒo ||_n tdƒ‚||_ t|_ dS(Nsinvalid header format( sresponsesNonesselfs isinstances basestringsheaderss HttpHeadersslists TypeErrorsstatuss_cookies(sselfsresponsesheaderssstatus((s/build/bdist.linux-i686/egg/colubrid/response.pys__init__s       cCs||i|= 3 and not m[2] is None: kwargs['requirements'] = m[2] if len(m) == 4: kwargs.update(m[3]) mapper.connect(name, m[0], controller=internal, **kwargs) mapper.create_regs(controllers.keys()) result._routes_mapper = mapper result._routes_controllers = controllers result._controller_map = controller_map return result class BaseApplication(object): """ Base class for Colubrid applications. """ def __init__(self, environ, start_response, request_class=Request): charset = 'utf-8' if hasattr(self, 'charset'): charset = self.charset self.request = request_class(environ, start_response, charset) def process_http_exception(self, exc): """Default routine to process a HttpException.""" return HttpResponse(exc.get_error_page(), exc.get_headers(), exc.code) def process_request(self): """Process a request. Must be overridden.""" raise NotImplementedError() def __iter__(self): try: response = self.process_request() if isinstance(self.request, ResponseRequest): response = self.request else: assert isinstance(response, HttpResponse), \ 'process_request() must return a HttpResponse instance' except HttpException, exc: response = self.process_http_exception(exc) return response(self.request) class RegexApplication(BaseApplication): """ Application that maps URLs based on regular expressions. """ __metaclass__ = RegexCompilerClass def process_request(self): """Process a single request.""" path_info = self.request.environ.get('PATH_INFO', '/')[1:] if hasattr(self, 'slash_append') and self.slash_append: fix_slash(self.request.environ, True) for url, module in self.urls: matchobj = url.search(path_info) if not matchobj is None: args = matchobj.groups() if module in (True, False): return fix_slash(self.request.environ, module) elif not '.' in module: handler = getattr(self, module) else: parts = module.split('.') mname, fname = '.'.join(parts[:-1]), parts[-1] package = __import__(mname, '', '', ['']) handler = getattr(package, fname) args = list(args) args.insert(0, self.request) args = tuple(args) return handler(*args) raise PageNotFound() class ResolveRegexApplication(BaseApplication): """ Application that ... """ __metaclass__ = RegexCompilerClass def process_request(self): """Process a single request.""" path_info = self.request.environ.get('PATH_INFO', '/')[1:] if hasattr(self, 'slash_append') and self.slash_append: fix_slash(self.request.environ, True) for url, module in self.urls: matchobj = url.search(path_info) if not matchobj is None: args = matchobj.groups() new_args = [] for pos, value in enumerate(args): search = '$%d' % (pos + 1) if search in module: module = module.replace(search, value.replace('.', '_')) else: new_args.append(value) args = tuple(new_args) if not '.' in module: if not hasattr(self, module): raise PageNotFound handler = getattr(self, module) else: parts = module.split('.') mname, fname = '.'.join(parts[:-1]), parts[-1] try: package = __import__(mname, '', '', ['']) handler = getattr(package, fname) except (ImportError, AttributeError): raise PageNotFound args = list(args) args.insert(0, self.request) args = tuple(args) if handler in (True, False): return fix_slash(self.request.environ, handler) return handler(*args) raise PageNotFound() class WebpyApplication(BaseApplication): """ Application compatible with web.py. """ __metaclass__ = RegexCompilerClass def process_request(self): """Process a single request.""" path_info = self.request.environ.get('PATH_INFO', '/')[1:] if hasattr(self, 'slash_append') and self.slash_append: fix_slash(self.request.environ, True) for url, cls in self.urls: matchobj = url.search(path_info) if not matchobj is None: cls = cls() cls.request = self.request handler = getattr(cls, self.request.environ['REQUEST_METHOD']) if handler in (True, False): return fix_slash(self.request.environ, handler) return handler(*matchobj.groups()) raise PageNotFound() class PathApplication(BaseApplication): """ Application that dispatches based on the first path element. """ def process_request(self): """Process a single request.""" path_info = self.request.environ.get('PATH_INFO', '/').strip('/') parts = path_info.strip('/').split('/') if not len(parts) or not parts[0]: handler = 'show_index' args = () else: handler = 'show_%s' % parts[0] args = tuple(parts[1:]) if hasattr(self, handler): return getattr(self, handler)(*args) fix_slash(self.request.environ, True) raise PageNotFound() class ObjectApplication(BaseApplication): """ A rather complex application type. It uses python class structures to handler the user requests. an ObjectApplication might look like this: class HelloWorld(object): def index(self): self.request.write('Hello World!') def name(self, name="Nobody"): self.request.write('Hello %s!' % name) class AdminPanel(object): def index(self): pass def login(self): pass class DispatcherApplication(ObjectApplication): root = HelloWorld root.admin = AdminPanel app = DispatcherApplication Let's say that the application listens on localhost: http://localhost/ --> HelloWorld.index() http://localhost/name/ --> HelloWorld.name('Nobody') http://localhost/name/Max --> HelloWorld.name('Max') http://localhost/admin/ --> AdminPanel.index() http://localhost/admin/login --> AdminPanel.login() """ def process_request(self): """Process a single request.""" if not hasattr(self, 'root'): raise AttributeError, 'ObjectApplication requires a root object.' path = self.request.environ.get('PATH_INFO', '').strip('/') parts = path.split('/') # Resolve the path handler = self.root args = [] for part in parts: if part.startswith('_'): raise PageNotFound node = getattr(handler, part, None) if node is None: if part: args.append(part) else: handler = node container = None # Find handler and make first container check import inspect if inspect.ismethod(handler): if handler.__name__ == 'index': # the handler is called index so it's the leaf of # itself. we don't want a slash, even if forced container = False else: index = getattr(handler, 'index', None) if not index is None: if not hasattr(index, 'container'): container = True handler = index else: raise PageNotFound() # update with hardcoded container information if container is None and hasattr(handler, 'container'): container = handler.container # Check for handler arguments and update container handler_args, varargs, _, defaults = inspect.getargspec(handler) if defaults is None: defaults = 0 else: defaults = len(defaults) max_len = len(handler_args) - 1 min_len = max_len - defaults cur_len = len(args) if varargs: max_len = -1 # check if the number of arguments fits our handler if max_len == -1: if cur_len < min_len: raise PageNotFound elif min_len <= cur_len <= max_len: if container is None: container = cur_len < max_len else: raise PageNotFound() if container is None: container = False fix_slash(self.request.environ, container) # call handler parent = handler.im_class() if hasattr(self, 'request'): parent.request = self.request return handler(parent, *args) class RoutesApplication(BaseApplication): """ Application that uses Routes (http://routes.groovie.org/) to dispatch URLs. """ __metaclass__ = RoutesMapperClass def __init__(self, environ, start_response): def create_request(e, s, c): return RoutesRequest(self, e, s, c) super(RoutesApplication, self).__init__(environ, start_response, create_request) path = self.request.environ.get('PATH_INFO') or '/' match = self._routes_mapper.match(path) if match is None: raise PageNotFound() handler = self._routes_controllers[match['controller']] app = handler.im_class() app.request = self.request if match['action'] == 'index': del match['action'] del match['controller'] # XXX: can't return from __init__ return handler(app, **match) PKò¢*5úׇ§—F—Fcolubrid/utils.pyc;ò ?MÃDc@s¹dZdklZdklZdklZdkZd„Zde fd„ƒYZ de fd „ƒYZ d e fd „ƒYZ d e fd „ƒYZed„Zd„Zd„ZdS(s/ Colubrid Utilities ------------------ (s generators(squote(sStringIONcCs?dkl}dkl}d||idƒdiƒfSdS(s'return the colubrid and python version.(s __version__(sversions%s - Python %ss iN(scolubrids __version__ssyssversionssplitsstrip(s __version__sversion((s,build/bdist.linux-i686/egg/colubrid/utils.pys get_version s  s MultiDictcBs˜tZfd„Zd„Zd„ZeZed„Zd„Zd„Z ed„Z fd„Z d „Z d „Z d „Zd „Zd „Zd„ZRS(NcCsti||ƒdS(N(sdicts__init__sselfskey_to_list_mapping(sselfskey_to_list_mapping((s,build/bdist.linux-i686/egg/colubrid/utils.pys__init__scCs<ti||ƒ}y |dSWntj o gSnXdS(s} Return the last data value for this key, or [] if it's an empty list; raises KeyError if not found. iÿÿÿÿN(sdicts __getitem__sselfskeyslist_s IndexError(sselfskeyslist_((s,build/bdist.linux-i686/egg/colubrid/utils.pys __getitem__s  cCsti|||gƒdS(N(sdicts __setitem__sselfskeysvalue(sselfskeysvalue((s,build/bdist.linux-i686/egg/colubrid/utils.pys _setitem_list%scCsEy||}Wntj o |SnX|gjo|Sn|SdS(s<Return the default value if the requested data doesn't existN(sselfskeysvalsKeyErrorsdefault(sselfskeysdefaultsval((s,build/bdist.linux-i686/egg/colubrid/utils.pysget)s  cCs2yti||ƒSWntj o gSnXdS(s8Return an empty list if the requested data doesn't existN(sdicts __getitem__sselfskeysKeyError(sselfskey((s,build/bdist.linux-i686/egg/colubrid/utils.pysgetlist3s cCsti|||ƒdS(N(sdicts __setitem__sselfskeyslist_(sselfskeyslist_((s,build/bdist.linux-i686/egg/colubrid/utils.pyssetlist:scCs'||jo||| -1: if removed >= count: break else: removed += 1 data.append((_key, _value)) self.data = data def reset(self): """Reset to default headers.""" self.data = self._defaults def clear(self): """clears all headers""" self.data = [] def set(self, key, value): """remove all header tuples for key and add a new one """ self.remove(key) self.add(key, value) def get(self, key=False, httpformat=False): """returns matching headers as list if httpformat is set the result is a HTTP header formatted list. """ if not key: result = self.data elif not isinstance(key, basestring): raise TypeError('keys have to be string') else: result = [] for k, v in self.data: if k.lower() == key.lower(): result.append((str(k), str(v))) if httpformat: return '\n'.join(['%s: %s' % item for item in result]) return result def get_full_url(environ, append=None): if 'REQUEST_URI' in environ and append is None: return environ['REQUEST_URI'] url = environ['wsgi.url_scheme']+'://' if environ.get('HTTP_HOST'): url += environ['HTTP_HOST'] else: url += environ['SERVER_NAME'] if environ['wsgi.url_scheme'] == 'https': if environ['SERVER_PORT'] != '443': url += ':' + environ['SERVER_PORT'] else: if environ['SERVER_PORT'] != '80': url += ':' + environ['SERVER_PORT'] if append is None: url += quote(environ.get('SCRIPT_NAME', '')) url += quote(environ.get('PATH_INFO', '')) if environ.get('QUERY_STRING'): url += '?' + environ['QUERY_STRING'] else: url += append return url def splitpath(p): return [s for s in (posixpath.normpath(posixpath.join('/', p)) + (p and p[-1] == '/' and '/' or '')).split('/') if s] def fix_slash(environ, wantslash): """ Fixes the trailing slash in an url. If the user requests an container object without an slash it will appends one. Requested an non container object with an traling slash will result in an redirect to the same url without it. the QUERY_STRING won't get lost but post data would. So don't forget the slash problem in your form actions ;-) """ from colubrid.exceptions import HttpMoved #FIXME # argh. never did something that supid # find a better solution for that problem. url = quote(environ.get('SCRIPT_NAME', '')) url += quote(environ.get('PATH_INFO', '')) query = environ.get('QUERY_STRING', '') oldurl = query and ('%s?%s' % (url, query)) or url if oldurl and oldurl != '/': if url.endswith('/'): if not wantslash: url = url[:-1] else: if wantslash: url += '/' newurl = query and ('%s?%s' % (url, query)) or url if oldurl != newurl: raise HttpMoved(newurl) PKò¢*5°ííEGG-INFO/PKG-INFOMetadata-Version: 1.0 Name: Colubrid Version: 0.10 Summary: simple wsgi publisher Home-page: http://wsgiarea.pocoo.org/colubrid/ Author: Armin Ronacher Author-email: armin.ronacher@active-4.com License: BSD License Download-URL: http://wsgiarea.pocoo.org/colubrid/dist/Colubrid-0.10.tar.gz Description: Colubrid WSGI Toolkit --------------------- Keywords: wsgi web Platform: any Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Topic :: Internet :: WWW/HTTP Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content PKò¢*5àUÝ®®EGG-INFO/SOURCES.txtez_setup.py setup.py Colubrid.egg-info/PKG-INFO Colubrid.egg-info/SOURCES.txt Colubrid.egg-info/top_level.txt colubrid/__init__.py colubrid/application.py colubrid/const.py colubrid/debug.py colubrid/exceptions.py colubrid/reloader.py colubrid/request.py colubrid/response.py colubrid/server.py colubrid/utils.py examples/__init__.py examples/customapp.py examples/dynamicresponse.py examples/helloworld.py examples/objectapplication.py examples/uploaddemo.py examples/webpylike.py examples/resolv/__init__.py examples/resolv/application.py examples/resolv/apps/__init__.py examples/resolv/apps/app_test.py examples/static/test.txt examples/wiki/wiki.py examples/wiki/shared/screen.css PKò¢*5ZS EGG-INFO/top_level.txtcolubrid PKò¢*5EGG-INFO/not-zip-safePKò¢*5¾‰fj?j?¤colubrid/application.pycPK#”*5§büü¤ ?colubrid/response.pyPK)W4mÖE•È È ¤ÎScolubrid/reloader.pyPK§pÄ4oÞݺ` ` ¤Èacolubrid/exceptions.pyPK%œ*5ý~¬r? ? ¤\ocolubrid/server.pyPKò¢*5Ý&1.f{f{¤Ëycolubrid/debug.pycPKò¢*5a) Ë Ë ¤aõcolubrid/reloader.pycPKò¢*52¡Mcðð¤_colubrid/const.pycPKò¢*5wÁ_Á¥¥¤colubrid/exceptions.pycPKÏH'5ZX#&k&k¤Y!colubrid/debug.pyPKEFn4ž‹Û›ÖÖ¤®Œcolubrid/const.pyPKò¢*5;bÇÁ/$/$¤³’colubrid/request.pycPKò¢*5x8ÄkAA¤·colubrid/server.pycPK#”*5»°D!^^¤†Çcolubrid/request.pyPKò¢*5VDÆ®®¤ãcolubrid/__init__.pycPKò¢*5þF›Õ¤öåcolubrid/response.pycPK΢*5E¶2Ÿ¿¿¤=ÿcolubrid/__init__.pyPKox5¯¾F¾»2»2¤.colubrid/application.pyPKò¢*5úׇ§—F—F¤5colubrid/utils.pycPKub÷44„Í{N(N(¤å{colubrid/utils.pyPKò¢*5°íí¤b¤EGG-INFO/PKG-INFOPKò¢*5àUÝ®®¤~§EGG-INFO/SOURCES.txtPKò¢*5ZS ¤^ªEGG-INFO/top_level.txtPKò¢*5¤›ªEGG-INFO/not-zip-safePK,Ϊ