Hello community,

here is the log from the commit of package python3-CherryPy for 
openSUSE:Factory checked in at 2014-12-19 09:38:45
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python3-CherryPy (Old)
 and      /work/SRC/openSUSE:Factory/.python3-CherryPy.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python3-CherryPy"

Changes:
--------
--- /work/SRC/openSUSE:Factory/python3-CherryPy/python3-CherryPy.changes        
2014-05-21 16:21:34.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.python3-CherryPy.new/python3-CherryPy.changes   
2014-12-19 09:37:40.000000000 +0100
@@ -1,0 +2,22 @@
+Tue Dec 16 05:54:57 UTC 2014 - a...@gmx.de
+
+- update to version 3.6.0:
+  * Fixed HTTP range headers for negative length larger than content size.
+  * Disabled universal wheel generation as wsgiserver has Python duality.
+  * Pull Request #42: Correct TypeError in ``check_auth`` when encrypt is used.
+  * Pull Request #59: Correct signature of HandlerWrapperTool.
+  * Pull Request #60: Fix error in SessionAuth where login_screen was
+    incorrectly used.
+    * Issue #1077: Support keyword-only arguments in dispatchers (Python 3).
+    * Issue #1019: Allow logging host name in the access log.
+    * Pull Request #50: Fixed race condition in session cleanup.
+
+- changes from version 3.5.0:
+  * Issue #1301: When the incoming queue is full, now reject additional
+    connections. This functionality was added to CherryPy 3.0, but
+      unintentionally lost in 3.1.
+
+- changes from version 3.4.0:
+  * Miscellaneous quality improvements.
+
+-------------------------------------------------------------------

Old:
----
  CherryPy-3.3.0.tar.gz

New:
----
  CherryPy-3.6.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python3-CherryPy.spec ++++++
--- /var/tmp/diff_new_pack.lGUKs9/_old  2014-12-19 09:37:41.000000000 +0100
+++ /var/tmp/diff_new_pack.lGUKs9/_new  2014-12-19 09:37:41.000000000 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           python3-CherryPy
-Version:        3.3.0
+Version:        3.6.0
 Release:        0
 Url:            http://www.cherrypy.org
 Summary:        Object-Oriented HTTP framework

++++++ CherryPy-3.3.0.tar.gz -> CherryPy-3.6.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/CherryPy.egg-info/PKG-INFO 
new/CherryPy-3.6.0/CherryPy.egg-info/PKG-INFO
--- old/CherryPy-3.3.0/CherryPy.egg-info/PKG-INFO       2014-04-16 
23:53:55.000000000 +0200
+++ new/CherryPy-3.6.0/CherryPy.egg-info/PKG-INFO       2014-09-14 
06:05:58.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: CherryPy
-Version: 3.3.0
+Version: 3.6.0
 Summary: Object-Oriented HTTP framework
 Home-page: http://www.cherrypy.org
 Author: CherryPy Team
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/CherryPy.egg-info/SOURCES.txt 
new/CherryPy-3.6.0/CherryPy.egg-info/SOURCES.txt
--- old/CherryPy-3.3.0/CherryPy.egg-info/SOURCES.txt    2014-04-16 
23:53:56.000000000 +0200
+++ new/CherryPy-3.6.0/CherryPy.egg-info/SOURCES.txt    2014-09-14 
06:06:03.000000000 +0200
@@ -87,6 +87,7 @@
 cherrypy/test/test_http.py
 cherrypy/test/test_httpauth.py
 cherrypy/test/test_httplib.py
+cherrypy/test/test_iterator.py
 cherrypy/test/test_json.py
 cherrypy/test/test_logging.py
 cherrypy/test/test_mime.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/PKG-INFO new/CherryPy-3.6.0/PKG-INFO
--- old/CherryPy-3.3.0/PKG-INFO 2014-04-16 23:53:56.000000000 +0200
+++ new/CherryPy-3.6.0/PKG-INFO 2014-09-14 06:06:03.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: CherryPy
-Version: 3.3.0
+Version: 3.6.0
 Summary: Object-Oriented HTTP framework
 Home-page: http://www.cherrypy.org
 Author: CherryPy Team
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/__init__.py 
new/CherryPy-3.6.0/cherrypy/__init__.py
--- old/CherryPy-3.3.0/cherrypy/__init__.py     2014-04-16 23:53:44.000000000 
+0200
+++ new/CherryPy-3.6.0/cherrypy/__init__.py     2014-09-14 06:05:54.000000000 
+0200
@@ -56,7 +56,7 @@
 These API's are described in the `CherryPy specification 
<https://bitbucket.org/cherrypy/cherrypy/wiki/CherryPySpec>`_.
 """
 
-__version__ = "3.3.0"
+__version__ = "3.6.0"
 
 from cherrypy._cpcompat import urljoin as _urljoin, urlencode as _urlencode
 from cherrypy._cpcompat import basestring, unicodestr, set
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/_cpdispatch.py 
new/CherryPy-3.6.0/cherrypy/_cpdispatch.py
--- old/CherryPy-3.3.0/cherrypy/_cpdispatch.py  2014-04-12 15:33:59.000000000 
+0200
+++ new/CherryPy-3.6.0/cherrypy/_cpdispatch.py  2014-09-14 05:00:33.000000000 
+0200
@@ -93,11 +93,11 @@
     show_mismatched_params = getattr(
         cherrypy.serving.request, 'show_mismatched_params', False)
     try:
-        (args, varargs, varkw, defaults) = inspect.getargspec(callable)
+        (args, varargs, varkw, defaults) = getargspec(callable)
     except TypeError:
         if isinstance(callable, object) and hasattr(callable, '__call__'):
             (args, varargs, varkw,
-             defaults) = inspect.getargspec(callable.__call__)
+             defaults) = getargspec(callable.__call__)
         else:
             # If it wasn't one of our own types, re-raise
             # the original error
@@ -205,6 +205,12 @@
     import inspect
 except ImportError:
     test_callable_spec = lambda callable, args, kwargs: None
+else:
+    getargspec = inspect.getargspec
+    # Python 3 requires using getfullargspec if keyword-only arguments are 
present
+    if hasattr(inspect, 'getfullargspec'):
+        def getargspec(callable):
+            return inspect.getfullargspec(callable)[:4]
 
 
 class LateParamPageHandler(PageHandler):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/_cplogging.py 
new/CherryPy-3.6.0/cherrypy/_cplogging.py
--- old/CherryPy-3.3.0/cherrypy/_cplogging.py   2014-04-12 15:33:59.000000000 
+0200
+++ new/CherryPy-3.6.0/cherrypy/_cplogging.py   2014-09-14 04:55:36.000000000 
+0200
@@ -56,6 +56,13 @@
 isn't--it receives messages from a variety of sources (including full error
 tracebacks, if enabled).
 
+If you are logging the access log and error log to the same source, then there
+is a possibility that a specially crafted error message may replicate an access
+log message as described in CWE-117.  In this case it is the application
+developer's responsibility to manually escape data before using CherryPy's 
log()
+functionality, or they may create an application that is vulnerable to CWE-117.
+This would be achieved by using a custom handler escape any special characters,
+and attached as described below.
 
 Custom Handlers
 ===============
@@ -249,6 +256,7 @@
                  'b': dict.get(outheaders, 'Content-Length', '') or "-",
                  'f': dict.get(inheaders, 'Referer', ''),
                  'a': dict.get(inheaders, 'User-Agent', ''),
+                 'o': dict.get(inheaders, 'Host', '-'),
                  }
         if py3k:
             for k, v in atoms.items():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/_cpserver.py 
new/CherryPy-3.6.0/cherrypy/_cpserver.py
--- old/CherryPy-3.3.0/cherrypy/_cpserver.py    2014-04-12 15:33:59.000000000 
+0200
+++ new/CherryPy-3.6.0/cherrypy/_cpserver.py    2014-09-11 02:52:02.000000000 
+0200
@@ -61,6 +61,14 @@
 
     socket_timeout = 10
     """The timeout in seconds for accepted connections (default 10)."""
+    
+    accepted_queue_size = -1
+    """The maximum number of requests which will be queued up before
+    the server refuses to accept it (default -1, meaning no limit)."""
+    
+    accepted_queue_timeout = 10
+    """The timeout in seconds for attempting to add a request to the
+    queue when the queue is full (default 10)."""
 
     shutdown_timeout = 5
     """The time to wait for HTTP worker threads to clean up."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/_cptools.py 
