aboutsummaryrefslogtreecommitdiff
blob: eff21467efe818024a41cd61be37fd15a1accaef (plain)
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
import pytest
from snakeoil import currying


def passthrough(*args, **kwargs):
    return args, kwargs


# docstring is part of the test


def documented():
    """original docstring"""


class TestPreCurry:
    pre_curry = staticmethod(currying.pre_curry)

    def test_pre_curry(self):
        noop = self.pre_curry(passthrough)
        assert noop() == ((), {})
        assert noop("foo", "bar") == (("foo", "bar"), {})
        assert noop(foo="bar") == ((), {"foo": "bar"})
        assert noop("foo", bar="baz") == (("foo",), {"bar": "baz"})

        one_arg = self.pre_curry(passthrough, 42)
        assert one_arg() == ((42,), {})
        assert one_arg("foo", "bar") == ((42, "foo", "bar"), {})
        assert one_arg(foo="bar") == ((42,), {"foo": "bar"})
        assert one_arg("foo", bar="baz") == ((42, "foo"), {"bar": "baz"})

        keyword_arg = self.pre_curry(passthrough, foo=42)
        assert keyword_arg() == ((), {"foo": 42})
        assert keyword_arg("foo", "bar") == (("foo", "bar"), {"foo": 42})
        assert keyword_arg(foo="bar") == ((), {"foo": "bar"})
        assert keyword_arg("foo", bar="baz") == (("foo",), {"bar": "baz", "foo": 42})

        both = self.pre_curry(passthrough, 42, foo=42)
        assert both() == ((42,), {"foo": 42})
        assert both("foo", "bar") == ((42, "foo", "bar"), {"foo": 42})
        assert both(foo="bar") == ((42,), {"foo": "bar"})
        assert both("foo", bar="baz") == ((42, "foo"), {"bar": "baz", "foo": 42})

    def test_curry_original(self):
        assert self.pre_curry(passthrough).func is passthrough

    def test_instancemethod(self):
        class Test:
            method = self.pre_curry(passthrough, "test")

        test = Test()
        assert (("test", test), {}) == test.method()


class Test_pretty_docs:
    currying_targets = (currying.pre_curry, currying.post_curry)

    def test_module_magic(self):
        for target in self.currying_targets:
            assert (
                currying.pretty_docs(target(passthrough)).__module__
                is passthrough.__module__
            )
            # test is kinda useless if they are identical without pretty_docs
            assert (
                getattr(target(passthrough), "__module__", None)
                is not passthrough.__module__
            )

    def test_pretty_docs(self):
        for target in self.currying_targets:
            for func in (passthrough, documented):
                assert (
                    currying.pretty_docs(target(func), "new doc").__doc__ == "new doc"
                )
                assert currying.pretty_docs(target(func)).__doc__ is func.__doc__


class TestPostCurry:
    def test_post_curry(self):
        noop = currying.post_curry(passthrough)
        assert noop() == ((), {})
        assert noop("foo", "bar") == (("foo", "bar"), {})
        assert noop(foo="bar") == ((), {"foo": "bar"})
        assert noop("foo", bar="baz") == (("foo",), {"bar": "baz"})

        one_arg = currying.post_curry(passthrough, 42)
        assert one_arg() == ((42,), {})
        assert one_arg("foo", "bar") == (("foo", "bar", 42), {})
        assert one_arg(foo="bar") == ((42,), {"foo": "bar"})
        assert one_arg("foo", bar="baz") == (("foo", 42), {"bar": "baz"})

        keyword_arg = currying.post_curry(passthrough, foo=42)
        assert keyword_arg() == ((), {"foo": 42})
        assert keyword_arg("foo", "bar") == (("foo", "bar"), {"foo": 42})
        assert keyword_arg(foo="bar") == ((), {"foo": 42})
        assert keyword_arg("foo", bar="baz") == (("foo",), {"bar": "baz", "foo": 42})

        both = currying.post_curry(passthrough, 42, foo=42)
        assert both() == ((42,), {"foo": 42})
        assert both("foo", "bar") == (("foo", "bar", 42), {"foo": 42})
        assert both(foo="bar") == ((42,), {"foo": 42})
        assert both("foo", bar="baz") == (("foo", 42), {"bar": "baz", "foo": 42})

    def test_curry_original(self):
        assert currying.post_curry(passthrough).func is passthrough

    def test_instancemethod(self):
        class Test:
            method = currying.post_curry(passthrough, "test")

        test = Test()
        assert ((test, "test"), {}) == test.method()


class Test_wrap_exception:
    def test_wrap_exception_complex(self):
        inner, outer = [], []

        inner_exception = ValueError
        wrapping_exception = IndexError

        def f(exception, functor, fargs, fkwds):
            assert isinstance(exception, inner_exception)
            assert functor is throwing_func
            assert fargs == (False,)
            assert fkwds == {"monkey": "bone"}
            outer.append(True)
            raise wrapping_exception()

        def throwing_func(*args, **kwds):
            assert args == (False,)
            assert kwds == {"monkey": "bone"}
            inner.append(True)
            raise inner_exception()

        func = currying.wrap_exception_complex(f, IndexError)(throwing_func)

        # basic behaviour
        pytest.raises(IndexError, func, False, monkey="bone")
        assert len(inner) == 1
        assert len(outer) == 1

        # ensure pass thru if it's an allowed exception
        inner_exception = IndexError
        pytest.raises(IndexError, func, False, monkey="bone")
        assert len(inner) == 2
        assert len(outer) == 1

        # finally, ensure it doesn't intercept, and passes thru for
        # exceptions it shouldn't handle
        inner_exception = MemoryError
        pytest.raises(MemoryError, func, False, monkey="bone")
        assert len(inner) == 3
        assert len(outer) == 1

    def test_wrap_exception(self):
        throw_kls = ValueError

        def throwing_func(*args, **kwds):
            raise throw_kls()

        class my_exception(Exception):
            def __init__(self, *args, **kwds):
                self.args = args
                self.kwds = kwds

        func = currying.wrap_exception(
            my_exception, 1, 3, 2, monkey="bone", ignores=ValueError
        )(throwing_func)
        assert func.__name__ == "throwing_func"
        pytest.raises(ValueError, func)
        throw_kls = IndexError
        pytest.raises(my_exception, func)
        try:
            func()
            raise AssertionError("shouldn't have been able to reach here")
        except my_exception as e:
            assert e.args == (1, 3, 2)
            assert e.kwds == {"monkey": "bone"}

        # finally, verify that the exception can be pased in.
        func = currying.wrap_exception(
            my_exception,
            1,
            3,
            2,
            monkey="bone",
            ignores=ValueError,
            pass_error="the_exception",
        )(throwing_func)
        assert func.__name__ == "throwing_func"
        pytest.raises(my_exception, func)
        try:
            func()
            raise AssertionError("shouldn't have been able to reach here")
        except my_exception as e:
            assert e.args == (1, 3, 2)
            assert e.kwds == {"monkey": "bone", "the_exception": e.__cause__}