************
Hosted files
************

The Launchpad web service sets restrictions on what kinds of documents
can be written to a particular file. This test shows what happens when
you try to upload a non-image for a field that expects an image.

    >>> from launchpadlib.testing.helpers import salgado_with_full_permissions
    >>> launchpad = salgado_with_full_permissions.login()
    >>> from launchpadlib.errors import HTTPError

    >>> mugshot = launchpad.me.mugshot
    >>> file_handle = mugshot.open("w", "image/png", "nonimage.txt")
    >>> file_handle.content_type
    'image/png'
    >>> file_handle.filename
    'nonimage.txt'
    >>> file_handle.write(b"Not an image.")
    >>> try:
    ...     file_handle.close()
    ... except HTTPError as e:
    ...     print(e.content.decode())
    <BLANKLINE>
    The file uploaded was not recognized as an image; please
    check it and retry.

Of course, uploading an image works fine.

    >>> import os
    >>> def load_image(filename):
    ...     image_file = os.path.join(
    ...         os.path.dirname(__file__), 'files', filename)
    ...     with open(image_file, "rb") as f:
    ...         return f.read()
    >>> image = load_image("mugshot.png")
    >>> len(image)
    2260

    >>> file_handle = mugshot.open("w", "image/png", "a-mugshot.png")
    >>> file_handle.write(image)
    >>> file_handle.close()


== Error handling ==

The server may set restrictions on what kinds of documents can be
written to a particular file.

    >>> file_handle = mugshot.open("w", "image/png", "nonimage.txt")
    >>> file_handle.content_type
    'image/png'
    >>> file_handle.filename
    'nonimage.txt'
    >>> file_handle.write(b"Not an image.")
    >>> file_handle.close()
    Traceback (most recent call last):
    ...
    lazr.restfulclient.errors.BadRequest: HTTP Error 400: Bad Request
    ...

== Caching ==

Hosted file resources implement the normal server-side caching
mechanism.

    >>> file_handle = mugshot.open("w", "image/png", "image.png")
    >>> file_handle.write(image)
    >>> file_handle.close()

    >>> import httplib2
    >>> httplib2.debuglevel = 1
    >>> launchpad = salgado_with_full_permissions.login()
    send: ...
    >>> mugshot = launchpad.me.mugshot
    send: ...

The first request for a file retrieves the file from the server.

    >>> len(mugshot.open().read())
    send: ...
    reply: 'HTTP/1.1 303 See Other...
    reply: 'HTTP/1.1 200 OK...
    2260

The second request retrieves the file from the cache. After receiving
the 303 request with its Location header, no further HTTP requests are
issued because the Librarian's Cache-Control: headers tell us we
already have a fresh copy.

    >>> len(mugshot.open().read())
    send: ...
    reply: 'HTTP/1.1 303 See Other...
    header: Location...
    2260

Finally, some cleanup code that deletes the mugshot.

    >>> mugshot.delete()
    send: b'DELETE...
    reply: 'HTTP/1.1 200...

    >>> httplib2.debuglevel = 0
