def test_return_type_specified_imperative(self): m = Mock() class T1(object): pass class T2(object): pass t = T1() def job1(): m.job1() return t @requires(T2) def job2(obj): m.job2(obj) runner = Runner() runner.add(job1, returns=returns(T2)) runner.add(job2, requires(T2)) runner() compare([ call.job1(), call.job2(t), ], m.mock_calls)
def test_returns_sequence(self): def foo(): return 1, 2 context = Context() result = context.call(foo, nothing, returns('foo', 'bar')) compare(result, (1, 2)) compare({'foo': 1, 'bar': 2}, context)
def test_returns_list(self): m = Mock() class T1(object): pass class T2(object): pass t1 = T1() t2 = T2() def job1(): m.job1() return [t1, t2] @requires(obj1=T1, obj2=T2) def job2(obj1, obj2): m.job2(obj1, obj2) runner = Runner() runner.add(job1, returns=returns(T1, T2)) runner.add(job2) runner() compare([ call.job1(), call.job2(t1, t2), ], m.mock_calls)
def test_supplied_explicitly(self): obj = object() rq = requires('foo') rt = returns('bar') result = CallPoint(obj, rq, rt)(self.context) compare(result, self.context.extract.return_value) self.context.extract.assert_called_with(obj, rq, rt)
def test_replace_for_behaviour(self): m = Mock() class T1(object): pass class T2(object): pass class T3(object): pass class T4(object): pass t2 = T2() def job0(): return t2 @requires(T1) @returns(T3) def job1(obj): raise Exception() # pragma: nocover job2 = requires(T4)(m.job2) runner = Runner(job0, job1, job2) runner.replace(job1, requires(T2)(returns(T4)(m.job1))) runner() compare([ call.job1(t2), call.job2(m.job1.return_value), ], actual=m.mock_calls)
def test_repr_maximal(self): def foo(): pass point = CallPoint(foo, requires('foo'), returns('bar')) point.labels.add('baz') point.labels.add('bob') compare(repr(foo)+" requires('foo') returns('bar') <-- baz, bob", repr(point))
def test_returns_single(self): def foo(): return 'bar' context = Context() result = context.extract(foo, nothing, returns(TheType)) compare(result, 'bar') compare({TheType: 'bar'}, context)
def test_returns_sequence(self): def foo(): return 1, 2 context = Context() result = context.extract(foo, nothing, returns('foo', 'bar')) compare(result, (1, 2)) compare({'foo': 1, 'bar': 2}, context)
def test_supplied_explicitly(self): obj = object() rq = requires('foo') rt = returns('bar') result = CallPoint(obj, rq, rt)(self.context) compare(result, self.context.call.return_value) self.context.call.assert_called_with(obj, rq, rt)
def test_decorator_trumps_annotations(self): @requires('foo') @returns('bar') def foo(a: 'x') -> 'y': pass check_extract(foo, expected_rq=requires('foo'), expected_rt=returns('bar'))
def test_returns_single(self): def foo(): return 'bar' context = Context() result = context.call(foo, nothing, returns(TheType)) compare(result, 'bar') compare({TheType: 'bar'}, context)
def test_ignore_return(self): def foo(): return 'bar' context = Context() result = context.call(foo, nothing, returns()) compare(result, 'bar') compare({}, context)
def test_explicit_trumps_decorators(self): @requires('foo') @returns('bar') def foo(): pass rq = requires('baz') rt = returns('bob') result = CallPoint(foo, requires=rq, returns=rt)(self.context) compare(result, self.context.call.return_value) self.context.call.assert_called_with(foo, rq, rt)
def test_extract_from_decorations(self): rq = requires('foo') rt = returns('bar') @rq @rt def foo(): pass result = CallPoint(foo)(self.context) compare(result, self.context.extract.return_value) self.context.extract.assert_called_with(foo, rq, rt)
def test_extract_from_decorations(self): rq = requires('foo') rt = returns('bar') @rq @rt def foo(): pass result = CallPoint(foo)(self.context) compare(result, self.context.call.return_value) self.context.call.assert_called_with(foo, rq, rt)
def test_explicit_trumps_decorators(self): @requires('foo') @returns('bar') def foo(): pass rq = requires('baz') rt = returns('bob') result = CallPoint(foo, requires=rq, returns=rt)(self.context) compare(result, self.context.extract.return_value) self.context.extract.assert_called_with(foo, rq, rt)
def test_missing_from_context_with_chain(self): class T(object): pass def job1(): pass def job2(): pass @requires(T) def job3(arg): pass # pragma: nocover def job4(): pass def job5(): pass runner = Runner() runner.add(job1, label='1') runner.add(job2) runner.add(job3) runner.add(job4, label='4') runner.add(job5, requires('foo', bar='baz'), returns('bob')) with ShouldRaise(ContextError) as s: runner() text = '\n'.join(( '', '', 'Already called:', repr(job1) + ' requires() returns_result_type() <-- 1', repr(job2) + ' requires() returns_result_type()', '', 'While calling: ' + repr(job3) + ' requires(T) returns_result_type()', 'with <Context: {}>:', '', 'No ' + repr(T) + ' in context', '', 'Still to call:', repr(job4) + ' requires() returns_result_type() <-- 4', repr(job5) + " requires('foo', bar='baz') returns('bob')", )) compare(text, repr(s.raised)) compare(text, str(s.raised))
def test_repr(self): class T1: pass class T2: pass m = Mock() runner = Runner() runner.add(m.job1, label='label1') runner.add(m.job2, requires('foo', T1), returns(T2), label='label2') runner.add(m.job3) compare('\n'.join(( '<Runner>', ' '+repr(m.job1)+' requires() returns_result_type() <-- label1', ' '+repr(m.job2)+" requires('foo', T1) returns(T2) <-- label2", ' '+repr(m.job3)+' requires() returns_result_type()', '</Runner>' )), repr(runner))
def test_extract_from_decorated_class(self, mock): class Wrapper(object): def __init__(self, func): self.func = func def __call__(self): return 'the '+self.func() def my_dec(func): return update_wrapper(Wrapper(func), func) @my_dec def foo(a: 'foo'=None) -> 'bar': return 'answer' compare(foo(), expected='the answer') check_extract(foo, expected_rq=requires(a='foo'), expected_rt=returns('bar'))
def test_missing_from_context_with_chain(self): class T(object): pass def job1(): pass def job2(): pass @requires(T) def job3(arg): pass # pragma: nocover def job4(): pass def job5(): pass runner = Runner() runner.add(job1, label='1') runner.add(job2) runner.add(job3) runner.add(job4, label='4') runner.add(job5, requires('foo', bar='baz'), returns('bob')) with ShouldRaise(ContextError) as s: runner() text = '\n'.join(( '', '', 'Already called:', repr(job1)+' requires() returns_result_type() <-- 1', repr(job2)+' requires() returns_result_type()', '', 'While calling: '+repr(job3)+' requires(T) returns_result_type()', 'with <Context: {}>:', '', 'No '+repr(T)+' in context', '', 'Still to call:', repr(job4)+' requires() returns_result_type() <-- 4', repr(job5)+" requires('foo', bar='baz') returns('bob')", )) compare(text, repr(s.raised)) compare(text, str(s.raised))
def test_extract_from_decorated_class(self): rq = requires('foo') rt = returns('bar') class Wrapper(object): def __init__(self, func): self.func = func def __call__(self): return 'the '+self.func() def my_dec(func): return update_wrapper(Wrapper(func), func) @my_dec @rq @rt def foo(): return 'answer' self.context.extract.side_effect = lambda func, rq, rt: (func(), rq, rt) result = CallPoint(foo)(self.context) compare(result, expected=('the answer', rq, rt))
def test_extract_from_decorated_class(self): rq = requires('foo') rt = returns('bar') class Wrapper(object): def __init__(self, func): self.func = func def __call__(self): return 'the '+self.func() def my_dec(func): return update_wrapper(Wrapper(func), func) @my_dec @rq @rt def foo(): return 'answer' self.context.call.side_effect = lambda func, rq, rt: (func(), rq, rt) result = CallPoint(foo)(self.context) compare(result, expected=('the answer', rq, rt))
def test_type(self): r = returns(Type1) compare(repr(r), 'returns(Type1)') compare(dict(r.process('foo')), {Type1: 'foo'})
def test_clone(self): m = Mock() class T1(object): pass class T2(object): pass def f1(): m.f1() def n1(): m.n1() return T1(), T2() def l1(): m.l1() def t1(obj): m.t1() def t2(obj): m.t2() # original runner1 = Runner() runner1.add(f1, label='first') runner1.add(n1, returns=returns(T1, T2), label='normal') runner1.add(l1, label='last') runner1.add(t1, requires(T1)) runner1.add(t2, requires(T2)) # now clone and add bits def f2(): m.f2() def n2(): m.n2() def l2(): m.l2() def tn(obj): m.tn() runner2 = runner1.clone() runner2['first'].add(f2) runner2['normal'].add(n2) runner2['last'].add(l2) # make sure types stay in order runner2.add(tn, requires(T2)) # now run both, and make sure we only get what we should runner1() verify(runner1, (f1, {'first'}), (n1, {'normal'}), (l1, {'last'}), (t1, set()), (t2, set()), ) compare([ call.f1(), call.n1(), call.l1(), call.t1(), call.t2(), ], m.mock_calls) m.reset_mock() runner2() verify(runner2, (f1, set()), (f2, {'first'}), (n1, set()), (n2, {'normal'}), (l1, set()), (l2, {'last'}), (t1, set()), (t2, set()), (tn, set()), ) compare([ call.f1(), call.f2(), call.n1(), call.n2(), call.l1(), call.l2(), call.t1(), call.t2(), call.tn() ], m.mock_calls)
def test_extract_from_annotations(self): def foo(a: 'foo', b, c: 'bar' = 1, d=2) -> 'bar': pass check_extract(foo, expected_rq=requires(a='foo', c='bar'), expected_rt=returns('bar'))
def test_string(self): r = returns('bar') compare(repr(r), "returns('bar')") compare(dict(r.process('foo')), {'bar': 'foo'})
def test_sequence(self): r = returns(Type1, 'bar') compare(repr(r), "returns(Type1, 'bar')") compare(dict(r.process(('foo', 'baz'))), {Type1: 'foo', 'bar': 'baz'})
def test_returns_only(self): def foo() -> 'bar': pass check_extract(foo, expected_rq=None, expected_rt=returns('bar'))