Gustavo Picon avatar Gustavo Picon committed 13d698d

Removed trailing whitespace from the codebase.

sed -i '' -e 's/ *$//' `find cherrypy -name '*.py'`

Comments (0)

Files changed (80)

cherrypy/__init__.py

 engine.listeners['after_request'] = set()
 
 class _TimeoutMonitor(process.plugins.Monitor):
-    
+
     def __init__(self, bus):
         self.servings = []
         process.plugins.Monitor.__init__(self, bus, self.run)
-    
+
     def before_request(self):
         self.servings.append((serving.request, serving.response))
-    
+
     def after_request(self):
         try:
             self.servings.remove((serving.request, serving.response))
         except ValueError:
             pass
-    
+
     def run(self):
         """Check timeout on all responses. (Internal)"""
         for req, resp in self.servings:
 
 def quickstart(root=None, script_name="", config=None):
     """Mount the given root, start the builtin server (and engine), then block.
-    
+
     root: an instance of a "controller class" (a collection of page handler
         methods) which represents the root of the application.
     script_name: a string containing the "mount point" of the application.
         at which to mount the given root. For example, if root.index() will
         handle requests to "http://www.example.com:8080/dept/app1/", then
         the script_name argument would be "/dept/app1".
-        
+
         It MUST NOT end in a slash. If the script_name refers to the root
         of the URI, it MUST be an empty string (not "/").
     config: a file or dict containing application config. If this contains
     """
     if config:
         _global_conf_alias.update(config)
-    
+
     tree.mount(root, script_name, config)
-    
+
     if hasattr(engine, "signal_handler"):
         engine.signal_handler.subscribe()
     if hasattr(engine, "console_control_handler"):
         engine.console_control_handler.subscribe()
-    
+
     engine.start()
     engine.block()
 
 
 class _Serving(_local):
     """An interface for registering request and response objects.
-    
+
     Rather than have a separate "thread local" object for the request and
     the response, this class works as a single threadlocal container for
     both objects (and any others which developers wish to define). In this
     conversation, yet still refer to them as module-level globals in a
     thread-safe way.
     """
-    
+
     request = _cprequest.Request(_httputil.Host("127.0.0.1", 80),
                                  _httputil.Host("127.0.0.1", 1111))
     """
     The request object for the current thread. In the main thread,
     and any threads which are not receiving HTTP requests, this is None."""
-    
+
     response = _cprequest.Response()
     """
     The response object for the current thread. In the main thread,
     and any threads which are not receiving HTTP requests, this is None."""
-    
+
     def load(self, request, response):
         self.request = request
         self.response = response
-    
+
     def clear(self):
         """Remove all attributes of self."""
         self.__dict__.clear()
 
 
 class _ThreadLocalProxy(object):
-    
+
     __slots__ = ['__attrname__', '__dict__']
-    
+
     def __init__(self, attrname):
         self.__attrname__ = attrname
-    
+
     def __getattr__(self, name):
         child = getattr(serving, self.__attrname__)
         return getattr(child, name)
-    
+
     def __setattr__(self, name, value):
         if name in ("__attrname__", ):
             object.__setattr__(self, name, value)
         else:
             child = getattr(serving, self.__attrname__)
             setattr(child, name, value)
-    
+
     def __delattr__(self, name):
         child = getattr(serving, self.__attrname__)
         delattr(child, name)
-    
+
     def _get_dict(self):
         child = getattr(serving, self.__attrname__)
         d = child.__class__.__dict__.copy()
         d.update(child.__dict__)
         return d
     __dict__ = property(_get_dict)
-    
+
     def __getitem__(self, key):
         child = getattr(serving, self.__attrname__)
         return child[key]
-    
+
     def __setitem__(self, key, value):
         child = getattr(serving, self.__attrname__)
         child[key] = value
-    
+
     def __delitem__(self, key):
         child = getattr(serving, self.__attrname__)
         del child[key]
-    
+
     def __contains__(self, key):
         child = getattr(serving, self.__attrname__)
         return key in child
-    
+
     def __len__(self):
         child = getattr(serving, self.__attrname__)
         return len(child)
-    
+
     def __nonzero__(self):
         child = getattr(serving, self.__attrname__)
         return bool(child)
 
 class _GlobalLogManager(_cplogging.LogManager):
     """A site-wide LogManager; routes to app.log or global log as appropriate.
-    
+
     This :class:`LogManager<cherrypy._cplogging.LogManager>` implements
     cherrypy.log() and cherrypy.log.access(). If either
     function is called during a request, the message will be sent to the
     logger for the current Application. If they are called outside of a
     request, the message will be sent to the site-wide logger.
     """
-    
+
     def __call__(self, *args, **kwargs):
         """Log the given message to the app.log or global log as appropriate."""
         # Do NOT use try/except here. See http://www.cherrypy.org/ticket/945
         else:
             log = self
         return log.error(*args, **kwargs)
-    
+
     def access(self):
         """Log an access message to the app.log or global log as appropriate."""
         try:
                 for a in alias:
                     parents[a.replace(".", "_")] = func
         return func
-    
+
     import sys, types
     if isinstance(func, (types.FunctionType, types.MethodType)):
         if alias is None:
         return expose_
 
 def popargs(*args, **kwargs):
-    """A decorator for _cp_dispatch 
+    """A decorator for _cp_dispatch
     (cherrypy.dispatch.Dispatcher.dispatch_method_name).
 
     Optional keyword argument: handler=(Object or Function)
-    
-    Provides a _cp_dispatch function that pops off path segments into 
+
+    Provides a _cp_dispatch function that pops off path segments into
     cherrypy.request.params under the names specified.  The dispatch
     is then forwarded on to the next vpath element.
-    
+
     Note that any existing (and exposed) member function of the class that
     popargs is applied to will override that value of the argument.  For
     instance, if you have a method named "list" on the class decorated with
     popargs, then accessing "/list" will call that function instead of popping
-    it off as the requested parameter.  This restriction applies to all 
+    it off as the requested parameter.  This restriction applies to all
     _cp_dispatch functions.  The only way around this restriction is to create
     a "blank class" whose only function is to provide _cp_dispatch.
-    
+
     If there are path elements after the arguments, or more arguments
     are requested than are available in the vpath, then the 'handler'
     keyword argument specifies the next object to handle the parameterized
     will be called with the args specified and the return value from that
     function used as the next object INSTEAD of adding the parameters to
     cherrypy.request.args.
-    
+
     This decorator may be used in one of two ways:
-    
+
     As a class decorator:
     @cherrypy.popargs('year', 'month', 'day')
     class Blog:
             #Process the parameters here; any url like
             #/, /2009, /2009/12, or /2009/12/31
             #will fill in the appropriate parameters.
-            
+
         def create(self):
             #This link will still be available at /create.  Defined functions
             #take precedence over arguments.
-            
+
     Or as a member of a class:
     class Blog:
         _cp_dispatch = cherrypy.popargs('year', 'month', 'day')
         #...
