Repository: oasis-open/cti-python-stix2

Issue:
Creating LanguageContent object has error
If you pass a language content object an empty contents dictionary, you get an exception saying it must be non-empty.  I do not see anywhere in the 2.1 specification that requires this.

```
from stix2.v21 import LanguageContent, Campaign
camp = Campaign(name='foo')
LanguageContent(object_ref=camp.id, object_modified=camp.modified, contents={})
```
produces:
```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/jmg/work/cti-i18n/p/lib/python2.7/site-packages/stix2/base.py", line 161, in __init__
    self._check_property(prop_name, prop_metadata, setting_kwargs)
  File "/Users/jmg/work/cti-i18n/p/lib/python2.7/site-packages/stix2/base.py", line 94, in _check_property
    raise InvalidValueError(self.__class__, prop_name, reason=str(exc))
stix2.exceptions.InvalidValueError: Invalid value for LanguageContent 'contents': The dictionary property must contain a non-empty dictionary
```

Discussion:

Patch:
diff --git a/stix2/properties.py b/stix2/properties.py
index 24549aa..7202f9a 100644
--- a/stix2/properties.py
+++ b/stix2/properties.py
@@ -291,8 +291,6 @@ class DictionaryProperty(Property):
             dictified = _get_dict(value)
         except ValueError:
             raise ValueError("The dictionary property must contain a dictionary")
-        if dictified == {}:
-            raise ValueError("The dictionary property must contain a non-empty dictionary")
         for k in dictified.keys():
             if self.spec_version == '2.0':
                 if len(k) < 3:
@@ -498,8 +496,6 @@ class ExtensionsProperty(DictionaryProperty):
             dictified = copy.deepcopy(dictified)
         except ValueError:
             raise ValueError("The extensions property must contain a dictionary")
-        if dictified == {}:
-            raise ValueError("The extensions property must contain a non-empty dictionary")
 
         v = 'v' + self.spec_version.replace('.', '')
 


Test patch:
diff --git a/stix2/test/v20/test_observed_data.py b/stix2/test/v20/test_observed_data.py
index 41a80d6..17d732e 100644
--- a/stix2/test/v20/test_observed_data.py
+++ b/stix2/test/v20/test_observed_data.py
@@ -1141,12 +1141,13 @@ def test_process_example_windows_process_ext_empty():
 
 
 def test_process_example_extensions_empty():
-    with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
-            stix2.v20.Process(extensions={})
+    proc = stix2.v20.Process(
+        pid=314,
+        name="foobar.exe",
+        extensions={},
+    )
 
-    assert excinfo.value.cls == stix2.v20.Process
-    assert excinfo.value.prop_name == 'extensions'
-    assert 'non-empty dictionary' in excinfo.value.reason
+    assert '{}' in str(proc)
 
 
 def test_process_example_with_WindowsProcessExt_Object():
diff --git a/stix2/test/v20/test_properties.py b/stix2/test/v20/test_properties.py
index 24c1c99..e9a513e 100644
--- a/stix2/test/v20/test_properties.py
+++ b/stix2/test/v20/test_properties.py
@@ -360,7 +360,6 @@ def test_dictionary_property_invalid_key(d):
 
 @pytest.mark.parametrize(
     "d", [
-        ({}, "The dictionary property must contain a non-empty dictionary"),
         # TODO: This error message could be made more helpful. The error is caused
         # because `json.loads()` doesn't like the *single* quotes around the key
         # name, even though they are valid in a Python dictionary. While technically
diff --git a/stix2/test/v21/test_observed_data.py b/stix2/test/v21/test_observed_data.py
index 5a5881a..d2aaf52 100644
--- a/stix2/test/v21/test_observed_data.py
+++ b/stix2/test/v21/test_observed_data.py
@@ -1115,12 +1115,12 @@ def test_process_example_windows_process_ext_empty():
 
 
 def test_process_example_extensions_empty():
-    with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
-            stix2.v21.Process(extensions={})
+    proc = stix2.v21.Process(
+        pid=314,
+        extensions={},
+    )
 
-    assert excinfo.value.cls == stix2.v21.Process
-    assert excinfo.value.prop_name == 'extensions'
-    assert 'non-empty dictionary' in excinfo.value.reason
+    assert '{}' in str(proc)
 
 
 def test_process_example_with_WindowsProcessExt_Object():
diff --git a/stix2/test/v21/test_properties.py b/stix2/test/v21/test_properties.py
index 611ec5e..298a8df 100644
--- a/stix2/test/v21/test_properties.py
+++ b/stix2/test/v21/test_properties.py
@@ -369,7 +369,6 @@ def test_dictionary_property_invalid_key(d):
 
 @pytest.mark.parametrize(
     "d", [
-        ({}, "The dictionary property must contain a non-empty dictionary"),
         # TODO: This error message could be made more helpful. The error is caused
         # because `json.loads()` doesn't like the *single* quotes around the key
         # name, even though they are valid in a Python dictionary. While technically