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):