News
====

.. contents::

1.0.5
------
* Restore Python 2.4 compatibility.

1.0.4
------

* The field names escaping bug semi-fixed in 1.0.3 and originally blamed on cgi module
  was in fact a ``webob.request._encode_multipart`` bug (also in Google Chrome) and was
  lurking in webob code for quite some time -- 1.0.2 just made it trigger more often.
  Now it is fixed properly.

* Make sure that req.url and related properties do not unnecessarily escape some chars
  (``:@&+$``) in the URI path. See also `related ticket
  <https://bitbucket.org/ianb/webob/issue/5>`_.

* Revert some changes from 1.0.3 that have broken backwards compatibility for some apps.
  Getting ``req.body_file`` does not make input stream seekable, but there's a new property
  ``req.body_file_seekable`` that does.

* ``Request.get_response`` and ``Request.call_application`` seek the input body to start
  before calling the app (if possible).

* Accessing ``req.body`` 'rewinds' the input stream back to pos 0 as well.

* When accessing ``req.POST`` we now avoid making the body seekable as the input stream data
  are preserved in ``FakeCGIBody`` anyway.

* Add new method ``Request.from_string``.

* Make sure ``Request.as_string()`` uses CRLF to separate headers.

* Improve parity between ``Request.as_string()`` and ``.from_file``/``.from_string``
  methods, so that the latter can parse output of the former and create a similar
  request object which wasn't always the case previously.

1.0.3
------

* Correct a caching issue introduced in WebOb 1.0.2 that was causing unnecessary reparsing
  of POST requests.

* Fix a bug regarding field names escaping for forms submitted as ``multipart/form-data``.
  For more infromation see `the bug report and discussion
  <https://bitbucket.org/ianb/webob/issue/2>`_ and 1.0.4 notes for further fix.

* Add ``req.http_version`` attribute.

1.0.2
------

* Primary maintainer is now `Sergey Schetinin <http://self.maluke.com/>`_.

* Issue tracker moved from `Trac <http://bit.ly/webob-tickets>`_ to bitbucket's `issue
  tracker <https://bitbucket.org/ianb/webob/issues>`_

* WebOb 1.0.1 changed the behavior of ``MultiDict.update`` to be more in line with
  other dict-like objects. We now also issue a warning when we detect that the
  client code seems to expect the old, extending semantics.

* Make ``Response.set_cookie(key, None)`` set the 'delete-cookie' (same as ``.delete_cookie(key)``)

* Make ``req.upath_info`` and ``req.uscript_name`` settable

* Add :meth:``Request.as_string()`` method

* Add a ``req.is_body_seekable`` property

* Support for the ``deflate`` method with ``resp.decode_content()``

* To better conform to WSGI spec we no longer attempt to use seek on ``wsgi.input`` file
  instead we assume it is not seekable unless ``env['webob.is_body_seekable']`` is set.
  When making the body seekable we set that flag.

* A call to ``req.make_body_seekable()`` now guarantees that the body is seekable, is at 0 position
  and that a correct ``req.content_length`` is present.

* ``req.body_file`` is always seekable. To access ``env['wsgi.input']`` without any processing,
  use ``req.body_file_raw``. (Partially reverted in 1.0.4)

* Fix responses to HEAD requests with Range.

* Fix ``del resp.content_type``, ``del req.body``, ``del req.cache_control``

* Fix ``resp.merge_cookies()`` when called with an argument that is not a Response instance.

* Fix ``resp.content_body = None`` (was removing Cache-Control instead)

* Fix ``req.body_file = f`` setting ``CONTENT_LENGTH`` to ``-1`` (now removes from environ)

* Fix: make sure req.copy() leaves the original with seekable body

* Fix handling of WSGI environs with missing ``SCRIPT_NAME``

* A lot of tests were added by Mariano Mara and Danny Navarro.



1.0.1
-----

* As WebOb requires Python 2.4 or later, drop some compatibility modules
  and update the code to use the decorator syntax.

* Implement optional on-the-fly response compression (``resp.encode_content(lazy=True)``)

* Drop ``util.safezip`` module and make ``util`` a module instead of a subpackage.
  Merge ``statusreasons`` into it.

