thirdparty/google_appengine/lib/webob/tests/test_response.txt
author Pawel Solyga <Pawel.Solyga@gmail.com>
Thu, 21 May 2009 14:44:41 +0200
changeset 2331 91379f6b8fcb
parent 109 620f9b141567
permissions -rw-r--r--
Add sorting of student projects on organization home page. List of student projects on organization home page is now sorted in alphabetical order by student name. Fixes issue 613.

This demonstrates how the Response object works, and tests it at the
same time.

    >>> from dtopt import ELLIPSIS
    >>> from webob import Response, UTC
    >>> from datetime import datetime
    >>> res = Response('Test', status='200 OK')

This is a minimal response object.  We can do things like get and set
the body:

    >>> res.body
    'Test'
    >>> res.body = 'Another test'
    >>> res.body
    'Another test'
    >>> res.body = 'Another'
    >>> res.write(' test')
    >>> res.app_iter
    ['Another test']
    >>> res.content_length
    12
    >>> res.headers['content-length']
    '12'
    
Content-Length is only applied when setting the body to a string; you
have to set it manually otherwise.  There are also getters and setters
for the various pieces:

    >>> res.app_iter = ['test']
    >>> print res.content_length
    None
    >>> res.content_length = 4
    >>> res.status
    '200 OK'
    >>> res.status_int
    200
    >>> res.headers
    HeaderDict([('content-type', 'text/html; charset=utf8'), ('Content-Length', '4')])
    >>> res.headerlist
    [('content-type', 'text/html; charset=utf8'), ('Content-Length', '4')]

Content-type and charset are handled separately as properties, though
they are both in the ``res.headers['content-type']`` header:

    >>> res.content_type
    'text/html'
    >>> res.content_type = 'text/html'
    >>> res.content_type
    'text/html'
    >>> res.charset
    'utf8'
    >>> res.charset = 'iso-8859-1'
    >>> res.charset
    'iso-8859-1'
    >>> res.content_type
    'text/html'
    >>> res.headers['content-type']
    'text/html; charset=iso-8859-1'

Cookie handling is done through methods:

    >>> res.set_cookie('test', 'value')
    >>> res.headers['set-cookie']
    'test=value; Path=/'
    >>> res.set_cookie('test2', 'value2', max_age=10000)
    >>> res.headers['set-cookie'] # We only see the last header
    'test2=value2; Max-Age=10000; Path=/'
    >>> res.headers.getall('set-cookie')
    ['test=value; Path=/', 'test2=value2; Max-Age=10000; Path=/']
    >>> res.unset_cookie('test')
    >>> res.headers.getall('set-cookie')
    ['test2=value2; Max-Age=10000; Path=/']

Most headers are available in a parsed getter/setter form through
properties:

    >>> res.age = 10
    >>> res.age, res.headers['age']
    (10, '10')
    >>> res.allow = ['GET', 'PUT']
    >>> res.allow, res.headers['allow']
    (['GET', 'PUT'], 'GET, PUT')
    >>> res.cache_control
    <CacheControl ''>
    >>> print res.cache_control.max_age
    None
    >>> res.cache_control.properties['max-age'] = None
    >>> print res.cache_control.max_age
    -1
    >>> res.cache_control.max_age = 10
    >>> res.cache_control
    <CacheControl 'max-age=10'>
    >>> res.headers['cache-control']
    'max-age=10'
    >>> res.cache_control.max_stale = 10
    Traceback (most recent call last):
        ...
    AttributeError: The property max-stale only applies to request Cache-Control
    >>> res.cache_control = {}
    >>> res.cache_control
    <CacheControl ''>
    >>> res.content_encoding = 'gzip'
    >>> (res.content_encoding, res.headers['content-encoding'])
    ('gzip', 'gzip')
    >>> res.content_language = 'en'
    >>> (res.content_language, res.headers['content-language'])
    (['en'], 'en')
    >>> res.content_location = 'http://localhost:8080'
    >>> res.headers['content-location']
    'http://localhost:8080'
    >>> res.content_range = (0, 100, 1000)
    >>> (res.content_range, res.headers['content-range'])
    (<ContentRange bytes 0-101/1000>, 'bytes 0-101/1000')
    >>> res.date = datetime(2005, 1, 1, 12, 0, tzinfo=UTC)
    >>> (res.date, res.headers['date'])
    (datetime.datetime(2005, 1, 1, 12, 0, tzinfo=UTC), 'Sat, 01 Jan 2005 12:00:00 GMT')
    >>> print res.etag
    None
    >>> res.etag = 'foo'
    >>> (res.etag, res.headers['etag'])
    ('foo', 'foo')
    >>> res.expires = res.date
    >>> res.retry_after = 120 # two minutes
    >>> res.retry_after
    datetime.datetime(...)
    >>> res.server = 'Python/foo'
    >>> res.headers['server']
    'Python/foo'
    >>> res.vary = ['Cookie']
    >>> (res.vary, res.headers['vary'])
    (['Cookie'], 'Cookie')

