Merge pull request #20 from emmanvg/master
Instantiate ImmutableError, more descriptive message. Check the attribute being requested actually exists in object. Fix being able to set certain empty values like: list, strings, False, etc.stix2.1
commit
35e973243f
|
@ -69,22 +69,19 @@ class _STIXBase(collections.Mapping):
|
||||||
if list_of_properties and (not list_of_properties_populated or list_of_properties_populated == set(["extensions"])):
|
if list_of_properties and (not list_of_properties_populated or list_of_properties_populated == set(["extensions"])):
|
||||||
raise AtLeastOnePropertyError(self.__class__, list_of_properties)
|
raise AtLeastOnePropertyError(self.__class__, list_of_properties)
|
||||||
|
|
||||||
def _check_properties_dependency(self, list_of_properties, list_of_dependent_properties, values=[]):
|
def _check_properties_dependency(self, list_of_properties, list_of_dependent_properties):
|
||||||
failed_dependency_pairs = []
|
failed_dependency_pairs = []
|
||||||
current_properties = self.properties_populated()
|
|
||||||
for p in list_of_properties:
|
for p in list_of_properties:
|
||||||
v = values.pop() if values else None
|
|
||||||
for dp in list_of_dependent_properties:
|
for dp in list_of_dependent_properties:
|
||||||
if dp in current_properties and (p not in current_properties or (v and not current_properties(p) == v)):
|
if not self.__getattr__(p) and self.__getattr__(dp):
|
||||||
failed_dependency_pairs.append((p, dp))
|
failed_dependency_pairs.append((p, dp))
|
||||||
if failed_dependency_pairs:
|
if failed_dependency_pairs:
|
||||||
raise DependentPropertiesError(self.__class__, failed_dependency_pairs)
|
raise DependentPropertiesError(self.__class__, failed_dependency_pairs)
|
||||||
|
|
||||||
def _check_object_constraints(self):
|
def _check_object_constraints(self):
|
||||||
if self.granular_markings:
|
for m in self.get("granular_markings", []):
|
||||||
for m in self.granular_markings:
|
# TODO: check selectors
|
||||||
# TODO: check selectors
|
pass
|
||||||
pass
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
cls = self.__class__
|
cls = self.__class__
|
||||||
|
@ -100,7 +97,7 @@ class _STIXBase(collections.Mapping):
|
||||||
# Remove any keyword arguments whose value is None
|
# Remove any keyword arguments whose value is None
|
||||||
setting_kwargs = {}
|
setting_kwargs = {}
|
||||||
for prop_name, prop_value in kwargs.items():
|
for prop_name, prop_value in kwargs.items():
|
||||||
if prop_value:
|
if prop_value is not None:
|
||||||
setting_kwargs[prop_name] = prop_value
|
setting_kwargs[prop_name] = prop_value
|
||||||
|
|
||||||
# Detect any missing required properties
|
# Detect any missing required properties
|
||||||
|
@ -127,11 +124,20 @@ class _STIXBase(collections.Mapping):
|
||||||
|
|
||||||
# Handle attribute access just like key access
|
# Handle attribute access just like key access
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
return self.get(name)
|
try:
|
||||||
|
# Return attribute value.
|
||||||
|
return self.__getitem__(name)
|
||||||
|
except KeyError:
|
||||||
|
# If attribute not found, check if its a property of the object.
|
||||||
|
if name in self._properties:
|
||||||
|
return None
|
||||||
|
|
||||||
|
raise AttributeError("'%s' object has no attribute '%s'" %
|
||||||
|
(self.__class__.__name__, name))
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
if name != '_inner' and not name.startswith("_STIXBase__"):
|
if name != '_inner' and not name.startswith("_STIXBase__"):
|
||||||
raise ImmutableError
|
raise ImmutableError(self.__class__, name)
|
||||||
super(_STIXBase, self).__setattr__(name, value)
|
super(_STIXBase, self).__setattr__(name, value)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
|
@ -47,8 +47,14 @@ class ExtraPropertiesError(STIXError, TypeError):
|
||||||
class ImmutableError(STIXError, ValueError):
|
class ImmutableError(STIXError, ValueError):
|
||||||
"""Attempted to modify an object after creation"""
|
"""Attempted to modify an object after creation"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, cls, key):
|
||||||
super(ImmutableError, self).__init__("Cannot modify properties after creation.")
|
super(ImmutableError, self).__init__()
|
||||||
|
self.cls = cls
|
||||||
|
self.key = key
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
msg = "Cannot modify '{0.key}' property in '{0.cls.__name__}' after creation."
|
||||||
|
return msg.format(self)
|
||||||
|
|
||||||
|
|
||||||
class DictionaryKeyError(STIXError, ValueError):
|
class DictionaryKeyError(STIXError, ValueError):
|
||||||
|
|
|
@ -129,7 +129,7 @@ def test_cannot_assign_to_indicator_attributes(indicator):
|
||||||
with pytest.raises(stix2.exceptions.ImmutableError) as excinfo:
|
with pytest.raises(stix2.exceptions.ImmutableError) as excinfo:
|
||||||
indicator.valid_from = dt.datetime.now()
|
indicator.valid_from = dt.datetime.now()
|
||||||
|
|
||||||
assert str(excinfo.value) == "Cannot modify properties after creation."
|
assert str(excinfo.value) == "Cannot modify 'valid_from' property in 'Indicator' after creation."
|
||||||
|
|
||||||
|
|
||||||
def test_invalid_kwarg_to_indicator():
|
def test_invalid_kwarg_to_indicator():
|
||||||
|
|
|
@ -92,7 +92,7 @@ def test_cannot_assign_to_malware_attributes(malware):
|
||||||
with pytest.raises(stix2.exceptions.ImmutableError) as excinfo:
|
with pytest.raises(stix2.exceptions.ImmutableError) as excinfo:
|
||||||
malware.name = "Cryptolocker II"
|
malware.name = "Cryptolocker II"
|
||||||
|
|
||||||
assert str(excinfo.value) == "Cannot modify properties after creation."
|
assert str(excinfo.value) == "Cannot modify 'name' property in 'Malware' after creation."
|
||||||
|
|
||||||
|
|
||||||
def test_invalid_kwarg_to_malware():
|
def test_invalid_kwarg_to_malware():
|
||||||
|
|
|
@ -764,8 +764,7 @@ def test_file_example_encryption_error():
|
||||||
with pytest.raises(stix2.exceptions.DependentPropertiesError) as excinfo:
|
with pytest.raises(stix2.exceptions.DependentPropertiesError) as excinfo:
|
||||||
stix2.File(name="qwerty.dll",
|
stix2.File(name="qwerty.dll",
|
||||||
is_encrypted=False,
|
is_encrypted=False,
|
||||||
encryption_algorithm="AES128-CBC"
|
encryption_algorithm="AES128-CBC")
|
||||||
)
|
|
||||||
|
|
||||||
assert excinfo.value.cls == stix2.File
|
assert excinfo.value.cls == stix2.File
|
||||||
assert excinfo.value.dependencies == [("is_encrypted", "encryption_algorithm")]
|
assert excinfo.value.dependencies == [("is_encrypted", "encryption_algorithm")]
|
||||||
|
|
|
@ -103,7 +103,7 @@ def test_cannot_assign_to_relationship_attributes(relationship):
|
||||||
with pytest.raises(stix2.exceptions.ImmutableError) as excinfo:
|
with pytest.raises(stix2.exceptions.ImmutableError) as excinfo:
|
||||||
relationship.relationship_type = "derived-from"
|
relationship.relationship_type = "derived-from"
|
||||||
|
|
||||||
assert str(excinfo.value) == "Cannot modify properties after creation."
|
assert str(excinfo.value) == "Cannot modify 'relationship_type' property in 'Relationship' after creation."
|
||||||
|
|
||||||
|
|
||||||
def test_invalid_kwarg_to_relationship():
|
def test_invalid_kwarg_to_relationship():
|
||||||
|
|
Loading…
Reference in New Issue