* Instead of using stdlib ``Cookie`` with monkeypatching, add a derived
  but thoroughly rewritten, cleaner, safer and faster ``webob.cookies`` module.

* Fix: ``Response.merge_cookies`` now copies the headers before modification instead of
  doing it in-place.

* Fix: setting request header attribute to ``None`` deletes that header.
  (Bug only affected the 1.0 release).

* Use ``io.BytesIO`` for the request body file on Python 2.7 and newer.

* If a UnicodeMultiDict was used as the ``multi`` argument of another
  UnicodeMultiDict, and a ``cgi.FieldStorage`` with a ``filename``
  with high-order characters was present in the underlying
  UnicodeMultiDict, a ``UnicodeEncodeError`` would be raised when any
  helper method caused the ``_decode_value`` method to be called,
  because the method would try to decode an already decoded string.

* Fix tests to pass under Python 2.4.

* Add descriptive docstrings to each exception in ``webob.exc``.

* Change the behaviour of ``MultiDict.update`` to overwrite existing header
  values instead of adding new headers. The extending semantics are now available
  via the ``extend`` method.

* Fix a bug in ``webob.exc.WSGIHTTPException.__init__``.  If a list of
  ``headers`` was passed as a sequence which contained duplicate keys (for
  example, multiple ``Set-Cookie`` headers), all but one of those headers
  would be lost, because the list was effectively flattened into a dictionary
  as the result of calling ``self.headers.update``.  Fixed via calling
  ``self.headers.extend`` instead.

1.0
---

* 1.0, yay!

* Pull in werkzeug Cookie fix for malformed cookie bug.

* Implement :meth:`Request.from_file` and
  :meth:`Response.from_file` which are kind of the inversion of
  ``str(req)`` and ``str(resp)``

* Add optional ``pattern`` argument to :meth:`Request.path_info_pop` that requires
  the ``path_info`` segment to match the passed regexp to get popped and returned.

* Rewrite most of descriptor implementations for speed.

* Reorder descriptor declarations to group them by their semantics.

* Move code around so that there are fewer compat modules.

* Change :meth:``HTTPError.__str__`` to better conform to PEP 352.

* Make :attr:`Request.cache_control` a view on the headers.

* Correct Accept-Language and Accept-Charset matching to fully conform to the HTTP spec.

* Expose parts of :meth:`Request.blank` as :func:`environ_from_url`
  and :func:`environ_add_POST`

* Fix Authorization header parsing for some corner cases.

* Fix an error generated if the user-agent sends a 'Content_Length' header
  (note the underscore).

* Kill :attr:`Request.default_charset`. Request charset defaults to UTF-8.
  This ensures that all values in ``req.GET``, ``req.POST`` and ``req.params``
  are always unicode.

* Fix the ``headerlist`` and ``content_type`` constructor arguments priorities
  for :class:`HTTPError` and subclasses.

* Add support for weak etags to conditional Response objects.

* Fix locale-dependence for some cookie dates strings.

* Improve overall test coverage.

* Rename class ``webob.datastruct.EnvironHeaders`` to ``webob.headers.EnvironHeaders``

* Rename class ``webob.headerdict.HeaderDict`` to ``webob.headers.ResponseHeaders``

* Rename class ``webob.updatedict.UpdateDict`` to ``webob.cachecontrol.UpdateDict``

0.9.8
-----

* Fix issue with WSGIHTTPException inadvertently generating unicode body
  and failing to encode it

* WWW-Authenticate response header is accessible as
  ``response.www_authenticate``

* ``response.www_authenticate`` and ``request.authorization`` hold None
  or tuple ``(auth_method, params)`` where ``params`` is a dictionary
  (or a string when ``auth_method`` is not one of known auth schemes
  and for Authenticate: Basic ...)

* Don't share response headers when getting a response like ``resp =
  req.get_response(some_app)``; this can avoid some funny errors with
  modifying headers and reusing Response objects.

* Add `overwrite` argument to :meth:`Response.set_cookie` that make the
  new value overwrite the previously set. `False` by default.

* Add `strict` argument to :meth:`Response.unset_cookie` that controls
  if an exception should be raised in case there are no cookies to unset.
  `True` by default.