-        
+
     The handler argument may be used to mix arguments with built in functions.
     For instance, the following setup allows different activities at the
     day, month, and year level:
-    
+
     class DayHandler:
         def index(self, year, month, day):
             #Do something with this day; probably list entries
-            
+
         def delete(self, year, month, day):
             #Delete all entries for this day
-            
+
     @cherrypy.popargs('day', handler=DayHandler())
     class MonthHandler:
         def index(self, year, month):
             #Do something with this month; probably list entries
-            
+
         def delete(self, year, month):
             #Delete all entries for this month
-            
+
     @cherrypy.popargs('month', handler=MonthHandler())
     class YearHandler:
         def index(self, year):
             #Do something with this year
-            
+
         #...
-        
+
     @cherrypy.popargs('year', handler=YearHandler())
     class Root:
         def index(self):
             #...
-        
+
     """
 
     #Since keyword arg comes after *args, we have to process it ourselves
     if handler is not None \
         and (hasattr(handler, '__call__') or inspect.isclass(handler)):
         handler_call = True
-    
+
     def decorated(cls_or_self=None, vpath=None):
         if inspect.isclass(cls_or_self):
             #cherrypy.popargs is a class decorator
             cls = cls_or_self
             setattr(cls, dispatch.Dispatcher.dispatch_method_name, decorated)
             return cls
-        
+
         #We're in the actual function
         self = cls_or_self
         parms = {}
             if not vpath:
                 break
             parms[arg] = vpath.pop(0)
-                
+
         if handler is not None:
             if handler_call:
                 return handler(**parms)
             else:
                 request.params.update(parms)
                 return handler
-                
+
         request.params.update(parms)
-            
+
         #If we are the ultimate handler, then to prevent our _cp_dispatch
         #from being called again, we will resolve remaining elements through
         #getattr() directly.
             return getattr(self, vpath.pop(0), None)
         else:
             return self
-        
+
     return decorated
 
 def url(path="", qs="", script_name=None, base=None, relative=None):
     """Create an absolute URL for the given path.
-    
+
     If 'path' starts with a slash ('/'), this will return
         (base + script_name + path + qs).
     If it does not start with a slash, this returns
         (base + script_name [+ request.path_info] + path + qs).
-    
+
     If script_name is None, cherrypy.request will be used
     to find a script_name, if available.
-    
+
     If base is None, cherrypy.request.base will be used (if available).
     Note that you can use cherrypy.tools.proxy to change this.
-    
+
     Finally, note that this function can be used to obtain an absolute URL
     for the current request path (minus the querystring) by passing no args.
     If you call url(qs=cherrypy.request.query_string), you should get the
     original browser URL (assuming no internal redirections).
-    
+
     If relative is None or not provided, request.app.relative_urls will
     be used (if available, else False). If False, the output will be an
     absolute URL (including the scheme, host, vhost, and script_name).
         qs = _urlencode(qs)
     if qs:
         qs = '?' + qs
-    
+
     if request.app:
         if not path.startswith("/"):
             # Append/remove trailing slash from path_info as needed
             elif request.is_index is False:
                 if pi.endswith('/') and pi != '/':
                     pi = pi[:-1]
-            
+
             if path == "":
                 path = pi
             else:
                 path = _urljoin(pi, path)
-        
+
         if script_name is None:
             script_name = request.script_name
         if base is None:
             base = request.base
-        
+
         newurl = base + script_name + path + qs
     else:
         # No request.app (we're being called outside a request).
         # if you're using vhosts or tools.proxy.
         if base is None:
             base = server.base()
-        
+
         path = (script_name or "") + path
         newurl = base + path + qs
-    
+
     if './' in newurl:
         # Normalize the URL by removing ./ and ../
         atoms = []
             else:
                 atoms.append(atom)
         newurl = '/'.join(atoms)
-    
+
     # At this point, we should have a fully-qualified absolute URL.
-    
+
     if relative is None:
         relative = getattr(request.app, "relative_urls", False)
-    
+
     # See http://www.ietf.org/rfc/rfc2396.txt
     if relative == 'server':
         # "A relative reference beginning with a single slash character is
             new.pop(0)
         new = (['..'] * len(old)) + new
         newurl = '/'.join(new)
-    
+
     return newurl
 
 

cherrypy/_cpchecker.py

 
 class Checker(object):
     """A checker for CherryPy sites and their mounted applications.
-    
+
     When this object is called at engine startup, it executes each
     of its own methods whose names start with ``check_``. If you wish
     to disable selected checks, simply add a line in your global
     config which sets the appropriate method to False::
-    
+
         [global]
         checker.check_skipped_app_config = False
-    
+
     You may also dynamically add or replace ``check_*`` methods in this way.
     """
-    
+
     on = True
     """If True (the default), run all checks; if False, turn off all checks."""
-    
-    
+
+
     def __init__(self):
         self._populate_known_types()
-    
+
     def __call__(self):
         """Run all check_* methods."""
         if self.on:
                             method()
             finally:
                 warnings.formatwarning = oldformatwarning
-    
+
     def formatwarning(self, message, category, filename, lineno, line=None):
         """Function to format a warning."""
         return "CherryPy Checker:\n%s\n\n" % message
-    
+
     # This value should be set inside _cpconfig.
     global_config_contained_paths = False
-    
+
     def check_app_config_entries_dont_start_with_script_name(self):
         """Check for Application config with sections that repeat script_name."""
         for sn, app in cherrypy.tree.apps.items():
                     warnings.warn(
                         "The application mounted at %r has config " \
                         "entries that start with its script name: %r" % (sn, key))
-    
+
     def check_site_config_entries_in_app_config(self):
         """Check for mounted Applications that have site-scoped config."""
         for sn, app in iteritems(cherrypy.tree.apps):
             if not isinstance(app, cherrypy.Application):
                 continue
-            
+
             msg = []
             for section, entries in iteritems(app.config):
                 if section.startswith('/'):
                     "config. Move them to a [global] section and pass them "
                     "to cherrypy.config.update() instead of tree.mount()." % sn)
                 warnings.warn(os.linesep.join(msg))
-    
+
     def check_skipped_app_config(self):
         """Check for mounted Applications that have no config."""
         for sn, app in cherrypy.tree.apps.items():
                             "cherrypy.tree.mount(..., config=app_config)")
                 warnings.warn(msg)
                 return
-    
+
     def check_app_config_brackets(self):
         """Check for Application config with extraneous brackets in section names."""
         for sn, app in cherrypy.tree.apps.items():
                         "section names with extraneous brackets: %r. "
                         "Config *files* need brackets; config *dicts* "
                         "(e.g. passed to tree.mount) do not." % (sn, key))
-    
+
     def check_static_paths(self):
         """Check Application config for incorrect static paths."""
         # Use the dummy Request object in the main thread.
                 # get_resource will populate request.config
                 request.get_resource(section + "/dummy.html")
                 conf = request.config.get
