File: calls.py

package info (click to toggle)
python-kgb 7.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 532 kB
  • sloc: python: 4,466; makefile: 3
file content (132 lines) | stat: -rw-r--r-- 4,304 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
"""Call tracking and checks for spiess."""

from __future__ import unicode_literals

from kgb.pycompat import iteritems, text_type
from kgb.signature import FunctionSig
from kgb.utils import format_spy_kwargs


class SpyCall(object):
    """Records arguments made to a spied function call.

    SpyCalls are created and stored by a FunctionSpy every time it is
    called. They're accessible through the FunctionSpy's ``calls`` attribute.
    """

    def __init__(self, spy, args, kwargs):
        """Initialize the call.

        Args:
            spy (kgb.spies.FunctionSpy):
                The function spy that the call was made on.

            args (tuple):
                A tuple of positional arguments from the spy. These correspond
                to positional arguments in the function's signature.

            kwargs (dict):
                A dictionary of keyword arguments from the spy. These
                correspond to keyword arguments in the function's signature.
        """
        self.spy = spy
        self.args = args
        self.kwargs = kwargs
        self.return_value = None
        self.exception = None

    def called_with(self, *args, **kwargs):
        """Return whether this call was made with the given arguments.

        Not every argument and keyword argument made in the call must be
        provided to this method. These can be a subset of the positional and
        keyword arguments in the call, but cannot contain any arguments not
        made in the call.

        Args:
            *args (tuple):
                The positional arguments made in the call, or a subset of
                those arguments (starting with the first argument).

            **kwargs (dict):
                The keyword arguments made in the call, or a subset of those
                arguments.

        Returns:
            bool:
            ``True`` if the call's arguments match the provided arguments.
            ``False`` if they do not.
        """
        if len(args) > len(self.args):
            return False

        if self.args[:len(args)] != args:
            return False

        pos_args = self.spy._sig.arg_names

        if self.spy.func_type in (FunctionSig.TYPE_BOUND_METHOD,
                                  FunctionSig.TYPE_UNBOUND_METHOD):
            pos_args = pos_args[1:]

        all_args = dict(zip(pos_args, self.args))
        all_args.update(self.kwargs)

        for key, value in iteritems(kwargs):
            if key not in all_args or all_args[key] != value:
                return False

        return True

    def returned(self, value):
        """Return whether this call returned the given value.

        Args:
            value (object):
                The expected returned value from the call.

        Returns:
            bool:
            ``True`` if this call returned the given value. ``False`` if it
            did not.
        """
        return self.return_value == value

    def raised(self, exception_cls):
        """Return whether this call raised this exception.

        Args:
            exception_cls (type):
                The expected type of exception raised by the call.

        Returns:
            bool:
            ``True`` if this call raised the given exception type.
            ``False`` if it did not.
        """
        return ((self.exception is None and exception_cls is None) or
                type(self.exception) is exception_cls)

    def raised_with_message(self, exception_cls, message):
        """Return whether this call raised this exception and message.

        Args:
            exception_cls (type):
                The expected type of exception raised by the call.

            message (unicode):
                The expected message from the exception.

        Returns:
            bool:
            ``True`` if this call raised the given exception type and message.
            ``False`` if it did not.
        """
        return (self.exception is not None and
                self.raised(exception_cls) and
                text_type(self.exception) == message)

    def __repr__(self):
        return '<SpyCall(args=%r, kwargs=%s, returned=%r, raised=%r)>' % (
            self.args, format_spy_kwargs(self.kwargs), self.return_value,
            self.exception)