Werkzeug v2.0.0 Release Notes

  • ๐Ÿš€ Released 2021-05-11

    • ๐Ÿ‘ Drop support for Python 2 and 3.5. :pr:1693
    • ๐Ÿ—„ Deprecate :func:utils.format_string, use :class:string.Template instead. :issue:1756
    • ๐Ÿ—„ Deprecate :func:utils.bind_arguments and :func:utils.validate_arguments, use :meth:Signature.bind and :func:inspect.signature instead. :issue:1757
    • ๐Ÿ—„ Deprecate :class:utils.HTMLBuilder. :issue:1761
    • ๐Ÿ—„ Deprecate :func:utils.escape and :func:utils.unescape, use MarkupSafe instead. :issue:1758
    • ๐Ÿ—„ Deprecate the undocumented python -m werkzeug.serving CLI. :issue:1834
    • ๐Ÿ—„ Deprecate the environ["werkzeug.server.shutdown"] function that is available when running the development server. :issue:1752
    • ๐Ÿ—„ Deprecate the useragents module and the built-in user agent parser. Use a dedicated parser library instead by subclassing user_agent.UserAgent and setting Request.user_agent_class. :issue:2078
    • ๐Ÿšš Remove the unused, internal posixemulation module. :issue:1759
    • All datetime values are timezone-aware with tzinfo=timezone.utc. This applies to anything using http.parse_date: Request.date, .if_modified_since, .if_unmodified_since; Response.date, .expires, .last_modified, .retry_after; parse_if_range_header, and IfRange.date. When comparing values, the other values must also be aware, or these values must be made naive. When passing parameters or setting attributes, naive values are still assumed to be in UTC. :pr:2040
    • ๐Ÿ”€ Merge all request and response wrapper mixin code into single Request and Response classes. Using the mixin classes is no longer necessary and will show a deprecation warning. Checking isinstance or issubclass against BaseRequest and BaseResponse will show a deprecation warning and check against Request or Response instead. :issue:1963
    • ๐Ÿ‘ JSON support no longer uses simplejson if it's installed. To use another JSON module, override Request.json_module and Response.json_module. :pr:1766
    • Response.get_json() no longer caches the result, and the cache parameter is removed. :issue:1698
    • Response.freeze() generates an ETag header if one is not set. The no_etag parameter (which usually wasn't visible anyway) is no longer used. :issue:1963
    • ๐Ÿ— Add a url_scheme argument to :meth:~routing.MapAdapter.build to override the bound scheme. :pr:1721
    • ๐Ÿ— Passing an empty list as a query string parameter to build() won't append an unnecessary ?. Also drop any number of None items in a list. :issue:1992
    • โœ… When passing a Headers object to a test client method or EnvironBuilder, multiple values for a key are joined into one comma separated value. This matches the HTTP spec on multi-value headers. :issue:1655
    • Setting Response.status and status_code uses identical parsing and error checking. :issue:1658, :pr:1728
    • MethodNotAllowed and RequestedRangeNotSatisfiable take a response kwarg, consistent with other HTTP errors. :pr:1748
    • The response generated by :exc:~exceptions.Unauthorized produces one WWW-Authenticate header per value in www_authenticate, rather than joining them into a single value, to improve interoperability with browsers and other clients. :pr:1755
    • If parse_authorization_header can't decode the header value, it returns None instead of raising a UnicodeDecodeError. :issue:1816
    • The debugger no longer uses jQuery. :issue:1807
    • โœ… The test client includes the query string in REQUEST_URI and RAW_URI. :issue:1781
    • Switch the parameter order of default_stream_factory to match the order used when calling it. :pr:1085
    • Add send_file function to generate a response that serves a file. Adapted from Flask's implementation. :issue:265, :pr:1850
    • Add send_from_directory function to safely serve an untrusted path within a trusted directory. Adapted from Flask's implementation. :issue:1880
    • send_file takes download_name, which is passed even if as_attachment=False by using Content-Disposition: inline. download_name replaces Flask's attachment_filename. :issue:1869
    • send_file sets conditional=True and max_age=None by default. Cache-Control is set to no-cache if max_age is not set, otherwise public. This tells browsers to validate conditional requests instead of using a timed cache. max_age=None replaces Flask's cache_timeout=43200. :issue:1882
    • send_file can be called with etag="string" to set a custom ETag instead of generating one. etag replaces Flask's add_etags. :issue:1868
    • send_file sets the Content-Encoding header if an encoding is returned when guessing mimetype from download_name. :pr:3896
    • Update the defaults used by generate_password_hash. Increase PBKDF2 iterations to 260000 from 150000. Increase salt length to 16 from 8. Use secrets module to generate salt. :pr:1935
    • The reloader doesn't crash if sys.stdin is somehow None. :pr:1915
    • Add arguments to delete_cookie to match set_cookie and the attributes modern browsers expect. :pr:1889
    • ๐Ÿ—„ utils.cookie_date is deprecated, use utils.http_date instead. The value for Set-Cookie expires is no longer "-" delimited. :pr:2040
    • Use request.headers instead of request.environ to look up header attributes. :pr:1808
    • โœ… The test Client request methods (client.get, etc.) always return an instance of TestResponse. In addition to the normal behavior of Response, this class provides request with the request that produced the response, and history to track intermediate responses when follow_redirects is used. :issue:763, 1894
    • โœ… The test Client request methods takes an auth parameter to add an Authorization header. It can be an Authorization object or a (username, password) tuple for Basic auth. :pr:1809
    • โœ… Calling response.close() on a response from the test Client will close the request input stream. This matches file behavior and can prevent a ResourceWarning in some cases. :issue:1785
    • EnvironBuilder.from_environ decodes values encoded for WSGI, to avoid double encoding the new values. :pr:1959
    • 0๏ธโƒฃ The default stat reloader will watch Python files under non-system/virtualenv sys.path entries, which should contain most user code. It will also watch all Python files under directories given in extra_files. :pr:1945
    • The reloader ignores __pycache__ directories again. :pr:1945
    • run_simple takes exclude_patterns a list of fnmatch patterns that will not be scanned by the reloader. :issue:1333
    • Cookie names are no longer unquoted. This was against :rfc:6265 and potentially allowed setting __Secure prefixed cookies. :pr:1965
    • Fix some word matches for user agent platform when the word can be a substring. :issue:1923
    • ๐Ÿ”Š The development server logs ignored SSL errors. :pr:1967
    • Temporary files for form data are opened in rb+ instead of wb+ mode for better compatibility with some libraries. :issue:1961
    • ๐Ÿ“Œ Use SHA-1 instead of MD5 for generating ETags and the debugger pin, and in some tests. MD5 is not available in some environments, such as FIPS 140. This may invalidate some caches since the ETag will be different. :issue:1897
    • Add Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy response header properties. :pr:2008
    • run_simple tries to show a valid IP address when binding to all addresses, instead of 0.0.0.0 or ::. It also warns about not running the development server in production in this case. :issue:1964
    • ๐ŸŒฒ Colors in the development server log are displayed if Colorama is installed on Windows. For all platforms, style support no longer requires Click. :issue:1832
    • A range request for an empty file (or other data with length 0) will return a 200 response with the empty file instead of a 416 error. :issue:1937
    • New sans-IO base classes for Request and Response have been extracted to contain all the behavior that is not WSGI or IO dependent. These are not a public API, they are part of an ongoing refactor to let ASGI frameworks use Werkzeug. :pr:2005
    • ๐Ÿ”จ Parsing multipart/form-data has been refactored to use sans-io patterns. This should also make parsing forms with large binary file uploads significantly faster. :issue:1788, 875
    • LocalProxy matches the current Python data model special methods, including all r-ops, in-place ops, and async. __class__ is proxied, so the proxy will look like the object in more cases, including isinstance. Use issubclass(type(obj), LocalProxy) to check if an object is actually a proxy. :issue:1754
    • Local uses ContextVar on Python 3.7+ instead of threading.local. :pr:1778
    • request.values does not include form for GET requests (even though GET bodies are undefined). This prevents bad caching proxies from caching form data instead of query strings. :pr:2037
    • The development server adds the underlying socket to environ as werkzeug.socket. This is non-standard and specific to the dev server, other servers may expose this under their own key. It is useful for handling a WebSocket upgrade request. :issue:2052
    • โฌ†๏ธ URL matching assumes websocket=True mode for WebSocket upgrade requests. :issue:2052
    • โšก๏ธ Updated UserAgentParser to handle more cases. :issue:1971
    • werzeug.DechunkedInput.readinto will not read beyond the size of the buffer. :issue:2021
    • Fix connection reset when exceeding max content size. :pr:2051
    • pbkdf2_hex, pbkdf2_bin, and safe_str_cmp are deprecated. hashlib and hmac provide equivalents. :pr:2083
    • invalidate_cached_property is deprecated. Use del obj.name instead. :pr:2084
    • ๐Ÿ—„ Href is deprecated. Use werkzeug.routing instead. :pr:2085
    • Request.disable_data_descriptor is deprecated. Create the request with shallow=True instead. :pr:2085
    • ๐Ÿ—„ HTTPException.wrap is deprecated. Create a subclass manually instead. :pr:2085