def test_get_unordered(self): with patch.dict( grainsmod.__grains__, OrderedDict([ ("a", "aval"), ( "b", OrderedDict([ ("z", "zval"), ( "l1", [ "l21", "l22", OrderedDict([("l23", "l23val")]) ], ), ]), ), ("c", 8), ]), ): res = grainsmod.get("b", ordered=False) self.assertEqual(type(res), dict) # Check that order doesn't matter self.assertTrue(res == OrderedDict([ ("l1", ["l21", "l22", OrderedDict([("l23", "l23val")])]), ("z", "zval"), ]))
def test_equals(self): with patch.dict( grainsmod.__grains__, OrderedDict([ ("a", "aval"), ( "b", OrderedDict([ ("z", "zval"), ( "l1", [ "l21", "l22", OrderedDict([("l23", "l23val")]) ], ), ]), ), ("c", 8), ]), ): res = grainsmod.equals("a", "aval") self.assertEqual(type(res), bool) self.assertTrue(res) res = grainsmod.equals("b:z", "zval") self.assertTrue(res) res = grainsmod.equals("b:z", "aval") self.assertFalse(res)
def __init__(self, init=None, **kwargs): """ Force internal dict to be ordered to ensure a consistent iteration order, irrespective of case. """ self._data = OrderedDict() self.update(init or {}, **kwargs)
class CaseInsensitiveDict(MutableMapping): """ Inspired by requests' case-insensitive dict implementation, but works with non-string keys as well. """ def __init__(self, init=None, **kwargs): """ Force internal dict to be ordered to ensure a consistent iteration order, irrespective of case. """ self._data = OrderedDict() self.update(init or {}, **kwargs) def __len__(self): return len(self._data) def __setitem__(self, key, value): # Store the case-sensitive key so it is available for dict iteration self._data[to_lowercase(key)] = (key, value) def __delitem__(self, key): del self._data[to_lowercase(key)] def __getitem__(self, key): return self._data[to_lowercase(key)][1] def __iter__(self): return (item[0] for item in iter(self._data.values())) def __eq__(self, rval): if not isinstance(rval, Mapping): # Comparing to non-mapping type (e.g. int) is always False return False return dict(self.items_lower()) == dict(CaseInsensitiveDict(rval).items_lower()) def __repr__(self): return repr(dict(iter(self.items()))) def items_lower(self): """ Returns a generator iterating over keys and values, with the keys all being lowercase. """ return ((key, val[1]) for key, val in iter(self._data.items())) def copy(self): """ Returns a copy of the object """ return CaseInsensitiveDict(iter(self._data.items()))
def parse_command_result(res, label=None): ''' Parse the result of a zpool/zfs command .. note:: Output on failure is rather predicatable. - retcode > 0 - each 'error' is a line on stderr - optional 'Usage:' block under those with hits We simple check those and return a OrderedDict were we set label = True|False and error = error_messages ''' ret = OrderedDict() if label: ret[label] = res['retcode'] == 0 if res['retcode'] != 0: ret['error'] = [] for error in res['stderr'].splitlines(): if error.lower().startswith('usage:'): break if error.lower().startswith("use '-f'"): error = error.replace('-f', 'force=True') if error.lower().startswith("use '-r'"): error = error.replace('-r', 'recursive=True') ret['error'].append(error) if ret['error']: ret['error'] = "\n".join(ret['error']) else: del ret['error'] return ret
def test_decode(self): ''' Companion to test_decode_to_str, they should both be kept up-to-date with one another. NOTE: This uses the lambda "_b" defined above in the global scope, which encodes a string to a bytestring, assuming utf-8. ''' expected = [ 'unicode_str', 'питон', 123, 456.789, True, False, None, 'яйца', BYTES, [123, 456.789, 'спам', True, False, None, 'яйца', BYTES], (987, 654.321, 'яйца', 'яйца', None, (True, 'яйца', BYTES)), { 'str_key': 'str_val', None: True, 123: 456.789, 'яйца': BYTES, 'subdict': { 'unicode_key': 'яйца', 'tuple': (123, 'hello', 'world', True, 'яйца', BYTES), 'list': [456, 'спам', False, 'яйца', BYTES] } }, OrderedDict([('foo', 'bar'), (123, 456), ('яйца', BYTES)]) ] ret = hubblestack.utils.data.decode(self.test_data, keep=True, normalize=True, preserve_dict_class=True, preserve_tuples=True) self.assertEqual(ret, expected) # The binary data in the data structure should fail to decode, even # using the fallback, and raise an exception. self.assertRaises(UnicodeDecodeError, hubblestack.utils.data.decode, self.test_data, keep=False, normalize=True, preserve_dict_class=True, preserve_tuples=True) # Now munge the expected data so that we get what we would expect if we # disable preservation of dict class and tuples expected[10] = [ 987, 654.321, 'яйца', 'яйца', None, [True, 'яйца', BYTES] ] expected[11]['subdict']['tuple'] = [ 123, 'hello', 'world', True, 'яйца', BYTES ] expected[12] = {'foo': 'bar', 123: 456, 'яйца': BYTES} ret = hubblestack.utils.data.decode(self.test_data, keep=True, normalize=True, preserve_dict_class=False, preserve_tuples=False) self.assertEqual(ret, expected) # Now test single non-string, non-data-structure items, these should # return the same value when passed to this function for item in (123, 4.56, True, False, None): log.debug('Testing decode of %s', item) self.assertEqual(hubblestack.utils.data.decode(item), item) # Test single strings (not in a data structure) self.assertEqual(hubblestack.utils.data.decode('foo'), 'foo') self.assertEqual(hubblestack.utils.data.decode(_b('bar')), 'bar') self.assertEqual(hubblestack.utils.data.decode(EGGS, normalize=True), 'яйца') self.assertEqual(hubblestack.utils.data.decode(EGGS, normalize=False), EGGS) # Test binary blob self.assertEqual(hubblestack.utils.data.decode(BYTES, keep=True), BYTES) self.assertRaises(UnicodeDecodeError, hubblestack.utils.data.decode, BYTES, keep=False)
def test_encode(self): ''' NOTE: This uses the lambda "_b" defined above in the global scope, which encodes a string to a bytestring, assuming utf-8. ''' expected = [ _b('unicode_str'), _b('питон'), 123, 456.789, True, False, None, _b(EGGS), BYTES, [123, 456.789, _b('спам'), True, False, None, _b(EGGS), BYTES], (987, 654.321, _b('яйца'), _b(EGGS), None, (True, _b(EGGS), BYTES)), { _b('str_key'): _b('str_val'), None: True, 123: 456.789, _b(EGGS): BYTES, _b('subdict'): { _b('unicode_key'): _b(EGGS), _b('tuple'): (123, _b('hello'), _b('world'), True, _b(EGGS), BYTES), _b('list'): [456, _b('спам'), False, _b(EGGS), BYTES] } }, OrderedDict([(_b('foo'), _b('bar')), (123, 456), (_b(EGGS), BYTES)]) ] # Both keep=True and keep=False should work because the BYTES data is # already bytes. ret = hubblestack.utils.data.encode(self.test_data, keep=True, preserve_dict_class=True, preserve_tuples=True) self.assertEqual(ret, expected) ret = hubblestack.utils.data.encode(self.test_data, keep=False, preserve_dict_class=True, preserve_tuples=True) self.assertEqual(ret, expected) # Now munge the expected data so that we get what we would expect if we # disable preservation of dict class and tuples expected[10] = [ 987, 654.321, _b('яйца'), _b(EGGS), None, [True, _b(EGGS), BYTES] ] expected[11][_b('subdict')][_b('tuple')] = [ 123, _b('hello'), _b('world'), True, _b(EGGS), BYTES ] expected[12] = {_b('foo'): _b('bar'), 123: 456, _b(EGGS): BYTES} ret = hubblestack.utils.data.encode(self.test_data, keep=True, preserve_dict_class=False, preserve_tuples=False) self.assertEqual(ret, expected) ret = hubblestack.utils.data.encode(self.test_data, keep=False, preserve_dict_class=False, preserve_tuples=False) self.assertEqual(ret, expected) # Now test single non-string, non-data-structure items, these should # return the same value when passed to this function for item in (123, 4.56, True, False, None): log.debug('Testing encode of %s', item) self.assertEqual(hubblestack.utils.data.encode(item), item) # Test single strings (not in a data structure) self.assertEqual(hubblestack.utils.data.encode('foo'), _b('foo')) self.assertEqual(hubblestack.utils.data.encode(_b('bar')), _b('bar')) # Test binary blob, nothing should happen even when keep=False since # the data is already bytes self.assertEqual(hubblestack.utils.data.encode(BYTES, keep=True), BYTES) self.assertEqual(hubblestack.utils.data.encode(BYTES, keep=False), BYTES)
class DataTestCase(TestCase): test_data = [ 'unicode_str', _b('питон'), 123, 456.789, True, False, None, EGGS, BYTES, [123, 456.789, _b('спам'), True, False, None, EGGS, BYTES], (987, 654.321, _b('яйца'), EGGS, None, (True, EGGS, BYTES)), { _b('str_key'): _b('str_val'), None: True, 123: 456.789, EGGS: BYTES, _b('subdict'): { 'unicode_key': EGGS, _b('tuple'): (123, 'hello', _b('world'), True, EGGS, BYTES), _b('list'): [456, _b('спам'), False, EGGS, BYTES] } }, OrderedDict([(_b('foo'), 'bar'), (123, 456), (EGGS, BYTES)]) ] def test_traverse_dict_and_list(self): test_two_level_dict = {'foo': {'bar': 'baz'}} test_two_level_dict_and_list = { 'foo': ['bar', 'baz', { 'lorem': { 'ipsum': [{ 'dolor': 'sit' }] } }] } # Check traversing too far: hubblestack.utils.data.traverse_dict_and_list() returns # the value corresponding to a given key path, and baz is a value # corresponding to the key path foo:bar. self.assertDictEqual({'not_found': 'nope'}, hubblestack.utils.data.traverse_dict_and_list( test_two_level_dict, 'foo:bar:baz', {'not_found': 'nope'})) # Now check to ensure that foo:bar corresponds to baz self.assertEqual( 'baz', hubblestack.utils.data.traverse_dict_and_list( test_two_level_dict, 'foo:bar', {'not_found': 'not_found'})) # Check traversing too far self.assertDictEqual({'not_found': 'nope'}, hubblestack.utils.data.traverse_dict_and_list( test_two_level_dict_and_list, 'foo:bar', {'not_found': 'nope'})) # Check index 1 (2nd element) of list corresponding to path 'foo' self.assertEqual( 'baz', hubblestack.utils.data.traverse_dict_and_list( test_two_level_dict_and_list, 'foo:1', {'not_found': 'not_found'})) # Traverse a couple times into dicts embedded in lists self.assertEqual( 'sit', hubblestack.utils.data.traverse_dict_and_list( test_two_level_dict_and_list, 'foo:lorem:ipsum:dolor', {'not_found': 'not_found'})) def test_compare_dicts(self): ret = hubblestack.utils.data.compare_dicts(old={'foo': 'bar'}, new={'foo': 'bar'}) self.assertEqual(ret, {}) ret = hubblestack.utils.data.compare_dicts(old={'foo': 'bar'}, new={'foo': 'woz'}) expected_ret = {'foo': {'new': 'woz', 'old': 'bar'}} self.assertDictEqual(ret, expected_ret) def test_decode(self): ''' Companion to test_decode_to_str, they should both be kept up-to-date with one another. NOTE: This uses the lambda "_b" defined above in the global scope, which encodes a string to a bytestring, assuming utf-8. ''' expected = [ 'unicode_str', 'питон', 123, 456.789, True, False, None, 'яйца', BYTES, [123, 456.789, 'спам', True, False, None, 'яйца', BYTES], (987, 654.321, 'яйца', 'яйца', None, (True, 'яйца', BYTES)), { 'str_key': 'str_val', None: True, 123: 456.789, 'яйца': BYTES, 'subdict': { 'unicode_key': 'яйца', 'tuple': (123, 'hello', 'world', True, 'яйца', BYTES), 'list': [456, 'спам', False, 'яйца', BYTES] } }, OrderedDict([('foo', 'bar'), (123, 456), ('яйца', BYTES)]) ] ret = hubblestack.utils.data.decode(self.test_data, keep=True, normalize=True, preserve_dict_class=True, preserve_tuples=True) self.assertEqual(ret, expected) # The binary data in the data structure should fail to decode, even # using the fallback, and raise an exception. self.assertRaises(UnicodeDecodeError, hubblestack.utils.data.decode, self.test_data, keep=False, normalize=True, preserve_dict_class=True, preserve_tuples=True) # Now munge the expected data so that we get what we would expect if we # disable preservation of dict class and tuples expected[10] = [ 987, 654.321, 'яйца', 'яйца', None, [True, 'яйца', BYTES] ] expected[11]['subdict']['tuple'] = [ 123, 'hello', 'world', True, 'яйца', BYTES ] expected[12] = {'foo': 'bar', 123: 456, 'яйца': BYTES} ret = hubblestack.utils.data.decode(self.test_data, keep=True, normalize=True, preserve_dict_class=False, preserve_tuples=False) self.assertEqual(ret, expected) # Now test single non-string, non-data-structure items, these should # return the same value when passed to this function for item in (123, 4.56, True, False, None): log.debug('Testing decode of %s', item) self.assertEqual(hubblestack.utils.data.decode(item), item) # Test single strings (not in a data structure) self.assertEqual(hubblestack.utils.data.decode('foo'), 'foo') self.assertEqual(hubblestack.utils.data.decode(_b('bar')), 'bar') self.assertEqual(hubblestack.utils.data.decode(EGGS, normalize=True), 'яйца') self.assertEqual(hubblestack.utils.data.decode(EGGS, normalize=False), EGGS) # Test binary blob self.assertEqual(hubblestack.utils.data.decode(BYTES, keep=True), BYTES) self.assertRaises(UnicodeDecodeError, hubblestack.utils.data.decode, BYTES, keep=False) def test_decode_to_str(self): ''' Companion to test_decode, they should both be kept up-to-date with one another. NOTE: This uses the lambda "_s" defined above in the global scope, which converts the string/bytestring to a str type. ''' expected = [ _s('unicode_str'), _s('питон'), 123, 456.789, True, False, None, _s('яйца'), BYTES, [123, 456.789, _s('спам'), True, False, None, _s('яйца'), BYTES], (987, 654.321, _s('яйца'), _s('яйца'), None, (True, _s('яйца'), BYTES)), { _s('str_key'): _s('str_val'), None: True, 123: 456.789, _s('яйца'): BYTES, _s('subdict'): { _s('unicode_key'): _s('яйца'), _s('tuple'): (123, _s('hello'), _s('world'), True, _s('яйца'), BYTES), _s('list'): [456, _s('спам'), False, _s('яйца'), BYTES] } }, OrderedDict([(_s('foo'), _s('bar')), (123, 456), (_s('яйца'), BYTES)]) ] ret = hubblestack.utils.data.decode(self.test_data, keep=True, normalize=True, preserve_dict_class=True, preserve_tuples=True, to_str=True) self.assertEqual(ret, expected) # The binary data in the data structure should fail to decode, even # using the fallback, and raise an exception. self.assertRaises(UnicodeDecodeError, hubblestack.utils.data.decode, self.test_data, keep=False, normalize=True, preserve_dict_class=True, preserve_tuples=True, to_str=True) # Now munge the expected data so that we get what we would expect if we # disable preservation of dict class and tuples expected[10] = [ 987, 654.321, _s('яйца'), _s('яйца'), None, [True, _s('яйца'), BYTES] ] expected[11][_s('subdict')][_s('tuple')] = [ 123, _s('hello'), _s('world'), True, _s('яйца'), BYTES ] expected[12] = {_s('foo'): _s('bar'), 123: 456, _s('яйца'): BYTES} ret = hubblestack.utils.data.decode(self.test_data, keep=True, normalize=True, preserve_dict_class=False, preserve_tuples=False, to_str=True) self.assertEqual(ret, expected) # Now test single non-string, non-data-structure items, these should # return the same value when passed to this function for item in (123, 4.56, True, False, None): log.debug('Testing decode of %s', item) self.assertEqual(hubblestack.utils.data.decode(item, to_str=True), item) # Test single strings (not in a data structure) self.assertEqual(hubblestack.utils.data.decode('foo', to_str=True), _s('foo')) self.assertEqual(hubblestack.utils.data.decode(_b('bar'), to_str=True), _s('bar')) # Test binary blob self.assertEqual( hubblestack.utils.data.decode(BYTES, keep=True, to_str=True), BYTES) self.assertRaises(UnicodeDecodeError, hubblestack.utils.data.decode, BYTES, keep=False, to_str=True) @skipIf(NO_MOCK, NO_MOCK_REASON) def test_decode_fallback(self): ''' Test fallback to utf-8 ''' with patch.object(builtins, '__salt_system_encoding__', 'ascii'): self.assertEqual(hubblestack.utils.data.decode(_b('яйца')), 'яйца') def test_encode(self): ''' NOTE: This uses the lambda "_b" defined above in the global scope, which encodes a string to a bytestring, assuming utf-8. ''' expected = [ _b('unicode_str'), _b('питон'), 123, 456.789, True, False, None, _b(EGGS), BYTES, [123, 456.789, _b('спам'), True, False, None, _b(EGGS), BYTES], (987, 654.321, _b('яйца'), _b(EGGS), None, (True, _b(EGGS), BYTES)), { _b('str_key'): _b('str_val'), None: True, 123: 456.789, _b(EGGS): BYTES, _b('subdict'): { _b('unicode_key'): _b(EGGS), _b('tuple'): (123, _b('hello'), _b('world'), True, _b(EGGS), BYTES), _b('list'): [456, _b('спам'), False, _b(EGGS), BYTES] } }, OrderedDict([(_b('foo'), _b('bar')), (123, 456), (_b(EGGS), BYTES)]) ] # Both keep=True and keep=False should work because the BYTES data is # already bytes. ret = hubblestack.utils.data.encode(self.test_data, keep=True, preserve_dict_class=True, preserve_tuples=True) self.assertEqual(ret, expected) ret = hubblestack.utils.data.encode(self.test_data, keep=False, preserve_dict_class=True, preserve_tuples=True) self.assertEqual(ret, expected) # Now munge the expected data so that we get what we would expect if we # disable preservation of dict class and tuples expected[10] = [ 987, 654.321, _b('яйца'), _b(EGGS), None, [True, _b(EGGS), BYTES] ] expected[11][_b('subdict')][_b('tuple')] = [ 123, _b('hello'), _b('world'), True, _b(EGGS), BYTES ] expected[12] = {_b('foo'): _b('bar'), 123: 456, _b(EGGS): BYTES} ret = hubblestack.utils.data.encode(self.test_data, keep=True, preserve_dict_class=False, preserve_tuples=False) self.assertEqual(ret, expected) ret = hubblestack.utils.data.encode(self.test_data, keep=False, preserve_dict_class=False, preserve_tuples=False) self.assertEqual(ret, expected) # Now test single non-string, non-data-structure items, these should # return the same value when passed to this function for item in (123, 4.56, True, False, None): log.debug('Testing encode of %s', item) self.assertEqual(hubblestack.utils.data.encode(item), item) # Test single strings (not in a data structure) self.assertEqual(hubblestack.utils.data.encode('foo'), _b('foo')) self.assertEqual(hubblestack.utils.data.encode(_b('bar')), _b('bar')) # Test binary blob, nothing should happen even when keep=False since # the data is already bytes self.assertEqual(hubblestack.utils.data.encode(BYTES, keep=True), BYTES) self.assertEqual(hubblestack.utils.data.encode(BYTES, keep=False), BYTES) def test_encode_keep(self): ''' Whereas we tested the keep argument in test_decode, it is much easier to do a more comprehensive test of keep in its own function where we can force the encoding. ''' unicode_str = 'питон' encoding = 'ascii' # Test single string self.assertEqual( hubblestack.utils.data.encode(unicode_str, encoding, keep=True), unicode_str) self.assertRaises(UnicodeEncodeError, hubblestack.utils.data.encode, unicode_str, encoding, keep=False) data = [ unicode_str, [b'foo', [unicode_str], { b'key': unicode_str }, (unicode_str, )], { b'list': [b'foo', unicode_str], b'dict': { b'key': unicode_str }, b'tuple': (b'foo', unicode_str) }, ([b'foo', unicode_str], { b'key': unicode_str }, (unicode_str, )) ] # Since everything was a bytestring aside from the bogus data, the # return data should be identical. We don't need to test recursive # decoding, that has already been tested in test_encode. self.assertEqual( hubblestack.utils.data.encode(data, encoding, keep=True, preserve_tuples=True), data) self.assertRaises(UnicodeEncodeError, hubblestack.utils.data.encode, data, encoding, keep=False, preserve_tuples=True) for index, item in enumerate(data): self.assertEqual( hubblestack.utils.data.encode(data[index], encoding, keep=True, preserve_tuples=True), data[index]) self.assertRaises(UnicodeEncodeError, hubblestack.utils.data.encode, data[index], encoding, keep=False, preserve_tuples=True) @skipIf(NO_MOCK, NO_MOCK_REASON) def test_encode_fallback(self): ''' Test fallback to utf-8 ''' with patch.object(builtins, '__salt_system_encoding__', 'ascii'): self.assertEqual(hubblestack.utils.data.encode('яйца'), _b('яйца')) with patch.object(builtins, '__salt_system_encoding__', 'CP1252'): self.assertEqual(hubblestack.utils.data.encode('Ψ'), _b('Ψ')) def test_repack_dict(self): list_of_one_element_dicts = [{ 'dict_key_1': 'dict_val_1' }, { 'dict_key_2': 'dict_val_2' }, { 'dict_key_3': 'dict_val_3' }] expected_ret = { 'dict_key_1': 'dict_val_1', 'dict_key_2': 'dict_val_2', 'dict_key_3': 'dict_val_3' } ret = hubblestack.utils.data.repack_dictlist(list_of_one_element_dicts) self.assertDictEqual(ret, expected_ret) # Try with yaml yaml_key_val_pair = '- key1: val1' ret = hubblestack.utils.data.repack_dictlist(yaml_key_val_pair) self.assertDictEqual(ret, {'key1': 'val1'}) # Make sure we handle non-yaml junk data ret = hubblestack.utils.data.repack_dictlist(LOREM_IPSUM) self.assertDictEqual(ret, {}) def test_stringify(self): self.assertRaises(TypeError, hubblestack.utils.data.stringify, 9) self.assertEqual( hubblestack.utils.data.stringify( ['one', 'two', str('three'), 4, 5]), # future lint: disable=blacklisted-function ['one', 'two', 'three', '4', '5']) def test_subdict_match(self): test_two_level_dict = {"foo": {"bar": "baz"}} test_two_level_comb_dict = {"foo": {"bar": "baz:woz"}} test_two_level_dict_and_list = { "abc": ["def", "ghi", { "lorem": { "ipsum": [{ "dolor": "sit" }] } }], } test_three_level_dict = {"a": {"b": {"c": "v"}}} self.assertTrue( hubblestack.utils.data.subdict_match(test_two_level_dict, "foo:bar:baz")) # In test_two_level_comb_dict, 'foo:bar' corresponds to 'baz:woz', not # 'baz'. This match should return False. self.assertFalse( hubblestack.utils.data.subdict_match(test_two_level_comb_dict, "foo:bar:baz")) # This tests matching with the delimiter in the value part (in other # words, that the path 'foo:bar' corresponds to the string 'baz:woz'). self.assertTrue( hubblestack.utils.data.subdict_match(test_two_level_comb_dict, "foo:bar:baz:woz")) # This would match if test_two_level_comb_dict['foo']['bar'] was equal # to 'baz:woz:wiz', or if there was more deep nesting. But it does not, # so this should return False. self.assertFalse( hubblestack.utils.data.subdict_match(test_two_level_comb_dict, "foo:bar:baz:woz:wiz")) # This tests for cases when a key path corresponds to a list. The # value part 'ghi' should be successfully matched as it is a member of # the list corresponding to key path 'abc'. It is somewhat a # duplication of a test within test_traverse_dict_and_list, but # hubblestack.utils.data.subdict_match() does more than just invoke # hubblestack.utils.traverse_list_and_dict() so this particular assertion is a # sanity check. self.assertTrue( hubblestack.utils.data.subdict_match(test_two_level_dict_and_list, "abc:ghi")) # This tests the use case of a dict embedded in a list, embedded in a # list, embedded in a dict. This is a rather absurd case, but it # confirms that match recursion works properly. self.assertTrue( hubblestack.utils.data.subdict_match(test_two_level_dict_and_list, "abc:lorem:ipsum:dolor:sit")) # Test four level dict match for reference self.assertTrue( hubblestack.utils.data.subdict_match(test_three_level_dict, "a:b:c:v")) # Test regression in 2015.8 where 'a:c:v' would match 'a:b:c:v' self.assertFalse( hubblestack.utils.data.subdict_match(test_three_level_dict, "a:c:v")) # Test wildcard match self.assertTrue( hubblestack.utils.data.subdict_match(test_three_level_dict, "a:*:c:v")) def test_subdict_match_with_wildcards(self): """ Tests subdict matching when wildcards are used in the expression """ data = { "a": { "b": { "ç": "d", "é": ["eff", "gee", "8ch"], "ĩ": { "j": "k" } } } } assert hubblestack.utils.data.subdict_match(data, "*:*:*:*") assert hubblestack.utils.data.subdict_match(data, "a:*:*:*") assert hubblestack.utils.data.subdict_match(data, "a:b:*:*") assert hubblestack.utils.data.subdict_match(data, "a:b:ç:*") assert hubblestack.utils.data.subdict_match(data, "a:b:*:d") assert hubblestack.utils.data.subdict_match(data, "a:*:ç:d") assert hubblestack.utils.data.subdict_match(data, "*:b:ç:d") assert hubblestack.utils.data.subdict_match(data, "*:*:ç:d") assert hubblestack.utils.data.subdict_match(data, "*:*:*:d") assert hubblestack.utils.data.subdict_match(data, "a:*:*:d") assert hubblestack.utils.data.subdict_match(data, "a:b:*:ef*") assert hubblestack.utils.data.subdict_match(data, "a:b:*:g*") assert hubblestack.utils.data.subdict_match(data, "a:b:*:j:*") assert hubblestack.utils.data.subdict_match(data, "a:b:*:j:k") assert hubblestack.utils.data.subdict_match(data, "a:b:*:*:k") assert hubblestack.utils.data.subdict_match(data, "a:b:*:*:*")
def test_decode_to_str(self): ''' Companion to test_decode, they should both be kept up-to-date with one another. NOTE: This uses the lambda "_s" defined above in the global scope, which converts the string/bytestring to a str type. ''' expected = [ _s('unicode_str'), _s('питон'), 123, 456.789, True, False, None, _s('яйца'), BYTES, [123, 456.789, _s('спам'), True, False, None, _s('яйца'), BYTES], (987, 654.321, _s('яйца'), _s('яйца'), None, (True, _s('яйца'), BYTES)), { _s('str_key'): _s('str_val'), None: True, 123: 456.789, _s('яйца'): BYTES, _s('subdict'): { _s('unicode_key'): _s('яйца'), _s('tuple'): (123, _s('hello'), _s('world'), True, _s('яйца'), BYTES), _s('list'): [456, _s('спам'), False, _s('яйца'), BYTES] } }, OrderedDict([(_s('foo'), _s('bar')), (123, 456), (_s('яйца'), BYTES)]) ] ret = hubblestack.utils.data.decode(self.test_data, keep=True, normalize=True, preserve_dict_class=True, preserve_tuples=True, to_str=True) self.assertEqual(ret, expected) # The binary data in the data structure should fail to decode, even # using the fallback, and raise an exception. self.assertRaises(UnicodeDecodeError, hubblestack.utils.data.decode, self.test_data, keep=False, normalize=True, preserve_dict_class=True, preserve_tuples=True, to_str=True) # Now munge the expected data so that we get what we would expect if we # disable preservation of dict class and tuples expected[10] = [ 987, 654.321, _s('яйца'), _s('яйца'), None, [True, _s('яйца'), BYTES] ] expected[11][_s('subdict')][_s('tuple')] = [ 123, _s('hello'), _s('world'), True, _s('яйца'), BYTES ] expected[12] = {_s('foo'): _s('bar'), 123: 456, _s('яйца'): BYTES} ret = hubblestack.utils.data.decode(self.test_data, keep=True, normalize=True, preserve_dict_class=False, preserve_tuples=False, to_str=True) self.assertEqual(ret, expected) # Now test single non-string, non-data-structure items, these should # return the same value when passed to this function for item in (123, 4.56, True, False, None): log.debug('Testing decode of %s', item) self.assertEqual(hubblestack.utils.data.decode(item, to_str=True), item) # Test single strings (not in a data structure) self.assertEqual(hubblestack.utils.data.decode('foo', to_str=True), _s('foo')) self.assertEqual(hubblestack.utils.data.decode(_b('bar'), to_str=True), _s('bar')) # Test binary blob self.assertEqual( hubblestack.utils.data.decode(BYTES, keep=True, to_str=True), BYTES) self.assertRaises(UnicodeDecodeError, hubblestack.utils.data.decode, BYTES, keep=False, to_str=True)
# -*- coding: utf-8 -*- ''' Application Kinds of Hubble. These are used to indicate what kind of Application is using RAET ''' from collections import namedtuple from hubblestack.utils.odict import OrderedDict # Python equivalent of an enum APPL_KINDS = OrderedDict([('master', 0), ('minion', 1), ('syndic', 2), ('caller', 3)]) APPL_KIND_NAMES = OrderedDict((v, k) for k, v in list(APPL_KINDS.items())) # inverse map ApplKind = namedtuple('ApplKind', list(APPL_KINDS.keys())) applKinds = ApplKind(**APPL_KINDS)