Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-waitress for openSUSE:Factory 
checked in at 2022-06-01 17:34:10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-waitress (Old)
 and      /work/SRC/openSUSE:Factory/.python-waitress.new.1548 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-waitress"

Wed Jun  1 17:34:10 2022 rev:25 rq:980052 version:2.1.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-waitress/python-waitress.changes  
2022-03-20 20:55:16.258502495 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-waitress.new.1548/python-waitress.changes    
    2022-06-01 17:34:23.866722068 +0200
@@ -1,0 +2,26 @@
+Tue May 31 03:16:03 UTC 2022 - Arun Persaud <a...@gmx.de>
+
+- specfile:
+  * be more specific in %files section
+
+- update to version 2.1.2:
+  * Bugfix
+    + When expose_tracebacks is enabled waitress would fail to
+      properly encode unicode thereby causing another error during
+      error handling. See https://github.com/Pylons/waitress/pull/378
+    + Header length checking had a calculation that was done
+      incorrectly when the data was received across multple socket
+      reads. This calculation has been corrected, and no longer will
+      Waitress send back a 413 Request Entity Too Large. See
+      https://github.com/Pylons/waitress/pull/376
+  * Security Bugfix
+    + in 2.1.0 a new feature was introduced that allowed the WSGI
+      thread to start sending data to the socket. However this
+      introduced a race condition whereby a socket may be closed in
+      the sending thread while the main thread is about to call
+      select() therey causing the entire application to be taken down.
+      Waitress will no longer close the socket in the WSGI thread,
+      instead waking up the main thread to cleanup. See
+      https://github.com/Pylons/waitress/pull/377
+
+-------------------------------------------------------------------

Old:
----
  waitress-2.1.1.tar.gz

New:
----
  waitress-2.1.2.tar.gz

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

Other differences:
------------------
++++++ python-waitress.spec ++++++
--- /var/tmp/diff_new_pack.VfCHgI/_old  2022-06-01 17:34:24.530722852 +0200
+++ /var/tmp/diff_new_pack.VfCHgI/_new  2022-06-01 17:34:24.534722857 +0200
@@ -16,24 +16,21 @@
 #
 
 
-%if 0%{?suse_version} > 1500
-%bcond_without libalternatives
-%else
-%bcond_with libalternatives
-%endif
-
 %global flavor @BUILD_FLAVOR@%{nil}
-
 %if "%{flavor}" == "doc"
 %define psuffix -doc
 %endif
 %if "%{flavor}" == ""
 %define psuffix %{nil}
 %endif
-
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
+%if 0%{?suse_version} > 1500
+%bcond_without libalternatives
+%else
+%bcond_with libalternatives
+%endif
 Name:           python-waitress%{psuffix}
-Version:        2.1.1
+Version:        2.1.2
 Release:        0
 Summary:        Waitress WSGI server
 License:        ZPL-2.1
@@ -46,13 +43,14 @@
 Source2:        fetch-intersphinx-inventories.sh
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros >= 20210929
+BuildArch:      noarch
 %if "%{flavor}" == ""
 BuildRequires:  %{python_module pytest-cov}
 BuildRequires:  %{python_module pytest}
 BuildRequires:  %{python_module setuptools}
 %if %{with libalternatives}
-Requires:       alts
 BuildRequires:  alts
+Requires:       alts
 %else
 Requires(post): update-alternatives
 Requires(postun):update-alternatives
@@ -65,7 +63,6 @@
 BuildRequires:  python3-waitress = %{version}
 Recommends:     python3-waitress = %{version}
 %endif
-BuildArch:      noarch
 %python_subpackages
 
 %if "%{flavor}" == ""
@@ -106,7 +103,9 @@
 %license LICENSE.txt
 %doc COPYRIGHT.txt README.rst
 %python_alternative %{_bindir}/waitress-serve