-                
+
                 if conf("tools.staticdir.on", False):
                     msg = ""
                     root = conf("tools.staticdir.root")
                                 fulldir = os.path.join(root, dir)
                                 if not os.path.isabs(fulldir):
                                     msg = "%r is not an absolute path." % fulldir
-                        
+
                         if fulldir and not os.path.exists(fulldir):
                             if msg:
                                 msg += "\n"
                             msg += ("%r (root + dir) is not an existing "
                                     "filesystem path." % fulldir)
-                    
+
                     if msg:
                         warnings.warn("%s\nsection: [%s]\nroot: %r\ndir: %r"
                                       % (msg, section, root, dir))
-    
-    
+
+
     # -------------------------- Compatibility -------------------------- #
-    
+
     obsolete = {
         'server.default_content_type': 'tools.response_headers.headers',
         'log_access_file': 'log.access_file',
         'profiler.on': ('cherrypy.tree.mount(profiler.make_app('
                         'cherrypy.Application(Root())))'),
         }
-    
+
     deprecated = {}
-    
+
     def _compat(self, config):
         """Process config and warn on each obsolete or deprecated entry."""
         for section, conf in config.items():
                 elif section in self.deprecated:
                     warnings.warn("%r is deprecated. Use %r instead."
                                   % (section, self.deprecated[section]))
-    
+
     def check_compatibility(self):
         """Process config and warn on each obsolete or deprecated entry."""
         self._compat(cherrypy.config)
             if not isinstance(app, cherrypy.Application):
                 continue
             self._compat(app.config)
-    
-    
+
+
     # ------------------------ Known Namespaces ------------------------ #
-    
+
     extra_config_namespaces = []
-    
+
     def _known_ns(self, app):
         ns = ["wsgi"]
         ns.extend(copykeys(app.toolboxes))
         ns.extend(copykeys(app.request_class.namespaces))
         ns.extend(copykeys(cherrypy.config.namespaces))
         ns += self.extra_config_namespaces
-        
+
         for section, conf in app.config.items():
             is_path_section = section.startswith("/")
             if is_path_section and isinstance(conf, dict):
                                        "because the %r tool was not found.\n"
                                        "section: [%s]" % (k, atoms[1], section))
                                 warnings.warn(msg)
-    
+
     def check_config_namespaces(self):
         """Process config and warn on each unknown config namespace."""
         for sn, app in cherrypy.tree.apps.items():
             self._known_ns(app)
 
 
-    
-    
+
+
     # -------------------------- Config Types -------------------------- #
-    
+
     known_config_types = {}
-    
+
     def _populate_known_types(self):
         b = [x for x in vars(builtins).values()
              if type(x) is type(str)]
-        
+
         def traverse(obj, namespace):
             for name in dir(obj):
                 # Hack for 3.2's warning about body_params
                 vtype = type(getattr(obj, name, None))
                 if vtype in b:
                     self.known_config_types[namespace + "." + name] = vtype
-        
+
         traverse(cherrypy.request, "request")
         traverse(cherrypy.response, "response")
         traverse(cherrypy.server, "server")
         traverse(cherrypy.engine, "engine")
         traverse(cherrypy.log, "log")
-    
+
     def _known_types(self, config):
         msg = ("The config entry %r in section %r is of type %r, "
                "which does not match the expected type %r.")
-        
+
         for section, conf in config.items():
             if isinstance(conf, dict):
                 for k, v in conf.items():
                     if expected_type and vtype != expected_type:
                         warnings.warn(msg % (k, section, vtype.__name__,
                                              expected_type.__name__))
-    
+
     def check_config_types(self):
         """Assert that config values are of the same type as default values."""
         self._known_types(cherrypy.config)
             if not isinstance(app, cherrypy.Application):
                 continue
             self._known_types(app.config)
-    
-    
+
+
     # -------------------- Specific config warnings -------------------- #
-    
+
     def check_localhost(self):
         """Warn if any socket_host is 'localhost'. See #711."""
         for k, v in cherrypy.config.items():

cherrypy/_cpconfig.py

 
     class Demo:
         _cp_config = {'tools.gzip.on': True}
-        
+
         def index(self):
             return "Hello world"
         index.exposed = True
         index._cp_config = {'request.show_tracebacks': False}
 
 .. note::
-    
+
     This behavior is only guaranteed for the default dispatcher.
     Other dispatchers may have different restrictions on where
     you can attach _cp_config attributes.
 
 def merge(base, other):
     """Merge one app config (from a dict, file, or filename) into another.
-    
+
     If the given config is a filename, it will be appended to
     the list of files to monitor for "autoreload" changes.
     """
     if isinstance(other, basestring):
         cherrypy.engine.autoreload.files.add(other)
-    
+
     # Load other into base
     for section, value_map in reprconf.as_dict(other).items():
         if not isinstance(value_map, dict):
         if 'tools.staticdir.dir' in config:
             config['tools.staticdir.section'] = "global"
         reprconf.Config._apply(self, config)
-    
+
     def __call__(self, *args, **kwargs):
         """Decorator for page handlers to set _cp_config."""
         if args:
         # to configure additional HTTP servers.
         if not hasattr(cherrypy, "servers"):
             cherrypy.servers = {}
-        
+
         servername, k = atoms
         if servername not in cherrypy.servers:
             from cherrypy import _cpserver
             cherrypy.servers[servername] = _cpserver.Server()
             # On by default, but 'on = False' can unsubscribe it (see below).
             cherrypy.servers[servername].subscribe()
-        
+
         if k == 'on':
             if v:
                 cherrypy.servers[servername].subscribe()

cherrypy/_cpdispatch.py

 
 class PageHandler(object):
     """Callable which sets response.body."""
-    
+
     def __init__(self, callable, *args, **kwargs):
         self.callable = callable
         self.args = args
         self.kwargs = kwargs
-    
+
     def __call__(self):
         try:
             return self.callable(*self.args, **self.kwargs)
         if isinstance(callable, object) and hasattr(callable, '__call__'):
             (args, varargs, varkw, defaults) = inspect.getargspec(callable.__call__)
         else:
-            # If it wasn't one of our own types, re-raise 
+            # If it wasn't one of our own types, re-raise
             # the original error
             raise
 
         # 2. not enough body parameters -> 400
         # 3. not enough path parts (partial matches) -> 404
         #
-        # We can't actually tell which case it is, 
+        # We can't actually tell which case it is,
         # so I'm raising a 404 because that covers 2/3 of the
         # possibilities
-        # 
+        #
         # In the case where the method does not allow body
         # arguments it's definitely a 404.
         message = None
     takes that into account, and allows request.params to be 'bound late'
     (it's more complicated than that, but that's the effect).
     """
-    
+
     def _get_kwargs(self):
         kwargs = cherrypy.serving.request.params.copy()
         if self._kwargs:
             kwargs.update(self._kwargs)
         return kwargs
-    
+
     def _set_kwargs(self, kwargs):
         self._kwargs = kwargs
-    
+
     kwargs = property(_get_kwargs, _set_kwargs,
                       doc='page handler kwargs (with '
                       'cherrypy.request.params copied in)')
 
 class Dispatcher(object):
     """CherryPy Dispatcher which walks a tree of objects to find a handler.