new/CherryPy-3.6.0/cherrypy/_cptools.py
--- old/CherryPy-3.3.0/cherrypy/_cptools.py     2014-04-12 15:33:59.000000000 
+0200
+++ new/CherryPy-3.6.0/cherrypy/_cptools.py     2014-09-11 14:59:15.000000000 
+0200
@@ -224,7 +224,7 @@
         self._name = name
         self._priority = priority
 
-    def callable(self, debug=False):
+    def callable(self, *args, **kwargs):
         innerfunc = cherrypy.serving.request.handler
 
         def wrap(*args, **kwargs):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/_cpwsgi.py 
new/CherryPy-3.6.0/cherrypy/_cpwsgi.py
--- old/CherryPy-3.3.0/cherrypy/_cpwsgi.py      2014-04-12 15:33:59.000000000 
+0200
+++ new/CherryPy-3.6.0/cherrypy/_cpwsgi.py      2014-09-11 02:52:02.000000000 
+0200
@@ -13,7 +13,7 @@
 from cherrypy._cpcompat import BytesIO, bytestr, ntob, ntou, py3k, unicodestr
 from cherrypy import _cperror
 from cherrypy.lib import httputil
-
+from cherrypy.lib import is_closable_iterator
 
 def downgrade_wsgi_ux_to_1x(environ):
     """Return a new environ dict for WSGI 1.x from the given WSGI u.x environ.
@@ -278,8 +278,20 @@
 
     def close(self):
         """Close and de-reference the current request and response. (Core)"""
+        streaming = _cherrypy.serving.response.stream
         self.cpapp.release_serving()
 
+        # We avoid the expense of examining the iterator to see if it's
+        # closable unless we are streaming the response, as that's the
+        # only situation where we are going to have an iterator which
+        # may not have been exhausted yet.
+        if streaming and is_closable_iterator(self.iter_response):
+            iter_close = self.iter_response.close
+            try:
+                iter_close()
+            except Exception:
+                _cherrypy.log(traceback=True, severity=40)
+
     def run(self):
         """Create a Request object using environ."""
         env = self.environ.get
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/_cpwsgi_server.py 
new/CherryPy-3.6.0/cherrypy/_cpwsgi_server.py
--- old/CherryPy-3.3.0/cherrypy/_cpwsgi_server.py       2014-04-12 
15:33:59.000000000 +0200
+++ new/CherryPy-3.6.0/cherrypy/_cpwsgi_server.py       2014-09-11 
02:52:02.000000000 +0200
@@ -39,6 +39,8 @@
                    request_queue_size=self.server_adapter.socket_queue_size,
                    timeout=self.server_adapter.socket_timeout,
                    shutdown_timeout=self.server_adapter.shutdown_timeout,
+                   accepted_queue_size=self.server_adapter.accepted_queue_size,
+                   
accepted_queue_timeout=self.server_adapter.accepted_queue_timeout,
                    )
         self.protocol = self.server_adapter.protocol_version
         self.nodelay = self.server_adapter.nodelay
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/lib/__init__.py 
new/CherryPy-3.6.0/cherrypy/lib/__init__.py
--- old/CherryPy-3.3.0/cherrypy/lib/__init__.py 2014-04-16 23:51:37.000000000 
+0200
+++ new/CherryPy-3.6.0/cherrypy/lib/__init__.py 2014-09-11 02:52:02.000000000 
+0200
@@ -16,6 +16,29 @@
         # Types which implement the protocol must return themselves when
         # invoking 'iter' upon them.
         return iter(obj) is obj
+        
+def is_closable_iterator(obj):
+    
+    # Not an iterator.
+    if not is_iterator(obj):
+        return False
+    
+    # A generator - the easiest thing to deal with.
+    import inspect
+    if inspect.isgenerator(obj):
+        return True
+    
+    # A custom iterator. Look for a close method...
+    if not (hasattr(obj, 'close') and callable(obj.close)):
+        return False
+    
+    #  ... which doesn't require any arguments.
+    try:
+        inspect.getcallargs(obj.close)
+    except TypeError:
+        return False
+    else:
+        return True
 
 class file_generator(object):
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/lib/cptools.py 
new/CherryPy-3.6.0/cherrypy/lib/cptools.py
--- old/CherryPy-3.3.0/cherrypy/lib/cptools.py  2014-04-16 23:51:37.000000000 
+0200
+++ new/CherryPy-3.6.0/cherrypy/lib/cptools.py  2014-09-14 04:38:02.000000000 
+0200
@@ -354,56 +354,51 @@
         username = sess.get(self.session_key)
         if not username:
             sess[self.session_key] = username = self.anonymous()
-            if self.debug:
-                cherrypy.log(
-                    'No session[username], trying anonymous', 'TOOLS.SESSAUTH')
+            self._debug_message('No session[username], trying anonymous')
         if not username:
             url = cherrypy.url(qs=request.query_string)
-            if self.debug:
-                cherrypy.log('No username, routing to login_screen with '
-                             'from_page %r' % url, 'TOOLS.SESSAUTH')
+            self._debug_message(
+                'No username, routing to login_screen with from_page %(url)r',
+                locals(),
+            )
             response.body = self.login_screen(url)
             if "Content-Length" in response.headers:
                 # Delete Content-Length header so finalize() recalcs it.
                 del response.headers["Content-Length"]
             return True
-        if self.debug:
-            cherrypy.log('Setting request.login to %r' %
-                         username, 'TOOLS.SESSAUTH')
+        self._debug_message('Setting request.login to %(username)r', locals())
         request.login = username
         self.on_check(username)
 
+    def _debug_message(self, template, context={}):
+        if not self.debug:
+            return
+        cherrypy.log(template % context, 'TOOLS.SESSAUTH')
+
     def run(self):
         request = cherrypy.serving.request
         response = cherrypy.serving.response
 
         path = request.path_info
         if path.endswith('login_screen'):
-            if self.debug:
-                cherrypy.log('routing %r to login_screen' %
-                             path, 'TOOLS.SESSAUTH')
-            return self.login_screen(**request.params)
+            self._debug_message('routing %(path)r to login_screen', locals())
+            response.body = self.login_screen()
+            return True
         elif path.endswith('do_login'):
             if request.method != 'POST':
                 response.headers['Allow'] = "POST"
-                if self.debug:
-                    cherrypy.log('do_login requires POST', 'TOOLS.SESSAUTH')
+                self._debug_message('do_login requires POST')
                 raise cherrypy.HTTPError(405)
-            if self.debug:
-                cherrypy.log('routing %r to do_login' % path, 'TOOLS.SESSAUTH')
+            self._debug_message('routing %(path)r to do_login', locals())
             return self.do_login(**request.params)
         elif path.endswith('do_logout'):
             if request.method != 'POST':
                 response.headers['Allow'] = "POST"
                 raise cherrypy.HTTPError(405)
-            if self.debug:
-                cherrypy.log('routing %r to do_logout' %
-                             path, 'TOOLS.SESSAUTH')
+            self._debug_message('routing %(path)r to do_logout', locals())
             return self.do_logout(**request.params)
         else:
-            if self.debug:
-                cherrypy.log('No special path, running do_check',
-                             'TOOLS.SESSAUTH')
+            self._debug_message('No special path, running do_check')
             return self.do_check()
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/lib/encoding.py 
new/CherryPy-3.6.0/cherrypy/lib/encoding.py
--- old/CherryPy-3.3.0/cherrypy/lib/encoding.py 2014-04-16 23:51:37.000000000 
+0200
+++ new/CherryPy-3.6.0/cherrypy/lib/encoding.py 2014-09-11 02:52:02.000000000 
+0200
@@ -4,6 +4,7 @@
 import cherrypy
 from cherrypy._cpcompat import basestring, BytesIO, ntob, set, unicodestr
 from cherrypy.lib import file_generator
+from cherrypy.lib import is_closable_iterator
 from cherrypy.lib import set_vary_header
 
 
@@ -32,23 +33,27 @@
         if not isinstance(default_encoding, list):
             default_encoding = [default_encoding]
         body.attempt_charsets = body.attempt_charsets + default_encoding
-        
+
 class UTF8StreamEncoder:
     def __init__(self, iterator):
         self._iterator = iterator
-        
+
     def __iter__(self):
         return self
-        
+
     def next(self):
         return self.__next__()
-        
+
     def __next__(self):
         res = next(self._iterator)
         if isinstance(res, unicodestr):
             res = res.encode('utf-8')
         return res
-        
+
+    def close(self):
+        if is_closable_iterator(self._iterator):
+            self._iterator.close()
+
     def __getattr__(self, attr):
         if attr.startswith('__'):
             raise AttributeError(self, attr)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/lib/httpauth.py 
new/CherryPy-3.6.0/cherrypy/lib/httpauth.py
--- old/CherryPy-3.3.0/cherrypy/lib/httpauth.py 2014-04-12 15:33:59.000000000 
+0200
+++ new/CherryPy-3.6.0/cherrypy/lib/httpauth.py 2014-09-11 03:11:00.000000000 
+0200
@@ -334,10 +334,14 @@
                         **kwargs):
     # Note that the Basic response doesn't provide the realm value so we cannot
     # test it
+    pass_through = lambda password, username=None: password
+    encrypt = encrypt or pass_through
     try:
-        return encrypt(auth_map["password"], auth_map["username"]) == password
+        candidate = encrypt(auth_map["password"], auth_map["username"])
     except TypeError:
-        return encrypt(auth_map["password"]) == password
+        # if encrypt only takes one parameter, it's the password
+        candidate = encrypt(auth_map["password"])
+    return candidate == password
 
 AUTH_RESPONSES = {
     "basic": _checkBasicResponse,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/lib/httputil.py 
new/CherryPy-3.6.0/cherrypy/lib/httputil.py
--- old/CherryPy-3.3.0/cherrypy/lib/httputil.py 2014-04-16 23:51:37.000000000 
+0200
+++ new/CherryPy-3.6.0/cherrypy/lib/httputil.py 2014-09-11 02:52:02.000000000 
+0200
@@ -103,7 +103,14 @@
                 # See rfc quote above.
                 return None
             # Negative subscript (last N bytes)
-            result.append((content_length - int(stop), content_length))
+            #
+            # RFC 2616 Section 14.35.1:
+            #   If the entity is shorter than the specified suffix-length,
+            #   the entire entity-body is used.
+            if int(stop) > content_length:
+              result.append((0, content_length))
+            else:
+              result.append((content_length - int(stop), content_length))
 
     return result
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/lib/sessions.py 
new/CherryPy-3.6.0/cherrypy/lib/sessions.py
--- old/CherryPy-3.3.0/cherrypy/lib/sessions.py 2014-04-16 23:51:37.000000000 
+0200
+++ new/CherryPy-3.6.0/cherrypy/lib/sessions.py 2014-09-14 05:50:14.000000000 
+0200
@@ -393,22 +393,26 @@
 
     def clean_up(self):
         """Clean up expired sessions."""
+
         now = self.now()
-        for id, (data, expiration_time) in copyitems(self.cache):
+        for _id, (data, expiration_time) in copyitems(self.cache):
             if expiration_time <= now:
                 try:
-                    del self.cache[id]
+                    del self.cache[_id]
                 except KeyError:
                     pass
                 try:
-                    del self.locks[id]
+                    if self.locks[_id].acquire(blocking=False):
+                        lock = self.locks.pop(_id)
+                        lock.release()
                 except KeyError:
                     pass
 
         # added to remove obsolete lock objects
-        for id in list(self.locks):
-            if id not in self.cache:
-                self.locks.pop(id, None)
+        for _id in list(self.locks):
+            if _id not in self.cache and 
self.locks[_id].acquire(blocking=False):
+                lock = self.locks.pop(_id)
+                lock.release()
 
     def _exists(self):
         return self.id in self.cache
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/lib/static.py 
new/CherryPy-3.6.0/cherrypy/lib/static.py
--- old/CherryPy-3.3.0/cherrypy/lib/static.py   2014-04-12 15:33:59.000000000 
+0200
+++ new/CherryPy-3.6.0/cherrypy/lib/static.py   2014-09-14 04:55:37.000000000 
+0200
@@ -1,24 +1,24 @@
+import os
+import re
+import stat
+import mimetypes
+
 try:
     from io import UnsupportedOperation
 except ImportError:
     UnsupportedOperation = object()
-import logging
-import mimetypes
+
+import cherrypy
+from cherrypy._cpcompat import ntob, unquote
+from cherrypy.lib import cptools, httputil, file_generator_limited
+
+
 mimetypes.init()
 mimetypes.types_map['.dwg'] = 'image/x-dwg'
 mimetypes.types_map['.ico'] = 'image/x-icon'
 mimetypes.types_map['.bz2'] = 'application/x-bzip2'
 mimetypes.types_map['.gz'] = 'application/x-gzip'
 
-import os
-import re
-import stat
-import time
-
-import cherrypy
-from cherrypy._cpcompat import ntob, unquote
-from cherrypy.lib import cptools, httputil, file_generator_limited
-
 
 def serve_file(path, content_type=None, disposition=None, name=None,
                debug=False):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/test/test_config.py 
new/CherryPy-3.6.0/cherrypy/test/test_config.py
--- old/CherryPy-3.3.0/cherrypy/test/test_config.py     2014-04-16 
23:52:08.000000000 +0200
+++ new/CherryPy-3.6.0/cherrypy/test/test_config.py     2014-09-14 
06:00:08.000000000 +0200
@@ -206,7 +206,7 @@
 
         if not compat.py3k:
             self.getPage("/repr?key=thing3")
-            self.assertBody(repr(u'test'))
+            self.assertBody(repr(unicode('test')))
 
         self.getPage("/repr?key=complex")
         self.assertBody("(3+2j)")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/test/test_conn.py 
new/CherryPy-3.6.0/cherrypy/test/test_conn.py
--- old/CherryPy-3.3.0/cherrypy/test/test_conn.py       2014-04-16 
23:52:08.000000000 +0200
+++ new/CherryPy-3.6.0/cherrypy/test/test_conn.py       2014-09-14 
06:00:08.000000000 +0200
@@ -1,5 +1,6 @@
 """Tests for TCP connection handling, including proper and timely close."""
 
+import httplib
 import socket
 import sys
 import time
@@ -8,7 +9,7 @@
 
 import cherrypy
 from cherrypy._cpcompat import HTTPConnection, HTTPSConnection, NotConnected
-from cherrypy._cpcompat import BadStatusLine, ntob, urlopen, unicodestr
+from cherrypy._cpcompat import BadStatusLine, ntob, tonative, urlopen, 
unicodestr
 from cherrypy.test import webtest
 from cherrypy import _cperror
 
@@ -133,10 +134,22 @@
         self.assertRaises(NotConnected, self.getPage, "/")
 
     def test_Streaming_no_len(self):
-        self._streaming(set_cl=False)
+        try:
+            self._streaming(set_cl=False)
+        finally:
+            try:
+                self.HTTP_CONN.close()
+            except (TypeError, AttributeError):
+                pass
 
     def test_Streaming_with_len(self):
-        self._streaming(set_cl=True)
+        try:
+            self._streaming(set_cl=True)
+        finally:
+            try:
+                self.HTTP_CONN.close()
+            except (TypeError, AttributeError):
+                pass
 
     def _streaming(self, set_cl):
         if cherrypy.server.protocol_version == "HTTP/1.1":
@@ -448,49 +461,53 @@
         # Try a page without an Expect request header first.
         # Note that httplib's response.begin automatically ignores
         # 100 Continue responses, so we must manually check for it.
-        conn.putrequest("POST", "/upload", skip_host=True)
-        conn.putheader("Host", self.HOST)
-        conn.putheader("Content-Type", "text/plain")
-        conn.putheader("Content-Length", "4")
-        conn.endheaders()
-        conn.send(ntob("d'oh"))
-        response = conn.response_class(conn.sock, method="POST")
-        version, status, reason = response._read_status()
-        self.assertNotEqual(status, 100)
-        conn.close()
+        try:
+            conn.putrequest("POST", "/upload", skip_host=True)
+            conn.putheader("Host", self.HOST)
+            conn.putheader("Content-Type", "text/plain")
+            conn.putheader("Content-Length", "4")
+            conn.endheaders()
+            conn.send(ntob("d'oh"))
+            response = conn.response_class(conn.sock, method="POST")
+            version, status, reason = response._read_status()
+            self.assertNotEqual(status, 100)
+        finally:
+            conn.close()
 
         # Now try a page with an Expect header...
-        conn.connect()
-        conn.putrequest("POST", "/upload", skip_host=True)
-        conn.putheader("Host", self.HOST)
-        conn.putheader("Content-Type", "text/plain")
-        conn.putheader("Content-Length", "17")
-        conn.putheader("Expect", "100-continue")
-        conn.endheaders()
-        response = conn.response_class(conn.sock, method="POST")
+        try:
+            conn.connect()
+            conn.putrequest("POST", "/upload", skip_host=True)
+            conn.putheader("Host", self.HOST)
+            conn.putheader("Content-Type", "text/plain")
+            conn.putheader("Content-Length", "17")
+            conn.putheader("Expect", "100-continue")
+            conn.endheaders()
+            response = conn.response_class(conn.sock, method="POST")
 
-        # ...assert and then skip the 100 response
-        version, status, reason = response._read_status()
-        self.assertEqual(status, 100)
-        while True:
-            line = response.fp.readline().strip()
-            if line:
-                self.fail(
-                    "100 Continue should not output any headers. Got %r" %
-                    line)
-            else:
-                break
+            # ...assert and then skip the 100 response
+            version, status, reason = response._read_status()
+            self.assertEqual(status, 100)
+            while True:
+                line = response.fp.readline().strip()
+                if line:
+                    self.fail(
+                        "100 Continue should not output any headers. Got %r" %
+                        line)
+                else:
+                    break
 
-        # ...send the body
-        body = ntob("I am a small file")
-        conn.send(body)
+            # ...send the body
+            body = ntob("I am a small file")
+            conn.send(body)
 
-        # ...get the final response
-        response.begin()
-        self.status, self.headers, self.body = webtest.shb(response)
-        self.assertStatus(200)
-        self.assertBody("thanks for '%s'" % body)
-        conn.close()
+            # ...get the final response
+            response.begin()
+            self.status, self.headers, self.body = webtest.shb(response)
+            self.assertStatus(200)
+            self.assertBody("thanks for '%s'" % body)
+        finally:
+            conn.close()
 
 
 class ConnectionTests(helper.CPWebCase):
@@ -717,6 +734,92 @@
         remote_data_conn.close()
 
 
+def setup_upload_server():
+
+    class Root:
+        def upload(self):
+            if not cherrypy.request.method == 'POST':
+                raise AssertionError("'POST' != request.method %r" %
+                                     cherrypy.request.method)
+            return "thanks for '%s'" % tonative(cherrypy.request.body.read())
+        upload.exposed = True
+
+    cherrypy.tree.mount(Root())
+    cherrypy.config.update({
+        'server.max_request_body_size': 1001,
+        'server.socket_timeout': 10,
+        'server.accepted_queue_size': 5,
+        'server.accepted_queue_timeout': 0.1,
+    })
+
+import errno
+socket_reset_errors = []
+# Not all of these names will be defined for every platform.
+for _ in ("ECONNRESET", "WSAECONNRESET"):
+    if _ in dir(errno):
+        socket_reset_errors.append(getattr(errno, _))
+
+class LimitedRequestQueueTests(helper.CPWebCase):
+    setup_server = staticmethod(setup_upload_server)    
+
+    def test_queue_full(self):
+        conns = []
+        overflow_conn = None
+        
+        try:
+            # Make 15 initial requests and leave them open, which should use
+            # all of wsgiserver's WorkerThreads and fill its Queue.
+            import time
+            for i in range(15):
+                conn = self.HTTP_CONN(self.HOST, self.PORT)
+                conn.putrequest("POST", "/upload", skip_host=True)
+                conn.putheader("Host", self.HOST)
+                conn.putheader("Content-Type", "text/plain")
+                conn.putheader("Content-Length", "4")
+                conn.endheaders()
+                conns.append(conn)
+            
+            # Now try a 16th conn, which should be closed by the server 
immediately.
+            overflow_conn = self.HTTP_CONN(self.HOST, self.PORT)
+            # Manually connect since httplib won't let us set a timeout
+            for res in socket.getaddrinfo(self.HOST, self.PORT, 0,
+                                          socket.SOCK_STREAM):
+                af, socktype, proto, canonname, sa = res
+                overflow_conn.sock = socket.socket(af, socktype, proto)
+                overflow_conn.sock.settimeout(5)
+                overflow_conn.sock.connect(sa)
+                break
+            
+            overflow_conn.putrequest("GET", "/", skip_host=True)
+            overflow_conn.putheader("Host", self.HOST)
+            overflow_conn.endheaders()
+            response = overflow_conn.response_class(overflow_conn.sock, 
method="GET")
+            try:
+                response.begin()
+            except socket.error as exc:
+                if exc.args[0] in socket_reset_errors:
+                    pass # Expected.
+                else:
+                    raise AssertionError("Overflow conn did not get RST. "
+                                         "Got %s instead" % repr(exc.args))
+            except httplib.BadStatusLine:
+                # This is a special case in OS X. Linux and Windows will
+                # RST correctly.
+                assert sys.platform == 'darwin'
+            else:
+                raise AssertionError("Overflow conn did not get RST ")
+        finally:
+            for conn in conns:
+                conn.send(ntob("done"))
+                response = conn.response_class(conn.sock, method="POST")
+                response.begin()
+                self.body = response.read()
+                self.assertBody("thanks for 'done'")
+                self.assertEqual(response.status, 200)
+                conn.close()
+            if overflow_conn:
+                overflow_conn.close()
+
 class BadRequestTests(helper.CPWebCase):
     setup_server = staticmethod(setup_server)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/test/test_core.py 
new/CherryPy-3.6.0/cherrypy/test/test_core.py
--- old/CherryPy-3.3.0/cherrypy/test/test_core.py       2014-04-16 
23:52:08.000000000 +0200
+++ new/CherryPy-3.6.0/cherrypy/test/test_core.py       2014-09-14 
06:00:08.000000000 +0200
@@ -496,6 +496,12 @@
         self.getPage("/ranges/get_ranges?bytes=2-4,-1")
         self.assertBody("[(2, 5), (7, 8)]")
 
+        # Test a suffix-byte-range longer than the content
+        # length. Note that in this test, the content length
+        # is 8 bytes.
+        self.getPage("/ranges/get_ranges?bytes=-100")
+        self.assertBody("[(0, 8)]")
+
         # Get a partial file.
         if cherrypy.server.protocol_version == "HTTP/1.1":
             self.getPage("/ranges/slice_file", [('Range', 'bytes=2-5')])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/test/test_iterator.py 
new/CherryPy-3.6.0/cherrypy/test/test_iterator.py
--- old/CherryPy-3.3.0/cherrypy/test/test_iterator.py   1970-01-01 
01:00:00.000000000 +0100
+++ new/CherryPy-3.6.0/cherrypy/test/test_iterator.py   2014-09-14 
06:00:08.000000000 +0200
@@ -0,0 +1,181 @@
+import cherrypy
+from cherrypy._cpcompat import unicodestr
+
+class IteratorBase(object):
+
+    created = 0
+    datachunk = u'butternut squash' * 256
+
+    @classmethod
+    def incr(cls):
+        cls.created += 1
+
+    @classmethod
+    def decr(cls):
+        cls.created -= 1
+
+class OurGenerator(IteratorBase):
+
+    def __iter__(self):
+        self.incr()
+        try:
+            for i in range(1024):
+                yield self.datachunk
+        finally:
+            self.decr()
+
+class OurIterator(IteratorBase):
+
+    started = False
+    closed_off = False
+    count = 0
+
+    def increment(self):
+        self.incr()
+
+    def decrement(self):
+        if not self.closed_off:
+            self.closed_off = True
+            self.decr()
+
+    def __iter__(self):
+        return self
+
+    def __next__(self):
+        if not self.started:
+            self.started = True
+            self.increment()
+        self.count += 1
+        if self.count > 1024:
+            raise StopIteration
+        return self.datachunk
+
+    next = __next__
+
+    def __del__(self):
+        self.decrement()
+
+class OurClosableIterator(OurIterator):
+
+    def close(self):
+        self.decrement()
+
+class OurNotClosableIterator(OurIterator):
+
+    # We can't close something which requires an additional argument.
+    def close(self, somearg):
+        self.decrement()
+
+class OurUnclosableIterator(OurIterator):
+    close = 'close' # not callable!
+
+from cherrypy.test import helper
+class IteratorTest(helper.CPWebCase):
+
+    @staticmethod
+    def setup_server():
+
+        class Root(object):
+
+            @cherrypy.expose
+            def count(self, clsname):
+                cherrypy.response.headers['Content-Type'] = 'text/plain'
+                return unicodestr(globals()[clsname].created)
+
+            @cherrypy.expose
+            def getall(self, clsname):
+                cherrypy.response.headers['Content-Type'] = 'text/plain'
+                return globals()[clsname]()
+
+            @cherrypy.expose
+            def stream(self, clsname):
+                return self.getall(clsname)
+            stream._cp_config = {'response.stream': True}
+
+        cherrypy.tree.mount(Root())
+
+    def test_iterator(self):
+        if cherrypy.server.protocol_version != "HTTP/1.1":
+            return self.skip()
+
+        self.PROTOCOL = "HTTP/1.1"
+
+        # Check the counts of all the classes, they should be zero.
+        closables = ['OurClosableIterator', 'OurGenerator']
+        unclosables = ['OurUnclosableIterator', 'OurNotClosableIterator']
+        all_classes = closables + unclosables
+
+        import random
+        random.shuffle(all_classes)
+
+        for clsname in all_classes:
+            self.getPage("/count/" + clsname)
+            self.assertStatus(200)
+            self.assertBody('0')
+
+        # We should also be able to read the entire content body
+        # successfully, though we don't need to, we just want to
+        # check the header.
+        for clsname in all_classes:
+            itr_conn = self.get_conn()
+            itr_conn.putrequest("GET", "/getall/" + clsname)
+            itr_conn.endheaders()
+            response = itr_conn.getresponse()
+            self.assertEqual(response.status, 200)
+            headers = response.getheaders()
+            for header_name, header_value in headers:
+                if header_name.lower() == 'content-length':
+                    assert header_value == unicodestr(1024 * 16 * 256), 
header_value
+                    break
+            else:
+                raise AssertionError('No Content-Length header found')
+
+            # As the response should be fully consumed by CherryPy
+            # before sending back, the count should still be at zero
+            # by the time the response has been sent.
+            self.getPage("/count/" + clsname)
+            self.assertStatus(200)
+            self.assertBody('0')
+
+        # Now we do the same check with streaming - some classes will
+        # be automatically closed, while others cannot.
+        stream_counts = {}
+        for clsname in all_classes:
+            itr_conn = self.get_conn()
+            itr_conn.putrequest("GET", "/stream/" + clsname)
+            itr_conn.endheaders()
+            response = itr_conn.getresponse()
+            self.assertEqual(response.status, 200)
+            response.fp.read(65536)
+
+            # Let's check the count - this should always be one.
+            self.getPage("/count/" + clsname)
+            self.assertBody('1')
+
+            # Now if we close the connection, the count should go back
+            # to zero.
+            itr_conn.close()
+            self.getPage("/count/" + clsname)
+
+            # If this is a response which should be easily closed, then
+            # we will test to see if the value has gone back down to
+            # zero.
+            if clsname in closables:
+
+                # Sometimes we try to get the answer too quickly - we
+                # will wait for 100 ms before asking again if we didn't
+                # get the answer we wanted.
+                if self.body != '0':
+                    import time
+                    time.sleep(0.1)
+                    self.getPage("/count/" + clsname)
+
+            stream_counts[clsname] = int(self.body)
+
+        # Check that we closed off the classes which should provide
+        # easy mechanisms for doing so.
+        for clsname in closables:
+            assert stream_counts[clsname] == 0, (
+                'did not close off stream response correctly, expected '
+                'count of zero for %s: %s' % (clsname, stream_counts)
+            )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/test/test_logging.py 
new/CherryPy-3.6.0/cherrypy/test/test_logging.py
--- old/CherryPy-3.3.0/cherrypy/test/test_logging.py    2014-04-16 
23:52:08.000000000 +0200
+++ new/CherryPy-3.6.0/cherrypy/test/test_logging.py    2014-09-14 
06:00:08.000000000 +0200
@@ -105,6 +105,26 @@
             self.assertLog(-1, '] "GET %s/as_yield HTTP/1.1" 200 - "" ""'
                            % self.prefix())
 
+    def testCustomLogFormat(self):
+        '''Test a customized access_log_format string,
+           which is a feature of _cplogging.LogManager.access() '''
+
+        original_logformat = cherrypy._cplogging.LogManager.access_log_format
+        cherrypy._cplogging.LogManager.access_log_format = \
+          '{h} {l} {u} {t} "{r}" {s} {b} "{f}" "{a}" {o}' \
+          if py3k else \
+          '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" %(o)s'
+
+        self.markLog()
+        self.getPage("/as_string", headers=[('Referer', 'REFERER'),
+                                            ('User-Agent', 'USERAGENT'),
+                                            ('Host', 'HOST')])
+        self.assertLog(-1, '%s - - [' % self.interface())
+        self.assertLog(-1, '] "GET /as_string HTTP/1.1" '
+                           '200 7 "REFERER" "USERAGENT" HOST')
+
+        cherrypy._cplogging.LogManager.access_log_format = original_logformat
+
     def testEscapedOutput(self):
         # Test unicode in access log pieces.
         self.markLog()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/test/test_objectmapping.py 
new/CherryPy-3.6.0/cherrypy/test/test_objectmapping.py
--- old/CherryPy-3.3.0/cherrypy/test/test_objectmapping.py      2014-04-16 
23:52:08.000000000 +0200
+++ new/CherryPy-3.6.0/cherrypy/test/test_objectmapping.py      2014-09-14 
06:00:08.000000000 +0200
@@ -1,3 +1,4 @@
+import sys
 import cherrypy
 from cherrypy._cpcompat import ntou
 from cherrypy._cptree import Application
@@ -414,3 +415,17 @@
         a = Application(Root(), script_name=None)
         # However, this does not apply to tree.mount
         self.assertRaises(TypeError, cherrypy.tree.mount, a, None)
+
+    def testKeywords(self):
+        if sys.version_info < (3,):
+            return self.skip("skipped (Python 3 only)")
+        exec("""class Root(object):
+    @cherrypy.expose
+    def hello(self, *, name='world'):
+        return 'Hello %s!' % name
+cherrypy.tree.mount(Application(Root(), '/keywords'))""")
+
+        self.getPage('/keywords/hello')
+        self.assertStatus(200)
+        self.getPage('/keywords/hello/extra')
+        self.assertStatus(404)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/test/test_session.py 
new/CherryPy-3.6.0/cherrypy/test/test_session.py
--- old/CherryPy-3.3.0/cherrypy/test/test_session.py    2014-04-16 
23:52:08.000000000 +0200
+++ new/CherryPy-3.6.0/cherrypy/test/test_session.py    2014-09-14 
06:00:08.000000000 +0200
@@ -1,6 +1,5 @@
 import os
 localDir = os.path.dirname(__file__)
-import sys
 import threading
 import time
 
@@ -358,10 +357,24 @@
             else:
                 self.fail("Unknown session id in cache: %r", cache)
 
+    def test_8_Ram_Cleanup(self):
+        def lock():
+            s1 = sessions.RamSession()
+            s1.acquire_lock()
+            time.sleep(1)
+            s1.release_lock()
+
+        t = threading.Thread(target=lock)
+        t.start()
+        s2 = sessions.RamSession()
+        s2.clean_up()
+        self.assertEqual(len(sessions.RamSession.locks), 1, 'Clean up should 
not remove active lock')
+        t.join()
+
 
 import socket
 try:
-    import memcache
+    import memcache  # NOQA
 
     host, port = '127.0.0.1', 11211
     for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC,
@@ -436,7 +449,7 @@
 ##                    sys.stdout.write("%d " % index)
                 if not self.body.isdigit():
                     self.fail(self.body)
-                data_dict[index] = v = int(self.body)
+                data_dict[index] = int(self.body)
 
             # Start <request_count> concurrent requests from
             # each of <client_thread_count> clients
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/test/test_static.py 
new/CherryPy-3.6.0/cherrypy/test/test_static.py
--- old/CherryPy-3.3.0/cherrypy/test/test_static.py     2014-04-16 
23:52:08.000000000 +0200
+++ new/CherryPy-3.6.0/cherrypy/test/test_static.py     2014-09-14 
06:00:08.000000000 +0200
@@ -7,7 +7,11 @@
 curdir = os.path.join(os.getcwd(), os.path.dirname(__file__))
 has_space_filepath = os.path.join(curdir, 'static', 'has space.html')
 bigfile_filepath = os.path.join(curdir, "static", "bigfile.log")
-BIGFILE_SIZE = 1024 * 1024
+
+# The file size needs to be big enough such that half the size of it
+# won't be socket-buffered (or server-buffered) all in one go. See
+# test_file_stream.
+BIGFILE_SIZE = 1024 * 1024 * 4
 
 import cherrypy
 from cherrypy.lib import static
@@ -19,7 +23,8 @@
     def setup_server():
         if not os.path.exists(has_space_filepath):
             open(has_space_filepath, 'wb').write(ntob('Hello, world\r\n'))
-        if not os.path.exists(bigfile_filepath):
+        if not os.path.exists(bigfile_filepath) or \
+            os.path.getsize(bigfile_filepath) != BIGFILE_SIZE:
             open(bigfile_filepath, 'wb').write(ntob("x" * BIGFILE_SIZE))
 
         class Root:
@@ -256,23 +261,38 @@
             else:
                 tell_position = int(b)
 
-            expected = len(body)
+            read_so_far = len(body)
+
+            # It is difficult for us to force the server to only read
+            # the bytes that we ask for - there are going to be buffers
+            # inbetween.
+            #
+            # CherryPy will attempt to write as much data as it can to
+            # the socket, and we don't have a way to determine what that
+            # size will be. So we make the following assumption - by
+            # the time we have read in the entire file on the server,
+            # we will have at least received half of it. If this is not
+            # the case, then this is an indicator that either:
+            #   - machines that are running this test are using buffer
+            #     sizes greater than half of BIGFILE_SIZE; or
+            #   - streaming is broken.
+            #
+            # At the time of writing, we seem to have encountered
+            # buffer sizes bigger than 512K, so we've increased
+            # BIGFILE_SIZE to 4MB.
             if tell_position >= BIGFILE_SIZE:
-                # We can't exactly control how much content the server asks
-                # for.
-                # Fudge it by only checking the first half of the reads.
-                if expected < (BIGFILE_SIZE / 2):
+                if read_so_far < (BIGFILE_SIZE / 2):
                     self.fail(
                         "The file should have advanced to position %r, but "
                         "has already advanced to the end of the file. It "
                         "may not be streamed as intended, or at the wrong "
-                        "chunk size (64k)" % expected)
-            elif tell_position < expected:
+                        "chunk size (64k)" % read_so_far)
+            elif tell_position < read_so_far:
                 self.fail(
                     "The file should have advanced to position %r, but has "
                     "only advanced to position %r. It may not be streamed "
-                    "as intended, or at the wrong chunk size (65536)" %
-                    (expected, tell_position))
+                    "as intended, or at the wrong chunk size (64k)" %
+                    (read_so_far, tell_position))
 
         if body != ntob("x" * BIGFILE_SIZE):
             self.fail("Body != 'x' * %d. Got %r instead (%d bytes)." %
@@ -307,7 +327,7 @@
         if self.body != ntob("x" * BIGFILE_SIZE):
             self.fail("Body != 'x' * %d. Got %r instead (%d bytes)." %
                       (BIGFILE_SIZE, self.body[:50], len(body)))
-                      
+
     def test_error_page_with_serve_file(self):
         self.getPage("/404test/yunyeen")
         self.assertStatus(404)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/test/test_tools.py 
new/CherryPy-3.6.0/cherrypy/test/test_tools.py
--- old/CherryPy-3.3.0/cherrypy/test/test_tools.py      2014-04-16 
23:52:08.000000000 +0200
+++ new/CherryPy-3.6.0/cherrypy/test/test_tools.py      2014-09-14 
06:00:08.000000000 +0200
@@ -108,6 +108,7 @@
         cherrypy.tools.rotator = cherrypy.Tool('before_finalize', Rotator())
 
         def stream_handler(next_handler, *args, **kwargs):
+            assert cherrypy.request.config.get('tools.streamer.arg') == 'arg 
value'
             cherrypy.response.output = o = BytesIO()
             try:
                 response = next_handler(*args, **kwargs)
@@ -126,10 +127,11 @@
             index.exposed = True
 
             def tarfile(self):
+                assert cherrypy.request.config.get('tools.streamer.arg') == 
'arg value'
                 cherrypy.response.output.write(ntob('I am '))
                 cherrypy.response.output.write(ntob('a tarfile'))
             tarfile.exposed = True
-            tarfile._cp_config = {'tools.streamer.on': True}
+            tarfile._cp_config = {'tools.streamer.on': True, 
'tools.streamer.arg': 'arg value'}
 
             def euro(self):
                 hooks = list(cherrypy.request.hooks['before_finalize'])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/wsgiserver/wsgiserver2.py 
new/CherryPy-3.6.0/cherrypy/wsgiserver/wsgiserver2.py
--- old/CherryPy-3.3.0/cherrypy/wsgiserver/wsgiserver2.py       2014-04-16 
23:53:44.000000000 +0200
+++ new/CherryPy-3.6.0/cherrypy/wsgiserver/wsgiserver2.py       2014-09-14 
06:05:54.000000000 +0200
@@ -1545,12 +1545,14 @@
     and stop(timeout) attributes.
     """
 
