PK4̖paste/profilemiddleware.py# Deprecated 18 Dec 2005 """ Deprecated -- see ``paste.debug.profile`` """ import warnings from paste.debug.profile import * __deprecated__ = True warnings.warn( "The paste.profilemiddleware module has been moved to " "paste.debug.profile", DeprecationWarning, 2) PK49{9EEpaste/wsgiwrappers.pyimport paste.httpexceptions from paste.request import EnvironHeaders, parse_formvars, parse_dict_querystring, get_cookie_dict, MultiDict from paste.response import HeaderDict import paste.registry as registry import paste.httpexceptions from Cookie import SimpleCookie # This should be set with the registry to a dict having at least: # content_type, charset settings = registry.StackedObjectProxy(default=dict(content_type='text/html', charset='UTF-8')) 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 does not in any way express anything beyond what is available in the environment dictionary. *All* state is kept in the environment dictionary; this is essential for interoperability. You are free to subclass this object. """ def __init__(self, environ, urlvars={}): self.environ = environ # This isn't "state" really, since the object is derivative: self.headers = EnvironHeaders(environ) 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') urlvars = environ_getter('paste.urlvars', default_factory=dict) 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 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, it will be present as a list. """ return parse_dict_querystring(self.environ) GET = property(GET, doc=GET.__doc__) def POST(self): """Dictionary-like object representing the POST body. Most values are strings, but file uploads can be FieldStorage objects. 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 output will be put in environ['paste.post_vars'] """ formvars = MultiDict() formvars.update(parse_formvars(self.environ, all_as_list=True, include_get_vars=False)) return formvars POST = property(POST, doc=POST.__doc__) def params(self): """MultiDict 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 """ pms = MultiDict() pms.update(self.POST) pms.update(self.GET) return pms 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__) class WSGIResponse(object): "A basic HTTP response, with content and dictionary-accessed headers" def __init__(self, content='', mimetype=None, code=200): if not mimetype: mimetype = "%s; charset=%s" % (settings['content_type'], settings['charset']) self.content = [content] self.headers = HeaderDict() self.headers['Content-Type'] = mimetype self.cookies = SimpleCookie() self.status_code = code def __str__(self): "Full HTTP message, including headers" return '\n'.join(['%s: %s' % (key, value) for key, value in self.headers.items()]) \ + '\n\n' + ''.join(self.content) def has_header(self, header): "Case-insensitive check for a header" header = header.lower() for key in self.headers.keys(): if key.lower() == header: return True return False def set_cookie(self, key, value='', max_age=None, expires=None, path='/', domain=None, secure=None): self.cookies[key] = value for var in ('max_age', 'path', 'domain', 'secure', 'expires'): val = locals()[var] if val is not None: self.cookies[key][var.replace('_', '-')] = val def delete_cookie(self, key): try: self.cookies[key]['max_age'] = 0 except KeyError: pass def get_content_as_string(self, encoding): """ Returns the content as a string, encoding it from a Unicode object if necessary. """ if isinstance(self.content, unicode): return [''.join(self.content).encode(encoding)] return self.content def wsgi_response(self, encoding=None): if not encoding: encoding = settings['charset'] status_text = STATUS_CODE_TEXT[self.status_code] status = '%s %s' % (self.status_code, status_text) response_headers = self.headers.items() for c in self.cookies.values(): response_headers.append(('Set-Cookie', c.output(header=''))) output = self.get_content_as_string(encoding) return status, response_headers, output # The remaining methods partially implement the file-like object interface. # See http://docs.python.org/lib/bltin-file-objects.html def write(self, content): self.content.append(content) def flush(self): pass def tell(self): return len(self.content) ## @@ 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', } PK4LDDpaste/response.py"""Routines to generate WSGI responses""" ############################################################ ## Headers ############################################################ import warnings class HeaderDict(dict): """ This represents response headers. It handles the headers as a dictionary, with case-insensitive keys. Also there is an ``.add(key, value)`` method, which sets the key, or adds the value to the current value (turning it into a list if necessary). For passing to WSGI there is a ``.headeritems()`` method which is like ``.items()`` but unpacks value that are lists. It also handles encoding -- all headers are encoded in ASCII (if they are unicode). @@: Should that encoding be ISO-8859-1 or UTF-8? I'm not sure what the spec says. """ def __getitem__(self, key): return dict.__getitem__(self, self.normalize(key)) def __setitem__(self, key, value): dict.__setitem__(self, self.normalize(key), value) def __delitem__(self, key): dict.__delitem__(self, self.normalize(key)) def __contains__(self, key): return dict.__contains__(self, self.normalize(key)) has_key = __contains__ def pop(self, key): return dict.pop(self, self.normalize(key)) def update(self, other): for key in other: self[self.normalize(key)] = other[key] def normalize(self, key): return str(key).lower().strip() def add(self, key, value): key = self.normalize(key) if key in self: if isinstance(self[key], list): self[key].append(value) else: self[key] = [self[key], value] else: self[key] = value def headeritems(self): result = [] for key in self: if isinstance(self[key], list): for v in self[key]: result.append((key, str(v))) else: result.append((key, str(self[key]))) return result #@classmethod def fromlist(cls, seq): self = cls() for name, value in seq: self.add(name, value) return self fromlist = classmethod(fromlist) def has_header(headers, name): """ Is header named ``name`` present in headers? """ name = name.lower() for header, value in headers: if header.lower() == name: return True return False def header_value(headers, name): """ Returns the header's value, or None if no such header. If a header appears more than once, all the values of the headers are joined with ','. Note that this is consistent /w RFC 2616 section 4.2 which states: 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. However, note that the original netscape usage of 'Set-Cookie', especially in MSIE which contains an 'expires' date will is not compatible with this particular concatination method. """ name = name.lower() result = [value for header, value in headers if header.lower() == name] if result: return ','.join(result) else: return None def remove_header(headers, name): """ Removes the named header from the list of headers. Returns the value of that header, or None if no header found. If multiple headers are found, only the last one is returned. """ name = name.lower() i = 0 result = None while i < len(headers): if headers[i][0].lower() == name: result = headers[i][1] del headers[i] continue i += 1 return result def replace_header(headers, name, value): """ Updates the headers replacing the first occurance of the given name with the value provided; asserting that no further occurances happen. Note that this is _not_ the same as remove_header and then append, as two distinct operations (del followed by an append) are not atomic in a threaded environment. Returns the previous header value for the provided name, if any. Clearly one should not use this function with ``set-cookie`` or other names that may have more than one occurance in the headers. """ name = name.lower() i = 0 result = None while i < len(headers): if headers[i][0].lower() == name: assert not result, "two values for the header '%s' found" % name result = headers[i][1] headers[i] = (name,value) i += 1 if not result: headers.append((name,value)) return result ############################################################ ## Deprecated methods ############################################################ def error_body_response(error_code, message, __warn=True): """ Returns a standard HTML response page for an HTTP error. **Note:** Deprecated """ if __warn: warnings.warn( 'wsgilib.error_body_response is deprecated; use the ' 'wsgi_application method on an HTTPException object ' 'instead', DeprecationWarning, 2) return '''\ %(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:: 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 PK4sEEpaste/httpserver.py# (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 """ WSGI HTTP Server This is a minimalistic WSGI server using Python's built-in BaseHTTPServer; if pyOpenSSL is installed, it also provides SSL capabilities. """ # @@: add in protection against HTTP/1.0 clients who claim to # be 1.1 but do not send a Content-Length # @@: add support for chunked encoding, this is not a 1.1 server # till this is completed. from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer from SocketServer import ThreadingMixIn import urlparse, sys, socket __all__ = ['WSGIHandlerMixin','WSGIServer','WSGIHandler', 'serve'] __version__ = "0.5" class ContinueHook(object): """ When a client request includes a 'Expect: 100-continue' header, then it is the responsibility of the server to send 100 Continue when it is ready for the content body. This allows authentication, access levels, and other exceptions to be detected *before* bandwith is spent on the request body. This is a rfile wrapper that implements this functionality by sending 100 Continue to the client immediately after the user requests the content via a read() operation on the rfile stream. After this response is sent, it becomes a pass-through object. """ def __init__(self, rfile, write): self._ContinueFile_rfile = rfile self._ContinueFile_write = write for attr in ('close','closed','fileno','flush', 'mode','bufsize','softspace'): if hasattr(rfile,attr): setattr(self,attr,getattr(rfile,attr)) for attr in ('read','readline','readlines'): if hasattr(rfile,attr): setattr(self,attr,getattr(self,'_ContinueFile_' + attr)) def _ContinueFile_send(self): self._ContinueFile_write("HTTP/1.1 100 Continue\r\n\r\n") rfile = self._ContinueFile_rfile for attr in ('read','readline','readlines'): if hasattr(rfile,attr): setattr(self,attr,getattr(rfile,attr)) def _ContinueFile_read(self, size=-1): self._ContinueFile_send() return self._ContinueFile_rfile.readline(size) def _ContinueFile_readline(self, size=-1): self._ContinueFile_send() return self._ContinueFile_rfile.readline(size) def _ContinueFile_readlines(self, sizehint=0): self._ContinueFile_send() return self._ContinueFile_rfile.readlines(sizehint) class WSGIHandlerMixin: """ WSGI mix-in for HTTPRequestHandler This class is a mix-in to provide WSGI functionality to any HTTPRequestHandler derivative (as provided in Python's BaseHTTPServer). This assumes a ``wsgi_application`` handler on ``self.server``. """ def log_request(self, *args, **kwargs): """ disable success request logging Logging transactions should not be part of a WSGI server, if you want logging; look at paste.translogger """ pass def log_message(self, *args, **kwargs): """ disable error message logging Logging transactions should not be part of a WSGI server, if you want logging; look at paste.translogger """ pass def version_string(self): """ behavior that BaseHTTPServer should have had """ if not self.sys_version: return self.server_version else: return self.server_version + ' ' + self.sys_version def wsgi_write_chunk(self, chunk): """ Write a chunk of the output stream; send headers if they have not already been sent. """ if not self.wsgi_headers_sent: self.wsgi_headers_sent = True (status, headers) = self.wsgi_curr_headers code, message = status.split(" ",1) self.send_response(int(code),message) # # HTTP/1.1 compliance; either send Content-Length or # signal that the connection is being closed. # send_close = True for (k,v) in headers: k = k.lower() if 'content-length' == k: send_close = False if 'connection' == k: if 'close' == v.lower(): self.close_connection = 1 send_close = False self.send_header(k,v) if send_close: self.close_connection = 1 self.send_header('Connection','close') self.end_headers() self.wfile.write(chunk) def wsgi_start_response(self,status,response_headers,exc_info=None): if exc_info: try: if self.wsgi_headers_sent: raise exc_info[0], exc_info[1], exc_info[2] else: # In this case, we're going to assume that the # higher-level code is currently handling the # issue and returning a resonable response. # self.log_error(repr(exc_info)) pass finally: exc_info = None elif self.wsgi_curr_headers: assert 0, "Attempt to set headers a second time w/o an exc_info" self.wsgi_curr_headers = (status, response_headers) return self.wsgi_write_chunk def wsgi_setup(self, environ=None): """ Setup the member variables used by this WSGI mixin, including the ``environ`` and status member variables. After the basic environment is created; the optional ``environ`` argument can be used to override any settings. """ (_,_,path,query,fragment) = urlparse.urlsplit(self.path) (server_name, server_port) = self.server.server_address rfile = self.rfile if 'HTTP/1.1' == self.protocol_version and \ '100-continue' == self.headers.get('Expect','').lower(): rfile = ContinueHook(rfile, self.wfile.write) self.wsgi_environ = { 'wsgi.version': (1,0) ,'wsgi.url_scheme': 'http' ,'wsgi.input': rfile ,'wsgi.errors': sys.stderr ,'wsgi.multithread': True ,'wsgi.multiprocess': False ,'wsgi.run_once': True # CGI variables required by PEP-333 ,'REQUEST_METHOD': self.command ,'SCRIPT_NAME': '' # application is root of server ,'PATH_INFO': path ,'QUERY_STRING': query ,'CONTENT_TYPE': self.headers.get('Content-Type', '') ,'CONTENT_LENGTH': self.headers.get('Content-Length', '') ,'SERVER_NAME': server_name ,'SERVER_PORT': str(server_port) ,'SERVER_PROTOCOL': self.request_version # CGI not required by PEP-333 ,'REMOTE_ADDR': self.client_address[0] ,'REMOTE_HOST': self.address_string() } for k,v in self.headers.items(): k = 'HTTP_' + k.replace("-","_").upper() if k in ('HTTP_CONTENT_TYPE','HTTP_CONTENT_LENGTH'): continue self.wsgi_environ[k] = v if hasattr(self.connection,'get_context'): self.wsgi_environ['wsgi.url_scheme'] = 'https' # @@: extract other SSL parameters from pyOpenSSL at... # http://www.modssl.org/docs/2.8/ssl_reference.html#ToC25 if environ: assert isinstance(environ,dict) self.wsgi_environ.update(environ) if 'on' == environ.get('HTTPS'): self.wsgi_environ['wsgi.url_scheme'] = 'https' self.wsgi_curr_headers = None self.wsgi_headers_sent = False def wsgi_connection_drop(self, exce, environ=None): """ Override this if you're interested in socket exceptions, such as when the user clicks 'Cancel' during a file download. """ pass def wsgi_execute(self, environ=None): """ Invoke the server's ``wsgi_application``. """ self.wsgi_setup(environ) try: result = self.server.wsgi_application(self.wsgi_environ, self.wsgi_start_response) try: for chunk in result: self.wsgi_write_chunk(chunk) if not self.wsgi_headers_sent: self.wsgi_write_chunk('') finally: if hasattr(result,'close'): result.close() except socket.error, exce: self.wsgi_connection_drop(exce, environ) return except: if not self.wsgi_headers_sent: self.wsgi_curr_headers = ('500 Internal Server Error', [('Content-type', 'text/plain')]) self.wsgi_write_chunk("Internal Server Error\n") raise # # SSL Functionality # # This implementation was motivated by Sebastien Martini's SSL example # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/442473 # try: from OpenSSL import SSL SocketErrors = (socket.error, SSL.ZeroReturnError, SSL.SysCallError) except ImportError: # Do not require pyOpenSSL to be installed, but disable SSL # functionality in that case. SSL = None SocketErrors = (socket.error,) class SecureHTTPServer(HTTPServer): def __init__(self, server_address, RequestHandlerClass, ssl_context=None): assert not ssl_context, "pyOpenSSL not installed" HTTPServer.__init__(self, server_address, RequestHandlerClass) else: class _ConnFixer(object): """ wraps a socket connection so it implements makefile """ def __init__(self, conn): self.__conn = conn def makefile(self, mode, bufsize): return socket._fileobject(self.__conn, mode, bufsize) def __getattr__(self, attrib): return getattr(self.__conn, attrib) class SecureHTTPServer(HTTPServer): """ Provides SSL server functionality on top of the BaseHTTPServer by overriding _private_ members of Python's standard distribution. The interface for this instance only changes by adding a an optional ssl_context attribute to the constructor: cntx = SSL.Context(SSL.SSLv23_METHOD) cntx.use_privatekey_file("host.pem") cntx.use_certificate_file("host.pem") """ def __init__(self, server_address, RequestHandlerClass, ssl_context=None): # This overrides the implementation of __init__ in python's # SocketServer.TCPServer (which BaseHTTPServer.HTTPServer # does not override, thankfully). HTTPServer.__init__(self, server_address, RequestHandlerClass) self.socket = socket.socket(self.address_family, self.socket_type) self.ssl_context = ssl_context if ssl_context: self.socket = SSL.Connection(ssl_context, self.socket) self.server_bind() self.server_activate() def get_request(self): # The default SSL request object does not seem to have a # ``makefile(mode, bufsize)`` method as expected by # Socketserver.StreamRequestHandler. (conn,info) = self.socket.accept() if self.ssl_context: conn = _ConnFixer(conn) return (conn,info) class WSGIHandler(WSGIHandlerMixin, BaseHTTPRequestHandler): """ A WSGI handler that overrides POST, GET and HEAD to delegate requests to the server's ``wsgi_application``. """ server_version = 'PasteWSGIServer/' + __version__ do_POST = do_GET = do_HEAD = do_DELETE = do_PUT = do_TRACE = \ WSGIHandlerMixin.wsgi_execute def handle(self): # don't bother logging disconnects while handling a request try: BaseHTTPRequestHandler.handle(self) except SocketErrors, exce: self.wsgi_connection_drop(exce) class WSGIServer(ThreadingMixIn, SecureHTTPServer): daemon_threads = False 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) def serve(application, host=None, port=None, handler=None, ssl_pem=None, server_version=None, protocol_version=None, start_loop=True, daemon_threads=None, socket_timeout=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 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 ``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. """ ssl_context = None if ssl_pem: assert SSL, "pyOpenSSL is not installed" port = int(port or 4443) ssl_context = SSL.Context(SSL.SSLv23_METHOD) ssl_context.use_privatekey_file(ssl_pem) ssl_context.use_certificate_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 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 start_loop: print "serving on %s:%s" % server.server_address 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, *args, **kwargs): """ A simple HTTP server. Also supports SSL if you give it an ``ssl_pem`` argument, see documentation for ``serve()``. """ serve(wsgi_app, *args, **kwargs) if __name__ == '__main__': # serve exactly 3 requests and then stop, use an external # program like wget or curl to submit these 3 requests. 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") PK4:,paste/__init__.pytry: import pkg_resources pkg_resources.declare_namespace('paste') except ImportError: # don't prevent use of paste if pkg_resources isn't installed pass PK4a##paste/urlmap.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 """ Map URL prefixes to WSGI applications. See ``URLMap`` """ from UserDict import DictMixin import re import os import httpexceptions __all__ = ['URLMap', 'PathProxyURLMap'] def urlmap_factory(loader, global_conf, **local_conf): if 'not_found_app' in local_conf: not_found_app = local_conf.pop('not_found_app') else: not_found_app = global_conf.get('not_found_app') if not_found_app: not_found_app = loader.get_app(not_found_app, global_conf=global_conf) urlmap = URLMap(not_found_app=not_found_app) for path, app_name in local_conf.items(): path = parse_path_expression(path) app = loader.get_app(app_name, global_conf=global_conf) urlmap[path] = app return urlmap def parse_path_expression(path): """ Parses a path expression like 'domain foobar.com port 20 /' or just '/foobar' for a path alone. Returns as an address that URLMap likes. """ parts = path.split() domain = port = path = None while parts: if parts[0] == 'domain': parts.pop(0) if not parts: raise ValueError("'domain' must be followed with a domain name") if domain: raise ValueError("'domain' given twice") domain = parts.pop(0) elif parts[0] == 'port': parts.pop(0) if not parts: raise ValueError("'port' must be followed with a port number") if port: raise ValueError("'port' given twice") port = parts.pop(0) else: if path: raise ValueError("more than one path given (have %r, got %r)" % (path, parts[0])) path = parts.pop(0) s = '' if domain: s = 'http://%s' % domain if port: if not domain: raise ValueError("If you give a port, you must also give a domain") s += ':' + port if path: if s: s += '/' s += path return s class URLMap(DictMixin): """ URLMap instances are dictionary-like object that dispatch to one of several applications based on the URL. The dictionary keys are URLs to match (like ``PATH_INFO.startswith(url)``), and the values are applications to dispatch to. URLs are matched most-specific-first, i.e., longest URL first. The ``SCRIPT_NAME`` and ``PATH_INFO`` environmental variables are adjusted to indicate the new context. URLs can also include domains, like ``http://blah.com/foo``, or as tuples ``('blah.com', '/foo')``. This will match domain names; without the ``http://domain`` or with a domain of ``None`` any domain will be matched (so long as no other explicit domain matches). """ def __init__(self, not_found_app=None): self.applications = [] self.not_found_application = self.not_found_app norm_url_re = re.compile('//+') domain_url_re = re.compile('^(http|https)://') def not_found_app(self, environ, start_response): mapper = environ.get('paste.urlmap_object') if mapper: matches = [p for p, a in mapper.applications] extra = 'defined apps: %s' % ( ',\n '.join(map(repr, matches))) else: extra = '' extra += '\nSCRIPT_NAME: %r' % environ.get('SCRIPT_NAME') extra += '\nPATH_INFO: %r' % environ.get('PATH_INFO') extra += '\nHTTP_HOST: %r' % environ.get('HTTP_HOST') app = httpexceptions.HTTPNotFound( 'The resource was not found', comment=extra).wsgi_application return app(environ, start_response) def normalize_url(self, url, trim=True): if isinstance(url, (list, tuple)): domain = url[0] url = self.normalize_url(url[1])[1] return domain, url assert (not url or url.startswith('/') or self.domain_url_re.search(url)), ( "URL fragments must start with / or http:// (you gave %r)" % url) match = self.domain_url_re.search(url) if match: url = url[match.end():] if '/' in url: domain, url = url.split('/', 1) url = '/' + url else: domain, url = url, '' else: domain = None url = self.norm_url_re.sub('/', url) if trim: url = url.rstrip('/') return domain, url def sort_apps(self): """ Make sure applications are sorted with longest URLs first """ def key(app_desc): (domain, url), app = app_desc if not domain: # Make sure empty domains sort last: return -len(url), '\xff' else: return -len(url), domain apps = [(key(desc), desc) for desc in self.applications] apps.sort() self.applications = [desc for (sortable, desc) in apps] def __setitem__(self, url, app): if app is None: try: del self[url] except KeyError: pass return dom_url = self.normalize_url(url) if dom_url in self: del self[dom_url] self.applications.append((dom_url, app)) self.sort_apps() def __getitem__(self, url): dom_url = self.normalize_url(url) for app_url, app in self.applications: if app_url == dom_url: return app raise KeyError( "No application with the url %r (domain: %r; existing: %s)" % (url[1], url[0] or '*', self.applications)) def __delitem__(self, url): url = self.normalize_url(url) for app_url, app in self.applications: if app_url == url: self.applications.remove((app_url, app)) break else: raise KeyError( "No application with the url %r" % (url,)) def keys(self): return [app_url for app_url, app in self.applications] def __call__(self, environ, start_response): host = environ.get('HTTP_HOST', environ.get('SERVER_NAME')).lower() if ':' in host: host, port = host.split(':', 1) else: if environ['wsgi.url_scheme'] == 'http': port = '80' else: port = '443' path_info = environ.get('PATH_INFO') path_info = self.normalize_url(path_info, False)[1] for (domain, app_url), app in self.applications: if domain and domain != host and domain != host+':'+port: continue if (path_info == app_url or path_info.startswith(app_url + '/')): environ['SCRIPT_NAME'] += app_url environ['PATH_INFO'] = path_info[len(app_url):] return app(environ, start_response) environ['paste.urlmap_object'] = self return self.not_found_application(environ, start_response) class PathProxyURLMap(object): """ This is a wrapper for URLMap that catches any strings that are passed in as applications; these strings are treated as filenames (relative to `base_path`) and are passed to the callable `builder`, which will return an application. This is intended for cases when configuration files can be treated as applications. `base_paste_url` is the URL under which all applications added through this wrapper must go. Use ``""`` if you want this to not change incoming URLs. """ def __init__(self, map, base_paste_url, base_path, builder): self.map = map self.base_paste_url = self.map.normalize_url(base_paste_url) self.base_path = base_path self.builder = builder def __setitem__(self, url, app): if isinstance(app, (str, unicode)): app_fn = os.path.join(self.base_path, app) app = self.builder(app_fn) url = self.map.normalize_url(url) # @@: This means http://foo.com/bar will potentially # match foo.com, but /base_paste_url/bar, which is unintuitive url = (url[0] or self.base_paste_url[0], self.base_paste_url[1] + url[1]) self.map[url] = app def __getattr__(self, attr): return getattr(self.map, attr) # This is really the only settable attribute def not_found_application__get(self): return self.map.not_found_application def not_found_application__set(self, value): self.map.not_found_application = value not_found_application = property(not_found_application__get, not_found_application__set) PK4c>>paste/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 request import get_cookies, parse_querystring, parse_formvars from request import construct_url, path_info_split, path_info_pop from response import HeaderDict, has_header, header_value, remove_header from response import error_body_response, error_response, error_response_app from traceback import print_exception from Cookie import SimpleCookie from cStringIO import StringIO import mimetypes import os import cgi import sys import re from urlparse import urlsplit import warnings __all__ = ['get_cookies', 'add_close', 'raw_interactive', 'interactive', 'construct_url', 'error_body_response', 'error_response', 'send_file', 'has_header', 'header_value', 'path_info_split', 'path_info_pop', 'capture_output', 'catch_errors', 'dump_environ', 'intercept_output'] class add_close: """ 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 def __iter__(self): return self def next(self): return self.app_iter.next() def close(self): if hasattr(self.app_iterable, 'close'): self.app_iterable.close() self.close_func() 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. """ error_occurred = False 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. """ error_occurred = False 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: ok_callback() return app_iter else: return _wrap_app_iter_app( environ, start_response, app_iter, error_callback_app, ok_callback) class _wrap_app_iter_app(object): def __init__(self, environ, start_response, app_iterable, error_callback_app, ok_callback): 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 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: 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)) 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', 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) 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:: 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:: 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:: def dehtmlifying_middleware(application): def replacement_app(environ, start_response): status, headers, body = capture_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) 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.ResponseHeaderDict", 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() PK45D77 paste/url.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 """ This module implements a class for handling URLs. """ import urllib import cgi from paste import request # Imported lazily from FormEncode: variabledecode = None __all__ = ["URL", "Image"] def html_quote(v): if v is None: return '' return cgi.escape(str(v), 1) def url_quote(v): if v is None: return '' return urllib.quote(str(v)) url_unquote = urllib.unquote def js_repr(v): if v is None: return 'null' elif v is False: return 'false' elif v is True: return 'true' elif isinstance(v, list): return '[%s]' % ', '.join(map(js_repr, v)) elif isinstance(v, dict): return '{%s}' % ', '.join( ['%s: %s' % (js_repr(key), js_repr(value)) for key, value in v]) elif isinstance(v, str): return repr(v) elif isinstance(v, unicode): # @@: how do you do Unicode literals in Javascript? return repr(v.encode('UTF-8')) elif isinstance(v, (float, int)): return repr(v) elif isinstance(v, long): return repr(v).lstrip('L') elif hasattr(v, '__js_repr__'): return v.__js_repr__() else: raise ValueError( "I don't know how to turn %r into a Javascript representation" % v) class URLResource(object): """ This is an abstract superclass for different kinds of URLs """ default_params = {} def __init__(self, url, vars=None, attrs=None, params=None): self.url = url or '/' self.vars = vars or [] self.attrs = attrs or {} self.params = self.default_params.copy() self.original_params = params or {} if params: self.params.update(params) #@classmethod def from_environ(cls, environ, with_query_string=True, with_path_info=True, script_name=None, path_info=None, querystring=None): url = request.construct_url( environ, with_query_string=False, with_path_info=with_path_info, script_name=script_name, path_info=path_info) if with_query_string: if querystring is None: vars = request.parse_querystring(environ) else: vars = cgi.parse_qsl( querystring, keep_blank_values=True, strict_parsing=False) else: vars = None v = cls(url, vars=vars) return v from_environ = classmethod(from_environ) def __call__(self, *args, **kw): res = self._add_positional(args) res = res._add_vars(kw) return res def __getitem__(self, item): if '=' in item: name, value = item.split('=', 1) return self._add_vars({url_unquote(name): url_unquote(value)}) return self._add_positional((item,)) def attr(self, **kw): for key in kw.keys(): if key.endswith('_'): kw[key[:-1]] = kw[key] del kw[key] new_attrs = self.attrs.copy() new_attrs.update(kw) return self.__class__(self.url, vars=self.vars, attrs=new_attrs, params=self.original_params) def param(self, **kw): new_params = self.original_params.copy() new_params.update(kw) return self.__class__(self.url, vars=self.vars, attrs=self.attrs, params=new_params) def coerce_vars(self, vars): global variabledecode need_variable_encode = False for key, value in vars.items(): if isinstance(value, dict): need_variable_encode = True if key.endswith('_'): vars[key[:-1]] = vars[key] del vars[key] if need_variable_encode: if variabledecode is None: from formencode import variabledecode vars = variabledecode.variable_encode(vars) return vars def var(self, **kw): kw = self.coerce_vars(kw) new_vars = self.vars + kw.items() return self.__class__(self.url, vars=new_vars, attrs=self.attrs, params=self.original_params) def setvar(self, **kw): """ Like ``.var(...)``, except overwrites keys, where .var simply extends the keys. Setting a variable to None here will effectively delete it. """ kw = self.coerce_vars(kw) new_vars = [] for name, values in self.vars: if name in kw: continue new_vars.append((name, values)) new_vars.extend(kw.items()) return self.__class__(self.url, vars=new_vars, attrs=self.attrs, params=self.original_params) def addpath(self, *paths): u = self for path in paths: path = str(path).lstrip('/') new_url = u.url if not new_url.endswith('/'): new_url += '/' u = u.__class__(new_url+path, vars=u.vars, attrs=u.attrs, params=u.original_params) return u __div__ = addpath def become(self, OtherClass): return OtherClass(self.url, vars=self.vars, attrs=self.attrs, params=self.original_params) def href__get(self): s = self.url if self.vars: s += '?' vars = [] for name, val in self.vars: if isinstance(val, (list, tuple)): val = [v for v in val if v is not None] elif val is None: continue vars.append((name, val)) s += urllib.urlencode(vars, True) return s href = property(href__get) def __repr__(self): base = '<%s %s' % (self.__class__.__name__, self.href or "''") if self.attrs: base += ' attrs(%s)' % ( ' '.join(['%s="%s"' % (html_quote(n), html_quote(v)) for n, v in self.attrs.items()])) if self.original_params: base += ' params(%s)' % ( ', '.join(['%s=%r' % (n, v) for n, v in self.attrs.items()])) return base + '>' def html__get(self): if not self.params.get('tag'): raise ValueError( "You cannot get the HTML of %r until you set the " "'tag' param'" % self) content = self._get_content() tag = '<%s' % self.params.get('tag') attrs = ' '.join([ '%s="%s"' % (html_quote(n), html_quote(v)) for n, v in self._html_attrs()]) if attrs: tag += ' ' + attrs tag += self._html_extra() if content is None: return tag + ' />' else: return '%s>%s' % (tag, content, self.params.get('tag')) html = property(html__get) def _html_attrs(self): return self.attrs.items() def _html_extra(self): return '' def _get_content(self): """ Return the content for a tag (for self.html); return None for an empty tag (like ````) """ raise NotImplementedError def _add_vars(self, vars): raise NotImplementedError def _add_positional(self, args): raise NotImplementedError class URL(URLResource): r""" >>> 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' """ default_params = {'tag': 'a'} def __str__(self): return self.href def _get_content(self): if not self.params.get('content'): raise ValueError( "You must give a content param to %r generate anchor tags" % self) return self.params['content'] def _add_vars(self, vars): url = self for name in ('confirm', 'content'): if name in vars: url = url.param(**{name: vars.pop(name)}) if 'target' in vars: url = url.attr(target=vars.pop('target')) return url.var(**vars) def _add_positional(self, args): return self.addpath(*args) def _html_attrs(self): attrs = self.attrs.items() attrs.insert(0, ('href', self.href)) if self.params.get('confirm'): attrs.append(('onclick', 'return confirm(%s)' % js_repr(self.params['confirm']))) return attrs def onclick_goto__get(self): return 'location.href=%s; return false' % js_repr(self.href) onclick_goto = property(onclick_goto__get) def button__get(self): return self.become(Button) button = property(button__get) def js_popup__get(self): return self.become(JSPopup) js_popup = property(js_popup__get) class Image(URLResource): r""" >>> i = Image('/images') >>> i = i / '/foo.png' >>> i.html '' >>> str(i['alt=foo']) 'foo' >>> i.href '/images/foo.png' """ default_params = {'tag': 'img'} def __str__(self): return self.html def _get_content(self): return None def _add_vars(self, vars): return self.attr(**vars) def _add_positional(self, args): return self.addpath(*args) def _html_attrs(self): attrs = self.attrs.items() attrs.insert(0, ('src', self.href)) return attrs class Button(URLResource): r""" >>> u = URL('/') >>> u = u / 'delete' >>> b = u.button['confirm=Sure?'](id=5, content='del') >>> str(b) '' """ default_params = {'tag': 'button'} def __str__(self): return self.html def _get_content(self): if self.params.get('content'): return self.params['content'] if self.attrs.get('value'): return self.attrs['content'] # @@: Error? return None def _add_vars(self, vars): button = self if 'confirm' in vars: button = button.param(confirm=vars.pop('confirm')) if 'content' in vars: button = button.param(content=vars.pop('content')) return button.var(**vars) def _add_positional(self, args): return self.addpath(*args) def _html_attrs(self): attrs = self.attrs.items() onclick = 'location.href=%s' % js_repr(self.href) if self.params.get('confirm'): onclick = 'if (confirm(%s)) {%s}' % ( js_repr(self.params['confirm']), onclick) onclick += '; return false' attrs.insert(0, ('onclick', onclick)) return attrs class JSPopup(URLResource): r""" >>> u = URL('/') >>> u = u / 'view' >>> j = u.js_popup(content='view') >>> j.html 'view' """ default_params = {'tag': 'a', 'target': '_blank'} def _add_vars(self, vars): button = self for var in ('width', 'height', 'stripped', 'content'): if var in vars: button = button.param(**{var: vars.pop(var)}) return button.var(**vars) def _window_args(self): p = self.params features = [] if p.get('stripped'): p['location'] = p['status'] = p['toolbar'] = '0' for param in 'channelmode directories fullscreen location menubar resizable scrollbars status titlebar'.split(): if param not in p: continue v = p[param] if v not in ('yes', 'no', '1', '0'): if v: v = '1' else: v = '0' features.append('%s=%s' % (param, v)) for param in 'height left top width': if not p.get(param): continue features.append('%s=%s' % (param, p[param])) args = [self.href, p['target']] if features: args.append(','.join(features)) return ', '.join(map(js_repr, args)) def _html_attrs(self): attrs = self.attrs.items() onclick = ('window.open(%s); return false' % self._window_args()) attrs.insert(0, ('target', self.params['target'])) attrs.insert(0, ('onclick', onclick)) attrs.insert(0, ('href', self.href)) return attrs def _get_content(self): if not self.params.get('content'): raise ValueError( "You must give a content param to %r generate anchor tags" % self) return self.params['content'] def _add_positional(self, args): return self.addpath(*args) if __name__ == '__main__': import doctest doctest.testmod() PK4.l l 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.deploy import converters __all__ = ['CGIError', 'CGIApplication'] class CGIError(Exception): pass 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): self.script_filename = script if path is None: path = (global_conf.get('path') or global_conf.get('PATH')) if path is None: path = os.environ.get('PATH', '').split(':') self.path = converters.aslist(path, ':') if '?' in script: assert query_string is None, ( "You cannot have '?' in your script name (%r) and also " "give a query_string (%r)" % (self.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 = converters.asbool(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() PK43A A paste/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. """ import httpexceptions 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: 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, 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) PK4 7)paste/recursive.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 """ 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 ``ForewardRequestException(new_path_info)`` to do a forward (aborting the current request). """ from cStringIO import StringIO import warnings __all__ = ['RecursiveMiddleware'] class RecursiveMiddleware(object): """ 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. """ def __init__(self, application, global_conf=None): self.application = application def __call__(self, environ, start_response): environ['paste.recursive.forward'] = Forwarder( self.application, environ, start_response) environ['paste.recursive.include'] = Includer( self.application, environ, start_response) my_script_name = environ.get('SCRIPT_NAME', '') current_path_info = environ.get('PATH_INFO', '') environ['paste.recursive.script_name'] = my_script_name try: return self.application(environ, start_response) except ForwardRequestException, e: if e.path_info in environ.get( 'paste.recursive.old_path_info', []): raise AssertionError( "Forwarding loop detected; %r visited twice (internal " "redirect path: %s)" % (e.path_info, environ['paste.recursive.old_path_info'])) environ.setdefault('paste.recursive.old_path_info', []).append(current_path_info) environ['SCRIPT_NAME'] = my_script_name environ['PATH_INFO'] = e.path_info return self(environ, start_response) class ForwardRequestException(Exception): """ Used to signal that a request should be forwarded to a different location. The ``path_info`` attribute (passed in as an argument to the constructor) is the position under the recursive middleware to redirect to. """ def __init__(self, path_info): self.path_info = path_info class Recursive(object): def __init__(self, application, environ, start_response): self.application = application self.original_environ = environ.copy() self.previous_environ = environ self.start_response = start_response def __call__(self, path, new_environ=None): """ `extra_environ` is an optional dictionary that is also added to the forwarded request. E.g., ``{'HTTP_HOST': 'new.host'}`` could be used to forward to a different virtual host. """ environ = self.original_environ.copy() if new_environ: environ.update(new_environ) environ['paste.recursive.previous_environ'] = self.previous_environ base_path = self.original_environ.get('SCRIPT_NAME') if path.startswith('/'): assert path.startswith(base_path), ( "You can only forward requests to resources under the " "path %r (not %r)" % (base_path, path)) path = path[len(base_path)+1:] assert not path.startswith('/') path_info = '/' + path environ['PATH_INFO'] = path_info environ['REQUEST_METHOD'] = 'GET' return self.activate(environ) def __repr__(self): return '<%s.%s from %s>' % ( self.__class__.__module__, self.__class__.__name__, self.original_environ.get('SCRIPT_NAME') or '/') class Forwarder(Recursive): """ 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:: 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. """ def activate(self, environ): warnings.warn( "recursive.Forwarder has been deprecated; please use " "ForwardRequestException", DeprecationWarning, 2) return self.application(environ, self.start_response) class Includer(Recursive): """ Starts another request with the given path and adding or overwriting any values in the `extra_environ` dictionary. Returns an IncludeResponse object. """ def activate(self, environ): response = IncludedResponse() def start_response(status, headers, exc_info=None): if exc_info: raise exc_info[0], exc_info[1], exc_info[2] response.status = status response.headers = headers return response.write app_iter = self.application(environ, start_response) try: for s in app_iter: response.write(s) finally: if hasattr(app_iter, 'close'): app_iter.close() response.close() return response class IncludedResponse(object): def __init__(self): self.headers = None self.status = None self.output = StringIO() self.str = None def close(self): self.str = self.output.getvalue() self.output.close() self.output = None def write(self, s): assert self.output is not None, ( "This response has already been closed and no further data " "can be written.") self.output.write(s) def __str__(self): return self.body def body__get(self): if self.str is None: return self.output.getvalue() else: return self.str body = property(body__get) PK4paste/error_document.pyimport warnings # Deprecated Mar 3 2006 (remove quickly: April 2006) warnings.warn( 'paste.error_document has been moved to paste.errordocument', DeprecationWarning, 2) from paste.errordocument import * PK4lGkkpaste/httpheaders.py# (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 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(connection) 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]) 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)) return value 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 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("=") 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 _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 = "%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: 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) PK4m:[XXpaste/urlparser.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 applications that parse the URL and dispatch to on-disk resources """ import os import sys import imp import pkg_resources import mimetypes import request import fileapp from paste.util import import_string from paste.deploy import converters import httpexceptions from httpheaders import ETAG class NoDefault: pass __all__ = ['URLParser', 'StaticURLParser', 'PkgResourcesParser'] class URLParser(object): """ 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 modified 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. """ parsers_by_directory = {} # This is lazily initialized init_module = NoDefault global_constructors = {} def __init__(self, global_conf, directory, base_python_name, index_names=NoDefault, hide_extensions=NoDefault, ignore_extensions=NoDefault, constructors=None, **constructor_conf): """ Create a URLParser object that looks at `directory`. `base_python_name` is the package that this directory represents, thus any Python modules in this directory will be given names under this package. """ if os.path.sep != '/': directory = directory.replace(os.path.sep, '/') self.directory = directory self.base_python_name = base_python_name if index_names is NoDefault: index_names = global_conf.get( 'index_names', ('index', 'Index', 'main', 'Main')) self.index_names = converters.aslist(index_names) if hide_extensions is NoDefault: hide_extensions = global_conf.get( 'hide_extensions', ('.pyc', 'bak', 'py~')) self.hide_extensions = converters.aslist(hide_extensions) if ignore_extensions is NoDefault: ignore_extensions = global_conf.get( 'ignore_extensions', ()) self.ignore_extensions = converters.aslist(ignore_extensions) self.constructors = self.global_constructors.copy() if constructors: self.constructors.update(constructors) # @@: Should we also check the global options for constructors? for name, value in constructor_conf.items(): if not name.startswith('constructor '): raise ValueError( "Only extra configuration keys allowed are " "'constructor .ext = import_expr'; you gave %r " "(=%r)" % (name, value)) ext = name[len('constructor '):].strip() if isinstance(value, (str, unicode)): value = import_string.eval_import(value) self.constructors[ext] = value def __call__(self, environ, start_response): environ['paste.urlparser.base_python_name'] = self.base_python_name if self.init_module is NoDefault: self.init_module = self.find_init_module(environ) path_info = environ.get('PATH_INFO', '') if not path_info: return self.add_slash(environ, start_response) if (self.init_module and getattr(self.init_module, 'urlparser_hook', None)): self.init_module.urlparser_hook(environ) orig_path_info = environ['PATH_INFO'] orig_script_name = environ['SCRIPT_NAME'] application, filename = self.find_application(environ) if not application: if (self.init_module and getattr(self.init_module, 'not_found_hook', None) and environ.get('paste.urlparser.not_found_parser') is not self): not_found_hook = self.init_module.not_found_hook environ['paste.urlparser.not_found_parser'] = self environ['PATH_INFO'] = orig_path_info environ['SCRIPT_NAME'] = orig_script_name return not_found_hook(environ, start_response) if filename is None: name, rest_of_path = request.path_info_split(environ['PATH_INFO']) if not name: name = 'one of %s' % ', '.join( self.index_names or ['(no index_names defined)']) return self.not_found( environ, start_response, 'Tried to load %s from directory %s' % (name, self.directory)) else: environ['wsgi.errors'].write( 'Found resource %s, but could not construct application\n' % filename) return self.not_found( environ, start_response, 'Tried to load %s from directory %s' % (filename, self.directory)) if (self.init_module and getattr(self.init_module, 'urlparser_wrap', None)): return self.init_module.urlparser_wrap( environ, start_response, application) else: return application(environ, start_response) def find_application(self, environ): if (self.init_module and getattr(self.init_module, 'application', None) and not environ.get('paste.urlparser.init_application') == environ['SCRIPT_NAME']): environ['paste.urlparser.init_application'] = environ['SCRIPT_NAME'] return self.init_module.application, None name, rest_of_path = request.path_info_split(environ['PATH_INFO']) environ['PATH_INFO'] = rest_of_path if name is not None: environ['SCRIPT_NAME'] = environ.get('SCRIPT_NAME', '') + '/' + name if not name: names = self.index_names for index_name in names: filename = self.find_file(environ, index_name) if filename: break else: # None of the index files found filename = None else: filename = self.find_file(environ, name) if filename is None: return None, filename else: return self.get_application(environ, filename), filename def not_found(self, environ, start_response, debug_message=None): exc = httpexceptions.HTTPNotFound( 'The resource at %s could not be found' % request.construct_url(environ), comment='SCRIPT_NAME=%r; PATH_INFO=%r; looking in %r; debug: %s' % (environ.get('SCRIPT_NAME'), environ.get('PATH_INFO'), self.directory, debug_message or '(none)')) return exc.wsgi_application(environ, start_response) def add_slash(self, environ, start_response): """ This happens when you try to get to a directory without a trailing / """ url = request.construct_url(environ, with_query_string=False) url += '/' if environ.get('QUERY_STRING'): url += '?' + environ['QUERY_STRING'] exc = httpexceptions.HTTPMovedPermanently( 'The resource has moved to %s - you should be redirected ' 'automatically.''' % url, headers=[('location', url)]) return exc.wsgi_application(environ, start_response) def find_file(self, environ, base_filename): possible = [] """Cache a few values to reduce function call overhead""" for filename in os.listdir(self.directory): base, ext = os.path.splitext(filename) full_filename = os.path.join(self.directory, filename) if (ext in self.hide_extensions or not base): continue if filename == base_filename: possible.append(full_filename) continue if ext in self.ignore_extensions: continue if base == base_filename: possible.append(full_filename) if not possible: #environ['wsgi.errors'].write( # 'No file found matching %r in %s\n' # % (base_filename, self.directory)) return None if len(possible) > 1: # If there is an exact match, this isn't 'ambiguous' # per se; it might mean foo.gif and foo.gif.back for # instance if full_filename in possible: return full_filename else: environ['wsgi.errors'].write( 'Ambiguous URL: %s; matches files %s\n' % (request.construct_url(environ), ', '.join(possible))) return None return possible[0] def get_application(self, environ, filename): if os.path.isdir(filename): t = 'dir' else: t = os.path.splitext(filename)[1] constructor = self.constructors.get(t, self.constructors.get('*')) if constructor is None: #environ['wsgi.errors'].write( # 'No constructor found for %s\n' % t) return constructor app = constructor(self, environ, filename) if app is None: #environ['wsgi.errors'].write( # 'Constructor %s return None for %s\n' % # (constructor, filename)) pass return app def register_constructor(cls, extension, constructor): """ Register a function as a constructor. Registered constructors apply to all instances of `URLParser`. The extension should have a leading ``.``, or the special extensions ``dir`` (for directories) and ``*`` (a catch-all). `constructor` must be a callable that takes two arguments: ``environ`` and ``filename``, and returns a WSGI application. """ d = cls.global_constructors assert not d.has_key(extension), ( "A constructor already exists for the extension %r (%r) " "when attemption to register constructor %r" % (extension, d[extension], constructor)) d[extension] = constructor register_constructor = classmethod(register_constructor) def get_parser(self, directory, base_python_name): """ Get a parser for the given directory, or create one if necessary. This way parsers can be cached and reused. # @@: settings are inherited from the first caller """ try: return self.parsers_by_directory[(directory, base_python_name)] except KeyError: parser = self.__class__( {}, directory, base_python_name, index_names=self.index_names, hide_extensions=self.hide_extensions, ignore_extensions=self.ignore_extensions, constructors=self.constructors) self.parsers_by_directory[(directory, base_python_name)] = parser return parser def find_init_module(self, environ): filename = os.path.join(self.directory, '__init__.py') if not os.path.exists(filename): return None return load_module(environ, filename) def __repr__(self): return '<%s directory=%r; module=%s at %s>' % ( self.__class__.__name__, self.directory, self.base_python_name, hex(abs(id(self)))) def make_directory(parser, environ, filename): base_python_name = environ['paste.urlparser.base_python_name'] if base_python_name: base_python_name += "." + os.path.basename(filename) else: base_python_name = os.path.basename(filename) return parser.get_parser(filename, base_python_name) URLParser.register_constructor('dir', make_directory) def make_unknown(parser, environ, filename): return fileapp.FileApp(filename) URLParser.register_constructor('*', make_unknown) def load_module(environ, filename): base_python_name = environ['paste.urlparser.base_python_name'] module_name = os.path.splitext(os.path.basename(filename))[0] if base_python_name: module_name = base_python_name + '.' + module_name return load_module_from_name(environ, filename, module_name, environ['wsgi.errors']) def load_module_from_name(environ, filename, module_name, errors): if sys.modules.has_key(module_name): return sys.modules[module_name] init_filename = os.path.join(os.path.dirname(filename), '__init__.py') if not os.path.exists(init_filename): try: f = open(init_filename, 'w') except (OSError, IOError), e: errors.write( 'Cannot write __init__.py file into directory %s (%s)\n' % (os.path.dirname(filename), e)) return None f.write('#\n') f.close() fp = None if sys.modules.has_key(module_name): return sys.modules[module_name] if '.' in module_name: parent_name = '.'.join(module_name.split('.')[:-1]) base_name = module_name.split('.')[-1] parent = load_module_from_name(environ, os.path.dirname(filename), parent_name, errors) else: base_name = module_name fp = None try: fp, pathname, stuff = imp.find_module( base_name, [os.path.dirname(filename)]) module = imp.load_module(module_name, fp, pathname, stuff) finally: if fp is not None: fp.close() return module def make_py(parser, environ, filename): module = load_module(environ, filename) if not module: return None if hasattr(module, 'application') and module.application: return getattr(module.application, 'wsgi_application', module.application) base_name = module.__name__.split('.')[-1] if hasattr(module, base_name): obj = getattr(module, base_name) if hasattr(obj, 'wsgi_application'): return obj.wsgi_application else: # @@: Old behavior; should probably be deprecated eventually: return getattr(module, base_name)() environ['wsgi.errors'].write( "Cound not find application or %s in %s\n" % (base_name, module)) return None URLParser.register_constructor('.py', make_py) class StaticURLParser(object): """ Like ``URLParser`` but only serves static files. """ # @@: Should URLParser subclass from this? def __init__(self, directory): if os.path.sep != '/': directory = directory.replace(os.path.sep, '/') self.directory = directory def __call__(self, environ, start_response): path_info = environ.get('PATH_INFO', '') if not path_info: return self.add_slash(environ, start_response) if path_info == '/': # @@: This should obviously be configurable filename = 'index.html' else: filename = request.path_info_pop(environ) full = os.path.join(self.directory, filename) if not os.path.exists(full): return self.not_found(environ, start_response) if os.path.isdir(full): # @@: Cache? return self.__class__(full)(environ, start_response) if environ.get('PATH_INFO') and environ.get('PATH_INFO') != '/': return self.error_extra_path(environ, start_response) if_none_match = environ.get('HTTP_IF_NONE_MATCH') if if_none_match: mytime = os.stat(full).st_mtime if str(mytime) == if_none_match: headers = [] ETAG.update(headers, mytime) start_response('304 Not Modified',headers) return [''] # empty body return fileapp.FileApp(full)(environ, start_response) def add_slash(self, environ, start_response): """ This happens when you try to get to a directory without a trailing / """ url = request.construct_url(environ, with_query_string=False) url += '/' if environ.get('QUERY_STRING'): url += '?' + environ['QUERY_STRING'] exc = httpexceptions.HTTPMovedPermanently( 'The resource has moved to %s - you should be redirected ' 'automatically.''' % url, headers=[('location', url)]) return exc.wsgi_application(environ, start_response) def not_found(self, environ, start_response, debug_message=None): exc = httpexceptions.HTTPNotFound( 'The resource at %s could not be found' % request.construct_url(environ), comment='SCRIPT_NAME=%r; PATH_INFO=%r; looking in %r; debug: %s' % (environ.get('SCRIPT_NAME'), environ.get('PATH_INFO'), self.directory, debug_message or '(none)')) return exc.wsgi_application(environ, start_response) def error_extra_path(self, environ, start_response): exc = httpexceptions.HTTPBadRequest( 'The trailing path %r is not allowed' % environ['PATH_INFO']) return exc.wsgi_application(environ, start_response) def __repr__(self): return '<%s %r>' % (self.__class__.__name__, self.directory) def make_static(global_conf, document_root): """ Return a WSGI application that serves a directory (configured with document_root) """ return StaticURLParser(document_root) class PkgResourcesParser(StaticURLParser): def __init__(self, egg_or_spec, resource_name, manager=None): if isinstance(egg_or_spec, (str, unicode)): self.egg = pkg_resources.get_distribution(egg_or_spec) else: self.egg = egg_or_spec self.resource_name = resource_name if manager is None: manager = pkg_resources.ResourceManager() self.manager = manager def __repr__(self): return '<%s for %s:%r>' % ( self.__class__.__name__, self.egg.project_name, self.resource_name) def __call__(self, environ, start_response): path_info = environ.get('PATH_INFO', '') if not path_info: return self.add_slash(environ, start_response) if path_info == '/': # @@: This should obviously be configurable filename = 'index.html' else: filename = request.path_info_pop(environ) resource = self.resource_name + '/' + filename if not self.egg.has_resource(resource): return self.not_found(environ, start_response) if self.egg.resource_isdir(resource): # @@: Cache? return self.__class__(self.egg, resource, self.manager)(environ, start_response) if environ.get('PATH_INFO') and environ.get('PATH_INFO') != '/': return self.error_extra_path(environ, start_response) type, encoding = mimetypes.guess_type(resource) if not type: type = 'application/octet-stream' # @@: I don't know what to do with the encoding. try: file = self.egg.get_resource_stream(self.manager, resource) except (IOError, OSError), e: exc = httpexceptions.HTTPForbidden( 'You are not permitted to view this file (%s)' % e) return exc.wsgi_application(environ, start_response) start_response('200 OK', [('content-type', type)]) return fileapp._FileIter(file) def not_found(self, environ, start_response, debug_message=None): exc = httpexceptions.HTTPNotFound( 'The resource at %s could not be found' % request.construct_url(environ), comment='SCRIPT_NAME=%r; PATH_INFO=%r; looking in egg:%s#%r; debug: %s' % (environ.get('SCRIPT_NAME'), environ.get('PATH_INFO'), self.egg, self.resource_name, debug_message or '(none)')) return exc.wsgi_application(environ, start_response) def make_pkg_resources(global_conf, egg, resource_name=''): """ 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. """ return PkgResourcesParser(egg, resource_name) PK4'paste/fileapp.py# (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 """ 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. """ import os, time, mimetypes from httpexceptions import * from httpheaders import * CACHE_SIZE = 4096 BLOCK_SIZE = 4096 * 16 __all__ = ['DataApp','FileApp'] class DataApp(object): """ Returns an application that will send content in a single chunk, this application has support for setting cashe-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. """ def __init__(self, content, headers=None, **kwargs): assert isinstance(headers,(type(None),list)) self.expires = None self.content = None self.content_length = None self.last_modified = 0 self.headers = headers or [] for (k,v) in kwargs.items(): header = get_header(k) header.update(self.headers,v) ACCEPT_RANGES.update(self.headers,bytes=True) if not CONTENT_TYPE(self.headers): CONTENT_TYPE.update(self.headers) if content: self.set_content(content) def cache_control(self, **kwargs): self.expires = CACHE_CONTROL.apply(self.headers, **kwargs) or None return self def set_content(self, content): assert content is not None self.last_modified = time.time() self.content = content self.content_length = len(content) LAST_MODIFIED.update(self.headers, time=self.last_modified) return self def content_disposition(self, **kwargs): CONTENT_DISPOSITION.apply(self.headers, **kwargs) return self def __call__(self, environ, start_response): headers = self.headers[:] ETAG.update(headers, self.last_modified) if self.expires is not None: EXPIRES.update(headers, delta=self.expires) try: client_clock = IF_MODIFIED_SINCE.parse(environ) if client_clock >= int(self.last_modified): # horribly inefficient, n^2 performance, yuck! for head in list_headers(entity=True): head.delete(headers) start_response('304 Not Modified',headers) return [''] # empty body except HTTPBadRequest, exce: return exce.wsgi_application(environ, start_response) (lower,upper) = (0, self.content_length - 1) range = RANGE.parse(environ) if range and 'bytes' == range[0] and 1 == len(range[1]): (lower,upper) = range[1][0] upper = upper or (self.content_length - 1) if upper >= self.content_length or lower > upper: return HTTPRequestRangeNotSatisfiable(( "Range request was made beyond the end of the content,\r\n" "which is %s long.\r\n Range: %s\r\n") % ( self.content_length, RANGE(environ)) ).wsgi_application(environ, start_response) content_length = upper - lower + 1 CONTENT_RANGE.update(headers, first_byte=lower, last_byte=upper, total_length = self.content_length) CONTENT_LENGTH.update(headers, content_length) if content_length == self.content_length: start_response('200 OK', headers) else: start_response('206 Partial Content', headers) if self.content is not None: return [self.content[lower:upper+1]] assert self.__class__ != DataApp, "DataApp must call set_content" return (lower, content_length) class FileApp(DataApp): """ 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``. """ def __init__(self, filename, headers=None, **kwargs): self.filename = filename content_type, content_encoding = mimetypes.guess_type(self.filename) if content_type and 'content_type' not in kwargs: kwargs['content_type'] = content_type if content_encoding and 'content_encoding' not in kwargs: kwargs['content_encoding'] = content_encoding DataApp.__init__(self, None, headers, **kwargs) def update(self, force=False): stat = os.stat(self.filename) if not force and stat.st_mtime == self.last_modified: return if stat.st_size < CACHE_SIZE: fh = open(self.filename,"rb") self.set_content(fh.read()) fh.close() else: self.content = None self.content_length = stat.st_size self.last_modified = stat.st_mtime def __call__(self, environ, start_response): if 'max-age=0' in CACHE_CONTROL(environ).lower(): self.update(force=True) # RFC 2616 13.2.6 else: self.update() if not self.content: try: file = open(self.filename, 'rb') except (IOError, OSError), e: exc = HTTPForbidden( 'You are not permitted to view this file (%s)' % e) return exc.wsgi_application( environ, start_response) retval = DataApp.__call__(self, environ, start_response) if isinstance(retval,list): # cached content, exception, or not-modified return retval (lower, content_length) = retval file.seek(lower) return _FileIter(file, size=content_length) class _FileIter: def __init__(self, file, block_size=None, size=None): self.file = file self.size = size self.block_size = block_size or BLOCK_SIZE def __iter__(self): return self def next(self): chunk_size = self.block_size if self.size is not None: if chunk_size > self.size: chunk_size = self.size self.size -= chunk_size data = self.file.read(chunk_size) if not data: raise StopIteration return data def close(self): self.file.close() PK4}I-paste/gzipper.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 middleware Gzip-encodes the response. """ import gzip import wsgilib class GzipOutput(object): pass class middleware(object): def __init__(self, application, global_conf, compress_level=5): self.application = application self.compress_level = int(compress_level) def __call__(self, environ, start_response): if 'gzip' not in environ.get('HTTP_ACCEPT_ENCODING', ''): # nothing for us to do, so this middleware will # be a no-op: return self.application(environ, start_response) response = GzipResponse(start_response, self.compress_level) app_iter = self.application(environ, response.gzip_start_response) try: if app_iter: response.finish_response(app_iter) finally: response.close() return None class GzipResponse(object): def __init__(self, start_response, compress_level): self.start_response = start_response self.compress_level = compress_level self.gzip_fileobj = None def gzip_start_response(self, status, headers, exc_info=None): # This isn't part of the spec yet: if wsgilib.has_header(headers, 'content-encoding'): # we won't double-encode return self.start_response(status, headers, exc_info) headers.append(('content-encoding', 'gzip')) raw_writer = self.start_response(status, headers, exc_info) dummy_fileobj = GzipOutput() dummy_fileobj.write = raw_writer self.gzip_fileobj = gzip.GzipFile('', 'wb', self.compress_level, dummy_fileobj) return self.gzip_fileobj.write def finish_response(self, app_iter): try: for s in app_iter: self.gzip_fileobj.write(s) finally: if hasattr(app_iter, 'close'): app_iter.close() def close(self): self.gzip_fileobj.close() PK4X\paste/proxy.py""" An application that proxies WSGI requests to a remote server. TODO: * Send ``Via`` header? It's not clear to me this is a Via in the style of a typical proxy. * Other headers or metadata? I put in X-Forwarded-For, but that's it. * Signed data of non-HTTP keys? This would be for things like REMOTE_USER. * Something to indicate what the original URL was? The original host, scheme, and base path. * Rewriting ``Location`` headers? mod_proxy does this. * Rewriting body? (Probably not on this one -- that can be done with a different middleware that wraps this middleware) * Example:: use = egg:Paste#proxy address = http://server3:8680/exist/rest/db/orgs/sch/config/ allowed_request_methods = GET """ import httplib import urlparse from paste import httpexceptions # Remove these headers from response (specify lower case header # names): filtered_headers = ( 'transfer-encoding', ) class Proxy(object): def __init__(self, address, allowed_request_methods=()): self.address = address self.parsed = urlparse.urlsplit(address) self.scheme = self.parsed[0].lower() self.host = self.parsed[1] self.path = self.parsed[2] self.allowed_request_methods = [ x.lower() for x in allowed_request_methods if x] def __call__(self, environ, start_response): if (self.allowed_request_methods and environ['REQUEST_METHOD'].lower() not in self.allowed_request_methods): return httpexceptions.HTTPBadRequest("Disallowed")(environ, start_response) if self.scheme == 'http': ConnClass = httplib.HTTPConnection elif self.scheme == 'https': ConnClass = httplib.HTTPSConnection else: raise ValueError( "Unknown scheme for %r: %r" % (self.address, self.scheme)) conn = ConnClass(self.host) headers = {} for key, value in environ.items(): if key.startswith('HTTP_'): key = key[5:].lower().replace('_', '-') if key == 'host': continue headers[key] = value headers['host'] = self.host if 'REMOTE_ADDR' in environ: headers['x-forwarded-for'] = environ['REMOTE_ADDR'] if environ.get('CONTENT_TYPE'): headers['content-type'] = environ['CONTENT_TYPE'] if environ.get('CONTENT_LENGTH'): length = int(environ['CONTENT_LENGTH']) body = environ['wsgi.input'].read(length) else: body = '' if self.path: request_path = environ['PATH_INFO'] if request_path[0] == '/': request_path = request_path[1:] path = urlparse.urljoin(self.path, request_path) else: path = environ['PATH_INFO'] conn.request(environ['REQUEST_METHOD'], path, body, headers) res = conn.getresponse() headers_out = [] for header, value in res.getheaders(): if header.lower() not in filtered_headers: headers_out.append((header, value)) status = '%s %s' % (res.status, res.reason) start_response(status, headers_out) # @@: Default? length = res.getheader('content-length') if length is not None: body = res.read(int(length)) else: body = res.read() conn.close() return [body] def make_proxy(global_conf, address, allowed_request_methods=""): """ Make a WSGI application that proxies to another address -- 'address' should be the full URL ending with a trailing / 'allowed_request_methods' is a space seperated list of request methods """ from paste.deploy.converters import aslist allowed_request_methods = aslist(allowed_request_methods) return Proxy(address, allowed_request_methods=allowed_request_methods) PK4> > paste/cascade.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 """ Cascades through several applications, so long as applications return ``404 Not Found``. """ import httpexceptions from paste.deploy import converters __all__ = ['Cascade'] def make_cascade(loader, global_conf, catch='404', **local_conf): """ Expects configuration like: [composit:cascade] use = egg:Paste#cascade # all start with 'app' and are sorted alphabetically app1 = foo app2 = bar ... catch = 404 500 ... """ catch = map(int, converters.aslist(catch)) apps = [] for name, value in local_conf.items(): if not name.startswith('app'): raise ValueError( "Bad configuration key %r (=%r); all configuration keys " "must start with 'app'" % (name, value)) app = loader.get_app(value, global_conf=global_conf) apps.append((name, app)) apps.sort() apps = [app for name, app in apps] return Cascade(apps, catch=catch) class Cascade(object): """ Passed a list of applications, ``Cascade`` will try each of them in turn. If one returns a status code listed in ``catch`` (by default just ``404 Not Found``) then the next application is tried. If all applications fail, then the last application's failure response is used. """ def __init__(self, applications, catch=(404,)): self.apps = applications self.catch_codes = {} self.catch_exceptions = [] for error in catch: if isinstance(error, str): error = int(error.split(None, 1)[0]) if isinstance(error, httpexceptions.HTTPException): exc = error code = error.code else: exc = httpexceptions.get_exception(error) code = error self.catch_codes[code] = exc self.catch_exceptions.append(exc) self.catch_exceptions = tuple(self.catch_exceptions) def __call__(self, environ, start_response): failed = [] def repl_start_response(status, headers, exc_info=None): code = int(status.split(None, 1)[0]) if code in self.catch_codes: failed.append(None) return _consuming_writer return start_response(status, headers, exc_info) for app in self.apps[:-1]: environ_copy = environ.copy() failed = [] try: v = app(environ_copy, repl_start_response) if not failed: return v else: if hasattr(v, 'close'): # Exhaust the iterator first: list(v) # then close: v.close() except self.catch_exceptions, e: pass return self.apps[-1](environ, start_response) def _consuming_writer(s): pass PK4T paste/pony.py""" We have a pony """ DATA = """ eJyFkkFuxCAMRfdzCisbJxK2D5D2JpbMrlI3XXQZDt9PCG0ySgcWIMT79rcN0XClUJlZRB9jVmci FmV19khjgRFl0RzrKmqzvY8lRUWFlXvCrD7UbAQR/17NUvGhypAF9og16vWtkC8DzUayS6pN3/dR ki0OnpzKjUBFpmlC7zVFRNL1rwoq6PWXXQSnIm9WoTzlM2//ke21o5g/l1ckRhiPbkDZXsKIR7l1 36hF9uMhnRiVjI8UgYjlsIKCrXXpcA9iX5y7zMmtG0fUpW61Ssttipf6cp3WARfkMVoYFryi2a+w o/2dhW0OXfcMTnmh53oR9egzPs+qkpY9IKxdUVRP5wHO7UDAuI6moA2N+/z4vtc2k8B+AIBimVU= """ class PonyMiddleware(object): def __init__(self, application): self.application = application def __call__(self, environ, start_response): path_info = environ.get('PATH_INFO', '') if path_info == '/pony': msg = DATA.decode('base64').decode('zlib') msg = '
%s
' % msg start_response('200 OK', [('content-type', 'text/html')]) return [msg] else: return self.application(environ, start_response) def make_pony(app, global_conf): return PonyMiddleware(app) PK4 >paste/fixture.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 """ 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. """ import sys import random import urllib import urlparse import mimetypes import time import cgi import os import shutil import webbrowser import smtplib import shlex from Cookie import SimpleCookie try: from cStringIO import StringIO except ImportError: from StringIO import StringIO import re try: import subprocess except ImportError: from paste.util import subprocess24 as subprocess from paste import wsgilib from paste import lint from paste.response import HeaderDict def tempnam_no_warning(*args): """ 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. """ return os.tempnam(*args) class NoDefault: pass def sorted(l): l = list(l) l.sort() return l class Dummy_smtplib(object): existing = None def __init__(self, server): assert not self.existing, ( "smtplib.SMTP() called again before Dummy_smtplib.existing.reset() " "called.") self.server = server self.open = True self.__class__.existing = self def quit(self): assert self.open, ( "Called %s.quit() twice" % self) self.open = False def sendmail(self, from_address, to_addresses, msg): self.from_address = from_address self.to_addresses = to_addresses self.message = msg def install(cls): smtplib.SMTP = cls install = classmethod(install) def reset(self): assert not self.open, ( "SMTP connection not quit") self.__class__.existing = None class AppError(Exception): pass class TestApp(object): # for py.test disabled = True def __init__(self, app, namespace=None, relative_to=None, extra_environ=None): """ 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. """ if isinstance(app, (str, unicode)): from paste.deploy import loadapp # @@: Should pick up relative_to from calling module's # __file__ app = loadapp(app, relative_to=relative_to) self.app = app self.namespace = namespace self.relative_to = relative_to if extra_environ is None: extra_environ = {} self.extra_environ = extra_environ self.reset() def reset(self): """ Resets the state of the application; currently just clears saved cookies. """ self.cookies = {} def _make_environ(self): environ = self.extra_environ.copy() environ['paste.throw_errors'] = True return environ def get(self, url, params=None, headers={}, extra_environ={}, status=None, expect_errors=False): """ Get the given url (well, actually a path like ``'/page.html'``). ``params``: A query string, or a dictionary that will be encoded into a query string. You may also include a query string on the ``url``. ``headers``: A dictionary of extra headers to send. ``extra_environ``: A dictionary of environmental variables that should be added to the request. ``status``: The integer status code you expect (if not 200 or 3xx). If you expect a 404 response, for instance, you must give ``status=404`` or it will be an error. You can also give a wildcard, like ``'3*'`` or ``'*'``. ``expect_errors``: If this is not true, then if anything is written to ``wsgi.errors`` it will be an error. If it is true, then non-200/3xx responses are also okay. Returns a `response object `_ """ # Hide from py.test: __tracebackhide__ = True if params: if not isinstance(params, (str, unicode)): params = urllib.urlencode(params) if '?' in url: url += '&' else: url += '?' url += params environ = self._make_environ() for header, value in headers.items(): environ['HTTP_%s' % header.replace('-', '_').upper()] = value url = str(url) if '?' in url: url, environ['QUERY_STRING'] = url.split('?', 1) else: environ['QUERY_STRING'] = '' environ.update(extra_environ) req = TestRequest(url, environ, expect_errors) return self.do_request(req, status=status) def post(self, url, params='', headers={}, extra_environ={}, status=None, upload_files=None, expect_errors=False): """ Do a POST 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 `_ """ environ = self._make_environ() # @@: Should this be all non-strings? if params and isinstance(params, (list, tuple, dict)): params = urllib.urlencode(params) if upload_files: params = cgi.parse_qsl(params, keep_blank_values=True) content_type, params = self.encode_multipart( params, upload_files) environ['CONTENT_TYPE'] = content_type if '?' in url: url, environ['QUERY_STRING'] = url.split('?', 1) else: environ['QUERY_STRING'] = '' environ['CONTENT_LENGTH'] = str(len(params)) environ['REQUEST_METHOD'] = 'POST' environ['wsgi.input'] = StringIO(params) for header, value in headers.items(): environ['HTTP_%s' % header.replace('-', '_').upper()] = value environ.update(extra_environ) req = TestRequest(url, environ, expect_errors) return self.do_request(req, status=status) def encode_multipart(self, params, files): """ Encodes a set of parameters (typically a name/value list) and a set of files (a list of (name, filename, file_body)) into a typical POST body, returning the (content_type, body). """ boundary = '----------a_BoUnDaRy%s$' % random.random() lines = [] for key, value in params: lines.append('--'+boundary) lines.append('Content-Disposition: form-data; name="%s"' % key) lines.append('') lines.append(value) for file_info in files: key, filename, value = self._get_file_info(file_info) lines.append('--'+boundary) lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename)) fcontent = mimetypes.guess_type(filename)[0] lines.append('Content-Type: %s' % fcontent or 'application/octet-stream') lines.append('') lines.append(value) lines.append('--' + boundary + '--') lines.append('') body = '\r\n'.join(lines) content_type = 'multipart/form-data; boundary=%s' % boundary return content_type, body def _get_file_info(self, file_info): if len(file_info) == 2: # It only has a filename filename = file_info[2] if self.relative_to: filename = os.path.join(self.relative_to, filename) f = open(filename, 'rb') content = f.read() f.close() return (file_info[0], filename, content) elif len(file_info) == 3: return file_info else: raise ValueError( "upload_files need to be a list of tuples of (fieldname, " "filename, filecontent) or (fieldname, filename); " "you gave: %r" % repr(file_info)[:100]) def do_request(self, req, status): """ Executes the given request (``req``), with the expected ``status``. Generally ``.get()`` and ``.post()`` are used instead. """ __tracebackhide__ = True if self.cookies: c = SimpleCookie() for name, value in self.cookies.items(): c[name] = value req.environ['HTTP_COOKIE'] = str(c).split(': ', 1)[1] req.environ['paste.testing'] = True req.environ['paste.testing_variables'] = {} app = lint.middleware(self.app) old_stdout = sys.stdout out = StringIO() try: sys.stdout = out start_time = time.time() raise_on_wsgi_error = not req.expect_errors raw_res = wsgilib.raw_interactive( app, req.url, raise_on_wsgi_error=raise_on_wsgi_error, **req.environ) end_time = time.time() finally: sys.stdout = old_stdout sys.stderr.write(out.getvalue()) res = self._make_response(raw_res, end_time - start_time) res.request = req for name, value in req.environ['paste.testing_variables'].items(): setattr(res, name, value) if self.namespace is not None: self.namespace['res'] = res if not req.expect_errors: self._check_status(status, res) self._check_errors(res) res.cookies_set = {} for header in res.all_headers('set-cookie'): c = SimpleCookie(header) for key, morsel in c.items(): self.cookies[key] = morsel.value res.cookies_set[key] = morsel.value if self.namespace is None: # It's annoying to return the response in doctests, as it'll # be printed, so we only return it is we couldn't assign # it anywhere return res def _check_status(self, status, res): __tracebackhide__ = True if status == '*': return if status is None: if res.status == 200 or ( res.status >= 300 and res.status < 400): return raise AppError( "Bad response: %s (not 200 OK or 3xx redirect for %s)\n%s" % (res.full_status, res.request.url, res.body)) if status != res.status: raise AppError( "Bad response: %s (not %s)" % (res.full_status, status)) def _check_errors(self, res): if res.errors: raise AppError( "Application had errors logged:\n%s" % res.errors) def _make_response(self, (status, headers, body, errors), total_time): return TestResponse(self, status, headers, body, errors, total_time) class TestResponse(object): # for py.test disabled = True """ Instances of this class are return by `TestApp `_ """ def __init__(self, test_app, status, headers, body, errors, total_time): self.test_app = test_app self.status = int(status.split()[0]) self.full_status = status self.headers = headers self.header_dict = HeaderDict.fromlist(self.headers) self.body = body self.errors = errors self._normal_body = None self.time = total_time self._forms_indexed = None def forms__get(self): """ Returns a dictionary of ``Form`` objects. Indexes are both in order (from zero) and by form id (if the form is given an id). """ if self._forms_indexed is None: self._parse_forms() return self._forms_indexed forms = property(forms__get, doc=""" A list of
s found on the page (instances of `Form `_) """) def form__get(self): forms = self.forms assert len(forms) == 1, ( "You used response.form, but more than one form exists") return forms[0] form = property(form__get, doc=""" Returns a single `Form `_ instance; it is an error if there are multiple forms on the page. """) _tag_re = re.compile(r'<(/?)([a-z0-9_\-]*)(.*?)>', re.S|re.I) def _parse_forms(self): forms = self._forms_indexed = {} form_texts = [] started = None for match in self._tag_re.finditer(self.body): end = match.group(1) == '/' tag = match.group(2).lower() if tag != 'form': continue if end: assert started, ( " unexpected at %s" % match.start()) form_texts.append(self.body[started:match.end()]) started = None else: assert not started, ( "Nested form tags at %s" % match.start()) started = match.start() assert not started, ( "Danging form: %r" % self.body[started:]) for i, text in enumerate(form_texts): form = Form(self, text) forms[i] = form if form.id: forms[form.id] = form def header(self, name, default=NoDefault): """ 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) """ found = None for cur_name, value in self.headers: if cur_name.lower() == name.lower(): assert not found, ( "Ambiguous header: %s matches %r and %r" % (name, found, value)) found = value if found is None: if default is NoDefault: raise KeyError( "No header found: %r (from %s)" % (name, ', '.join([n for n, v in self.headers]))) else: return default return found def all_headers(self, name): """ Gets all headers by the ``name``, returns as a list """ found = [] for cur_name, value in self.headers: if cur_name.lower() == name.lower(): found.append(value) return found def follow(self, **kw): """ If this request is a redirect, follow that redirect. It is an error if this is not a redirect response. Returns another response object. """ assert self.status >= 300 and self.status < 400, ( "You can only follow redirect responses (not %s)" % self.full_status) location = self.header('location') type, rest = urllib.splittype(location) host, path = urllib.splithost(rest) # @@: We should test that it's not a remote redirect return self.test_app.get(location, **kw) def click(self, description=None, linkid=None, href=None, anchor=None, index=None, verbose=False): """ 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. """ __tracebackhide__ = True found_html, found_desc, found_attrs = self._find_element( tag='a', href_attr='href', href_extract=None, content=description, id=linkid, href_pattern=href, html_pattern=anchor, index=index, verbose=verbose) return self.goto(found_attrs['uri']) def clickbutton(self, description=None, buttonid=None, href=None, button=None, index=None, verbose=False): """ Like ``.click()``, except looks for link-like buttons. This kind of button should look like ``
' % 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 fields = [] for name, value_list in wsgilib.parse_formvars( environ, all_as_list=True, include_get_vars=False).items(): for value in value_list: 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 ''' PK4|+!]]paste/evalexception/__init__.py""" An exception handler for interactive debugging """ from middleware import EvalException PKZ4 p/ #paste/evalexception/evalcontext.pyc; u]Dc@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((s=build/bdist.linux-i686/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((s=build/bdist.linux-i686/egg/paste/evalexception/evalcontext.pys exec_exprs*         (s__name__s __module__s__doc__s__init__s exec_expr(((s=build/bdist.linux-i686/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((s=build/bdist.linux-i686/egg/paste/evalexception/evalcontext.pys__init__6s cGs=ti}|it_ztii||SWd|t_XdS(N( ssyssstdouts save_stdoutsselfs_OutputRedirectingPdb__outspdbsPdbstrace_dispatchsargs(sselfsargss save_stdout((s=build/bdist.linux-i686/egg/paste/evalexception/evalcontext.pystrace_dispatch:s   (s__name__s __module__s__doc__s__init__strace_dispatch(((s=build/bdist.linux-i686/egg/paste/evalexception/evalcontext.pys_OutputRedirectingPdb0s  ( s cStringIOsStringIOs tracebacks threadingspdbssyssLocks exec_locksobjects EvalContextsPdbs_OutputRedirectingPdb(s EvalContexts exec_locksStringIOs tracebackssyss threadingspdbs_OutputRedirectingPdb((s=build/bdist.linux-i686/egg/paste/evalexception/evalcontext.pys?s      'PKZ4_bb"paste/evalexception/middleware.pyc; u]Dc@s~dZdkZdkZdkZdkZdklZdkZdkZdk Z dk Z dk l Z l Z lZdklZdklZdklZdklZdkZdZd Zed Zd Zd Zd ZdZeiee i Zde fdYZ!de fdYZ"de i#fdYZ$dZ%dZ&dZ'dZ(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(srequesticCs/|tjodSntit|dSdS(s; Escape HTML characters, plus translate None to '' siN(svsNonescgisescapesstr(sv((s<build/bdist.linux-i686/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((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pyspreserve_whitespace3scCsTt|iddjodSn|iddt|idddSdS(Niis s (slensmatchsgroup(smatch((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pys _repl_nbspBscsd}|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(s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pyssimplecatcher_appLs    N(ssimplecatcher_app(s applicationssimplecatcher_app((s applications<build/bdist.linux-i686/egg/paste/evalexception/middleware.pys simplecatcherGs cCsd}|SdS(s= Turns a function or method into a WSGI application. csd}t|_|SdS(Ncstdjo%d}d}dgn\}}gd}ti|}t|}|||SdS(Niiiicsti|}tihdd<dd<}||d<||d<|}|i d}|||i |gSdS(Ns content-types text/htmlsstatuss200 OKsenvironsheaders( swsgilibsparse_formvarssenvironsformsResponseHeaderDictsheaderssfuncsargssresspopsstatussstart_responses headeritems(senvironsstart_responsesstatussformsressheaders(sargssfunc(s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pys applicationis!  ( slensargssenvironsstart_responses applicationshttpexceptionssmake_middlewaresapps simplecatcher(sargssstart_responsesapps applicationsenviron(sfunc(sargss<build/bdist.linux-i686/egg/paste/evalexception/middleware.pyswsgiapp_wrapper_s     (swsgiapp_wrappersTruesexposed(sfuncswsgiapp_wrapper((sfuncs<build/bdist.linux-i686/egg/paste/evalexception/middleware.pys decorator^s  N(s decorator(s decorator((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pyswsgiappZs 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(s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pysdebug_info_replacements  N(sdebug_info_replacement(sfuncsdebug_info_replacement((sfuncs<build/bdist.linux-i686/egg/paste/evalexception/middleware.pysget_debug_info{s s EvalExceptioncBstZeedZdZdZdZee_dZ ee _dZ ee _dZ dZ e ee Z d Ze eeZd Zd 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((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pys__init__s     cCsZ|d p td|iddido|i||Sn|i||SdS(Nswsgi.multiprocesssIThe EvalException middleware is not usable in a multi-process environments PATH_INFOss/_debug/(senvironsAssertionErrorsgets startswithsselfsdebugsstart_responsesrespond(sselfsenvironsstart_response((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pys__call__scCsti|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((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pysdebugs"cCs;titiitiitd}|||SdS(Nsmedia( s urlparsersStaticURLParsersosspathsjoinsdirnames__file__sappsenvironsstart_response(sselfsenvironsstart_responsesapp((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pysmedias*cCs;titiitiitd}|||SdS(Nsmochikit( s urlparsersStaticURLParsersosspathsjoinsdirnames__file__sappsenvironsstart_response(sselfsenvironsstart_responsesapp((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pysmochikits*cCsktti|}||ijo%|dddfgd|gSn|i|}|i ||SdS(Ns500 Server Errors Content-types text/htmlsHTraceback by id %s does not exist (maybe the server has been restarted?)( sintsrequests path_info_popsenvironsidsselfs debug_infossstart_responses debug_infoswsgi_application(sselfsenvironsstart_responses debug_infosid((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pysviews cCs|d|SdS(Ns/_debug/view/%s(s base_pathscount(sselfsenvirons base_pathscount((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pys make_view_urlscKsS|it|}|ii}|ot|}nd}t |||SdS(Ns No local vars( s debug_infosframesintstbidstb_framesf_localssvarss make_tables local_varss input_form(sselfstbids debug_infoskwsvarss local_varssframe((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pys show_frames  c Ks|i odSn|id}|it|} | ii}| ii } t i || }|i|}ti|}dt|dtt|fSdS(Nss sD>>> %s
%ssquote(sinputsstripsrstrips debug_infosframesintstbidstb_framesf_localssvarss f_globalss glob_varss evalcontexts EvalContextscontexts exec_exprsoutputs formattersstr2htmls input_htmlspreserve_whitespacesFalse( sselfstbids debug_infosinputskws input_htmlscontextsvarssoutputs glob_varssframe((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pys exec_inputs  c sK|ido|i|Snti|dtdt} t |dError in .close():
%s(serrormiddlewares Supplementsselfsenvirons__traceback_supplement__sapp_iters StopIterationsFalseserror_on_closesvshasattrsTruesclosesexception_handlerssyssexc_infosresponsesclose_response(sselfsapp_itersenvironsclose_responses__traceback_supplement__svsresponseserror_on_close((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pys catching_iter2s( c Cspt}|io6ti|}t|i |io t }qFnt i ||ddt dt d|SdS(Ns wsgi.errorsshtmls debug_modessimple_html_error(sFalsessimple_html_errorsselfs xmlhttp_keyswsgilibsparse_querystringsenvironsget_varssdictsgetsTrueserrormiddlewareshandle_exceptionsexc_info(sselfsexc_infosenvironsget_varsssimple_html_error((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pysexception_handlerJs (s__name__s __module__sNones__init__s__call__sdebugsmediasTruesexposedsmochikitsviews make_view_urls show_frameswsgiappsget_debug_infos exec_inputsresponds catching_itersexception_handler(((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pys EvalExceptions"          9 s DebugInfocBs5tZdZdZdZdZdZRS(Nc Cs||_||_||_||_|\|_|_|_d}g|_ d}|i}xj|t j ot t jp |t joB|iiidoPn|i i||i}|d7}q]WdS(Niis__exception_formatter__(scountersselfsexc_datas base_pathsenvironsexc_infosexc_types exc_valuestbs__exception_formatter__sframessnsNoneslimitstb_framesf_localssgetsappendstb_next( sselfscountersexc_infosexc_datas base_pathsenvironsns__exception_formatter__stb((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pys__init__Xs       ' cCsIxB|iD]!}t||jo|Sq q Wtd||ifdS(NsNo frame by id %s found from %r(sselfsframessframesidstbids ValueError(sselfstbidsframe((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pysframeks   cCs$|dddfg|iSdS(Ns200 OKs content-types text-html(sstart_responsesselfscontent(sselfsenvironsstart_response((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pyswsgi_applicationsscCst|i|i|i}titi}||i 7}t |i }thd|pd<d|<d|<}|gSdS(Ns repost_buttonss head_htmlsbody(sformat_eval_htmlsselfsexc_datas base_pathscountershtmls formatters error_cssshide_display_jss head_htmlseval_javascriptsmake_repost_buttonsenvirons repost_buttonserror_templatespage(sselfshtmls repost_buttons head_htmlspage((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pyscontentws ,cCs(|id}d||||ifSdS(Ns/_debugs (sselfs base_pathscounter(sselfs base_path((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pyseval_javascripts (s__name__s __module__s__init__sframeswsgi_applicationscontentseval_javascript(((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pys DebugInfoVs     sEvalHTMLFormattercBstZdZdZRS(NcKs,tt|i|||_||_dS(N(ssupersEvalHTMLFormattersselfs__init__skws base_pathscounter(sselfs base_pathscounterskw((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pys__init__s cCs4tii|||}|d|i|ifSdS(Ns        ( s formatters HTMLFormattersformat_source_linesselfsfilenamesframeslinestbids base_path(sselfsfilenamesframesline((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pysformat_source_lines(s__name__s __module__s__init__sformat_source_line(((s<build/bdist.linux-i686/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((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pys make_tables2        0c Cstd|d|dti|}td|d|dtdtdti|}t i |dt}d||t i |fSdS(Ns base_pathscountersinclude_reusablesshow_hidden_framessshow_extra_datas %s
%s

(sEvalHTMLFormatters base_pathscountersFalsesformat_collected_datasexc_datasshort_ersTrueslong_ers formatters format_textstext_erscgisescape(sexc_datas base_pathscounterslong_erstext_ersshort_er((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pysformat_eval_htmls  cCsti|}|ddjo d|SntSg}xti|dtdt i D]]\}}xN|D]F}t|do |i }n|idt|t|fqkWqXWd|d i|fSdS( NsREQUEST_METHODsGETsB
s all_as_listsinclude_get_varssfilenames*sW
%s
s (srequests construct_urlsenvironsurlsNonesfieldsswsgilibsparse_formvarssTruesFalsesitemssnames value_listsvalueshasattrsappends html_quotesjoin(senvironsnamesurlsfieldssvalues value_list((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pysmake_repost_buttons "  +cCsdhd|<SdS(Ns~

stbid(stbid(stbids debug_info((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pys input_formssE Server Error %(head_html)s %(repost_button)s %(body)s (*s__doc__ssyssosscgis tracebacks cStringIOsStringIOspprints itertoolsstimesrespaste.exceptionsserrormiddlewares formatters collectorspasteswsgilibs urlparsershttpexceptionssrequests evalcontextslimits html_quotesTruespreserve_whitespaces _repl_nbsps simplecatcherswsgiappsget_debug_infoscountsints debug_countersobjects EvalExceptions DebugInfos HTMLFormattersEvalHTMLFormatters make_tablesformat_eval_htmlsmake_repost_buttons input_formserror_template(!s simplecatchers debug_counterswsgiappspreserve_whitespacesmake_repost_buttons collectors evalcontextswsgilibspprintsres DebugInfos formatterscgisformat_eval_htmlsEvalHTMLFormatterssyss input_forms _repl_nbspserror_templateserrormiddlewaresStringIOshttpexceptionss EvalExceptions tracebacksrequestsget_debug_infos make_tables itertoolss urlparserslimitstimesoss html_quote((s<build/bdist.linux-i686/egg/paste/evalexception/middleware.pys?s>                   ! 9 !   PKZ45Ϟ** paste/evalexception/__init__.pyc; u]Dc@sdZdklZdS(s0 An exception handler for interactive debugging (s EvalExceptionN(s__doc__s middlewares EvalException(s EvalException((s:build/bdist.linux-i686/egg/paste/evalexception/__init__.pys?sPK4#gg#paste/evalexception/media/minus.jpgJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222 "$!4BTs! ?ZTz9mCQA7^g;j?WQJM{Oh,PK4;"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; } PK4#>ii"paste/evalexception/media/plus.jpgJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222 "#"#4Ts! ?gnIe=%iȑ>󧼎n.sU1}\p7?/Z2Y?PK4pp+paste/evalexception/mochikit/__package__.jsdojo.hostenv.conditionalLoadModule({"common": ["MochiKit.MochiKit"]}); dojo.hostenv.moduleLoaded("MochiKit.*"); PK4\ɻ  (paste/evalexception/mochikit/MochiKit.js/*** MochiKit.MochiKit 1.4 : 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.4"; 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.4"; 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.4"; 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(); },_xhr_onreadystatechange:function(d){ var m=MochiKit.Base; if(this.readyState==4){ try{ this.onreadystatechange=null; } catch(e){ try{ this.onreadystatechange=m.noop; } catch(e){ } } var _290=null; try{ _290=this.status; if(!_290&&m.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.Base.noop; } 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.Base"); } if(typeof (JSAN)!="undefined"){ JSAN.use("MochiKit.Base",[]); } try{ if(typeof (MochiKit.Base)=="undefined"){ throw ""; } } catch(e){ throw "MochiKit.DOM depends on MochiKit.Base!"; } if(typeof (MochiKit.DOM)=="undefined"){ MochiKit.DOM={}; } MochiKit.DOM.NAME="MochiKit.DOM"; MochiKit.DOM.VERSION="1.4"; 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 m=MochiKit.Base; var im=MochiKit.Iter; var self=MochiKit.DOM; if(im){ var iter=im.iter; var _350=im.repeat; var map=m.map; } var _351=self.domConverters; var _352=arguments.callee; var _353=m.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.__dom__)=="function"){ node=node.__dom__(ctx); continue; } if(typeof (node.dom)=="function"){ node=node.dom(ctx); continue; } if(typeof (node)=="function"){ node=node.apply(ctx,[ctx]); continue; } if(im){ var _354=null; try{ _354=iter(node); } catch(e){ } if(_354){ return map(_352,_354,_350(ctx)); } } try{ node=_351.match(node,ctx); continue; } catch(e){ if(e!=_353){ throw e; } } return self._document.createTextNode(node.toString()); } return undefined; },setNodeAttribute:function(node,attr,_356){ var o={}; o[attr]=_356; try{ return MochiKit.DOM.updateNodeAttributes(node,o); } catch(e){ } return null; },getNodeAttribute:function(node,attr){ var self=MochiKit.DOM; var _357=self.attributeArray.renames[attr]; node=self.getElement(node); try{ if(_357){ return node[_357]; } return node.getAttribute(attr); } catch(e){ } return null; },updateNodeAttributes:function(node,_358){ var elem=node; var self=MochiKit.DOM; if(typeof (node)=="string"){ elem=self.getElement(node); } if(_358){ var _359=MochiKit.Base.updatetree; if(self.attributeArray.compliant){ for(var k in _358){ var v=_358[k]; if(typeof (v)=="object"&&typeof (elem[k])=="object"){ _359(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 _360=self.attributeArray.renames; for(k in _358){ v=_358[k]; var _361=_360[k]; if(k=="style"&&typeof (v)=="string"){ elem.style.cssText=v; }else{ if(typeof (_361)=="string"){ elem[_361]=v; }else{ if(typeof (elem[k])=="object"&&typeof (v)=="object"){ _359(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 _362=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)]; var _363=MochiKit.Base.concat; while(_362.length){ var n=_362.shift(); if(typeof (n)=="undefined"||n===null){ }else{ if(typeof (n.nodeType)=="number"){ elem.appendChild(n); }else{ _362=_363(n,_362); } } } return elem; },replaceChildNodes:function(node){ var elem=node; var self=MochiKit.DOM; if(typeof (node)=="string"){ elem=self.getElement(node); arguments[0]=elem; } var _364; while((_364=elem.firstChild)){ elem.removeChild(_364); } if(arguments.length<2){ return elem; }else{ return self.appendChildNodes.apply(this,arguments); } },createDOM:function(name,_365){ var elem; var self=MochiKit.DOM; var m=MochiKit.Base; if(typeof (_365)=="string"||typeof (_365)=="number"){ var args=m.extend([name,null],arguments,1); return arguments.callee.apply(this,args); } if(typeof (name)=="string"){ if(_365&&!self.attributeArray.compliant){ var _366=""; if("name" in _365){ _366+=" name=\""+self.escapeHTML(_365.name)+"\""; } if(name=="input"&&"type" in _365){ _366+=" type=\""+self.escapeHTML(_365.type)+"\""; } if(_366){ name="<"+name+_366+">"; } } elem=self._document.createElement(name); }else{ elem=name; } if(_365){ self.updateNodeAttributes(elem,_365); } 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); var lst=m.map(MochiKit.DOM.getElement,_418); for(var i=0;i0){ var _424=m.filter; _423=function(node){ return _424(_423.ignoreAttrFilter,node.attributes); }; _423.ignoreAttr={}; var _425=_422.attributes; var _426=_423.ignoreAttr; for(var i=0;i<_425.length;i++){ var a=_425[i]; _426[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 _427=this.createDOMFunc; this.UL=_427("ul"); this.OL=_427("ol"); this.LI=_427("li"); this.TD=_427("td"); this.TR=_427("tr"); this.TBODY=_427("tbody"); this.THEAD=_427("thead"); this.TFOOT=_427("tfoot"); this.TABLE=_427("table"); this.TH=_427("th"); this.INPUT=_427("input"); this.SPAN=_427("span"); this.A=_427("a"); this.DIV=_427("div"); this.IMG=_427("img"); this.BUTTON=_427("button"); this.TT=_427("tt"); this.PRE=_427("pre"); this.H1=_427("h1"); this.H2=_427("h2"); this.H3=_427("h3"); this.BR=_427("br"); this.HR=_427("hr"); this.LABEL=_427("label"); this.TEXTAREA=_427("textarea"); this.FORM=_427("form"); this.P=_427("p"); this.SELECT=_427("select"); this.OPTION=_427("option"); this.OPTGROUP=_427("optgroup"); this.LEGEND=_427("legend"); this.FIELDSET=_427("fieldset"); this.STRONG=_427("strong"); this.CANVAS=_427("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.4"; MochiKit.LoggingPane.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.LoggingPane.toString=function(){ return this.__repr__(); }; MochiKit.LoggingPane.createLoggingPane=function(_428){ var m=MochiKit.LoggingPane; _428=!(!_428); if(m._loggingPane&&m._loggingPane.inline!=_428){ m._loggingPane.closePane(); m._loggingPane=null; } if(!m._loggingPane||m._loggingPane.closed){ m._loggingPane=new m.LoggingPane(_428,MochiKit.Logging.logger); } return m._loggingPane; }; MochiKit.LoggingPane.LoggingPane=function(_429,_430){ if(typeof (_430)=="undefined"||_430===null){ _430=MochiKit.Logging.logger; } this.logger=_430; var _431=MochiKit.Base.update; var _432=MochiKit.Base.updatetree; var bind=MochiKit.Base.bind; var _433=MochiKit.Base.clone; var win=window; var uid="_MochiKit_LoggingPane"; if(typeof (MochiKit.DOM)!="undefined"){ win=MochiKit.DOM.currentWindow(); } if(!_429){ 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 _436=doc.getElementById(uid); var _437=!!_436; if(_436&&typeof (_436.loggingPane)!="undefined"){ _436.loggingPane.logger=this.logger; _436.loggingPane.buildAndApplyFilter(); return _436.loggingPane; } if(_437){ var _438; while((_438=_436.firstChild)){ _436.removeChild(_438); } }else{ _436=doc.createElement("div"); _436.id=uid; } _436.loggingPane=this; var _439=doc.createElement("input"); var _440=doc.createElement("input"); var _441=doc.createElement("button"); var _442=doc.createElement("button"); var _443=doc.createElement("button"); var _444=doc.createElement("button"); var _445=doc.createElement("div"); var _446=doc.createElement("div"); var _447=uid+"_Listener"; this.colorTable=_433(this.colorTable); var _448=[]; var _449=null; var _450=function(msg){ var _451=msg.level; if(typeof (_451)=="number"){ _451=MochiKit.Logging.LogLevel[_451]; } return _451; }; var _452=function(msg){ return msg.info.join(" "); }; var _453=bind(function(msg){ var _454=_450(msg); var text=_452(msg); var c=this.colorTable[_454]; var p=doc.createElement("span"); p.className="MochiKit-LogMessage MochiKit-LogLevel-"+_454; 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(_454+": "+text)); _446.appendChild(p); _446.appendChild(doc.createElement("br")); if(_445.offsetHeight>_445.scrollHeight){ _445.scrollTop=0; }else{ _445.scrollTop=_445.scrollHeight; } },this); var _456=function(msg){ _448[_448.length]=msg; _453(msg); }; var _457=function(){ var _458,infore; try{ _458=new RegExp(_439.value); infore=new RegExp(_440.value); } catch(e){ logDebug("Error in filter regex: "+e.message); return null; } return function(msg){ return (_458.test(_450(msg))&&infore.test(_452(msg))); }; }; var _459=function(){ while(_446.firstChild){ _446.removeChild(_446.firstChild); } }; var _460=function(){ _448=[]; _459(); }; var _461=bind(function(){ if(this.closed){ return; } this.closed=true; if(MochiKit.LoggingPane._loggingPane==this){ MochiKit.LoggingPane._loggingPane=null; } this.logger.removeListener(_447); _436.loggingPane=null; if(_429){ _436.parentNode.removeChild(_436); }else{ this.win.close(); } },this); var _462=function(){ _459(); for(var i=0;i<_448.length;i++){ var msg=_448[i]; if(_449===null||_449(msg)){ _453(msg); } } }; this.buildAndApplyFilter=function(){ _449=_457(); _462(); this.logger.removeListener(_447); this.logger.addListener(_447,_449,_456); }; var _463=bind(function(){ _448=this.logger.getMessages(); _462(); },this); var _464=bind(function(_465){ _465=_465||window.event; key=_465.which||_465.keyCode; if(key==13){ this.buildAndApplyFilter(); } },this); var _466="display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: "+this.logFont; if(_429){ _466+="; height: 10em; border-top: 2px solid black"; }else{ _466+="; height: 100%;"; } _436.style.cssText=_466; if(!_437){ doc.body.appendChild(_436); } _466={"cssText":"width: 33%; display: inline; font: "+this.logFont}; _432(_439,{"value":"FATAL|ERROR|WARNING|INFO|DEBUG","onkeypress":_464,"style":_466}); _436.appendChild(_439); _432(_440,{"value":".*","onkeypress":_464,"style":_466}); _436.appendChild(_440); _466="width: 8%; display:inline; font: "+this.logFont; _441.appendChild(doc.createTextNode("Filter")); _441.onclick=bind("buildAndApplyFilter",this); _441.style.cssText=_466; _436.appendChild(_441); _442.appendChild(doc.createTextNode("Load")); _442.onclick=_463; _442.style.cssText=_466; _436.appendChild(_442); _443.appendChild(doc.createTextNode("Clear")); _443.onclick=_460; _443.style.cssText=_466; _436.appendChild(_443); _444.appendChild(doc.createTextNode("Close")); _444.onclick=_461; _444.style.cssText=_466; _436.appendChild(_444); _445.style.cssText="overflow: auto; width: 100%"; _446.style.cssText="width: 100%; height: "+(_429?"8em":"100%"); _445.appendChild(_446); _436.appendChild(_445); this.buildAndApplyFilter(); _463(); if(_429){ this.win=undefined; }else{ this.win=win; } this.inline=_429; this.closePane=_461; 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.4"; MochiKit.Color.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.Color.toString=function(){ return this.__repr__(); }; MochiKit.Color.Color=function(red,_468,blue,_470){ if(typeof (_470)=="undefined"||_470===null){ _470=1; } this.rgb={r:red,g:_468,b:blue,a:_470}; }; MochiKit.Color.Color.prototype={__class__:MochiKit.Color.Color,colorWithAlpha:function(_471){ var rgb=this.rgb; var m=MochiKit.Color; return m.Color.fromRGB(rgb.r,rgb.g,rgb.b,_471); },colorWithHue:function(hue){ var hsl=this.asHSL(); hsl.h=hue; var m=MochiKit.Color; return m.Color.fromHSL(hsl); },colorWithSaturation:function(_475){ var hsl=this.asHSL(); hsl.s=_475; var m=MochiKit.Color; return m.Color.fromHSL(hsl); },colorWithLightness:function(_476){ var hsl=this.asHSL(); hsl.l=_476; var m=MochiKit.Color; return m.Color.fromHSL(hsl); },darkerColorWithLevel:function(_477){ var hsl=this.asHSL(); hsl.l=Math.max(hsl.l-_477,0); var m=MochiKit.Color; return m.Color.fromHSL(hsl); },lighterColorWithLevel:function(_478){ var hsl=this.asHSL(); hsl.l=Math.min(hsl.l+_478,1); var m=MochiKit.Color; return m.Color.fromHSL(hsl); },blendedColor:function(_479,_480){ if(typeof (_480)=="undefined"||_480===null){ _480=0.5; } var sf=1-_480; var s=this.rgb; var d=_479.rgb; var df=_480; 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(_483){ var a=this.asRGB(); var b=_483.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,_488,blue,_489){ var _490=MochiKit.Color.Color; if(arguments.length==1){ var rgb=red; red=rgb.r; _488=rgb.g; blue=rgb.b; if(typeof (rgb.a)=="undefined"){ _489=undefined; }else{ _489=rgb.a; } } return new _490(red,_488,blue,_489); },fromHSL:function(hue,_491,_492,_493){ var m=MochiKit.Color; return m.Color.fromRGB(m.hslToRGB.apply(m,arguments)); },fromHSV:function(hue,_494,_495,_496){ var m=MochiKit.Color; return m.Color.fromRGB(m.hsvToRGB.apply(m,arguments)); },fromName:function(name){ var _497=MochiKit.Color.Color; if(name.charAt(0)=="\""){ name=name.substr(1,name.length-2); } var _498=_497._namedColors[name.toLowerCase()]; if(typeof (_498)=="string"){ return _497.fromHexString(_498); }else{ if(name=="transparent"){ return _497.transparentColor(); } } return null; },fromString:function(_499){ var self=MochiKit.Color.Color; var _500=_499.substr(0,3); if(_500=="rgb"){ return self.fromRGBString(_499); }else{ if(_500=="hsl"){ return self.fromHSLString(_499); }else{ if(_499.charAt(0)=="#"){ return self.fromHexString(_499); } } } return self.fromName(_499); },fromHexString:function(_501){ if(_501.charAt(0)=="#"){ _501=_501.substring(1); } var _502=[]; var i,hex; if(_501.length==3){ for(i=0;i<3;i++){ hex=_501.substr(i,1); _502.push(parseInt(hex+hex,16)/255); } }else{ for(i=0;i<6;i+=2){ hex=_501.substr(i,2); _502.push(parseInt(hex,16)/255); } } var _503=MochiKit.Color.Color; return _503.fromRGB.apply(_503,_502); },_fromColorString:function(pre,_505,_506,_507){ if(_507.indexOf(pre)===0){ _507=_507.substring(_507.indexOf("(",3)+1,_507.length-1); } var _508=_507.split(/\s*,\s*/); var _509=[]; for(var i=0;i<_508.length;i++){ var c=_508[i]; var val; var _510=c.substring(c.length-3); if(c.charAt(c.length-1)=="%"){ val=0.01*parseFloat(c.substring(0,c.length-1)); }else{ if(_510=="deg"){ val=parseFloat(c)/360; }else{ if(_510=="rad"){ val=parseFloat(c)/(Math.PI*2); }else{ val=_506[i]*parseFloat(c); } } } _509.push(val); } return this[_505].apply(this,_509); },fromComputedStyle:function(elem,_511,_512){ var d=MochiKit.DOM; var cls=MochiKit.Color.Color; for(elem=d.getElement(elem);elem;elem=elem.parentNode){ var _513=d.computedStyle.apply(d,arguments); if(!_513){ continue; } var _514=cls.fromString(_513); if(!_514){ break; } if(_514.asRGB().a>0){ return _514; } } 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,_515){ v*=_515; if(v<0){ return 0; }else{ if(v>_515){ return _515; }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,_518,_519,_520){ if(arguments.length==1){ var hsv=hue; hue=hsv.h; _518=hsv.s; _519=hsv.v; _520=hsv.a; } var red; var _521; var blue; if(_518===0){ red=0; _521=0; blue=0; }else{ var i=Math.floor(hue*6); var f=(hue*6)-i; var p=_519*(1-_518); var q=_519*(1-(_518*f)); var t=_519*(1-(_518*(1-f))); switch(i){ case 1: red=q; _521=_519; blue=p; break; case 2: red=p; _521=_519; blue=t; break; case 3: red=p; _521=q; blue=_519; break; case 4: red=t; _521=p; blue=_519; break; case 5: red=_519; _521=p; blue=q; break; case 6: case 0: red=_519; _521=t; blue=p; break; } } return {r:red,g:_521,b:blue,a:_520}; },hslToRGB:function(hue,_523,_524,_525){ if(arguments.length==1){ var hsl=hue; hue=hsl.h; _523=hsl.s; _524=hsl.l; _525=hsl.a; } var red; var _526; var blue; if(_523===0){ red=_524; _526=_524; blue=_524; }else{ var m2; if(_524<=0.5){ m2=_524*(1+_523); }else{ m2=_524+_523-(_524*_523); } var m1=(2*_524)-m2; var f=MochiKit.Color._hslValue; var h6=hue*6; red=f(m1,m2,h6+2); _526=f(m1,m2,h6); blue=f(m1,m2,h6-2); } return {r:red,g:_526,b:blue,a:_525}; },rgbToHSV:function(red,_530,blue,_531){ if(arguments.length==1){ var rgb=red; red=rgb.r; _530=rgb.g; blue=rgb.b; _531=rgb.a; } var max=Math.max(Math.max(red,_530),blue); var min=Math.min(Math.min(red,_530),blue); var hue; var _534; var _535=max; if(min==max){ hue=0; _534=0; }else{ var _536=(max-min); _534=_536/max; if(red==max){ hue=(_530-blue)/_536; }else{ if(_530==max){ hue=2+((blue-red)/_536); }else{ hue=4+((red-_530)/_536); } } hue/=6; if(hue<0){ hue+=1; } if(hue>1){ hue-=1; } } return {h:hue,s:_534,v:_535,a:_531}; },rgbToHSL:function(red,_537,blue,_538){ if(arguments.length==1){ var rgb=red; red=rgb.r; _537=rgb.g; blue=rgb.b; _538=rgb.a; } var max=Math.max(red,Math.max(_537,blue)); var min=Math.min(red,Math.min(_537,blue)); var hue; var _539; var _540=(max+min)/2; var _541=max-min; if(_541===0){ hue=0; _539=0; }else{ if(_540<=0.5){ _539=_541/(max+min); }else{ _539=_541/(2-max-min); } if(red==max){ hue=(_537-blue)/_541; }else{ if(_537==max){ hue=2+((blue-red)/_541); }else{ hue=4+((red-_537)/_541); } } hue/=6; if(hue<0){ hue+=1; } if(hue>1){ hue-=1; } } return {h:hue,s:_539,l:_540,a:_538}; },toColorPart:function(num){ num=Math.round(num); var _542=num.toString(16); if(num<16){ return "0"+_542; } return _542; },__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 _543=1/3; var _544={black:[0,0,0],blue:[0,0,1],brown:[0.6,0.4,0.2],cyan:[0,1,1],darkGray:[_543,_543,_543],gray:[0.5,0.5,0.5],green:[0,1,0],lightGray:[2*_543,2*_543,2*_543],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 _545=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 _544){ var name=k+"Color"; var _547=m.concat([_545,this.Color,name],_544[k]); this.Color[name]=m.bind.apply(null,_547); } var _548=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=_564.length-1;i>=0;i--){ var o=_564[i]; if(o[0]===src&&o[1]===sig&&o[4]===obj&&o[5]===func){ self._disconnect(o); _564.splice(i,1); return true; } } }else{ var idx=m.findIdentical(_564,_563); if(idx>=0){ self._disconnect(_563); _564.splice(idx,1); return true; } } return false; },disconnectAll:function(src,sig){ src=MochiKit.DOM.getElement(src); var m=MochiKit.Base; var _565=m.flattenArguments(m.extend(null,arguments,1)); var self=MochiKit.Signal; var _566=self._disconnect; var _567=self._observers; if(_565.length===0){ for(var i=_567.length-1;i>=0;i--){ var _568=_567[i]; if(_568[0]===src){ _566(_568); _567.splice(i,1); } } }else{ var sigs={}; for(var i=0;i<_565.length;i++){ sigs[_565[i]]=true; } for(var i=_567.length-1;i>=0;i--){ var _568=_567[i]; if(_568[0]===src&&_568[1] in sigs){ _566(_568); _567.splice(i,1); } } } },signal:function(src,sig){ var _570=MochiKit.Signal._observers; src=MochiKit.DOM.getElement(src); var args=MochiKit.Base.extend(null,arguments,2); var _571=[]; for(var i=0;i<_570.length;i++){ var _572=_570[i]; if(_572[0]===src&&_572[1]===sig){ try{ _572[2].apply(src,args); } catch(e){ _571.push(e); } } } if(_571.length==1){ throw _571[0]; }else{ if(_571.length>1){ var e=new Error("Multiple errors thrown in handling 'sig', see errors property"); e.errors=_571; 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"); dojo.require("MochiKit.Iter"); } if(typeof (JSAN)!="undefined"){ JSAN.use("MochiKit.Base",[]); JSAN.use("MochiKit.DOM",[]); JSAN.use("MochiKit.Color",[]); JSAN.use("MochiKit.Iter",[]); } try{ if(typeof (MochiKit.Base)==="undefined"||typeof (MochiKit.DOM)==="undefined"||typeof (MochiKit.Color)==="undefined"||typeof (MochiKit.Iter)==="undefined"){ throw ""; } } catch(e){ throw "MochiKit.Visual depends on MochiKit.Base, MochiKit.DOM, MochiKit.Color and MochiKit.Iter!"; } if(typeof (MochiKit.Visual)=="undefined"){ MochiKit.Visual={}; } MochiKit.Visual.NAME="MochiKit.Visual"; MochiKit.Visual.VERSION="1.4"; MochiKit.Visual.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.Visual.toString=function(){ return this.__repr__(); }; MochiKit.Visual._RoundCorners=function(e,_573){ e=MochiKit.DOM.getElement(e); this._setOptions(_573); if(this.options.__unstable__wrapElement){ e=this._doWrap(e); } var _574=this.options.color; var C=MochiKit.Color.Color; if(this.options.color==="fromElement"){ _574=C.fromBackground(e); }else{ if(!(_574 instanceof C)){ _574=C.fromString(_574); } } this.isTransparent=(_574.asRGB().a<=0); var _576=this.options.bgColor; if(this.options.bgColor==="fromParent"){ _576=C.fromBackground(e.offsetParent); }else{ if(!(_576 instanceof C)){ _576=C.fromString(_576); } } this._roundCornersImpl(e,_574,_576); }; MochiKit.Visual._RoundCorners.prototype={_doWrap:function(e){ var _577=e.parentNode; var doc=MochiKit.DOM.currentDocument(); if(typeof (doc.defaultView)==="undefined"||doc.defaultView===null){ return e; } var _578=doc.defaultView.getComputedStyle(e,null); if(typeof (_578)==="undefined"||_578===null){ return e; } var _579=MochiKit.DOM.DIV({"style":{display:"block",marginTop:_578.getPropertyValue("padding-top"),marginRight:_578.getPropertyValue("padding-right"),marginBottom:_578.getPropertyValue("padding-bottom"),marginLeft:_578.getPropertyValue("padding-left"),padding:"0px"}}); _579.innerHTML=e.innerHTML; e.innerHTML=""; e.appendChild(_579); return e; },_roundCornersImpl:function(e,_580,_581){ if(this.options.border){ this._renderBorder(e,_581); } if(this._isTopRounded()){ this._roundTopCorners(e,_580,_581); } if(this._isBottomRounded()){ this._roundBottomCorners(e,_580,_581); } },_renderBorder:function(el,_582){ var _583="1px solid "+this._borderColor(_582); var _584="border-left: "+_583; var _585="border-right: "+_583; var _586="style='"+_584+";"+_585+"'"; el.innerHTML="
"+el.innerHTML+"
"; },_roundTopCorners:function(el,_587,_588){ var _589=this._createCorner(_588); for(var i=0;i=0;i--){ _592.appendChild(this._createCornerSlice(_590,_591,i,"bottom")); } el.style.paddingBottom=0; el.appendChild(_592); },_createCorner:function(_593){ var dom=MochiKit.DOM; return dom.DIV({style:{backgroundColor:_593.toString()}}); },_createCornerSlice:function(_594,_595,n,_596){ var _597=MochiKit.DOM.SPAN(); var _598=_597.style; _598.backgroundColor=_594.toString(); _598.display="block"; _598.height="1px"; _598.overflow="hidden"; _598.fontSize="1px"; var _599=this._borderColor(_594,_595); if(this.options.border&&n===0){ _598.borderTopStyle="solid"; _598.borderTopWidth="1px"; _598.borderLeftWidth="0px"; _598.borderRightWidth="0px"; _598.borderBottomWidth="0px"; _598.height="0px"; _598.borderColor=_599.toString(); }else{ if(_599){ _598.borderColor=_599.toString(); _598.borderStyle="solid"; _598.borderWidth="0px 1px"; } } if(!this.options.compact&&(n==(this.options.numSlices-1))){ _598.height="2px"; } this._setMargin(_597,n,_596); this._setBorder(_597,n,_596); return _597; },_setOptions:function(_600){ this.options={corners:"all",color:"fromElement",bgColor:"fromParent",blend:true,border:false,compact:false,__unstable__wrapElement:false}; MochiKit.Base.update(this.options,_600); this.options.numSlices=(this.options.compact?2:4); },_whichSideTop:function(){ var _601=this.options.corners; if(this._hasString(_601,"all","top")){ return ""; } var _602=(_601.indexOf("tl")!=-1); var _603=(_601.indexOf("tr")!=-1); if(_602&&_603){ return ""; } if(_602){ return "left"; } if(_603){ return "right"; } return ""; },_whichSideBottom:function(){ var _604=this.options.corners; if(this._hasString(_604,"all","bottom")){ return ""; } var _605=(_604.indexOf("bl")!=-1); var _606=(_604.indexOf("br")!=-1); if(_605&&_606){ return ""; } if(_605){ return "left"; } if(_606){ return "right"; } return ""; },_borderColor:function(_607,_608){ if(_607=="transparent"){ return _608; }else{ if(this.options.border){ return this.options.border; }else{ if(this.options.blend){ return _608.blendedColor(_607); } } } return ""; },_setMargin:function(el,n,_609){ var _610=this._marginSize(n)+"px"; var _611=(_609=="top"?this._whichSideTop():this._whichSideBottom()); var _612=el.style; if(_611=="left"){ _612.marginLeft=_610; _612.marginRight="0px"; }else{ if(_611=="right"){ _612.marginRight=_610; _612.marginLeft="0px"; }else{ _612.marginLeft=_610; _612.marginRight=_610; } } },_setBorder:function(el,n,_613){ var _614=this._borderSize(n)+"px"; var _615=(_613=="top"?this._whichSideTop():this._whichSideBottom()); var _616=el.style; if(_615=="left"){ _616.borderLeftWidth=_614; _616.borderRightWidth="0px"; }else{ if(_615=="right"){ _616.borderRightWidth=_614; _616.borderLeftWidth="0px"; }else{ _616.borderLeftWidth=_614; _616.borderRightWidth=_614; } } },_marginSize:function(n){ if(this.isTransparent){ return 0; } var o=this.options; if(o.compact&&o.blend){ var _617=[1,0]; return _617[n]; }else{ if(o.compact){ var _618=[2,1]; return _618[n]; }else{ if(o.blend){ var _619=[3,2,1,0]; return _619[n]; }else{ var _620=[5,3,2,1]; return _620[n]; } } } },_borderSize:function(n){ var o=this.options; var _621; if(o.compact&&(o.blend||this.isTransparent)){ return 1; }else{ if(o.compact){ _621=[1,0]; }else{ if(o.blend){ _621=[2,1,1,1]; }else{ if(o.border){ _621=[0,2,0,0]; }else{ if(this.isTransparent){ _621=[5,3,2,1]; }else{ return 0; } } } } } return _621[n]; },_hasString:function(str){ for(var i=1;i=(_646||i)){ _646=i; } }); _644=_646||_644; break; } _643.startOn+=_644; _643.finishOn+=_644; if(!_643.options.queue.limit||this.effects.length<_643.options.queue.limit){ this.effects.push(_643); } if(!this.interval){ this.interval=setInterval(MochiKit.Base.bind(this.loop,this),40); } },remove:function(_647){ this.effects=MochiKit.Base.filter(function(e){ return e!=_647; },this.effects); if(this.effects.length==0){ clearInterval(this.interval); this.interval=null; } },loop:function(){ var _648=new Date().getTime(); MochiKit.Iter.forEach(this.effects,function(_649){ _649.loop(_648); }); }}); MochiKit.Visual.Queues={instances:{},get:function(_650){ if(typeof (_650)!="string"){ return _650; } if(!this.instances[_650]){ this.instances[_650]=new MochiKit.Visual.ScopedQueue(); } return this.instances[_650]; }}; MochiKit.Visual.Queue=MochiKit.Visual.Queues.get("global"); MochiKit.Visual.DefaultOptions={transition:MochiKit.Visual.Transitions.sinoidal,duration:1,fps:25,sync:false,from:0,to:1,delay:0,queue:"parallel"}; MochiKit.Visual.Base=function(){ }; MochiKit.Visual.Base.prototype={__class__:MochiKit.Visual.Base,position:null,start:function(_651){ var v=MochiKit.Visual; this.options=MochiKit.Base.setdefault(_651||{},v.DefaultOptions); this.currentFrame=0; this.state="idle"; this.startOn=this.options.delay*1000; this.finishOn=this.startOn+(this.options.duration*1000); this.event("beforeStart"); if(!this.options.sync){ v.Queues.get(typeof (this.options.queue)=="string"?"global":this.options.queue.scope).add(this); } },loop:function(_652){ if(_652>=this.startOn){ if(_652>=this.finishOn){ this.render(1); this.cancel(); this.event("beforeFinish"); if(this.finish){ this.finish(); } this.event("afterFinish"); return; } var pos=(_652-this.startOn)/(this.finishOn-this.startOn); var _653=Math.round(pos*this.options.fps*this.options.duration); if(_653>this.currentFrame){ this.render(pos); this.currentFrame=_653; } } },render:function(pos){ if(this.state=="idle"){ this.state="running"; this.event("beforeSetup"); if(this.setup){ this.setup(); } this.event("afterSetup"); } if(this.state=="running"){ if(this.options.transition){ pos=this.options.transition(pos); } pos*=(this.options.to-this.options.from); pos+=this.options.from; this.position=pos; this.event("beforeUpdate"); if(this.update){ this.update(pos); } this.event("afterUpdate"); } },cancel:function(){ if(!this.options.sync){ MochiKit.Visual.Queues.get(typeof (this.options.queue)=="string"?"global":this.options.queue.scope).remove(this); } this.state="finished"; },event:function(_654){ if(this.options[_654+"Internal"]){ this.options[_654+"Internal"](this); } if(this.options[_654]){ this.options[_654](this); } },repr:function(){ return "["+this.__class__.NAME+", options:"+MochiKit.Base.repr(this.options)+"]"; }}; MochiKit.Visual.Parallel=function(_655,_656){ this.__init__(_655,_656); }; MochiKit.Base.update(MochiKit.Visual.Parallel.prototype,MochiKit.Visual.Base.prototype); MochiKit.Base.update(MochiKit.Visual.Parallel.prototype,{__init__:function(_657,_658){ this.effects=_657||[]; this.start(_658); },update:function(_659){ MochiKit.Iter.forEach(this.effects,function(_660){ _660.render(_659); }); },finish:function(_661){ MochiKit.Iter.forEach(this.effects,function(_662){ _662.render(1); _662.cancel(); _662.event("beforeFinish"); if(_662.finish){ _662.finish(_661); } _662.event("afterFinish"); }); }}); MochiKit.Visual.Opacity=function(_663,_664){ this.__init__(_663,_664); }; MochiKit.Base.update(MochiKit.Visual.Opacity.prototype,MochiKit.Visual.Base.prototype); MochiKit.Base.update(MochiKit.Visual.Opacity.prototype,{__init__:function(_665,_666){ var b=MochiKit.Base; var d=MochiKit.DOM; this.element=d.getElement(_665); if(b.isIE()&&(!this.element.hasLayout)){ d.setStyle(this.element,{zoom:1}); } _666=b.update({from:d.getOpacity(this.element)||0,to:1},_666||{}); this.start(_666); },update:function(_667){ MochiKit.DOM.setOpacity(this.element,_667); }}); MochiKit.Visual.Move=function(_668,_669){ this.__init__(_668,_669); }; MochiKit.Base.update(MochiKit.Visual.Move.prototype,MochiKit.Visual.Base.prototype); MochiKit.Base.update(MochiKit.Visual.Move.prototype,{__init__:function(_670,_671){ this.element=MochiKit.DOM.getElement(_670); _671=MochiKit.Base.update({x:0,y:0,mode:"relative"},_671||{}); this.start(_671); },setup:function(){ var d=MochiKit.DOM; d.makePositioned(this.element); var s=this.element.style; var _672=s.visibility; var _673=s.display; if(_673=="none"){ s.visibility="hidden"; s.display=""; } this.originalLeft=parseFloat(d.getStyle(this.element,"left")||"0"); this.originalTop=parseFloat(d.getStyle(this.element,"top")||"0"); if(this.options.mode=="absolute"){ this.options.x-=this.originalLeft; this.options.y-=this.originalTop; } if(_673=="none"){ s.visibility=_672; s.display=_673; } },update:function(_674){ MochiKit.DOM.setStyle(this.element,{left:this.options.x*_674+this.originalLeft+"px",top:this.options.y*_674+this.originalTop+"px"}); }}); MochiKit.Visual.Scale=function(_675,_676,_677){ this.__init__(_675,_676,_677); }; MochiKit.Base.update(MochiKit.Visual.Scale.prototype,MochiKit.Visual.Base.prototype); MochiKit.Base.update(MochiKit.Visual.Scale.prototype,{__init__:function(_678,_679,_680){ this.element=MochiKit.DOM.getElement(_678); _680=MochiKit.Base.update({scaleX:true,scaleY:true,scaleContent:true,scaleFromCenter:false,scaleMode:"box",scaleFrom:100,scaleTo:_679},_680||{}); this.start(_680); },setup:function(){ this.restoreAfterFinish=this.options.restoreAfterFinish||false; this.elementPositioning=MochiKit.DOM.getStyle(this.element,"position"); var fe=MochiKit.Iter.forEach; var b=MochiKit.Base.bind; this.originalStyle={}; fe(["top","left","width","height","fontSize"],b(function(k){ this.originalStyle[k]=this.element.style[k]; },this)); this.originalTop=this.element.offsetTop; this.originalLeft=this.element.offsetLeft; var _681=MochiKit.DOM.getStyle(this.element,"font-size")||"100%"; fe(["em","px","%"],b(function(_682){ if(_681.indexOf(_682)>0){ this.fontSize=parseFloat(_681); this.fontSizeType=_682; } },this)); this.factor=(this.options.scaleTo-this.options.scaleFrom)/100; if(/^content/.test(this.options.scaleMode)){ this.dims=[this.element.scrollHeight,this.element.scrollWidth]; }else{ if(this.options.scaleMode=="box"){ this.dims=[this.element.offsetHeight,this.element.offsetWidth]; }else{ this.dims=[this.options.scaleMode.originalHeight,this.options.scaleMode.originalWidth]; } } },update:function(_683){ var _684=(this.options.scaleFrom/100)+(this.factor*_683); if(this.options.scaleContent&&this.fontSize){ MochiKit.DOM.setStyle(this.element,{fontSize:this.fontSize*_684+this.fontSizeType}); } this.setDimensions(this.dims[0]*_684,this.dims[1]*_684); },finish:function(_685){ if(this.restoreAfterFinish){ MochiKit.DOM.setStyle(this.element,this.originalStyle); } },setDimensions:function(_686,_687){ var d={}; if(this.options.scaleX){ d.width=_687+"px"; } if(this.options.scaleY){ d.height=_686+"px"; } if(this.options.scaleFromCenter){ var topd=(_686-this.dims[0])/2; var _689=(_687-this.dims[1])/2; if(this.elementPositioning=="absolute"){ if(this.options.scaleY){ d.top=this.originalTop-topd+"px"; } if(this.options.scaleX){ d.left=this.originalLeft-_689+"px"; } }else{ if(this.options.scaleY){ d.top=-topd+"px"; } if(this.options.scaleX){ d.left=-_689+"px"; } } } MochiKit.DOM.setStyle(this.element,d); }}); MochiKit.Visual.Highlight=function(_690,_691){ this.__init__(_690,_691); }; MochiKit.Base.update(MochiKit.Visual.Highlight.prototype,MochiKit.Visual.Base.prototype); MochiKit.Base.update(MochiKit.Visual.Highlight.prototype,{__init__:function(_692,_693){ this.element=MochiKit.DOM.getElement(_692); _693=MochiKit.Base.update({startcolor:"#ffff99"},_693||{}); this.start(_693); },setup:function(){ var d=MochiKit.DOM; var b=MochiKit.Base; if(d.getStyle(this.element,"display")=="none"){ this.cancel(); return; } this.oldStyle={backgroundImage:d.getStyle(this.element,"background-image")}; d.setStyle(this.element,{backgroundImage:"none"}); if(!this.options.endcolor){ this.options.endcolor=MochiKit.Color.Color.fromBackground(this.element).toHexString(); } if(!this.options.restorecolor){ this.options.restorecolor=d.getStyle(this.element,"background-color"); } this._base=b.map(b.bind(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16); },this),[0,1,2]); this._delta=b.map(b.bind(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i]; },this),[0,1,2]); },update:function(_694){ var m="#"; MochiKit.Iter.forEach([0,1,2],MochiKit.Base.bind(function(i){ m+=MochiKit.Color.toColorPart(Math.round(this._base[i]+this._delta[i]*_694)); },this)); MochiKit.DOM.setStyle(this.element,{backgroundColor:m}); },finish:function(){ MochiKit.DOM.setStyle(this.element,MochiKit.Base.update(this.oldStyle,{backgroundColor:this.options.endcolor})); }}); MochiKit.Visual.ScrollTo=function(_695,_696){ this.__init__(_695,_696); }; MochiKit.Base.update(MochiKit.Visual.ScrollTo.prototype,MochiKit.Visual.Base.prototype); MochiKit.Base.update(MochiKit.Visual.ScrollTo.prototype,{__init__:function(_697,_698){ this.element=MochiKit.DOM.getElement(_697); this.start(_698||{}); },setup:function(){ var p=MochiKit.Position; p.prepare(); var _699=p.cumulativeOffset(this.element); if(this.options.offset){ _699.y+=this.options.offset; } var max; if(window.innerHeight){ max=window.innerHeight-window.height; }else{ if(document.documentElement&&document.documentElement.clientHeight){ max=document.documentElement.clientHeight-document.body.scrollHeight; }else{ if(document.body){ max=document.body.clientHeight-document.body.scrollHeight; } } } this.scrollStart=p.windowOffset.y; this.delta=(_699.y>max?max:_699.y)-this.scrollStart; },update:function(_700){ var p=MochiKit.Position; p.prepare(); window.scrollTo(p.windowOffset.x,this.scrollStart+(_700*this.delta)); }}); MochiKit.Visual.fade=function(_701,_702){ var d=MochiKit.DOM; var _703=d.getInlineOpacity(_701); _702=MochiKit.Base.update({from:d.getOpacity(_701)||1,to:0,afterFinishInternal:function(_704){ if(_704.options.to!==0){ return; } d.hideElement(_704.element); d.setStyle(_704.element,{opacity:_703}); }},_702||{}); return new MochiKit.Visual.Opacity(_701,_702); }; MochiKit.Visual.appear=function(_705,_706){ var d=MochiKit.DOM; var v=MochiKit.Visual; _706=MochiKit.Base.update({from:(d.getStyle(_705,"display")=="none"?0:d.getOpacity(_705)||0),to:1,afterFinishInternal:function(_707){ v.forceRerendering(_707.element); },beforeSetup:function(_708){ d.setOpacity(_708.element,_708.options.from); d.showElement(_708.element); }},_706||{}); return new v.Opacity(_705,_706); }; MochiKit.Visual.puff=function(_709,_710){ var d=MochiKit.DOM; var v=MochiKit.Visual; _709=d.getElement(_709); var _711={opacity:d.getInlineOpacity(_709),position:d.getStyle(_709,"position")}; _710=MochiKit.Base.update({beforeSetupInternal:function(_712){ d.setStyle(_712.effects[0].element,{position:"absolute"}); },afterFinishInternal:function(_713){ d.hideElement(_713.effects[0].element); d.setStyle(_713.effects[0].element,_711); }},_710||{}); return new v.Parallel([new v.Scale(_709,200,{sync:true,scaleFromCenter:true,scaleContent:true,restoreAfterFinish:true}),new v.Opacity(_709,{sync:true,to:0})],_710); }; MochiKit.Visual.blindUp=function(_714,_715){ var d=MochiKit.DOM; _714=d.getElement(_714); d.makeClipping(_714); _715=MochiKit.Base.update({scaleContent:false,scaleX:false,restoreAfterFinish:true,afterFinishInternal:function(_716){ d.hideElement(_716.element); d.undoClipping(_716.element); }},_715||{}); return new MochiKit.Visual.Scale(_714,0,_715); }; MochiKit.Visual.blindDown=function(_717,_718){ var d=MochiKit.DOM; _717=d.getElement(_717); var _719=d.elementDimensions(_717); _718=MochiKit.Base.update({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:_719.h,originalWidth:_719.w},restoreAfterFinish:true,afterSetup:function(_720){ d.makeClipping(_720.element); d.setStyle(_720.element,{height:"0px"}); d.showElement(_720.element); },afterFinishInternal:function(_721){ d.undoClipping(_721.element); }},_718||{}); return new MochiKit.Visual.Scale(_717,100,_718); }; MochiKit.Visual.switchOff=function(_722){ var d=MochiKit.DOM; _722=d.getElement(_722); var _723=d.getInlineOpacity(_722); var _724={duration:0.3,scaleFromCenter:true,scaleX:false,scaleContent:false,restoreAfterFinish:true,beforeSetup:function(_725){ d.makePositioned(_725.element); d.makeClipping(_725.element); },afterFinishInternal:function(_726){ d.hideElement(_726.element); d.undoClipping(_726.element); d.undoPositioned(_726.element); d.setStyle(_726.element,{opacity:_723}); }}; var v=MochiKit.Visual; return new v.appear(_722,{duration:0.4,from:0,transition:v.Transitions.flicker,afterFinishInternal:function(_727){ new v.Scale(_727.element,1,_724); }}); }; MochiKit.Visual.dropOut=function(_728,_729){ var d=MochiKit.DOM; _728=d.getElement(_728); var _730={top:d.getStyle(_728,"top"),left:d.getStyle(_728,"left"),opacity:d.getInlineOpacity(_728)}; _729=MochiKit.Base.update({duration:0.5,beforeSetup:function(_731){ d.makePositioned(_731.effects[0].element); },afterFinishInternal:function(_732){ d.hideElement(_732.effects[0].element); d.undoPositioned(_732.effects[0].element); d.setStyle(_732.effects[0].element,_730); }},_729||{}); var v=MochiKit.Visual; return new v.Parallel([new v.Move(_728,{x:0,y:100,sync:true}),new v.Opacity(_728,{sync:true,to:0})],_729); }; MochiKit.Visual.shake=function(_733){ var d=MochiKit.DOM; var v=MochiKit.Visual; _733=d.getElement(_733); var _734={top:d.getStyle(_733,"top"),left:d.getStyle(_733,"left")}; return new v.Move(_733,{x:20,y:0,duration:0.05,afterFinishInternal:function(_735){ new v.Move(_735.element,{x:-40,y:0,duration:0.1,afterFinishInternal:function(_735){ new v.Move(_735.element,{x:40,y:0,duration:0.1,afterFinishInternal:function(_735){ new v.Move(_735.element,{x:-40,y:0,duration:0.1,afterFinishInternal:function(_735){ new v.Move(_735.element,{x:40,y:0,duration:0.1,afterFinishInternal:function(_735){ new v.Move(_735.element,{x:-20,y:0,duration:0.05,afterFinishInternal:function(_735){ d.undoPositioned(_735.element); d.setStyle(_735.element,_734); }}); }}); }}); }}); }}); }}); }; MochiKit.Visual.slideDown=function(_736,_737){ var d=MochiKit.DOM; var b=MochiKit.Base; _736=d.getElement(_736); d.cleanWhitespace(_736); var _738=d.getStyle(_736.firstChild,"bottom")||0; var _739=d.elementDimensions(_736); _737=b.update({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:_739.h,originalWidth:_739.w},restoreAfterFinish:true,afterSetup:function(_740){ d.makePositioned(_740.element); d.makePositioned(_740.element.firstChild); if(b.isOpera()){ d.setStyle(_740.element,{top:""}); } d.makeClipping(_740.element); d.setStyle(_740.element,{height:"0px"}); d.showElement(_736); },afterUpdateInternal:function(_741){ d.setStyle(_741.element.firstChild,{bottom:(_741.dims[0]-_741.element.clientHeight)+"px"}); },afterFinishInternal:function(_742){ d.undoClipping(_742.element); if(b.isIE()){ d.undoPositioned(_742.element); d.undoPositioned(_742.element.firstChild); }else{ d.undoPositioned(_742.element.firstChild); d.undoPositioned(_742.element); } d.setStyle(_742.element.firstChild,{bottom:_738}); }},_737||{}); return new MochiKit.Visual.Scale(_736,100,_737); }; MochiKit.Visual.slideUp=function(_743,_744){ var d=MochiKit.DOM; var b=MochiKit.Base; _743=d.getElement(_743); d.cleanWhitespace(_743); var _745=d.getStyle(_743.firstChild,"bottom"); _744=b.update({scaleContent:false,scaleX:false,scaleMode:"box",scaleFrom:100,restoreAfterFinish:true,beforeStartInternal:function(_746){ d.makePositioned(_746.element); d.makePositioned(_746.element.firstChild); if(b.isOpera()){ d.setStyle(_746.element,{top:""}); } d.makeClipping(_746.element); d.showElement(_743); },afterUpdateInternal:function(_747){ d.setStyle(_747.element.firstChild,{bottom:(_747.dims[0]-_747.element.clientHeight)+"px"}); },afterFinishInternal:function(_748){ d.hideElement(_748.element); d.undoClipping(_748.element); d.undoPositioned(_748.element.firstChild); d.undoPositioned(_748.element); d.setStyle(_748.element.firstChild,{bottom:_745}); }},_744||{}); return new MochiKit.Visual.Scale(_743,0,_744); }; MochiKit.Visual.squish=function(_749,_750){ var d=MochiKit.DOM; var b=MochiKit.Base; _750=b.update({restoreAfterFinish:true,beforeSetup:function(_751){ d.makeClipping(_751.element); },afterFinishInternal:function(_752){ d.hideElement(_752.element); d.undoClipping(_752.element); }},_750||{}); return new MochiKit.Visual.Scale(_749,b.isOpera()?1:0,_750); }; MochiKit.Visual.grow=function(_753,_754){ var d=MochiKit.DOM; var v=MochiKit.Visual; _753=d.getElement(_753); _754=MochiKit.Base.update({direction:"center",moveTransition:v.Transitions.sinoidal,scaleTransition:v.Transitions.sinoidal,opacityTransition:v.Transitions.full},_754||{}); var _755={top:_753.style.top,left:_753.style.left,height:_753.style.height,width:_753.style.width,opacity:d.getInlineOpacity(_753)}; var dims=d.elementDimensions(_753); var _757,initialMoveY; var _758,moveY; switch(_754.direction){ case "top-left": _757=initialMoveY=_758=moveY=0; break; case "top-right": _757=dims.w; initialMoveY=moveY=0; _758=-dims.w; break; case "bottom-left": _757=_758=0; initialMoveY=dims.h; moveY=-dims.h; break; case "bottom-right": _757=dims.w; initialMoveY=dims.h; _758=-dims.w; moveY=-dims.h; break; case "center": _757=dims.w/2; initialMoveY=dims.h/2; _758=-dims.w/2; moveY=-dims.h/2; break; } var _759=MochiKit.Base.update({beforeSetup:function(_760){ d.setStyle(_760.effects[0].element,{height:"0px"}); d.showElement(_760.effects[0].element); },afterFinishInternal:function(_761){ d.undoClipping(_761.effects[0].element); d.undoPositioned(_761.effects[0].element); d.setStyle(_761.effects[0].element,_755); }},_754||{}); return new v.Move(_753,{x:_757,y:initialMoveY,duration:0.01,beforeSetup:function(_762){ d.hideElement(_762.element); d.makeClipping(_762.element); d.makePositioned(_762.element); },afterFinishInternal:function(_763){ new v.Parallel([new v.Opacity(_763.element,{sync:true,to:1,from:0,transition:_754.opacityTransition}),new v.Move(_763.element,{x:_758,y:moveY,sync:true,transition:_754.moveTransition}),new v.Scale(_763.element,100,{scaleMode:{originalHeight:dims.h,originalWidth:dims.w},sync:true,scaleFrom:MochiKit.Base.isOpera()?1:0,transition:_754.scaleTransition,restoreAfterFinish:true})],_759); }}); }; MochiKit.Visual.shrink=function(_764,_765){ var d=MochiKit.DOM; var v=MochiKit.Visual; _764=d.getElement(_764); _765=MochiKit.Base.update({direction:"center",moveTransition:v.Transitions.sinoidal,scaleTransition:v.Transitions.sinoidal,opacityTransition:v.Transitions.none},_765||{}); var _766={top:_764.style.top,left:_764.style.left,height:_764.style.height,width:_764.style.width,opacity:d.getInlineOpacity(_764)}; var dims=d.elementDimensions(_764); var _767,moveY; switch(_765.direction){ case "top-left": _767=moveY=0; break; case "top-right": _767=dims.w; moveY=0; break; case "bottom-left": _767=0; moveY=dims.h; break; case "bottom-right": _767=dims.w; moveY=dims.h; break; case "center": _767=dims.w/2; moveY=dims.h/2; break; } var _768=MochiKit.Base.update({beforeStartInternal:function(_769){ d.makePositioned(_769.effects[0].element); d.makeClipping(_769.effects[0].element); },afterFinishInternal:function(_770){ d.hideElement(_770.effects[0].element); d.undoClipping(_770.effects[0].element); d.undoPositioned(_770.effects[0].element); d.setStyle(_770.effects[0].element,_766); }},_765||{}); return new v.Parallel([new v.Opacity(_764,{sync:true,to:0,from:1,transition:_765.opacityTransition}),new v.Scale(_764,MochiKit.Base.isOpera()?1:0,{sync:true,transition:_765.scaleTransition,restoreAfterFinish:true}),new v.Move(_764,{x:_767,y:moveY,sync:true,transition:_765.moveTransition})],_768); }; MochiKit.Visual.pulsate=function(_771,_772){ var d=MochiKit.DOM; var v=MochiKit.Visual; var b=MochiKit.Base; _771=d.getElement(_771); _772=b.update({duration:3,from:0,afterFinishInternal:function(_773){ d.setStyle(_773.element,{opacity:oldOpacity}); }},_772||{}); var _774=d.getInlineOpacity(_771); var _775=_772.transition||v.Transitions.sinoidal; var _776=b.bind(function(pos){ return _775(1-v.Transitions.pulse(pos)); },_775); b.bind(_776,_775); return new v.Opacity(_771,b.update({transition:_776},_772)); }; MochiKit.Visual.fold=function(_777,_778){ var d=MochiKit.DOM; var v=MochiKit.Visual; _777=d.getElement(_777); var _779={top:_777.style.top,left:_777.style.left,width:_777.style.width,height:_777.style.height}; d.makeClipping(_777); _778=MochiKit.Base.update({scaleContent:false,scaleX:false,afterFinishInternal:function(_780){ new v.Scale(_777,1,{scaleContent:false,scaleY:false,afterFinishInternal:function(_780){ d.hideElement(_780.element); d.undoClipping(_780.element); d.setStyle(_780.element,_779); }}); }},_778||{}); return new v.Scale(_777,5,_778); }; MochiKit.Visual.Color=MochiKit.Color.Color; MochiKit.Visual.getElementsComputedStyle=MochiKit.DOM.computedStyle; MochiKit.Visual.__new__=function(){ var m=MochiKit.Base; m.nameFunctions(this); this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; }; MochiKit.Visual.EXPORT=["roundElement","roundClass","tagifyText","multiple","toggle","Base","Parallel","Opacity","Move","Scale","Highlight","ScrollTo","fade","appear","puff","blindUp","blindDown","switchOff","dropOut","shake","slideDown","slideUp","squish","grow","shrink","pulsate","fold"]; MochiKit.Visual.EXPORT_OK=["PAIRS"]; MochiKit.Visual.__new__(); MochiKit.Base._exportSymbols(this,MochiKit.Visual); if(typeof (MochiKit)=="undefined"){ MochiKit={}; } if(typeof (MochiKit.MochiKit)=="undefined"){ MochiKit.MochiKit={}; } MochiKit.MochiKit.NAME="MochiKit.MochiKit"; MochiKit.MochiKit.VERSION="1.4"; MochiKit.MochiKit.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.MochiKit.toString=function(){ return this.__repr__(); }; MochiKit.MochiKit.SUBMODULES=["Base","Iter","Logging","DateTime","Format","Async","DOM","LoggingPane","Color","Signal","Visual"]; if(typeof (JSAN)!="undefined"||typeof (dojo)!="undefined"){ if(typeof (dojo)!="undefined"){ dojo.provide("MochiKit.MochiKit"); dojo.require("MochiKit.*"); } if(typeof (JSAN)!="undefined"){ JSAN.use("MochiKit.Base",[]); JSAN.use("MochiKit.Iter",[]); JSAN.use("MochiKit.Logging",[]); JSAN.use("MochiKit.DateTime",[]); JSAN.use("MochiKit.Format",[]); JSAN.use("MochiKit.Async",[]); JSAN.use("MochiKit.DOM",[]); JSAN.use("MochiKit.LoggingPane",[]); JSAN.use("MochiKit.Color",[]); JSAN.use("MochiKit.Signal",[]); JSAN.use("MochiKit.Visual",[]); } (function(){ var _781=MochiKit.Base.extend; var self=MochiKit.MochiKit; var _782=self.SUBMODULES; var _783=[]; var _784=[]; var _785={}; var i,k,m,all; for(i=0;i<_782.length;i++){ m=MochiKit[_782[i]]; _781(_783,m.EXPORT); _781(_784,m.EXPORT_OK); for(k in m.EXPORT_TAGS){ _785[k]=_781(_785[k],m.EXPORT_TAGS[k]); } all=m.EXPORT_TAGS[":all"]; if(!all){ all=_781(null,m.EXPORT,m.EXPORT_OK); } var j; for(j=0;j"); } } })(); } PK44YYpaste/util/threadinglocal.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 try: import threading except ImportError: # No threads, so "thread local" means process-global class local(object): pass else: try: local = threading.local except AttributeError: # Added in 2.4, but now we'll have to define it ourselves import thread class local(object): def __init__(self): self.__dict__['__objs'] = {} def __getattr__(self, attr, g=thread.get_ident): try: return self.__dict__['__objs'][g()][attr] except KeyError: raise AttributeError( "No variable %s defined for the thread %s" % (attr, g())) def __setattr__(self, attr, value, g=thread.get_ident): self.__dict__['__objs'].setdefault(g(), {})[attr] = value def __delattr__(self, attr, g=thread.get_ident): try: del self.__dict__['__objs'][g()][attr] except KeyError: raise AttributeError( "No variable %s defined for thread %s" % (attr, g())) PK4NFFpaste/util/UserDict24.py"""A more or less complete user-defined wrapper around dictionary objects.""" class UserDict: def __init__(self, dict=None, **kwargs): self.data = {} if dict is not None: if not hasattr(dict,'keys'): dict = type({})(dict) # make mapping from a sequence self.update(dict) if len(kwargs): self.update(kwargs) def __repr__(self): return repr(self.data) def __cmp__(self, dict): if isinstance(dict, UserDict): return cmp(self.data, dict.data) else: return cmp(self.data, dict) def __len__(self): return len(self.data) def __getitem__(self, key): return self.data[key] def __setitem__(self, key, item): self.data[key] = item def __delitem__(self, key): del self.data[key] def clear(self): self.data.clear() def copy(self): if self.__class__ is UserDict: return UserDict(self.data) import copy data = self.data try: self.data = {} c = copy.copy(self) finally: self.data = data c.update(self) return c def keys(self): return self.data.keys() def items(self): return self.data.items() def iteritems(self): return self.data.iteritems() def iterkeys(self): return self.data.iterkeys() def itervalues(self): return self.data.itervalues() def values(self): return self.data.values() def has_key(self, key): return self.data.has_key(key) def update(self, dict): if isinstance(dict, UserDict): self.data.update(dict.data) elif isinstance(dict, type(self.data)): self.data.update(dict) else: for k, v in dict.items(): self[k] = v def get(self, key, failobj=None): if not self.has_key(key): return failobj return self[key] def setdefault(self, key, failobj=None): if not self.has_key(key): self[key] = failobj return self[key] def pop(self, key, *args): return self.data.pop(key, *args) def popitem(self): return self.data.popitem() def __contains__(self, key): return key in self.data def fromkeys(cls, iterable, value=None): d = cls() for key in iterable: d[key] = value return d fromkeys = classmethod(fromkeys) class IterableUserDict(UserDict): def __iter__(self): return iter(self.data) class DictMixin: # Mixin defining all dictionary methods for classes that already have # a minimum dictionary interface including getitem, setitem, delitem, # and keys. Without knowledge of the subclass constructor, the mixin # does not define __init__() or copy(). In addition to the four base # methods, progressively more efficiency comes with defining # __contains__(), __iter__(), and iteritems(). # second level definitions support higher levels def __iter__(self): for k in self.keys(): yield k def has_key(self, key): try: value = self[key] except KeyError: return False return True def __contains__(self, key): return self.has_key(key) # third level takes advantage of second level definitions def iteritems(self): for k in self: yield (k, self[k]) def iterkeys(self): return self.__iter__() # fourth level uses definitions from lower levels def itervalues(self): for _, v in self.iteritems(): yield v def values(self): return [v for _, v in self.iteritems()] def items(self): return list(self.iteritems()) def clear(self): for key in self.keys(): del self[key] def setdefault(self, key, default): try: return self[key] except KeyError: self[key] = default return default def pop(self, key, *args): if len(args) > 1: raise TypeError, "pop expected at most 2 arguments, got "\ + repr(1 + len(args)) try: value = self[key] except KeyError: if args: return args[0] raise del self[key] return value def popitem(self): try: k, v = self.iteritems().next() except StopIteration: raise KeyError, 'container is empty' del self[k] return (k, v) def update(self, other): # Make progressively weaker assumptions about "other" if hasattr(other, 'iteritems'): # iteritems saves memory and lookups for k, v in other.iteritems(): self[k] = v elif hasattr(other, '__iter__'): # iter saves memory for k in other: self[k] = other[k] else: for k in other.keys(): self[k] = other[k] def get(self, key, default=None): try: return self[key] except KeyError: return default def __repr__(self): return repr(dict(self.iteritems())) def __cmp__(self, other): if other is None: return 1 if isinstance(other, DictMixin): other = dict(other.iteritems()) return cmp(dict(self.iteritems()), other) def __len__(self): return len(self.keys()) PK4SM599paste/util/classinit.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 class ClassInitMeta(type): def __new__(meta, class_name, bases, new_attrs): cls = type.__new__(meta, class_name, bases, new_attrs) if (new_attrs.has_key('__classinit__') and not isinstance(cls.__classinit__, staticmethod)): setattr(cls, '__classinit__', staticmethod(cls.__classinit__.im_func)) if hasattr(cls, '__classinit__'): cls.__classinit__(cls, new_attrs) return cls def build_properties(cls, new_attrs): """ Given a class and a new set of attributes (as passed in by __classinit__), create or modify properties based on functions with special names ending in __get, __set, and __del. """ for name, value in new_attrs.items(): if (name.endswith('__get') or name.endswith('__set') or name.endswith('__del')): base = name[:-5] if hasattr(cls, base): old_prop = getattr(cls, base) if not isinstance(old_prop, property): raise ValueError( "Attribute %s is a %s, not a property; function %s is named like a property" % (base, type(old_prop), name)) attrs = {'fget': old_prop.fget, 'fset': old_prop.fset, 'fdel': old_prop.fdel, 'doc': old_prop.__doc__} else: attrs = {} attrs['f' + name[-3:]] = value if name.endswith('__get') and value.__doc__: attrs['doc'] = value.__doc__ new_prop = property(**attrs) setattr(cls, base, new_prop) PK45F>**paste/util/datetimeutil.py# (c) 2005 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 """ Date, Time, and Timespan Parsing Utilities This module contains parsing support to create "human friendly" ``datetime`` object parsing. The explicit goal of these routines is to provide a multi-format date/time support not unlike that found in Microsoft Excel. In most approaches, the input is very "strict" to prevent errors -- however, this approach is much more liberal since we are assuming the user-interface is parroting back the normalized value and thus the user has immediate feedback if the data is not typed in correctly. ``parse_date`` and ``normalize_date`` These functions take a value like '9 jan 2007' and returns either an ``date`` object, or an ISO 8601 formatted date value such as '2007-01-09'. There is an option to provide an Oracle database style output as well, ``09 JAN 2007``, but this is not the default. This module always treats '/' delimiters as using US date order (since the author's clients are US based), hence '1/9/2007' is January 9th. Since this module treats the '-' as following European order this supports both modes of data-entry; together with immediate parroting back the result to the screen, the author has found this approach to work well in pratice. ``parse_time`` and ``normalize_time`` These functions take a value like '1 pm' and returns either an ``time`` object, or an ISO 8601 formatted 24h clock time such as '13:00'. There is an option to provide for US style time values, '1:00 PM', however this is not the default. ``parse_datetime`` and ``normalize_datetime`` These functions take a value like '9 jan 2007 at 1 pm' and returns either an ``datetime`` object, or an ISO 8601 formatted return (without the T) such as '2007-01-09 13:00'. There is an option to provide for Oracle / US style, '09 JAN 2007 @ 1:00 PM', however this is not the default. ``parse_delta`` and ``normalize_delta`` These functions take a value like '1h 15m' and returns either an ``timedelta`` object, or an 2-decimal fixed-point numerical value in hours, such as '1.25'. The rationale is to support meeting or time-billing lengths, not to be an accurate representation in mili-seconds. As such not all valid ``timedelta`` values will have a normalized representation. """ from datetime import timedelta, time, date, datetime from time import localtime import string __all__ = ['parse_timedelta', 'normalize_timedelta', 'parse_time', 'normalize_time', 'parse_date', 'normalize_date'] def _number(val): try: return string.atoi(val) except: return None # # timedelta # def parse_timedelta(val): """ returns a ``timedelta`` object, or None """ if not val: return None val = string.lower(val) if "." in val: val = float(val) return timedelta(hours=int(val), minutes=60*(val % 1.0)) fHour = ("h" in val or ":" in val) fMin = ("m" in val or ":" in val) fFraction = "." in val for noise in "minu:teshour()": val = string.replace(val,noise,' ') val = string.strip(val) val = string.split(val) hr = 0.0 mi = 0 val.reverse() if fHour: hr = int(val.pop()) if fMin: mi = int(val.pop()) if len(val) > 0 and not hr: hr = int(val.pop()) return timedelta(hours=hr, minutes=mi) def normalize_timedelta(val): """ produces a normalized string value of the timedelta This module returns a normalized time span value consisting of the number of hours in fractional form. For example '1h 15min' is formatted as 01.25. """ if type(val) == str: val = parse_timedelta(val) if not val: return '' hr = val.seconds/3600 mn = (val.seconds % 3600)/60 return "%d.%02d" % (hr,mn*100/60) # # time # def parse_time(val): if not val: return None hr = mi = 0 val = string.lower(val) amflag = (-1 != string.find(val,'a')) # set if AM is found pmflag = (-1 != string.find(val,'p')) # set if PM is found for noise in ":amp.": val = string.replace(val,noise,' ') val = string.split(val) if len(val) > 1: hr = int(val[0]) mi = int(val[1]) else: val = val[0] if len(val) < 1: pass elif 'now' == val: tm = localtime() hr = tm[3] mi = tm[4] elif 'noon' == val: hr = 12 elif len(val) < 3: hr = int(val) if not amflag and not pmflag and hr < 7: hr += 12 elif len(val) < 5: hr = int(val[:-2]) mi = int(val[-2:]) else: hr = int(val[:1]) if amflag and hr >= 12: hr = hr - 12 if pmflag and hr < 12 : hr = hr + 12 return time(hr,mi) def normalize_time(value, ampm): if not value: return '' if type(value) == str: value = parse_time(value) if not ampm: return "%02d:%02d" % (value.hour, value.minute) hr = value.hour am = "AM" if hr < 1 or hr > 23: hr = 12 elif hr >= 12: am = "PM" if hr > 12: hr = hr - 12 return "%02d:%02d %s" % (hr,value.minute,am) # # Date Processing # _one_day = timedelta(days=1) _str2num = {'jan':1, 'feb':2, 'mar':3, 'apr':4, 'may':5, 'jun':6, 'jul':7, 'aug':8, 'sep':9, 'oct':10, 'nov':11, 'dec':12 } def _month(val): for (key,mon) in _str2num.items(): if key in val: return mon return None _days_in_month = {1:31,2:28,3:31,4:30,5:31,6:30, 7:31,8:31,9:30,10:31,11:30,12:31 } _num2str = { 1:'Jan', 2:'Feb', 3:'Mar', 4:'Apr', 5:'May', 6:'Jun', 7:'Jul', 8:'Aug', 9:'Sep', 10:'Oct', 11:'Nov', 12:'Dec' } _wkdy = ("mon","tue","wed","thu","fri","sat","sun" ) def parse_date(val): if not(val): return None val = string.lower(val) now = None # optimized check for YYYY-MM-DD strict = val.split("-") if len(strict) == 3: (y,m,d) = strict if "+" in d: d = d.split("+")[0] if " " in d: d = d.split(" ")[0] try: now = date(int(y),int(m),int(d)) val = "xxx" + val[10:] except ValueError: pass # allow for 'now', 'mon', 'tue', etc. if not now: chk = val[:3] if 'now' == chk: now = date.today() elif chk in _wkdy: now = date.today() idx = list(_wkdy).index(chk) while now.day_of_week != idx: now += _one_day # allow dates to be modified via + or - /w number of days, so # that now+3 is three days from now if now: tail = val[3:].strip() tail = tail.replace("+"," +").replace("-"," -") for item in tail.split(): try: days = int(item) except ValueError: pass else: now += timedelta(days=days) return now # ok, standard parsing yr = mo = dy = None for noise in ('/','-',',','*'): val = string.replace(val,noise,' ') for noise in _wkdy: val = string.replace(val,noise,' ') out = [] last = False ldig = False for ch in val: if ch.isdigit(): if last and not ldig: out.append(' ') last = ldig = True else: if ldig: out.append(' ') ldig = False last = True out.append(ch) val = string.split("".join(out)) if 3 == len(val): a = _number(val[0]) b = _number(val[1]) c = _number(val[2]) if len(val[0]) == 4: yr = a if b: # 1999 6 23 mo = b dy = c else: # 1999 Jun 23 mo = _month(val[1]) dy = c elif a > 0: yr = c if len(val[2]) < 4: raise TypeError("four digit year required") if b: # 6 23 1999 dy = b mo = a else: # 23 Jun 1999 dy = a mo = _month(val[1]) else: # Jun 23, 2000 dy = b yr = c if len(val[2]) < 4: raise TypeError("four digit year required") mo = _month(val[0]) elif 2 == len(val): a = _number(val[0]) b = _number(val[1]) if a > 999: yr = a dy = 1 if b > 0: # 1999 6 mo = b else: # 1999 Jun mo = _month(val[1]) elif a > 0: if b > 999: # 6 1999 mo = a yr = b dy = 1 elif b > 0: # 6 23 mo = a dy = b else: # 23 Jun dy = a mo = _month(val[1]) else: if b > 999: # Jun 2001 yr = b dy = 1 else: # Jun 23 dy = b mo = _month(val[0]) elif 1 == len(val): val = val[0] if not val.isdigit(): mo = _month(val) if mo is not None: dy = 1 else: v = _number(val) val = str(v) if 8 == len(val): # 20010623 yr = _number(val[:4]) mo = _number(val[4:6]) dy = _number(val[6:]) elif len(val) in (3,4): if v > 1300: # 2004 yr = v mo = 1 dy = 1 else: # 1202 mo = _number(val[:-2]) dy = _number(val[-2:]) elif v < 32: dy = v else: raise TypeError("four digit year required") tm = localtime() if mo is None: mo = tm[1] if dy is None: dy = tm[2] if yr is None: yr = tm[0] return date(yr,mo,dy) def normalize_date(val, iso8601=True): if not val: return '' if type(val) == str: val = parse_date(val) if iso8601: return "%4d-%02d-%02d" % (val.year, val.month, val.day) return "%02d %s %4d" % (val.day,_num2str[val.month],val.year) PK4,]]paste/util/classinstance.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 class classinstancemethod(object): """ Acts like a class method when called from a class, like an instance method when called by an instance. The method should take two arguments, 'self' and 'cls'; one of these will be None depending on how the method was called. """ def __init__(self, func): self.func = func self.__doc__ = func.__doc__ def __get__(self, obj, type=None): return _methodwrapper(self.func, obj=obj, type=type) class _methodwrapper(object): def __init__(self, func, obj, type): self.func = func self.obj = obj self.type = type def __call__(self, *args, **kw): assert not kw.has_key('self') and not kw.has_key('cls'), ( "You cannot use 'self' or 'cls' arguments to a " "classinstancemethod") return self.func(*((self.obj, self.type) + args), **kw) def __repr__(self): if self.obj is None: return ('' % (self.type.__name__, self.func.func_name)) else: return ('' % (self.type.__name__, self.func.func_name, self.obj)) PK4-7$7$paste/util/ip4.py# -*- coding: iso-8859-15 -*- """IP4 address range set implementation. Implements an IPv4-range type. Copyright (C) 2006, Heiko Wundram. Released under the MIT-license. """ # Version information # ------------------- __author__ = "Heiko Wundram " __version__ = "0.2" __revision__ = "3" __date__ = "2006-01-20" # Imports # ------- import intset import socket # IP4Range class # -------------- class IP4Range(intset.IntSet): """IP4 address range class with efficient storage of address ranges. Supports all set operations.""" _MINIP4 = 0 _MAXIP4 = (1<<32) - 1 _UNITYTRANS = "".join([chr(n) for n in range(256)]) _IPREMOVE = "0123456789." def __init__(self,*args): """Initialize an ip4range class. The constructor accepts an unlimited number of arguments that may either be tuples in the form (start,stop), integers, longs or strings, where start and stop in a tuple may also be of the form integer, long or string. Passing an integer or long means passing an IPv4-address that's already been converted to integer notation, whereas passing a string specifies an address where this conversion still has to be done. A string address may be in the following formats: - 1.2.3.4 - a plain address, interpreted as a single address - 1.2.3 - a set of addresses, interpreted as 1.2.3.0-1.2.3.255 - localhost - hostname to look up, interpreted as single address - 1.2.3<->5 - a set of addresses, interpreted as 1.2.3.0-1.2.5.255 - 1.2.0.0/16 - a set of addresses, interpreted as 1.2.0.0-1.2.255.255 Only the first three notations are valid if you use a string address in a tuple, whereby notation 2 is interpreted as 1.2.3.0 if specified as lower bound and 1.2.3.255 if specified as upper bound, not as a range of addresses. Specifying a range is done with the <-> operator. This is necessary because '-' might be present in a hostname. '<->' shouldn't be, ever. """ # Special case copy constructor. if len(args) == 1 and isinstance(args[0],IP4Range): super(IP4Range,self).__init__(args[0]) return # Convert arguments to tuple syntax. args = list(args) for i in range(len(args)): argval = args[i] if isinstance(argval,str): if "<->" in argval: # Type 4 address. args[i] = self._parseRange(*argval.split("<->",1)) continue elif "/" in argval: # Type 5 address. args[i] = self._parseMask(*argval.split("/",1)) else: # Type 1, 2 or 3. args[i] = self._parseAddrRange(argval) elif isinstance(argval,tuple): if len(tuple) <> 2: raise ValueError("Tuple is of invalid length.") addr1, addr2 = argval if isinstance(addr1,str): addr1 = self._parseAddrRange(addr1)[0] elif not isinstance(addr1,(int,long)): raise TypeError("Invalid argument.") if isinstance(addr2,str): addr2 = self._parseAddrRange(addr2)[1] elif not isinstance(addr2,(int,long)): raise TypeError("Invalid argument.") args[i] = (addr1,addr2) elif not isinstance(argval,(int,long)): raise TypeError("Invalid argument.") # Initialize the integer set. super(IP4Range,self).__init__(min=self._MINIP4,max=self._MAXIP4,*args) # Parsing functions # ----------------- def _parseRange(self,addr1,addr2): naddr1, naddr1len = _parseAddr(addr1) naddr2, naddr2len = _parseAddr(addr2) if naddr2len < naddr1len: naddr2 += naddr1&(((1<<((naddr1len-naddr2len)*8))-1)<< (naddr2len*8)) naddr2len = naddr1len elif naddr2len > naddr1len: raise ValueError("Range has more dots than address.") naddr1 <<= (4-naddr1len)*8 naddr2 <<= (4-naddr2len)*8 naddr2 += (1<<((4-naddr2len)*8))-1 return (naddr1,naddr2) def _parseMask(self,addr,mask): naddr, naddrlen = _parseAddr(addr) naddr <<= (4-naddrlen)*8 try: if not mask: masklen = 0 else: masklen = int(mask) if not 0 <= masklen <= 32: raise ValueError except ValueError: try: mask = _parseAddr(mask,False) except ValueError: raise ValueError("Mask isn't parseable.") remaining = 0 masklen = 0 if not mask: masklen = 0 else: while not (mask&1): remaining += 1 while (mask&1): mask >>= 1 masklen += 1 if remaining+masklen <> 32: raise ValueError("Mask isn't a proper host mask.") naddr1 = naddr & (((1<>= 8 return ".".join(reversed(rv)) # Iterating # --------- def iteraddresses(self): """Returns an iterator which iterates over ips in this iprange. An IP is returned in string form (e.g. '1.2.3.4').""" for v in super(IP4Range,self).__iter__(): yield self._int2ip(v) def iterranges(self): """Returns an iterator which iterates over ip-ip ranges which build this iprange if combined. An ip-ip pair is returned in string form (e.g. '1.2.3.4-2.3.4.5').""" for r in self._ranges: if r[1]-r[0] == 1: yield self._int2ip(r[0]) else: yield '%s-%s' % (self._int2ip(r[0]),self._int2ip(r[1]-1)) def itermasks(self): """Returns an iterator which iterates over ip/mask pairs which build this iprange if combined. An IP/Mask pair is returned in string form (e.g. '1.2.3.0/24').""" for r in self._ranges: for v in self._itermasks(r): yield v def _itermasks(self,r): ranges = [r] while ranges: cur = ranges.pop() curmask = 0 while True: curmasklen = 1<<(32-curmask) start = (cur[0]+curmasklen-1)&(((1<= cur[0] and start+curmasklen <= cur[1]: break else: curmask += 1 yield "%s/%s" % (self._int2ip(start),curmask) if cur[0] < start: ranges.append((cur[0],start)) if cur[1] > start+curmasklen: ranges.append((start+curmasklen,cur[1])) __iter__ = iteraddresses # Printing # -------- def __repr__(self): """Returns a string which can be used to reconstruct this iprange.""" rv = [] for start, stop in self._ranges: if stop-start == 1: rv.append("%r" % (self._int2ip(start),)) else: rv.append("(%r,%r)" % (self._int2ip(start), self._int2ip(stop-1))) return "%s(%s)" % (self.__class__.__name__,",".join(rv)) def _parseAddr(addr,lookup=True): if lookup and addr.translate(IP4Range._UNITYTRANS, IP4Range._IPREMOVE): try: addr = socket.gethostbyname(addr) except socket.error: raise ValueError("Invalid Hostname as argument.") naddr = 0 for naddrpos, part in enumerate(addr.split(".")): if naddrpos >= 4: raise ValueError("Address contains more than four parts.") try: if not part: part = 0 else: part = int(part) if not 0 <= part < 256: raise ValueError except ValueError: raise ValueError("Address part out of range.") naddr <<= 8 naddr += part return naddr, naddrpos+1 def ip2int(addr, lookup=True): return _parseAddr(addr, lookup=lookup)[0] if __name__ == "__main__": # Little test script. x = IP4Range("172.22.162.250/24") y = IP4Range("172.22.162.250","172.22.163.250","172.22.163.253<->255") print x for val in x.itermasks(): print val for val in y.itermasks(): print val for val in (x|y).itermasks(): print val for val in (x^y).iterranges(): print val for val in x: print val PK4>paste/util/findpackage.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 import sys import os def find_package(dir): """ Given a directory, finds the equivalent package name. If it is directly in sys.path, returns ''. """ dir = os.path.abspath(dir) orig_dir = dir path = map(os.path.abspath, sys.path) packages = [] last_dir = None while 1: if dir in path: return '.'.join(packages) packages.insert(0, os.path.basename(dir)) dir = os.path.dirname(dir) if last_dir == dir: raise ValueError( "%s is not under any path found in sys.path" % orig_dir) last_dir = dir PK4vpaste/util/threadedprint.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 """ threadedprint.py ================ :author: Ian Bicking :date: 12 Jul 2004 Multi-threaded printing; allows the output produced via print to be separated according to the thread. To use this, you must install the catcher, like:: threadedprint.install() The installation optionally takes one of three parameters: default The default destination for print statements (e.g., ``sys.stdout``). factory A function that will produce the stream for a thread, given the thread's name. paramwriter Instead of writing to a file-like stream, this function will be called like ``paramwriter(thread_name, text)`` for every write. The thread name is the value returned by ``threading.currentThread().getName()``, a string (typically something like Thread-N). You can also submit file-like objects for specific threads, which will override any of these parameters. To do this, call ``register(stream, [threadName])``. ``threadName`` is optional, and if not provided the stream will be registered for the current thread. If no specific stream is registered for a thread, and no default has been provided, then an error will occur when anything is written to ``sys.stdout`` (or printed). Note: the stream's ``write`` method will be called in the thread the text came from, so you should consider thread safety, especially if multiple threads share the same writer. Note: if you want access to the original standard out, use ``sys.__stdout__``. You may also uninstall this, via:: threadedprint.uninstall() TODO ---- * Something with ``sys.stderr``. * Some default handlers. Maybe something that hooks into `logging`. * Possibly cache the results of ``factory`` calls. This would be a semantic change. """ import threading import sys import filemixin class PrintCatcher(filemixin.FileMixin): def __init__(self, default=None, factory=None, paramwriter=None, leave_stdout=False): assert len(filter(lambda x: x is not None, [default, factory, paramwriter])) <= 1, ( "You can only provide one of default, factory, or paramwriter") if leave_stdout: assert not default, ( "You cannot pass in both default (%r) and " "leave_stdout=True" % default) default = sys.stdout if default: self._defaultfunc = self._writedefault elif factory: self._defaultfunc = self._writefactory elif paramwriter: self._defaultfunc = self._writeparam else: self._defaultfunc = self._writeerror self._default = default self._factory = factory self._paramwriter = paramwriter self._catchers = {} def write(self, v, currentThread=threading.currentThread): name = currentThread().getName() catchers = self._catchers if not catchers.has_key(name): self._defaultfunc(name, v) else: catcher = catchers[name] catcher.write(v) def _writedefault(self, name, v): self._default.write(v) def _writefactory(self, name, v): self._factory(name).write(v) def _writeparam(self, name, v): self._paramwriter(name, v) def _writeerror(self, name, v): assert False, ( "There is no PrintCatcher output stream for the thread %r" % name) def register(self, catcher, name=None, currentThread=threading.currentThread): if name is None: name = currentThread().getName() self._catchers[name] = catcher def deregister(self, name=None, currentThread=threading.currentThread): if name is None: name = currentThread().getName() assert self._catchers.has_key(name), ( "There is no PrintCatcher catcher for the thread %r" % name) del self._catchers[name] _printcatcher = None _oldstdout = None def install(**kw): global _printcatcher, _oldstdout, register, deregister if not _printcatcher: _oldstdout = sys.stdout _printcatcher = sys.stdout = PrintCatcher(**kw) register = _printcatcher.register deregister = _printcatcher.deregister def uninstall(): global _printcatcher, _oldstdout, register, deregister if _printcatcher: sys.stdout = _oldstdout _printcatcher = _oldstdout = None register = not_installed_error deregister = not_installed_error def not_installed_error(*args, **kw): assert False, ( "threadedprint has not yet been installed (call " "threadedprint.install())") register = deregister = not_installed_error class StdinCatcher(filemixin.FileMixin): def __init__(self, default=None, factory=None, paramwriter=None): assert len(filter(lambda x: x is not None, [default, factory, paramwriter])) <= 1, ( "You can only provide one of default, factory, or paramwriter") if default: self._defaultfunc = self._readdefault elif factory: self._defaultfunc = self._readfactory elif paramwriter: self._defaultfunc = self._readparam else: self._defaultfunc = self._readerror self._default = default self._factory = factory self._paramwriter = paramwriter self._catchers = {} def read(self, size=None, currentThread=threading.currentThread): name = currentThread().getName() catchers = self._catchers if not catchers.has_key(name): self._defaultfunc(name, size) else: catcher = catchers[name] catcher.read(size) def _readdefault(self, name, size): self._default.read(size) def _readfactory(self, name, size): self._factory(name).read(size) def _readparam(self, name, size): self._paramreader(name, size) def _readerror(self, name, size): assert False, ( "There is no StdinCatcher output stream for the thread %r" % name) def register(self, catcher, name=None, currentThread=threading.currentThread): if name is None: name = currentThread.getName() self._catchers[name] = catcher def deregister(self, catcher, name=None, currentThread=threading.currentThread): if name is None: name = currentThread().getName() assert self._catchers.has_key(name), ( "There is no StdinCatcher catcher for the thread %r" % name) del self._catchers[name] _stdincatcher = None _oldstdin = None def install_stdin(**kw): global _stdincatcher, _oldstdin, register_stdin, deregister_stdin if not _stdincatcher: _oldstdin = sys.stdin _stdincatcher = sys.stdin = StdinCatcher(**kw) register_stdin = _stdincatcher.register deregister_stdin = _stdincatcher.deregister def uninstall(): global _stdincatcher, _oldstin, register_stdin, deregister_stdin if _stdincatcher: sys.stdin = _oldstdin _stdincatcher = _oldstdin = None register_stdin = deregister_stdin = not_installed_error_stdin def not_installed_error_stdin(*args, **kw): assert False, ( "threadedprint has not yet been installed for stdin (call " "threadedprint.install_stdin())") PK4_5paste/util/multidict.pyfrom UserDict import DictMixin class multidict(DictMixin): """ An ordered dictionary that can have multiple values for each key. Adds the methods getall, getone, and add to the normal dictionary interface. """ def __init__(self, *args, **kw): if len(args) > 1: raise TypeError( "multidict can only be called with one positional argument") if args and kw: raise TypeError( "multidict can be called with a positional argument *or* " "keyword arguments, not both") if args: if hasattr(args[0], 'iteritems'): items = list(args[0].iteritems()) elif hasattr(args[0], 'items'): items = args[0].items() else: items = list(args[0]) self._items = items elif kw: self._items = kw.items() else: self._items = [] def __getitem__(self, key): for k, v in self._items: if k == key: return v raise KeyError(repr(key)) def __setitem__(self, key, value): try: del self[key] except KeyError: pass self._items.append((key, value)) def add(self, key, value): """ Add they key and value, not overwriting any previous value. """ self._items.append((key, value)) def getall(self, key): """ Return a list of all values matching the key (may be an empty list) """ result = [] for k, v in self._items: if key == k: result.append(v) return result def getone(self, key): """ Get one value matching the key, raising a KeyError if multiple values were found. """ v = self.getall(key) if not v: raise KeyError('Key not found: %r' % key) if len(v) > 1: raise KeyError('Multiple values match %r: %r' % (key, v)) return v[0] def __delitem__(self, key): items = self._items found = False for i in range(len(items)-1, -1, -1): if items[i][0] == key: del items[i] found = True if not found: raise KeyError(repr(key)) def __contains__(self, key): for k, v in self._items: if k == key: return True return False has_key = __contains__ def clear(self): self._items = [] def setdefault(self, key, default=None): for k, v in self._items: if key == k: return v self._items.append(default) return default def pop(self, key, *args): if len(args) > 1: raise TypeError, "pop expected at most 2 arguments, got "\ + repr(1 + len(args)) for i in range(len(self._items)): if self._items[i][0] == key: v = self._items[i][1] del self._items[i] return v if args: return args[0] else: raise KeyError(repr(key)) def popitem(self): return self._items.pop() def update(self, other=None, **kwargs): if other is None: pass elif hasattr(other, 'items'): self._items.extend(other.items()) elif hasattr(other, 'keys'): for k in other.keys(): self._items.append((k, other[k])) else: for k, v in other: self._items.append((k, v)) if kwargs: self.update(kwargs) def __repr__(self): items = ', '.join(['(%r, %r)' % v for v in self._items]) return 'multidict([%s])' % items def __len__(self): return len(self._items) ## ## All the iteration: ## def keys(self): return [k for k, v in self._items] def iterkeys(self): for k, v in self._items: yield k __iter__ = iterkeys def items(self): return self._items[:] def iteritems(self): return iter(self._items) def values(self): return [v for k, v in self._items] def itervalues(self): for k, v in self._items: yield v __test__ = { 'general': """ >>> d = multidict(a=1, b=2) >>> d['a'] 1 >>> d.getall('c') [] >>> d.add('a', 2) >>> d['a'] 1 >>> d.getall('a') [1, 2] >>> d['b'] = 4 >>> d.getall('b') [4] >>> d.keys() ['a', 'a', 'b'] >>> d.items() [('a', 1), ('a', 2), ('b', 4)] """} if __name__ == '__main__': import doctest doctest.testmod() PK4FtaÜÜpaste/util/subprocess24.py# subprocess - Subprocesses with accessible I/O streams # # For more information about this module, see PEP 324. # # This module should remain compatible with Python 2.2, see PEP 291. # # Copyright (c) 2003-2005 by Peter Astrand # # Licensed to PSF under a Contributor Agreement. # See http://www.python.org/2.4/license for licensing details. r"""subprocess - Subprocesses with accessible I/O streams This module allows you to spawn processes, connect to their input/output/error pipes, and obtain their return codes. This module intends to replace several other, older modules and functions, like: os.system os.spawn* os.popen* popen2.* commands.* Information about how the subprocess module can be used to replace these modules and functions can be found below. Using the subprocess module =========================== This module defines one class called Popen: class Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0): Arguments are: args should be a string, or a sequence of program arguments. The program to execute is normally the first item in the args sequence or string, but can be explicitly set by using the executable argument. On UNIX, with shell=False (default): In this case, the Popen class uses os.execvp() to execute the child program. args should normally be a sequence. A string will be treated as a sequence with the string as the only item (the program to execute). On UNIX, with shell=True: If args is a string, it specifies the command string to execute through the shell. If args is a sequence, the first item specifies the command string, and any additional items will be treated as additional shell arguments. On Windows: the Popen class uses CreateProcess() to execute the child program, which operates on strings. If args is a sequence, it will be converted to a string using the list2cmdline method. Please note that not all MS Windows applications interpret the command line the same way: The list2cmdline is designed for applications using the same rules as the MS C runtime. bufsize, if given, has the same meaning as the corresponding argument to the built-in open() function: 0 means unbuffered, 1 means line buffered, any other positive value means use a buffer of (approximately) that size. A negative bufsize means to use the system default, which usually means fully buffered. The default value for bufsize is 0 (unbuffered). stdin, stdout and stderr specify the executed programs' standard input, standard output and standard error file handles, respectively. Valid values are PIPE, an existing file descriptor (a positive integer), an existing file object, and None. PIPE indicates that a new pipe to the child should be created. With None, no redirection will occur; the child's file handles will be inherited from the parent. Additionally, stderr can be STDOUT, which indicates that the stderr data from the applications should be captured into the same file handle as for stdout. If preexec_fn is set to a callable object, this object will be called in the child process just before the child is executed. If close_fds is true, all file descriptors except 0, 1 and 2 will be closed before the child process is executed. if shell is true, the specified command will be executed through the shell. If cwd is not None, the current directory will be changed to cwd before the child is executed. If env is not None, it defines the environment variables for the new process. If universal_newlines is true, the file objects stdout and stderr are opened as a text files, but lines may be terminated by any of '\n', the Unix end-of-line convention, '\r', the Macintosh convention or '\r\n', the Windows convention. All of these external representations are seen as '\n' by the Python program. Note: This feature is only available if Python is built with universal newline support (the default). Also, the newlines attribute of the file objects stdout, stdin and stderr are not updated by the communicate() method. The startupinfo and creationflags, if given, will be passed to the underlying CreateProcess() function. They can specify things such as appearance of the main window and priority for the new process. (Windows only) This module also defines two shortcut functions: call(*args, **kwargs): Run command with arguments. Wait for command to complete, then return the returncode attribute. The arguments are the same as for the Popen constructor. Example: retcode = call(["ls", "-l"]) Exceptions ---------- Exceptions raised in the child process, before the new program has started to execute, will be re-raised in the parent. Additionally, the exception object will have one extra attribute called 'child_traceback', which is a string containing traceback information from the childs point of view. The most common exception raised is OSError. This occurs, for example, when trying to execute a non-existent file. Applications should prepare for OSErrors. A ValueError will be raised if Popen is called with invalid arguments. Security -------- Unlike some other popen functions, this implementation will never call /bin/sh implicitly. This means that all characters, including shell metacharacters, can safely be passed to child processes. Popen objects ============= Instances of the Popen class have the following methods: poll() Check if child process has terminated. Returns returncode attribute. wait() Wait for child process to terminate. Returns returncode attribute. communicate(input=None) Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate. The optional stdin argument should be a string to be sent to the child process, or None, if no data should be sent to the child. communicate() returns a tuple (stdout, stderr). Note: The data read is buffered in memory, so do not use this method if the data size is large or unlimited. The following attributes are also available: stdin If the stdin argument is PIPE, this attribute is a file object that provides input to the child process. Otherwise, it is None. stdout If the stdout argument is PIPE, this attribute is a file object that provides output from the child process. Otherwise, it is None. stderr If the stderr argument is PIPE, this attribute is file object that provides error output from the child process. Otherwise, it is None. pid The process ID of the child process. returncode The child return code. A None value indicates that the process hasn't terminated yet. A negative value -N indicates that the child was terminated by signal N (UNIX only). Replacing older functions with the subprocess module ==================================================== In this section, "a ==> b" means that b can be used as a replacement for a. Note: All functions in this section fail (more or less) silently if the executed program cannot be found; this module raises an OSError exception. In the following examples, we assume that the subprocess module is imported with "from subprocess import *". Replacing /bin/sh shell backquote --------------------------------- output=`mycmd myarg` ==> output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0] Replacing shell pipe line ------------------------- output=`dmesg | grep hda` ==> p1 = Popen(["dmesg"], stdout=PIPE) p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) output = p2.communicate()[0] Replacing os.system() --------------------- sts = os.system("mycmd" + " myarg") ==> p = Popen("mycmd" + " myarg", shell=True) sts = os.waitpid(p.pid, 0) Note: * Calling the program through the shell is usually not required. * It's easier to look at the returncode attribute than the exitstatus. A more real-world example would look like this: try: retcode = call("mycmd" + " myarg", shell=True) if retcode < 0: print >>sys.stderr, "Child was terminated by signal", -retcode else: print >>sys.stderr, "Child returned", retcode except OSError, e: print >>sys.stderr, "Execution failed:", e Replacing os.spawn* ------------------- P_NOWAIT example: pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg") ==> pid = Popen(["/bin/mycmd", "myarg"]).pid P_WAIT example: retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg") ==> retcode = call(["/bin/mycmd", "myarg"]) Vector example: os.spawnvp(os.P_NOWAIT, path, args) ==> Popen([path] + args[1:]) Environment example: os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env) ==> Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"}) Replacing os.popen* ------------------- pipe = os.popen(cmd, mode='r', bufsize) ==> pipe = Popen(cmd, shell=True, bufsize=bufsize, stdout=PIPE).stdout pipe = os.popen(cmd, mode='w', bufsize) ==> pipe = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE).stdin (child_stdin, child_stdout) = os.popen2(cmd, mode, bufsize) ==> p = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, close_fds=True) (child_stdin, child_stdout) = (p.stdin, p.stdout) (child_stdin, child_stdout, child_stderr) = os.popen3(cmd, mode, bufsize) ==> p = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) (child_stdin, child_stdout, child_stderr) = (p.stdin, p.stdout, p.stderr) (child_stdin, child_stdout_and_stderr) = os.popen4(cmd, mode, bufsize) ==> p = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True) (child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout) Replacing popen2.* ------------------ Note: If the cmd argument to popen2 functions is a string, the command is executed through /bin/sh. If it is a list, the command is directly executed. (child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode) ==> p = Popen(["somestring"], shell=True, bufsize=bufsize stdin=PIPE, stdout=PIPE, close_fds=True) (child_stdout, child_stdin) = (p.stdout, p.stdin) (child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode) ==> p = Popen(["mycmd", "myarg"], bufsize=bufsize, stdin=PIPE, stdout=PIPE, close_fds=True) (child_stdout, child_stdin) = (p.stdout, p.stdin) The popen2.Popen3 and popen3.Popen4 basically works as subprocess.Popen, except that: * subprocess.Popen raises an exception if the execution fails * the capturestderr argument is replaced with the stderr argument. * stdin=PIPE and stdout=PIPE must be specified. * popen2 closes all filedescriptors by default, but you have to specify close_fds=True with subprocess.Popen. """ import sys mswindows = (sys.platform == "win32") import os import types import traceback if mswindows: import threading import msvcrt ## @@: Changed in Paste ## Since this module is only used on pre-python-2.4 systems, they probably ## don't have _subprocess installed, but hopefully have the win32 stuff ## installed. if 1: # <-- change this to use pywin32 instead of the _subprocess driver import pywintypes from win32api import GetStdHandle, STD_INPUT_HANDLE, \ STD_OUTPUT_HANDLE, STD_ERROR_HANDLE from win32api import GetCurrentProcess, DuplicateHandle, \ GetModuleFileName, GetVersion from win32con import DUPLICATE_SAME_ACCESS, SW_HIDE from win32pipe import CreatePipe from win32process import CreateProcess, STARTUPINFO, \ GetExitCodeProcess, STARTF_USESTDHANDLES, \ STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE from win32event import WaitForSingleObject, INFINITE, WAIT_OBJECT_0 else: from _subprocess import * class STARTUPINFO: dwFlags = 0 hStdInput = None hStdOutput = None hStdError = None class pywintypes: error = IOError else: import select import errno import fcntl import pickle __all__ = ["Popen", "PIPE", "STDOUT", "call"] try: MAXFD = os.sysconf("SC_OPEN_MAX") except: MAXFD = 256 # True/False does not exist on 2.2.0 try: False except NameError: False = 0 True = 1 _active = [] def _cleanup(): for inst in _active[:]: inst.poll() PIPE = -1 STDOUT = -2 def call(*args, **kwargs): """Run command with arguments. Wait for command to complete, then return the returncode attribute. The arguments are the same as for the Popen constructor. Example: retcode = call(["ls", "-l"]) """ return Popen(*args, **kwargs).wait() def list2cmdline(seq): """ Translate a sequence of arguments into a command line string, using the same rules as the MS C runtime: 1) Arguments are delimited by white space, which is either a space or a tab. 2) A string surrounded by double quotation marks is interpreted as a single argument, regardless of white space contained within. A quoted string can be embedded in an argument. 3) A double quotation mark preceded by a backslash is interpreted as a literal double quotation mark. 4) Backslashes are interpreted literally, unless they immediately precede a double quotation mark. 5) If backslashes immediately precede a double quotation mark, every pair of backslashes is interpreted as a literal backslash. If the number of backslashes is odd, the last backslash escapes the next double quotation mark as described in rule 3. """ # See # http://msdn.microsoft.com/library/en-us/vccelng/htm/progs_12.asp result = [] needquote = False for arg in seq: bs_buf = [] # Add a space to separate this argument from the others if result: result.append(' ') needquote = (" " in arg) or ("\t" in arg) if needquote: result.append('"') for c in arg: if c == '\\': # Don't know if we need to double yet. bs_buf.append(c) elif c == '"': # Double backspaces. result.append('\\' * len(bs_buf)*2) bs_buf = [] result.append('\\"') else: # Normal char if bs_buf: result.extend(bs_buf) bs_buf = [] result.append(c) # Add remaining backspaces, if any. if bs_buf: result.extend(bs_buf) if needquote: result.extend(bs_buf) result.append('"') return ''.join(result) class Popen(object): def __init__(self, args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0): """Create new Popen instance.""" _cleanup() if not isinstance(bufsize, (int, long)): raise TypeError("bufsize must be an integer") if mswindows: if preexec_fn is not None: raise ValueError("preexec_fn is not supported on Windows " "platforms") if close_fds: raise ValueError("close_fds is not supported on Windows " "platforms") else: # POSIX if startupinfo is not None: raise ValueError("startupinfo is only supported on Windows " "platforms") if creationflags != 0: raise ValueError("creationflags is only supported on Windows " "platforms") self.stdin = None self.stdout = None self.stderr = None self.pid = None self.returncode = None self.universal_newlines = universal_newlines # Input and output objects. The general principle is like # this: # # Parent Child # ------ ----- # p2cwrite ---stdin---> p2cread # c2pread <--stdout--- c2pwrite # errread <--stderr--- errwrite # # On POSIX, the child objects are file descriptors. On # Windows, these are Windows file handles. The parent objects # are file descriptors on both platforms. The parent objects # are None when not using PIPEs. The child objects are None # when not redirecting. (p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) = self._get_handles(stdin, stdout, stderr) self._execute_child(args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) if p2cwrite: self.stdin = os.fdopen(p2cwrite, 'wb', bufsize) if c2pread: if universal_newlines: self.stdout = os.fdopen(c2pread, 'rU', bufsize) else: self.stdout = os.fdopen(c2pread, 'rb', bufsize) if errread: if universal_newlines: self.stderr = os.fdopen(errread, 'rU', bufsize) else: self.stderr = os.fdopen(errread, 'rb', bufsize) _active.append(self) def _translate_newlines(self, data): data = data.replace("\r\n", "\n") data = data.replace("\r", "\n") return data if mswindows: # # Windows methods # def _get_handles(self, stdin, stdout, stderr): """Construct and return tupel with IO objects: p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite """ if stdin == None and stdout == None and stderr == None: return (None, None, None, None, None, None) p2cread, p2cwrite = None, None c2pread, c2pwrite = None, None errread, errwrite = None, None if stdin == None: p2cread = GetStdHandle(STD_INPUT_HANDLE) elif stdin == PIPE: p2cread, p2cwrite = CreatePipe(None, 0) # Detach and turn into fd p2cwrite = p2cwrite.Detach() p2cwrite = msvcrt.open_osfhandle(p2cwrite, 0) elif type(stdin) == types.IntType: p2cread = msvcrt.get_osfhandle(stdin) else: # Assuming file-like object p2cread = msvcrt.get_osfhandle(stdin.fileno()) p2cread = self._make_inheritable(p2cread) if stdout == None: c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE) elif stdout == PIPE: c2pread, c2pwrite = CreatePipe(None, 0) # Detach and turn into fd c2pread = c2pread.Detach() c2pread = msvcrt.open_osfhandle(c2pread, 0) elif type(stdout) == types.IntType: c2pwrite = msvcrt.get_osfhandle(stdout) else: # Assuming file-like object c2pwrite = msvcrt.get_osfhandle(stdout.fileno()) c2pwrite = self._make_inheritable(c2pwrite) if stderr == None: errwrite = GetStdHandle(STD_ERROR_HANDLE) elif stderr == PIPE: errread, errwrite = CreatePipe(None, 0) # Detach and turn into fd errread = errread.Detach() errread = msvcrt.open_osfhandle(errread, 0) elif stderr == STDOUT: errwrite = c2pwrite elif type(stderr) == types.IntType: errwrite = msvcrt.get_osfhandle(stderr) else: # Assuming file-like object errwrite = msvcrt.get_osfhandle(stderr.fileno()) errwrite = self._make_inheritable(errwrite) return (p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) def _make_inheritable(self, handle): """Return a duplicate of handle, which is inheritable""" return DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), 0, 1, DUPLICATE_SAME_ACCESS) def _find_w9xpopen(self): """Find and return absolut path to w9xpopen.exe""" w9xpopen = os.path.join(os.path.dirname(GetModuleFileName(0)), "w9xpopen.exe") if not os.path.exists(w9xpopen): # Eeek - file-not-found - possibly an embedding # situation - see if we can locate it in sys.exec_prefix w9xpopen = os.path.join(os.path.dirname(sys.exec_prefix), "w9xpopen.exe") if not os.path.exists(w9xpopen): raise RuntimeError("Cannot locate w9xpopen.exe, which is " "needed for Popen to work with your " "shell or platform.") return w9xpopen def _execute_child(self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite): """Execute program (MS Windows version)""" if not isinstance(args, types.StringTypes): args = list2cmdline(args) # Process startup details default_startupinfo = STARTUPINFO() if startupinfo == None: startupinfo = default_startupinfo if not None in (p2cread, c2pwrite, errwrite): startupinfo.dwFlags |= STARTF_USESTDHANDLES startupinfo.hStdInput = p2cread startupinfo.hStdOutput = c2pwrite startupinfo.hStdError = errwrite if shell: default_startupinfo.dwFlags |= STARTF_USESHOWWINDOW default_startupinfo.wShowWindow = SW_HIDE comspec = os.environ.get("COMSPEC", "cmd.exe") args = comspec + " /c " + args if (GetVersion() >= 0x80000000L or os.path.basename(comspec).lower() == "command.com"): # Win9x, or using command.com on NT. We need to # use the w9xpopen intermediate program. For more # information, see KB Q150956 # (http://web.archive.org/web/20011105084002/http://support.microsoft.com/support/kb/articles/Q150/9/56.asp) w9xpopen = self._find_w9xpopen() args = '"%s" %s' % (w9xpopen, args) # Not passing CREATE_NEW_CONSOLE has been known to # cause random failures on win9x. Specifically a # dialog: "Your program accessed mem currently in # use at xxx" and a hopeful warning about the # stability of your system. Cost is Ctrl+C wont # kill children. creationflags |= CREATE_NEW_CONSOLE # Start the process try: hp, ht, pid, tid = CreateProcess(executable, args, # no special security None, None, # must inherit handles to pass std # handles 1, creationflags, env, cwd, startupinfo) except pywintypes.error, e: # Translate pywintypes.error to WindowsError, which is # a subclass of OSError. FIXME: We should really # translate errno using _sys_errlist (or simliar), but # how can this be done from Python? raise WindowsError(*e.args) # Retain the process handle, but close the thread handle self._handle = hp self.pid = pid ht.Close() # Child is launched. Close the parent's copy of those pipe # handles that only the child should have open. You need # to make sure that no handles to the write end of the # output pipe are maintained in this process or else the # pipe will not close when the child process exits and the # ReadFile will hang. if p2cread != None: p2cread.Close() if c2pwrite != None: c2pwrite.Close() if errwrite != None: errwrite.Close() def poll(self): """Check if child process has terminated. Returns returncode attribute.""" if self.returncode == None: if WaitForSingleObject(self._handle, 0) == WAIT_OBJECT_0: self.returncode = GetExitCodeProcess(self._handle) _active.remove(self) return self.returncode def wait(self): """Wait for child process to terminate. Returns returncode attribute.""" if self.returncode == None: obj = WaitForSingleObject(self._handle, INFINITE) self.returncode = GetExitCodeProcess(self._handle) _active.remove(self) return self.returncode def _readerthread(self, fh, buffer): buffer.append(fh.read()) def communicate(self, input=None): """Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate. The optional input argument should be a string to be sent to the child process, or None, if no data should be sent to the child. communicate() returns a tuple (stdout, stderr).""" stdout = None # Return stderr = None # Return if self.stdout: stdout = [] stdout_thread = threading.Thread(target=self._readerthread, args=(self.stdout, stdout)) stdout_thread.setDaemon(True) stdout_thread.start() if self.stderr: stderr = [] stderr_thread = threading.Thread(target=self._readerthread, args=(self.stderr, stderr)) stderr_thread.setDaemon(True) stderr_thread.start() if self.stdin: if input != None: self.stdin.write(input) self.stdin.close() if self.stdout: stdout_thread.join() if self.stderr: stderr_thread.join() # All data exchanged. Translate lists into strings. if stdout != None: stdout = stdout[0] if stderr != None: stderr = stderr[0] # Translate newlines, if requested. We cannot let the file # object do the translation: It is based on stdio, which is # impossible to combine with select (unless forcing no # buffering). if self.universal_newlines and hasattr(open, 'newlines'): if stdout: stdout = self._translate_newlines(stdout) if stderr: stderr = self._translate_newlines(stderr) self.wait() return (stdout, stderr) else: # # POSIX methods # def _get_handles(self, stdin, stdout, stderr): """Construct and return tupel with IO objects: p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite """ p2cread, p2cwrite = None, None c2pread, c2pwrite = None, None errread, errwrite = None, None if stdin == None: pass elif stdin == PIPE: p2cread, p2cwrite = os.pipe() elif type(stdin) == types.IntType: p2cread = stdin else: # Assuming file-like object p2cread = stdin.fileno() if stdout == None: pass elif stdout == PIPE: c2pread, c2pwrite = os.pipe() elif type(stdout) == types.IntType: c2pwrite = stdout else: # Assuming file-like object c2pwrite = stdout.fileno() if stderr == None: pass elif stderr == PIPE: errread, errwrite = os.pipe() elif stderr == STDOUT: errwrite = c2pwrite elif type(stderr) == types.IntType: errwrite = stderr else: # Assuming file-like object errwrite = stderr.fileno() return (p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) def _set_cloexec_flag(self, fd): try: cloexec_flag = fcntl.FD_CLOEXEC except AttributeError: cloexec_flag = 1 old = fcntl.fcntl(fd, fcntl.F_GETFD) fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag) def _close_fds(self, but): for i in range(3, MAXFD): if i == but: continue try: os.close(i) except: pass def _execute_child(self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite): """Execute program (POSIX version)""" if isinstance(args, types.StringTypes): args = [args] if shell: args = ["/bin/sh", "-c"] + args if executable == None: executable = args[0] # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = os.pipe() self._set_cloexec_flag(errpipe_write) self.pid = os.fork() if self.pid == 0: # Child try: # Close parent's pipe ends if p2cwrite: os.close(p2cwrite) if c2pread: os.close(c2pread) if errread: os.close(errread) os.close(errpipe_read) # Dup fds for child if p2cread: os.dup2(p2cread, 0) if c2pwrite: os.dup2(c2pwrite, 1) if errwrite: os.dup2(errwrite, 2) # Close pipe fds. Make sure we doesn't close the same # fd more than once. if p2cread: os.close(p2cread) if c2pwrite and c2pwrite not in (p2cread,): os.close(c2pwrite) if errwrite and errwrite not in (p2cread, c2pwrite): os.close(errwrite) # Close all other fds, if asked for if close_fds: self._close_fds(but=errpipe_write) if cwd != None: os.chdir(cwd) if preexec_fn: apply(preexec_fn) if env == None: os.execvp(executable, args) else: os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) # This exitcode won't be reported to applications, so it # really doesn't matter what we return. os._exit(255) # Parent os.close(errpipe_write) if p2cread and p2cwrite: os.close(p2cread) if c2pwrite and c2pread: os.close(c2pwrite) if errwrite and errread: os.close(errwrite) # Wait for exec to fail or succeed; possibly raising exception data = os.read(errpipe_read, 1048576) # Exceptions limited to 1 MB os.close(errpipe_read) if data != "": os.waitpid(self.pid, 0) child_exception = pickle.loads(data) raise child_exception def _handle_exitstatus(self, sts): if os.WIFSIGNALED(sts): self.returncode = -os.WTERMSIG(sts) elif os.WIFEXITED(sts): self.returncode = os.WEXITSTATUS(sts) else: # Should never happen raise RuntimeError("Unknown child exit status!") _active.remove(self) def poll(self): """Check if child process has terminated. Returns returncode attribute.""" if self.returncode == None: try: pid, sts = os.waitpid(self.pid, os.WNOHANG) if pid == self.pid: self._handle_exitstatus(sts) except os.error: pass return self.returncode def wait(self): """Wait for child process to terminate. Returns returncode attribute.""" if self.returncode == None: pid, sts = os.waitpid(self.pid, 0) self._handle_exitstatus(sts) return self.returncode def communicate(self, input=None): """Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate. The optional input argument should be a string to be sent to the child process, or None, if no data should be sent to the child. communicate() returns a tuple (stdout, stderr).""" read_set = [] write_set = [] stdout = None # Return stderr = None # Return if self.stdin: # Flush stdio buffer. This might block, if the user has # been writing to .stdin in an uncontrolled fashion. self.stdin.flush() if input: write_set.append(self.stdin) else: self.stdin.close() if self.stdout: read_set.append(self.stdout) stdout = [] if self.stderr: read_set.append(self.stderr) stderr = [] while read_set or write_set: rlist, wlist, xlist = select.select(read_set, write_set, []) if self.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 bytes_written = os.write(self.stdin.fileno(), input[:512]) input = input[bytes_written:] if not input: self.stdin.close() write_set.remove(self.stdin) if self.stdout in rlist: data = os.read(self.stdout.fileno(), 1024) if data == "": self.stdout.close() read_set.remove(self.stdout) stdout.append(data) if self.stderr in rlist: data = os.read(self.stderr.fileno(), 1024) if data == "": self.stderr.close() read_set.remove(self.stderr) stderr.append(data) # All data exchanged. Translate lists into strings. if stdout != None: stdout = ''.join(stdout) if stderr != None: stderr = ''.join(stderr) # Translate newlines, if requested. We cannot let the file # object do the translation: It is based on stdio, which is # impossible to combine with select (unless forcing no # buffering). if self.universal_newlines and hasattr(open, 'newlines'): if stdout: stdout = self._translate_newlines(stdout) if stderr: stderr = self._translate_newlines(stderr) self.wait() return (stdout, stderr) def _demo_posix(): # # Example 1: Simple redirection: Get process list # plist = Popen(["ps"], stdout=PIPE).communicate()[0] print "Process list:" print plist # # Example 2: Change uid before executing child # if os.getuid() == 0: p = Popen(["id"], preexec_fn=lambda: os.setuid(100)) p.wait() # # Example 3: Connecting several subprocesses # print "Looking for 'hda'..." p1 = Popen(["dmesg"], stdout=PIPE) p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) print repr(p2.communicate()[0]) # # Example 4: Catch execution error # print print "Trying a weird file..." try: print Popen(["/this/path/does/not/exist"]).communicate() except OSError, e: if e.errno == errno.ENOENT: print "The file didn't exist. I thought so..." print "Child traceback:" print e.child_traceback else: print "Error", e.errno else: print >>sys.stderr, "Gosh. No error." def _demo_windows(): # # Example 1: Connecting several subprocesses # print "Looking for 'PROMPT' in set output..." p1 = Popen("set", stdout=PIPE, shell=True) p2 = Popen('find "PROMPT"', stdin=p1.stdout, stdout=PIPE) print repr(p2.communicate()[0]) # # Example 2: Simple execution of program # print "Executing calc..." p = Popen("calc") p.wait() if __name__ == "__main__": if mswindows: _demo_windows() else: _demo_posix() PK4-"VVpaste/util/__init__.py""" Package for miscellaneous routines that do not depend on other parts of Paste """ PK4fkqqpaste/util/import_string.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 """ 'imports' a string -- converts a string to a Python object, importing any necessary modules and evaluating the expression. Everything before the : in an import expression is the module path; everything after is an expression to be evaluated in the namespace of that module. Alternately, if no : is present, then import the modules and get the attributes as necessary. Arbitrary expressions are not allowed in that case. """ def eval_import(s): if ':' not in s: return simple_import(s) module_name, expr = s.split(':', 1) module = import_module(module_name) obj = eval(expr, module.__dict__) return obj def simple_import(s): parts = s.split('.') module = import_module(parts[0]) name = parts[0] parts = parts[1:] last_import_error = None while parts: name += '.' + parts[0] try: module = import_module(name) parts = parts[1:] except ImportError, e: last_import_error = e break obj = module while parts: try: obj = getattr(module, parts[0]) except AttributeError: raise ImportError( "Cannot find %s in module %r (stopped importing modules with error %s)" % (parts[0], module, last_import_error)) parts = parts[1:] return obj def import_module(s): mod = __import__(s) parts = s.split('.') for part in parts[1:]: mod = getattr(mod, part) return mod PK4?gJJpaste/util/intset.py# -*- coding: iso-8859-15 -*- """Immutable integer set type. Integer set class. Copyright (C) 2006, Heiko Wundram. Released under the MIT license. """ # Version information # ------------------- __author__ = "Heiko Wundram " __version__ = "0.2" __revision__ = "6" __date__ = "2006-01-20" # Utility classes # --------------- class _Infinity(object): """Internal type used to represent infinity values.""" __slots__ = ["_neg"] def __init__(self,neg): self._neg = neg def __lt__(self,value): if not isinstance(value,(int,long,_Infinity)): return NotImplemented return ( self._neg and not ( isinstance(value,_Infinity) and value._neg ) ) def __le__(self,value): if not isinstance(value,(int,long,_Infinity)): return NotImplemented return self._neg def __gt__(self,value): if not isinstance(value,(int,long,_Infinity)): return NotImplemented return not ( self._neg or ( isinstance(value,_Infinity) and not value._neg ) ) def __ge__(self,value): if not isinstance(value,(int,long,_Infinity)): return NotImplemented return not self._neg def __eq__(self,value): if not isinstance(value,(int,long,_Infinity)): return NotImplemented return isinstance(value,_Infinity) and self._neg == value._neg def __ne__(self,value): if not isinstance(value,(int,long,_Infinity)): return NotImplemented return not isinstance(value,_Infinity) or self._neg <> value._neg def __repr__(self): return "None" # Constants # --------- _MININF = _Infinity(True) _MAXINF = _Infinity(False) # Integer set class # ----------------- class IntSet(object): """Integer set class with efficient storage in a RLE format of ranges. Supports minus and plus infinity in the range.""" __slots__ = ["_ranges","_min","_max","_hash"] def __init__(self,*args,**kwargs): """Initialize an integer set. The constructor accepts an unlimited number of arguments that may either be tuples in the form of (start,stop) where either start or stop may be a number or None to represent maximum/minimum in that direction. The range specified by (start,stop) is always inclusive (differing from the builtin range operator). Keyword arguments that can be passed to an integer set are min and max, which specify the minimum and maximum number in the set, respectively. You can also pass None here to represent minus or plus infinity, which is also the default. """ # Special case copy constructor. if len(args) == 1 and isinstance(args[0],IntSet): if kwargs: raise ValueError("No keyword arguments for copy constructor.") self._min = args[0]._min self._max = args[0]._max self._ranges = args[0]._ranges self._hash = args[0]._hash return # Initialize set. self._ranges = [] # Process keyword arguments. self._min = kwargs.pop("min",_MININF) self._max = kwargs.pop("max",_MAXINF) if self._min is None: self._min = _MININF if self._max is None: self._max = _MAXINF # Check keyword arguments. if kwargs: raise ValueError("Invalid keyword argument.") if not ( isinstance(self._min,(int,long)) or self._min is _MININF ): raise TypeError("Invalid type of min argument.") if not ( isinstance(self._max,(int,long)) or self._max is _MAXINF ): raise TypeError("Invalid type of max argument.") if ( self._min is not _MININF and self._max is not _MAXINF and self._min > self._max ): raise ValueError("Minimum is not smaller than maximum.") if isinstance(self._max,(int,long)): self._max += 1 # Process arguments. for arg in args: if isinstance(arg,(int,long)): start, stop = arg, arg+1 elif isinstance(arg,tuple): if len(arg) <> 2: raise ValueError("Invalid tuple, must be (start,stop).") # Process argument. start, stop = arg if start is None: start = self._min if stop is None: stop = self._max # Check arguments. if not ( isinstance(start,(int,long)) or start is _MININF ): raise TypeError("Invalid type of tuple start.") if not ( isinstance(stop,(int,long)) or stop is _MAXINF ): raise TypeError("Invalid type of tuple stop.") if ( start is not _MININF and stop is not _MAXINF and start > stop ): continue if isinstance(stop,(int,long)): stop += 1 else: raise TypeError("Invalid argument.") if start > self._max: continue elif start < self._min: start = self._min if stop < self._min: continue elif stop > self._max: stop = self._max self._ranges.append((start,stop)) # Normalize set. self._normalize() # Utility functions for set operations # ------------------------------------ def _iterranges(self,r1,r2,minval=_MININF,maxval=_MAXINF): curval = minval curstates = {"r1":False,"r2":False} imax, jmax = 2*len(r1), 2*len(r2) i, j = 0, 0 while i < imax or j < jmax: if i < imax and ( ( j < jmax and r1[i>>1][i&1] < r2[j>>1][j&1] ) or j == jmax ): cur_r, newname, newstate = r1[i>>1][i&1], "r1", not (i&1) i += 1 else: cur_r, newname, newstate = r2[j>>1][j&1], "r2", not (j&1) j += 1 if curval < cur_r: if cur_r > maxval: break yield curstates, (curval,cur_r) curval = cur_r curstates[newname] = newstate if curval < maxval: yield curstates, (curval,maxval) def _normalize(self): self._ranges.sort() i = 1 while i < len(self._ranges): if self._ranges[i][0] < self._ranges[i-1][1]: self._ranges[i-1] = (self._ranges[i-1][0], max(self._ranges[i-1][1], self._ranges[i][1])) del self._ranges[i] else: i += 1 self._ranges = tuple(self._ranges) self._hash = hash(self._ranges) def __coerce__(self,other): if isinstance(other,IntSet): return self, other elif isinstance(other,(int,long,tuple)): try: return self, self.__class__(other) except TypeError: # Catch a type error, in that case the structure specified by # other is something we can't coerce, return NotImplemented. # ValueErrors are not caught, they signal that the data was # invalid for the constructor. This is appropriate to signal # as a ValueError to the caller. return NotImplemented elif isinstance(other,list): try: return self, self.__class__(*other) except TypeError: # See above. return NotImplemented return NotImplemented # Set function definitions # ------------------------ def _make_function(name,type,doc,pall,pany=None): """Makes a function to match two ranges. Accepts two types: either 'set', which defines a function which returns a set with all ranges matching pall (pany is ignored), or 'bool', which returns True if pall matches for all ranges and pany matches for any one range. doc is the dostring to give this function. pany may be none to ignore the any match. The predicates get a dict with two keys, 'r1', 'r2', which denote whether the current range is present in range1 (self) and/or range2 (other) or none of the two, respectively.""" if type == "set": def f(self,other): coerced = self.__coerce__(other) if coerced is NotImplemented: return NotImplemented other = coerced[1] newset = self.__class__.__new__(self.__class__) newset._min = min(self._min,other._min) newset._max = max(self._max,other._max) newset._ranges = [] for states, (start,stop) in \ self._iterranges(self._ranges,other._ranges, newset._min,newset._max): if pall(states): if newset._ranges and newset._ranges[-1][1] == start: newset._ranges[-1] = (newset._ranges[-1][0],stop) else: newset._ranges.append((start,stop)) newset._ranges = tuple(newset._ranges) newset._hash = hash(self._ranges) return newset elif type == "bool": def f(self,other): coerced = self.__coerce__(other) if coerced is NotImplemented: return NotImplemented other = coerced[1] _min = min(self._min,other._min) _max = max(self._max,other._max) found = not pany for states, (start,stop) in \ self._iterranges(self._ranges,other._ranges,_min,_max): if not pall(states): return False found = found or pany(states) return found else: raise ValueError("Invalid type of function to create.") try: f.func_name = name except TypeError: pass f.func_doc = doc return f # Intersection. __and__ = _make_function("__and__","set", "Intersection of two sets as a new set.", lambda s: s["r1"] and s["r2"]) __rand__ = _make_function("__rand__","set", "Intersection of two sets as a new set.", lambda s: s["r1"] and s["r2"]) intersection = _make_function("intersection","set", "Intersection of two sets as a new set.", lambda s: s["r1"] and s["r2"]) # Union. __or__ = _make_function("__or__","set", "Union of two sets as a new set.", lambda s: s["r1"] or s["r2"]) __ror__ = _make_function("__ror__","set", "Union of two sets as a new set.", lambda s: s["r1"] or s["r2"]) union = _make_function("union","set", "Union of two sets as a new set.", lambda s: s["r1"] or s["r2"]) # Difference. __sub__ = _make_function("__sub__","set", "Difference of two sets as a new set.", lambda s: s["r1"] and not s["r2"]) __rsub__ = _make_function("__rsub__","set", "Difference of two sets as a new set.", lambda s: s["r2"] and not s["r1"]) difference = _make_function("difference","set", "Difference of two sets as a new set.", lambda s: s["r1"] and not s["r2"]) # Symmetric difference. __xor__ = _make_function("__xor__","set", "Symmetric difference of two sets as a new set.", lambda s: s["r1"] ^ s["r2"]) __rxor__ = _make_function("__rxor__","set", "Symmetric difference of two sets as a new set.", lambda s: s["r1"] ^ s["r2"]) symmetric_difference = _make_function("symmetric_difference","set", "Symmetric difference of two sets as a new set.", lambda s: s["r1"] ^ s["r2"]) # Containership testing. __contains__ = _make_function("__contains__","bool", "Returns true if self is superset of other.", lambda s: s["r1"] or not s["r2"]) issubset = _make_function("issubset","bool", "Returns true if self is subset of other.", lambda s: s["r2"] or not s["r1"]) istruesubset = _make_function("istruesubset","bool", "Returns true if self is true subset of other.", lambda s: s["r2"] or not s["r1"], lambda s: s["r2"] and not s["r1"]) issuperset = _make_function("issuperset","bool", "Returns true if self is superset of other.", lambda s: s["r1"] or not s["r2"]) istruesuperset = _make_function("istruesuperset","bool", "Returns true if self is true superset of other.", lambda s: s["r1"] or not s["r2"], lambda s: s["r1"] and not s["r2"]) overlaps = _make_function("overlaps","bool", "Returns true if self overlaps with other.", lambda s: True, lambda s: s["r1"] and s["r2"]) # Comparison. __eq__ = _make_function("__eq__","bool", "Returns true if self is equal to other.", lambda s: not ( s["r1"] ^ s["r2"] )) __ne__ = _make_function("__ne__","bool", "Returns true if self is different to other.", lambda s: True, lambda s: s["r1"] ^ s["r2"]) # Clean up namespace. del _make_function # Define other functions. def inverse(self): """Inverse of set as a new set.""" newset = self.__class__.__new__(self.__class__) newset._min = self._min newset._max = self._max newset._ranges = [] laststop = self._min for r in self._ranges: if laststop < r[0]: newset._ranges.append((laststop,r[0])) laststop = r[1] if laststop < self._max: newset._ranges.append((laststop,self._max)) return newset __invert__ = inverse # Hashing # ------- def __hash__(self): """Returns a hash value representing this integer set. As the set is always stored normalized, the hash value is guaranteed to match for matching ranges.""" return self._hash # Iterating # --------- def __len__(self): """Get length of this integer set. In case the length is larger than 2**31 (including infinitely sized integer sets), it raises an OverflowError. This is due to len() restricting the size to 0 <= len < 2**31.""" if not self._ranges: return 0 if self._ranges[0][0] is _MININF or self._ranges[-1][1] is _MAXINF: raise OverflowError("Infinitely sized integer set.") rlen = 0 for r in self._ranges: rlen += r[1]-r[0] if rlen >= 2**31: raise OverflowError("Integer set bigger than 2**31.") return rlen def len(self): """Returns the length of this integer set as an integer. In case the length is infinite, returns -1. This function exists because of a limitation of the builtin len() function which expects values in the range 0 <= len < 2**31. Use this function in case your integer set might be larger.""" if not self._ranges: return 0 if self._ranges[0][0] is _MININF or self._ranges[-1][1] is _MAXINF: return -1 rlen = 0 for r in self._ranges: rlen += r[1]-r[0] return rlen def __nonzero__(self): """Returns true if this integer set contains at least one item.""" return bool(self._ranges) def __iter__(self): """Iterate over all values in this integer set. Iteration always starts by iterating from lowest to highest over the ranges that are bounded. After processing these, all ranges that are unbounded (maximum 2) are yielded intermixed.""" ubranges = [] for r in self._ranges: if r[0] is _MININF: if r[1] is _MAXINF: ubranges.extend(([0,1],[-1,-1])) else: ubranges.append([r[1]-1,-1]) elif r[1] is _MAXINF: ubranges.append([r[0],1]) else: for val in xrange(r[0],r[1]): yield val if ubranges: while True: for ubrange in ubranges: yield ubrange[0] ubrange[0] += ubrange[1] # Printing # -------- def __repr__(self): """Return a representation of this integer set. The representation is executable to get an equal integer set.""" rv = [] for start, stop in self._ranges: if ( isinstance(start,(int,long)) and isinstance(stop,(int,long)) and stop-start == 1 ): rv.append("%r" % start) elif isinstance(stop,(int,long)): rv.append("(%r,%r)" % (start,stop-1)) else: rv.append("(%r,%r)" % (start,stop)) if self._min is not _MININF: rv.append("min=%r" % self._min) if self._max is not _MAXINF: rv.append("max=%r" % self._max) return "%s(%s)" % (self.__class__.__name__,",".join(rv)) if __name__ == "__main__": # Little test script demonstrating functionality. x = IntSet((10,20),30) y = IntSet((10,20)) z = IntSet((10,20),30,(15,19),min=0,max=40) print x print x&110 print x|110 print x^(15,25) print x-12 print 12 in x print x.issubset(x) print y.issubset(x) print x.istruesubset(x) print y.istruesubset(x) for val in x: print val print x.inverse() print x == z print x == y print x <> y print hash(x) print hash(z) print len(x) print x.len() PK4 ؂aOaOpaste/util/PySourceColor.py# -*- coding: Latin-1 -*- """ PySourceColor: color Python source code """ """ PySourceColor.py ---------------------------------------------------------------------------- A python source to colorized html/css/xhtml converter. Hacked by M.E.Farmer Jr. 2004, 2005 Python license ---------------------------------------------------------------------------- - HTML markup does not create w3c valid html, but it works on every browser i've tried so far.(I.E.,Mozilla/Firefox,Opera,Konqueror,wxHTML). - CSS markup is w3c validated html 4.01 strict, but will not render correctly on all browsers. - XHTML markup is w3c validated xhtml 1.0 strict, like html 4.01, will not render correctly on all browsers. ---------------------------------------------------------------------------- Features: -Three types of markup: html (default) css/html 4.01 strict xhtml 1.0 strict -Can tokenize and colorize: 12 types of strings 2 comment types numbers operators brackets math operators class / name def / name decorator / name keywords arguments class/def/decorator linenumbers names text -Eight colorschemes built-in: null mono lite (default) dark dark2 idle viewcvs pythonwin -Header and footer set to '' for builtin header / footer. give path to a file containing the html you want added as header or footer. -Arbitrary text and html html markup converts all to raw (TEXT token) #@# for raw -> send raw text. #$# for span -> inline html and text. #%# for div -> block level html and text. -Linenumbers Supports all styles. New token is called LINENUMBER. Defaults to NAME if not defined. Style options -ALL markups support these text styles: b = bold i = italic u = underline -CSS and XHTML has limited support for borders: HTML markup functions will ignore these. Optional: Border color in RGB hex Defaults to the text forecolor. #rrggbb = border color Border size: l = thick m = medium t = thin Border type: - = dashed . = dotted s = solid d = double g = groove r = ridge n = inset o = outset You can specify multiple sides, they will all use the same style. Optional: Default is full border. v = bottom < = left > = right ^ = top NOTE: Specify the styles you want. The markups will ignore unsupported styles Also note not all browsers can show these options -All tokens default to NAME if not defined so the only absolutely critical ones to define are: NAME, ERRORTOKEN, PAGEBACKGROUND ---------------------------------------------------------------------------- Example usage:: # import import PySourceColor as psc psc.convert('c:/Python22/PySourceColor.py', colors=psc.idle, show=1) # from module import * from PySourceColor import * convert('c:/Python22/Lib', colors=lite, markup="css", header='#$#This is a simpe heading
') # How to use a custom colorscheme, and most of the 'features' from PySourceColor import * new = { ERRORTOKEN: ('bui','#FF8080',''), DECORATOR_NAME: ('s','#AACBBC',''), DECORATOR: ('n','#333333',''), NAME: ('t.','#000000','#FFFFFF'), TRIPLEDOUBLEQUOTE_R: ('tub','#000000','#FFFFFF'), TRIPLEDOUBLEQUOTE_U: ('-', '#CCAABB','#FFFAFF'), LINENUMBER: ('ib-','#ff66aa','#7733FF'),] TEXT: ('','#546634',''), PAGEBACKGROUND: '#FFFAAA', } if __name__ == '__main__': import sys convert(sys.argv[1], './xhtml.html', colors=new, markup='xhtml', show=1, linenumbers=1) convert(sys.argv[1], './html.html', colors=new, markup='html', show=1, linenumbers=1) """ __all__ = ['ERRORTOKEN','DECORATOR_NAME', 'DECORATOR', 'ARGS', 'EXTRASPACE', 'NAME', 'NUMBER', 'OPERATOR', 'COMMENT', 'MATH_OPERATOR', 'DOUBLECOMMENT', 'CLASS_NAME', 'DEF_NAME', 'KEYWORD', 'BRACKETS', 'SINGLEQUOTE','SINGLEQUOTE_R','SINGLEQUOTE_U','DOUBLEQUOTE', 'DOUBLEQUOTE_R', 'DOUBLEQUOTE_U', 'TRIPLESINGLEQUOTE', 'TEXT', 'TRIPLESINGLEQUOTE_R', 'TRIPLESINGLEQUOTE_U', 'TRIPLEDOUBLEQUOTE', 'TRIPLEDOUBLEQUOTE_R', 'TRIPLEDOUBLEQUOTE_U', 'PAGEBACKGROUND', 'LINENUMBER', 'CODESTART', 'CODEEND', 'PY', 'TOKEN_NAMES', 'CSSHOOK', 'null', 'mono', 'lite', 'dark','dark2', 'pythonwin','idle', 'viewcvs', 'Usage', 'cli', 'str2stdout', 'path2stdout', 'Parser', 'str2file', 'str2html', 'str2css', 'str2markup', 'path2file', 'path2html', 'convert', 'walkdir', 'defaultColors', 'showpage', 'pageconvert','tagreplace', 'MARKUPDICT'] __title__ = 'PySourceColor' __version__ = "2.1a" __date__ = '25 April 2005' __author__ = "M.E.Farmer Jr." __credits__ = '''This was originally based on a python recipe submitted by Jrgen Hermann to ASPN. Now based on the voices in my head. M.E.Farmer 2004, 2005 Python license ''' import os import sys import time import glob import getopt import keyword import token import tokenize import traceback import webbrowser try : import cStringIO as StringIO except: import StringIO # Do not edit NAME = token.NAME NUMBER = token.NUMBER COMMENT = tokenize.COMMENT OPERATOR = token.OP ERRORTOKEN = token.ERRORTOKEN ARGS = token.NT_OFFSET + 1 DOUBLECOMMENT = token.NT_OFFSET + 2 CLASS_NAME = token.NT_OFFSET + 3 DEF_NAME = token.NT_OFFSET + 4 KEYWORD = token.NT_OFFSET + 5 SINGLEQUOTE = token.NT_OFFSET + 6 SINGLEQUOTE_R = token.NT_OFFSET + 7 SINGLEQUOTE_U = token.NT_OFFSET + 8 DOUBLEQUOTE = token.NT_OFFSET + 9 DOUBLEQUOTE_R = token.NT_OFFSET + 10 DOUBLEQUOTE_U = token.NT_OFFSET + 11 TRIPLESINGLEQUOTE = token.NT_OFFSET + 12 TRIPLESINGLEQUOTE_R = token.NT_OFFSET + 13 TRIPLESINGLEQUOTE_U = token.NT_OFFSET + 14 TRIPLEDOUBLEQUOTE = token.NT_OFFSET + 15 TRIPLEDOUBLEQUOTE_R = token.NT_OFFSET + 16 TRIPLEDOUBLEQUOTE_U = token.NT_OFFSET + 17 PAGEBACKGROUND = token.NT_OFFSET + 18 DECORATOR = token.NT_OFFSET + 19 DECORATOR_NAME = token.NT_OFFSET + 20 BRACKETS = token.NT_OFFSET + 21 MATH_OPERATOR = token.NT_OFFSET + 22 LINENUMBER = token.NT_OFFSET + 23 TEXT = token.NT_OFFSET + 24 PY = token.NT_OFFSET + 25 CODESTART = token.NT_OFFSET + 26 CODEEND = token.NT_OFFSET + 27 CSSHOOK = token.NT_OFFSET + 28 EXTRASPACE = token.NT_OFFSET + 29 # markup classname lookup MARKUPDICT = { ERRORTOKEN: 'py_err', DECORATOR_NAME: 'py_decn', DECORATOR: 'py_dec', ARGS: 'py_args', NAME: 'py_name', NUMBER: 'py_num', OPERATOR: 'py_op', COMMENT: 'py_com', DOUBLECOMMENT: 'py_dcom', CLASS_NAME: 'py_clsn', DEF_NAME: 'py_defn', KEYWORD: 'py_key', SINGLEQUOTE: 'py_sq', SINGLEQUOTE_R: 'py_sqr', SINGLEQUOTE_U: 'py_squ', DOUBLEQUOTE: 'py_dq', DOUBLEQUOTE_R: 'py_dqr', DOUBLEQUOTE_U: 'py_dqu', TRIPLESINGLEQUOTE: 'py_tsq', TRIPLESINGLEQUOTE_R: 'py_tsqr', TRIPLESINGLEQUOTE_U: 'py_tsqu', TRIPLEDOUBLEQUOTE: 'py_tdq', TRIPLEDOUBLEQUOTE_R: 'py_tdqr', TRIPLEDOUBLEQUOTE_U: 'py_tdqu', BRACKETS: 'py_bra', MATH_OPERATOR: 'py_mop', LINENUMBER: 'py_lnum', TEXT: 'py_text', } # might help users that want to create custom schemes TOKEN_NAMES= { ERRORTOKEN:'ERRORTOKEN', DECORATOR_NAME:'DECORATOR_NAME', DECORATOR:'DECORATOR', ARGS:'ARGS', NAME:'NAME', NUMBER:'NUMBER', OPERATOR:'OPERATOR', COMMENT:'COMMENT', DOUBLECOMMENT:'DOUBLECOMMENT', CLASS_NAME:'CLASS_NAME', DEF_NAME:'DEF_NAME', KEYWORD:'KEYWORD', SINGLEQUOTE:'SINGLEQUOTE', SINGLEQUOTE_R:'SINGLEQUOTE_R', SINGLEQUOTE_U:'SINGLEQUOTE_U', DOUBLEQUOTE:'DOUBLEQUOTE', DOUBLEQUOTE_R:'DOUBLEQUOTE_R', DOUBLEQUOTE_U:'DOUBLEQUOTE_U', TRIPLESINGLEQUOTE:'TRIPLESINGLEQUOTE', TRIPLESINGLEQUOTE_R:'TRIPLESINGLEQUOTE_R', TRIPLESINGLEQUOTE_U:'TRIPLESINGLEQUOTE_U', TRIPLEDOUBLEQUOTE:'TRIPLEDOUBLEQUOTE', TRIPLEDOUBLEQUOTE_R:'TRIPLEDOUBLEQUOTE_R', TRIPLEDOUBLEQUOTE_U:'TRIPLEDOUBLEQUOTE_U', BRACKETS:'BRACKETS', MATH_OPERATOR:'MATH_OPERATOR', LINENUMBER:'LINENUMBER', TEXT:'TEXT', PAGEBACKGROUND:'PAGEBACKGROUND', } ###################################################################### # Edit colors and styles to taste # Create your own scheme, just copy one below , rename and edit. # Custom styles must at least define NAME, ERRORTOKEN, PAGEBACKGROUND, # all missing elements will default to NAME. # See module docstring for details on style attributes. ###################################################################### # Copy null and use it as a starter colorscheme. null = {# tokentype: ('tags border_color', 'textforecolor', 'textbackcolor') ERRORTOKEN: ('','#000000',''),# Error token DECORATOR_NAME: ('','#000000',''),# Decorator name DECORATOR: ('','#000000',''),# @ symbol ARGS: ('','#000000',''),# class,def,deco arguments NAME: ('','#000000',''),# All other python text NUMBER: ('','#000000',''),# 0->10 OPERATOR: ('','#000000',''),# ':','<=',';',',','.','==', etc MATH_OPERATOR: ('','#000000',''),# '+','-','=','','**',etc BRACKETS: ('','#000000',''),# '[',']','(',')','{','}' COMMENT: ('','#000000',''),# Single comment DOUBLECOMMENT: ('','#000000',''),## Double comment CLASS_NAME: ('','#000000',''),# Class name DEF_NAME: ('','#000000',''),# Def name KEYWORD: ('','#000000',''),# Python keywords SINGLEQUOTE: ('','#000000',''),# 'SINGLEQUOTE' SINGLEQUOTE_R: ('','#000000',''),# r'SINGLEQUOTE' SINGLEQUOTE_U: ('','#000000',''),# u'SINGLEQUOTE' DOUBLEQUOTE: ('','#000000',''),# "DOUBLEQUOTE" DOUBLEQUOTE_R: ('','#000000',''),# r"DOUBLEQUOTE" DOUBLEQUOTE_U: ('','#000000',''),# u"DOUBLEQUOTE" TRIPLESINGLEQUOTE: ('','#000000',''),# '''TRIPLESINGLEQUOTE''' TRIPLESINGLEQUOTE_R: ('','#000000',''),# r'''TRIPLESINGLEQUOTE''' TRIPLESINGLEQUOTE_U: ('','#000000',''),# u'''TRIPLESINGLEQUOTE''' TRIPLEDOUBLEQUOTE: ('','#000000',''),# """TRIPLEDOUBLEQUOTE""" TRIPLEDOUBLEQUOTE_R: ('','#000000',''),# r"""TRIPLEDOUBLEQUOTE""" TRIPLEDOUBLEQUOTE_U: ('','#000000',''),# u"""TRIPLEDOUBLEQUOTE""" TEXT: ('','#000000',''),# non python text LINENUMBER: ('>ti#555555','#000000',''),# Linenumbers PAGEBACKGROUND: '#FFFFFF'# set the page background } mono = { ERRORTOKEN: ('s#FF0000','#FF8080',''), DECORATOR_NAME: ('bu','#000000',''), DECORATOR: ('b','#000000',''), ARGS: ('b','#555555',''), NAME: ('','#000000',''), NUMBER: ('b','#000000',''), OPERATOR: ('b','#000000',''), MATH_OPERATOR: ('b','#000000',''), BRACKETS: ('b','#000000',''), COMMENT: ('i','#999999',''), DOUBLECOMMENT: ('b','#999999',''), CLASS_NAME: ('bu','#000000',''), DEF_NAME: ('b','#000000',''), KEYWORD: ('b','#000000',''), SINGLEQUOTE: ('','#000000',''), SINGLEQUOTE_R: ('','#000000',''), SINGLEQUOTE_U: ('','#000000',''), DOUBLEQUOTE: ('','#000000',''), DOUBLEQUOTE_R: ('','#000000',''), DOUBLEQUOTE_U: ('','#000000',''), TRIPLESINGLEQUOTE: ('','#000000',''), TRIPLESINGLEQUOTE_R: ('','#000000',''), TRIPLESINGLEQUOTE_U: ('','#000000',''), TRIPLEDOUBLEQUOTE: ('i','#000000',''), TRIPLEDOUBLEQUOTE_R: ('i','#000000',''), TRIPLEDOUBLEQUOTE_U: ('i','#000000',''), TEXT: ('','#000000',''), LINENUMBER: ('>ti#555555','#000000',''), PAGEBACKGROUND: '#FFFFFF' } dark = { ERRORTOKEN: ('s#FF0000','#FF8080',''), DECORATOR_NAME: ('b','#FFBBAA',''), DECORATOR: ('b','#CC5511',''), ARGS: ('b','#DDDDFF',''), NAME: ('','#DDDDDD',''), NUMBER: ('','#FF0000',''), OPERATOR: ('b','#FAF785',''), MATH_OPERATOR: ('b','#FAF785',''), BRACKETS: ('b','#FAF785',''), COMMENT: ('','#45FCA0',''), DOUBLECOMMENT: ('i','#A7C7A9',''), CLASS_NAME: ('b','#B666FD',''), DEF_NAME: ('b','#EBAE5C',''), KEYWORD: ('b','#8680FF',''), SINGLEQUOTE: ('','#F8BAFE',''), SINGLEQUOTE_R: ('','#F8BAFE',''), SINGLEQUOTE_U: ('','#F8BAFE',''), DOUBLEQUOTE: ('','#FF80C0',''), DOUBLEQUOTE_R: ('','#FF80C0',''), DOUBLEQUOTE_U: ('','#FF80C0',''), TRIPLESINGLEQUOTE: ('','#FF9595',''), TRIPLESINGLEQUOTE_R: ('','#FF9595',''), TRIPLESINGLEQUOTE_U: ('','#FF9595',''), TRIPLEDOUBLEQUOTE: ('','#B3FFFF',''), TRIPLEDOUBLEQUOTE_R: ('','#B3FFFF',''), TRIPLEDOUBLEQUOTE_U: ('','#B3FFFF',''), TEXT: ('','#FFFFFF',''), LINENUMBER: ('>mi#555555','#bbccbb','#333333'), PAGEBACKGROUND: '#000000' } dark2 = { ERRORTOKEN: ('','#FF0000',''), DECORATOR_NAME: ('b','#FFBBAA',''), DECORATOR: ('b','#CC5511',''), ARGS: ('b','#DDDDDD',''), NAME: ('','#C0C0C0',''), NUMBER: ('b','#00FF00',''), OPERATOR: ('b','#FF090F',''), MATH_OPERATOR: ('b','#EE7020',''), BRACKETS: ('b','#FFB90F',''), COMMENT: ('i','#D0D000','#522000'),#'#88AA88','#11111F'), DOUBLECOMMENT: ('i','#D0D000','#522000'),#'#77BB77','#11111F'), CLASS_NAME: ('b','#DD4080',''), DEF_NAME: ('b','#FF8040',''), KEYWORD: ('b','#4726d1',''), SINGLEQUOTE: ('','#8080C0',''), SINGLEQUOTE_R: ('','#8080C0',''), SINGLEQUOTE_U: ('','#8080C0',''), DOUBLEQUOTE: ('','#ADB9F1',''), DOUBLEQUOTE_R: ('','#ADB9F1',''), DOUBLEQUOTE_U: ('','#ADB9F1',''), TRIPLESINGLEQUOTE: ('','#00C1C1',''),#A050C0 TRIPLESINGLEQUOTE_R: ('','#00C1C1',''),#A050C0 TRIPLESINGLEQUOTE_U: ('','#00C1C1',''),#A050C0 TRIPLEDOUBLEQUOTE: ('','#33E3E3',''),#B090E0 TRIPLEDOUBLEQUOTE_R: ('','#33E3E3',''),#B090E0 TRIPLEDOUBLEQUOTE_U: ('','#33E3E3',''),#B090E0 TEXT: ('','#C0C0C0',''), LINENUMBER: ('>mi#555555','#bbccbb','#333333'), PAGEBACKGROUND: '#000000' } lite = { ERRORTOKEN: ('s#FF0000','#FF8080',''), DECORATOR_NAME: ('b','#BB4422',''), DECORATOR: ('b','#3333AF',''), ARGS: ('b','#000000',''), NAME: ('','#333333',''), NUMBER: ('b','#DD2200',''), OPERATOR: ('b','#000000',''), MATH_OPERATOR: ('b','#000000',''), BRACKETS: ('b','#000000',''), COMMENT: ('','#007F00',''), DOUBLECOMMENT: ('','#608060',''), CLASS_NAME: ('b','#0000DF',''), DEF_NAME: ('b','#9C7A00',''),#f09030 KEYWORD: ('b','#0000AF',''), SINGLEQUOTE: ('','#600080',''), SINGLEQUOTE_R: ('','#600080',''), SINGLEQUOTE_U: ('','#600080',''), DOUBLEQUOTE: ('','#A0008A',''), DOUBLEQUOTE_R: ('','#A0008A',''), DOUBLEQUOTE_U: ('','#A0008A',''), TRIPLESINGLEQUOTE: ('','#337799',''), TRIPLESINGLEQUOTE_R: ('','#337799',''), TRIPLESINGLEQUOTE_U: ('','#337799',''), TRIPLEDOUBLEQUOTE: ('','#1166AA',''), TRIPLEDOUBLEQUOTE_R: ('','#1166AA',''), TRIPLEDOUBLEQUOTE_U: ('','#1166AA',''), TEXT: ('','#000000',''), LINENUMBER: ('>ti#555555','#000000',''), PAGEBACKGROUND: '#FFFFFF' } idle = { ERRORTOKEN: ('s#FF0000','#FF8080',''), DECORATOR_NAME: ('','#900090',''), DECORATOR: ('','#FF7700',''), NAME: ('','#000000',''), NUMBER: ('','#000000',''), OPERATOR: ('','#000000',''), MATH_OPERATOR: ('','#000000',''), BRACKETS: ('','#000000',''), COMMENT: ('','#DD0000',''), DOUBLECOMMENT: ('','#DD0000',''), CLASS_NAME: ('','#0000FF',''), DEF_NAME: ('','#0000FF',''), KEYWORD: ('','#FF7700',''), SINGLEQUOTE: ('','#00AA00',''), SINGLEQUOTE_R: ('','#00AA00',''), SINGLEQUOTE_U: ('','#00AA00',''), DOUBLEQUOTE: ('','#00AA00',''), DOUBLEQUOTE_R: ('','#00AA00',''), DOUBLEQUOTE_U: ('','#00AA00',''), TRIPLESINGLEQUOTE: ('','#00AA00',''), TRIPLESINGLEQUOTE_R: ('','#00AA00',''), TRIPLESINGLEQUOTE_U: ('','#00AA00',''), TRIPLEDOUBLEQUOTE: ('','#00AA00',''), TRIPLEDOUBLEQUOTE_R: ('','#00AA00',''), TRIPLEDOUBLEQUOTE_U: ('','#00AA00',''), TEXT: ('','#000000',''), LINENUMBER: ('>ti#555555','#000000',''), PAGEBACKGROUND: '#FFFFFF' } pythonwin = { ERRORTOKEN: ('s#FF0000','#FF8080',''), DECORATOR_NAME: ('b','#DD0080',''), DECORATOR: ('b','#000080',''), ARGS: ('','#000000',''), NAME: ('','#303030',''), NUMBER: ('','#008080',''), OPERATOR: ('','#000000',''), MATH_OPERATOR: ('','#000000',''), BRACKETS: ('','#000000',''), COMMENT: ('','#007F00',''), DOUBLECOMMENT: ('','#7F7F7F',''), CLASS_NAME: ('b','#0000FF',''), DEF_NAME: ('b','#007F7F',''), KEYWORD: ('b','#000080',''), SINGLEQUOTE: ('','#808000',''), SINGLEQUOTE_R: ('','#808000',''), SINGLEQUOTE_U: ('','#808000',''), DOUBLEQUOTE: ('','#808000',''), DOUBLEQUOTE_R: ('','#808000',''), DOUBLEQUOTE_U: ('','#808000',''), TRIPLESINGLEQUOTE: ('','#808000',''), TRIPLESINGLEQUOTE_R: ('','#808000',''), TRIPLESINGLEQUOTE_U: ('','#808000',''), TRIPLEDOUBLEQUOTE: ('','#808000',''), TRIPLEDOUBLEQUOTE_R: ('','#808000',''), TRIPLEDOUBLEQUOTE_U: ('','#808000',''), TEXT: ('','#303030',''), LINENUMBER: ('>ti#555555','#000000',''), PAGEBACKGROUND: '#FFFFFF' } viewcvs = { ERRORTOKEN: ('s#FF0000','#FF8080',''), DECORATOR_NAME: ('','#000000',''), DECORATOR: ('','#000000',''), ARGS: ('','#000000',''), NAME: ('','#000000',''), NUMBER: ('','#000000',''), OPERATOR: ('','#000000',''), MATH_OPERATOR: ('','#000000',''), BRACKETS: ('','#000000',''), COMMENT: ('i','#b22222',''), DOUBLECOMMENT: ('i','#b22222',''), CLASS_NAME: ('','#000000',''), DEF_NAME: ('b','#0000ff',''), KEYWORD: ('b','#a020f0',''), SINGLEQUOTE: ('b','#bc8f8f',''), SINGLEQUOTE_R: ('b','#bc8f8f',''), SINGLEQUOTE_U: ('b','#bc8f8f',''), DOUBLEQUOTE: ('b','#bc8f8f',''), DOUBLEQUOTE_R: ('b','#bc8f8f',''), DOUBLEQUOTE_U: ('b','#bc8f8f',''), TRIPLESINGLEQUOTE: ('b','#bc8f8f',''), TRIPLESINGLEQUOTE_R: ('b','#bc8f8f',''), TRIPLESINGLEQUOTE_U: ('b','#bc8f8f',''), TRIPLEDOUBLEQUOTE: ('b','#bc8f8f',''), TRIPLEDOUBLEQUOTE_R: ('b','#bc8f8f',''), TRIPLEDOUBLEQUOTE_U: ('b','#bc8f8f',''), TEXT: ('','#000000',''), LINENUMBER: ('>ti#555555','#000000',''), PAGEBACKGROUND: '#FFFFFF' } defaultColors = lite def Usage(): doc = """ ----------------------------------------------------------------------------- PySourceColor.py ver: %s ----------------------------------------------------------------------------- Module summary: This module is designed to colorize python source code. Input--->python source Output-->colorized (html, html4.01/css, xhtml1.0) Standalone: This module will work from the command line with options. This module will work with redirected stdio. Imported: This module can be imported and used directly in your code. ----------------------------------------------------------------------------- Command line options: -h, --help Optional-> Display this help message. -t, --test Optional-> Will ignore all others flags but --profile test all schemes and markup combinations -p, --profile Optional-> Works only with --test or -t runs profile.py and makes the test work in quiet mode. -i, --in, --input Optional-> If you give input on stdin. Use any of these for the current dir (.,cwd) Input can be file or dir. Input from stdin use one of the following (-,stdin) If stdin is used as input stdout is output unless specified. -o, --out, --output Optional-> output dir for the colorized source. default: output dir is the input dir. To output html to stdout use one of the following (-,stdout) Stdout can be used without stdin if you give a file as input. -c, --color Optional-> null, mono, dark, dark2, lite, idle, pythonwin, viewcvs default: dark -s, --show Optional-> Show page after creation. default: no show -m, --markup Optional-> html, css, xhtml css, xhtml also support external stylesheets (-e,--external) default: HTML -e, --external Optional-> use with css, xhtml Writes an style sheet instead of embedding it in the page saves it as pystyle.css in the same directory. html markup will silently ignore this flag. -H, --header Opional-> add a page header to the top of the output -H Builtin header (name,date,hrule) --header You must specify a filename. The header file must be valid html and must handle its own font colors. ex. --header c:/tmp/header.txt -F, --footer Opional-> add a page footer to the bottom of the output -F Builtin footer (hrule,name,date) --footer You must specify a filename. The footer file must be valid html and must handle its own font colors. ex. --footer c:/tmp/footer.txt -l, --linenumbers Optional-> default is no linenumbers Adds line numbers to the start of each line in the code. --convertpage Given a webpage that has code embedded in tags it will convert embedded code to colorized html. (see pageconvert for details) ----------------------------------------------------------------------------- Option usage: # Test and show pages python PySourceColor.py -t -s # Test and only show profile results python PySourceColor.py -t -p # Colorize all .py,.pyw files in cwdir you can also use: (.,cwd) python PySourceColor.py -i . # Using long options w/ = python PySourceColor.py --in=c:/myDir/my.py --color=lite --show # Using short options w/out = python PySourceColor.py -i c:/myDir/ -c idle -m css -e # Using any mix python PySourceColor.py --in . -o=c:/myDir --show # Place a custom header on your files python PySourceColor.py -i . -o c:/tmp -m xhtml --header c:/header.txt ----------------------------------------------------------------------------- Stdio usage: # Stdio using no options python PySourceColor.py < c:/MyFile.py > c:/tmp/MyFile.html # Using stdin alone automatically uses stdout for output: (stdin,-) python PySourceColor.py -i- < c:/MyFile.py > c:/tmp/myfile.html # Stdout can also be written to directly from a file instead of stdin python PySourceColor.py -i c:/MyFile.py -m css -o- > c:/tmp/myfile.html # Stdin can be used as input , but output can still be specified python PySourceColor.py -i- -o c:/pydoc.py.html -s < c:/Python22/my.py _____________________________________________________________________________ """ print doc % (__version__) sys.exit(1) ###################################################### Command line interface def cli(): """Handle command line args and redirections""" try: # try to get command line args opts, args = getopt.getopt(sys.argv[1:], "hseqtplHFi:o:c:m:h:f:",["help", "show", "quiet", "test", "external", "linenumbers", "convertpage", "profile", "input=", "output=", "color=", "markup=","header=", "footer="]) except getopt.GetoptError: # on error print help information and exit: Usage() # init some names input = None output = None colorscheme = None markup = 'html' header = None footer = None linenumbers = 0 show = 0 quiet = 0 test = 0 profile = 0 convertpage = 0 form = None # if we have args then process them for o, a in opts: if o in ["-h", "--help"]: Usage() sys.exit() if o in ["-o", "--output", "--out"]: output = a if o in ["-i", "--input", "--in"]: input = a if input in [".", "cwd"]: input = os.getcwd() if o in ["-s", "--show"]: show = 1 if o in ["-q", "--quiet"]: quiet = 1 if o in ["-t", "--test"]: test = 1 if o in ["--convertpage"]: convertpage = 1 if o in ["-p", "--profile"]: profile = 1 if o in ["-e", "--external"]: form = 'external' if o in ["-m", "--markup"]: markup = str(a) if o in ["-l", "--linenumbers"]: linenumbers = 1 if o in ["--header"]: header = str(a) elif o == "-H": header = '' if o in ["--footer"]: footer = str(a) elif o == "-F": footer = '' if o in ["-c", "--color"]: try: colorscheme = globals().get(a.lower()) except: traceback.print_exc() Usage() if test: if profile: import profile profile.run('_test(show=%s, quiet=%s)'%(show,quiet)) else: # Parse this script in every possible colorscheme and markup _test(show,quiet) elif input in [None, "-", "stdin"] or output in ["-", "stdout"]: # determine if we are going to use stdio if input not in [None, "-", "stdin"]: if os.path.isfile(input) : path2stdout(input, colors=colorscheme, markup=markup, linenumbers=linenumbers, header=header, footer=footer, form=form) else: raise PathError, 'File does not exists!' else: try: if sys.stdin.isatty(): raise InputError, 'Please check input!' else: if output in [None,"-","stdout"]: str2stdout(sys.stdin.read(), colors=colorscheme, markup=markup, header=header, footer=footer, linenumbers=linenumbers, form=form) else: str2file(sys.stdin.read(), outfile=output, show=show, markup=markup, header=header, footer=footer, linenumbers=linenumbers, form=form) except: traceback.print_exc() Usage() else: if os.path.exists(input): if convertpage: # if there was at least an input given we can proceed pageconvert(input, out=output, colors=colorscheme, show=show, markup=markup,linenumbers=linenumbers) else: # if there was at least an input given we can proceed convert(source=input, outdir=output, colors=colorscheme, show=show, markup=markup, quiet=quiet, header=header, footer=footer, linenumbers=linenumbers, form=form) else: raise PathError, 'File does not exists!' Usage() ######################################################### Simple markup tests def _test(show=0, quiet=0): """Test the parser and most of the functions. There are 19 test total(eight colorschemes in three diffrent markups, and a str2file test. Most functions are tested by this. """ fi = sys.argv[0] if not fi.endswith('.exe'):# Do not test if frozen as an archive # this is a collection of test, most things are covered. path2file(fi, '/tmp/null.html', null, show=show, quiet=quiet) path2file(fi, '/tmp/null_css.html', null, show=show, markup='css', quiet=quiet) path2file(fi, '/tmp/mono.html', mono, show=show, quiet=quiet) path2file(fi, '/tmp/mono_css.html', mono, show=show, markup='css', quiet=quiet) path2file(fi, '/tmp/lite.html', lite, show=show, quiet=quiet) path2file(fi, '/tmp/lite_css.html', lite, show=show, markup='css', quiet=quiet, header='', footer='', linenumbers=1) path2file(fi, '/tmp/lite_xhtml.html', lite, show=show, markup='xhtml', quiet=quiet) path2file(fi, '/tmp/dark.html', dark, show=show, quiet=quiet) path2file(fi, '/tmp/dark_css.html', dark, show=show, markup='css', quiet=quiet, linenumbers=1) path2file(fi, '/tmp/dark2.html', dark2, show=show, quiet=quiet) path2file(fi, '/tmp/dark2_css.html', dark2, show=show, markup='css', quiet=quiet) path2file(fi, '/tmp/dark2_xhtml.html', dark2, show=show, markup='xhtml', quiet=quiet, header='', footer='', linenumbers=1, form='external') path2file(fi, '/tmp/idle.html', idle, show=show, quiet=quiet) path2file(fi, '/tmp/idle_css.html', idle, show=show, markup='css', quiet=quiet) path2file(fi, '/tmp/viewcvs.html', viewcvs, show=show, quiet=quiet, linenumbers=1) path2file(fi, '/tmp/viewcvs_css.html', viewcvs, show=show, markup='css', linenumbers=1, quiet=quiet) path2file(fi, '/tmp/pythonwin.html', pythonwin, show=show, quiet=quiet) path2file(fi, '/tmp/pythonwin_css.html', pythonwin, show=show, markup='css', quiet=quiet) teststr=r'''"""This is a test of decorators and other things""" # This should be line 421... @whatever(arg,arg2) @A @B(arghh) @C def LlamaSaysNi(arg='Ni!',arg2="RALPH"): """This docstring is deeply disturbed by all the llama references""" print '%s The Wonder Llama says %s'% (arg2,arg) # So I was like duh!, and he was like ya know?!, # and so we were both like huh...wtf!? RTFM!! LOL!!;) @staticmethod## Double comments are KewL. def LlamasRLumpy(): """This docstring is too sexy to be here. """ u""" ============================= A Mse once bit my sister... ============================= """ ## Relax, this won't hurt a bit, just a simple, painless procedure, ## hold still while I get the anesthetizing hammer. m = {'three':'1','won':'2','too':'3'} o = r'fishy\fishy\fishy/fish\oh/where/is\my/little\..' python = uR""" No realli! She was Karving her initials n the mse with the sharpened end of an interspace tthbrush given her by Svenge - her brother-in-law -an Oslo dentist and star of many Norwegian mvies: "The Ht Hands of an Oslo Dentist", "Fillings of Passion", "The Huge Mlars of Horst Nordfink"...""" RU"""142 MEXICAN WHOOPING LLAMAS"""#<-Can you fit 142 llamas in a red box? n = u' HERMSGERVRDENBRTBRDA ' + """ YUTTE """ t = """SAMALLNIATNUOMNAIRODAUCE"""+"DENIARTYLLAICEPS04" ## We apologise for the fault in the ## comments. Those responsible have been ## sacked. y = '14 NORTH CHILEAN GUANACOS \ (CLOSELY RELATED TO THE LLAMA)' rules = [0,1,2,3,4,5] print y''' htmlPath = os.path.abspath('/tmp/strtest_lines.html') str2file(teststr, htmlPath, colors=dark, markup='xhtml', linenumbers=420, show=show) _printinfo(" wrote %s" % htmlPath, quiet) htmlPath = os.path.abspath('/tmp/strtest_nolines.html') str2file(teststr, htmlPath, colors=dark, markup='xhtml', show=show) _printinfo(" wrote %s" % htmlPath, quiet) else: Usage() return # emacs wants this: ' ####################################################### User funtctions def str2stdout(sourcestring, colors=None, title='', markup='html', header=None, footer=None, linenumbers=0, form=None): """Converts a code(string) to colorized HTML. Writes to stdout. form='code',or'snip' (for "
yourcode
" only) colors=null,mono,lite,dark,dark2,idle,or pythonwin """ Parser(sourcestring, colors=colors, title=title, markup=markup, header=header, footer=footer, linenumbers=linenumbers).format(form) def path2stdout(sourcepath, title='', colors=None, markup='html', header=None, footer=None, linenumbers=0, form=None): """Converts code(file) to colorized HTML. Writes to stdout. form='code',or'snip' (for "
yourcode
" only) colors=null,mono,lite,dark,dark2,idle,or pythonwin """ sourcestring = open(sourcepath).read() Parser(sourcestring, colors=colors, title=sourcepath, markup=markup, header=header, footer=footer, linenumbers=linenumbers).format(form) def str2html(sourcestring, colors=None, title='', markup='html', header=None, footer=None, linenumbers=0, form=None): """Converts a code(string) to colorized HTML. Returns an HTML string. form='code',or'snip' (for "
yourcode
" only) colors=null,mono,lite,dark,dark2,idle,or pythonwin """ stringIO = StringIO.StringIO() Parser(sourcestring, colors=colors, title=title, out=stringIO, markup=markup, header=header, footer=footer, linenumbers=linenumbers).format(form) stringIO.seek(0) return stringIO.read() def str2css(sourcestring, colors=None, title='', markup='css', header=None, footer=None, linenumbers=0, form=None): """Converts a code string to colorized CSS/HTML. Returns CSS/HTML string If form != None then this will return (stylesheet_str, code_str) colors=null,mono,lite,dark,dark2,idle,or pythonwin """ if markup.lower() not in ['css' ,'xhtml']: markup = 'css' stringIO = StringIO.StringIO() parse = Parser(sourcestring, colors=colors, title=title, out=stringIO, markup=markup, header=header, footer=footer, linenumbers=linenumbers) parse.format(form) stringIO.seek(0) if form != None: return parse._sendCSSStyle(external=1), stringIO.read() else: return None, stringIO.read() def str2markup(sourcestring, colors=None, title = '', markup='xhtml', header=None, footer=None, linenumbers=0, form=None): """ Convert code strings into ([stylesheet or None], colorized string) """ if markup.lower() == 'html': return None, str2html(sourcestring, colors=colors, title=title, header=header, footer=footer, markup=markup, linenumbers=linenumbers, form=form) else: return str2css(sourcestring, colors=colors, title=title, header=header, footer=footer, markup=markup, linenumbers=linenumbers, form=form) def str2file(sourcestring, outfile, colors=None, title='', markup='html', header=None, footer=None, linenumbers=0, show=0, dosheet=1, form=None): """Converts a code string to a file. makes no attempt at correcting bad pathnames """ css , html = str2markup(sourcestring, colors=colors, title='', markup=markup, header=header, footer=footer, linenumbers=linenumbers, form=form) # write html f = open(outfile,'wt') f.writelines(html) f.close() #write css if css != None and dosheet: dir = os.path.dirname(outfile) outcss = os.path.join(dir,'pystyle.css') f = open(outcss,'wt') f.writelines(css) f.close() if show: showpage(outfile) def path2html(sourcepath, colors=None, markup='html', header=None, footer=None, linenumbers=0, form=None): """Converts code(file) to colorized HTML. Returns an HTML string. form='code',or'snip' (for "
yourcode
" only) colors=null,mono,lite,dark,dark2,idle,or pythonwin """ stringIO = StringIO.StringIO() sourcestring = open(sourcepath).read() Parser(sourcestring, colors, title=sourcepath, out=stringIO, markup=markup, header=header, footer=footer, linenumbers=linenumbers).format(form) stringIO.seek(0) return stringIO.read() def convert(source, outdir=None, colors=None, show=0, markup='html', quiet=0, header=None, footer=None, linenumbers=0, form=None): """Takes a file or dir as input and places the html in the outdir. If outdir is none it defaults to the input dir """ count=0 # If it is a filename then path2file if not os.path.isdir(source): if os.path.isfile(source): count+=1 path2file(source, outdir, colors, show, markup, quiet, form, header, footer, linenumbers, count) else: raise PathError, 'File does not exist!' # If we pass in a dir we need to walkdir for files. # Then we need to colorize them with path2file else: fileList = walkdir(source) if fileList != None: # make sure outdir is a dir if outdir != None: if os.path.splitext(outdir)[1] != '': outdir = os.path.split(outdir)[0] for item in fileList: count+=1 path2file(item, outdir, colors, show, markup, quiet, form, header, footer, linenumbers, count) _printinfo('Completed colorizing %s files.'%str(count), quiet) else: _printinfo("No files to convert in dir.", quiet) def path2file(sourcePath, out=None, colors=None, show=0, markup='html', quiet=0, form=None, header=None, footer=None, linenumbers=0, count=1): """ Converts python source to html file""" # If no outdir is given we use the sourcePath if out == None:#this is a guess htmlPath = sourcePath + '.html' else: # If we do give an out_dir, and it does # not exist , it will be created. if os.path.splitext(out)[1] == '': if not os.path.isdir(out): os.makedirs(out) sourceName = os.path.basename(sourcePath) htmlPath = os.path.join(out,sourceName)+'.html' # If we do give an out_name, and its dir does # not exist , it will be created. else: outdir = os.path.split(out)[0] if not os.path.isdir(outdir): os.makedirs(outdir) htmlPath = out htmlPath = os.path.abspath(htmlPath) # Open the text and do the parsing. source = open(sourcePath).read() parse = Parser(source, colors, sourcePath, open(htmlPath, 'wt'), markup, header, footer, linenumbers) parse.format(form) _printinfo(" wrote %s" % htmlPath, quiet) # html markup will ignore the external flag, but # we need to stop the blank file from being written. if form == 'external' and count == 1 and markup != 'html': cssSheet = parse._sendCSSStyle(external=1) cssPath = os.path.join(os.path.dirname(htmlPath),'pystyle.css') css = open(cssPath, 'wt') css.write(cssSheet) css.close() _printinfo(" wrote %s" % cssPath, quiet) if show: # load HTML page into the default web browser. showpage(htmlPath) return htmlPath def tagreplace(sourcestr, colors=lite, markup='xhtml', linenumbers=0, dosheet=1, tagstart=''.lower(), tagend=''.lower(), stylesheet='pystyle.css'): """This is a helper function for pageconvert. Returns css, page. """ if markup.lower() != 'html': link = '' css = link%stylesheet if sourcestr.find(css) == -1: sourcestr = sourcestr.replace('', css, 1) starttags = sourcestr.count(tagstart) endtags = sourcestr.count(tagend) if starttags: if starttags == endtags: for _ in range(starttags): datastart = sourcestr.find(tagstart) dataend = sourcestr.find(tagend) data = sourcestr[datastart+len(tagstart):dataend] data = unescape(data) css , data = str2markup(data, colors=colors, linenumbers=linenumbers, markup=markup, form='embed') start = sourcestr[:datastart] end = sourcestr[dataend+len(tagend):] sourcestr = ''.join([start,data,end]) else: raise InputError,'Tag mismatch!\nCheck %s,%s tags'%tagstart,tagend if not dosheet: css = None return css, sourcestr def pageconvert(path, out=None, colors=lite, markup='xhtml', linenumbers=0, dosheet=1, tagstart=''.lower(), tagend=''.lower(), stylesheet='pystyle', show=1, returnstr=0): """This function can colorize Python source that is written in a webpage enclosed in tags. """ if out == None: out = os.path.dirname(path) infile = open(path, 'r').read() css,page = tagreplace(sourcestr=infile,colors=colors, markup=markup, linenumbers=linenumbers, dosheet=dosheet, tagstart=tagstart, tagend=tagend, stylesheet=stylesheet) if not returnstr: newpath = os.path.abspath(os.path.join( out,'tmp', os.path.basename(path))) if not os.path.exists(newpath): try: os.makedirs(os.path.dirname(newpath)) except: pass#traceback.print_exc() #Usage() y = open(newpath, 'w') y.write(page) y.close() if css: csspath = os.path.abspath(os.path.join( out,'tmp','%s.css'%stylesheet)) x = open(csspath,'w') x.write(css) x.close() if show: try: os.startfile(newpath) except: traceback.print_exc() return newpath else: return css, page ##################################################################### helpers def walkdir(dir): """Return a list of .py and .pyw files from a given directory. This function can be written as a generator Python 2.3, or a genexp in Python 2.4. But 2.2 and 2.1 would be left out.... """ # Get a list of files that match *.py* GLOB_PATTERN = os.path.join(dir, "*.[p][y]*") pathlist = glob.glob(GLOB_PATTERN) # Now filter out all but py and pyw filterlist = [x for x in pathlist if x.endswith('.py') or x.endswith('.pyw')] if filterlist != []: # if we have a list send it return filterlist else: return None def showpage(path): """Helper function to open webpages""" try: webbrowser.open_new(os.path.abspath(path)) except: traceback.print_exc() def _printinfo(message, quiet): """Helper to print messages""" if not quiet: print message def escape(text): """escape text for html. similar to cgi.escape""" text = text.replace("&", "&") text = text.replace("<", "<") text = text.replace(">", ">") return text def unescape(text): """unsecape escaped text""" text = text.replace(""", '"') text = text.replace(">", ">") text = text.replace("<", "<") text = text.replace("&", "&") return text ########################################################### Custom Exceptions class PySourceColorError(Exception): # Base for custom errors def __init__(self, msg=''): self._msg = msg Exception.__init__(self, msg) def __repr__(self): return self._msg __str__ = __repr__ class PathError(PySourceColorError): def __init__(self, msg): PySourceColorError.__init__(self, 'Path error! : %s'% msg) class InputError(PySourceColorError): def __init__(self, msg): PySourceColorError.__init__(self, 'Input error! : %s'% msg) ########################################################## Python code parser class Parser(object): """MoinMoin python parser heavily chopped :)""" def __init__(self, raw, colors=None, title='', out=sys.stdout, markup='html', header=None, footer=None, linenumbers=0): """Store the source text & set some flags""" if colors == None: colors = defaultColors self.raw = raw.expandtabs().rstrip() self.title = os.path.basename(title) self.out = out self.line = '' self.lasttext = '' self.argFlag = 0 self.classFlag = 0 self.defFlag = 0 self.decoratorFlag = 0 self.external = 0 self.markup = markup.upper() self.colors = colors self.header = header self.footer = footer self.doArgs = 1 # overrides the new tokens self.doNames = 1 # overrides the new tokens self.doMathOps = 1 # overrides the new tokens self.doBrackets = 1 # overrides the new tokens self.doURL = 1 # override url conversion self.LINENUMHOLDER = "___line___".upper() self.LINESTART = "___start___".upper() self.skip = 0 # add space left side of code for padding.Override in color dict. self.extraspace = self.colors.get(EXTRASPACE, '') # Linenumbers less then zero also have numberlinks self.dolinenums = self.linenum = abs(linenumbers) if linenumbers < 0: self.numberlinks = 1 else: self.numberlinks = 0 def format(self, form=None): """Parse and send the colorized source""" if form in ('snip','code'): self.addEnds = 0 elif form == 'embed': self.addEnds = 0 self.external = 1 else: if form == 'external': self.external = 1 self.addEnds = 1 # Store line offsets in self.lines self.lines = [0, 0] pos = 0 # Add linenumbers if self.dolinenums: start=self.LINENUMHOLDER+' '+self.extraspace else: start=''+self.extraspace newlines = [] lines = self.raw.splitlines(0) for l in lines: # span and div escape for customizing and embedding raw text if (l.startswith('#$#') or l.startswith('#%#') or l.startswith('#@#')): newlines.append(l) else: # kludge for line spans in css,xhtml if self.markup in ['XHTML','CSS']: newlines.append(self.LINESTART+' '+start+l) else: newlines.append(start+l) self.raw = "\n".join(newlines)+'\n'# plus an extra newline at the end # Gather lines while 1: pos = self.raw.find('\n', pos) + 1 if not pos: break self.lines.append(pos) self.lines.append(len(self.raw)) # Wrap text in a filelike object self.pos = 0 text = StringIO.StringIO(self.raw) # Markup start if self.addEnds: self._doPageStart() else: self._doSnippetStart() ## Tokenize calls the __call__ ## function for each token till done. # Parse the source and write out the results. try: tokenize.tokenize(text.readline, self) except tokenize.TokenError, ex: msg = ex[0] line = ex[1][0] self.out.write("

ERROR: %s

%s\n"% (msg, self.raw[self.lines[line]:])) #traceback.print_exc() # Markup end if self.addEnds: self._doPageEnd() else: self._doSnippetEnd() def __call__(self, toktype, toktext, (srow,scol), (erow,ecol), line): """Token handler. Order is important do not rearrange.""" self.line = line # Calculate new positions oldpos = self.pos newpos = self.lines[srow] + scol self.pos = newpos + len(toktext) # Handle newlines if toktype in (token.NEWLINE, tokenize.NL): self.decoratorFlag = self.argFlag = 0 # kludge for line spans in css,xhtml if self.markup in ['XHTML','CSS']: self.out.write('') self.out.write('\n') return # Send the original whitespace, and tokenize backslashes if present. # Tokenizer.py just sends continued line backslashes with whitespace. # This is a hack to tokenize continued line slashes as operators. # Should continued line backslashes be treated as operators # or some other token? if newpos > oldpos: if self.raw[oldpos:newpos].isspace(): # consume a single space after linestarts and linenumbers # had to have them so tokenizer could seperate them. # multiline strings are handled by do_Text functions if self.lasttext != self.LINESTART \ and self.lasttext != self.LINENUMHOLDER: self.out.write(self.raw[oldpos:newpos]) else: self.out.write(self.raw[oldpos+1:newpos]) else: slash = self.raw[oldpos:newpos].find('\\')+oldpos self.out.write(self.raw[oldpos:slash]) getattr(self, '_send%sText'%(self.markup))(OPERATOR, '\\') self.linenum+=1 # kludge for line spans in css,xhtml if self.markup in ['XHTML','CSS']: self.out.write('') self.out.write(self.raw[slash+1:newpos]) # Skip indenting tokens if toktype in (token.INDENT, token.DEDENT): self.pos = newpos return # Look for operators if token.LPAR <= toktype and toktype <= token.OP: # Trap decorators py2.4 > if toktext == '@': toktype = DECORATOR # Set a flag if this was the decorator start so # the decorator name and arguments can be identified self.decoratorFlag = self.argFlag = 1 else: if self.doArgs: # Find the start for arguments if toktext == '(' and self.argFlag: self.argFlag = 2 # Find the end for arguments elif toktext == ':': self.argFlag = 0 ## Seperate the diffrent operator types # Brackets if self.doBrackets and toktext in ['[',']','(',')','{','}']: toktype = BRACKETS # Math operators elif self.doMathOps and toktext in ['*=','**=','-=','+=','|=', '%=','>>=','<<=','=','^=', '/=', '+','-','**','*','/','%']: toktype = MATH_OPERATOR # Operator else: toktype = OPERATOR # example how flags should work. # def fun(arg=argvalue,arg2=argvalue2): # 0 1 2 A 1 N 2 A 1 N 0 if toktext == "=" and self.argFlag == 2: self.argFlag = 1 elif toktext == "," and self.argFlag == 1: self.argFlag = 2 # Look for keywords elif toktype == NAME and keyword.iskeyword(toktext): toktype = KEYWORD # Set a flag if this was the class / def start so # the class / def name and arguments can be identified if toktext in ['class', 'def']: if toktext =='class' and \ not line[:line.find('class')].endswith('.'): self.classFlag = self.argFlag = 1 elif toktext == 'def' and \ not line[:line.find('def')].endswith('.'): self.defFlag = self.argFlag = 1 else: # must have used a keyword as a name i.e. self.class toktype = ERRORTOKEN # Look for class, def, decorator name elif (self.classFlag or self.defFlag or self.decoratorFlag) \ and self.doNames: if self.classFlag: self.classFlag = 0 toktype = CLASS_NAME elif self.defFlag: self.defFlag = 0 toktype = DEF_NAME elif self.decoratorFlag: self.decoratorFlag = 0 toktype = DECORATOR_NAME # Look for strings # Order of evaluation is important do not change. elif toktype == token.STRING: text = toktext.lower() # TRIPLE DOUBLE QUOTE's if (text[:3] == '"""'): toktype = TRIPLEDOUBLEQUOTE elif (text[:4] == 'r"""'): toktype = TRIPLEDOUBLEQUOTE_R elif (text[:4] == 'u"""' or text[:5] == 'ur"""'): toktype = TRIPLEDOUBLEQUOTE_U # DOUBLE QUOTE's elif (text[:1] == '"'): toktype = DOUBLEQUOTE elif (text[:2] == 'r"'): toktype = DOUBLEQUOTE_R elif (text[:2] == 'u"' or text[:3] == 'ur"'): toktype = DOUBLEQUOTE_U # TRIPLE SINGLE QUOTE's elif (text[:3] == "'''"): toktype = TRIPLESINGLEQUOTE elif (text[:4] == "r'''"): toktype = TRIPLESINGLEQUOTE_R elif (text[:4] == "u'''" or text[:5] == "ur'''"): toktype = TRIPLESINGLEQUOTE_U # SINGLE QUOTE's elif (text[:1] == "'"): toktype = SINGLEQUOTE elif (text[:2] == "r'"): toktype = SINGLEQUOTE_R elif (text[:2] == "u'" or text[:3] == "ur'"): toktype = SINGLEQUOTE_U # test for invalid string declaration if self.lasttext.lower() == 'ru': toktype = ERRORTOKEN # Look for comments elif toktype == COMMENT: if toktext[:2] == "##": toktype = DOUBLECOMMENT elif toktext[:3] == '#$#': toktype = TEXT self.textFlag = 'SPAN' toktext = toktext[3:] elif toktext[:3] == '#%#': toktype = TEXT self.textFlag = 'DIV' toktext = toktext[3:] elif toktext[:3] == '#@#': toktype = TEXT self.textFlag = 'RAW' toktext = toktext[3:] if self.doURL: # this is a 'fake helper function' # url(URI,Alias_name) or url(URI) url_pos = toktext.find('url(') if url_pos != -1: before = toktext[:url_pos] url = toktext[url_pos+4:] splitpoint = url.find(',') endpoint = url.find(')') after = url[endpoint+1:] url = url[:endpoint] if splitpoint != -1: urlparts = url.split(',',1) toktext = '%s%s%s'%( before,urlparts[0],urlparts[1].lstrip(),after) else: toktext = '%s%s%s'%(before,url,url,after) # Seperate errors from decorators elif toktype == ERRORTOKEN: # Bug fix for < py2.4 # space between decorators if self.argFlag and toktext.isspace(): #toktype = NAME self.out.write(toktext) return # Bug fix for py2.2 linenumbers with decorators elif toktext.isspace(): # What if we have a decorator after a >>> or ... #p = line.find('@') #if p >= 0 and not line[:p].isspace(): #self.out.write(toktext) #return if self.skip: self.skip=0 return else: self.out.write(toktext) return # trap decorators < py2.4 elif toktext == '@': toktype = DECORATOR # Set a flag if this was the decorator start so # the decorator name and arguments can be identified self.decoratorFlag = self.argFlag = 1 # Seperate args from names elif (self.argFlag == 2 and toktype == NAME and toktext != 'None' and self.doArgs): toktype = ARGS # Look for line numbers # The conversion code for them is in the send_text functions. if toktext in [self.LINENUMHOLDER,self.LINESTART]: toktype = LINENUMBER # if we don't have linenumbers set flag # to skip the trailing space from linestart if toktext == self.LINESTART and not self.dolinenums \ or toktext == self.LINENUMHOLDER: self.skip=1 # Skip blank token that made it thru ## bugfix for the last empty tag. if toktext == '': return # Last token text history self.lasttext = toktext # escape all but the urls in the comments if toktype in (DOUBLECOMMENT, COMMENT): if toktext.find('\n') else: # Start of css/xhtml snippet self.out.write(self.colors.get(CODESTART,'
\n'))

    def _doSnippetEnd(self):
        # End of html snippet
        self.out.write(self.colors.get(CODEEND,'
\n')) ######################################################## markup selectors def _getFile(self, filepath): try: _file = open(filepath,'r') content = _file.read() _file.close() except: traceback.print_exc() content = '' return content def _doPageStart(self): getattr(self, '_do%sStart'%(self.markup))() def _doPageHeader(self): if self.header != None: if self.header.find('#$#') != -1 or \ self.header.find('#$#') != -1 or \ self.header.find('#%#') != -1: self.out.write(self.header[3:]) else: if self.header != '': self.header = self._getFile(self.header) getattr(self, '_do%sHeader'%(self.markup))() def _doPageFooter(self): if self.footer != None: if self.footer.find('#$#') != -1 or \ self.footer.find('#@#') != -1 or \ self.footer.find('#%#') != -1: self.out.write(self.footer[3:]) else: if self.footer != '': self.footer = self._getFile(self.footer) getattr(self, '_do%sFooter'%(self.markup))() def _doPageEnd(self): getattr(self, '_do%sEnd'%(self.markup))() ################################################### color/style retrieval ## Some of these are not used anymore but are kept for documentation def _getLineNumber(self): num = self.linenum self.linenum+=1 return str(num).rjust(5)+" " def _getTags(self, key): # style tags return self.colors.get(key, self.colors[NAME])[0] def _getForeColor(self, key): # get text foreground color, if not set to black color = self.colors.get(key, self.colors[NAME])[1] if color[:1] != '#': color = '#000000' return color def _getBackColor(self, key): # get text background color return self.colors.get(key, self.colors[NAME])[2] def _getPageColor(self): # get page background color return self.colors.get(PAGEBACKGROUND, '#FFFFFF') def _getStyle(self, key): # get the token style from the color dictionary return self.colors.get(key, self.colors[NAME]) def _getMarkupClass(self, key): # get the markup class name from the markup dictionary return MARKUPDICT.get(key, MARKUPDICT[NAME]) def _getDocumentCreatedBy(self): return '\n'%( __title__,__version__,time.ctime()) ################################################### HTML markup functions def _doHTMLStart(self): # Start of html page self.out.write('\n') self.out.write('%s\n'%(self.title)) self.out.write(self._getDocumentCreatedBy()) self.out.write('\n') # Get background self.out.write('\n'%self._getPageColor()) self._doPageHeader() self.out.write('
')

    def _getHTMLStyles(self, toktype, toktext):
        # Get styles
        tags, color = self.colors.get(toktype, self.colors[NAME])[:2]#
        tagstart=[]
        tagend=[]
        # check for styles and set them if needed.
        if 'b' in tags:#Bold
            tagstart.append('')
            tagend.append('')
        if 'i' in tags:#Italics
            tagstart.append('')
            tagend.append('')
        if 'u' in tags:#Underline
            tagstart.append('')
            tagend.append('')
        # HTML tags should be paired like so : Doh!
        tagend.reverse()
        starttags="".join(tagstart)
        endtags="".join(tagend)
        return starttags,endtags,color

    def _sendHTMLText(self, toktype, toktext):
        numberlinks = self.numberlinks
        
        # If it is an error, set a red box around the bad tokens
        # older browsers should ignore it
        if toktype == ERRORTOKEN:
            style = ' style="border: solid 1.5pt #FF0000;"'
        else:
            style = ''
        # Get styles
        starttag, endtag, color = self._getHTMLStyles(toktype, toktext)
        # This is a hack to 'fix' multi-line  strings.
        # Multi-line strings are treated as only one token 
        # even though they can be several physical lines.
        # That makes it hard to spot the start of a line,
        # because at this level all we know about are tokens.
        
        if toktext.count(self.LINENUMHOLDER):
            # rip apart the string and separate it by line.
            # count lines and change all linenum token to line numbers.
            # embedded all the new font tags inside the current one.
            # Do this by ending the tag first then writing our new tags,
            # then starting another font tag exactly like the first one.
            if toktype == LINENUMBER:
                splittext = toktext.split(self.LINENUMHOLDER)
            else:    
                splittext = toktext.split(self.LINENUMHOLDER+' ')
            store = []
            store.append(splittext.pop(0))
            lstarttag, lendtag, lcolor = self._getHTMLStyles(LINENUMBER, toktext)
            count = len(splittext)
            for item in splittext:
                num =  self._getLineNumber()
                if numberlinks:
                    numstrip = num.strip()
                    content = '%s' \
                              %(numstrip,numstrip,num)
                else:
                    content = num
                if count <= 1:
                    endtag,starttag = '',''
                linenumber = ''.join([endtag,'',
                            lstarttag, content, lendtag, '' ,starttag])
                store.append(linenumber+item)
            toktext = ''.join(store)
        # send text
        ## Output optimization
        # skip font tag if black text, but styles will still be sent. (b,u,i)
        if color !='#000000':
            startfont = ''%(color, style)
            endfont = ''
        else:
            startfont, endfont = ('','')
        if toktype != LINENUMBER:
            self.out.write(''.join([startfont,starttag,
                                     toktext,endtag,endfont]))
        else:
            self.out.write(toktext)
        return

    def _doHTMLHeader(self):
        # Optional
        if self.header != '':
            self.out.write('%s\n'%self.header)
        else:
            color = self._getForeColor(NAME)
            self.out.write('# %s \
                            
# %s

\n'% (color, self.title, time.ctime())) def _doHTMLFooter(self): # Optional if self.footer != '': self.out.write('%s\n'%self.footer) else: color = self._getForeColor(NAME) self.out.write(' \
# %s
# %s
\n'% (color, self.title, time.ctime())) def _doHTMLEnd(self): # End of html page self.out.write('
\n') # Write a little info at the bottom self._doPageFooter() self.out.write('\n') #################################################### CSS markup functions def _getCSSStyle(self, key): # Get the tags and colors from the dictionary tags, forecolor, backcolor = self._getStyle(key) style=[] border = None bordercolor = None tags = tags.lower() if tags: # get the border color if specified # the border color will be appended to # the list after we define a border if '#' in tags:# border color start = tags.find('#') end = start + 7 bordercolor = tags[start:end] tags.replace(bordercolor,'',1) # text styles if 'b' in tags:# Bold style.append('font-weight:bold;') else: style.append('font-weight:normal;') if 'i' in tags:# Italic style.append('font-style:italic;') if 'u' in tags:# Underline style.append('text-decoration:underline;') # border size if 'l' in tags:# thick border size='thick' elif 'm' in tags:# medium border size='medium' elif 't' in tags:# thin border size='thin' else:# default size='medium' # border styles if 'n' in tags:# inset border border='inset' elif 'o' in tags:# outset border border='outset' elif 'r' in tags:# ridge border border='ridge' elif 'g' in tags:# groove border border='groove' elif '=' in tags:# double border border='double' elif '.' in tags:# dotted border border='dotted' elif '-' in tags:# dashed border border='dashed' elif 's' in tags:# solid border border='solid' # border type check seperate_sides=0 for side in ['<','>','^','v']: if side in tags: seperate_sides+=1 # border box or seperate sides if seperate_sides==0 and border: style.append('border: %s %s;'%(border,size)) else: if border == None: border = 'solid' if 'v' in tags:# bottom border style.append('border-bottom:%s %s;'%(border,size)) if '<' in tags:# left border style.append('border-left:%s %s;'%(border,size)) if '>' in tags:# right border style.append('border-right:%s %s;'%(border,size)) if '^' in tags:# top border style.append('border-top:%s %s;'%(border,size)) else: style.append('font-weight:normal;')# css inherited style fix # we have to define our borders before we set colors if bordercolor: style.append('border-color:%s;'%bordercolor) # text forecolor style.append('color:%s;'% forecolor) # text backcolor if backcolor: style.append('background-color:%s;'%backcolor) return (self._getMarkupClass(key),' '.join(style)) def _sendCSSStyle(self, external=0): """ create external and internal style sheets""" styles = [] external += self.external if not external: styles.append('\n') return ''.join(styles) def _doCSSStart(self): # Start of css/html 4.01 page self.out.write('\n') self.out.write('%s\n'%(self.title)) self.out.write(self._getDocumentCreatedBy()) self.out.write('\n') self._doCSSStyleSheet() self.out.write('\n\n') # Write a little info at the top. self._doPageHeader() self.out.write(self.colors.get(CODESTART,'
\n'))
        return

    def _doCSSStyleSheet(self):
        if not self.external:
            # write an embedded style sheet
            self.out.write(self._sendCSSStyle())
        else:
            # write a link to an external style sheet
            self.out.write('')
        return

    def _sendCSSText(self, toktype, toktext):
        # This is a hack to 'fix' multi-line strings.
        # Multi-line strings are treated as only one token 
        # even though they can be several physical lines.
        # That makes it hard to spot the start of a line,
        # because at this level all we know about are tokens.
        markupclass = MARKUPDICT.get(toktype, MARKUPDICT[NAME])
        # if it is a LINENUMBER type then we can skip the rest
        if toktext == self.LINESTART and toktype == LINENUMBER:
            self.out.write('')
            return
        if toktext.count(self.LINENUMHOLDER):
            # rip apart the string and separate it by line
            # count lines and change all linenum token to line numbers
            # also convert linestart and lineend tokens
            #   lnum  text 
            #################################################
            newmarkup = MARKUPDICT.get(LINENUMBER, MARKUPDICT[NAME])
            lstartspan = ''%(newmarkup)
            if toktype == LINENUMBER:
                splittext = toktext.split(self.LINENUMHOLDER)
            else:    
                splittext = toktext.split(self.LINENUMHOLDER+' ')
            store = []
            # we have already seen the first linenumber token
            # so we can skip the first one
            store.append(splittext.pop(0))
            for item in splittext:
                num = self._getLineNumber()
                if self.numberlinks:
                    numstrip = num.strip()
                    content= '%s' \
                              %(numstrip,numstrip,num)
                else:
                    content = num
                linenumber= ''.join([lstartspan,content,''])
                store.append(linenumber+item)
            toktext = ''.join(store)
        if toktext.count(self.LINESTART):
            # wraps the textline in a line span
            # this adds a lot of kludges, is it really worth it?
            store = []
            parts = toktext.split(self.LINESTART+' ')
            # handle the first part differently
            # the whole token gets wraqpped in a span later on
            first = parts.pop(0)
            # place spans before the newline
            pos = first.rfind('\n')
            if pos != -1:
                first=first[:pos]+''+first[pos:]
            store.append(first)
            #process the rest of the string
            for item in parts:
                #handle line numbers if present
                if self.dolinenums:
                    item = item.replace('',
                           ''%(markupclass))
                else:
                    item = '%s'%(markupclass,item)
                # add endings for line and string tokens
                pos = item.rfind('\n')
                if pos != -1:
                    item=item[:pos]+'\n'
                store.append(item)
            # add start tags for lines
            toktext = ''.join(store)
        # Send text
        if toktype != LINENUMBER:
            if toktype == TEXT and self.textFlag == 'DIV':
                startspan = '
'%(markupclass) endspan = '
' elif toktype == TEXT and self.textFlag == 'RAW': startspan,endspan = ('','') else: startspan = ''%(markupclass) endspan = '' self.out.write(''.join([startspan, toktext, endspan])) else: self.out.write(toktext) return def _doCSSHeader(self): if self.header != '': self.out.write('%s\n'%self.header) else: name = MARKUPDICT.get(NAME) self.out.write('
# %s
\ # %s

\n'%(name, self.title, time.ctime())) def _doCSSFooter(self): # Optional if self.footer != '': self.out.write('%s\n'%self.footer) else: self.out.write('
# %s
\ # %s
\n'%(MARKUPDICT.get(NAME),self.title, time.ctime())) def _doCSSEnd(self): # End of css/html page self.out.write(self.colors.get(CODEEND,'
\n')) # Write a little info at the bottom self._doPageFooter() self.out.write('\n') return ################################################## XHTML markup functions def _doXHTMLStart(self): # XHTML is really just XML + HTML 4.01. # We only need to change the page headers, # and a few tags to get valid XHTML. # Start of xhtml page self.out.write('\n \ \n \ \n') self.out.write('%s\n'%(self.title)) self.out.write(self._getDocumentCreatedBy()) self.out.write('\n') self._doXHTMLStyleSheet() self.out.write('\n\n') # Write a little info at the top. self._doPageHeader() self.out.write(self.colors.get(CODESTART,'
\n'))
        return

    def _doXHTMLStyleSheet(self):
        if not self.external:
            # write an embedded style sheet
            self.out.write(self._sendCSSStyle())
        else:
            # write a link to an external style sheet
            self.out.write('\n')
        return

    def _sendXHTMLText(self, toktype, toktext):
        self._sendCSSText(toktype, toktext)

    def _doXHTMLHeader(self):
        # Optional
        if self.header:
            self.out.write('%s\n'%self.header)
        else:
            name = MARKUPDICT.get(NAME)
            self.out.write('
# %s
\ # %s

\n '%( name, self.title, time.ctime())) def _doXHTMLFooter(self): # Optional if self.footer: self.out.write('%s\n'%self.footer) else: self.out.write('
# %s
\ # %s
\n'%(MARKUPDICT.get(NAME), self.title, time.ctime())) def _doXHTMLEnd(self): self._doCSSEnd() ############################################################################# if __name__ == '__main__': cli() ############################################################################# # PySourceColor.py # 2004, 2005 M.E.Farmer Jr. # Python license PK4,JJpaste/util/finddata.py# Note: you may want to copy this into your setup.py file verbatim, as # you can't import this from another package, when you don't know if # that package is installed yet. import os import sys from fnmatch import fnmatchcase from distutils.util import convert_path # Provided as an attribute, so you can append to these instead # of replicating them: standard_exclude = ('*.py', '*.pyc', '*~', '.*', '*.bak') standard_exclude_directories = ('.*', 'CVS', '_darcs', './build', './dist', 'EGG-INFO', '*.egg-info') def find_package_data( where='.', package='', exclude=standard_exclude, exclude_directories=standard_exclude_directories, only_in_packages=True, show_ignored=False): """ Return a dictionary suitable for use in ``package_data`` in a distutils ``setup.py`` file. The dictionary looks like:: {'package': [files]} Where ``files`` is a list of all the files in that package that don't match anything in ``exclude``. If ``only_in_packages`` is true, then top-level directories that are not packages won't be included (but directories under packages will). Directories matching any pattern in ``exclude_directories`` will be ignored; by default directories with leading ``.``, ``CVS``, and ``_darcs`` will be ignored. If ``show_ignored`` is true, then all the files that aren't included in package data are shown on stderr (for debugging purposes). Note patterns use wildcards, or can be exact paths (including leading ``./``), and all searching is case-insensitive. """ out = {} stack = [(convert_path(where), '', package, only_in_packages)] while stack: where, prefix, package, only_in_packages = stack.pop(0) for name in os.listdir(where): fn = os.path.join(where, name) if os.path.isdir(fn): bad_name = False for pattern in exclude_directories: if (fnmatchcase(name, pattern) or fn.lower() == pattern.lower()): bad_name = True if show_ignored: print >> sys.stderr, ( "Directory %s ignored by pattern %s" % (fn, pattern)) break if bad_name: continue if (os.path.isfile(os.path.join(fn, '__init__.py')) and not prefix): if not package: new_package = name else: new_package = package + '.' + name stack.append((fn, '', new_package, False)) else: stack.append((fn, prefix + name + '/', package, only_in_packages)) elif package or not only_in_packages: # is a file bad_name = False for pattern in exclude: if (fnmatchcase(name, pattern) or fn.lower() == pattern.lower()): bad_name = True if show_ignored: print >> sys.stderr, ( "File %s ignored by pattern %s" % (fn, pattern)) break if bad_name: continue out.setdefault(package, []).append(prefix+name) return out if __name__ == '__main__': import pprint pprint.pprint( find_package_data(show_ignored=True)) PK4522paste/util/doctest24.py# Module doctest. # Released to the public domain 16-Jan-2001, by Tim Peters (tim@python.org). # Major enhancements and refactoring by: # Jim Fulton # Edward Loper # Provided as-is; use at your own risk; no warranty; no promises; enjoy! r"""Module doctest -- a framework for running examples in docstrings. In simplest use, end each module M to be tested with: def _test(): import doctest doctest.testmod() if __name__ == "__main__": _test() Then running the module as a script will cause the examples in the docstrings to get executed and verified: python M.py This won't display anything unless an example fails, in which case the failing example(s) and the cause(s) of the failure(s) are printed to stdout (why not stderr? because stderr is a lame hack <0.2 wink>), and the final line of output is "Test failed.". Run it with the -v switch instead: python M.py -v and a detailed report of all examples tried is printed to stdout, along with assorted summaries at the end. You can force verbose mode by passing "verbose=True" to testmod, or prohibit it by passing "verbose=False". In either of those cases, sys.argv is not examined by testmod. There are a variety of other ways to run doctests, including integration with the unittest framework, and support for running non-Python text files containing doctests. There are also many ways to override parts of doctest's default behaviors. See the Library Reference Manual for details. """ __docformat__ = 'reStructuredText en' __all__ = [ # 0, Option Flags 'register_optionflag', 'DONT_ACCEPT_TRUE_FOR_1', 'DONT_ACCEPT_BLANKLINE', 'NORMALIZE_WHITESPACE', 'ELLIPSIS', 'IGNORE_EXCEPTION_DETAIL', 'COMPARISON_FLAGS', 'REPORT_UDIFF', 'REPORT_CDIFF', 'REPORT_NDIFF', 'REPORT_ONLY_FIRST_FAILURE', 'REPORTING_FLAGS', # 1. Utility Functions 'is_private', # 2. Example & DocTest 'Example', 'DocTest', # 3. Doctest Parser 'DocTestParser', # 4. Doctest Finder 'DocTestFinder', # 5. Doctest Runner 'DocTestRunner', 'OutputChecker', 'DocTestFailure', 'UnexpectedException', 'DebugRunner', # 6. Test Functions 'testmod', 'testfile', 'run_docstring_examples', # 7. Tester 'Tester', # 8. Unittest Support 'DocTestSuite', 'DocFileSuite', 'set_unittest_reportflags', # 9. Debugging Support 'script_from_examples', 'testsource', 'debug_src', 'debug', ] import __future__ import sys, traceback, inspect, linecache, os, re, types import unittest, difflib, pdb, tempfile import warnings from StringIO import StringIO # Don't whine about the deprecated is_private function in this # module's tests. warnings.filterwarnings("ignore", "is_private", DeprecationWarning, __name__, 0) # There are 4 basic classes: # - Example: a pair, plus an intra-docstring line number. # - DocTest: a collection of examples, parsed from a docstring, plus # info about where the docstring came from (name, filename, lineno). # - DocTestFinder: extracts DocTests from a given object's docstring and # its contained objects' docstrings. # - DocTestRunner: runs DocTest cases, and accumulates statistics. # # So the basic picture is: # # list of: # +------+ +---------+ +-------+ # |object| --DocTestFinder-> | DocTest | --DocTestRunner-> |results| # +------+ +---------+ +-------+ # | Example | # | ... | # | Example | # +---------+ # Option constants. OPTIONFLAGS_BY_NAME = {} def register_optionflag(name): flag = 1 << len(OPTIONFLAGS_BY_NAME) OPTIONFLAGS_BY_NAME[name] = flag return flag DONT_ACCEPT_TRUE_FOR_1 = register_optionflag('DONT_ACCEPT_TRUE_FOR_1') DONT_ACCEPT_BLANKLINE = register_optionflag('DONT_ACCEPT_BLANKLINE') NORMALIZE_WHITESPACE = register_optionflag('NORMALIZE_WHITESPACE') ELLIPSIS = register_optionflag('ELLIPSIS') IGNORE_EXCEPTION_DETAIL = register_optionflag('IGNORE_EXCEPTION_DETAIL') COMPARISON_FLAGS = (DONT_ACCEPT_TRUE_FOR_1 | DONT_ACCEPT_BLANKLINE | NORMALIZE_WHITESPACE | ELLIPSIS | IGNORE_EXCEPTION_DETAIL) REPORT_UDIFF = register_optionflag('REPORT_UDIFF') REPORT_CDIFF = register_optionflag('REPORT_CDIFF') REPORT_NDIFF = register_optionflag('REPORT_NDIFF') REPORT_ONLY_FIRST_FAILURE = register_optionflag('REPORT_ONLY_FIRST_FAILURE') REPORTING_FLAGS = (REPORT_UDIFF | REPORT_CDIFF | REPORT_NDIFF | REPORT_ONLY_FIRST_FAILURE) # Special string markers for use in `want` strings: BLANKLINE_MARKER = '' ELLIPSIS_MARKER = '...' ###################################################################### ## Table of Contents ###################################################################### # 1. Utility Functions # 2. Example & DocTest -- store test cases # 3. DocTest Parser -- extracts examples from strings # 4. DocTest Finder -- extracts test cases from objects # 5. DocTest Runner -- runs test cases # 6. Test Functions -- convenient wrappers for testing # 7. Tester Class -- for backwards compatibility # 8. Unittest Support # 9. Debugging Support # 10. Example Usage ###################################################################### ## 1. Utility Functions ###################################################################### def is_private(prefix, base): """prefix, base -> true iff name prefix + "." + base is "private". Prefix may be an empty string, and base does not contain a period. Prefix is ignored (although functions you write conforming to this protocol may make use of it). Return true iff base begins with an (at least one) underscore, but does not both begin and end with (at least) two underscores. >>> is_private("a.b", "my_func") False >>> is_private("____", "_my_func") True >>> is_private("someclass", "__init__") False >>> is_private("sometypo", "__init_") True >>> is_private("x.y.z", "_") True >>> is_private("_x.y.z", "__") False >>> is_private("", "") # senseless but consistent False """ warnings.warn("is_private is deprecated; it wasn't useful; " "examine DocTestFinder.find() lists instead", DeprecationWarning, stacklevel=2) return base[:1] == "_" and not base[:2] == "__" == base[-2:] def _extract_future_flags(globs): """ Return the compiler-flags associated with the future features that have been imported into the given namespace (globs). """ flags = 0 for fname in __future__.all_feature_names: feature = globs.get(fname, None) if feature is getattr(__future__, fname): flags |= feature.compiler_flag return flags def _normalize_module(module, depth=2): """ Return the module specified by `module`. In particular: - If `module` is a module, then return module. - If `module` is a string, then import and return the module with that name. - If `module` is None, then return the calling module. The calling module is assumed to be the module of the stack frame at the given depth in the call stack. """ if inspect.ismodule(module): return module elif isinstance(module, (str, unicode)): return __import__(module, globals(), locals(), ["*"]) elif module is None: return sys.modules[sys._getframe(depth).f_globals['__name__']] else: raise TypeError("Expected a module, string, or None") def _indent(s, indent=4): """ Add the given number of space characters to the beginning every non-blank line in `s`, and return the result. """ # This regexp matches the start of non-blank lines: return re.sub('(?m)^(?!$)', indent*' ', s) def _exception_traceback(exc_info): """ Return a string containing a traceback message for the given exc_info tuple (as returned by sys.exc_info()). """ # Get a traceback message. excout = StringIO() exc_type, exc_val, exc_tb = exc_info traceback.print_exception(exc_type, exc_val, exc_tb, file=excout) return excout.getvalue() # Override some StringIO methods. class _SpoofOut(StringIO): def getvalue(self): result = StringIO.getvalue(self) # If anything at all was written, make sure there's a trailing # newline. There's no way for the expected output to indicate # that a trailing newline is missing. if result and not result.endswith("\n"): result += "\n" # Prevent softspace from screwing up the next test case, in # case they used print with a trailing comma in an example. if hasattr(self, "softspace"): del self.softspace return result def truncate(self, size=None): StringIO.truncate(self, size) if hasattr(self, "softspace"): del self.softspace # Worst-case linear-time ellipsis matching. def _ellipsis_match(want, got): """ Essentially the only subtle case: >>> _ellipsis_match('aa...aa', 'aaa') False """ if ELLIPSIS_MARKER not in want: return want == got # Find "the real" strings. ws = want.split(ELLIPSIS_MARKER) assert len(ws) >= 2 # Deal with exact matches possibly needed at one or both ends. startpos, endpos = 0, len(got) w = ws[0] if w: # starts with exact match if got.startswith(w): startpos = len(w) del ws[0] else: return False w = ws[-1] if w: # ends with exact match if got.endswith(w): endpos -= len(w) del ws[-1] else: return False if startpos > endpos: # Exact end matches required more characters than we have, as in # _ellipsis_match('aa...aa', 'aaa') return False # For the rest, we only need to find the leftmost non-overlapping # match for each piece. If there's no overall match that way alone, # there's no overall match period. for w in ws: # w may be '' at times, if there are consecutive ellipses, or # due to an ellipsis at the start or end of `want`. That's OK. # Search for an empty string succeeds, and doesn't change startpos. startpos = got.find(w, startpos, endpos) if startpos < 0: return False startpos += len(w) return True def _comment_line(line): "Return a commented form of the given line" line = line.rstrip() if line: return '# '+line else: return '#' 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 # [XX] Normalize with respect to os.path.pardir? def _module_relative_path(module, path): if not inspect.ismodule(module): raise TypeError, 'Expected a module: %r' % module if path.startswith('/'): raise ValueError, 'Module-relative files may not have absolute paths' # Find the base directory for the path. if hasattr(module, '__file__'): # A normal module/package basedir = os.path.split(module.__file__)[0] elif module.__name__ == '__main__': # An interactive session. if len(sys.argv)>0 and sys.argv[0] != '': basedir = os.path.split(sys.argv[0])[0] else: basedir = os.curdir else: # A module w/o __file__ (this includes builtins) raise ValueError("Can't resolve paths relative to the module " + module + " (it has no __file__)") # Combine the base directory and the path. return os.path.join(basedir, *(path.split('/'))) ###################################################################### ## 2. Example & DocTest ###################################################################### ## - An "example" is a pair, where "source" is a ## fragment of source code, and "want" is the expected output for ## "source." The Example class also includes information about ## where the example was extracted from. ## ## - A "doctest" is a collection of examples, typically extracted from ## a string (such as an object's docstring). The DocTest class also ## includes information about where the string was extracted from. class Example: """ A single doctest example, consisting of source code and expected output. `Example` defines the following attributes: - source: A single Python statement, always ending with a newline. The constructor adds a newline if needed. - want: The expected output from running the source code (either from stdout, or a traceback in case of exception). `want` ends with a newline unless it's empty, in which case it's an empty string. The constructor adds a newline if needed. - exc_msg: The exception message generated by the example, if the example is expected to generate an exception; or `None` if it is not expected to generate an exception. This exception message is compared against the return value of `traceback.format_exception_only()`. `exc_msg` ends with a newline unless it's `None`. The constructor adds a newline if needed. - lineno: The line number within the DocTest string containing this Example where the Example begins. This line number is zero-based, with respect to the beginning of the DocTest. - indent: The example's indentation in the DocTest string. I.e., the number of space characters that preceed the example's first prompt. - options: A dictionary mapping from option flags to True or False, which is used to override default options for this example. Any option flags not contained in this dictionary are left at their default value (as specified by the DocTestRunner's optionflags). By default, no options are set. """ def __init__(self, source, want, exc_msg=None, lineno=0, indent=0, options=None): # Normalize inputs. if not source.endswith('\n'): source += '\n' if want and not want.endswith('\n'): want += '\n' if exc_msg is not None and not exc_msg.endswith('\n'): exc_msg += '\n' # Store properties. self.source = source self.want = want self.lineno = lineno self.indent = indent if options is None: options = {} self.options = options self.exc_msg = exc_msg class DocTest: """ A collection of doctest examples that should be run in a single namespace. Each `DocTest` defines the following attributes: - examples: the list of examples. - globs: The namespace (aka globals) that the examples should be run in. - name: A name identifying the DocTest (typically, the name of the object whose docstring this DocTest was extracted from). - filename: The name of the file that this DocTest was extracted from, or `None` if the filename is unknown. - lineno: The line number within filename where this DocTest begins, or `None` if the line number is unavailable. This line number is zero-based, with respect to the beginning of the file. - docstring: The string that the examples were extracted from, or `None` if the string is unavailable. """ def __init__(self, examples, globs, name, filename, lineno, docstring): """ Create a new DocTest containing the given examples. The DocTest's globals are initialized with a copy of `globs`. """ assert not isinstance(examples, basestring), \ "DocTest no longer accepts str; use DocTestParser instead" self.examples = examples self.docstring = docstring self.globs = globs.copy() self.name = name self.filename = filename self.lineno = lineno def __repr__(self): if len(self.examples) == 0: examples = 'no examples' elif len(self.examples) == 1: examples = '1 example' else: examples = '%d examples' % len(self.examples) return ('' % (self.name, self.filename, self.lineno, examples)) # This lets us sort tests by name: def __cmp__(self, other): if not isinstance(other, DocTest): return -1 return cmp((self.name, self.filename, self.lineno, id(self)), (other.name, other.filename, other.lineno, id(other))) ###################################################################### ## 3. DocTestParser ###################################################################### class DocTestParser: """ A class used to parse strings containing doctest examples. """ # This regular expression is used to find doctest examples in a # string. It defines three groups: `source` is the source code # (including leading indentation and prompts); `indent` is the # indentation of the first (PS1) line of the source code; and # `want` is the expected output (including leading indentation). _EXAMPLE_RE = re.compile(r''' # Source consists of a PS1 line followed by zero or more PS2 lines. (?P (?:^(?P [ ]*) >>> .*) # PS1 line (?:\n [ ]* \.\.\. .*)*) # PS2 lines \n? # Want consists of any non-blank lines that do not start with PS1. (?P (?:(?![ ]*$) # Not a blank line (?![ ]*>>>) # Not a line starting with PS1 .*$\n? # But any other line )*) ''', re.MULTILINE | re.VERBOSE) # A regular expression for handling `want` strings that contain # expected exceptions. It divides `want` into three pieces: # - the traceback header line (`hdr`) # - the traceback stack (`stack`) # - the exception message (`msg`), as generated by # traceback.format_exception_only() # `msg` may have multiple lines. We assume/require that the # exception message is the first non-indented line starting with a word # character following the traceback header line. _EXCEPTION_RE = re.compile(r""" # Grab the traceback header. Different versions of Python have # said different things on the first traceback line. ^(?P Traceback\ \( (?: most\ recent\ call\ last | innermost\ last ) \) : ) \s* $ # toss trailing whitespace on the header. (?P .*?) # don't blink: absorb stuff until... ^ (?P \w+ .*) # a line *starts* with alphanum. """, re.VERBOSE | re.MULTILINE | re.DOTALL) # A callable returning a true value iff its argument is a blank line # or contains a single comment. _IS_BLANK_OR_COMMENT = re.compile(r'^[ ]*(#.*)?$').match def parse(self, string, name=''): """ Divide the given string into examples and intervening text, and return them as a list of alternating Examples and strings. Line numbers for the Examples are 0-based. The optional argument `name` is a name identifying this string, and is only used for error messages. """ string = string.expandtabs() # If all lines begin with the same indentation, then strip it. min_indent = self._min_indent(string) if min_indent > 0: string = '\n'.join([l[min_indent:] for l in string.split('\n')]) output = [] charno, lineno = 0, 0 # Find all doctest examples in the string: for m in self._EXAMPLE_RE.finditer(string): # Add the pre-example text to `output`. output.append(string[charno:m.start()]) # Update lineno (lines before this example) lineno += string.count('\n', charno, m.start()) # Extract info from the regexp match. (source, options, want, exc_msg) = \ self._parse_example(m, name, lineno) # Create an Example, and add it to the list. if not self._IS_BLANK_OR_COMMENT(source): output.append( Example(source, want, exc_msg, lineno=lineno, indent=min_indent+len(m.group('indent')), options=options) ) # Update lineno (lines inside this example) lineno += string.count('\n', m.start(), m.end()) # Update charno. charno = m.end() # Add any remaining post-example text to `output`. output.append(string[charno:]) return output def get_doctest(self, string, globs, name, filename, lineno): """ Extract all doctest examples from the given string, and collect them into a `DocTest` object. `globs`, `name`, `filename`, and `lineno` are attributes for the new `DocTest` object. See the documentation for `DocTest` for more information. """ return DocTest(self.get_examples(string, name), globs, name, filename, lineno, string) def get_examples(self, string, name=''): """ Extract all doctest examples from the given string, and return them as a list of `Example` objects. Line numbers are 0-based, because it's most common in doctests that nothing interesting appears on the same line as opening triple-quote, and so the first interesting line is called \"line 1\" then. The optional argument `name` is a name identifying this string, and is only used for error messages. """ return [x for x in self.parse(string, name) if isinstance(x, Example)] def _parse_example(self, m, name, lineno): """ Given a regular expression match from `_EXAMPLE_RE` (`m`), return a pair `(source, want)`, where `source` is the matched example's source code (with prompts and indentation stripped); and `want` is the example's expected output (with indentation stripped). `name` is the string's name, and `lineno` is the line number where the example starts; both are used for error messages. """ # Get the example's indentation level. indent = len(m.group('indent')) # Divide source into lines; check that they're properly # indented; and then strip their indentation & prompts. source_lines = m.group('source').split('\n') self._check_prompt_blank(source_lines, indent, name, lineno) self._check_prefix(source_lines[1:], ' '*indent + '.', name, lineno) source = '\n'.join([sl[indent+4:] for sl in source_lines]) # Divide want into lines; check that it's properly indented; and # then strip the indentation. Spaces before the last newline should # be preserved, so plain rstrip() isn't good enough. want = m.group('want') want_lines = want.split('\n') if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]): del want_lines[-1] # forget final newline & spaces after it self._check_prefix(want_lines, ' '*indent, name, lineno + len(source_lines)) want = '\n'.join([wl[indent:] for wl in want_lines]) # If `want` contains a traceback message, then extract it. m = self._EXCEPTION_RE.match(want) if m: exc_msg = m.group('msg') else: exc_msg = None # Extract options from the source. options = self._find_options(source, name, lineno) return source, options, want, exc_msg # This regular expression looks for option directives in the # source code of an example. Option directives are comments # starting with "doctest:". Warning: this may give false # positives for string-literals that contain the string # "#doctest:". Eliminating these false positives would require # actually parsing the string; but we limit them by ignoring any # line containing "#doctest:" that is *followed* by a quote mark. _OPTION_DIRECTIVE_RE = re.compile(r'#\s*doctest:\s*([^\n\'"]*)$', re.MULTILINE) def _find_options(self, source, name, lineno): """ Return a dictionary containing option overrides extracted from option directives in the given source string. `name` is the string's name, and `lineno` is the line number where the example starts; both are used for error messages. """ options = {} # (note: with the current regexp, this will match at most once:) for m in self._OPTION_DIRECTIVE_RE.finditer(source): option_strings = m.group(1).replace(',', ' ').split() for option in option_strings: if (option[0] not in '+-' or option[1:] not in OPTIONFLAGS_BY_NAME): raise ValueError('line %r of the doctest for %s ' 'has an invalid option: %r' % (lineno+1, name, option)) flag = OPTIONFLAGS_BY_NAME[option[1:]] options[flag] = (option[0] == '+') if options and self._IS_BLANK_OR_COMMENT(source): raise ValueError('line %r of the doctest for %s has an option ' 'directive on a line with no example: %r' % (lineno, name, source)) return options # This regular expression finds the indentation of every non-blank # line in a string. _INDENT_RE = re.compile('^([ ]*)(?=\S)', re.MULTILINE) def _min_indent(self, s): "Return the minimum indentation of any non-blank line in `s`" indents = [len(indent) for indent in self._INDENT_RE.findall(s)] if len(indents) > 0: return min(indents) else: return 0 def _check_prompt_blank(self, lines, indent, name, lineno): """ Given the lines of a source string (including prompts and leading indentation), check to make sure that every prompt is followed by a space character. If any line is not followed by a space character, then raise ValueError. """ for i, line in enumerate(lines): if len(line) >= indent+4 and line[indent+3] != ' ': raise ValueError('line %r of the docstring for %s ' 'lacks blank after %s: %r' % (lineno+i+1, name, line[indent:indent+3], line)) def _check_prefix(self, lines, prefix, name, lineno): """ Check that every line in the given list starts with the given prefix; if any line does not, then raise a ValueError. """ for i, line in enumerate(lines): if line and not line.startswith(prefix): raise ValueError('line %r of the docstring for %s has ' 'inconsistent leading whitespace: %r' % (lineno+i+1, name, line)) ###################################################################### ## 4. DocTest Finder ###################################################################### class DocTestFinder: """ A class used to extract the DocTests that are relevant to a given object, from its docstring and the docstrings of its contained objects. Doctests can currently be extracted from the following object types: modules, functions, classes, methods, staticmethods, classmethods, and properties. """ def __init__(self, verbose=False, parser=DocTestParser(), recurse=True, _namefilter=None, exclude_empty=True): """ Create a new doctest finder. The optional argument `parser` specifies a class or function that should be used to create new DocTest objects (or objects that implement the same interface as DocTest). The signature for this factory function should match the signature of the DocTest constructor. If the optional argument `recurse` is false, then `find` will only examine the given object, and not any contained objects. If the optional argument `exclude_empty` is false, then `find` will include tests for objects with empty docstrings. """ self._parser = parser self._verbose = verbose self._recurse = recurse self._exclude_empty = exclude_empty # _namefilter is undocumented, and exists only for temporary backward- # compatibility support of testmod's deprecated isprivate mess. self._namefilter = _namefilter def find(self, obj, name=None, module=None, globs=None, extraglobs=None): """ Return a list of the DocTests that are defined by the given object's docstring, or by any of its contained objects' docstrings. The optional parameter `module` is the module that contains the given object. If the module is not specified or is None, then the test finder will attempt to automatically determine the correct module. The object's module is used: - As a default namespace, if `globs` is not specified. - To prevent the DocTestFinder from extracting DocTests from objects that are imported from other modules. - To find the name of the file containing the object. - To help find the line number of the object within its file. Contained objects whose module does not match `module` are ignored. If `module` is False, no attempt to find the module will be made. This is obscure, of use mostly in tests: if `module` is False, or is None but cannot be found automatically, then all objects are considered to belong to the (non-existent) module, so all contained objects will (recursively) be searched for doctests. The globals for each DocTest is formed by combining `globs` and `extraglobs` (bindings in `extraglobs` override bindings in `globs`). A new copy of the globals dictionary is created for each DocTest. If `globs` is not specified, then it defaults to the module's `__dict__`, if specified, or {} otherwise. If `extraglobs` is not specified, then it defaults to {}. """ # If name was not specified, then extract it from the object. if name is None: name = getattr(obj, '__name__', None) if name is None: raise ValueError("DocTestFinder.find: name must be given " "when obj.__name__ doesn't exist: %r" % (type(obj),)) # Find the module that contains the given object (if obj is # a module, then module=obj.). Note: this may fail, in which # case module will be None. if module is False: module = None elif module is None: module = inspect.getmodule(obj) # Read the module's source code. This is used by # DocTestFinder._find_lineno to find the line number for a # given object's docstring. try: file = inspect.getsourcefile(obj) or inspect.getfile(obj) source_lines = linecache.getlines(file) if not source_lines: source_lines = None except TypeError: source_lines = None # Initialize globals, and merge in extraglobs. if globs is None: if module is None: globs = {} else: globs = module.__dict__.copy() else: globs = globs.copy() if extraglobs is not None: globs.update(extraglobs) # Recursively expore `obj`, extracting DocTests. tests = [] self._find(tests, obj, name, module, source_lines, globs, {}) return tests def _filter(self, obj, prefix, base): """ Return true if the given object should not be examined. """ return (self._namefilter is not None and self._namefilter(prefix, base)) def _from_module(self, module, object): """ Return true if the given object is defined in the given module. """ if module is None: return True elif inspect.isfunction(object): return module.__dict__ is object.func_globals elif inspect.isclass(object): return module.__name__ == object.__module__ elif inspect.getmodule(object) is not None: return module is inspect.getmodule(object) elif hasattr(object, '__module__'): return module.__name__ == object.__module__ elif isinstance(object, property): return True # [XX] no way not be sure. else: raise ValueError("object must be a class or function") def _find(self, tests, obj, name, module, source_lines, globs, seen): """ Find tests for the given object and any contained objects, and add them to `tests`. """ if self._verbose: print 'Finding tests in %s' % name # If we've already processed this object, then ignore it. if id(obj) in seen: return seen[id(obj)] = 1 # Find a test for this object, and add it to the list of tests. test = self._get_test(obj, name, module, globs, source_lines) if test is not None: tests.append(test) # Look for tests in a module's contained objects. if inspect.ismodule(obj) and self._recurse: for valname, val in obj.__dict__.items(): # Check if this contained object should be ignored. if self._filter(val, name, valname): continue valname = '%s.%s' % (name, valname) # Recurse to functions & classes. if ((inspect.isfunction(val) or inspect.isclass(val)) and self._from_module(module, val)): self._find(tests, val, valname, module, source_lines, globs, seen) # Look for tests in a module's __test__ dictionary. if inspect.ismodule(obj) and self._recurse: for valname, val in getattr(obj, '__test__', {}).items(): if not isinstance(valname, basestring): raise ValueError("DocTestFinder.find: __test__ keys " "must be strings: %r" % (type(valname),)) if not (inspect.isfunction(val) or inspect.isclass(val) or inspect.ismethod(val) or inspect.ismodule(val) or isinstance(val, basestring)): raise ValueError("DocTestFinder.find: __test__ values " "must be strings, functions, methods, " "classes, or modules: %r" % (type(val),)) valname = '%s.__test__.%s' % (name, valname) self._find(tests, val, valname, module, source_lines, globs, seen) # Look for tests in a class's contained objects. if inspect.isclass(obj) and self._recurse: for valname, val in obj.__dict__.items(): # Check if this contained object should be ignored. if self._filter(val, name, valname): continue # Special handling for staticmethod/classmethod. if isinstance(val, staticmethod): val = getattr(obj, valname) if isinstance(val, classmethod): val = getattr(obj, valname).im_func # Recurse to methods, properties, and nested classes. if ((inspect.isfunction(val) or inspect.isclass(val) or isinstance(val, property)) and self._from_module(module, val)): valname = '%s.%s' % (name, valname) self._find(tests, val, valname, module, source_lines, globs, seen) def _get_test(self, obj, name, module, globs, source_lines): """ Return a DocTest for the given object, if it defines a docstring; otherwise, return None. """ # Extract the object's docstring. If it doesn't have one, # then return None (no test for this object). if isinstance(obj, basestring): docstring = obj else: try: if obj.__doc__ is None: docstring = '' else: docstring = obj.__doc__ if not isinstance(docstring, basestring): docstring = str(docstring) except (TypeError, AttributeError): docstring = '' # Find the docstring's location in the file. lineno = self._find_lineno(obj, source_lines) # Don't bother if the docstring is empty. if self._exclude_empty and not docstring: return None # Return a DocTest for this object. if module is None: filename = None else: filename = getattr(module, '__file__', module.__name__) if filename[-4:] in (".pyc", ".pyo"): filename = filename[:-1] return self._parser.get_doctest(docstring, globs, name, filename, lineno) def _find_lineno(self, obj, source_lines): """ Return a line number of the given object's docstring. Note: this method assumes that the object has a docstring. """ lineno = None # Find the line number for modules. if inspect.ismodule(obj): lineno = 0 # Find the line number for classes. # Note: this could be fooled if a class is defined multiple # times in a single file. if inspect.isclass(obj): if source_lines is None: return None pat = re.compile(r'^\s*class\s*%s\b' % getattr(obj, '__name__', '-')) for i, line in enumerate(source_lines): if pat.match(line): lineno = i break # Find the line number for functions & methods. if inspect.ismethod(obj): obj = obj.im_func if inspect.isfunction(obj): obj = obj.func_code if inspect.istraceback(obj): obj = obj.tb_frame if inspect.isframe(obj): obj = obj.f_code if inspect.iscode(obj): lineno = getattr(obj, 'co_firstlineno', None)-1 # Find the line number where the docstring starts. Assume # that it's the first line that begins with a quote mark. # Note: this could be fooled by a multiline function # signature, where a continuation line begins with a quote # mark. if lineno is not None: if source_lines is None: return lineno+1 pat = re.compile('(^|.*:)\s*\w*("|\')') for lineno in range(lineno, len(source_lines)): if pat.match(source_lines[lineno]): return lineno # We couldn't find the line number. return None ###################################################################### ## 5. DocTest Runner ###################################################################### class DocTestRunner: """ A class used to run DocTest test cases, and accumulate statistics. The `run` method is used to process a single DocTest case. It returns a tuple `(f, t)`, where `t` is the number of test cases tried, and `f` is the number of test cases that failed. >>> tests = DocTestFinder().find(_TestClass) >>> runner = DocTestRunner(verbose=False) >>> for test in tests: ... print runner.run(test) (0, 2) (0, 1) (0, 2) (0, 2) The `summarize` method prints a summary of all the test cases that have been run by the runner, and returns an aggregated `(f, t)` tuple: >>> runner.summarize(verbose=1) 4 items passed all tests: 2 tests in _TestClass 2 tests in _TestClass.__init__ 2 tests in _TestClass.get 1 tests in _TestClass.square 7 tests in 4 items. 7 passed and 0 failed. Test passed. (0, 7) The aggregated number of tried examples and failed examples is also available via the `tries` and `failures` attributes: >>> runner.tries 7 >>> runner.failures 0 The comparison between expected outputs and actual outputs is done by an `OutputChecker`. This comparison may be customized with a number of option flags; see the documentation for `testmod` for more information. If the option flags are insufficient, then the comparison may also be customized by passing a subclass of `OutputChecker` to the constructor. The test runner's display output can be controlled in two ways. First, an output function (`out) can be passed to `TestRunner.run`; this function will be called with strings that should be displayed. It defaults to `sys.stdout.write`. If capturing the output is not sufficient, then the display output can be also customized by subclassing DocTestRunner, and overriding the methods `report_start`, `report_success`, `report_unexpected_exception`, and `report_failure`. """ # This divider string is used to separate failure messages, and to # separate sections of the summary. DIVIDER = "*" * 70 def __init__(self, checker=None, verbose=None, optionflags=0): """ Create a new test runner. Optional keyword arg `checker` is the `OutputChecker` that should be used to compare the expected outputs and actual outputs of doctest examples. Optional keyword arg 'verbose' prints lots of stuff if true, only failures if false; by default, it's true iff '-v' is in sys.argv. Optional argument `optionflags` can be used to control how the test runner compares expected output to actual output, and how it displays failures. See the documentation for `testmod` for more information. """ self._checker = checker or OutputChecker() if verbose is None: verbose = '-v' in sys.argv self._verbose = verbose self.optionflags = optionflags self.original_optionflags = optionflags # Keep track of the examples we've run. self.tries = 0 self.failures = 0 self._name2ft = {} # Create a fake output target for capturing doctest output. self._fakeout = _SpoofOut() #///////////////////////////////////////////////////////////////// # Reporting methods #///////////////////////////////////////////////////////////////// def report_start(self, out, test, example): """ Report that the test runner is about to process the given example. (Only displays a message if verbose=True) """ if self._verbose: if example.want: out('Trying:\n' + _indent(example.source) + 'Expecting:\n' + _indent(example.want)) else: out('Trying:\n' + _indent(example.source) + 'Expecting nothing\n') def report_success(self, out, test, example, got): """ Report that the given example ran successfully. (Only displays a message if verbose=True) """ if self._verbose: out("ok\n") def report_failure(self, out, test, example, got): """ Report that the given example failed. """ out(self._failure_header(test, example) + self._checker.output_difference(example, got, self.optionflags)) def report_unexpected_exception(self, out, test, example, exc_info): """ Report that the given example raised an unexpected exception. """ out(self._failure_header(test, example) + 'Exception raised:\n' + _indent(_exception_traceback(exc_info))) def _failure_header(self, test, example): out = [self.DIVIDER] if test.filename: if test.lineno is not None and example.lineno is not None: lineno = test.lineno + example.lineno + 1 else: lineno = '?' out.append('File "%s", line %s, in %s' % (test.filename, lineno, test.name)) else: out.append('Line %s, in %s' % (example.lineno+1, test.name)) out.append('Failed example:') source = example.source out.append(_indent(source)) return '\n'.join(out) #///////////////////////////////////////////////////////////////// # DocTest Running #///////////////////////////////////////////////////////////////// def __run(self, test, compileflags, out): """ Run the examples in `test`. Write the outcome of each example with one of the `DocTestRunner.report_*` methods, using the writer function `out`. `compileflags` is the set of compiler flags that should be used to execute examples. Return a tuple `(f, t)`, where `t` is the number of examples tried, and `f` is the number of examples that failed. The examples are run in the namespace `test.globs`. """ # Keep track of the number of failures and tries. failures = tries = 0 # Save the option flags (since option directives can be used # to modify them). original_optionflags = self.optionflags SUCCESS, FAILURE, BOOM = range(3) # `outcome` state check = self._checker.check_output # Process each example. for examplenum, example in enumerate(test.examples): # If REPORT_ONLY_FIRST_FAILURE is set, then supress # reporting after the first failure. quiet = (self.optionflags & REPORT_ONLY_FIRST_FAILURE and failures > 0) # Merge in the example's options. self.optionflags = original_optionflags if example.options: for (optionflag, val) in example.options.items(): if val: self.optionflags |= optionflag else: self.optionflags &= ~optionflag # Record that we started this example. tries += 1 if not quiet: self.report_start(out, test, example) # Use a special filename for compile(), so we can retrieve # the source code during interactive debugging (see # __patched_linecache_getlines). filename = '' % (test.name, examplenum) # Run the example in the given context (globs), and record # any exception that gets raised. (But don't intercept # keyboard interrupts.) try: # Don't blink! This is where the user's code gets run. exec compile(example.source, filename, "single", compileflags, 1) in test.globs self.debugger.set_continue() # ==== Example Finished ==== exception = None except KeyboardInterrupt: raise except: exception = sys.exc_info() self.debugger.set_continue() # ==== Example Finished ==== got = self._fakeout.getvalue() # the actual output self._fakeout.truncate(0) outcome = FAILURE # guilty until proved innocent or insane # If the example executed without raising any exceptions, # verify its output. if exception is None: if check(example.want, got, self.optionflags): outcome = SUCCESS # The example raised an exception: check if it was expected. else: exc_info = sys.exc_info() exc_msg = traceback.format_exception_only(*exc_info[:2])[-1] if not quiet: got += _exception_traceback(exc_info) # If `example.exc_msg` is None, then we weren't expecting # an exception. if example.exc_msg is None: outcome = BOOM # We expected an exception: see whether it matches. elif check(example.exc_msg, exc_msg, self.optionflags): outcome = SUCCESS # Another chance if they didn't care about the detail. elif self.optionflags & IGNORE_EXCEPTION_DETAIL: m1 = re.match(r'[^:]*:', example.exc_msg) m2 = re.match(r'[^:]*:', exc_msg) if m1 and m2 and check(m1.group(0), m2.group(0), self.optionflags): outcome = SUCCESS # Report the outcome. if outcome is SUCCESS: if not quiet: self.report_success(out, test, example, got) elif outcome is FAILURE: if not quiet: self.report_failure(out, test, example, got) failures += 1 elif outcome is BOOM: if not quiet: self.report_unexpected_exception(out, test, example, exc_info) failures += 1 else: assert False, ("unknown outcome", outcome) # Restore the option flags (in case they were modified) self.optionflags = original_optionflags # Record and return the number of failures and tries. self.__record_outcome(test, failures, tries) return failures, tries def __record_outcome(self, test, f, t): """ Record the fact that the given DocTest (`test`) generated `f` failures out of `t` tried examples. """ f2, t2 = self._name2ft.get(test.name, (0,0)) self._name2ft[test.name] = (f+f2, t+t2) self.failures += f self.tries += t __LINECACHE_FILENAME_RE = re.compile(r'[\w\.]+)' r'\[(?P\d+)\]>$') def __patched_linecache_getlines(self, filename): m = self.__LINECACHE_FILENAME_RE.match(filename) if m and m.group('name') == self.test.name: example = self.test.examples[int(m.group('examplenum'))] return example.source.splitlines(True) else: return self.save_linecache_getlines(filename) def run(self, test, compileflags=None, out=None, clear_globs=True): """ Run the examples in `test`, and display the results using the writer function `out`. The examples are run in the namespace `test.globs`. If `clear_globs` is true (the default), then this namespace will be cleared after the test runs, to help with garbage collection. If you would like to examine the namespace after the test completes, then use `clear_globs=False`. `compileflags` gives the set of flags that should be used by the Python compiler when running the examples. If not specified, then it will default to the set of future-import flags that apply to `globs`. The output of each example is checked using `DocTestRunner.check_output`, and the results are formatted by the `DocTestRunner.report_*` methods. """ self.test = test if compileflags is None: compileflags = _extract_future_flags(test.globs) save_stdout = sys.stdout if out is None: out = save_stdout.write sys.stdout = self._fakeout # Patch pdb.set_trace to restore sys.stdout during interactive # debugging (so it's not still redirected to self._fakeout). # Note that the interactive output will go to *our* # save_stdout, even if that's not the real sys.stdout; this # allows us to write test cases for the set_trace behavior. save_set_trace = pdb.set_trace self.debugger = _OutputRedirectingPdb(save_stdout) self.debugger.reset() pdb.set_trace = self.debugger.set_trace # Patch linecache.getlines, so we can see the example's source # when we're inside the debugger. self.save_linecache_getlines = linecache.getlines linecache.getlines = self.__patched_linecache_getlines try: return self.__run(test, compileflags, out) finally: sys.stdout = save_stdout pdb.set_trace = save_set_trace linecache.getlines = self.save_linecache_getlines if clear_globs: test.globs.clear() #///////////////////////////////////////////////////////////////// # Summarization #///////////////////////////////////////////////////////////////// def summarize(self, verbose=None): """ Print a summary of all the test cases that have been run by this DocTestRunner, and return a tuple `(f, t)`, where `f` is the total number of failed examples, and `t` is the total number of tried examples. The optional `verbose` argument controls how detailed the summary is. If the verbosity is not specified, then the DocTestRunner's verbosity is used. """ if verbose is None: verbose = self._verbose notests = [] passed = [] failed = [] totalt = totalf = 0 for x in self._name2ft.items(): name, (f, t) = x assert f <= t totalt += t totalf += f if t == 0: notests.append(name) elif f == 0: passed.append( (name, t) ) else: failed.append(x) if verbose: if notests: print len(notests), "items had no tests:" notests.sort() for thing in notests: print " ", thing if passed: print len(passed), "items passed all tests:" passed.sort() for thing, count in passed: print " %3d tests in %s" % (count, thing) if failed: print self.DIVIDER print len(failed), "items had failures:" failed.sort() for thing, (f, t) in failed: print " %3d of %3d in %s" % (f, t, thing) if verbose: print totalt, "tests in", len(self._name2ft), "items." print totalt - totalf, "passed and", totalf, "failed." if totalf: print "***Test Failed***", totalf, "failures." elif verbose: print "Test passed." return totalf, totalt #///////////////////////////////////////////////////////////////// # Backward compatibility cruft to maintain doctest.master. #///////////////////////////////////////////////////////////////// def merge(self, other): d = self._name2ft for name, (f, t) in other._name2ft.items(): if name in d: print "*** DocTestRunner.merge: '" + name + "' in both" \ " testers; summing outcomes." f2, t2 = d[name] f = f + f2 t = t + t2 d[name] = f, t class OutputChecker: """ A class used to check the whether the actual output from a doctest example matches the expected output. `OutputChecker` defines two methods: `check_output`, which compares a given pair of outputs, and returns true if they match; and `output_difference`, which returns a string describing the differences between two outputs. """ def check_output(self, want, got, optionflags): """ Return True iff the actual output from an example (`got`) matches the expected output (`want`). These strings are always considered to match if they are identical; but depending on what option flags the test runner is using, several non-exact match types are also possible. See the documentation for `TestRunner` for more information about option flags. """ # Handle the common case first, for efficiency: # if they're string-identical, always return true. if got == want: return True # The values True and False replaced 1 and 0 as the return # value for boolean comparisons in Python 2.3. if not (optionflags & DONT_ACCEPT_TRUE_FOR_1): if (got,want) == ("True\n", "1\n"): return True if (got,want) == ("False\n", "0\n"): return True # can be used as a special sequence to signify a # blank line, unless the DONT_ACCEPT_BLANKLINE flag is used. if not (optionflags & DONT_ACCEPT_BLANKLINE): # Replace in want with a blank line. want = re.sub('(?m)^%s\s*?$' % re.escape(BLANKLINE_MARKER), '', want) # If a line in got contains only spaces, then remove the # spaces. got = re.sub('(?m)^\s*?$', '', got) if got == want: return True # This flag causes doctest to ignore any differences in the # contents of whitespace strings. Note that this can be used # in conjunction with the ELLIPSIS flag. if optionflags & NORMALIZE_WHITESPACE: got = ' '.join(got.split()) want = ' '.join(want.split()) if got == want: return True # The ELLIPSIS flag says to let the sequence "..." in `want` # match any substring in `got`. if optionflags & ELLIPSIS: if _ellipsis_match(want, got): return True # We didn't find any match; return false. return False # Should we do a fancy diff? def _do_a_fancy_diff(self, want, got, optionflags): # Not unless they asked for a fancy diff. if not optionflags & (REPORT_UDIFF | REPORT_CDIFF | REPORT_NDIFF): return False # If expected output uses ellipsis, a meaningful fancy diff is # too hard ... or maybe not. In two real-life failures Tim saw, # a diff was a major help anyway, so this is commented out. # [todo] _ellipsis_match() knows which pieces do and don't match, # and could be the basis for a kick-ass diff in this case. ##if optionflags & ELLIPSIS and ELLIPSIS_MARKER in want: ## return False # ndiff does intraline difference marking, so can be useful even # for 1-line differences. if optionflags & REPORT_NDIFF: return True # The other diff types need at least a few lines to be helpful. return want.count('\n') > 2 and got.count('\n') > 2 def output_difference(self, example, got, optionflags): """ Return a string describing the differences between the expected output for a given example (`example`) and the actual output (`got`). `optionflags` is the set of option flags used to compare `want` and `got`. """ want = example.want # If s are being used, then replace blank lines # with in the actual output string. if not (optionflags & DONT_ACCEPT_BLANKLINE): got = re.sub('(?m)^[ ]*(?=\n)', BLANKLINE_MARKER, got) # Check if we should use diff. if self._do_a_fancy_diff(want, got, optionflags): # Split want & got into lines. want_lines = want.splitlines(True) # True == keep line ends got_lines = got.splitlines(True) # Use difflib to find their differences. if optionflags & REPORT_UDIFF: diff = difflib.unified_diff(want_lines, got_lines, n=2) diff = list(diff)[2:] # strip the diff header kind = 'unified diff with -expected +actual' elif optionflags & REPORT_CDIFF: diff = difflib.context_diff(want_lines, got_lines, n=2) diff = list(diff)[2:] # strip the diff header kind = 'context diff with expected followed by actual' elif optionflags & REPORT_NDIFF: engine = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) diff = list(engine.compare(want_lines, got_lines)) kind = 'ndiff with -expected +actual' else: assert 0, 'Bad diff option' # Remove trailing whitespace on diff output. diff = [line.rstrip() + '\n' for line in diff] return 'Differences (%s):\n' % kind + _indent(''.join(diff)) # If we're not using diff, then simply list the expected # output followed by the actual output. if want and got: return 'Expected:\n%sGot:\n%s' % (_indent(want), _indent(got)) elif want: return 'Expected:\n%sGot nothing\n' % _indent(want) elif got: return 'Expected nothing\nGot:\n%s' % _indent(got) else: return 'Expected nothing\nGot nothing\n' class DocTestFailure(Exception): """A DocTest example has failed in debugging mode. The exception instance has variables: - test: the DocTest object being run - excample: the Example object that failed - got: the actual output """ def __init__(self, test, example, got): self.test = test self.example = example self.got = got def __str__(self): return str(self.test) class UnexpectedException(Exception): """A DocTest example has encountered an unexpected exception The exception instance has variables: - test: the DocTest object being run - excample: the Example object that failed - exc_info: the exception info """ def __init__(self, test, example, exc_info): self.test = test self.example = example self.exc_info = exc_info def __str__(self): return str(self.test) class DebugRunner(DocTestRunner): r"""Run doc tests but raise an exception as soon as there is a failure. If an unexpected exception occurs, an UnexpectedException is raised. It contains the test, the example, and the original exception: >>> runner = DebugRunner(verbose=False) >>> test = DocTestParser().get_doctest('>>> raise KeyError\n42', ... {}, 'foo', 'foo.py', 0) >>> try: ... runner.run(test) ... except UnexpectedException, failure: ... pass >>> failure.test is test True >>> failure.example.want '42\n' >>> exc_info = failure.exc_info >>> raise exc_info[0], exc_info[1], exc_info[2] Traceback (most recent call last): ... KeyError We wrap the original exception to give the calling application access to the test and example information. If the output doesn't match, then a DocTestFailure is raised: >>> test = DocTestParser().get_doctest(''' ... >>> x = 1 ... >>> x ... 2 ... ''', {}, 'foo', 'foo.py', 0) >>> try: ... runner.run(test) ... except DocTestFailure, failure: ... pass DocTestFailure objects provide access to the test: >>> failure.test is test True As well as to the example: >>> failure.example.want '2\n' and the actual output: >>> failure.got '1\n' If a failure or error occurs, the globals are left intact: >>> del test.globs['__builtins__'] >>> test.globs {'x': 1} >>> test = DocTestParser().get_doctest(''' ... >>> x = 2 ... >>> raise KeyError ... ''', {}, 'foo', 'foo.py', 0) >>> runner.run(test) Traceback (most recent call last): ... UnexpectedException: >>> del test.globs['__builtins__'] >>> test.globs {'x': 2} But the globals are cleared if there is no error: >>> test = DocTestParser().get_doctest(''' ... >>> x = 2 ... ''', {}, 'foo', 'foo.py', 0) >>> runner.run(test) (0, 1) >>> test.globs {} """ def run(self, test, compileflags=None, out=None, clear_globs=True): r = DocTestRunner.run(self, test, compileflags, out, False) if clear_globs: test.globs.clear() return r def report_unexpected_exception(self, out, test, example, exc_info): raise UnexpectedException(test, example, exc_info) def report_failure(self, out, test, example, got): raise DocTestFailure(test, example, got) ###################################################################### ## 6. Test Functions ###################################################################### # These should be backwards compatible. # For backward compatibility, a global instance of a DocTestRunner # class, updated by testmod. master = None def testmod(m=None, name=None, globs=None, verbose=None, isprivate=None, report=True, optionflags=0, extraglobs=None, raise_on_error=False, exclude_empty=False): """m=None, name=None, globs=None, verbose=None, isprivate=None, report=True, optionflags=0, extraglobs=None, raise_on_error=False, exclude_empty=False Test examples in docstrings in functions and classes reachable from module m (or the current module if m is not supplied), starting with m.__doc__. Unless isprivate is specified, private names are not skipped. Also test examples reachable from dict m.__test__ if it exists and is not None. m.__test__ maps names to functions, classes and strings; function and class docstrings are tested even if the name is private; strings are tested directly, as if they were docstrings. Return (#failures, #tests). See doctest.__doc__ for an overview. Optional keyword arg "name" gives the name of the module; by default use m.__name__. Optional keyword arg "globs" gives a dict to be used as the globals when executing examples; by default, use m.__dict__. A copy of this dict is actually used for each docstring, so that each docstring's examples start with a clean slate. Optional keyword arg "extraglobs" gives a dictionary that should be merged into the globals that are used to execute examples. By default, no extra globals are used. This is new in 2.4. Optional keyword arg "verbose" prints lots of stuff if true, prints only failures if false; by default, it's true iff "-v" is in sys.argv. Optional keyword arg "report" prints a summary at the end when true, else prints nothing at the end. In verbose mode, the summary is detailed, else very brief (in fact, empty if all tests passed). Optional keyword arg "optionflags" or's together module constants, and defaults to 0. This is new in 2.3. Possible values (see the docs for details): DONT_ACCEPT_TRUE_FOR_1 DONT_ACCEPT_BLANKLINE NORMALIZE_WHITESPACE ELLIPSIS IGNORE_EXCEPTION_DETAIL REPORT_UDIFF REPORT_CDIFF REPORT_NDIFF REPORT_ONLY_FIRST_FAILURE Optional keyword arg "raise_on_error" raises an exception on the first unexpected exception or failure. This allows failures to be post-mortem debugged. Deprecated in Python 2.4: Optional keyword arg "isprivate" specifies a function used to determine whether a name is private. The default function is treat all functions as public. Optionally, "isprivate" can be set to doctest.is_private to skip over functions marked as private using the underscore naming convention; see its docs for details. Advanced tomfoolery: testmod runs methods of a local instance of class doctest.Tester, then merges the results into (or creates) global Tester instance doctest.master. Methods of doctest.master can be called directly too, if you want to do something unusual. Passing report=0 to testmod is especially useful then, to delay displaying a summary. Invoke doctest.master.summarize(verbose) when you're done fiddling. """ global master if isprivate is not None: warnings.warn("the isprivate argument is deprecated; " "examine DocTestFinder.find() lists instead", DeprecationWarning) # If no module was given, then use __main__. if m is None: # DWA - m will still be None if this wasn't invoked from the command # line, in which case the following TypeError is about as good an error # as we should expect m = sys.modules.get('__main__') # Check that we were actually given a module. if not inspect.ismodule(m): raise TypeError("testmod: module required; %r" % (m,)) # If no name was given, then use the module's name. if name is None: name = m.__name__ # Find, parse, and run all tests in the given module. finder = DocTestFinder(_namefilter=isprivate, exclude_empty=exclude_empty) if raise_on_error: runner = DebugRunner(verbose=verbose, optionflags=optionflags) else: runner = DocTestRunner(verbose=verbose, optionflags=optionflags) for test in finder.find(m, name, globs=globs, extraglobs=extraglobs): runner.run(test) if report: runner.summarize() if master is None: master = runner else: master.merge(runner) return runner.failures, runner.tries def testfile(filename, module_relative=True, name=None, package=None, globs=None, verbose=None, report=True, optionflags=0, extraglobs=None, raise_on_error=False, parser=DocTestParser()): """ Test examples in the given file. Return (#failures, #tests). Optional keyword arg "module_relative" specifies how filenames should be interpreted: - If "module_relative" is True (the default), then "filename" specifies a module-relative path. By default, this path is relative to the calling module's directory; but if the "package" argument is specified, then it is relative to that package. To ensure os-independence, "filename" should use "/" characters to separate path segments, and should not be an absolute path (i.e., it may not begin with "/"). - If "module_relative" is False, then "filename" specifies an os-specific path. The path may be absolute or relative (to the current working directory). Optional keyword arg "name" gives the name of the test; by default use the file's basename. Optional keyword argument "package" is a Python package or the name of a Python package whose directory should be used as the base directory for a module relative filename. If no package is specified, then the calling module's directory is used as the base directory for module relative filenames. It is an error to specify "package" if "module_relative" is False. Optional keyword arg "globs" gives a dict to be used as the globals when executing examples; by default, use {}. A copy of this dict is actually used for each docstring, so that each docstring's examples start with a clean slate. Optional keyword arg "extraglobs" gives a dictionary that should be merged into the globals that are used to execute examples. By default, no extra globals are used. Optional keyword arg "verbose" prints lots of stuff if true, prints only failures if false; by default, it's true iff "-v" is in sys.argv. Optional keyword arg "report" prints a summary at the end when true, else prints nothing at the end. In verbose mode, the summary is detailed, else very brief (in fact, empty if all tests passed). Optional keyword arg "optionflags" or's together module constants, and defaults to 0. Possible values (see the docs for details): DONT_ACCEPT_TRUE_FOR_1 DONT_ACCEPT_BLANKLINE NORMALIZE_WHITESPACE ELLIPSIS IGNORE_EXCEPTION_DETAIL REPORT_UDIFF REPORT_CDIFF REPORT_NDIFF REPORT_ONLY_FIRST_FAILURE Optional keyword arg "raise_on_error" raises an exception on the first unexpected exception or failure. This allows failures to be post-mortem debugged. Optional keyword arg "parser" specifies a DocTestParser (or subclass) that should be used to extract tests from the files. Advanced tomfoolery: testmod runs methods of a local instance of class doctest.Tester, then merges the results into (or creates) global Tester instance doctest.master. Methods of doctest.master can be called directly too, if you want to do something unusual. Passing report=0 to testmod is especially useful then, to delay displaying a summary. Invoke doctest.master.summarize(verbose) when you're done fiddling. """ global master if package and not module_relative: raise ValueError("Package may only be specified for module-" "relative paths.") # Relativize the path if module_relative: package = _normalize_module(package) filename = _module_relative_path(package, filename) # If no name was given, then use the file's name. if name is None: name = os.path.basename(filename) # Assemble the globals. if globs is None: globs = {} else: globs = globs.copy() if extraglobs is not None: globs.update(extraglobs) if raise_on_error: runner = DebugRunner(verbose=verbose, optionflags=optionflags) else: runner = DocTestRunner(verbose=verbose, optionflags=optionflags) # Read the file, convert it to a test, and run it. s = open(filename).read() test = parser.get_doctest(s, globs, name, filename, 0) runner.run(test) if report: runner.summarize() if master is None: master = runner else: master.merge(runner) return runner.failures, runner.tries def run_docstring_examples(f, globs, verbose=False, name="NoName", compileflags=None, optionflags=0): """ Test examples in the given object's docstring (`f`), using `globs` as globals. Optional argument `name` is used in failure messages. If the optional argument `verbose` is true, then generate output even if there are no failures. `compileflags` gives the set of flags that should be used by the Python compiler when running the examples. If not specified, then it will default to the set of future-import flags that apply to `globs`. Optional keyword arg `optionflags` specifies options for the testing and output. See the documentation for `testmod` for more information. """ # Find, parse, and run all tests in the given module. finder = DocTestFinder(verbose=verbose, recurse=False) runner = DocTestRunner(verbose=verbose, optionflags=optionflags) for test in finder.find(f, name, globs=globs): runner.run(test, compileflags=compileflags) ###################################################################### ## 7. Tester ###################################################################### # This is provided only for backwards compatibility. It's not # actually used in any way. class Tester: def __init__(self, mod=None, globs=None, verbose=None, isprivate=None, optionflags=0): warnings.warn("class Tester is deprecated; " "use class doctest.DocTestRunner instead", DeprecationWarning, stacklevel=2) if mod is None and globs is None: raise TypeError("Tester.__init__: must specify mod or globs") if mod is not None and not inspect.ismodule(mod): raise TypeError("Tester.__init__: mod must be a module; %r" % (mod,)) if globs is None: globs = mod.__dict__ self.globs = globs self.verbose = verbose self.isprivate = isprivate self.optionflags = optionflags self.testfinder = DocTestFinder(_namefilter=isprivate) self.testrunner = DocTestRunner(verbose=verbose, optionflags=optionflags) def runstring(self, s, name): test = DocTestParser().get_doctest(s, self.globs, name, None, None) if self.verbose: print "Running string", name (f,t) = self.testrunner.run(test) if self.verbose: print f, "of", t, "examples failed in string", name return (f,t) def rundoc(self, object, name=None, module=None): f = t = 0 tests = self.testfinder.find(object, name, module=module, globs=self.globs) for test in tests: (f2, t2) = self.testrunner.run(test) (f,t) = (f+f2, t+t2) return (f,t) def rundict(self, d, name, module=None): import new m = new.module(name) m.__dict__.update(d) if module is None: module = False return self.rundoc(m, name, module) def run__test__(self, d, name): import new m = new.module(name) m.__test__ = d return self.rundoc(m, name) def summarize(self, verbose=None): return self.testrunner.summarize(verbose) def merge(self, other): self.testrunner.merge(other.testrunner) ###################################################################### ## 8. Unittest Support ###################################################################### _unittest_reportflags = 0 def set_unittest_reportflags(flags): """Sets the unittest option flags. The old flag is returned so that a runner could restore the old value if it wished to: >>> old = _unittest_reportflags >>> set_unittest_reportflags(REPORT_NDIFF | ... REPORT_ONLY_FIRST_FAILURE) == old True >>> import doctest >>> doctest._unittest_reportflags == (REPORT_NDIFF | ... REPORT_ONLY_FIRST_FAILURE) True Only reporting flags can be set: >>> set_unittest_reportflags(ELLIPSIS) Traceback (most recent call last): ... ValueError: ('Only reporting flags allowed', 8) >>> set_unittest_reportflags(old) == (REPORT_NDIFF | ... REPORT_ONLY_FIRST_FAILURE) True """ global _unittest_reportflags if (flags & REPORTING_FLAGS) != flags: raise ValueError("Only reporting flags allowed", flags) old = _unittest_reportflags _unittest_reportflags = flags return old class DocTestCase(unittest.TestCase): def __init__(self, test, optionflags=0, setUp=None, tearDown=None, checker=None): unittest.TestCase.__init__(self) self._dt_optionflags = optionflags self._dt_checker = checker self._dt_test = test self._dt_setUp = setUp self._dt_tearDown = tearDown def setUp(self): test = self._dt_test if self._dt_setUp is not None: self._dt_setUp(test) def tearDown(self): test = self._dt_test if self._dt_tearDown is not None: self._dt_tearDown(test) test.globs.clear() def runTest(self): test = self._dt_test old = sys.stdout new = StringIO() optionflags = self._dt_optionflags if not (optionflags & REPORTING_FLAGS): # The option flags don't include any reporting flags, # so add the default reporting flags optionflags |= _unittest_reportflags runner = DocTestRunner(optionflags=optionflags, checker=self._dt_checker, verbose=False) try: runner.DIVIDER = "-"*70 failures, tries = runner.run( test, out=new.write, clear_globs=False) finally: sys.stdout = old if failures: raise self.failureException(self.format_failure(new.getvalue())) def format_failure(self, err): test = self._dt_test if test.lineno is None: lineno = 'unknown line number' else: lineno = '%s' % test.lineno lname = '.'.join(test.name.split('.')[-1:]) return ('Failed doctest test for %s\n' ' File "%s", line %s, in %s\n\n%s' % (test.name, test.filename, lineno, lname, err) ) def debug(self): r"""Run the test case without results and without catching exceptions The unit test framework includes a debug method on test cases and test suites to support post-mortem debugging. The test code is run in such a way that errors are not caught. This way a caller can catch the errors and initiate post-mortem debugging. The DocTestCase provides a debug method that raises UnexpectedException errors if there is an unexepcted exception: >>> test = DocTestParser().get_doctest('>>> raise KeyError\n42', ... {}, 'foo', 'foo.py', 0) >>> case = DocTestCase(test) >>> try: ... case.debug() ... except UnexpectedException, failure: ... pass The UnexpectedException contains the test, the example, and the original exception: >>> failure.test is test True >>> failure.example.want '42\n' >>> exc_info = failure.exc_info >>> raise exc_info[0], exc_info[1], exc_info[2] Traceback (most recent call last): ... KeyError If the output doesn't match, then a DocTestFailure is raised: >>> test = DocTestParser().get_doctest(''' ... >>> x = 1 ... >>> x ... 2 ... ''', {}, 'foo', 'foo.py', 0) >>> case = DocTestCase(test) >>> try: ... case.debug() ... except DocTestFailure, failure: ... pass DocTestFailure objects provide access to the test: >>> failure.test is test True As well as to the example: >>> failure.example.want '2\n' and the actual output: >>> failure.got '1\n' """ self.setUp() runner = DebugRunner(optionflags=self._dt_optionflags, checker=self._dt_checker, verbose=False) runner.run(self._dt_test) self.tearDown() def id(self): return self._dt_test.name def __repr__(self): name = self._dt_test.name.split('.') return "%s (%s)" % (name[-1], '.'.join(name[:-1])) __str__ = __repr__ def shortDescription(self): return "Doctest: " + self._dt_test.name def DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None, **options): """ Convert doctest tests for a module to a unittest test suite. This converts each documentation string in a module that contains doctest tests to a unittest test case. If any of the tests in a doc string fail, then the test case fails. An exception is raised showing the name of the file containing the test and a (sometimes approximate) line number. The `module` argument provides the module to be tested. The argument can be either a module or a module name. If no argument is given, the calling module is used. A number of options may be provided as keyword arguments: setUp A set-up function. This is called before running the tests in each file. The setUp function will be passed a DocTest object. The setUp function can access the test globals as the globs attribute of the test passed. tearDown A tear-down function. This is called after running the tests in each file. The tearDown function will be passed a DocTest object. The tearDown function can access the test globals as the globs attribute of the test passed. globs A dictionary containing initial global variables for the tests. optionflags A set of doctest option flags expressed as an integer. """ if test_finder is None: test_finder = DocTestFinder() module = _normalize_module(module) tests = test_finder.find(module, globs=globs, extraglobs=extraglobs) if globs is None: globs = module.__dict__ if not tests: # Why do we want to do this? Because it reveals a bug that might # otherwise be hidden. raise ValueError(module, "has no tests") tests.sort() suite = unittest.TestSuite() for test in tests: if len(test.examples) == 0: continue if not test.filename: filename = module.__file__ if filename[-4:] in (".pyc", ".pyo"): filename = filename[:-1] test.filename = filename suite.addTest(DocTestCase(test, **options)) return suite class DocFileCase(DocTestCase): def id(self): return '_'.join(self._dt_test.name.split('.')) def __repr__(self): return self._dt_test.filename __str__ = __repr__ def format_failure(self, err): return ('Failed doctest test for %s\n File "%s", line 0\n\n%s' % (self._dt_test.name, self._dt_test.filename, err) ) def DocFileTest(path, module_relative=True, package=None, globs=None, parser=DocTestParser(), **options): if globs is None: globs = {} if package and not module_relative: raise ValueError("Package may only be specified for module-" "relative paths.") # Relativize the path. if module_relative: package = _normalize_module(package) path = _module_relative_path(package, path) # Find the file and read it. name = os.path.basename(path) doc = open(path).read() # Convert it to a test, and wrap it in a DocFileCase. test = parser.get_doctest(doc, globs, name, path, 0) return DocFileCase(test, **options) def DocFileSuite(*paths, **kw): """A unittest suite for one or more doctest files. The path to each doctest file is given as a string; the interpretation of that string depends on the keyword argument "module_relative". A number of options may be provided as keyword arguments: module_relative If "module_relative" is True, then the given file paths are interpreted as os-independent module-relative paths. By default, these paths are relative to the calling module's directory; but if the "package" argument is specified, then they are relative to that package. To ensure os-independence, "filename" should use "/" characters to separate path segments, and may not be an absolute path (i.e., it may not begin with "/"). If "module_relative" is False, then the given file paths are interpreted as os-specific paths. These paths may be absolute or relative (to the current working directory). package A Python package or the name of a Python package whose directory should be used as the base directory for module relative paths. If "package" is not specified, then the calling module's directory is used as the base directory for module relative filenames. It is an error to specify "package" if "module_relative" is False. setUp A set-up function. This is called before running the tests in each file. The setUp function will be passed a DocTest object. The setUp function can access the test globals as the globs attribute of the test passed. tearDown A tear-down function. This is called after running the tests in each file. The tearDown function will be passed a DocTest object. The tearDown function can access the test globals as the globs attribute of the test passed. globs A dictionary containing initial global variables for the tests. optionflags A set of doctest option flags expressed as an integer. parser A DocTestParser (or subclass) that should be used to extract tests from the files. """ suite = unittest.TestSuite() # We do this here so that _normalize_module is called at the right # level. If it were called in DocFileTest, then this function # would be the caller and we might guess the package incorrectly. if kw.get('module_relative', True): kw['package'] = _normalize_module(kw.get('package')) for path in paths: suite.addTest(DocFileTest(path, **kw)) return suite ###################################################################### ## 9. Debugging Support ###################################################################### def script_from_examples(s): r"""Extract script from text with examples. Converts text with examples to a Python script. Example input is converted to regular code. Example output and all other words are converted to comments: >>> text = ''' ... Here are examples of simple math. ... ... Python has super accurate integer addition ... ... >>> 2 + 2 ... 5 ... ... And very friendly error messages: ... ... >>> 1/0 ... To Infinity ... And ... Beyond ... ... You can use logic if you want: ... ... >>> if 0: ... ... blah ... ... blah ... ... ... ... Ho hum ... ''' >>> print script_from_examples(text) # Here are examples of simple math. # # Python has super accurate integer addition # 2 + 2 # Expected: ## 5 # # And very friendly error messages: # 1/0 # Expected: ## To Infinity ## And ## Beyond # # You can use logic if you want: # if 0: blah blah # # Ho hum """ output = [] for piece in DocTestParser().parse(s): if isinstance(piece, Example): # Add the example's source code (strip trailing NL) output.append(piece.source[:-1]) # Add the expected output: want = piece.want if want: output.append('# Expected:') output += ['## '+l for l in want.split('\n')[:-1]] else: # Add non-example text. output += [_comment_line(l) for l in piece.split('\n')[:-1]] # Trim junk on both ends. while output and output[-1] == '#': output.pop() while output and output[0] == '#': output.pop(0) # Combine the output, and return it. return '\n'.join(output) def testsource(module, name): """Extract the test sources from a doctest docstring as a script. Provide the module (or dotted name of the module) containing the test to be debugged and the name (within the module) of the object with the doc string with tests to be debugged. """ module = _normalize_module(module) tests = DocTestFinder().find(module) test = [t for t in tests if t.name == name] if not test: raise ValueError(name, "not found in tests") test = test[0] testsrc = script_from_examples(test.docstring) return testsrc def debug_src(src, pm=False, globs=None): """Debug a single doctest docstring, in argument `src`'""" testsrc = script_from_examples(src) debug_script(testsrc, pm, globs) def debug_script(src, pm=False, globs=None): "Debug a test script. `src` is the script, as a string." import pdb # Note that tempfile.NameTemporaryFile() cannot be used. As the # docs say, a file so created cannot be opened by name a second time # on modern Windows boxes, and execfile() needs to open it. srcfilename = tempfile.mktemp(".py", "doctestdebug") f = open(srcfilename, 'w') f.write(src) f.close() try: if globs: globs = globs.copy() else: globs = {} if pm: try: execfile(srcfilename, globs, globs) except: print sys.exc_info()[1] pdb.post_mortem(sys.exc_info()[2]) else: # Note that %r is vital here. '%s' instead can, e.g., cause # backslashes to get treated as metacharacters on Windows. pdb.run("execfile(%r)" % srcfilename, globs, globs) finally: os.remove(srcfilename) def debug(module, name, pm=False): """Debug a single doctest docstring. Provide the module (or dotted name of the module) containing the test to be debugged and the name (within the module) of the object with the docstring with tests to be debugged. """ module = _normalize_module(module) testsrc = testsource(module, name) debug_script(testsrc, pm, module.__dict__) ###################################################################### ## 10. Example Usage ###################################################################### class _TestClass: """ A pointless class, for sanity-checking of docstring testing. Methods: square() get() >>> _TestClass(13).get() + _TestClass(-12).get() 1 >>> hex(_TestClass(13).square().get()) '0xa9' """ def __init__(self, val): """val -> _TestClass object with associated value val. >>> t = _TestClass(123) >>> print t.get() 123 """ self.val = val def square(self): """square() -> square TestClass's associated value >>> _TestClass(13).square().get() 169 """ self.val = self.val ** 2 return self def get(self): """get() -> return TestClass's associated value. >>> x = _TestClass(-42) >>> print x.get() -42 """ return self.val __test__ = {"_TestClass": _TestClass, "string": r""" Example of a string object, searched as-is. >>> x = 1; y = 2 >>> x + y, x * y (3, 2) """, "bool-int equivalence": r""" In 2.2, boolean expressions displayed 0 or 1. By default, we still accept them. This can be disabled by passing DONT_ACCEPT_TRUE_FOR_1 to the new optionflags argument. >>> 4 == 4 1 >>> 4 == 4 True >>> 4 > 4 0 >>> 4 > 4 False """, "blank lines": r""" Blank lines can be marked with : >>> print 'foo\n\nbar\n' foo bar """, "ellipsis": r""" If the ellipsis flag is used, then '...' can be used to elide substrings in the desired output: >>> print range(1000) #doctest: +ELLIPSIS [0, 1, 2, ..., 999] """, "whitespace normalization": r""" If the whitespace normalization flag is used, then differences in whitespace are ignored. >>> print range(30) #doctest: +NORMALIZE_WHITESPACE [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29] """, } def _test(): r = unittest.TextTestRunner() r.run(DocTestSuite()) if __name__ == "__main__": _test() PK4paste/util/scgiserver.py#! /usr/bin/env python """ SCGI-->WSGI application proxy, "SWAP". (Originally written by Titus Brown.) This lets an SCGI front-end like mod_scgi be used to execute WSGI application objects. To use it, subclass the SWAP class like so:: class TestAppHandler(swap.SWAP): def __init__(self, *args, **kwargs): self.prefix = '/canal' self.app_obj = TestAppClass swap.SWAP.__init__(self, *args, **kwargs) where 'TestAppClass' is the application object from WSGI and '/canal' is the prefix for what is served by the SCGI Web-server-side process. Then execute the SCGI handler "as usual" by doing something like this:: scgi_server.SCGIServer(TestAppHandler, port=4000).serve() and point mod_scgi (or whatever your SCGI front end is) at port 4000. Kudos to the WSGI folk for writing a nice PEP & the Quixote folk for writing a nice extensible SCGI server for Python! """ import sys import time import os from scgi import scgi_server def debug(msg): timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) sys.stderr.write("[%s] %s\n" % (timestamp, msg)) class SWAP(scgi_server.SCGIHandler): """ SCGI->WSGI application proxy: let an SCGI server execute WSGI application objects. """ app_obj = None prefix = None def __init__(self, *args, **kwargs): assert self.app_obj, "must set app_obj" assert self.prefix, "must set prefix" args = (self,) + args scgi_server.SCGIHandler.__init__(*args, **kwargs) def handle_connection(self, conn): """ Handle an individual connection. """ input = conn.makefile("r") output = conn.makefile("w") environ = self.read_env(input) environ['wsgi.input'] = input environ['wsgi.errors'] = sys.stderr environ['wsgi.version'] = (1,0) environ['wsgi.multithread'] = False environ['wsgi.multiprocess'] = True environ['wsgi.run_once'] = False # dunno how SCGI does HTTPS signalling; can't test it myself... @CTB if environ.get('HTTPS','off') in ('on','1'): environ['wsgi.url_scheme'] = 'https' else: environ['wsgi.url_scheme'] = 'http' ## SCGI does some weird environ manglement. We need to set ## SCRIPT_NAME from 'prefix' and then set PATH_INFO from ## REQUEST_URI. prefix = self.prefix path = environ['REQUEST_URI'][len(prefix):].split('?', 1)[0] environ['SCRIPT_NAME'] = prefix environ['PATH_INFO'] = path headers_set = [] headers_sent = [] chunks = [] def write(data): chunks.append(data) def start_response(status,response_headers,exc_info=None): if exc_info: try: if headers_sent: # Re-raise original exception if headers sent raise exc_info[0], exc_info[1], exc_info[2] finally: exc_info = None # avoid dangling circular ref elif headers_set: raise AssertionError("Headers already set!") headers_set[:] = [status,response_headers] return write ### result = self.app_obj(environ, start_response) try: for data in result: chunks.append(data) # Before the first output, send the stored headers if not headers_set: # Error -- the app never called start_response status = '500 Server Error' response_headers = [('Content-type', 'text/html')] chunks = ["XXX start_response never called"] else: status, response_headers = headers_sent[:] = headers_set output.write('Status: %s\r\n' % status) for header in response_headers: output.write('%s: %s\r\n' % header) output.write('\r\n') for data in chunks: output.write(data) finally: if hasattr(result,'close'): result.close() # SCGI backends use connection closing to signal 'fini'. try: input.close() output.close() conn.close() except IOError, err: debug("IOError while closing connection ignored: %s" % err) def serve_application (application, prefix, port): class SCGIAppHandler(SWAP): def __init__ (self, *args, **kwargs): self.prefix = prefix self.app_obj = application SWAP.__init__(self, *args, **kwargs) scgi_server.SCGIServer(SCGIAppHandler, port=port).serve() PK4QRgAgApaste/util/string24.py"""A collection of string operations (most are no longer used). Warning: most of the code you see here isn't normally used nowadays. Beginning with Python 1.6, many of these functions are implemented as methods on the standard string object. They used to be implemented by a built-in module called strop, but strop is now obsolete itself. Public module variables: whitespace -- a string containing all characters considered whitespace lowercase -- a string containing all characters considered lowercase letters uppercase -- a string containing all characters considered uppercase letters letters -- a string containing all characters considered letters digits -- a string containing all characters considered decimal digits hexdigits -- a string containing all characters considered hexadecimal digits octdigits -- a string containing all characters considered octal digits punctuation -- a string containing all characters considered punctuation printable -- a string containing all characters considered printable """ # Some strings for ctype-style character classification whitespace = ' \t\n\r\v\f' lowercase = 'abcdefghijklmnopqrstuvwxyz' uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' letters = lowercase + uppercase ascii_lowercase = lowercase ascii_uppercase = uppercase ascii_letters = ascii_lowercase + ascii_uppercase digits = '0123456789' hexdigits = digits + 'abcdef' + 'ABCDEF' octdigits = '01234567' punctuation = """!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~""" printable = digits + letters + punctuation + whitespace # Case conversion helpers # Use str to convert Unicode literal in case of -U # Note that Cookie.py bogusly uses _idmap :( l = map(chr, xrange(256)) _idmap = str('').join(l) del l # Functions which aren't available as string methods. # Capitalize the words in a string, e.g. " aBc dEf " -> "Abc Def". # See also regsub.capwords(). def capwords(s, sep=None): """capwords(s, [sep]) -> string Split the argument into words using split, capitalize each word using capitalize, and join the capitalized words using join. Note that this replaces runs of whitespace characters by a single space. """ return (sep or ' ').join([x.capitalize() for x in s.split(sep)]) # Construct a translation string _idmapL = None def maketrans(fromstr, tostr): """maketrans(frm, to) -> string Return a translation table (a string of 256 bytes long) suitable for use in string.translate. The strings frm and to must be of the same length. """ if len(fromstr) != len(tostr): raise ValueError, "maketrans arguments must have same length" global _idmapL if not _idmapL: _idmapL = map(None, _idmap) L = _idmapL[:] fromstr = map(ord, fromstr) for i in range(len(fromstr)): L[fromstr[i]] = tostr[i] return ''.join(L) #################################################################### import re as _re class _multimap: """Helper class for combining multiple mappings. Used by .{safe_,}substitute() to combine the mapping and keyword arguments. """ def __init__(self, primary, secondary): self._primary = primary self._secondary = secondary def __getitem__(self, key): try: return self._primary[key] except KeyError: return self._secondary[key] class _TemplateMetaclass(type): pattern = r""" %(delim)s(?: (?P%(delim)s) | # Escape sequence of two delimiters (?P%(id)s) | # delimiter and a Python identifier {(?P%(id)s)} | # delimiter and a braced identifier (?P) # Other ill-formed delimiter exprs ) """ def __init__(cls, name, bases, dct): super(_TemplateMetaclass, cls).__init__(name, bases, dct) if 'pattern' in dct: pattern = cls.pattern else: pattern = _TemplateMetaclass.pattern % { 'delim' : _re.escape(cls.delimiter), 'id' : cls.idpattern, } cls.pattern = _re.compile(pattern, _re.IGNORECASE | _re.VERBOSE) class Template: """A string class for supporting $-substitutions.""" __metaclass__ = _TemplateMetaclass delimiter = '$' idpattern = r'[_a-z][_a-z0-9]*' def __init__(self, template): self.template = template # Search for $$, $identifier, ${identifier}, and any bare $'s def _invalid(self, mo): i = mo.start('invalid') lines = self.template[:i].splitlines(True) if not lines: colno = 1 lineno = 1 else: colno = i - len(''.join(lines[:-1])) lineno = len(lines) raise ValueError('Invalid placeholder in string: line %d, col %d' % (lineno, colno)) def substitute(self, *args, **kws): if len(args) > 1: raise TypeError('Too many positional arguments') if not args: mapping = kws elif kws: mapping = _multimap(kws, args[0]) else: mapping = args[0] # Helper function for .sub() def convert(mo): # Check the most common path first. named = mo.group('named') or mo.group('braced') if named is not None: val = mapping[named] # We use this idiom instead of str() because the latter will # fail if val is a Unicode containing non-ASCII characters. return '%s' % val if mo.group('escaped') is not None: return self.delimiter if mo.group('invalid') is not None: self._invalid(mo) raise ValueError('Unrecognized named group in pattern', self.pattern) return self.pattern.sub(convert, self.template) def safe_substitute(self, *args, **kws): if len(args) > 1: raise TypeError('Too many positional arguments') if not args: mapping = kws elif kws: mapping = _multimap(kws, args[0]) else: mapping = args[0] # Helper function for .sub() def convert(mo): named = mo.group('named') if named is not None: try: # We use this idiom instead of str() because the latter # will fail if val is a Unicode containing non-ASCII return '%s' % mapping[named] except KeyError: return self.delimiter + named braced = mo.group('braced') if braced is not None: try: return '%s' % mapping[braced] except KeyError: return self.delimiter + '{' + braced + '}' if mo.group('escaped') is not None: return self.delimiter if mo.group('invalid') is not None: return self.delimiter raise ValueError('Unrecognized named group in pattern', self.pattern) return self.pattern.sub(convert, self.template) #################################################################### # NOTE: Everything below here is deprecated. Use string methods instead. # This stuff will go away in Python 3.0. # Backward compatible names for exceptions index_error = ValueError atoi_error = ValueError atof_error = ValueError atol_error = ValueError # convert UPPER CASE letters to lower case def lower(s): """lower(s) -> string Return a copy of the string s converted to lowercase. """ return s.lower() # Convert lower case letters to UPPER CASE def upper(s): """upper(s) -> string Return a copy of the string s converted to uppercase. """ return s.upper() # Swap lower case letters and UPPER CASE def swapcase(s): """swapcase(s) -> string Return a copy of the string s with upper case characters converted to lowercase and vice versa. """ return s.swapcase() # Strip leading and trailing tabs and spaces def strip(s, chars=None): """strip(s [,chars]) -> string Return a copy of the string s with leading and trailing whitespace removed. If chars is given and not None, remove characters in chars instead. If chars is unicode, S will be converted to unicode before stripping. """ return s.strip(chars) # Strip leading tabs and spaces def lstrip(s, chars=None): """lstrip(s [,chars]) -> string Return a copy of the string s with leading whitespace removed. If chars is given and not None, remove characters in chars instead. """ return s.lstrip(chars) # Strip trailing tabs and spaces def rstrip(s, chars=None): """rstrip(s [,chars]) -> string Return a copy of the string s with trailing whitespace removed. If chars is given and not None, remove characters in chars instead. """ return s.rstrip(chars) # Split a string into a list of space/tab-separated words def split(s, sep=None, maxsplit=-1): """split(s [,sep [,maxsplit]]) -> list of strings Return a list of the words in the string s, using sep as the delimiter string. If maxsplit is given, splits at no more than maxsplit places (resulting in at most maxsplit+1 words). If sep is not specified or is None, any whitespace string is a separator. (split and splitfields are synonymous) """ return s.split(sep, maxsplit) splitfields = split # Split a string into a list of space/tab-separated words def rsplit(s, sep=None, maxsplit=-1): """rsplit(s [,sep [,maxsplit]]) -> list of strings Return a list of the words in the string s, using sep as the delimiter string, starting at the end of the string and working to the front. If maxsplit is given, at most maxsplit splits are done. If sep is not specified or is None, any whitespace string is a separator. """ return s.rsplit(sep, maxsplit) # Join fields with optional separator def join(words, sep = ' '): """join(list [,sep]) -> string Return a string composed of the words in list, with intervening occurrences of sep. The default separator is a single space. (joinfields and join are synonymous) """ return sep.join(words) joinfields = join # Find substring, raise exception if not found def index(s, *args): """index(s, sub [,start [,end]]) -> int Like find but raises ValueError when the substring is not found. """ return s.index(*args) # Find last substring, raise exception if not found def rindex(s, *args): """rindex(s, sub [,start [,end]]) -> int Like rfind but raises ValueError when the substring is not found. """ return s.rindex(*args) # Count non-overlapping occurrences of substring def count(s, *args): """count(s, sub[, start[,end]]) -> int Return the number of occurrences of substring sub in string s[start:end]. Optional arguments start and end are interpreted as in slice notation. """ return s.count(*args) # Find substring, return -1 if not found def find(s, *args): """find(s, sub [,start [,end]]) -> in Return the lowest index in s where substring sub is found, such that sub is contained within s[start,end]. Optional arguments start and end are interpreted as in slice notation. Return -1 on failure. """ return s.find(*args) # Find last substring, return -1 if not found def rfind(s, *args): """rfind(s, sub [,start [,end]]) -> int Return the highest index in s where substring sub is found, such that sub is contained within s[start,end]. Optional arguments start and end are interpreted as in slice notation. Return -1 on failure. """ return s.rfind(*args) # for a bit of speed _float = float _int = int _long = long # Convert string to float def atof(s): """atof(s) -> float Return the floating point number represented by the string s. """ return _float(s) # Convert string to integer def atoi(s , base=10): """atoi(s [,base]) -> int Return the integer represented by the string s in the given base, which defaults to 10. The string s must consist of one or more digits, possibly preceded by a sign. If base is 0, it is chosen from the leading characters of s, 0 for octal, 0x or 0X for hexadecimal. If base is 16, a preceding 0x or 0X is accepted. """ return _int(s, base) # Convert string to long integer def atol(s, base=10): """atol(s [,base]) -> long Return the long integer represented by the string s in the given base, which defaults to 10. The string s must consist of one or more digits, possibly preceded by a sign. If base is 0, it is chosen from the leading characters of s, 0 for octal, 0x or 0X for hexadecimal. If base is 16, a preceding 0x or 0X is accepted. A trailing L or l is not accepted, unless base is 0. """ return _long(s, base) # Left-justify a string def ljust(s, width, *args): """ljust(s, width[, fillchar]) -> string Return a left-justified version of s, in a field of the specified width, padded with spaces as needed. The string is never truncated. If specified the fillchar is used instead of spaces. """ return s.ljust(width, *args) # Right-justify a string def rjust(s, width, *args): """rjust(s, width[, fillchar]) -> string Return a right-justified version of s, in a field of the specified width, padded with spaces as needed. The string is never truncated. If specified the fillchar is used instead of spaces. """ return s.rjust(width, *args) # Center a string def center(s, width, *args): """center(s, width[, fillchar]) -> string Return a center version of s, in a field of the specified width. padded with spaces as needed. The string is never truncated. If specified the fillchar is used instead of spaces. """ return s.center(width, *args) # Zero-fill a number, e.g., (12, 3) --> '012' and (-3, 3) --> '-03' # Decadent feature: the argument may be a string or a number # (Use of this is deprecated; it should be a string as with ljust c.s.) def zfill(x, width): """zfill(x, width) -> string Pad a numeric string x with zeros on the left, to fill a field of the specified width. The string x is never truncated. """ if not isinstance(x, basestring): x = repr(x) return x.zfill(width) # Expand tabs in a string. # Doesn't take non-printing chars into account, but does understand \n. def expandtabs(s, tabsize=8): """expandtabs(s [,tabsize]) -> string Return a copy of the string s with all tab characters replaced by the appropriate number of spaces, depending on the current column, and the tabsize (default 8). """ return s.expandtabs(tabsize) # Character translation through look-up table. def translate(s, table, deletions=""): """translate(s,table [,deletions]) -> string Return a copy of the string s, where all characters occurring in the optional argument deletions are removed, and the remaining characters have been mapped through the given translation table, which must be a string of length 256. The deletions argument is not allowed for Unicode strings. """ if deletions: return s.translate(table, deletions) else: # Add s[:0] so that if s is Unicode and table is an 8-bit string, # table is converted to Unicode. This means that table *cannot* # be a dictionary -- for that feature, use u.translate() directly. return s.translate(table + s[:0]) # Capitalize a string, e.g. "aBc dEf" -> "Abc def". def capitalize(s): """capitalize(s) -> string Return a copy of the string s with only its first character capitalized. """ return s.capitalize() # Substring replacement (global) def replace(s, old, new, maxsplit=-1): """replace (str, old, new[, maxsplit]) -> string Return a copy of string str with all occurrences of substring old replaced by new. If the optional argument maxsplit is given, only the first maxsplit occurrences are replaced. """ return s.replace(old, new, maxsplit) # Try importing optional built-in module "strop" -- if it exists, # it redefines some string operations that are 100-1000 times faster. # It also defines values for whitespace, lowercase and uppercase # that match 's definitions. try: from strop import maketrans, lowercase, uppercase, whitespace letters = lowercase + uppercase except ImportError: pass # Use the original versions PK4G+qcn n paste/util/dateinterval.py""" DateInterval.py Convert interval strings (in the form of 1w2d, etc) to seconds, and back again. Is not exactly about months or years (leap years in particular). Accepts (y)ear, (b)month, (w)eek, (d)ay, (h)our, (m)inute, (s)econd. Exports only timeEncode and timeDecode functions. """ import re __all__ = ['interval_decode', 'interval_encode'] second = 1 minute = second*60 hour = minute*60 day = hour*24 week = day*7 month = day*30 year = day*365 timeValues = { 'y': year, 'b': month, 'w': week, 'd': day, 'h': hour, 'm': minute, 's': second, } timeOrdered = timeValues.items() timeOrdered.sort(lambda a, b: -cmp(a[1], b[1])) def interval_encode(seconds, include_sign=False): """Encodes a number of seconds (representing a time interval) into a form like 1h2d3s. >>> interval_encode(10) '10s' >>> interval_encode(493939) '5d17h12m19s' """ s = '' orig = seconds seconds = abs(seconds) for char, amount in timeOrdered: if seconds >= amount: i, seconds = divmod(seconds, amount) s += '%i%s' % (i, char) if orig < 0: s = '-' + s elif not orig: return '0' elif include_sign: s = '+' + s return s _timeRE = re.compile(r'[0-9]+[a-zA-Z]') def interval_decode(s): """Decodes a number in the format 1h4d3m (1 hour, 3 days, 3 minutes) into a number of seconds >>> interval_decode('40s') 40 >>> interval_decode('10000s') 10000 >>> interval_decode('3d1w45s') 864045 """ time = 0 sign = 1 s = s.strip() if s.startswith('-'): s = s[1:] sign = -1 elif s.startswith('+'): s = s[1:] for match in allMatches(s, _timeRE): char = match.group(0)[-1].lower() if not timeValues.has_key(char): # @@: should signal error continue time += int(match.group(0)[:-1]) * timeValues[char] return time # @@-sgd 2002-12-23 - this function does not belong in this module, find a better place. def allMatches(source, regex): """Return a list of matches for regex in source """ pos = 0 end = len(source) rv = [] match = regex.search(source, pos) while match: rv.append(match) match = regex.search(source, match.end() ) return rv if __name__ == '__main__': import doctest doctest.testmod() PK4問paste/util/filemixin.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 class FileMixin: """ Used to provide auxiliary methods to objects simulating files. Objects must implement write, and read if they are input files. Also they should implement close. Other methods you may wish to override: * flush() * seek(offset[, whence]) * tell() * truncate([size]) Attributes you may wish to provide: * closed * encoding (you should also respect that in write()) * mode * newlines (hard to support) * softspace """ def flush(self): pass def next(self): return self.readline() def readline(self, size=None): # @@: This is a lame implementation; but a buffer would probably # be necessary for a better implementation output = [] while 1: next = self.read(1) if not next: return ''.join(output) output.append(next) if size and size > 0 and len(output) >= size: return ''.join(output) if next == '\n': # @@: also \r? return ''.join(output) def xreadlines(self): return self def writelines(self, lines): for line in lines: self.write(line) PK4 ܾpaste/util/quoting.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 import cgi import htmlentitydefs import urllib import re __all__ = ['html_quote', 'html_unquote', 'url_quote', 'url_unquote', 'strip_html'] default_encoding = 'UTF-8' def html_quote(v, encoding=None): r""" Quote the value (turned to a string) as HTML. This quotes <, >, and quotes: >>> html_quote(1) '1' >>> html_quote(None) '' >>> html_quote('') '<hey!>' >>> html_quote(u'\u1029') '\xe1\x80\xa9' """ encoding = encoding or default_encoding if v is None: return '' elif isinstance(v, str): return cgi.escape(v, 1) elif isinstance(v, unicode): return cgi.escape(v.encode(encoding), 1) else: return cgi.escape(unicode(v).encode(encoding), 1) _unquote_re = re.compile(r'&([a-zA-Z]+);') def _entity_subber(match, name2c=htmlentitydefs.name2codepoint): code = name2c.get(match.group(1)) if code: return unichr(code) else: return match.group(0) def html_unquote(s, encoding=None): r""" Decode the value. >>> html_unquote('<hey you>') u'' >>> html_unquote('') '' >>> html_unquote('&blahblah;') u'&blahblah;' >>> html_unquote('\xe1\x80\xa9') u'\u1029' """ if isinstance(s, str): s = s.decode(encoding or default_encoding) return _unquote_re.sub(_entity_subber, s) def strip_html(s): # should this use html_unquote? s = re.sub('<.*?>', '', s) s = s.replace(' ', ' ').replace('<', '<') s = s.replace('>', '>').replace('&','&') return s def no_quote(s): """ Quoting that doesn't do anything """ return s url_quote = urllib.quote url_unquote = urllib.unquote if __name__ == '__main__': import doctest doctest.testmod() PKZ4paste/util/threadinglocal.pyc; u]Dc@sy dkZWn)ej odefdYZnDXy eiZWn2ej o&dkZdefdYZnXdS(NslocalcBstZRS(N(s__name__s __module__(((s7build/bdist.linux-i686/egg/paste/util/threadinglocal.pyslocalscBs>tZdZeidZeidZeidZRS(NcCsh|idscCs,|}x|D]}|||fZd?Zed@ZdS(As. Date, Time, and Timespan Parsing Utilities This module contains parsing support to create "human friendly" ``datetime`` object parsing. The explicit goal of these routines is to provide a multi-format date/time support not unlike that found in Microsoft Excel. In most approaches, the input is very "strict" to prevent errors -- however, this approach is much more liberal since we are assuming the user-interface is parroting back the normalized value and thus the user has immediate feedback if the data is not typed in correctly. ``parse_date`` and ``normalize_date`` These functions take a value like '9 jan 2007' and returns either an ``date`` object, or an ISO 8601 formatted date value such as '2007-01-09'. There is an option to provide an Oracle database style output as well, ``09 JAN 2007``, but this is not the default. This module always treats '/' delimiters as using US date order (since the author's clients are US based), hence '1/9/2007' is January 9th. Since this module treats the '-' as following European order this supports both modes of data-entry; together with immediate parroting back the result to the screen, the author has found this approach to work well in pratice. ``parse_time`` and ``normalize_time`` These functions take a value like '1 pm' and returns either an ``time`` object, or an ISO 8601 formatted 24h clock time such as '13:00'. There is an option to provide for US style time values, '1:00 PM', however this is not the default. ``parse_datetime`` and ``normalize_datetime`` These functions take a value like '9 jan 2007 at 1 pm' and returns either an ``datetime`` object, or an ISO 8601 formatted return (without the T) such as '2007-01-09 13:00'. There is an option to provide for Oracle / US style, '09 JAN 2007 @ 1:00 PM', however this is not the default. ``parse_delta`` and ``normalize_delta`` These functions take a value like '1h 15m' and returns either an ``timedelta`` object, or an 2-decimal fixed-point numerical value in hours, such as '1.25'. The rationale is to support meeting or time-billing lengths, not to be an accurate representation in mili-seconds. As such not all valid ``timedelta`` values will have a normalized representation. (s timedeltastimesdatesdatetime(s localtimeNsparse_timedeltasnormalize_timedeltas parse_timesnormalize_times parse_datesnormalize_datecCs#yti|SWn tSnXdS(N(sstringsatoisvalsNone(sval((s5build/bdist.linux-i686/egg/paste/util/datetimeutil.pys_number@scCsw| otSnti|}d|jo1t|}tdt|dd|dSnd|jp d|j}d|jp d|j}d|j}x#d D]}ti ||d }qWti |}ti |}d }d }|i|ot|i}n|ot|i}nt|d jo| ot|i}ntd|d|Sd S(s1 returns a ``timedelta`` object, or None s.shourssminutesi<f1.0shs:smsminu:teshour()s f0.0iN(svalsNonesstringslowersfloats timedeltasintsfHoursfMins fFractionsnoisesreplacesstripssplitshrsmisreversespopslen(svalsnoisesmishrs fFractionsfHoursfMin((s5build/bdist.linux-i686/egg/paste/util/datetimeutil.pysparse_timedeltaIs2  %  cCskt|tjot|}n| odSn|id}|idd}d||ddfSdS(s produces a normalized string value of the timedelta This module returns a normalized time span value consisting of the number of hours in fractional form. For example '1h 15min' is formatted as 01.25. sii<s%d.%02didN(stypesvalsstrsparse_timedeltassecondsshrsmn(svalshrsmn((s5build/bdist.linux-i686/egg/paste/util/datetimeutil.pysnormalize_timedeltacs cCs| otSnd}}ti|}dti|dj}dti|dj}x#dD]}ti ||d}q`Wti |}t |djo$t |d}t |d}n|d}t |djond|jo!t}|d }|d }nd |jo d }nt |d jo;t |}| o| o |d jo|d 7}qnHt |djo$t |d }t |d}nt |d }|o |d jo|d }n|o |d jo|d }nt||SdS(Niisasps:amp.s isnowiisnooni iii(svalsNoneshrsmisstringslowersfindsamflagspmflagsnoisesreplacessplitslensints localtimestmstime(svalsnoiseshrsamflagsmistmspmflag((s5build/bdist.linux-i686/egg/paste/util/datetimeutil.pys parse_timevsF        cCs| odSnt|tjot|}n| od|i|ifSn|i}d}|djp |djo d}n3|djo%d}|djo|d}qnd||i|fSdS( Nss %02d:%02dsAMiii sPMs %02d:%02d %s( svaluestypesstrs parse_timesampmshoursminuteshrsam(svaluesampmshrsam((s5build/bdist.linux-i686/egg/paste/util/datetimeutil.pysnormalize_times    sdaysisjansfebismarisaprismayisjunisjulisaugissepi socti snovi sdeci cCs:x/tiD]!\}}||jo|Sq q WtSdS(N(s_str2numsitemsskeysmonsvalsNone(svalskeysmon((s5build/bdist.linux-i686/egg/paste/util/datetimeutil.pys_months    iiisJansFebsMarsAprsMaysJunsJulsAugsSepsOctsNovsDecsmonstueswedsthusfrissatssuncCs| otSnti|}t}|id}t|djo|\}}}d|jo|idd}nd|jo|idd}ny6t t |t |t |}d|d}Wqt j oqXn| o|d }d|jot i}qu|tjoGt i}tti|}x#|i|jo|t7}qNWqun|o|di}|idd idd }xM|iD]?}yt |}Wnt j oqX|td |7}qW|Snt} }} x/d dd dfD]} ti|| d}q#Wx#tD]} ti|| d}qIWg}t!}t!} xz|D]r}|i%o.|o| o|i&dnt'}} n%| o|i&dt!} nt'}|i&|qWtidi(|}dt|jo0t)|d}t)|d}t)|d}t|ddjo7|} |o|}|} qNt-|d}|} q|djo^|} t|ddjot.dn|o|} |}qN|} t-|d}q|} |} t|ddjot.dnt-|d}nQdt|jot)|d}t)|d}|djo7|} d} |djo |}qct-|d}q|djoZ|djo|}|} d} qc|djo|}|} qc|} t-|d}q|djo|} d} n|} t-|d}n<dt|jo(|d}|i% o't-|}|tj o d} qqt)|}t0|}dt|jo7t)|d } t)|dd!}t)|d} qt|ddfjoG|djo|} d}d} qt)|d }t)|d} q|djo |} qt.dnt1} |tjo| d}n| tjo| d} n| tjo| d} nt | || SdS(Ns-is+is sxxxi snows +s -sdayss/s,s*siiisfour digit year requirediiiiii (3svalsNonesstringslowersnowssplitsstrictslensysmsdsdatesints ValueErrorschkstodays_wkdyslistsindexsidxs day_of_weeks_one_daysstripstailsreplacesitemsdayss timedeltasyrsmosdysnoisesoutsFalseslastsldigschsisdigitsappendsTruesjoins_numbersasbscs_months TypeErrorsvsstrs localtimestm(svalschsmsdayssoutsnowschksstrictstailstmsldigsnoisesdysyrsascsbslastsdsidxsmositemsvsy((s5build/bdist.linux-i686/egg/paste/util/datetimeutil.pys parse_dates  $                                    cCsz| odSnt|tjot|}n|od|i|i|ifSnd|it|i|ifSdS(Nss %4d-%02d-%02ds %02d %s %4d( svalstypesstrs parse_datesiso8601syearsmonthsdays_num2str(svalsiso8601((s5build/bdist.linux-i686/egg/paste/util/datetimeutil.pysnormalize_dateYs(s__doc__sdatetimes timedeltastimesdates localtimesstrings__all__s_numbersparse_timedeltasnormalize_timedeltas parse_timesnormalize_times_one_days_str2nums_months_days_in_months_num2strs_wkdys parse_datesTruesnormalize_date(sparse_timedeltasnormalize_times_num2strsstrings timedeltas_months_str2nums_wkdys__all__sdatetimesnormalize_timedeltasnormalize_dates_days_in_months parse_datestimesdates parse_times_numbers_one_days localtime((s5build/bdist.linux-i686/egg/paste/util/datetimeutil.pys?7s"     $ r rr PKZ4L paste/util/classinstance.pyc; u]Dc@s0defdYZdefdYZdS(sclassinstancemethodcBs#tZdZdZedZRS(s Acts like a class method when called from a class, like an instance method when called by an instance. The method should take two arguments, 'self' and 'cls'; one of these will be None depending on how the method was called. cCs||_|i|_dS(N(sfuncsselfs__doc__(sselfsfunc((s6build/bdist.linux-i686/egg/paste/util/classinstance.pys__init__ s cCst|id|d|SdS(Nsobjstype(s_methodwrappersselfsfuncsobjstype(sselfsobjstype((s6build/bdist.linux-i686/egg/paste/util/classinstance.pys__get__s(s__name__s __module__s__doc__s__init__sNones__get__(((s6build/bdist.linux-i686/egg/paste/util/classinstance.pysclassinstancemethods  s_methodwrappercBs#tZdZdZdZRS(NcCs||_||_||_dS(N(sfuncsselfsobjstype(sselfsfuncsobjstype((s6build/bdist.linux-i686/egg/paste/util/classinstance.pys__init__s  cOsP|id o|id p td|i|i|if||SdS(NsselfsclssAYou cannot use 'self' or 'cls' arguments to a classinstancemethod(skwshas_keysAssertionErrorsselfsfuncsobjstypesargs(sselfsargsskw((s6build/bdist.linux-i686/egg/paste/util/classinstance.pys__call__s,cCsR|itjod|ii|iifSn!d|ii|ii|ifSdS(Nss(sselfsobjsNonestypes__name__sfuncs func_name(sself((s6build/bdist.linux-i686/egg/paste/util/classinstance.pys__repr__ s(s__name__s __module__s__init__s__call__s__repr__(((s6build/bdist.linux-i686/egg/paste/util/classinstance.pys_methodwrappers  N(sobjectsclassinstancemethods_methodwrapper(sclassinstancemethods_methodwrapper((s6build/bdist.linux-i686/egg/paste/util/classinstance.pys?sPKZ4M ( (paste/util/ip4.pyc; u]Dc@s'dZdZdZdZdZdkZdkZdeifdYZe dZ e d Z e d joed Z ed d dZe GHxe iD] ZeGHqWxeiD] ZeGHqWxe eBiD] ZeGHqWxe eAiD] ZeGHqWxe D] ZeGHqWndS(sIP4 address range set implementation. Implements an IPv4-range type. Copyright (C) 2006, Heiko Wundram. Released under the MIT-license. s Heiko Wundram s0.2s3s 2006-01-20NsIP4RangecBstZdZdZdd>dZdigiZedD]Z ee e q:[Z dZ dZ dZd Zd Zd Zd Zd ZdZdZeZdZRS(sbIP4 address range class with efficient storage of address ranges. Supports all set operations.iii sis 0123456789.cGsHt|djot|dto"tt|i|ddSnt|}xtt|D]}||}t|t ozd|jo&|i |i dd||5 - a set of addresses, interpreted as 1.2.3.0-1.2.5.255 - 1.2.0.0/16 - a set of addresses, interpreted as 1.2.0.0-1.2.255.255 Only the first three notations are valid if you use a string address in a tuple, whereby notation 2 is interpreted as 1.2.3.0 if specified as lower bound and 1.2.3.255 if specified as upper bound, not as a range of addresses. Specifying a range is done with the <-> operator. This is necessary because '-' might be present in a hostname. '<->' shouldn't be, ever. iiNs<->s/isTuple is of invalid length.sInvalid argument.sminsmax(slensargss isinstancesIP4Rangessupersselfs__init__slistsrangesisargvalsstrs _parseRangessplits _parseMasks_parseAddrRangestuples ValueErrorsaddr1saddr2sintslongs TypeErrors_MINIP4s_MAXIP4(sselfsargssisargvalsaddr1saddr2((s,build/bdist.linux-i686/egg/paste/util/ip4.pys__init__&s>'    # cCst|\}}t|\}}||jo0||d||d>d|d>@7}|}n||jotdn|d|dK}|d|dK}|dd|d>d7}||fSdS(Niis!Range has more dots than address.i(s _parseAddrsaddr1snaddr1s naddr1lensaddr2snaddr2s naddr2lens ValueError(sselfsaddr1saddr2s naddr2lens naddr1lensnaddr2snaddr1((s,build/bdist.linux-i686/egg/paste/util/ip4.pys _parseRangejs &  c Cs|t|\}}|d|dK}yK| o d}n t|}d|jo djn o tnWntj oyt|t}Wntj otdnXd}d}| o d}q>x|d@ o|d7}qWx$|d@o|dL}|d7}qW||djotdq>nX|d|>dd|>@}|dd|>d}||fSdS(Niiii sMask isn't parseable.isMask isn't a proper host mask.( s _parseAddrsaddrsnaddrsnaddrlensmasksmasklensints ValueErrorsFalses remainingsnaddr1snaddr2( sselfsaddrsmasksmasklensnaddrlensnaddr2snaddr1s remainingsnaddr((s,build/bdist.linux-i686/egg/paste/util/ip4.pys _parseMaskxs:      cCsXt|\}}|d|d>}|d|d>dd|d>d}||fSdS(Niii(s _parseAddrsaddrsnaddrsnaddrlensnaddr1snaddr2(sselfsaddrsnaddrlensnaddr2snaddr1snaddr((s,build/bdist.linux-i686/egg/paste/util/ip4.pys_parseAddrRanges&cCsUg}x5tdD]'}|it|d@|dL}qWdit|SdS(Niiis.(srvsrangesisappendsstrsnumsjoinsreversed(sselfsnumsrvsi((s,build/bdist.linux-i686/egg/paste/util/ip4.pys_int2ips  ccs1x*tt|iD]}|i|VqWdS(swReturns an iterator which iterates over ips in this iprange. An IP is returned in string form (e.g. '1.2.3.4').N(ssupersIP4Rangesselfs__iter__svs_int2ip(sselfsv((s,build/bdist.linux-i686/egg/paste/util/ip4.pys iteraddressessccsrxk|iD]`}|d|ddjo|i|dVq d|i|d|i|ddfVq WdS(sReturns an iterator which iterates over ip-ip ranges which build this iprange if combined. An ip-ip pair is returned in string form (e.g. '1.2.3.4-2.3.4.5').iis%s-%sN(sselfs_rangessrs_int2ip(sselfsr((s,build/bdist.linux-i686/egg/paste/util/ip4.pys iterrangess  ccs6x/|iD]$}x|i|D] }|Vq Wq WdS(sReturns an iterator which iterates over ip/mask pairs which build this iprange if combined. An IP/Mask pair is returned in string form (e.g. '1.2.3.0/24').N(sselfs_rangessrs _itermaskssv(sselfsrsv((s,build/bdist.linux-i686/egg/paste/util/ip4.pys itermaskss  ccs|g}x |o|i}d}xutomdd|>}|d|dd|>dd|>@}||djo|||djoPq(|d7}q(Wd|i ||fV|d|jo|i |d|fn|d||jo|i |||dfq q WdS(Niii s%s/%s( srsrangesspopscurscurmasksTrues curmasklensstartsselfs_int2ipsappend(sselfsrscursstartsrangess curmasklenscurmask((s,build/bdist.linux-i686/egg/paste/util/ip4.pys _itermaskss"  &&cCsg}xv|iD]k\}}||djo!|id|i|fq|id|i||i|dfqWd|iidi |fSdS(s?Returns a string which can be used to reconstruct this iprange.is%rs(%r,%r)s%s(%s)s,N( srvsselfs_rangessstartsstopsappends_int2ips __class__s__name__sjoin(sselfsstartsstopsrv((s,build/bdist.linux-i686/egg/paste/util/ip4.pys__repr__s !1(s__name__s __module__s__doc__s_MINIP4s_MAXIP4sjoinsappends_[1]srangesnschrs _UNITYTRANSs _IPREMOVEs__init__s _parseRanges _parseMasks_parseAddrRanges_int2ips iteraddressess iterrangess itermaskss _itermaskss__iter__s__repr__(((s,build/bdist.linux-i686/egg/paste/util/ip4.pysIP4Ranges < D    cCs8|o|ititio<yti|}Wq\tij ot dq\Xnd}xt |i dD]\}}|djot dnyK| o d}n t|}d|jo djn o t nWnt j ot dnX|dK}||7}qxW||d fSdS( NsInvalid Hostname as argument.is.is&Address contains more than four parts.isAddress part out of range.ii(slookupsaddrs translatesIP4Ranges _UNITYTRANSs _IPREMOVEssockets gethostbynameserrors ValueErrorsnaddrs enumeratessplitsnaddrposspartsint(saddrslookupsnaddrposspartsnaddr((s,build/bdist.linux-i686/egg/paste/util/ip4.pys _parseAddrs*      cCst|d|dSdS(Nslookupi(s _parseAddrsaddrslookup(saddrslookup((s,build/bdist.linux-i686/egg/paste/util/ip4.pysip2intss__main__s172.22.162.250/24s172.22.162.250s172.22.163.250s172.22.163.253<->255(s__doc__s __author__s __version__s __revision__s__date__sintsetssocketsIntSetsIP4RangesTrues _parseAddrsip2ints__name__sxsys itermaskssvals iterranges( s __revision__ssocketsvals _parseAddrsip2intsintsets __author__s__date__sIP4Rangesxsys __version__((s,build/bdist.linux-i686/egg/paste/util/ip4.pys?s8            PKZ4R%paste/util/findpackage.pyc; u]Dc@sdkZdkZdZdS(NcCstii|}|}ttiiti}g}t}xnow||jodi |Sn|i dtii |tii |}||jotd|n|}qFWdS(so Given a directory, finds the equivalent package name. If it is directly in sys.path, returns ''. is.is*%s is not under any path found in sys.pathN(sosspathsabspathsdirsorig_dirsmapssysspackagessNoneslast_dirsjoinsinsertsbasenamesdirnames ValueError(sdirslast_dirsorig_dirspathspackages((s4build/bdist.linux-i686/egg/paste/util/findpackage.pys find_packages  (ssyssoss find_package(ssyss find_packagesos((s4build/bdist.linux-i686/egg/paste/util/findpackage.pys?s  PKZ4Į,,paste/util/threadedprint.pyc; u]Dc@sdZdkZdkZdkZdeifdYZeaeadZ dZ dZ e a a deifdYZeaead Zd Z d ZdS( s threadedprint.py ================ :author: Ian Bicking :date: 12 Jul 2004 Multi-threaded printing; allows the output produced via print to be separated according to the thread. To use this, you must install the catcher, like:: threadedprint.install() The installation optionally takes one of three parameters: default The default destination for print statements (e.g., ``sys.stdout``). factory A function that will produce the stream for a thread, given the thread's name. paramwriter Instead of writing to a file-like stream, this function will be called like ``paramwriter(thread_name, text)`` for every write. The thread name is the value returned by ``threading.currentThread().getName()``, a string (typically something like Thread-N). You can also submit file-like objects for specific threads, which will override any of these parameters. To do this, call ``register(stream, [threadName])``. ``threadName`` is optional, and if not provided the stream will be registered for the current thread. If no specific stream is registered for a thread, and no default has been provided, then an error will occur when anything is written to ``sys.stdout`` (or printed). Note: the stream's ``write`` method will be called in the thread the text came from, so you should consider thread safety, especially if multiple threads share the same writer. Note: if you want access to the original standard out, use ``sys.__stdout__``. You may also uninstall this, via:: threadedprint.uninstall() TODO ---- * Something with ``sys.stderr``. * Some default handlers. Maybe something that hooks into `logging`. * Possibly cache the results of ``factory`` calls. This would be a semantic change. Ns PrintCatchercBsttZeeeedZeidZdZdZ dZ dZ eeidZ eeidZ RS( NcCsttd|||gdjp td|o#| ptd|ti}n|o|i |_ n;|o|i |_ n$|o|i |_ n |i|_ ||_||_||_h|_dS(NcCs |tj S(N(sxsNone(sx((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pysGsis<You can only provide one of default, factory, or paramwriters:You cannot pass in both default (%r) and leave_stdout=True(slensfiltersdefaultsfactorys paramwritersAssertionErrors leave_stdoutssyssstdoutsselfs _writedefaults _defaultfuncs _writefactorys _writeparams _writeerrors_defaults_factorys _paramwriters _catchers(sselfsdefaultsfactorys paramwriters leave_stdout((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pys__init__Es  &     cCsX|i}|i}|i| o|i||n||}|i |dS(N( s currentThreadsgetNamesnamesselfs _catchersscatchersshas_keys _defaultfuncsvscatcherswrite(sselfsvs currentThreadscatchersnamescatchers((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pyswrite\s   cCs|ii|dS(N(sselfs_defaultswritesv(sselfsnamesv((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pys _writedefaultescCs|i|i|dS(N(sselfs_factorysnameswritesv(sselfsnamesv((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pys _writefactoryhscCs|i||dS(N(sselfs _paramwritersnamesv(sselfsnamesv((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pys _writeparamkscCstptd|dS(Ns8There is no PrintCatcher output stream for the thread %r(sFalsesAssertionErrorsname(sselfsnamesv((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pys _writeerrornscCs1|tjo|i}n||i|t o2tiat|at_tiatiandS(N(s _printcatcherssyssstdouts _oldstdouts PrintCatcherskwsregisters deregister(skw((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pysinstalls   cCs.to#tt_taatatandS(N(s _printcatchers _oldstdoutssyssstdoutsNonesnot_installed_errorsregisters deregister(((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pys uninstalls   cOstp tddS(NsGthreadedprint has not yet been installed (call threadedprint.install())(sFalsesAssertionError(sargsskw((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pysnot_installed_errorss StdinCatchercBsttZeeedZeeidZdZdZdZ dZ eeidZ eeidZ RS( NcCsttd|||gdjp td|o|i|_n;|o|i |_n$|o|i |_n |i |_||_ ||_ ||_h|_dS(NcCs |tj S(N(sxsNone(sx((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pyssis<You can only provide one of default, factory, or paramwriter(slensfiltersdefaultsfactorys paramwritersAssertionErrorsselfs _readdefaults _defaultfuncs _readfactorys _readparams _readerrors_defaults_factorys _paramwriters _catchers(sselfsdefaultsfactorys paramwriter((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pys__init__s &    cCsX|i}|i}|i| o|i||n||}|i |dS(N( s currentThreadsgetNamesnamesselfs _catchersscatchersshas_keys _defaultfuncssizescatchersread(sselfssizes currentThreadscatchersnamescatchers((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pysreads   cCs|ii|dS(N(sselfs_defaultsreadssize(sselfsnamessize((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pys _readdefaultscCs|i|i|dS(N(sselfs_factorysnamesreadssize(sselfsnamessize((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pys _readfactoryscCs|i||dS(N(sselfs _paramreadersnamessize(sselfsnamessize((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pys _readparamscCstptd|dS(Ns8There is no StdinCatcher output stream for the thread %r(sFalsesAssertionErrorsname(sselfsnamessize((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pys _readerrorscCs.|tjo|i}n||i|t o2tiat|at_tiatia ndS(N( s _stdincatcherssyssstdins _oldstdins StdinCatcherskwsregistersregister_stdins deregistersderegister_stdin(skw((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pys install_stdins   cCs,to!|t_ta}taandS(N(s _stdincatchers _oldstdinssyssstdinsNonesnot_installed_error_stdinsregister_stdinsderegister_stdin(s _oldstdin((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pys uninstalls   cOstp tddS(NsWthreadedprint has not yet been installed for stdin (call threadedprint.install_stdin())(sFalsesAssertionError(sargsskw((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pysnot_installed_error_stdins(s__doc__s threadingssyss filemixins FileMixins PrintCatchersNones _printcatchers _oldstdoutsinstalls uninstallsnot_installed_errorsregisters deregisters StdinCatchers _stdincatchers _oldstdins install_stdinsnot_installed_error_stdin( snot_installed_errors StdinCatchers install_stdins PrintCatchers filemixinssyss threadingsinstallsnot_installed_error_stdins uninstall((s6build/bdist.linux-i686/egg/paste/util/threadedprint.pys?=s    >    8  PKZ44w paste/util/multidict.pyc; u]Dc@sZdklZdefdYZhdd>> d = multidict(a=1, b=2) >>> d['a'] 1 >>> d.getall('c') [] >>> d.add('a', 2) >>> d['a'] 1 >>> d.getall('a') [1, 2] >>> d['b'] = 4 >>> d.getall('b') [4] >>> d.keys() ['a', 'a', 'b'] >>> d.items() [('a', 1), ('a', 2), ('b', 4)] s__main__N(sUserDicts DictMixins multidicts__test__s__name__sdocteststestmod(s DictMixins__test__s multidictsdoctest((s2build/bdist.linux-i686/egg/paste/util/multidict.pys?s   PKZ4NJS##paste/util/subprocess24.pyc; u]Dc@s?dZdkZeidjZdkZdkZdkZeodkZdkZnodk Z dk l Z l Z l Z lZdk lZlZlZlZdklZlZdklZdklZlZlZlZlZlZd kl Z l!Z!l"Z"q]d k#Td fd YZd fdYZ n%dk$Z$dk%Z%dk&Z&dk'Z'ddddgZ(yei)dZ*Wn dZ*nXye+Wne,j odZ+dZ-nXgZ.dZ/dZ0dZ1dZ2dZ3de4fdYZ5dZ6dZ7e8djoeo e7q;e6ndS(sT)subprocess - Subprocesses with accessible I/O streams This module allows you to spawn processes, connect to their input/output/error pipes, and obtain their return codes. This module intends to replace several other, older modules and functions, like: os.system os.spawn* os.popen* popen2.* commands.* Information about how the subprocess module can be used to replace these modules and functions can be found below. Using the subprocess module =========================== This module defines one class called Popen: class Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0): Arguments are: args should be a string, or a sequence of program arguments. The program to execute is normally the first item in the args sequence or string, but can be explicitly set by using the executable argument. On UNIX, with shell=False (default): In this case, the Popen class uses os.execvp() to execute the child program. args should normally be a sequence. A string will be treated as a sequence with the string as the only item (the program to execute). On UNIX, with shell=True: If args is a string, it specifies the command string to execute through the shell. If args is a sequence, the first item specifies the command string, and any additional items will be treated as additional shell arguments. On Windows: the Popen class uses CreateProcess() to execute the child program, which operates on strings. If args is a sequence, it will be converted to a string using the list2cmdline method. Please note that not all MS Windows applications interpret the command line the same way: The list2cmdline is designed for applications using the same rules as the MS C runtime. bufsize, if given, has the same meaning as the corresponding argument to the built-in open() function: 0 means unbuffered, 1 means line buffered, any other positive value means use a buffer of (approximately) that size. A negative bufsize means to use the system default, which usually means fully buffered. The default value for bufsize is 0 (unbuffered). stdin, stdout and stderr specify the executed programs' standard input, standard output and standard error file handles, respectively. Valid values are PIPE, an existing file descriptor (a positive integer), an existing file object, and None. PIPE indicates that a new pipe to the child should be created. With None, no redirection will occur; the child's file handles will be inherited from the parent. Additionally, stderr can be STDOUT, which indicates that the stderr data from the applications should be captured into the same file handle as for stdout. If preexec_fn is set to a callable object, this object will be called in the child process just before the child is executed. If close_fds is true, all file descriptors except 0, 1 and 2 will be closed before the child process is executed. if shell is true, the specified command will be executed through the shell. If cwd is not None, the current directory will be changed to cwd before the child is executed. If env is not None, it defines the environment variables for the new process. If universal_newlines is true, the file objects stdout and stderr are opened as a text files, but lines may be terminated by any of '\n', the Unix end-of-line convention, '\r', the Macintosh convention or '\r\n', the Windows convention. All of these external representations are seen as '\n' by the Python program. Note: This feature is only available if Python is built with universal newline support (the default). Also, the newlines attribute of the file objects stdout, stdin and stderr are not updated by the communicate() method. The startupinfo and creationflags, if given, will be passed to the underlying CreateProcess() function. They can specify things such as appearance of the main window and priority for the new process. (Windows only) This module also defines two shortcut functions: call(*args, **kwargs): Run command with arguments. Wait for command to complete, then return the returncode attribute. The arguments are the same as for the Popen constructor. Example: retcode = call(["ls", "-l"]) Exceptions ---------- Exceptions raised in the child process, before the new program has started to execute, will be re-raised in the parent. Additionally, the exception object will have one extra attribute called 'child_traceback', which is a string containing traceback information from the childs point of view. The most common exception raised is OSError. This occurs, for example, when trying to execute a non-existent file. Applications should prepare for OSErrors. A ValueError will be raised if Popen is called with invalid arguments. Security -------- Unlike some other popen functions, this implementation will never call /bin/sh implicitly. This means that all characters, including shell metacharacters, can safely be passed to child processes. Popen objects ============= Instances of the Popen class have the following methods: poll() Check if child process has terminated. Returns returncode attribute. wait() Wait for child process to terminate. Returns returncode attribute. communicate(input=None) Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate. The optional stdin argument should be a string to be sent to the child process, or None, if no data should be sent to the child. communicate() returns a tuple (stdout, stderr). Note: The data read is buffered in memory, so do not use this method if the data size is large or unlimited. The following attributes are also available: stdin If the stdin argument is PIPE, this attribute is a file object that provides input to the child process. Otherwise, it is None. stdout If the stdout argument is PIPE, this attribute is a file object that provides output from the child process. Otherwise, it is None. stderr If the stderr argument is PIPE, this attribute is file object that provides error output from the child process. Otherwise, it is None. pid The process ID of the child process. returncode The child return code. A None value indicates that the process hasn't terminated yet. A negative value -N indicates that the child was terminated by signal N (UNIX only). Replacing older functions with the subprocess module ==================================================== In this section, "a ==> b" means that b can be used as a replacement for a. Note: All functions in this section fail (more or less) silently if the executed program cannot be found; this module raises an OSError exception. In the following examples, we assume that the subprocess module is imported with "from subprocess import *". Replacing /bin/sh shell backquote --------------------------------- output=`mycmd myarg` ==> output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0] Replacing shell pipe line ------------------------- output=`dmesg | grep hda` ==> p1 = Popen(["dmesg"], stdout=PIPE) p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) output = p2.communicate()[0] Replacing os.system() --------------------- sts = os.system("mycmd" + " myarg") ==> p = Popen("mycmd" + " myarg", shell=True) sts = os.waitpid(p.pid, 0) Note: * Calling the program through the shell is usually not required. * It's easier to look at the returncode attribute than the exitstatus. A more real-world example would look like this: try: retcode = call("mycmd" + " myarg", shell=True) if retcode < 0: print >>sys.stderr, "Child was terminated by signal", -retcode else: print >>sys.stderr, "Child returned", retcode except OSError, e: print >>sys.stderr, "Execution failed:", e Replacing os.spawn* ------------------- P_NOWAIT example: pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg") ==> pid = Popen(["/bin/mycmd", "myarg"]).pid P_WAIT example: retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg") ==> retcode = call(["/bin/mycmd", "myarg"]) Vector example: os.spawnvp(os.P_NOWAIT, path, args) ==> Popen([path] + args[1:]) Environment example: os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env) ==> Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"}) Replacing os.popen* ------------------- pipe = os.popen(cmd, mode='r', bufsize) ==> pipe = Popen(cmd, shell=True, bufsize=bufsize, stdout=PIPE).stdout pipe = os.popen(cmd, mode='w', bufsize) ==> pipe = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE).stdin (child_stdin, child_stdout) = os.popen2(cmd, mode, bufsize) ==> p = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, close_fds=True) (child_stdin, child_stdout) = (p.stdin, p.stdout) (child_stdin, child_stdout, child_stderr) = os.popen3(cmd, mode, bufsize) ==> p = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) (child_stdin, child_stdout, child_stderr) = (p.stdin, p.stdout, p.stderr) (child_stdin, child_stdout_and_stderr) = os.popen4(cmd, mode, bufsize) ==> p = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True) (child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout) Replacing popen2.* ------------------ Note: If the cmd argument to popen2 functions is a string, the command is executed through /bin/sh. If it is a list, the command is directly executed. (child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode) ==> p = Popen(["somestring"], shell=True, bufsize=bufsize stdin=PIPE, stdout=PIPE, close_fds=True) (child_stdout, child_stdin) = (p.stdout, p.stdin) (child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode) ==> p = Popen(["mycmd", "myarg"], bufsize=bufsize, stdin=PIPE, stdout=PIPE, close_fds=True) (child_stdout, child_stdin) = (p.stdout, p.stdin) The popen2.Popen3 and popen3.Popen4 basically works as subprocess.Popen, except that: * subprocess.Popen raises an exception if the execution fails * the capturestderr argument is replaced with the stderr argument. * stdin=PIPE and stdout=PIPE must be specified. * popen2 closes all filedescriptors by default, but you have to specify close_fds=True with subprocess.Popen. Nswin32i(s GetStdHandlesSTD_INPUT_HANDLEsSTD_OUTPUT_HANDLEsSTD_ERROR_HANDLE(sGetCurrentProcesssDuplicateHandlesGetModuleFileNames GetVersion(sDUPLICATE_SAME_ACCESSsSW_HIDE(s CreatePipe(s CreateProcesss STARTUPINFOsGetExitCodeProcesssSTARTF_USESTDHANDLESsSTARTF_USESHOWWINDOWsCREATE_NEW_CONSOLE(sWaitForSingleObjectsINFINITEs WAIT_OBJECT_0(s*s STARTUPINFOcBs tZdZeZeZeZRS(Ni(s__name__s __module__sdwFlagssNones hStdInputs hStdOutputs hStdError(((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys STARTUPINFOrss pywintypescBstZeZRS(N(s__name__s __module__sIOErrorserror(((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys pywintypeswssPopensPIPEsSTDOUTscalls SC_OPEN_MAXiicCs xtD]}|iqWdS(N(s_activesinstspoll(sinst((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys_cleanupsiicOst||iSdS(sRun command with arguments. Wait for command to complete, then return the returncode attribute. The arguments are the same as for the Popen constructor. Example: retcode = call(["ls", "-l"]) N(sPopensargsskwargsswait(sargsskwargs((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pyscallscCsSg}t}x3|D]+}g}|o|idnd|jp d|j}|o|idnx|D]}|djo|i|qo|djo2|idt|dg}|idqo|o|i |g}n|i|qoW|o|i |n|o|i ||idqqWdi |SdS( s Translate a sequence of arguments into a command line string, using the same rules as the MS C runtime: 1) Arguments are delimited by white space, which is either a space or a tab. 2) A string surrounded by double quotation marks is interpreted as a single argument, regardless of white space contained within. A quoted string can be embedded in an argument. 3) A double quotation mark preceded by a backslash is interpreted as a literal double quotation mark. 4) Backslashes are interpreted literally, unless they immediately precede a double quotation mark. 5) If backslashes immediately precede a double quotation mark, every pair of backslashes is interpreted as a literal backslash. If the number of backslashes is odd, the last backslash escapes the next double quotation mark as described in rule 3. s s s"s\is\"sN( sresultsFalses needquotesseqsargsbs_bufsappendscslensextendsjoin(sseqscs needquotesresultsargsbs_buf((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys list2cmdlines:     cBstZdeeeeeeeeeeedd ZdZeoOdZdZdZ dZ dZ d Z d Z ed ZnLd Zd ZdZdZ dZdZ dZ edZRS(NicCstt|ttf otdnto8|tj ot dn|ot dqn;| tj ot dn|djot dnt|_t|_t|_t|_t|_| |_|i|||\}}}}}}|i||||| | | | || |||||||ot!i"|d||_n|o?| ot!i"|d||_qt!i"|d ||_n|o?| ot!i"|d||_qt!i"|d ||_nt#i$|d S( sCreate new Popen instance.sbufsize must be an integers0preexec_fn is not supported on Windows platformss/close_fds is not supported on Windows platformss2startupinfo is only supported on Windows platformsis4creationflags is only supported on Windows platformsswbsrUsrbN(%s_cleanups isinstancesbufsizesintslongs TypeErrors mswindowss preexec_fnsNones ValueErrors close_fdss startupinfos creationflagssselfsstdinsstdoutsstderrspids returncodesuniversal_newliness _get_handlessp2creadsp2cwritesc2preadsc2pwriteserrreadserrwrites_execute_childsargss executablescwdsenvsshellsossfdopens_activesappend(sselfsargssbufsizes executablesstdinsstdoutsstderrs preexec_fns close_fdssshellscwdsenvsuniversal_newliness startupinfos creationflagsserrreadsc2preadserrwritesc2pwritesp2creadsp2cwrite((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys__init__sJ         '   cCs,|idd}|idd}|SdS(Ns s s (sdatasreplace(sselfsdata((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys_translate_newlines3sc Cs|tjo|tjo |tjottttttfSnttf\}}ttf\} }ttf\}}|tjot t }n|t jo7t td\}}|i}ti|d}n?t|tijoti|}nti|i}|i|}|tjot t}n|t jo7t td\} }| i} ti| d} n?t|tijoti|}nti|i}|i|}|tjot t}n|t jo7t td\}}|i}ti|d}nV|tjo |}n?t|tijoti|}nti|i}|i|}||| |||fSdS(s|Construct and return tupel with IO objects: p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite iN(sstdinsNonesstdoutsstderrsp2creadsp2cwritesc2preadsc2pwriteserrreadserrwrites GetStdHandlesSTD_INPUT_HANDLEsPIPEs CreatePipesDetachsmsvcrtsopen_osfhandlestypestypessIntTypes get_osfhandlesfilenosselfs_make_inheritablesSTD_OUTPUT_HANDLEsSTD_ERROR_HANDLEsSTDOUT( sselfsstdinsstdoutsstderrserrreadsp2creadsp2cwriteserrwritesc2pwritesc2pread((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys _get_handles=sN'           cCs#tt|tddtSdS(s2Return a duplicate of handle, which is inheritableiiN(sDuplicateHandlesGetCurrentProcessshandlesDUPLICATE_SAME_ACCESS(sselfshandle((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys_make_inheritableys  cCstiitiitdd}tii| oLtiitiitid}tii| ot dqn|SdS(s,Find and return absolut path to w9xpopen.exeis w9xpopen.exesZCannot locate w9xpopen.exe, which is needed for Popen to work with your shell or platform.N( sosspathsjoinsdirnamesGetModuleFileNamesw9xpopensexistsssyss exec_prefixs RuntimeError(sselfsw9xpopen((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys_find_w9xpopens  c Cst|ti ot|}nt}|tjo |}nt| ||fj o.|i t O_ | |_||_||_n| o|i tO_ t|_tiidd}|d|}tdjptii|idjo*|i}d||f}| t!O} q(ny4t"||ttd| ||| \}}}}Wn't*i+j o}t-|inX||_.||_(|i/| tjo| i/n|tjo|i/n|tjo|i/ndS( s$Execute program (MS Windows version)sCOMSPECscmd.exes /c ls command.coms"%s" %siN(0s isinstancesargsstypess StringTypess list2cmdlines STARTUPINFOsdefault_startupinfos startupinfosNonesp2creadsc2pwriteserrwritesdwFlagssSTARTF_USESTDHANDLESs hStdInputs hStdOutputs hStdErrorsshellsSTARTF_USESHOWWINDOWsSW_HIDEs wShowWindowsossenvironsgetscomspecs GetVersionspathsbasenameslowersselfs_find_w9xpopensw9xpopens creationflagssCREATE_NEW_CONSOLEs CreateProcesss executablesenvscwdshpshtspidstids pywintypesserrorses WindowsErrors_handlesClose(sselfsargss executables preexec_fns close_fdsscwdsenvsuniversal_newliness startupinfos creationflagssshellsp2creadsp2cwritesc2preadsc2pwriteserrreadserrwritespidscomspecstidsdefault_startupinfoshpshtsesw9xpopen((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys_execute_childsN       /        cCs[|itjo@t|idtjo#t|i|_ti|qPn|iSdS(sQCheck if child process has terminated. Returns returncode attribute.iN( sselfs returncodesNonesWaitForSingleObjects_handles WAIT_OBJECT_0sGetExitCodeProcesss_activesremove(sself((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pyspolls cCsP|itjo5t|it}t|i|_ti |n|iSdS(sOWait for child process to terminate. Returns returncode attribute.N( sselfs returncodesNonesWaitForSingleObjects_handlesINFINITEsobjsGetExitCodeProcesss_activesremove(sselfsobj((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pyswaits cCs|i|idS(N(sbuffersappendsfhsread(sselfsfhsbuffer((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys _readerthreadscCst}t}|ioEg}tid|id|i|f}|it |i n|ioEg}tid|id|i|f}|it |i n|i o2|tjo|i i|n|i in|io|in|io|in|tjo|d}n|tjo|d}n|io ttdo8|o|i|}n|o|i|}qn|i||fSdS(szInteract with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate. The optional input argument should be a string to be sent to the child process, or None, if no data should be sent to the child. communicate() returns a tuple (stdout, stderr).stargetsargsisnewlinesN(sNonesstdoutsstderrsselfs threadingsThreads _readerthreads stdout_threads setDaemonsTruesstarts stderr_threadsstdinsinputswritesclosesjoinsuniversal_newlinesshasattrsopens_translate_newlinesswait(sselfsinputsstdoutsstderrs stdout_threads stderr_thread((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys communicatesD           c Csttf\}}ttf\} }ttf\}}|tjonP|tjot i \}}n-t |t i jo |}n |i}|tjonP|tjot i \} }n-t |t i jo |}n |i}|tjong|tjot i \}}nD|tjo |}n-t |t i jo |}n |i}||| |||fSdS(s|Construct and return tupel with IO objects: p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite N(sNonesp2creadsp2cwritesc2preadsc2pwriteserrreadserrwritesstdinsPIPEsosspipestypestypessIntTypesfilenosstdoutsstderrsSTDOUT( sselfsstdinsstdoutsstderrserrreadsp2creadsp2cwriteserrwritesc2pwritesc2pread((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys _get_handles1s8              cCs\y ti}Wntj o d}nXti|ti}ti|ti||BdS(Ni(sfcntls FD_CLOEXECs cloexec_flagsAttributeErrorsfdsF_GETFDsoldsF_SETFD(sselfsfdsolds cloexec_flag((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys_set_cloexec_flag^s   cCsMxFtdtD]5}||joqnyti|WqqXqWdS(Ni(srangesMAXFDsisbutsossclose(sselfsbutsi((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys _close_fdshs cCsat|tio |g}n| oddg|}n|tjo|d}nti\}}|i |ti |_|idjoy| oti| n| oti| n|oti|nti|| oti| dn|oti|dn|oti|dn| oti| n|o || fjoti|n|o|| |fjoti|n|o|id|n|tjoti|n|ot|n|tjoti||nti|||Wn\t i!\}}}t%i&|||}di(||_)ti*|t+i,|nXti-dnti|| o| oti| n|o| oti|n|o|oti|nti.|d }ti||djo,ti0|idt+i1|}|nd S( sExecute program (POSIX version)s/bin/shs-ciiisbutsiiN(3s isinstancesargsstypess StringTypessshells executablesNonesosspipes errpipe_reads errpipe_writesselfs_set_cloexec_flagsforkspidsp2cwritesclosesc2preadserrreadsp2creadsdup2sc2pwriteserrwrites close_fdss _close_fdsscwdschdirs preexec_fnsapplysenvsexecvpsexecvpessyssexc_infosexc_types exc_valuestbs tracebacksformat_exceptions exc_linessjoinschild_tracebackswritespicklesdumpss_exitsreadsdataswaitpidsloadsschild_exception(sselfsargss executables preexec_fns close_fdsscwdsenvsuniversal_newliness startupinfos creationflagssshellsp2creadsp2cwritesc2preadsc2pwriteserrreadserrwrites exc_linesschild_exceptions errpipe_writesexc_typestbsdatas errpipe_reads exc_value((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys_execute_childrsz           cCsjti|oti| |_n3ti|oti||_n tdt i |dS(NsUnknown child exit status!( soss WIFSIGNALEDsstssWTERMSIGsselfs returncodes WIFEXITEDs WEXITSTATUSs RuntimeErrors_activesremove(sselfssts((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys_handle_exitstatuss  cCs{|itjo`yCti|iti\}}||ijo|i|nWqpti j oqpXn|iSdS(sQCheck if child process has terminated. Returns returncode attribute.N( sselfs returncodesNonesosswaitpidspidsWNOHANGsstss_handle_exitstatusserror(sselfspidssts((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pyspolls cCsG|itjo,ti|id\}}|i|n|iSdS(sOWait for child process to terminate. Returns returncode attribute.iN(sselfs returncodesNonesosswaitpidspidsstss_handle_exitstatus(sselfspidssts((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pyswaits c Csg}g}t}t} |io9|ii|o|i |iq[|ii n|io|i |ig}n|io|i |ig} nxk|p|o\t i ||g\}} }|i| joVti|ii|d }||}| o!|ii |i|iq8n|i|joZti|iid}|djo!|ii |i|in|i |n|i|joZti|iid}|djo!|ii |i|in| i |qqW|tjodi|}n| tjodi| } n|io ttdo8|o|i|}n| o|i| } qn|i|| fSdS(szInteract with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate. The optional input argument should be a string to be sent to the child process, or None, if no data should be sent to the child. communicate() returns a tuple (stdout, stderr).iissnewlinesN(sread_sets write_setsNonesstdoutsstderrsselfsstdinsflushsinputsappendsclosesselectsrlistswlistsxlistsosswritesfilenos bytes_writtensremovesreadsdatasjoinsuniversal_newlinesshasattrsopens_translate_newlinesswait( sselfsinputsrlistsxlistsstdouts write_setsdatas bytes_writtensread_setsstderrswlist((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys communicates`               (s__name__s __module__sNonesFalses__init__s_translate_newliness mswindowss _get_handless_make_inheritables_find_w9xpopens_execute_childspollswaits _readerthreads communicates_set_cloexec_flags _close_fdss_handle_exitstatus(((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pysPopens&0L  <   P 9 - c cCs.tdgdtid}dGH|GHtidjo&tdgdd}|indGHtd gdt}td d gd |i dt}t |idGHHd GHytdgiGHWnJt j o>}|itijodGHdGH|iGHq*dG|iGHnXtidIJdS(Nspssstdoutis Process list:sids preexec_fncCs tidS(Nid(sosssetuid(((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pysNssLooking for 'hda'...sdmesgsgrepshdasstdinsTrying a weird file...s/this/path/does/not/exists'The file didn't exist. I thought so...sChild traceback:sErrorsGosh. No error.(sPopensPIPEs communicatesplistsossgetuidspswaitsp1sstdoutsp2sreprsOSErrorseserrnosENOENTschild_tracebackssyssstderr(sp2sp1sespsplist((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys _demo_posixBs*! cCsldGHtddtdt}tdd|idt}t|idGHdGHtd }|i dS( Ns%Looking for 'PROMPT' in set output...ssetsstdoutsshells find "PROMPT"sstdinisExecuting calc...scalc( sPopensPIPEsTruesp1sstdoutsp2sreprs communicatespswait(sp2sp1sp((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys _demo_windowsks s__main__(9s__doc__ssyssplatforms mswindowssosstypess tracebacks threadingsmsvcrts pywintypesswin32apis GetStdHandlesSTD_INPUT_HANDLEsSTD_OUTPUT_HANDLEsSTD_ERROR_HANDLEsGetCurrentProcesssDuplicateHandlesGetModuleFileNames GetVersionswin32consDUPLICATE_SAME_ACCESSsSW_HIDEs win32pipes CreatePipes win32processs CreateProcesss STARTUPINFOsGetExitCodeProcesssSTARTF_USESTDHANDLESsSTARTF_USESHOWWINDOWsCREATE_NEW_CONSOLEs win32eventsWaitForSingleObjectsINFINITEs WAIT_OBJECT_0s _subprocesssselectserrnosfcntlspickles__all__ssysconfsMAXFDsFalses NameErrorsTrues_actives_cleanupsPIPEsSTDOUTscalls list2cmdlinesobjectsPopens _demo_posixs _demo_windowss__name__(-sfcntlsSW_HIDEs GetStdHandlesSTDOUTsWaitForSingleObjectsGetExitCodeProcesssGetModuleFileNames pywintypessselectsPIPEs CreatePipesGetCurrentProcesss__all__serrnos _demo_posixs CreateProcesssmsvcrts_cleanupscallsTrues _demo_windowss mswindowssMAXFDs STARTUPINFOs WAIT_OBJECT_0sSTARTF_USESTDHANDLESsPopenssyssINFINITEsDuplicateHandlestypessDUPLICATE_SAME_ACCESSsFalsespickles_actives tracebacks list2cmdlines threadingsSTD_ERROR_HANDLEsCREATE_NEW_CONSOLEsSTARTF_USESHOWWINDOWs GetVersionsSTD_INPUT_HANDLEsossSTD_OUTPUT_HANDLE((s5build/bdist.linux-i686/egg/paste/util/subprocess24.pys?Ts`        +        D^ )   PKZ4Dspaste/util/__init__.pyc; u]Dc@s dZdS(sO Package for miscellaneous routines that do not depend on other parts of Paste N(s__doc__(((s1build/bdist.linux-i686/egg/paste/util/__init__.pys?sPKZ4Apaste/util/import_string.pyc; u]Dc@s%dZdZdZdZdS(s 'imports' a string -- converts a string to a Python object, importing any necessary modules and evaluating the expression. Everything before the : in an import expression is the module path; everything after is an expression to be evaluated in the namespace of that module. Alternately, if no : is present, then import the modules and get the attributes as necessary. Arbitrary expressions are not allowed in that case. cCsYd|jot|Sn|idd\}}t|}t||i}|SdS(Ns:i( sss simple_importssplits module_namesexprs import_modulesmodulesevals__dict__sobj(sssobjsexprsmodules module_name((s6build/bdist.linux-i686/egg/paste/util/import_string.pys eval_imports   cCs|id}t|d}|d}|d}t}xW|oO|d|d7}yt|}|d}Wq<tj o}|}Pq<Xq<W|}x`|oXyt ||d}Wn0t j o$td|d||fnX|d}qW|SdS(Ns.iisECannot find %s in module %r (stopped importing modules with error %s)( ssssplitspartss import_modulesmodulesnamesNoneslast_import_errors ImportErrorsesobjsgetattrsAttributeError(sssesnamesmodulespartssobjslast_import_error((s6build/bdist.linux-i686/egg/paste/util/import_string.pys simple_imports.    "cCsGt|}|id}x!|dD]}t||}q&W|SdS(Ns.i(s __import__sssmodssplitspartsspartsgetattr(ssspartsspartsmod((s6build/bdist.linux-i686/egg/paste/util/import_string.pys import_module0s   N(s__doc__s eval_imports simple_imports import_module(s import_modules eval_imports simple_import((s6build/bdist.linux-i686/egg/paste/util/import_string.pys?s  PKZ4imhJhJpaste/util/intset.pyc; u]Dc@sdZdZdZdZdZdefdYZeeZee Z defdYZ e d jo5e d d fd Z e d d fZe d d fd d dfddddZe GHe d@GHe dBGHe d dfAGHe dGHde jGHe ie GHeie GHe ie GHeie GHxe D] ZeGHq9We iGHe ejGHe ejGHe ejGHee GHeeGHee GHe iGHndS(stImmutable integer set type. Integer set class. Copyright (C) 2006, Heiko Wundram. Released under the MIT license. s Heiko Wundram s0.2s6s 2006-01-20s _InfinitycBs_tZdZdgZdZdZdZdZdZdZ dZ d Z RS( s0Internal type used to represent infinity values.s_negcCs ||_dS(N(snegsselfs_neg(sselfsneg((s/build/bdist.linux-i686/egg/paste/util/intset.pys__init__scCsHt|tttf otSn|iot|to|i SdS(N(s isinstancesvaluesintslongs _InfinitysNotImplementedsselfs_neg(sselfsvalue((s/build/bdist.linux-i686/egg/paste/util/intset.pys__lt__scCs-t|tttf otSn|iSdS(N(s isinstancesvaluesintslongs _InfinitysNotImplementedsselfs_neg(sselfsvalue((s/build/bdist.linux-i686/egg/paste/util/intset.pys__le__$scCsIt|tttf otSn|ipt|to|i SdS(N(s isinstancesvaluesintslongs _InfinitysNotImplementedsselfs_neg(sselfsvalue((s/build/bdist.linux-i686/egg/paste/util/intset.pys__gt__)scCs.t|tttf otSn|i SdS(N(s isinstancesvaluesintslongs _InfinitysNotImplementedsselfs_neg(sselfsvalue((s/build/bdist.linux-i686/egg/paste/util/intset.pys__ge__/scCsFt|tttf otSnt|to|i|ijSdS(N(s isinstancesvaluesintslongs _InfinitysNotImplementedsselfs_neg(sselfsvalue((s/build/bdist.linux-i686/egg/paste/util/intset.pys__eq__4scCsGt|tttf otSnt|t p|i|ijSdS(N(s isinstancesvaluesintslongs _InfinitysNotImplementedsselfs_neg(sselfsvalue((s/build/bdist.linux-i686/egg/paste/util/intset.pys__ne__9scCsdSdS(NsNone((sself((s/build/bdist.linux-i686/egg/paste/util/intset.pys__repr__>s( s__name__s __module__s__doc__s __slots__s__init__s__lt__s__le__s__gt__s__ge__s__eq__s__ne__s__repr__(((s/build/bdist.linux-i686/egg/paste/util/intset.pys _Infinitys         sIntSetcBstZdZddddgZdZeedZdZdZ e d Z e d d d d Z e dd d d Z e dd d d Ze dd ddZe dd ddZe dd ddZe dd ddZe dd ddZe dd ddZe dd ddZe dd ddZe dd ddZe d d!d"d#Ze d$d!d%d&Ze d'd!d(d&dZe d)d!d"d#Ze d*d!d+d#dZe d,d!d-d.d Ze d/d!d0d1Ze d2d!d3d.dZ[ d4Z e Z!d5Z"d6Z#d7Z$d8Z%d9Z&d:Z'RS(;svInteger set class with efficient storage in a RLE format of ranges. Supports minus and plus infinity in the range.s_rangess_mins_maxs_hashcOst|djot|dto_|otdn|di|_|di|_|di |_ |di |_ dSng|_ |i dt |_|i dt |_|itjo t |_n|itjo t |_n|otdnt|ittfp |it j otdnt|ittfp |it j otd n|it j o |it j o|i|ijotd nt|ittfo|id7_nx|D]}t|ttfo||df\}}n>t|to!t|d jotd n|\}}|tjo |i}n|tjo |i}nt|ttfp |t j otd nt|ttfp |t j otdn|t j o|t j o ||joqnt|ttfo|d7}qgn td||ijoqn||ijo |i}n||ijoqn||ijo |i}n|i i||fqW|idS(sInitialize an integer set. The constructor accepts an unlimited number of arguments that may either be tuples in the form of (start,stop) where either start or stop may be a number or None to represent maximum/minimum in that direction. The range specified by (start,stop) is always inclusive (differing from the builtin range operator). Keyword arguments that can be passed to an integer set are min and max, which specify the minimum and maximum number in the set, respectively. You can also pass None here to represent minus or plus infinity, which is also the default. iis*No keyword arguments for copy constructor.NsminsmaxsInvalid keyword argument.sInvalid type of min argument.sInvalid type of max argument.s$Minimum is not smaller than maximum.is$Invalid tuple, must be (start,stop).sInvalid type of tuple start.sInvalid type of tuple stop.sInvalid argument.(slensargss isinstancesIntSetskwargss ValueErrors_minsselfs_maxs_rangess_hashspops_MININFs_MAXINFsNonesintslongs TypeErrorsargsstartsstopstuplesappends _normalize(sselfsargsskwargssstopsstartsarg((s/build/bdist.linux-i686/egg/paste/util/intset.pys__init__Rsr '   **3     $$'   ccs|}hdt<dt<} dt|dt|f\} } ddf\}}x(|| jp || jo || joD|| jo*||d?|d@||d?|d@jp || jo;||d?|d@d|d@ f\} } }|d7}n8||d?|d@d|d@ f\} } }|d7}|| jo,| |joPn| || ffV| }n|| | 'ss__rand__s intersections__or__sUnion of two sets as a new set.cCs|dp|dS(Nsr1sr2(ss(ss((s/build/bdist.linux-i686/egg/paste/util/intset.pys2ss__ror__sunions__sub__s$Difference of two sets as a new set.cCs|do |d S(Nsr1sr2(ss(ss((s/build/bdist.linux-i686/egg/paste/util/intset.pys=ss__rsub__cCs|do |d S(Nsr2sr1(ss(ss((s/build/bdist.linux-i686/egg/paste/util/intset.pys@ss differences__xor__s.Symmetric difference of two sets as a new set.cCs|d|dAS(Nsr1sr2(ss(ss((s/build/bdist.linux-i686/egg/paste/util/intset.pysHss__rxor__ssymmetric_differences __contains__sbools*Returns true if self is superset of other.cCs|dp |d S(Nsr1sr2(ss(ss((s/build/bdist.linux-i686/egg/paste/util/intset.pysSssissubsets(Returns true if self is subset of other.cCs|dp |d S(Nsr2sr1(ss(ss((s/build/bdist.linux-i686/egg/paste/util/intset.pysVss istruesubsets-Returns true if self is true subset of other.s issupersetsistruesupersets/Returns true if self is true superset of other.soverlapss)Returns true if self overlaps with other.cCstS(N(sTrue(ss((s/build/bdist.linux-i686/egg/paste/util/intset.pysdss__eq__s'Returns true if self is equal to other.cCs|d|dA S(Nsr1sr2(ss(ss((s/build/bdist.linux-i686/egg/paste/util/intset.pysjss__ne__s+Returns true if self is different to other.cCs|ii|i}|i|_|i|_g|_|i}xJ|iD]?}||djo(|ii ||df|d}qIqIW||ijo|ii ||ifn|SdS(sInverse of set as a new set.iiN( sselfs __class__s__new__snewsets_mins_maxs_rangesslaststopsrsappend(sselfslaststopsrsnewset((s/build/bdist.linux-i686/egg/paste/util/intset.pysinversets     cCs |iSdS(sReturns a hash value representing this integer set. As the set is always stored normalized, the hash value is guaranteed to match for matching ranges.N(sselfs_hash(sself((s/build/bdist.linux-i686/egg/paste/util/intset.pys__hash__scCs|i odSn|iddtjp|iddtjotdnd}x'|iD]}||d|d7}qcW|ddjotdn|SdS( sGet length of this integer set. In case the length is larger than 2**31 (including infinitely sized integer sets), it raises an OverflowError. This is due to len() restricting the size to 0 <= len < 2**31.iiisInfinitely sized integer set.iisInteger set bigger than 2**31.N(sselfs_rangess_MININFs_MAXINFs OverflowErrorsrlensr(sselfsrlensr((s/build/bdist.linux-i686/egg/paste/util/intset.pys__len__s 0 cCs|i odSn|iddtjp|iddtjodSnd}x'|iD]}||d|d7}q[W|SdS(s<Returns the length of this integer set as an integer. In case the length is infinite, returns -1. This function exists because of a limitation of the builtin len() function which expects values in the range 0 <= len < 2**31. Use this function in case your integer set might be larger.iiiN(sselfs_rangess_MININFs_MAXINFsrlensr(sselfsrlensr((s/build/bdist.linux-i686/egg/paste/util/intset.pyslens 0 cCst|iSdS(s<Returns true if this integer set contains at least one item.N(sboolsselfs_ranges(sself((s/build/bdist.linux-i686/egg/paste/util/intset.pys __nonzero__sccsg}x|iD]}|dtjoS|dtjo#|iddgddgfq|i|dddgq|dtjo|i|ddgqx#t|d|dD] }|VqWqW|o@x=t o1x*|D]"}|dV|dc|d7Zd?Zd@ZdAZdBZdCkZdCkZdCk Z dCk Z dCk Z dCk Z dCk Z dCkZdCkZdCkZy dCkZWndCkZnXe iZe iZeiZe iZe iZe idDZe idEZe idFZe idGZe idHZe idIZe idJZ e idKZ!e idLZ"e idMZ#e idNZ$e idOZ%e idPZ&e idQZ'e idRZ(e idSZ)e idTZ*e idUZ+e idVZ,e idWZ-e idXZ.e idYZ/e idZZ0e id[Z1e id\Z2e id]Z3e id^Z4e id_Z5e id`Z6heda<e-db<e,dc<edd<ede<edf<edg<edh<edi<edj<edk<edl<edm<e dn<e!do<e"dp<e#dq<e$dr<e%ds<e&dt<e'du<e(dv<e)dw<e*dx<e.dy<e/dz<e0d{<e1d|heddd}f<e-ddd}f<e,ddd}f<ed}d~d}f<ed}dd}f<ed}dd}f<ed}d~d}f<e/d}d~d}f<e.d}d~d}f<ed}dd}f<ed}dd}f<eddd}f<eddd}f<eddd}f<ed}dd}f<e d}dd}f<e!d}dd}f<e"d}dd}f<e#d}dd}f<e$d}dd}f<e%d}dd}f<e&d}dd}f<e'd}dd}f<e(d}dd}f<e)d}dd}f<e*d}dd}f<e1d}dd}f<e0dd~d}f<e+dti#555555s#FFFFFFss#FF0000s#FF8080sbusbs#555555sis#999999s#FFBBAAs#CC5511s#DDDDFFs#DDDDDDs#FF0000s#FAF785s#45FCA0s#A7C7A9s#B666FDs#EBAE5Cs#8680FFs#F8BAFEs#FF80C0s#FF9595s#B3FFFFs >mi#555555s#bbccbbs#333333s#C0C0C0s#00FF00s#FF090Fs#EE7020s#FFB90Fs#D0D000s#522000s#DD4080s#FF8040s#4726d1s#8080C0s#ADB9F1s#00C1C1s#33E3E3s#BB4422s#3333AFs#DD2200s#007F00s#608060s#0000DFs#9C7A00s#0000AFs#600080s#A0008As#337799s#1166AAs#900090s#FF7700s#DD0000s#0000FFs#00AA00s#DD0080s#000080s#303030s#008080s#7F7F7Fs#007F7Fs#808000s#b22222s#0000ffs#a020f0s#bc8f8fcCs d}|tGHtiddS(Ns ----------------------------------------------------------------------------- PySourceColor.py ver: %s ----------------------------------------------------------------------------- Module summary: This module is designed to colorize python source code. Input--->python source Output-->colorized (html, html4.01/css, xhtml1.0) Standalone: This module will work from the command line with options. This module will work with redirected stdio. Imported: This module can be imported and used directly in your code. ----------------------------------------------------------------------------- Command line options: -h, --help Optional-> Display this help message. -t, --test Optional-> Will ignore all others flags but --profile test all schemes and markup combinations -p, --profile Optional-> Works only with --test or -t runs profile.py and makes the test work in quiet mode. -i, --in, --input Optional-> If you give input on stdin. Use any of these for the current dir (.,cwd) Input can be file or dir. Input from stdin use one of the following (-,stdin) If stdin is used as input stdout is output unless specified. -o, --out, --output Optional-> output dir for the colorized source. default: output dir is the input dir. To output html to stdout use one of the following (-,stdout) Stdout can be used without stdin if you give a file as input. -c, --color Optional-> null, mono, dark, dark2, lite, idle, pythonwin, viewcvs default: dark -s, --show Optional-> Show page after creation. default: no show -m, --markup Optional-> html, css, xhtml css, xhtml also support external stylesheets (-e,--external) default: HTML -e, --external Optional-> use with css, xhtml Writes an style sheet instead of embedding it in the page saves it as pystyle.css in the same directory. html markup will silently ignore this flag. -H, --header Opional-> add a page header to the top of the output -H Builtin header (name,date,hrule) --header You must specify a filename. The header file must be valid html and must handle its own font colors. ex. --header c:/tmp/header.txt -F, --footer Opional-> add a page footer to the bottom of the output -F Builtin footer (hrule,name,date) --footer You must specify a filename. The footer file must be valid html and must handle its own font colors. ex. --footer c:/tmp/footer.txt -l, --linenumbers Optional-> default is no linenumbers Adds line numbers to the start of each line in the code. --convertpage Given a webpage that has code embedded in tags it will convert embedded code to colorized html. (see pageconvert for details) ----------------------------------------------------------------------------- Option usage: # Test and show pages python PySourceColor.py -t -s # Test and only show profile results python PySourceColor.py -t -p # Colorize all .py,.pyw files in cwdir you can also use: (.,cwd) python PySourceColor.py -i . # Using long options w/ = python PySourceColor.py --in=c:/myDir/my.py --color=lite --show # Using short options w/out = python PySourceColor.py -i c:/myDir/ -c idle -m css -e # Using any mix python PySourceColor.py --in . -o=c:/myDir --show # Place a custom header on your files python PySourceColor.py -i . -o c:/tmp -m xhtml --header c:/header.txt ----------------------------------------------------------------------------- Stdio usage: # Stdio using no options python PySourceColor.py < c:/MyFile.py > c:/tmp/MyFile.html # Using stdin alone automatically uses stdout for output: (stdin,-) python PySourceColor.py -i- < c:/MyFile.py > c:/tmp/myfile.html # Stdout can also be written to directly from a file instead of stdin python PySourceColor.py -i c:/MyFile.py -m css -o- > c:/tmp/myfile.html # Stdin can be used as input , but output can still be specified python PySourceColor.py -i- -o c:/pydoc.py.html -s < c:/Python22/my.py _____________________________________________________________________________ i(sdocs __version__ssyssexit(sdoc((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pysUsage8sf cCsJyPtitiddddddddd d d d d dddg\}}Wntij otnXt}t}t} d} t}t} d}d}d} d}d}d}t}xF|D]>\}} |ddgjottin|dddgjo | }n|dddgjo-| }|ddgjoti}q\n|ddgjo d}n|dd gjo d} n|d!d"gjo d}n|d#gjo d}n|d$d%gjo d}n|d&d'gjo d}n|d(d)gjot| } n|d*d+gjo d}n|d,gjot| }n|d-jo d.}n|d/gjot| } n|d0jo d.} n|d1d2gjo;yti| i} WqtitqXqqW|o<|o$d3k}|i d4|| fqFt!|| n|td5d6gjp|d5d7gjo6|td5d6gjoRti"i#|o2t$|d8| d9| d|d:|d;| d<|qt%d=qFyti&i'o t(d>n|td5d7gjo;t)ti&i*d8| d9| d:|d;| d|d<|n>t+ti&i*d?|d|d9| d:|d;| d|d<|WqFtitqFXnti"i,|oz|o,t-|d@|d8| d|d9| d|qFt.dA|dB|d8| d|d9| d| d:|d;| d|d<| nt%d=td3S(Cs)Handle command line args and redirectionsishseqtplHFi:o:c:m:h:f:shelpsshowsquietstestsexternals linenumberss convertpagesprofilesinput=soutput=scolor=smarkup=sheader=sfooter=shtmlis-hs--helps-os--outputs--outs-is--inputs--ins.scwds-ss--shows-qs--quiets-ts--tests --convertpages-ps --profiles-es --externals-ms--markups-ls --linenumberss--headers-Hss--footers-Fs-cs--colorNs_test(show=%s, quiet=%s)s-sstdinsstdoutscolorssmarkupsheadersfootersformsFile does not exists!sPlease check input!soutfilesoutssourcesoutdir(/sgetoptssyssargvsoptssargss GetoptErrorsUsagesNonesinputsoutputs colorschemesmarkupsheadersfooters linenumberssshowsquietstestsprofiles convertpagesformsosasexitsossgetcwdsstrsglobalssgetslowers tracebacks print_excsruns_testspathsisfiles path2stdouts PathErrorsstdinsisattys InputErrors str2stdoutsreadsstr2filesexistss pageconvertsconvert(sshowsheaders convertpagestestsinputsprofilesformsargss linenumberssasfootersmarkups colorschemesquietsosoutputsopts((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pysclis@                )       icCs1tid}|id ot|dtd|d|t|dtd|ddd|t|d td|d|t|d td|ddd|t|d t d|d|t|d t d|ddd|d dddddt|dt d|ddd|t|dt d|d|t|dt d|ddd|ddt|dt d|d|t|dt d|ddd|t|dt d|ddd|d dddddddt|dt d|d|t|dt d|ddd|t|dt d|d|ddt|dt d|ddddd|t|dtd|d|t|d td|ddd|d!}tiid"}t||d#t dddd$d|td%||tiid&}t||d#t ddd|td%||ntd'Sd'S((sTest the parser and most of the functions. There are 19 test total(eight colorschemes in three diffrent markups, and a str2file test. Most functions are tested by this. is.exes/tmp/null.htmlsshowsquiets/tmp/null_css.htmlsmarkupscsss/tmp/mono.htmls/tmp/mono_css.htmls/tmp/lite.htmls/tmp/lite_css.htmlsheaderssfooters linenumbersis/tmp/lite_xhtml.htmlsxhtmls/tmp/dark.htmls/tmp/dark_css.htmls/tmp/dark2.htmls/tmp/dark2_css.htmls/tmp/dark2_xhtml.htmlsformsexternals/tmp/idle.htmls/tmp/idle_css.htmls/tmp/viewcvs.htmls/tmp/viewcvs_css.htmls/tmp/pythonwin.htmls/tmp/pythonwin_css.htmls"""This is a test of decorators and other things""" # This should be line 421... @whatever(arg,arg2) @A @B(arghh) @C def LlamaSaysNi(arg='Ni!',arg2="RALPH"): """This docstring is deeply disturbed by all the llama references""" print '%s The Wonder Llama says %s'% (arg2,arg) # So I was like duh!, and he was like ya know?!, # and so we were both like huh...wtf!? RTFM!! LOL!!;) @staticmethod## Double comments are KewL. def LlamasRLumpy(): """This docstring is too sexy to be here. """ u""" ============================= A Mse once bit my sister... ============================= """ ## Relax, this won't hurt a bit, just a simple, painless procedure, ## hold still while I get the anesthetizing hammer. m = {'three':'1','won':'2','too':'3'} o = r'fishy\fishy\fishy/fish\oh/where/is\my/little\..' python = uR""" No realli! She was Karving her initials n the mse with the sharpened end of an interspace tthbrush given her by Svenge - her brother-in-law -an Oslo dentist and star of many Norwegian mvies: "The Ht Hands of an Oslo Dentist", "Fillings of Passion", "The Huge Mlars of Horst Nordfink"...""" RU"""142 MEXICAN WHOOPING LLAMAS"""#<-Can you fit 142 llamas in a red box? n = u' HERMSGERVRDENBRTBRDA ' + """ YUTTE """ t = """SAMALLNIATNUOMNAIRODAUCE"""+"DENIARTYLLAICEPS04" ## We apologise for the fault in the ## comments. Those responsible have been ## sacked. y = '14 NORTH CHILEAN GUANACOS \ (CLOSELY RELATED TO THE LLAMA)' rules = [0,1,2,3,4,5] print ys/tmp/strtest_lines.htmlscolorsis wrote %ss/tmp/strtest_nolines.htmlN(ssyssargvsfisendswiths path2filesnullsshowsquietsmonoslitesdarksdark2sidlesviewcvss pythonwinsteststrsosspathsabspathshtmlPathsstr2files _printinfosUsage(sshowsquietshtmlPathsteststrsfi((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys_tests\   % shtmlcCs;t|d|d|d|d|d|d|i|dS(sConverts a code(string) to colorized HTML. Writes to stdout. form='code',or'snip' (for "
yourcode
" only) colors=null,mono,lite,dark,dark2,idle,or pythonwin scolorsstitlesmarkupsheadersfooters linenumbersN( sParsers sourcestringscolorsstitlesmarkupsheadersfooters linenumberssformatsform(s sourcestringscolorsstitlesmarkupsheadersfooters linenumberssform((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys str2stdoutvs c CsMt|i}t|d|d|d|d|d|d|i |dS(sConverts code(file) to colorized HTML. Writes to stdout. form='code',or'snip' (for "
yourcode
" only) colors=null,mono,lite,dark,dark2,idle,or pythonwin scolorsstitlesmarkupsheadersfooters linenumbersN( sopens sourcepathsreads sourcestringsParserscolorssmarkupsheadersfooters linenumberssformatsform( s sourcepathstitlescolorssmarkupsheadersfooters linenumberssforms sourcestring((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys path2stdouts c Csdti}t|d|d|d|d|d|d|d|i ||i d|i Sd S( sConverts a code(string) to colorized HTML. Returns an HTML string. form='code',or'snip' (for "
yourcode
" only) colors=null,mono,lite,dark,dark2,idle,or pythonwin scolorsstitlesoutsmarkupsheadersfooters linenumbersiN(sStringIOsstringIOsParsers sourcestringscolorsstitlesmarkupsheadersfooters linenumberssformatsformsseeksread( s sourcestringscolorsstitlesmarkupsheadersfooters linenumberssformsstringIO((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pysstr2htmls  scssc Cs|iddgjo d}nti} t|d|d|d| d|d|d|d |}|i || id |tjo |id d | ifSnt| ifSd S(sConverts a code string to colorized CSS/HTML. Returns CSS/HTML string If form != None then this will return (stylesheet_str, code_str) colors=null,mono,lite,dark,dark2,idle,or pythonwin scsssxhtmlscolorsstitlesoutsmarkupsheadersfooters linenumbersisexternaliN(smarkupslowersStringIOsstringIOsParsers sourcestringscolorsstitlesheadersfooters linenumberssparsesformatsformsseeksNones _sendCSSStylesread( s sourcestringscolorsstitlesmarkupsheadersfooters linenumberssformsparsesstringIO((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pysstr2csss         sxhtmlcCs|idjo>tt|d|d|d|d|d|d|d|fSn5t |d|d|d|d|d|d|d|Sd S( sD Convert code strings into ([stylesheet or None], colorized string) shtmlscolorsstitlesheadersfootersmarkups linenumberssformN( smarkupslowersNonesstr2htmls sourcestringscolorsstitlesheadersfooters linenumberssformsstr2css(s sourcestringscolorsstitlesmarkupsheadersfooters linenumberssform((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys str2markupsc Cst|d|ddd|d|d|d|d| \}} t |d } | i | | i|tjo| oQtii|} tii| d }t |d } | i || in|ot|nd S( s[Converts a code string to a file. makes no attempt at correcting bad pathnames scolorsstitlessmarkupsheadersfooters linenumberssformswts pystyle.cssN(s str2markups sourcestringscolorssmarkupsheadersfooters linenumberssformscssshtmlsopensoutfilesfs writelinessclosesNonesdosheetsosspathsdirnamesdirsjoinsoutcsssshowsshowpage(s sourcestringsoutfilescolorsstitlesmarkupsheadersfooters linenumberssshowsdosheetsformsfshtmlsdirsoutcssscss((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pysstr2files   c Cssti}t|i}t||d|d|d|d|d|d|i ||id|iSdS( sConverts code(file) to colorized HTML. Returns an HTML string. form='code',or'snip' (for "
yourcode
" only) colors=null,mono,lite,dark,dark2,idle,or pythonwin stitlesoutsmarkupsheadersfooters linenumbersiN(sStringIOsstringIOsopens sourcepathsreads sourcestringsParserscolorssmarkupsheadersfooters linenumberssformatsformsseek( s sourcepathscolorssmarkupsheadersfooters linenumberssforms sourcestringsstringIO((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys path2htmls  c Cs@d} tii| oVtii|o6| d7} t||||||| |||| q<tdnt|} | tjo|tjo;tii|ddjotii|d}qnx@| D]8} | d7} t| |||||| |||| qWtdt| |ntd|dS(s{Takes a file or dir as input and places the html in the outdir. If outdir is none it defaults to the input dir iisFile does not exist!ssCompleted colorizing %s files.sNo files to convert in dir.N(scountsosspathsisdirssourcesisfiles path2filesoutdirscolorssshowsmarkupsquietsformsheadersfooters linenumberss PathErrorswalkdirsfileListsNonessplitextssplitsitems _printinfosstr( ssourcesoutdirscolorssshowsmarkupsquietsheadersfooters linenumberssformscountsfileListsitem((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pysconverts(      c  Cs|tjo|d} ntii|ddjoTtii| oti|ntii |}tii ||d} nBtii |d}tii| oti|n|} tii| } t|i}t|||t| d|||| } | i|td| ||djo| djo |djon| idd} tii tii | d }t|d}|i#| |i$td ||n|ot&| n| Sd S( s$ Converts python source to html files.htmlisiswts wrote %ssexternalshtmls pystyle.csss wrote %sN('soutsNones sourcePathshtmlPathsosspathssplitextsisdirsmakedirssbasenames sourceNamesjoinssplitsoutdirsabspathsopensreadssourcesParserscolorssmarkupsheadersfooters linenumberssparsesformatsforms _printinfosquietscounts _sendCSSStylescssSheetsdirnamescssPathscssswritesclosesshowsshowpage(s sourcePathsoutscolorssshowsmarkupsquietsformsheadersfooters linenumbersscountshtmlPathsparsescssSheetssources sourceNamescsssoutdirscssPath((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys path2file s8  '!  sss pystyle.cssc Csx|idjoCd} | |} |i| djo|id| d}qVn|i|}|i|}|o||joxt |D]}|i|} |i|}|| t||!}t|}t|d|d|d|d d \} }|| } ||t|} d i| || g}qWqXtd ||n| o t} n| |fSd S(sBThis is a helper function for pageconvert. Returns css, page. shtmls9isiscolorss linenumberssmarkupsformsembedssTag mismatch! Check %s,%s tagsN(smarkupslowerslinks stylesheetscsss sourcestrsfindsreplacescountstagstarts starttagsstagendsendtagssranges_s datastartsdataendslensdatasunescapes str2markupscolorss linenumberssstartsendsjoins InputErrorsdosheetsNone(s sourcestrscolorssmarkups linenumberssdosheetstagstartstagends stylesheetsdataendsendsstartscssslinks datastartsdatas_sendtagss starttags((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys tagreplace5s2        spystylec Cs|tjotii|}nt|di} td| d|d|d|d|d|d|d |\} }| o&tiitii|d tii|}tii| o+ytitii|WqqXnt|d }|i||i| oRtiitii|d d |} t| d }|i| |in| o)yti|Wqt i!qXn|Sn | |fSd S(sdThis function can colorize Python source that is written in a webpage enclosed in tags. srs sourcestrscolorssmarkups linenumberssdosheetstagstartstagends stylesheetstmpsws%s.cssN("soutsNonesosspathsdirnamesopensreadsinfiles tagreplacescolorssmarkups linenumberssdosheetstagstartstagends stylesheetscssspages returnstrsabspathsjoinsbasenamesnewpathsexistssmakedirssyswritesclosescsspathsxsshows startfiles tracebacks print_exc(spathsoutscolorssmarkups linenumberssdosheetstagstartstagends stylesheetsshows returnstrsinfilescssscsspathsnewpathsysxspage((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys pageconvertSs: 0  ( cCstii|d}ti|}gi}|D]4}|i dp |i do||q2q2~}|gjo|Snt SdS(sReturn a list of .py and .pyw files from a given directory. This function can be written as a generator Python 2.3, or a genexp in Python 2.4. But 2.2 and 2.1 would be left out.... s *.[p][y]*s.pys.pywN( sosspathsjoinsdirs GLOB_PATTERNsglobspathlistsappends_[1]sxsendswiths filterlistsNone(sdirs_[1]spathlists filterlistsxs GLOB_PATTERN((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pyswalkdir}sK cCs5ytitii|WntinXdS(s Helper function to open webpagesN(s webbrowsersopen_newsosspathsabspaths tracebacks print_exc(spath((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pysshowpages cCs| o |GHndS(sHelper to print messagesN(squietsmessage(smessagesquiet((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _printinfoscCs>|idd}|idd}|idd}|SdS(s+escape text for html. similar to cgi.escapes&s&ss>N(stextsreplace(stext((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pysescapes cCsP|idd}|idd}|idd}|idd}|Sd S( sunsecape escaped texts"s"s>s>s<sERROR: %s%s N(#sformsselfsaddEndssexternalslinessposs dolinenumss LINENUMHOLDERs extraspacesstartsnewlinessraws splitlinessls startswithsappendsmarkups LINESTARTsjoinsfindslensStringIOstexts _doPageStarts_doSnippetStartstokenizesreadlines TokenErrorsexsmsgslinesoutswrites _doPageEnds _doSnippetEnd( sselfsformstextslinessposslsstartsexsmsgslinesnewlines((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pysformatsZ         0     - cCs |\}}|\}} ||_|i}|i||}|t ||_|t itifjoRd|_|_|iddgjo|iidn|iiddSn||jo,|i||!iof|i|ijo|i|ijo|ii|i||!q|ii|i|d|!q|i||!id|}|ii|i||!t|d |itd|id7_|iddgjo|iidn|ii|i|d|!n|t i t i!fjo||_dSnt i"|jo |t i#joX|d jot$}d|_|_q |i%oB|d jo|io d |_q|d jo d|_qn|i&o|ddd dddgjo t'}q |i(o=|dddddddddddddd d!d"d#gjo t)}q t}|djo |id jo d|_q |d$jo |idjo d |_q n|t*jo t+i,|ot-}|d%d&gjo|d%jo||id% i.d' od|_/|_qR|d&jo||id& i.d' od|_0|_qRt1}q n|i/p|i0p|io|i2o[|i/od|_/t3}q |i0od|_0t4}q |iod|_t5}q n=|t i6jo|i7} | d( d)jo t9}nn| d* d+jo t:}nS| d* d,jp| d- d.jo t;}n'| d d/jo t<}n | d d0jo t=}n| d d1jp| d( d2jo t>}n| d( d3jo t?}n| d* d4jo t@}n| d* d5jp| d- d6jo tA}nc| d d7jo tB}nH| d d8jo tC}n-| d d9jp| d( d:jo tD}n|ii7d;jo t1}q nu|tEjo|d d<jo tF}n|d( d=jotG}d>|_H|d(}n]|d( d?jotG}d@|_H|d(}n/|d( dAjotG}dB|_H|d(}n|iIo|idC}|dDjo|| } ||d*}|id$} |id}||d}|| }| dDjo:|iPd$d} dE| | d| diR|f}q(dE| |||f}q,q n|t1jo|io |io|ii|dSq |io3|iSod|_SdSq|ii|dSq |d jot$}d|_|_q n?|id jo!|t*jo|dFjo|i%o tT}n||i|igjoBtU}||ijo|iV p ||ijo d|_Sqp n|dGjodSn||_|tFtEfjo*|idHdDjotW|}q n|tGjon tW|}t|d |i||dSdS(Is3Token handler. Order is important do not rearrange.isXHTMLsCSSss Nis\s _send%sTexts@s(is:s[s]s)s{s}s*=s**=s-=s+=s|=s%=s>>=s<<=s=s^=s/=s+s-s**s*s/s%s,sclasssdefs.is"""isr"""su"""isur"""s"sr"su"sur"s'''sr'''su'''sur'''s'sr'su'sur'srus##s#$#sSPANs#%#sDIVs#@#sRAWsurl(is%s%s%ssNoness s
(sselfsmarkupsoutswritescolorssgets	CODESTART(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys_doSnippetStart3scCs#|ii|iitddS(Ns
(sselfsoutswritescolorssgetsCODEEND(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _doSnippetEnd;scCsKy)t|d}|i}|iWntid}nX|SdS(Nsrs(sopensfilepaths_filesreadscontentscloses tracebacks print_exc(sselfsfilepaths_filescontent((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys_getFileAs   cCst|d|idS(Ns _do%sStart(sgetattrsselfsmarkup(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _doPageStartKscCs|itjo|iiddjp/|iiddjp|iiddjo|ii|idq|idjo|i|i|_nt|d|indS(Ns#$#is#%#iss _do%sHeader( sselfsheadersNonesfindsoutswrites_getFilesgetattrsmarkup(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _doPageHeaderNs KcCs|itjo|iiddjp/|iiddjp|iiddjo|ii|idq|idjo|i|i|_nt|d|indS(Ns#$#is#@#s#%#iss _do%sFooter( sselfsfootersNonesfindsoutswrites_getFilesgetattrsmarkup(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _doPageFooterYs KcCst|d|idS(Ns_do%sEnd(sgetattrsselfsmarkup(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _doPageEnddscCs3|i}|id7_t|iddSdS(Niis (sselfslinenumsnumsstrsrjust(sselfsnum((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys_getLineNumberjs cCs"|ii||itdSdS(Ni(sselfscolorssgetskeysNAME(sselfskey((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys_getTagsoscCsC|ii||itd}|d djo d}n|SdS(Nis#s#000000(sselfscolorssgetskeysNAMEscolor(sselfskeyscolor((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _getForeColorss  cCs"|ii||itdSdS(Ni(sselfscolorssgetskeysNAME(sselfskey((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _getBackColorzscCs|iitdSdS(Ns#FFFFFF(sselfscolorssgetsPAGEBACKGROUND(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _getPageColor~scCs|ii||itSdS(N(sselfscolorssgetskeysNAME(sselfskey((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _getStylescCsti|ttSdS(N(s MARKUPDICTsgetskeysNAME(sselfskey((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys_getMarkupClassscCsdtttifSdS(Ns1 (s __title__s __version__stimesctime(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys_getDocumentCreatedByscCs|iid|iid|i|ii|i|iid|iid|i|i|iiddS(Ns3 s%s sH s s
(sselfsoutswritestitles_getDocumentCreatedBys
_getPageColors
_doPageHeader(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys_doHTMLStarts
c	Cs|ii||itd \}}g}g}d|jo|i	d|i	dnd|jo|i	d|i	dnd|jo|i	d	|i	d
n|i
di|}di|}|||fSdS(Nisbsssisssusss(sselfscolorssgetstoktypesNAMEstagsscolorstagstartstagendsappendsreversesjoins	starttagssendtags(	sselfstoktypestoktextstagsscolorstagstartstagendsendtagss	starttags((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys_getHTMLStyless &






cCs|i}|tjo
d}nd}|i||\}}
}|i
|io:|tjo|i
|i}n|i
|id}g}|i|id|it|\}}}t|}x|D]}|i}|o#|i}d|||f}	n|}	|djoddf\}
}ndi|
d|d||	|d	|g	}|i||qWdi|}n|d
jod||f}
d	}nddf\}
}|tjo,|i i!di|
|||
|gn|i i!|dSdS(Ns% style="border: solid 1.5pt #FF0000;"ss is%sisss#000000s("sselfsnumberlinksstoktypes
ERRORTOKENsstyles_getHTMLStylesstoktextsstarttagsendtagscolorscounts
LINENUMHOLDERs
LINENUMBERssplits	splittextsstoresappendspops	lstarttagslendtagslcolorslensitems_getLineNumbersnumsstripsnumstripscontentsjoins
linenumbers	startfontsendfontsoutswrite(sselfstoktypestoktextscolorsnums	splittextsstylesstarttags	lstarttagscontents	startfontsstorescountsendtagsnumstripsendfontsnumberlinksslendtagslcolorsitems
linenumber((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys
_sendHTMLTextsB	



*


,cCsd|idjo|iid|in6|it}|iid||iti	fdS(Nss%s
sM# %s                             
# %s

( sselfsheadersoutswrites _getForeColorsNAMEscolorstitlestimesctime(sselfscolor((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _doHTMLHeaderscCsd|idjo|iid|in6|it}|iid||iti fdS(Nss%s sM
# %s
# %s
( sselfsfootersoutswrites _getForeColorsNAMEscolorstitlestimesctime(sselfscolor((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _doHTMLFooterscCs.|iid|i|iiddS(Ns
s (sselfsoutswrites _doPageFooter(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _doHTMLEnds c Cs|i|\}}}g}t} t}|i }|od|jo=|i d}|d}|||!}|i|ddnd|jo|idn|idd|jo|id nd |jo|id nd |jo d } n5d|jo d} nd|jo d} nd} d|jo d} nd|jo d} nd|jo d} ntd|jo d} n]d|jo d} nFd|jo d} n/d|jo d} nd |jo d!} nd"} x5d#d$d%d&gD]!} | |jo| d7} q q W| d"jo| o|id'| | fq&| tjo d!} nd&|jo|id(| | fnd#|jo|id)| | fnd$|jo|id*| | fnd%|jo|id+| | fq&n|id|o|id,|n|id-||o|id.|n|i|d/i|fSdS(0Ns#isisbsfont-weight:bold;sfont-weight:normal;sisfont-style:italic;sustext-decoration:underline;slsthicksmsmediumststhinsnsinsetsosoutsetsrsridgesgsgrooves=sdoubles.sdotteds-sdashedssssolidiss^svsborder: %s %s;sborder-bottom:%s %s;sborder-left:%s %s;sborder-right:%s %s;sborder-top:%s %s;sborder-color:%s;s color:%s;sbackground-color:%s;s (sselfs _getStyleskeystagss forecolors backcolorsstylesNonesborders bordercolorslowersfindsstartsendsreplacesappendssizesseperate_sidesssides_getMarkupClasssjoin( sselfskeys bordercolorsstylesendstagssstarts forecolors backcolorsseperate_sidessborderssidessize((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _getCSSStyle s                                      cCsg}||i7}| o|idn|id|ix(tD] }|id|i|qJW|i|ii t d|i|ii t d|i o|idndi |SdS(s* create external and internal style sheetss N( sstylessexternalsselfsappends _getPageColors MARKUPDICTskeys _getCSSStylescolorssgetsPYsCSSHOOKsjoin(sselfsexternalsstylesskey((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _sendCSSStyle]s  cCs|iid|iid|i|ii|i|iid|i|iid|i|ii|iit ddSdS(Ns3 s%s sH s s
(
sselfsoutswritestitles_getDocumentCreatedBys_doCSSStyleSheets
_doPageHeaderscolorssgets	CODESTART(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys_doCSSStartvs

cCs=|io|ii|in|iiddSdS(Ns:(sselfsexternalsoutswrites
_sendCSSStyle(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys_doCSSStyleSheetscCs2ti|tt}||ijo
|tjo|i	i
ddSn|i|iotittt}d|}|tjo|i|i}n|i|id}g}|i|idxv|D]n}|i}|io#|i}
d|
|
|f}	n|}	di||	dg}|i||qWdi|}n|i|iog}|i|id}
|
id}|id}|d	jo|| d
||}n|i|x}|
D]u}|i!o|i"dd|}nd||f}|id}|d	jo|| d
}n|i|qWdi|}n|tjo|t#jo
|i$djod|}d}nD|t#jo
|i$djoddf\}}nd|}d}|i	i
di|||gn|i	i
|dSdS(Nsss is%ssss
isss%ss
sDIVs
s
sRAW('s MARKUPDICTsgetstoktypesNAMEs markupclassstoktextsselfs LINESTARTs LINENUMBERsoutswritescounts LINENUMHOLDERs newmarkups lstartspanssplits splittextsstoresappendspopsitems_getLineNumbersnums numberlinkssstripsnumstripscontentsjoins linenumberspartssfirstsrfindsposs dolinenumssreplacesTEXTstextFlags startspansendspan(sselfstoktypestoktexts newmarkupspossnums splittexts markupclasss lstartspanscontentspartssendspansstoresnumstrips startspansitems linenumbersfirst((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _sendCSSTextsh              &cCsd|idjo|iid|in6tit}|iid||it i fdS(Nss%s s)
# %s
# %s

( sselfsheadersoutswrites MARKUPDICTsgetsNAMEsnamestitlestimesctime(sselfsname((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _doCSSHeaderscCs^|idjo|iid|in0|iidtit|iti fdS(Nss%s s)
# %s
# %s
( sselfsfootersoutswrites MARKUPDICTsgetsNAMEstitlestimesctime(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _doCSSFooterscCsA|ii|iitd|i|iiddSdS(Ns
s (sselfsoutswritescolorssgetsCODEENDs _doPageFooter(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _doCSSEnds cCs|iid|iid|i|ii|i|iid|i|iid|i|ii|iit ddSdS(Ns s%s sI s s
(
sselfsoutswritestitles_getDocumentCreatedBys_doXHTMLStyleSheets
_doPageHeaderscolorssgets	CODESTART(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys
_doXHTMLStarts

cCs=|io|ii|in|iiddSdS(Ns<
(sselfsexternalsoutswrites
_sendCSSStyle(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys_doXHTMLStyleSheet
scCs|i||dS(N(sselfs_sendCSSTextstoktypestoktext(sselfstoktypestoktext((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys_sendXHTMLTextscCs^|io|iid|in6tit}|iid||it	i
fdS(Ns%s
s,
# %s
# %s

( sselfsheadersoutswrites MARKUPDICTsgetsNAMEsnamestitlestimesctime(sselfsname((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys_doXHTMLHeaders cCsX|io|iid|in0|iidtit|iti fdS(Ns%s s+
# %s
# %s
( sselfsfootersoutswrites MARKUPDICTsgetsNAMEstitlestimesctime(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys_doXHTMLFooter$s cCs|idS(N(sselfs _doCSSEnd(sself((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys _doXHTMLEnd,s(,s__name__s __module__s__doc__sNonessyssstdouts__init__sformats__call__s_doSnippetStarts _doSnippetEnds_getFiles _doPageStarts _doPageHeaders _doPageFooters _doPageEnds_getLineNumbers_getTagss _getForeColors _getBackColors _getPageColors _getStyles_getMarkupClasss_getDocumentCreatedBys _doHTMLStarts_getHTMLStyless _sendHTMLTexts _doHTMLHeaders _doHTMLFooters _doHTMLEnds _getCSSStyles _sendCSSStyles _doCSSStarts_doCSSStyleSheets _sendCSSTexts _doCSSHeaders _doCSSFooters _doCSSEnds _doXHTMLStarts_doXHTMLStyleSheets_sendXHTMLTexts_doXHTMLHeaders_doXHTMLFooters _doXHTMLEnd(((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pysParsersP !$ H               < R   Q     s__main__(^s__doc__s__all__s __title__s __version__s__date__s __author__s __credits__sosssysstimesglobsgetoptskeywordstokenstokenizes tracebacks webbrowsers cStringIOsStringIOsNAMEsNUMBERsCOMMENTsOPsOPERATORs ERRORTOKENs NT_OFFSETsARGSs DOUBLECOMMENTs CLASS_NAMEsDEF_NAMEsKEYWORDs SINGLEQUOTEs SINGLEQUOTE_Rs SINGLEQUOTE_Us DOUBLEQUOTEs DOUBLEQUOTE_Rs DOUBLEQUOTE_UsTRIPLESINGLEQUOTEsTRIPLESINGLEQUOTE_RsTRIPLESINGLEQUOTE_UsTRIPLEDOUBLEQUOTEsTRIPLEDOUBLEQUOTE_RsTRIPLEDOUBLEQUOTE_UsPAGEBACKGROUNDs DECORATORsDECORATOR_NAMEsBRACKETSs MATH_OPERATORs LINENUMBERsTEXTsPYs CODESTARTsCODEENDsCSSHOOKs EXTRASPACEs MARKUPDICTs TOKEN_NAMESsnullsmonosdarksdark2slitesidles pythonwinsviewcvss defaultColorssUsagesclis_testsNones str2stdouts path2stdoutsstr2htmlsstr2csss str2markupsstr2files path2htmlsconverts path2fileslowers tagreplaces pageconvertswalkdirsshowpages _printinfosescapesunescapes ExceptionsPySourceColorErrors PathErrors InputErrorsobjectsParsers__name__(UsDECORATOR_NAMEs path2fileswalkdirsTEXTs TOKEN_NAMESsUsages CODESTARTs defaultColorssCOMMENTsclisCSSHOOKs str2stdoutsdarksTRIPLEDOUBLEQUOTEsgetopts DOUBLECOMMENTsBRACKETSs__date__s tagreplaces DOUBLEQUOTE_Us SINGLEQUOTE_Rs SINGLEQUOTE_Us _printinfos DOUBLEQUOTE_RsPAGEBACKGROUNDs pageconvertsARGSs path2htmlsescapes EXTRASPACEs__all__s CLASS_NAMEsPYstokensTRIPLEDOUBLEQUOTE_RsTRIPLEDOUBLEQUOTE_Us ERRORTOKENsDEF_NAMEsOPERATORsconverts PathErrorsStringIOsmonos tracebacksstr2filesoss_tests pythonwins __credits__s path2stdoutstokenizesshowpages InputErrors __author__s webbrowsersunescapes DOUBLEQUOTEsNAMEskeywordsstr2csssidlesviewcvssstr2htmlsParsersKEYWORDs __title__sNUMBERs MARKUPDICTsnullsTRIPLESINGLEQUOTEs SINGLEQUOTEs LINENUMBERslitesCODEENDs __version__sglobsdark2ssyssPySourceColorErrors MATH_OPERATORs str2markupsTRIPLESINGLEQUOTE_UsTRIPLESINGLEQUOTE_Rstimes DECORATOR((s6build/bdist.linux-i686/egg/paste/util/PySourceColor.pys?s                                                (   l t^   $$!'+*3*      r PKZ4#[] ] paste/util/finddata.pyc; u]Dc@sdkZdkZdklZdklZdddddfZddd d d d d fZddeeee dZ e djo#dk Z e i e dendS(N(s fnmatchcase(s convert_paths*.pys*.pycs*~s.*s*.baksCVSs_darcss./builds./distsEGG-INFOs *.egg-infos.sc CsGh} t|d||fg} x| o| id\}} }}xti |D]}ti i ||} ti i| ot}xd|D]\} t|| p| i| ijo-t}|otid| | fIJnPqqW|oqVnti iti i | do| o=| o |}n|d|}| i| d|tfq6| i| | |d||fqV|p| ot}xd|D]\} t|| p| i| ijo-t}|otid| | fIJnPqqW|oqVn| i|gi| |qVqVWq$W| SdS( sj Return a dictionary suitable for use in ``package_data`` in a distutils ``setup.py`` file. The dictionary looks like:: {'package': [files]} Where ``files`` is a list of all the files in that package that don't match anything in ``exclude``. If ``only_in_packages`` is true, then top-level directories that are not packages won't be included (but directories under packages will). Directories matching any pattern in ``exclude_directories`` will be ignored; by default directories with leading ``.``, ``CVS``, and ``_darcs`` will be ignored. If ``show_ignored`` is true, then all the files that aren't included in package data are shown on stderr (for debugging purposes). Note patterns use wildcards, or can be exact paths (including leading ``./``), and all searching is case-insensitive. sis"Directory %s ignored by pattern %ss __init__.pys.s/sFile %s ignored by pattern %sN(souts convert_pathswherespackagesonly_in_packagessstackspopsprefixsosslistdirsnamespathsjoinsfnsisdirsFalsesbad_namesexclude_directoriesspatterns fnmatchcaseslowersTrues show_ignoredssyssstderrsisfiles new_packagesappendsexcludes setdefault(swherespackagesexcludesexclude_directoriessonly_in_packagess show_ignoredsnames new_packagesbad_namesprefixspatternsstacksfnsout((s1build/bdist.linux-i686/egg/paste/util/finddata.pysfind_package_datasN) * %) *s__main__s show_ignored( sosssyssfnmatchs fnmatchcasesdistutils.utils convert_pathsstandard_excludesstandard_exclude_directoriessTruesFalsesfind_package_datas__name__spprint(s convert_paths fnmatchcasespprintssyssstandard_exclude_directoriessstandard_excludesfind_package_datasos((s1build/bdist.linux-i686/egg/paste/util/finddata.pys?s    N  PKZ4_C^yypaste/util/doctest24.pyc; u]Dc!@sdZdZdddddddd d d d d ddddddddddddddddddd d!d"g!Zd#kZd#kZd#kZd#kZd#kZd#kZd#k Z d#k Z d#k Z d#k Z d#k Z d#kZd#kZd$klZeid%deed&hZd'ZedZedZedZedZedZeeBeBeBeBZed Zed Zed Zed ZeeBeBeBZ d(Z!d)Z"d*Z#d+Z$d,d-Z%d.d/Z&d0Z'd1efd2YZ(d3Z)d4Z*d5e i+fd6YZ,d7Z-dfd8YZ.dfd9YZ/dfd:YZ0dfd;YZ1dfd<YZ2dfd=YZ3de4fd>YZ5de4fd?YZ6de2fd@YZ7e8a9e8e8e8e8e8e:d&e8e;e;dA Z<e:e8e8e8e8e:d&e8e;e0dB Z=e;dCe8d&dDZ>dfdEYZ?d&a@dFZAdGe iBfdHYZCe8e8e8e8dIZDdJeCfdKYZEe:e8e8e0dLZFdMZGdNZHdOZIe;e8dPZJe;e8dQZKe;dRZLdSfdTYZMhdSeM<dUdV<dWdX<dYdZ<d[d\<d]d^), and the final line of output is "Test failed.". Run it with the -v switch instead: python M.py -v and a detailed report of all examples tried is printed to stdout, along with assorted summaries at the end. You can force verbose mode by passing "verbose=True" to testmod, or prohibit it by passing "verbose=False". In either of those cases, sys.argv is not examined by testmod. There are a variety of other ways to run doctests, including integration with the unittest framework, and support for running non-Python text files containing doctests. There are also many ways to override parts of doctest's default behaviors. See the Library Reference Manual for details. sreStructuredText ensregister_optionflagsDONT_ACCEPT_TRUE_FOR_1sDONT_ACCEPT_BLANKLINEsNORMALIZE_WHITESPACEsELLIPSISsIGNORE_EXCEPTION_DETAILsCOMPARISON_FLAGSs REPORT_UDIFFs REPORT_CDIFFs REPORT_NDIFFsREPORT_ONLY_FIRST_FAILUREsREPORTING_FLAGSs is_privatesExamplesDocTests DocTestParsers DocTestFinders DocTestRunners OutputCheckersDocTestFailuresUnexpectedExceptions DebugRunnerstestmodstestfilesrun_docstring_examplessTesters DocTestSuites DocFileSuitesset_unittest_reportflagssscript_from_exampless testsources debug_srcsdebugN(sStringIOsignoreicCs"dtt>}|t|<|SdS(Ni(slensOPTIONFLAGS_BY_NAMEsflagsname(snamesflag((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysregister_optionflags s s...cCsOtidtdd|d djo$|d djo|djn SdS( sprefix, base -> true iff name prefix + "." + base is "private". Prefix may be an empty string, and base does not contain a period. Prefix is ignored (although functions you write conforming to this protocol may make use of it). Return true iff base begins with an (at least one) underscore, but does not both begin and end with (at least) two underscores. >>> is_private("a.b", "my_func") False >>> is_private("____", "_my_func") True >>> is_private("someclass", "__init__") False >>> is_private("sometypo", "__init_") True >>> is_private("x.y.z", "_") True >>> is_private("_x.y.z", "__") False >>> is_private("", "") # senseless but consistent False sVis_private is deprecated; it wasn't useful; examine DocTestFinder.find() lists insteads stackleveliis_s__iN(swarningsswarnsDeprecationWarningsbase(sprefixsbase((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys is_privates  cCs[d}xJtiD]?}|i|t}|tt|jo||i O}qqW|SdS(s Return the compiler-flags associated with the future features that have been imported into the given namespace (globs). iN( sflagss __future__sall_feature_namessfnamesglobssgetsNonesfeaturesgetattrs compiler_flag(sglobssfeaturesflagssfname((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys_extract_future_flagss icCsti|o|Snot|ttfo t|ttdgSn9|t jot i t i |idSn tddS(s Return the module specified by `module`. In particular: - If `module` is a module, then return module. - If `module` is a string, then import and return the module with that name. - If `module` is None, then return the calling module. The calling module is assumed to be the module of the stack frame at the given depth in the call stack. s*s__name__s"Expected a module, string, or NoneN(sinspectsismodulesmodules isinstancesstrsunicodes __import__sglobalsslocalssNonessyssmoduless _getframesdepths f_globalss TypeError(smodulesdepth((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys_normalize_modules   icCstid|d|SdS(s{ Add the given number of space characters to the beginning every non-blank line in `s`, and return the result. s (?m)^(?!$)s N(sressubsindentss(sssindent((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys_indentscCs?t}|\}}}ti|||d||iSdS(sz Return a string containing a traceback message for the given exc_info tuple (as returned by sys.exc_info()). sfileN( sStringIOsexcoutsexc_infosexc_typesexc_valsexc_tbs tracebacksprint_exceptionsgetvalue(sexc_infosexc_valsexc_typesexcoutsexc_tb((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys_exception_tracebacks  s _SpoofOutcBstZdZedZRS(NcCsWti|}|o|id o|d7}nt|do |`n|SdS(Ns s softspace(sStringIOsgetvaluesselfsresultsendswithshasattrs softspace(sselfsresult((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysgetvalues  cCs.ti||t|do |`ndS(Ns softspace(sStringIOstruncatesselfssizeshasattrs softspace(sselfssize((s2build/bdist.linux-i686/egg/paste/util/doctest24.pystruncates(s__name__s __module__sgetvaluesNonestruncate(((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys _SpoofOuts cCsHt|jo||jSn|it}t|djptdt|f\}}|d}|o/|i |ot|}|d=qt Sn|d}|o3|i |o|t|8}|d=qt Sn||jot SnxH|D]@}|i |||}|djot Sn|t|7}qWtSdS(s_ Essentially the only subtle case: >>> _ellipsis_match('aa...aa', 'aaa') False iiiN(sELLIPSIS_MARKERswantsgotssplitswsslensAssertionErrorsstartpossendpossws startswithsFalsesendswithsfindsTrue(swantsgotswswssstartpossendpos((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys_ellipsis_matchs6        cCs'|i}|o d|SndSdS(s)Return a commented form of the given lines# s#N(slinesrstrip(sline((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys _comment_lineHs   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((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys__init__Vs cGs=ti}|it_ztii||SWd|t_XdS(N( ssyssstdouts save_stdoutsselfs_OutputRedirectingPdb__outspdbsPdbstrace_dispatchsargs(sselfsargss save_stdout((s2build/bdist.linux-i686/egg/paste/util/doctest24.pystrace_dispatchZs   (s__name__s __module__s__doc__s__init__strace_dispatch(((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys_OutputRedirectingPdbPs  cCsti| otd|n|ido tdnt|dotii |i d}n}|i djoXt tidjotiddjo!tii tidd}qti}ntd|d tii||i dSdS( NsExpected a module: %rs/s1Module-relative files may not have absolute pathss__file__is__main__ss+Can't resolve paths relative to the module s (it has no __file__)(sinspectsismodulesmodules TypeErrorspaths startswiths ValueErrorshasattrsosssplits__file__sbasedirs__name__slenssyssargvscurdirsjoin(smodulespathsbasedir((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys_module_relative_pathes *! cBs#tZdZeddedZRS(sn A single doctest example, consisting of source code and expected output. `Example` defines the following attributes: - source: A single Python statement, always ending with a newline. The constructor adds a newline if needed. - want: The expected output from running the source code (either from stdout, or a traceback in case of exception). `want` ends with a newline unless it's empty, in which case it's an empty string. The constructor adds a newline if needed. - exc_msg: The exception message generated by the example, if the example is expected to generate an exception; or `None` if it is not expected to generate an exception. This exception message is compared against the return value of `traceback.format_exception_only()`. `exc_msg` ends with a newline unless it's `None`. The constructor adds a newline if needed. - lineno: The line number within the DocTest string containing this Example where the Example begins. This line number is zero-based, with respect to the beginning of the DocTest. - indent: The example's indentation in the DocTest string. I.e., the number of space characters that preceed the example's first prompt. - options: A dictionary mapping from option flags to True or False, which is used to override default options for this example. Any option flags not contained in this dictionary are left at their default value (as specified by the DocTestRunner's optionflags). By default, no options are set. icCs|id o|d7}n|o|id o|d7}n|tj o|id o|d7}n||_||_||_||_|tjo h}n||_||_dS(Ns ( ssourcesendswithswantsexc_msgsNonesselfslinenosindentsoptions(sselfssourceswantsexc_msgslinenosindentsoptions((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys__init__s      (s__name__s __module__s__doc__sNones__init__(((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysExamples "cBs)tZdZdZdZdZRS(se A collection of doctest examples that should be run in a single namespace. Each `DocTest` defines the following attributes: - examples: the list of examples. - globs: The namespace (aka globals) that the examples should be run in. - name: A name identifying the DocTest (typically, the name of the object whose docstring this DocTest was extracted from). - filename: The name of the file that this DocTest was extracted from, or `None` if the filename is unknown. - lineno: The line number within filename where this DocTest begins, or `None` if the line number is unavailable. This line number is zero-based, with respect to the beginning of the file. - docstring: The string that the examples were extracted from, or `None` if the string is unavailable. cCs[t|t p td||_||_|i|_||_||_ ||_ dS(s Create a new DocTest containing the given examples. The DocTest's globals are initialized with a copy of `globs`. s8DocTest no longer accepts str; use DocTestParser insteadN( s isinstancesexampless basestringsAssertionErrorsselfs docstringsglobsscopysnamesfilenameslineno(sselfsexamplessglobssnamesfilenameslinenos docstring((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys__init__s    cCstt|idjo d}n4t|idjo d}ndt|i}d|i|i|i|fSdS(Nis no examplesis 1 examples %d exampless(slensselfsexamplessnamesfilenameslineno(sselfsexamples((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys__repr__s   cCs`t|t odSnt|i|i|it|f|i|i|it|fSdS(Ni( s isinstancesothersDocTestscmpsselfsnamesfilenameslinenosid(sselfsother((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys__cmp__s!(s__name__s __module__s__doc__s__init__s__repr__s__cmp__(((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysDocTests   cBstZdZeideieiBZeideieiBeiBZ eidi Z ddZ dZ ddZdZeid eiZd Zeid eiZd Zd ZdZRS(sD A class used to parse strings containing doctest examples. s # Source consists of a PS1 line followed by zero or more PS2 lines. (?P (?:^(?P [ ]*) >>> .*) # PS1 line (?:\n [ ]* \.\.\. .*)*) # PS2 lines \n? # Want consists of any non-blank lines that do not start with PS1. (?P (?:(?![ ]*$) # Not a blank line (?![ ]*>>>) # Not a line starting with PS1 .*$\n? # But any other line )*) s # Grab the traceback header. Different versions of Python have # said different things on the first traceback line. ^(?P Traceback\ \( (?: most\ recent\ call\ last | innermost\ last ) \) : ) \s* $ # toss trailing whitespace on the header. (?P .*?) # don't blink: absorb stuff until... ^ (?P \w+ .*) # a line *starts* with alphanum. s ^[ ]*(#.*)?$sc Cs|i}|i|}|djoAdigi}|idD]}|||qE~}ng} ddf\} } x|i i|D]}| i|| |i!| |id| |i7} |i||| \}} } }|i| oB| it|| |d| d|t|idd| n| |id|i|i7} |i} qW| i|| | SdS(s= Divide the given string into examples and intervening text, and return them as a list of alternating Examples and strings. Line numbers for the Examples are 0-based. The optional argument `name` is a name identifying this string, and is only used for error messages. is slinenosindentsoptionsN(sstrings expandtabssselfs _min_indents min_indentsjoinsappends_[1]ssplitslsoutputscharnoslinenos _EXAMPLE_REsfinditersmsstartscounts_parse_examplesnamessourcesoptionsswantsexc_msgs_IS_BLANK_OR_COMMENTsExampleslensgroupsend(sselfsstringsnames min_indentsexc_msgsmsls_[1]ssourceslinenoswantsoutputscharnosoptions((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysparse*s*  A!%cCs)t|i|||||||SdS(s" Extract all doctest examples from the given string, and collect them into a `DocTest` object. `globs`, `name`, `filename`, and `lineno` are attributes for the new `DocTest` object. See the documentation for `DocTest` for more information. N(sDocTestsselfs get_examplessstringsnamesglobssfilenameslineno(sselfsstringsglobssnamesfilenameslineno((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys get_doctestQscCsIgi}|i||D]$}t|to||qq~SdS(s Extract all doctest examples from the given string, and return them as a list of `Example` objects. Line numbers are 0-based, because it's most common in doctests that nothing interesting appears on the same line as opening triple-quote, and so the first interesting line is called "line 1" then. The optional argument `name` is a name identifying this string, and is only used for error messages. N( sappends_[1]sselfsparsesstringsnamesxs isinstancesExample(sselfsstringsnames_[1]sx((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys get_examples]s cCst|id}|idid} |i| ||||i | dd|d||di gi }| D]} || |dqy~} |id} | id}t|djotid |d o |d =n|i |d|||t| di gi }|D]}|||q(~} |ii| }|o|id }nt}|i| ||} | | | |fSd S( s Given a regular expression match from `_EXAMPLE_RE` (`m`), return a pair `(source, want)`, where `source` is the matched example's source code (with prompts and indentation stripped); and `want` is the example's expected output (with indentation stripped). `name` is the string's name, and `lineno` is the line number where the example starts; both are used for error messages. sindentssources is s.iswants *$ismsgN(slensmsgroupsindentssplits source_linessselfs_check_prompt_blanksnameslinenos _check_prefixsjoinsappends_[1]sslssourceswants want_linessresmatchswls _EXCEPTION_REsexc_msgsNones _find_optionssoptions(sselfsmsnameslinenosindents want_linessexc_msgswls_[1]ssourceswantssls source_linessoptions((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys_parse_exampleks& "8* 4s#\s*doctest:\s*([^\n\'"]*)$c Csh}x|ii|D]}|ididdi}xs|D]k}|ddjp|dt jo!t d|d||fnt |d}|ddj||>> tests = DocTestFinder().find(_TestClass) >>> runner = DocTestRunner(verbose=False) >>> for test in tests: ... print runner.run(test) (0, 2) (0, 1) (0, 2) (0, 2) The `summarize` method prints a summary of all the test cases that have been run by the runner, and returns an aggregated `(f, t)` tuple: >>> runner.summarize(verbose=1) 4 items passed all tests: 2 tests in _TestClass 2 tests in _TestClass.__init__ 2 tests in _TestClass.get 1 tests in _TestClass.square 7 tests in 4 items. 7 passed and 0 failed. Test passed. (0, 7) The aggregated number of tried examples and failed examples is also available via the `tries` and `failures` attributes: >>> runner.tries 7 >>> runner.failures 0 The comparison between expected outputs and actual outputs is done by an `OutputChecker`. This comparison may be customized with a number of option flags; see the documentation for `testmod` for more information. If the option flags are insufficient, then the comparison may also be customized by passing a subclass of `OutputChecker` to the constructor. The test runner's display output can be controlled in two ways. First, an output function (`out) can be passed to `TestRunner.run`; this function will be called with strings that should be displayed. It defaults to `sys.stdout.write`. If capturing the output is not sufficient, then the display output can be also customized by subclassing DocTestRunner, and overriding the methods `report_start`, `report_success`, `report_unexpected_exception`, and `report_failure`. s*iFicCsy|pt|_|tjodtij}n||_||_ ||_ d|_ d|_ h|_ t|_dS(sc Create a new test runner. Optional keyword arg `checker` is the `OutputChecker` that should be used to compare the expected outputs and actual outputs of doctest examples. Optional keyword arg 'verbose' prints lots of stuff if true, only failures if false; by default, it's true iff '-v' is in sys.argv. Optional argument `optionflags` can be used to control how the test runner compares expected output to actual output, and how it displays failures. See the documentation for `testmod` for more information. s-viN(scheckers OutputCheckersselfs_checkersverbosesNonessyssargvs_verboses optionflagssoriginal_optionflagsstriessfailuress_name2fts _SpoofOuts_fakeout(sselfscheckersverboses optionflags((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys__init__Js       cCsc|ioU|io,|dt|idt|iq_|dt|idndS(s Report that the test runner is about to process the given example. (Only displays a message if verbose=True) sTrying: s Expecting: sExpecting nothing N(sselfs_verbosesexampleswantsouts_indentssource(sselfsoutstestsexample((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys report_startns   ,cCs|io|dndS(st Report that the given example ran successfully. (Only displays a message if verbose=True) sok N(sselfs_verbosesout(sselfsoutstestsexamplesgot((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysreport_success{s cCs3||i|||ii|||idS(s7 Report that the given example failed. N( soutsselfs_failure_headerstestsexamples_checkersoutput_differencesgots optionflags(sselfsoutstestsexamplesgot((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysreport_failurescCs.||i||dtt|dS(sO Report that the given example raised an unexpected exception. sException raised: N(soutsselfs_failure_headerstestsexamples_indents_exception_tracebacksexc_info(sselfsoutstestsexamplesexc_info((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysreport_unexpected_exceptionscCs|ig}|iob|itj o |itj o|i|id}nd}|id|i||i fn"|id|id|i f|id|i }|it |di |SdS(Nis?sFile "%s", line %s, in %ssLine %s, in %ssFailed example:s ( sselfsDIVIDERsoutstestsfilenameslinenosNonesexamplesappendsnamessources_indentsjoin(sselfstestsexamplessourceslinenosout((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys_failure_headers   $!  cBsd}} |i} ed\} }}|i i }xUe |iD]D\}}|ie@o |dj}| |_|ioNxK|iiD]6\}}|o|i|O_q|i|M_qWn| d7} | o|i|||nd|i|f}y7e|i|d|d|iU|ii e!}Wn5e#j o n!e$i%}|ii nX|i&i'} |i&i)d|}|e!jo'||i+| |io | }qne$i%}e,i-|d d} | o| e/|7} n|i.e!jo |}n||i.| |io | }nz|ie0@oke1i2d|i.}e1i2d| }|o,|o%||i5d|i5d|io | }qn|| jo&| o|i6|||| qqD||jo0| o|i7|||| n|d7}qD||jo0| o|i8||||n|d7}qDe9pt:d |fqDW| |_|i;||| || fSd S( s Run the examples in `test`. Write the outcome of each example with one of the `DocTestRunner.report_*` methods, using the writer function `out`. `compileflags` is the set of compiler flags that should be used to execute examples. Return a tuple `(f, t)`, where `t` is the number of examples tried, and `f` is the number of examples that failed. The examples are run in the namespace `test.globs`. iiisssingleiis[^:]*:sunknown outcomeN(<sfailuresstriessselfs optionflagssoriginal_optionflagssrangesSUCCESSsFAILUREsBOOMs_checkers check_outputschecks enumeratestestsexampless examplenumsexamplesREPORT_ONLY_FIRST_FAILUREsquietsoptionssitemss optionflagsvals report_startsoutsnamesfilenamescompilessources compileflagssglobssdebuggers set_continuesNones exceptionsKeyboardInterruptssyssexc_infos_fakeoutsgetvaluesgotstruncatesoutcomeswants tracebacksformat_exception_onlysexc_msgs_exception_tracebacksIGNORE_EXCEPTION_DETAILsresmatchsm1sm2sgroupsreport_successsreport_failuresreport_unexpected_exceptionsFalsesAssertionErrors_DocTestRunner__record_outcome(sselfstests compileflagssoutschecksvalsfilenamesm1sm2sgotsoriginal_optionflagssSUCCESSsexc_msgstriessexc_infos exceptions optionflagsquietsFAILUREsBOOMs examplenumsfailuressoutcomesexample((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys__runs                )      cCsd|ii|iddf\}}||||f|i|i<|i |7_ |i |7_ dS(s{ Record the fact that the given DocTest (`test`) generated `f` failures out of `t` tried examples. iN( sselfs_name2ftsgetstestsnamesf2st2sfstsfailuresstries(sselfstestsfstsf2st2((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys__record_outcomes $s3[\w\.]+)\[(?P\d+)\]>$cCsy|ii|}|o|id|iijo3|iit |id}|i i t Sn|i|SdS(Nsnames examplenum(sselfs%_DocTestRunner__LINECACHE_FILENAME_REsmatchsfilenamesmsgroupstestsnamesexamplessintsexamplessources splitlinessTruessave_linecache_getlines(sselfsfilenamesmsexample((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys__patched_linecache_getlines*s #cCs||_|tjot|i}nti}|tjo |i }n|i t_t i }t||_|ii|ii t _ ti|_|it_z|i|||SWd|t_|t _ |it_|o|iinXdS(sJ Run the examples in `test`, and display the results using the writer function `out`. The examples are run in the namespace `test.globs`. If `clear_globs` is true (the default), then this namespace will be cleared after the test runs, to help with garbage collection. If you would like to examine the namespace after the test completes, then use `clear_globs=False`. `compileflags` gives the set of flags that should be used by the Python compiler when running the examples. If not specified, then it will default to the set of future-import flags that apply to `globs`. The output of each example is checked using `DocTestRunner.check_output`, and the results are formatted by the `DocTestRunner.report_*` methods. N(stestsselfs compileflagssNones_extract_future_flagssglobsssyssstdouts save_stdoutsoutswrites_fakeoutspdbs set_tracessave_set_traces_OutputRedirectingPdbsdebuggersresets linecachesgetlinesssave_linecache_getliness*_DocTestRunner__patched_linecache_getliness_DocTestRunner__runs clear_globssclear(sselfstests compileflagssouts clear_globss save_stdoutssave_set_trace((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysrun2s,             c Cs7|tjo |i}ng} g}g}d}} x|i i D]} | \}\}}||jpt||7}| |7} |djo| i|qF|djo|i||fqF|i| qFW|o| o7t| GdGH| ix| D]} dG| GHqWn|oCt|GdGH|ix'|D]\} }d|| fGHqEWqln|oT|iGHt|GdGH|ix0|D]$\} \}}d||| fGHqWn|o3|GdGt|i Gd GH|| Gd G| Gd GHn| od G| Gd GHn|o dGHn| |fSdS(s Print a summary of all the test cases that have been run by this DocTestRunner, and return a tuple `(f, t)`, where `f` is the total number of failed examples, and `t` is the total number of tried examples. The optional `verbose` argument controls how detailed the summary is. If the verbosity is not specified, then the DocTestRunner's verbosity is used. isitems had no tests:s sitems passed all tests:s %3d tests in %ssitems had failures:s %3d of %3d in %sstests insitems.s passed andsfailed.s***Test Failed***s failures.s Test passed.N(sverbosesNonesselfs_verbosesnotestsspassedsfailedstotaltstotalfs_name2ftsitemssxsnamesfstsAssertionErrorsappendslenssortsthingscountsDIVIDER( sselfsverbosescountsfstotaltsnamesfailedstspassedsxstotalfsthingsnotests((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys summarizeks\             cCs|i}xu|iiD]d\}\}}||jo5d|dGH||\}}||}||}n||f||>> runner = DebugRunner(verbose=False) >>> test = DocTestParser().get_doctest('>>> raise KeyError\n42', ... {}, 'foo', 'foo.py', 0) >>> try: ... runner.run(test) ... except UnexpectedException, failure: ... pass >>> failure.test is test True >>> failure.example.want '42\n' >>> exc_info = failure.exc_info >>> raise exc_info[0], exc_info[1], exc_info[2] Traceback (most recent call last): ... KeyError We wrap the original exception to give the calling application access to the test and example information. If the output doesn't match, then a DocTestFailure is raised: >>> test = DocTestParser().get_doctest(''' ... >>> x = 1 ... >>> x ... 2 ... ''', {}, 'foo', 'foo.py', 0) >>> try: ... runner.run(test) ... except DocTestFailure, failure: ... pass DocTestFailure objects provide access to the test: >>> failure.test is test True As well as to the example: >>> failure.example.want '2\n' and the actual output: >>> failure.got '1\n' If a failure or error occurs, the globals are left intact: >>> del test.globs['__builtins__'] >>> test.globs {'x': 1} >>> test = DocTestParser().get_doctest(''' ... >>> x = 2 ... >>> raise KeyError ... ''', {}, 'foo', 'foo.py', 0) >>> runner.run(test) Traceback (most recent call last): ... UnexpectedException: >>> del test.globs['__builtins__'] >>> test.globs {'x': 2} But the globals are cleared if there is no error: >>> test = DocTestParser().get_doctest(''' ... >>> x = 2 ... ''', {}, 'foo', 'foo.py', 0) >>> runner.run(test) (0, 1) >>> test.globs {} cCs;ti||||t}|o|i i n|SdS(N( s DocTestRunnersrunsselfstests compileflagssoutsFalsesrs clear_globssglobssclear(sselfstests compileflagssouts clear_globssr((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysrunscCst|||dS(N(sUnexpectedExceptionstestsexamplesexc_info(sselfsoutstestsexamplesexc_info((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysreport_unexpected_exceptionscCst|||dS(N(sDocTestFailurestestsexamplesgot(sselfsoutstestsexamplesgot((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysreport_failures(s__name__s __module__s__doc__sNonesTruesrunsreport_unexpected_exceptionsreport_failure(((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys DebugRunnerZs Y c CsS|tj otidtn|tjotiid}nt i | ot d|fn|tjo |i }ntd|d| } |otd|d|} ntd|d|} x3| i||d|d |D]} | i| qW|o| inttjo | anti| | i | i!fSd S( s m=None, name=None, globs=None, verbose=None, isprivate=None, report=True, optionflags=0, extraglobs=None, raise_on_error=False, exclude_empty=False Test examples in docstrings in functions and classes reachable from module m (or the current module if m is not supplied), starting with m.__doc__. Unless isprivate is specified, private names are not skipped. Also test examples reachable from dict m.__test__ if it exists and is not None. m.__test__ maps names to functions, classes and strings; function and class docstrings are tested even if the name is private; strings are tested directly, as if they were docstrings. Return (#failures, #tests). See doctest.__doc__ for an overview. Optional keyword arg "name" gives the name of the module; by default use m.__name__. Optional keyword arg "globs" gives a dict to be used as the globals when executing examples; by default, use m.__dict__. A copy of this dict is actually used for each docstring, so that each docstring's examples start with a clean slate. Optional keyword arg "extraglobs" gives a dictionary that should be merged into the globals that are used to execute examples. By default, no extra globals are used. This is new in 2.4. Optional keyword arg "verbose" prints lots of stuff if true, prints only failures if false; by default, it's true iff "-v" is in sys.argv. Optional keyword arg "report" prints a summary at the end when true, else prints nothing at the end. In verbose mode, the summary is detailed, else very brief (in fact, empty if all tests passed). Optional keyword arg "optionflags" or's together module constants, and defaults to 0. This is new in 2.3. Possible values (see the docs for details): DONT_ACCEPT_TRUE_FOR_1 DONT_ACCEPT_BLANKLINE NORMALIZE_WHITESPACE ELLIPSIS IGNORE_EXCEPTION_DETAIL REPORT_UDIFF REPORT_CDIFF REPORT_NDIFF REPORT_ONLY_FIRST_FAILURE Optional keyword arg "raise_on_error" raises an exception on the first unexpected exception or failure. This allows failures to be post-mortem debugged. Deprecated in Python 2.4: Optional keyword arg "isprivate" specifies a function used to determine whether a name is private. The default function is treat all functions as public. Optionally, "isprivate" can be set to doctest.is_private to skip over functions marked as private using the underscore naming convention; see its docs for details. Advanced tomfoolery: testmod runs methods of a local instance of class doctest.Tester, then merges the results into (or creates) global Tester instance doctest.master. Methods of doctest.master can be called directly too, if you want to do something unusual. Passing report=0 to testmod is especially useful then, to delay displaying a summary. Invoke doctest.master.summarize(verbose) when you're done fiddling. sPthe isprivate argument is deprecated; examine DocTestFinder.find() lists insteads__main__stestmod: module required; %rs _namefilters exclude_emptysverboses optionflagssglobss extraglobsN("s isprivatesNoneswarningsswarnsDeprecationWarningsmssyssmodulessgetsinspectsismodules TypeErrorsnames__name__s DocTestFinders exclude_emptysfindersraise_on_errors DebugRunnersverboses optionflagssrunners DocTestRunnersfindsglobss extraglobsstestsrunsreports summarizesmastersmergesfailuresstries( smsnamesglobssverboses isprivatesreports optionflagss extraglobssraise_on_errors exclude_emptysrunnerstestsfinder((s2build/bdist.linux-i686/egg/paste/util/doctest24.pystestmods0H         c Cse|o| otdn|ot|}t||}n|tjoti i |}n|tjo h}n |i }|tj o|i|n| otd|d|} ntd|d|} t|i} | i| |||d} | i| |o| inttjo | anti| | i | i!fSdS(s Test examples in the given file. Return (#failures, #tests). Optional keyword arg "module_relative" specifies how filenames should be interpreted: - If "module_relative" is True (the default), then "filename" specifies a module-relative path. By default, this path is relative to the calling module's directory; but if the "package" argument is specified, then it is relative to that package. To ensure os-independence, "filename" should use "/" characters to separate path segments, and should not be an absolute path (i.e., it may not begin with "/"). - If "module_relative" is False, then "filename" specifies an os-specific path. The path may be absolute or relative (to the current working directory). Optional keyword arg "name" gives the name of the test; by default use the file's basename. Optional keyword argument "package" is a Python package or the name of a Python package whose directory should be used as the base directory for a module relative filename. If no package is specified, then the calling module's directory is used as the base directory for module relative filenames. It is an error to specify "package" if "module_relative" is False. Optional keyword arg "globs" gives a dict to be used as the globals when executing examples; by default, use {}. A copy of this dict is actually used for each docstring, so that each docstring's examples start with a clean slate. Optional keyword arg "extraglobs" gives a dictionary that should be merged into the globals that are used to execute examples. By default, no extra globals are used. Optional keyword arg "verbose" prints lots of stuff if true, prints only failures if false; by default, it's true iff "-v" is in sys.argv. Optional keyword arg "report" prints a summary at the end when true, else prints nothing at the end. In verbose mode, the summary is detailed, else very brief (in fact, empty if all tests passed). Optional keyword arg "optionflags" or's together module constants, and defaults to 0. Possible values (see the docs for details): DONT_ACCEPT_TRUE_FOR_1 DONT_ACCEPT_BLANKLINE NORMALIZE_WHITESPACE ELLIPSIS IGNORE_EXCEPTION_DETAIL REPORT_UDIFF REPORT_CDIFF REPORT_NDIFF REPORT_ONLY_FIRST_FAILURE Optional keyword arg "raise_on_error" raises an exception on the first unexpected exception or failure. This allows failures to be post-mortem debugged. Optional keyword arg "parser" specifies a DocTestParser (or subclass) that should be used to extract tests from the files. Advanced tomfoolery: testmod runs methods of a local instance of class doctest.Tester, then merges the results into (or creates) global Tester instance doctest.master. Methods of doctest.master can be called directly too, if you want to do something unusual. Passing report=0 to testmod is especially useful then, to delay displaying a summary. Invoke doctest.master.summarize(verbose) when you're done fiddling. s8Package may only be specified for module-relative paths.sverboses optionflagsiN("spackagesmodule_relatives ValueErrors_normalize_modules_module_relative_pathsfilenamesnamesNonesosspathsbasenamesglobsscopys extraglobssupdatesraise_on_errors DebugRunnersverboses optionflagssrunners DocTestRunnersopensreadsssparsers get_docteststestsrunsreports summarizesmastersmergesfailuresstries(sfilenamesmodule_relativesnamespackagesglobssverbosesreports optionflagss extraglobssraise_on_errorsparsersrunnerstestss((s2build/bdist.linux-i686/egg/paste/util/doctest24.pystestfile>s4J          sNoNamec Csdtd|dt}td|d|}x3|i||d|D]}|i |d|qCWdS(sr Test examples in the given object's docstring (`f`), using `globs` as globals. Optional argument `name` is used in failure messages. If the optional argument `verbose` is true, then generate output even if there are no failures. `compileflags` gives the set of flags that should be used by the Python compiler when running the examples. If not specified, then it will default to the set of future-import flags that apply to `globs`. Optional keyword arg `optionflags` specifies options for the testing and output. See the documentation for `testmod` for more information. sverbosesrecurses optionflagssglobss compileflagsN(s DocTestFindersverbosesFalsesfinders DocTestRunners optionflagssrunnersfindsfsnamesglobsstestsruns compileflags( sfsglobssverbosesnames compileflagss optionflagssrunnerstestsfinder((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysrun_docstring_exampless cBsbtZeeeeddZdZeedZedZdZedZdZ RS( NicCstidtdd|tjo |tjotdn|tj oti| otd|fn|tjo |i }n||_||_ ||_ ||_ td||_td|d||_dS( NsCclass Tester is deprecated; use class doctest.DocTestRunner insteads stacklevelis*Tester.__init__: must specify mod or globss)Tester.__init__: mod must be a module; %rs _namefiltersverboses optionflags(swarningsswarnsDeprecationWarningsmodsNonesglobss TypeErrorsinspectsismodules__dict__sselfsverboses isprivates optionflagss DocTestFinders testfinders DocTestRunners testrunner(sselfsmodsglobssverboses isprivates optionflags((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys__init__s         cCsti||i|tt}|io dG|GHn|i i |\}}|io|GdG|GdG|GHn||fSdS(NsRunning stringsofsexamples failed in string( s DocTestParsers get_doctestsssselfsglobssnamesNonestestsverboses testrunnersrunsfst(sselfsssnamesfststest((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys runstrings!   c Csd}}|ii||d|d|i}x@|D]8} |i i | \}}||||f\}}q5W||fSdS(Nismodulesglobs(sfstsselfs testfindersfindsobjectsnamesmodulesglobsstestsstests testrunnersrunsf2st2( sselfsobjectsnamesmodulestestssfst2sf2ststest((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysrundocs cCsVdk}|i|}|ii||tjo t}n|i |||SdS(N( snewsmodulesnamesms__dict__supdatesdsNonesFalsesselfsrundoc(sselfsdsnamesmodulesmsnew((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysrundicts    cCs5dk}|i|}||_|i||SdS(N(snewsmodulesnamesmsds__test__sselfsrundoc(sselfsdsnamesnewsm((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys run__test__s  cCs|ii|SdS(N(sselfs testrunners summarizesverbose(sselfsverbose((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys summarizescCs|ii|idS(N(sselfs testrunnersmergesother(sselfsother((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysmerge s( s__name__s __module__sNones__init__s runstringsrundocsrundicts run__test__s summarizesmerge(((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysTesters    cCs8|t@|jotd|nt}|a|SdS(sSets the unittest option flags. The old flag is returned so that a runner could restore the old value if it wished to: >>> old = _unittest_reportflags >>> set_unittest_reportflags(REPORT_NDIFF | ... REPORT_ONLY_FIRST_FAILURE) == old True >>> import doctest >>> doctest._unittest_reportflags == (REPORT_NDIFF | ... REPORT_ONLY_FIRST_FAILURE) True Only reporting flags can be set: >>> set_unittest_reportflags(ELLIPSIS) Traceback (most recent call last): ... ValueError: ('Only reporting flags allowed', 8) >>> set_unittest_reportflags(old) == (REPORT_NDIFF | ... REPORT_ONLY_FIRST_FAILURE) True sOnly reporting flags allowedN(sflagssREPORTING_FLAGSs ValueErrors_unittest_reportflagssold(sflagssold((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysset_unittest_reportflagsss DocTestCasecBsktZdeeedZdZdZdZdZdZdZ d Z e Z d Z RS( NicCsAtii|||_||_||_ ||_ ||_ dS(N(sunittestsTestCases__init__sselfs optionflagss_dt_optionflagsscheckers _dt_checkerstests_dt_testssetUps _dt_setUpstearDowns _dt_tearDown(sselfstests optionflagsssetUpstearDownschecker((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys__init__:s     cCs.|i}|itj o|i|ndS(N(sselfs_dt_teststests _dt_setUpsNone(sselfstest((s2build/bdist.linux-i686/egg/paste/util/doctest24.pyssetUpDs cCs;|i}|itj o|i|n|iidS(N(sselfs_dt_teststests _dt_tearDownsNonesglobssclear(sselfstest((s2build/bdist.linux-i686/egg/paste/util/doctest24.pystearDownJs cCs|i}ti}t}|i}|t @ o|t O}nt d|d|i dt}z5dd|_|i|d|idt\}}Wd|t_X|o"|i|i|indS(Ns optionflagsscheckersverboses-iFsouts clear_globs(sselfs_dt_teststestssyssstdoutsoldsStringIOsnews_dt_optionflagss optionflagssREPORTING_FLAGSs_unittest_reportflagss DocTestRunners _dt_checkersFalsesrunnersDIVIDERsrunswritesfailuresstriessfailureExceptionsformat_failuresgetvalue(sselfsoldsrunnerstriessfailuresstestsnews optionflags((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysrunTestRs       ( cCsp|i}|itjo d}nd|i}di|iidd}d|i|i |||fSdS(Nsunknown line numbers%ss.is:Failed doctest test for %s File "%s", line %s, in %s %s( sselfs_dt_teststestslinenosNonesjoinsnamessplitslnamesfilenameserr(sselfserrslnameslinenostest((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysformat_failurejs    cCsI|itd|id|idt}|i|i|i dS(sRun the test case without results and without catching exceptions The unit test framework includes a debug method on test cases and test suites to support post-mortem debugging. The test code is run in such a way that errors are not caught. This way a caller can catch the errors and initiate post-mortem debugging. The DocTestCase provides a debug method that raises UnexpectedException errors if there is an unexepcted exception: >>> test = DocTestParser().get_doctest('>>> raise KeyError\n42', ... {}, 'foo', 'foo.py', 0) >>> case = DocTestCase(test) >>> try: ... case.debug() ... except UnexpectedException, failure: ... pass The UnexpectedException contains the test, the example, and the original exception: >>> failure.test is test True >>> failure.example.want '42\n' >>> exc_info = failure.exc_info >>> raise exc_info[0], exc_info[1], exc_info[2] Traceback (most recent call last): ... KeyError If the output doesn't match, then a DocTestFailure is raised: >>> test = DocTestParser().get_doctest(''' ... >>> x = 1 ... >>> x ... 2 ... ''', {}, 'foo', 'foo.py', 0) >>> case = DocTestCase(test) >>> try: ... case.debug() ... except DocTestFailure, failure: ... pass DocTestFailure objects provide access to the test: >>> failure.test is test True As well as to the example: >>> failure.example.want '2\n' and the actual output: >>> failure.got '1\n' s optionflagsscheckersverboseN( sselfssetUps DebugRunners_dt_optionflagss _dt_checkersFalsesrunnersruns_dt_teststearDown(sselfsrunner((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysdebugvs @  cCs|iiSdS(N(sselfs_dt_testsname(sself((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysidscCs8|iiid}d|ddi|d fSdS(Ns.s%s (%s)i(sselfs_dt_testsnamessplitsjoin(sselfsname((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys__repr__scCsd|iiSdS(Ns Doctest: (sselfs_dt_testsname(sself((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysshortDescriptions( s__name__s __module__sNones__init__ssetUpstearDownsrunTestsformat_failuresdebugsids__repr__s__str__sshortDescription(((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys DocTestCase8s    H  c Ks|tjo t}nt|}|i|d|d|}|tjo |i }n| ot |dn|i t i }x|D]}t|idjoqn|i o;|i}|dddfjo|d }n||_n|it||qW|Sd S( s Convert doctest tests for a module to a unittest test suite. This converts each documentation string in a module that contains doctest tests to a unittest test case. If any of the tests in a doc string fail, then the test case fails. An exception is raised showing the name of the file containing the test and a (sometimes approximate) line number. The `module` argument provides the module to be tested. The argument can be either a module or a module name. If no argument is given, the calling module is used. A number of options may be provided as keyword arguments: setUp A set-up function. This is called before running the tests in each file. The setUp function will be passed a DocTest object. The setUp function can access the test globals as the globs attribute of the test passed. tearDown A tear-down function. This is called after running the tests in each file. The tearDown function will be passed a DocTest object. The tearDown function can access the test globals as the globs attribute of the test passed. globs A dictionary containing initial global variables for the tests. optionflags A set of doctest option flags expressed as an integer. sglobss extraglobss has no testsiis.pycs.pyoiN(s test_findersNones DocTestFinders_normalize_modulesmodulesfindsglobss extraglobsstestss__dict__s ValueErrorssortsunittests TestSuitessuitestestslensexamplessfilenames__file__saddTests DocTestCasesoptions( smodulesglobss extraglobss test_findersoptionsstestsstestssuitesfilename((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys DocTestSuites,#          s DocFileCasecBs)tZdZdZeZdZRS(NcCs di|iiidSdS(Ns_s.(sjoinsselfs_dt_testsnamessplit(sself((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysid scCs|iiSdS(N(sselfs_dt_testsfilename(sself((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys__repr__ scCs!d|ii|ii|fSdS(Ns2Failed doctest test for %s File "%s", line 0 %s(sselfs_dt_testsnamesfilenameserr(sselfserr((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysformat_failure s(s__name__s __module__sids__repr__s__str__sformat_failure(((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys DocFileCase s  c Ks|tjo h}n|o| otdn|ot|}t||}ntii |}t |i }|i||||d}t||SdS(Ns8Package may only be specified for module-relative paths.i(sglobssNonespackagesmodule_relatives ValueErrors_normalize_modules_module_relative_pathspathsossbasenamesnamesopensreadsdocsparsers get_docteststests DocFileCasesoptions( spathsmodule_relativespackagesglobssparsersoptionssnamesdocstest((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys DocFileTest s   cOskti}|idtot|id|dA unittest suite for one or more doctest files. The path to each doctest file is given as a string; the interpretation of that string depends on the keyword argument "module_relative". A number of options may be provided as keyword arguments: module_relative If "module_relative" is True, then the given file paths are interpreted as os-independent module-relative paths. By default, these paths are relative to the calling module's directory; but if the "package" argument is specified, then they are relative to that package. To ensure os-independence, "filename" should use "/" characters to separate path segments, and may not be an absolute path (i.e., it may not begin with "/"). If "module_relative" is False, then the given file paths are interpreted as os-specific paths. These paths may be absolute or relative (to the current working directory). package A Python package or the name of a Python package whose directory should be used as the base directory for module relative paths. If "package" is not specified, then the calling module's directory is used as the base directory for module relative filenames. It is an error to specify "package" if "module_relative" is False. setUp A set-up function. This is called before running the tests in each file. The setUp function will be passed a DocTest object. The setUp function can access the test globals as the globs attribute of the test passed. tearDown A tear-down function. This is called after running the tests in each file. The tearDown function will be passed a DocTest object. The tearDown function can access the test globals as the globs attribute of the test passed. globs A dictionary containing initial global variables for the tests. optionflags A set of doctest option flags expressed as an integer. parser A DocTestParser (or subclass) that should be used to extract tests from the files. smodule_relativespackageN( sunittests TestSuitessuiteskwsgetsTrues_normalize_modulespathsspathsaddTests DocFileTest(spathsskwspathssuite((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys DocFileSuite- s4 cCsNg}xti|D]}t|tou|i|id |i }|oM|id|gi}|i dd D]}|d|q~~7}qq|gi}|i dd D]}|t |q~7}qWx'|o|ddjo|iqWx*|o|ddjo|idqWdi|SdS(scExtract script from text with examples. Converts text with examples to a Python script. Example input is converted to regular code. Example output and all other words are converted to comments: >>> text = ''' ... Here are examples of simple math. ... ... Python has super accurate integer addition ... ... >>> 2 + 2 ... 5 ... ... And very friendly error messages: ... ... >>> 1/0 ... To Infinity ... And ... Beyond ... ... You can use logic if you want: ... ... >>> if 0: ... ... blah ... ... blah ... ... ... ... Ho hum ... ''' >>> print script_from_examples(text) # Here are examples of simple math. # # Python has super accurate integer addition # 2 + 2 # Expected: ## 5 # # And very friendly error messages: # 1/0 # Expected: ## To Infinity ## And ## Beyond # # You can use logic if you want: # if 0: blah blah # # Ho hum is # Expected:s s## s#iN(soutputs DocTestParsersparsessspieces isinstancesExamplesappendssourceswants_[1]ssplitsls _comment_linespopsjoin(ssspiecesls_[1]swantsoutput((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysscript_from_exampless s$8  DBcCst|}ti|}gi}|D]$}|i|jo||q,q,~}| ot |dn|d}t |i }|SdS(sExtract the test sources from a doctest docstring as a script. Provide the module (or dotted name of the module) containing the test to be debugged and the name (within the module) of the object with the doc string with tests to be debugged. snot found in testsiN(s_normalize_modulesmodules DocTestFindersfindstestssappends_[1]stsnamestests ValueErrorsscript_from_exampless docstringstestsrc(smodulesnamestestss_[1]stestsrcststest((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys testsource s ; cCs t|}t|||dS(s4Debug a single doctest docstring, in argument `src`'N(sscript_from_examplesssrcstestsrcs debug_scriptspmsglobs(ssrcspmsglobsstestsrc((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys debug_src s cCsdk}tidd}t|d}|i||iz|o|i }nh}|oHyt |||Wqt idGH|it idqXn|id|||Wdti|XdS(s7Debug a test script. `src` is the script, as a string.Ns.pys doctestdebugswiis execfile(%r)(spdbstempfilesmktemps srcfilenamesopensfswritessrcsclosesglobsscopyspmsexecfilessyssexc_infos post_mortemsrunsossremove(ssrcspmsglobssfs srcfilenamespdb((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys debug_script s&   cCs2t|}t||}t|||idS(sDebug a single doctest docstring. Provide the module (or dotted name of the module) containing the test to be debugged and the name (within the module) of the object with the docstring with tests to be debugged. N(s_normalize_modulesmodules testsourcesnamestestsrcs debug_scriptspms__dict__(smodulesnamespmstestsrc((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysdebug s s _TestClasscBs)tZdZdZdZdZRS(s A pointless class, for sanity-checking of docstring testing. Methods: square() get() >>> _TestClass(13).get() + _TestClass(-12).get() 1 >>> hex(_TestClass(13).square().get()) '0xa9' cCs ||_dS(sval -> _TestClass object with associated value val. >>> t = _TestClass(123) >>> print t.get() 123 N(svalsself(sselfsval((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys__init__ scCs|id|_|SdS(sosquare() -> square TestClass's associated value >>> _TestClass(13).square().get() 169 iN(sselfsval(sself((s2build/bdist.linux-i686/egg/paste/util/doctest24.pyssquare scCs |iSdS(s}get() -> return TestClass's associated value. >>> x = _TestClass(-42) >>> print x.get() -42 N(sselfsval(sself((s2build/bdist.linux-i686/egg/paste/util/doctest24.pysget( s(s__name__s __module__s__doc__s__init__ssquaresget(((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys _TestClass s  sstrings Example of a string object, searched as-is. >>> x = 1; y = 2 >>> x + y, x * y (3, 2) sbool-int equivalences In 2.2, boolean expressions displayed 0 or 1. By default, we still accept them. This can be disabled by passing DONT_ACCEPT_TRUE_FOR_1 to the new optionflags argument. >>> 4 == 4 1 >>> 4 == 4 True >>> 4 > 4 0 >>> 4 > 4 False s blank liness Blank lines can be marked with : >>> print 'foo\n\nbar\n' foo bar sellipsiss If the ellipsis flag is used, then '...' can be used to elide substrings in the desired output: >>> print range(1000) #doctest: +ELLIPSIS [0, 1, 2, ..., 999] swhitespace normalizations| If the whitespace normalization flag is used, then differences in whitespace are ignored. >>> print range(30) #doctest: +NORMALIZE_WHITESPACE [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29] cCs ti}|itdS(N(sunittestsTextTestRunnersrsruns DocTestSuite(sr((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys_testd s s__main__(Ps__doc__s __docformat__s__all__s __future__ssyss tracebacksinspects linecachesossrestypessunittestsdifflibspdbstempfileswarningssStringIOsfilterwarningssDeprecationWarnings__name__sOPTIONFLAGS_BY_NAMEsregister_optionflagsDONT_ACCEPT_TRUE_FOR_1sDONT_ACCEPT_BLANKLINEsNORMALIZE_WHITESPACEsELLIPSISsIGNORE_EXCEPTION_DETAILsCOMPARISON_FLAGSs REPORT_UDIFFs REPORT_CDIFFs REPORT_NDIFFsREPORT_ONLY_FIRST_FAILUREsREPORTING_FLAGSsBLANKLINE_MARKERsELLIPSIS_MARKERs is_privates_extract_future_flagss_normalize_modules_indents_exception_tracebacks _SpoofOuts_ellipsis_matchs _comment_linesPdbs_OutputRedirectingPdbs_module_relative_pathsExamplesDocTests DocTestParsers DocTestFinders DocTestRunners OutputCheckers ExceptionsDocTestFailuresUnexpectedExceptions DebugRunnersNonesmastersTruesFalsestestmodstestfilesrun_docstring_examplessTesters_unittest_reportflagssset_unittest_reportflagssTestCases DocTestCases DocTestSuites DocFileCases DocFileTests DocFileSuitesscript_from_exampless testsources debug_srcs debug_scriptsdebugs _TestClasss__test__s_test(Ds_module_relative_paths __future__s OutputCheckersBLANKLINE_MARKERsunittestsCOMPARISON_FLAGSs __docformat__stestmods_normalize_modules REPORT_UDIFFsDONT_ACCEPT_TRUE_FOR_1sNORMALIZE_WHITESPACEs_OutputRedirectingPdbs_ellipsis_matchs _TestClasssIGNORE_EXCEPTION_DETAILs__all__sTesterstempfiles DocFileCases DocTestRunners DocFileTestsres is_privatesDocTestFailures DocTestCasesELLIPSISs_tests _comment_lines REPORT_CDIFFs testsourcesDocTestsDONT_ACCEPT_BLANKLINEs _SpoofOutswarningss DocFileSuitesrun_docstring_examplessREPORT_ONLY_FIRST_FAILUREsinspects debug_scriptsregister_optionflagsscript_from_exampless debug_srcs__test__s_extract_future_flagss_indentsExamplestypess DocTestSuitessyssOPTIONFLAGS_BY_NAMEs DocTestParsersStringIOsset_unittest_reportflagss REPORT_NDIFFs tracebacksdifflibs linecaches DocTestFinders DebugRunnersELLIPSIS_MARKERsREPORTING_FLAGSsdebugsUnexpectedExceptionsosspdbstestfiles_exception_traceback((s2build/bdist.linux-i686/egg/paste/util/doctest24.pys?.si. ?$                  1  $5<+n't*vA $? F P  ,<2  PKZ4Bם,paste/util/scgiserver.pyc; u]Dc@s]dZdkZdkZdkZdklZdZdeifdYZdZ dS(so SCGI-->WSGI application proxy, "SWAP". (Originally written by Titus Brown.) This lets an SCGI front-end like mod_scgi be used to execute WSGI application objects. To use it, subclass the SWAP class like so:: class TestAppHandler(swap.SWAP): def __init__(self, *args, **kwargs): self.prefix = '/canal' self.app_obj = TestAppClass swap.SWAP.__init__(self, *args, **kwargs) where 'TestAppClass' is the application object from WSGI and '/canal' is the prefix for what is served by the SCGI Web-server-side process. Then execute the SCGI handler "as usual" by doing something like this:: scgi_server.SCGIServer(TestAppHandler, port=4000).serve() and point mod_scgi (or whatever your SCGI front end is) at port 4000. Kudos to the WSGI folk for writing a nice PEP & the Quixote folk for writing a nice extensible SCGI server for Python! N(s scgi_servercCs?tidtiti}tiid||fdS(Ns%Y-%m-%d %H:%M:%Ss[%s] %s (stimesstrftimes localtimes timestampssyssstderrswritesmsg(smsgs timestamp((s3build/bdist.linux-i686/egg/paste/util/scgiserver.pysdebug"s sSWAPcBs,tZdZeZeZdZdZRS(s` SCGI->WSGI application proxy: let an SCGI server execute WSGI application objects. cOsL|ip td|ip td|f|}tii||dS(Nsmust set app_objsmust set prefix( sselfsapp_objsAssertionErrorsprefixsargss scgi_servers SCGIHandlers__init__skwargs(sselfsargsskwargs((s3build/bdist.linux-i686/egg/paste/util/scgiserver.pys__init__/s c sX|id} |id}|i| }| |dd,d-Z?d d.Z@d/ZAdd0ZBy-d1kClZlZlZlZeeZWneDj onXd S(2sA collection of string operations (most are no longer used). Warning: most of the code you see here isn't normally used nowadays. Beginning with Python 1.6, many of these functions are implemented as methods on the standard string object. They used to be implemented by a built-in module called strop, but strop is now obsolete itself. Public module variables: whitespace -- a string containing all characters considered whitespace lowercase -- a string containing all characters considered lowercase letters uppercase -- a string containing all characters considered uppercase letters letters -- a string containing all characters considered letters digits -- a string containing all characters considered decimal digits hexdigits -- a string containing all characters considered hexadecimal digits octdigits -- a string containing all characters considered octal digits punctuation -- a string containing all characters considered punctuation printable -- a string containing all characters considered printable s sabcdefghijklmnopqrstuvwxyzsABCDEFGHIJKLMNOPQRSTUVWXYZs 0123456789sabcdefsABCDEFs01234567s !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~iscCsH|pdigi}|i|D]}||iq$~SdS(scapwords(s, [sep]) -> string Split the argument into words using split, capitalize each word using capitalize, and join the capitalized words using join. Note that this replaces runs of whitespace characters by a single space. s N(ssepsjoinsappends_[1]ssssplitsxs capitalize(sssseps_[1]sx((s1build/bdist.linux-i686/egg/paste/util/string24.pyscapwords/scCst|t|jo tdnt otttant}tt |}x,t t|D]}||||| string Return a translation table (a string of 256 bytes long) suitable for use in string.translate. The strings frm and to must be of the same length. s)maketrans arguments must have same lengthsN( slensfromstrstostrs ValueErrors_idmapLsmapsNones_idmapsLsordsrangesisjoin(sfromstrstostrsisL((s1build/bdist.linux-i686/egg/paste/util/string24.pys maketrans=s Ns _multimapcBs tZdZdZdZRS(sHelper class for combining multiple mappings. Used by .{safe_,}substitute() to combine the mapping and keyword arguments. cCs||_||_dS(N(sprimarysselfs_primarys secondarys _secondary(sselfsprimarys secondary((s1build/bdist.linux-i686/egg/paste/util/string24.pys__init__[s cCs4y|i|SWntj o|i|SnXdS(N(sselfs_primaryskeysKeyErrors _secondary(sselfskey((s1build/bdist.linux-i686/egg/paste/util/string24.pys __getitem___s(s__name__s __module__s__doc__s__init__s __getitem__(((s1build/bdist.linux-i686/egg/paste/util/string24.pys _multimapUs  s_TemplateMetaclasscBstZdZdZRS(Ns/ %(delim)s(?: (?P%(delim)s) | # Escape sequence of two delimiters (?P%(id)s) | # delimiter and a Python identifier {(?P%(id)s)} | # delimiter and a braced identifier (?P) # Other ill-formed delimiter exprs ) cCstt|i|||d|jo |i}n/tihdti |i <d|i <}ti |ti tiB|_dS(Nspatternsdelimsid(ssupers_TemplateMetaclasssclss__init__snamesbasessdctspatterns_resescapes delimiters idpatternscompiles IGNORECASEsVERBOSE(sclssnamesbasessdctspattern((s1build/bdist.linux-i686/egg/paste/util/string24.pys__init__ps   .(s__name__s __module__spatterns__init__(((s1build/bdist.linux-i686/egg/paste/util/string24.pys_TemplateMetaclassfs sTemplatecBsDtZdZeZdZdZdZdZdZ dZ RS(s.A string class for supporting $-substitutions.s$s[_a-z][_a-z0-9]*cCs ||_dS(N(stemplatesself(sselfstemplate((s1build/bdist.linux-i686/egg/paste/util/string24.pys__init__scCs|id}|i| it}| od}d}n*|t di |d }t |}t d||fdS(Nsinvalidisis.Invalid placeholder in string: line %d, col %d( smosstartsisselfstemplates splitlinessTrueslinesscolnoslinenoslensjoins ValueError(sselfsmosislinesslinenoscolno((s1build/bdist.linux-i686/egg/paste/util/string24.pys_invalids  cst|djotdn| o |n)|ot||dn |dd}ii |i SdS(NisToo many positional argumentsics|idp |id}|tj o|}d|Sn|idtj o iSn|idtj oi|nt di dS(Nsnamedsbraceds%ssescapedsinvalids#Unrecognized named group in pattern( smosgroupsnamedsNonesmappingsvalsselfs delimiters_invalids ValueErrorspattern(smosvalsnamed(smappingsself(s1build/bdist.linux-i686/egg/paste/util/string24.pysconverts    ( slensargss TypeErrorskwssmappings _multimapsconvertsselfspatternssubstemplate(sselfsargsskwssconvertsmapping((sselfsmappings1build/bdist.linux-i686/egg/paste/util/string24.pys substitutes  cst|djotdn| o |n)|ot||dn |dd}ii |i SdS(NisToo many positional argumentsics|id}|tj o5yd|SWqQtj oi|SqQXn|id}|tj o=yd|SWqtj oid|dSqXn|idtj o iSn|idtj o iSnt di dS( Nsnameds%ssbraceds{s}sescapedsinvalids#Unrecognized named group in pattern( smosgroupsnamedsNonesmappingsKeyErrorsselfs delimitersbraceds ValueErrorspattern(smosnamedsbraced(smappingsself(s1build/bdist.linux-i686/egg/paste/util/string24.pysconverts$    ( slensargss TypeErrorskwssmappings _multimapsconvertsselfspatternssubstemplate(sselfsargsskwssconvertsmapping((sselfsmappings1build/bdist.linux-i686/egg/paste/util/string24.pyssafe_substitutes  ( s__name__s __module__s__doc__s_TemplateMetaclasss __metaclass__s delimiters idpatterns__init__s_invalids substitutessafe_substitute(((s1build/bdist.linux-i686/egg/paste/util/string24.pysTemplate|s   cCs|iSdS(sSlower(s) -> string Return a copy of the string s converted to lowercase. N(ssslower(ss((s1build/bdist.linux-i686/egg/paste/util/string24.pyslowerscCs|iSdS(sSupper(s) -> string Return a copy of the string s converted to uppercase. N(sssupper(ss((s1build/bdist.linux-i686/egg/paste/util/string24.pysupperscCs|iSdS(sswapcase(s) -> string Return a copy of the string s with upper case characters converted to lowercase and vice versa. N(sssswapcase(ss((s1build/bdist.linux-i686/egg/paste/util/string24.pysswapcasescCs|i|SdS(sstrip(s [,chars]) -> string Return a copy of the string s with leading and trailing whitespace removed. If chars is given and not None, remove characters in chars instead. If chars is unicode, S will be converted to unicode before stripping. N(sssstripschars(ssschars((s1build/bdist.linux-i686/egg/paste/util/string24.pysstripscCs|i|SdS(slstrip(s [,chars]) -> string Return a copy of the string s with leading whitespace removed. If chars is given and not None, remove characters in chars instead. N(ssslstripschars(ssschars((s1build/bdist.linux-i686/egg/paste/util/string24.pyslstripscCs|i|SdS(srstrip(s [,chars]) -> string Return a copy of the string s with trailing whitespace removed. If chars is given and not None, remove characters in chars instead. N(sssrstripschars(ssschars((s1build/bdist.linux-i686/egg/paste/util/string24.pysrstripsicCs|i||SdS(srsplit(s [,sep [,maxsplit]]) -> list of strings Return a list of the words in the string s, using sep as the delimiter string. If maxsplit is given, splits at no more than maxsplit places (resulting in at most maxsplit+1 words). If sep is not specified or is None, any whitespace string is a separator. (split and splitfields are synonymous) N(ssssplitssepsmaxsplit(ssssepsmaxsplit((s1build/bdist.linux-i686/egg/paste/util/string24.pyssplits cCs|i||SdS(sWrsplit(s [,sep [,maxsplit]]) -> list of strings Return a list of the words in the string s, using sep as the delimiter string, starting at the end of the string and working to the front. If maxsplit is given, at most maxsplit splits are done. If sep is not specified or is None, any whitespace string is a separator. N(sssrsplitssepsmaxsplit(ssssepsmaxsplit((s1build/bdist.linux-i686/egg/paste/util/string24.pysrsplit(ss cCs|i|SdS(sjoin(list [,sep]) -> string Return a string composed of the words in list, with intervening occurrences of sep. The default separator is a single space. (joinfields and join are synonymous) N(ssepsjoinswords(swordsssep((s1build/bdist.linux-i686/egg/paste/util/string24.pysjoin4s cGs|i|SdS(spindex(s, sub [,start [,end]]) -> int Like find but raises ValueError when the substring is not found. N(sssindexsargs(sssargs((s1build/bdist.linux-i686/egg/paste/util/string24.pysindexBscGs|i|SdS(srrindex(s, sub [,start [,end]]) -> int Like rfind but raises ValueError when the substring is not found. N(sssrindexsargs(sssargs((s1build/bdist.linux-i686/egg/paste/util/string24.pysrindexKscGs|i|SdS(scount(s, sub[, start[,end]]) -> int Return the number of occurrences of substring sub in string s[start:end]. Optional arguments start and end are interpreted as in slice notation. N(ssscountsargs(sssargs((s1build/bdist.linux-i686/egg/paste/util/string24.pyscountTscGs|i|SdS(sfind(s, sub [,start [,end]]) -> in Return the lowest index in s where substring sub is found, such that sub is contained within s[start,end]. Optional arguments start and end are interpreted as in slice notation. Return -1 on failure. N(sssfindsargs(sssargs((s1build/bdist.linux-i686/egg/paste/util/string24.pysfind_s cGs|i|SdS(srfind(s, sub [,start [,end]]) -> int Return the highest index in s where substring sub is found, such that sub is contained within s[start,end]. Optional arguments start and end are interpreted as in slice notation. Return -1 on failure. N(sssrfindsargs(sssargs((s1build/bdist.linux-i686/egg/paste/util/string24.pysrfindls cCst|SdS(sYatof(s) -> float Return the floating point number represented by the string s. N(s_floatss(ss((s1build/bdist.linux-i686/egg/paste/util/string24.pysatof~si cCst||SdS(ssatoi(s [,base]) -> int Return the integer represented by the string s in the given base, which defaults to 10. The string s must consist of one or more digits, possibly preceded by a sign. If base is 0, it is chosen from the leading characters of s, 0 for octal, 0x or 0X for hexadecimal. If base is 16, a preceding 0x or 0X is accepted. N(s_intsssbase(sssbase((s1build/bdist.linux-i686/egg/paste/util/string24.pysatois cCst||SdS(satol(s [,base]) -> long Return the long integer represented by the string s in the given base, which defaults to 10. The string s must consist of one or more digits, possibly preceded by a sign. If base is 0, it is chosen from the leading characters of s, 0 for octal, 0x or 0X for hexadecimal. If base is 16, a preceding 0x or 0X is accepted. A trailing L or l is not accepted, unless base is 0. N(s_longsssbase(sssbase((s1build/bdist.linux-i686/egg/paste/util/string24.pysatols cGs|i||SdS(sljust(s, width[, fillchar]) -> string Return a left-justified version of s, in a field of the specified width, padded with spaces as needed. The string is never truncated. If specified the fillchar is used instead of spaces. N(sssljustswidthsargs(ssswidthsargs((s1build/bdist.linux-i686/egg/paste/util/string24.pysljustscGs|i||SdS(srjust(s, width[, fillchar]) -> string Return a right-justified version of s, in a field of the specified width, padded with spaces as needed. The string is never truncated. If specified the fillchar is used instead of spaces. N(sssrjustswidthsargs(ssswidthsargs((s1build/bdist.linux-i686/egg/paste/util/string24.pysrjustscGs|i||SdS(scenter(s, width[, fillchar]) -> string Return a center version of s, in a field of the specified width. padded with spaces as needed. The string is never truncated. If specified the fillchar is used instead of spaces. N(ssscenterswidthsargs(ssswidthsargs((s1build/bdist.linux-i686/egg/paste/util/string24.pyscenterscCs2t|t ot|}n|i|SdS(szfill(x, width) -> string Pad a numeric string x with zeros on the left, to fill a field of the specified width. The string x is never truncated. N(s isinstancesxs basestringsreprszfillswidth(sxswidth((s1build/bdist.linux-i686/egg/paste/util/string24.pyszfillsicCs|i|SdS(sexpandtabs(s [,tabsize]) -> string Return a copy of the string s with all tab characters replaced by the appropriate number of spaces, depending on the current column, and the tabsize (default 8). N(sss expandtabsstabsize(ssstabsize((s1build/bdist.linux-i686/egg/paste/util/string24.pys expandtabsscCs4|o|i||Sn|i||d SdS(sgtranslate(s,table [,deletions]) -> string Return a copy of the string s, where all characters occurring in the optional argument deletions are removed, and the remaining characters have been mapped through the given translation table, which must be a string of length 256. The deletions argument is not allowed for Unicode strings. iN(s deletionssss translatestable(ssstables deletions((s1build/bdist.linux-i686/egg/paste/util/string24.pys translates cCs|iSdS(socapitalize(s) -> string Return a copy of the string s with only its first character capitalized. N(sss capitalize(ss((s1build/bdist.linux-i686/egg/paste/util/string24.pys capitalizescCs|i|||SdS(sreplace (str, old, new[, maxsplit]) -> string Return a copy of string str with all occurrences of substring old replaced by new. If the optional argument maxsplit is given, only the first maxsplit occurrences are replaced. N(sssreplacesoldsnewsmaxsplit(sssoldsnewsmaxsplit((s1build/bdist.linux-i686/egg/paste/util/string24.pysreplaces(s maketranss lowercases uppercases whitespace(Es__doc__s whitespaces lowercases uppercasesletterssascii_lowercasesascii_uppercases ascii_letterssdigitss hexdigitss octdigitss punctuations printablesmapschrsxrangeslsstrsjoins_idmapsNonescapwordss_idmapLs maketranssres_res _multimapstypes_TemplateMetaclasssTemplates ValueErrors index_errors atoi_errors atof_errors atol_errorslowersuppersswapcasesstripslstripsrstripssplits splitfieldssrsplits joinfieldssindexsrindexscountsfindsrfindsfloats_floatsints_intslongs_longsatofsatoisatolsljustsrjustscenterszfills expandtabss translates capitalizesreplacesstrops ImportError(6sascii_lowercasesuppers_resletterss atol_errorslstrips uppercases ascii_letterssatofsreplacescapwordss index_errors expandtabssTemplatesstripsascii_uppercases octdigitsscountsindexsljusts whitespaces_intsrindexs_floats punctuationsfinds splitfieldsssplitsrstrips translates _multimaps joinfieldssrjusts printableslowersswapcases atof_errorsatois hexdigitssatolsrsplitsdigitss lowercasesjoinscenters_longslsrfinds atoi_errors maketranss capitalizes_TemplateMetaclassszfills_idmap((s1build/bdist.linux-i686/egg/paste/util/string24.pys?sz     Z        PKZ4 paste/util/dateinterval.pyc; u]Dc@sdZdkZddgZdZedZedZedZedZedZed Z hd e <d e<d e<d e<de<de<de"scCsd}|}t|}xNtD]F\}}||jo-t||\}}|d||f7}qqW|djod|}n&| odSn|od|}n|SdS(sEncodes a number of seconds (representing a time interval) into a form like 1h2d3s. >>> interval_encode(10) '10s' >>> interval_encode(493939) '5d17h12m19s' ss%i%sis-s0s+N( ssssecondssorigsabss timeOrderedscharsamountsdivmodsis include_sign(ssecondss include_signsamountscharsisssorig((s5build/bdist.linux-i686/egg/paste/util/dateinterval.pysinterval_encode$s     s[0-9]+[a-zA-Z]cCsd}d}|i}|ido|d}d}n|ido|d}nxmt|tD]\}|iddi }t i | oqjn|t |idd t |7}qjW|SdS(sDecodes a number in the format 1h4d3m (1 hour, 3 days, 3 minutes) into a number of seconds >>> interval_decode('40s') 40 >>> interval_decode('10000s') 10000 >>> interval_decode('3d1w45s') 864045 iis-is+N(stimessignsssstrips startswiths allMatchess_timeREsmatchsgroupslowerschars timeValuesshas_keysint(ssssignscharstimesmatch((s5build/bdist.linux-i686/egg/paste/util/dateinterval.pysinterval_decode=s    )cCsfd}t|}g}|i||}x1|o)|i||i||i}q-W|SdS(s1Return a list of matches for regex in source iN( sposslenssourcesendsrvsregexssearchsmatchsappend(ssourcesregexsrvsendspossmatch((s5build/bdist.linux-i686/egg/paste/util/dateinterval.pys allMatchesYs  s__main__(s__doc__sres__all__ssecondsminuteshoursdaysweeksmonthsyears timeValuessitemss timeOrderedssortsFalsesinterval_encodescompiles_timeREsinterval_decodes allMatchess__name__sdocteststestmod(sweeks timeOrderedshours__all__sinterval_encodes_timeREs allMatchessmonthsressecondsinterval_decodesdoctestsyearsdaysminutes timeValues((s5build/bdist.linux-i686/egg/paste/util/dateinterval.pys? s&        E     PKZ4TjEEpaste/util/filemixin.pyc; u]Dc@sdfdYZdS(s FileMixincBs>tZdZdZdZedZdZdZRS(s Used to provide auxiliary methods to objects simulating files. Objects must implement write, and read if they are input files. Also they should implement close. Other methods you may wish to override: * flush() * seek(offset[, whence]) * tell() * truncate([size]) Attributes you may wish to provide: * closed * encoding (you should also respect that in write()) * mode * newlines (hard to support) * softspace cCsdS(N((sself((s2build/bdist.linux-i686/egg/paste/util/filemixin.pysflushscCs|iSdS(N(sselfsreadline(sself((s2build/bdist.linux-i686/egg/paste/util/filemixin.pysnextscCsg}xno|id}| odi|Sn|i||o|djot||jodi|Sn|djodi|Sq qWdS(Nisis (soutputsselfsreadsnextsjoinsappendssizeslen(sselfssizesoutputsnext((s2build/bdist.linux-i686/egg/paste/util/filemixin.pysreadlines ' cCs|SdS(N(sself(sself((s2build/bdist.linux-i686/egg/paste/util/filemixin.pys xreadlines.scCs"x|D]}|i|qWdS(N(slinesslinesselfswrite(sselfslinessline((s2build/bdist.linux-i686/egg/paste/util/filemixin.pys writelines1s( s__name__s __module__s__doc__sflushsnextsNonesreadlines xreadliness writelines(((s2build/bdist.linux-i686/egg/paste/util/filemixin.pys FileMixins     N(s FileMixin(s FileMixin((s2build/bdist.linux-i686/egg/paste/util/filemixin.pys?sPKZ4'Q  paste/util/quoting.pyc; u]Dc@sdkZdkZdkZdkZdddddgZdZedZeidZ ei d Z ed Z d Z d ZeiZeiZed jodkZeindS(Ns html_quotes html_unquotes url_quotes url_unquotes strip_htmlsUTF-8cCs|pt}|tjodSnqt|toti|dSnMt|toti|i |dSn tit|i |dSdS(s Quote the value (turned to a string) as HTML. This quotes <, >, and quotes: >>> html_quote(1) '1' >>> html_quote(None) '' >>> html_quote('') '<hey!>' >>> html_quote(u'\u1029') '\xe1\x80\xa9' siN( sencodingsdefault_encodingsvsNones isinstancesstrscgisescapesunicodesencode(svsencoding((s0build/bdist.linux-i686/egg/paste/util/quoting.pys html_quotes   s &([a-zA-Z]+);cCs>|i|id}|ot|Sn|idSdS(Nii(sname2csgetsmatchsgroupscodesunichr(smatchsname2cscode((s0build/bdist.linux-i686/egg/paste/util/quoting.pys_entity_subber'scCs>t|to|i|pt}ntit|SdS(s Decode the value. >>> html_unquote('<hey you>') u'' >>> html_unquote('') '' >>> html_unquote('&blahblah;') u'&blahblah;' >>> html_unquote('\xe1\x80\xa9') u'\u1029' N( s isinstancesssstrsdecodesencodingsdefault_encodings _unquote_ressubs_entity_subber(sssencoding((s0build/bdist.linux-i686/egg/paste/util/quoting.pys html_unquote.s cCsYtidd|}|iddidd}|iddid d }|SdS( Ns<.*?>ss s s<ss&s&(sressubsssreplace(ss((s0build/bdist.linux-i686/egg/paste/util/quoting.pys strip_html?scCs|SdS(s* Quoting that doesn't do anything N(ss(ss((s0build/bdist.linux-i686/egg/paste/util/quoting.pysno_quoteFss__main__(scgishtmlentitydefssurllibsres__all__sdefault_encodingsNones html_quotescompiles _unquote_resname2codepoints_entity_subbers html_unquotes strip_htmlsno_quotesquotes url_quotesunquotes url_unquotes__name__sdocteststestmod(scgis__all__s html_unquotes url_quoteshtmlentitydefssdefault_encodingsurllibs _unquote_resresno_quotesdoctests_entity_subbers strip_htmls url_unquotes html_quote((s0build/bdist.linux-i686/egg/paste/util/quoting.pys?s            PKZ4-`/JJEGG-INFO/requires.txt [Flup] flup [openid] python-openid [Paste] [hotshot] [subprocess] PKZ4gEGG-INFO/PKG-INFOMetadata-Version: 1.0 Name: Paste Version: 0.9.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 :: 4 - Beta 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 PK/4EGG-INFO/not-zip-safePKZ4KEGG-INFO/namespace_packages.txtpaste PKZ4KEGG-INFO/top_level.txtpaste PKZ4x5VVEGG-INFO/entry_points.txt [paste.app_factory] cgi = paste.cgiapp:CGIApplication [subprocess] pycgi = paste.pycgiwrapper:CGIWrapper static = paste.urlparser:make_static pkg_resources = paste.urlparser:make_pkg_resources proxy = paste.proxy:make_proxy test = paste.debug.debugapp:make_test_app test_slow = paste.debug.debugapp:make_slow_app [paste.composit_factory] urlmap = paste.urlmap:urlmap_factory cascade = paste.cascade:make_cascade [paste.filter_app_factory] error_catcher = paste.exceptions.errormiddleware:ErrorMiddleware cgitb = paste.cgitb_catcher:CgitbMiddleware flup_session = paste.flup_session:SessionMiddleware [Flup] gzip = paste.gzipper:middleware httpexceptions = paste.httpexceptions:make_middleware lint = paste.lint:make_middleware printdebug = paste.debug.prints:PrintDebugMiddleware profile = paste.debug.profile:ProfileMiddleware [hotshot] recursive = paste.recursive:RecursiveMiddleware # This isn't good enough to deserve the name egg:Paste#session: paste_session = paste.session:SessionMiddleware wdg_validate = paste.debug.wdg_validate:WDGValidateMiddleware [subprocess] evalerror = paste.evalexception:EvalException auth_tkt = paste.auth.auth_tkt:make_auth_tkt_middleware grantip = paste.auth.grantip:make_grantip openid = paste.auth.open_id:make_open_id_middleware [openid] recorder = paste.debug.recorder.record:make_recorder pony = paste.pony:make_pony [paste.server_runner] http = paste.httpserver:server_runner PKZ41EGG-INFO/SOURCES.txtsetup.cfg setup.py Paste.egg-info/PKG-INFO Paste.egg-info/SOURCES.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/doc.conf docs/enabled.txt docs/index.txt docs/install-example.txt docs/news.txt docs/package_index.txt docs/rebuild docs/related-projects.txt docs/template.tmpl 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/error_document.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/pony.py paste/printdebug.py paste/profilemiddleware.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/wdg_validate.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/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/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/multidict.py paste/util/quoting.py paste/util/scgiserver.py paste/util/string24.py paste/util/subprocess24.py paste/util/threadedprint.py paste/util/threadinglocal.py tests/conftest.py tests/test_cgiapp.py tests/test_cgitb_catcher.py tests/test_errordocument.py tests/test_fileapp.py tests/test_grantip.py tests/test_httpheaders.py tests/test_import_string.py tests/test_profilemiddleware.py tests/test_proxy.py tests/test_registry.py tests/test_request.py tests/test_urlmap.py tests/test_urlparser.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/deep/index.html tests/urlparser_data/deep/sub/Main.txt tests/urlparser_data/find_file/index.txt tests/urlparser_data/find_file/test2.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 PK4̖paste/profilemiddleware.pyPK49{9EEOpaste/wsgiwrappers.pyPK4LDD paste/response.pyPK4sEE:=paste/httpserver.pyPK4:,paste/__init__.pyPK4a##paste/urlmap.pyPK4c>>-paste/wsgilib.pyPK45D77 5paste/url.pyPK4.l l paste/cgiapp.pyPK43A A >paste/flup_session.pyPK4 7)!Lpaste/recursive.pyPK4fpaste/error_document.pyPK4lGkkgpaste/httpheaders.pyPK4m:[XXpaste/urlparser.pyPK4'apaste/fileapp.pyPK4}I-~paste/gzipper.pyPK4X\cpaste/proxy.pyPK4> > vpaste/cascade.pyPK4T paste/pony.pyPK4 >paste/fixture.pyPK4,}--tpaste/errordocument.pyPK4_uW337paste/request.pyPK4[[Epaste/httpexceptions.pyPK4v!!S2paste/wdg_validate.pyPK4N N 3paste/reloader.pyPK4(X  $Apaste/printdebug.pyPK4ff@@bBpaste/progress.pyPK4e,99 apaste/lint.pyPK4`((paste/registry.pyPK4kf> > paste/cgitb_catcher.pyPK4I&paste/transaction.pyPK4R9paste/session.pyPK4d* paste/translogger.pyPKZ4 ( paste/profilemiddleware.pycPKZ4--paste/wsgiwrappers.pycPKZ4dn(n(K4paste/response.pycPKZ4Jw;P;P\paste/httpserver.pycPKZ4揼 Vpaste/__init__.pycPKZ4ͱ_,_,paste/urlmap.pycPKZ4i>RRpaste/wsgilib.pycPKZ4}|RR /.paste/url.pycPKZ4K%%!%! paste/cgiapp.pycPKZ4P\paste/flup_session.pycPKZ4/%%Npaste/recursive.pycPKZ4{LLzpaste/error_document.pycPKZ4đ/paste/httpheaders.pycPKZ4/``paste/urlparser.pycPKZ4m4$4$paste/fileapp.pycPKZ4I, , Hpaste/gzipper.pycPKZ4e5'paste/proxy.pycPKZ4 {g9paste/cascade.pycPKZ4Ipaste/pony.pycPKZ4Ppaste/fixture.pycPKZ4_0_0N paste/errordocument.pycPKZ4DZ==~ paste/request.pycPKZ4nȬs paste/httpexceptions.pycPKZ4&d'; paste/wdg_validate.pycPKZ40r``= paste/reloader.pycPKZ4xZN paste/printdebug.pycPKZ4l4*4*SP paste/progress.pycPKZ4DMPNNz paste/lint.pycPKZ42WpN55 paste/registry.pycPKZ4. . r paste/cgitb_catcher.pycPKZ47xS paste/transaction.pycPKZ45-I8 ' paste/session.pycPKZ4>>)I paste/translogger.pycPK4U9&:&:X paste/debug/doctest_webapp.pyPK4v,LL paste/debug/wdg_validate.pyPK4I<44 paste/debug/__init__.pyPK4x{ paste/debug/prints.pyPK4r0 paste/debug/profile.pyPK4.)2)2 paste/debug/fsdiff.pyPK4T6 6 [ paste/debug/testserver.pyPK4{ጲ paste/debug/debugapp.pyPKZ4ϢEE paste/debug/doctest_webapp.pycPKZ4u>>] paste/debug/wdg_validate.pycPKZ4R7zAp paste/debug/__init__.pycPKZ4=~>=q paste/debug/prints.pycPKZ4Pg%% paste/debug/profile.pycPKZ4˰AA' paste/debug/fsdiff.pycPKZ4!!= paste/debug/testserver.pycPKZ4dr  paste/debug/debugapp.pycPK4(+// paste/auth/cookie.pyPK4 < paste/auth/multi.pyPK4X??H paste/auth/open_id.pyPK4SSij paste/auth/__init__.pyPK4e==܉ paste/auth/digest.pyPK4d K paste/auth/basic.pyPK4[//B paste/auth/auth_tkt.pyPK4-Kuu` paste/auth/form.pyPK4,s,## paste/auth/grantip.pyPK4[paste/auth/cas.pyPKZ4QZ;;%paste/auth/cookie.pycPKZ443Spaste/auth/multi.pycPKZ4 U;;wdpaste/auth/open_id.pycPKZ4݀s+jpaste/auth/__init__.pycPKZ4jC##Cpaste/auth/digest.pycPKZ4 _\paste/auth/basic.pycPKZ4H 5757'paste/auth/auth_tkt.pycPKZ4@bpaste/auth/form.pycPKZ4lޯ~$paste/auth/grantip.pycPKZ4I\_/7paste/auth/cas.pycPK4洤+Jpaste/exceptions/serial_number_generator.pyPK4*SS Zpaste/exceptions/__init__.pyPK4=Zpaste/exceptions/reporter.pyPK4RVƴIIkjpaste/exceptions/formatter.pyPK4ĎyWFFZpaste/exceptions/collector.pyPK4K55#paste/exceptions/errormiddleware.pyPKZ4 ,0paste/exceptions/serial_number_generator.pycPKZ4Vc*0Bpaste/exceptions/__init__.pycPKZ4OЦii"paste/evalexception/media/plus.jpgPK4pp+paste/evalexception/mochikit/__package__.jsPK4\ɻ  (=paste/evalexception/mochikit/MochiKit.jsPK44YY6paste/util/threadinglocal.pyPK4NFF<paste/util/UserDict24.pyPK4SM599Qpaste/util/classinit.pyPK45F>** Ypaste/util/datetimeutil.pyPK4,]] paste/util/classinstance.pyPK4-7$7$paste/util/ip4.pyPK4>paste/util/findpackage.pyPK4vepaste/util/threadedprint.pyPK4_5Mpaste/util/multidict.pyPK4FtaÜÜpaste/util/subprocess24.pyPK4-"VVpaste/util/__init__.pyPK4fkqqpaste/util/import_string.pyPK4?gJJDpaste/util/intset.pyPK4 ؂aOaO1paste/util/PySourceColor.pyPK4,JJ paste/util/finddata.pyPK4522I/paste/util/doctest24.pyPK4paste/util/scgiserver.pyPK4QRgAgApaste/util/string24.pyPK4G+qcn n dpaste/util/dateinterval.pyPK4問 paste/util/filemixin.pyPK4 ܾpaste/util/quoting.pyPKZ4paste/util/threadinglocal.pycPKZ4jV-V-(paste/util/UserDict24.pycPKZ49FllUpaste/util/classinit.pycPKZ4,,C^paste/util/datetimeutil.pycPKZ4L paste/util/classinstance.pycPKZ4M ( (paste/util/ip4.pycPKZ4R%paste/util/findpackage.pycPKZ4Į,,paste/util/threadedprint.pycPKZ44w paste/util/multidict.pycPKZ4NJS##paste/util/subprocess24.pycPKZ4Ds"paste/util/__init__.pycPKZ4A>paste/util/import_string.pycPKZ4imhJhJ#paste/util/intset.pycPKZ4r_paste/util/PySourceColor.pycPKZ4#[] ] paste/util/finddata.pycPKZ4_C^yypaste/util/doctest24.pycPKZ4Bם,lpaste/util/scgiserver.pycPKZ4+DQDQwpaste/util/string24.pycPKZ4 paste/util/dateinterval.pycPKZ4TjEE paste/util/filemixin.pycPKZ4'Q  paste/util/quoting.pycPKZ4-`/JJEGG-INFO/requires.txtPKZ4g:EGG-INFO/PKG-INFOPK/46 EGG-INFO/not-zip-safePKZ4Ki EGG-INFO/namespace_packages.txtPKZ4K EGG-INFO/top_level.txtPKZ4x5VV EGG-INFO/entry_points.txtPKZ41sEGG-INFO/SOURCES.txtPK.7#