-    
+
     The tree is rooted at cherrypy.request.app.root, and each hierarchical
     component in the path_info argument is matched to a corresponding nested
     attribute of the root object. Matching handlers must have an 'exposed'
     matches a URI which ends in a slash ("/"). The special method name
     "default" may match a portion of the path_info (but only when no longer
     substring of the path_info matches some other object).
-    
+
     This is the default, built-in dispatcher for CherryPy.
     """
-    
+
     dispatch_method_name = '_cp_dispatch'
     """
     The name of the dispatch method that nodes may optionally implement
     to provide their own dynamic dispatch algorithm.
     """
-    
+
     def __init__(self, dispatch_method_name=None,
                  translate=punctuation_to_underscores):
         validate_translator(translate)
         """Set handler and config for the current request."""
         request = cherrypy.serving.request
         func, vpath = self.find_handler(path_info)
-        
+
         if func:
             # Decode any leftover %2F in the virtual_path atoms.
             vpath = [x.replace("%2F", "/") for x in vpath]
             request.handler = LateParamPageHandler(func, *vpath)
         else:
             request.handler = cherrypy.NotFound()
-    
+
     def find_handler(self, path):
         """Return the appropriate page handler, plus any virtual path.
-        
+
         This will return two objects. The first will be a callable,
         which can be used to generate page output. Any parameters from
         the query string or request body will be sent to that callable
         as keyword arguments.
-        
+
         The callable is found by traversing the application's tree,
         starting from cherrypy.request.app.root, and matching path
         components to successive objects in the tree. For example, the
         URL "/path/to/handler" might return root.path.to.handler.
-        
+
         The second object returned will be a list of names which are
         'virtual path' components: parts of the URL which are dynamic,
         and were not used when looking up the handler.
         app = request.app
         root = app.root
         dispatch_name = self.dispatch_method_name
-        
+
         # Get config for the root object/path.
         fullpath = [x for x in path.strip('/').split('/') if x] + ['index']
         fullpath_len = len(fullpath)
         if "/" in app.config:
             nodeconf.update(app.config["/"])
         object_trail = [['root', root, nodeconf, segleft]]
-        
+
         node = root
         iternames = fullpath[:]
         while iternames:
             name = iternames[0]
             # map to legal Python identifiers (e.g. replace '.' with '_')
             objname = name.translate(self.translate)
-            
+
             nodeconf = {}
             subnode = getattr(node, objname, None)
             pre_len = len(iternames)
                     )
             elif segleft == pre_len:
                 #Assume that the handler used the current path segment, but
-                #did not pop it.  This allows things like 
+                #did not pop it.  This allows things like
                 #return getattr(self, vpath[0], None)
                 iternames.pop(0)
                 segleft -= 1
                 # Get _cp_config attached to this node.
                 if hasattr(node, "_cp_config"):
                     nodeconf.update(node._cp_config)
-            
+
             # Mix in values from app.config for this path.
             existing_len = fullpath_len - pre_len
             if existing_len != 0:
                 curpath += '/' + seg
                 if curpath in app.config:
                     nodeconf.update(app.config[curpath])
-            
+
             object_trail.append([name, node, nodeconf, segleft])
-            
+
         def set_conf():
             """Collapse all object_trail config into cherrypy.request.config."""
             base = cherrypy.config.copy()
                 if 'tools.staticdir.dir' in conf:
                     base['tools.staticdir.section'] = '/' + '/'.join(fullpath[0:fullpath_len - segleft])
             return base
-        
+
         # Try successive objects (reverse order)
         num_candidates = len(object_trail) - 1
         for i in range(num_candidates, -1, -1):
-            
+
             name, candidate, nodeconf, segleft = object_trail[i]
             if candidate is None:
                 continue
-            
+
             # Try a "default" method on the current leaf.
             if hasattr(candidate, "default"):
                 defhandler = candidate.default
                     # See http://www.cherrypy.org/ticket/613
                     request.is_index = path.endswith("/")
                     return defhandler, fullpath[fullpath_len - segleft:-1]
-            
+
             # Uncomment the next line to restrict positional params to "default".
             # if i < num_candidates - 2: continue
-            
+
             # Try the current leaf.
             if getattr(candidate, 'exposed', False):
                 request.config = set_conf()
                     # positional parameters (virtual paths).
                     request.is_index = False
                 return candidate, fullpath[fullpath_len - segleft:-1]
-        
+
         # We didn't find anything
         request.config = set_conf()
         return None, []
 
 class MethodDispatcher(Dispatcher):
     """Additional dispatch based on cherrypy.request.method.upper().
-    
+
     Methods named GET, POST, etc will be called on an exposed class.
     The method names must be all caps; the appropriate Allow header
     will be output showing all capitalized method names as allowable
     HTTP verbs.
-    
+
     Note that the containing class must be exposed, not the methods.
     """
-    
+
     def __call__(self, path_info):
         """Set handler and config for the current request."""
         request = cherrypy.serving.request
         resource, vpath = self.find_handler(path_info)
-        
+
         if resource:
             # Set Allow header
             avail = [m for m in dir(resource) if m.isupper()]
                 avail.append("HEAD")
             avail.sort()
             cherrypy.serving.response.headers['Allow'] = ", ".join(avail)
-            
+
             # Find the subhandler
             meth = request.method.upper()
             func = getattr(resource, meth, None)
                 # Grab any _cp_config on the subhandler.
                 if hasattr(func, "_cp_config"):
                     request.config.update(func._cp_config)
-                
+
                 # Decode any leftover %2F in the virtual_path atoms.
                 vpath = [x.replace("%2F", "/") for x in vpath]
                 request.handler = LateParamPageHandler(func, *vpath)
 
 class RoutesDispatcher(object):
     """A Routes based dispatcher for CherryPy."""
