diff --git a/stix2/test/test_custom.py b/stix2/test/test_custom.py index a14503f..b45670f 100644 --- a/stix2/test/test_custom.py +++ b/stix2/test/test_custom.py @@ -479,6 +479,27 @@ def test_custom_extension_wrong_observable_type(): assert 'Cannot determine extension type' in excinfo.value.reason +@pytest.mark.parametrize("data", [ + """{ + "keys": [ + { + "test123": 123, + "test345": "aaaa" + } + ] +}""", +]) +def test_custom_extension_with_list_and_dict_properties_observable_type(data): + @stix2.observables.CustomExtension(stix2.UserAccount, 'some-extension', [ + ('keys', stix2.properties.ListProperty(stix2.properties.DictionaryProperty, required=True)) + ]) + class SomeCustomExtension: + pass + + example = SomeCustomExtension(keys=[{'test123': 123, 'test345': 'aaaa'}]) + assert data == str(example) + + def test_custom_extension_invalid_observable(): # These extensions are being applied to improperly-created Observables. # The Observable classes should have been created with the CustomObservable decorator. diff --git a/stix2/utils.py b/stix2/utils.py index 9febd78..4ef3d23 100644 --- a/stix2/utils.py +++ b/stix2/utils.py @@ -166,7 +166,7 @@ def get_dict(data): def find_property_index(obj, properties, tuple_to_find): """Recursively find the property in the object model, return the index according to the _properties OrderedDict. If it's a list look for - individual objects. + individual objects. Returns and integer indicating its location """ from .base import _STIXBase try: @@ -183,6 +183,11 @@ def find_property_index(obj, properties, tuple_to_find): tuple_to_find) if val is not None: return val + elif isinstance(item, dict): + for idx, val in enumerate(sorted(item)): + if (tuple_to_find[0] == val and + item.get(val) == tuple_to_find[1]): + return idx elif isinstance(pv, dict): if pv.get(tuple_to_find[0]) is not None: try: