Rework ListProperty, fix merging issues

stix2.1
clenk 2017-04-14 10:42:17 -04:00
parent bc8bdccece
commit 35981025c5
4 changed files with 41 additions and 45 deletions

View File

@ -12,7 +12,7 @@ COMMON_PROPERTIES = {
'external_references': Property(),
'revoked': BooleanProperty(),
'created_by_ref': ReferenceProperty(type="identity"),
'object_marking_refs': ListProperty(ReferenceProperty, element_type="marking-definition"),
'object_marking_refs': ListProperty(ReferenceProperty(type="marking-definition")),
'granular_markings': ListProperty(Property)
}

View File

@ -5,14 +5,21 @@ from .properties import IDProperty, TypeProperty, ListProperty, ReferencePropert
from .utils import NOW
class GranularMarking(_STIXBase):
_properties = {
'marking_ref': ReferenceProperty(required=True, type="marking-definition"),
'selectors': ListProperty(SelectorProperty, required=True),
}
class MarkingDefinition(_STIXBase):
_type = 'marking-definition'
_properties = {
'created': Property(default=lambda: NOW),
'external_references': Property(),
'created_by_ref': ReferenceProperty(type="identity"),
'object_marking_refs': ListProperty(ReferenceProperty, element_type="marking-definition"),
'granular_marking': ListProperty(Property, element_type="granular-marking"),
'object_marking_refs': ListProperty(ReferenceProperty(type="marking-definition")),
'granular_marking': ListProperty(GranularMarking),
'type': TypeProperty(_type),
'id': IDProperty(_type),
'definition_type': Property(),
@ -20,13 +27,6 @@ class MarkingDefinition(_STIXBase):
}
class GranularMarking(_STIXBase):
_properties = {
'marking_ref': ReferenceProperty(required=True, type="marking-definition"),
'selectors': ListProperty(SelectorProperty, required=True),
}
class TLPMarking(_STIXBase):
# TODO: don't allow the creation of any other TLPMarkings than the ones below
_properties = {

View File

@ -4,6 +4,7 @@ from six import PY2
import datetime as dt
import pytz
from dateutil import parser
import inspect
from .base import _STIXBase
@ -77,45 +78,31 @@ class Property(object):
pass
return value
def __call__(self, value=None):
if value is not None:
return value
class ListProperty(Property):
def __init__(self, contained, element_type=None, **kwargs):
def __init__(self, contained, **kwargs):
"""
contained should be a type whose constructor creates an object from the value
Contained should be a function which returns an object from the value.
"""
if contained == StringProperty:
self.contained = StringProperty().string_type
elif contained == BooleanProperty:
self.contained = bool
elif inspect.isclass(contained) and issubclass(contained, Property):
# If it's a class and not an instance, instantiate it so that
# validate() can be called on it, and ListProperty.validate() will
# use __call__ when it appends the item.
self.contained = contained()
else:
self.contained = contained
self.element_type = element_type
super(ListProperty, self).__init__(**kwargs)
def validate(self, value):
try:
list_ = self.clean(value)
except ValueError:
raise
# STIX spec forbids empty lists
if len(list_) < 1:
raise ValueError("must not be empty.")
try:
for item in list_:
self.contained.validate(item)
except ValueError:
raise
except AttributeError:
# type of list has no validate() function (eg. built in Python types)
# TODO Should we raise an error here?
pass
return list_
def clean(self, value):
try:
iter(value)
except TypeError:
@ -124,14 +111,23 @@ class ListProperty(Property):
result = []
for item in value:
try:
if type(item) is dict:
result.append(self.contained(**item))
elif isinstance(item, ReferenceProperty):
result.append(self.contained(type=self.element_type))
else:
result.append(self.contained(item))
except TypeError:
raise ValueError("the type of objects in the list must have a constructor that creates an object from the value.")
valid = self.contained.validate(item)
except ValueError:
raise
except AttributeError:
# type of list has no validate() function (eg. built in Python types)
# TODO Should we raise an error here?
valid = item
if type(valid) is dict:
result.append(self.contained(**valid))
else:
result.append(self.contained(valid))
# STIX spec forbids empty lists
if len(result) < 1:
raise ValueError("must not be empty.")
return result

View File

@ -45,8 +45,8 @@ class Sighting(_STIXBase):
'last_seen': Property(),
'count': Property(),
'sighting_of_ref': ReferenceProperty(required=True),
'observed_data_refs': ListProperty(ReferenceProperty, element_type="observed-data"),
'where_sighted_refs': ListProperty(ReferenceProperty, element_type="identity"),
'observed_data_refs': ListProperty(ReferenceProperty(type="observed-data")),
'where_sighted_refs': ListProperty(ReferenceProperty(type="identity")),
'summary': Property(),
})