-    
+
     def __init__(self, full_result=False):
         """
         Routes dispatcher
         self.controllers = {}
         self.mapper = routes.Mapper()
         self.mapper.controller_scan = self.controllers.keys
-        
+
     def connect(self, name, route, controller, **kwargs):
         self.controllers[name] = controller
         self.mapper.connect(name, route, controller=name, **kwargs)
-    
+
     def redirect(self, url):
         raise cherrypy.HTTPRedirect(url)
-    
+
     def __call__(self, path_info):
         """Set handler and config for the current request."""
         func = self.find_handler(path_info)
             cherrypy.serving.request.handler = LateParamPageHandler(func)
         else:
             cherrypy.serving.request.handler = cherrypy.NotFound()
-    
+
     def find_handler(self, path_info):
         """Find the right page handler, and set request.config."""
         import routes
-        
+
         request = cherrypy.serving.request
-        
+
         config = routes.request_config()
         config.mapper = self.mapper
         if hasattr(request, 'wsgi_environ'):
         config.host = request.headers.get('Host', None)
         config.protocol = request.scheme
         config.redirect = self.redirect
-        
+
         result = self.mapper.match(path_info)
-        
+
         config.mapper_dict = result
         params = {}
         if result:
             params.pop('controller', None)
             params.pop('action', None)
         request.params.update(params)
-        
+
         # Get config for the root object/path.
         request.config = base = cherrypy.config.copy()
         curpath = ""
-        
+
         def merge(nodeconf):
             if 'tools.staticdir.dir' in nodeconf:
                 nodeconf['tools.staticdir.section'] = curpath or "/"
             base.update(nodeconf)
-        
+
         app = request.app
         root = app.root
         if hasattr(root, "_cp_config"):
             merge(root._cp_config)
         if "/" in app.config:
             merge(app.config["/"])
-        
+
         # Mix in values from app.config.
         atoms = [x for x in path_info.split("/") if x]
         if atoms:
             curpath = "/".join((curpath, atom))
             if curpath in app.config:
                 merge(app.config[curpath])
-        
+
         handler = None
         if result:
             controller = result.get('controller')
                 # Get config from the controller.
                 if hasattr(controller, "_cp_config"):
                     merge(controller._cp_config)
-            
+
             action = result.get('action')
             if action is not None:
                 handler = getattr(controller, action, None)
-                # Get config from the handler 
-                if hasattr(handler, "_cp_config"): 
+                # Get config from the handler
+                if hasattr(handler, "_cp_config"):
                     merge(handler._cp_config)
             else:
                 handler = controller
-        
+
         # Do the last path atom here so it can
         # override the controller's _cp_config.
         if last:
             curpath = "/".join((curpath, last))
             if curpath in app.config:
                 merge(app.config[curpath])
-        
+
         return handler
 
 
 def VirtualHost(next_dispatcher=Dispatcher(), use_x_forwarded_host=True, **domains):
     """
     Select a different handler based on the Host header.
-    
+
     This can be useful when running multiple sites within one CP server.
     It allows several domains to point to different parts of a single
     website structure. For example::
-    
+
         http://www.domain.example  ->  root
         http://www.domain2.example  ->  root/domain2/
         http://www.domain2.example:443  ->  root/secure
-    
+
     can be accomplished via the following config::
-    
+
         [/]
         request.dispatch = cherrypy.dispatch.VirtualHost(
             **{'www.domain2.example': '/domain2',
                'www.domain2.example:443': '/secure',
               })
-    
+
     next_dispatcher
         The next dispatcher object in the dispatch chain.
         The VirtualHost dispatcher adds a prefix to the URL and calls
         another dispatcher. Defaults to cherrypy.dispatch.Dispatcher().
-    
+
     use_x_forwarded_host
         If True (the default), any "X-Forwarded-Host"
         request header will be used instead of the "Host" header. This
         is commonly added by HTTP servers (such as Apache) when proxying.
-    
+
     ``**domains``
         A dict of {host header value: virtual prefix} pairs.
         The incoming "Host" request header is looked up in this dict,
     def vhost_dispatch(path_info):
         request = cherrypy.serving.request
         header = request.headers.get
-        
+
         domain = header('Host', '')
         if use_x_forwarded_host:
             domain = header("X-Forwarded-Host", domain)
-        
+
         prefix = domains.get(domain, "")
         if prefix:
             path_info = httputil.urljoin(prefix, path_info)
-        
+
         result = next_dispatcher(path_info)
-        
+
         # Touch up staticdir config. See http://www.cherrypy.org/ticket/614.
         section = request.config.get('tools.staticdir.section')
         if section:
             section = section[len(prefix):]
             request.config['tools.staticdir.section'] = section
-        
+
         return result
     return vhost_dispatch
 

cherrypy/_cplogging.py

 
     #python
     log = app.log
-    
+
     # Remove the default FileHandlers if present.
     log.error_file = ""
     log.access_file = ""
-    
+
     maxBytes = getattr(log, "rot_maxBytes", 10000000)
     backupCount = getattr(log, "rot_backupCount", 1000)
-    
+
     # Make a new RotatingFileHandler for the error log.
     fname = getattr(log, "rot_error_file", "error.log")
     h = handlers.RotatingFileHandler(fname, 'a', maxBytes, backupCount)
     h.setLevel(DEBUG)
     h.setFormatter(_cplogging.logfmt)
     log.error_log.addHandler(h)
-    
+
     # Make a new RotatingFileHandler for the access log.
     fname = getattr(log, "rot_access_file", "access.log")
     h = handlers.RotatingFileHandler(fname, 'a', maxBytes, backupCount)
 
 class LogManager(object):
     """An object to assist both simple and advanced logging.
-    
+
     ``cherrypy.log`` is an instance of this class.
     """
-    
+
     appid = None
     """The id() of the Application object which owns this log manager. If this
     is a global log manager, appid is None."""
-   
+
     error_log = None
     """The actual :class:`logging.Logger` instance for error messages."""
-    
+
     access_log = None
     """The actual :class:`logging.Logger` instance for access messages."""
-    
+
     if py3k:
         access_log_format = \
             '{h} {l} {u} {t} "{r}" {s} {b} "{f}" "{a}"'
     else:
         access_log_format = \
             '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
-    
+
     logger_root = None
     """The "top-level" logger name.
-    
+
     This string will be used as the first segment in the Logger names.
     The default is "cherrypy", for example, in which case the Logger names
     will be of the form::
-    
+
         cherrypy.error.<appid>
         cherrypy.access.<appid>
     """
-    
+
     def __init__(self, appid=None, logger_root="cherrypy"):
         self.logger_root = logger_root
         self.appid = appid
                     h.stream.close()
                     h.stream = open(h.baseFilename, h.mode)
                     h.release()
-    
+
     def error(self, msg='', context='', severity=logging.INFO, traceback=False):
         """Write the given ``msg`` to the error log.
-        
+
         This is not just for errors! Applications may call this at any time
         to log application-specific information.
-        
+
         If ``traceback`` is True, the traceback of the current exception
         (if any) will be appended to ``msg``.
         """
         if traceback:
             msg += _cperror.format_exc()
         self.error_log.log(severity, ' '.join((self.time(), context, msg)))
-    
+
     def __call__(self, *args, **kwargs):
         """An alias for ``error``."""
         return self.error(*args, **kwargs)
