What's New in WebOb 1.7
=======================

Compatibility
~~~~~~~~~~~~~

- WebOb is no longer supported on Python 2.6 and PyPy3 (due to pip no longer
  supporting Python 3.2 even on PyPy)

  If you would like Python 2.6 support, please pin to WebOb 1.6, which still
  has Python 2.6 support.


Backwards Incompatibility
~~~~~~~~~~~~~~~~~~~~~~~~~

- Response.set_cookie no longer accepts a key argument. This was deprecated in
  WebOb 1.5 and as mentioned in the deprecation, is being removed in 1.7

  Use:

  .. code-block:: python

     res = Response()
     res.set_cookie(name='cookie_name', value='val')

     # or

     res.set_cookie('cookie_name', 'val')

  Instead of:

  .. code-block:: python

     res = Response()
     res.set_cookie(key='cookie_name', value='val')

- Response `__init__` will no longer set the default Content-Type, nor
  Content-Length on Responses that don't have a body. This allows WebOb to
  return proper responses for things like `Response(status='204 No Content')`.

- Response.text will no longer raise if the Content-Type does not have a
  charset, it will fall back to using the new default_body_encoding. To get the
  old behaviour back please sub-class Response and set default_body_encoding to
  None. See https://github.com/Pylons/webob/pull/287

  An example of a Response class that has the old behaviour:

  .. code-block:: python

     class MyResponse(Response):
        default_body_encoding = None

     res = MyResponse(content_type='application/json')
     # This will raise as application/json doesn't have a charset
     res.text = 'sometext'

- WebOb no longer supports Chunked Encoding, this means that if you are using
  WebOb and need Chunked Encoding you will be required to have a proxy that
  unchunks the request for you. Please read
  https://github.com/Pylons/webob/issues/279 for more background.

Feature
~~~~~~~

- Response has a new default_body_encoding which may be used to allow
  getting/setting Response.text when a Content-Type has no charset. See
  https://github.com/Pylons/webob/pull/287

  .. code-block:: python

     res = Response()
     res.default_body_encoding = 'latin1'
     res.text = 'Will be encoded as latin1 and .body will be set'

     res = Response()
     res.default_body_encoding = 'latin1'
     res.body = b'A valid latin-1 string'
     res.text == 'A valid latin-1 string'


- webob.Request with any HTTP method is now allowed to have a body. This allows
  DELETE to have a request body for passing extra information. See
  https://github.com/Pylons/webob/pull/283 and
  https://github.com/Pylons/webob/pull/274

- Add `tell()` to `ResponseBodyFile` so that it may be used for example for
  ZipFile support. See https://github.com/Pylons/webob/pull/117

- Allow the return from `wsgify.middleware` to be used as a decorator. See
  https://github.com/Pylons/webob/pull/228

  .. code-block:: python

     @wsgify.middleware
     def restrict_ip(req, app, ips):
         if req.remote_addr not in ips:
             raise webob.exc.HTTPForbidden('Bad IP: %s' % req.remote_addr)
         return app
     
     @restrict_ip(ips=['127.0.0.1'])
     @wsgify
     def app(req):
           return 'hi'

Bugfix
~~~~~~

- Fixup cgi.FieldStorage on Python 3.x to work-around issue reported in Python
  bug report 27777 and 24764. This is currently applied for Python versions
  less than 3.7. See https://github.com/Pylons/webob/pull/294

- Response.set_cookie now accepts datetime objects for the expire kwarg and
  will correctly convert them to UTC with no tzinfo for use in calculating the
  max_age. See https://github.com/Pylons/webob/issues/254 and
  https://github.com/Pylons/webob/pull/292

- Fixes request.PATH_SAFE to contain all of the path safe characters according
  to RFC3986. See https://github.com/Pylons/webob/pull/291

- WebOb's exceptions will lazily read underlying variables when inserted into
  templates to avoid expensive computations/crashes when inserting into the
  template. This had a bad performance regression on Py27 because of the way
  the lazified class was created and returned. See
  https://github.com/Pylons/webob/pull/284

- `wsgify.__call__` raised a `TypeError` with an unhelpful message, it will now
  return the `repr` for the wrapped function:
  https://github.com/Pylons/webob/issues/119

- Response.content_type removes the charset content_type parameters unless the
  new content_type is a text like type that has a charset parameter.
  See https://github.com/Pylons/webob/pull/261 and
  https://github.com/Pylons/webob/issues/130

  Future versions of WebOb will remove all Content-Type parameters, and the
  user will have to explicitly add them back. Here's how to save and restore
  the Content-Type parameters:

  .. code-block:: python

     res = Response(content_type='text/html', charset='UTF-8')
     assert res.content_type == 'text/html'
     assert res.charset == 'UTF-8'

     params = res.content_type_params
     
     # Change the Content-Type
     res.content_type = 'application/unknown'
     assert res.content_type == 'application/unknown'
     assert res.charset == None

     # This will add the ``charset=UTF-8`` parameter to the Content-Type
     res.content_type_params = params

     assert res.headers['Content-Type'] == 'application/unknown; charset=UTF-8'

- Response.json's json.dumps/loads are now always UTF-8. It no longer tries to
  use the charset.

- The Response `__init__` will by default no longer set the Content-Type to the
  default if a headerlist is provided. This fixes issues whereby
  `Request.get_response()` would return a Response that didn't match the actual
  response.
  See https://github.com/Pylons/webob/pull/261 and
  https://github.com/Pylons/webob/issues/205

- Cleans up the remainder of the issues with the updated WebOb exceptions that
  were taught to return JSON in version 1.6. See
  https://github.com/Pylons/webob/issues/237 and
  https://github.com/Pylons/webob/issues/236

- Response.from_file now parses the status line correctly when the status line
  contains an HTTP with version, as well as a status text that contains
  multiple white spaces (e.g HTTP/1.1 404 Not Found). See
  https://github.com/Pylons/webob/issues/250

- Response now has a new property named `has_body` that may be used to
  interrogate the Response to find out if `Response.body` is or isn't set.

  This is used in the exception handling code so that if you use a WebOb HTTP
  Exception and pass a generator to `app_iter` WebOb won't attempt to read the
  whole thing and instead allows it to be returned to the WSGI server. See
  https://github.com/Pylons/webob/pull/259

