1from __future__ import absolute_import, unicode_literals
2
3import sys
4
5import pytest
6from case import Mock, skip
7
8from celery.five import PY3, long_t, python_2_unicode_compatible, string
9from celery.local import PromiseProxy, Proxy, maybe_evaluate, try_import
10
11
12class test_try_import:
13
14    def test_imports(self):
15        assert try_import(__name__)
16
17    def test_when_default(self):
18        default = object()
19        assert try_import('foobar.awqewqe.asdwqewq', default) is default
20
21
22class test_Proxy:
23
24    def test_std_class_attributes(self):
25        assert Proxy.__name__ == 'Proxy'
26        assert Proxy.__module__ == 'celery.local'
27        assert isinstance(Proxy.__doc__, str)
28
29    def test_doc(self):
30        def real():
31            pass
32        x = Proxy(real, __doc__='foo')
33        assert x.__doc__ == 'foo'
34
35    def test_name(self):
36
37        def real():
38            """real function"""
39            return 'REAL'
40
41        x = Proxy(lambda: real, name='xyz')
42        assert x.__name__ == 'xyz'
43
44        y = Proxy(lambda: real)
45        assert y.__name__ == 'real'
46
47        assert x.__doc__ == 'real function'
48
49        assert x.__class__ == type(real)
50        assert x.__dict__ == real.__dict__
51        assert repr(x) == repr(real)
52        assert x.__module__
53
54    def test_get_current_local(self):
55        x = Proxy(lambda: 10)
56        object.__setattr__(x, '_Proxy_local', Mock())
57        assert x._get_current_object()
58
59    def test_bool(self):
60
61        class X(object):
62
63            def __bool__(self):
64                return False
65            __nonzero__ = __bool__
66
67        x = Proxy(lambda: X())
68        assert not x
69
70    def test_slots(self):
71
72        class X(object):
73            __slots__ = ()
74
75        x = Proxy(X)
76        with pytest.raises(AttributeError):
77            x.__dict__
78
79    @skip.if_python3()
80    def test_unicode(self):
81
82        @python_2_unicode_compatible
83        class X(object):
84
85            def __unicode__(self):
86                return 'UNICODE'
87            __str__ = __unicode__
88
89            def __repr__(self):
90                return 'REPR'
91
92        x = Proxy(lambda: X())
93        assert string(x) == 'UNICODE'
94        del(X.__unicode__)
95        del(X.__str__)
96        assert string(x) == 'REPR'
97
98    def test_dir(self):
99
100        class X(object):
101
102            def __dir__(self):
103                return ['a', 'b', 'c']
104
105        x = Proxy(lambda: X())
106        assert dir(x) == ['a', 'b', 'c']
107
108        class Y(object):
109
110            def __dir__(self):
111                raise RuntimeError()
112        y = Proxy(lambda: Y())
113        assert dir(y) == []
114
115    def test_getsetdel_attr(self):
116
117        class X(object):
118            a = 1
119            b = 2
120            c = 3
121
122            def __dir__(self):
123                return ['a', 'b', 'c']
124
125        v = X()
126
127        x = Proxy(lambda: v)
128        assert x.__members__ == ['a', 'b', 'c']
129        assert x.a == 1
130        assert x.b == 2
131        assert x.c == 3
132
133        setattr(x, 'a', 10)
134        assert x.a == 10
135
136        del(x.a)
137        assert x.a == 1
138
139    def test_dictproxy(self):
140        v = {}
141        x = Proxy(lambda: v)
142        x['foo'] = 42
143        assert x['foo'] == 42
144        assert len(x) == 1
145        assert 'foo' in x
146        del(x['foo'])
147        with pytest.raises(KeyError):
148            x['foo']
149        assert iter(x)
150
151    def test_listproxy(self):
152        v = []
153        x = Proxy(lambda: v)
154        x.append(1)
155        x.extend([2, 3, 4])
156        assert x[0] == 1
157        assert x[:-1] == [1, 2, 3]
158        del(x[-1])
159        assert x[:-1] == [1, 2]
160        x[0] = 10
161        assert x[0] == 10
162        assert 10 in x
163        assert len(x) == 3
164        assert iter(x)
165        x[0:2] = [1, 2]
166        del(x[0:2])
167        assert str(x)
168        if sys.version_info[0] < 3:
169            assert x.__cmp__(object()) == -1
170
171    def test_complex_cast(self):
172
173        class O(object):
174
175            def __complex__(self):
176                return complex(10.333)
177
178        o = Proxy(O)
179        assert o.__complex__() == complex(10.333)
180
181    def test_index(self):
182
183        class O(object):
184
185            def __index__(self):
186                return 1
187
188        o = Proxy(O)
189        assert o.__index__() == 1
190
191    def test_coerce(self):
192
193        class O(object):
194
195            def __coerce__(self, other):
196                return self, other
197
198        o = Proxy(O)
199        assert o.__coerce__(3)
200
201    def test_int(self):
202        assert Proxy(lambda: 10) + 1 == Proxy(lambda: 11)
203        assert Proxy(lambda: 10) - 1 == Proxy(lambda: 9)
204        assert Proxy(lambda: 10) * 2 == Proxy(lambda: 20)
205        assert Proxy(lambda: 10) ** 2 == Proxy(lambda: 100)
206        assert Proxy(lambda: 20) / 2 == Proxy(lambda: 10)
207        assert Proxy(lambda: 20) // 2 == Proxy(lambda: 10)
208        assert Proxy(lambda: 11) % 2 == Proxy(lambda: 1)
209        assert Proxy(lambda: 10) << 2 == Proxy(lambda: 40)
210        assert Proxy(lambda: 10) >> 2 == Proxy(lambda: 2)
211        assert Proxy(lambda: 10) ^ 7 == Proxy(lambda: 13)
212        assert Proxy(lambda: 10) | 40 == Proxy(lambda: 42)
213        assert Proxy(lambda: 10) != Proxy(lambda: -11)
214        assert Proxy(lambda: 10) != Proxy(lambda: -10)
215        assert Proxy(lambda: -10) == Proxy(lambda: -10)
216
217        assert Proxy(lambda: 10) < Proxy(lambda: 20)
218        assert Proxy(lambda: 20) > Proxy(lambda: 10)
219        assert Proxy(lambda: 10) >= Proxy(lambda: 10)
220        assert Proxy(lambda: 10) <= Proxy(lambda: 10)
221        assert Proxy(lambda: 10) == Proxy(lambda: 10)
222        assert Proxy(lambda: 20) != Proxy(lambda: 10)
223        assert Proxy(lambda: 100).__divmod__(30)
224        assert Proxy(lambda: 100).__truediv__(30)
225        assert abs(Proxy(lambda: -100))
226
227        x = Proxy(lambda: 10)
228        x -= 1
229        assert x == 9
230        x = Proxy(lambda: 9)
231        x += 1
232        assert x == 10
233        x = Proxy(lambda: 10)
234        x *= 2
235        assert x == 20
236        x = Proxy(lambda: 20)
237        x /= 2
238        assert x == 10
239        x = Proxy(lambda: 10)
240        x %= 2
241        assert x == 0
242        x = Proxy(lambda: 10)
243        x <<= 3
244        assert x == 80
245        x = Proxy(lambda: 80)
246        x >>= 4
247        assert x == 5
248        x = Proxy(lambda: 5)
249        x ^= 1
250        assert x == 4
251        x = Proxy(lambda: 4)
252        x **= 4
253        assert x == 256
254        x = Proxy(lambda: 256)
255        x //= 2
256        assert x == 128
257        x = Proxy(lambda: 128)
258        x |= 2
259        assert x == 130
260        x = Proxy(lambda: 130)
261        x &= 10
262        assert x == 2
263
264        x = Proxy(lambda: 10)
265        assert type(x.__float__()) == float
266        assert type(x.__int__()) == int
267        if not PY3:
268            assert type(x.__long__()) == long_t
269        assert hex(x)
270        assert oct(x)
271
272    def test_hash(self):
273
274        class X(object):
275
276            def __hash__(self):
277                return 1234
278
279        assert hash(Proxy(lambda: X())) == 1234
280
281    def test_call(self):
282
283        class X(object):
284
285            def __call__(self):
286                return 1234
287
288        assert Proxy(lambda: X())() == 1234
289
290    def test_context(self):
291
292        class X(object):
293            entered = exited = False
294
295            def __enter__(self):
296                self.entered = True
297                return 1234
298
299            def __exit__(self, *exc_info):
300                self.exited = True
301
302        v = X()
303        x = Proxy(lambda: v)
304        with x as val:
305            assert val == 1234
306        assert x.entered
307        assert x.exited
308
309    def test_reduce(self):
310
311        class X(object):
312
313            def __reduce__(self):
314                return 123
315
316        x = Proxy(lambda: X())
317        assert x.__reduce__() == 123
318
319
320class test_PromiseProxy:
321
322    def test_only_evaluated_once(self):
323
324        class X(object):
325            attr = 123
326            evals = 0
327
328            def __init__(self):
329                self.__class__.evals += 1
330
331        p = PromiseProxy(X)
332        assert p.attr == 123
333        assert p.attr == 123
334        assert X.evals == 1
335
336    def test_callbacks(self):
337        source = Mock(name='source')
338        p = PromiseProxy(source)
339        cbA = Mock(name='cbA')
340        cbB = Mock(name='cbB')
341        cbC = Mock(name='cbC')
342        p.__then__(cbA, p)
343        p.__then__(cbB, p)
344        assert not p.__evaluated__()
345        assert object.__getattribute__(p, '__pending__')
346
347        assert repr(p)
348        assert p.__evaluated__()
349        with pytest.raises(AttributeError):
350            object.__getattribute__(p, '__pending__')
351        cbA.assert_called_with(p)
352        cbB.assert_called_with(p)
353
354        assert p.__evaluated__()
355        p.__then__(cbC, p)
356        cbC.assert_called_with(p)
357
358        with pytest.raises(AttributeError):
359            object.__getattribute__(p, '__pending__')
360
361    def test_maybe_evaluate(self):
362        x = PromiseProxy(lambda: 30)
363        assert not x.__evaluated__()
364        assert maybe_evaluate(x) == 30
365        assert maybe_evaluate(x) == 30
366
367        assert maybe_evaluate(30) == 30
368        assert x.__evaluated__()
369