-    
+
     def access(self):
         """Write to the access log (in Apache/NCSA Combined Log format).
-        
+
         See http://httpd.apache.org/docs/2.0/logs.html#combined for format
         details.
-        
+
         CherryPy calls this automatically for you. Note there are no arguments;
         it collects the data itself from
         :class:`cherrypy.request<cherrypy._cprequest.Request>`.
-        
+
         Like Apache started doing in 2.0.46, non-printable and other special
         characters in %r (and we expand that to all parts) are escaped using
         \\xhh sequences, where hh stands for the hexadecimal representation
             status = response.output_status.split(ntob(" "), 1)[0]
             if py3k:
                 status = status.decode('ISO-8859-1')
-        
+
         atoms = {'h': remote.name or remote.ip,
                  'l': '-',
                  'u': getattr(request, "login", None) or "-",
                 # Fortunately, repr(str) escapes unprintable chars, \n, \t, etc
                 # and backslash for us. All we have to do is strip the quotes.
                 v = repr(v)[2:-1]
-                
-                # in python 3.0 the repr of bytes (as returned by encode) 
+
+                # in python 3.0 the repr of bytes (as returned by encode)
                 # uses double \'s.  But then the logger escapes them yet, again
                 # resulting in quadruple slashes.  Remove the extra one here.
                 v = v.replace('\\\\', '\\')
-                
+
                 # Escape double-quote.
                 atoms[k] = v
-            
+
             try:
                 self.access_log.log(logging.INFO, self.access_log_format.format(**atoms))
             except:
                 v = repr(v)[1:-1]
                 # Escape double-quote.
                 atoms[k] = v.replace('"', '\\"')
-            
+
             try:
                 self.access_log.log(logging.INFO, self.access_log_format % atoms)
             except:
                 self(traceback=True)
-    
+
     def time(self):
         """Return now() in Apache Common Log Format (no timezone)."""
         now = datetime.datetime.now()
         month = monthnames[now.month - 1].capitalize()
         return ('[%02d/%s/%04d:%02d:%02d:%02d]' %
                 (now.day, month, now.year, now.hour, now.minute, now.second))
-    
+
     def _get_builtin_handler(self, log, key):
         for h in log.handlers:
             if getattr(h, "_cpbuiltin", None) == key:
                 return h
-    
-    
+
+
     # ------------------------- Screen handlers ------------------------- #
-    
+
     def _set_screen_handler(self, log, enable, stream=None):
         h = self._get_builtin_handler(log, "screen")
         if enable:
                 log.addHandler(h)
         elif h:
             log.handlers.remove(h)
-    
+
     def _get_screen(self):
         h = self._get_builtin_handler
         has_h = h(self.error_log, "screen") or h(self.access_log, "screen")
         return bool(has_h)
-    
+
     def _set_screen(self, newvalue):
         self._set_screen_handler(self.error_log, newvalue, stream=sys.stderr)
         self._set_screen_handler(self.access_log, newvalue, stream=sys.stdout)
     screen = property(_get_screen, _set_screen,
         doc="""Turn stderr/stdout logging on or off.
-        
+
         If you set this to True, it'll add the appropriate StreamHandler for
         you. If you set it to False, it will remove the handler.
         """)
-    
+
     # -------------------------- File handlers -------------------------- #
-    
+
     def _add_builtin_file_handler(self, log, fname):
         h = logging.FileHandler(fname)
         h.setFormatter(logfmt)
         h._cpbuiltin = "file"
         log.addHandler(h)
-    
+
     def _set_file_handler(self, log, filename):
         h = self._get_builtin_handler(log, "file")
         if filename:
             if h:
                 h.close()
                 log.handlers.remove(h)
-    
+
     def _get_error_file(self):
         h = self._get_builtin_handler(self.error_log, "file")
         if h:
         self._set_file_handler(self.error_log, newvalue)
     error_file = property(_get_error_file, _set_error_file,
         doc="""The filename for self.error_log.
-        
+
         If you set this to a string, it'll add the appropriate FileHandler for
         you. If you set it to ``None`` or ``''``, it will remove the handler.
         """)
-    
+
     def _get_access_file(self):
         h = self._get_builtin_handler(self.access_log, "file")
         if h:
         self._set_file_handler(self.access_log, newvalue)
     access_file = property(_get_access_file, _set_access_file,
         doc="""The filename for self.access_log.
-        
+
         If you set this to a string, it'll add the appropriate FileHandler for
         you. If you set it to ``None`` or ``''``, it will remove the handler.
         """)
-    
+
     # ------------------------- WSGI handlers ------------------------- #
-    
+
     def _set_wsgi_handler(self, log, enable):
         h = self._get_builtin_handler(log, "wsgi")
         if enable:
                 log.addHandler(h)
         elif h:
             log.handlers.remove(h)
-    
+
     def _get_wsgi(self):
         return bool(self._get_builtin_handler(self.error_log, "wsgi"))
-    
+
     def _set_wsgi(self, newvalue):
         self._set_wsgi_handler(self.error_log, newvalue)
     wsgi = property(_get_wsgi, _set_wsgi,
         doc="""Write errors to wsgi.errors.
-        
+
         If you set this to True, it'll add the appropriate
         :class:`WSGIErrorHandler<cherrypy._cplogging.WSGIErrorHandler>` for you
         (which writes errors to ``wsgi.errors``).
 
 class WSGIErrorHandler(logging.Handler):
     "A handler class which writes logging records to environ['wsgi.errors']."
-    
+
     def flush(self):
         """Flushes the stream."""
         try:
             pass
         else:
             stream.flush()
-    
+
     def emit(self, record):
         """Emit a record."""
         try:

cherrypy/_cpmodpy.py

 LoadModule python_module /usr/lib/apache2/modules/mod_python.so
 
 <Location "/">
-	PythonPath "sys.path+['/path/to/my/application']" 
+	PythonPath "sys.path+['/path/to/my/application']"
 	SetHandler python-program
 	PythonHandler cherrypy._cpmodpy::handler
 	PythonOption cherrypy.setup myapp::setup_server
 	PythonDebug On
-</Location> 
+</Location>
 # End
 
 The actual path to your mod_python.so is dependent on your
 
 def setup(req):
     from mod_python import apache
-    
+
     # Run any setup functions defined by a "PythonOption cherrypy.setup" directive.
     options = req.get_options()
     if 'cherrypy.setup' in options:
                 mod = __import__(modname, globals(), locals(), [fname])
                 func = getattr(mod, fname)
                 func()
-    
+
     cherrypy.config.update({'log.screen': False,
                             "tools.ignore_headers.on": True,
                             "tools.ignore_headers.headers": ['Range'],
                             })
-    
+
     engine = cherrypy.engine
     if hasattr(engine, "signal_handler"):
         engine.signal_handler.unsubscribe()
         engine.console_control_handler.unsubscribe()
     engine.autoreload.unsubscribe()
     cherrypy.server.unsubscribe()
-    
+
     def _log(msg, level):
         newlevel = apache.APLOG_ERR
         if logging.DEBUG >= level:
         # Also, "When server is not specified...LogLevel does not apply..."
         apache.log_error(msg, newlevel, req.server)
     engine.subscribe('log', _log)
-    
+
     engine.start()
-    
+
     def cherrypy_cleanup(data):
         engine.exit()
     try:
         if not _isSetUp:
             setup(req)
             _isSetUp = True
-        
+
         # Obtain a Request object from CherryPy
         local = req.connection.local_addr
         local = httputil.Host(local[0], local[1], req.connection.local_host or "")
         remote = req.connection.remote_addr
         remote = httputil.Host(remote[0], remote[1], req.connection.remote_host or "")