* Fix ``req.GET.copy()``

* Make sure that 304 Not Modified responses generated by
  :meth:`Response.conditional_response_app` exclude Content-{Length/Type}
  headers

* Fix ``Response.copy()`` not being an independent copy

* When the requested range is not satisfiable, return a 416 error
  (was returning entire body)

* Truncate response for range requests that go beyond the end of body
  (was treating as invalid).

0.9.7.1
-------

* Fix an import problem with Pylons

0.9.7
-----

* Moved repository from svn location to
  http://bitbucket.org/ianb/webob/

* Arguments to :meth:`Accept.best_match` must be specific types,
  not wildcards. The server should know a list of specic types it can
  offer and use ``best_match`` to select a specific one.

* With ``req.accept.best_match([types])`` prefer the first type in the
  list (previously it preferred later types).

* Also, make sure that if the user-agent accepts multiple types and
  there are multiple matches to the types that the application offers,
  ``req.accept.best_match([..])`` returns the most specific match.
  So if the server can satisfy either ``image/*`` or ``text/plain``
  types, the latter will be picked independent from the order the accepted
  or offered types are listed (given they have the same quality rating).

* Fix Range, Content-Range and AppIter support all of which were broken
  in many ways, incorrectly parsing ranges, reporting incorrect
  content-ranges, failing to generate the correct body to satisfy the range
  from ``app_iter`` etc.

* Fix assumption that presense of a ``seek`` method means that the stream
  is seekable.

* Add ``ubody`` alias for ``Response.unicode_body``

* Add Unicode versions of ``Request.script_name`` and ``path_info``:
  ``uscript_name`` and ``upath_info``.

* Split __init__.py into four modules: request, response, descriptors and
  datetime_utils.

* Fix ``Response.body`` access resetting Content-Length to zero
  for HEAD responses.

* Support passing Unicode bodies to :class:`WSGIHTTPException`
  constructors.

* Make ``bool(req.accept)`` return ``False`` for requests with missing
  Accept header.

* Add HTTP version to :meth:`Request.__str__` output.

* Resolve deprecation warnings for parse_qsl on Python 2.6 and newer.

* Fix :meth:`Response.md5_etag` setting Content-MD5 in incorrect
  format.

* Add ``Request.authorization`` property for Authorization header.

* Make sure ETag value is always quoted (required by RFC)

* Moved most ``Request`` behavior into a new class named
  ``BaseRequest``.  The ``Request`` class is now a superclass for
  ``BaseRequest`` and a simple mixin which manages
  ``environ['webob.adhoc_attrs']`` when ``__setitem__``,
  ``__delitem__`` and ``__getitem__`` are called.  This allows
  framework developers who do not want the
  ``environ['webob.adhoc_attrs']`` mutation behavior from
  ``__setattr__``.  (chrism)

* Added response attribute ``response.content_disposition`` for its
  associated header.

* Changed how ``charset`` is determined on :class:`webob.Request`
  objects.  Now the ``charset`` parameter is read on the Content-Type
  header, if it is present.  Otherwise a ``default_charset`` parameter
  is read, or the ``charset`` argument to the Request constructor.
  This is more similar to how :class:`webob.Response` handles the
  charset.

* Made the case of the Content-Type header consistent (note: this
  might break some doctests).

* Make ``req.GET`` settable, such that ``req.environ['QUERY_STRING']``
  is updated.

* Fix problem with ``req.POST`` causing a re-parse of the body when
  you instantiate multiple ``Request`` objects over the same environ
  (e.g., when using middleware that looks at ``req.POST``).

* Recreate the request body properly when a ``POST`` includes file
  uploads.

* When ``req.POST`` is updated, the generated body will include the
  new values.

* Added a ``POST`` parameter to :meth:`webob.Request.blank`; when
  given this will create a request body for the POST parameters (list
  of two-tuples or dictionary-like object).  Note: this does not
  handle unicode or file uploads.

* Added method :meth:`webob.Response.merge_cookies`, which takes the
  ``Set-Cookie`` headers from a Response, and merges them with another
  response or WSGI application.  (This is useful for flash messages.)

* Fix a problem with creating exceptions like
  ``webob.exc.HTTPNotFound(body='<notfound/>',
  content_type='application/xml')`` (i.e., non-HTML exceptions).

* When a Location header is not absolute in a Response, it will be
  made absolute when the Response is called as a WSGI application.
  This makes the response less bound to a specific request.

* Added :mod:`webob.dec`, a decorator for making WSGI applications
  from functions with the signature ``resp = app(req)``.

0.9.6.1
-------

* Fixed :meth:`Response.__init__`, which for some content types would
  raise an exception.

* The ``req.body`` property will not recreate a StringIO object
  unnecessarily when rereading the body.

0.9.6
-----

* Removed `environ_getter` from :class:`webob.Request`.  This
  largely-unused option allowed a Request object to be instantiated
  with a dynamic underlying environ.  Since it wasn't used much, and
  might have been ill-advised from the beginning, and affected
  performance, it has been removed (from Chris McDonough).

* Speed ups for :meth:`webob.Response.__init__` and
  :meth:`webob.Request.__init__`

* Fix defaulting of ``CONTENT_TYPE`` instead of ``CONTENT_LENGTH`` to
  0 in ``Request.str_POST``.

* Added :meth:`webob.Response.copy`

0.9.5
-----

* Fix ``Request.blank('/').copy()`` raising an exception.

* Fix a potential memory leak with HEAD requests and 304 responses.

* Make :func:`webob.html_escape` respect the ``.__html__()`` magic
  method, which allows you to use HTML in
  :class`webob.exc.HTTPException` instances.

* Handle unicode values for ``resp.location``.

* Allow arbitrary keyword arguments to ``exc.HTTP*`` (the same
  keywords you can send to :class:`webob.Response`).

* Allow setting :meth:`webob.Response.cache_expires` (usually it is
  called as a method).  This is primarily to allow
  ``Response(cache_expires=True)``.

0.9.4
-----

* Quiet Python 2.6 deprecation warnings.

* Added an attribute ``unicode_errors`` to :class:`webob.Response` --
  if set to something like ``unicode_errors='replace'`` it will decode
  ``resp.body`` appropriately.  The default is ``strict`` (which was
  the former un-overridable behavior).

0.9.3
-----

* Make sure that if changing the body the Content-MD5 header is
  removed. (Otherwise a lot of middleware would accidentally
  corrupt responses).

* Fixed ``Response.encode_content('identity')`` case (was a no-op even
  for encoded bodies).

* Fixed :meth:`Request.remove_conditional_headers` that was removing
  If-Match header instead of If-None-Match.

* Fixed ``resp.set_cookie(max_age=timedelta(...))``

* ``request.POST`` now supports PUT requests with the appropriate
  Content-Type.

0.9.2
-----

* Add more arguments to :meth:`Request.remove_conditional_headers`
  for more fine-grained control: `remove_encoding`, `remove_range`,
  `remove_match`, `remove_modified`. All of them are `True` by default.

* Add an `set_content_md5` argument to :meth:`Response.md5_etag`
  that calculates and sets Content-MD5 reponse header from current
  body.

* Change formatting of cookie expires, to use the more traditional
  format ``Wed, 5-May-2001 15:34:10 GMT`` (dashes instead of spaces).
  Browsers should deal with either format, but some other code expects
  dashes.

* Added in ``sorted`` function for backward compatibility with Python
  2.3.

* Allow keyword arguments to :class:`webob.Request`, which assign
  attributes (possibly overwriting values in the environment).

* Added methods :meth:`webob.Request.make_body_seekable` and
  :meth:`webob.Request.copy_body`, which make it easier to share a
  request body among different consuming applications, doing something
  like `req.make_body_seekable(); req.body_file.seek(0)`

0.9.1
-----

* ``request.params.copy()`` now returns a writable MultiDict (before
  it returned an unwritable object).

* There were several things broken with ``UnicodeMultiDict`` when
  ``decode_param_names`` is turned on (when the dictionary keys are
  unicode).

* You can pass keyword arguments to ``Request.blank()`` that will be
  used to construct ``Request`` (e.g., ``Request.blank('/',
  decode_param_names=True)``).

* If you set headers like ``response.etag`` to a unicode value, they
  will be encoded as ISO-8859-1 (however, they will remain encoded,
  and ``response.etag`` will not be a unicode value).

* When parsing, interpret times with no timezone as UTC (previously
  they would be interpreted as local time).

* Set the Expires property on cookies when using
  ``response.set_cookie()``.  This is inherited from ``max_age``.

* Support Unicode cookie values

0.9
---

* Added ``req.urlarg``, which represents positional arguments in
  ``environ['wsgiorg.routing_args']``.

* For Python 2.4, added attribute get/set proxies on exception objects
  from, for example, ``webob.exc.HTTPNotFound().exception``, so that
  they act more like normal response objects (despite not being
  new-style classes or ``webob.Response`` objects).  In Python 2.5 the
  exceptions are ``webob.Response`` objects.

Backward Incompatible Changes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* The ``Response`` constructor has changed: it is now ``Response([body],
  [status], ...)`` (before it was ``Response([status], [body], ...)``).
  Body may be str or unicode.

* The ``Response`` class defaults to ``text/html`` for the
  Content-Type, and ``utf8`` for the charset (charset is only set on
  ``text/*`` and ``application/*+xml`` responses).

Bugfixes and Small Changes
~~~~~~~~~~~~~~~~~~~~~~~~~~

* Use ``BaseCookie`` instead of ``SimpleCookie`` for parsing cookies.

* Added ``resp.write(text)`` method, which is equivalent to
  ``resp.body += text`` or ``resp.unicode_body += text``, depending on
  the type of ``text``.

* The ``decode_param_names`` argument (used like
  ``Request(decode_param_names=True)``) was being ignored.

* Unicode decoding of file uploads and file upload filenames were
  causing errors when decoding non-file-upload fields (both fixes from
  Ryan Barrett).

0.8.5
-----

* Added response methods ``resp.encode_content()`` and
  ``resp.decode_content()`` to gzip or ungzip content.

* ``Response(status=404)`` now works (before you would have to use
  ``status="404 Not Found"``).

* Bugfix (typo) with reusing POST body.

* Added ``226 IM Used`` response status.

* Backport of ``string.Template`` included for Python 2.3
  compatibility.

0.8.4
-----

* ``__setattr__`` would keep ``Request`` subclasses from having
  properly settable environ proxies (like ``req.path_info``).

0.8.3
-----

* ``request.POST`` was giving FieldStorage objects for *every*
  attribute, not just file uploads.  This is fixed now.


* Added request attributes ``req.server_name`` and ``req.server_port``
  for the environ keys ``SERVER_NAME`` and ``SERVER_PORT``.

* Avoid exceptions in ``req.content_length``, even if
  ``environ['CONTENT_LENGTH']`` is somehow invalid.

0.8.2
-----

* Python 2.3 compatibility: backport of ``reversed(seq)``

* Made separate ``.exception`` attribute on ``webob.exc`` objects,
  since new-style classes can't be raised as exceptions.

* Deprecate ``req.postvars`` and ``req.queryvars``, instead using the
  sole names ``req.GET`` and ``req.POST`` (also ``req.str_GET`` and
  ``req.str_POST``).  The old names give a warning; will give an error
  in next release, and be completely gone in the following release.

* ``req.user_agent`` is now just a simple string (parsing the
  User-Agent header was just too volatile, and required too much
  knowledge about current browsers).  Similarly,
  ``req.referer_search_query()`` is gone.

* Added parameters ``version`` and ``comment`` to
  ``Response.set_cookie()``, per William Dode's suggestion.

* Was accidentally consuming file uploads, instead of putting the
  ``FieldStorage`` object directly in the parameters.

0.8.1
-----

* Added ``res.set_cookie(..., httponly=True)`` to set the ``HttpOnly``
  attribute on the cookie, which keeps Javascript from reading the
  cookie.

* Added some WebDAV-related responses to ``webob.exc``

* Set default ``Last-Modified`` when using ``response.cache_expire()``
  (fixes issue with Opera)

* Generally fix ``.cache_control``

0.8
---

First release.  Nothing is new, or everything is new, depending on how
you think about it.
