def test_merge_dicts_overwrite(self): mergee = {'two':5,'four':4,'three':None,'one':(1,2,3)} p = Parameters(dict(dict=SIMPLE)) p.merge(Parameters(dict(dict=mergee))) goal = SIMPLE.copy() goal.update(mergee) self.assertDictEqual(p.as_dict(), dict(dict=goal))
def test_interpolate_single(self): v = 42 d = {'foo': 'bar'.join(PARAMETER_INTERPOLATION_SENTINELS), 'bar': v} p = Parameters(d) p.interpolate() self.assertEqual(p.as_dict()['foo'], v)
def _construct_mocked_params(self, iterable=None, delimiter=None): p = Parameters(iterable, delimiter) self._base = base = p._base p._base = mock.MagicMock(spec_set=dict, wraps=base) p._base.__repr__ = mock.MagicMock(autospec=dict.__repr__, return_value=repr(base)) return p, p._base
def test_interpolate_list(self): l = [41,42,43] d = {'foo': 'bar'.join(PARAMETER_INTERPOLATION_SENTINELS), 'bar': l} p = Parameters(d) p.interpolate() self.assertEqual(p.as_dict()['foo'], l)
def test_interpolate_infrecursion(self): v = 42 d = {'foo': 'bar'.join(PARAMETER_INTERPOLATION_SENTINELS), 'bar': 'foo'.join(PARAMETER_INTERPOLATION_SENTINELS)} p = Parameters(d) with self.assertRaises(InfiniteRecursionError): p.interpolate()
def test_merge_lists(self): l1 = [1,2,3] l2 = [2,3,4] p1 = Parameters(dict(list=l1[:])) p2 = Parameters(dict(list=l2)) p1.merge(p2) self.assertListEqual(p1.as_dict()['list'], l1+l2)
def test_merge_scalars(self): p = Parameters(SIMPLE) mergee = {'five':5,'four':4,'None':None,'tuple':(1,2,3)} p.merge(mergee) goal = SIMPLE.copy() goal.update(mergee) self.assertDictEqual(p.as_dict(), goal)
def test_merge_scalars_overwrite(self): p = Parameters(SIMPLE) mergee = {'two':5,'four':4,'three':None,'one':(1,2,3)} p.merge(mergee) goal = SIMPLE.copy() goal.update(mergee) self.assertDictEqual(p.as_dict(), goal)
def test_interpolate_multiple(self): v = '42' d = {'foo': 'bar'.join(PARAMETER_INTERPOLATION_SENTINELS) + 'meep'.join(PARAMETER_INTERPOLATION_SENTINELS), 'bar': v[0], 'meep': v[1]} p = Parameters(d) p.interpolate() self.assertEqual(p.as_dict()['foo'], v)
def test_merge_dicts_override(self): """Validate that tilde merge overrides function properly.""" mergee = {'~one': {'a': 'alpha'}, '~two': ['gamma']} base = {'one': {'b': 'beta'}, 'two': ['delta']} goal = {'one': {'a': 'alpha'}, 'two': ['gamma']} p = Parameters(dict(dict=base)) p.merge(Parameters(dict(dict=mergee))) self.assertDictEqual(p.as_dict(), dict(dict=goal))
def test_escaped_string_in_ref_dict_2(self): # test with escaped string in second dict to be merged p1 = Parameters( { 'a': { 'one': '${a_ref}' }, 'b': { 'two': '\${not_a_ref}' }, 'c': '${a}', 'a_ref': 123 }, SETTINGS, '') p2 = Parameters({'c': '${b}'}, SETTINGS, '') r = { 'a': { 'one': 123 }, 'b': { 'two': '${not_a_ref}' }, 'c': { 'one': 123, 'two': '${not_a_ref}' }, 'a_ref': 123 } p1.merge(p2) p1.interpolate() self.assertEqual(p1.as_dict(), r)
def test_merge_referenced_dicts(self): p1 = Parameters( { 'one': { 'a': 1, 'b': 2 }, 'two': { 'c': 3, 'd': 4 }, 'three': '${one}' }, SETTINGS, '') p2 = Parameters({'three': '${two}'}, SETTINGS, '') r = { 'one': { 'a': 1, 'b': 2 }, 'two': { 'c': 3, 'd': 4 }, 'three': { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } } p1.merge(p2) p1.interpolate() self.assertEqual(p1.as_dict(), r)
def test_same_list_if_expr_invquery_different_flags(self): inventory = { 'node1': NodeInventory({'a': 1}, True), 'node2': NodeInventory({'a': 2}, True), 'node3': NodeInventory({'a': 2}, False) } parameters = Parameters( { 'alpha': '$[ if exports:a == 2 ]', 'beta': '$[ +AllEnvs if exports:a == 2]' }, SETTINGS, '') result = {'alpha': ['node2'], 'beta': ['node2', 'node3']} parameters.interpolate(inventory) self.assertEqual(parameters.as_dict(), result)
def test_nested_refs_error_message(self): # beta is missing, oops p1 = Parameters( { 'alpha': { 'one': 1, 'two': 2 }, 'gamma': '${alpha:${beta}}' }, SETTINGS, '') with self.assertRaises(InterpolationError) as error: p1.interpolate() self.assertEqual(error.exception.message, "-> \n Bad references, at gamma\n ${beta}")
def test_interpolate_infrecursion(self): v = 42 d = { 'foo': 'bar'.join(SETTINGS.reference_sentinels), 'bar': 'foo'.join(SETTINGS.reference_sentinels) } p = Parameters(d, SETTINGS, '') with self.assertRaises(InfiniteRecursionError) as e: p.interpolate() # interpolation can start with foo or bar self.assertIn(e.exception.message, [ "-> \n Infinite recursion: ${foo}, at bar", "-> \n Infinite recursion: ${bar}, at foo" ])
def test_interpolate_multiple(self): v = '42' d = { 'foo': 'bar'.join(SETTINGS.reference_sentinels) + 'meep'.join(SETTINGS.reference_sentinels), 'bar': v[0], 'meep': v[1] } p = Parameters(d, SETTINGS, '') p.interpolate() self.assertEqual(p.as_dict()['foo'], v)
def test_merge_none_over_dict_allow(self): settings = Settings({'allow_none_override': True}) p1 = Parameters(dict(key=SIMPLE), settings, '') p2 = Parameters(dict(key=None), settings, '') p1.merge(p2) p1.interpolate() self.assertEqual(p1.as_dict()['key'], None)
def test_escaped_string_overwrites(self): p1 = Parameters({'test': '\${not_a_ref}'}, SETTINGS, '') p2 = Parameters({'test': '\${also_not_a_ref}'}, SETTINGS, '') r = {'test': '${also_not_a_ref}'} p1.merge(p2) p1.interpolate() self.assertEqual(p1.as_dict(), r)
def test_interpolate_multiple(self): v = '42' d = { 'foo': 'bar'.join(PARAMETER_INTERPOLATION_SENTINELS) + 'meep'.join(PARAMETER_INTERPOLATION_SENTINELS), 'bar': v[0], 'meep': v[1] } p = Parameters(d) p.interpolate() self.assertEqual(p.as_dict()['foo'], v)
def _get_automatic_parameters(self, nodename, environment): if self._settings.automatic_parameters: return Parameters( { '_reclass_': { 'name': { 'full': nodename, 'short': str.split(nodename, '.')[0] }, 'environment': environment } }, self._settings, '__auto__') else: return Parameters({}, self._settings, '')
def test_referenced_dict_deep_overwrite(self): p1 = Parameters({'alpha': {'one': {'a': 1, 'b': 2} } }) p2 = Parameters({'beta': '${alpha}'}) p3 = Parameters({'alpha': {'one': {'c': 3, 'd': 4} }, 'beta': {'one': {'a': 99} } }) r = {'alpha': {'one': {'a':1, 'b': 2, 'c': 3, 'd':4} }, 'beta': {'one': {'a':99, 'b': 2, 'c': 3, 'd':4} } } p1.merge(p2) p1.merge(p3) p1.interpolate() self.assertEqual(p1.as_dict(), r)
def test_nested_reference_with_overwriting(self): p1 = Parameters({'one': {'a': 1, 'b': 2, 'z': 'a'}, 'two': '${one:${one:z}}' }) p2 = Parameters({'one': {'z': 'b'} }) r = {'one': {'a': 1, 'b':2, 'z': 'b'}, 'two': 2} p1.merge(p2) p1.interpolate() self.assertEqual(p1.as_dict(), r)
def test_merge_scalar_over_dict(self): options = MergeOptions() options.allow_scalar_over_dict = True p = Parameters(dict(base=SIMPLE), options=options) mergee = {'base':'foo'} p.merge(Parameters(mergee)) p.initialise_interpolation() self.assertDictEqual(p.as_dict(), mergee)
def test_merging_inv_queries(self): e = {'node1': {'a': 1}, 'node2': {'a': 1}, 'node3': {'a': 2}} p1 = Parameters({'exp': '$[ if exports:a == 1 ]'}, SETTINGS, '') p2 = Parameters({'exp': '$[ if exports:a == 2 ]'}, SETTINGS, '') r = {'exp': ['node1', 'node2', 'node3']} p1.merge(p2) p1.interpolate(e) self.assertEqual(p1.as_dict(), r)
def test_merge_none_over_list(self): l = ['foo', 1, 2] settings = Settings({'allow_none_override': True}) p1 = Parameters(dict(key=l[:2]), settings, '') p2 = Parameters(dict(key=None), settings, '') p1.merge(p2) p1.initialise_interpolation() self.assertEqual(p1.as_dict()['key'], None)
def test_merge_lists(self): l1 = [1,2,3] l2 = [2,3,4] p1 = Parameters(dict(list=l1[:])) p2 = Parameters(dict(list=l2)) p1.merge(p2) p1.initialise_interpolation() self.assertListEqual(p1.as_dict()['list'], l1+l2)
def test_merge_scalar_over_dict(self): settings = Settings({'allow_scalar_over_dict': True}) p = Parameters(dict(base=SIMPLE), settings, '') mergee = {'base': 'foo'} p2 = Parameters(mergee, settings, '') p.merge(p2) p.initialise_interpolation() self.assertDictEqual(p.as_dict(), mergee)
def test_merge_scalar_over_list(self): l = ['foo', 1, 2] options = MergeOptions() options.allow_scalar_over_list = True p1 = Parameters(dict(key=l[:2]), options=options) p1.merge(Parameters(dict(key=l[2]))) p1.initialise_interpolation() self.assertEqual(p1.as_dict()['key'], l[2])
def test_merge_list_into_scalar(self): l = ['foo', 1, 2] options = MergeOptions() options.allow_list_over_scalar = True p1 = Parameters(dict(key=l[0]), options=options) p1.merge(Parameters(dict(key=l[1:]))) p1.initialise_interpolation() self.assertListEqual(p1.as_dict()['key'], l)
def test_merge_dicts_overwrite(self): mergee = {'two':5,'four':4,'three':None,'one':(1,2,3)} p = Parameters(dict(dict=SIMPLE)) p.merge(Parameters(dict(dict=mergee))) p.initialise_interpolation() goal = SIMPLE.copy() goal.update(mergee) self.assertDictEqual(p.as_dict(), dict(dict=goal))
def test_merge_list_into_scalar_allow(self): settings = Settings({'allow_list_over_scalar': True}) l = ['foo', 1, 2] p1 = Parameters(dict(key=l[0]), settings, '') p2 = Parameters(dict(key=l[1:]), settings, '') p1.merge(p2) p1.interpolate() self.assertListEqual(p1.as_dict()['key'], l)
def test_value_expr_invquery(self): inventory = self._make_inventory({ 'node1': { 'a': 1, 'b': 2 }, 'node2': { 'a': 3, 'b': 4 } }) parameters = Parameters({'exp': '$[ exports:a ]'}, SETTINGS, '') result = {'exp': {'node1': 1, 'node2': 3}} parameters.interpolate(inventory) self.assertEqual(parameters.as_dict(), result)
def test_merge_scalar_over_list_allow(self): l = ['foo', 1, 2] settings = Settings({'allow_scalar_over_list': True}) p1 = Parameters(dict(key=l[:2]), settings, '') p2 = Parameters(dict(key=l[2]), settings, '') p1.merge(p2) p1.interpolate() self.assertEqual(p1.as_dict()['key'], l[2])
def test_merge_scalar_over_dict_allow(self): d = {'one': 1, 'two': 2} settings = Settings({'allow_scalar_over_dict': True}) p1 = Parameters({'a': d}, settings, '') p2 = Parameters({'a': 1}, settings, '') p1.merge(p2) p1.interpolate() self.assertEqual(p1.as_dict(), {'a': 1})
def test_merge_dicts(self): mergee = {'five': 5, 'four': 4, 'None': None, 'tuple': (1, 2, 3)} p = Parameters(dict(dict=SIMPLE), SETTINGS, '') p2 = Parameters(dict(dict=mergee), SETTINGS, '') p.merge(p2) p.initialise_interpolation() goal = SIMPLE.copy() goal.update(mergee) self.assertDictEqual(p.as_dict(), dict(dict=goal))
def test_interpolate_escaping_backwards_compatibility(self): """In all following cases, escaping should not happen and the escape character needs to be printed as-is, to ensure backwards compatibility to older versions.""" v = ' '.join([ # Escape character followed by unescapable character '1', ESCAPE_CHARACTER, # Escape character followed by escape character '2', ESCAPE_CHARACTER + ESCAPE_CHARACTER, # Escape character followed by interpolation end sentinel '3', ESCAPE_CHARACTER + REFERENCE_SENTINELS[1], # Escape character at the end of the string '4', ESCAPE_CHARACTER ]) d = {'foo': v} p = Parameters(d) p.initialise_interpolation() self.assertEqual(p.as_dict()['foo'], v)
def test_reference_to_an_export(self): inventory = {'node1': {'a': 1, 'b': 2}, 'node2': {'a': 3, 'b': 4}} node3_exports = Exports({'a': '${a}', 'b': '${b}'}) node3_parameters = Parameters({ 'name': 'node3', 'ref': '${exp}', 'a': '${c}', 'b': 5 }) node3_parameters.merge({'c': 3, 'exp': '$[ exports:a ]'}) node3_entity = Entity(None, None, node3_parameters, node3_exports) node3_entity.interpolate_exports() inventory['node3'] = node3_entity.exports.as_dict() node3_entity.interpolate('node3', inventory) res_inv = { 'node1': { 'a': 1, 'b': 2 }, 'node2': { 'a': 3, 'b': 4 }, 'node3': { 'a': 3, 'b': 5 } } res_params = { 'a': 3, 'c': 3, 'b': 5, 'name': 'node3', 'exp': { 'node1': 1, 'node3': 3, 'node2': 3 }, 'ref': { 'node1': 1, 'node3': 3, 'node2': 3 } } self.assertDictEqual(node3_parameters.as_dict(), res_params) self.assertDictEqual(inventory, res_inv)
def test_merge_dicts_override(self): """Validate that tilde merge overrides function properly.""" mergee = {'~one': {'a': 'alpha'}, '~two': ['gamma']} base = {'one': {'b': 'beta'}, 'two': ['delta']} goal = {'one': {'a': 'alpha'}, 'two': ['gamma']} p = Parameters(dict(dict=base), SETTINGS, '') p2 = Parameters(dict(dict=mergee), SETTINGS, '') p.merge(p2) p.interpolate() self.assertDictEqual(p.as_dict(), dict(dict=goal))
def test_ignore_overwriten_missing_reference(self): settings = copy.deepcopy(SETTINGS) settings.ignore_overwritten_missing_references = True p1 = Parameters({'alpha': '${beta}'}, settings, '') p2 = Parameters({'alpha': '${gamma}'}, settings, '') p3 = Parameters({'gamma': 3}, settings, '') r1 = {'alpha': 3, 'gamma': 3} p1.merge(p2) p1.merge(p3) err1 = "[WARNING] Reference '${beta}' undefined\n" with mock.patch('sys.stderr', new=MockDevice()) as std_err: p1.interpolate() self.assertEqual(p1.as_dict(), r1) self.assertEqual(std_err.text(), err1)
def test_interpolated_list_type(self): p1 = Parameters({'a': [1, 2, 3]}, SETTINGS, 'first') r = {'a': [1, 2, 3]} self.assertIs(type(p1.as_dict()['a']), ParameterList) p1.interpolate() self.assertIs(type(p1.as_dict()['a']), list) self.assertEqual(p1.as_dict(), r)
def _merge(a, b): ''' merge the contents of dictionary ``b`` into dictionary ``a``, using reclass' sensible form of deep-dictionary merging and interpolation. ''' m = Parameters(a) m.merge(b) m.interpolate() return m.as_dict()
def test_constructor1(self): DATA = {'blue':'white', 'black':'yellow'} c = Parameters(DATA) assert len(c) == len(DATA) for i in c.iterkeys(): assert DATA[i] == c[i]
def test_stray_occurrence_overwrites_during_interpolation(self): p1 = Parameters({'r' : mock.sentinel.ref, 'b': '${r}'}) p2 = Parameters({'b' : mock.sentinel.goal}) p1.merge(p2) p1.interpolate() self.assertEqual(p1.as_dict()['b'], mock.sentinel.goal)
def test_merge_list_into_scalar(self): l = ['foo', 1, 2] p1 = Parameters(dict(key=l[0])) p1.merge(Parameters(dict(key=l[1:]))) self.assertListEqual(p1.as_dict()['key'], l)
def test_merge_scalar_over_list(self): l = ['foo', 1, 2] p1 = Parameters(dict(key=l[:2])) p1.merge(Parameters(dict(key=l[2]))) self.assertEqual(p1.as_dict()['key'], l[2])
def test_merge_dict_into_scalar(self): p = Parameters(dict(base='foo')) with self.assertRaises(TypeError): p.merge(Parameters(dict(base=SIMPLE)))
def test_merge_scalar_over_dict(self): p = Parameters(dict(base=SIMPLE)) mergee = {'base':'foo'} p.merge(Parameters(mergee)) self.assertDictEqual(p.as_dict(), mergee)