-        
+
         scheme = req.parsed_uri[0] or 'http'
         req.get_basic_auth_pw()
-        
+
         try:
             # apache.mpm_query only became available in mod_python 3.1
             q = apache.mpm_query
             bad_value = ("You must provide a PythonOption '%s', "
                          "either 'on' or 'off', when running a version "
                          "of mod_python < 3.1")
-            
+
             threaded = options.get('multithread', '').lower()
             if threaded == 'on':
                 threaded = True
                 threaded = False
             else:
                 raise ValueError(bad_value % "multithread")
-            
+
             forked = options.get('multiprocess', '').lower()
             if forked == 'on':
                 forked = True
                 forked = False
             else:
                 raise ValueError(bad_value % "multiprocess")
-        
+
         sn = cherrypy.tree.script_name(req.uri or "/")
         if sn is None:
             send_response(req, '404 Not Found', [], '')
             headers = copyitems(req.headers_in)
             rfile = _ReadOnlyRequest(req)
             prev = None
-            
+
             try:
                 redirections = []
                 while True:
                     request.multiprocess = bool(forked)
                     request.app = app
                     request.prev = prev
-                    
+
                     # Run the CherryPy Request object and obtain the response
                     try:
                         request.run(method, path, qs, reqproto, headers, rfile)
                         ir = sys.exc_info()[1]
                         app.release_serving()
                         prev = request
-                        
+
                         if not recursive:
                             if ir.path in redirections:
                                 raise RuntimeError("InternalRedirector visited the "
                                 if qs:
                                     qs = "?" + qs
                                 redirections.append(sn + path + qs)
-                        
+
                         # Munge environment and try again.
                         method = "GET"
                         path = ir.path
                         qs = ir.query_string
                         rfile = BytesIO()
-                
+
                 send_response(req, response.output_status, response.header_list,
                               response.body, response.stream)
             finally:
 def send_response(req, status, headers, body, stream=False):
     # Set response status
     req.status = int(status[:3])
-    
+
     # Set response headers
     req.content_type = "text/plain"
     for header, value in headers:
             req.content_type = value
             continue
         req.headers_out.add(header, value)
-    
+
     if stream:
         # Flush now so the status and headers are sent immediately.
         req.flush()
-    
+
     # Set response body
     if isinstance(body, basestring):
         req.write(body)
 
 
 class ModPythonServer(object):
-    
+
     template = """
 # Apache2 server configuration file for running CherryPy with mod_python.
 
 %(opts)s
 </Location>
 """
-    
+
     def __init__(self, loc="/", port=80, opts=None, apache_path="apache",
                  handler="cherrypy._cpmodpy::handler"):
         self.loc = loc
         self.opts = opts
         self.apache_path = apache_path
         self.handler = handler
-    
+
     def start(self):
         opts = "".join(["    PythonOption %s %s\n" % (k, v)
                         for k, v in self.opts])
                                      "opts": opts,
                                      "handler": self.handler,
                                      }
-        
+
         mpconf = os.path.join(os.path.dirname(__file__), "cpmodpy.conf")
         f = open(mpconf, 'wb')
         try:
             f.write(conf_data)
         finally:
             f.close()
-        
+
         response = read_process(self.apache_path, "-k start -f %s" % mpconf)
         self.ready = True
         return response
-    
+
     def stop(self):
         os.popen("apache -k stop")
         self.ready = False

cherrypy/_cpnative_server.py

 
 
 class NativeGateway(wsgiserver.Gateway):
-    
+
     recursive = False
-    
+
     def respond(self):
         req = self.req
         try:
             local = httputil.Host(local[0], local[1], "")
             remote = req.conn.remote_addr, req.conn.remote_port
             remote = httputil.Host(remote[0], remote[1], "")
-            
+
             scheme = req.scheme
             sn = cherrypy.tree.script_name(req.uri or "/")
             if sn is None:
                 headers = req.inheaders.items()
                 rfile = req.rfile
                 prev = None
-                
+
                 try:
                     redirections = []
                     while True:
                         request.multiprocess = False
                         request.app = app
                         request.prev = prev
-                        
+
                         # Run the CherryPy Request object and obtain the response
                         try:
                             request.run(method, path, qs, req.request_protocol, headers, rfile)
                             ir = sys.exc_info()[1]
                             app.release_serving()
                             prev = request