-    def __init__(self, server, min=10, max=-1):
+    def __init__(self, server, min=10, max=-1,
+        accepted_queue_size=-1, accepted_queue_timeout=10):
         self.server = server
         self.min = min
         self.max = max
         self._threads = []
-        self._queue = queue.Queue()
+        self._queue = queue.Queue(maxsize=accepted_queue_size)
+        self._queue_put_timeout = accepted_queue_timeout
         self.get = self._queue.get
 
     def start(self):
@@ -1570,7 +1572,7 @@
     idle = property(_get_idle, doc=_get_idle.__doc__)
 
     def put(self, obj):
-        self._queue.put(obj)
+        self._queue.put(obj, block=True, timeout=self._queue_put_timeout)
         if obj is _SHUTDOWNREQUEST:
             return
 
@@ -1755,7 +1757,7 @@
     timeout = 10
     """The timeout in seconds for accepted connections (default 10)."""
 
-    version = "CherryPy/3.3.0"
+    version = "CherryPy/3.6.0"
     """A version string for the HTTPServer."""
 
     software = None
@@ -2072,7 +2074,12 @@
 
             conn.ssl_env = ssl_env
 
-            self.requests.put(conn)
+            try:
+                self.requests.put(conn)
+            except queue.Full:
+                # Just drop the conn. TODO: write 503 back?
+                conn.close()
+                return
         except socket.timeout:
             # The only reason for the timeout in start() is so we can
             # notice keyboard interrupts on Win32, which don't interrupt
