PK;^W7K[((paste/modpython.py"""WSGI Paste wrapper for mod_python. Requires Python 2.2 or greater. Example httpd.conf section for a Paste app with an ini file:: SetHandler python-program PythonHandler paste.modpython PythonOption paste.ini /some/location/your/pasteconfig.ini Or if you want to load a WSGI application under /your/homedir in the module ``startup`` and the WSGI app is ``app``:: SetHandler python-program PythonHandler paste.modpython PythonPath "['/virtual/project/directory'] + sys.path" PythonOption wsgi.application startup::app If you'd like to use a virtual installation, make sure to add it in the path like so:: SetHandler python-program PythonHandler paste.modpython PythonPath "['/virtual/project/directory', '/virtual/lib/python2.4/'] + sys.path" PythonOption paste.ini /virtual/project/directory/pasteconfig.ini Some WSGI implementations assume that the SCRIPT_NAME environ variable will always be equal to "the root URL of the app"; Apache probably won't act as you expect in that case. You can add another PythonOption directive to tell modpython_gateway to force that behavior: PythonOption SCRIPT_NAME /mcontrol Some WSGI applications need to be cleaned up when Apache exits. You can register a cleanup handler with yet another PythonOption directive: PythonOption wsgi.cleanup module::function The module.function will be called with no arguments on server shutdown, once for each child process or thread. This module highly based on Robert Brewer's, here: http://projects.amor.org/misc/svn/modpython_gateway.py """ import traceback try: from mod_python import apache except: pass from paste.deploy import loadapp class InputWrapper(object): def __init__(self, req): self.req = req def close(self): pass def read(self, size=-1): return self.req.read(size) def readline(self, size=-1): return self.req.readline(size) def readlines(self, hint=-1): return self.req.readlines(hint) def __iter__(self): line = self.readline() while line: yield line # Notice this won't prefetch the next line; it only # gets called if the generator is resumed. line = self.readline() class ErrorWrapper(object): def __init__(self, req): self.req = req def flush(self): pass def write(self, msg): self.req.log_error(msg) def writelines(self, seq): self.write(''.join(seq)) bad_value = ("You must provide a PythonOption '%s', either 'on' or 'off', " "when running a version of mod_python < 3.1") class Handler(object): def __init__(self, req): self.started = False options = req.get_options() # Threading and forking try: q = apache.mpm_query threaded = q(apache.AP_MPMQ_IS_THREADED) forked = q(apache.AP_MPMQ_IS_FORKED) except AttributeError: threaded = options.get('multithread', '').lower() if threaded == 'on': threaded = True elif threaded == 'off': threaded = False else: raise ValueError(bad_value % "multithread") forked = options.get('multiprocess', '').lower() if forked == 'on': forked = True elif forked == 'off': forked = False else: raise ValueError(bad_value % "multiprocess") env = self.environ = dict(apache.build_cgi_env(req)) if 'SCRIPT_NAME' in options: # Override SCRIPT_NAME and PATH_INFO if requested. env['SCRIPT_NAME'] = options['SCRIPT_NAME'] env['PATH_INFO'] = req.uri[len(options['SCRIPT_NAME']):] else: env['SCRIPT_NAME'] = '' env['PATH_INFO'] = req.uri env['wsgi.input'] = InputWrapper(req) env['wsgi.errors'] = ErrorWrapper(req) env['wsgi.version'] = (1, 0) env['wsgi.run_once'] = False if env.get("HTTPS") in ('yes', 'on', '1'): env['wsgi.url_scheme'] = 'https' else: env['wsgi.url_scheme'] = 'http' env['wsgi.multithread'] = threaded env['wsgi.multiprocess'] = forked self.request = req def run(self, application): try: result = application(self.environ, self.start_response) for data in result: self.write(data) if not self.started: self.request.set_content_length(0) if hasattr(result, 'close'): result.close() except: traceback.print_exc(None, self.environ['wsgi.errors']) if not self.started: self.request.status = 500 self.request.content_type = 'text/plain' data = "A server error occurred. Please contact the administrator." self.request.set_content_length(len(data)) self.request.write(data) def start_response(self, status, headers, exc_info=None): if exc_info: try: if self.started: raise exc_info[0], exc_info[1], exc_info[2] finally: exc_info = None self.request.status = int(status[:3]) for key, val in headers: if key.lower() == 'content-length': self.request.set_content_length(int(val)) elif key.lower() == 'content-type': self.request.content_type = val else: self.request.headers_out.add(key, val) return self.write def write(self, data): if not self.started: self.started = True self.request.write(data) startup = None cleanup = None wsgiapps = {} def handler(req): options = req.get_options() # Run a startup function if requested. global startup if 'wsgi.startup' in options and not startup: func = options['wsgi.startup'] if func: module_name, object_str = func.split('::', 1) module = __import__(module_name, globals(), locals(), ['']) startup = apache.resolve_object(module, object_str) startup(req) # Register a cleanup function if requested. global cleanup if 'wsgi.cleanup' in options and not cleanup: func = options['wsgi.cleanup'] if func: module_name, object_str = func.split('::', 1) module = __import__(module_name, globals(), locals(), ['']) cleanup = apache.resolve_object(module, object_str) def cleaner(data): cleanup() try: # apache.register_cleanup wasn't available until 3.1.4. apache.register_cleanup(cleaner) except AttributeError: req.server.register_cleanup(req, cleaner) # Import the wsgi 'application' callable and pass it to Handler.run global wsgiapps appini = options.get('paste.ini') app = None if appini: if appini not in wsgiapps: wsgiapps[appini] = loadapp("config:%s" % appini) app = wsgiapps[appini] # Import the wsgi 'application' callable and pass it to Handler.run appwsgi = options.get('wsgi.application') if appwsgi and not appini: modname, objname = appwsgi.split('::', 1) module = __import__(modname, globals(), locals(), ['']) app = getattr(module, objname) Handler(req).run(app) # status was set in Handler; always return apache.OK return apache.OK PK;^W7o2=Ȣ##paste/cgiapp.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php """ Application that runs a CGI script. """ import os import subprocess try: import select except ImportError: select = None from paste.util import converters __all__ = ['CGIError', 'CGIApplication'] class CGIError(Exception): """ Raised when the CGI script can't be found or doesn't act like a proper CGI script. """ class CGIApplication(object): """ This object acts as a proxy to a CGI application. You pass in the script path (``script``), an optional path to search for the script (if the name isn't absolute) (``path``). If you don't give a path, then ``$PATH`` will be used. """ def __init__(self, global_conf, script, path=None, include_os_environ=True, query_string=None): if global_conf: raise NotImplemented( "global_conf is no longer supported for CGIApplication " "(use make_cgi_application); please pass None instead") self.script_filename = script if path is None: path = os.environ.get('PATH', '').split(':') self.path = path if '?' in script: assert query_string is None, ( "You cannot have '?' in your script name (%r) and also " "give a query_string (%r)" % (script, query_string)) script, query_string = script.split('?', 1) if os.path.abspath(script) != script: # relative path for path_dir in self.path: if os.path.exists(os.path.join(path_dir, script)): self.script = os.path.join(path_dir, script) break else: raise CGIError( "Script %r not found in path %r" % (script, self.path)) else: self.script = script self.include_os_environ = include_os_environ self.query_string = query_string def __call__(self, environ, start_response): if 'REQUEST_URI' not in environ: environ['REQUEST_URI'] = ( environ.get('SCRIPT_NAME', '') + environ.get('PATH_INFO', '')) if self.include_os_environ: cgi_environ = os.environ.copy() else: cgi_environ = {} for name in environ: # Should unicode values be encoded? if (name.upper() == name and isinstance(environ[name], str)): cgi_environ[name] = environ[name] if self.query_string is not None: old = cgi_environ.get('QUERY_STRING', '') if old: old += '&' cgi_environ['QUERY_STRING'] = old + self.query_string cgi_environ['SCRIPT_FILENAME'] = self.script proc = subprocess.Popen( [self.script], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=cgi_environ, cwd=os.path.dirname(self.script), ) writer = CGIWriter(environ, start_response) if select: proc_communicate( proc, stdin=StdinReader.from_environ(environ), stdout=writer, stderr=environ['wsgi.errors']) else: stdout, stderr = proc.communicate(StdinReader.from_environ(environ).read()) if stderr: environ['wsgi.errors'].write(stderr) writer(stdout) if not writer.headers_finished: start_response(writer.status, writer.headers) return [] class CGIWriter(object): def __init__(self, environ, start_response): self.environ = environ self.start_response = start_response self.status = '200 OK' self.headers = [] self.headers_finished = False self.writer = None self.buffer = '' def write(self, data): if self.headers_finished: self.writer(data) return self.buffer += data while '\n' in self.buffer: if '\r\n' in self.buffer: line1, self.buffer = self.buffer.split('\r\n', 1) else: line1, self.buffer = self.buffer.split('\n', 1) if not line1: self.headers_finished = True self.writer = self.start_response( self.status, self.headers) self.writer(self.buffer) del self.buffer del self.headers del self.status break elif ':' not in line1: raise CGIError( "Bad header line: %r" % line1) else: name, value = line1.split(':', 1) value = value.lstrip() name = name.strip() if name.lower() == 'status': self.status = value else: self.headers.append((name, value)) class StdinReader(object): def __init__(self, stdin, content_length): self.stdin = stdin self.content_length = content_length def from_environ(cls, environ): length = environ.get('CONTENT_LENGTH') if length: length = int(length) else: length = 0 return cls(environ['wsgi.input'], length) from_environ = classmethod(from_environ) def read(self, size=None): if not self.content_length: return '' if size is None: text = self.stdin.read(self.content_length) else: text = self.stdin.read(min(self.content_length, size)) self.content_length -= len(text) return text def proc_communicate(proc, stdin=None, stdout=None, stderr=None): """ Run the given process, piping input/output/errors to the given file-like objects (which need not be actual file objects, unlike the arguments passed to Popen). Wait for process to terminate. Note: this is taken from the posix version of subprocess.Popen.communicate, but made more general through the use of file-like objects. """ read_set = [] write_set = [] input_buffer = '' trans_nl = proc.universal_newlines and hasattr(open, 'newlines') if proc.stdin: # Flush stdio buffer. This might block, if the user has # been writing to .stdin in an uncontrolled fashion. proc.stdin.flush() if input: write_set.append(proc.stdin) else: proc.stdin.close() else: assert stdin is None if proc.stdout: read_set.append(proc.stdout) else: assert stdout is None if proc.stderr: read_set.append(proc.stderr) else: assert stderr is None while read_set or write_set: rlist, wlist, xlist = select.select(read_set, write_set, []) if proc.stdin in wlist: # When select has indicated that the file is writable, # we can write up to PIPE_BUF bytes without risk # blocking. POSIX defines PIPE_BUF >= 512 next, input_buffer = input_buffer, '' next_len = 512-len(next) if next_len: next += stdin.read(next_len) if not next: proc.stdin.close() write_set.remove(proc.stdin) else: bytes_written = os.write(proc.stdin.fileno(), next) if bytes_written < len(next): input_buffer = next[bytes_written:] if proc.stdout in rlist: data = os.read(proc.stdout.fileno(), 1024) if data == "": proc.stdout.close() read_set.remove(proc.stdout) if trans_nl: data = proc._translate_newlines(data) stdout.write(data) if proc.stderr in rlist: data = os.read(proc.stderr.fileno(), 1024) if data == "": proc.stderr.close() read_set.remove(proc.stderr) if trans_nl: data = proc._translate_newlines(data) stderr.write(data) proc.wait() def make_cgi_application(global_conf, script, path=None, include_os_environ=None, query_string=None): """ This object acts as a proxy to a CGI application. You pass in the script path (``script``), an optional path to search for the script (if the name isn't absolute) (``path``). If you don't give a path, then ``$PATH`` will be used. """ if path is None: path = global_conf.get('path') or global_conf.get('PATH') include_os_environ = converters.asbool(include_os_environ) return CGIApplication( script, path=path, include_os_environ=include_os_environ, query_string=query_string) PK;^W7Zpaste/reloader.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php """ A file monitor and server restarter. Use this like: ..code-block:: Python import reloader reloader.install() Then make sure your server is installed with a shell script like:: err=3 while test "$err" -eq 3 ; do python server.py err="$?" done or is run from this .bat file (if you use Windows):: @echo off :repeat python server.py if %errorlevel% == 3 goto repeat or run a monitoring process in Python (``paster serve --reload`` does this). Use the watch_file(filename) function to cause a reload/restart for other other non-Python files (e.g., configuration files). """ import os import sys import time import threading from paste.util.classinstance import classinstancemethod def install(poll_interval=1): """ Install the reloading monitor. On some platforms server threads may not terminate when the main thread does, causing ports to remain open/locked. The ``raise_keyboard_interrupt`` option creates a unignorable signal which causes the whole application to shut-down (rudely). """ mon = Monitor(poll_interval=poll_interval) t = threading.Thread(target=mon.periodic_reload) t.setDaemon(True) t.start() class Monitor(object): instances = [] global_extra_files = [] def __init__(self, poll_interval): self.module_mtimes = {} self.keep_running = True self.poll_interval = poll_interval self.extra_files = self.global_extra_files[:] self.instances.append(self) def periodic_reload(self): while 1: if not self.check_reload(): # use os._exit() here and not sys.exit() since within a # thread sys.exit() just closes the given thread and # won't kill the process; note os._exit does not call # any atexit callbacks, nor does it do finally blocks, # flush open files, etc. In otherwords, it is rude. os._exit(3) break time.sleep(self.poll_interval) def check_reload(self): filenames = self.extra_files[:] for module in sys.modules.values(): try: filenames.append(module.__file__) except AttributeError: continue for filename in filenames: try: stat = os.stat(filename) if stat: mtime = stat.st_mtime else: mtime = 0 except (OSError, IOError): continue if filename.endswith('.pyc') and os.path.exists(filename[:-1]): mtime = max(os.stat(filename[:-1]).st_mtime, mtime) if not self.module_mtimes.has_key(filename): self.module_mtimes[filename] = mtime elif self.module_mtimes[filename] < mtime: print >> sys.stderr, ( "%s changed; reloading..." % filename) return False return True def watch_file(self, cls, filename): filename = os.path.abspath(filename) if self is None: for instance in cls.instances: instance.watch_file(filename) cls.global_extra_files.append(filename) else: self.extra_files.append(filename) watch_file = classinstancemethod(watch_file) watch_file = Monitor.watch_file PK-68 a66paste/fileapp.pyc; #Gc@sdZdkZdkZdkZdkZdkZdkTdkTdZddZ dddgZ de fdYZ de fd YZ d e fd YZde fd YZdS( s This module handles sending static content such as in-memory data or files. At this time it has cache helpers and understands the if-modified-since request header. N(s*iisDataAppsFileApps ArchiveStorecBsbtZdZddfZeedZdZedZdZdZ dZ d Z RS( s Returns an application that will send content in a single chunk, this application has support for setting cache-control and for responding to conditional (or HEAD) requests. Constructor Arguments: ``content`` the content being sent to the client ``headers`` the headers to send /w the response The remaining ``kwargs`` correspond to headers, where the underscore is replaced with a dash. These values are only added to the headers if they are not already provided; thus, they can be used for default values. Examples include, but are not limited to: ``content_type`` ``content_encoding`` ``content_location`` ``cache_control()`` This method provides validated construction of the ``Cache-Control`` header as well as providing for automated filling out of the ``EXPIRES`` header for HTTP/1.0 clients. ``set_content()`` This method provides a mechanism to set the content after the application has been constructed. This method does things like changing ``Last-Modified`` and ``Content-Length`` headers. sGETsHEADcKs t|tttfptt|_t|_t|_ d|_ |tj o ||_ n|pg|_x9|i D]+\}}t|}|i|i|q~Wti|idtt|i oti|in|tj o|i|ndS(Nisbytes(s isinstancesheadersstypesNoneslistsAssertionErrorsselfsexpiresscontentscontent_lengths last_modifiedsallowed_methodsskwargssitemssksvs get_headersheadersupdates ACCEPT_RANGESsTrues CONTENT_TYPEs set_content(sselfscontentsheaderssallowed_methodsskwargssheadersvsk((s1build/bdist.darwin-8.0.1-x86/egg/paste/fileapp.pys__init__;s"#         cKs'ti|i|pt|_|SdS(N(s CACHE_CONTROLsapplysselfsheadersskwargssNonesexpires(sselfskwargs((s1build/bdist.darwin-8.0.1-x86/egg/paste/fileapp.pys cache_controlNscCsv|tj pt|tjoti|_n ||_||_t||_ti |i d|i|SdS(Nstime( scontentsNonesAssertionErrors last_modifiedstimesselfslenscontent_lengths LAST_MODIFIEDsupdatesheaders(sselfscontents last_modified((s1build/bdist.darwin-8.0.1-x86/egg/paste/fileapp.pys set_contentRs   cKsti|i||SdS(N(sCONTENT_DISPOSITIONsapplysselfsheadersskwargs(sselfskwargs((s1build/bdist.darwin-8.0.1-x86/egg/paste/fileapp.pyscontent_disposition]scCsp|di}||ijo<td|dddi|ifg}|||Sn|i ||SdS(NsREQUEST_METHODsYou cannot %s a filesheaderssAllows,( senvironsuppersmethodsselfsallowed_methodssHTTPMethodNotAllowedsjoinsexcsstart_responsesget(sselfsenvironsstart_responsesexcsmethod((s1build/bdist.darwin-8.0.1-x86/egg/paste/fileapp.pys__call__as  !cCs"t|idt|iSdS(Ns-(sstrsselfs last_modifiedscontent_length(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/fileapp.pyscalculate_etagjscCs|i}|i} ti|| |itj oti|d|inyt i |} | onxk| D]_}|| jp |djo?x$tdtD]}|i|qW|d|dgSqpqpWnWn%tj o}|i||SnX| oyhti |} | t|ijo?x$tdtD]}|i|q@W|d|dgSnWqtj o}|i||SqXnd|idf\} }ti |} | o%d| djodt| djov| dd\} }|p |id}||ijp | |jo-t d |it|fi||Sqin|| d}t!i|d | d |d |it"i||||ijo|d |n|d||i#tj o|i#| |d!gSn| |fSdS(Nsdeltas*sentitys304 Not ModifiedsiisbytessWRange request was made beyond the end of the content, which is %s long. Range: %s s first_bytes last_bytes total_lengths200 OKs206 Partial Content($sselfsheadersscalculate_etags current_etagsETAGsupdatesexpiressNonesEXPIRESs IF_NONE_MATCHsparsesenvirons client_etagssetags list_headerssTruesheadsdeletesstart_responsesHTTPBadRequestsexceswsgi_applicationsIF_MODIFIED_SINCEs client_clocksints last_modifiedscontent_lengthslowersuppersRANGEsrangeslensHTTPRequestRangeNotSatisfiables CONTENT_RANGEsCONTENT_LENGTHscontent(sselfsenvironsstart_responsescontent_lengthsuppersheadsheaderssetagsexces client_etagsslowers client_clocks current_etagsrange((s1build/bdist.darwin-8.0.1-x86/egg/paste/fileapp.pysgetms\    /1  ( s__name__s __module__s__doc__sallowed_methodssNones__init__s cache_controls set_contentscontent_dispositions__call__scalculate_etagsget(((s1build/bdist.darwin-8.0.1-x86/egg/paste/fileapp.pysDataApps "    cBs8tZdZedZdZedZdZRS(s Returns an application that will send the file at the given filename. Adds a mime type based on ``mimetypes.guess_type()``. See DataApp for the arguments beyond ``filename``. cKsy||_|i\}}|o d|jo||defd?YZ,d@efdAYZ-dBefdCYZ.dDefdEYZ/dFe/fdGYZ0dHe/fdIYZ1dJe/fdKYZ2dLe/fdMYZ3dNe/fdOYZ4dPe/fdQYZ5dd d gZ6hZ7xne8i9D]]\Z:Z;e<e;e=ei>foe?e;eoe;i@oe;e7e;i@ %(title)s

%(title)s

%(body)s


%(server)s
s HTTPExceptioncBstZdZeZeZdZdZdZdZ fZ eeedZ edZ dZ dZdZdZed ZeZd ZRS( s the HTTP exception base class This encapsulates an HTTP response that interrupts normal application flow; but one which is not necessarly an error condition. For example, codes in the 300's are exceptions in that they interrupt normal processing; however, they are not considered errors. This class is complicated by 4 factors: 1. The content given to the exception may either be plain-text or as html-text. 2. The template may want to have string-substitutions taken from the current ``environ`` or values from incoming headers. This is especially troublesome due to case sensitivity. 3. The final output may either be text/plain or text/html mime-type as requested by the client application. 4. Each exception has a default explanation, but those who raise exceptions may want to provide additional detail. Attributes: ``code`` the HTTP status code for the exception ``title`` remainder of the status line (stuff after the code) ``explanation`` a plain-text explanation of the error message that is not subject to environment or header substitutions; it is accessible in the template via %(explanation)s ``detail`` a plain-text message customization that is not subject to environment or header substitutions; accessible in the template via %(detail)s ``template`` a content fragment (in HTML) used for environment and header substitution; the default template includes both the explanation and further detail provided in the message ``required_headers`` a sequence of headers which are required for proper construction of the exception Parameters: ``detail`` a plain-text override of the default ``detail`` ``headers`` a list of (k,v) header pairs ``comment`` a plain-text additional information which is usually stripped/hidden for end-users To override the template (which is HTML content) or the plain-text explanation, one must subclass the given exception; or customize it after it has been created. This particular breakdown of a message into explanation, detail and template allows both the creation of plain-text and html messages for various clients as well as error-free substitution of environment variables and headers. ss6%(explanation)s
%(detail)s cCsQ|ip tdt|tttfptd|t|ttt fptd|t|ttt fptd||pt |_xE|i D]:}|o t||ptd|ii||fqW|tj o ||_n|tj o ||_ nti|d|i|i|i|ifdS(Ns0Do not directly instantiate abstract exceptions.s"headers must be None or a list: %rs#detail must be None or a string: %rs$comment must be None or a string: %rs;Exception %s must be passed the header %r (got headers: %r)s %s %s %s %s (sselfscodesAssertionErrors isinstancesheadersstypesNoneslistsdetails basestringscommentstuplesrequired_headerssreqs has_headers __class__s__name__s Exceptions__init__stitles explanation(sselfsdetailsheadersscommentsreq((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys__init__s*** 8    cCs|p|}hd||i<d||i<d||i<}ti|ijo ||Snx*|i D]\}}||||(sselfs __class__s__name__stitlescode(sself((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys__repr__ s(s__name__s __module__s__doc__sNonescodestitles explanationsdetailscommentstemplatesrequired_headerss__init__s make_bodysplainshtmlsprepare_contentsresponseswsgi_applications__call__s__repr__(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys HTTPException_s" F     s HTTPErrorcBstZdZRS(s base class for status codes in the 400's and 500's This is an exception which indicates that an error has occurred, and that any work in progress should not be committed. These are typically results in the 400's and 500's. (s__name__s __module__s__doc__(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys HTTPErrors sHTTPRedirectioncBstZdZRS(s base class for 300's status code (redirections) This is an abstract base class for 3xx redirection. It indicates that further action needs to be taken by the user agent in order to fulfill the request. It does not necessarly signal an error condition. (s__name__s __module__s__doc__(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPRedirection"s s _HTTPMovecBs\tZdZdfZdZdZeeedZeeedZe eZdZ RS(s redirections which require a Location field Since a 'Location' header is a required attribute of 301, 302, 303, 305 and 307 (but not 304), this base class provides the mechanics to make this easy. While this has the same parameters as HTTPException, if a location is not provided in the headers; it is assumed that the detail _is_ the location (this for backward compatibility, otherwise we'd add a new attribute). slocationsThe resource has been moved tos%(explanation)s %(location)s; you should be redirected automatically. %(detail)s cCst|tttfpt|pg}t|d}| o#|}d}|i d|fn|p tdt i |||||tj o ||_ndS(NslocationssaHTTPRedirection specified neither a location in the headers nor did it provide a detail argument.(s isinstancesheadersstypesNoneslistsAssertionErrors header_valueslocationsdetailsappendsHTTPRedirections__init__sselfscomment(sselfsdetailsheadersscommentslocation((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys__init__>s#  cCsLt||}|pg}|id|f|d|d|d|SdS(s Create a redirect object with the dest_uri, which may be relative, considering it relative to the uri implied by the given environ. sLocationsdetailsheadersscommentN( sresolve_relative_urlsdest_urisenvironslocationsheaderssappendsclssdetailscomment(sclssdest_urisenvironsdetailsheadersscommentslocation((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysrelative_redirectMs  cCsIxB|iD]'\}}|idjo|Sq q Wtd|dS(NslocationsNo location set for %s(sselfsheaderssnamesvalueslowersKeyError(sselfsnamesvalue((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pyslocationYs   ( s__name__s __module__s__doc__srequired_headerss explanationstemplatesNones__init__srelative_redirects classmethodslocation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys _HTTPMove,s   sHTTPMultipleChoicescBstZdZdZRS(Ni,sMultiple Choices(s__name__s __module__scodestitle(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPMultipleChoices`ssHTTPMovedPermanentlycBstZdZdZRS(Ni-sMoved Permanently(s__name__s __module__scodestitle(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPMovedPermanentlydss HTTPFoundcBstZdZdZdZRS(Ni.sFoundsThe resource was found at(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys HTTPFoundhss HTTPSeeOthercBstZdZdZRS(Ni/s See Other(s__name__s __module__scodestitle(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys HTTPSeeOtherossHTTPNotModifiedcBs,tZdZdZdZdZdZRS(Ni0s Not ModifiedscCsdSdS(Ns((sselfsenviron((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysplain|scCsdSdS(s+ text/html representation of the exception sN((sselfsenviron((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pyshtml~s(s__name__s __module__scodestitlesmessagesplainshtml(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPNotModifiedss  s HTTPUseProxycBstZdZdZdZRS(Ni1s Use Proxys8The resource must be accessed through a proxy located at(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys HTTPUseProxyssHTTPTemporaryRedirectcBstZdZdZRS(Ni3sTemporary Redirect(s__name__s __module__scodestitle(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPTemporaryRedirectssHTTPClientErrorcBs tZdZdZdZdZRS(s8 base class for the 400's, where the client is in-error This is an error condition in which the client is presumed to be in-error. This is an expected problem, and thus is not considered a bug. A server-side traceback is not warranted. Unless specialized, this is a '400 Bad Request' is Bad RequestsdThe server could not comply with the request since it is either malformed or otherwise incorrect. (s__name__s __module__s__doc__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPClientErrors sHTTPBadRequestcBstZRS(N(s__name__s __module__(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPBadRequestssHTTPUnauthorizedcBstZdZdZdZRS(Nis UnauthorizedsThis server could not verify that you are authorized to access the document you requested. Either you supplied the wrong credentials (e.g., bad password), or your browser does not understand how to supply the credentials required. (s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPUnauthorizedssHTTPPaymentRequiredcBstZdZdZdZRS(NisPayment Requireds(Access was denied for financial reasons.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPPaymentRequiredss HTTPForbiddencBstZdZdZdZRS(Nis Forbiddens#Access was denied to this resource.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys HTTPForbiddenss HTTPNotFoundcBstZdZdZdZRS(Nis Not Founds The resource could not be found.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys HTTPNotFoundssHTTPMethodNotAllowedcBs#tZdfZdZdZdZRS(NsallowisMethod Not AllowedsKThe method %(REQUEST_METHOD)s is not allowed for this resource. %(detail)s(s__name__s __module__srequired_headersscodestitlestemplate(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPMethodNotAlloweds sHTTPNotAcceptablecBstZdZdZdZRS(NisNot AcceptableswThe resource could not be generated that was acceptable to your browser (content of type %(HTTP_ACCEPT)s). %(detail)s(s__name__s __module__scodestitlestemplate(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPNotAcceptablessHTTPProxyAuthenticationRequiredcBstZdZdZdZRS(NisProxy Authentication Requireds*Authentication /w a local proxy is needed.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPProxyAuthenticationRequiredssHTTPRequestTimeoutcBstZdZdZdZRS(NisRequest TimeoutsHThe server has waited too long for the request to be sent by the client.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPRequestTimeoutss HTTPConflictcBstZdZdZdZRS(NisConflicts:There was a conflict when trying to complete your request.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys HTTPConflictssHTTPGonecBstZdZdZdZRS(NisGonesFThis resource is no longer available. No forwarding address is given.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPGonessHTTPLengthRequiredcBstZdZdZdZRS(NisLength RequiredsContent-Length header required.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPLengthRequiredssHTTPPreconditionFailedcBstZdZdZdZRS(NisPrecondition FailedsRequest precondition failed.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPPreconditionFailedssHTTPRequestEntityTooLargecBstZdZdZdZRS(NisRequest Entity Too Larges7The body of your request was too large for this server.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPRequestEntityTooLargessHTTPRequestURITooLongcBstZdZdZdZRS(NisRequest-URI Too Longs-The request URI was too long for this server.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPRequestURITooLongssHTTPUnsupportedMediaTypecBstZdZdZdZRS(NisUnsupported Media TypesTThe request media type %(CONTENT_TYPE)s is not supported by this server. %(detail)s(s__name__s __module__scodestitlestemplate(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPUnsupportedMediaTypessHTTPRequestRangeNotSatisfiablecBstZdZdZdZRS(NisRequest Range Not Satisfiables%The Range requested is not available.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPRequestRangeNotSatisfiablessHTTPExpectationFailedcBstZdZdZdZRS(NisExpectation FailedsExpectation failed.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPExpectationFailed ssHTTPServerErrorcBs tZdZdZdZdZRS(sF base class for the 500's, where the server is in-error This is an error condition in which the server is presumed to be in-error. This is usually unexpected, and thus requires a traceback; ideally, opening a support ticket for the customer. Unless specialized, this is a '500 Internal Server Error' isInternal Server ErrorsUThe server has either erred or is incapable of performing the requested operation. (s__name__s __module__s__doc__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPServerErrors sHTTPInternalServerErrorcBstZRS(N(s__name__s __module__(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPInternalServerError)ssHTTPNotImplementedcBstZdZdZdZRS(NisNot ImplementedsUThe request method %(REQUEST_METHOD)s is not implemented for this server. %(detail)s(s__name__s __module__scodestitlestemplate(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPNotImplemented,ssHTTPBadGatewaycBstZdZdZdZRS(Nis Bad Gateways Bad gateway.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPBadGateway3ssHTTPServiceUnavailablecBstZdZdZdZRS(NisService UnavailablesFThe server is currently unavailable. Please try again at a later time.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPServiceUnavailable8ssHTTPGatewayTimeoutcBstZdZdZdZRS(NisGateway TimeoutsThe gateway has timed out.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPGatewayTimeout>ssHTTPVersionNotSupportedcBstZdZdZdZRS(NisHTTP Version Not Supporteds"The HTTP version is not supported.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPVersionNotSupportedCscCs t|SdS(N(s _exceptionsscode(scode((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys get_exceptionSssHTTPExceptionHandlercBs#tZdZedZdZRS(s catches exceptions and turns them into proper HTTP responses Attributes: ``warning_level`` This attribute determines for what exceptions a stack trace is kept for lower level reporting; by default, it only keeps stack trace for 5xx, HTTPServerError exceptions. To keep a stack trace for 4xx, HTTPClientError exceptions, set this to 400. This middleware catches any exceptions (which are subclasses of ``HTTPException``) and turns them into proper HTTP responses. Note if the headers have already been sent, the stack trace is always maintained as this indicates a programming error. cCsF| p|djo |djpt|pd|_||_dS(NiciXi(s warning_levelsAssertionErrorsselfs application(sselfs applications warning_level((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys__init__ms)cCs`||d<|idgity|i||SWn"tj o}|||SnXdS(Nspaste.httpexceptionsspaste.expected_exceptions(sselfsenvirons setdefaultsappends HTTPExceptions applicationsstart_responsesexc(sselfsenvironsstart_responsesexc((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys__call__ss  (s__name__s __module__s__doc__sNones__init__s__call__(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPExceptionHandlerZs  cOs-dk}|idtdt||SdS(Ns\httpexceptions.middleware is deprecated; use make_middleware or HTTPExceptionHandler insteadi(swarningsswarnsDeprecationWarningsmake_middlewaresargsskw(sargsskwswarnings((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys middleware|s   cCs+|ot|}nt|d|SdS(s ``httpexceptions`` middleware; this catches any ``paste.httpexceptions.HTTPException`` exceptions (exceptions like ``HTTPNotFound``, ``HTTPMovedPermanently``, etc) and turns them into proper HTTP responses. ``warning_level`` can be an integer corresponding to an HTTP code. Any code over that value will be passed 'up' the chain, potentially reported on by another piece of middleware. s warning_levelN(s warning_levelsintsHTTPExceptionHandlersapp(sapps global_confs warning_level((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysmake_middlewares s get_exception(Is__doc__stypess paste.wsgilibscatch_errors_appspaste.responses has_headers header_valuesreplace_headers paste.requestsresolve_relative_urlspaste.util.quotings strip_htmls html_quotesno_quotes SERVER_NAMEsTEMPLATEs Exceptions HTTPExceptions HTTPErrorsHTTPRedirections _HTTPMovesHTTPMultipleChoicessHTTPMovedPermanentlys HTTPFounds HTTPSeeOthersHTTPNotModifieds HTTPUseProxysHTTPTemporaryRedirectsHTTPClientErrorsHTTPBadRequestsHTTPUnauthorizedsHTTPPaymentRequireds HTTPForbiddens HTTPNotFoundsHTTPMethodNotAllowedsHTTPNotAcceptablesHTTPProxyAuthenticationRequiredsHTTPRequestTimeouts HTTPConflictsHTTPGonesHTTPLengthRequiredsHTTPPreconditionFailedsHTTPRequestEntityTooLargesHTTPRequestURITooLongsHTTPUnsupportedMediaTypesHTTPRequestRangeNotSatisfiablesHTTPExpectationFailedsHTTPServerErrorsHTTPInternalServerErrorsHTTPNotImplementedsHTTPBadGatewaysHTTPServiceUnavailablesHTTPGatewayTimeoutsHTTPVersionNotSupporteds__all__s _exceptionssglobalssitemssnamesvalues isinstancestypes ClassTypes issubclassscodesappends get_exceptionsobjectsHTTPExceptionHandlers middlewaresNonesmake_middlewaresextend(8sHTTPRequestEntityTooLarges HTTPUseProxys HTTPSeeOthers HTTPConflictsHTTPServiceUnavailablesmake_middlewaresHTTPMultipleChoicessHTTPRequestRangeNotSatisfiablesHTTPRequestURITooLongsHTTPRedirectionsHTTPRequestTimeoutsHTTPBadRequestsHTTPUnsupportedMediaTypesHTTPMethodNotAllowedsHTTPBadGatewaysHTTPMovedPermanentlysHTTPNotImplementedsHTTPExpectationFaileds HTTPForbiddens SERVER_NAMEsHTTPVersionNotSupportedsresolve_relative_urlsHTTPServerErrorsnames get_exceptionsHTTPNotModifiedsHTTPNotAcceptablesHTTPPaymentRequireds HTTPExceptionsHTTPTemporaryRedirectsHTTPPreconditionFaileds HTTPFoundsHTTPInternalServerErrors header_valuesHTTPUnauthorizeds HTTPErrors _HTTPMovestypess__all__sHTTPGatewayTimeouts HTTPNotFounds _exceptionssHTTPExceptionHandlersHTTPClientErrorsHTTPGonesreplace_headersHTTPProxyAuthenticationRequiredscatch_errors_appsno_quotesHTTPLengthRequiredsTEMPLATEs strip_htmls has_headersvalues html_quotes middleware((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys?Jsp     4  3  " PK;^W7MHHpaste/httpheaders.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php # (c) 2005 Ian Bicking, Clark C. Evans and contributors # This module is part of the Python Paste Project and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php # Some of this code was funded by: http://prometheusresearch.com """ HTTP Message Header Fields (see RFC 4229) This contains general support for HTTP/1.1 message headers [1]_ in a manner that supports WSGI ``environ`` [2]_ and ``response_headers`` [3]_. Specifically, this module defines a ``HTTPHeader`` class whose instances correspond to field-name items. The actual field-content for the message-header is stored in the appropriate WSGI collection (either the ``environ`` for requests, or ``response_headers`` for responses). Each ``HTTPHeader`` instance is a callable (defining ``__call__``) that takes one of the following: - an ``environ`` dictionary, returning the corresponding header value by according to the WSGI's ``HTTP_`` prefix mechanism, e.g., ``USER_AGENT(environ)`` returns ``environ.get('HTTP_USER_AGENT')`` - a ``response_headers`` list, giving a comma-delimited string for each corresponding ``header_value`` tuple entries (see below). - a sequence of string ``*args`` that are comma-delimited into a single string value: ``CONTENT_TYPE("text/html","text/plain")`` returns ``"text/html, text/plain"`` - a set of ``**kwargs`` keyword arguments that are used to create a header value, in a manner dependent upon the particular header in question (to make value construction easier and error-free): ``CONTENT_DISPOSITION(max_age=CONTENT_DISPOSITION.ONEWEEK)`` returns ``"public, max-age=60480"`` Each ``HTTPHeader`` instance also provides several methods to act on a WSGI collection, for removing and setting header values. ``delete(collection)`` This method removes all entries of the corresponding header from the given collection (``environ`` or ``response_headers``), e.g., ``USER_AGENT.remove(environ)`` deletes the 'HTTP_USER_AGENT' entry from the ``environ``. ``update(collection, *args, **kwargs)`` This method does an in-place replacement of the given header entry, for example: ``CONTENT_LENGTH(response_headers,len(body))`` The first argument is a valid ``environ`` dictionary or ``response_headers`` list; remaining arguments are passed on to ``__call__(*args, **kwargs)`` for value construction. ``apply(collection, **kwargs)`` This method is similar to update, only that it may affect other headers. For example, according to recommendations in RFC 2616, certain Cache-Control configurations should also set the ``Expires`` header for HTTP/1.0 clients. By default, ``apply()`` is simply ``update()`` but limited to keyword arguments. This particular approach to managing headers within a WSGI collection has several advantages: 1. Typos in the header name are easily detected since they become a ``NameError`` when executed. The approach of using header strings directly can be problematic; for example, the following should return ``None`` : ``environ.get("HTTP_ACCEPT_LANGUAGES")`` 2. For specific headers with validation, using ``__call__`` will result in an automatic header value check. For example, the _ContentDisposition header will reject a value having ``maxage`` or ``max_age`` (the appropriate parameter is ``max-age`` ). 3. When appending/replacing headers, the field-name has the suggested RFC capitalization (e.g. ``Content-Type`` or ``ETag``) for user-agents that incorrectly use case-sensitive matches. 4. Some headers (such as ``Content-Type``) are 0, that is, only one entry of this type may occur in a given set of ``response_headers``. This module knows about those cases and enforces this cardinality constraint. 5. The exact details of WSGI header management are abstracted so the programmer need not worry about operational differences between ``environ`` dictionary or ``response_headers`` list. 6. Sorting of ``HTTPHeaders`` is done following the RFC suggestion that general-headers come first, followed by request and response headers, and finishing with entity-headers. 7. Special care is given to exceptional cases such as Set-Cookie which violates the RFC's recommendation about combining header content into a single entry using comma separation. A particular difficulty with HTTP message headers is a categorization of sorts as described in section 4.2: Multiple message-header fields with the same field-name MAY be present in a message if and only if the entire field-value for that header field is defined as a comma-separated list [i.e., #(values)]. It MUST be possible to combine the multiple header fields into one "field-name: field-value" pair, without changing the semantics of the message, by appending each subsequent field-value to the first, each separated by a comma. This creates three fundamentally different kinds of headers: - Those that do not have a #(values) production, and hence are singular and may only occur once in a set of response fields; this case is handled by the ``_SingleValueHeader`` subclass. - Those which have the #(values) production and follow the combining rule outlined above; our ``_MultiValueHeader`` case. - Those which are multi-valued, but cannot be combined (such as the ``Set-Cookie`` header due to its ``Expires`` parameter); or where combining them into a single header entry would cause common user-agents to fail (``WWW-Authenticate``, ``Warning``) since they fail to handle dates even when properly quoted. This case is handled by ``_MultiEntryHeader``. Since this project does not have time to provide rigorous support and validation for all headers, it does a basic construction of headers listed in RFC 2616 (plus a few others) so that they can be obtained by simply doing ``from paste.httpheaders import *``; the name of the header instance is the "common name" less any dashes to give CamelCase style names. .. [1] http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 .. [2] http://www.python.org/peps/pep-0333.html#environ-variables .. [3] http://www.python.org/peps/pep-0333.html#the-start-response-callable """ import urllib2 import re from mimetypes import guess_type from rfc822 import formatdate, parsedate_tz, mktime_tz from time import time as now from httpexceptions import HTTPBadRequest __all__ = ['get_header', 'list_headers', 'normalize_headers', 'HTTPHeader', 'EnvironVariable' ] class EnvironVariable(str): """ a CGI ``environ`` variable as described by WSGI This is a helper object so that standard WSGI ``environ`` variables can be extracted w/o syntax error possibility. """ def __call__(self, environ): return environ.get(self,'') def __repr__(self): return '' % self def update(self, environ, value): environ[self] = value REMOTE_USER = EnvironVariable("REMOTE_USER") REMOTE_SESSION = EnvironVariable("REMOTE_SESSION") AUTH_TYPE = EnvironVariable("AUTH_TYPE") REQUEST_METHOD = EnvironVariable("REQUEST_METHOD") SCRIPT_NAME = EnvironVariable("SCRIPT_NAME") PATH_INFO = EnvironVariable("PATH_INFO") for _name, _obj in globals().items(): if isinstance(_obj, EnvironVariable): __all__.append(_name) _headers = {} class HTTPHeader(object): """ an HTTP header HTTPHeader instances represent a particular ``field-name`` of an HTTP message header. They do not hold a field-value, but instead provide operations that work on is corresponding values. Storage of the actual field values is done with WSGI ``environ`` or ``response_headers`` as appropriate. Typically, a sub-classes that represent a specific HTTP header, such as _ContentDisposition, are 0. Once constructed the HTTPHeader instances themselves are immutable and stateless. For purposes of documentation a "container" refers to either a WSGI ``environ`` dictionary, or a ``response_headers`` list. Member variables (and correspondingly constructor arguments). ``name`` the ``field-name`` of the header, in "common form" as presented in RFC 2616; e.g. 'Content-Type' ``category`` one of 'general', 'request', 'response', or 'entity' ``version`` version of HTTP (informational) with which the header should be recognized ``sort_order`` sorting order to be applied before sorting on field-name when ordering headers in a response Special Methods: ``__call__`` The primary method of the HTTPHeader instance is to make it a callable, it takes either a collection, a string value, or keyword arguments and attempts to find/construct a valid field-value ``__lt__`` This method is used so that HTTPHeader objects can be sorted in a manner suggested by RFC 2616. ``__str__`` The string-value for instances of this class is the ``field-name``. Primary Methods: ``delete()`` remove the all occurrences (if any) of the given header in the collection provided ``update()`` replaces (if they exist) all field-value items in the given collection with the value provided ``tuples()`` returns a set of (field-name, field-value) tuples 5 for extending ``response_headers`` Custom Methods (these may not be implemented): ``apply()`` similar to ``update``, but with two differences; first, only keyword arguments can be used, and second, specific sub-classes may introduce side-effects ``parse()`` converts a string value of the header into a more usable form, such as time in seconds for a date header, etc. The collected versions of initialized header instances are immediately registered and accessible through the ``get_header`` function. Do not inherit from this directly, use one of ``_SingleValueHeader``, ``_MultiValueHeader``, or ``_MultiEntryHeader`` as appropriate. """ # # Things which can be customized # version = '1.1' category = 'general' reference = '' extensions = {} def compose(self, **kwargs): """ build header value from keyword arguments This method is used to build the corresponding header value when keyword arguments (or no arguments) were provided. The result should be a sequence of values. For example, the ``Expires`` header takes a keyword argument ``time`` (e.g. time.time()) from which it returns a the corresponding date. """ raise NotImplementedError() def parse(self, *args, **kwargs): """ convert raw header value into more usable form This method invokes ``values()`` with the arguments provided, parses the header results, and then returns a header-specific data structure corresponding to the header. For example, the ``Expires`` header returns seconds (as returned by time.time()) """ raise NotImplementedError() def apply(self, collection, **kwargs): """ update the collection /w header value (may have side effects) This method is similar to ``update`` only that usage may result in other headers being changed as recommended by the corresponding specification. The return value is defined by the particular sub-class. For example, the ``_CacheControl.apply()`` sets the ``Expires`` header in addition to its normal behavior. """ self.update(collection, **kwargs) # # Things which are standardized (mostly) # def __new__(cls, name, category=None, reference=None, version=None): """ construct a new ``HTTPHeader`` instance We use the ``__new__`` operator to ensure that only one ``HTTPHeader`` instance exists for each field-name, and to register the header so that it can be found/enumerated. """ self = get_header(name, raiseError=False) if self: # Allow the registration to happen again, but assert # that everything is identical. assert self.name == name, \ "duplicate registration with different capitalization" assert self.category == category, \ "duplicate registration with different category" assert cls == self.__class__, \ "duplicate registration with different class" return self self = object.__new__(cls) self.name = name assert isinstance(self.name, str) self.category = category or self.category self.version = version or self.version self.reference = reference or self.reference _headers[self.name.lower()] = self self.sort_order = {'general': 1, 'request': 2, 'response': 3, 'entity': 4 }[self.category] self._environ_name = getattr(self, '_environ_name', 'HTTP_'+ self.name.upper().replace("-","_")) self._headers_name = getattr(self, '_headers_name', self.name.lower()) assert self.version in ('1.1', '1.0', '0.9') return self def __str__(self): return self.name def __lt__(self, other): """ sort header instances as specified by RFC 2616 Re-define sorting so that general headers are first, followed by request/response headers, and then entity headers. The list.sort() methods use the less-than operator for this purpose. """ if isinstance(other, HTTPHeader): if self.sort_order != other.sort_order: return self.sort_order < other.sort_order return self.name < other.name return False def __repr__(self): ref = self.reference and (' (%s)' % self.reference) or '' return '<%s %s%s>' % (self.__class__.__name__, self.name, ref) def values(self, *args, **kwargs): """ find/construct field-value(s) for the given header Resolution is done according to the following arguments: - If only keyword arguments are given, then this is equivalent to ``compose(**kwargs)``. - If the first (and only) argument is a dict, it is assumed to be a WSGI ``environ`` and the result of the corresponding ``HTTP_`` entry is returned. - If the first (and only) argument is a list, it is assumed to be a WSGI ``response_headers`` and the field-value(s) for this header are collected and returned. - In all other cases, the arguments are collected, checked that they are string values, possibly verified by the header's logic, and returned. At this time it is an error to provide keyword arguments if args is present (this might change). It is an error to provide both a WSGI object and also string arguments. If no arguments are provided, then ``compose()`` is called to provide a default value for the header; if there is not default it is an error. """ if not args: return self.compose(**kwargs) if list == type(args[0]): assert 1 == len(args) result = [] name = self.name.lower() for value in [value for header, value in args[0] if header.lower() == name]: result.append(value) return result if dict == type(args[0]): assert 1 == len(args) and 'wsgi.version' in args[0] value = args[0].get(self._environ_name) if not value: return () return (value,) for item in args: assert not type(item) in (dict, list) return args def __call__(self, *args, **kwargs): """ converts ``values()`` into a string value This method converts the results of ``values()`` into a string value for common usage. By default, it is asserted that only one value exists; if you need to access all values then either call ``values()`` directly, or inherit ``_MultiValueHeader`` which overrides this method to return a comma separated list of values as described by section 4.2 of RFC 2616. """ values = self.values(*args, **kwargs) assert isinstance(values, (tuple, list)) if not values: return '' assert len(values) == 1, "more than one value: %s" % repr(values) return str(values[0]).strip() def delete(self, collection): """ removes all occurances of the header from the collection provided """ if type(collection) == dict: if self._environ_name in collection: del collection[self._environ_name] return self assert list == type(collection) i = 0 while i < len(collection): if collection[i][0].lower() == self._headers_name: del collection[i] continue i += 1 def update(self, collection, *args, **kwargs): """ updates the collection with the provided header value This method replaces (in-place when possible) all occurrences of the given header with the provided value. If no value is provided, this is the same as ``remove`` (note that this case can only occur if the target is a collection w/o a corresponding header value). The return value is the new header value (which could be a list for ``_MultiEntryHeader`` instances). """ value = self.__call__(*args, **kwargs) if not value: self.remove(collection) return if type(collection) == dict: collection[self._environ_name] = value return assert list == type(collection) i = 0 found = False while i < len(collection): if collection[i][0].lower() == self._headers_name: if found: del collection[i] continue collection[i] = (self.name, value) found = True i += 1 if not found: collection.append((self.name, value)) def tuples(self, *args, **kwargs): value = self.__call__(*args, **kwargs) if not value: return () return [(self.name, value)] class _SingleValueHeader(HTTPHeader): """ a ``HTTPHeader`` with exactly a single value This is the default behavior of ``HTTPHeader`` where returning a the string-value of headers via ``__call__`` assumes that only a single value exists. """ pass class _MultiValueHeader(HTTPHeader): """ a ``HTTPHeader`` with one or more values The field-value for these header instances is is allowed to be more than one value; whereby the ``__call__`` method returns a comma separated list as described by section 4.2 of RFC 2616. """ def __call__(self, *args, **kwargs): results = self.values(*args, **kwargs) if not results: return '' return ", ".join([str(v).strip() for v in results]) def parse(self, *args, **kwargs): value = self.__call__(*args, **kwargs) values = value.split(',') return [ v.strip() for v in values if v.strip()] class _MultiEntryHeader(HTTPHeader): """ a multi-value ``HTTPHeader`` where items cannot be combined with a comma This header is multi-valued, but the values should not be combined with a comma since the header is not in compliance with RFC 2616 (Set-Cookie due to Expires parameter) or which common user-agents do not behave well when the header values are combined. """ def update(self, collection, *args, **kwargs): assert list == type(collection), "``environ`` may not be updated" self.delete(collection) collection.extend(self.tuples(*args, **kwargs)) def tuples(self, *args, **kwargs): values = self.values(*args, **kwargs) if not values: return () return [(self.name, value.strip()) for value in values] def get_header(name, raiseError=True): """ find the given ``HTTPHeader`` instance This function finds the corresponding ``HTTPHeader`` for the ``name`` provided. So that python-style names can be used, underscores are converted to dashes before the lookup. """ retval = _headers.get(str(name).strip().lower().replace("_","-")) if not retval and raiseError: raise AssertionError("'%s' is an unknown header" % name) return retval def list_headers(general=None, request=None, response=None, entity=None): " list all headers for a given category " if not (general or request or response or entity): general = request = response = entity = True search = [] for (bool, strval) in ((general, 'general'), (request, 'request'), (response, 'response'), (entity, 'entity')): if bool: search.append(strval) return [head for head in _headers.values() if head.category in search] def normalize_headers(response_headers, strict=True): """ sort headers as suggested by RFC 2616 This alters the underlying response_headers to use the common name for each header; as well as sorting them with general headers first, followed by request/response headers, then entity headers, and unknown headers last. """ category = {} for idx in range(len(response_headers)): (key, val) = response_headers[idx] head = get_header(key, strict) if not head: newhead = '-'.join([x.capitalize() for x in key.replace("_","-").split("-")]) response_headers[idx] = (newhead, val) category[newhead] = 4 continue response_headers[idx] = (str(head), val) category[str(head)] = head.sort_order def compare(a, b): ac = category[a[0]] bc = category[b[0]] if ac == bc: return cmp(a[0], b[0]) return cmp(ac, bc) response_headers.sort(compare) class _DateHeader(_SingleValueHeader): """ handle date-based headers This extends the ``_SingleValueHeader`` object with specific treatment of time values: - It overrides ``compose`` to provide a sole keyword argument ``time`` which is an offset in seconds from the current time. - A ``time`` method is provided which parses the given value and returns the current time value. """ def compose(self, time=None, delta=None): time = time or now() if delta: assert type(delta) == int time += delta return (formatdate(time),) def parse(self, *args, **kwargs): """ return the time value (in seconds since 1970) """ value = self.__call__(*args, **kwargs) if value: try: return mktime_tz(parsedate_tz(value)) except TypeError: raise HTTPBadRequest(( "Received an ill-formed timestamp for %s: %s\r\n") % (self.name, value)) # # Following are specific HTTP headers. Since these classes are mostly # singletons, there is no point in keeping the class around once it has # been instantiated, so we use the same name. # class _CacheControl(_MultiValueHeader): """ Cache-Control, RFC 2616 14.9 (use ``CACHE_CONTROL``) This header can be constructed (using keyword arguments), by first specifying one of the following mechanisms: ``public`` if True, this argument specifies that the response, as a whole, may be cashed. ``private`` if True, this argument specifies that the response, as a whole, may be cashed; this implementation does not support the enumeration of private fields ``no_cache`` if True, this argument specifies that the response, as a whole, may not be cashed; this implementation does not support the enumeration of private fields In general, only one of the above three may be True, the other 2 must then be False or None. If all three are None, then the cache is assumed to be ``public``. Following one of these mechanism specifiers are various modifiers: ``no_store`` indicates if content may be stored on disk; otherwise cache is limited to memory (note: users can still save the data, this applies to intermediate caches) ``max_age`` the maximum duration (in seconds) for which the content should be cached; if ``no-cache`` is specified, this defaults to 0 seconds ``s_maxage`` the maximum duration (in seconds) for which the content should be allowed in a shared cache. ``no_transform`` specifies that an intermediate cache should not convert the content from one type to another (e.g. transform a BMP to a PNG). ``extensions`` gives additional cache-control extensions, such as items like, community="UCI" (14.9.6) The usage of ``apply()`` on this header has side-effects. As recommended by RFC 2616, if ``max_age`` is provided, then then the ``Expires`` header is also calculated for HTTP/1.0 clients and proxies (this is done at the time ``apply()`` is called). For ``no-cache`` and for ``private`` cases, we either do not want the response cached or do not want any response accidently returned to other users; so to prevent this case, we set the ``Expires`` header to the time of the request, signifying to HTTP/1.0 transports that the content isn't to be cached. If you are using SSL, your communication is already "private", so to work with HTTP/1.0 browsers over SSL, consider specifying your cache as ``public`` as the distinction between public and private is moot. """ # common values for max-age; "good enough" approximates ONE_HOUR = 60*60 ONE_DAY = ONE_HOUR * 24 ONE_WEEK = ONE_DAY * 7 ONE_MONTH = ONE_DAY * 30 ONE_YEAR = ONE_WEEK * 52 def _compose(self, public=None, private=None, no_cache=None, no_store=False, max_age=None, s_maxage=None, no_transform=False, **extensions): assert isinstance(max_age, (type(None), int)) assert isinstance(s_maxage, (type(None), int)) expires = 0 result = [] if private is True: assert not public and not no_cache and not s_maxage result.append('private') elif no_cache is True: assert not public and not private and not max_age result.append('no-cache') else: assert public is None or public is True assert not private and not no_cache expires = max_age result.append('public') if no_store: result.append('no-store') if no_transform: result.append('no-transform') if max_age is not None: result.append('max-age=%d' % max_age) if s_maxage is not None: result.append('s-maxage=%d' % s_maxage) for (k, v) in extensions.items(): if k not in self.extensions: raise AssertionError("unexpected extension used: '%s'" % k) result.append('%s="%s"' % (k.replace("_", "-"), v)) return (result, expires) def compose(self, **kwargs): (result, expires) = self._compose(**kwargs) return result def apply(self, collection, **kwargs): """ returns the offset expiration in seconds """ (result, expires) = self._compose(**kwargs) if expires is not None: EXPIRES.update(collection, delta=expires) self.update(collection, *result) return expires _CacheControl('Cache-Control', 'general', 'RFC 2616, 14.9') class _ContentType(_SingleValueHeader): """ Content-Type, RFC 2616 section 14.17 Unlike other headers, use the CGI variable instead. """ version = '1.0' _environ_name = 'CONTENT_TYPE' # common mimetype constants UNKNOWN = 'application/octet-stream' TEXT_PLAIN = 'text/plain' TEXT_HTML = 'text/html' TEXT_XML = 'text/xml' def compose(self, major=None, minor=None, charset=None): if not major: if minor in ('plain', 'html', 'xml'): major = 'text' else: assert not minor and not charset return (self.UNKNOWN,) if not minor: minor = "*" result = "%s/%s" % (major, minor) if charset: result += "; charset=%s" % charset return (result,) _ContentType('Content-Type', 'entity', 'RFC 2616, 14.17') class _ContentLength(_SingleValueHeader): """ Content-Length, RFC 2616 section 14.13 Unlike other headers, use the CGI variable instead. """ version = "1.0" _environ_name = 'CONTENT_LENGTH' _ContentLength('Content-Length', 'entity', 'RFC 2616, 14.13') class _ContentDisposition(_SingleValueHeader): """ Content-Disposition, RFC 2183 (use ``CONTENT_DISPOSITION``) This header can be constructed (using keyword arguments), by first specifying one of the following mechanisms: ``attachment`` if True, this specifies that the content should not be shown in the browser and should be handled externally, even if the browser could render the content ``inline`` exclusive with attachment; indicates that the content should be rendered in the browser if possible, but otherwise it should be handled externally Only one of the above 2 may be True. If both are None, then the disposition is assumed to be an ``attachment``. These are distinct fields since support for field enumeration may be added in the future. ``filename`` the filename parameter, if any, to be reported; if this is None, then the current object's filename attribute is used The usage of ``apply()`` on this header has side-effects. If filename is provided, and Content-Type is not set or is 'application/octet-stream', then the mimetypes.guess is used to upgrade the Content-Type setting. """ def _compose(self, attachment=None, inline=None, filename=None): result = [] if inline is True: assert not attachment result.append('inline') else: assert not inline result.append('attachment') if filename: assert '"' not in filename filename = filename.split("/")[-1] filename = filename.split("\\")[-1] result.append('filename="%s"' % filename) return (("; ".join(result),), filename) def compose(self, **kwargs): (result, mimetype) = self._compose(**kwargs) return result def apply(self, collection, **kwargs): """ return the new Content-Type side-effect value """ (result, filename) = self._compose(**kwargs) mimetype = CONTENT_TYPE(collection) if filename and (not mimetype or CONTENT_TYPE.UNKNOWN == mimetype): mimetype, _ = guess_type(filename) if mimetype and CONTENT_TYPE.UNKNOWN != mimetype: CONTENT_TYPE.update(collection, mimetype) self.update(collection, *result) return mimetype _ContentDisposition('Content-Disposition', 'entity', 'RFC 2183') class _IfModifiedSince(_DateHeader): """ If-Modified-Since, RFC 2616 section 14.25 """ version = '1.0' def __call__(self, *args, **kwargs): """ Split the value on ';' incase the header includes extra attributes. E.g. IE 6 is known to send: If-Modified-Since: Sun, 25 Jun 2006 20:36:35 GMT; length=1506 """ return _DateHeader.__call__(self, *args, **kwargs).split(';', 1)[0] def parse(self, *args, **kwargs): value = _DateHeader.parse(self, *args, **kwargs) if value and value > now(): raise HTTPBadRequest(( "Please check your system clock.\r\n" "According to this server, the time provided in the\r\n" "%s header is in the future.\r\n") % self.name) return value _IfModifiedSince('If-Modified-Since', 'request', 'RFC 2616, 14.25') class _Range(_MultiValueHeader): """ Range, RFC 2616 14.35 (use ``RANGE``) According to section 14.16, the response to this message should be a 206 Partial Content and that if multiple non-overlapping byte ranges are requested (it is an error to request multiple overlapping ranges) the result should be sent as multipart/byteranges mimetype. The server should respond with '416 Requested Range Not Satisfiable' if the requested ranges are out-of-bounds. The specification also indicates that a syntax error in the Range request should result in the header being ignored rather than a '400 Bad Request'. """ def parse(self, *args, **kwargs): """ Returns a tuple (units, list), where list is a sequence of (begin, end) tuples; and end is None if it was not provided. """ value = self.__call__(*args, **kwargs) if not value: return None ranges = [] last_end = -1 try: (units, range) = value.split("=", 1) units = units.strip().lower() for item in range.split(","): (begin, end) = item.split("-") if not begin.strip(): begin = 0 else: begin = int(begin) if begin <= last_end: raise ValueError() if not end.strip(): end = None else: end = int(end) last_end = end ranges.append((begin, end)) except ValueError: # In this case where the Range header is malformed, # section 14.16 says to treat the request as if the # Range header was not present. How do I log this? return None return (units, ranges) _Range('Range', 'request', 'RFC 2616, 14.35') class _AcceptLanguage(_MultiValueHeader): """ Accept-Language, RFC 2616 section 14.4 """ def parse(self, *args, **kwargs): """ Return a list of language tags sorted by their "q" values. For example, "en-us,en;q=0.5" should return ``["en-us", "en"]``. If there is no ``Accept-Language`` header present, default to ``[]``. """ header = self.__call__(*args, **kwargs) if header is None: return [] langs = [v for v in header.split(",") if v] qs = [] for lang in langs: pieces = lang.split(";") lang, params = pieces[0].strip().lower(), pieces[1:] q = 1 for param in params: if '=' not in param: # Malformed request; probably a bot, we'll ignore continue lvalue, rvalue = param.split("=") lvalue = lvalue.strip().lower() rvalue = rvalue.strip() if lvalue == "q": q = float(rvalue) qs.append((lang, q)) qs.sort(lambda a, b: -cmp(a[1], b[1])) return [lang for (lang, q) in qs] _AcceptLanguage('Accept-Language', 'request', 'RFC 2616, 14.4') class _AcceptRanges(_MultiValueHeader): """ Accept-Ranges, RFC 2616 section 14.5 """ def compose(self, none=None, bytes=None): if bytes: return ('bytes',) return ('none',) _AcceptRanges('Accept-Ranges', 'response', 'RFC 2616, 14.5') class _ContentRange(_SingleValueHeader): """ Content-Range, RFC 2616 section 14.6 """ def compose(self, first_byte=None, last_byte=None, total_length=None): retval = "bytes %d-%d/%d" % (first_byte, last_byte, total_length) assert last_byte == -1 or first_byte <= last_byte assert last_byte < total_length return (retval,) _ContentRange('Content-Range', 'entity', 'RFC 2616, 14.6') class _Authorization(_SingleValueHeader): """ Authorization, RFC 2617 (RFC 2616, 14.8) """ def compose(self, digest=None, basic=None, username=None, password=None, challenge=None, path=None, method=None): assert username and password if basic or not challenge: assert not digest userpass = "%s:%s" % (username.strip(), password.strip()) return "Basic %s" % userpass.encode('base64').strip() assert challenge and not basic path = path or "/" (_, realm) = challenge.split('realm="') (realm, _) = realm.split('"', 1) auth = urllib2.AbstractDigestAuthHandler() auth.add_password(realm, path, username, password) (token, challenge) = challenge.split(' ', 1) chal = urllib2.parse_keqv_list(urllib2.parse_http_list(challenge)) class FakeRequest(object): def get_full_url(self): return path def has_data(self): return False def get_method(self): return method or "GET" get_selector = get_full_url retval = "Digest %s" % auth.get_authorization(FakeRequest(), chal) return (retval,) _Authorization('Authorization', 'request', 'RFC 2617') # # For now, construct a minimalistic version of the field-names; at a # later date more complicated headers may sprout content constructors. # The items commented out have concrete variants. # for (name, category, version, style, comment) in \ (("Accept" ,'request' ,'1.1','multi-value','RFC 2616, 14.1' ) ,("Accept-Charset" ,'request' ,'1.1','multi-value','RFC 2616, 14.2' ) ,("Accept-Encoding" ,'request' ,'1.1','multi-value','RFC 2616, 14.3' ) #,("Accept-Language" ,'request' ,'1.1','multi-value','RFC 2616, 14.4' ) #,("Accept-Ranges" ,'response','1.1','multi-value','RFC 2616, 14.5' ) ,("Age" ,'response','1.1','singular' ,'RFC 2616, 14.6' ) ,("Allow" ,'entity' ,'1.0','multi-value','RFC 2616, 14.7' ) #,("Authorization" ,'request' ,'1.0','singular' ,'RFC 2616, 14.8' ) #,("Cache-Control" ,'general' ,'1.1','multi-value','RFC 2616, 14.9' ) ,("Cookie" ,'request' ,'1.0','multi-value','RFC 2109/Netscape') ,("Connection" ,'general' ,'1.1','multi-value','RFC 2616, 14.10') ,("Content-Encoding" ,'entity' ,'1.0','multi-value','RFC 2616, 14.11') #,("Content-Disposition",'entity' ,'1.1','multi-value','RFC 2616, 15.5' ) ,("Content-Language" ,'entity' ,'1.1','multi-value','RFC 2616, 14.12') #,("Content-Length" ,'entity' ,'1.0','singular' ,'RFC 2616, 14.13') ,("Content-Location" ,'entity' ,'1.1','singular' ,'RFC 2616, 14.14') ,("Content-MD5" ,'entity' ,'1.1','singular' ,'RFC 2616, 14.15') #,("Content-Range" ,'entity' ,'1.1','singular' ,'RFC 2616, 14.16') #,("Content-Type" ,'entity' ,'1.0','singular' ,'RFC 2616, 14.17') ,("Date" ,'general' ,'1.0','date-header','RFC 2616, 14.18') ,("ETag" ,'response','1.1','singular' ,'RFC 2616, 14.19') ,("Expect" ,'request' ,'1.1','multi-value','RFC 2616, 14.20') ,("Expires" ,'entity' ,'1.0','date-header','RFC 2616, 14.21') ,("From" ,'request' ,'1.0','singular' ,'RFC 2616, 14.22') ,("Host" ,'request' ,'1.1','singular' ,'RFC 2616, 14.23') ,("If-Match" ,'request' ,'1.1','multi-value','RFC 2616, 14.24') #,("If-Modified-Since" ,'request' ,'1.0','date-header','RFC 2616, 14.25') ,("If-None-Match" ,'request' ,'1.1','multi-value','RFC 2616, 14.26') ,("If-Range" ,'request' ,'1.1','singular' ,'RFC 2616, 14.27') ,("If-Unmodified-Since",'request' ,'1.1','date-header' ,'RFC 2616, 14.28') ,("Last-Modified" ,'entity' ,'1.0','date-header','RFC 2616, 14.29') ,("Location" ,'response','1.0','singular' ,'RFC 2616, 14.30') ,("Max-Forwards" ,'request' ,'1.1','singular' ,'RFC 2616, 14.31') ,("Pragma" ,'general' ,'1.0','multi-value','RFC 2616, 14.32') ,("Proxy-Authenticate" ,'response','1.1','multi-value','RFC 2616, 14.33') ,("Proxy-Authorization",'request' ,'1.1','singular' ,'RFC 2616, 14.34') #,("Range" ,'request' ,'1.1','multi-value','RFC 2616, 14.35') ,("Referer" ,'request' ,'1.0','singular' ,'RFC 2616, 14.36') ,("Retry-After" ,'response','1.1','singular' ,'RFC 2616, 14.37') ,("Server" ,'response','1.0','singular' ,'RFC 2616, 14.38') ,("Set-Cookie" ,'response','1.0','multi-entry','RFC 2109/Netscape') ,("TE" ,'request' ,'1.1','multi-value','RFC 2616, 14.39') ,("Trailer" ,'general' ,'1.1','multi-value','RFC 2616, 14.40') ,("Transfer-Encoding" ,'general' ,'1.1','multi-value','RFC 2616, 14.41') ,("Upgrade" ,'general' ,'1.1','multi-value','RFC 2616, 14.42') ,("User-Agent" ,'request' ,'1.0','singular' ,'RFC 2616, 14.43') ,("Vary" ,'response','1.1','multi-value','RFC 2616, 14.44') ,("Via" ,'general' ,'1.1','multi-value','RFC 2616, 14.45') ,("Warning" ,'general' ,'1.1','multi-entry','RFC 2616, 14.46') ,("WWW-Authenticate" ,'response','1.0','multi-entry','RFC 2616, 14.47')): klass = {'multi-value': _MultiValueHeader, 'multi-entry': _MultiEntryHeader, 'date-header': _DateHeader, 'singular' : _SingleValueHeader}[style] klass(name, category, comment, version).__doc__ = comment del klass for head in _headers.values(): headname = head.name.replace("-","_").upper() locals()[headname] = head __all__.append(headname) __pudge_all__ = __all__[:] for _name, _obj in globals().items(): if isinstance(_obj, type) and issubclass(_obj, HTTPHeader): __pudge_all__.append(_name) PK-68xllpaste/transaction.pyo; #Gc@sdZdklZdklZdefdYZdefdYZdefdYZd Z dd gZ d e joe omd k lZeed dZeZeiZeideidei\ZZeGeGHndS(s Middleware related to transactions and database connections. At this time it is very basic; but will eventually sprout all that two-phase commit goodness that I don't need. .. note:: This is experimental, and will change in the future. (s HTTPException(s catch_errorssTransactionManagerMiddlewarecBstZdZdZRS(NcCs ||_dS(N(s applicationsself(sselfs application((s5build/bdist.darwin-8.0.1-x86/egg/paste/transaction.pys__init__scCsDt|d<}t|dCss PgQuoteString(smodulesselfsargsskwargssquoteshasattrs PgQuoteString(sselfsmodulesargsskwargs((s5build/bdist.darwin-8.0.1-x86/egg/paste/transaction.pys__init__<s     cCsC|ii|i|i}|i|id<|i|id<|SdS(Nsmodulesquote(sselfsmodulesconnectsargsskwargssconns__dict__squote(sselfsenvironsconn((s5build/bdist.darwin-8.0.1-x86/egg/paste/transaction.pys__call__Gs(s__name__s __module__s__doc__s__init__sNones__call__(((s5build/bdist.darwin-8.0.1-x86/egg/paste/transaction.pysConnectionFactory5s  csd}|SdS(s Provides a simple mechanism for starting a transaction based on the factory; and for either committing or rolling back the transaction depending on the result. It checks for the response's current status code either through the latest call to start_response; or through a HTTPException's code. If it is a 100, 200, or 300; the transaction is committed; otherwise it is rolled back. c s]||d<d?d@<dAdB<dCdD<dEdF<dGdH<dIdJ<dKdL<dMdN<dOdP<dQdR<dSdT<dUdV<dWdX<dYdZ<d[d\<d]d^<d_d`<dadb<dcdd<dedf(sselfskey(sself((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pys__repr__6s(s__name__s __module__s__doc__sNones__init__s__get__s__repr__(((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pysenviron_getter$s  c BstZdZedededddeddZdZe d Z e d Z e d Z e d Z e d ZdZeedeiZdZeedeiZdZeedeiZdZeedeiZdZdZeedeiZdZdZeedeiZdZeedeiZdZeedeiZdZdZdZRS(s#WSGI Request API Object This object represents a WSGI request with a more friendly interface. This does not expose every detail of the WSGI environment, and attempts to express nothing beyond what is available in the environment dictionary. The only state maintained in this object is the desired ``charset``, its associated ``errors`` handler, and the ``decode_param_names`` option. The incoming parameter values will be automatically coerced to unicode objects of the ``charset`` encoding when ``charset`` is set. The incoming parameter names are not decoded to unicode unless the ``decode_param_names`` option is enabled. When unicode is expected, ``charset`` will overridden by the the value of the ``Content-Type`` header's charset parameter if one was specified by the client. The class variable ``defaults`` specifies default values for ``charset``, ``errors``, and ``langauge``. These can be overridden for the current request via the registry. The ``language`` default value is considered the fallback during i18n translations to ensure in odd cases that mixed languages don't occur should the ``language`` file contain the string but not another language in the accepted languages list. The ``language`` value only applies when getting a list of accepted languages from the HTTP Accept header. This behavior is duplicated from Aquarium, and may seem strange but is very useful. Normally, everything in the code is in "en-us". However, the "en-us" translation catalog is usually empty. If the user requests ``["en-us", "zh-cn"]`` and a translation isn't found for a string in "en-us", you don't want gettext to fallback to "zh-cn". You want it to just use the string itself. Hence, if a string isn't found in the ``language`` catalog, the string in the source code will be used. *All* other state is kept in the environment dictionary; this is essential for interoperability. You are free to subclass this object. sdefaultscharsetserrorssreplacesdecode_param_namesslanguagesen-uscCs||_t||_|ii}|id|_|io$|i}|o ||_qgn|idd|_ |idt |_ t |_dS(Nscharsetserrorssstrictsdecode_param_names(senvironsselfsEnvironHeaderssheaderssdefaultss _current_objsgetscharsetsdetermine_browser_charsetsbrowser_charsetserrorssFalsesdecode_param_namessNones _languages(sselfsenvironsdefaultssbrowser_charset((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pys__init__is   s wsgi.inputswsgi.url_schemesREQUEST_METHODs SCRIPT_NAMEs PATH_INFOcCsJd|ijo|idSn(d|ijo|iddSnhSdS(sc Return any variables matched in the URL (e.g., ``wsgiorg.routing_args``). s paste.urlvarsswsgiorg.routing_argsiN(sselfsenviron(sself((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pysurlvarss sdoccCs|iidddjSdS(sEReturns a boolean if X-Requested-With is present and a XMLHttpRequestsHTTP_X_REQUESTED_WITHssXMLHttpRequestN(sselfsenvironsget(sself((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pysis_xhrscCs#|iid|iidSdS(s>Host name provided in HTTP_HOST, with fall-back to SERVER_NAMEs HTTP_HOSTs SERVER_NAMEN(sselfsenvironsget(sself((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pyshostscCs|itj o |iSn|iid}ti|i}|i idd}| o|Sn||jo|i |n|i |}g||d)||_|iSdS(slReturn a list of preferred languages, most preferred first. The list may be empty. sHTTP_ACCEPT_LANGUAGEslanguagesen-usiN( sselfs _languagessNonesenvironsgetsacceptLanguagesACCEPT_LANGUAGEsparseslangssdefaultssfallbacksappendsindex(sselfsindexsacceptLanguagesfallbackslangs((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pys languagess   cCst|iSdS(N(sparse_dict_querystringsselfsenviron(sself((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pys_GETscCsI|i}|io+t|d|id|id|i}n|SdS(s Dictionary-like object representing the QUERY_STRING parameters. Always present, if possibly empty. If the same key is present in the query string multiple times, a list of its values can be retrieved from the ``MultiDict`` via the ``getall`` method. Returns a ``MultiDict`` container or a ``UnicodeMultiDict`` when ``charset`` is set. sencodingserrorss decode_keysN(sselfs_GETsparamsscharsetsUnicodeMultiDictserrorssdecode_param_names(sselfsparams((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pysGETs    cCst|idtSdS(Nsinclude_get_vars(sparse_formvarssselfsenvironsFalse(sself((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pys_POSTscCsI|i}|io+t|d|id|id|i}n|SdS(skDictionary-like object representing the POST body. Most values are encoded strings, or unicode strings when ``charset`` is set. There may also be FieldStorage objects representing file uploads. If this is not a POST request, or the body is not encoded fields (e.g., an XMLRPC request) then this will be empty. This will consume wsgi.input when first accessed if applicable, but the raw version will be put in environ['paste.parsed_formvars']. Returns a ``MultiDict`` container or a ``UnicodeMultiDict`` when ``charset`` is set. sencodingserrorss decode_keysN(sselfs_POSTsparamsscharsetsUnicodeMultiDictserrorssdecode_param_names(sselfsparams((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pysPOSTs   cCslt}|i|i|i|i|io+t|d|id|id|i }n|SdS(sDictionary-like object of keys from POST, GET, URL dicts Return a key value from the parameters, they are checked in the following order: POST, GET, URL Additional methods supported: ``getlist(key)`` Returns a list of all the values by that key, collected from POST, GET, URL dicts Returns a ``MultiDict`` container or a ``UnicodeMultiDict`` when ``charset`` is set. sencodingserrorss decode_keysN( s MultiDictsparamssupdatesselfs_POSTs_GETscharsetsUnicodeMultiDictserrorssdecode_param_names(sselfsparams((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pysparamss   cCst|iSdS(szDictionary of cookies keyed by cookie name. Just a plain dictionary, may be empty but not None. N(sget_cookie_dictsselfsenviron(sself((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pyscookiesscCs:ti|iidd}|o|idSndS(s Determine the encoding as specified by the browser via the Content-Type's charset parameter, if one is set s Content-TypesiN(s _CHARSET_REssearchsselfsheaderssgets charset_matchsgroup(sselfs charset_match((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pysdetermine_browser_charsetscCs t||iiddSdS(sqReturn a list of specified mime-types that the browser's HTTP Accept header allows in the order provided.s HTTP_ACCEPTs*/*N(sdesired_matchess mimetypessselfsenvironsget(sselfs mimetypes((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pys match_acceptscCs t}d|ii|iit|||if}|d||i ||i ||i ||i f7}|d||i 7}|io*|d||i||if7}n|d||i7}|d||i7}|d||i7}|SdS( s,Show important attributes of the WSGIRequests <%s.%s object at 0x%x method=%s,s2 scheme=%s, host=%s, script_name=%s, path_info=%s,s languges=%s,s charset=%s, errors=%s,s GET=%s,s POST=%s,s cookies=%s>N(spformatspfsselfs __class__s __module__s__name__sidsmethodsmsgsschemeshosts script_names path_infos languagesscharsetserrorssGETsPOSTscookies(sselfsmsgspf((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pys__repr__s1> *(s__name__s __module__s__doc__sStackedObjectProxysdictsNonesFalsesdefaultss__init__senviron_gettersbodysschemesmethods script_names path_infosurlvarsspropertysis_xhrshosts languagess_GETsGETs_POSTsPOSTsparamsscookiessdetermine_browser_charsets match_accepts__repr__(((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pys WSGIRequest9s> ,                 cBs[tZdZededddddddhd d <Zd ed d ZdZdZ dZ dZ d eedeedZ dedZ dZededdZdZdZdZdZdZdZdZd ZeeeedeiZd!Zd"Zd#ZeeeedeiZRS($sA basic HTTP response with content, headers, and out-bound cookies The class variable ``defaults`` specifies default values for ``content_type``, ``charset`` and ``errors``. These can be overridden for the current request via the registry. sdefaults content_types text/htmlscharsetsutf-8serrorssstrictsheaderss Cache-Controlsno-cachesicCst|_t|_||_t|_t|_ ||_ |i i }| o@|idd}|id}|od||f}qn|ii|idh||id<|idd|_dS( Ns content_types text/htmlscharsets%s; charset=%ssheaderss Content-Typeserrorssstrict(sNonesselfs_itersTrues _is_str_iterscontents HeaderDictsheaderss SimpleCookiescookiesscodes status_codesdefaultss _current_objsmimetypesgetscharsetsupdateserrors(sselfscontentsmimetypescodescharsetsdefaults((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pys__init__,s       cCs|iodi|i}nt|i}digi}|ii D] \}}|d||fqO~d|SdS(sReturns a rendition of the full HTTP message, including headers. When the content is an iterator, the actual content is replaced with the output of str(iterator) (to avoid exhausting the iterator). ss s%s: %ss N( sselfs _is_str_itersjoins get_contentscontentsstrsappends_[1]sheaderss headeritemsskeysvalue(sselfs_[1]svaluescontentskey((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pys__str__?s  csti}di|f}ii}x6ii D]%}|i d|i ddfq?W|||tit}d|jo|o|diSn|otddSniSdS(sConvenience call to return output and set status information Conforms to the WSGI interface for calling purposes only. Example usage: .. code-block:: Python def wsgi_app(environ, start_response): response = WSGIResponse() response.write("Hello world") response.headers['Content-Type'] = 'latin1' return response(environ, start_response) s%s %ss Set-Cookiesheadersswsgi.file_wrappercs iiS(N(sselfscontentsread((sself(s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pysgsN(sSTATUS_CODE_TEXTsselfs status_codes status_textsstatussheaderss headeritemssresponse_headersscookiessvaluesscsappendsoutputsstart_responses isinstancescontentsfilesis_filesenvironsiters get_content(sselfsenvironsstart_responsesstatusscsresponse_headerssis_files status_text((sselfs6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pys__call__Ms # cCs:ti|iidd}|o|idSndS(st Determine the encoding as specified by the Content-Type's charset parameter, if one is set s Content-TypesiN(s _CHARSET_REssearchsselfsheaderssgets charset_matchsgroup(sselfs charset_match((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pysdetermine_charsetjscCs'tidtd|ii|SdS(s5 Case-insensitive check for a header sOWSGIResponse.has_header is deprecated, use WSGIResponse.headers.has_key insteadiN(swarningsswarnsDeprecationWarningsselfsheadersshas_keysheader(sselfsheader((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pys has_headerss  s/c Cs||i|ssdocsGet/set the specified content, where content can be: a string, a list of strings, a generator function that yields strings, or an iterable object that produces strings.cCs8|i}|ot|i||iSn|iSdS(s Returns the content as an iterable of strings, encoding each element of the iterator from a Unicode object if necessary. N(sselfsdetermine_charsetscharsetsencode_unicode_app_iterscontentserrors(sselfscharset((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pys get_contents  cCst|i}d|i|f}|ii}x6|ii D]%}|i d|i ddfq?W|||i fSdS(s| Return this WSGIResponse as a tuple of WSGI formatted data, including: (status, headers, iterable) s%s %ss Set-CookiesheadersN(sSTATUS_CODE_TEXTsselfs status_codes status_textsstatussheaderss headeritemssresponse_headersscookiessvaluesscsappendsoutputs get_content(sselfsstatusscsresponse_headerss status_text((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pys wsgi_responses #cCs6|i otd|iin|ii|dS(NsDThis %s instance's content is not writable: (content is an iterator)(sselfs _is_str_itersIOErrors __class__s__name__scontentsappend(sselfscontent((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pyswrites cCsdS(N((sself((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pysflushscCsZ|i otd|iintgi}|iD]}|t |q6~SdS(NsCThis %s instance cannot tell its position: (content is an iterator)( sselfs _is_str_itersIOErrors __class__s__name__ssumsappends_[1]s_iterschunkslen(sselfschunks_[1]((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pystells cCsQ|iid}| otSnti|}|o|idSntSdS(s; Get/set the charset (in the Content-Type) s content-typeiN( sselfsheaderssgetsheadersNones _CHARSET_REssearchsmatchsgroup(sselfsheadersmatch((s6build/bdist.darwin-8.0.1-x86/egg/paste/wsgiwrappers.pys charset__getscCs|tjo|`dSny|iid}Wntj otdnXti |}|o"||i ||i }n|d|7}||ids sStatusBasedForwardcBs#tZdZedZdZRS(s Middleware that lets you test a response against a custom mapper object to programatically determine whether to internally forward to another URL and if so, which URL to forward to. If you don't need the full power of this middleware you might choose to use the simpler ``forward`` middleware instead. The arguments are: ``app`` The WSGI application or middleware chain. ``mapper`` A callable that takes a status code as the first parameter, a message as the second, and accepts optional environ, global_conf and named argments afterwards. It should return a URL to forward to or ``None`` if the code is not to be intercepted. ``global_conf`` Optional default configuration from your config file. If ``debug`` is set to ``true`` a message will be written to ``wsgi.errors`` on each internal forward stating the URL forwarded to. ``**params`` Optional, any other configuration and extra arguments you wish to pass which will in turn be passed back to the custom mapper object. Here is an example where a ``404 File Not Found`` status response would be redirected to the URL ``/error?code=404&message=File%20Not%20Found``. This could be useful for passing the status code and message into another application to display an error document: .. code-block:: Python from paste.errordocument import StatusBasedForward from paste.recursive import RecursiveMiddleware from urllib import urlencode def error_mapper(code, message, environ, global_conf, kw) if code in [404, 500]: params = urlencode({'message':message, 'code':code}) url = '/error?'%(params) return url else: return None app = RecursiveMiddleware( StatusBasedForward(app, mapper=error_mapper), ) cKsq|tjo h}n|o"ti|idt|_n t|_||_ ||_ ||_||_ dS(Nsdebug( s global_confsNones converterssasboolsgetsFalsesselfsdebugsapps applicationsmappersparams(sselfsappsmappers global_confsparams((s7build/bdist.darwin-8.0.1-x86/egg/paste/errordocument.pys__init__s  "    cs|gtd}i|}o=t|do|ind}t d|n|SdS(Ncs|id}yt|d}Wn3ttfj o!tdt|dnXdi |d}i ||ii}|tjp t|t otdt|n|oi|||gn|||SdS(Ns is@StatusBasedForward middleware received an invalid status code %sisiExpected the url to internally redirect to in the StatusBasedForward mapperto be a string or None, not %s(sstatusssplits status_codesintscodes ValueErrors TypeErrors Exceptionsreprsjoinsmessagesselfsmappersenvirons global_confsparamssnew_urlsNones isinstancesstrsurlsappendsheaderssstart_responsesexc_info(sstatussheaderssexc_infoscodes status_codesnew_urlsmessage(sstart_responsesselfsenvironsurl(s7build/bdist.darwin-8.0.1-x86/egg/paste/errordocument.pyschange_responses sclosec s8t|dddddddddSdS(Nsstatusiisurlsheadersi(s StatusKeepersappsurl(sapp(surl(s7build/bdist.darwin-8.0.1-x86/egg/paste/errordocument.pysfactorys"sfactory( surlsNoneschange_responsesselfs applicationsenvironsapp_itershasattrsclosesfactorysForwardRequestException(sselfsenvironsstart_responseschange_responsesapp_itersfactorysurl((sselfsenvironsstart_responsesurls7build/bdist.darwin-8.0.1-x86/egg/paste/errordocument.pys__call__s (s__name__s __module__s__doc__sNones__init__s__call__(((s7build/bdist.darwin-8.0.1-x86/egg/paste/errordocument.pysStatusBasedForwardVs 4 cKszh}xZ|iD]L\}}yt|}Wn#tj otd|nX||| Error %(code)s

Error %(code)s

%(message)s


Additionally an error occurred trying to produce an error document. A description of the error was logged to wsgi.errors.

( swarningsswarnsDeprecationWarnings global_confsNonesappsselfs applicationsmapperskwsfallback_template(sselfsappsmappers global_confskw((s7build/bdist.darwin-8.0.1-x86/egg/paste/errordocument.pys__init__s        c sggy1td}i|}Wny#dk} t | i d} Wn d} nXyd\}}Wnddg\}}nXdidt | ihd|<d|<gSn7Xo+dh} xIiD];\}}|d jotd | d ( sreprsselfs _current_objs TypeErrorsAttributeErrors __class__s __module__s__name__sid(sself((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys__repr__scCst|iSdS(N(sitersselfs _current_obj(sself((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys__iter__scCst|iSdS(N(slensselfs _current_obj(sself((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys__len__scCs||ijSdS(N(skeysselfs _current_obj(sselfskey((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys __contains__scCst|iSdS(N(sboolsselfs _current_obj(sself((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys __nonzero__scCsit|idt}|o |dSn>|iidt}|tj o|Snt d|i dS(sReturns the current active object being proxied to In the event that no object was pushed, the default object if provided will be used. Otherwise, a TypeError will be raised. sobjectsis____default_object__s8No object (name: %s) has been registered for this threadN( sgetattrsselfs ____local__sNonesobjectss__dict__sgets NoDefaultsobjs TypeErrors ____name__(sselfsobjsobjects((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys _current_objs  cCs;t|id og|i_n|iii|dS(sMake ``obj`` the active object for this thread-local. This should be used like: .. code-block:: Python obj = yourobject() module.glob = StackedObjectProxy() module.glob._push_object(obj) try: ... do stuff ... finally: module.glob._pop_object(conf) sobjectsN(shasattrsselfs ____local__sobjectssappendsobj(sselfsobj((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys _push_objectscCslt|id otdn|iii}|o+||j otd||fqhndS(sRemove a thread-local object. If ``obj`` is given, it is checked against the popped object and an error is emitted if they don't match. sobjectss-No object has been registered for this threadsBThe object popped (%s) is not the same as the object expected (%s)N(shasattrsselfs ____local__sAssertionErrorsobjectsspopspoppedsobj(sselfsobjspopped((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys _pop_objects cCs-y|iiSWntj o gSnXdS(sjReturns all of the objects stacked in this container (Might return [] if there are none) N(sselfs ____local__sobjectssAssertionError(sself((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys _object_stacks cCs5ti}|oti||Sn|iSdS(N(srestorersin_restorations request_idsget_saved_proxied_objsselfs_current_obj_orig(sselfs request_id((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys_current_obj_restorations s.%s (StackedObjectRestorer restoration enabled)cCs#ti o|i|ndS(N(srestorersin_restorationsselfs_push_object_origsobj(sselfsobj((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys_push_object_restorationscCs#ti o|i|ndS(N(srestorersin_restorationsselfs_pop_object_origsobj(sselfsobj((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys_pop_object_restorations(s__name__s __module__s__doc__s NoDefaults__init__s __getattr__s __setattr__s __delattr__s __getitem__s __setitem__s __delitem__s__call__s__repr__s__iter__s__len__s __contains__s __nonzero__s _current_objs _push_objectsNones _pop_objects _object_stacks_current_obj_restorations_push_object_restorations_pop_object_restoration(((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pysStackedObjectProxyds0                    sRegistrycBs8tZdZdZdZdZeZdZRS(sTrack objects and stacked object proxies for removal The Registry object is instantiated a single time for the request no matter how many times the RegistryManager is used in a WSGI stack. Each RegistryManager must call ``prepare`` before continuing the call to start a new context for object registering. Each context is tracked with a dict inside a list. The last list element is the currently executing context. Each context dict is keyed by the id of the StackedObjectProxy instance being proxied, the value is a tuple of the StackedObjectProxy instance and the object being tracked. cCs g|_dS(sCreate a new Registry object ``prepare`` must still be called before this Registry object can be used to register objects. N(sselfsreglist(sself((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys__init__scCs|iihdS(sUsed to create a new registry context Anytime a new RegistryManager is called, ``prepare`` needs to be called on the existing Registry object. This sets up a new context for registering objects. N(sselfsreglistsappend(sself((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pyspreparescCsg|id}t|}||jo |i||d||=n|i|||f|||idd\}}|iht|t|<Sn|i|fSdS(Ns=i(sitemssplitsnamesvaluesselfs _add_varss url_unquotes_add_positional(sselfsitemsnamesvalue((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys __getitem__fs &cKsxA|iD]3}|ido||||d <||=q q W|ii}|i||i |i d|i d|d|i SdS(Ns_isvarssattrssparams( skwskeysskeysendswithsselfsattrsscopys new_attrssupdates __class__surlsvarssoriginal_params(sselfskws new_attrsskey((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysattrls  cKsH|ii}|i||i|id|id|i d|SdS(Nsvarssattrssparams( sselfsoriginal_paramsscopys new_paramssupdateskws __class__surlsvarssattrs(sselfskws new_params((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysparamws   cCst}xa|iD]S\}}t|to t}n|i do||||d <||=qqW|o1t t jodk l a nt i |}n|SdS(Ns_i(svariabledecode(sFalsesneed_variable_encodesvarssitemsskeysvalues isinstancesdictsTruesendswithsvariabledecodesNones formencodesvariable_encode(sselfsvarssneed_variable_encodesvalueskey((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys coerce_vars~s   cKsN|i|}|i|i}|i|id|d|id|i SdS(Nsvarssattrssparams( sselfs coerce_varsskwsvarssitemssnew_varss __class__surlsattrssoriginal_params(sselfskwsnew_vars((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysvars  cKs|i|}g}x>|iD]3\}}||joqn|i||fqW|i|i |i |i d|d|i d|i SdS(s Like ``.var(...)``, except overwrites keys, where .var simply extends the keys. Setting a variable to None here will effectively delete it. svarssattrssparamsN(sselfs coerce_varsskwsnew_varssvarssnamesvaluessappendsextendsitemss __class__surlsattrssoriginal_params(sselfskwsvaluessnew_varssname((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pyssetvars   cKs2|i|id|id|id|iSdS(s Creates a copy of this URL, but with all the variables set/reset (like .setvar(), except clears past variables at the same time) svarssattrssparamsN(sselfs __class__surlskwsitemssattrssoriginal_params(sselfskw((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pyssetvarss c Gs|}xy|D]q}t|id}|i}|id o|d7}n|i ||d|i d|i d|i }q W|SdS(Ns/svarssattrssparams( sselfsuspathsspathsstrslstripsurlsnew_urlsendswiths __class__svarssattrssoriginal_params(sselfspathssnew_urlsuspath((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysaddpaths  cCs,||id|id|id|iSdS(Nsvarssattrssparams(s OtherClasssselfsurlsvarssattrssoriginal_params(sselfs OtherClass((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysbecomes cCs|i}|io|d7}g}x|iD]\}}t|ttfo<gi }|D]!}|t j o||q]q]~}n|t joq-n|i ||fq-W|t i|t7}n|SdS(Ns?(sselfsurlsssvarssnamesvals isinstancesliststuplesappends_[1]svsNonesurllibs urlencodesTrue(sselfsvarssvals_[1]sssvsname((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys href__gets    < c Csd|ii|ipdf}|ioa|ddigi}|ii D],\}}|dt |t |fqM~7}n|i oU|ddigi}|ii D] \}}|d||fq~7}n|d SdS( Ns<%s %ss''s attrs(%s)s s%s="%s"s params(%s)s, s%s=%rs>(sselfs __class__s__name__shrefsbasesattrssjoinsappends_[1]sitemssnsvs html_quotesoriginal_params(sselfsns_[1]sbasesv((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys__repr__s   a UcCs|iid otd|n|i}d|iid}digi}|i D],\}}|dt |t |fqd~}|o|d|7}n||i7}|tjo |dSnd|||iidfSdS(Nstags<You cannot get the HTML of %r until you set the 'tag' param's<%ss s%s="%s"s />s %s>%s(sselfsparamssgets ValueErrors _get_contentscontentstagsjoinsappends_[1]s _html_attrssnsvs html_quotesattrss _html_extrasNone(sselfs_[1]snscontentstagsattrssv((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys html__gets R  cCs|iiSdS(N(sselfsattrssitems(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _html_attrsscCsdSdS(Ns((sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _html_extrascCs tdS(sw Return the content for a tag (for self.html); return None for an empty tag (like ````) N(sNotImplementedError(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _get_contentscCs tdS(N(sNotImplementedError(sselfsvars((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _add_varsscCs tdS(N(sNotImplementedError(sselfsargs((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys_add_positionals(s__name__s __module__s__doc__sdefault_paramssNones__init__sTrues from_environs classmethods__call__s __getitem__sattrsparams coerce_varssvarssetvarssetvarssaddpaths__div__sbecomes href__getspropertyshrefs__repr__s html__getshtmls _html_attrss _html_extras _get_contents _add_varss_add_positional(((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys URLResource8s4                   cBstZdZhdd>> u = URL('http://localhost') >>> u >>> u = u['view'] >>> str(u) 'http://localhost/view' >>> u['//foo'].param(content='view').html 'view' >>> u.param(confirm='Really?', content='goto').html 'goto' >>> u(title='See "it"', content='goto').html 'goto' >>> u('another', var='fuggetaboutit', content='goto').html 'goto' >>> u.attr(content='goto').html Traceback (most recent call last): .... ValueError: You must give a content param to generate anchor tags >>> str(u['foo=bar%20stuff']) 'http://localhost/view?foo=bar+stuff' stagsacCs |iSdS(N(sselfshref(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys__str__!scCs7|iid otd|n|idSdS(Nscontents8You must give a content param to %r generate anchor tags(sselfsparamssgets ValueError(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _get_content$scCs|}xFddfD]8}||jo%|ih||i|<}qqWd|jo|id|id}n|i|SdS(Nsconfirmscontentstarget(sselfsurlsnamesvarssparamspopsattrsvar(sselfsvarssurlsname((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _add_vars+s  ) cCs|i|SdS(N(sselfsaddpathsargs(sselfsargs((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys_add_positional4scCsk|ii}|idd|if|iido(|iddt|idfn|SdS(Nishrefsconfirmsonclicksreturn confirm(%s)( sselfsattrssitemssinsertshrefsparamssgetsappendsjs_repr(sselfsattrs((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _html_attrs7s (cCsdt|iSdS(Nslocation.href=%s; return false(sjs_reprsselfshref(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysonclick_goto__get?scCs|itSdS(N(sselfsbecomesButton(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys button__getDscCs|itSdS(N(sselfsbecomesJSPopup(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys js_popup__getIs(s__name__s __module__s__doc__sdefault_paramss__str__s _get_contents _add_varss_add_positionals _html_attrssonclick_goto__getspropertys onclick_gotos button__getsbuttons js_popup__getsjs_popup(((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysURLs          cBsJtZdZhdd>> i = Image('/images') >>> i = i / '/foo.png' >>> i.html '' >>> str(i['alt=foo']) 'foo' >>> i.href '/images/foo.png' stagsimgcCs |iSdS(N(sselfshtml(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys__str__]scCstSdS(N(sNone(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _get_content`scCs|i|SdS(N(sselfsattrsvars(sselfsvars((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _add_varscscCs|i|SdS(N(sselfsaddpathsargs(sselfsargs((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys_add_positionalfscCs0|ii}|idd|if|SdS(Nissrc(sselfsattrssitemssinsertshref(sselfsattrs((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _html_attrsis( s__name__s __module__s__doc__sdefault_paramss__str__s _get_contents _add_varss_add_positionals _html_attrs(((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysImageNs     sButtoncBsJtZdZhdd>> u = URL('/') >>> u = u / 'delete' >>> b = u.button['confirm=Sure?'](id=5, content='del') >>> str(b) '' stagsbuttoncCs |iSdS(N(sselfshtml(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys__str__zscCsL|iido|idSn|iido|idSntSdS(Nscontentsvalue(sselfsparamssgetsattrssNone(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _get_content}s cCso|}d|jo|id|id}nd|jo|id|id}n|i|SdS(Nsconfirmscontent(sselfsbuttonsvarssparamspopsvar(sselfsvarssbutton((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _add_varss   cCs|i|SdS(N(sselfsaddpathsargs(sselfsargs((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys_add_positionalscCs~|ii}dt|i}|iido!dt|id|f}n|d7}|idd|f|SdS(Nslocation.href=%ssconfirmsif (confirm(%s)) {%s}s; return falseisonclick( sselfsattrssitemssjs_reprshrefsonclicksparamssgetsinsert(sselfsattrssonclick((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _html_attrss! ( s__name__s __module__s__doc__sdefault_paramss__str__s _get_contents _add_varss_add_positionals _html_attrs(((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysButtonns     sJSPopupcBsStZdZhdd<dd>> u = URL('/') >>> u = u / 'view' >>> j = u.js_popup(content='view') >>> j.html 'view' stagsastargets_blankcCsf|}xLddddfD]8}||jo%|ih||i|<}qqW|i|SdS(Nswidthsheightsstrippedscontent(sselfsbuttonsvarsvarssparamspop(sselfsvarssvarsbutton((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _add_varss  )cCsO|i}g}|idod|d<|d<|d  PK-68d??paste/request.pyc; #Gc @s}dZdkZdklZdklZdkZdkZydklZWn e j odk lZnXdk l Z dddd d d d d dg Z dZdZdZdZedZeeeeedZdZdZdZhdd<dd<dd>> environ = {'QUERY_STRING': 'day=Monday&user=fred&user=jane'} >>> parsed = parse_dict_querystring(environ) >>> parsed['day'] 'Monday' >>> parsed['user'] 'fred' >>> parsed.getall('user') ['fred', 'jane'] s QUERY_STRINGsspaste.parsed_dict_querystringskeep_blank_valuessstrict_parsingN( senvironsgetssources MultiDictsparseds check_sourcescgis parse_qslsTruesFalsesmulti(senvironsmultis check_sourcessourcesparsed((s1build/bdist.darwin-8.0.1-x86/egg/paste/request.pysparse_dict_querystringbs      cCsU|d}d|joG|d\}}||jo&|o|it|n|Sq^n|iddi}d|jo|i ddd}n|ddd fj} |id  od |d >> def call_it(script_name, path_info): ... env = {'SCRIPT_NAME': script_name, 'PATH_INFO': path_info} ... result = path_info_pop(env) ... print 'SCRIPT_NAME=%r; PATH_INFO=%r; returns=%r' % ( ... env['SCRIPT_NAME'], env['PATH_INFO'], result) >>> call_it('/foo', '/bar') SCRIPT_NAME='/foo/bar'; PATH_INFO=''; returns='bar' >>> call_it('/foo/bar', '') SCRIPT_NAME='/foo/bar'; PATH_INFO=''; returns=None >>> call_it('/foo/bar', '/') SCRIPT_NAME='/foo/bar/'; PATH_INFO=''; returns='' >>> call_it('', '/1/2/3') SCRIPT_NAME='/1'; PATH_INFO='/2/3'; returns='1' >>> call_it('', '//1/2') SCRIPT_NAME='//1'; PATH_INFO='/2'; returns='1' s PATH_INFOss/s SCRIPT_NAMEiN(senvironsgetspathsNones startswithssplitssegment(senvironspathssegment((s1build/bdist.darwin-8.0.1-x86/egg/paste/request.pys path_info_pops   sHTTP_CGI_AUTHORIZATIONs AuthorizationsCONTENT_LENGTHsContent-Lengths CONTENT_TYPEs Content-Typeccstxm|iD]_\}}|tjot||fVq |ido$|diidd|fVq q WdS(s Parse the headers in the environment (like ``HTTP_HOST``) and yield a sequence of those (header_name, value) tuples. sHTTP_is_s-N(senvirons iteritemsscgi_varsvalues_parse_headers_specials startswithstitlesreplace(senvironscgi_varsvalue((s1build/bdist.darwin-8.0.1-x86/egg/paste/request.pys parse_headersBs  cBs_tZdZdZdZdZdZdZdZdZ dZ d Z RS( sgAn object that represents the headers as present in a WSGI environment. This object is a wrapper (with no internal state) for a WSGI request object, representing the CGI-style HTTP_* keys as a dictionary. Because a CGI environment can only hold one value for each key, this dictionary is single-valued (unlike outgoing headers). cCs ||_dS(N(senvironsself(sselfsenviron((s1build/bdist.darwin-8.0.1-x86/egg/paste/request.pys__init__YscCsRd|iddi}|djo d}n|djo d}n|SdS(NsHTTP_s-s_sHTTP_CONTENT_LENGTHsCONTENT_LENGTHsHTTP_CONTENT_TYPEs CONTENT_TYPE(snamesreplacesupperskey(sselfsnameskey((s1build/bdist.darwin-8.0.1-x86/egg/paste/request.pys _trans_name\s     cCs`|djodSnH|djodSn3|ido|diddiSntSdS( Ns CONTENT_TYPEs Content-TypesCONTENT_LENGTHsContent-LengthsHTTP_is_s-(skeys startswithsreplacestitlesNone(sselfskey((s1build/bdist.darwin-8.0.1-x86/egg/paste/request.pys _trans_keyds  cCs|i|i|SdS(N(sselfsenvirons _trans_namesitem(sselfsitem((s1build/bdist.darwin-8.0.1-x86/egg/paste/request.pys __getitem__nscCs||i|i|tZdZedZdZdZdZdZRS(s An an iterable that iterates over app_iter, calls start_func before the first item is returned, then calls close_func at the end. cCs@||_t||_t|_||_||_t|_ dS(N( s app_iterablesselfsitersapp_itersTruesfirsts start_funcs close_funcsFalses_closed(sselfs app_iterables start_funcs close_func((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys__init__Ds     cCs|SdS(N(sself(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys__iter__LscCs2|io|it|_n|iiSdS(N(sselfsfirsts start_funcsFalsesapp_itersnext(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pysnextOs   cCsOt|_t|ido|iin|itj o|indS(Nsclose(sTruesselfs_closedshasattrs app_iterablescloses close_funcsNone(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pyscloseUs  cCs'|i otid|iIJndS(NsgError: app_iter.close() was not called when finishing WSGI request. finalization function %s not called(sselfs_closedssyssstderrs close_func(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys__del__\s ( s__name__s __module__s__doc__sNones__init__s__iter__snextscloses__del__(((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pysadd_start_close=s     cBs;tZdZdZdZdZdZdZRS(sZ Chains several app_iters together, also delegating .close() to each of them. cGsF||_gi}|D]}|t|q~|_t|_dS(N( schainedsselfs app_iterssappends_[1]sitemsitersFalses_closed(sselfschaineds_[1]sitem((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys__init__ks 0cCs|SdS(N(sself(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys__iter__pscCstt|idjo|idiSnFy|idiSWn-tj o!|iid|iSnXdS(Nii(slensselfschainedsnexts StopIterationspop(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pysnextsscCst|_t}xI|iD]>}y"t|do|inWqt i }qXqW|o|d|d|dndS(Nscloseiii( sTruesselfs_closedsNonesgot_excs app_iterssapp_itershasattrsclosessyssexc_info(sselfsapp_itersgot_exc((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pysclose}s  cCs'|i otid|iIJndS(NsgError: app_iter.close() was not called when finishing WSGI request. finalization function %s not called(sselfs_closedssyssstderrs close_func(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys__del__s (s__name__s __module__s__doc__s__init__s__iter__snextscloses__del__(((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pyschained_app_itersds    cBs>tZdZeiddZdZdZdZRS(s@ Encodes an app_iterable's unicode responses as strings sstrictcCs.||_t||_||_||_dS(N(s app_iterablesselfsitersapp_itersencodingserrors(sselfs app_iterablesencodingserrors((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys__init__s  cCs|SdS(N(sself(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys__iter__scCsC|ii}t|to|i|i|i}n|SdS(N( sselfsapp_itersnextscontents isinstancesunicodesencodesencodingserrors(sselfscontent((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pysnextscCs(t|ido|iindS(Nsclose(shasattrsselfs app_iterablesclose(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pyscloses( s__name__s __module__s__doc__ssyssgetdefaultencodings__init__s__iter__snextsclose(((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pysencode_unicode_app_iters   cCswy|||}Wn|tinXt|tt fjo|o |n|Snt |||SdS(s& Runs the application, and returns the application iterator (which should be passed upstream). If an error occurs then error_callback will be called with exc_info as its sole argument. If no errors occur and ok_callback is given, then it will be called with no arguments. N( s applicationsenvironsstart_responsesapp_iterserror_callbackssyssexc_infostypesliststuples ok_callbacks_wrap_app_iter(s applicationsenvironsstart_responseserror_callbacks ok_callbacksapp_iter((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys catch_errorss s_wrap_app_itercBs#tZdZdZdZRS(NcCsT||_t||_||_||_t|ido|ii|_ndS(Nsclose(s app_iterablesselfsitersapp_iterserror_callbacks ok_callbackshasattrsclose(sselfs app_iterableserror_callbacks ok_callback((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys__init__s    cCs|SdS(N(sself(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys__iter__scCsby|iiSWnJtj o"|io|inn|itinXdS(N(sselfsapp_itersnexts StopIterations ok_callbackserror_callbackssyssexc_info(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pysnexts (s__name__s __module__s__init__s__iter__snext(((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys_wrap_app_iters  cCsy|||}Wn)|j o|||tiSnXt|t t fjo |t j o |n|Snt |||||d|SdS(s Like ``catch_errors``, except error_callback_app should be a callable that will receive *three* arguments -- ``environ``, ``start_response``, and ``exc_info``. It should call ``start_response`` (*with* the exc_info argument!) and return an iterator. scatchN(s applicationsenvironsstart_responsesapp_iterscatchserror_callback_appssyssexc_infostypesliststuples ok_callbacksNones_wrap_app_iter_app(s applicationsenvironsstart_responseserror_callback_apps ok_callbackscatchsapp_iter((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pyscatch_errors_apps   s_wrap_app_iter_appcBs&tZedZdZdZRS(NcCso||_||_||_t||_||_||_||_t |ido|ii |_ ndS(Nsclose( senvironsselfsstart_responses app_iterablesitersapp_iterserror_callback_apps ok_callbackscatchshasattrsclose(sselfsenvironsstart_responses app_iterableserror_callback_apps ok_callbackscatch((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys__init__s      cCs|SdS(N(sself(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys__iter__scCsy|iiSWntj o"|io|inn|ij ot|idoy|iiWqqXn|i |i |i t i }t|}t|do|i|_n|i|_|iSnXdS(Nsclose(sselfsapp_itersnexts StopIterations ok_callbackscatchshasattrs app_iterablescloseserror_callback_appsenvironsstart_responsessyssexc_infosnew_app_iterablesiter(sselfsapp_itersnew_app_iterable((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pysnexts$ !  (s__name__s __module__s Exceptions__init__s__iter__snext(((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys_wrap_app_iter_apps sc s|o t}n t}hdd<dd<dd<dd<dd <d d <d d df<dd<dtd<d|<dt<dt<dt<}|oStt|\}}} }} t i| } | |d<|o||dt$j o2}|i&dd| f|i&d |_&nXWdt'| d o| i(nXd!d"di)|i*fSdS(#s5 Runs the application in a fake environment. sREQUEST_METHODsGETs SCRIPT_NAMEss PATH_INFOs SERVER_NAMEs localhosts SERVER_PORTs80sSERVER_PROTOCOLsHTTP/1.0s wsgi.versioniiswsgi.url_schemeshttps wsgi.inputs wsgi.errorsswsgi.multithreadswsgi.multiprocesss wsgi.run_onces QUERY_STRINGs__s.s HTTP_HOSTsCONTENT_LENGTHcs|o5z'o|d|d|dnWdt}Xnotdnit|d<|d<iSdS(Niiis$Headers already set and no exc_info!sstatussheaders( sexc_infos headers_sentsNones headers_setsAssertionErrorsappendsTruesstatussdatasheaderssoutput(sstatussheaderssexc_info(s headers_sets headers_sentsdatasoutput(s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pysstart_responseDs     sAThe app_iter response can only contain str (not unicode); got: %rsContent sent w/o headers!s iterable: %rNsclosesstatussheaders(+sraise_on_wsgi_errors ErrorRaiserserrorssStringIOsFalses basic_environspathsurlsplitsstrs_s path_infosquerysfragmentsurllibsunquotesenvironsitemssnamesvaluesreplacesistreams isinstanceslensdatasoutputs headers_sets headers_sentsNonesstart_responses applicationsapp_itersss ValueErrorsappendsTruesAssertionErrors TypeErrorsesargsshasattrsclosesjoinsgetvalue(s applicationspathsraise_on_wsgi_errorsenvirons headers_sets headers_sentsstart_responsesqueryserrorssapp_itersistreamsfragments path_infosdatas basic_environs_snamesvaluesssoutputse((s headers_sets headers_sentsdatasoutputs1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pysraw_interactivesZ  !    & s ErrorRaisercBs,tZdZdZdZdZRS(NcCsdS(N((sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pysflushnscCs$| odSntd|dS(Ns%No errors should be written (got: %r)(svaluesAssertionError(sselfsvalue((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pyswriteqscCstdt|dS(Ns+No errors should be written (got lines: %s)(sAssertionErrorslistsseq(sselfsseq((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys writelineswscCsdSdS(Ns((sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pysgetvalue{s(s__name__s __module__sflushswrites writelinessgetvalue(((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys ErrorRaiserls   c Ost||\}}}}t}|o1|i d|i |i |i dn|i |dx+|D]#\}}|i d||fqtW|i d|i ||i SdS(sx Runs the application interatively, wrapping `raw_interactive` but returning the output in a formatted way. sErrors: s ----------end errors s s%s: %s N(sraw_interactivesargsskwsstatussheadersscontentserrorssStringIOsfullswritesstripsnamesvaluesgetvalue( sargsskwsstatusserrorssnamesvaluescontentsheaderssfull((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys interactive~s     cCsg}|i}|ixA|D]9}t||idd}|id||fq#W|id|i dd}|o1|i|di t ||idndi |}ddfd tt|fg}|d ||gSd S( sl Application which simply dumps the current environment variables out as a plain text response. s s s%s: %s sCONTENT_LENGTHss wsgi.inputs Content-Types text/plainsContent-Lengths200 OKN(soutputsenvironskeysssortsksstrsreplacesvsappendsgetscontent_lengthsreadsintsjoinslensheaderssstart_response(senvironsstart_responsescontent_lengthsheadersskskeyssvsoutput((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys dump_environs"    $ cCs1tidtddkl}|i|SdS(Ns9wsgilib.send_file has been moved to paste.fileapp.FileAppi(sfileapp(swarningsswarnsDeprecationWarningspastesfileappsFileAppsfilename(sfilenamesfileapp((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys send_files   c stidtdgttd}|||}z"x|D]}i |qPWWdt |do|inX oitntdjoitniiSdS(s Runs application with environ and start_response, and captures status, headers, and body. Sends status and header, but *not* body. Returns (status, headers, body). Typically this is used like: .. code-block:: Python def dehtmlifying_middleware(application): def replacement_app(environ, start_response): status, headers, body = capture_output( environ, start_response, application) content_type = header_value(headers, 'content-type') if (not content_type or not content_type.startswith('text/html')): return [body] body = re.sub(r'<.*?>', '', body) return [body] return replacement_app sOwsgilib.capture_output has been deprecated in favor of wsgilib.intercept_outputicsGo g(ni|i||||iSdS(N(sdatasappendsstatussheaderssstart_responsesexc_infosoutputswrite(sstatussheaderssexc_info(sstart_responsesoutputsdata(s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pysreplacement_start_responses    Nsclose(swarningsswarnsDeprecationWarningsdatasStringIOsoutputsNonesreplacement_start_responses applicationsenvironsapp_itersitemswriteshasattrsclosesappendslensgetvalue(senvironsstart_responses applicationsreplacement_start_responsesapp_itersitemsoutputsdata((sstart_responsesoutputsdatas1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pyscapture_outputs(   c stj o tjotdngttd}|||}dtjott|fSnz"x|D]}i |qWWdt |do|inX oitntdjoitniiSdS(s Runs application with environ and captures status, headers, and body. None are sent on; you must send them on yourself (unlike ``capture_output``) Typically this is used like: .. code-block:: Python def dehtmlifying_middleware(application): def replacement_app(environ, start_response): status, headers, body = intercept_output( environ, application) content_type = header_value(headers, 'content-type') if (not content_type or not content_type.startswith('text/html')): return [body] body = re.sub(r'<.*?>', '', body) return [body] return replacement_app A third optional argument ``conditional`` should be a function that takes ``conditional(status, headers)`` and returns False if the request should not be intercepted. In that case ``start_response`` will be called and ``(None, None, app_iter)`` will be returned. You must detect that in your code and return the app_iter, like: .. code-block:: Python def dehtmlifying_middleware(application): def replacement_app(environ, start_response): status, headers, body = intercept_output( environ, application, lambda s, h: header_value(headers, 'content-type').startswith('text/html'), start_response) if status is None: return body body = re.sub(r'<.*?>', '', body) return [body] return replacement_app s?If you provide conditional you must also provide start_responsecsvtj o|| o!it|||Sno g(ni|i|i SdS(N( s conditionalsNonesstatussheaderssdatasappendsstart_responsesexc_infosoutputswrite(sstatussheaderssexc_info(sstart_responses conditionalsoutputsdata(s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pysreplacement_start_responses    iNsclosei(s conditionalsNonesstart_responses TypeErrorsdatasStringIOsoutputsreplacement_start_responses applicationsenvironsapp_itersitemswriteshasattrsclosesappendslensgetvalue( senvirons applications conditionalsstart_responsesapp_itersreplacement_start_responsesitemsoutputsdata((s conditionalsstart_responsesoutputsdatas1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pysintercept_outputs,+  sResponseHeaderDictcBstZdZRS(NcOs*tidtdti|||dS(NsPThe class wsgilib.ResponseHeaderDict has been moved to paste.response.HeaderDicti(swarningsswarnsDeprecationWarnings HeaderDicts__init__sselfsargsskw(sselfsargsskw((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys__init__/s  (s__name__s __module__s__init__(((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pysResponseHeaderDict-scsRiiddd}yi|_WnnX|SdS(Ns__name__s.cs.tidftd||SdS(Ns,The function wsgilib.%s has been moved to %si(swarningsswarnsnew_namesnew_pathsDeprecationWarningsnew_funcsargsskw(sargsskw(snew_namesnew_pathsnew_func(s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys replacement9s (snew_funcs func_namesnew_names func_globalssnew_paths replacement(snew_funcsnew_namesnew_paths replacement((snew_funcsnew_namesnew_paths1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys_warn_deprecated6s s func_globalss__name__s__main__(8s__doc__s paste.requests get_cookiessparse_querystringsparse_formvarss construct_urlspath_info_splits path_info_popspaste.responses HeaderDicts has_headers header_values remove_headerserror_body_responseserror_responseserror_response_apps tracebacksprint_exceptionsurllibs cStringIOsStringIOssyssurlparsesurlsplitswarningss__all__sobjects add_closesadd_start_closeschained_app_iterssencode_unicode_app_itersNones catch_errorss_wrap_app_iters Exceptionscatch_errors_apps_wrap_app_iter_appsFalsesraw_interactives ErrorRaisers interactivesproxys dump_environs send_filescapture_outputsintercept_outputsResponseHeaderDicts_warn_deprecateds_namesglobalss_funcshasattrs func_globalss__name__sdocteststestmod((spath_info_splits get_cookiessparse_querystringsprint_exceptions remove_headers add_closeserror_responseserror_body_responsesurlsplits__all__sResponseHeaderDictsurllibs_wrap_app_iter_apps_warn_deprecatedsencode_unicode_app_itersparse_formvarss_funcs send_fileswarningss HeaderDicts dump_environssyss_wrap_app_iters construct_urls header_valuesintercept_outputsraw_interactivesStringIOs catch_errorss path_info_popsadd_start_closes_namescapture_outputscatch_errors_apps ErrorRaisersdoctestserror_response_appschained_app_iterss has_headers interactive((s1build/bdist.darwin-8.0.1-x86/egg/paste/wsgilib.pys?sJ      B '- 'W     2M  $  PK-68*pLKpaste/reloader.pyo; #Gc@sfdZdkZdkZdkZdkZdklZddZdefdYZ e i Z dS(sx A file monitor and server restarter. Use this like: ..code-block:: Python import reloader reloader.install() Then make sure your server is installed with a shell script like:: err=3 while test "$err" -eq 3 ; do python server.py err="$?" done or is run from this .bat file (if you use Windows):: @echo off :repeat python server.py if %errorlevel% == 3 goto repeat or run a monitoring process in Python (``paster serve --reload`` does this). Use the watch_file(filename) function to cause a reload/restart for other other non-Python files (e.g., configuration files). N(sclassinstancemethodicCs?td|}tid|i}|it|i dS(s, Install the reloading monitor. On some platforms server threads may not terminate when the main thread does, causing ports to remain open/locked. The ``raise_keyboard_interrupt`` option creates a unignorable signal which causes the whole application to shut-down (rudely). s poll_intervalstargetN( sMonitors poll_intervalsmons threadingsThreadsperiodic_reloadsts setDaemonsTruesstart(s poll_intervalstsmon((s2build/bdist.darwin-8.0.1-x86/egg/paste/reloader.pysinstall(s  sMonitorcBsDtZgZgZdZdZdZdZeeZRS(NcCs<h|_t|_||_|i|_|ii|dS(N( sselfs module_mtimessTrues keep_runnings poll_intervalsglobal_extra_filess extra_filess instancessappend(sselfs poll_interval((s2build/bdist.darwin-8.0.1-x86/egg/paste/reloader.pys__init__;s     cCsCx<no4|i otidPnti|iq WdS(Nii(sselfs check_reloadsoss_exitstimessleeps poll_interval(sself((s2build/bdist.darwin-8.0.1-x86/egg/paste/reloader.pysperiodic_reloadBs  cCsR|i}xDtiiD]3}y|i|iWqt j o qqXqWx|D]}y-t i |}|o |i }nd}Wnttfj o qXnX|idot ii|d o#tt i |d i |}n|ii| o||i| 100). * That the headers is a list (not a subclass, not another kind of sequence). * That the items of the headers are tuples of strings. * That there is no 'status' header (that is used in CGI, but not in WSGI). * That the headers don't contain newlines or colons, end in _ or -, or contain characters codes below 037. * That Content-Type is given if there is content (CGI often has a default content type, but WSGI does not). * That no Content-Type is given when there is no content (@@: is this too restrictive?) * That the exc_info argument to start_response is a tuple or None. * That all calls to the writer are with strings, and no other methods on the writer are accessed. * That wsgi.input is used properly: - .read() is called with zero or one argument - That it returns a string - That readline, readlines, and __iter__ return strings - That .close() is not called - No other methods are provided * That wsgi.errors is used properly: - .write() and .writelines() is called with a string - That .close() is not called, and no other methods are provided. * The response iterator: - That it is not a string (it should be a list of a single string; a string will work, but perform horribly). - That .next() returns a string - That the iterator is not iterated over until start_response has been called (that can signal either a server or application error). - That .close() is called (doesn't raise exception, only prints to sys.stderr, because we only know it isn't called when the object is garbage collected). N(sDictTypes StringTypes TupleTypesListTypes^[a-zA-Z][a-zA-Z0-9\-_]*$s [\000-\037]s WSGIWarningcBstZdZRS(s: Raised in response to WSGI-spec-related warnings (s__name__s __module__s__doc__(((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys WSGIWarningxs csd}|SdS(s When applied between a WSGI server and a WSGI application, this middleware will check for WSGI compliancy on a number of levels. This middleware does not modify the request or response in any way, but will throw an AssertionError if anything seems off (except for a failure to close the application iterator, which will be printed to stderr -- there's no way to throw an exception at that point). cst|djp td| p td|\}t|gd}t |d|dThe application must return an iterator, if only an empty list(slensargssAssertionErrorskwsenvironsstart_responses check_environsstart_response_startedsstart_response_wrappers InputWrappers ErrorWrappers applicationsiteratorsNonesFalsescheck_iteratorsIteratorWrapper(sargsskwsiteratorsstart_responsesstart_response_wrappersenvironsstart_response_started(s application(sstart_responsesstart_response_starteds.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pyslint_apps  $ N(slint_app(s applications global_confslint_app((s applications.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys middleware}s  )s InputWrappercBs>tZdZdZdZdZdZdZRS(NcCs ||_dS(N(s wsgi_inputsselfsinput(sselfs wsgi_input((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys__init__scGsTt|djpt|ii|}t|tdjpt|SdS(Nis(slensargssAssertionErrorsselfsinputsreadsvstype(sselfsargssv((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pysreads cGs:|ii|}t|tdjpt|SdS(Ns(sselfsinputsreadlinesargssvstypesAssertionError(sselfsargssv((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pysreadlines cGst|djpt|ii|}t|tgjptx.|D]&}t|tdjptqSW|SdS(Nis( slensargssAssertionErrorsselfsinputs readlinesslinesstypesline(sselfsargsslinessline((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys readliness $ccs3x,no$|i}| odSn|Vq WdS(Ni(sselfsreadlinesline(sselfsline((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys__iter__s  cCsdp tddS(Nis input.close() must not be called(sAssertionError(sself((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pyscloses(s__name__s __module__s__init__sreadsreadlines readliness__iter__sclose(((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys InputWrappers      s ErrorWrappercBs5tZdZdZdZdZdZRS(NcCs ||_dS(N(s wsgi_errorssselfserrors(sselfs wsgi_errors((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys__init__scCs4t|tdjpt|ii|dS(Ns(stypesssAssertionErrorsselfserrorsswrite(sselfss((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pyswrites cCs|iidS(N(sselfserrorssflush(sself((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pysflushscCs"x|D]}|i|qWdS(N(sseqslinesselfswrite(sselfsseqsline((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys writelinesscCsdp tddS(Nis!errors.close() must not be called(sAssertionError(sself((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pyscloses(s__name__s __module__s__init__swritesflushs writelinessclose(((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys ErrorWrappers     s WriteWrappercBstZdZdZRS(NcCs ||_dS(N(s wsgi_writersselfswriter(sselfs wsgi_writer((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys__init__scCs1t|tdjpt|i|dS(Ns(stypesssAssertionErrorsselfswriter(sselfss((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys__call__s (s__name__s __module__s__init__s__call__(((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys WriteWrappers sPartialIteratorWrappercBstZdZdZRS(NcCs ||_dS(N(s wsgi_iteratorsselfsiterator(sselfs wsgi_iterator((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys__init__scCst|iSdS(N(sIteratorWrappersselfsiterator(sself((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys__iter__s(s__name__s __module__s__init__s__iter__(((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pysPartialIteratorWrappers sIteratorWrappercBs5tZdZdZdZdZdZRS(NcCs.||_t||_t|_||_dS(N(s wsgi_iteratorsselfsoriginal_iteratorsitersiteratorsFalsesclosedscheck_start_response(sselfs wsgi_iteratorscheck_start_response((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys__init__s  cCs|SdS(N(sself(sself((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys__iter__scCs]|i p td|ii}|itj o!|ip tdt|_n|SdS(NsIterator read after closedsjThe application returns and we started iterating over its body, but start_response has not yet been called(sselfsclosedsAssertionErrorsiteratorsnextsvscheck_start_responsesNone(sselfsv((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pysnexts  cCs1t|_t|ido|iindS(Nsclose(sTruesselfsclosedshasattrsoriginal_iteratorsclose(sself((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pyscloses cCs7|i otiidn|ip tddS(Ns/Iterator garbage collected without being closed(sselfsclosedssyssstderrswritesAssertionError(sself((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys__del__s (s__name__s __module__s__init__s__iter__snextscloses__del__(((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pysIteratorWrappers    c Cst|tjptdt||fxDdddddddd d g D]!}||jptd |qOWx9d d gD]+}||jptd||dfqWd|jotidtnxd|iD]V}d|joqnt||t jp%td|t||||fqWt|dt jptd|d|dddfjptd|dt |dt |d|ddddddddfjotid |dtn|i d! p|d!id"ptd#|d!|i d$ p|d$id"ptd%|d$|i d&o-t|d&d'jptd(|d&n|i d! o|id$p td)n|i d!d"jp td*dS(+Ns:Environment is not of the right type: %r (environment: %r)sREQUEST_METHODs SERVER_NAMEs SERVER_PORTs wsgi.versions wsgi.inputs wsgi.errorsswsgi.multithreadswsgi.multiprocesss wsgi.run_onces$Environment missing required key: %rsHTTP_CONTENT_TYPEsHTTP_CONTENT_LENGTHs8Environment should not have the key: %s (use %s instead)is QUERY_STRINGsQUERY_STRING is not in the WSGI environment; the cgi module will use sys.argv when this variable is missing, so application errors are more likelys.s9Environmental variable %s is not a string: %r (value: %r)s#wsgi.version should be a tuple (%r)swsgi.url_schemeshttpshttpsswsgi.url_scheme unknown: %rsGETsHEADsPOSTsOPTIONSsPUTsDELETEsTRACEsUnknown REQUEST_METHOD: %rs SCRIPT_NAMEs/s$SCRIPT_NAME doesn't start with /: %rs PATH_INFOs"PATH_INFO doesn't start with /: %rsCONTENT_LENGTHisInvalid CONTENT_LENGTH: %rsgOne of SCRIPT_NAME or PATH_INFO are required (PATH_INFO should at least be '/' if SCRIPT_NAME is empty)sOSCRIPT_NAME cannot be '/'; it should instead be '', and PATH_INFO should be '/'(stypesenvironsDictTypesAssertionErrorskeyswarningsswarns WSGIWarningskeyss StringTypes TupleTypes check_inputs check_errorssgets startswithsintshas_key(senvironskey((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys check_environs:-" )     @))& 77-cCsEx>ddddgD]*}t||ptd||fqWdS(Nsreadsreadlines readliness__iter__s-wsgi.input (%r) doesn't have the attribute %s(sattrshasattrs wsgi_inputsAssertionError(s wsgi_inputsattr((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys check_input]scCsBx;dddgD]*}t||ptd||fqWdS(Nsflushswrites writeliness.wsgi.errors (%r) doesn't have the attribute %s(sattrshasattrs wsgi_errorssAssertionError(s wsgi_errorssattr((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys check_errorscscCst|tjptd||itdd}t|djptd|t|}|djptd|t|djp|dd jot i d |t ndS( Ns Status must be a string (not %r)iiis)Status codes must be three characters: %ridsStatus code is invalid: %ris sjThe status string (%r) should be a three-digit integer followed by a single space and a status explanation( stypesstatuss StringTypesAssertionErrorssplitsNones status_codeslensints status_intswarningsswarns WSGIWarning(sstatuss status_codes status_int((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys check_statusis!! $ cCsyt|tjptd|t|fh}x?|D]7}t|tjptd|t|ft|djpt|\}}|i djptd|t ||i q>W||jodpt d|ndS( Niiiii0s content-typesJContent-Type header found in a %s response, which must not return content.s,No Content-Type header found in headers (%s)( sintsstatusssplitsNonescodesNO_MESSAGE_BODYsNO_MESSAGE_TYPEsheaderssnamesvalueslowersAssertionError(sstatussheadersscodesnamesvaluesNO_MESSAGE_TYPEsNO_MESSAGE_BODY((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pyscheck_content_types    cCsD|tjpt|tfjptd|t|fdS(Ns exc_info (%r) is not a tuple: %r(sexc_infosNonestypesAssertionError(sexc_info((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pyscheck_exc_infoscCst|t p tddS(NsvYou should not return a string as your application iterator, instead return a single-item list containing that string.(s isinstancesiteratorsstrsAssertionError(siterator((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pyscheck_iteratorscCst|SdS(N(s middlewares application(s applications global_conf((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pysmake_middlewaress middlewaresmake_middleware( s__doc__sressysstypessDictTypes StringTypes TupleTypesListTypeswarningsscompiles header_resbad_header_value_resWarnings WSGIWarningsNones middlewaresobjects InputWrappers ErrorWrappers WriteWrappersPartialIteratorWrappersIteratorWrappers check_environs check_inputs check_errorss check_statuss check_headersscheck_content_typescheck_exc_infoscheck_iteratorsmake_middlewares__all__(s check_environscheck_content_typescheck_iteratorsmake_middlewares header_res check_statuss WriteWrappersPartialIteratorWrappers StringTypes check_inputs__all__sresDictTypeswarningss check_headersssyssListTypes TupleTypesIteratorWrappers InputWrappersbad_header_value_rescheck_exc_infos middlewares check_errorss WSGIWarnings ErrorWrapper((s.build/bdist.darwin-8.0.1-x86/egg/paste/lint.pys?ns0    7"  ! A         PK;^W70eepaste/flup_session.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php """ Creates a session object. In your application, use:: environ['paste.flup_session_service'].session This will return a dictionary. The contents of this dictionary will be saved to disk when the request is completed. The session will be created when you first fetch the session dictionary, and a cookie will be sent in that case. There's current no way to use sessions without cookies, and there's no way to delete a session except to clear its data. """ from paste import httpexceptions from paste import wsgilib import flup.middleware.session flup_session = flup.middleware.session # This is a dictionary of existing stores, keyed by a tuple of # store type and parameters store_cache = {} class NoDefault(object): pass class SessionMiddleware(object): session_classes = { 'memory': (flup_session.MemorySessionStore, [('session_timeout', 'timeout', int, 60)]), 'disk': (flup_session.DiskSessionStore, [('session_timeout', 'timeout', int, 60), ('session_dir', 'storeDir', str, '/tmp/sessions')]), 'shelve': (flup_session.ShelveSessionStore, [('session_timeout', 'timeout', int, 60), ('session_file', 'storeFile', str, '/tmp/session.shelve')]), } def __init__(self, app, global_conf=None, session_type=NoDefault, cookie_name=NoDefault, **store_config ): self.application = app if session_type is NoDefault: session_type = global_conf.get('session_type', 'disk') self.session_type = session_type try: self.store_class, self.store_args = self.session_classes[self.session_type] except KeyError: raise KeyError( "The session_type %s is unknown (I know about %s)" % (self.session_type, ', '.join(self.session_classes.keys()))) kw = {} for config_name, kw_name, coercer, default in self.store_args: value = coercer(store_config.get(config_name, default)) kw[kw_name] = value self.store = self.store_class(**kw) if cookie_name is NoDefault: cookie_name = global_conf.get('session_cookie', '_SID_') self.cookie_name = cookie_name def __call__(self, environ, start_response): service = flup_session.SessionService( self.store, environ, cookieName=self.cookie_name, fieldName=self.cookie_name) environ['paste.flup_session_service'] = service def cookie_start_response(status, headers, exc_info=None): service.addCookie(headers) return start_response(status, headers, exc_info) try: app_iter = self.application(environ, cookie_start_response) except httpexceptions.HTTPException, e: headers = (e.headers or {}).items() service.addCookie(headers) e.headers = dict(headers) service.close() raise except: service.close() raise return wsgilib.add_close(app_iter, service.close) def make_session_middleware(app, global_conf, session_type=NoDefault, cookie_name=NoDefault, **store_config): """ Wraps the application in a session-managing middleware. The session service can then be found in ``environ['paste.flup_session_service']`` """ return SessionMiddleware( app, global_conf=global_conf, session_type=session_type, cookie_name=cookie_name, **store_config) PK;^W7}]MMpaste/wsgilib.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php """ A module of many disparate routines. """ # functions which moved to paste.request and paste.response # Deprecated around 15 Dec 2005 from paste.request import get_cookies, parse_querystring, parse_formvars from paste.request import construct_url, path_info_split, path_info_pop from paste.response import HeaderDict, has_header, header_value, remove_header from paste.response import error_body_response, error_response, error_response_app from traceback import print_exception import urllib from cStringIO import StringIO import sys from urlparse import urlsplit import warnings __all__ = ['add_close', 'add_start_close', 'capture_output', 'catch_errors', 'catch_errors_app', 'chained_app_iters', 'construct_url', 'dump_environ', 'encode_unicode_app_iter', 'error_body_response', 'error_response', 'get_cookies', 'has_header', 'header_value', 'interactive', 'intercept_output', 'path_info_pop', 'path_info_split', 'raw_interactive', 'send_file'] class add_close(object): """ An an iterable that iterates over app_iter, then calls close_func. """ def __init__(self, app_iterable, close_func): self.app_iterable = app_iterable self.app_iter = iter(app_iterable) self.close_func = close_func self._closed = False def __iter__(self): return self def next(self): return self.app_iter.next() def close(self): self._closed = True if hasattr(self.app_iterable, 'close'): self.app_iterable.close() self.close_func() def __del__(self): if not self._closed: # We can't raise an error or anything at this stage print >> sys.stderr, ( "Error: app_iter.close() was not called when finishing " "WSGI request. finalization function %s not called" % self.close_func) class add_start_close(object): """ An an iterable that iterates over app_iter, calls start_func before the first item is returned, then calls close_func at the end. """ def __init__(self, app_iterable, start_func, close_func=None): self.app_iterable = app_iterable self.app_iter = iter(app_iterable) self.first = True self.start_func = start_func self.close_func = close_func self._closed = False def __iter__(self): return self def next(self): if self.first: self.start_func() self.first = False return self.app_iter.next() def close(self): self._closed = True if hasattr(self.app_iterable, 'close'): self.app_iterable.close() if self.close_func is not None: self.close_func() def __del__(self): if not self._closed: # We can't raise an error or anything at this stage print >> sys.stderr, ( "Error: app_iter.close() was not called when finishing " "WSGI request. finalization function %s not called" % self.close_func) class chained_app_iters(object): """ Chains several app_iters together, also delegating .close() to each of them. """ def __init__(self, *chained): self.app_iters = chained self.chained = [iter(item) for item in chained] self._closed = False def __iter__(self): return self def next(self): if len(self.chained) == 1: return self.chained[0].next() else: try: return self.chained[0].next() except StopIteration: self.chained.pop(0) return self.next() def close(self): self._closed = True got_exc = None for app_iter in self.app_iters: try: if hasattr(app_iter, 'close'): app_iter.close() except: got_exc = sys.exc_info() if got_exc: raise got_exc[0], got_exc[1], got_exc[2] def __del__(self): if not self._closed: # We can't raise an error or anything at this stage print >> sys.stderr, ( "Error: app_iter.close() was not called when finishing " "WSGI request. finalization function %s not called" % self.close_func) class encode_unicode_app_iter(object): """ Encodes an app_iterable's unicode responses as strings """ def __init__(self, app_iterable, encoding=sys.getdefaultencoding(), errors='strict'): self.app_iterable = app_iterable self.app_iter = iter(app_iterable) self.encoding = encoding self.errors = errors def __iter__(self): return self def next(self): content = self.app_iter.next() if isinstance(content, unicode): content = content.encode(self.encoding, self.errors) return content def close(self): if hasattr(self.app_iterable, 'close'): self.app_iterable.close() def catch_errors(application, environ, start_response, error_callback, ok_callback=None): """ Runs the application, and returns the application iterator (which should be passed upstream). If an error occurs then error_callback will be called with exc_info as its sole argument. If no errors occur and ok_callback is given, then it will be called with no arguments. """ try: app_iter = application(environ, start_response) except: error_callback(sys.exc_info()) raise if type(app_iter) in (list, tuple): # These won't produce exceptions if ok_callback: ok_callback() return app_iter else: return _wrap_app_iter(app_iter, error_callback, ok_callback) class _wrap_app_iter(object): def __init__(self, app_iterable, error_callback, ok_callback): self.app_iterable = app_iterable self.app_iter = iter(app_iterable) self.error_callback = error_callback self.ok_callback = ok_callback if hasattr(self.app_iterable, 'close'): self.close = self.app_iterable.close def __iter__(self): return self def next(self): try: return self.app_iter.next() except StopIteration: if self.ok_callback: self.ok_callback() raise except: self.error_callback(sys.exc_info()) raise def catch_errors_app(application, environ, start_response, error_callback_app, ok_callback=None, catch=Exception): """ Like ``catch_errors``, except error_callback_app should be a callable that will receive *three* arguments -- ``environ``, ``start_response``, and ``exc_info``. It should call ``start_response`` (*with* the exc_info argument!) and return an iterator. """ try: app_iter = application(environ, start_response) except catch: return error_callback_app(environ, start_response, sys.exc_info()) if type(app_iter) in (list, tuple): # These won't produce exceptions if ok_callback is not None: ok_callback() return app_iter else: return _wrap_app_iter_app( environ, start_response, app_iter, error_callback_app, ok_callback, catch=catch) class _wrap_app_iter_app(object): def __init__(self, environ, start_response, app_iterable, error_callback_app, ok_callback, catch=Exception): self.environ = environ self.start_response = start_response self.app_iterable = app_iterable self.app_iter = iter(app_iterable) self.error_callback_app = error_callback_app self.ok_callback = ok_callback self.catch = catch if hasattr(self.app_iterable, 'close'): self.close = self.app_iterable.close def __iter__(self): return self def next(self): try: return self.app_iter.next() except StopIteration: if self.ok_callback: self.ok_callback() raise except self.catch: if hasattr(self.app_iterable, 'close'): try: self.app_iterable.close() except: # @@: Print to wsgi.errors? pass new_app_iterable = self.error_callback_app( self.environ, self.start_response, sys.exc_info()) app_iter = iter(new_app_iterable) if hasattr(new_app_iterable, 'close'): self.close = new_app_iterable.close self.next = app_iter.next return self.next() def raw_interactive(application, path='', raise_on_wsgi_error=False, **environ): """ Runs the application in a fake environment. """ assert "path_info" not in environ, "argument list changed" if raise_on_wsgi_error: errors = ErrorRaiser() else: errors = StringIO() basic_environ = { # mandatory CGI variables 'REQUEST_METHOD': 'GET', # always mandatory 'SCRIPT_NAME': '', # may be empty if app is at the root 'PATH_INFO': '', # may be empty if at root of app 'SERVER_NAME': 'localhost', # always mandatory 'SERVER_PORT': '80', # always mandatory 'SERVER_PROTOCOL': 'HTTP/1.0', # mandatory wsgi variables 'wsgi.version': (1, 0), 'wsgi.url_scheme': 'http', 'wsgi.input': StringIO(''), 'wsgi.errors': errors, 'wsgi.multithread': False, 'wsgi.multiprocess': False, 'wsgi.run_once': False, } if path: (_, _, path_info, query, fragment) = urlsplit(str(path)) path_info = urllib.unquote(path_info) basic_environ['PATH_INFO'] = path_info if query: basic_environ['QUERY_STRING'] = query for name, value in environ.items(): name = name.replace('__', '.') basic_environ[name] = value if ('SERVER_NAME' in basic_environ and 'HTTP_HOST' not in basic_environ): basic_environ['HTTP_HOST'] = basic_environ['SERVER_NAME'] istream = basic_environ['wsgi.input'] if isinstance(istream, str): basic_environ['wsgi.input'] = StringIO(istream) basic_environ['CONTENT_LENGTH'] = len(istream) data = {} output = [] headers_set = [] headers_sent = [] def start_response(status, headers, exc_info=None): if exc_info: try: if headers_sent: # Re-raise original exception only if headers sent raise exc_info[0], exc_info[1], exc_info[2] finally: # avoid dangling circular reference exc_info = None elif headers_set: # You cannot set the headers more than once, unless the # exc_info is provided. raise AssertionError("Headers already set and no exc_info!") headers_set.append(True) data['status'] = status data['headers'] = headers return output.append app_iter = application(basic_environ, start_response) try: try: for s in app_iter: if not isinstance(s, str): raise ValueError( "The app_iter response can only contain str (not " "unicode); got: %r" % s) headers_sent.append(True) if not headers_set: raise AssertionError("Content sent w/o headers!") output.append(s) except TypeError, e: # Typically "iteration over non-sequence", so we want # to give better debugging information... e.args = ((e.args[0] + ' iterable: %r' % app_iter),) + e.args[1:] raise finally: if hasattr(app_iter, 'close'): app_iter.close() return (data['status'], data['headers'], ''.join(output), errors.getvalue()) class ErrorRaiser(object): def flush(self): pass def write(self, value): if not value: return raise AssertionError( "No errors should be written (got: %r)" % value) def writelines(self, seq): raise AssertionError( "No errors should be written (got lines: %s)" % list(seq)) def getvalue(self): return '' def interactive(*args, **kw): """ Runs the application interatively, wrapping `raw_interactive` but returning the output in a formatted way. """ status, headers, content, errors = raw_interactive(*args, **kw) full = StringIO() if errors: full.write('Errors:\n') full.write(errors.strip()) full.write('\n----------end errors\n') full.write(status + '\n') for name, value in headers: full.write('%s: %s\n' % (name, value)) full.write('\n') full.write(content) return full.getvalue() interactive.proxy = 'raw_interactive' def dump_environ(environ, start_response): """ Application which simply dumps the current environment variables out as a plain text response. """ output = [] keys = environ.keys() keys.sort() for k in keys: v = str(environ[k]).replace("\n","\n ") output.append("%s: %s\n" % (k, v)) output.append("\n") content_length = environ.get("CONTENT_LENGTH", '') if content_length: output.append(environ['wsgi.input'].read(int(content_length))) output.append("\n") output = "".join(output) headers = [('Content-Type', 'text/plain'), ('Content-Length', str(len(output)))] start_response("200 OK", headers) return [output] def send_file(filename): warnings.warn( "wsgilib.send_file has been moved to paste.fileapp.FileApp", DeprecationWarning, 2) from paste import fileapp return fileapp.FileApp(filename) def capture_output(environ, start_response, application): """ Runs application with environ and start_response, and captures status, headers, and body. Sends status and header, but *not* body. Returns (status, headers, body). Typically this is used like: .. code-block:: Python def dehtmlifying_middleware(application): def replacement_app(environ, start_response): status, headers, body = capture_output( environ, start_response, application) content_type = header_value(headers, 'content-type') if (not content_type or not content_type.startswith('text/html')): return [body] body = re.sub(r'<.*?>', '', body) return [body] return replacement_app """ warnings.warn( 'wsgilib.capture_output has been deprecated in favor ' 'of wsgilib.intercept_output', DeprecationWarning, 2) data = [] output = StringIO() def replacement_start_response(status, headers, exc_info=None): if data: data[:] = [] data.append(status) data.append(headers) start_response(status, headers, exc_info) return output.write app_iter = application(environ, replacement_start_response) try: for item in app_iter: output.write(item) finally: if hasattr(app_iter, 'close'): app_iter.close() if not data: data.append(None) if len(data) < 2: data.append(None) data.append(output.getvalue()) return data def intercept_output(environ, application, conditional=None, start_response=None): """ Runs application with environ and captures status, headers, and body. None are sent on; you must send them on yourself (unlike ``capture_output``) Typically this is used like: .. code-block:: Python def dehtmlifying_middleware(application): def replacement_app(environ, start_response): status, headers, body = intercept_output( environ, application) content_type = header_value(headers, 'content-type') if (not content_type or not content_type.startswith('text/html')): return [body] body = re.sub(r'<.*?>', '', body) return [body] return replacement_app A third optional argument ``conditional`` should be a function that takes ``conditional(status, headers)`` and returns False if the request should not be intercepted. In that case ``start_response`` will be called and ``(None, None, app_iter)`` will be returned. You must detect that in your code and return the app_iter, like: .. code-block:: Python def dehtmlifying_middleware(application): def replacement_app(environ, start_response): status, headers, body = intercept_output( environ, application, lambda s, h: header_value(headers, 'content-type').startswith('text/html'), start_response) if status is None: return body body = re.sub(r'<.*?>', '', body) return [body] return replacement_app """ if conditional is not None and start_response is None: raise TypeError( "If you provide conditional you must also provide " "start_response") data = [] output = StringIO() def replacement_start_response(status, headers, exc_info=None): if conditional is not None and not conditional(status, headers): data.append(None) return start_response(status, headers, exc_info) if data: data[:] = [] data.append(status) data.append(headers) return output.write app_iter = application(environ, replacement_start_response) if data[0] is None: return (None, None, app_iter) try: for item in app_iter: output.write(item) finally: if hasattr(app_iter, 'close'): app_iter.close() if not data: data.append(None) if len(data) < 2: data.append(None) data.append(output.getvalue()) return data ## Deprecation warning wrapper: class ResponseHeaderDict(HeaderDict): def __init__(self, *args, **kw): warnings.warn( "The class wsgilib.ResponseHeaderDict has been moved " "to paste.response.HeaderDict", DeprecationWarning, 2) HeaderDict.__init__(self, *args, **kw) def _warn_deprecated(new_func): new_name = new_func.func_name new_path = new_func.func_globals['__name__'] + '.' + new_name def replacement(*args, **kw): warnings.warn( "The function wsgilib.%s has been moved to %s" % (new_name, new_path), DeprecationWarning, 2) return new_func(*args, **kw) try: replacement.func_name = new_func.func_name except: pass return replacement # Put warnings wrapper in place for all public functions that # were imported from elsewhere: for _name in __all__: _func = globals()[_name] if (hasattr(_func, 'func_globals') and _func.func_globals['__name__'] != __name__): globals()[_name] = _warn_deprecated(_func) if __name__ == '__main__': import doctest doctest.testmod() PK-68wHVUU paste/url.pyo; #Gc@sdZdkZdkZdklZeaddgZdZdZ ei Z dZ de fd YZdefd YZdefd YZd efd YZdefdYZedjodkZeindS(s3 This module implements a class for handling URLs. N(srequestsURLsImagecCs/|tjodSntit|dSdS(Nsi(svsNonescgisescapesstr(sv((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys html_quotes cCs,|tjodSntit|SdS(Ns(svsNonesurllibsquotesstr(sv((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys url_quotes c Cs|tjodSny|tjodSnd|tjodSnOt|todditt|Sn!t|t oRddigi }|D],\}}|dt|t|fq~Snt|tot|Snt|tot|idSnzt|ttfot|SnVt|tot|id Sn/t|d o|iSntd |dS( Nsnullsfalsestrues[%s]s, s{%s}s%s: %ssUTF-8sLs __js_repr__s<I don't know how to turn %r into a Javascript representation(svsNonesFalsesTrues isinstanceslistsjoinsmapsjs_reprsdictsappends_[1]skeysvaluesstrsreprsunicodesencodesfloatsintslongslstripshasattrs __js_repr__s ValueError(svsvalues_[1]skey((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysjs_reprs*   Rs URLResourcecBs tZdZhZeeedZeeeeedZeeZdZ dZ dZ dZ dZ dZd Zd Zd ZeZd Zd ZeeZdZdZeeZdZdZdZdZdZRS(sD This is an abstract superclass for different kinds of URLs cCsq|pd|_|pg|_|ph|_|ii|_|ph|_|o|ii|ndS(Ns/( surlsselfsvarssattrssdefault_paramsscopysparamssoriginal_paramssupdate(sselfsurlsvarssattrssparams((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys__init__@sc Csti|dtd|d|d|}|o?|t joti |}qst i|dtdt}nt }||d|} | SdS(Nswith_query_stringswith_path_infos script_names path_infoskeep_blank_valuessstrict_parsingsvars(srequests construct_urlsenvironsFalseswith_path_infos script_names path_infosurlswith_query_strings querystringsNonesparse_querystringsvarsscgis parse_qslsTruesclssv( sclssenvironswith_query_stringswith_path_infos script_names path_infos querystringsvarssurlsv((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys from_environKs    cOs&|i|}|i|}|SdS(N(sselfs_add_positionalsargssress _add_varsskw(sselfsargsskwsres((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys__call__ascCs_d|jo>|idd\}}|iht|t|<Sn|i|fSdS(Ns=i(sitemssplitsnamesvaluesselfs _add_varss url_unquotes_add_positional(sselfsitemsnamesvalue((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys __getitem__fs &cKsxA|iD]3}|ido||||d <||=q q W|ii}|i||i |i d|i d|d|i SdS(Ns_isvarssattrssparams( skwskeysskeysendswithsselfsattrsscopys new_attrssupdates __class__surlsvarssoriginal_params(sselfskws new_attrsskey((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysattrls  cKsH|ii}|i||i|id|id|i d|SdS(Nsvarssattrssparams( sselfsoriginal_paramsscopys new_paramssupdateskws __class__surlsvarssattrs(sselfskws new_params((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysparamws   cCst}xa|iD]S\}}t|to t}n|i do||||d <||=qqW|o1t t jodk l a nt i |}n|SdS(Ns_i(svariabledecode(sFalsesneed_variable_encodesvarssitemsskeysvalues isinstancesdictsTruesendswithsvariabledecodesNones formencodesvariable_encode(sselfsvarssneed_variable_encodesvalueskey((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys coerce_vars~s   cKsN|i|}|i|i}|i|id|d|id|i SdS(Nsvarssattrssparams( sselfs coerce_varsskwsvarssitemssnew_varss __class__surlsattrssoriginal_params(sselfskwsnew_vars((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysvars  cKs|i|}g}x>|iD]3\}}||joqn|i||fqW|i|i |i |i d|d|i d|i SdS(s Like ``.var(...)``, except overwrites keys, where .var simply extends the keys. Setting a variable to None here will effectively delete it. svarssattrssparamsN(sselfs coerce_varsskwsnew_varssvarssnamesvaluessappendsextendsitemss __class__surlsattrssoriginal_params(sselfskwsvaluessnew_varssname((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pyssetvars   cKs2|i|id|id|id|iSdS(s Creates a copy of this URL, but with all the variables set/reset (like .setvar(), except clears past variables at the same time) svarssattrssparamsN(sselfs __class__surlskwsitemssattrssoriginal_params(sselfskw((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pyssetvarss c Gs|}xy|D]q}t|id}|i}|id o|d7}n|i ||d|i d|i d|i }q W|SdS(Ns/svarssattrssparams( sselfsuspathsspathsstrslstripsurlsnew_urlsendswiths __class__svarssattrssoriginal_params(sselfspathssnew_urlsuspath((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysaddpaths  cCs,||id|id|id|iSdS(Nsvarssattrssparams(s OtherClasssselfsurlsvarssattrssoriginal_params(sselfs OtherClass((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysbecomes cCs|i}|io|d7}g}x|iD]\}}t|ttfo<gi }|D]!}|t j o||q]q]~}n|t joq-n|i ||fq-W|t i|t7}n|SdS(Ns?(sselfsurlsssvarssnamesvals isinstancesliststuplesappends_[1]svsNonesurllibs urlencodesTrue(sselfsvarssvals_[1]sssvsname((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys href__gets    < c Csd|ii|ipdf}|ioa|ddigi}|ii D],\}}|dt |t |fqM~7}n|i oU|ddigi}|ii D] \}}|d||fq~7}n|d SdS( Ns<%s %ss''s attrs(%s)s s%s="%s"s params(%s)s, s%s=%rs>(sselfs __class__s__name__shrefsbasesattrssjoinsappends_[1]sitemssnsvs html_quotesoriginal_params(sselfsns_[1]sbasesv((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys__repr__s   a UcCs|iid otd|n|i}d|iid}digi}|i D],\}}|dt |t |fqd~}|o|d|7}n||i7}|tjo |dSnd|||iidfSdS(Nstags<You cannot get the HTML of %r until you set the 'tag' param's<%ss s%s="%s"s />s %s>%s(sselfsparamssgets ValueErrors _get_contentscontentstagsjoinsappends_[1]s _html_attrssnsvs html_quotesattrss _html_extrasNone(sselfs_[1]snscontentstagsattrssv((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys html__gets R  cCs|iiSdS(N(sselfsattrssitems(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _html_attrsscCsdSdS(Ns((sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _html_extrascCs tdS(sw Return the content for a tag (for self.html); return None for an empty tag (like ````) N(sNotImplementedError(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _get_contentscCs tdS(N(sNotImplementedError(sselfsvars((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _add_varsscCs tdS(N(sNotImplementedError(sselfsargs((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys_add_positionals(s__name__s __module__s__doc__sdefault_paramssNones__init__sTrues from_environs classmethods__call__s __getitem__sattrsparams coerce_varssvarssetvarssetvarssaddpaths__div__sbecomes href__getspropertyshrefs__repr__s html__getshtmls _html_attrss _html_extras _get_contents _add_varss_add_positional(((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys URLResource8s4                   cBstZdZhdd>> u = URL('http://localhost') >>> u >>> u = u['view'] >>> str(u) 'http://localhost/view' >>> u['//foo'].param(content='view').html 'view' >>> u.param(confirm='Really?', content='goto').html 'goto' >>> u(title='See "it"', content='goto').html 'goto' >>> u('another', var='fuggetaboutit', content='goto').html 'goto' >>> u.attr(content='goto').html Traceback (most recent call last): .... ValueError: You must give a content param to generate anchor tags >>> str(u['foo=bar%20stuff']) 'http://localhost/view?foo=bar+stuff' stagsacCs |iSdS(N(sselfshref(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys__str__!scCs7|iid otd|n|idSdS(Nscontents8You must give a content param to %r generate anchor tags(sselfsparamssgets ValueError(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _get_content$scCs|}xFddfD]8}||jo%|ih||i|<}qqWd|jo|id|id}n|i|SdS(Nsconfirmscontentstarget(sselfsurlsnamesvarssparamspopsattrsvar(sselfsvarssurlsname((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _add_vars+s  ) cCs|i|SdS(N(sselfsaddpathsargs(sselfsargs((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys_add_positional4scCsk|ii}|idd|if|iido(|iddt|idfn|SdS(Nishrefsconfirmsonclicksreturn confirm(%s)( sselfsattrssitemssinsertshrefsparamssgetsappendsjs_repr(sselfsattrs((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _html_attrs7s (cCsdt|iSdS(Nslocation.href=%s; return false(sjs_reprsselfshref(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysonclick_goto__get?scCs|itSdS(N(sselfsbecomesButton(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys button__getDscCs|itSdS(N(sselfsbecomesJSPopup(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys js_popup__getIs(s__name__s __module__s__doc__sdefault_paramss__str__s _get_contents _add_varss_add_positionals _html_attrssonclick_goto__getspropertys onclick_gotos button__getsbuttons js_popup__getsjs_popup(((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysURLs          cBsJtZdZhdd>> i = Image('/images') >>> i = i / '/foo.png' >>> i.html '' >>> str(i['alt=foo']) 'foo' >>> i.href '/images/foo.png' stagsimgcCs |iSdS(N(sselfshtml(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys__str__]scCstSdS(N(sNone(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _get_content`scCs|i|SdS(N(sselfsattrsvars(sselfsvars((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _add_varscscCs|i|SdS(N(sselfsaddpathsargs(sselfsargs((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys_add_positionalfscCs0|ii}|idd|if|SdS(Nissrc(sselfsattrssitemssinsertshref(sselfsattrs((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _html_attrsis( s__name__s __module__s__doc__sdefault_paramss__str__s _get_contents _add_varss_add_positionals _html_attrs(((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysImageNs     sButtoncBsJtZdZhdd>> u = URL('/') >>> u = u / 'delete' >>> b = u.button['confirm=Sure?'](id=5, content='del') >>> str(b) '' stagsbuttoncCs |iSdS(N(sselfshtml(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys__str__zscCsL|iido|idSn|iido|idSntSdS(Nscontentsvalue(sselfsparamssgetsattrssNone(sself((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _get_content}s cCso|}d|jo|id|id}nd|jo|id|id}n|i|SdS(Nsconfirmscontent(sselfsbuttonsvarssparamspopsvar(sselfsvarssbutton((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _add_varss   cCs|i|SdS(N(sselfsaddpathsargs(sselfsargs((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys_add_positionalscCs~|ii}dt|i}|iido!dt|id|f}n|d7}|idd|f|SdS(Nslocation.href=%ssconfirmsif (confirm(%s)) {%s}s; return falseisonclick( sselfsattrssitemssjs_reprshrefsonclicksparamssgetsinsert(sselfsattrssonclick((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _html_attrss! ( s__name__s __module__s__doc__sdefault_paramss__str__s _get_contents _add_varss_add_positionals _html_attrs(((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pysButtonns     sJSPopupcBsStZdZhdd<dd>> u = URL('/') >>> u = u / 'view' >>> j = u.js_popup(content='view') >>> j.html 'view' stagsastargets_blankcCsf|}xLddddfD]8}||jo%|ih||i|<}qqW|i|SdS(Nswidthsheightsstrippedscontent(sselfsbuttonsvarsvarssparamspop(sselfsvarssvarsbutton((s-build/bdist.darwin-8.0.1-x86/egg/paste/url.pys _add_varss  )cCsO|i}g}|idod|d<|d<|d  PK-68I[t?&&paste/modpython.pyc; #Gc@sdZdkZydklZWnnXdklZdefdYZdefdYZdZ d efd YZ e a e a had ZdS( sWSGI Paste wrapper for mod_python. Requires Python 2.2 or greater. Example httpd.conf section for a Paste app with an ini file:: SetHandler python-program PythonHandler paste.modpython PythonOption paste.ini /some/location/your/pasteconfig.ini Or if you want to load a WSGI application under /your/homedir in the module ``startup`` and the WSGI app is ``app``:: SetHandler python-program PythonHandler paste.modpython PythonPath "['/virtual/project/directory'] + sys.path" PythonOption wsgi.application startup::app If you'd like to use a virtual installation, make sure to add it in the path like so:: SetHandler python-program PythonHandler paste.modpython PythonPath "['/virtual/project/directory', '/virtual/lib/python2.4/'] + sys.path" PythonOption paste.ini /virtual/project/directory/pasteconfig.ini Some WSGI implementations assume that the SCRIPT_NAME environ variable will always be equal to "the root URL of the app"; Apache probably won't act as you expect in that case. You can add another PythonOption directive to tell modpython_gateway to force that behavior: PythonOption SCRIPT_NAME /mcontrol Some WSGI applications need to be cleaned up when Apache exits. You can register a cleanup handler with yet another PythonOption directive: PythonOption wsgi.cleanup module::function The module.function will be called with no arguments on server shutdown, once for each child process or thread. This module highly based on Robert Brewer's, here: http://projects.amor.org/misc/svn/modpython_gateway.py N(sapache(sloadapps InputWrappercBsGtZdZdZddZddZddZdZRS(NcCs ||_dS(N(sreqsself(sselfsreq((s3build/bdist.darwin-8.0.1-x86/egg/paste/modpython.pys__init__>scCsdS(N((sself((s3build/bdist.darwin-8.0.1-x86/egg/paste/modpython.pyscloseAsicCs|ii|SdS(N(sselfsreqsreadssize(sselfssize((s3build/bdist.darwin-8.0.1-x86/egg/paste/modpython.pysreadDscCs|ii|SdS(N(sselfsreqsreadlinessize(sselfssize((s3build/bdist.darwin-8.0.1-x86/egg/paste/modpython.pysreadlineGscCs|ii|SdS(N(sselfsreqs readlinesshint(sselfshint((s3build/bdist.darwin-8.0.1-x86/egg/paste/modpython.pys readlinesJsccs/|i}x|o|V|i}qWdS(N(sselfsreadlinesline(sselfsline((s3build/bdist.darwin-8.0.1-x86/egg/paste/modpython.pys__iter__Ms  (s__name__s __module__s__init__sclosesreadsreadlines readliness__iter__(((s3build/bdist.darwin-8.0.1-x86/egg/paste/modpython.pys InputWrapper<s      s ErrorWrappercBs,tZdZdZdZdZRS(NcCs ||_dS(N(sreqsself(sselfsreq((s3build/bdist.darwin-8.0.1-x86/egg/paste/modpython.pys__init__XscCsdS(N((sself((s3build/bdist.darwin-8.0.1-x86/egg/paste/modpython.pysflush[scCs|ii|dS(N(sselfsreqs log_errorsmsg(sselfsmsg((s3build/bdist.darwin-8.0.1-x86/egg/paste/modpython.pyswrite^scCs|idi|dS(Ns(sselfswritesjoinsseq(sselfsseq((s3build/bdist.darwin-8.0.1-x86/egg/paste/modpython.pys writelinesas(s__name__s __module__s__init__sflushswrites writelines(((s3build/bdist.darwin-8.0.1-x86/egg/paste/modpython.pys ErrorWrapperVs   sfYou must provide a PythonOption '%s', either 'on' or 'off', when running a version of mod_python < 3.1sHandlercBs/tZdZdZedZdZRS(NcCst|_|i}y+ti}|ti }|ti }Wnt j o|iddi}|djo t}n(|djo t}nttd|iddi}|djo t}q|djo t}qttdnXtti|}|_d|jo-|d|d<|it|d|d 100). * That the headers is a list (not a subclass, not another kind of sequence). * That the items of the headers are tuples of strings. * That there is no 'status' header (that is used in CGI, but not in WSGI). * That the headers don't contain newlines or colons, end in _ or -, or contain characters codes below 037. * That Content-Type is given if there is content (CGI often has a default content type, but WSGI does not). * That no Content-Type is given when there is no content (@@: is this too restrictive?) * That the exc_info argument to start_response is a tuple or None. * That all calls to the writer are with strings, and no other methods on the writer are accessed. * That wsgi.input is used properly: - .read() is called with zero or one argument - That it returns a string - That readline, readlines, and __iter__ return strings - That .close() is not called - No other methods are provided * That wsgi.errors is used properly: - .write() and .writelines() is called with a string - That .close() is not called, and no other methods are provided. * The response iterator: - That it is not a string (it should be a list of a single string; a string will work, but perform horribly). - That .next() returns a string - That the iterator is not iterated over until start_response has been called (that can signal either a server or application error). - That .close() is called (doesn't raise exception, only prints to sys.stderr, because we only know it isn't called when the object is garbage collected). """ import re import sys from types import DictType, StringType, TupleType, ListType import warnings header_re = re.compile(r'^[a-zA-Z][a-zA-Z0-9\-_]*$') bad_header_value_re = re.compile(r'[\000-\037]') class WSGIWarning(Warning): """ Raised in response to WSGI-spec-related warnings """ def middleware(application, global_conf=None): """ When applied between a WSGI server and a WSGI application, this middleware will check for WSGI compliancy on a number of levels. This middleware does not modify the request or response in any way, but will throw an AssertionError if anything seems off (except for a failure to close the application iterator, which will be printed to stderr -- there's no way to throw an exception at that point). """ def lint_app(*args, **kw): assert len(args) == 2, "Two arguments required" assert not kw, "No keyword arguments allowed" environ, start_response = args check_environ(environ) # We use this to check if the application returns without # calling start_response: start_response_started = [] def start_response_wrapper(*args, **kw): assert len(args) == 2 or len(args) == 3, ( "Invalid number of arguments: %s" % args) assert not kw, "No keyword arguments allowed" status = args[0] headers = args[1] if len(args) == 3: exc_info = args[2] else: exc_info = None check_status(status) check_headers(headers) check_content_type(status, headers) check_exc_info(exc_info) start_response_started.append(None) return WriteWrapper(start_response(*args)) environ['wsgi.input'] = InputWrapper(environ['wsgi.input']) environ['wsgi.errors'] = ErrorWrapper(environ['wsgi.errors']) iterator = application(environ, start_response_wrapper) assert iterator is not None and iterator != False, ( "The application must return an iterator, if only an empty list") check_iterator(iterator) return IteratorWrapper(iterator, start_response_started) return lint_app class InputWrapper(object): def __init__(self, wsgi_input): self.input = wsgi_input def read(self, *args): assert len(args) <= 1 v = self.input.read(*args) assert type(v) is type("") return v def readline(self, *args): v = self.input.readline(*args) assert type(v) is type("") return v def readlines(self, *args): assert len(args) <= 1 lines = self.input.readlines(*args) assert type(lines) is type([]) for line in lines: assert type(line) is type("") return lines def __iter__(self): while 1: line = self.readline() if not line: return yield line def close(self): assert 0, "input.close() must not be called" class ErrorWrapper(object): def __init__(self, wsgi_errors): self.errors = wsgi_errors def write(self, s): assert type(s) is type("") self.errors.write(s) def flush(self): self.errors.flush() def writelines(self, seq): for line in seq: self.write(line) def close(self): assert 0, "errors.close() must not be called" class WriteWrapper(object): def __init__(self, wsgi_writer): self.writer = wsgi_writer def __call__(self, s): assert type(s) is type("") self.writer(s) class PartialIteratorWrapper(object): def __init__(self, wsgi_iterator): self.iterator = wsgi_iterator def __iter__(self): # We want to make sure __iter__ is called return IteratorWrapper(self.iterator) class IteratorWrapper(object): def __init__(self, wsgi_iterator, check_start_response): self.original_iterator = wsgi_iterator self.iterator = iter(wsgi_iterator) self.closed = False self.check_start_response = check_start_response def __iter__(self): return self def next(self): assert not self.closed, ( "Iterator read after closed") v = self.iterator.next() if self.check_start_response is not None: assert self.check_start_response, ( "The application returns and we started iterating over its body, but start_response has not yet been called") self.check_start_response = None return v def close(self): self.closed = True if hasattr(self.original_iterator, 'close'): self.original_iterator.close() def __del__(self): if not self.closed: sys.stderr.write( "Iterator garbage collected without being closed") assert self.closed, ( "Iterator garbage collected without being closed") def check_environ(environ): assert type(environ) is DictType, ( "Environment is not of the right type: %r (environment: %r)" % (type(environ), environ)) for key in ['REQUEST_METHOD', 'SERVER_NAME', 'SERVER_PORT', 'wsgi.version', 'wsgi.input', 'wsgi.errors', 'wsgi.multithread', 'wsgi.multiprocess', 'wsgi.run_once']: assert key in environ, ( "Environment missing required key: %r" % key) for key in ['HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH']: assert key not in environ, ( "Environment should not have the key: %s " "(use %s instead)" % (key, key[5:])) if 'QUERY_STRING' not in environ: warnings.warn( 'QUERY_STRING is not in the WSGI environment; the cgi ' 'module will use sys.argv when this variable is missing, ' 'so application errors are more likely', WSGIWarning) for key in environ.keys(): if '.' in key: # Extension, we don't care about its type continue assert type(environ[key]) is StringType, ( "Environmental variable %s is not a string: %r (value: %r)" % (key, type(environ[key]), environ[key])) assert type(environ['wsgi.version']) is TupleType, ( "wsgi.version should be a tuple (%r)" % environ['wsgi.version']) assert environ['wsgi.url_scheme'] in ('http', 'https'), ( "wsgi.url_scheme unknown: %r" % environ['wsgi.url_scheme']) check_input(environ['wsgi.input']) check_errors(environ['wsgi.errors']) # @@: these need filling out: if environ['REQUEST_METHOD'] not in ( 'GET', 'HEAD', 'POST', 'OPTIONS','PUT','DELETE','TRACE'): warnings.warn( "Unknown REQUEST_METHOD: %r" % environ['REQUEST_METHOD'], WSGIWarning) assert (not environ.get('SCRIPT_NAME') or environ['SCRIPT_NAME'].startswith('/')), ( "SCRIPT_NAME doesn't start with /: %r" % environ['SCRIPT_NAME']) assert (not environ.get('PATH_INFO') or environ['PATH_INFO'].startswith('/')), ( "PATH_INFO doesn't start with /: %r" % environ['PATH_INFO']) if environ.get('CONTENT_LENGTH'): assert int(environ['CONTENT_LENGTH']) >= 0, ( "Invalid CONTENT_LENGTH: %r" % environ['CONTENT_LENGTH']) if not environ.get('SCRIPT_NAME'): assert environ.has_key('PATH_INFO'), ( "One of SCRIPT_NAME or PATH_INFO are required (PATH_INFO " "should at least be '/' if SCRIPT_NAME is empty)") assert environ.get('SCRIPT_NAME') != '/', ( "SCRIPT_NAME cannot be '/'; it should instead be '', and " "PATH_INFO should be '/'") def check_input(wsgi_input): for attr in ['read', 'readline', 'readlines', '__iter__']: assert hasattr(wsgi_input, attr), ( "wsgi.input (%r) doesn't have the attribute %s" % (wsgi_input, attr)) def check_errors(wsgi_errors): for attr in ['flush', 'write', 'writelines']: assert hasattr(wsgi_errors, attr), ( "wsgi.errors (%r) doesn't have the attribute %s" % (wsgi_errors, attr)) def check_status(status): assert type(status) is StringType, ( "Status must be a string (not %r)" % status) # Implicitly check that we can turn it into an integer: status_code = status.split(None, 1)[0] assert len(status_code) == 3, ( "Status codes must be three characters: %r" % status_code) status_int = int(status_code) assert status_int >= 100, "Status code is invalid: %r" % status_int if len(status) < 4 or status[3] != ' ': warnings.warn( "The status string (%r) should be a three-digit integer " "followed by a single space and a status explanation" % status, WSGIWarning) def check_headers(headers): assert type(headers) is ListType, ( "Headers (%r) must be of type list: %r" % (headers, type(headers))) header_names = {} for item in headers: assert type(item) is TupleType, ( "Individual headers (%r) must be of type tuple: %r" % (item, type(item))) assert len(item) == 2 name, value = item assert name.lower() != 'status', ( "The Status header cannot be used; it conflicts with CGI " "script, and HTTP status is not given through headers " "(value: %r)." % value) header_names[name.lower()] = None assert '\n' not in name and ':' not in name, ( "Header names may not contain ':' or '\\n': %r" % name) assert header_re.search(name), "Bad header name: %r" % name assert not name.endswith('-') and not name.endswith('_'), ( "Names may not end in '-' or '_': %r" % name) assert not bad_header_value_re.search(value), ( "Bad header value: %r (bad char: %r)" % (value, bad_header_value_re.search(value).group(0))) def check_content_type(status, headers): code = int(status.split(None, 1)[0]) # @@: need one more person to verify this interpretation of RFC 2616 # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html NO_MESSAGE_BODY = (201, 204, 304) NO_MESSAGE_TYPE = (204, 304) for name, value in headers: if name.lower() == 'content-type': if code not in NO_MESSAGE_TYPE: return assert 0, (("Content-Type header found in a %s response, " "which must not return content.") % code) if code not in NO_MESSAGE_BODY: assert 0, "No Content-Type header found in headers (%s)" % headers def check_exc_info(exc_info): assert exc_info is None or type(exc_info) is type(()), ( "exc_info (%r) is not a tuple: %r" % (exc_info, type(exc_info))) # More exc_info checks? def check_iterator(iterator): # Technically a string is legal, which is why it's a really bad # idea, because it may cause the response to be returned # character-by-character assert not isinstance(iterator, str), ( "You should not return a string as your application iterator, " "instead return a single-item list containing that string.") def make_middleware(application, global_conf): # @@: global_conf should be taken out of the middleware function, # and isolated here return middleware(application) make_middleware.__doc__ = __doc__ __all__ = ['middleware', 'make_middleware'] PK;^W7WVWVpaste/wsgiwrappers.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php """WSGI Wrappers for a Request and Response The WSGIRequest and WSGIResponse objects are light wrappers to make it easier to deal with an incoming request and sending a response. """ import re import warnings from pprint import pformat from Cookie import SimpleCookie from paste.request import EnvironHeaders, get_cookie_dict, \ parse_dict_querystring, parse_formvars from paste.util.multidict import MultiDict, UnicodeMultiDict from paste.registry import StackedObjectProxy from paste.response import HeaderDict from paste.wsgilib import encode_unicode_app_iter from paste.httpheaders import ACCEPT_LANGUAGE from paste.util.mimeparse import desired_matches __all__ = ['WSGIRequest', 'WSGIResponse'] _CHARSET_RE = re.compile(r';\s*charset=([^;]*)', re.I) class DeprecatedSettings(StackedObjectProxy): def _push_object(self, obj): warnings.warn('paste.wsgiwrappers.settings is deprecated: Please use ' 'paste.wsgiwrappers.WSGIRequest.defaults instead', DeprecationWarning, 3) WSGIResponse.defaults._push_object(obj) StackedObjectProxy._push_object(self, obj) # settings is deprecated: use WSGIResponse.defaults instead settings = DeprecatedSettings(default=dict()) class environ_getter(object): """For delegating an attribute to a key in self.environ.""" # @@: Also __set__? Should setting be allowed? def __init__(self, key, default='', default_factory=None): self.key = key self.default = default self.default_factory = default_factory def __get__(self, obj, type=None): if type is None: return self if self.key not in obj.environ: if self.default_factory: val = obj.environ[self.key] = self.default_factory() return val else: return self.default return obj.environ[self.key] def __repr__(self): return '' % self.key class WSGIRequest(object): """WSGI Request API Object This object represents a WSGI request with a more friendly interface. This does not expose every detail of the WSGI environment, and attempts to express nothing beyond what is available in the environment dictionary. The only state maintained in this object is the desired ``charset``, its associated ``errors`` handler, and the ``decode_param_names`` option. The incoming parameter values will be automatically coerced to unicode objects of the ``charset`` encoding when ``charset`` is set. The incoming parameter names are not decoded to unicode unless the ``decode_param_names`` option is enabled. When unicode is expected, ``charset`` will overridden by the the value of the ``Content-Type`` header's charset parameter if one was specified by the client. The class variable ``defaults`` specifies default values for ``charset``, ``errors``, and ``langauge``. These can be overridden for the current request via the registry. The ``language`` default value is considered the fallback during i18n translations to ensure in odd cases that mixed languages don't occur should the ``language`` file contain the string but not another language in the accepted languages list. The ``language`` value only applies when getting a list of accepted languages from the HTTP Accept header. This behavior is duplicated from Aquarium, and may seem strange but is very useful. Normally, everything in the code is in "en-us". However, the "en-us" translation catalog is usually empty. If the user requests ``["en-us", "zh-cn"]`` and a translation isn't found for a string in "en-us", you don't want gettext to fallback to "zh-cn". You want it to just use the string itself. Hence, if a string isn't found in the ``language`` catalog, the string in the source code will be used. *All* other state is kept in the environment dictionary; this is essential for interoperability. You are free to subclass this object. """ defaults = StackedObjectProxy(default=dict(charset=None, errors='replace', decode_param_names=False, language='en-us')) def __init__(self, environ): self.environ = environ # This isn't "state" really, since the object is derivative: self.headers = EnvironHeaders(environ) defaults = self.defaults._current_obj() self.charset = defaults.get('charset') if self.charset: # There's a charset: params will be coerced to unicode. In that # case, attempt to use the charset specified by the browser browser_charset = self.determine_browser_charset() if browser_charset: self.charset = browser_charset self.errors = defaults.get('errors', 'strict') self.decode_param_names = defaults.get('decode_param_names', False) self._languages = None body = environ_getter('wsgi.input') scheme = environ_getter('wsgi.url_scheme') method = environ_getter('REQUEST_METHOD') script_name = environ_getter('SCRIPT_NAME') path_info = environ_getter('PATH_INFO') def urlvars(self): """ Return any variables matched in the URL (e.g., ``wsgiorg.routing_args``). """ if 'paste.urlvars' in self.environ: return self.environ['paste.urlvars'] elif 'wsgiorg.routing_args' in self.environ: return self.environ['wsgiorg.routing_args'][1] else: return {} urlvars = property(urlvars, doc=urlvars.__doc__) def is_xhr(self): """Returns a boolean if X-Requested-With is present and a XMLHttpRequest""" return self.environ.get('HTTP_X_REQUESTED_WITH', '') == 'XMLHttpRequest' is_xhr = property(is_xhr, doc=is_xhr.__doc__) def host(self): """Host name provided in HTTP_HOST, with fall-back to SERVER_NAME""" return self.environ.get('HTTP_HOST', self.environ.get('SERVER_NAME')) host = property(host, doc=host.__doc__) def languages(self): """Return a list of preferred languages, most preferred first. The list may be empty. """ if self._languages is not None: return self._languages acceptLanguage = self.environ.get('HTTP_ACCEPT_LANGUAGE') langs = ACCEPT_LANGUAGE.parse(self.environ) fallback = self.defaults.get('language', 'en-us') if not fallback: return langs if fallback not in langs: langs.append(fallback) index = langs.index(fallback) langs[index+1:] = [] self._languages = langs return self._languages languages = property(languages, doc=languages.__doc__) def _GET(self): return parse_dict_querystring(self.environ) def GET(self): """ Dictionary-like object representing the QUERY_STRING parameters. Always present, if possibly empty. If the same key is present in the query string multiple times, a list of its values can be retrieved from the ``MultiDict`` via the ``getall`` method. Returns a ``MultiDict`` container or a ``UnicodeMultiDict`` when ``charset`` is set. """ params = self._GET() if self.charset: params = UnicodeMultiDict(params, encoding=self.charset, errors=self.errors, decode_keys=self.decode_param_names) return params GET = property(GET, doc=GET.__doc__) def _POST(self): return parse_formvars(self.environ, include_get_vars=False) def POST(self): """Dictionary-like object representing the POST body. Most values are encoded strings, or unicode strings when ``charset`` is set. There may also be FieldStorage objects representing file uploads. If this is not a POST request, or the body is not encoded fields (e.g., an XMLRPC request) then this will be empty. This will consume wsgi.input when first accessed if applicable, but the raw version will be put in environ['paste.parsed_formvars']. Returns a ``MultiDict`` container or a ``UnicodeMultiDict`` when ``charset`` is set. """ params = self._POST() if self.charset: params = UnicodeMultiDict(params, encoding=self.charset, errors=self.errors, decode_keys=self.decode_param_names) return params POST = property(POST, doc=POST.__doc__) def params(self): """Dictionary-like object of keys from POST, GET, URL dicts Return a key value from the parameters, they are checked in the following order: POST, GET, URL Additional methods supported: ``getlist(key)`` Returns a list of all the values by that key, collected from POST, GET, URL dicts Returns a ``MultiDict`` container or a ``UnicodeMultiDict`` when ``charset`` is set. """ params = MultiDict() params.update(self._POST()) params.update(self._GET()) if self.charset: params = UnicodeMultiDict(params, encoding=self.charset, errors=self.errors, decode_keys=self.decode_param_names) return params params = property(params, doc=params.__doc__) def cookies(self): """Dictionary of cookies keyed by cookie name. Just a plain dictionary, may be empty but not None. """ return get_cookie_dict(self.environ) cookies = property(cookies, doc=cookies.__doc__) def determine_browser_charset(self): """ Determine the encoding as specified by the browser via the Content-Type's charset parameter, if one is set """ charset_match = _CHARSET_RE.search(self.headers.get('Content-Type', '')) if charset_match: return charset_match.group(1) def match_accept(self, mimetypes): """Return a list of specified mime-types that the browser's HTTP Accept header allows in the order provided.""" return desired_matches(mimetypes, self.environ.get('HTTP_ACCEPT', '*/*')) def __repr__(self): """Show important attributes of the WSGIRequest""" pf = pformat msg = '<%s.%s object at 0x%x method=%s,' % \ (self.__class__.__module__, self.__class__.__name__, id(self), pf(self.method)) msg += '\nscheme=%s, host=%s, script_name=%s, path_info=%s,' % \ (pf(self.scheme), pf(self.host), pf(self.script_name), pf(self.path_info)) msg += '\nlanguges=%s,' % pf(self.languages) if self.charset: msg += ' charset=%s, errors=%s,' % (pf(self.charset), pf(self.errors)) msg += '\nGET=%s,' % pf(self.GET) msg += '\nPOST=%s,' % pf(self.POST) msg += '\ncookies=%s>' % pf(self.cookies) return msg class WSGIResponse(object): """A basic HTTP response with content, headers, and out-bound cookies The class variable ``defaults`` specifies default values for ``content_type``, ``charset`` and ``errors``. These can be overridden for the current request via the registry. """ defaults = StackedObjectProxy( default=dict(content_type='text/html', charset='utf-8', errors='strict', headers={'Cache-Control':'no-cache'}) ) def __init__(self, content='', mimetype=None, code=200): self._iter = None self._is_str_iter = True self.content = content self.headers = HeaderDict() self.cookies = SimpleCookie() self.status_code = code defaults = self.defaults._current_obj() if not mimetype: mimetype = defaults.get('content_type', 'text/html') charset = defaults.get('charset') if charset: mimetype = '%s; charset=%s' % (mimetype, charset) self.headers.update(defaults.get('headers', {})) self.headers['Content-Type'] = mimetype self.errors = defaults.get('errors', 'strict') def __str__(self): """Returns a rendition of the full HTTP message, including headers. When the content is an iterator, the actual content is replaced with the output of str(iterator) (to avoid exhausting the iterator). """ if self._is_str_iter: content = ''.join(self.get_content()) else: content = str(self.content) return '\n'.join(['%s: %s' % (key, value) for key, value in self.headers.headeritems()]) \ + '\n\n' + content def __call__(self, environ, start_response): """Convenience call to return output and set status information Conforms to the WSGI interface for calling purposes only. Example usage: .. code-block:: Python def wsgi_app(environ, start_response): response = WSGIResponse() response.write("Hello world") response.headers['Content-Type'] = 'latin1' return response(environ, start_response) """ status_text = STATUS_CODE_TEXT[self.status_code] status = '%s %s' % (self.status_code, status_text) response_headers = self.headers.headeritems() for c in self.cookies.values(): response_headers.append(('Set-Cookie', c.output(header=''))) start_response(status, response_headers) is_file = isinstance(self.content, file) if 'wsgi.file_wrapper' in environ and is_file: return environ['wsgi.file_wrapper'](self.content) elif is_file: return iter(lambda: self.content.read(), '') return self.get_content() def determine_charset(self): """ Determine the encoding as specified by the Content-Type's charset parameter, if one is set """ charset_match = _CHARSET_RE.search(self.headers.get('Content-Type', '')) if charset_match: return charset_match.group(1) def has_header(self, header): """ Case-insensitive check for a header """ warnings.warn('WSGIResponse.has_header is deprecated, use ' 'WSGIResponse.headers.has_key instead', DeprecationWarning, 2) return self.headers.has_key(header) def set_cookie(self, key, value='', max_age=None, expires=None, path='/', domain=None, secure=None): """ Define a cookie to be sent via the outgoing HTTP headers """ self.cookies[key] = value for var_name, var_value in [ ('max_age', max_age), ('path', path), ('domain', domain), ('secure', secure), ('expires', expires)]: if var_value is not None and var_value is not False: self.cookies[key][var_name.replace('_', '-')] = var_value def delete_cookie(self, key, path='/', domain=None): """ Notify the browser the specified cookie has expired and should be deleted (via the outgoing HTTP headers) """ self.cookies[key] = '' if path is not None: self.cookies[key]['path'] = path if domain is not None: self.cookies[key]['domain'] = path self.cookies[key]['expires'] = 0 self.cookies[key]['max-age'] = 0 def _set_content(self, content): if hasattr(content, '__iter__'): self._iter = content if isinstance(content, list): self._is_str_iter = True else: self._is_str_iter = False else: self._iter = [content] self._is_str_iter = True content = property(lambda self: self._iter, _set_content, doc='Get/set the specified content, where content can ' 'be: a string, a list of strings, a generator function ' 'that yields strings, or an iterable object that ' 'produces strings.') def get_content(self): """ Returns the content as an iterable of strings, encoding each element of the iterator from a Unicode object if necessary. """ charset = self.determine_charset() if charset: return encode_unicode_app_iter(self.content, charset, self.errors) else: return self.content def wsgi_response(self): """ Return this WSGIResponse as a tuple of WSGI formatted data, including: (status, headers, iterable) """ status_text = STATUS_CODE_TEXT[self.status_code] status = '%s %s' % (self.status_code, status_text) response_headers = self.headers.headeritems() for c in self.cookies.values(): response_headers.append(('Set-Cookie', c.output(header=''))) return status, response_headers, self.get_content() # The remaining methods partially implement the file-like object interface. # See http://docs.python.org/lib/bltin-file-objects.html def write(self, content): if not self._is_str_iter: raise IOError, "This %s instance's content is not writable: (content " \ 'is an iterator)' % self.__class__.__name__ self.content.append(content) def flush(self): pass def tell(self): if not self._is_str_iter: raise IOError, 'This %s instance cannot tell its position: (content ' \ 'is an iterator)' % self.__class__.__name__ return sum([len(chunk) for chunk in self._iter]) ######################################## ## Content-type and charset def charset__get(self): """ Get/set the charset (in the Content-Type) """ header = self.headers.get('content-type') if not header: return None match = _CHARSET_RE.search(header) if match: return match.group(1) return None def charset__set(self, charset): if charset is None: del self.charset return try: header = self.headers.pop('content-type') except KeyError: raise AttributeError( "You cannot set the charset when no content-type is defined") match = _CHARSET_RE.search(header) if match: header = header[:match.start()] + header[match.end():] header += '; charset=%s' % charset self.headers['content-type'] = header def charset__del(self): try: header = self.headers.pop('content-type') except KeyError: # Don't need to remove anything return match = _CHARSET_RE.search(header) if match: header = header[:match.start()] + header[match.end():] self.headers['content-type'] = header charset = property(charset__get, charset__set, charset__del, doc=charset__get.__doc__) def content_type__get(self): """ Get/set the Content-Type header (or None), *without* the charset or any parameters. If you include parameters (or ``;`` at all) when setting the content_type, any existing parameters will be deleted; otherwise they will be preserved. """ header = self.headers.get('content-type') if not header: return None return header.split(';', 1)[0] def content_type__set(self, value): if ';' not in value: header = self.headers.get('content-type', '') if ';' in header: params = header.split(';', 1)[1] value += ';' + params self.headers['content-type'] = value def content_type__del(self): try: del self.headers['content-type'] except KeyError: pass content_type = property(content_type__get, content_type__set, content_type__del, doc=content_type__get.__doc__) ## @@ I'd love to remove this, but paste.httpexceptions.get_exception ## doesn't seem to work... # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html STATUS_CODE_TEXT = { 100: 'CONTINUE', 101: 'SWITCHING PROTOCOLS', 200: 'OK', 201: 'CREATED', 202: 'ACCEPTED', 203: 'NON-AUTHORITATIVE INFORMATION', 204: 'NO CONTENT', 205: 'RESET CONTENT', 206: 'PARTIAL CONTENT', 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', } PK-68lpaste/__init__.pyo; #Gc@szydkZeieWn/ej o#dklZeeeZnXdkZxeD]Zei eeq\WdS(N(s extend_path( s pkg_resourcessdeclare_namespaces__name__s ImportErrorspkgutils extend_paths__path__s modulefinderspsAddPackagePath(s extend_paths modulefinders pkg_resourcessps__path__((s2build/bdist.darwin-8.0.1-x86/egg/paste/__init__.pys?s   PK;^W7FT S4S4paste/errordocument.py# (c) 2005-2006 James Gardner # This module is part of the Python Paste Project and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """ Middleware to display error documents for certain status codes The middleware in this module can be used to intercept responses with specified status codes and internally forward the request to an appropriate URL where the content can be displayed to the user as an error document. """ import warnings from urlparse import urlparse from paste.recursive import ForwardRequestException, RecursiveMiddleware from paste.util import converters from paste.response import replace_header def forward(app, codes): """ Intercepts a response with a particular status code and returns the content from a specified URL instead. The arguments are: ``app`` The WSGI application or middleware chain. ``codes`` A dictionary of integer status codes and the URL to be displayed if the response uses that code. For example, you might want to create a static file to display a "File Not Found" message at the URL ``/error404.html`` and then use ``forward`` middleware to catch all 404 status codes and display the page you created. In this example ``app`` is your exisiting WSGI applicaiton:: from paste.errordocument import forward app = forward(app, codes={404:'/error404.html'}) """ for code in codes: if not isinstance(code, int): raise TypeError('All status codes should be type int. ' '%s is not valid'%repr(code)) def error_codes_mapper(code, message, environ, global_conf, codes): if codes.has_key(code): return codes[code] else: return None #return _StatusBasedRedirect(app, error_codes_mapper, codes=codes) return RecursiveMiddleware( StatusBasedForward( app, error_codes_mapper, codes=codes, ) ) class StatusKeeper(object): def __init__(self, app, status, url, headers): self.app = app self.status = status self.url = url self.headers = headers def __call__(self, environ, start_response): def keep_status_start_response(status, headers, exc_info=None): for header, value in headers: if header.lower() == 'set-cookie': self.headers.append((header, value)) else: replace_header(self.headers, header, value) return start_response(self.status, self.headers, exc_info) parts = self.url.split('?') environ['PATH_INFO'] = parts[0] if len(parts) > 1: environ['QUERY_STRING'] = parts[1] else: environ['QUERY_STRING'] = '' #raise Exception(self.url, self.status) return self.app(environ, keep_status_start_response) class StatusBasedForward(object): """ Middleware that lets you test a response against a custom mapper object to programatically determine whether to internally forward to another URL and if so, which URL to forward to. If you don't need the full power of this middleware you might choose to use the simpler ``forward`` middleware instead. The arguments are: ``app`` The WSGI application or middleware chain. ``mapper`` A callable that takes a status code as the first parameter, a message as the second, and accepts optional environ, global_conf and named argments afterwards. It should return a URL to forward to or ``None`` if the code is not to be intercepted. ``global_conf`` Optional default configuration from your config file. If ``debug`` is set to ``true`` a message will be written to ``wsgi.errors`` on each internal forward stating the URL forwarded to. ``**params`` Optional, any other configuration and extra arguments you wish to pass which will in turn be passed back to the custom mapper object. Here is an example where a ``404 File Not Found`` status response would be redirected to the URL ``/error?code=404&message=File%20Not%20Found``. This could be useful for passing the status code and message into another application to display an error document: .. code-block:: Python from paste.errordocument import StatusBasedForward from paste.recursive import RecursiveMiddleware from urllib import urlencode def error_mapper(code, message, environ, global_conf, kw) if code in [404, 500]: params = urlencode({'message':message, 'code':code}) url = '/error?'%(params) return url else: return None app = RecursiveMiddleware( StatusBasedForward(app, mapper=error_mapper), ) """ def __init__(self, app, mapper, global_conf=None, **params): if global_conf is None: global_conf = {} # @@: global_conf shouldn't really come in here, only in a # separate make_status_based_forward function if global_conf: self.debug = converters.asbool(global_conf.get('debug', False)) else: self.debug = False self.application = app self.mapper = mapper self.global_conf = global_conf self.params = params def __call__(self, environ, start_response): url = [] def change_response(status, headers, exc_info=None): status_code = status.split(' ') try: code = int(status_code[0]) except (ValueError, TypeError): raise Exception( 'StatusBasedForward middleware ' 'received an invalid status code %s'%repr(status_code[0]) ) message = ' '.join(status_code[1:]) new_url = self.mapper( code, message, environ, self.global_conf, **self.params ) if not (new_url == None or isinstance(new_url, str)): raise TypeError( 'Expected the url to internally ' 'redirect to in the StatusBasedForward mapper' 'to be a string or None, not %s'%repr(new_url) ) if new_url: url.append([new_url, status, headers]) else: return start_response(status, headers, exc_info) app_iter = self.application(environ, change_response) if url: if hasattr(app_iter, 'close'): app_iter.close() def factory(app): return StatusKeeper(app, status=url[0][1], url=url[0][0], headers=url[0][2]) raise ForwardRequestException(factory=factory) else: return app_iter def make_errordocument(app, global_conf, **kw): """ Paste Deploy entry point to create a error document wrapper. Use like:: [filter-app:main] use = egg:Paste#errordocument next = real-app 500 = /lib/msg/500.html 404 = /lib/msg/404.html """ map = {} for status, redir_loc in kw.items(): try: status = int(status) except ValueError: raise ValueError('Bad status code: %r' % status) map[status] = redir_loc forwarder = forward(app, map) return forwarder __pudge_all__ = [ 'forward', 'make_errordocument', 'empty_error', 'make_empty_error', 'StatusBasedForward', ] ############################################################################### ## Deprecated ############################################################################### def custom_forward(app, mapper, global_conf=None, **kw): """ Deprectated; use StatusBasedForward instead. """ warnings.warn( "errordocuments.custom_forward has been deprecated; please " "use errordocuments.StatusBasedForward", DeprecationWarning, 2) if global_conf is None: global_conf = {} return _StatusBasedRedirect(app, mapper, global_conf, **kw) class _StatusBasedRedirect(object): """ Deprectated; use StatusBasedForward instead. """ def __init__(self, app, mapper, global_conf=None, **kw): warnings.warn( "errordocuments._StatusBasedRedirect has been deprecated; please " "use errordocuments.StatusBasedForward", DeprecationWarning, 2) if global_conf is None: global_conf = {} self.application = app self.mapper = mapper self.global_conf = global_conf self.kw = kw self.fallback_template = """ Error %(code)s

Error %(code)s

%(message)s


Additionally an error occurred trying to produce an error document. A description of the error was logged to wsgi.errors.

""" def __call__(self, environ, start_response): url = [] code_message = [] try: def change_response(status, headers, exc_info=None): new_url = None parts = status.split(' ') try: code = int(parts[0]) except ValueError, TypeError: raise Exception( '_StatusBasedRedirect middleware ' 'received an invalid status code %s'%repr(parts[0]) ) message = ' '.join(parts[1:]) new_url = self.mapper( code, message, environ, self.global_conf, self.kw ) if not (new_url == None or isinstance(new_url, str)): raise TypeError( 'Expected the url to internally ' 'redirect to in the _StatusBasedRedirect error_mapper' 'to be a string or None, not %s'%repr(new_url) ) if new_url: url.append(new_url) code_message.append([code, message]) return start_response(status, headers, exc_info) app_iter = self.application(environ, change_response) except: try: import sys error = str(sys.exc_info()[1]) except: error = '' try: code, message = code_message[0] except: code, message = ['', ''] environ['wsgi.errors'].write( 'Error occurred in _StatusBasedRedirect ' 'intercepting the response: '+str(error) ) return [self.fallback_template % {'message': message, 'code': code}] else: if url: url_ = url[0] new_environ = {} for k, v in environ.items(): if k != 'QUERY_STRING': new_environ['QUERY_STRING'] = urlparse(url_)[4] else: new_environ[k] = v class InvalidForward(Exception): pass def eat_start_response(status, headers, exc_info=None): """ We don't want start_response to do anything since it has already been called """ if status[:3] != '200': raise InvalidForward( "The URL %s to internally forward " "to in order to create an error document did not " "return a '200' status code." % url_ ) forward = environ['paste.recursive.forward'] old_start_response = forward.start_response forward.start_response = eat_start_response try: app_iter = forward(url_, new_environ) except InvalidForward, e: code, message = code_message[0] environ['wsgi.errors'].write( 'Error occurred in ' '_StatusBasedRedirect redirecting ' 'to new URL: '+str(url[0]) ) return [ self.fallback_template%{ 'message':message, 'code':code, } ] else: forward.start_response = old_start_response return app_iter else: return app_iter PK-68)ySRSRpaste/recursive.pyc; #Gc@s dZdklZdkZdgZddgZdefdYZdefdYZde fdYZ d efd YZ d e fd YZ d e fdYZ defdYZde fdYZdefdYZdZee_dS(s Middleware to make internal requests and forward requests internally. When applied, several keys are added to the environment that will allow you to trigger recursive redirects and forwards. paste.recursive.include: When you call ``environ['paste.recursive.include'](new_path_info)`` a response will be returned. The response has a ``body`` attribute, a ``status`` attribute, and a ``headers`` attribute. paste.recursive.script_name: The ``SCRIPT_NAME`` at the point that recursive lives. Only paths underneath this path can be redirected to. paste.recursive.old_path_info: A list of previous ``PATH_INFO`` values from previous redirects. Raise ``ForwardRequestException(new_path_info)`` to do a forward (aborting the current request). (sStringIONsRecursiveMiddlewaresForwardRequestExceptionsCheckForRecursionMiddlewarecBstZdZdZRS(NcCs||_||_dS(N(sappsselfsenv(sselfsappsenv((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pys__init__!s cCs|idd}||iidgjo!td||idfn|iidg}|i|iidd|i ||SdS(Ns PATH_INFOsspaste.recursive.old_path_infosGForwarding loop detected; %r visited twice (internal redirect path: %s)( senvironsgets path_infosselfsenvsAssertionErrors setdefaults old_path_infosappendsappsstart_response(sselfsenvironsstart_responses old_path_infos path_info((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pys__call__%s !(s__name__s __module__s__init__s__call__(((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pysCheckForRecursionMiddleware s cBs#tZdZedZdZRS(s} A WSGI middleware that allows for recursive and forwarded calls. All these calls go to the same 'application', but presumably that application acts differently with different URLs. The forwarded URLs must be relative to this container. Interface is entirely through the ``paste.recursive.forward`` and ``paste.recursive.include`` environmental keys. cCs ||_dS(N(s applicationsself(sselfs applications global_conf((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pys__init__=scCst|i|||ds SCRIPT_NAMEs/(sselfs __class__s __module__s__name__soriginal_environsget(sself((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pys__repr__s(s__name__s __module__s__init__sNones__call__sactivates__repr__(((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pys Recursives   s ForwardercBstZdZdZRS(s  The forwarder will try to restart the request, except with the new `path` (replacing ``PATH_INFO`` in the request). It must not be called after and headers have been returned. It returns an iterator that must be returned back up the call stack, so it must be used like: .. code-block:: Python return environ['paste.recursive.forward'](path) Meaningful transformations cannot be done, since headers are sent directly to the server and cannot be inspected or rewritten. cCs*tidtd|i||iSdS(NsKrecursive.Forwarder has been deprecated; please use ForwardRequestExceptioni(swarningsswarnsDeprecationWarningsselfs applicationsenvironsstart_response(sselfsenviron((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pysactivate*s  (s__name__s __module__s__doc__sactivate(((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pys Forwarders sIncludercBstZdZdZRS(s Starts another request with the given path and adding or overwriting any values in the `extra_environ` dictionary. Returns an IncludeResponse object. csttd}|i||}z"x|D]}i |q4WWdt |do|i nXi SdS(Ncs@|o|d|d|dn|_|_iSdS(Niii(sexc_infosstatussresponsesheadersswrite(sstatussheaderssexc_info(sresponse(s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pysstart_response<s   sclose( sIncludedResponsesresponsesNonesstart_responsesselfs applicationsenvironsapp_iterssswriteshasattrsclose(sselfsenvironsapp_itersstart_responsesssresponse((sresponses3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pysactivate:s  (s__name__s __module__s__doc__sactivate(((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pysIncluder2s sIncludedResponsecBsAtZdZdZdZdZdZeeZRS(NcCs+t|_t|_t|_t|_dS(N(sNonesselfsheaderssstatussStringIOsoutputsstr(sself((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pys__init__Ns   cCs,|ii|_|iit|_dS(N(sselfsoutputsgetvaluesstrsclosesNone(sself((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pyscloseTs cCs.|itj p td|ii|dS(NsIThis response has already been closed and no further data can be written.(sselfsoutputsNonesAssertionErrorswritess(sselfss((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pyswriteYscCs |iSdS(N(sselfsbody(sself((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pys__str___scCs,|itjo|iiSn|iSdS(N(sselfsstrsNonesoutputsgetvalue(sself((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pys body__getbs( s__name__s __module__s__init__scloseswrites__str__s body__getspropertysbody(((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pysIncludedResponseLs      sIncluderAppItercBstZdZdZRS(sk Like Includer, but just stores the app_iter response (be sure to call close on the response!) cs;ttd}|i||}|_SdS(Ncs@|o|d|d|dn|_|_iSdS(Niii(sexc_infosstatussresponsesheadersswrite(sstatussheaderssexc_info(sresponse(s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pysstart_responsers   (sIncludedAppIterResponsesresponsesNonesstart_responsesselfs applicationsenvironsapp_iter(sselfsenvironsapp_itersstart_responsesresponse((sresponses3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pysactivateps   (s__name__s __module__s__doc__sactivate(((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pysIncluderAppIterjs sIncludedAppIterResponsecBs#tZdZdZdZRS(NcCs1t|_t|_g|_t|_t|_dS(N(sNonesselfsstatussheaderss accumulatedsapp_itersFalses_closed(sself((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pys__init__~s     cCs=|i p tdt|ido|iindS(NsTried to close twicesclose(sselfs_closedsAssertionErrorshasattrsapp_itersclose(sself((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pysclosescCs|iidS(N(sselfs accumulatedsappend(sselfss((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pyswrites(s__name__s __module__s__init__scloseswrite(((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pysIncludedAppIterResponse|s  cCst|SdS(N(sRecursiveMiddlewaresapp(sapps global_conf((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pysmake_recursive_middlewares(s__doc__s cStringIOsStringIOswarningss__all__s __pudge_all__sobjectsCheckForRecursionMiddlewaresRecursiveMiddlewares ExceptionsForwardRequestExceptions Recursives ForwardersIncludersIncludedResponsesIncluderAppItersIncludedAppIterResponsesmake_recursive_middleware(s RecursivesForwardRequestExceptions__all__swarningssCheckForRecursionMiddlewaresIncludersRecursiveMiddlewares ForwardersIncludedResponsesIncludedAppIterResponses __pudge_all__smake_recursive_middlewaresIncluderAppItersStringIO((s3build/bdist.darwin-8.0.1-x86/egg/paste/recursive.pys?s    %* PK-68i_  paste/cgitb_catcher.pyc; #Gc@swdZdkZdklZdkZdklZdefdYZdefdYZ ee dd d Z dS( s WSGI middleware Captures any exceptions and prints a pretty report. See the `cgitb documentation `_ for more. N(sStringIO(s converterss NoDefaultcBstZRS(N(s__name__s __module__(((s7build/bdist.darwin-8.0.1-x86/egg/paste/cgitb_catcher.pys NoDefaultssCgitbMiddlewarecBs;tZeeedddZdZdZdZRS(NishtmlcCs||_|tjo h}n|tjo|id}nt|tot i |}n||_||_ t ||_ ||_dS(Nsdebug(sappsselfs global_confsNonesdisplays NoDefaultsgets isinstances basestrings converterssasboolslogdirsintscontextsformat(sselfsapps global_confsdisplayslogdirscontextsformat((s7build/bdist.darwin-8.0.1-x86/egg/paste/cgitb_catcher.pys__init__s      cCsry&|i||}|i||SWnEti}|dddfg||i||}|gSnXdS(Ns500 Internal Server Errors content-types text/html( sselfsappsenvironsstart_responsesapp_iters catching_iterssyssexc_infosexception_handlersresponse(sselfsenvironsstart_responsesapp_itersexc_infosresponse((s7build/bdist.darwin-8.0.1-x86/egg/paste/cgitb_catcher.pys__call__)s  ccs| o tnt}y=x|D] }|Vq"Wt|dot}|inWn}|i t i |}| o t|doBy|iWq|i t i |}|d|7}qXn|VnXdS(Nscloses$
Error in .close():
%s(sapp_iters StopIterationsFalseserror_on_closesvshasattrsTruesclosesselfsexception_handlerssyssexc_infosenvironsresponsesclose_response(sselfsapp_itersenvironsclose_responseserror_on_closesvsresponse((s7build/bdist.darwin-8.0.1-x86/egg/paste/cgitb_catcher.pys catching_iter5s& c CsWt}tid|d|id|id|id|i}|||i SdS(Nsfilesdisplayslogdirscontextsformat( sStringIOs dummy_filescgitbsHooksselfsdisplayslogdirscontextsformatshooksexc_infosgetvalue(sselfsexc_infosenvironshooks dummy_file((s7build/bdist.darwin-8.0.1-x86/egg/paste/cgitb_catcher.pysexception_handlerLs      (s__name__s __module__sNones NoDefaults__init__s__call__s catching_itersexception_handler(((s7build/bdist.darwin-8.0.1-x86/egg/paste/cgitb_catcher.pysCgitbMiddlewares ishtmlc Cs{dkl}|tj o||}nd|jo||d|d`_ for more. N(sStringIO(s converterss NoDefaultcBstZRS(N(s__name__s __module__(((s7build/bdist.darwin-8.0.1-x86/egg/paste/cgitb_catcher.pys NoDefaultssCgitbMiddlewarecBs;tZeeedddZdZdZdZRS(NishtmlcCs||_|tjo h}n|tjo|id}nt|tot i |}n||_||_ t ||_ ||_dS(Nsdebug(sappsselfs global_confsNonesdisplays NoDefaultsgets isinstances basestrings converterssasboolslogdirsintscontextsformat(sselfsapps global_confsdisplayslogdirscontextsformat((s7build/bdist.darwin-8.0.1-x86/egg/paste/cgitb_catcher.pys__init__s      cCsry&|i||}|i||SWnEti}|dddfg||i||}|gSnXdS(Ns500 Internal Server Errors content-types text/html( sselfsappsenvironsstart_responsesapp_iters catching_iterssyssexc_infosexception_handlersresponse(sselfsenvironsstart_responsesapp_itersexc_infosresponse((s7build/bdist.darwin-8.0.1-x86/egg/paste/cgitb_catcher.pys__call__)s  ccs| o tnt}y=x|D] }|Vq"Wt|dot}|inWn}|i t i |}| o t|doBy|iWq|i t i |}|d|7}qXn|VnXdS(Nscloses$
Error in .close():
%s(sapp_iters StopIterationsFalseserror_on_closesvshasattrsTruesclosesselfsexception_handlerssyssexc_infosenvironsresponsesclose_response(sselfsapp_itersenvironsclose_responseserror_on_closesvsresponse((s7build/bdist.darwin-8.0.1-x86/egg/paste/cgitb_catcher.pys catching_iter5s& c CsWt}tid|d|id|id|id|i}|||i SdS(Nsfilesdisplayslogdirscontextsformat( sStringIOs dummy_filescgitbsHooksselfsdisplayslogdirscontextsformatshooksexc_infosgetvalue(sselfsexc_infosenvironshooks dummy_file((s7build/bdist.darwin-8.0.1-x86/egg/paste/cgitb_catcher.pysexception_handlerLs      (s__name__s __module__sNones NoDefaults__init__s__call__s catching_itersexception_handler(((s7build/bdist.darwin-8.0.1-x86/egg/paste/cgitb_catcher.pysCgitbMiddlewares ishtmlc Cs{dkl}|tj o||}nd|jo||d|d %(error_code)s

%(error_code)s

%(message)s ''' % { 'error_code': error_code, 'message': message, } def error_response(environ, error_code, message, debug_message=None, __warn=True): """ Returns the status, headers, and body of an error response. Use like: .. code-block:: Python status, headers, body = wsgilib.error_response( '301 Moved Permanently', 'Moved to %s' % (url, url)) start_response(status, headers) return [body] **Note:** Deprecated """ if __warn: warnings.warn( 'wsgilib.error_response is deprecated; use the ' 'wsgi_application method on an HTTPException object ' 'instead', DeprecationWarning, 2) if debug_message and environ.get('paste.config', {}).get('debug'): message += '\n\n' % debug_message body = error_body_response(error_code, message, __warn=False) headers = [('content-type', 'text/html'), ('content-length', str(len(body)))] return error_code, headers, body def error_response_app(error_code, message, debug_message=None, __warn=True): """ An application that emits the given error response. **Note:** Deprecated """ if __warn: warnings.warn( 'wsgilib.error_response_app is deprecated; use the ' 'wsgi_application method on an HTTPException object ' 'instead', DeprecationWarning, 2) def application(environ, start_response): status, headers, body = error_response( environ, error_code, message, debug_message=debug_message, __warn=False) start_response(status, headers) return [body] return application PK;^W7"H.paste/progress.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php # (c) 2005 Clark C. Evans # This module is part of the Python Paste Project and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php # This code was written with funding by http://prometheusresearch.com """ Upload Progress Monitor This is a WSGI middleware component which monitors the status of files being uploaded. It includes a small query application which will return a list of all files being uploaded by particular session/user. >>> from paste.httpserver import serve >>> from paste.urlmap import URLMap >>> from paste.auth.basic import AuthBasicHandler >>> from paste.debug.debugapp import SlowConsumer, SimpleApplication >>> # from paste.progress import * >>> realm = 'Test Realm' >>> def authfunc(username, password): ... return username == password >>> map = URLMap({}) >>> ups = UploadProgressMonitor(map, threshold=1024) >>> map['/upload'] = SlowConsumer() >>> map['/simple'] = SimpleApplication() >>> map['/report'] = UploadProgressReporter(ups) >>> serve(AuthBasicHandler(ups, realm, authfunc)) serving on... .. note:: This is experimental, and will change in the future. """ import time from paste.wsgilib import catch_errors DEFAULT_THRESHOLD = 1024 * 1024 # one megabyte DEFAULT_TIMEOUT = 60*5 # five minutes ENVIRON_RECEIVED = 'paste.bytes_received' REQUEST_STARTED = 'paste.request_started' REQUEST_FINISHED = 'paste.request_finished' class _ProgressFile(object): """ This is the input-file wrapper used to record the number of ``paste.bytes_received`` for the given request. """ def __init__(self, environ, rfile): self._ProgressFile_environ = environ self._ProgressFile_rfile = rfile self.flush = rfile.flush self.write = rfile.write self.writelines = rfile.writelines def __iter__(self): environ = self._ProgressFile_environ riter = iter(self._ProgressFile_rfile) def iterwrap(): for chunk in riter: environ[ENVIRON_RECEIVED] += len(chunk) yield chunk return iter(iterwrap) def read(self, size=-1): chunk = self._ProgressFile_rfile.read(size) self._ProgressFile_environ[ENVIRON_RECEIVED] += len(chunk) return chunk def readline(self): chunk = self._ProgressFile_rfile.readline() self._ProgressFile_environ[ENVIRON_RECEIVED] += len(chunk) return chunk def readlines(self, hint=None): chunk = self._ProgressFile_rfile.readlines(hint) self._ProgressFile_environ[ENVIRON_RECEIVED] += len(chunk) return chunk class UploadProgressMonitor(object): """ monitors and reports on the status of uploads in progress Parameters: ``application`` This is the next application in the WSGI stack. ``threshold`` This is the size in bytes that is needed for the upload to be included in the monitor. ``timeout`` This is the amount of time (in seconds) that a upload remains in the monitor after it has finished. Methods: ``uploads()`` This returns a list of ``environ`` dict objects for each upload being currently monitored, or finished but whose time has not yet expired. For each request ``environ`` that is monitored, there are several variables that are stored: ``paste.bytes_received`` This is the total number of bytes received for the given request; it can be compared with ``CONTENT_LENGTH`` to build a percentage complete. This is an integer value. ``paste.request_started`` This is the time (in seconds) when the request was started as obtained from ``time.time()``. One would want to format this for presentation to the user, if necessary. ``paste.request_finished`` This is the time (in seconds) when the request was finished, canceled, or otherwise disconnected. This is None while the given upload is still in-progress. TODO: turn monitor into a queue and purge queue of finished requests that have passed the timeout period. """ def __init__(self, application, threshold=None, timeout=None): self.application = application self.threshold = threshold or DEFAULT_THRESHOLD self.timeout = timeout or DEFAULT_TIMEOUT self.monitor = [] def __call__(self, environ, start_response): length = environ.get('CONTENT_LENGTH', 0) if length and int(length) > self.threshold: # replace input file object self.monitor.append(environ) environ[ENVIRON_RECEIVED] = 0 environ[REQUEST_STARTED] = time.time() environ[REQUEST_FINISHED] = None environ['wsgi.input'] = \ _ProgressFile(environ, environ['wsgi.input']) def finalizer(exc_info=None): environ[REQUEST_FINISHED] = time.time() return catch_errors(self.application, environ, start_response, finalizer, finalizer) return self.application(environ, start_response) def uploads(self): return self.monitor class UploadProgressReporter(object): """ reports on the progress of uploads for a given user This reporter returns a JSON file (for use in AJAX) listing the uploads in progress for the given user. By default, this reporter uses the ``REMOTE_USER`` environment to compare between the current request and uploads in-progress. If they match, then a response record is formed. ``match()`` This member function can be overriden to provide alternative matching criteria. It takes two environments, the first is the current request, the second is a current upload. ``report()`` This member function takes an environment and builds a ``dict`` that will be used to create a JSON mapping for the given upload. By default, this just includes the percent complete and the request url. """ def __init__(self, monitor): self.monitor = monitor def match(self, search_environ, upload_environ): if search_environ.get('REMOTE_USER', None) == \ upload_environ.get('REMOTE_USER', 0): return True return False def report(self, environ): retval = { 'started': time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(environ[REQUEST_STARTED])), 'finished': '', 'content_length': environ.get('CONTENT_LENGTH'), 'bytes_received': environ[ENVIRON_RECEIVED], 'path_info': environ.get('PATH_INFO',''), 'query_string': environ.get('QUERY_STRING','')} finished = environ[REQUEST_FINISHED] if finished: retval['finished'] = time.strftime("%Y:%m:%d %H:%M:%S", time.gmtime(finished)) return retval def __call__(self, environ, start_response): body = [] for map in [self.report(env) for env in self.monitor.uploads() if self.match(environ, env)]: parts = [] for k, v in map.items(): v = str(v).replace("\\", "\\\\").replace('"', '\\"') parts.append('%s: "%s"' % (k, v)) body.append("{ %s }" % ", ".join(parts)) body = "[ %s ]" % ", ".join(body) start_response("200 OK", [('Content-Type', 'text/plain'), ('Content-Length', len(body))]) return [body] __all__ = ['UploadProgressMonitor', 'UploadProgressReporter'] if "__main__" == __name__: import doctest doctest.testmod(optionflags=doctest.ELLIPSIS) PK;^W7o  paste/transaction.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php # (c) 2005 Clark C. Evans # This module is part of the Python Paste Project and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """ Middleware related to transactions and database connections. At this time it is very basic; but will eventually sprout all that two-phase commit goodness that I don't need. .. note:: This is experimental, and will change in the future. """ from paste.httpexceptions import HTTPException from wsgilib import catch_errors class TransactionManagerMiddleware(object): def __init__(self, application): self.application = application def __call__(self, environ, start_response): environ['paste.transaction_manager'] = manager = Manager() # This makes sure nothing else traps unexpected exceptions: environ['paste.throw_errors'] = True return catch_errors(self.application, environ, start_response, error_callback=manager.error, ok_callback=manager.finish) class Manager(object): def __init__(self): self.aborted = False self.transactions = [] def abort(self): self.aborted = True def error(self, exc_info): self.aborted = True self.finish() def finish(self): for trans in self.transactions: if self.aborted: trans.rollback() else: trans.commit() class ConnectionFactory(object): """ Provides a callable interface for connecting to ADBAPI databases in a WSGI style (using the environment). More advanced connection factories might use the REMOTE_USER and/or other environment variables to make the connection returned depend upon the request. """ def __init__(self, module, *args, **kwargs): #assert getattr(module,'threadsaftey',0) > 0 self.module = module self.args = args self.kwargs = kwargs # deal with database string quoting issues self.quote = lambda s: "'%s'" % s.replace("'","''") if hasattr(self.module,'PgQuoteString'): self.quote = self.module.PgQuoteString def __call__(self, environ=None): conn = self.module.connect(*self.args, **self.kwargs) conn.__dict__['module'] = self.module conn.__dict__['quote'] = self.quote return conn def BasicTransactionHandler(application, factory): """ Provides a simple mechanism for starting a transaction based on the factory; and for either committing or rolling back the transaction depending on the result. It checks for the response's current status code either through the latest call to start_response; or through a HTTPException's code. If it is a 100, 200, or 300; the transaction is committed; otherwise it is rolled back. """ def basic_transaction(environ, start_response): conn = factory(environ) environ['paste.connection'] = conn should_commit = [500] def finalizer(exc_info=None): if exc_info: if isinstance(exc_info[1], HTTPException): should_commit.append(exc_info[1].code) if should_commit.pop() < 400: conn.commit() else: try: conn.rollback() except: # TODO: check if rollback has already happened return conn.close() def basictrans_start_response(status, headers, exc_info = None): should_commit.append(int(status.split(" ")[0])) return start_response(status, headers, exc_info) return catch_errors(application, environ, basictrans_start_response, finalizer, finalizer) return basic_transaction __all__ = ['ConnectionFactory', 'BasicTransactionHandler'] if '__main__' == __name__ and False: from pyPgSQL import PgSQL factory = ConnectionFactory(PgSQL, database="testing") conn = factory() curr = conn.cursor() curr.execute("SELECT now(), %s" % conn.quote("B'n\\'gles")) (time, bing) = curr.fetchone() print bing, time PK-68.vnnpaste/urlparser.pyc; #Gc@sdZdkZdkZdkZdkZy dkZWnej o eZnXdkl Z dkl Z dk l Z dkl Z dklZdk lZdefd YZd d d gZd efd YZdZeidedZeidedZdZdZeided efdYZedZd efdYZddZeeedZdS(sH WSGI applications that parse the URL and dispatch to on-disk resources N(srequest(sfileapp(s import_string(shttpexceptions(sETAG(s converterss NoDefaultcBstZRS(N(s__name__s __module__(((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys NoDefaultss URLParsersStaticURLParsersPkgResourcesParsercBstZdZhZeZhZeeeedZdZ dZ edZ dZ dZ dZdZeeZd Zd Zd ZRS( s WSGI middleware Application dispatching, based on URL. An instance of `URLParser` is an application that loads and delegates to other applications. It looks for files in its directory that match the first part of PATH_INFO; these may have an extension, but are not required to have one, in which case the available files are searched to find the appropriate file. If it is ambiguous, a 404 is returned and an error logged. By default there is a constructor for .py files that loads the module, and looks for an attribute ``application``, which is a ready application object, or an attribute that matches the module name, which is a factory for building applications, and is called with no arguments. URLParser will also look in __init__.py for special overrides. These overrides are: ``urlparser_hook(environ)`` This can modify the environment. Its return value is ignored, and it cannot be used to change the response in any way. You *can* use this, for example, to manipulate SCRIPT_NAME/PATH_INFO (try to keep them consistent with the original URL -- but consuming PATH_INFO and moving that to SCRIPT_NAME is ok). ``urlparser_wrap(environ, start_response, app)``: After URLParser finds the application, it calls this function (if present). If this function doesn't call ``app(environ, start_response)`` then the application won't be called at all! This can be used to allocate resources (with ``try:finally:``) or otherwise filter the output of the application. ``not_found_hook(environ, start_response)``: If no file can be found (*in this directory*) to match the request, then this WSGI application will be called. You can use this to change the URL and pass the request back to URLParser again, or on to some other application. This doesn't catch all ``404 Not Found`` responses, just missing files. ``application(environ, start_response)``: This basically overrides URLParser completely, and the given application is used for all requests. ``urlparser_wrap`` and ``urlparser_hook`` are still called, but the filesystem isn't searched in any way. c Ks|odk} | idtnh}tiidjo|itiid}n||_||_ |t jo"|i dddddf}nti||_ |t jo"|i d d d d d f}nti||_|t jo|i df}nti||_|ii|_|o|ii|nx|iD]\} } | id otd| | fn| tdi} t| t t!fot"i#| } n| |i| (sselfs __class__s__name__s directorysbase_python_nameshexsabssid(sself((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys__repr__Ps(s__name__s __module__s__doc__sparsers_by_directorys NoDefaults init_modulesglobal_constructorssNones__init__s__call__sfind_applications not_founds add_slashs find_filesget_applicationsregister_constructors classmethods get_parsersfind_init_modules__repr__(((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys URLParsers 26 0   #     cCsU|d}|o|dtii|7}ntii|}|i||SdS(Ns paste.urlparser.base_python_names.(senvironsbase_python_namesosspathsbasenamesfilenamesparsers get_parser(sparsersenvironsfilenamesbase_python_name((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pysmake_directoryWs  sdircCsti|SdS(N(sfileappsFileAppsfilename(sparsersenvironsfilename((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys make_unknownass*cCs`|d}tiitii|d}|o|d|}nt||||dSdS(Ns paste.urlparser.base_python_nameis.s wsgi.errors( senvironsbase_python_namesosspathssplitextsbasenamesfilenames module_namesload_module_from_name(senvironsfilenamesbase_python_names module_name((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys load_modulefs  " cCstii|oti|Sntiitii|d} tii |  osyt | d} WnBt tfj o0} |idtii|| ftSnX| id| int}tii|oti|Snd|joTdi|idd }|idd} t|tii|||}n|} t}zFti| tii|g\}}} ti|||| }Wd|tj o|inX|SdS(Ns __init__.pysws5Cannot write __init__.py file into directory %s (%s) s# s.i(!ssyssmodulesshas_keys module_namesosspathsjoinsdirnamesfilenames init_filenamesexistssopensfsOSErrorsIOErrorseserrorsswritesNonesclosesfpssplits parent_names base_namesload_module_from_namesenvironsparentsimps find_modulespathnamesstuffs load_modulesmodule(senvironsfilenames module_nameserrorssmodules parent_namespathnamesfpsparents init_filenameses base_namesfsstuff((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pysload_module_from_namens8!#   * cCst||}| otSnt|do|iot|id|iSn|ii dd}t||o>t||}t|do |i Sqt||Sn|di d||ftSdS(Ns applicationswsgi_applications.is wsgi.errorss'Cound not find application or %s in %s (s load_modulesenvironsfilenamesmodulesNoneshasattrs applicationsgetattrs__name__ssplits base_namesobjswsgi_applicationswrite(sparsersenvironsfilenamesobjs base_namesmodule((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pysmake_pys s.pycBsVtZdZeedZdZdZdZedZdZ dZ RS(s Like ``URLParser`` but only serves static files. ``cache_max_age``: integer specifies Cache-Control max_age in seconds cCstiidjo|itiid}n||_||_|tj otii|i|_n ||_||_ tiidjo:|idtii}|iidtii|_ndS(Ns/( sosspathsseps directorysreplacesselfsroot_directorysNonesnormpaths cache_max_age(sselfs directorysroot_directorys cache_max_age((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys__init__s     c CsN|idd} | o|i||Sn| djo d}nti|}t i i t i i |i |}t i idjo|idt i i}n|itj o|i|i o|i||Snt i i| o|i||Snt i i|oL|itj o|ip|i }|i|d|d|i||Sn|ido|iddjo|i||Sn|id}|oWt i|i} t| |jo.g}t!i"|| |d|dgSq n|i#|}|io|i%d |in|||SdS( Ns PATH_INFOss/s index.htmlsroot_directorys cache_max_agesHTTP_IF_NONE_MATCHs304 Not Modifiedsmax_age(&senvironsgets path_infosselfs add_slashsstart_responsesfilenamesrequests path_info_popsosspathsnormpathsjoins directorysfullssepsreplacesroot_directorysNones startswiths not_foundsexistssisdirs child_roots __class__s cache_max_ageserror_extra_paths if_none_matchsstatsst_mtimesmytimesstrsheaderssETAGsupdatesmake_appsfas cache_control( sselfsenvironsstart_responsesfulls if_none_matchs child_rootsfilenamesheaderssfas path_infosmytime((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys__call__s@  $$# &  cCsti|SdS(N(sfileappsFileAppsfilename(sselfsfilename((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pysmake_appscCs{ti|dt}|d7}|ido|d|d7}ntid|dd|fg}|i ||SdS( s^ This happens when you try to get to a directory without a trailing / swith_query_strings/s QUERY_STRINGs?sFThe resource has moved to %s - you should be redirected automatically.sheadersslocationN( srequests construct_urlsenvironsFalsesurlsgetshttpexceptionssHTTPMovedPermanentlysexcswsgi_applicationsstart_response(sselfsenvironsstart_responsesexcsurl((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys add_slashs  cCsbtidti|dd|id|id|i|pdf}|i ||SdS(Ns%The resource at %s could not be foundscomments6SCRIPT_NAME=%r; PATH_INFO=%r; looking in %r; debug: %ss SCRIPT_NAMEs PATH_INFOs(none)( shttpexceptionss HTTPNotFoundsrequests construct_urlsenvironsgetsselfs directorys debug_messagesexcswsgi_applicationsstart_response(sselfsenvironsstart_responses debug_messagesexc((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys not_founds8cCs+tid|d}|i||SdS(Ns#The trailing path %r is not alloweds PATH_INFO(shttpexceptionss HTTPNotFoundsenvironsexcswsgi_applicationsstart_response(sselfsenvironsstart_responsesexc((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pyserror_extra_pathscCsd|ii|ifSdS(Ns<%s %r>(sselfs __class__s__name__s directory(sself((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys__repr__s( s__name__s __module__s__doc__sNones__init__s__call__smake_apps add_slashs not_foundserror_extra_paths__repr__(((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pysStaticURLParsers  (   cCs1|tj ot|}nt|d|SdS(s Return a WSGI application that serves a directory (configured with document_root) cache_max_age - integer specifies CACHE_CONTROL max_age in seconds s cache_max_ageN(s cache_max_agesNonesintsStaticURLParsers document_root(s global_confs document_roots cache_max_age((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys make_static s cBs5tZeedZdZdZedZRS(NcCsttjotdnt|ttfoti||_ n ||_ ||_ |tjoti }n||_ |tjo |}ntii||_ dS(Ns"This class requires pkg_resources.(s pkg_resourcessNonesNotImplementedErrors isinstances egg_or_specsstrsunicodesget_distributionsselfseggs resource_namesmanagersResourceManagers root_resourcesosspathsnormpath(sselfs egg_or_specs resource_namesmanagers root_resource((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys__init__s       cCs$d|ii|ii|ifSdS(Ns<%s for %s:%r>(sselfs __class__s__name__seggs project_names resource_name(sself((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys__repr__&sc Cs|idd} | o|i||Sn| djo d}nti|}t i i |i d|}|itj o|i|i o|i||Sn|ii| o|i||Sn|ii|oO|itj o|ip|i }|i|i||id|||Sn|ido|iddjo|i||Snti|\}}| o d}ny|ii|i|} Wn>tt fj o,} t"i#d| }|i%||SnX|dd |fgt&i'| SdS( Ns PATH_INFOss/s index.htmls root_resourcesapplication/octet-streams,You are not permitted to view this file (%s)s200 OKs content-type((senvironsgets path_infosselfs add_slashsstart_responsesfilenamesrequests path_info_popsosspathsnormpaths resource_namesresources root_resourcesNones startswiths not_foundseggs has_resourcesresource_isdirs child_roots __class__smanagerserror_extra_paths mimetypess guess_typestypesencodingsget_resource_streamsfilesIOErrorsOSErrorseshttpexceptionss HTTPForbiddensexcswsgi_applicationsfileapps _FileIter( sselfsenvironsstart_responsesresourcesexcs child_rootstypesencodingsfilenames path_infosfilese((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys__call__,s8  $#& c Cshtidti|dd|id|id|i|i|pdf}|i ||SdS(Ns%The resource at %s could not be foundscomments=SCRIPT_NAME=%r; PATH_INFO=%r; looking in egg:%s#%r; debug: %ss SCRIPT_NAMEs PATH_INFOs(none)( shttpexceptionss HTTPNotFoundsrequests construct_urlsenvironsgetsselfseggs resource_names debug_messagesexcswsgi_applicationsstart_response(sselfsenvironsstart_responses debug_messagesexc((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys not_foundRs>(s__name__s __module__sNones__init__s__repr__s__call__s not_found(((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pysPkgResourcesParsers  &scCs.ttjotdnt||SdS(s A static file parser that loads data from an egg using ``pkg_resources``. Takes a configuration value ``egg``, which is an egg spec, and a base ``resource_name`` (default empty string) which is the path in the egg that this starts at. s%This function requires pkg_resources.N(s pkg_resourcessNonesNotImplementedErrorsPkgResourcesParserseggs resource_name(s global_confseggs resource_name((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pysmake_pkg_resources[s c Ks|tjo"|idddddf}nti|}|tjo|idddd f}nti|}|tjo|id f}nti|}th||d|d|d ||Sd S( s Create a URLParser application that looks in ``directory``, which should be the directory for the Python package named in ``base_python_name``. ``index_names`` are used when viewing the directory (like ``'index'`` for ``'index.html'``). ``hide_extensions`` are extensions that are not viewable (like ``'.pyc'``) and ``ignore_extensions`` are viewable but only if an explicit extension is given. s index_namessindexsIndexsmainsMainshide_extensionss.pycsbakspy~signore_extensionsN( s index_namessNones global_confsgets converterssaslistshide_extensionssignore_extensionss URLParsers directorysbase_python_namesconstructor_conf(s global_confs directorysbase_python_names index_namesshide_extensionssignore_extensionssconstructor_conf((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pysmake_url_parserfs  "   ( s__doc__sosssyssimps mimetypess pkg_resourcess ImportErrorsNonespastesrequestsfileapps paste.utils import_stringshttpexceptionss httpheaderssETAGs converterssobjects NoDefaults__all__s URLParsersmake_directorysregister_constructors make_unknowns load_modulesload_module_from_namesmake_pysStaticURLParsers make_staticsPkgResourcesParsersmake_pkg_resourcessmake_url_parser(s make_unknownsload_module_from_names URLParsers make_staticsmake_url_parsersmake_pkg_resourcess__all__sfileapps load_modulesimpshttpexceptionss converterss NoDefaults mimetypesssyssmake_pysStaticURLParsersmake_directorysPkgResourcesParsersrequests pkg_resourcess import_stringsETAGsos((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys?s>            =    " d F PK-68I虤**paste/progress.pyc; #Gc@sdZdkZdklZddZddZdZdZdZd e fd YZ d e fd YZ d e fdYZ d d gZ dejo dkZeideindS(s~ Upload Progress Monitor This is a WSGI middleware component which monitors the status of files being uploaded. It includes a small query application which will return a list of all files being uploaded by particular session/user. >>> from paste.httpserver import serve >>> from paste.urlmap import URLMap >>> from paste.auth.basic import AuthBasicHandler >>> from paste.debug.debugapp import SlowConsumer, SimpleApplication >>> # from paste.progress import * >>> realm = 'Test Realm' >>> def authfunc(username, password): ... return username == password >>> map = URLMap({}) >>> ups = UploadProgressMonitor(map, threshold=1024) >>> map['/upload'] = SlowConsumer() >>> map['/simple'] = SimpleApplication() >>> map['/report'] = UploadProgressReporter(ups) >>> serve(AuthBasicHandler(ups, realm, authfunc)) serving on... .. note:: This is experimental, and will change in the future. N(s catch_errorsii<ispaste.bytes_receivedspaste.request_startedspaste.request_finisheds _ProgressFilecBsAtZdZdZdZddZdZedZRS(sy This is the input-file wrapper used to record the number of ``paste.bytes_received`` for the given request. cCs:||_||_|i|_|i|_|i|_dS(N(senvironsselfs_ProgressFile_environsrfiles_ProgressFile_rfilesflushswrites writelines(sselfsenvironsrfile((s2build/bdist.darwin-8.0.1-x86/egg/paste/progress.pys__init__1s     cs5|it|id}t|SdS(Nc#s/x(D] }tct|7<|VqWdS(N(sriterschunksenvironsENVIRON_RECEIVEDslen(schunk(senvironsriter(s2build/bdist.darwin-8.0.1-x86/egg/paste/progress.pysiterwrap;s(sselfs_ProgressFile_environsenvironsiters_ProgressFile_rfilesritersiterwrap(sselfsiterwrapsenvironsriter((senvironsriters2build/bdist.darwin-8.0.1-x86/egg/paste/progress.pys__iter__8s icCs3|ii|}|itct|7<|SdS(N(sselfs_ProgressFile_rfilesreadssizeschunks_ProgressFile_environsENVIRON_RECEIVEDslen(sselfssizeschunk((s2build/bdist.darwin-8.0.1-x86/egg/paste/progress.pysreadAscCs0|ii}|itct|7<|SdS(N(sselfs_ProgressFile_rfilesreadlineschunks_ProgressFile_environsENVIRON_RECEIVEDslen(sselfschunk((s2build/bdist.darwin-8.0.1-x86/egg/paste/progress.pysreadlineFscCs3|ii|}|itct|7<|SdS(N(sselfs_ProgressFile_rfiles readlinesshintschunks_ProgressFile_environsENVIRON_RECEIVEDslen(sselfshintschunk((s2build/bdist.darwin-8.0.1-x86/egg/paste/progress.pys readlinesKs( s__name__s __module__s__doc__s__init__s__iter__sreadsreadlinesNones readlines(((s2build/bdist.darwin-8.0.1-x86/egg/paste/progress.pys _ProgressFile+s    sUploadProgressMonitorcBs/tZdZeedZdZdZRS(s< monitors and reports on the status of uploads in progress Parameters: ``application`` This is the next application in the WSGI stack. ``threshold`` This is the size in bytes that is needed for the upload to be included in the monitor. ``timeout`` This is the amount of time (in seconds) that a upload remains in the monitor after it has finished. Methods: ``uploads()`` This returns a list of ``environ`` dict objects for each upload being currently monitored, or finished but whose time has not yet expired. For each request ``environ`` that is monitored, there are several variables that are stored: ``paste.bytes_received`` This is the total number of bytes received for the given request; it can be compared with ``CONTENT_LENGTH`` to build a percentage complete. This is an integer value. ``paste.request_started`` This is the time (in seconds) when the request was started as obtained from ``time.time()``. One would want to format this for presentation to the user, if necessary. ``paste.request_finished`` This is the time (in seconds) when the request was finished, canceled, or otherwise disconnected. This is None while the given upload is still in-progress. TODO: turn monitor into a queue and purge queue of finished requests that have passed the timeout period. cCs6||_|pt|_|pt|_g|_dS(N(s applicationsselfs thresholdsDEFAULT_THRESHOLDstimeoutsDEFAULT_TIMEOUTsmonitor(sselfs applications thresholdstimeout((s2build/bdist.darwin-8.0.1-x86/egg/paste/progress.pys__init__s csidd}|ot||ijow|iidtefd?YZ,d@efdAYZ-dBefdCYZ.dDefdEYZ/dFe/fdGYZ0dHe/fdIYZ1dJe/fdKYZ2dLe/fdMYZ3dNe/fdOYZ4dPe/fdQYZ5dd d gZ6hZ7xne8i9D]]\Z:Z;e<e;e=ei>foe?e;eoe;i@oe;e7e;i@ %(title)s

%(title)s

%(body)s


%(server)s
s HTTPExceptioncBstZdZeZeZdZdZdZdZ fZ eeedZ edZ dZ dZdZdZed ZeZd ZRS( s the HTTP exception base class This encapsulates an HTTP response that interrupts normal application flow; but one which is not necessarly an error condition. For example, codes in the 300's are exceptions in that they interrupt normal processing; however, they are not considered errors. This class is complicated by 4 factors: 1. The content given to the exception may either be plain-text or as html-text. 2. The template may want to have string-substitutions taken from the current ``environ`` or values from incoming headers. This is especially troublesome due to case sensitivity. 3. The final output may either be text/plain or text/html mime-type as requested by the client application. 4. Each exception has a default explanation, but those who raise exceptions may want to provide additional detail. Attributes: ``code`` the HTTP status code for the exception ``title`` remainder of the status line (stuff after the code) ``explanation`` a plain-text explanation of the error message that is not subject to environment or header substitutions; it is accessible in the template via %(explanation)s ``detail`` a plain-text message customization that is not subject to environment or header substitutions; accessible in the template via %(detail)s ``template`` a content fragment (in HTML) used for environment and header substitution; the default template includes both the explanation and further detail provided in the message ``required_headers`` a sequence of headers which are required for proper construction of the exception Parameters: ``detail`` a plain-text override of the default ``detail`` ``headers`` a list of (k,v) header pairs ``comment`` a plain-text additional information which is usually stripped/hidden for end-users To override the template (which is HTML content) or the plain-text explanation, one must subclass the given exception; or customize it after it has been created. This particular breakdown of a message into explanation, detail and template allows both the creation of plain-text and html messages for various clients as well as error-free substitution of environment variables and headers. ss6%(explanation)s
%(detail)s cCs|pt|_x|iD]}qW|tj o ||_n|tj o ||_nti |d|i |i |i |ifdS(Ns %s %s %s %s ( sheadersstuplesselfsrequired_headerssreqsdetailsNonescomments Exceptions__init__scodestitles explanation(sselfsdetailsheadersscommentsreq((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys__init__s     cCs|p|}hd||i<d||i<d||i<}ti|ijo ||Snx*|i D]\}}||||(sselfs __class__s__name__stitlescode(sself((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys__repr__ s(s__name__s __module__s__doc__sNonescodestitles explanationsdetailscommentstemplatesrequired_headerss__init__s make_bodysplainshtmlsprepare_contentsresponseswsgi_applications__call__s__repr__(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys HTTPException_s" F     s HTTPErrorcBstZdZRS(s base class for status codes in the 400's and 500's This is an exception which indicates that an error has occurred, and that any work in progress should not be committed. These are typically results in the 400's and 500's. (s__name__s __module__s__doc__(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys HTTPErrors sHTTPRedirectioncBstZdZRS(s base class for 300's status code (redirections) This is an abstract base class for 3xx redirection. It indicates that further action needs to be taken by the user agent in order to fulfill the request. It does not necessarly signal an error condition. (s__name__s __module__s__doc__(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPRedirection"s s _HTTPMovecBs\tZdZdfZdZdZeeedZeeedZe eZdZ RS(s redirections which require a Location field Since a 'Location' header is a required attribute of 301, 302, 303, 305 and 307 (but not 304), this base class provides the mechanics to make this easy. While this has the same parameters as HTTPException, if a location is not provided in the headers; it is assumed that the detail _is_ the location (this for backward compatibility, otherwise we'd add a new attribute). slocationsThe resource has been moved tos%(explanation)s %(location)s; you should be redirected automatically. %(detail)s cCs{|pg}t|d}| o#|}d}|id|fnti|||||t j o ||_ndS(Nslocations( sheaderss header_valueslocationsdetailsappendsHTTPRedirections__init__sselfscommentsNone(sselfsdetailsheadersscommentslocation((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys__init__>s  cCsLt||}|pg}|id|f|d|d|d|SdS(s Create a redirect object with the dest_uri, which may be relative, considering it relative to the uri implied by the given environ. sLocationsdetailsheadersscommentN( sresolve_relative_urlsdest_urisenvironslocationsheaderssappendsclssdetailscomment(sclssdest_urisenvironsdetailsheadersscommentslocation((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysrelative_redirectMs  cCsIxB|iD]'\}}|idjo|Sq q Wtd|dS(NslocationsNo location set for %s(sselfsheaderssnamesvalueslowersKeyError(sselfsnamesvalue((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pyslocationYs   ( s__name__s __module__s__doc__srequired_headerss explanationstemplatesNones__init__srelative_redirects classmethodslocation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys _HTTPMove,s   sHTTPMultipleChoicescBstZdZdZRS(Ni,sMultiple Choices(s__name__s __module__scodestitle(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPMultipleChoices`ssHTTPMovedPermanentlycBstZdZdZRS(Ni-sMoved Permanently(s__name__s __module__scodestitle(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPMovedPermanentlydss HTTPFoundcBstZdZdZdZRS(Ni.sFoundsThe resource was found at(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys HTTPFoundhss HTTPSeeOthercBstZdZdZRS(Ni/s See Other(s__name__s __module__scodestitle(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys HTTPSeeOtherossHTTPNotModifiedcBs,tZdZdZdZdZdZRS(Ni0s Not ModifiedscCsdSdS(Ns((sselfsenviron((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysplain|scCsdSdS(s+ text/html representation of the exception sN((sselfsenviron((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pyshtml~s(s__name__s __module__scodestitlesmessagesplainshtml(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPNotModifiedss  s HTTPUseProxycBstZdZdZdZRS(Ni1s Use Proxys8The resource must be accessed through a proxy located at(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys HTTPUseProxyssHTTPTemporaryRedirectcBstZdZdZRS(Ni3sTemporary Redirect(s__name__s __module__scodestitle(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPTemporaryRedirectssHTTPClientErrorcBs tZdZdZdZdZRS(s8 base class for the 400's, where the client is in-error This is an error condition in which the client is presumed to be in-error. This is an expected problem, and thus is not considered a bug. A server-side traceback is not warranted. Unless specialized, this is a '400 Bad Request' is Bad RequestsdThe server could not comply with the request since it is either malformed or otherwise incorrect. (s__name__s __module__s__doc__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPClientErrors sHTTPBadRequestcBstZRS(N(s__name__s __module__(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPBadRequestssHTTPUnauthorizedcBstZdZdZdZRS(Nis UnauthorizedsThis server could not verify that you are authorized to access the document you requested. Either you supplied the wrong credentials (e.g., bad password), or your browser does not understand how to supply the credentials required. (s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPUnauthorizedssHTTPPaymentRequiredcBstZdZdZdZRS(NisPayment Requireds(Access was denied for financial reasons.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPPaymentRequiredss HTTPForbiddencBstZdZdZdZRS(Nis Forbiddens#Access was denied to this resource.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys HTTPForbiddenss HTTPNotFoundcBstZdZdZdZRS(Nis Not Founds The resource could not be found.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys HTTPNotFoundssHTTPMethodNotAllowedcBs#tZdfZdZdZdZRS(NsallowisMethod Not AllowedsKThe method %(REQUEST_METHOD)s is not allowed for this resource. %(detail)s(s__name__s __module__srequired_headersscodestitlestemplate(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPMethodNotAlloweds sHTTPNotAcceptablecBstZdZdZdZRS(NisNot AcceptableswThe resource could not be generated that was acceptable to your browser (content of type %(HTTP_ACCEPT)s). %(detail)s(s__name__s __module__scodestitlestemplate(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPNotAcceptablessHTTPProxyAuthenticationRequiredcBstZdZdZdZRS(NisProxy Authentication Requireds*Authentication /w a local proxy is needed.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPProxyAuthenticationRequiredssHTTPRequestTimeoutcBstZdZdZdZRS(NisRequest TimeoutsHThe server has waited too long for the request to be sent by the client.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPRequestTimeoutss HTTPConflictcBstZdZdZdZRS(NisConflicts:There was a conflict when trying to complete your request.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys HTTPConflictssHTTPGonecBstZdZdZdZRS(NisGonesFThis resource is no longer available. No forwarding address is given.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPGonessHTTPLengthRequiredcBstZdZdZdZRS(NisLength RequiredsContent-Length header required.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPLengthRequiredssHTTPPreconditionFailedcBstZdZdZdZRS(NisPrecondition FailedsRequest precondition failed.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPPreconditionFailedssHTTPRequestEntityTooLargecBstZdZdZdZRS(NisRequest Entity Too Larges7The body of your request was too large for this server.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPRequestEntityTooLargessHTTPRequestURITooLongcBstZdZdZdZRS(NisRequest-URI Too Longs-The request URI was too long for this server.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPRequestURITooLongssHTTPUnsupportedMediaTypecBstZdZdZdZRS(NisUnsupported Media TypesTThe request media type %(CONTENT_TYPE)s is not supported by this server. %(detail)s(s__name__s __module__scodestitlestemplate(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPUnsupportedMediaTypessHTTPRequestRangeNotSatisfiablecBstZdZdZdZRS(NisRequest Range Not Satisfiables%The Range requested is not available.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPRequestRangeNotSatisfiablessHTTPExpectationFailedcBstZdZdZdZRS(NisExpectation FailedsExpectation failed.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPExpectationFailed ssHTTPServerErrorcBs tZdZdZdZdZRS(sF base class for the 500's, where the server is in-error This is an error condition in which the server is presumed to be in-error. This is usually unexpected, and thus requires a traceback; ideally, opening a support ticket for the customer. Unless specialized, this is a '500 Internal Server Error' isInternal Server ErrorsUThe server has either erred or is incapable of performing the requested operation. (s__name__s __module__s__doc__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPServerErrors sHTTPInternalServerErrorcBstZRS(N(s__name__s __module__(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPInternalServerError)ssHTTPNotImplementedcBstZdZdZdZRS(NisNot ImplementedsUThe request method %(REQUEST_METHOD)s is not implemented for this server. %(detail)s(s__name__s __module__scodestitlestemplate(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPNotImplemented,ssHTTPBadGatewaycBstZdZdZdZRS(Nis Bad Gateways Bad gateway.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPBadGateway3ssHTTPServiceUnavailablecBstZdZdZdZRS(NisService UnavailablesFThe server is currently unavailable. Please try again at a later time.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPServiceUnavailable8ssHTTPGatewayTimeoutcBstZdZdZdZRS(NisGateway TimeoutsThe gateway has timed out.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPGatewayTimeout>ssHTTPVersionNotSupportedcBstZdZdZdZRS(NisHTTP Version Not Supporteds"The HTTP version is not supported.(s__name__s __module__scodestitles explanation(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPVersionNotSupportedCscCs t|SdS(N(s _exceptionsscode(scode((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys get_exceptionSssHTTPExceptionHandlercBs#tZdZedZdZRS(s catches exceptions and turns them into proper HTTP responses Attributes: ``warning_level`` This attribute determines for what exceptions a stack trace is kept for lower level reporting; by default, it only keeps stack trace for 5xx, HTTPServerError exceptions. To keep a stack trace for 4xx, HTTPClientError exceptions, set this to 400. This middleware catches any exceptions (which are subclasses of ``HTTPException``) and turns them into proper HTTP responses. Note if the headers have already been sent, the stack trace is always maintained as this indicates a programming error. cCs|pd|_||_dS(Ni(s warning_levelsselfs application(sselfs applications warning_level((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys__init__mscCs`||d<|idgity|i||SWn"tj o}|||SnXdS(Nspaste.httpexceptionsspaste.expected_exceptions(sselfsenvirons setdefaultsappends HTTPExceptions applicationsstart_responsesexc(sselfsenvironsstart_responsesexc((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys__call__ss  (s__name__s __module__s__doc__sNones__init__s__call__(((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysHTTPExceptionHandlerZs  cOs-dk}|idtdt||SdS(Ns\httpexceptions.middleware is deprecated; use make_middleware or HTTPExceptionHandler insteadi(swarningsswarnsDeprecationWarningsmake_middlewaresargsskw(sargsskwswarnings((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys middleware|s   cCs+|ot|}nt|d|SdS(s ``httpexceptions`` middleware; this catches any ``paste.httpexceptions.HTTPException`` exceptions (exceptions like ``HTTPNotFound``, ``HTTPMovedPermanently``, etc) and turns them into proper HTTP responses. ``warning_level`` can be an integer corresponding to an HTTP code. Any code over that value will be passed 'up' the chain, potentially reported on by another piece of middleware. s warning_levelN(s warning_levelsintsHTTPExceptionHandlersapp(sapps global_confs warning_level((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pysmake_middlewares s get_exception(Is__doc__stypess paste.wsgilibscatch_errors_appspaste.responses has_headers header_valuesreplace_headers paste.requestsresolve_relative_urlspaste.util.quotings strip_htmls html_quotesno_quotes SERVER_NAMEsTEMPLATEs Exceptions HTTPExceptions HTTPErrorsHTTPRedirections _HTTPMovesHTTPMultipleChoicessHTTPMovedPermanentlys HTTPFounds HTTPSeeOthersHTTPNotModifieds HTTPUseProxysHTTPTemporaryRedirectsHTTPClientErrorsHTTPBadRequestsHTTPUnauthorizedsHTTPPaymentRequireds HTTPForbiddens HTTPNotFoundsHTTPMethodNotAllowedsHTTPNotAcceptablesHTTPProxyAuthenticationRequiredsHTTPRequestTimeouts HTTPConflictsHTTPGonesHTTPLengthRequiredsHTTPPreconditionFailedsHTTPRequestEntityTooLargesHTTPRequestURITooLongsHTTPUnsupportedMediaTypesHTTPRequestRangeNotSatisfiablesHTTPExpectationFailedsHTTPServerErrorsHTTPInternalServerErrorsHTTPNotImplementedsHTTPBadGatewaysHTTPServiceUnavailablesHTTPGatewayTimeoutsHTTPVersionNotSupporteds__all__s _exceptionssglobalssitemssnamesvalues isinstancestypes ClassTypes issubclassscodesappends get_exceptionsobjectsHTTPExceptionHandlers middlewaresNonesmake_middlewaresextend(8sHTTPRequestEntityTooLarges HTTPUseProxys HTTPSeeOthers HTTPConflictsHTTPServiceUnavailablesmake_middlewaresHTTPMultipleChoicessHTTPRequestRangeNotSatisfiablesHTTPRequestURITooLongsHTTPRedirectionsHTTPRequestTimeoutsHTTPBadRequestsHTTPUnsupportedMediaTypesHTTPMethodNotAllowedsHTTPBadGatewaysHTTPMovedPermanentlysHTTPNotImplementedsHTTPExpectationFaileds HTTPForbiddens SERVER_NAMEsHTTPVersionNotSupportedsresolve_relative_urlsHTTPServerErrorsnames get_exceptionsHTTPNotModifiedsHTTPNotAcceptablesHTTPPaymentRequireds HTTPExceptionsHTTPTemporaryRedirectsHTTPPreconditionFaileds HTTPFoundsHTTPInternalServerErrors header_valuesHTTPUnauthorizeds HTTPErrors _HTTPMovestypess__all__sHTTPGatewayTimeouts HTTPNotFounds _exceptionssHTTPExceptionHandlersHTTPClientErrorsHTTPGonesreplace_headersHTTPProxyAuthenticationRequiredscatch_errors_appsno_quotesHTTPLengthRequiredsTEMPLATEs strip_htmls has_headersvalues html_quotes middleware((s8build/bdist.darwin-8.0.1-x86/egg/paste/httpexceptions.pys?Jsp     4  3  " PK-68xllpaste/transaction.pyc; #Gc@sdZdklZdklZdefdYZdefdYZdefdYZd Z dd gZ d e joe omd k lZeed dZeZeiZeideidei\ZZeGeGHndS(s Middleware related to transactions and database connections. At this time it is very basic; but will eventually sprout all that two-phase commit goodness that I don't need. .. note:: This is experimental, and will change in the future. (s HTTPException(s catch_errorssTransactionManagerMiddlewarecBstZdZdZRS(NcCs ||_dS(N(s applicationsself(sselfs application((s5build/bdist.darwin-8.0.1-x86/egg/paste/transaction.pys__init__scCsDt|d<}t|dCss PgQuoteString(smodulesselfsargsskwargssquoteshasattrs PgQuoteString(sselfsmodulesargsskwargs((s5build/bdist.darwin-8.0.1-x86/egg/paste/transaction.pys__init__<s     cCsC|ii|i|i}|i|id<|i|id<|SdS(Nsmodulesquote(sselfsmodulesconnectsargsskwargssconns__dict__squote(sselfsenvironsconn((s5build/bdist.darwin-8.0.1-x86/egg/paste/transaction.pys__call__Gs(s__name__s __module__s__doc__s__init__sNones__call__(((s5build/bdist.darwin-8.0.1-x86/egg/paste/transaction.pysConnectionFactory5s  csd}|SdS(s Provides a simple mechanism for starting a transaction based on the factory; and for either committing or rolling back the transaction depending on the result. It checks for the response's current status code either through the latest call to start_response; or through a HTTPException's code. If it is a 100, 200, or 300; the transaction is committed; otherwise it is rolled back. c s]||dt j o2t d|idi |ii fnXh} x?|i D]4\}} } }| |i||}|| | ' % self.length def read(self, length=None): left = self.length - self._consumed if length is None: length = left else: length = min(length, left) # next two lines are hnecessary only if read(0) blocks if not left: return '' data = self.file.read(length) self._consumed += len(data) return data def readline(self, *args): data = self.file.readline(self.length - self._consumed) self._consumed += len(data) return data def readlines(self, hint=None): data = self.file.readlines(hint) for chunk in data: self._consumed += len(chunk) return data def __iter__(self): return self def next(self): if self.length - self._consumed <= 0: raise StopIteration return self.readline() ## Optional methods ## def seek(self, place): self.file.seek(place) self._consumed = place def tell(self): if hasattr(self.file, 'tell'): return self.file.tell() else: return self._consumed class ThreadPool(object): """ Generic thread pool with a queue of callables to consume. Keeps a notion of the status of its worker threads: idle: worker thread with nothing to do busy: worker thread doing its job hung: worker thread that's been doing a job for too long dying: a hung thread that has been killed, but hasn't died quite yet. zombie: what was a worker thread that we've tried to kill but isn't dead yet. At any time you can call track_threads, to get a dictionary with these keys and lists of thread_ids that fall in that status. All keys will be present, even if they point to emty lists. hung threads are threads that have been busy more than hung_thread_limit seconds. Hung threads are killed when they live longer than kill_thread_limit seconds. A thread is then considered dying for dying_limit seconds, if it is still alive after that it is considered a zombie. When there are no idle workers and a request comes in, another worker *may* be spawned. If there are less than spawn_if_under threads in the busy state, another thread will be spawned. So if the limit is 5, and there are 4 hung threads and 6 busy threads, no thread will be spawned. When there are more than max_zombie_threads_before_die zombie threads, a SystemExit exception will be raised, stopping the server. Use 0 or None to never raise this exception. Zombie threads *should* get cleaned up, but killing threads is no necessarily reliable. This is turned off by default, since it is only a good idea if you've deployed the server with some process watching from above (something similar to daemontools or zdaemon). Each worker thread only processes ``max_requests`` tasks before it dies and replaces itself with a new worker thread. """ SHUTDOWN = object() def __init__( self, nworkers, name="ThreadPool", daemon=False, max_requests=100, # threads are killed after this many requests hung_thread_limit=30, # when a thread is marked "hung" kill_thread_limit=1800, # when you kill that hung thread dying_limit=300, # seconds that a kill should take to go into effect (longer than this and the thread is a "zombie") spawn_if_under=5, # spawn if there's too many hung threads max_zombie_threads_before_die=0, # when to give up on the process hung_check_period=100, # every 100 requests check for hung workers logger=None, # Place to log messages to error_email=None, # Person(s) to notify if serious problem occurs ): """ Create thread pool with `nworkers` worker threads. """ self.nworkers = nworkers self.max_requests = max_requests self.name = name self.queue = Queue.Queue() self.workers = [] self.daemon = daemon if logger is None: logger = logging.getLogger('paste.httpserver.ThreadPool') if isinstance(logger, basestring): logger = logging.getLogger(logger) self.logger = logger self.error_email = error_email self._worker_count = count() assert (not kill_thread_limit or kill_thread_limit >= hung_thread_limit), ( "kill_thread_limit (%s) should be higher than hung_thread_limit (%s)" % (kill_thread_limit, hung_thread_limit)) if not killthread: kill_thread_limit = 0 self.logger.info( "Cannot use kill_thread_limit as ctypes/killthread is not available") self.kill_thread_limit = kill_thread_limit self.dying_limit = dying_limit self.hung_thread_limit = hung_thread_limit assert spawn_if_under <= nworkers, ( "spawn_if_under (%s) should be less than nworkers (%s)" % (spawn_if_under, nworkers)) self.spawn_if_under = spawn_if_under self.max_zombie_threads_before_die = max_zombie_threads_before_die self.hung_check_period = hung_check_period self.requests_since_last_hung_check = 0 # Used to keep track of what worker is doing what: self.worker_tracker = {} # Used to keep track of the workers not doing anything: self.idle_workers = [] # Used to keep track of threads that have been killed, but maybe aren't dead yet: self.dying_threads = {} # This is used to track when we last had to add idle workers; # we shouldn't cull extra workers until some time has passed # (hung_thread_limit) since workers were added: self._last_added_new_idle_workers = 0 if not daemon: atexit.register(self.shutdown) for i in range(self.nworkers): self.add_worker_thread(message='Initial worker pool') def add_task(self, task): """ Add a task to the queue """ self.logger.debug('Added task (%i tasks queued)', self.queue.qsize()) if self.hung_check_period: self.requests_since_last_hung_check += 1 if self.requests_since_last_hung_check > self.hung_check_period: self.requests_since_last_hung_check = 0 self.kill_hung_threads() if not self.idle_workers and self.spawn_if_under: # spawn_if_under can come into effect... busy = 0 now = time.time() self.logger.debug('No idle workers for task; checking if we need to make more workers') for worker in self.workers: if not hasattr(worker, 'thread_id'): # Not initialized continue time_started, info = self.worker_tracker.get(worker.thread_id, (None, None)) if time_started is not None: if now - time_started < self.hung_thread_limit: busy += 1 if busy < self.spawn_if_under: self.logger.info( 'No idle tasks, and only %s busy tasks; adding %s more ' 'workers', busy, self.spawn_if_under-busy) self._last_added_new_idle_workers = time.time() for i in range(self.spawn_if_under - busy): self.add_worker_thread(message='Response to lack of idle workers') else: self.logger.debug( 'No extra workers needed (%s busy workers)', busy) if (len(self.workers) > self.nworkers and len(self.idle_workers) > 3 and time.time()-self._last_added_new_idle_workers > self.hung_thread_limit): # We've spawned worers in the past, but they aren't needed # anymore; kill off some self.logger.info( 'Culling %s extra workers (%s idle workers present)', len(self.workers)-self.nworkers, len(self.idle_workers)) self.logger.debug( 'Idle workers: %s', self.idle_workers) for i in range(len(self.workers) - self.nworkers): self.queue.put(self.SHUTDOWN) self.queue.put(task) def track_threads(self): """ Return a dict summarizing the threads in the pool (as described in the ThreadPool docstring). """ result = dict(idle=[], busy=[], hung=[], dying=[], zombie=[]) now = time.time() for worker in self.workers: if not hasattr(worker, 'thread_id'): # The worker hasn't fully started up, we should just # ignore it continue time_started, info = self.worker_tracker.get(worker.thread_id, (None, None)) if time_started is not None: if now - time_started > self.hung_thread_limit: result['hung'].append(worker) else: result['busy'].append(worker) else: result['idle'].append(worker) for thread_id, (time_killed, worker) in self.dying_threads.items(): if not self.thread_exists(thread_id): # Cull dying threads that are actually dead and gone self.logger.info('Killed thread %s no longer around', thread_id) try: del self.dying_threads[thread_id] except KeyError: pass continue if now - time_killed > self.dying_limit: result['zombie'].append(worker) else: result['dying'].append(worker) return result def kill_worker(self, thread_id): """ Removes the worker with the given thread_id from the pool, and replaces it with a new worker thread. This should only be done for mis-behaving workers. """ if killthread is None: raise RuntimeError( "Cannot kill worker; killthread/ctypes not available") thread_obj = threading._active.get(thread_id) killthread.async_raise(thread_id, SystemExit) try: del self.worker_tracker[thread_id] except KeyError: pass self.logger.info('Killing thread %s', thread_id) if thread_obj in self.workers: self.workers.remove(thread_obj) self.dying_threads[thread_id] = (time.time(), thread_obj) self.add_worker_thread(message='Replacement for killed thread %s' % thread_id) def thread_exists(self, thread_id): """ Returns true if a thread with this id is still running """ return thread_id in threading._active def add_worker_thread(self, *args, **kwargs): index = self._worker_count.next() worker = threading.Thread(target=self.worker_thread_callback, args=args, kwargs=kwargs, name=("worker %d" % index)) worker.setDaemon(self.daemon) worker.start() def kill_hung_threads(self): """ Tries to kill any hung threads """ if not self.kill_thread_limit: # No killing should occur return now = time.time() max_time = 0 total_time = 0 idle_workers = 0 starting_workers = 0 working_workers = 0 killed_workers = 0 for worker in self.workers: if not hasattr(worker, 'thread_id'): # Not setup yet starting_workers += 1 continue time_started, info = self.worker_tracker.get(worker.thread_id, (None, None)) if time_started is None: # Must be idle idle_workers += 1 continue working_workers += 1 max_time = max(max_time, now-time_started) total_time += now-time_started if now - time_started > self.kill_thread_limit: self.logger.warning( 'Thread %s hung (working on task for %i seconds)', worker.thread_id, now - time_started) try: import pprint info_desc = pprint.pformat(info) except: out = StringIO() traceback.print_exc(file=out) info_desc = 'Error:\n%s' % out.getvalue() self.notify_problem( "Killing worker thread (id=%(thread_id)s) because it has been \n" "working on task for %(time)s seconds (limit is %(limit)s)\n" "Info on task:\n" "%(info)s" % dict(thread_id=worker.thread_id, time=now - time_started, limit=self.kill_thread_limit, info=info_desc)) self.kill_worker(worker.thread_id) killed_workers += 1 if working_workers: ave_time = float(total_time) / working_workers ave_time = '%.2fsec' % ave_time else: ave_time = 'N/A' self.logger.info( "kill_hung_threads status: %s threads (%s working, %s idle, %s starting) " "ave time %s, max time %.2fsec, killed %s workers" % (idle_workers + starting_workers + working_workers, working_workers, idle_workers, starting_workers, ave_time, max_time, killed_workers)) self.check_max_zombies() def check_max_zombies(self): """ Check if we've reached max_zombie_threads_before_die; if so then kill the entire process. """ if not self.max_zombie_threads_before_die: return found = [] now = time.time() for thread_id, (time_killed, worker) in self.dying_threads.items(): if not self.thread_exists(thread_id): # Cull dying threads that are actually dead and gone try: del self.dying_threads[thread_id] except KeyError: pass continue if now - time_killed > self.dying_limit: found.append(thread_id) if found: self.logger.info('Found %s zombie threads', found) if len(found) > self.max_zombie_threads_before_die: self.logger.fatal( 'Exiting process because %s zombie threads is more than %s limit', len(found), self.max_zombie_threads_before_die) self.notify_problem( "Exiting process because %(found)s zombie threads " "(more than limit of %(limit)s)\n" "Bad threads (ids):\n" " %(ids)s\n" % dict(found=len(found), limit=self.max_zombie_threads_before_die, ids="\n ".join(map(str, found))), subject="Process restart (too many zombie threads)") self.shutdown(10) print 'Shutting down', threading.currentThread() raise ServerExit(3) def worker_thread_callback(self, message=None): """ Worker thread should call this method to get and process queued callables. """ thread_obj = threading.currentThread() thread_id = thread_obj.thread_id = thread.get_ident() self.workers.append(thread_obj) self.idle_workers.append(thread_id) requests_processed = 0 add_replacement_worker = False self.logger.debug('Started new worker %s: %s', thread_id, message) try: while True: if self.max_requests and self.max_requests < requests_processed: # Replace this thread then die self.logger.debug('Thread %s processed %i requests (limit %s); stopping thread' % (thread_id, requests_processed, self.max_requests)) add_replacement_worker = True break runnable = self.queue.get() if runnable is ThreadPool.SHUTDOWN: self.logger.debug('Worker %s asked to SHUTDOWN', thread_id) break try: self.idle_workers.remove(thread_id) except ValueError: pass self.worker_tracker[thread_id] = [time.time(), None] requests_processed += 1 try: try: runnable() except: # We are later going to call sys.exc_clear(), # removing all remnants of any exception, so # we should log it now. But ideally no # exception should reach this level print >> sys.stderr, ( 'Unexpected exception in worker %r' % runnable) traceback.print_exc() if thread_id in self.dying_threads: # That last exception was intended to kill me break finally: try: del self.worker_tracker[thread_id] except KeyError: pass sys.exc_clear() self.idle_workers.append(thread_id) finally: try: del self.worker_tracker[thread_id] except KeyError: pass try: self.idle_workers.remove(thread_id) except ValueError: pass try: self.workers.remove(thread_obj) except ValueError: pass try: del self.dying_threads[thread_id] except KeyError: pass if add_replacement_worker: self.add_worker_thread(message='Voluntary replacement for thread %s' % thread_id) def shutdown(self, force_quit_timeout=0): """ Shutdown the queue (after finishing any pending requests). """ self.logger.info('Shutting down threadpool') # Add a shutdown request for every worker for i in range(len(self.workers)): self.queue.put(ThreadPool.SHUTDOWN) # Wait for each thread to terminate hung_workers = [] for worker in self.workers: worker.join(0.5) if worker.isAlive(): hung_workers.append(worker) zombies = [] for thread_id in self.dying_threads: if self.thread_exists(thread_id): zombies.append(thread_id) if hung_workers or zombies: self.logger.info("%s workers didn't stop properly, and %s zombies", len(hung_workers), len(zombies)) if hung_workers: for worker in hung_workers: self.kill_worker(worker.thread_id) self.logger.info('Workers killed forcefully') if force_quit_timeout: hung = [] timed_out = False need_force_quit = bool(zombies) for workers in self.workers: if not timed_out and worker.isAlive(): timed_out = True worker.join(force_quit_timeout) if worker.isAlive(): print "Worker %s won't die" % worker need_force_quit = True if need_force_quit: import atexit # Remove the threading atexit callback for callback in list(atexit._exithandlers): func = getattr(callback[0], 'im_func', None) if not func: continue globs = getattr(func, 'func_globals', {}) mod = globs.get('__name__') if mod == 'threading': atexit._exithandlers.remove(callback) atexit._run_exitfuncs() print 'Forcefully exiting process' os._exit(3) else: self.logger.info('All workers eventually killed') else: self.logger.info('All workers stopped') def notify_problem(self, msg, subject=None, spawn_thread=True): """ Called when there's a substantial problem. msg contains the body of the notification, subject the summary. If spawn_thread is true, then the email will be send in another thread (so this doesn't block). """ if not self.error_email: return if spawn_thread: t = threading.Thread( target=self.notify_problem, args=(msg, subject, False)) t.start() return from_address = 'errors@localhost' if not subject: subject = msg.strip().splitlines()[0] subject = subject[:50] subject = '[http threadpool] %s' % subject headers = [ "To: %s" % self.error_email, "From: %s" % from_address, "Subject: %s" % subject, ] try: system = ' '.join(os.uname()) except: system = '(unknown)' body = ( "An error has occurred in the paste.httpserver.ThreadPool\n" "Error:\n" " %(msg)s\n" "Occurred at: %(time)s\n" "PID: %(pid)s\n" "System: %(system)s\n" "Server .py file: %(file)s\n" % dict(msg=msg, time=time.strftime("%c"), pid=os.getpid(), system=system, file=os.path.abspath(__file__), )) message = '\n'.join(headers) + "\n\n" + body import smtplib server = smtplib.SMTP('localhost') error_emails = [ e.strip() for e in self.error_email.split(",") if e.strip()] server.sendmail(from_address, error_emails, message) server.quit() print 'email sent to', error_emails, message class ThreadPoolMixIn(object): """ Mix-in class to process requests from a thread pool """ def __init__(self, nworkers, daemon=False, **threadpool_options): # Create and start the workers self.running = True assert nworkers > 0, "ThreadPoolMixIn servers must have at least one worker" self.thread_pool = ThreadPool( nworkers, "ThreadPoolMixIn HTTP server on %s:%d" % (self.server_name, self.server_port), daemon, **threadpool_options) def process_request(self, request, client_address): """ Queue the request to be processed by on of the thread pool threads """ # This sets the socket to blocking mode (and no timeout) since it # may take the thread pool a little while to get back to it. (This # is the default but since we set a timeout on the parent socket so # that we can trap interrupts we need to restore this,.) request.setblocking(1) # Queue processing of the request self.thread_pool.add_task( lambda: self.process_request_in_thread(request, client_address)) def handle_error(self, request, client_address): exc_class, exc, tb = sys.exc_info() if exc_class is ServerExit: # This is actually a request to stop the server raise return super(ThreadPoolMixIn, self).handle_error(request, client_address) def process_request_in_thread(self, request, client_address): """ The worker thread should call back here to do the rest of the request processing. Error handling normaller done in 'handle_request' must be done here. """ try: self.finish_request(request, client_address) self.close_request(request) except: self.handle_error(request, client_address) self.close_request(request) def serve_forever(self): """ Overrides `serve_forever` to shut the threadpool down cleanly. """ try: while self.running: try: self.handle_request() except socket.timeout: # Timeout is expected, gives interrupts a chance to # propogate, just keep handling pass finally: self.thread_pool.shutdown() def server_activate(self): """ Overrides server_activate to set timeout on our listener socket. """ # We set the timeout here so that we can trap interrupts on windows self.socket.settimeout(1) self.socket.listen(self.request_queue_size) def server_close(self): """ Finish pending requests and shutdown the server. """ self.running = False self.socket.close() self.thread_pool.shutdown(60) class WSGIServerBase(SecureHTTPServer): def __init__(self, wsgi_application, server_address, RequestHandlerClass=None, ssl_context=None): SecureHTTPServer.__init__(self, server_address, RequestHandlerClass, ssl_context) self.wsgi_application = wsgi_application self.wsgi_socket_timeout = None def get_request(self): # If there is a socket_timeout, set it on the accepted (conn,info) = SecureHTTPServer.get_request(self) if self.wsgi_socket_timeout: conn.settimeout(self.wsgi_socket_timeout) return (conn, info) class WSGIServer(ThreadingMixIn, WSGIServerBase): daemon_threads = False class WSGIThreadPoolServer(ThreadPoolMixIn, WSGIServerBase): def __init__(self, wsgi_application, server_address, RequestHandlerClass=None, ssl_context=None, nworkers=10, daemon_threads=False, threadpool_options=None): WSGIServerBase.__init__(self, wsgi_application, server_address, RequestHandlerClass, ssl_context) if threadpool_options is None: threadpool_options = {} ThreadPoolMixIn.__init__(self, nworkers, daemon_threads, **threadpool_options) class ServerExit(SystemExit): """ Raised to tell the server to really exit (SystemExit is normally caught) """ def serve(application, host=None, port=None, handler=None, ssl_pem=None, ssl_context=None, server_version=None, protocol_version=None, start_loop=True, daemon_threads=None, socket_timeout=None, use_threadpool=None, threadpool_workers=10, threadpool_options=None): """ Serves your ``application`` over HTTP(S) via WSGI interface ``host`` This is the ipaddress to bind to (or a hostname if your nameserver is properly configured). This defaults to 127.0.0.1, which is not a public interface. ``port`` The port to run on, defaults to 8080 for HTTP, or 4443 for HTTPS. This can be a string or an integer value. ``handler`` This is the HTTP request handler to use, it defaults to ``WSGIHandler`` in this module. ``ssl_pem`` This an optional SSL certificate file (via OpenSSL). You can supply ``*`` and a development-only certificate will be created for you, or you can generate a self-signed test PEM certificate file as follows:: $ openssl genrsa 1024 > host.key $ chmod 400 host.key $ openssl req -new -x509 -nodes -sha1 -days 365 \\ -key host.key > host.cert $ cat host.cert host.key > host.pem $ chmod 400 host.pem ``ssl_context`` This an optional SSL context object for the server. A SSL context will be automatically constructed for you if you supply ``ssl_pem``. Supply this to use a context of your own construction. ``server_version`` The version of the server as reported in HTTP response line. This defaults to something like "PasteWSGIServer/0.5". Many servers hide their code-base identity with a name like 'Amnesiac/1.0' ``protocol_version`` This sets the protocol used by the server, by default ``HTTP/1.0``. There is some support for ``HTTP/1.1``, which defaults to nicer keep-alive connections. This server supports ``100 Continue``, but does not yet support HTTP/1.1 Chunked Encoding. Hence, if you use HTTP/1.1, you're somewhat in error since chunked coding is a mandatory requirement of a HTTP/1.1 server. If you specify HTTP/1.1, every response *must* have a ``Content-Length`` and you must be careful not to read past the end of the socket. ``start_loop`` This specifies if the server loop (aka ``server.serve_forever()``) should be called; it defaults to ``True``. ``daemon_threads`` This flag specifies if when your webserver terminates all in-progress client connections should be droppped. It defaults to ``False``. You might want to set this to ``True`` if you are using ``HTTP/1.1`` and don't set a ``socket_timeout``. ``socket_timeout`` This specifies the maximum amount of time that a connection to a given client will be kept open. At this time, it is a rude disconnect, but at a later time it might follow the RFC a bit more closely. ``use_threadpool`` Server requests from a pool of worker threads (``threadpool_workers``) rather than creating a new thread for each request. This can substantially reduce latency since there is a high cost associated with thread creation. ``threadpool_workers`` Number of worker threads to create when ``use_threadpool`` is true. This can be a string or an integer value. ``threadpool_options`` A dictionary of options to be used when instantiating the threadpool. See paste.httpserver.ThreadPool for specific options (``threadpool_workers`` is a specific option that can also go here). """ is_ssl = False if ssl_pem or ssl_context: assert SSL, "pyOpenSSL is not installed" is_ssl = True port = int(port or 4443) if not ssl_context: if ssl_pem == '*': ssl_context = _auto_ssl_context() else: ssl_context = SSL.Context(SSL.SSLv23_METHOD) ssl_context.use_privatekey_file(ssl_pem) ssl_context.use_certificate_chain_file(ssl_pem) host = host or '127.0.0.1' if not port: if ':' in host: host, port = host.split(':', 1) else: port = 8080 server_address = (host, int(port)) if not handler: handler = WSGIHandler if server_version: handler.server_version = server_version handler.sys_version = None if protocol_version: assert protocol_version in ('HTTP/0.9', 'HTTP/1.0', 'HTTP/1.1') handler.protocol_version = protocol_version if use_threadpool is None: use_threadpool = True if converters.asbool(use_threadpool): server = WSGIThreadPoolServer(application, server_address, handler, ssl_context, int(threadpool_workers), daemon_threads, threadpool_options=threadpool_options) else: server = WSGIServer(application, server_address, handler, ssl_context) if daemon_threads: server.daemon_threads = daemon_threads if socket_timeout: server.wsgi_socket_timeout = int(socket_timeout) if converters.asbool(start_loop): protocol = is_ssl and 'https' or 'http' host, port = server.server_address if host == '0.0.0.0': print 'serving on 0.0.0.0:%s view at %s://127.0.0.1:%s' % \ (port, protocol, port) else: print "serving on %s://%s:%s" % (protocol, host, port) try: server.serve_forever() except KeyboardInterrupt: # allow CTRL+C to shutdown pass return server # For paste.deploy server instantiation (egg:Paste#http) # Note: this gets a separate function because it has to expect string # arguments (though that's not much of an issue yet, ever?) def server_runner(wsgi_app, global_conf, **kwargs): from paste.deploy.converters import asbool for name in ['port', 'socket_timeout', 'threadpool_workers', 'threadpool_hung_thread_limit', 'threadpool_kill_thread_limit', 'threadpool_dying_limit', 'threadpool_spawn_if_under', 'threadpool_max_zombie_threads_before_die', 'threadpool_hung_check_period', 'threadpool_max_requests']: if name in kwargs: kwargs[name] = int(kwargs[name]) for name in ['use_threadpool', 'daemon_threads']: if name in kwargs: kwargs[name] = asbool(kwargs[name]) threadpool_options = {} for name, value in kwargs.items(): if name.startswith('threadpool_') and name != 'threadpool_workers': threadpool_options[name[len('threadpool_'):]] = value del kwargs[name] if ('error_email' not in threadpool_options and 'error_email' in global_conf): threadpool_options['error_email'] = global_conf['error_email'] kwargs['threadpool_options'] = threadpool_options serve(wsgi_app, **kwargs) server_runner.__doc__ = serve.__doc__ + """ You can also set these threadpool options: ``threadpool_max_requests``: The maximum number of requests a worker thread will process before dying (and replacing itself with a new worker thread). Default 100. ``threadpool_hung_thread_limit``: The number of seconds a thread can work on a task before it is considered hung (stuck). Default 30 seconds. ``threadpool_kill_thread_limit``: The number of seconds a thread can work before you should kill it (assuming it will never finish). Default 600 seconds (10 minutes). ``threadpool_dying_limit``: The length of time after killing a thread that it should actually disappear. If it lives longer than this, it is considered a "zombie". Note that even in easy situations killing a thread can be very slow. Default 300 seconds (5 minutes). ``threadpool_spawn_if_under``: If there are no idle threads and a request comes in, and there are less than this number of *busy* threads, then add workers to the pool. Busy threads are threads that have taken less than ``threadpool_hung_thread_limit`` seconds so far. So if you get *lots* of requests but they complete in a reasonable amount of time, the requests will simply queue up (adding more threads probably wouldn't speed them up). But if you have lots of hung threads and one more request comes in, this will add workers to handle it. Default 5. ``threadpool_max_zombie_threads_before_die``: If there are more zombies than this, just kill the process. This is only good if you have a monitor that will automatically restart the server. This can clean up the mess. Default 0 (disabled). `threadpool_hung_check_period``: Every X requests, check for hung threads that need to be killed, or for zombie threads that should cause a restart. Default 100 requests. ``threadpool_logger``: Logging messages will go the logger named here. ``threadpool_error_email`` (or global ``error_email`` setting): When threads are killed or the process restarted, this email address will be contacted (using an SMTP server on localhost). """ if __name__ == '__main__': from paste.wsgilib import dump_environ #serve(dump_environ, ssl_pem="test.pem") serve(dump_environ, server_version="Wombles/1.0", protocol_version="HTTP/1.1", port="8888") PK-68*pLKpaste/reloader.pyc; #Gc@sfdZdkZdkZdkZdkZdklZddZdefdYZ e i Z dS(sx A file monitor and server restarter. Use this like: ..code-block:: Python import reloader reloader.install() Then make sure your server is installed with a shell script like:: err=3 while test "$err" -eq 3 ; do python server.py err="$?" done or is run from this .bat file (if you use Windows):: @echo off :repeat python server.py if %errorlevel% == 3 goto repeat or run a monitoring process in Python (``paster serve --reload`` does this). Use the watch_file(filename) function to cause a reload/restart for other other non-Python files (e.g., configuration files). N(sclassinstancemethodicCs?td|}tid|i}|it|i dS(s, Install the reloading monitor. On some platforms server threads may not terminate when the main thread does, causing ports to remain open/locked. The ``raise_keyboard_interrupt`` option creates a unignorable signal which causes the whole application to shut-down (rudely). s poll_intervalstargetN( sMonitors poll_intervalsmons threadingsThreadsperiodic_reloadsts setDaemonsTruesstart(s poll_intervalstsmon((s2build/bdist.darwin-8.0.1-x86/egg/paste/reloader.pysinstall(s  sMonitorcBsDtZgZgZdZdZdZdZeeZRS(NcCs<h|_t|_||_|i|_|ii|dS(N( sselfs module_mtimessTrues keep_runnings poll_intervalsglobal_extra_filess extra_filess instancessappend(sselfs poll_interval((s2build/bdist.darwin-8.0.1-x86/egg/paste/reloader.pys__init__;s     cCsCx<no4|i otidPnti|iq WdS(Nii(sselfs check_reloadsoss_exitstimessleeps poll_interval(sself((s2build/bdist.darwin-8.0.1-x86/egg/paste/reloader.pysperiodic_reloadBs  cCsR|i}xDtiiD]3}y|i|iWqt j o qqXqWx|D]}y-t i |}|o |i }nd}Wnttfj o qXnX|idot ii|d o#tt i |d i |}n|ii| o||i||} | ddjo| d} nt!i"|i| } n|} |i#|d| || |i$}t&|i'}d|i)|i*f}||||i+d}|t,j o|it|}n |i}|i-|gSdS(NsREQUEST_METHODs DisallowedshttpshttpssUnknown scheme for %r: %rsHTTP_is_s-shosts REMOTE_ADDRsx-forwarded-fors CONTENT_TYPEs content-typesCONTENT_LENGTHs wsgi.inputss PATH_INFOis/is%s %sscontent-length(.sselfsallowed_request_methodssenvironslowershttpexceptionssHTTPBadRequestsstart_responsesschemeshttplibsHTTPConnections ConnClasssHTTPSConnections ValueErrorsaddressshostsconnsheaderssitemsskeysvalues startswithsreplacessuppress_http_headerssgetsintslengthsreadsbodysurllibsquotes path_infospaths request_pathsurlparsesurljoinsrequests getresponsesress parse_headerssmsgs headers_outsstatussreasons getheadersNonesclose(sselfsenvironsstart_responsesstatuss ConnClasssconnsressbodys path_infoskeyspaths request_pathsvaluesheadersslengths headers_out((s/build/bdist.darwin-8.0.1-x86/egg/paste/proxy.pys__call__<sZ$             (s__name__s __module__s__init__s__call__(((s/build/bdist.darwin-8.0.1-x86/egg/paste/proxy.pysProxy-s scCs2t|}t|}t|d|d|SdS(s Make a WSGI application that proxies to another address: ``address`` the full URL ending with a trailing ``/`` ``allowed_request_methods``: a space seperated list of request methods (e.g., ``GET POST``) ``suppress_http_headers`` a space seperated list of http headers (lower case, without the leading ``http_``) that should not be passed on to target host sallowed_request_methodsssuppress_http_headersN(saslistsallowed_request_methodsssuppress_http_headerssProxysaddress(s global_confsaddresssallowed_request_methodsssuppress_http_headers((s/build/bdist.darwin-8.0.1-x86/egg/paste/proxy.pys make_proxyvs   sTransparentProxycBs/tZdZeddZdZdZRS(s$ A proxy that sends the request just as it was given, including respecting HTTP_HOST, wsgi.url_scheme, etc. This is a way of translating WSGI requests directly to real HTTP requests. All information goes in the environment; modify it to modify the way the request is made. If you specify ``force_host`` (and optionally ``force_scheme``) then HTTP_HOST won't be used to determine where to connect to; instead a specific host will be connected to, but the ``Host`` header in the request will remain intact. shttpcCs||_||_dS(N(s force_hostsselfs force_scheme(sselfs force_hosts force_scheme((s/build/bdist.darwin-8.0.1-x86/egg/paste/proxy.pys__init__s cCs0d|iitt||i|ifSdS(Ns%<%s %s force_host=%r force_scheme=%r>(sselfs __class__s__name__shexsids force_hosts force_scheme(sself((s/build/bdist.darwin-8.0.1-x86/egg/paste/proxy.pys__repr__scCs|d}|itjo |}n |i}|djo ti}n+|djo ti }nt d|d|jot dn|d} |itjo | }n |i}||}h}xT|iD]F\} } | ido*| diid d } | || %s %ss200 OKs content-types text/html(senvironsgets path_infos construct_urlsFalsesurlsUNICORNsdataslinksPONYsdecodesmsgsstart_responsesselfs application(sselfsenvironsstart_responsesurls path_infoslinksdatasmsg((s.build/bdist.darwin-8.0.1-x86/egg/paste/pony.pys__call__!s    (s__name__s __module__s__init__s__call__(((s.build/bdist.darwin-8.0.1-x86/egg/paste/pony.pysPonyMiddlewares cCst|SdS(s6 Adds pony power to any application, at /pony N(sPonyMiddlewaresapp(sapps global_conf((s.build/bdist.darwin-8.0.1-x86/egg/paste/pony.pys make_pony4sN(s__doc__s paste.requests construct_urlsPONYsUNICORNsobjectsPonyMiddlewares make_pony(sPONYs make_ponysPonyMiddlewaresUNICORNs construct_url((s.build/bdist.darwin-8.0.1-x86/egg/paste/pony.pys?s   PK;^W7MMpaste/registry.py# (c) 2005 Ben Bangert # This module is part of the Python Paste Project and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """Registry for handling request-local module globals sanely Dealing with module globals in a thread-safe way is good if your application is the sole responder in a thread, however that approach fails to properly account for various scenarios that occur with WSGI applications and middleware. What is actually needed in the case where a module global is desired that is always set properly depending on the current request, is a stacked thread-local object. Such an object is popped or pushed during the request cycle so that it properly represents the object that should be active for the current request. To make it easy to deal with such variables, this module provides a special StackedObjectProxy class which you can instantiate and attach to your module where you'd like others to access it. The object you'd like this to actually "be" during the request is then registered with the RegistryManager middleware, which ensures that for the scope of the current WSGI application everything will work properly. Example: .. code-block:: Python #yourpackage/__init__.py from paste.registry import RegistryManager, StackedObjectProxy myglobal = StackedObjectProxy() #wsgi app stack app = RegistryManager(yourapp) #inside your wsgi app class yourapp(object): def __call__(self, environ, start_response): obj = someobject # The request-local object you want to access # via yourpackage.myglobal if environ.has_key('paste.registry'): environ['paste.registry'].register(myglobal, obj) You will then be able to import yourpackage anywhere in your WSGI app or in the calling stack below it and be assured that it is using the object you registered with Registry. RegistryManager can be in the WSGI stack multiple times, each time it appears it registers a new request context. Performance =========== The overhead of the proxy object is very minimal, however if you are using proxy objects extensively (Thousands of accesses per request or more), there are some ways to avoid them. A proxy object runs approximately 3-20x slower than direct access to the object, this is rarely your performance bottleneck when developing web applications. Should you be developing a system which may be accessing the proxy object thousands of times per request, the performance of the proxy will start to become more noticeable. In that circumstance, the problem can be avoided by getting at the actual object via the proxy with the ``_current_obj`` function: .. code-block:: Python #sessions.py Session = StackedObjectProxy() # ... initialization code, etc. # somemodule.py import sessions def somefunc(): session = sessions.Session._current_obj() # ... tons of session access This way the proxy is used only once to retrieve the object for the current context and the overhead is minimized while still making it easy to access the underlying object. The ``_current_obj`` function is preceded by an underscore to more likely avoid clashing with the contained object's attributes. **NOTE:** This is *highly* unlikely to be an issue in the vast majority of cases, and requires incredibly large amounts of proxy object access before one should consider the proxy object to be causing slow-downs. This section is provided solely in the extremely rare case that it is an issue so that a quick way to work around it is documented. """ import sys import paste.util.threadinglocal as threadinglocal __all__ = ['StackedObjectProxy', 'RegistryManager', 'StackedObjectRestorer', 'restorer'] class NoDefault(object): pass class StackedObjectProxy(object): """Track an object instance internally using a stack The StackedObjectProxy proxies access to an object internally using a stacked thread-local. This makes it safe for complex WSGI environments where access to the object may be desired in multiple places without having to pass the actual object around. New objects are added to the top of the stack with _push_object while objects can be removed with _pop_object. """ def __init__(self, default=NoDefault, name="Default"): """Create a new StackedObjectProxy If a default is given, its used in every thread if no other object has been pushed on. """ self.__dict__['____name__'] = name self.__dict__['____local__'] = threadinglocal.local() if default is not NoDefault: self.__dict__['____default_object__'] = default def __getattr__(self, attr): return getattr(self._current_obj(), attr) def __setattr__(self, attr, value): setattr(self._current_obj(), attr, value) def __delattr__(self, name): delattr(self._current_obj(), name) def __getitem__(self, key): return self._current_obj()[key] def __setitem__(self, key, value): self._current_obj()[key] = value def __delitem__(self, key): del self._current_obj()[key] def __call__(self, *args, **kw): return self._current_obj()(*args, **kw) def __repr__(self): try: return repr(self._current_obj()) except (TypeError, AttributeError): return '<%s.%s object at 0x%x>' % (self.__class__.__module__, self.__class__.__name__, id(self)) def __iter__(self): return iter(self._current_obj()) def __len__(self): return len(self._current_obj()) def __contains__(self, key): return key in self._current_obj() def __nonzero__(self): return bool(self._current_obj()) def _current_obj(self): """Returns the current active object being proxied to In the event that no object was pushed, the default object if provided will be used. Otherwise, a TypeError will be raised. """ objects = getattr(self.____local__, 'objects', None) if objects: return objects[-1] else: obj = self.__dict__.get('____default_object__', NoDefault) if obj is not NoDefault: return obj else: raise TypeError( 'No object (name: %s) has been registered for this ' 'thread' % self.____name__) def _push_object(self, obj): """Make ``obj`` the active object for this thread-local. This should be used like: .. code-block:: Python obj = yourobject() module.glob = StackedObjectProxy() module.glob._push_object(obj) try: ... do stuff ... finally: module.glob._pop_object(conf) """ if not hasattr(self.____local__, 'objects'): self.____local__.objects = [] self.____local__.objects.append(obj) def _pop_object(self, obj=None): """Remove a thread-local object. If ``obj`` is given, it is checked against the popped object and an error is emitted if they don't match. """ if not hasattr(self.____local__, 'objects'): raise AssertionError('No object has been registered for this thread') popped = self.____local__.objects.pop() if obj: if popped is not obj: raise AssertionError( 'The object popped (%s) is not the same as the object ' 'expected (%s)' % (popped, obj)) def _object_stack(self): """Returns all of the objects stacked in this container (Might return [] if there are none) """ try: return self.____local__.objects[:] except AssertionError: return [] # The following methods will be swapped for their original versions by # StackedObjectRestorer when restoration is enabled. The original # functions (e.g. _current_obj) will be available at _current_obj_orig def _current_obj_restoration(self): request_id = restorer.in_restoration() if request_id: return restorer.get_saved_proxied_obj(self, request_id) return self._current_obj_orig() _current_obj_restoration.__doc__ = \ ('%s\n(StackedObjectRestorer restoration enabled)' % \ _current_obj.__doc__) def _push_object_restoration(self, obj): if not restorer.in_restoration(): self._push_object_orig(obj) _push_object_restoration.__doc__ = \ ('%s\n(StackedObjectRestorer restoration enabled)' % \ _push_object.__doc__) def _pop_object_restoration(self, obj=None): if not restorer.in_restoration(): self._pop_object_orig(obj) _pop_object_restoration.__doc__ = \ ('%s\n(StackedObjectRestorer restoration enabled)' % \ _pop_object.__doc__) class Registry(object): """Track objects and stacked object proxies for removal The Registry object is instantiated a single time for the request no matter how many times the RegistryManager is used in a WSGI stack. Each RegistryManager must call ``prepare`` before continuing the call to start a new context for object registering. Each context is tracked with a dict inside a list. The last list element is the currently executing context. Each context dict is keyed by the id of the StackedObjectProxy instance being proxied, the value is a tuple of the StackedObjectProxy instance and the object being tracked. """ def __init__(self): """Create a new Registry object ``prepare`` must still be called before this Registry object can be used to register objects. """ self.reglist = [] def prepare(self): """Used to create a new registry context Anytime a new RegistryManager is called, ``prepare`` needs to be called on the existing Registry object. This sets up a new context for registering objects. """ self.reglist.append({}) def register(self, stacked, obj): """Register an object with a StackedObjectProxy""" myreglist = self.reglist[-1] stacked_id = id(stacked) if stacked_id in myreglist: stacked._pop_object(myreglist[stacked_id][1]) del myreglist[stacked_id] stacked._push_object(obj) myreglist[stacked_id] = (stacked, obj) # Replace now does the same thing as register replace = register def cleanup(self): """Remove all objects from all StackedObjectProxy instances that were tracked at this Registry context""" for stacked, obj in self.reglist[-1].itervalues(): stacked._pop_object(obj) self.reglist.pop() class RegistryManager(object): """Creates and maintains a Registry context RegistryManager creates a new registry context for the registration of StackedObjectProxy instances. Multiple RegistryManager's can be in a WSGI stack and will manage the context so that the StackedObjectProxies always proxy to the proper object. The object being registered can be any object sub-class, list, or dict. Registering objects is done inside a WSGI application under the RegistryManager instance, using the ``environ['paste.registry']`` object which is a Registry instance. """ def __init__(self, application): self.application = application def __call__(self, environ, start_response): app_iter = None reg = environ.setdefault('paste.registry', Registry()) reg.prepare() try: app_iter = self.application(environ, start_response) except Exception, e: # Regardless of if the content is an iterable, generator, list # or tuple, we clean-up right now. If its an iterable/generator # care should be used to ensure the generator has its own ref # to the actual object if environ.get('paste.evalexception'): # EvalException is present in the WSGI stack expected = False for expect in environ.get('paste.expected_exceptions', []): if isinstance(e, expect): expected = True if not expected: # An unexpected exception: save state for EvalException restorer.save_registry_state(environ) reg.cleanup() raise except: # Save state for EvalException if it's present if environ.get('paste.evalexception'): restorer.save_registry_state(environ) reg.cleanup() raise else: reg.cleanup() return app_iter class StackedObjectRestorer(object): """Track StackedObjectProxies and their proxied objects for automatic restoration within EvalException's interactive debugger. An instance of this class tracks all StackedObjectProxy state in existence when unexpected exceptions are raised by WSGI applications housed by EvalException and RegistryManager. Like EvalException, this information is stored for the life of the process. When an unexpected exception occurs and EvalException is present in the WSGI stack, save_registry_state is intended to be called to store the Registry state and enable automatic restoration on all currently registered StackedObjectProxies. With restoration enabled, those StackedObjectProxies' _current_obj (overwritten by _current_obj_restoration) method's strategy is modified: it will return its appropriate proxied object from the restorer when a restoration context is active in the current thread. The StackedObjectProxies' _push/pop_object methods strategies are also changed: they no-op when a restoration context is active in the current thread (because the pushing/popping work is all handled by the Registry/restorer). The request's Registry objects' reglists are restored from the restorer when a restoration context begins, enabling the Registry methods to work while their changes are tracked by the restorer. The overhead of enabling restoration is negligible (another threadlocal access for the changed StackedObjectProxy methods) for normal use outside of a restoration context, but worth mentioning when combined with StackedObjectProxies normal overhead. Once enabled it does not turn off, however: o Enabling restoration only occurs after an unexpected exception is detected. The server is likely to be restarted shortly after the exception is raised to fix the cause o StackedObjectRestorer is only enabled when EvalException is enabled (not on a production server) and RegistryManager exists in the middleware stack""" def __init__(self): # Registries and their saved reglists by request_id self.saved_registry_states = {} self.restoration_context_id = threadinglocal.local() def save_registry_state(self, environ): """Save the state of this request's Registry (if it hasn't already been saved) to the saved_registry_states dict, keyed by the request's unique identifier""" registry = environ.get('paste.registry') if not registry or not len(registry.reglist) or \ self.get_request_id(environ) in self.saved_registry_states: # No Registry, no state to save, or this request's state has # already been saved return self.saved_registry_states[self.get_request_id(environ)] = \ (registry, registry.reglist[:]) # Tweak the StackedObjectProxies we want to save state for -- change # their methods to act differently when a restoration context is active # in the current thread for reglist in registry.reglist: for stacked, obj in reglist.itervalues(): self.enable_restoration(stacked) def get_saved_proxied_obj(self, stacked, request_id): """Retrieve the saved object proxied by the specified StackedObjectProxy for the request identified by request_id""" # All state for the request identified by request_id reglist = self.saved_registry_states[request_id][1] # The top of the stack was current when the exception occurred stack_level = len(reglist) - 1 stacked_id = id(stacked) while True: if stack_level < 0: # Nothing registered: Call _current_obj_orig to raise a # TypeError return stacked._current_obj_orig() context = reglist[stack_level] if stacked_id in context: break # This StackedObjectProxy may not have been registered by the # RegistryManager that was active when the exception was raised -- # continue searching down the stack until it's found stack_level -= 1 return context[stacked_id][1] def enable_restoration(self, stacked): """Replace the specified StackedObjectProxy's methods with their respective restoration versions. _current_obj_restoration forces recovery of the saved proxied object when a restoration context is active in the current thread. _push/pop_object_restoration avoid pushing/popping data (pushing/popping is only done at the Registry level) when a restoration context is active in the current thread""" if '_current_obj_orig' in stacked.__dict__: # Restoration already enabled return for func_name in ('_current_obj', '_push_object', '_pop_object'): orig_func = getattr(stacked, func_name) restoration_func = getattr(stacked, func_name + '_restoration') stacked.__dict__[func_name + '_orig'] = orig_func stacked.__dict__[func_name] = restoration_func def get_request_id(self, environ): """Return a unique identifier for the current request""" from paste.evalexception.middleware import get_debug_count return get_debug_count(environ) def restoration_begin(self, request_id): """Enable a restoration context in the current thread for the specified request_id""" if request_id in self.saved_registry_states: # Restore the old Registry object's state registry, reglist = self.saved_registry_states[request_id] registry.reglist = reglist self.restoration_context_id.request_id = request_id def restoration_end(self): """Register a restoration context as finished, if one exists""" try: del self.restoration_context_id.request_id except AttributeError: pass def in_restoration(self): """Determine if a restoration context is active for the current thread. Returns the request_id it's active for if so, otherwise False""" return getattr(self.restoration_context_id, 'request_id', False) restorer = StackedObjectRestorer() # Paste Deploy entry point def make_registry_manager(app, global_conf): return RegistryManager(app) make_registry_manager.__doc__ = RegistryManager.__doc__ PK;^W71Ypaste/config.py# (c) 2006 Ian Bicking, Philip Jenvey and contributors # Written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php """Paste Configuration Middleware and Objects""" from paste.registry import RegistryManager, StackedObjectProxy __all__ = ['DispatchingConfig', 'CONFIG', 'ConfigMiddleware'] class DispatchingConfig(StackedObjectProxy): """ This is a configuration object that can be used globally, imported, have references held onto. The configuration may differ by thread (or may not). Specific configurations are registered (and deregistered) either for the process or for threads. """ # @@: What should happen when someone tries to add this # configuration to itself? Probably the conf should become # resolved, and get rid of this delegation wrapper def __init__(self, name='DispatchingConfig'): super(DispatchingConfig, self).__init__(name=name) self.__dict__['_process_configs'] = [] def push_thread_config(self, conf): """ Make ``conf`` the active configuration for this thread. Thread-local configuration always overrides process-wide configuration. This should be used like:: conf = make_conf() dispatching_config.push_thread_config(conf) try: ... do stuff ... finally: dispatching_config.pop_thread_config(conf) """ self._push_object(conf) def pop_thread_config(self, conf=None): """ Remove a thread-local configuration. If ``conf`` is given, it is checked against the popped configuration and an error is emitted if they don't match. """ self._pop_object(conf) def push_process_config(self, conf): """ Like push_thread_config, but applies the configuration to the entire process. """ self._process_configs.append(conf) def pop_process_config(self, conf=None): self._pop_from(self._process_configs, conf) def _pop_from(self, lst, conf): popped = lst.pop() if conf is not None and popped is not conf: raise AssertionError( "The config popped (%s) is not the same as the config " "expected (%s)" % (popped, conf)) def _current_obj(self): try: return super(DispatchingConfig, self)._current_obj() except TypeError: if self._process_configs: return self._process_configs[-1] raise AttributeError( "No configuration has been registered for this process " "or thread") current = current_conf = _current_obj CONFIG = DispatchingConfig() no_config = object() class ConfigMiddleware(RegistryManager): """ A WSGI middleware that adds a ``paste.config`` key (by default) to the request environment, as well as registering the configuration temporarily (for the length of the request) with ``paste.config.CONFIG`` (or any other ``DispatchingConfig`` object). """ def __init__(self, application, config, dispatching_config=CONFIG, environ_key='paste.config'): """ This delegates all requests to `application`, adding a *copy* of the configuration `config`. """ def register_config(environ, start_response): popped_config = environ.get(environ_key, no_config) current_config = environ[environ_key] = config.copy() environ['paste.registry'].register(dispatching_config, current_config) try: app_iter = application(environ, start_response) finally: if popped_config is no_config: environ.pop(environ_key, None) else: environ[environ_key] = popped_config return app_iter super(self.__class__, self).__init__(register_config) def make_config_filter(app, global_conf, **local_conf): conf = global_conf.copy() conf.update(local_conf) return ConfigMiddleware(app, conf) make_config_middleware = ConfigMiddleware.__doc__ PK;^W7$++paste/session.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php """ Creates a session object in your WSGI environment. Use like: ..code-block:: Python environ['paste.session.factory']() This will return a dictionary. The contents of this dictionary will be saved to disk when the request is completed. The session will be created when you first fetch the session dictionary, and a cookie will be sent in that case. There's current no way to use sessions without cookies, and there's no way to delete a session except to clear its data. @@: This doesn't do any locking, and may cause problems when a single session is accessed concurrently. Also, it loads and saves the session for each request, with no caching. Also, sessions aren't expired. """ from Cookie import SimpleCookie import time import random import os import md5 import datetime import threading try: import cPickle except ImportError: import pickle as cPickle from paste import wsgilib from paste import request class SessionMiddleware(object): def __init__(self, application, global_conf=None, **factory_kw): self.application = application self.factory_kw = factory_kw def __call__(self, environ, start_response): session_factory = SessionFactory(environ, **self.factory_kw) environ['paste.session.factory'] = session_factory remember_headers = [] def session_start_response(status, headers, exc_info=None): if not session_factory.created: remember_headers[:] = [status, headers] return start_response(status, headers) headers.append(session_factory.set_cookie_header()) return start_response(status, headers, exc_info) app_iter = self.application(environ, session_start_response) def start(): if session_factory.created and remember_headers: # Tricky bastard used the session after start_response status, headers = remember_headers headers.append(session_factory.set_cookie_header()) exc = ValueError( "You cannot get the session after content from the " "app_iter has been returned") start_response(status, headers, (exc.__class__, exc, None)) def close(): if session_factory.used: session_factory.close() return wsgilib.add_start_close(app_iter, start, close) class SessionFactory(object): def __init__(self, environ, cookie_name='_SID_', session_class=None, session_expiration=60*12, # in minutes **session_class_kw): self.created = False self.used = False self.environ = environ self.cookie_name = cookie_name self.session = None self.session_class = session_class or FileSession self.session_class_kw = session_class_kw self.expiration = session_expiration def __call__(self): self.used = True if self.session is not None: return self.session.data() cookies = request.get_cookies(self.environ) session = None if cookies.has_key(self.cookie_name): self.sid = cookies[self.cookie_name].value try: session = self.session_class(self.sid, create=False, **self.session_class_kw) except KeyError: # Invalid SID pass if session is None: self.created = True self.sid = self.make_sid() session = self.session_class(self.sid, create=True, **self.session_class_kw) session.clean_up() self.session = session return session.data() def has_session(self): if self.session is not None: return True cookies = request.get_cookies(self.environ) if cookies.has_key(self.cookie_name): return True return False def make_sid(self): # @@: need better algorithm return (''.join(['%02d' % x for x in time.localtime(time.time())[:6]]) + '-' + self.unique_id()) def unique_id(self, for_object=None): """ Generates an opaque, identifier string that is practically guaranteed to be unique. If an object is passed, then its id() is incorporated into the generation. Relies on md5 and returns a 32 character long string. """ r = [time.time(), random.random(), os.times()] if for_object is not None: r.append(id(for_object)) md5_hash = md5.new(str(r)) try: return md5_hash.hexdigest() except AttributeError: # Older versions of Python didn't have hexdigest, so we'll # do it manually hexdigest = [] for char in md5_hash.digest(): hexdigest.append('%02x' % ord(char)) return ''.join(hexdigest) def set_cookie_header(self): c = SimpleCookie() c[self.cookie_name] = self.sid c[self.cookie_name]['path'] = '/' gmt_expiration_time = time.gmtime(time.time() + (self.expiration * 60)) c[self.cookie_name]['expires'] = time.strftime("%a, %d-%b-%Y %H:%M:%S GMT", gmt_expiration_time) name, value = str(c).split(': ', 1) return (name, value) def close(self): if self.session is not None: self.session.close() last_cleanup = None cleaning_up = False cleanup_cycle = datetime.timedelta(seconds=15*60) #15 min class FileSession(object): def __init__(self, sid, create=False, session_file_path='/tmp', chmod=None, expiration=2880, # in minutes: 48 hours ): if chmod and isinstance(chmod, basestring): chmod = int(chmod, 8) self.chmod = chmod if not sid: # Invalid... raise KeyError self.session_file_path = session_file_path self.sid = sid if not create: if not os.path.exists(self.filename()): raise KeyError self._data = None self.expiration = expiration def filename(self): return os.path.join(self.session_file_path, self.sid) def data(self): if self._data is not None: return self._data if os.path.exists(self.filename()): f = open(self.filename(), 'rb') self._data = cPickle.load(f) f.close() else: self._data = {} return self._data def close(self): if self._data is not None: filename = self.filename() exists = os.path.exists(filename) if not self._data: if exists: os.unlink(filename) else: f = open(filename, 'wb') cPickle.dump(self._data, f) f.close() if not exists and self.chmod: os.chmod(filename, self.chmod) def _clean_up(self): global cleaning_up try: exp_time = datetime.timedelta(seconds=self.expiration*60) now = datetime.datetime.now() #Open every session and check that it isn't too old for root, dirs, files in os.walk(self.session_file_path): for f in files: self._clean_up_file(f, exp_time=exp_time, now=now) finally: cleaning_up = False def _clean_up_file(self, f, exp_time, now): t = f.split("-") if len(t) != 2: return t = t[0] try: sess_time = datetime.datetime( int(t[0:4]), int(t[4:6]), int(t[6:8]), int(t[8:10]), int(t[10:12]), int(t[12:14])) except ValueError: # Probably not a session file at all return if sess_time + exp_time < now: os.remove(os.path.join(self.session_file_path, f)) def clean_up(self): global last_cleanup, cleanup_cycle, cleaning_up now = datetime.datetime.now() if cleaning_up: return if not last_cleanup or last_cleanup + cleanup_cycle < now: if not cleaning_up: cleaning_up = True try: last_cleanup = now t = threading.Thread(target=self._clean_up) t.start() except: # Normally _clean_up should set cleaning_up # to false, but if something goes wrong starting # it... cleaning_up = False raise class _NoDefault(object): def __repr__(self): return '' NoDefault = _NoDefault() def make_session_middleware( app, global_conf, session_expiration=NoDefault, expiration=NoDefault, cookie_name=NoDefault, session_file_path=NoDefault, chmod=NoDefault): """ Adds a middleware that handles sessions for your applications. The session is a peristent dictionary. To get this dictionary in your application, use ``environ['paste.session.factory']()`` which returns this persistent dictionary. Configuration: session_expiration: The time each session lives, in minutes. This controls the cookie expiration. Default 12 hours. expiration: The time each session lives on disk. Old sessions are culled from disk based on this. Default 48 hours. cookie_name: The cookie name used to track the session. Use different names to avoid session clashes. session_file_path: Sessions are put in this location, default /tmp. chmod: The octal chmod you want to apply to new sessions (e.g., 660 to make the sessions group readable/writable) Each of these also takes from the global configuration. cookie_name and chmod take from session_cookie_name and session_chmod """ if session_expiration is NoDefault: session_expiration = global_conf.get('session_expiration', 60*12) session_expiration = int(session_expiration) if expiration is NoDefault: expiration = global_conf.get('expiration', 60*48) expiration = int(expiration) if cookie_name is NoDefault: cookie_name = global_conf.get('session_cookie_name', '_SID_') if session_file_path is NoDefault: session_file_path = global_conf.get('session_file_path', '/tmp') if chmod is NoDefault: chmod = global_conf.get('session_chmod', None) return SessionMiddleware( app, session_expiration=session_expiration, expiration=expiration, cookie_name=cookie_name, session_file_path=session_file_path, chmod=chmod) PK-68uxxpaste/gzipper.pyo; #Gc@sdZdkZdklZlZdklZydklZWn e j odklZnXde fdYZ de fdYZ d e fd YZ d Zd d ZdS(s- WSGI middleware Gzip-encodes the response. N(s header_values remove_header(sCONTENT_LENGTH(sStringIOs GzipOutputcBstZRS(N(s__name__s __module__(((s1build/bdist.darwin-8.0.1-x86/egg/paste/gzipper.pys GzipOutputss middlewarecBstZddZdZRS(NicCs||_t||_dS(N(s applicationsselfsintscompress_level(sselfs applicationscompress_level((s1build/bdist.darwin-8.0.1-x86/egg/paste/gzipper.pys__init__s cCszd|iddjo|i||Snt||i}|i||i}|o|i |n|i SdS(NsgzipsHTTP_ACCEPT_ENCODINGs( senvironsgetsselfs applicationsstart_responses GzipResponsescompress_levelsresponsesgzip_start_responsesapp_itersfinish_responseswrite(sselfsenvironsstart_responsesapp_itersresponse((s1build/bdist.darwin-8.0.1-x86/egg/paste/gzipper.pys__call__s  (s__name__s __module__s__init__s__call__(((s1build/bdist.darwin-8.0.1-x86/egg/paste/gzipper.pys middlewares s GzipResponsecBs/tZdZedZdZdZRS(NcCs4||_||_t|_t|_t|_dS(N( sstart_responsesselfscompress_levelsStringIOsbuffersFalses compressiblesNonescontent_length(sselfsstart_responsescompress_level((s1build/bdist.darwin-8.0.1-x86/egg/paste/gzipper.pys__init__.s     cCs||_t|d}t|d}t|_|o*|idp |ido d|jo t|_n|o t|_n|io|i ddfnt |d||_||_ |i i SdS(Ns content-typescontent-encodingstext/s application/szipsgzipscontent-length(sheaderssselfs header_valuesctscesFalses compressibles startswithsTruesappends remove_headersstatussbufferswrite(sselfsstatussheaderssexc_infoscesct((s1build/bdist.darwin-8.0.1-x86/egg/paste/gzipper.pysgzip_start_response5s  4      cCs7|i}|id|i}|i|gSdS(Ni(sselfsbuffersoutsseeksgetvaluesssclose(sselfsssout((s1build/bdist.darwin-8.0.1-x86/egg/paste/gzipper.pyswriteFs     cCs|io(tiddd|id|i}n |i}z:x|D]}|i |qEW|io|i nWdt |do|i nX|ii }ti|i||i|i|idS(Nsmodeswbs compresslevelsfileobjsclose(sselfs compressiblesgzipsGzipFilescompress_levelsbuffersoutputsapp_iterssswritescloseshasattrstellscontent_lengthsCONTENT_LENGTHsupdatesheaderssstart_responsesstatus(sselfsapp_iterscontent_lengthsssoutput((s1build/bdist.darwin-8.0.1-x86/egg/paste/gzipper.pysfinish_responseMs    (s__name__s __module__s__init__sNonesgzip_start_responseswritesfinish_response(((s1build/bdist.darwin-8.0.1-x86/egg/paste/gzipper.pys GzipResponse,s   cKs-dk}|idtdd}|SdS(Ns=This function is deprecated; use make_gzip_middleware insteadicCst|SdS(N(s middlewares application(s application((s1build/bdist.darwin-8.0.1-x86/egg/paste/gzipper.pysfilterds(swarningsswarnsDeprecationWarningsfilter(s applicationsconfsfilterswarnings((s1build/bdist.darwin-8.0.1-x86/egg/paste/gzipper.pysfilter_factory_s     icCs t|}t|d|SdS(s Wrap the middleware, so that it applies gzipping to a response when it is supported by the browser and the content is of type ``text/*`` or ``application/*`` scompress_levelN(sintscompress_levels middlewaresapp(sapps global_confscompress_level((s1build/bdist.darwin-8.0.1-x86/egg/paste/gzipper.pysmake_gzip_middlewarehs (s__doc__sgzipspaste.responses header_values remove_headerspaste.httpheaderssCONTENT_LENGTHs cStringIOsStringIOs ImportErrorsobjects GzipOutputs middlewares GzipResponsesfilter_factorysmake_gzip_middleware( sCONTENT_LENGTHsStringIOs GzipOutputs middlewares remove_headersgzips header_valuesmake_gzip_middlewares GzipResponsesfilter_factory((s1build/bdist.darwin-8.0.1-x86/egg/paste/gzipper.pys? s  3 PK-68$^ n npaste/urlparser.pyo; #Gc@sdZdkZdkZdkZdkZy dkZWnej o eZnXdkl Z dkl Z dk l Z dkl Z dklZdk lZdefd YZd d d gZd efd YZdZeidedZeidedZdZdZeided efdYZedZd efdYZddZeeedZdS(sH WSGI applications that parse the URL and dispatch to on-disk resources N(srequest(sfileapp(s import_string(shttpexceptions(sETAG(s converterss NoDefaultcBstZRS(N(s__name__s __module__(((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys NoDefaultss URLParsersStaticURLParsersPkgResourcesParsercBstZdZhZeZhZeeeedZdZ dZ edZ dZ dZ dZdZeeZd Zd Zd ZRS( s WSGI middleware Application dispatching, based on URL. An instance of `URLParser` is an application that loads and delegates to other applications. It looks for files in its directory that match the first part of PATH_INFO; these may have an extension, but are not required to have one, in which case the available files are searched to find the appropriate file. If it is ambiguous, a 404 is returned and an error logged. By default there is a constructor for .py files that loads the module, and looks for an attribute ``application``, which is a ready application object, or an attribute that matches the module name, which is a factory for building applications, and is called with no arguments. URLParser will also look in __init__.py for special overrides. These overrides are: ``urlparser_hook(environ)`` This can modify the environment. Its return value is ignored, and it cannot be used to change the response in any way. You *can* use this, for example, to manipulate SCRIPT_NAME/PATH_INFO (try to keep them consistent with the original URL -- but consuming PATH_INFO and moving that to SCRIPT_NAME is ok). ``urlparser_wrap(environ, start_response, app)``: After URLParser finds the application, it calls this function (if present). If this function doesn't call ``app(environ, start_response)`` then the application won't be called at all! This can be used to allocate resources (with ``try:finally:``) or otherwise filter the output of the application. ``not_found_hook(environ, start_response)``: If no file can be found (*in this directory*) to match the request, then this WSGI application will be called. You can use this to change the URL and pass the request back to URLParser again, or on to some other application. This doesn't catch all ``404 Not Found`` responses, just missing files. ``application(environ, start_response)``: This basically overrides URLParser completely, and the given application is used for all requests. ``urlparser_wrap`` and ``urlparser_hook`` are still called, but the filesystem isn't searched in any way. c Ks|odk} | idtnh}tiidjo|itiid}n||_||_ |t jo"|i dddddf}nti||_ |t jo"|i d d d d d f}nti||_|t jo|i df}nti||_|ii|_|o|ii|nx|iD]\} } | id otd| | fn| tdi} t| t t!fot"i#| } n| |i| (sselfs __class__s__name__s directorysbase_python_nameshexsabssid(sself((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys__repr__Ps(s__name__s __module__s__doc__sparsers_by_directorys NoDefaults init_modulesglobal_constructorssNones__init__s__call__sfind_applications not_founds add_slashs find_filesget_applicationsregister_constructors classmethods get_parsersfind_init_modules__repr__(((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys URLParsers 26 0   #     cCsU|d}|o|dtii|7}ntii|}|i||SdS(Ns paste.urlparser.base_python_names.(senvironsbase_python_namesosspathsbasenamesfilenamesparsers get_parser(sparsersenvironsfilenamesbase_python_name((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pysmake_directoryWs  sdircCsti|SdS(N(sfileappsFileAppsfilename(sparsersenvironsfilename((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys make_unknownass*cCs`|d}tiitii|d}|o|d|}nt||||dSdS(Ns paste.urlparser.base_python_nameis.s wsgi.errors( senvironsbase_python_namesosspathssplitextsbasenamesfilenames module_namesload_module_from_name(senvironsfilenamesbase_python_names module_name((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys load_modulefs  " cCstii|oti|Sntiitii|d} tii |  osyt | d} WnBt tfj o0} |idtii|| ftSnX| id| int}tii|oti|Snd|joTdi|idd }|idd} t|tii|||}n|} t}zFti| tii|g\}}} ti|||| }Wd|tj o|inX|SdS(Ns __init__.pysws5Cannot write __init__.py file into directory %s (%s) s# s.i(!ssyssmodulesshas_keys module_namesosspathsjoinsdirnamesfilenames init_filenamesexistssopensfsOSErrorsIOErrorseserrorsswritesNonesclosesfpssplits parent_names base_namesload_module_from_namesenvironsparentsimps find_modulespathnamesstuffs load_modulesmodule(senvironsfilenames module_nameserrorssmodules parent_namespathnamesfpsparents init_filenameses base_namesfsstuff((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pysload_module_from_namens8!#   * cCst||}| otSnt|do|iot|id|iSn|ii dd}t||o>t||}t|do |i Sqt||Sn|di d||ftSdS(Ns applicationswsgi_applications.is wsgi.errorss'Cound not find application or %s in %s (s load_modulesenvironsfilenamesmodulesNoneshasattrs applicationsgetattrs__name__ssplits base_namesobjswsgi_applicationswrite(sparsersenvironsfilenamesobjs base_namesmodule((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pysmake_pys s.pycBsVtZdZeedZdZdZdZedZdZ dZ RS(s Like ``URLParser`` but only serves static files. ``cache_max_age``: integer specifies Cache-Control max_age in seconds cCstiidjo|itiid}n||_||_|tj otii|i|_n ||_||_ tiidjo:|idtii}|iidtii|_ndS(Ns/( sosspathsseps directorysreplacesselfsroot_directorysNonesnormpaths cache_max_age(sselfs directorysroot_directorys cache_max_age((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys__init__s     c CsN|idd} | o|i||Sn| djo d}nti|}t i i t i i |i |}t i idjo|idt i i}n|itj o|i|i o|i||Snt i i| o|i||Snt i i|oL|itj o|ip|i }|i|d|d|i||Sn|ido|iddjo|i||Sn|id}|oWt i|i} t| |jo.g}t!i"|| |d|dgSq n|i#|}|io|i%d |in|||SdS( Ns PATH_INFOss/s index.htmlsroot_directorys cache_max_agesHTTP_IF_NONE_MATCHs304 Not Modifiedsmax_age(&senvironsgets path_infosselfs add_slashsstart_responsesfilenamesrequests path_info_popsosspathsnormpathsjoins directorysfullssepsreplacesroot_directorysNones startswiths not_foundsexistssisdirs child_roots __class__s cache_max_ageserror_extra_paths if_none_matchsstatsst_mtimesmytimesstrsheaderssETAGsupdatesmake_appsfas cache_control( sselfsenvironsstart_responsesfulls if_none_matchs child_rootsfilenamesheaderssfas path_infosmytime((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys__call__s@  $$# &  cCsti|SdS(N(sfileappsFileAppsfilename(sselfsfilename((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pysmake_appscCs{ti|dt}|d7}|ido|d|d7}ntid|dd|fg}|i ||SdS( s^ This happens when you try to get to a directory without a trailing / swith_query_strings/s QUERY_STRINGs?sFThe resource has moved to %s - you should be redirected automatically.sheadersslocationN( srequests construct_urlsenvironsFalsesurlsgetshttpexceptionssHTTPMovedPermanentlysexcswsgi_applicationsstart_response(sselfsenvironsstart_responsesexcsurl((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys add_slashs  cCsbtidti|dd|id|id|i|pdf}|i ||SdS(Ns%The resource at %s could not be foundscomments6SCRIPT_NAME=%r; PATH_INFO=%r; looking in %r; debug: %ss SCRIPT_NAMEs PATH_INFOs(none)( shttpexceptionss HTTPNotFoundsrequests construct_urlsenvironsgetsselfs directorys debug_messagesexcswsgi_applicationsstart_response(sselfsenvironsstart_responses debug_messagesexc((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys not_founds8cCs+tid|d}|i||SdS(Ns#The trailing path %r is not alloweds PATH_INFO(shttpexceptionss HTTPNotFoundsenvironsexcswsgi_applicationsstart_response(sselfsenvironsstart_responsesexc((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pyserror_extra_pathscCsd|ii|ifSdS(Ns<%s %r>(sselfs __class__s__name__s directory(sself((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys__repr__s( s__name__s __module__s__doc__sNones__init__s__call__smake_apps add_slashs not_foundserror_extra_paths__repr__(((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pysStaticURLParsers  (   cCs1|tj ot|}nt|d|SdS(s Return a WSGI application that serves a directory (configured with document_root) cache_max_age - integer specifies CACHE_CONTROL max_age in seconds s cache_max_ageN(s cache_max_agesNonesintsStaticURLParsers document_root(s global_confs document_roots cache_max_age((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys make_static s cBs5tZeedZdZdZedZRS(NcCsttjotdnt|ttfoti||_ n ||_ ||_ |tjoti }n||_ |tjo |}ntii||_ dS(Ns"This class requires pkg_resources.(s pkg_resourcessNonesNotImplementedErrors isinstances egg_or_specsstrsunicodesget_distributionsselfseggs resource_namesmanagersResourceManagers root_resourcesosspathsnormpath(sselfs egg_or_specs resource_namesmanagers root_resource((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys__init__s       cCs$d|ii|ii|ifSdS(Ns<%s for %s:%r>(sselfs __class__s__name__seggs project_names resource_name(sself((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys__repr__&sc Cs|idd} | o|i||Sn| djo d}nti|}t i i |i d|}|itj o|i|i o|i||Sn|ii| o|i||Sn|ii|oO|itj o|ip|i }|i|i||id|||Sn|ido|iddjo|i||Snti|\}}| o d}ny|ii|i|} Wn>tt fj o,} t"i#d| }|i%||SnX|dd |fgt&i'| SdS( Ns PATH_INFOss/s index.htmls root_resourcesapplication/octet-streams,You are not permitted to view this file (%s)s200 OKs content-type((senvironsgets path_infosselfs add_slashsstart_responsesfilenamesrequests path_info_popsosspathsnormpaths resource_namesresources root_resourcesNones startswiths not_foundseggs has_resourcesresource_isdirs child_roots __class__smanagerserror_extra_paths mimetypess guess_typestypesencodingsget_resource_streamsfilesIOErrorsOSErrorseshttpexceptionss HTTPForbiddensexcswsgi_applicationsfileapps _FileIter( sselfsenvironsstart_responsesresourcesexcs child_rootstypesencodingsfilenames path_infosfilese((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys__call__,s8  $#& c Cshtidti|dd|id|id|i|i|pdf}|i ||SdS(Ns%The resource at %s could not be foundscomments=SCRIPT_NAME=%r; PATH_INFO=%r; looking in egg:%s#%r; debug: %ss SCRIPT_NAMEs PATH_INFOs(none)( shttpexceptionss HTTPNotFoundsrequests construct_urlsenvironsgetsselfseggs resource_names debug_messagesexcswsgi_applicationsstart_response(sselfsenvironsstart_responses debug_messagesexc((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys not_foundRs>(s__name__s __module__sNones__init__s__repr__s__call__s not_found(((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pysPkgResourcesParsers  &scCs.ttjotdnt||SdS(s A static file parser that loads data from an egg using ``pkg_resources``. Takes a configuration value ``egg``, which is an egg spec, and a base ``resource_name`` (default empty string) which is the path in the egg that this starts at. s%This function requires pkg_resources.N(s pkg_resourcessNonesNotImplementedErrorsPkgResourcesParserseggs resource_name(s global_confseggs resource_name((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pysmake_pkg_resources[s c Ks|tjo"|idddddf}nti|}|tjo|idddd f}nti|}|tjo|id f}nti|}th||d|d|d ||Sd S( s Create a URLParser application that looks in ``directory``, which should be the directory for the Python package named in ``base_python_name``. ``index_names`` are used when viewing the directory (like ``'index'`` for ``'index.html'``). ``hide_extensions`` are extensions that are not viewable (like ``'.pyc'``) and ``ignore_extensions`` are viewable but only if an explicit extension is given. s index_namessindexsIndexsmainsMainshide_extensionss.pycsbakspy~signore_extensionsN( s index_namessNones global_confsgets converterssaslistshide_extensionssignore_extensionss URLParsers directorysbase_python_namesconstructor_conf(s global_confs directorysbase_python_names index_namesshide_extensionssignore_extensionssconstructor_conf((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pysmake_url_parserfs  "   ( s__doc__sosssyssimps mimetypess pkg_resourcess ImportErrorsNonespastesrequestsfileapps paste.utils import_stringshttpexceptionss httpheaderssETAGs converterssobjects NoDefaults__all__s URLParsersmake_directorysregister_constructors make_unknowns load_modulesload_module_from_namesmake_pysStaticURLParsers make_staticsPkgResourcesParsersmake_pkg_resourcessmake_url_parser(s make_unknownsload_module_from_names URLParsers make_staticsmake_url_parsersmake_pkg_resourcess__all__sfileapps load_modulesimpshttpexceptionss converterss NoDefaults mimetypesssyssmake_pysStaticURLParsersmake_directorysPkgResourcesParsersrequests pkg_resourcess import_stringsETAGsos((s3build/bdist.darwin-8.0.1-x86/egg/paste/urlparser.pys?s>            =    " d F PK-68kR]]paste/registry.pyo; #Gc@sdZdkZdkiiZddddgZdefdYZdefdYZd efd YZ defd YZ defd YZ e Z d Z e ie _dS(s Registry for handling request-local module globals sanely Dealing with module globals in a thread-safe way is good if your application is the sole responder in a thread, however that approach fails to properly account for various scenarios that occur with WSGI applications and middleware. What is actually needed in the case where a module global is desired that is always set properly depending on the current request, is a stacked thread-local object. Such an object is popped or pushed during the request cycle so that it properly represents the object that should be active for the current request. To make it easy to deal with such variables, this module provides a special StackedObjectProxy class which you can instantiate and attach to your module where you'd like others to access it. The object you'd like this to actually "be" during the request is then registered with the RegistryManager middleware, which ensures that for the scope of the current WSGI application everything will work properly. Example: .. code-block:: Python #yourpackage/__init__.py from paste.registry import RegistryManager, StackedObjectProxy myglobal = StackedObjectProxy() #wsgi app stack app = RegistryManager(yourapp) #inside your wsgi app class yourapp(object): def __call__(self, environ, start_response): obj = someobject # The request-local object you want to access # via yourpackage.myglobal if environ.has_key('paste.registry'): environ['paste.registry'].register(myglobal, obj) You will then be able to import yourpackage anywhere in your WSGI app or in the calling stack below it and be assured that it is using the object you registered with Registry. RegistryManager can be in the WSGI stack multiple times, each time it appears it registers a new request context. Performance =========== The overhead of the proxy object is very minimal, however if you are using proxy objects extensively (Thousands of accesses per request or more), there are some ways to avoid them. A proxy object runs approximately 3-20x slower than direct access to the object, this is rarely your performance bottleneck when developing web applications. Should you be developing a system which may be accessing the proxy object thousands of times per request, the performance of the proxy will start to become more noticeable. In that circumstance, the problem can be avoided by getting at the actual object via the proxy with the ``_current_obj`` function: .. code-block:: Python #sessions.py Session = StackedObjectProxy() # ... initialization code, etc. # somemodule.py import sessions def somefunc(): session = sessions.Session._current_obj() # ... tons of session access This way the proxy is used only once to retrieve the object for the current context and the overhead is minimized while still making it easy to access the underlying object. The ``_current_obj`` function is preceded by an underscore to more likely avoid clashing with the contained object's attributes. **NOTE:** This is *highly* unlikely to be an issue in the vast majority of cases, and requires incredibly large amounts of proxy object access before one should consider the proxy object to be causing slow-downs. This section is provided solely in the extremely rare case that it is an issue so that a quick way to work around it is documented. NsStackedObjectProxysRegistryManagersStackedObjectRestorersrestorers NoDefaultcBstZRS(N(s__name__s __module__(((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys NoDefaultbscBstZdZeddZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZedZdZdZdeie_dZdeie_edZdeie_RS(sTrack an object instance internally using a stack The StackedObjectProxy proxies access to an object internally using a stacked thread-local. This makes it safe for complex WSGI environments where access to the object may be desired in multiple places without having to pass the actual object around. New objects are added to the top of the stack with _push_object while objects can be removed with _pop_object. sDefaultcCsB||id( sreprsselfs _current_objs TypeErrorsAttributeErrors __class__s __module__s__name__sid(sself((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys__repr__scCst|iSdS(N(sitersselfs _current_obj(sself((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys__iter__scCst|iSdS(N(slensselfs _current_obj(sself((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys__len__scCs||ijSdS(N(skeysselfs _current_obj(sselfskey((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys __contains__scCst|iSdS(N(sboolsselfs _current_obj(sself((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys __nonzero__scCsit|idt}|o |dSn>|iidt}|tj o|Snt d|i dS(sReturns the current active object being proxied to In the event that no object was pushed, the default object if provided will be used. Otherwise, a TypeError will be raised. sobjectsis____default_object__s8No object (name: %s) has been registered for this threadN( sgetattrsselfs ____local__sNonesobjectss__dict__sgets NoDefaultsobjs TypeErrors ____name__(sselfsobjsobjects((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys _current_objs  cCs;t|id og|i_n|iii|dS(sMake ``obj`` the active object for this thread-local. This should be used like: .. code-block:: Python obj = yourobject() module.glob = StackedObjectProxy() module.glob._push_object(obj) try: ... do stuff ... finally: module.glob._pop_object(conf) sobjectsN(shasattrsselfs ____local__sobjectssappendsobj(sselfsobj((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys _push_objectscCslt|id otdn|iii}|o+||j otd||fqhndS(sRemove a thread-local object. If ``obj`` is given, it is checked against the popped object and an error is emitted if they don't match. sobjectss-No object has been registered for this threadsBThe object popped (%s) is not the same as the object expected (%s)N(shasattrsselfs ____local__sAssertionErrorsobjectsspopspoppedsobj(sselfsobjspopped((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys _pop_objects cCs-y|iiSWntj o gSnXdS(sjReturns all of the objects stacked in this container (Might return [] if there are none) N(sselfs ____local__sobjectssAssertionError(sself((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys _object_stacks cCs5ti}|oti||Sn|iSdS(N(srestorersin_restorations request_idsget_saved_proxied_objsselfs_current_obj_orig(sselfs request_id((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys_current_obj_restorations s.%s (StackedObjectRestorer restoration enabled)cCs#ti o|i|ndS(N(srestorersin_restorationsselfs_push_object_origsobj(sselfsobj((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys_push_object_restorationscCs#ti o|i|ndS(N(srestorersin_restorationsselfs_pop_object_origsobj(sselfsobj((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys_pop_object_restorations(s__name__s __module__s__doc__s NoDefaults__init__s __getattr__s __setattr__s __delattr__s __getitem__s __setitem__s __delitem__s__call__s__repr__s__iter__s__len__s __contains__s __nonzero__s _current_objs _push_objectsNones _pop_objects _object_stacks_current_obj_restorations_push_object_restorations_pop_object_restoration(((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pysStackedObjectProxyds0                    sRegistrycBs8tZdZdZdZdZeZdZRS(sTrack objects and stacked object proxies for removal The Registry object is instantiated a single time for the request no matter how many times the RegistryManager is used in a WSGI stack. Each RegistryManager must call ``prepare`` before continuing the call to start a new context for object registering. Each context is tracked with a dict inside a list. The last list element is the currently executing context. Each context dict is keyed by the id of the StackedObjectProxy instance being proxied, the value is a tuple of the StackedObjectProxy instance and the object being tracked. cCs g|_dS(sCreate a new Registry object ``prepare`` must still be called before this Registry object can be used to register objects. N(sselfsreglist(sself((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pys__init__scCs|iihdS(sUsed to create a new registry context Anytime a new RegistryManager is called, ``prepare`` needs to be called on the existing Registry object. This sets up a new context for registering objects. N(sselfsreglistsappend(sself((s2build/bdist.darwin-8.0.1-x86/egg/paste/registry.pyspreparescCsg|id}t|}||jo |i||d||=n|i|||f||Z<e8d?Z=d@Z>dS(As Routines for testing WSGI applications. Most interesting is the `TestApp `_ for testing WSGI applications, and the `TestFileEnvironment `_ class for testing the effects of command-line scripts. N(s SimpleCookie(sStringIO(s subprocess24(swsgilib(slint(s HeaderDictcGsti|SdS(s An os.tempnam with the warning turned off, because sometimes you just need to use this and don't care about the stupid security warning. N(sosstempnamsargs(sargs((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pystempnam_no_warning'ss NoDefaultcBstZRS(N(s__name__s __module__(((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pys NoDefault/scCst|}|i|SdS(N(slistslssort(sl((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pyssorted2s  s Dummy_smtplibcBsGtZeZdZdZdZdZeeZdZ RS(NcCsSdk}|idtd|i p td||_t|_||i _dS(Ns1Dummy_smtplib is not maintained and is deprecatedisIsmtplib.SMTP() called again before Dummy_smtplib.existing.reset() called.( swarningsswarnsDeprecationWarningsselfsexistingsAssertionErrorsserversTruesopens __class__(sselfsserverswarnings((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pys__init__;s     cCs%|iptd|t|_dS(NsCalled %s.quit() twice(sselfsopensAssertionErrorsFalse(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pysquitGscCs||_||_||_dS(N(s from_addresssselfs to_addressessmsgsmessage(sselfs from_addresss to_addressessmsg((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pyssendmailLs  cCs |t_dS(N(sclsssmtplibsSMTP(scls((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pysinstallQscCs%|i p tdt|i_dS(NsSMTP connection not quit(sselfsopensAssertionErrorsNones __class__sexisting(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pysresetVs( s__name__s __module__sNonesexistings__init__squitssendmailsinstalls classmethodsreset(((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pys Dummy_smtplib7s    sAppErrorcBstZRS(N(s__name__s __module__(((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pysAppError[ssTestAppcBstZeZeeeeedZdZdZeeeeedZ deeeeedZ deeeeedZ deeeeedZ deeeed Z d Zd Zd Zd ZdZdZdZRS(NcCst|ttfo#dkl}||d|}n||_||_||_|t jo h}n||_ ||_ ||_ |i dS(s} Wraps a WSGI application in a more convenient interface for testing. ``app`` may be an application, or a Paste Deploy app URI, like ``'config:filename.ini#test'``. ``namespace`` is a dictionary that will be written to (if provided). This can be used with doctest or some other system, and the variable ``res`` will be assigned everytime you make a request (instead of returning the request). ``relative_to`` is a directory, and filenames used for file uploads are calculated relative to this. Also ``config:`` URIs that aren't absolute. ``extra_environ`` is a dictionary of values that should go into the environment for each request. These can provide a communication channel with the application. ``pre_request_hook`` is a function to be called prior to making requests (such as ``post`` or ``get``). This function must take one argument (the instance of the TestApp). ``post_request_hook`` is a function, similar to ``pre_request_hook``, to be called after requests are made. (sloadapps relative_toN(s isinstancesappsstrsunicodes paste.deploysloadapps relative_tosselfs namespaces extra_environsNonespre_request_hookspost_request_hooksreset(sselfsapps namespaces relative_tos extra_environspre_request_hookspost_request_hooksloadapp((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pys__init__cs         cCs h|_dS(sc Resets the state of the application; currently just clears saved cookies. N(sselfscookies(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pysresetscCs!|ii}t|d<|SdS(Nspaste.throw_errors(sselfs extra_environscopysenvironsTrue(sselfsenviron((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pys _make_environs c Cs|tjo h}nt}|oct|ttf oti |dt}nd|jo|d7}n |d7}||7}n|i } t|}d|jo |idd\}| d`_ sdoseqs?s&is QUERY_STRINGssstatusN(s extra_environsNonesTrues__tracebackhide__sparamss isinstancesstrsunicodesurllibs urlencodesurlsselfs _make_environsenvironssplits _set_headerssheaderssupdates TestRequests expect_errorssreqs do_requestsstatus( sselfsurlsparamssheaderss extra_environsstatuss expect_errorssreqs__tracebackhide__senviron((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pysgets(          sc Csp|tjo h}n|tjo h}n|i} t|tt t fot i |}n|o;ti|dt}|i||\} }| | d`_ sPOSTsparamssheaderss extra_environsstatuss upload_filess expect_errorsN( sselfs _gen_requestsurlsparamssheaderss extra_environsstatuss upload_filess expect_errors(sselfsurlsparamssheaderss extra_environsstatuss upload_filess expect_errors((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pysposts  cCs8|id|d|d|d|d|d|d|SdS( s Do a PUT request. Very like the ``.get()`` method. ``params`` are put in the body of the request. ``upload_files`` is for file uploads. It should be a list of ``[(fieldname, filename, file_content)]``. You can also use just ``[(fieldname, filename)]`` and the file content will be read from disk. Returns a `response object `_ sPUTsparamssheaderss extra_environsstatuss upload_filess expect_errorsN( sselfs _gen_requestsurlsparamssheaderss extra_environsstatuss upload_filess expect_errors(sselfsurlsparamssheaderss extra_environsstatuss upload_filess expect_errors((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pysputs  cCs8|id|d|d|d|d|dtd|SdS( s Do a DELETE request. Very like the ``.get()`` method. ``params`` are put in the body of the request. Returns a `response object `_ sDELETEsparamssheaderss extra_environsstatuss upload_filess expect_errorsN( sselfs _gen_requestsurlsparamssheaderss extra_environsstatussNones expect_errors(sselfsurlsparamssheaderss extra_environsstatuss expect_errors((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pysdeletes cCs| odSnxz|iD]l\}}|idjo d}n:|idjo d}nd|iddi}|||td|idi t t ||i i |ifndSn|tjoQ|idjo |idjodSntd|i|i i |ifn||ijotd|i|fndS(Ns*s*Bad response: %s (not one of %s for %s) %ss, iis7Bad response: %s (not 200 OK or 3xx redirect for %s) %ssBad response: %s (not %s)(sTrues__tracebackhide__sstatuss isinstancesliststuplesressAppErrors full_statussjoinsmapsstrsrequestsurlsbodysNone(sselfsstatussress__tracebackhide__((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pys _check_statuss >  )cCs%|iotd|indS(Ns!Application had errors logged: %s(sresserrorssAppError(sselfsres((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pys _check_errorss cCs/|\}}}}t||||||SdS(N(sstatussheaderssbodyserrorss TestResponsesselfs total_time(sselfs.2s total_timesstatussheaderssbodyserrors((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pys_make_responses(s__name__s __module__sTruesdisabledsNones__init__sresets _make_environsFalsesgets _gen_requestspostsputsdeletes _set_headerssencode_multiparts_get_file_infos do_requests _check_statuss _check_errorss_make_response(((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pysTestApp^s -  7     ;  s CaptureStdoutcBs5tZdZdZdZdZdZRS(NcCst|_||_dS(N(sStringIOsselfscapturedsactual(sselfsactual((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pys__init__s cCs$|ii||ii|dS(N(sselfscapturedswritesssactual(sselfss((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pyswritescCs|iidS(N(sselfsactualsflush(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pysflushscCs"x|D]}|i|qWdS(N(slinessitemsselfswrite(sselfslinessitem((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pys writelinesscCs|iiSdS(N(sselfscapturedsgetvalue(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pysgetvalues(s__name__s __module__s__init__swritesflushs writelinessgetvalue(((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pys CaptureStdouts     s TestResponsecBs2tZeZdZdZeeddZdZeeddZ e i de i e i BZdZed Zd Zd Zeeeeeed Zeeeeeed ZdZddZe i dZdZeeddZdZdZdZdZ dZ!RS(NcCsz||_t|id|_||_||_ti|i|_ ||_ ||_ t |_ ||_t |_dS(Ni(stest_appsselfsintsstatusssplits full_statussheaderss HeaderDictsfromlists header_dictsbodyserrorssNones _normal_bodys total_timestimes_forms_indexed(sselfstest_appsstatussheaderssbodyserrorss total_time((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pys__init__s       cCs)|itjo|in|iSdS(s Returns a dictionary of ``Form`` objects. Indexes are both in order (from zero) and by form id (if the form is given an id). N(sselfs_forms_indexedsNones _parse_forms(sself((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pys forms__getssdocs A list of
s found on the page (instances of `Form `_) cCsJ|i}| otdnd|jotdn|dSdS(Ns*You used response.form, but no forms existis5You used response.form, but more than one form existsi(sselfsformss TypeError(sselfsforms((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pys form__gets   s Returns a single `Form `_ instance; it is an error if there are multiple forms on the page. s<(/?)([:a-z0-9_\-]*)(.*?)>c CsZh}|_g}t}x|ii|iD]} | i ddj}| i di }|djoq/n|oB|ptd| i|i|i|| i !t}q/| ptd| i| i}q/W| ptd|i|xNt|D]@\}}t||}|||<|io|||i unexpected at %ssNested form tags at %ssDanging form: %r(sformssselfs_forms_indexeds form_textssNonesstarteds_tag_resfinditersbodysmatchsgroupsendslowerstagsAssertionErrorsstartsappends enumeratesistextsFormsformsid( sselfsendsformsstartedstextsformssistags form_textssmatch((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pys _parse_formss,      c Cst}xY|iD]N\}}|i|ijo)| ptd|||f|}qqW|tjob|t joMt d|di gi }|iD]\}}||q~fq|Sn|SdS(s Returns the named header; an error if there is not exactly one matching header (unless you give a default -- always an error if there is more than one header) s&Ambiguous header: %s matches %r and %rsNo header found: %r (from %s)s, N(sNonesfoundsselfsheadersscur_namesvalueslowersnamesAssertionErrorsdefaults NoDefaultsKeyErrorsjoinsappends_[1]snsv( sselfsnamesdefaultscur_namesvaluesns_[1]svsfound((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pysheader+s   McCsRg}xA|iD]6\}}|i|ijo|i|qqW|SdS(sE Gets all headers by the ``name``, returns as a list N(sfoundsselfsheadersscur_namesvalueslowersnamesappend(sselfsnamesfoundscur_namesvalue((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pys all_headersAs cKs|idjo |idjptd|i|id}ti|\}}ti |\}}|i i||SdS(s If this request is a redirect, follow that redirect. It is an error if this is not a redirect response. Returns another response object. i,is/You can only follow redirect responses (not %s)slocationN(sselfsstatussAssertionErrors full_statussheaderslocationsurllibs splittypestypesrests splithostshostspathstest_appsgetskw(sselfskwsrestshostslocationspathstype((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pysfollowKs 1c Csft} |idddddtd|d|d|d |d |d | \}}} |i| d Sd S(s Click the link as described. Each of ``description``, ``linkid``, and ``url`` are *patterns*, meaning that they are either strings (regular expressions), compiled regular expressions (objects with a ``search`` method), or callables returning true or false. All the given patterns are ANDed together: * ``description`` is a pattern that matches the contents of the anchor (HTML and all -- everything between ```` and ````) * ``linkid`` is a pattern that matches the ``id`` attribute of the anchor. It will receive the empty string if no id is given. * ``href`` is a pattern that matches the ``href`` of the anchor; the literal content of that attribute, not the fully qualified attribute. * ``anchor`` is a pattern that matches the entire anchor, with its contents. If more than one link matches, then the ``index`` link is followed. If ``index`` is not given and more than one link matches, or if no link matches, then ``IndexError`` will be raised. If you give ``verbose`` then messages will be printed about each link, and why it does or doesn't match. If you use ``app.click(verbose=True)`` you'll see a list of all the links. You can use multiple criteria to essentially assert multiple aspects about the link, e.g., where the link's destination is. stagsas href_attrshrefs href_extractscontentsids href_patterns html_patternsindexsverbosesuriN(sTrues__tracebackhide__sselfs _find_elementsNones descriptionslinkidshrefsanchorsindexsverboses found_htmls found_descs found_attrssgoto( sselfs descriptionslinkidshrefsanchorsindexsverboses found_htmls found_descs__tracebackhide__s found_attrs((s1build/bdist.darwin-8.0.1-x86/egg/paste/fixture.pysclickZs&c Csot} |idddddtidd|d|d |d |d |d | \}}} |i| d SdS(s Like ``.click()``, except looks for link-like buttons. This kind of button should look like ``
(srequests construct_urlsenvironsurlsNone(senvironsurl((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pysmake_repost_button s  cCsdhd|<SdS(Ns~
stbid(stbid(stbids debug_info((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys input_form*ssE Server Error %(head_html)s %(repost_button)s %(body)s cCs7|tjo|idd}nt|d|SdS(s Wraps the application in an interactive debugger. This debugger is a major security hole, and should only be used during development. xmlhttp_key is a string that, if present in QUERY_STRING, indicates that the request is an XMLHttp request, and the Javascript/interactive debugger should not be returned. (If you try to put the debugger somewhere with innerHTML, you will often crash the browser) s xmlhttp_keys_N(s xmlhttp_keysNones global_confsgets EvalExceptionsapp(sapps global_confs xmlhttp_key((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pysmake_eval_exceptionSs  (/s__doc__ssyssosscgis tracebacks cStringIOsStringIOspprints itertoolsstimesrespaste.exceptionsserrormiddlewares formatters collectorspasteswsgilibs urlparsershttpexceptionssregistrysrequestsresponses evalcontextslimits html_quotesTruespreserve_whitespaces _repl_nbsps simplecatcherswsgiappsget_debug_infoscountsints debug_countersget_debug_countsobjects EvalExceptions DebugInfos HTMLFormattersEvalHTMLFormatters make_tablesformat_eval_htmlsmake_repost_buttons input_formserror_templatesNonesmake_eval_exception(%s simplecatchers debug_counterswsgiappsmake_eval_exceptionspreserve_whitespacesmake_repost_buttons input_forms collectors evalcontextswsgilibspprintserror_templatesres DebugInfosget_debug_counts formattershttpexceptionsscgisformat_eval_htmlsEvalHTMLFormatterssyssregistrys _repl_nbspsresponseserrormiddlewaresStringIOsoss EvalExceptions tracebacksrequestsget_debug_infos make_tables itertoolss urlparserslimitstimes html_quote((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys?sF                     "  E ! *  PK-68kYDD paste/evalexception/__init__.pyo; !Gc@sdZdklZdS(s0 An exception handler for interactive debugging (s EvalExceptionN(s__doc__spaste.evalexception.middlewares EvalException(s EvalException((s@build/bdist.darwin-8.0.1-x86/egg/paste/evalexception/__init__.pys?sPK-68CȤƏll"paste/evalexception/middleware.pyc; !Gc@sdZdkZdkZdkZdkZdklZdkZdkZdk Z dk Z dk l Z l Z lZdklZdklZdklZdklZdklZd klZdkZd Zd Zed Zd ZdZdZdZeie e i Z!dZ"de#fdYZ$de#fdYZ%de i&fdYZ'dZ(dZ)dZ*dZ+dZ,e-dZ.dS(s Exception-catching middleware that allows interactive debugging. This middleware catches all unexpected exceptions. A normal traceback, like produced by ``paste.exceptions.errormiddleware.ErrorMiddleware`` is given, plus controls to see local variables and evaluate expressions in a local context. This can only be used in single-process environments, because subsequent requests must go back to the same process that the exception originally occurred in. Threaded or non-concurrent environments both work. This shouldn't be used in production in any way. That would just be silly. If calling from an XMLHttpRequest call, if the GET variable ``_`` is given then it will make the response more compact (and less Javascripty), since if you use innerHTML it'll kill your browser. You can look for the header X-Debug-URL in your 500 responses if you want to see the full debuggable traceback. Also, this URL is printed to ``wsgi.errors``, so you can open it up in another browser window. N(sStringIO(serrormiddlewares formatters collector(swsgilib(s urlparser(shttpexceptions(sregistry(srequest(sresponseicCs/|tjodSntit|dSdS(s; Escape HTML characters, plus translate None to '' siN(svsNonescgisescapesstr(sv((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys html_quote/s cCst|ot|}n|idd}tidt|}tidt|}tidt|}d|SdS(s Quote a value for HTML, preserving whitespace (translating newlines to ``
`` and multiple spaces to use `` ``). If ``quote`` is true, then the value will be HTML quoted first. s s
s()( +)s(\n)( +)s^()( +)s%sN(squotes html_quotesvsreplacesressubs _repl_nbsp(svsquote((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pyspreserve_whitespace7scCsTt|iddjodSn|iddt|idddSdS(Niis s (slensmatchsgroup(smatch((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys _repl_nbspFscsd}|SdS(s\ A simple middleware that catches errors and turns them into simple tracebacks. csty||SWn\t}tid||dddfgti|i }dt |gSnXdS(Nsfiles500 Server Errors content-types text/htmls

Error

%s
( s applicationsenvironsstart_responsesStringIOsouts tracebacks print_excssyssexc_infosgetvaluesress html_quote(senvironsstart_responsesressout(s application(sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pyssimplecatcher_appPs    N(ssimplecatcher_app(s applicationssimplecatcher_app((s applicationsBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys simplecatcherKs cCsd}|SdS(s= Turns a function or method into a WSGI application. csd}t|_|SdS(Ncstdjo%d}d}dgn\}}gd}ti|}t|}|||SdS(Niiiicsti|dt}tihdd<dd<}||d<||d<|i }|i d}|||i|gSdS(Nsinclude_get_varss content-types text/htmlsstatuss200 OKsenvironsheaders(swsgilibsparse_formvarssenvironsTruesformsresponses HeaderDictsheaderssfuncsargssmixedsresspopsstatussstart_responses headeritems(senvironsstart_responsesstatussformsheaderssres(sargssfunc(sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys applicationms  !  ( slensargssenvironsstart_responses applicationshttpexceptionssmake_middlewaresapps simplecatcher(sargssstart_responsesapps applicationsenviron(sfunc(sargssBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pyswsgiapp_wrappercs     (swsgiapp_wrappersTruesexposed(sfuncswsgiapp_wrapper((sfuncsBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys decoratorbs  N(s decorator(s decorator((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pyswsgiapp^s csd}|SdS(s A decorator (meant to be used under ``wsgiapp()``) that resolves the ``debugcount`` variable to a ``DebugInfo`` object (or gives an error if it can't be found). c syd|jotdn|id}yt|}Wntj otdnX||ijotd|n|i|}|d||SWn1tj o%}d|ddThere was an error: %s( sforms ValueErrorspops debugcountsintsselfs debug_infoss debug_infosfuncses html_quote(sselfsforms debugcountses debug_info(sfunc(sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pysdebug_info_replacements  N(sdebug_info_replacement(sfuncsdebug_info_replacement((sfuncsBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pysget_debug_infos cCs5d|jo |dSnti|d<}|SdS(s? Return the unique debug count for the current request spaste.evalexception.debug_countN(senvirons debug_countersnext(senvironsnext((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pysget_debug_counts   s EvalExceptioncBstZeedZdZdZdZee_dZ ee _dZ ee _dZ ee _dZ d Z eee Z d ZeeeZd Zd ZRS( NcCsY||_h|_|tjo-|tjo d}qL|idd}n||_dS(Ns_s xmlhttp_key(s applicationsselfs debug_infoss xmlhttp_keysNones global_confsget(sselfs applications global_confs xmlhttp_key((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys__init__s     cCsd|d p td||d<|iddido|i||Sn|i||SdS(Nswsgi.multiprocesssIThe EvalException middleware is not usable in a multi-process environmentspaste.evalexceptions PATH_INFOss/_debug/(senvironsAssertionErrorsselfsgets startswithsdebugsstart_responsesrespond(sselfsenvironsstart_response((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys__call__s  cCsti|djptti|}t||t}| o6t i d|t i |f}|i||Snt|dt o't id|}|i||Sn|||SdS(Ns_debugs%r not found when parsing %rsexposeds%r not allowed(srequests path_info_popsenvironsAssertionErrors next_partsgetattrsselfsNonesmethodshttpexceptionss HTTPNotFoundswsgilibs construct_urlsexcswsgi_applicationsstart_responsesFalses HTTPForbidden(sselfsenvironsstart_responsesexcs next_partsmethod((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pysdebugs"cCs;titiitiitd}|||SdS(s? Static path where images and other files live smediaN( s urlparsersStaticURLParsersosspathsjoinsdirnames__file__sappsenvironsstart_response(sselfsenvironsstart_responsesapp((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pysmedias*cCs;titiitiitd}|||SdS(s2 Static path where MochiKit lives smochikitN( s urlparsersStaticURLParsersosspathsjoinsdirnames__file__sappsenvironsstart_response(sselfsenvironsstart_responsesapp((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pysmochikits*cCsy|dddfgg}|ii}|idgi}|D]}||i qI~}t |gSdS(s[ Returns a JSON-format summary of all the cached exception reports s200 OKs Content-types text/x-jsoncCst|i|iS(N(scmpsascreatedsb(sasb((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pyssN( sstart_responsesdatasselfs debug_infossvaluessitemsssortsappends_[1]sitemsjsonsrepr(sselfsenvironsstart_responsesitemss_[1]sitemsdata((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pyssummarys-cCsktti|}||ijo%|dddfgd|gSn|i|}|i ||SdS(s, View old exception reports s500 Server Errors Content-types text/htmlsHTraceback by id %s does not exist (maybe the server has been restarted?)N( sintsrequests path_info_popsenvironsidsselfs debug_infossstart_responses debug_infoswsgi_application(sselfsenvironsstart_responses debug_infosid((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pysviews cCs|d|SdS(Ns/_debug/view/%s(s base_pathscount(sselfsenvirons base_pathscount((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys make_view_urlscKss|it|}|ii}|o0tii |i t |}tii nd}t|||SdS(Ns No local vars(s debug_infosframesintstbidstb_framesf_localssvarssregistrysrestorersrestoration_beginscounters make_tables local_varssrestoration_ends input_form(sselfstbids debug_infoskwsvarss local_varssframe((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys show_frames  c Ks|i odSn|id}|it|} | ii}| ii } t i || }tii|i|i|}tiiti|}dt|dtt|fSdS(Nss sD>>> %s
%ssquote(sinputsstripsrstrips debug_infosframesintstbidstb_framesf_localssvarss f_globalss glob_varss evalcontexts EvalContextscontextsregistrysrestorersrestoration_beginscounters exec_exprsoutputsrestoration_ends formattersstr2htmls input_htmlspreserve_whitespacesFalse( sselfstbids debug_infosinputskws input_htmlscontextsvarssoutputs glob_varssframe((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys exec_inputs   c s^|ido|i|Snti|dtdt} t |dtZdZdZdZdZdZdZRS(Nc Cs||_||_||_||_||_ti|_|\|_ |_ |_ d}g|_ d}|i } xj| tj ottjp |tjoB| iiidoPn|i i| | i} |d7}quWdS(Niis__exception_formatter__(scountersselfsexc_datas base_pathsenvironsview_uristimescreatedsexc_infosexc_types exc_valuestbs__exception_formatter__sframessnsNoneslimitstb_framesf_localssgetsappendstb_next( sselfscountersexc_infosexc_datas base_pathsenvironsview_urisns__exception_formatter__stb((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys__init__ms$       ' cCsehd|i<dtidti|i<d|i<dt|i<dt|i (sselfs base_pathscounter(sselfs base_path((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pyseval_javascripts (s__name__s __module__s__init__sjsonsframeswsgi_applicationscontentseval_javascript(((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys DebugInfoks     sEvalHTMLFormattercBstZdZdZRS(NcKs,tt|i|||_||_dS(N(ssupersEvalHTMLFormattersselfs__init__skws base_pathscounter(sselfs base_pathscounterskw((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys__init__s cCs4tii|||}|d|i|ifSdS(Ns        ( s formatters HTMLFormattersformat_source_linesselfsfilenamesframeslinestbids base_path(sselfsfilenamesframesline((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pysformat_source_lines(s__name__s __module__s__init__sformat_source_line(((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pysEvalHTMLFormatters c CsZt|to|i}|ing}d}x |D]\}}|d7}t}yt i ||Wn#t j o}|d|IJnXt |i}t|djo0|}|d }|d7}|d|d7}nti|}|do d}nd }|id |t |t|d tfq=Wd d i|SdS(Niis Error: %sidsj...s%%sis class="even"s class="odd"s[%s%ssquotes%s
s (s isinstancesitemssdictssortsrowssisnamesvaluesStringIOsoutspprints Exceptionses html_quotesgetvalueslens orig_values formattersmake_wrappablesattrsappendspreserve_whitespacesFalsesjoin( sitemssrowssesnamesisvalues orig_valuesattrsout((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys make_tables2        0c Cstd|d|dt}|i|}td|d|dtdtdt}|i|}t i |dt}|i|i|i|ijod|}nd}d||ti|fSdS( Ns base_pathscountersinclude_reusablesshow_hidden_framessshow_extra_datas
%s
ss %s %s
(sEvalHTMLFormatters base_pathscountersFalsesshort_formattersformat_collected_datasexc_datasshort_ersTrueslong_formatterslong_ers formatters format_textstext_ers filter_framessframessfull_traceback_htmlscgisescape( sexc_datas base_pathscountersshort_formatterslong_erstext_ersfull_traceback_htmlslong_formattersshort_er((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pysformat_eval_htmls    % cCs4ti|}|ddjo d|SntSdS(NsREQUEST_METHODsGETsB
(srequests construct_urlsenvironsurlsNone(senvironsurl((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pysmake_repost_button s  cCsdhd|<SdS(Ns~

stbid(stbid(stbids debug_info((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys input_form*ssE Server Error %(head_html)s %(repost_button)s %(body)s cCs7|tjo|idd}nt|d|SdS(s Wraps the application in an interactive debugger. This debugger is a major security hole, and should only be used during development. xmlhttp_key is a string that, if present in QUERY_STRING, indicates that the request is an XMLHttp request, and the Javascript/interactive debugger should not be returned. (If you try to put the debugger somewhere with innerHTML, you will often crash the browser) s xmlhttp_keys_N(s xmlhttp_keysNones global_confsgets EvalExceptionsapp(sapps global_confs xmlhttp_key((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pysmake_eval_exceptionSs  (/s__doc__ssyssosscgis tracebacks cStringIOsStringIOspprints itertoolsstimesrespaste.exceptionsserrormiddlewares formatters collectorspasteswsgilibs urlparsershttpexceptionssregistrysrequestsresponses evalcontextslimits html_quotesTruespreserve_whitespaces _repl_nbsps simplecatcherswsgiappsget_debug_infoscountsints debug_countersget_debug_countsobjects EvalExceptions DebugInfos HTMLFormattersEvalHTMLFormatters make_tablesformat_eval_htmlsmake_repost_buttons input_formserror_templatesNonesmake_eval_exception(%s simplecatchers debug_counterswsgiappsmake_eval_exceptionspreserve_whitespacesmake_repost_buttons input_forms collectors evalcontextswsgilibspprintserror_templatesres DebugInfosget_debug_counts formattershttpexceptionsscgisformat_eval_htmlsEvalHTMLFormatterssyssregistrys _repl_nbspsresponseserrormiddlewaresStringIOsoss EvalExceptions tracebacksrequestsget_debug_infos make_tables itertoolss urlparserslimitstimes html_quote((sBbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/middleware.pys?sF                     "  E ! *  PK:^W73|\V\V!paste/evalexception/middleware.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php """ Exception-catching middleware that allows interactive debugging. This middleware catches all unexpected exceptions. A normal traceback, like produced by ``paste.exceptions.errormiddleware.ErrorMiddleware`` is given, plus controls to see local variables and evaluate expressions in a local context. This can only be used in single-process environments, because subsequent requests must go back to the same process that the exception originally occurred in. Threaded or non-concurrent environments both work. This shouldn't be used in production in any way. That would just be silly. If calling from an XMLHttpRequest call, if the GET variable ``_`` is given then it will make the response more compact (and less Javascripty), since if you use innerHTML it'll kill your browser. You can look for the header X-Debug-URL in your 500 responses if you want to see the full debuggable traceback. Also, this URL is printed to ``wsgi.errors``, so you can open it up in another browser window. """ import sys import os import cgi import traceback from cStringIO import StringIO import pprint import itertools import time import re from paste.exceptions import errormiddleware, formatter, collector from paste import wsgilib from paste import urlparser from paste import httpexceptions from paste import registry from paste import request from paste import response import evalcontext limit = 200 def html_quote(v): """ Escape HTML characters, plus translate None to '' """ if v is None: return '' return cgi.escape(str(v), 1) def preserve_whitespace(v, quote=True): """ Quote a value for HTML, preserving whitespace (translating newlines to ``
`` and multiple spaces to use `` ``). If ``quote`` is true, then the value will be HTML quoted first. """ if quote: v = html_quote(v) v = v.replace('\n', '
\n') v = re.sub(r'()( +)', _repl_nbsp, v) v = re.sub(r'(\n)( +)', _repl_nbsp, v) v = re.sub(r'^()( +)', _repl_nbsp, v) return '%s' % v def _repl_nbsp(match): if len(match.group(2)) == 1: return ' ' return match.group(1) + ' ' * (len(match.group(2))-1) + ' ' def simplecatcher(application): """ A simple middleware that catches errors and turns them into simple tracebacks. """ def simplecatcher_app(environ, start_response): try: return application(environ, start_response) except: out = StringIO() traceback.print_exc(file=out) start_response('500 Server Error', [('content-type', 'text/html')], sys.exc_info()) res = out.getvalue() return ['

Error

%s
' % html_quote(res)] return simplecatcher_app def wsgiapp(): """ Turns a function or method into a WSGI application. """ def decorator(func): def wsgiapp_wrapper(*args): # we get 3 args when this is a method, two when it is # a function :( if len(args) == 3: environ = args[1] start_response = args[2] args = [args[0]] else: environ, start_response = args args = [] def application(environ, start_response): form = wsgilib.parse_formvars(environ, include_get_vars=True) headers = response.HeaderDict( {'content-type': 'text/html', 'status': '200 OK'}) form['environ'] = environ form['headers'] = headers res = func(*args, **form.mixed()) status = headers.pop('status') start_response(status, headers.headeritems()) return [res] app = httpexceptions.make_middleware(application) app = simplecatcher(app) return app(environ, start_response) wsgiapp_wrapper.exposed = True return wsgiapp_wrapper return decorator def get_debug_info(func): """ A decorator (meant to be used under ``wsgiapp()``) that resolves the ``debugcount`` variable to a ``DebugInfo`` object (or gives an error if it can't be found). """ def debug_info_replacement(self, **form): try: if 'debugcount' not in form: raise ValueError('You must provide a debugcount parameter') debugcount = form.pop('debugcount') try: debugcount = int(debugcount) except ValueError: raise ValueError('Bad value for debugcount') if debugcount not in self.debug_infos: raise ValueError( 'Debug %s no longer found (maybe it has expired?)' % debugcount) debug_info = self.debug_infos[debugcount] return func(self, debug_info=debug_info, **form) except ValueError, e: form['headers']['status'] = '500 Server Error' return 'There was an error: %s' % html_quote(e) return debug_info_replacement debug_counter = itertools.count(int(time.time())) def get_debug_count(environ): """ Return the unique debug count for the current request """ if 'paste.evalexception.debug_count' in environ: return environ['paste.evalexception.debug_count'] else: environ['paste.evalexception.debug_count'] = next = debug_counter.next() return next class EvalException(object): def __init__(self, application, global_conf=None, xmlhttp_key=None): self.application = application self.debug_infos = {} if xmlhttp_key is None: if global_conf is None: xmlhttp_key = '_' else: xmlhttp_key = global_conf.get('xmlhttp_key', '_') self.xmlhttp_key = xmlhttp_key def __call__(self, environ, start_response): assert not environ['wsgi.multiprocess'], ( "The EvalException middleware is not usable in a " "multi-process environment") environ['paste.evalexception'] = self if environ.get('PATH_INFO', '').startswith('/_debug/'): return self.debug(environ, start_response) else: return self.respond(environ, start_response) def debug(self, environ, start_response): assert request.path_info_pop(environ) == '_debug' next_part = request.path_info_pop(environ) method = getattr(self, next_part, None) if not method: exc = httpexceptions.HTTPNotFound( '%r not found when parsing %r' % (next_part, wsgilib.construct_url(environ))) return exc.wsgi_application(environ, start_response) if not getattr(method, 'exposed', False): exc = httpexceptions.HTTPForbidden( '%r not allowed' % next_part) return exc.wsgi_application(environ, start_response) return method(environ, start_response) def media(self, environ, start_response): """ Static path where images and other files live """ app = urlparser.StaticURLParser( os.path.join(os.path.dirname(__file__), 'media')) return app(environ, start_response) media.exposed = True def mochikit(self, environ, start_response): """ Static path where MochiKit lives """ app = urlparser.StaticURLParser( os.path.join(os.path.dirname(__file__), 'mochikit')) return app(environ, start_response) mochikit.exposed = True def summary(self, environ, start_response): """ Returns a JSON-format summary of all the cached exception reports """ start_response('200 OK', [('Content-type', 'text/x-json')]) data = []; items = self.debug_infos.values() items.sort(lambda a, b: cmp(a.created, b.created)) data = [item.json() for item in items] return [repr(data)] summary.exposed = True def view(self, environ, start_response): """ View old exception reports """ id = int(request.path_info_pop(environ)) if id not in self.debug_infos: start_response( '500 Server Error', [('Content-type', 'text/html')]) return [ "Traceback by id %s does not exist (maybe " "the server has been restarted?)" % id] debug_info = self.debug_infos[id] return debug_info.wsgi_application(environ, start_response) view.exposed = True def make_view_url(self, environ, base_path, count): return base_path + '/_debug/view/%s' % count #@wsgiapp() #@get_debug_info def show_frame(self, tbid, debug_info, **kw): frame = debug_info.frame(int(tbid)) vars = frame.tb_frame.f_locals if vars: registry.restorer.restoration_begin(debug_info.counter) local_vars = make_table(vars) registry.restorer.restoration_end() else: local_vars = 'No local vars' return input_form(tbid, debug_info) + local_vars show_frame = wsgiapp()(get_debug_info(show_frame)) #@wsgiapp() #@get_debug_info def exec_input(self, tbid, debug_info, input, **kw): if not input.strip(): return '' input = input.rstrip() + '\n' frame = debug_info.frame(int(tbid)) vars = frame.tb_frame.f_locals glob_vars = frame.tb_frame.f_globals context = evalcontext.EvalContext(vars, glob_vars) registry.restorer.restoration_begin(debug_info.counter) output = context.exec_expr(input) registry.restorer.restoration_end() input_html = formatter.str2html(input) return ('>>> ' '%s
\n%s' % (preserve_whitespace(input_html, quote=False), preserve_whitespace(output))) exec_input = wsgiapp()(get_debug_info(exec_input)) def respond(self, environ, start_response): if environ.get('paste.throw_errors'): return self.application(environ, start_response) base_path = request.construct_url(environ, with_path_info=False, with_query_string=False) environ['paste.throw_errors'] = True started = [] def detect_start_response(status, headers, exc_info=None): try: return start_response(status, headers, exc_info) except: raise else: started.append(True) try: __traceback_supplement__ = errormiddleware.Supplement, self, environ app_iter = self.application(environ, detect_start_response) try: return_iter = list(app_iter) return return_iter finally: if hasattr(app_iter, 'close'): app_iter.close() except: exc_info = sys.exc_info() for expected in environ.get('paste.expected_exceptions', []): if isinstance(exc_info[1], expected): raise # Tell the Registry to save its StackedObjectProxies current state # for later restoration registry.restorer.save_registry_state(environ) count = get_debug_count(environ) view_uri = self.make_view_url(environ, base_path, count) if not started: headers = [('content-type', 'text/html')] headers.append(('X-Debug-URL', view_uri)) start_response('500 Internal Server Error', headers, exc_info) environ['wsgi.errors'].write('Debug at: %s\n' % view_uri) exc_data = collector.collect_exception(*exc_info) debug_info = DebugInfo(count, exc_info, exc_data, base_path, environ, view_uri) assert count not in self.debug_infos self.debug_infos[count] = debug_info if self.xmlhttp_key: get_vars = wsgilib.parse_querystring(environ) if dict(get_vars).get(self.xmlhttp_key): exc_data = collector.collect_exception(*exc_info) html = formatter.format_html( exc_data, include_hidden_frames=False, include_reusable=False, show_extra_data=False) return [html] # @@: it would be nice to deal with bad content types here return debug_info.content() def exception_handler(self, exc_info, environ): simple_html_error = False if self.xmlhttp_key: get_vars = wsgilib.parse_querystring(environ) if dict(get_vars).get(self.xmlhttp_key): simple_html_error = True return errormiddleware.handle_exception( exc_info, environ['wsgi.errors'], html=True, debug_mode=True, simple_html_error=simple_html_error) class DebugInfo(object): def __init__(self, counter, exc_info, exc_data, base_path, environ, view_uri): self.counter = counter self.exc_data = exc_data self.base_path = base_path self.environ = environ self.view_uri = view_uri self.created = time.time() self.exc_type, self.exc_value, self.tb = exc_info __exception_formatter__ = 1 self.frames = [] n = 0 tb = self.tb while tb is not None and (limit is None or n < limit): if tb.tb_frame.f_locals.get('__exception_formatter__'): # Stop recursion. @@: should make a fake ExceptionFrame break self.frames.append(tb) tb = tb.tb_next n += 1 def json(self): """Return the JSON-able representation of this object""" return { 'uri': self.view_uri, 'created': time.strftime('%c', time.gmtime(self.created)), 'created_timestamp': self.created, 'exception_type': str(self.exc_type), 'exception': str(self.exc_value), } def frame(self, tbid): for frame in self.frames: if id(frame) == tbid: return frame else: raise ValueError, ( "No frame by id %s found from %r" % (tbid, self.frames)) def wsgi_application(self, environ, start_response): start_response('200 OK', [('content-type', 'text/html')]) return self.content() def content(self): html = format_eval_html(self.exc_data, self.base_path, self.counter) head_html = (formatter.error_css + formatter.hide_display_js) head_html += self.eval_javascript() repost_button = make_repost_button(self.environ) page = error_template % { 'repost_button': repost_button or '', 'head_html': head_html, 'body': html} return [page] def eval_javascript(self): base_path = self.base_path + '/_debug' return ( '\n' '\n' '\n' % (base_path, base_path, base_path, self.counter)) class EvalHTMLFormatter(formatter.HTMLFormatter): def __init__(self, base_path, counter, **kw): super(EvalHTMLFormatter, self).__init__(**kw) self.base_path = base_path self.counter = counter def format_source_line(self, filename, frame): line = formatter.HTMLFormatter.format_source_line( self, filename, frame) return (line + '     ' '    ' % (frame.tbid, self.base_path)) def make_table(items): if isinstance(items, dict): items = items.items() items.sort() rows = [] i = 0 for name, value in items: i += 1 out = StringIO() try: pprint.pprint(value, out) except Exception, e: print >> out, 'Error: %s' % e value = html_quote(out.getvalue()) if len(value) > 100: # @@: This can actually break the HTML :( # should I truncate before quoting? orig_value = value value = value[:100] value += '...' value += '%s' % orig_value[100:] value = formatter.make_wrappable(value) if i % 2: attr = ' class="even"' else: attr = ' class="odd"' rows.append('' '%s%s' % (attr, html_quote(name), preserve_whitespace(value, quote=False))) return '%s
' % ( '\n'.join(rows)) def format_eval_html(exc_data, base_path, counter): short_formatter = EvalHTMLFormatter( base_path=base_path, counter=counter, include_reusable=False) short_er = short_formatter.format_collected_data(exc_data) long_formatter = EvalHTMLFormatter( base_path=base_path, counter=counter, show_hidden_frames=True, show_extra_data=False, include_reusable=False) long_er = long_formatter.format_collected_data(exc_data) text_er = formatter.format_text(exc_data, show_hidden_frames=True) if short_formatter.filter_frames(exc_data.frames) != \ long_formatter.filter_frames(exc_data.frames): # Only display the full traceback when it differs from the # short version full_traceback_html = """
%s
""" % long_er else: full_traceback_html = '' return """ %s %s
""" % (short_er, full_traceback_html, cgi.escape(text_er)) def make_repost_button(environ): url = request.construct_url(environ) if environ['REQUEST_METHOD'] == 'GET': return ('
' % url) else: # @@: I'd like to reconstruct this, but I can't because # the POST body is probably lost at this point, and # I can't get it back :( return None # @@: Use or lose the following code block """ fields = [] for name, value in wsgilib.parse_formvars( environ, include_get_vars=False).items(): if hasattr(value, 'filename'): # @@: Arg, we'll just submit the body, and leave out # the filename :( value = value.value fields.append( '' % (html_quote(name), html_quote(value))) return '''
%s
''' % (url, '\n'.join(fields)) """ def input_form(tbid, debug_info): return '''

''' % {'tbid': tbid} error_template = ''' Server Error %(head_html)s %(repost_button)s %(body)s ''' def make_eval_exception(app, global_conf, xmlhttp_key=None): """ Wraps the application in an interactive debugger. This debugger is a major security hole, and should only be used during development. xmlhttp_key is a string that, if present in QUERY_STRING, indicates that the request is an XMLHttp request, and the Javascript/interactive debugger should not be returned. (If you try to put the debugger somewhere with innerHTML, you will often crash the browser) """ if xmlhttp_key is None: xmlhttp_key = global_conf.get('xmlhttp_key', '_') return EvalException(app, xmlhttp_key=xmlhttp_key) PK-68kYDD paste/evalexception/__init__.pyc; !Gc@sdZdklZdS(s0 An exception handler for interactive debugging (s EvalExceptionN(s__doc__spaste.evalexception.middlewares EvalException(s EvalException((s@build/bdist.darwin-8.0.1-x86/egg/paste/evalexception/__init__.pys?sPK:^W7OO"paste/evalexception/evalcontext.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php from cStringIO import StringIO import traceback import threading import pdb import sys exec_lock = threading.Lock() class EvalContext(object): """ Class that represents a interactive interface. It has its own namespace. Use eval_context.exec_expr(expr) to run commands; the output of those commands is returned, as are print statements. This is essentially what doctest does, and is taken directly from doctest. """ def __init__(self, namespace, globs): self.namespace = namespace self.globs = globs def exec_expr(self, s): out = StringIO() exec_lock.acquire() save_stdout = sys.stdout try: debugger = _OutputRedirectingPdb(save_stdout) debugger.reset() pdb.set_trace = debugger.set_trace sys.stdout = out try: code = compile(s, '', "single", 0, 1) exec code in self.namespace, self.globs debugger.set_continue() except KeyboardInterrupt: raise except: traceback.print_exc(file=out) debugger.set_continue() finally: sys.stdout = save_stdout exec_lock.release() return out.getvalue() # From doctest class _OutputRedirectingPdb(pdb.Pdb): """ A specialized version of the python debugger that redirects stdout to a given stream when interacting with the user. Stdout is *not* redirected when traced code is executed. """ def __init__(self, out): self.__out = out pdb.Pdb.__init__(self) def trace_dispatch(self, *args): # Redirect stdout to the given stream. save_stdout = sys.stdout sys.stdout = self.__out # Call Pdb's trace dispatch method. try: return pdb.Pdb.trace_dispatch(self, *args) finally: sys.stdout = save_stdout PK-68 #paste/evalexception/evalcontext.pyc; !Gc@spdklZdkZdkZdkZdkZeiZdefdYZ dei fdYZ dS((sStringIONs EvalContextcBs tZdZdZdZRS(s% Class that represents a interactive interface. It has its own namespace. Use eval_context.exec_expr(expr) to run commands; the output of those commands is returned, as are print statements. This is essentially what doctest does, and is taken directly from doctest. cCs||_||_dS(N(s namespacesselfsglobs(sselfs namespacesglobs((sCbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/evalcontext.pys__init__s cBse}eiei}ze|}|i |i e _ |e_y6e |dddd}||i|iU|iWn6ej o n"eid||inXWd|e_eiX|iSdS(Nsssingleiisfile(sStringIOsouts exec_locksacquiressyssstdouts save_stdouts_OutputRedirectingPdbsdebuggersresets set_tracespdbscompilessscodesselfs namespacesglobss set_continuesKeyboardInterrupts tracebacks print_excsreleasesgetvalue(sselfsss save_stdoutscodesdebuggersout((sCbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/evalcontext.pys exec_exprs*         (s__name__s __module__s__doc__s__init__s exec_expr(((sCbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/evalcontext.pys EvalContext s  s_OutputRedirectingPdbcBs tZdZdZdZRS(s A specialized version of the python debugger that redirects stdout to a given stream when interacting with the user. Stdout is *not* redirected when traced code is executed. cCs||_tii|dS(N(soutsselfs_OutputRedirectingPdb__outspdbsPdbs__init__(sselfsout((sCbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/evalcontext.pys__init__8s cGs=ti}|it_ztii||SWd|t_XdS(N( ssyssstdouts save_stdoutsselfs_OutputRedirectingPdb__outspdbsPdbstrace_dispatchsargs(sselfsargss save_stdout((sCbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/evalcontext.pystrace_dispatch<s   (s__name__s __module__s__doc__s__init__strace_dispatch(((sCbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/evalcontext.pys_OutputRedirectingPdb2s  ( s cStringIOsStringIOs tracebacks threadingspdbssyssLocks exec_locksobjects EvalContextsPdbs_OutputRedirectingPdb(s EvalContexts exec_locksStringIOs tracebackssyss threadingspdbs_OutputRedirectingPdb((sCbuild/bdist.darwin-8.0.1-x86/egg/paste/evalexception/evalcontext.pys?s      'PK=^W7yr:ll(paste/evalexception/mochikit/MochiKit.js/*** MochiKit.MochiKit 1.3.1 : PACKED VERSION THIS FILE IS AUTOMATICALLY GENERATED. If creating patches, please diff against the source tree, not this file. See for documentation, downloads, license, etc. (c) 2005 Bob Ippolito. All rights Reserved. ***/ if(typeof (dojo)!="undefined"){ dojo.provide("MochiKit.Base"); } if(typeof (MochiKit)=="undefined"){ MochiKit={}; } if(typeof (MochiKit.Base)=="undefined"){ MochiKit.Base={}; } MochiKit.Base.VERSION="1.3.1"; MochiKit.Base.NAME="MochiKit.Base"; MochiKit.Base.update=function(_1,_2){ if(_1===null){ _1={}; } for(var i=1;i=0;i--){ _12.unshift(o[i]); } }else{ res.push(o); } } return res; },extend:function(_13,obj,_15){ if(!_15){ _15=0; } if(obj){ var l=obj.length; if(typeof (l)!="number"){ if(typeof (MochiKit.Iter)!="undefined"){ obj=MochiKit.Iter.list(obj); l=obj.length; }else{ throw new TypeError("Argument not an array-like and MochiKit.Iter not present"); } } if(!_13){ _13=[]; } for(var i=_15;i>b; },zrshift:function(a,b){ return a>>>b; },eq:function(a,b){ return a==b; },ne:function(a,b){ return a!=b; },gt:function(a,b){ return a>b; },ge:function(a,b){ return a>=b; },lt:function(a,b){ return al){ _41=l; } } _40=[]; for(i=0;i<_41;i++){ var _42=[]; for(var j=1;j0){ _57=m.concat(me.im_preargs,_57); } var _52=me.im_self; if(!_52){ _52=this; } return me.im_func.apply(_52,_57); }; _56.im_self=_55; _56.im_func=_53; _56.im_preargs=_54; return _56; },bindMethods:function(_58){ var _59=MochiKit.Base.bind; for(var k in _58){ var _60=_58[k]; if(typeof (_60)=="function"){ _58[k]=_59(_60,_58); } } },registerComparator:function(_61,_62,_63,_64){ MochiKit.Base.comparatorRegistry.register(_61,_62,_63,_64); },_primitives:{"boolean":true,"string":true,"number":true},compare:function(a,b){ if(a==b){ return 0; } var _65=(typeof (a)=="undefined"||a===null); var _66=(typeof (b)=="undefined"||b===null); if(_65&&_66){ return 0; }else{ if(_65){ return -1; }else{ if(_66){ return 1; } } } var m=MochiKit.Base; var _67=m._primitives; if(!(typeof (a) in _67&&typeof (b) in _67)){ try{ return m.comparatorRegistry.match(a,b); } catch(e){ if(e!=m.NotFound){ throw e; } } } if(ab){ return 1; } } var _68=m.repr; throw new TypeError(_68(a)+" and "+_68(b)+" can not be compared"); },compareDateLike:function(a,b){ return MochiKit.Base.compare(a.getTime(),b.getTime()); },compareArrayLike:function(a,b){ var _69=MochiKit.Base.compare; var _70=a.length; var _71=0; if(_70>b.length){ _71=1; _70=b.length; }else{ if(_700))){ var kv=MochiKit.DOM.formContents(_113); _113=kv[0]; _114=kv[1]; }else{ if(arguments.length==1){ var o=_113; _113=[]; _114=[]; for(var k in o){ var v=o[k]; if(typeof (v)!="function"){ _113.push(k); _114.push(v); } } } } var rval=[]; var len=Math.min(_113.length,_114.length); var _118=MochiKit.Base.urlEncode; for(var i=0;i=stop){ throw self.StopIteration; } _147+=step; return rval; }}; },imap:function(fun,p,q){ var m=MochiKit.Base; var self=MochiKit.Iter; var _151=m.map(self.iter,m.extend(null,arguments,1)); var map=m.map; var next=self.next; return {repr:function(){ return "imap(...)"; },toString:m.forwardCall("repr"),next:function(){ return fun.apply(this,map(next,_151)); }}; },applymap:function(fun,seq,self){ seq=MochiKit.Iter.iter(seq); var m=MochiKit.Base; return {repr:function(){ return "applymap(...)"; },toString:m.forwardCall("repr"),next:function(){ return fun.apply(self,seq.next()); }}; },chain:function(p,q){ var self=MochiKit.Iter; var m=MochiKit.Base; if(arguments.length==1){ return self.iter(arguments[0]); } var _153=m.map(self.iter,arguments); return {repr:function(){ return "chain(...)"; },toString:m.forwardCall("repr"),next:function(){ while(_153.length>1){ try{ return _153[0].next(); } catch(e){ if(e!=self.StopIteration){ throw e; } _153.shift(); } } if(_153.length==1){ var arg=_153.shift(); this.next=m.bind("next",arg); return this.next(); } throw self.StopIteration; }}; },takewhile:function(pred,seq){ var self=MochiKit.Iter; seq=self.iter(seq); return {repr:function(){ return "takewhile(...)"; },toString:MochiKit.Base.forwardCall("repr"),next:function(){ var rval=seq.next(); if(!pred(rval)){ this.next=function(){ throw self.StopIteration; }; this.next(); } return rval; }}; },dropwhile:function(pred,seq){ seq=MochiKit.Iter.iter(seq); var m=MochiKit.Base; var bind=m.bind; return {"repr":function(){ return "dropwhile(...)"; },"toString":m.forwardCall("repr"),"next":function(){ while(true){ var rval=seq.next(); if(!pred(rval)){ break; } } this.next=bind("next",seq); return rval; }}; },_tee:function(_155,sync,_157){ sync.pos[_155]=-1; var m=MochiKit.Base; var _158=m.listMin; return {repr:function(){ return "tee("+_155+", ...)"; },toString:m.forwardCall("repr"),next:function(){ var rval; var i=sync.pos[_155]; if(i==sync.max){ rval=_157.next(); sync.deque.push(rval); sync.max+=1; sync.pos[_155]+=1; }else{ rval=sync.deque[i-sync.min]; sync.pos[_155]+=1; if(i==sync.min&&_158(sync.pos)!=sync.min){ sync.min+=1; sync.deque.shift(); } } return rval; }}; },tee:function(_159,n){ var rval=[]; var sync={"pos":[],"deque":[],"max":-1,"min":-1}; if(arguments.length==1){ n=2; } var self=MochiKit.Iter; _159=self.iter(_159); var _tee=self._tee; for(var i=0;i0&&_165>=stop)||(step<0&&_165<=stop)){ throw MochiKit.Iter.StopIteration; } var rval=_165; _165+=step; return rval; },repr:function(){ return "range("+[_165,stop,step].join(", ")+")"; },toString:MochiKit.Base.forwardCall("repr")}; },sum:function(_166,_167){ var x=_167||0; var self=MochiKit.Iter; _166=self.iter(_166); try{ while(true){ x+=_166.next(); } } catch(e){ if(e!=self.StopIteration){ throw e; } } return x; },exhaust:function(_168){ var self=MochiKit.Iter; _168=self.iter(_168); try{ while(true){ _168.next(); } } catch(e){ if(e!=self.StopIteration){ throw e; } } },forEach:function(_169,func,self){ var m=MochiKit.Base; if(arguments.length>2){ func=m.bind(func,self); } if(m.isArrayLike(_169)){ try{ for(var i=0;i<_169.length;i++){ func(_169[i]); } } catch(e){ if(e!=MochiKit.Iter.StopIteration){ throw e; } } }else{ self=MochiKit.Iter; self.exhaust(self.imap(func,_169)); } },every:function(_171,func){ var self=MochiKit.Iter; try{ self.ifilterfalse(func,_171).next(); return false; } catch(e){ if(e!=self.StopIteration){ throw e; } return true; } },sorted:function(_172,cmp){ var rval=MochiKit.Iter.list(_172); if(arguments.length==1){ cmp=MochiKit.Base.compare; } rval.sort(cmp); return rval; },reversed:function(_173){ var rval=MochiKit.Iter.list(_173); rval.reverse(); return rval; },some:function(_174,func){ var self=MochiKit.Iter; try{ self.ifilter(func,_174).next(); return true; } catch(e){ if(e!=self.StopIteration){ throw e; } return false; } },iextend:function(lst,_175){ if(MochiKit.Base.isArrayLike(_175)){ for(var i=0;i<_175.length;i++){ lst.push(_175[i]); } }else{ var self=MochiKit.Iter; _175=self.iter(_175); try{ while(true){ lst.push(_175.next()); } } catch(e){ if(e!=self.StopIteration){ throw e; } } } return lst; },groupby:function(_176,_177){ var m=MochiKit.Base; var self=MochiKit.Iter; if(arguments.length<2){ _177=m.operator.identity; } _176=self.iter(_176); var pk=undefined; var k=undefined; var v; function fetch(){ v=_176.next(); k=_177(v); } function eat(){ var ret=v; v=undefined; return ret; } var _180=true; return {repr:function(){ return "groupby(...)"; },next:function(){ while(k==pk){ fetch(); if(_180){ _180=false; break; } } pk=k; return [k,{next:function(){ if(v==undefined){ fetch(); } if(k!=pk){ throw self.StopIteration; } return eat(); }}]; }}; },groupby_as_array:function(_181,_182){ var m=MochiKit.Base; var self=MochiKit.Iter; if(arguments.length<2){ _182=m.operator.identity; } _181=self.iter(_181); var _183=[]; var _184=true; var _185; while(true){ try{ var _186=_181.next(); var key=_182(_186); } catch(e){ if(e==self.StopIteration){ break; } throw e; } if(_184||key!=_185){ var _187=[]; _183.push([key,_187]); } _187.push(_186); _184=false; _185=key; } return _183; },arrayLikeIter:function(_188){ var i=0; return {repr:function(){ return "arrayLikeIter(...)"; },toString:MochiKit.Base.forwardCall("repr"),next:function(){ if(i>=_188.length){ throw MochiKit.Iter.StopIteration; } return _188[i++]; }}; },hasIterateNext:function(_189){ return (_189&&typeof (_189.iterateNext)=="function"); },iterateNextIter:function(_190){ return {repr:function(){ return "iterateNextIter(...)"; },toString:MochiKit.Base.forwardCall("repr"),next:function(){ var rval=_190.iterateNext(); if(rval===null||rval===undefined){ throw MochiKit.Iter.StopIteration; } return rval; }}; }}); MochiKit.Iter.EXPORT_OK=["iteratorRegistry","arrayLikeIter","hasIterateNext","iterateNextIter",]; MochiKit.Iter.EXPORT=["StopIteration","registerIteratorFactory","iter","count","cycle","repeat","next","izip","ifilter","ifilterfalse","islice","imap","applymap","chain","takewhile","dropwhile","tee","list","reduce","range","sum","exhaust","forEach","every","sorted","reversed","some","iextend","groupby","groupby_as_array"]; MochiKit.Iter.__new__=function(){ var m=MochiKit.Base; this.StopIteration=new m.NamedError("StopIteration"); this.iteratorRegistry=new m.AdapterRegistry(); this.registerIteratorFactory("arrayLike",m.isArrayLike,this.arrayLikeIter); this.registerIteratorFactory("iterateNext",this.hasIterateNext,this.iterateNextIter); this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; m.nameFunctions(this); }; MochiKit.Iter.__new__(); if(!MochiKit.__compat__){ reduce=MochiKit.Iter.reduce; } MochiKit.Base._exportSymbols(this,MochiKit.Iter); if(typeof (dojo)!="undefined"){ dojo.provide("MochiKit.Logging"); dojo.require("MochiKit.Base"); } if(typeof (JSAN)!="undefined"){ JSAN.use("MochiKit.Base",[]); } try{ if(typeof (MochiKit.Base)=="undefined"){ throw ""; } } catch(e){ throw "MochiKit.Logging depends on MochiKit.Base!"; } if(typeof (MochiKit.Logging)=="undefined"){ MochiKit.Logging={}; } MochiKit.Logging.NAME="MochiKit.Logging"; MochiKit.Logging.VERSION="1.3.1"; MochiKit.Logging.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.Logging.toString=function(){ return this.__repr__(); }; MochiKit.Logging.EXPORT=["LogLevel","LogMessage","Logger","alertListener","logger","log","logError","logDebug","logFatal","logWarning"]; MochiKit.Logging.EXPORT_OK=["logLevelAtLeast","isLogMessage","compareLogMessage"]; MochiKit.Logging.LogMessage=function(num,_192,info){ this.num=num; this.level=_192; this.info=info; this.timestamp=new Date(); }; MochiKit.Logging.LogMessage.prototype={repr:function(){ var m=MochiKit.Base; return "LogMessage("+m.map(m.repr,[this.num,this.level,this.info]).join(", ")+")"; },toString:MochiKit.Base.forwardCall("repr")}; MochiKit.Base.update(MochiKit.Logging,{logLevelAtLeast:function(_194){ var self=MochiKit.Logging; if(typeof (_194)=="string"){ _194=self.LogLevel[_194]; } return function(msg){ var _196=msg.level; if(typeof (_196)=="string"){ _196=self.LogLevel[_196]; } return _196>=_194; }; },isLogMessage:function(){ var _197=MochiKit.Logging.LogMessage; for(var i=0;i=0&&this._messages.length>this.maxSize){ this._messages.shift(); } },getMessages:function(_206){ var _207=0; if(!(typeof (_206)=="undefined"||_206===null)){ _207=Math.max(0,this._messages.length-_206); } return this._messages.slice(_207); },getMessageText:function(_208){ if(typeof (_208)=="undefined"||_208===null){ _208=30; } var _209=this.getMessages(_208); if(_209.length){ var lst=map(function(m){ return "\n ["+m.num+"] "+m.level+": "+m.info.join(" "); },_209); lst.unshift("LAST "+_209.length+" MESSAGES:"); return lst.join(""); } return ""; },debuggingBookmarklet:function(_210){ if(typeof (MochiKit.LoggingPane)=="undefined"){ alert(this.getMessageText()); }else{ MochiKit.LoggingPane.createLoggingPane(_210||false); } }}; MochiKit.Logging.__new__=function(){ this.LogLevel={ERROR:40,FATAL:50,WARNING:30,INFO:20,DEBUG:10}; var m=MochiKit.Base; m.registerComparator("LogMessage",this.isLogMessage,this.compareLogMessage); var _211=m.partial; var _212=this.Logger; var _213=_212.prototype.baseLog; m.update(this.Logger.prototype,{debug:_211(_213,"DEBUG"),log:_211(_213,"INFO"),error:_211(_213,"ERROR"),fatal:_211(_213,"FATAL"),warning:_211(_213,"WARNING")}); var self=this; var _214=function(name){ return function(){ self.logger[name].apply(self.logger,arguments); }; }; this.log=_214("log"); this.logError=_214("error"); this.logDebug=_214("debug"); this.logFatal=_214("fatal"); this.logWarning=_214("warning"); this.logger=new _212(); this.logger.useNativeConsole=true; this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; m.nameFunctions(this); }; if(typeof (printfire)=="undefined"&&typeof (document)!="undefined"&&document.createEvent&&typeof (dispatchEvent)!="undefined"){ printfire=function(){ printfire.args=arguments; var ev=document.createEvent("Events"); ev.initEvent("printfire",false,true); dispatchEvent(ev); }; } MochiKit.Logging.__new__(); MochiKit.Base._exportSymbols(this,MochiKit.Logging); if(typeof (dojo)!="undefined"){ dojo.provide("MochiKit.DateTime"); } if(typeof (MochiKit)=="undefined"){ MochiKit={}; } if(typeof (MochiKit.DateTime)=="undefined"){ MochiKit.DateTime={}; } MochiKit.DateTime.NAME="MochiKit.DateTime"; MochiKit.DateTime.VERSION="1.3.1"; MochiKit.DateTime.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.DateTime.toString=function(){ return this.__repr__(); }; MochiKit.DateTime.isoDate=function(str){ str=str+""; if(typeof (str)!="string"||str.length===0){ return null; } var iso=str.split("-"); if(iso.length===0){ return null; } return new Date(iso[0],iso[1]-1,iso[2]); }; MochiKit.DateTime._isoRegexp=/(\d{4,})(?:-(\d{1,2})(?:-(\d{1,2})(?:[T ](\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d+))?)?(?:(Z)|([+-])(\d{1,2})(?::(\d{1,2}))?)?)?)?)?/; MochiKit.DateTime.isoTimestamp=function(str){ str=str+""; if(typeof (str)!="string"||str.length===0){ return null; } var res=str.match(MochiKit.DateTime._isoRegexp); if(typeof (res)=="undefined"||res===null){ return null; } var year,month,day,hour,min,sec,msec; year=parseInt(res[1],10); if(typeof (res[2])=="undefined"||res[2]===""){ return new Date(year); } month=parseInt(res[2],10)-1; day=parseInt(res[3],10); if(typeof (res[4])=="undefined"||res[4]===""){ return new Date(year,month,day); } hour=parseInt(res[4],10); min=parseInt(res[5],10); sec=(typeof (res[6])!="undefined"&&res[6]!=="")?parseInt(res[6],10):0; if(typeof (res[7])!="undefined"&&res[7]!==""){ msec=Math.round(1000*parseFloat("0."+res[7])); }else{ msec=0; } if((typeof (res[8])=="undefined"||res[8]==="")&&(typeof (res[9])=="undefined"||res[9]==="")){ return new Date(year,month,day,hour,min,sec,msec); } var ofs; if(typeof (res[9])!="undefined"&&res[9]!==""){ ofs=parseInt(res[10],10)*3600000; if(typeof (res[11])!="undefined"&&res[11]!==""){ ofs+=parseInt(res[11],10)*60000; } if(res[9]=="-"){ ofs=-ofs; } }else{ ofs=0; } return new Date(Date.UTC(year,month,day,hour,min,sec,msec)-ofs); }; MochiKit.DateTime.toISOTime=function(date,_221){ if(typeof (date)=="undefined"||date===null){ return null; } var hh=date.getHours(); var mm=date.getMinutes(); var ss=date.getSeconds(); var lst=[((_221&&(hh<10))?"0"+hh:hh),((mm<10)?"0"+mm:mm),((ss<10)?"0"+ss:ss)]; return lst.join(":"); }; MochiKit.DateTime.toISOTimestamp=function(date,_225){ if(typeof (date)=="undefined"||date===null){ return null; } var sep=_225?"T":" "; var foot=_225?"Z":""; if(_225){ date=new Date(date.getTime()+(date.getTimezoneOffset()*60000)); } return MochiKit.DateTime.toISODate(date)+sep+MochiKit.DateTime.toISOTime(date,_225)+foot; }; MochiKit.DateTime.toISODate=function(date){ if(typeof (date)=="undefined"||date===null){ return null; } var _228=MochiKit.DateTime._padTwo; return [date.getFullYear(),_228(date.getMonth()+1),_228(date.getDate())].join("-"); }; MochiKit.DateTime.americanDate=function(d){ d=d+""; if(typeof (d)!="string"||d.length===0){ return null; } var a=d.split("/"); return new Date(a[2],a[0]-1,a[1]); }; MochiKit.DateTime._padTwo=function(n){ return (n>9)?n:"0"+n; }; MochiKit.DateTime.toPaddedAmericanDate=function(d){ if(typeof (d)=="undefined"||d===null){ return null; } var _230=MochiKit.DateTime._padTwo; return [_230(d.getMonth()+1),_230(d.getDate()),d.getFullYear()].join("/"); }; MochiKit.DateTime.toAmericanDate=function(d){ if(typeof (d)=="undefined"||d===null){ return null; } return [d.getMonth()+1,d.getDate(),d.getFullYear()].join("/"); }; MochiKit.DateTime.EXPORT=["isoDate","isoTimestamp","toISOTime","toISOTimestamp","toISODate","americanDate","toPaddedAmericanDate","toAmericanDate"]; MochiKit.DateTime.EXPORT_OK=[]; MochiKit.DateTime.EXPORT_TAGS={":common":MochiKit.DateTime.EXPORT,":all":MochiKit.DateTime.EXPORT}; MochiKit.DateTime.__new__=function(){ var base=this.NAME+"."; for(var k in this){ var o=this[k]; if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){ try{ o.NAME=base+k; } catch(e){ } } } }; MochiKit.DateTime.__new__(); if(typeof (MochiKit.Base)!="undefined"){ MochiKit.Base._exportSymbols(this,MochiKit.DateTime); }else{ (function(_231,_232){ if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(typeof (MochiKit.__compat__)=="boolean"&&MochiKit.__compat__)){ var all=_232.EXPORT_TAGS[":all"]; for(var i=0;i_240){ var i=_246.length-_240; res=fmt.separator+_246.substring(i,_246.length)+res; _246=_246.substring(0,i); } } res=_246+res; if(_238>0){ while(frac.length<_241){ frac=frac+"0"; } res=res+fmt.decimal+frac; } return _242+res+_243; }; }; MochiKit.Format.numberFormatter=function(_248,_249,_250){ if(typeof (_249)=="undefined"){ _249=""; } var _251=_248.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/); if(!_251){ throw TypeError("Invalid pattern"); } var _252=_248.substr(0,_251.index); var _253=_248.substr(_251.index+_251[0].length); if(_252.search(/-/)==-1){ _252=_252+"-"; } var _254=_251[1]; var frac=(typeof (_251[2])=="string"&&_251[2]!="")?_251[2]:""; var _255=(typeof (_251[3])=="string"&&_251[3]!=""); var tmp=_254.split(/,/); var _257; if(typeof (_250)=="undefined"){ _250="default"; } if(tmp.length==1){ _257=null; }else{ _257=tmp[1].length; } var _258=_254.length-_254.replace(/0/g,"").length; var _259=frac.length-frac.replace(/0/g,"").length; var _260=frac.length; var rval=MochiKit.Format._numberFormatter(_249,_252,_253,_250,_255,_260,_258,_257,_259); var m=MochiKit.Base; if(m){ var fn=arguments.callee; var args=m.concat(arguments); rval.repr=function(){ return [self.NAME,"(",map(m.repr,args).join(", "),")"].join(""); }; } return rval; }; MochiKit.Format.formatLocale=function(_262){ if(typeof (_262)=="undefined"||_262===null){ _262="default"; } if(typeof (_262)=="string"){ var rval=MochiKit.Format.LOCALE[_262]; if(typeof (rval)=="string"){ rval=arguments.callee(rval); MochiKit.Format.LOCALE[_262]=rval; } return rval; }else{ return _262; } }; MochiKit.Format.twoDigitAverage=function(_263,_264){ if(_264){ var res=_263/_264; if(!isNaN(res)){ return MochiKit.Format.twoDigitFloat(_263/_264); } } return "0"; }; MochiKit.Format.twoDigitFloat=function(_265){ var sign=(_265<0?"-":""); var s=Math.floor(Math.abs(_265)*100).toString(); if(s=="0"){ return s; } if(s.length<3){ while(s.charAt(s.length-1)=="0"){ s=s.substring(0,s.length-1); } return sign+"0."+s; } var head=sign+s.substring(0,s.length-2); var tail=s.substring(s.length-2,s.length); if(tail=="00"){ return head; }else{ if(tail.charAt(1)=="0"){ return head+"."+tail.charAt(0); }else{ return head+"."+tail; } } }; MochiKit.Format.lstrip=function(str,_270){ str=str+""; if(typeof (str)!="string"){ return null; } if(!_270){ return str.replace(/^\s+/,""); }else{ return str.replace(new RegExp("^["+_270+"]+"),""); } }; MochiKit.Format.rstrip=function(str,_271){ str=str+""; if(typeof (str)!="string"){ return null; } if(!_271){ return str.replace(/\s+$/,""); }else{ return str.replace(new RegExp("["+_271+"]+$"),""); } }; MochiKit.Format.strip=function(str,_272){ var self=MochiKit.Format; return self.rstrip(self.lstrip(str,_272),_272); }; MochiKit.Format.truncToFixed=function(_273,_274){ _273=Math.floor(_273*Math.pow(10,_274)); var res=(_273*Math.pow(10,-_274)).toFixed(_274); if(res.charAt(0)=="."){ res="0"+res; } return res; }; MochiKit.Format.roundToFixed=function(_275,_276){ return MochiKit.Format.truncToFixed(_275+0.5*Math.pow(10,-_276),_276); }; MochiKit.Format.percentFormat=function(_277){ return MochiKit.Format.twoDigitFloat(100*_277)+"%"; }; MochiKit.Format.EXPORT=["truncToFixed","roundToFixed","numberFormatter","formatLocale","twoDigitAverage","twoDigitFloat","percentFormat","lstrip","rstrip","strip"]; MochiKit.Format.LOCALE={en_US:{separator:",",decimal:".",percent:"%"},de_DE:{separator:".",decimal:",",percent:"%"},fr_FR:{separator:" ",decimal:",",percent:"%"},"default":"en_US"}; MochiKit.Format.EXPORT_OK=[]; MochiKit.Format.EXPORT_TAGS={":all":MochiKit.Format.EXPORT,":common":MochiKit.Format.EXPORT}; MochiKit.Format.__new__=function(){ var base=this.NAME+"."; var k,v,o; for(k in this.LOCALE){ o=this.LOCALE[k]; if(typeof (o)=="object"){ o.repr=function(){ return this.NAME; }; o.NAME=base+"LOCALE."+k; } } for(k in this){ o=this[k]; if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){ try{ o.NAME=base+k; } catch(e){ } } } }; MochiKit.Format.__new__(); if(typeof (MochiKit.Base)!="undefined"){ MochiKit.Base._exportSymbols(this,MochiKit.Format); }else{ (function(_278,_279){ if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(typeof (MochiKit.__compat__)=="boolean"&&MochiKit.__compat__)){ var all=_279.EXPORT_TAGS[":all"]; for(var i=0;i=0)){ this._fire(); } },_continue:function(res){ this._resback(res); this._unpause(); },_resback:function(res){ this.fired=((res instanceof Error)?1:0); this.results[this.fired]=res; this._fire(); },_check:function(){ if(this.fired!=-1){ if(!this.silentlyCancelled){ throw new MochiKit.Async.AlreadyCalledError(this); } this.silentlyCancelled=false; return; } },callback:function(res){ this._check(); if(res instanceof MochiKit.Async.Deferred){ throw new Error("Deferred instances can only be chained if they are the result of a callback"); } this._resback(res); },errback:function(res){ this._check(); var self=MochiKit.Async; if(res instanceof self.Deferred){ throw new Error("Deferred instances can only be chained if they are the result of a callback"); } if(!(res instanceof Error)){ res=new self.GenericError(res); } this._resback(res); },addBoth:function(fn){ if(arguments.length>1){ fn=MochiKit.Base.partial.apply(null,arguments); } return this.addCallbacks(fn,fn); },addCallback:function(fn){ if(arguments.length>1){ fn=MochiKit.Base.partial.apply(null,arguments); } return this.addCallbacks(fn,null); },addErrback:function(fn){ if(arguments.length>1){ fn=MochiKit.Base.partial.apply(null,arguments); } return this.addCallbacks(null,fn); },addCallbacks:function(cb,eb){ if(this.chained){ throw new Error("Chained Deferreds can not be re-used"); } this.chain.push([cb,eb]); if(this.fired>=0){ this._fire(); } return this; },_fire:function(){ var _284=this.chain; var _285=this.fired; var res=this.results[_285]; var self=this; var cb=null; while(_284.length>0&&this.paused===0){ var pair=_284.shift(); var f=pair[_285]; if(f===null){ continue; } try{ res=f(res); _285=((res instanceof Error)?1:0); if(res instanceof MochiKit.Async.Deferred){ cb=function(res){ self._continue(res); }; this._pause(); } } catch(err){ _285=1; if(!(err instanceof Error)){ err=new MochiKit.Async.GenericError(err); } res=err; } } this.fired=_285; this.results[_285]=res; if(cb&&this.paused){ res.addBoth(cb); res.chained=true; } }}; MochiKit.Base.update(MochiKit.Async,{evalJSONRequest:function(){ return eval("("+arguments[0].responseText+")"); },succeed:function(_287){ var d=new MochiKit.Async.Deferred(); d.callback.apply(d,arguments); return d; },fail:function(_288){ var d=new MochiKit.Async.Deferred(); d.errback.apply(d,arguments); return d; },getXMLHttpRequest:function(){ var self=arguments.callee; if(!self.XMLHttpRequest){ var _289=[function(){ return new XMLHttpRequest(); },function(){ return new ActiveXObject("Msxml2.XMLHTTP"); },function(){ return new ActiveXObject("Microsoft.XMLHTTP"); },function(){ return new ActiveXObject("Msxml2.XMLHTTP.4.0"); },function(){ throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest"); }]; for(var i=0;i<_289.length;i++){ var func=_289[i]; try{ self.XMLHttpRequest=func; return func(); } catch(e){ } } } return self.XMLHttpRequest(); },_nothing:function(){ },_xhr_onreadystatechange:function(d){ if(this.readyState==4){ try{ this.onreadystatechange=null; } catch(e){ try{ this.onreadystatechange=MochiKit.Async._nothing; } catch(e){ } } var _290=null; try{ _290=this.status; if(!_290&&MochiKit.Base.isNotEmpty(this.responseText)){ _290=304; } } catch(e){ } if(_290==200||_290==304){ d.callback(this); }else{ var err=new MochiKit.Async.XMLHttpRequestError(this,"Request failed"); if(err.number){ d.errback(err); }else{ d.errback(err); } } } },_xhr_canceller:function(req){ try{ req.onreadystatechange=null; } catch(e){ try{ req.onreadystatechange=MochiKit.Async._nothing; } catch(e){ } } req.abort(); },sendXMLHttpRequest:function(req,_293){ if(typeof (_293)=="undefined"||_293===null){ _293=""; } var m=MochiKit.Base; var self=MochiKit.Async; var d=new self.Deferred(m.partial(self._xhr_canceller,req)); try{ req.onreadystatechange=m.bind(self._xhr_onreadystatechange,req,d); req.send(_293); } catch(e){ try{ req.onreadystatechange=null; } catch(ignore){ } d.errback(e); } return d; },doSimpleXMLHttpRequest:function(url){ var self=MochiKit.Async; var req=self.getXMLHttpRequest(); if(arguments.length>1){ var m=MochiKit.Base; var qs=m.queryString.apply(null,m.extend(null,arguments,1)); if(qs){ url+="?"+qs; } } req.open("GET",url,true); return self.sendXMLHttpRequest(req); },loadJSONDoc:function(url){ var self=MochiKit.Async; var d=self.doSimpleXMLHttpRequest.apply(self,arguments); d=d.addCallback(self.evalJSONRequest); return d; },wait:function(_296,_297){ var d=new MochiKit.Async.Deferred(); var m=MochiKit.Base; if(typeof (_297)!="undefined"){ d.addCallback(function(){ return _297; }); } var _298=setTimeout(m.bind("callback",d),Math.floor(_296*1000)); d.canceller=function(){ try{ clearTimeout(_298); } catch(e){ } }; return d; },callLater:function(_299,func){ var m=MochiKit.Base; var _300=m.partial.apply(m,m.extend(null,arguments,1)); return MochiKit.Async.wait(_299).addCallback(function(res){ return _300(); }); }}); MochiKit.Async.DeferredLock=function(){ this.waiting=[]; this.locked=false; this.id=this._nextId(); }; MochiKit.Async.DeferredLock.prototype={__class__:MochiKit.Async.DeferredLock,acquire:function(){ d=new MochiKit.Async.Deferred(); if(this.locked){ this.waiting.push(d); }else{ this.locked=true; d.callback(this); } return d; },release:function(){ if(!this.locked){ throw TypeError("Tried to release an unlocked DeferredLock"); } this.locked=false; if(this.waiting.length>0){ this.locked=true; this.waiting.shift().callback(this); } },_nextId:MochiKit.Base.counter(),repr:function(){ var _301; if(this.locked){ _301="locked, "+this.waiting.length+" waiting"; }else{ _301="unlocked"; } return "DeferredLock("+this.id+", "+_301+")"; },toString:MochiKit.Base.forwardCall("repr")}; MochiKit.Async.DeferredList=function(list,_303,_304,_305,_306){ this.list=list; this.resultList=new Array(this.list.length); this.chain=[]; this.id=this._nextId(); this.fired=-1; this.paused=0; this.results=[null,null]; this.canceller=_306; this.silentlyCancelled=false; if(this.list.length===0&&!_303){ this.callback(this.resultList); } this.finishedCount=0; this.fireOnOneCallback=_303; this.fireOnOneErrback=_304; this.consumeErrors=_305; var _307=0; MochiKit.Base.map(MochiKit.Base.bind(function(d){ d.addCallback(MochiKit.Base.bind(this._cbDeferred,this),_307,true); d.addErrback(MochiKit.Base.bind(this._cbDeferred,this),_307,false); _307+=1; },this),this.list); }; MochiKit.Base.update(MochiKit.Async.DeferredList.prototype,MochiKit.Async.Deferred.prototype); MochiKit.Base.update(MochiKit.Async.DeferredList.prototype,{_cbDeferred:function(_308,_309,_310){ this.resultList[_308]=[_309,_310]; this.finishedCount+=1; if(this.fired!==0){ if(_309&&this.fireOnOneCallback){ this.callback([_308,_310]); }else{ if(!_309&&this.fireOnOneErrback){ this.errback(_310); }else{ if(this.finishedCount==this.list.length){ this.callback(this.resultList); } } } } if(!_309&&this.consumeErrors){ _310=null; } return _310; }}); MochiKit.Async.gatherResults=function(_311){ var d=new MochiKit.Async.DeferredList(_311,false,true,false); d.addCallback(function(_312){ var ret=[]; for(var i=0;i<_312.length;i++){ ret.push(_312[i][1]); } return ret; }); return d; }; MochiKit.Async.maybeDeferred=function(func){ var self=MochiKit.Async; var _313; try{ var r=func.apply(null,MochiKit.Base.extend([],arguments,1)); if(r instanceof self.Deferred){ _313=r; }else{ if(r instanceof Error){ _313=self.fail(r); }else{ _313=self.succeed(r); } } } catch(e){ _313=self.fail(e); } return _313; }; MochiKit.Async.EXPORT=["AlreadyCalledError","CancelledError","BrowserComplianceError","GenericError","XMLHttpRequestError","Deferred","succeed","fail","getXMLHttpRequest","doSimpleXMLHttpRequest","loadJSONDoc","wait","callLater","sendXMLHttpRequest","DeferredLock","DeferredList","gatherResults","maybeDeferred"]; MochiKit.Async.EXPORT_OK=["evalJSONRequest"]; MochiKit.Async.__new__=function(){ var m=MochiKit.Base; var ne=m.partial(m._newNamedError,this); ne("AlreadyCalledError",function(_316){ this.deferred=_316; }); ne("CancelledError",function(_317){ this.deferred=_317; }); ne("BrowserComplianceError",function(msg){ this.message=msg; }); ne("GenericError",function(msg){ this.message=msg; }); ne("XMLHttpRequestError",function(req,msg){ this.req=req; this.message=msg; try{ this.number=req.status; } catch(e){ } }); this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; m.nameFunctions(this); }; MochiKit.Async.__new__(); MochiKit.Base._exportSymbols(this,MochiKit.Async); if(typeof (dojo)!="undefined"){ dojo.provide("MochiKit.DOM"); dojo.require("MochiKit.Iter"); } if(typeof (JSAN)!="undefined"){ JSAN.use("MochiKit.Iter",[]); } try{ if(typeof (MochiKit.Iter)=="undefined"){ throw ""; } } catch(e){ throw "MochiKit.DOM depends on MochiKit.Iter!"; } if(typeof (MochiKit.DOM)=="undefined"){ MochiKit.DOM={}; } MochiKit.DOM.NAME="MochiKit.DOM"; MochiKit.DOM.VERSION="1.3.1"; MochiKit.DOM.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.DOM.toString=function(){ return this.__repr__(); }; MochiKit.DOM.EXPORT=["formContents","currentWindow","currentDocument","withWindow","withDocument","registerDOMConverter","coerceToDOM","createDOM","createDOMFunc","getNodeAttribute","setNodeAttribute","updateNodeAttributes","appendChildNodes","replaceChildNodes","removeElement","swapDOM","BUTTON","TT","PRE","H1","H2","H3","BR","CANVAS","HR","LABEL","TEXTAREA","FORM","STRONG","SELECT","OPTION","OPTGROUP","LEGEND","FIELDSET","P","UL","OL","LI","TD","TR","THEAD","TBODY","TFOOT","TABLE","TH","INPUT","SPAN","A","DIV","IMG","getElement","$","computedStyle","getElementsByTagAndClassName","addToCallStack","addLoadEvent","focusOnLoad","setElementClass","toggleElementClass","addElementClass","removeElementClass","swapElementClass","hasElementClass","escapeHTML","toHTML","emitHTML","setDisplayForElement","hideElement","showElement","scrapeText","elementDimensions","elementPosition","setElementDimensions","setElementPosition","getViewportDimensions","setOpacity"]; MochiKit.DOM.EXPORT_OK=["domConverters"]; MochiKit.DOM.Dimensions=function(w,h){ this.w=w; this.h=h; }; MochiKit.DOM.Dimensions.prototype.repr=function(){ var repr=MochiKit.Base.repr; return "{w: "+repr(this.w)+", h: "+repr(this.h)+"}"; }; MochiKit.DOM.Coordinates=function(x,y){ this.x=x; this.y=y; }; MochiKit.DOM.Coordinates.prototype.repr=function(){ var repr=MochiKit.Base.repr; return "{x: "+repr(this.x)+", y: "+repr(this.y)+"}"; }; MochiKit.DOM.Coordinates.prototype.toString=function(){ return this.repr(); }; MochiKit.Base.update(MochiKit.DOM,{setOpacity:function(elem,o){ elem=MochiKit.DOM.getElement(elem); MochiKit.DOM.updateNodeAttributes(elem,{"style":{"opacity":o,"-moz-opacity":o,"-khtml-opacity":o,"filter":" alpha(opacity="+(o*100)+")"}}); },getViewportDimensions:function(){ var d=new MochiKit.DOM.Dimensions(); var w=MochiKit.DOM._window; var b=MochiKit.DOM._document.body; if(w.innerWidth){ d.w=w.innerWidth; d.h=w.innerHeight; }else{ if(b.parentElement.clientWidth){ d.w=b.parentElement.clientWidth; d.h=b.parentElement.clientHeight; }else{ if(b&&b.clientWidth){ d.w=b.clientWidth; d.h=b.clientHeight; } } } return d; },elementDimensions:function(elem){ var self=MochiKit.DOM; if(typeof (elem.w)=="number"||typeof (elem.h)=="number"){ return new self.Dimensions(elem.w||0,elem.h||0); } elem=self.getElement(elem); if(!elem){ return undefined; } if(self.computedStyle(elem,"display")!="none"){ return new self.Dimensions(elem.offsetWidth||0,elem.offsetHeight||0); } var s=elem.style; var _322=s.visibility; var _323=s.position; s.visibility="hidden"; s.position="absolute"; s.display=""; var _324=elem.offsetWidth; var _325=elem.offsetHeight; s.display="none"; s.position=_323; s.visibility=_322; return new self.Dimensions(_324,_325); },elementPosition:function(elem,_326){ var self=MochiKit.DOM; elem=self.getElement(elem); if(!elem){ return undefined; } var c=new self.Coordinates(0,0); if(elem.x&&elem.y){ c.x+=elem.x||0; c.y+=elem.y||0; return c; }else{ if(elem.parentNode===null||self.computedStyle(elem,"display")=="none"){ return undefined; } } var box=null; var _329=null; var d=MochiKit.DOM._document; var de=d.documentElement; var b=d.body; if(elem.getBoundingClientRect){ box=elem.getBoundingClientRect(); c.x+=box.left+(de.scrollLeft||b.scrollLeft)-(de.clientLeft||b.clientLeft); c.y+=box.top+(de.scrollTop||b.scrollTop)-(de.clientTop||b.clientTop); }else{ if(d.getBoxObjectFor){ box=d.getBoxObjectFor(elem); c.x+=box.x; c.y+=box.y; }else{ if(elem.offsetParent){ c.x+=elem.offsetLeft; c.y+=elem.offsetTop; _329=elem.offsetParent; if(_329!=elem){ while(_329){ c.x+=_329.offsetLeft; c.y+=_329.offsetTop; _329=_329.offsetParent; } } var ua=navigator.userAgent.toLowerCase(); if((typeof (opera)!="undefined"&&parseFloat(opera.version())<9)||(ua.indexOf("safari")!=-1&&self.computedStyle(elem,"position")=="absolute")){ c.x-=b.offsetLeft; c.y-=b.offsetTop; } } } } if(typeof (_326)!="undefined"){ _326=arguments.callee(_326); if(_326){ c.x-=(_326.x||0); c.y-=(_326.y||0); } } if(elem.parentNode){ _329=elem.parentNode; }else{ _329=null; } while(_329&&_329.tagName!="BODY"&&_329.tagName!="HTML"){ c.x-=_329.scrollLeft; c.y-=_329.scrollTop; if(_329.parentNode){ _329=_329.parentNode; }else{ _329=null; } } return c; },setElementDimensions:function(elem,_332,_333){ elem=MochiKit.DOM.getElement(elem); if(typeof (_333)=="undefined"){ _333="px"; } MochiKit.DOM.updateNodeAttributes(elem,{"style":{"width":_332.w+_333,"height":_332.h+_333}}); },setElementPosition:function(elem,_334,_335){ elem=MochiKit.DOM.getElement(elem); if(typeof (_335)=="undefined"){ _335="px"; } MochiKit.DOM.updateNodeAttributes(elem,{"style":{"left":_334.x+_335,"top":_334.y+_335}}); },currentWindow:function(){ return MochiKit.DOM._window; },currentDocument:function(){ return MochiKit.DOM._document; },withWindow:function(win,func){ var self=MochiKit.DOM; var _337=self._document; var _338=self._win; var rval; try{ self._window=win; self._document=win.document; rval=func(); } catch(e){ self._window=_338; self._document=_337; throw e; } self._window=_338; self._document=_337; return rval; },formContents:function(elem){ var _339=[]; var _340=[]; var m=MochiKit.Base; var self=MochiKit.DOM; if(typeof (elem)=="undefined"||elem===null){ elem=self._document; }else{ elem=self.getElement(elem); } m.nodeWalk(elem,function(elem){ var name=elem.name; if(m.isNotEmpty(name)){ var _341=elem.nodeName; if(_341=="INPUT"&&(elem.type=="radio"||elem.type=="checkbox")&&!elem.checked){ return null; } if(_341=="SELECT"){ if(elem.selectedIndex>=0){ var opt=elem.options[elem.selectedIndex]; _339.push(name); _340.push((opt.value)?opt.value:opt.text); return null; } _339.push(name); _340.push(""); return null; } if(_341=="FORM"||_341=="P"||_341=="SPAN"||_341=="DIV"){ return elem.childNodes; } _339.push(name); _340.push(elem.value||""); return null; } return elem.childNodes; }); return [_339,_340]; },withDocument:function(doc,func){ var self=MochiKit.DOM; var _344=self._document; var rval; try{ self._document=doc; rval=func(); } catch(e){ self._document=_344; throw e; } self._document=_344; return rval; },registerDOMConverter:function(name,_345,wrap,_346){ MochiKit.DOM.domConverters.register(name,_345,wrap,_346); },coerceToDOM:function(node,ctx){ var im=MochiKit.Iter; var self=MochiKit.DOM; var iter=im.iter; var _350=im.repeat; var imap=im.imap; var _352=self.domConverters; var _353=self.coerceToDOM; var _354=MochiKit.Base.NotFound; while(true){ if(typeof (node)=="undefined"||node===null){ return null; } if(typeof (node.nodeType)!="undefined"&&node.nodeType>0){ return node; } if(typeof (node)=="number"||typeof (node)=="boolean"){ node=node.toString(); } if(typeof (node)=="string"){ return self._document.createTextNode(node); } if(typeof (node.toDOM)=="function"){ node=node.toDOM(ctx); continue; } if(typeof (node)=="function"){ node=node(ctx); continue; } var _355=null; try{ _355=iter(node); } catch(e){ } if(_355){ return imap(_353,_355,_350(ctx)); } try{ node=_352.match(node,ctx); continue; } catch(e){ if(e!=_354){ throw e; } } return self._document.createTextNode(node.toString()); } return undefined; },setNodeAttribute:function(node,attr,_357){ var o={}; o[attr]=_357; try{ return MochiKit.DOM.updateNodeAttributes(node,o); } catch(e){ } return null; },getNodeAttribute:function(node,attr){ var self=MochiKit.DOM; var _358=self.attributeArray.renames[attr]; node=self.getElement(node); try{ if(_358){ return node[_358]; } return node.getAttribute(attr); } catch(e){ } return null; },updateNodeAttributes:function(node,_359){ var elem=node; var self=MochiKit.DOM; if(typeof (node)=="string"){ elem=self.getElement(node); } if(_359){ var _360=MochiKit.Base.updatetree; if(self.attributeArray.compliant){ for(var k in _359){ var v=_359[k]; if(typeof (v)=="object"&&typeof (elem[k])=="object"){ _360(elem[k],v); }else{ if(k.substring(0,2)=="on"){ if(typeof (v)=="string"){ v=new Function(v); } elem[k]=v; }else{ elem.setAttribute(k,v); } } } }else{ var _361=self.attributeArray.renames; for(k in _359){ v=_359[k]; var _362=_361[k]; if(k=="style"&&typeof (v)=="string"){ elem.style.cssText=v; }else{ if(typeof (_362)=="string"){ elem[_362]=v; }else{ if(typeof (elem[k])=="object"&&typeof (v)=="object"){ _360(elem[k],v); }else{ if(k.substring(0,2)=="on"){ if(typeof (v)=="string"){ v=new Function(v); } elem[k]=v; }else{ elem.setAttribute(k,v); } } } } } } } return elem; },appendChildNodes:function(node){ var elem=node; var self=MochiKit.DOM; if(typeof (node)=="string"){ elem=self.getElement(node); } var _363=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)]; var _364=MochiKit.Base.concat; while(_363.length){ var n=_363.shift(); if(typeof (n)=="undefined"||n===null){ }else{ if(typeof (n.nodeType)=="number"){ elem.appendChild(n); }else{ _363=_364(n,_363); } } } return elem; },replaceChildNodes:function(node){ var elem=node; var self=MochiKit.DOM; if(typeof (node)=="string"){ elem=self.getElement(node); arguments[0]=elem; } var _365; while((_365=elem.firstChild)){ elem.removeChild(_365); } if(arguments.length<2){ return elem; }else{ return self.appendChildNodes.apply(this,arguments); } },createDOM:function(name,_366){ var elem; var self=MochiKit.DOM; var m=MochiKit.Base; if(typeof (_366)=="string"||typeof (_366)=="number"){ var args=m.extend([name,null],arguments,1); return arguments.callee.apply(this,args); } if(typeof (name)=="string"){ if(_366&&"name" in _366&&!self.attributeArray.compliant){ name=("<"+name+" name=\""+self.escapeHTML(_366.name)+"\">"); } elem=self._document.createElement(name); }else{ elem=name; } if(_366){ self.updateNodeAttributes(elem,_366); } if(arguments.length<=2){ return elem; }else{ var args=m.extend([elem],arguments,2); return self.appendChildNodes.apply(this,args); } },createDOMFunc:function(){ var m=MochiKit.Base; return m.partial.apply(this,m.extend([MochiKit.DOM.createDOM],arguments)); },swapDOM:function(dest,src){ var self=MochiKit.DOM; dest=self.getElement(dest); var _369=dest.parentNode; if(src){ src=self.getElement(src); _369.replaceChild(src,dest); }else{ _369.removeChild(dest); } return src; },getElement:function(id){ var self=MochiKit.DOM; if(arguments.length==1){ return ((typeof (id)=="string")?self._document.getElementById(id):id); }else{ return MochiKit.Base.map(self.getElement,arguments); } },computedStyle:function(_371,_372,_373){ if(arguments.length==2){ _373=_372; } var self=MochiKit.DOM; var el=self.getElement(_371); var _375=self._document; if(!el||el==_375){ return undefined; } if(el.currentStyle){ return el.currentStyle[_372]; } if(typeof (_375.defaultView)=="undefined"){ return undefined; } if(_375.defaultView===null){ return undefined; } var _376=_375.defaultView.getComputedStyle(el,null); if(typeof (_376)=="undefined"||_376===null){ return undefined; } return _376.getPropertyValue(_373); },getElementsByTagAndClassName:function(_377,_378,_379){ var self=MochiKit.DOM; if(typeof (_377)=="undefined"||_377===null){ _377="*"; } if(typeof (_379)=="undefined"||_379===null){ _379=self._document; } _379=self.getElement(_379); var _380=(_379.getElementsByTagName(_377)||self._document.all); if(typeof (_378)=="undefined"||_378===null){ return MochiKit.Base.extend(null,_380); } var _381=[]; for(var i=0;i<_380.length;i++){ var _382=_380[i]; var _383=_382.className.split(" "); for(var j=0;j<_383.length;j++){ if(_383[j]==_378){ _381.push(_382); break; } } } return _381; },_newCallStack:function(path,once){ var rval=function(){ var _386=arguments.callee.callStack; for(var i=0;i<_386.length;i++){ if(_386[i].apply(this,arguments)===false){ break; } } if(once){ try{ this[path]=null; } catch(e){ } } }; rval.callStack=[]; return rval; },addToCallStack:function(_387,path,func,once){ var self=MochiKit.DOM; var _388=_387[path]; var _389=_388; if(!(typeof (_388)=="function"&&typeof (_388.callStack)=="object"&&_388.callStack!==null)){ _389=self._newCallStack(path,once); if(typeof (_388)=="function"){ _389.callStack.push(_388); } _387[path]=_389; } _389.callStack.push(func); },addLoadEvent:function(func){ var self=MochiKit.DOM; self.addToCallStack(self._window,"onload",func,true); },focusOnLoad:function(_390){ var self=MochiKit.DOM; self.addLoadEvent(function(){ _390=self.getElement(_390); if(_390){ _390.focus(); } }); },setElementClass:function(_391,_392){ var self=MochiKit.DOM; var obj=self.getElement(_391); if(self.attributeArray.compliant){ obj.setAttribute("class",_392); }else{ obj.setAttribute("className",_392); } },toggleElementClass:function(_393){ var self=MochiKit.DOM; for(var i=1;i/g,">"); },toHTML:function(dom){ return MochiKit.DOM.emitHTML(dom).join(""); },emitHTML:function(dom,lst){ if(typeof (lst)=="undefined"||lst===null){ lst=[]; } var _409=[dom]; var self=MochiKit.DOM; var _410=self.escapeHTML; var _411=self.attributeArray; while(_409.length){ dom=_409.pop(); if(typeof (dom)=="string"){ lst.push(dom); }else{ if(dom.nodeType==1){ lst.push("<"+dom.nodeName.toLowerCase()); var _412=[]; var _413=_411(dom); for(var i=0;i<_413.length;i++){ var a=_413[i]; _412.push([" ",a.name,"=\"",_410(a.value),"\""]); } _412.sort(); for(i=0;i<_412.length;i++){ var _414=_412[i]; for(var j=0;j<_414.length;j++){ lst.push(_414[j]); } } if(dom.hasChildNodes()){ lst.push(">"); _409.push(""); var _415=dom.childNodes; for(i=_415.length-1;i>=0;i--){ _409.push(_415[i]); } }else{ lst.push("/>"); } }else{ if(dom.nodeType==3){ lst.push(_410(dom.nodeValue)); } } } } return lst; },setDisplayForElement:function(_416,_417){ var m=MochiKit.Base; var _418=m.extend(null,arguments,1); MochiKit.Iter.forEach(m.filter(null,m.map(MochiKit.DOM.getElement,_418)),function(_417){ _417.style.display=_416; }); },scrapeText:function(node,_419){ var rval=[]; (function(node){ var cn=node.childNodes; if(cn){ for(var i=0;i0){ var _424=m.filter; _423=function(node){ return _424(_423.ignoreAttrFilter,node.attributes); }; _423.ignoreAttr={}; MochiKit.Iter.forEach(_422.attributes,function(a){ _423.ignoreAttr[a.name]=a.value; }); _423.ignoreAttrFilter=function(a){ return (_423.ignoreAttr[a.name]!=a.value); }; _423.compliant=false; _423.renames={"class":"className","checked":"defaultChecked","usemap":"useMap","for":"htmlFor"}; }else{ _423=function(node){ return node.attributes; }; _423.compliant=true; _423.renames={}; } this.attributeArray=_423; var _425=this.createDOMFunc; this.UL=_425("ul"); this.OL=_425("ol"); this.LI=_425("li"); this.TD=_425("td"); this.TR=_425("tr"); this.TBODY=_425("tbody"); this.THEAD=_425("thead"); this.TFOOT=_425("tfoot"); this.TABLE=_425("table"); this.TH=_425("th"); this.INPUT=_425("input"); this.SPAN=_425("span"); this.A=_425("a"); this.DIV=_425("div"); this.IMG=_425("img"); this.BUTTON=_425("button"); this.TT=_425("tt"); this.PRE=_425("pre"); this.H1=_425("h1"); this.H2=_425("h2"); this.H3=_425("h3"); this.BR=_425("br"); this.HR=_425("hr"); this.LABEL=_425("label"); this.TEXTAREA=_425("textarea"); this.FORM=_425("form"); this.P=_425("p"); this.SELECT=_425("select"); this.OPTION=_425("option"); this.OPTGROUP=_425("optgroup"); this.LEGEND=_425("legend"); this.FIELDSET=_425("fieldset"); this.STRONG=_425("strong"); this.CANVAS=_425("canvas"); this.hideElement=m.partial(this.setDisplayForElement,"none"); this.showElement=m.partial(this.setDisplayForElement,"block"); this.removeElement=this.swapDOM; this.$=this.getElement; this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; m.nameFunctions(this); }}); MochiKit.DOM.__new__(((typeof (window)=="undefined")?this:window)); if(!MochiKit.__compat__){ withWindow=MochiKit.DOM.withWindow; withDocument=MochiKit.DOM.withDocument; } MochiKit.Base._exportSymbols(this,MochiKit.DOM); if(typeof (dojo)!="undefined"){ dojo.provide("MochiKit.LoggingPane"); dojo.require("MochiKit.Logging"); dojo.require("MochiKit.Base"); } if(typeof (JSAN)!="undefined"){ JSAN.use("MochiKit.Logging",[]); JSAN.use("MochiKit.Base",[]); } try{ if(typeof (MochiKit.Base)=="undefined"||typeof (MochiKit.Logging)=="undefined"){ throw ""; } } catch(e){ throw "MochiKit.LoggingPane depends on MochiKit.Base and MochiKit.Logging!"; } if(typeof (MochiKit.LoggingPane)=="undefined"){ MochiKit.LoggingPane={}; } MochiKit.LoggingPane.NAME="MochiKit.LoggingPane"; MochiKit.LoggingPane.VERSION="1.3.1"; MochiKit.LoggingPane.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.LoggingPane.toString=function(){ return this.__repr__(); }; MochiKit.LoggingPane.createLoggingPane=function(_426){ var m=MochiKit.LoggingPane; _426=!(!_426); if(m._loggingPane&&m._loggingPane.inline!=_426){ m._loggingPane.closePane(); m._loggingPane=null; } if(!m._loggingPane||m._loggingPane.closed){ m._loggingPane=new m.LoggingPane(_426,MochiKit.Logging.logger); } return m._loggingPane; }; MochiKit.LoggingPane.LoggingPane=function(_427,_428){ if(typeof (_428)=="undefined"||_428===null){ _428=MochiKit.Logging.logger; } this.logger=_428; var _429=MochiKit.Base.update; var _430=MochiKit.Base.updatetree; var bind=MochiKit.Base.bind; var _431=MochiKit.Base.clone; var win=window; var uid="_MochiKit_LoggingPane"; if(typeof (MochiKit.DOM)!="undefined"){ win=MochiKit.DOM.currentWindow(); } if(!_427){ var url=win.location.href.split("?")[0].replace(/[:\/.><&]/g,"_"); var name=uid+"_"+url; var nwin=win.open("",name,"dependent,resizable,height=200"); if(!nwin){ alert("Not able to open debugging window due to pop-up blocking."); return undefined; } nwin.document.write(""+"[MochiKit.LoggingPane]"+""); nwin.document.close(); nwin.document.title+=" "+win.document.title; win=nwin; } var doc=win.document; this.doc=doc; var _434=doc.getElementById(uid); var _435=!!_434; if(_434&&typeof (_434.loggingPane)!="undefined"){ _434.loggingPane.logger=this.logger; _434.loggingPane.buildAndApplyFilter(); return _434.loggingPane; } if(_435){ var _436; while((_436=_434.firstChild)){ _434.removeChild(_436); } }else{ _434=doc.createElement("div"); _434.id=uid; } _434.loggingPane=this; var _437=doc.createElement("input"); var _438=doc.createElement("input"); var _439=doc.createElement("button"); var _440=doc.createElement("button"); var _441=doc.createElement("button"); var _442=doc.createElement("button"); var _443=doc.createElement("div"); var _444=doc.createElement("div"); var _445=uid+"_Listener"; this.colorTable=_431(this.colorTable); var _446=[]; var _447=null; var _448=function(msg){ var _449=msg.level; if(typeof (_449)=="number"){ _449=MochiKit.Logging.LogLevel[_449]; } return _449; }; var _450=function(msg){ return msg.info.join(" "); }; var _451=bind(function(msg){ var _452=_448(msg); var text=_450(msg); var c=this.colorTable[_452]; var p=doc.createElement("span"); p.className="MochiKit-LogMessage MochiKit-LogLevel-"+_452; p.style.cssText="margin: 0px; white-space: -moz-pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; white-space: pre-line; word-wrap: break-word; wrap-option: emergency; color: "+c; p.appendChild(doc.createTextNode(_452+": "+text)); _444.appendChild(p); _444.appendChild(doc.createElement("br")); if(_443.offsetHeight>_443.scrollHeight){ _443.scrollTop=0; }else{ _443.scrollTop=_443.scrollHeight; } },this); var _454=function(msg){ _446[_446.length]=msg; _451(msg); }; var _455=function(){ var _456,infore; try{ _456=new RegExp(_437.value); infore=new RegExp(_438.value); } catch(e){ logDebug("Error in filter regex: "+e.message); return null; } return function(msg){ return (_456.test(_448(msg))&&infore.test(_450(msg))); }; }; var _457=function(){ while(_444.firstChild){ _444.removeChild(_444.firstChild); } }; var _458=function(){ _446=[]; _457(); }; var _459=bind(function(){ if(this.closed){ return; } this.closed=true; if(MochiKit.LoggingPane._loggingPane==this){ MochiKit.LoggingPane._loggingPane=null; } this.logger.removeListener(_445); _434.loggingPane=null; if(_427){ _434.parentNode.removeChild(_434); }else{ this.win.close(); } },this); var _460=function(){ _457(); for(var i=0;i<_446.length;i++){ var msg=_446[i]; if(_447===null||_447(msg)){ _451(msg); } } }; this.buildAndApplyFilter=function(){ _447=_455(); _460(); this.logger.removeListener(_445); this.logger.addListener(_445,_447,_454); }; var _461=bind(function(){ _446=this.logger.getMessages(); _460(); },this); var _462=bind(function(_463){ _463=_463||window.event; key=_463.which||_463.keyCode; if(key==13){ this.buildAndApplyFilter(); } },this); var _464="display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: "+this.logFont; if(_427){ _464+="; height: 10em; border-top: 2px solid black"; }else{ _464+="; height: 100%;"; } _434.style.cssText=_464; if(!_435){ doc.body.appendChild(_434); } _464={"cssText":"width: 33%; display: inline; font: "+this.logFont}; _430(_437,{"value":"FATAL|ERROR|WARNING|INFO|DEBUG","onkeypress":_462,"style":_464}); _434.appendChild(_437); _430(_438,{"value":".*","onkeypress":_462,"style":_464}); _434.appendChild(_438); _464="width: 8%; display:inline; font: "+this.logFont; _439.appendChild(doc.createTextNode("Filter")); _439.onclick=bind("buildAndApplyFilter",this); _439.style.cssText=_464; _434.appendChild(_439); _440.appendChild(doc.createTextNode("Load")); _440.onclick=_461; _440.style.cssText=_464; _434.appendChild(_440); _441.appendChild(doc.createTextNode("Clear")); _441.onclick=_458; _441.style.cssText=_464; _434.appendChild(_441); _442.appendChild(doc.createTextNode("Close")); _442.onclick=_459; _442.style.cssText=_464; _434.appendChild(_442); _443.style.cssText="overflow: auto; width: 100%"; _444.style.cssText="width: 100%; height: "+(_427?"8em":"100%"); _443.appendChild(_444); _434.appendChild(_443); this.buildAndApplyFilter(); _461(); if(_427){ this.win=undefined; }else{ this.win=win; } this.inline=_427; this.closePane=_459; this.closed=false; return this; }; MochiKit.LoggingPane.LoggingPane.prototype={"logFont":"8pt Verdana,sans-serif","colorTable":{"ERROR":"red","FATAL":"darkred","WARNING":"blue","INFO":"black","DEBUG":"green"}}; MochiKit.LoggingPane.EXPORT_OK=["LoggingPane"]; MochiKit.LoggingPane.EXPORT=["createLoggingPane"]; MochiKit.LoggingPane.__new__=function(){ this.EXPORT_TAGS={":common":this.EXPORT,":all":MochiKit.Base.concat(this.EXPORT,this.EXPORT_OK)}; MochiKit.Base.nameFunctions(this); MochiKit.LoggingPane._loggingPane=null; }; MochiKit.LoggingPane.__new__(); MochiKit.Base._exportSymbols(this,MochiKit.LoggingPane); if(typeof (dojo)!="undefined"){ dojo.provide("MochiKit.Color"); dojo.require("MochiKit.Base"); } if(typeof (JSAN)!="undefined"){ JSAN.use("MochiKit.Base",[]); } try{ if(typeof (MochiKit.Base)=="undefined"){ throw ""; } } catch(e){ throw "MochiKit.Color depends on MochiKit.Base"; } if(typeof (MochiKit.Color)=="undefined"){ MochiKit.Color={}; } MochiKit.Color.NAME="MochiKit.Color"; MochiKit.Color.VERSION="1.3.1"; MochiKit.Color.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.Color.toString=function(){ return this.__repr__(); }; MochiKit.Color.Color=function(red,_466,blue,_468){ if(typeof (_468)=="undefined"||_468===null){ _468=1; } this.rgb={r:red,g:_466,b:blue,a:_468}; }; MochiKit.Color.Color.prototype={__class__:MochiKit.Color.Color,colorWithAlpha:function(_469){ var rgb=this.rgb; var m=MochiKit.Color; return m.Color.fromRGB(rgb.r,rgb.g,rgb.b,_469); },colorWithHue:function(hue){ var hsl=this.asHSL(); hsl.h=hue; var m=MochiKit.Color; return m.Color.fromHSL(hsl); },colorWithSaturation:function(_473){ var hsl=this.asHSL(); hsl.s=_473; var m=MochiKit.Color; return m.Color.fromHSL(hsl); },colorWithLightness:function(_474){ var hsl=this.asHSL(); hsl.l=_474; var m=MochiKit.Color; return m.Color.fromHSL(hsl); },darkerColorWithLevel:function(_475){ var hsl=this.asHSL(); hsl.l=Math.max(hsl.l-_475,0); var m=MochiKit.Color; return m.Color.fromHSL(hsl); },lighterColorWithLevel:function(_476){ var hsl=this.asHSL(); hsl.l=Math.min(hsl.l+_476,1); var m=MochiKit.Color; return m.Color.fromHSL(hsl); },blendedColor:function(_477,_478){ if(typeof (_478)=="undefined"||_478===null){ _478=0.5; } var sf=1-_478; var s=this.rgb; var d=_477.rgb; var df=_478; return MochiKit.Color.Color.fromRGB((s.r*sf)+(d.r*df),(s.g*sf)+(d.g*df),(s.b*sf)+(d.b*df),(s.a*sf)+(d.a*df)); },compareRGB:function(_481){ var a=this.asRGB(); var b=_481.asRGB(); return MochiKit.Base.compare([a.r,a.g,a.b,a.a],[b.r,b.g,b.b,b.a]); },isLight:function(){ return this.asHSL().b>0.5; },isDark:function(){ return (!this.isLight()); },toHSLString:function(){ var c=this.asHSL(); var ccc=MochiKit.Color.clampColorComponent; var rval=this._hslString; if(!rval){ var mid=(ccc(c.h,360).toFixed(0)+","+ccc(c.s,100).toPrecision(4)+"%"+","+ccc(c.l,100).toPrecision(4)+"%"); var a=c.a; if(a>=1){ a=1; rval="hsl("+mid+")"; }else{ if(a<=0){ a=0; } rval="hsla("+mid+","+a+")"; } this._hslString=rval; } return rval; },toRGBString:function(){ var c=this.rgb; var ccc=MochiKit.Color.clampColorComponent; var rval=this._rgbString; if(!rval){ var mid=(ccc(c.r,255).toFixed(0)+","+ccc(c.g,255).toFixed(0)+","+ccc(c.b,255).toFixed(0)); if(c.a!=1){ rval="rgba("+mid+","+c.a+")"; }else{ rval="rgb("+mid+")"; } this._rgbString=rval; } return rval; },asRGB:function(){ return MochiKit.Base.clone(this.rgb); },toHexString:function(){ var m=MochiKit.Color; var c=this.rgb; var ccc=MochiKit.Color.clampColorComponent; var rval=this._hexString; if(!rval){ rval=("#"+m.toColorPart(ccc(c.r,255))+m.toColorPart(ccc(c.g,255))+m.toColorPart(ccc(c.b,255))); this._hexString=rval; } return rval; },asHSV:function(){ var hsv=this.hsv; var c=this.rgb; if(typeof (hsv)=="undefined"||hsv===null){ hsv=MochiKit.Color.rgbToHSV(this.rgb); this.hsv=hsv; } return MochiKit.Base.clone(hsv); },asHSL:function(){ var hsl=this.hsl; var c=this.rgb; if(typeof (hsl)=="undefined"||hsl===null){ hsl=MochiKit.Color.rgbToHSL(this.rgb); this.hsl=hsl; } return MochiKit.Base.clone(hsl); },toString:function(){ return this.toRGBString(); },repr:function(){ var c=this.rgb; var col=[c.r,c.g,c.b,c.a]; return this.__class__.NAME+"("+col.join(", ")+")"; }}; MochiKit.Base.update(MochiKit.Color.Color,{fromRGB:function(red,_486,blue,_487){ var _488=MochiKit.Color.Color; if(arguments.length==1){ var rgb=red; red=rgb.r; _486=rgb.g; blue=rgb.b; if(typeof (rgb.a)=="undefined"){ _487=undefined; }else{ _487=rgb.a; } } return new _488(red,_486,blue,_487); },fromHSL:function(hue,_489,_490,_491){ var m=MochiKit.Color; return m.Color.fromRGB(m.hslToRGB.apply(m,arguments)); },fromHSV:function(hue,_492,_493,_494){ var m=MochiKit.Color; return m.Color.fromRGB(m.hsvToRGB.apply(m,arguments)); },fromName:function(name){ var _495=MochiKit.Color.Color; if(name.charAt(0)=="\""){ name=name.substr(1,name.length-2); } var _496=_495._namedColors[name.toLowerCase()]; if(typeof (_496)=="string"){ return _495.fromHexString(_496); }else{ if(name=="transparent"){ return _495.transparentColor(); } } return null; },fromString:function(_497){ var self=MochiKit.Color.Color; var _498=_497.substr(0,3); if(_498=="rgb"){ return self.fromRGBString(_497); }else{ if(_498=="hsl"){ return self.fromHSLString(_497); }else{ if(_497.charAt(0)=="#"){ return self.fromHexString(_497); } } } return self.fromName(_497); },fromHexString:function(_499){ if(_499.charAt(0)=="#"){ _499=_499.substring(1); } var _500=[]; var i,hex; if(_499.length==3){ for(i=0;i<3;i++){ hex=_499.substr(i,1); _500.push(parseInt(hex+hex,16)/255); } }else{ for(i=0;i<6;i+=2){ hex=_499.substr(i,2); _500.push(parseInt(hex,16)/255); } } var _501=MochiKit.Color.Color; return _501.fromRGB.apply(_501,_500); },_fromColorString:function(pre,_503,_504,_505){ if(_505.indexOf(pre)===0){ _505=_505.substring(_505.indexOf("(",3)+1,_505.length-1); } var _506=_505.split(/\s*,\s*/); var _507=[]; for(var i=0;i<_506.length;i++){ var c=_506[i]; var val; var _508=c.substring(c.length-3); if(c.charAt(c.length-1)=="%"){ val=0.01*parseFloat(c.substring(0,c.length-1)); }else{ if(_508=="deg"){ val=parseFloat(c)/360; }else{ if(_508=="rad"){ val=parseFloat(c)/(Math.PI*2); }else{ val=_504[i]*parseFloat(c); } } } _507.push(val); } return this[_503].apply(this,_507); },fromComputedStyle:function(elem,_509,_510){ var d=MochiKit.DOM; var cls=MochiKit.Color.Color; for(elem=d.getElement(elem);elem;elem=elem.parentNode){ var _511=d.computedStyle.apply(d,arguments); if(!_511){ continue; } var _512=cls.fromString(_511); if(!_512){ break; } if(_512.asRGB().a>0){ return _512; } } return null; },fromBackground:function(elem){ var cls=MochiKit.Color.Color; return cls.fromComputedStyle(elem,"backgroundColor","background-color")||cls.whiteColor(); },fromText:function(elem){ var cls=MochiKit.Color.Color; return cls.fromComputedStyle(elem,"color","color")||cls.blackColor(); },namedColors:function(){ return MochiKit.Base.clone(MochiKit.Color.Color._namedColors); }}); MochiKit.Base.update(MochiKit.Color,{clampColorComponent:function(v,_513){ v*=_513; if(v<0){ return 0; }else{ if(v>_513){ return _513; }else{ return v; } } },_hslValue:function(n1,n2,hue){ if(hue>6){ hue-=6; }else{ if(hue<0){ hue+=6; } } var val; if(hue<1){ val=n1+(n2-n1)*hue; }else{ if(hue<3){ val=n2; }else{ if(hue<4){ val=n1+(n2-n1)*(4-hue); }else{ val=n1; } } } return val; },hsvToRGB:function(hue,_516,_517,_518){ if(arguments.length==1){ var hsv=hue; hue=hsv.h; _516=hsv.s; _517=hsv.v; _518=hsv.a; } var red; var _519; var blue; if(_516===0){ red=0; _519=0; blue=0; }else{ var i=Math.floor(hue*6); var f=(hue*6)-i; var p=_517*(1-_516); var q=_517*(1-(_516*f)); var t=_517*(1-(_516*(1-f))); switch(i){ case 1: red=q; _519=_517; blue=p; break; case 2: red=p; _519=_517; blue=t; break; case 3: red=p; _519=q; blue=_517; break; case 4: red=t; _519=p; blue=_517; break; case 5: red=_517; _519=p; blue=q; break; case 6: case 0: red=_517; _519=t; blue=p; break; } } return {r:red,g:_519,b:blue,a:_518}; },hslToRGB:function(hue,_521,_522,_523){ if(arguments.length==1){ var hsl=hue; hue=hsl.h; _521=hsl.s; _522=hsl.l; _523=hsl.a; } var red; var _524; var blue; if(_521===0){ red=_522; _524=_522; blue=_522; }else{ var m2; if(_522<=0.5){ m2=_522*(1+_521); }else{ m2=_522+_521-(_522*_521); } var m1=(2*_522)-m2; var f=MochiKit.Color._hslValue; var h6=hue*6; red=f(m1,m2,h6+2); _524=f(m1,m2,h6); blue=f(m1,m2,h6-2); } return {r:red,g:_524,b:blue,a:_523}; },rgbToHSV:function(red,_528,blue,_529){ if(arguments.length==1){ var rgb=red; red=rgb.r; _528=rgb.g; blue=rgb.b; _529=rgb.a; } var max=Math.max(Math.max(red,_528),blue); var min=Math.min(Math.min(red,_528),blue); var hue; var _532; var _533=max; if(min==max){ hue=0; _532=0; }else{ var _534=(max-min); _532=_534/max; if(red==max){ hue=(_528-blue)/_534; }else{ if(_528==max){ hue=2+((blue-red)/_534); }else{ hue=4+((red-_528)/_534); } } hue/=6; if(hue<0){ hue+=1; } if(hue>1){ hue-=1; } } return {h:hue,s:_532,v:_533,a:_529}; },rgbToHSL:function(red,_535,blue,_536){ if(arguments.length==1){ var rgb=red; red=rgb.r; _535=rgb.g; blue=rgb.b; _536=rgb.a; } var max=Math.max(red,Math.max(_535,blue)); var min=Math.min(red,Math.min(_535,blue)); var hue; var _537; var _538=(max+min)/2; var _539=max-min; if(_539===0){ hue=0; _537=0; }else{ if(_538<=0.5){ _537=_539/(max+min); }else{ _537=_539/(2-max-min); } if(red==max){ hue=(_535-blue)/_539; }else{ if(_535==max){ hue=2+((blue-red)/_539); }else{ hue=4+((red-_535)/_539); } } hue/=6; if(hue<0){ hue+=1; } if(hue>1){ hue-=1; } } return {h:hue,s:_537,l:_538,a:_536}; },toColorPart:function(num){ num=Math.round(num); var _540=num.toString(16); if(num<16){ return "0"+_540; } return _540; },__new__:function(){ var m=MochiKit.Base; this.Color.fromRGBString=m.bind(this.Color._fromColorString,this.Color,"rgb","fromRGB",[1/255,1/255,1/255,1]); this.Color.fromHSLString=m.bind(this.Color._fromColorString,this.Color,"hsl","fromHSL",[1/360,0.01,0.01,1]); var _541=1/3; var _542={black:[0,0,0],blue:[0,0,1],brown:[0.6,0.4,0.2],cyan:[0,1,1],darkGray:[_541,_541,_541],gray:[0.5,0.5,0.5],green:[0,1,0],lightGray:[2*_541,2*_541,2*_541],magenta:[1,0,1],orange:[1,0.5,0],purple:[0.5,0,0.5],red:[1,0,0],transparent:[0,0,0,0],white:[1,1,1],yellow:[1,1,0]}; var _543=function(name,r,g,b,a){ var rval=this.fromRGB(r,g,b,a); this[name]=function(){ return rval; }; return rval; }; for(var k in _542){ var name=k+"Color"; var _545=m.concat([_543,this.Color,name],_542[k]); this.Color[name]=m.bind.apply(null,_545); } var _546=function(){ for(var i=0;i1){ var src=MochiKit.DOM.getElement(arguments[0]); var sig=arguments[1]; var obj=arguments[2]; var func=arguments[3]; for(var i=_562.length-1;i>=0;i--){ var o=_562[i]; if(o[0]===src&&o[1]===sig&&o[4]===obj&&o[5]===func){ self._disconnect(o); _562.splice(i,1); return true; } } }else{ var idx=m.findIdentical(_562,_561); if(idx>=0){ self._disconnect(_561); _562.splice(idx,1); return true; } } return false; },disconnectAll:function(src,sig){ src=MochiKit.DOM.getElement(src); var m=MochiKit.Base; var _563=m.flattenArguments(m.extend(null,arguments,1)); var self=MochiKit.Signal; var _564=self._disconnect; var _565=self._observers; if(_563.length===0){ for(var i=_565.length-1;i>=0;i--){ var _566=_565[i]; if(_566[0]===src){ _564(_566); _565.splice(i,1); } } }else{ var sigs={}; for(var i=0;i<_563.length;i++){ sigs[_563[i]]=true; } for(var i=_565.length-1;i>=0;i--){ var _566=_565[i]; if(_566[0]===src&&_566[1] in sigs){ _564(_566); _565.splice(i,1); } } } },signal:function(src,sig){ var _568=MochiKit.Signal._observers; src=MochiKit.DOM.getElement(src); var args=MochiKit.Base.extend(null,arguments,2); var _569=[]; for(var i=0;i<_568.length;i++){ var _570=_568[i]; if(_570[0]===src&&_570[1]===sig){ try{ _570[2].apply(src,args); } catch(e){ _569.push(e); } } } if(_569.length==1){ throw _569[0]; }else{ if(_569.length>1){ var e=new Error("Multiple errors thrown in handling 'sig', see errors property"); e.errors=_569; throw e; } } }}); MochiKit.Signal.EXPORT_OK=[]; MochiKit.Signal.EXPORT=["connect","disconnect","signal","disconnectAll"]; MochiKit.Signal.__new__=function(win){ var m=MochiKit.Base; this._document=document; this._window=win; try{ this.connect(window,"onunload",this._unloadCache); } catch(e){ } this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; m.nameFunctions(this); }; MochiKit.Signal.__new__(this); if(!MochiKit.__compat__){ connect=MochiKit.Signal.connect; disconnect=MochiKit.Signal.disconnect; disconnectAll=MochiKit.Signal.disconnectAll; signal=MochiKit.Signal.signal; } MochiKit.Base._exportSymbols(this,MochiKit.Signal); if(typeof (dojo)!="undefined"){ dojo.provide("MochiKit.Visual"); dojo.require("MochiKit.Base"); dojo.require("MochiKit.DOM"); dojo.require("MochiKit.Color"); } if(typeof (JSAN)!="undefined"){ JSAN.use("MochiKit.Base",[]); JSAN.use("MochiKit.DOM",[]); JSAN.use("MochiKit.Color",[]); } try{ if(typeof (MochiKit.Base)=="undefined"||typeof (MochiKit.DOM)=="undefined"||typeof (MochiKit.Color)=="undefined"){ throw ""; } } catch(e){ throw "MochiKit.Visual depends on MochiKit.Base, MochiKit.DOM and MochiKit.Color!"; } if(typeof (MochiKit.Visual)=="undefined"){ MochiKit.Visual={}; } MochiKit.Visual.NAME="MochiKit.Visual"; MochiKit.Visual.VERSION="1.3.1"; MochiKit.Visual.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.Visual.toString=function(){ return this.__repr__(); }; MochiKit.Visual._RoundCorners=function(e,_571){ e=MochiKit.DOM.getElement(e); this._setOptions(_571); if(this.options.__unstable__wrapElement){ e=this._doWrap(e); } var _572=this.options.color; var C=MochiKit.Color.Color; if(this.options.color=="fromElement"){ _572=C.fromBackground(e); }else{ if(!(_572 instanceof C)){ _572=C.fromString(_572); } } this.isTransparent=(_572.asRGB().a<=0); var _574=this.options.bgColor; if(this.options.bgColor=="fromParent"){ _574=C.fromBackground(e.offsetParent); }else{ if(!(_574 instanceof C)){ _574=C.fromString(_574); } } this._roundCornersImpl(e,_572,_574); }; MochiKit.Visual._RoundCorners.prototype={_doWrap:function(e){ var _575=e.parentNode; var doc=MochiKit.DOM.currentDocument(); if(typeof (doc.defaultView)=="undefined"||doc.defaultView===null){ return e; } var _576=doc.defaultView.getComputedStyle(e,null); if(typeof (_576)=="undefined"||_576===null){ return e; } var _577=MochiKit.DOM.DIV({"style":{display:"block",marginTop:_576.getPropertyValue("padding-top"),marginRight:_576.getPropertyValue("padding-right"),marginBottom:_576.getPropertyValue("padding-bottom"),marginLeft:_576.getPropertyValue("padding-left"),padding:"0px"}}); _577.innerHTML=e.innerHTML; e.innerHTML=""; e.appendChild(_577); return e; },_roundCornersImpl:function(e,_578,_579){ if(this.options.border){ this._renderBorder(e,_579); } if(this._isTopRounded()){ this._roundTopCorners(e,_578,_579); } if(this._isBottomRounded()){ this._roundBottomCorners(e,_578,_579); } },_renderBorder:function(el,_580){ var _581="1px solid "+this._borderColor(_580); var _582="border-left: "+_581; var _583="border-right: "+_581; var _584="style='"+_582+";"+_583+"'"; el.innerHTML="
"+el.innerHTML+"
"; },_roundTopCorners:function(el,_585,_586){ var _587=this._createCorner(_586); for(var i=0;i=0;i--){ _590.appendChild(this._createCornerSlice(_588,_589,i,"bottom")); } el.style.paddingBottom=0; el.appendChild(_590); },_createCorner:function(_591){ var dom=MochiKit.DOM; return dom.DIV({style:{backgroundColor:_591.toString()}}); },_createCornerSlice:function(_592,_593,n,_594){ var _595=MochiKit.DOM.SPAN(); var _596=_595.style; _596.backgroundColor=_592.toString(); _596.display="block"; _596.height="1px"; _596.overflow="hidden"; _596.fontSize="1px"; var _597=this._borderColor(_592,_593); if(this.options.border&&n===0){ _596.borderTopStyle="solid"; _596.borderTopWidth="1px"; _596.borderLeftWidth="0px"; _596.borderRightWidth="0px"; _596.borderBottomWidth="0px"; _596.height="0px"; _596.borderColor=_597.toString(); }else{ if(_597){ _596.borderColor=_597.toString(); _596.borderStyle="solid"; _596.borderWidth="0px 1px"; } } if(!this.options.compact&&(n==(this.options.numSlices-1))){ _596.height="2px"; } this._setMargin(_595,n,_594); this._setBorder(_595,n,_594); return _595; },_setOptions:function(_598){ this.options={corners:"all",color:"fromElement",bgColor:"fromParent",blend:true,border:false,compact:false,__unstable__wrapElement:false}; MochiKit.Base.update(this.options,_598); this.options.numSlices=(this.options.compact?2:4); },_whichSideTop:function(){ var _599=this.options.corners; if(this._hasString(_599,"all","top")){ return ""; } var _600=(_599.indexOf("tl")!=-1); var _601=(_599.indexOf("tr")!=-1); if(_600&&_601){ return ""; } if(_600){ return "left"; } if(_601){ return "right"; } return ""; },_whichSideBottom:function(){ var _602=this.options.corners; if(this._hasString(_602,"all","bottom")){ return ""; } var _603=(_602.indexOf("bl")!=-1); var _604=(_602.indexOf("br")!=-1); if(_603&&_604){ return ""; } if(_603){ return "left"; } if(_604){ return "right"; } return ""; },_borderColor:function(_605,_606){ if(_605=="transparent"){ return _606; }else{ if(this.options.border){ return this.options.border; }else{ if(this.options.blend){ return _606.blendedColor(_605); } } } return ""; },_setMargin:function(el,n,_607){ var _608=this._marginSize(n)+"px"; var _609=(_607=="top"?this._whichSideTop():this._whichSideBottom()); var _610=el.style; if(_609=="left"){ _610.marginLeft=_608; _610.marginRight="0px"; }else{ if(_609=="right"){ _610.marginRight=_608; _610.marginLeft="0px"; }else{ _610.marginLeft=_608; _610.marginRight=_608; } } },_setBorder:function(el,n,_611){ var _612=this._borderSize(n)+"px"; var _613=(_611=="top"?this._whichSideTop():this._whichSideBottom()); var _614=el.style; if(_613=="left"){ _614.borderLeftWidth=_612; _614.borderRightWidth="0px"; }else{ if(_613=="right"){ _614.borderRightWidth=_612; _614.borderLeftWidth="0px"; }else{ _614.borderLeftWidth=_612; _614.borderRightWidth=_612; } } },_marginSize:function(n){ if(this.isTransparent){ return 0; } var o=this.options; if(o.compact&&o.blend){ var _615=[1,0]; return _615[n]; }else{ if(o.compact){ var _616=[2,1]; return _616[n]; }else{ if(o.blend){ var _617=[3,2,1,0]; return _617[n]; }else{ var _618=[5,3,2,1]; return _618[n]; } } } },_borderSize:function(n){ var o=this.options; var _619; if(o.compact&&(o.blend||this.isTransparent)){ return 1; }else{ if(o.compact){ _619=[1,0]; }else{ if(o.blend){ _619=[2,1,1,1]; }else{ if(o.border){ _619=[0,2,0,0]; }else{ if(this.isTransparent){ _619=[5,3,2,1]; }else{ return 0; } } } } } return _619[n]; },_hasString:function(str){ for(var i=1;i"); } } })(); } PK=^W7pp+paste/evalexception/mochikit/__package__.jsdojo.hostenv.conditionalLoadModule({"common": ["MochiKit.MochiKit"]}); dojo.hostenv.moduleLoaded("MochiKit.*"); PK:^W7#>ii"paste/evalexception/media/plus.jpgJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222 "#"#4Ts! ?gnIe=%iȑ>󧼎n.sU1}\p7?/Z2Y?PK:^W7#gg#paste/evalexception/media/minus.jpgJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222 "$!4BTs! ?ZTz9mCQA7^g;j?WQJM{Oh,PK:^W7;"paste/evalexception/media/debug.jsfunction showFrame(anchor) { var tbid = anchor.getAttribute('tbid'); var expanded = anchor.expanded; if (expanded) { MochiKit.DOM.hideElement(anchor.expandedElement); anchor.expanded = false; _swapImage(anchor); return false; } anchor.expanded = true; if (anchor.expandedElement) { MochiKit.DOM.showElement(anchor.expandedElement); _swapImage(anchor); $('debug_input_'+tbid).focus(); return false; } var url = debug_base + '/show_frame?tbid=' + tbid + '&debugcount=' + debug_count; var d = MochiKit.Async.doSimpleXMLHttpRequest(url); d.addCallbacks(function (data) { var el = MochiKit.DOM.DIV({}); anchor.parentNode.insertBefore(el, anchor.nextSibling); el.innerHTML = data.responseText; anchor.expandedElement = el; _swapImage(anchor); $('debug_input_'+tbid).focus(); }, function (error) { showError(error.req.responseText); }); return false; } function _swapImage(anchor) { var el = anchor.getElementsByTagName('IMG')[0]; if (anchor.expanded) { var img = 'minus.jpg'; } else { var img = 'plus.jpg'; } el.src = debug_base + '/media/' + img; } function submitInput(button, tbid) { var input = $(button.getAttribute('input-from')); var output = $(button.getAttribute('output-to')); var url = debug_base + '/exec_input'; var history = input.form.history; input.historyPosition = 0; if (! history) { history = input.form.history = []; } history.push(input.value); var vars = { tbid: tbid, debugcount: debug_count, input: input.value }; MochiKit.DOM.showElement(output); var d = MochiKit.Async.doSimpleXMLHttpRequest(url, vars); d.addCallbacks(function (data) { var result = data.responseText; output.innerHTML += result; input.value = ''; input.focus(); }, function (error) { showError(error.req.responseText); }); return false; } function showError(msg) { var el = $('error-container'); if (el.innerHTML) { el.innerHTML += '
\n' + msg; } else { el.innerHTML = msg; } MochiKit.DOM.showElement('error-area'); } function clearError() { var el = $('error-container'); el.innerHTML = ''; MochiKit.DOM.hideElement('error-area'); } function expandInput(button) { var input = button.form.elements.input; stdops = { name: 'input', style: 'width: 100%', autocomplete: 'off' }; if (input.tagName == 'INPUT') { var newEl = MochiKit.DOM.TEXTAREA(stdops); var text = 'Contract'; } else { stdops['type'] = 'text'; stdops['onkeypress'] = 'upArrow(this)'; var newEl = MochiKit.DOM.INPUT(stdops); var text = 'Expand'; } newEl.value = input.value; newEl.id = input.id; MochiKit.DOM.swapDOM(input, newEl); newEl.focus(); button.value = text; return false; } function upArrow(input, event) { if (window.event) { event = window.event; } if (event.keyCode != 38 && event.keyCode != 40) { // not an up- or down-arrow return true; } var dir = event.keyCode == 38 ? 1 : -1; var history = input.form.history; if (! history) { history = input.form.history = []; } var pos = input.historyPosition || 0; if (! pos && dir == -1) { return true; } if (! pos && input.value) { history.push(input.value); pos = 1; } pos += dir; if (history.length-pos < 0) { pos = 1; } if (history.length-pos > history.length-1) { input.value = ''; return true; } input.historyPosition = pos; var line = history[history.length-pos]; input.value = line; } function expandLong(anchor) { var span = anchor; while (span) { if (span.style && span.style.display == 'none') { break; } span = span.nextSibling; } if (! span) { return false; } MochiKit.DOM.showElement(span); MochiKit.DOM.hideElement(anchor); return false; } PKR-68KEGG-INFO/namespace_packages.txtpaste PK`-68\$EGG-INFO/SOURCES.txtsetup.cfg setup.py Paste.egg-info/PKG-INFO Paste.egg-info/SOURCES.txt Paste.egg-info/dependency_links.txt Paste.egg-info/entry_points.txt Paste.egg-info/namespace_packages.txt Paste.egg-info/not-zip-safe Paste.egg-info/requires.txt Paste.egg-info/top_level.txt docs/DeveloperGuidelines.txt docs/StyleGuide.txt docs/default.css docs/develop-example.txt docs/developer-features.txt docs/do-it-yourself-framework.txt docs/enabled.txt docs/index.txt docs/install-example.txt docs/license.txt docs/news.txt docs/package_index.txt docs/paste-httpserver-threadpool.txt docs/related-projects.txt docs/test_server.ini docs/testing-applications.txt docs/url-parsing-with-wsgi.txt docs/community/index.txt docs/community/mailing-list.txt docs/community/repository.txt docs/download/index.txt docs/include/contact.txt docs/include/reference_header.txt docs/web/default-site.css docs/web/index.txt docs/web/site.js docs/web/style.css paste/__init__.py paste/cascade.py paste/cgiapp.py paste/cgitb_catcher.py paste/config.py paste/errordocument.py paste/fileapp.py paste/fixture.py paste/flup_session.py paste/gzipper.py paste/httpexceptions.py paste/httpheaders.py paste/httpserver.py paste/lint.py paste/modpython.py paste/pony.py paste/progress.py paste/proxy.py paste/recursive.py paste/registry.py paste/reloader.py paste/request.py paste/response.py paste/session.py paste/transaction.py paste/translogger.py paste/url.py paste/urlmap.py paste/urlparser.py paste/wsgilib.py paste/wsgiwrappers.py paste/auth/__init__.py paste/auth/auth_tkt.py paste/auth/basic.py paste/auth/cas.py paste/auth/cookie.py paste/auth/digest.py paste/auth/form.py paste/auth/grantip.py paste/auth/multi.py paste/auth/open_id.py paste/debug/__init__.py paste/debug/debugapp.py paste/debug/doctest_webapp.py paste/debug/fsdiff.py paste/debug/prints.py paste/debug/profile.py paste/debug/testserver.py paste/debug/watchthreads.py paste/debug/wdg_validate.py paste/evalexception/__init__.py paste/evalexception/evalcontext.py paste/evalexception/middleware.py paste/evalexception/media/debug.js paste/evalexception/media/minus.jpg paste/evalexception/media/plus.jpg paste/evalexception/mochikit/MochiKit.js paste/evalexception/mochikit/__package__.js paste/exceptions/__init__.py paste/exceptions/collector.py paste/exceptions/errormiddleware.py paste/exceptions/formatter.py paste/exceptions/reporter.py paste/exceptions/serial_number_generator.py paste/util/PySourceColor.py paste/util/UserDict24.py paste/util/__init__.py paste/util/classinit.py paste/util/classinstance.py paste/util/converters.py paste/util/dateinterval.py paste/util/datetimeutil.py paste/util/doctest24.py paste/util/filemixin.py paste/util/finddata.py paste/util/findpackage.py paste/util/import_string.py paste/util/intset.py paste/util/ip4.py paste/util/killthread.py paste/util/looper.py paste/util/mimeparse.py paste/util/multidict.py paste/util/quoting.py paste/util/scgiserver.py paste/util/string24.py paste/util/subprocess24.py paste/util/template.py paste/util/threadedprint.py paste/util/threadinglocal.py tests/conftest.py tests/test_cgiapp.py tests/test_cgitb_catcher.py tests/test_config.py tests/test_doctests.py tests/test_errordocument.py tests/test_fileapp.py tests/test_fixture.py tests/test_grantip.py tests/test_gzipper.py tests/test_httpheaders.py tests/test_import_string.py tests/test_multidict.py tests/test_profilemiddleware.py tests/test_proxy.py tests/test_recursive.py tests/test_registry.py tests/test_request.py tests/test_request_form.py tests/test_response.py tests/test_session.py tests/test_template.txt tests/test_urlmap.py tests/test_urlparser.py tests/test_wsgiwrappers.py tests/cgiapp_data/error.cgi tests/cgiapp_data/form.cgi tests/cgiapp_data/ok.cgi tests/cgiapp_data/stderr.cgi tests/test_auth/test_auth_cookie.py tests/test_auth/test_auth_digest.py tests/test_exceptions/__init__.py tests/test_exceptions/test_error_middleware.py tests/test_exceptions/test_formatter.py tests/test_exceptions/test_httpexceptions.py tests/test_exceptions/test_reporter.py tests/test_util/test_datetimeutil.py tests/urlparser_data/__init__.py tests/urlparser_data/secured.txt tests/urlparser_data/deep/index.html tests/urlparser_data/deep/sub/Main.txt tests/urlparser_data/find_file/index.txt tests/urlparser_data/find_file/test 3.html tests/urlparser_data/find_file/test2.html tests/urlparser_data/find_file/dir with spaces/test 4.html tests/urlparser_data/hook/__init__.py tests/urlparser_data/hook/app.py tests/urlparser_data/hook/index.py tests/urlparser_data/not_found/__init__.py tests/urlparser_data/not_found/recur/__init__.py tests/urlparser_data/not_found/recur/isfound.txt tests/urlparser_data/not_found/simple/__init__.py tests/urlparser_data/not_found/simple/found.txt tests/urlparser_data/not_found/user/__init__.py tests/urlparser_data/not_found/user/list.py tests/urlparser_data/python/__init__.py tests/urlparser_data/python/simpleapp.py tests/urlparser_data/python/stream.py tests/urlparser_data/python/sub/__init__.py tests/urlparser_data/python/sub/simpleapp.py PKS-68FEGG-INFO/entry_points.txt [paste.app_factory] cgi = paste.cgiapp:make_cgi_application [subprocess] static = paste.urlparser:make_static pkg_resources = paste.urlparser:make_pkg_resources urlparser = paste.urlparser:make_url_parser proxy = paste.proxy:make_proxy test = paste.debug.debugapp:make_test_app test_slow = paste.debug.debugapp:make_slow_app transparent_proxy = paste.proxy:make_transparent_proxy watch_threads = paste.debug.watchthreads:make_watch_threads [paste.composite_factory] urlmap = paste.urlmap:urlmap_factory cascade = paste.cascade:make_cascade [paste.filter_app_factory] error_catcher = paste.exceptions.errormiddleware:make_error_middleware cgitb = paste.cgitb_catcher:make_cgitb_middleware flup_session = paste.flup_session:make_session_middleware [Flup] gzip = paste.gzipper:make_gzip_middleware httpexceptions = paste.httpexceptions:make_middleware lint = paste.lint:make_middleware printdebug = paste.debug.prints:PrintDebugMiddleware profile = paste.debug.profile:make_profile_middleware [hotshot] recursive = paste.recursive:make_recursive_middleware # This isn't good enough to deserve the name egg:Paste#session: paste_session = paste.session:make_session_middleware wdg_validate = paste.debug.wdg_validate:make_wdg_validate_middleware [subprocess] evalerror = paste.evalexception.middleware:make_eval_exception auth_tkt = paste.auth.auth_tkt:make_auth_tkt_middleware auth_basic = paste.auth.basic:make_basic auth_digest = paste.auth.digest:make_digest auth_form = paste.auth.form:make_form grantip = paste.auth.grantip:make_grantip openid = paste.auth.open_id:make_open_id_middleware [openid] pony = paste.pony:make_pony errordocument = paste.errordocument:make_errordocument auth_cookie = paste.auth.cookie:make_auth_cookie translogger = paste.translogger:make_filter config = paste.config:make_config_filter registry = paste.registry:make_registry_manager [paste.server_runner] http = paste.httpserver:server_runner PKS-682EGG-INFO/dependency_links.txt PKR-689EGG-INFO/PKG-INFOMetadata-Version: 1.0 Name: Paste Version: 1.5.1 Summary: Tools for using a Web Server Gateway Interface stack Home-page: http://pythonpaste.org Author: Ian Bicking Author-email: ianb@colorstudy.com License: MIT Description: These provide several pieces of "middleware" (or filters) that can be nested to build web applications. Each piece of middleware uses the WSGI (`PEP 333`_) interface, and should be compatible with other middleware based on those interfaces. .. _PEP 333: http://www.python.org/peps/pep-0333.html Includes these features... Testing ------- * A fixture for testing WSGI applications conveniently and in-process, in ``paste.fixture`` * A fixture for testing command-line applications, also in ``paste.fixture`` * Check components for WSGI-compliance in ``paste.lint`` Dispatching ----------- * Chain and cascade WSGI applications (returning the first non-error response) in ``paste.cascade`` * Dispatch to several WSGI applications based on URL prefixes, in ``paste.urlmap`` * Allow applications to make subrequests and forward requests internally, in ``paste.recursive`` Web Application --------------- * Run CGI programs as WSGI applications in ``paste.cgiapp`` * Traverse files and load WSGI applications from ``.py`` files (or static files), in ``paste.urlparser`` * Serve static directories of files, also in ``paste.urlparser``; also in that module serving from Egg resources using ``pkg_resources``. Tools ----- * Catch HTTP-related exceptions (e.g., ``HTTPNotFound``) and turn them into proper responses in ``paste.httpexceptions`` * Several authentication techniques, including HTTP (Basic and Digest), signed cookies, and CAS single-signon, in the ``paste.auth`` package. * Create sessions in ``paste.session`` and ``paste.flup_session`` * Gzip responses in ``paste.gzip`` * A wide variety of routines for manipulating WSGI requests and producing responses, in ``paste.request``, ``paste.response`` and ``paste.wsgilib`` Debugging Filters ----------------- * Catch (optionally email) errors with extended tracebacks (using Zope/ZPT conventions) in ``paste.exceptions`` * Catch errors presenting a `cgitb `_-based output, in ``paste.cgitb_catcher``. * Profile each request and append profiling information to the HTML, in ``paste.debug.profile`` * Capture ``print`` output and present it in the browser for debugging, in ``paste.debug.prints`` * Validate all HTML output from applications using the `WDG Validator `_, appending any errors or warnings to the page, in ``paste.debug.wdg_validator`` Other Tools ----------- * A file monitor to allow restarting the server when files have been updated (for automatic restarting when editing code) in ``paste.reloader`` * A class for generating and traversing URLs, and creating associated HTML code, in ``paste.url`` The latest version is available in a `Subversion repository `_. For the latest changes see the `news file `_. Keywords: web application server wsgi Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Programming Language :: Python Classifier: Topic :: Internet :: WWW/HTTP Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: Internet :: WWW/HTTP :: WSGI Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Server Classifier: Framework :: Paste PKR-68-`/JJEGG-INFO/requires.txt [Flup] flup [openid] python-openid [Paste] [hotshot] [subprocess] PKS-68KEGG-INFO/top_level.txtpaste PKO^W72EGG-INFO/not-zip-safe PK;^W7K[((paste/modpython.pyPK;^W7o2=Ȣ##Xpaste/cgiapp.pyPK;^W7Z'Cpaste/reloader.pyPK-68 a66kQpaste/fileapp.pycPK-68|sځځppaste/httpexceptions.pycPK;^W7MHH paste/httpheaders.pyPK-68xllpaste/transaction.pyoPK-68G-nnpaste/wsgiwrappers.pyoPK-68Pf<<\=paste/errordocument.pycPK;^W7 sypaste/__init__.pyPK-68|`,`,{paste/urlmap.pyoPK-6813vvJpaste/cascade.pycPK-68?&pppaste/config.pycPK-68kR]]paste/registry.pycPK-68=u$u$1paste/cgiapp.pyoPK-68wHVUU nVpaste/url.pycPK-68d??]paste/request.pycPK-68a4k4k'paste/wsgilib.pyoPK-68*pLKWpaste/reloader.pyoPK-68*6@P@Phhpaste/lint.pycPK;^W70eeԸpaste/flup_session.pyPK;^W7}]MMlpaste/wsgilib.pyPK-68wHVUU npaste/url.pyoPK-68I[t?&&]lpaste/modpython.pycPK;^W7KB8:: 9paste/lint.pyPK;^W7WVWVpaste/wsgiwrappers.pyPK-68l$paste/__init__.pyoPK;^W7FT S4S4&paste/errordocument.pyPK-68)ySRSR>[paste/recursive.pycPK-68i_  ­paste/cgitb_catcher.pycPK-68i_  paste/cgitb_catcher.pyoPK;^W7^ >paste/response.pyPK;^W7"H.^paste/progress.pyPK;^W7o  opaste/transaction.pyPK-68.vnn!paste/urlparser.pycPK-68I虤**paste/progress.pycPK;^W7A``Upaste/gzipper.pyPK;^W7 )Q paste/pony.pyPK-68uxxpaste/gzipper.pycPK-68_c ~~paste/httpexceptions.pyoPK-68xllxgpaste/transaction.pycPK-68/paste/flup_session.pycPK-688X6X6paste/fileapp.pyoPK;^W7U+rr|paste/httpserver.pyPK-68*pLK paste/reloader.pycPK-68M&& paste/proxy.pyoPK-68?&pp paste/config.pyoPK-68bu ,, paste/urlmap.pycPK-68*؏  paste/pony.pycPK;^W7MM) paste/registry.pyPK;^W71Ygw paste/config.pyPK;^W7$++l paste/session.pyPK-68uxxX paste/gzipper.pyoPK-68$^ n n paste/urlparser.pyoPK-68kR]]<8 paste/registry.pyoPK-68&Hz paste/fixture.pycPK-68Pf<< paste/errordocument.pyoPK-68y剦 paste/httpheaders.pycPK;^W7C paste/fixture.pyPK-68q,ґpaste/httpserver.pyoPK;^W7G$$hpaste/proxy.pyPK;^W7* 9 9 ڍpaste/url.pyPK;^W7 ]]$paste/httpexceptions.pyPK;^W7wdh9h9%paste/recursive.pyPK-68l$Y^paste/httpheaders.pyoPK-6813vvpaste/cascade.pyoPK-68ϙE;;Z3paste/translogger.pyoPK-688$"w8w8Gpaste/session.pycPK;^W7#5,npaste/translogger.pyPK-68l|paste/__init__.pycPK-68䑑W+W+paste/response.pycPK-68/0paste/flup_session.pyoPK-68ϙE;;paste/translogger.pycPK;^W7nHf,,|paste/cascade.pyPK-68I虤**paste/progress.pyoPK;^W7//"paste/fileapp.pyPK-68RskskQpaste/wsgilib.pycPK-68(T%T%ppaste/cgiapp.pycPK-68|!pppaste/httpserver.pycPK-68M&&paste/proxy.pycPK-68h5?5?paste/request.pyoPK;^W7ii#paste/urlparser.pyPK-688[**paste/fixture.pyoPK-68G-nnpaste/wsgiwrappers.pycPK-68 {++ paste/response.pyoPK-68*؏ 5paste/pony.pyoPK;^W7]S@paste/cgitb_catcher.pyPK-68I[t?&&Opaste/modpython.pyoPK-68'q:gPPvpaste/recursive.pyoPK-688$"w8w8paste/session.pyoPK;^W7! 66Epaste/request.pyPK;^W7Vb#b#C7paste/urlmap.pyPK-68IA>>Zpaste/lint.pyoPK;^W7 ؂aOaO֙paste/util/PySourceColor.pyPK;^W7Nʌppaste/util/UserDict24.pyPK-68^  2paste/util/classinstance.pycPK-68فb{{ paste/util/template.pyoPK;^W73paste/util/threadedprint.pyPK;^W7-"VVpaste/util/__init__.pyPK;^W7-7$7$:paste/util/ip4.pyPK-68...paste/util/killthread.pyoPK-68Lpaste/util/classinit.pycPK;^W7Ƹ paste/util/mimeparse.pyPK-68%iyypaste/util/looper.pyoPK-68K-paste/util/findpackage.pyoPK;^W7:^^paste/util/template.pyPK-68]ˆˆwpaste/util/subprocess24.pycPK-68^4K4Kpaste/util/intset.pyoPK;^W7G+qcn n 9Jpaste/util/dateinterval.pyPK-68x xs s Spaste/util/classinstance.pyoPK;^W7QD/]paste/util/threadinglocal.pyPK-68-% % cpaste/util/quoting.pycPK;^W7i>p0opaste/util/scgiserver.pyPK;^W7vEV++<paste/util/killthread.pyPK-68$paste/util/scgiserver.pyoPK-68_!E/E/vpaste/util/UserDict24.pyoPK;^W7 __paste/util/converters.pyPK-68 Ǣ}}paste/util/filemixin.pyoPK-68-% % :paste/util/quoting.pyoPK-68Lpaste/util/classinit.pyoPK-68...Mpaste/util/killthread.pycPK;^W7SM599paste/util/classinit.pyPK-68 ۨY paste/util/__init__.pyoPK;^W7^AΗBpaste/util/filemixin.pyPK-68"4R4R paste/util/string24.pyoPK-68_!E/E/w\paste/util/UserDict24.pycPK-68!}|}|paste/util/template.pycPK-68zzpaste/util/doctest24.pyoPK-68:|]''paste/util/threadedprint.pyoPK-68kpaste/util/PySourceColor.pycPK-68?!paste/util/findpackage.pyPK-68 Ǣ}}6!paste/util/filemixin.pycPK;^W7"ǁ!paste/util/looper.pyPK;^W7Y9!paste/util/finddata.pyPK;^W7w',,!paste/util/multidict.pyPK-68e$"paste/util/converters.pyoPK-68]ˆˆ)"paste/util/subprocess24.pyoPK;^W7QRgAgA"paste/util/string24.pyPK-68_(fA"paste/util/import_string.pycPK-68?$paste/util/doctest24.pyPK-68IS1|1|&paste/util/doctest24.pycPK-68Şp-p- 'paste/util/threadedprint.pycPK-68k'paste/util/PySourceColor.pyoPK-68%iyy(paste/util/looper.pycPK-68 a(a(C(paste/util/ip4.pycPK-68S/(paste/util/dateinterval.pyoPK-68q;;)paste/auth/open_id.pycPK-68qVVA)paste/auth/multi.pyoPK9^W7R)paste/auth/grantip.pyPK9^W7 b)paste/auth/__init__.pyPK9^W7v{҄d)paste/auth/digest.pyPK-68G)paste/auth/grantip.pycPK-68<)paste/auth/form.pycPK-68qVV~)paste/auth/multi.pycPK-68̠c!&!&)paste/auth/digest.pyoPK-68Z)paste/auth/grantip.pyoPK-68)paste/auth/basic.pycPK-68Lȥ*paste/auth/cas.pyoPK-68~4#*paste/auth/__init__.pyoPK-68c$'$'_%*paste/auth/digest.pycPK9^W7d6M L*paste/auth/multi.pyPK9^W7yjPX*paste/auth/basic.pyPK9^W7G`v==h*paste/auth/cookie.pyPK9^W7O11*paste/auth/auth_tkt.pyPK-68Qn3939}*paste/auth/auth_tkt.pycPK-68 fmm+paste/auth/basic.pyoPK9^W7v'+paste/auth/cas.pyPK-68pWO7+paste/auth/cas.pycPK-68y;;J+paste/auth/open_id.pyoPK-68  d+paste/auth/form.pyoPK-68HH+paste/auth/cookie.pyoPK9^W7"]JJ+paste/auth/form.pyPK9^W70Lz??<+paste/auth/open_id.pyPK-68Qn3939.<,paste/auth/auth_tkt.pyoPK-68~4u,paste/auth/__init__.pycPK-68CICIuw,paste/auth/cookie.pycPK9^W7 ,paste/debug/debugapp.pyPK-689VMFMF*,paste/debug/doctest_webapp.pycPK-68E/paste/debug/watchthreads.pycPK-68e#9ccq/paste/debug/testserver.pycPK-68ER/paste/debug/profile.pyPK9^W7139 9 0paste/debug/testserver.pyPK-68rQ!!K0paste/debug/debugapp.pycPK-68reded 0paste/exceptions/formatter.pyoPK:^W7єkC0paste/exceptions/__init__.pyPK-68,y0paste/exceptions/serial_number_generator.pycPK-68:tWDWD$0paste/exceptions/errormiddleware.pycPK-681RKKV0paste/exceptions/collector.pycPK-681RKKw(1paste/exceptions/collector.pyoPK-68,t1paste/exceptions/serial_number_generator.pyoPK-68{2܅1paste/exceptions/__init__.pyoPK-68:tWDWD$1paste/exceptions/errormiddleware.pyoPK-68u=__1paste/exceptions/reporter.pycPK:^W7HzKzK:1paste/exceptions/collector.pyPK-68|o62paste/exceptions/reporter.pyoPK-68{2U2paste/exceptions/__init__.pycPK:^W71GW^{?{?#V2paste/exceptions/errormiddleware.pyPK-68reded2paste/exceptions/formatter.pycPK:^W7{a L L@2paste/exceptions/formatter.pyPK:^W7㷽G3paste/exceptions/reporter.pyPK:^W7 ,+}Y3paste/exceptions/serial_number_generator.pyPK-68 #h3paste/evalexception/evalcontext.pyoPK:^W7$zu3paste/evalexception/__init__.pyPK-68(kk"!w3paste/evalexception/middleware.pyoPK-68kYDD 3paste/evalexception/__init__.pyoPK-68CȤƏll"3paste/evalexception/middleware.pycPK:^W73|\V\V!OQ4paste/evalexception/middleware.pyPK-68kYDD 4paste/evalexception/__init__.pycPK:^W7OO"l4paste/evalexception/evalcontext.pyPK-68 #4paste/evalexception/evalcontext.pycPK=^W7yr:ll(4paste/evalexception/mochikit/MochiKit.jsPK=^W7pp+x6paste/evalexception/mochikit/__package__.jsPK:^W7#>ii"y6paste/evalexception/media/plus.jpgPK:^W7#gg#0{6paste/evalexception/media/minus.jpgPK:^W7;"|6paste/evalexception/media/debug.jsPKR-68K6EGG-INFO/namespace_packages.txtPK`-68\$6EGG-INFO/SOURCES.txtPKS-68F6EGG-INFO/entry_points.txtPKS-6826EGG-INFO/dependency_links.txtPKR-689۪6EGG-INFO/PKG-INFOPKR-68-`/JJ6EGG-INFO/requires.txtPKS-68Ko6EGG-INFO/top_level.txtPKO^W726EGG-INFO/not-zip-safePK  Hݽ6