-                            
+
                             if not self.recursive:
                                 if ir.path in redirections:
                                     raise RuntimeError("InternalRedirector visited the "
                                     if qs:
                                         qs = "?" + qs
                                     redirections.append(sn + path + qs)
-                            
+
                             # Munge environment and try again.
                             method = "GET"
                             path = ir.path
                             qs = ir.query_string
                             rfile = BytesIO()
-                    
+
                     self.send_response(
                         response.output_status, response.header_list,
                         response.body)
             cherrypy.log(tb, 'NATIVE_ADAPTER', severity=logging.ERROR)
             s, h, b = bare_error()
             self.send_response(s, h, b)
-    
+
     def send_response(self, status, headers, body):
         req = self.req
-        
+
         # Set response status
         req.status = str(status or "500 Server Error")
-        
+
         # Set response headers
         for header, value in headers:
             req.outheaders.append((header, value))
         if (req.ready and not req.sent_headers):
             req.sent_headers = True
             req.send_headers()
-        
+
         # Set response body
         for seg in body:
             req.write(seg)
 
 class CPHTTPServer(wsgiserver.HTTPServer):
     """Wrapper for wsgiserver.HTTPServer.
-    
+
     wsgiserver has been designed to not reference CherryPy in any way,
     so that it can be used in other frameworks and applications.
     Therefore, we wrap it here, so we can apply some attributes
     from config -> cherrypy.server -> HTTPServer.
     """
-    
+
     def __init__(self, server_adapter=cherrypy.server):
         self.server_adapter = server_adapter
-        
+
         server_name = (self.server_adapter.socket_host or
                        self.server_adapter.socket_file or
                        None)
-        
+
         wsgiserver.HTTPServer.__init__(
             self, server_adapter.bind_addr, NativeGateway,
             minthreads=server_adapter.thread_pool,
             maxthreads=server_adapter.thread_pool_max,
             server_name=server_name)
-        
+
         self.max_request_header_size = self.server_adapter.max_request_header_size or 0
         self.max_request_body_size = self.server_adapter.max_request_body_size or 0
         self.request_queue_size = self.server_adapter.socket_queue_size
         self.shutdown_timeout = self.server_adapter.shutdown_timeout
         self.protocol = self.server_adapter.protocol_version
         self.nodelay = self.server_adapter.nodelay
-        
+
         ssl_module = self.server_adapter.ssl_module or 'pyopenssl'
         if self.server_adapter.ssl_context:
             adapter_class = wsgiserver.get_ssl_adapter_class(ssl_module)

cherrypy/_cpreqbody.py

 
 You can add your own processors for any specific or major MIME type. Simply add
 it to the :attr:`processors<cherrypy._cprequest.Entity.processors>` dict in a
-hook/tool that runs at ``on_start_resource`` or ``before_request_body``. 
+hook/tool that runs at ``on_start_resource`` or ``before_request_body``.
 Here's the built-in JSON tool for an example::
 
     def json_in(force=True, debug=False):
             \"""Read application/json data into request.json.\"""
             if not entity.headers.get("Content-Length", ""):
                 raise cherrypy.HTTPError(411)
-            
+
             body = entity.fp.read()
             try:
                 request.json = json_decode(body)
                 for pair in aparam.split(ntob(';')):
                     if not pair:
                         continue
-                    
+
                     atoms = pair.split(ntob('='), 1)
                     if len(atoms) == 1:
                         atoms.append(ntob(''))
-                    
+
                     key = unquote_plus(atoms[0]).decode(charset)
                     value = unquote_plus(atoms[1]).decode(charset)
-                    
+
                     if key in params:
                         if not isinstance(params[key], list):
                             params[key] = [params[key]]
         raise cherrypy.HTTPError(
             400, "The request entity could not be decoded. The following "
             "charsets were attempted: %s" % repr(entity.attempt_charsets))
-        
+
     # Now that all values have been successfully parsed and decoded,
     # apply them to the entity.params dict.
     for key, value in params.items():
         # is often necessary to enclose the boundary parameter values in quotes
         # on the Content-type line"
         ib = entity.content_type.params['boundary'].strip('"')
-    
+
     if not re.match("^[ -~]{0,200}[!-~]$", ib):
         raise ValueError('Invalid boundary in multipart form: %r' % (ib,))
-    
+
     ib = ('--' + ib).encode('ascii')
-    
+
     # Find the first marker
     while True:
         b = entity.readline()
         if not b:
             return
-        
+
         b = b.strip()
         if b == ib:
             break
-    
+
     # Read all parts
     while True:
         part = entity.part_class.from_fp(entity.fp, ib)
 def process_multipart_form_data(entity):
     """Read all multipart/form-data parts into entity.parts or entity.params."""
     process_multipart(entity)
-    
+
     kept_parts = []
     for part in entity.parts:
         if part.name is None:
                 # It's a file upload. Retain the whole part so consumer code
                 # has access to its .file and .filename attributes.
                 value = part
-            
+
             if part.name in entity.params:
                 if not isinstance(entity.params[part.name], list):
                     entity.params[part.name] = [entity.params[part.name]]
                 entity.params[part.name].append(value)
             else:
                 entity.params[part.name] = value
-    
+
     entity.parts = kept_parts
 
 def _old_process_multipart(entity):
     """The behavior of 3.2 and lower. Deprecated and will be changed in 3.3."""
     process_multipart(entity)
-    
+
     params = entity.params
-    
+
     for part in entity.parts:
         if part.name is None:
             key = ntou('parts')
         else:
             key = part.name
-        
+
         if part.filename is None:
             # It's a regular field
             value = part.fullvalue()
             # It's a file upload. Retain the whole part so consumer code
             # has access to its .file and .filename attributes.
             value = part
-        
+
         if key in params:
             if not isinstance(params[key], list):
                 params[key] = [params[key]]
 
 class Entity(object):
     """An HTTP request body, or MIME multipart body.
-    
+
     This class collects information about the HTTP request entity. When a
     given entity is of MIME type "multipart", each part is parsed into its own
     Entity instance, and the set of parts stored in
     :attr:`entity.parts<cherrypy._cpreqbody.Entity.parts>`.
-    
+
     Between the ``before_request_body`` and ``before_handler`` tools, CherryPy
     tries to process the request body (if any) by calling
     :func:`request.body.process<cherrypy._cpreqbody.RequestBody.process`.
     processor is still not found, then the
     :func:`default_proc<cherrypy._cpreqbody.Entity.default_proc>` method of the
     Entity is called (which does nothing by default; you can override this too).
-    
+
     CherryPy includes processors for the "application/x-www-form-urlencoded"
     type, the "multipart/form-data" type, and the "multipart" major type.
     CherryPy 3.2 processes these types almost exactly as older versions.
     case it will have ``file`` and ``filename`` attributes, or possibly a
     ``value`` attribute). Each Part is itself a subclass of
     Entity, and has its own ``process`` method and ``processors`` dict.
-    
+
     There is a separate processor for the "multipart" major type which is more
     flexible, and simply stores all multipart parts in
     :attr:`request.body.parts<cherrypy._cpreqbody.Entity.parts>`. You can
     enable it with::
-    
+
         cherrypy.request.body.processors['multipart'] = _cpreqbody.process_multipart
-    
+
     in an ``on_start_resource`` tool.
     """
-    
+
     # http://tools.ietf.org/html/rfc2046#section-4.1.2:
     # "The default character set, which must be assumed in the
     # absence of a charset parameter, is US-ASCII."
     # However, many browsers send data in utf-8 with no charset.
     attempt_charsets = ['utf-8']
     """A list of strings, each of which should be a known encoding.
-    
+
     When the Content-Type of the request body warrants it, each of the given
     encodings will be tried in order. The first one to successfully decode the
     entity without raising an error is stored as
     :attr:`entity.charset<cherrypy._cpreqbody.Entity.charset>`. This defaults
-    to ``['utf-8']`` (plus 'ISO-8859-1' for "text/\*" types, as required by 
-    `HTTP/1.1 <http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7.1>`_), 
+    to ``['utf-8']`` (plus 'ISO-8859-1' for "text/\*" types, as required by
+    `HTTP/1.1 <http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7.1>`_),
     but ``['us-ascii', 'utf-8']`` for multipart parts.
     """
-    
+
     charset = None
     """The successful decoding; see "attempt_charsets" above."""
-    
+
     content_type = None
     """The value of the Content-Type request header.
-    
+
     If the Entity is part of a multipart payload, this will be the Content-Type
     given in the MIME headers for this part.
     """
-    
+
     default_content_type = 'application/x-www-form-urlencoded'
     """This defines a default ``Content-Type`` to use if no Content-Type header
     is given. The empty string is used for RequestBody, which results in the
     declares that a part with no Content-Type defaults to "text/plain"
     (see :class:`Part<cherrypy._cpreqbody.Part>`).
     """
-    
+
     filename = None
     """The ``Content-Disposition.filename`` header, if available."""
-    
+
     fp = None
     """The readable socket file object."""
-    
+
     headers = None
     """A dict of request/multipart header names and values.
-    
+
     This is a copy of the ``request.headers`` for the ``request.body``;
     for multipart parts, it is the set of headers for that part.
     """
-    
+
     length = None
     """The value of the ``Content-Length`` header, if provided."""
-    
+
     name = None
     """The "name" parameter of the ``Content-Disposition`` header, if any."""
-    
+
     params = None
     """
     If the request Content-Type is 'application/x-www-form-urlencoded' or
     can be sent with various HTTP method verbs). This value is set between
     the 'before_request_body' and 'before_handler' hooks (assuming that
     process_request_body is True)."""