~rvb/maas/dj-migrations

« back to all changes in this revision

Viewing changes to src/maastesting/djangoclient.py

  • Committer: Raphael Badin
  • Date: 2015-03-13 15:22:22 UTC
  • mfrom: (3631.1.15 maas)
  • Revision ID: raphael.badin@canonical.com-20150313152222-nhq1vs6hop1ooq7e
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright 2015 Canonical Ltd.  This software is licensed under the
 
2
# GNU Affero General Public License version 3 (see the file LICENSE).
 
3
 
 
4
"""Django client with sensible handling of data."""
 
5
 
 
6
from __future__ import (
 
7
    absolute_import,
 
8
    print_function,
 
9
    unicode_literals,
 
10
    )
 
11
 
 
12
str = None
 
13
 
 
14
__metaclass__ = type
 
15
__all__ = [
 
16
    'SensibleClient',
 
17
    ]
 
18
 
 
19
from functools import wraps
 
20
 
 
21
from django.test import client
 
22
 
 
23
 
 
24
def transparent_encode_multipart(func):
 
25
    """Wrap an HTTP client method, transparently encoding multipart data.
 
26
 
 
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.
 
31
 
 
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
 
34
    encoding.
 
35
    """
 
36
    @wraps(func)
 
37
    def maybe_encode_multipart(
 
38
            self, path, data=b"", content_type=None, **extra):
 
39
 
 
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)
 
46
        else:
 
47
            raise TypeError(
 
48
                "Cannot combine data (%r) with content-type (%r)."
 
49
                % (data, content_type))
 
50
 
 
51
        return func(self, path, data, content_type, **extra)
 
52
 
 
53
    return maybe_encode_multipart
 
54
 
 
55
 
 
56
class SensibleClient(client.Client):
 
57
    """A Django test client that transparently encodes multipart data."""
 
58
 
 
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)