@@ -2215,8 +2222,11 @@
     """The version of WSGI to produce."""
 
     def __init__(self, bind_addr, wsgi_app, numthreads=10, server_name=None,
-                 max=-1, request_queue_size=5, timeout=10, shutdown_timeout=5):
-        self.requests = ThreadPool(self, min=numthreads or 1, max=max)
+                 max=-1, request_queue_size=5, timeout=10, shutdown_timeout=5,
+                 accepted_queue_size=-1, accepted_queue_timeout=10):
+        self.requests = ThreadPool(self, min=numthreads or 1, max=max,
+            accepted_queue_size=accepted_queue_size,
+            accepted_queue_timeout=accepted_queue_timeout)
         self.wsgi_app = wsgi_app
         self.gateway = wsgi_gateways[self.wsgi_version]
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/cherrypy/wsgiserver/wsgiserver3.py 
new/CherryPy-3.6.0/cherrypy/wsgiserver/wsgiserver3.py
--- old/CherryPy-3.3.0/cherrypy/wsgiserver/wsgiserver3.py       2014-04-16 
23:53:44.000000000 +0200
+++ new/CherryPy-3.6.0/cherrypy/wsgiserver/wsgiserver3.py       2014-09-14 
06:05:54.000000000 +0200
@@ -1261,12 +1261,14 @@
     and stop(timeout) attributes.
     """
 
-    def __init__(self, server, min=10, max=-1):
+    def __init__(self, server, min=10, max=-1,
+        accepted_queue_size=-1, accepted_queue_timeout=10):
         self.server = server
         self.min = min
         self.max = max
         self._threads = []
-        self._queue = queue.Queue()
+        self._queue = queue.Queue(maxsize=accepted_queue_size)
+        self._queue_put_timeout = accepted_queue_timeout
         self.get = self._queue.get
 
     def start(self):
@@ -1286,7 +1288,7 @@
     idle = property(_get_idle, doc=_get_idle.__doc__)
 
     def put(self, obj):
-        self._queue.put(obj)
+        self._queue.put(obj, block=True, timeout=self._queue_put_timeout)
         if obj is _SHUTDOWNREQUEST:
             return
 
@@ -1466,7 +1468,7 @@
     timeout = 10
     """The timeout in seconds for accepted connections (default 10)."""
 
-    version = "CherryPy/3.3.0"
+    version = "CherryPy/3.6.0"
     """A version string for the HTTPServer."""
 
     software = None
@@ -1764,7 +1766,12 @@
 
             conn.ssl_env = ssl_env
 
-            self.requests.put(conn)
+            try:
+                self.requests.put(conn)
+            except queue.Full:
+                # Just drop the conn. TODO: write 503 back?
+                conn.close()
+                return
         except socket.timeout:
             # The only reason for the timeout in start() is so we can
             # notice keyboard interrupts on Win32, which don't interrupt
@@ -1906,8 +1913,11 @@
     """The version of WSGI to produce."""
 
     def __init__(self, bind_addr, wsgi_app, numthreads=10, server_name=None,
-                 max=-1, request_queue_size=5, timeout=10, shutdown_timeout=5):
-        self.requests = ThreadPool(self, min=numthreads or 1, max=max)
+                 max=-1, request_queue_size=5, timeout=10, shutdown_timeout=5,
+                 accepted_queue_size=-1, accepted_queue_timeout=10):
+        self.requests = ThreadPool(self, min=numthreads or 1, max=max,
+            accepted_queue_size=accepted_queue_size,
+            accepted_queue_timeout=accepted_queue_timeout)
         self.wsgi_app = wsgi_app
         self.gateway = wsgi_gateways[self.wsgi_version]
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/setup.cfg new/CherryPy-3.6.0/setup.cfg
--- old/CherryPy-3.3.0/setup.cfg        2014-04-16 23:53:56.000000000 +0200
+++ new/CherryPy-3.6.0/setup.cfg        2014-09-14 06:06:03.000000000 +0200
@@ -7,11 +7,8 @@
 verbosity = 2
 nocapture = True
 
-[wheel]
-universal = 1
-
 [egg_info]
-tag_build = 
 tag_svn_revision = 0
 tag_date = 0
+tag_build = 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-3.3.0/setup.py new/CherryPy-3.6.0/setup.py
--- old/CherryPy-3.3.0/setup.py 2014-04-16 23:53:44.000000000 +0200
+++ new/CherryPy-3.6.0/setup.py 2014-09-14 06:05:54.000000000 +0200
@@ -36,7 +36,7 @@
 # arguments for the setup command
 ###############################################################################
 name = "CherryPy"
-version = "3.3.0"
+version = "3.6.0"
 desc = "Object-Oriented HTTP framework"
 long_desc = "CherryPy is a pythonic, object-oriented HTTP framework"
 classifiers = [
@@ -126,6 +126,21 @@
 if 'bdist_wininst' in sys.argv or '--format=wininst' in sys.argv:
     data_files = [(r'\PURELIB\%s' % path, files) for path, files in data_files]
 
+setup_params = dict(
+    name=name,
+    version=version,
+    description=desc,
+    long_description=long_desc,
+    classifiers=classifiers,
+    author=author,
+    author_email=author_email,
+    url=url,
+    license=cp_license,
+    packages=packages,
+    data_files=data_files,
+    scripts=scripts,
+    cmdclass=cmd_class,
+)
 
 def main():
     if sys.version < required_python_version:
@@ -137,21 +152,7 @@
     for scheme in list(INSTALL_SCHEMES.values()):
         scheme['data'] = scheme['purelib']
 
-    setup(
-        name=name,
-        version=version,
-        description=desc,
-        long_description=long_desc,
-        classifiers=classifiers,
-        author=author,
-        author_email=author_email,
-        url=url,
-        license=cp_license,
-        packages=packages,
-        data_files=data_files,
-        scripts=scripts,
-        cmdclass=cmd_class,
-    )
+    setup(**setup_params)
 
 
 if __name__ == "__main__":

-- 
To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org
For additional commands, e-mail: opensuse-commit+h...@opensuse.org

Reply via email to