Repository: oasis-open/cti-python-stix2
Pull request #271 (2019-06-25 20:00:18)

Update observed-data SDO class for stix2.1
Update observed-data SDO class, adding the new stix2.1 property "object_refs".  Added a couple tests for it.


Patch:
diff --git a/stix2/v21/sdo.py b/stix2/v21/sdo.py
index ffdc5e1..70e81e4 100644
--- a/stix2/v21/sdo.py
+++ b/stix2/v21/sdo.py
@@ -349,7 +349,8 @@ class ObservedData(STIXDomainObject):
         ('first_observed', TimestampProperty(required=True)),
         ('last_observed', TimestampProperty(required=True)),
         ('number_observed', IntegerProperty(min=1, max=999999999, required=True)),
-        ('objects', ObservableProperty(spec_version='2.1', required=True)),
+        ('objects', ObservableProperty(spec_version='2.1')),
+        ('object_refs', ListProperty(ReferenceProperty(spec_version="2.1"))),
         ('revoked', BooleanProperty(default=lambda: False)),
         ('labels', ListProperty(StringProperty)),
         ('confidence', IntegerProperty()),
@@ -379,6 +380,10 @@ class ObservedData(STIXDomainObject):
             msg = "{0.id} 'last_observed' must be greater than or equal to 'first_observed'"
             raise ValueError(msg.format(self))
 
+        self._check_mutually_exclusive_properties(
+            ["objects", "object_refs"],
+        )
+
 
 class Opinion(STIXDomainObject):
     # TODO: Add link


Test patch:
diff --git a/stix2/test/v21/test_observed_data.py b/stix2/test/v21/test_observed_data.py
index e729f60..8dd4487 100644
--- a/stix2/test/v21/test_observed_data.py
+++ b/stix2/test/v21/test_observed_data.py
@@ -5,6 +5,7 @@ import pytest
 import pytz
 
 import stix2
+import stix2.exceptions
 
 from .constants import OBSERVED_DATA_ID
 
@@ -101,6 +102,67 @@ def test_observed_data_example_with_refs():
     assert str(observed_data) == EXPECTED_WITH_REF
 
 
+EXPECTED_OBJECT_REFS = """{
+    "type": "observed-data",
+    "spec_version": "2.1",
+    "id": "observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
+    "created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
+    "created": "2016-04-06T19:58:16.000Z",
+    "modified": "2016-04-06T19:58:16.000Z",
+    "first_observed": "2015-12-21T19:00:00Z",
+    "last_observed": "2015-12-21T19:00:00Z",
+    "number_observed": 50,
+    "object_refs": [
+        "foo--758bf2c0-a6f1-56d1-872e-6b727467739a",
+        "bar--d97ed5c4-3f33-46d9-b25b-c3d7b94d1457",
+        "baz--eca0b3ba-8d76-11e9-a1fd-34415dabec0c"
+    ]
+}"""
+
+
+def test_observed_data_example_with_object_refs():
+    observed_data = stix2.v21.ObservedData(
+        id="observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
+        created_by_ref="identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
+        created="2016-04-06T19:58:16.000Z",
+        modified="2016-04-06T19:58:16.000Z",
+        first_observed="2015-12-21T19:00:00Z",
+        last_observed="2015-12-21T19:00:00Z",
+        number_observed=50,
+        object_refs=[
+            "foo--758bf2c0-a6f1-56d1-872e-6b727467739a",
+            "bar--d97ed5c4-3f33-46d9-b25b-c3d7b94d1457",
+            "baz--eca0b3ba-8d76-11e9-a1fd-34415dabec0c",
+        ],
+    )
+
+    assert str(observed_data) == EXPECTED_OBJECT_REFS
+
+
+def test_observed_data_object_constraint():
+    with pytest.raises(stix2.exceptions.MutuallyExclusivePropertiesError):
+        stix2.v21.ObservedData(
+            id="observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
+            created_by_ref="identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
+            created="2016-04-06T19:58:16.000Z",
+            modified="2016-04-06T19:58:16.000Z",
+            first_observed="2015-12-21T19:00:00Z",
+            last_observed="2015-12-21T19:00:00Z",
+            number_observed=50,
+            objects={
+                "0": {
+                    "name": "foo.exe",
+                    "type": "file",
+                },
+            },
+            object_refs=[
+                "foo--758bf2c0-a6f1-56d1-872e-6b727467739a",
+                "bar--d97ed5c4-3f33-46d9-b25b-c3d7b94d1457",
+                "baz--eca0b3ba-8d76-11e9-a1fd-34415dabec0c",
+            ],
+        )
+
+
 def test_observed_data_example_with_bad_refs():
     with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
         stix2.v21.ObservedData(