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
Greg Back 2017-06-05 09:30:04 -05:00 committed by GitHub
commit 35e973243f
6 changed files with 29 additions and 18 deletions

View File

@ -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):

View File

@ -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):

View File

@ -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():

View File

@ -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():

View File

@ -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")]

View File

@ -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():