1
# Copyright 2015 Canonical Ltd. This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
4
"""Django client with sensible handling of data."""
6
from __future__ import (
19
from functools import wraps
21
from django.test import client
24
def transparent_encode_multipart(func):
25
"""Wrap an HTTP client method, transparently encoding multipart data.
27
This wraps Django's `Client` HTTP verb methods -- put, get, etc. -- in a
28
way that's both convenient and compatible across Django versions. It
29
augments those methods to accept a dict of data to be sent as part of the
30
request body, in MIME multipart encoding.
32
Since Django 1.5, these HTTP verb methods require data in the form of a
33
byte string. The application (that's us) need to take care of MIME
37
def maybe_encode_multipart(
38
self, path, data=b"", content_type=None, **extra):
40
if isinstance(data, bytes):
41
if content_type is None:
42
content_type = 'application/octet-stream'
43
elif content_type is None:
44
content_type = client.MULTIPART_CONTENT
45
data = client.encode_multipart(client.BOUNDARY, data)
48
"Cannot combine data (%r) with content-type (%r)."
49
% (data, content_type))
51
return func(self, path, data, content_type, **extra)
53
return maybe_encode_multipart
56
class SensibleClient(client.Client):
57
"""A Django test client that transparently encodes multipart data."""
59
# get(), post(), and head() handle their own payload-encoding and accept
60
# dicts as `data`, so they're not wrapped. The following all accept
61
# byte-strings as `data` so they are transparently wrapped.
62
delete = transparent_encode_multipart(client.Client.delete)
63
options = transparent_encode_multipart(client.Client.options)
64
patch = transparent_encode_multipart(client.Client.patch)
65
put = transparent_encode_multipart(client.Client.put)