The location header will try to absolutify itself if you have a
request object attached.

    >>> res.location = '/test.html'
    >>> from webob import Request
    >>> res.request = Request.blank('/')
    >>> res.location
    'http://localhost/test.html'
    >>> res.request = None
    >>> res.location
    '/test.html'
    >>> res.request = Request.blank('/')
    >>> res.location = '/test2.html'
    >>> res.request = None
    >>> res.location
    'http://localhost/test2.html'

There's some conditional response handling too (you have to turn on
conditioanl_response)::

    >>> res = Response(conditional_response=True)
    >>> req = Request.blank('/')
    >>> res.etag = 'tag'
    >>> req.if_none_match = 'tag'
    >>> req.get_response(res)
    <Response ... 304 Not Modified>
    >>> res.etag = 'other-tag'
    >>> req.get_response(res)
    <Response ... 200 OK>
    >>> del req.if_none_match
    >>> req.if_modified_since = datetime(2005, 1, 1, 12, 1, tzinfo=UTC)
    >>> res.last_modified = datetime(2005, 1, 1, 12, 1, tzinfo=UTC)
    >>> req.get_response(res)
    <Response ... 304 Not Modified>
    >>> res.last_modified = datetime(2006, 1, 1, 12, 1, tzinfo=UTC)
    >>> req.get_response(res)
    <Response ... 200 OK>
    >>> res.last_modified = None
    >>> req.get_response(res)
    <Response ... 200 OK>

Also range response::

    >>> res = Response(conditional_response=True)
    >>> req = Request.blank('/')
    >>> res.body = '0123456789'
    >>> req.range = (1, 5)
    >>> result = req.get_response(res)
    >>> result.body
    '1234'
    >>> result.content_range
    <ContentRange bytes 1-6/10>
    >>> tuple(result.content_range)
    (1, 5, 10)
    >>> # Now an invalid range:
    >>> req.range = (0, 20)
    >>> str(req.range)
    'bytes=0-21'
    >>> result = req.get_response(res)
    >>> result.body
    '0123456789'
    >>> print result.content_range
    None

That was easier; we'll try it with a iterator for the body::

    >>> res = Response(conditional_response=True)
    >>> res.app_iter = ['01234', '567', '89']
    >>> req = Request.blank('/')
    >>> req.range = (1, 5)
    >>> result = req.get_response(res)
    >>> # Because we don't know the length of the app_iter, this
    >>> # doesn't work:
    >>> result.body
    '0123456789'
    >>> print result.content_range
    None
    >>> req.range = (5, None)
    >>> result = req.get_response(res)
    >>> result.body
    '56789'
    >>> result.content_range
    <ContentRange bytes 5-*/10>
    >>> # If we set Content-Length then we can use it with an app_iter
    >>> res.content_length = 10
    >>> req.range = (1, 5)
    >>> result = req.get_response(res)
    >>> result.body
    '1234'
    >>> result.content_range
    <ContentRange bytes 1-6/10>
    >>> # And trying If-modified-since
    >>> res.etag = 'foobar'
    >>> req.if_range = 'foobar'
    >>> req.if_range
    <IfRange etag=foobar, date=*>
    >>> result = req.get_response(res)
    >>> result.content_range
    <ContentRange bytes 1-6/10>
    >>> req.if_range = 'blah'
    >>> result = req.get_response(res)
    >>> result.content_range
    >>> req.if_range = datetime(2005, 1, 1, 12, 0, tzinfo=UTC)
    >>> res.last_modified = datetime(2005, 1, 1, 12, 0, tzinfo=UTC)
    >>> result = req.get_response(res)
    >>> result.content_range
    <ContentRange bytes 1-6/10>
    >>> res.last_modified = datetime(2006, 1, 1, 12, 0, tzinfo=UTC)
    >>> result = req.get_response(res)
    >>> result.content_range

Some tests of exceptions::

    >>> from webob import exc
    >>> res = exc.HTTPNotFound('Not found!')
    >>> res.exception.content_type = 'text/plain'
    >>> res.content_type
    'text/plain'
    >>> res = exc.HTTPNotModified()
    >>> res.headers
    HeaderDict([])