def test_append(self): m = Mock() runner = Runner() runner.add(m.job1, label='one') class MyPlug(Plug): @append() def run_plug(self): m.do_it() plug = MyPlug() plug.add_to(runner) runner() compare([ call.job1(), call.do_it() ], actual=m.mock_calls) verify(runner, (m.job1, {'one'}), (plug.run_plug, set()), )
def test_explict(self): m = Mock() runner = Runner() runner.add(m.job1, label='one') class MyPlug(Plug): explicit = True def helper(self): m.plug_one() @insert() def one(self): self.helper() plug = MyPlug() plug.add_to(runner) runner() compare([ call.job1(), call.plug_one() ], actual=m.mock_calls) verify(runner, (m.job1, set()), (plug.one, {'one'}), )
def test_ignore(self): m = Mock() runner = Runner() runner.add(m.job1, label='one') class MyPlug(Plug): @ignore() def helper(self): # pragma: no cover m.plug_bad() def one(self): m.plug_good() plug = MyPlug() plug.add_to(runner) runner() compare([ call.job1(), call.plug_good() ], actual=m.mock_calls) verify(runner, (m.job1, set()), (plug.one, {'one'}), )
def test_remap_name(self): m = Mock() runner = Runner() runner.add(m.job1, label='one') class MyPlug(Plug): @insert(label='one') def run_plug(self): m.plug_one() plug = MyPlug() plug.add_to(runner) runner() compare([ call.job1(), call.plug_one() ], m.mock_calls) verify(runner, (m.job1, set()), (plug.run_plug, {'one'}), )
def run_with(main, conn, argv): runner = Runner(ArgumentParser) runner.extend(main.clone(added_using='args')) runner.add(lambda parser: parser.parse_args(argv), requires=ArgumentParser) runner.add(lambda: conn) runner.extend(main.clone(start_label='body')) runner()
def test_ordering_runners(self): m = Mock() class Type(): pass @requires(first()) def f_none(): m.f_none() def n_none(): m.n_none() def l_none(): m.l_none() def make_t(): return Type() @requires(first(Type)) def f_t(t): m.f_t() @requires(Type) def n_t(t): m.n_t() @requires(last(Type)) def l_t(t): m.l_t() runner = Runner() runner.add(l_none, last()) runner.add(f_t) Runner(Runner(l_t, n_t), runner, Runner(f_none, n_none), Runner(make_t))() compare([ call.f_none(), call.n_none(), call.l_none(), call.f_t(), call.n_t(), call.l_t(), ], m.mock_calls)
def run(): runner = Runner() runner.add(load) runner.add(scrap_coins) runner.add(go_get_them) runner.add(scrap_exchanges) runner.add(cleanup) runner.add(get_all_trends) runner()
def test_simple(self): m = Mock() def job(): m.job() runner = Runner() runner.add(job) runner() compare([ call.job() ], m.mock_calls)
def test_simple(self): m = Mock() runner = Runner() runner.add(m.job1, label='one') runner.add(m.job2) runner.add(m.job3, label='three') runner.add(m.job4) class MyPlug(Plug): def one(self): m.plug_one() def three(self): m.plug_two() plug = MyPlug() plug.add_to(runner) runner() compare([ call.job1(), call.plug_one(), call.job2(), call.job3(), call.plug_two(), call.job4() ], m.mock_calls) verify(runner, (m.job1, set()), (plug.one, {'one'}), (m.job2, set()), (m.job3, set()), (plug.three, {'three'}), (m.job4, set()), )
def test_complex_(self): # parser -> args -> dbs (later) -> job (earlier) m = Mock() class T1(object): pass class T2(object): pass class T3(object): pass def parser(): m.parser() return T1() @requires(T1) def args(obj): m.args(type(obj)) @requires(T2) def dbs(obj): m.dbs(type(obj)) return T3() @requires(last(T1)) def parse(obj): m.parse(type(obj)) return T2() runner = Runner(parser, args, dbs, parse) @requires(T1) def more_args(obj): m.more_args(type(obj)) @requires(T2, T3) def job(o1, o2): m.job(type(o1), type(o2)) runner.add(more_args) runner.add(job) runner() compare([ call.parser(), call.args(T1), call.more_args(T1), call.parse(T1), call.dbs(T2), call.job(T2, T3), ], m.mock_calls)
def test_attr(self): class T(object): foo = 'bar' m = Mock() def job1(): m.job1() return T() def job2(obj): m.job2(obj) runner = Runner() runner.add(job1) runner.add(job2, attr(T, 'foo')) runner() compare([ call.job1(), call.job2('bar'), ], m.mock_calls)
def test_item_multiple(self): class MyDict(dict): pass m = Mock() def job1(): m.job1() obj = MyDict() obj['the_thing'] = dict(other_thing=m.the_thing) return obj def job2(obj): m.job2(obj) runner = Runner() runner.add(job1) runner.add(job2, item(MyDict, 'the_thing', 'other_thing')) runner() compare([ call.job1(), call.job2(m.the_thing), ], m.mock_calls)
def test_nested(self): class T(object): foo = dict(baz='bar') m = Mock() def job1(): m.job1() return T() def job2(obj): m.job2(obj) runner = Runner() runner.add(job1) runner.add(job2, item(attr(T, 'foo'), 'baz')) runner() compare([ call.job1(), call.job2('bar'), ], m.mock_calls)
def test_simple_chain(self): m = Mock() class T1(object): pass class T2(object): pass t1 = T1() t2 = T2() def parser(): m.parser() return t1 @requires(T1) def base_args(obj): m.base_args(obj) @requires(last(T1)) def parse(obj): m.parse(obj) return t2 runner = Runner(parser, base_args, parse) @requires(T1) def my_args(obj): m.my_args(obj) runner.add(my_args) @requires(T2) def job(obj): m.job(obj) runner.add(job) runner() compare([ call.parser(), call.base_args(t1), call.my_args(t1), call.parse(t1), call.job(t2), ], m.mock_calls)
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, first()) runner1.add(n1) runner1.add(l1, last()) runner1.add(t1, T1) runner1.add(t2, 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.add(f2, first()) runner2.add(n2) runner2.add(l2, last()) # make sure types stay in order runner2.add(tn, T2) # now run both, and make sure we only get what we should runner1() compare([ call.f1(), call.n1(), call.l1(), call.t1(), call.t2(), ], m.mock_calls) m.reset_mock() runner2() compare([ call.f1(), call.f2(), call.n1(), call.n2(), call.l1(), call.l2(), call.t1(), call.t2(), call.tn() ], m.mock_calls)
def test_attr_multiple(self): class T2: bar = 'baz' class T: foo = T2() m = Mock() def job1(): m.job1() return T() def job2(obj): m.job2(obj) runner = Runner() runner.add(job1) runner.add(job2, attr(T, 'foo', 'bar')) runner() compare([ call.job1(), call.job2('baz'), ], m.mock_calls)
def test_requirements_and_returns(self): m = Mock() @returns('r1') def job1(): m.job1() return 1 @requires('r2') def job3(r): m.job3(r) runner = Runner() runner.add(job1, label='point') runner.add(job3) class MyPlug(Plug): @requires('r1') @returns('r2') def point(self, r): m.point(r) return 2 plug = MyPlug() plug.add_to(runner) runner() compare([ call.job1(), call.point(1), call.job3(2), ], m.mock_calls) verify( runner, (job1, set()), (plug.point, {'point'}), (job3, set()), )
def test_requirements_and_returns(self): m = Mock() @returns('r1') def job1(): m.job1() return 1 @requires('r2') def job3(r): m.job3(r) runner = Runner() runner.add(job1, label='point') runner.add(job3) class MyPlug(Plug): @requires('r1') @returns('r2') def point(self, r): m.point(r) return 2 plug = MyPlug() plug.add_to(runner) runner() compare([ call.job1(), call.point(1), call.job3(2), ], m.mock_calls) verify(runner, (job1, set()), (plug.point, {'point'}), (job3, set()), )
def test_add_plug(self): m = Mock() runner = Runner() runner.add(m.job1, label='one') class MyPlug(Plug): def one(self): m.plug_one() plug = MyPlug() runner.add(plug) runner() compare([ call.job1(), call.plug_one() ], m.mock_calls) verify(runner, (m.job1, set()), (plug.one, {'one'}), )
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_returning(job1, T2) runner.add(job2, T2) runner() compare([ call.job1(), call.job2(t), ], m.mock_calls)
def test_context_imperative(self): m = Mock() class T1(object): pass class T2(object): pass t1 = T1() t2 = T2() def job1(): m.job1() return t1 def job2(obj): m.job2(obj) return t2 def job3(t2_): m.job3(t2_) # imperative config trumps declarative @requires(T1) def job4(t2_): m.job4(t2_) runner = Runner() runner.add(job1) runner.add(job2, T1) runner.add(job3, t2_=T2) runner.add(job4, T2) runner() compare([ call.job1(), call.job2(t1), call.job3(t2), call.job4(t2), ], m.mock_calls)
def test_circular(self): class T1(object): pass class T2(object): pass class T3(object): pass def f1(): return T1() def f2(t1, t3): return T2() # pragma: no cover def f3(t2): return T3() # pragma: no cover runner = Runner() runner.add(f1) runner.add(f2, T1, T3) runner.add(f3, T2) with ShouldRaise(KeyError( "'No T3 in context' attempting to call "+repr(f2) )): runner()
class DatabaseHandler: def __init__(self, db_path): self.conn = sqlite3.connect(db_path) def __enter__(self): return self def __exit__(self, type, obj, tb): if type: log.exception('Something went wrong') self.conn.rollback() base_runner = Runner(ArgumentParser) base_runner.add(base_options, label='args') base_runner.extend(parse_args, parse_config) base_runner.add( setup_logging, requires(log_path=item('config', 'log'), quiet=attr(Namespace, 'quiet'), verbose=attr(Namespace, 'verbose'))) def args(parser): parser.add_argument('path', help='Path to the file to process') def do(conn, path): filename = os.path.basename(path) with open(path) as source:
def make_runner(do): runner = Runner(ArgumentParser) runner.add(options, requires=ArgumentParser) runner.add(parse_args, requires=ArgumentParser) runner.add(parse_config, requires=Namespace) runner.add(setup_logging, requires( log_path = item('config', 'log'), quiet = attr(Namespace, 'quiet'), verbose = attr(Namespace, 'verbose') )) runner.add(DatabaseHandler, requires=item('config', 'db')) runner.add( do, requires(attr(DatabaseHandler, 'conn'), attr(Namespace, 'path')) ) return runner
def test_debug(self): class T1(object): pass class T2(object): pass class T3(object): pass def makes_t1(): pass @requires(T1) def makes_t2(obj): pass @requires(T2) def makes_t3(obj): pass def user(obj1, obj2): pass expected = '''\ Added {makes_t1} to 'normal' period for {nonetype} with Requirements() Current call order: For {nonetype}: normal: {makes_t1} requires Requirements() Added {makes_t2} to 'normal' period for {T1} with Requirements(T1) Current call order: For {nonetype}: normal: {makes_t1} requires Requirements() For {T1}: normal: {makes_t2} requires Requirements(T1) Added {makes_t3} to 'normal' period for {T2} with Requirements(T2) Current call order: For {nonetype}: normal: {makes_t1} requires Requirements() For {T1}: normal: {makes_t2} requires Requirements(T1) For {T2}: normal: {makes_t3} requires Requirements(T2) Added {user} to 'normal' period for {T3} with Requirements(T3, T1) Current call order: For {nonetype}: normal: {makes_t1} requires Requirements() For {T1}: normal: {makes_t2} requires Requirements(T1) For {T2}: normal: {makes_t3} requires Requirements(T2) For {T3}: normal: {user} requires Requirements(T3, T1) '''.format(nonetype=repr(None.__class__), makes_t1=repr(makes_t1), makes_t2=repr(makes_t2), makes_t3=repr(makes_t3), user=repr(user), T1=repr(T1), T2=repr(T2), T3=repr(T3)) with OutputCapture() as output: runner1 = Runner(makes_t1, debug=True) runner1.extend(makes_t2, makes_t3) runner1.add(user, T3, T1) compare(expected, output.captured) actual = StringIO() runner2 = Runner(makes_t1, debug=actual) runner2.extend(makes_t2, makes_t3) runner2.add(user, T3, T1) compare(expected, actual.getvalue())
def make_runner(do): runner = Runner(ArgumentParser) runner.add(options, ArgumentParser) runner.add(parse_args, last(ArgumentParser)) runner.add(parse_config, first(Namespace)) runner.add(setup_logging, log_path = item(first(Config), 'log'), quiet = attr(first(Namespace), 'quiet'), verbose = attr(first(Namespace), 'verbose')) runner.add(DatabaseHandler, item(Config, 'db')) runner.add(do, attr(DatabaseHandler, 'conn'), attr(Namespace, 'path')) return runner
def make_runner(do): runner = Runner(ArgumentParser) runner.add(options, requires=ArgumentParser) runner.add(parse_args, requires=ArgumentParser) runner.add(parse_config, requires=Namespace) runner.add( setup_logging, requires(log_path=item('config', 'log'), quiet=attr(Namespace, 'quiet'), verbose=attr(Namespace, 'verbose'))) runner.add(DatabaseHandler, requires=item('config', 'db')) runner.add( do, requires(attr(DatabaseHandler, 'conn'), attr(Namespace, 'path'))) return runner
def script(body, args=None): script = Runner() script.add(ArgumentParser) script.add(common_arguments) if args: script.add(args, requires=ArgumentParser) script.add(parse_args) script.add(load_config, requires=attr(Namespace, 'config'), returns='config') script.add(adjust_config) script.add( setup_logging, requires( log_path=item('config', 'log_path'), quiet=attr(Namespace, 'quiet'), verbose=attr(Namespace, 'verbose'), )) script.add(log_details) script.add( handle_database, requires( name=item('config', 'db', 'name'), user=item('config', 'db', 'user'), password=item('config', 'db', 'password'), )) script.add(body) return script
handler.setLevel(logging.DEBUG if verbose else logging.INFO) log.addHandler(handler) class DatabaseHandler: def __init__(self, db_path): self.conn = sqlite3.connect(db_path) def __enter__(self): return self def __exit__(self, type, obj, tb): if type: log.exception('Something went wrong') self.conn.rollback() base_runner = Runner(ArgumentParser, base_options, parse_args, parse_config) base_runner.add(setup_logging, log_path = item(first(Config), 'log'), quiet = attr(first(Namespace), 'quiet'), verbose = attr(first(Namespace), 'verbose')) def args(parser): parser.add_argument('path', help='Path to the file to process') def do(conn, path): filename = os.path.basename(path) with open(path) as source: conn.execute('insert into notes values (?, ?)', (filename, source.read())) conn.commit() log.info('Successfully added %r', filename) main = base_runner.clone()
handler = logging.StreamHandler(sys.stderr) handler.setLevel(logging.DEBUG if verbose else logging.INFO) log.addHandler(handler) class DatabaseHandler: def __init__(self, db_path): self.conn = sqlite3.connect(db_path) def __enter__(self): return self def __exit__(self, type, obj, tb): if type: log.exception('Something went wrong') self.conn.rollback() base_runner = Runner(ArgumentParser) base_runner.add(base_options, label='args') base_runner.extend(parse_args, parse_config) base_runner.add(setup_logging, requires( log_path = item('config', 'log'), quiet = attr(Namespace, 'quiet'), verbose = attr(Namespace, 'verbose') )) def args(parser): parser.add_argument('path', help='Path to the file to process') def do(conn, path): filename = os.path.basename(path) with open(path) as source: conn.execute('insert into notes values (?, ?)',