-%{python_sitelib}/*
+%dir %{python_sitelib}/waitress
+%{python_sitelib}/waitress/*
+%{python_sitelib}/waitress-%{version}-py*.egg-info
 
 %else
 


++++++ waitress-2.1.1.tar.gz -> waitress-2.1.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/CHANGES.txt 
new/waitress-2.1.2/CHANGES.txt
--- old/waitress-2.1.1/CHANGES.txt      2022-03-16 22:26:39.000000000 +0100
+++ new/waitress-2.1.2/CHANGES.txt      2022-05-30 23:30:56.000000000 +0200
@@ -1,3 +1,28 @@
+2.1.2
+-----
+
+Bugfix
+~~~~~~
+
+- When expose_tracebacks is enabled waitress would fail to properly encode
+  unicode thereby causing another error during error handling. See
+  https://github.com/Pylons/waitress/pull/378
+
+- Header length checking had a calculation that was done incorrectly when the
+  data was received across multple socket reads. This calculation has been
+  corrected, and no longer will Waitress send back a 413 Request Entity Too
+  Large. See https://github.com/Pylons/waitress/pull/376
+
+Security Bugfix
+~~~~~~~~~~~~~~~
+
+- in 2.1.0 a new feature was introduced that allowed the WSGI thread to start
+  sending data to the socket. However this introduced a race condition whereby
+  a socket may be closed in the sending thread while the main thread is about
+  to call select() therey causing the entire application to be taken down.
+  Waitress will no longer close the socket in the WSGI thread, instead waking
+  up the main thread to cleanup. See 
https://github.com/Pylons/waitress/pull/377
+
 2.1.1
 -----
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/PKG-INFO new/waitress-2.1.2/PKG-INFO
--- old/waitress-2.1.1/PKG-INFO 2022-03-16 22:34:36.896260300 +0100
+++ new/waitress-2.1.2/PKG-INFO 2022-05-30 23:38:47.581633300 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: waitress
-Version: 2.1.1
+Version: 2.1.2
 Summary: Waitress WSGI server
 Home-page: https://github.com/Pylons/waitress
 Author: Zope Foundation and Contributors
@@ -12,7 +12,6 @@
 Project-URL: Changelog, 
https://docs.pylonsproject.org/projects/waitress/en/latest/index.html#change-history
 Project-URL: Issue Tracker, https://github.com/Pylons/waitress/issues
 Keywords: waitress wsgi server http
-Platform: UNKNOWN
 Classifier: Development Status :: 6 - Mature
 Classifier: Environment :: Web Environment
 Classifier: Intended Audience :: Developers
@@ -61,6 +60,31 @@
 For more information, see the "docs" directory of the Waitress package or visit
 https://docs.pylonsproject.org/projects/waitress/en/latest/
 
+2.1.2
+-----
+
+Bugfix
+~~~~~~
+
+- When expose_tracebacks is enabled waitress would fail to properly encode
+  unicode thereby causing another error during error handling. See
+  https://github.com/Pylons/waitress/pull/378
+
+- Header length checking had a calculation that was done incorrectly when the
+  data was received across multple socket reads. This calculation has been
+  corrected, and no longer will Waitress send back a 413 Request Entity Too
+  Large. See https://github.com/Pylons/waitress/pull/376
+
+Security Bugfix
+~~~~~~~~~~~~~~~
+
+- in 2.1.0 a new feature was introduced that allowed the WSGI thread to start
+  sending data to the socket. However this introduced a race condition whereby
+  a socket may be closed in the sending thread while the main thread is about
+  to call select() therey causing the entire application to be taken down.
+  Waitress will no longer close the socket in the WSGI thread, instead waking
+  up the main thread to cleanup. See 
https://github.com/Pylons/waitress/pull/377
+
 2.1.1
 -----
 
@@ -138,5 +162,3 @@
   REQUEST_URI is similar to ``request_uri`` in nginx. It is a string that
   contains the request path before separating the query string and
   decoding ``%``-escaped characters. 
-
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/setup.cfg new/waitress-2.1.2/setup.cfg
--- old/waitress-2.1.1/setup.cfg        2022-03-16 22:34:36.896597900 +0100
+++ new/waitress-2.1.2/setup.cfg        2022-05-30 23:38:47.582001200 +0200
@@ -1,6 +1,6 @@
 [metadata]
 name = waitress
-version = 2.1.1
+version = 2.1.2
 description = Waitress WSGI server
 long_description = file: README.rst, CHANGES.txt
 long_description_content_type = text/x-rst
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/src/waitress/adjustments.py 
new/waitress-2.1.2/src/waitress/adjustments.py
--- old/waitress-2.1.1/src/waitress/adjustments.py      2022-01-14 
03:57:32.000000000 +0100
+++ new/waitress-2.1.2/src/waitress/adjustments.py      2022-05-30 
23:30:25.000000000 +0200
@@ -147,7 +147,7 @@
     # TCP port to listen on
     port = _int_marker(8080)
 
-    listen = ["{}:{}".format(host, port)]
+    listen = [f"{host}:{port}"]
 
     # number of threads available for tasks
     threads = 4
@@ -327,7 +327,7 @@
         if not isinstance(self.host, _str_marker) or not isinstance(
             self.port, _int_marker
         ):
-            self.listen = ["{}:{}".format(self.host, self.port)]
+            self.listen = [f"{self.host}:{self.port}"]
 
         enabled_families = socket.AF_UNSPEC
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/src/waitress/channel.py 
new/waitress-2.1.2/src/waitress/channel.py
--- old/waitress-2.1.1/src/waitress/channel.py  2022-02-06 19:28:31.000000000 
+0100
+++ new/waitress-2.1.2/src/waitress/channel.py  2022-05-30 21:03:51.000000000 
+0200
@@ -126,10 +126,10 @@
         if self.will_close:
             self.handle_close()
 
-    def _flush_exception(self, flush):
+    def _flush_exception(self, flush, do_close=True):
         if flush:
             try:
-                return (flush(), False)
+                return (flush(do_close=do_close), False)
             except OSError:
                 if self.adj.log_socket_errors:
                     self.logger.exception("Socket error")
@@ -240,20 +240,20 @@
 
         return True
 
-    def _flush_some_if_lockable(self):
+    def _flush_some_if_lockable(self, do_close=True):
         # Since our task may be appending to the outbuf, we try to acquire
         # the lock, but we don't block if we can't.
 
         if self.outbuf_lock.acquire(False):
             try:
-                self._flush_some()
+                self._flush_some(do_close=do_close)
 
                 if self.total_outbufs_len < self.adj.outbuf_high_watermark:
                     self.outbuf_lock.notify()
             finally:
                 self.outbuf_lock.release()
 
-    def _flush_some(self):
+    def _flush_some(self, do_close=True):
         # Send as much data as possible to our client
 
         sent = 0
@@ -267,7 +267,7 @@
 
             while outbuflen > 0:
                 chunk = outbuf.get(self.sendbuf_len)
-                num_sent = self.send(chunk)
+                num_sent = self.send(chunk, do_close=do_close)
 
                 if num_sent:
                     outbuf.skip(num_sent, True)
@@ -374,7 +374,9 @@
                 self.total_outbufs_len += num_bytes
 
                 if self.total_outbufs_len >= self.adj.send_bytes:
-                    (flushed, exception) = 
self._flush_exception(self._flush_some)
+                    (flushed, exception) = self._flush_exception(
+                        self._flush_some, do_close=False
+                    )
 
                     if (
                         exception
@@ -392,7 +394,7 @@
 
         if self.total_outbufs_len > self.adj.outbuf_high_watermark:
             with self.outbuf_lock:
-                (_, exception) = self._flush_exception(self._flush_some)
+                (_, exception) = self._flush_exception(self._flush_some, 
do_close=False)
 
                 if exception:
                     # An exception happened while flushing, wake up the main
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/src/waitress/parser.py 
new/waitress-2.1.2/src/waitress/parser.py
--- old/waitress-2.1.1/src/waitress/parser.py   2022-03-16 22:26:39.000000000 
+0100
+++ new/waitress-2.1.2/src/waitress/parser.py   2022-05-25 04:06:09.000000000 
+0200
@@ -103,7 +103,7 @@
                 # If the headers have ended, and we also have part of the body
                 # message in data we still want to validate we aren't going
                 # over our limit for received headers.
-                self.header_bytes_received += index
+                self.header_bytes_received = index
                 consumed = datalen - (len(s) - index)
             else:
                 self.header_bytes_received += datalen
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/src/waitress/proxy_headers.py 
new/waitress-2.1.2/src/waitress/proxy_headers.py
--- old/waitress-2.1.1/src/waitress/proxy_headers.py    2022-01-14 
03:57:32.000000000 +0100
+++ new/waitress-2.1.2/src/waitress/proxy_headers.py    2022-05-30 
21:03:51.000000000 +0200
@@ -52,7 +52,7 @@
                     ex.reason,
                     ex.value,
                 )
-                error = BadRequest('Header "{}" malformed.'.format(ex.header))
+                error = BadRequest(f'Header "{ex.header}" malformed.')
                 return error.wsgi_response(environ, start_response)
 
         # Clear out the untrusted proxy headers
@@ -95,7 +95,7 @@
                 if "." not in forward_hop and (
                     ":" in forward_hop and forward_hop[-1] != "]"
                 ):
-                    forwarded_for.append("[{}]".format(forward_hop))
+                    forwarded_for.append(f"[{forward_hop}]")
                 else:
                     forwarded_for.append(forward_hop)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/src/waitress/runner.py 
new/waitress-2.1.2/src/waitress/runner.py
--- old/waitress-2.1.1/src/waitress/runner.py   2022-01-14 03:57:32.000000000 
+0100
+++ new/waitress-2.1.2/src/waitress/runner.py   2022-05-30 21:03:51.000000000 
+0200
@@ -198,7 +198,7 @@
 def match(obj_name):
     matches = RUNNER_PATTERN.match(obj_name)
     if not matches:
-        raise ValueError("Malformed application '{}'".format(obj_name))
+        raise ValueError(f"Malformed application '{obj_name}'")
     return matches.group("module"), matches.group("object")
 
 
@@ -223,7 +223,7 @@
 
 def show_help(stream, name, error=None):  # pragma: no cover
     if error is not None:
-        print("Error: {}\n".format(error), file=stream)
+        print(f"Error: {error}\n", file=stream)
     print(HELP.format(name), file=stream)
 
 
@@ -239,7 +239,7 @@
     if args:
         print("It had these arguments: ", file=stream)
         for idx, arg in enumerate(args, start=1):
-            print("{}. {}\n".format(idx, arg), file=stream)
+            print(f"{idx}. {arg}\n", file=stream)
     else:
         print("It had no arguments.", file=stream)
 
@@ -282,11 +282,11 @@
     try:
         app = resolve(module, obj_name)
     except ImportError:
-        show_help(sys.stderr, name, "Bad module '{}'".format(module))
+        show_help(sys.stderr, name, f"Bad module '{module}'")
         show_exception(sys.stderr)
         return 1
     except AttributeError:
-        show_help(sys.stderr, name, "Bad object name '{}'".format(obj_name))
+        show_help(sys.stderr, name, f"Bad object name '{obj_name}'")
         show_exception(sys.stderr)
         return 1
     if kw["call"]:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/src/waitress/server.py 
new/waitress-2.1.2/src/waitress/server.py
--- old/waitress-2.1.1/src/waitress/server.py   2022-01-14 03:57:32.000000000 
+0100
+++ new/waitress-2.1.2/src/waitress/server.py   2022-05-30 21:03:51.000000000 
+0200
@@ -157,7 +157,7 @@
             l = list(l)
 
             if ":" in l[0]:
-                l[0] = "[{}]".format(l[0])
+                l[0] = f"[{l[0]}]"
 
             self.log_info(format_str.format(*l))
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/src/waitress/task.py 
new/waitress-2.1.2/src/waitress/task.py
--- old/waitress-2.1.1/src/waitress/task.py     2022-01-14 03:57:32.000000000 
+0100
+++ new/waitress-2.1.2/src/waitress/task.py     2022-05-30 21:03:51.000000000 
+0200
@@ -57,7 +57,7 @@
 
     def start_new_thread(self, target, thread_no):
         t = threading.Thread(
-            target=target, name="waitress-{}".format(thread_no), 
args=(thread_no,)
+            target=target, name=f"waitress-{thread_no}", args=(thread_no,)
         )
         t.daemon = True
         t.start()
@@ -266,7 +266,7 @@
 
         self.response_headers = response_headers
 
-        first_line = "HTTP/%s %s" % (self.version, self.status)
+        first_line = f"HTTP/{self.version} {self.status}"
         # NB: sorting headers needs to preserve same-named-header order
         # as per RFC 2616 section 4.2; thus the key=lambda x: x[0] here;
         # rely on stable sort to keep relative position of same-named headers
@@ -355,7 +355,7 @@
         self.response_headers.append(("Connection", "close"))
         self.close_on_finish = True
         self.content_length = len(body)
-        self.write(body.encode("latin-1"))
+        self.write(body)
 
 
 class WSGITask(Task):
@@ -400,11 +400,11 @@
             for k, v in headers:
                 if not k.__class__ is str:
                     raise AssertionError(
-                        "Header name %r is not a string in %r" % (k, (k, v))
+                        f"Header name {k!r} is not a string in {(k, v)!r}"
                     )
                 if not v.__class__ is str:
                     raise AssertionError(
-                        "Header value %r is not a string in %r" % (v, (k, v))
+                        f"Header value {v!r} is not a string in {(k, v)!r}"
                     )
 
                 if "\n" in v or "\r" in v:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/src/waitress/trigger.py 
new/waitress-2.1.2/src/waitress/trigger.py
--- old/waitress-2.1.1/src/waitress/trigger.py  2022-02-06 19:28:31.000000000 
+0100
+++ new/waitress-2.1.2/src/waitress/trigger.py  2022-05-30 21:03:51.000000000 
+0200
@@ -106,9 +106,7 @@
                     thunk()
                 except:
                     nil, t, v, tbinfo = wasyncore.compact_traceback()
-                    self.log_info(
-                        "exception in trigger thunk: (%s:%s %s)" % (t, v, 
tbinfo)
-                    )
+                    self.log_info(f"exception in trigger thunk: ({t}:{v} 
{tbinfo})")
             self.thunks = []
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/src/waitress/utilities.py 
new/waitress-2.1.2/src/waitress/utilities.py
--- old/waitress-2.1.1/src/waitress/utilities.py        2022-03-16 
22:26:39.000000000 +0100
+++ new/waitress-2.1.2/src/waitress/utilities.py        2022-05-30 
21:03:51.000000000 +0200
@@ -259,11 +259,11 @@
         self.body = body
 
     def to_response(self):
-        status = "%s %s" % (self.code, self.reason)
-        body = "%s\r\n\r\n%s" % (self.reason, self.body)
+        status = f"{self.code} {self.reason}"
+        body = f"{self.reason}\r\n\r\n{self.body}"
         tag = "\r\n\r\n(generated by waitress)"
-        body = body + tag
-        headers = [("Content-Type", "text/plain")]
+        body = (body + tag).encode("utf-8")
+        headers = [("Content-Type", "text/plain; charset=utf-8")]
 
         return status, headers, body
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/src/waitress/wasyncore.py 
new/waitress-2.1.2/src/waitress/wasyncore.py
--- old/waitress-2.1.1/src/waitress/wasyncore.py        2022-01-14 
03:57:32.000000000 +0100
+++ new/waitress-2.1.2/src/waitress/wasyncore.py        2022-05-30 
21:03:51.000000000 +0200
@@ -328,7 +328,7 @@
                 status.append("%s:%d" % self.addr)
             except TypeError:  # pragma: no cover
                 status.append(repr(self.addr))
-        return "<%s at %#x>" % (" ".join(status), id(self))
+        return "<{} at {:#x}>".format(" ".join(status), id(self))
 
     __str__ = __repr__
 
@@ -426,7 +426,7 @@
         else:
             return conn, addr
 
-    def send(self, data):
+    def send(self, data, do_close=True):
         try:
             result = self.socket.send(data)
             return result
@@ -434,7 +434,8 @@
             if why.args[0] == EWOULDBLOCK:
                 return 0
             elif why.args[0] in _DISCONNECTED:
-                self.handle_close()
+                if do_close:
+                    self.handle_close()
                 return 0
             else:
                 raise
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/src/waitress.egg-info/PKG-INFO 
new/waitress-2.1.2/src/waitress.egg-info/PKG-INFO
--- old/waitress-2.1.1/src/waitress.egg-info/PKG-INFO   2022-03-16 
22:34:36.000000000 +0100
+++ new/waitress-2.1.2/src/waitress.egg-info/PKG-INFO   2022-05-30 
23:38:47.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: waitress
-Version: 2.1.1
+Version: 2.1.2
 Summary: Waitress WSGI server
 Home-page: https://github.com/Pylons/waitress
 Author: Zope Foundation and Contributors
@@ -12,7 +12,6 @@
 Project-URL: Changelog, 
https://docs.pylonsproject.org/projects/waitress/en/latest/index.html#change-history
 Project-URL: Issue Tracker, https://github.com/Pylons/waitress/issues
 Keywords: waitress wsgi server http
-Platform: UNKNOWN
 Classifier: Development Status :: 6 - Mature
 Classifier: Environment :: Web Environment
 Classifier: Intended Audience :: Developers
@@ -61,6 +60,31 @@
 For more information, see the "docs" directory of the Waitress package or visit
 https://docs.pylonsproject.org/projects/waitress/en/latest/
 
+2.1.2
+-----
+
+Bugfix
+~~~~~~
+
+- When expose_tracebacks is enabled waitress would fail to properly encode
+  unicode thereby causing another error during error handling. See
+  https://github.com/Pylons/waitress/pull/378
+
+- Header length checking had a calculation that was done incorrectly when the
+  data was received across multple socket reads. This calculation has been
+  corrected, and no longer will Waitress send back a 413 Request Entity Too
+  Large. See https://github.com/Pylons/waitress/pull/376
+
+Security Bugfix
+~~~~~~~~~~~~~~~
+
+- in 2.1.0 a new feature was introduced that allowed the WSGI thread to start
+  sending data to the socket. However this introduced a race condition whereby
+  a socket may be closed in the sending thread while the main thread is about
+  to call select() therey causing the entire application to be taken down.
+  Waitress will no longer close the socket in the WSGI thread, instead waking
+  up the main thread to cleanup. See 
https://github.com/Pylons/waitress/pull/377
+
 2.1.1
 -----
 
@@ -138,5 +162,3 @@
   REQUEST_URI is similar to ``request_uri`` in nginx. It is a string that
   contains the request path before separating the query string and
   decoding ``%``-escaped characters. 
-
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/src/waitress.egg-info/SOURCES.txt 
new/waitress-2.1.2/src/waitress.egg-info/SOURCES.txt
--- old/waitress-2.1.1/src/waitress.egg-info/SOURCES.txt        2022-03-16 
22:34:36.000000000 +0100
+++ new/waitress-2.1.2/src/waitress.egg-info/SOURCES.txt        2022-05-30 
23:38:47.000000000 +0200
@@ -72,6 +72,7 @@
 tests/fixtureapps/badcl.py
 tests/fixtureapps/echo.py
 tests/fixtureapps/error.py
+tests/fixtureapps/error_traceback.py
 tests/fixtureapps/filewrapper.py
 tests/fixtureapps/getline.py
 tests/fixtureapps/groundhog1.jpg
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/tests/fixtureapps/error_traceback.py 
new/waitress-2.1.2/tests/fixtureapps/error_traceback.py
--- old/waitress-2.1.1/tests/fixtureapps/error_traceback.py     1970-01-01 
01:00:00.000000000 +0100
+++ new/waitress-2.1.2/tests/fixtureapps/error_traceback.py     2022-05-25 
04:06:09.000000000 +0200
@@ -0,0 +1,2 @@
+def app(environ, start_response):  # pragma: no cover
+    raise ValueError("Invalid application: " + chr(8364))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/tests/test_channel.py 
new/waitress-2.1.2/tests/test_channel.py
--- old/waitress-2.1.1/tests/test_channel.py    2022-02-06 19:28:31.000000000 
+0100
+++ new/waitress-2.1.2/tests/test_channel.py    2022-05-30 21:03:51.000000000 
+0200
@@ -376,7 +376,7 @@
         inst.total_outbufs_len = len(inst.outbufs[0])
         inst.adj.send_bytes = 1
         inst.adj.outbuf_high_watermark = 2
-        sock.send = lambda x: False
+        sock.send = lambda x, do_close=True: False
         inst.will_close = False
         inst.last_activity = 0
         result = inst.handle_write()
@@ -453,7 +453,7 @@
 
         buf = DummyHugeOutbuffer()
         inst.outbufs = [buf]
-        inst.send = lambda *arg: 0
+        inst.send = lambda *arg, do_close: 0
         result = inst._flush_some()
         # we are testing that _flush_some doesn't raise an OverflowError
         # when one of its outbufs has a __len__ that returns gt sys.maxint
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/tests/test_functional.py 
new/waitress-2.1.2/tests/test_functional.py
--- old/waitress-2.1.1/tests/test_functional.py 2022-03-16 22:26:39.000000000 
+0100
+++ new/waitress-2.1.2/tests/test_functional.py 2022-05-25 04:06:09.000000000 
+0200
@@ -359,7 +359,7 @@
                 sorted(headers.keys()),
                 ["connection", "content-length", "content-type", "date", 
"server"],
             )
-            self.assertEqual(headers["content-type"], "text/plain")
+            self.assertEqual(headers["content-type"], "text/plain; 
charset=utf-8")
             # connection has been closed
             self.send_check_error(to_send)
             self.assertRaises(ConnectionClosed, read_http, fp)
@@ -381,7 +381,7 @@
                 sorted(headers.keys()),
                 ["connection", "content-length", "content-type", "date", 
"server"],
             )
-            self.assertEqual(headers["content-type"], "text/plain")
+            self.assertEqual(headers["content-type"], "text/plain; 
charset=utf-8")
             # connection has been closed
             self.send_check_error(to_send)
             self.assertRaises(ConnectionClosed, read_http, fp)
@@ -403,7 +403,7 @@
                 sorted(headers.keys()),
                 ["connection", "content-length", "content-type", "date", 
"server"],
             )
-            self.assertEqual(headers["content-type"], "text/plain")
+            self.assertEqual(headers["content-type"], "text/plain; 
charset=utf-8")
             # connection has been closed
             self.send_check_error(to_send)
             self.assertRaises(ConnectionClosed, read_http, fp)
@@ -428,7 +428,7 @@
                 sorted(headers.keys()),
                 ["connection", "content-length", "content-type", "date", 
"server"],
             )
-            self.assertEqual(headers["content-type"], "text/plain")
+            self.assertEqual(headers["content-type"], "text/plain; 
charset=utf-8")
             # connection has been closed
             self.send_check_error(to_send)
             self.assertRaises(ConnectionClosed, read_http, fp)
@@ -1121,7 +1121,7 @@
             self.assertline(line, "413", "Request Entity Too Large", 
"HTTP/1.1")
             cl = int(headers["content-length"])
             self.assertEqual(cl, len(response_body))
-            self.assertEqual(headers["content-type"], "text/plain")
+            self.assertEqual(headers["content-type"], "text/plain; 
charset=utf-8")
             # connection has been closed
             self.send_check_error(to_send)
             self.assertRaises(ConnectionClosed, read_http, fp)
@@ -1269,6 +1269,49 @@
             self.assertRaises(ConnectionClosed, read_http, fp)
 
 
+class InternalServerErrorTestsWithTraceback:
+    def setUp(self):
+        from tests.fixtureapps import error_traceback
+
+        self.start_subprocess(error_traceback.app, expose_tracebacks=True)
+
+    def tearDown(self):
+        self.stop_subprocess()
+
+    def test_expose_tracebacks_http_10(self):
+        to_send = b"GET / HTTP/1.0\r\n\r\n"
+        self.connect()
+        self.sock.send(to_send)
+        with self.sock.makefile("rb", 0) as fp:
+            line, headers, response_body = read_http(fp)
+            self.assertline(line, "500", "Internal Server Error", "HTTP/1.0")
+            cl = int(headers["content-length"])
+            self.assertEqual(cl, len(response_body))
+            self.assertTrue(response_body.startswith(b"Internal Server Error"))
+            self.assertEqual(headers["connection"], "close")
+            # connection has been closed
+            self.send_check_error(to_send)
+            self.assertRaises(ConnectionClosed, read_http, fp)
+
+    def test_expose_tracebacks_http_11(self):
+        to_send = b"GET / HTTP/1.1\r\n\r\n"
+        self.connect()
+        self.sock.send(to_send)
+        with self.sock.makefile("rb", 0) as fp:
+            line, headers, response_body = read_http(fp)
+            self.assertline(line, "500", "Internal Server Error", "HTTP/1.1")
+            cl = int(headers["content-length"])
+            self.assertEqual(cl, len(response_body))
+            self.assertTrue(response_body.startswith(b"Internal Server Error"))
+            self.assertEqual(
+                sorted(headers.keys()),
+                ["connection", "content-length", "content-type", "date", 
"server"],
+            )
+            # connection has been closed
+            self.send_check_error(to_send)
+            self.assertRaises(ConnectionClosed, read_http, fp)
+
+
 class FileWrapperTests:
     def setUp(self):
         from tests.fixtureapps import filewrapper
@@ -1538,6 +1581,12 @@
     pass
 
 
+class TcpInternalServerErrorTestsWithTraceback(
+    InternalServerErrorTestsWithTraceback, TcpTests, unittest.TestCase
+):
+    pass
+
+
 class TcpFileWrapperTests(FileWrapperTests, TcpTests, unittest.TestCase):
     pass
 
@@ -1604,6 +1653,11 @@
     ):
         pass
 
+    class UnixInternalServerErrorTestsWithTraceback(
+        InternalServerErrorTestsWithTraceback, UnixTests, unittest.TestCase
+    ):
+        pass
+
     class UnixFileWrapperTests(FileWrapperTests, UnixTests, unittest.TestCase):
         pass
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/tests/test_parser.py 
new/waitress-2.1.2/tests/test_parser.py
--- old/waitress-2.1.1/tests/test_parser.py     2022-03-16 22:26:39.000000000 
+0100
+++ new/waitress-2.1.2/tests/test_parser.py     2022-05-25 04:06:09.000000000 
+0200
@@ -106,6 +106,18 @@
         self.assertTrue(self.parser.completed)
         self.assertTrue(isinstance(self.parser.error, RequestEntityTooLarge))
 
+    def test_received_headers_not_too_large_multiple_chunks(self):
+
+        data = b"GET /foobar HTTP/8.4\r\nX-Foo: 1\r\n"
+        data2 = b"X-Foo-Other: 3\r\n\r\n"
+        self.parser.adj.max_request_header_size = len(data) + len(data2) + 1
+        result = self.parser.received(data)
+        self.assertEqual(result, 32)
+        result = self.parser.received(data2)
+        self.assertEqual(result, 18)
+        self.assertTrue(self.parser.completed)
+        self.assertFalse(self.parser.error)
+
     def test_received_headers_too_large(self):
 
         self.parser.adj.max_request_header_size = 2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/tests/test_proxy_headers.py 
new/waitress-2.1.2/tests/test_proxy_headers.py
--- old/waitress-2.1.1/tests/test_proxy_headers.py      2022-01-14 
03:57:32.000000000 +0100
+++ new/waitress-2.1.2/tests/test_proxy_headers.py      2022-05-25 
04:06:09.000000000 +0200
@@ -16,7 +16,7 @@
             response.headers = response_headers
 
         response.steps = list(app(environ, start_response))
-        response.body = b"".join(s.encode("latin-1") for s in response.steps)
+        response.body = b"".join(s for s in response.steps)
         return response
 
     def test_get_environment_values_w_scheme_override_untrusted(self):
@@ -727,7 +727,7 @@
     def __call__(self, environ, start_response):
         self.environ = environ
         start_response("200 OK", [("Content-Type", "text/plain")])
-        yield "hello"
+        yield b"hello"
 
 
 class DummyResponse:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/tests/test_task.py 
new/waitress-2.1.2/tests/test_task.py
--- old/waitress-2.1.1/tests/test_task.py       2022-01-14 03:57:32.000000000 
+0100
+++ new/waitress-2.1.2/tests/test_task.py       2022-05-25 04:06:09.000000000 
+0200
@@ -869,7 +869,7 @@
         self.assertEqual(lines[0], b"HTTP/1.0 432 Too Ugly")
         self.assertEqual(lines[1], b"Connection: close")
         self.assertEqual(lines[2], b"Content-Length: 43")
-        self.assertEqual(lines[3], b"Content-Type: text/plain")
+        self.assertEqual(lines[3], b"Content-Type: text/plain; charset=utf-8")
         self.assertTrue(lines[4])
         self.assertEqual(lines[5], b"Server: waitress")
         self.assertEqual(lines[6], b"Too Ugly")
@@ -885,7 +885,7 @@
         self.assertEqual(lines[0], b"HTTP/1.1 432 Too Ugly")
         self.assertEqual(lines[1], b"Connection: close")
         self.assertEqual(lines[2], b"Content-Length: 43")
-        self.assertEqual(lines[3], b"Content-Type: text/plain")
+        self.assertEqual(lines[3], b"Content-Type: text/plain; charset=utf-8")
         self.assertTrue(lines[4])
         self.assertEqual(lines[5], b"Server: waitress")
         self.assertEqual(lines[6], b"Too Ugly")
@@ -902,7 +902,7 @@
         self.assertEqual(lines[0], b"HTTP/1.1 432 Too Ugly")
         self.assertEqual(lines[1], b"Connection: close")
         self.assertEqual(lines[2], b"Content-Length: 43")
-        self.assertEqual(lines[3], b"Content-Type: text/plain")
+        self.assertEqual(lines[3], b"Content-Type: text/plain; charset=utf-8")
         self.assertTrue(lines[4])
         self.assertEqual(lines[5], b"Server: waitress")
         self.assertEqual(lines[6], b"Too Ugly")
@@ -919,7 +919,7 @@
         self.assertEqual(lines[0], b"HTTP/1.1 432 Too Ugly")
         self.assertEqual(lines[1], b"Connection: close")
         self.assertEqual(lines[2], b"Content-Length: 43")
-        self.assertEqual(lines[3], b"Content-Type: text/plain")
+        self.assertEqual(lines[3], b"Content-Type: text/plain; charset=utf-8")
         self.assertTrue(lines[4])
         self.assertEqual(lines[5], b"Server: waitress")
         self.assertEqual(lines[6], b"Too Ugly")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waitress-2.1.1/tests/test_wasyncore.py 
new/waitress-2.1.2/tests/test_wasyncore.py
--- old/waitress-2.1.1/tests/test_wasyncore.py  2022-03-13 01:58:54.000000000 
+0100
+++ new/waitress-2.1.2/tests/test_wasyncore.py  2022-05-30 21:03:51.000000000 
+0200
@@ -31,7 +31,7 @@
 else:
     TESTFN = "@test"
 
-TESTFN = "{}_{}_tmp".format(TESTFN, os.getpid())
+TESTFN = f"{TESTFN}_{os.getpid()}_tmp"
 
 
 class DummyLogger:  # pragma: no cover
@@ -574,7 +574,7 @@
         self.assertEqual(function, "test_compact_traceback")
         self.assertEqual(t, real_t)
         self.assertEqual(v, real_v)
-        self.assertEqual(info, "[%s|%s|%s]" % (f, function, line))
+        self.assertEqual(info, f"[{f}|{function}|{line}]")
 
 
 class DispatcherTests(unittest.TestCase):

Reply via email to