def test_scope_override(): class MesosConfig(Struct): ports = Map(String, Integer) config = MesosConfig(ports = {'http': 80, 'health': 8888}) env = Environment({ref('config.ports[http]'): 5000}, config = config) assert env.find(ref('config.ports[http]')) == '5000' assert env.find(ref('config.ports[health]')) == Integer(8888)
def test_scope_override(): class MesosConfig(Struct): ports = Map(String, Integer) config = MesosConfig(ports={'http': 80, 'health': 8888}) env = Environment({ref('config.ports[http]'): 5000}, config=config) assert env.find(ref('config.ports[http]')) == '5000' assert env.find(ref('config.ports[health]')) == Integer(8888)
def test_environment_constructors(): oe = Environment(a = 1, b = 2) assert oe._table == dtd({'a': 1, 'b': 2}) oe = Environment({'a': 1, 'b': 2}) assert oe._table == dtd({'a': 1, 'b': 2}) oe = Environment({'a': 1}, b = 2) assert oe._table == dtd({'a': 1, 'b': 2}) oe = Environment({'a': 1}, a = 2) assert oe._table == dtd({'a': 2}), "last update should win" oe = Environment({'b': 1}, a = 2) assert oe._table == dtd({'a': 2, 'b': 1}) oe = Environment(oe, a = 3) assert oe._table == dtd({'a': 3, 'b': 1}) bad_values = [None, 3, 'a', type, ()] for value in bad_values: with pytest.raises(ValueError): Environment(value) bad_values = [None, type, ()] for value in bad_values: with pytest.raises(ValueError): Environment(foo = value)
def test_nested_mustache_resolution(): # straight oe = Environment(foo='{{bar}}', bar='{{baz}}', baz='hello') for pattern in ('{{foo}}', '{{bar}}', '{{baz}}', 'hello'): resolved, unbound = MustacheParser.resolve('%s world' % pattern, oe) assert resolved == 'hello world' assert unbound == [] # in structs class Process(Struct): name = Required(String) cmdline = String class Task(Struct): name = Default(String, '{{processes[0].name}}') processes = List(Process) task = Task(processes=[Process(name="hello"), Process(name="world")]) assert task.name().get() == 'hello' # iterably resolve_string = '{{foo[{{bar}}]}}' resolve_list = List(String)(["hello", "world"]) resolved, unbound = MustacheParser.resolve( resolve_string, Environment(foo=resolve_list, bar=0)) assert resolved == 'hello' assert unbound == [] resolved, unbound = MustacheParser.resolve( resolve_string, Environment(foo=resolve_list, bar="0")) assert resolved == 'hello' assert unbound == [] resolved, _ = MustacheParser.resolve(resolve_string, Environment(foo=resolve_list, bar=1)) assert resolved == 'world' resolved, unbound = MustacheParser.resolve( resolve_string, Environment(foo=resolve_list, bar=2)) assert resolved == '{{foo[2]}}' assert unbound == [ref('foo[2]')]
def test_mustache_joining(): oe = Environment(foo="foo herp", bar="bar derp", baz="baz blerp") joined, unbound = MustacheParser.join(MustacheParser.split("{{foo}}"), oe) assert joined == "foo herp" assert unbound == [] splits = MustacheParser.split('blech {{foo}} {{bar}} bonk {{&baz}} bling') joined, unbound = MustacheParser.join(splits, oe) assert joined == 'blech foo herp bar derp bonk {{baz}} bling' assert unbound == [] splits = MustacheParser.split('{{foo}} {{bar}} {{unbound}}') joined, unbound = MustacheParser.join(splits, oe) assert joined == 'foo herp bar derp {{unbound}}' assert unbound == [Ref.from_address('unbound')]
def test_complex_lookup(): class Employee(Struct): first = String last = String class Employer(Struct): name = String employees = List(Employee) twttr = Employer(name='Twitter', employees=[ Employee(first='brian', last='wickman'), Employee(first='marius'), Employee(last='{{default.last}}') ]) assert Environment(twttr=twttr).find( ref('twttr.employees[1].first')) == String('marius') assert Map(String,Employer)({'twttr': twttr}).find(ref('[twttr].employees[1].first')) == \ String('marius') assert List(Employer)([twttr]).find( ref('[0].employees[0].last')) == String('wickman') assert List(Employer)([twttr]).find( ref('[0].employees[2].last')) == String('{{default.last}}')
def test_environment_bad_values(): bad_values = [None, type, object()] for val in bad_values: with pytest.raises(ValueError): Environment(a = val)
def test_environment_merge(): oe1 = Environment(a = 1) oe2 = Environment(b = 2) assert Environment(oe1, oe2)._table == { ref('a'): '1', ref('b'): '2' } oe1 = Environment(a = 1, b = 2) oe2 = Environment(a = 1, b = {'c': 2}) assert Environment(oe1, oe2)._table == { ref('a'): '1', ref('b'): '2', ref('b.c'): '2' } oe1 = Environment(a = 1, b = 2) oe2 = Environment(a = 1, b = {'c': 2}) assert Environment(oe2, oe1)._table == { ref('a'): '1', ref('b'): '2', ref('b.c'): '2' } oe1 = Environment(a = { 'b': 1 }) oe2 = Environment(a = { 'c': 2 }) assert Environment(oe1, oe2)._table == { ref('a.b'): '1', ref('a.c'): '2' } assert Environment(oe2, oe1)._table == { ref('a.b'): '1', ref('a.c'): '2' }
def test_environment_find(): oe1 = Environment(a = { 'b': 1 }) oe2 = Environment(a = { 'b': { 'c': List(Integer)([1,2,3]) } } ) oe = Environment(oe1, oe2) assert oe.find(ref('a.b')) == '1' assert oe.find(ref('a.b.c[0]')) == Integer(1) assert oe.find(ref('a.b.c[1]')) == Integer(2) assert oe.find(ref('a.b.c[2]')) == Integer(3) missing_refs = [ref('b'), ref('b.c'), ref('a.c'), ref('a.b.c[3]')] for r in missing_refs: with pytest.raises(Namable.NotFound): oe.find(r) oe = Environment(a = { 'b': { 'c': 5 } } ) assert oe.find(ref('a.b.c')) == '5'
def test_ref_lookup(): oe = Environment(a = 1) assert oe.find(ref("a")) == '1' oe = Environment(a = {'b': 1}) assert oe.find(ref("a.b")) == '1' oe = Environment(a = {'b': {'c': 1}, 'c': Environment(d = 2)}) assert oe.find(ref('a.b.c')) == '1' assert oe.find(ref('a.c.d')) == '2' for address in ["a", "a.b", "a.c"]: with pytest.raises(Namable.NotFound): oe.find(ref(address)) oe = List(String)(["a", "b", "c"]) assert oe.find(ref('[0]')) == String('a') with pytest.raises(Namable.NotFound): oe.find(ref('[3]')) oe = List(Map(String,Integer))([{'a': 27}]) oe.find(ref('[0][a]')) == Integer(27) Environment(foo = oe).find(ref('foo[0][a]')) == Integer(27)
def test_ref_lookup(): oe = Environment(a=1) assert oe.find(ref("a")) == '1' oe = Environment(a={'b': 1}) assert oe.find(ref("a.b")) == '1' oe = Environment(a={'b': {'c': 1}, 'c': Environment(d=2)}) assert oe.find(ref('a.b.c')) == '1' assert oe.find(ref('a.c.d')) == '2' for address in ["a", "a.b", "a.c"]: with pytest.raises(Namable.NotFound): oe.find(ref(address)) oe = List(String)(["a", "b", "c"]) assert oe.find(ref('[0]')) == String('a') with pytest.raises(Namable.NotFound): oe.find(ref('[3]')) oe = List(Map(String, Integer))([{'a': 27}]) oe.find(ref('[0][a]')) == Integer(27) Environment(foo=oe).find(ref('foo[0][a]')) == Integer(27)
def test_environment_provides(): oe1 = Environment(a = { 'b': 1 }) oe2 = Environment(a = { 'b': { 'c': List(Integer)([1,2,3]) } } ) oe = Environment(oe1, oe2) for address in ['a.b', 'a.b.c', 'a.b.c[0]']: assert oe.provides(ref(address)) for address in ['a', 'b', 'b.c', 'a.c', 'a.b.c.d', 'a.b.c[2].d']: assert not oe.provides(ref(address)) class Nested(Struct): value = String class Composite(Struct): first = String checks = Map(Integer, Nested) ce = Environment(composite = Composite()) assert not ce.provides(ref('random')) assert ce.provides(ref('composite')) assert ce.provides(ref('composite.first')) assert not ce.provides(ref('composite.first.poop')) assert ce.provides(ref('composite.checks')) assert ce.provides(ref('composite.checks[0]')) assert ce.provides(ref('composite.checks[0].value')) assert not ce.provides(ref('composite.checks[0].nonvalue')) assert not ce.provides(ref('composite.checks[0][nonvalue]')) ce = Environment({'composite': {'unioned': 1}}, composite = Composite()) assert ce.provides(ref('composite')) assert ce.provides(ref('composite.first')) assert ce.provides(ref('composite.unioned')) assert not ce.provides(ref('composite.unioned.anythingelse'))
def test_mustache_resolve_cycles(): with pytest.raises(MustacheParser.Uninterpolatable): MustacheParser.resolve( '{{foo[{{bar}}]}} {{baz}}', Environment(foo=List(String)(["{{foo[{{bar}}]}}", "world"])), Environment(bar=0))