The read_complete flag lets us know if all of the wrapped file's data
has been read.  We want to know this because Browser.back() must
.reload() the response if not.

I've noted here the various cases where .read_complete may be set.

>>> text = "To err is human, to moo, bovine.\n"*10
>>> def get_wrapper():
...     import cStringIO
...     from mechanize._response import seek_wrapper
...     f = cStringIO.StringIO(text)
...     wr = seek_wrapper(f)
...     return wr

.read() case #1

>>> wr = get_wrapper()
>>> wr.read_complete
False
>>> junk = wr.read()
>>> wr.read_complete
True
>>> wr.seek(0)
>>> wr.read_complete
True

Excercise partial .read() and .readline(), and .seek() case #1

>>> wr = get_wrapper()
>>> junk = wr.read(10)
>>> wr.read_complete
False
>>> junk = wr.readline()
>>> wr.read_complete
False
>>> wr.seek(0, 2)
>>> wr.read_complete
True
>>> wr.seek(0)
>>> wr.read_complete
True

.readlines() case #1

>>> wr = get_wrapper()
>>> junk = wr.readlines()
>>> wr.read_complete
True
>>> wr.seek(0)
>>> wr.read_complete
True

.seek() case #2

>>> wr = get_wrapper()
>>> wr.seek(10)
>>> wr.read_complete
False
>>> wr.seek(1000000)

.read() case #2

>>> wr = get_wrapper()
>>> junk = wr.read(1000000)
>>> wr.read_complete  # we read to the end, but don't know it yet
False
>>> junk = wr.read(10)
>>> wr.read_complete
True

.readline() case #1

>>> wr = get_wrapper()
>>> junk = wr.read(len(text)-10)
>>> wr.read_complete
False
>>> junk = wr.readline()
>>> wr.read_complete  # we read to the end, but don't know it yet
False
>>> junk = wr.readline()
>>> wr.read_complete
True

Test copying and sharing of .read_complete state

>>> import copy
>>> wr = get_wrapper()
>>> wr2 = copy.copy(wr)
>>> wr.read_complete
False
>>> wr2.read_complete
False
>>> junk = wr2.read()
>>> wr.read_complete
True
>>> wr2.read_complete
True


Fix from -r36082: .read() after .close() used to break
.read_complete state

>>> from mechanize._response import test_response
>>> r = test_response(text)
>>> junk = r.read(64)
>>> r.close()
>>> r.read_complete
False
>>> r.read()
''
>>> r.read_complete
False



Tests for the truly horrendous upgrade_response()

>>> def is_response(r):
...     names = "get_data read readline readlines close seek code msg".split()
...     for name in names:
...         if not hasattr(r, name):
...             return False
...     return r.get_data() == "test data"

>>> from cStringIO import StringIO
>>> from mechanize._response import upgrade_response, make_headers, \
...     make_response, closeable_response, seek_wrapper
>>> data="test data"; url="http://example.com/"; code=200; msg="OK"

Normal response (closeable_response wrapped with seek_wrapper): return a copy

>>> r1 = make_response(data, [], url, code, msg)
>>> r2 = upgrade_response(r1)
>>> is_response(r2)
True
>>> r1 is not r2
True
>>> r1.wrapped is r2.wrapped
True

closeable_response with no seek_wrapper: wrap with seek_wrapper

>>> r1 = closeable_response(StringIO(data), make_headers([]), url, code, msg)
>>> is_response(r1)
False
>>> r2 = upgrade_response(r1)
>>> is_response(r2)
True
>>> r1 is not r2
True
>>> r1 is r2.wrapped
True

urllib2.addinfourl: extract .fp and wrap it with closeable_response
and seek_wrapper

>>> import urllib2
>>> r1= urllib2.addinfourl(StringIO(data), make_headers([]), url)
>>> is_response(r1)
False
>>> r2 = upgrade_response(r1)
>>> is_response(r2)
True
>>> r1 is not r2
True
>>> r1 is not r2.wrapped
True
>>> r1.fp is r2.wrapped.fp
True

addinfourl with code, msg

>>> r1= urllib2.addinfourl(StringIO(data), make_headers([]), url)
>>> r1.code = 206
>>> r1.msg = "cool"
>>> r2 = upgrade_response(r1)
>>> is_response(r2)
True
>>> r2.code == r1.code
True
>>> r2.msg == r1.msg
True

addinfourl with seek wrapper: cached data is not lost

>>> r1= urllib2.addinfourl(StringIO(data), make_headers([]), url)
>>> r1 = seek_wrapper(r1)
>>> r1.read(4)
'test'
>>> r2 = upgrade_response(r1)
>>> is_response(r2)
True

addinfourl wrapped with HTTPError -- remains an HTTPError of the same
subclass (through horrible trickery)

>>> hdrs = make_headers([])
>>> r1 = urllib2.addinfourl(StringIO(data), hdrs, url)
>>> class MyHTTPError(urllib2.HTTPError): pass
>>> r1 = MyHTTPError(url, code, msg, hdrs, r1)
>>> is_response(r1)
False
>>> r2 = upgrade_response(r1)
>>> is_response(r2)
True
>>> isinstance(r2, MyHTTPError)
True
>>> r2  # doctest: +ELLIPSIS
<httperror_seek_wrapper (MyHTTPError instance) at ...

The trickery does not cause double-wrapping

>>> r3 = upgrade_response(r2)
>>> is_response(r3)
True
>>> r3 is not r2
True
>>> r3.wrapped is r2.wrapped
True

Test dynamically-created class __repr__ for case where we have the
module name

>>> r4 = urllib2.addinfourl(StringIO(data), hdrs, url)
>>> r4 = urllib2.HTTPError(url, code, msg, hdrs, r4)
>>> upgrade_response(r4)  # doctest: +ELLIPSIS
<httperror_seek_wrapper (urllib2.HTTPError instance) at ...
