Rework ListProperty, fix merging issues
parent
bc8bdccece
commit
35981025c5
|
@ -12,7 +12,7 @@ COMMON_PROPERTIES = {
|
||||||
'external_references': Property(),
|
'external_references': Property(),
|
||||||
'revoked': BooleanProperty(),
|
'revoked': BooleanProperty(),
|
||||||
'created_by_ref': ReferenceProperty(type="identity"),
|
'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)
|
'granular_markings': ListProperty(Property)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,14 +5,21 @@ from .properties import IDProperty, TypeProperty, ListProperty, ReferencePropert
|
||||||
from .utils import NOW
|
from .utils import NOW
|
||||||
|
|
||||||
|
|
||||||
|
class GranularMarking(_STIXBase):
|
||||||
|
_properties = {
|
||||||
|
'marking_ref': ReferenceProperty(required=True, type="marking-definition"),
|
||||||
|
'selectors': ListProperty(SelectorProperty, required=True),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class MarkingDefinition(_STIXBase):
|
class MarkingDefinition(_STIXBase):
|
||||||
_type = 'marking-definition'
|
_type = 'marking-definition'
|
||||||
_properties = {
|
_properties = {
|
||||||
'created': Property(default=lambda: NOW),
|
'created': Property(default=lambda: NOW),
|
||||||
'external_references': Property(),
|
'external_references': Property(),
|
||||||
'created_by_ref': ReferenceProperty(type="identity"),
|
'created_by_ref': ReferenceProperty(type="identity"),
|
||||||
'object_marking_refs': ListProperty(ReferenceProperty, element_type="marking-definition"),
|
'object_marking_refs': ListProperty(ReferenceProperty(type="marking-definition")),
|
||||||
'granular_marking': ListProperty(Property, element_type="granular-marking"),
|
'granular_marking': ListProperty(GranularMarking),
|
||||||
'type': TypeProperty(_type),
|
'type': TypeProperty(_type),
|
||||||
'id': IDProperty(_type),
|
'id': IDProperty(_type),
|
||||||
'definition_type': Property(),
|
'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):
|
class TLPMarking(_STIXBase):
|
||||||
# TODO: don't allow the creation of any other TLPMarkings than the ones below
|
# TODO: don't allow the creation of any other TLPMarkings than the ones below
|
||||||
_properties = {
|
_properties = {
|
||||||
|
|
|
@ -4,6 +4,7 @@ from six import PY2
|
||||||
import datetime as dt
|
import datetime as dt
|
||||||
import pytz
|
import pytz
|
||||||
from dateutil import parser
|
from dateutil import parser
|
||||||
|
import inspect
|
||||||
from .base import _STIXBase
|
from .base import _STIXBase
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,45 +78,31 @@ class Property(object):
|
||||||
pass
|
pass
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def __call__(self, value=None):
|
||||||
|
if value is not None:
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
class ListProperty(Property):
|
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:
|
if contained == StringProperty:
|
||||||
self.contained = StringProperty().string_type
|
self.contained = StringProperty().string_type
|
||||||
elif contained == BooleanProperty:
|
elif contained == BooleanProperty:
|
||||||
self.contained = bool
|
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:
|
else:
|
||||||
self.contained = contained
|
self.contained = contained
|
||||||
self.element_type = element_type
|
|
||||||
super(ListProperty, self).__init__(**kwargs)
|
super(ListProperty, self).__init__(**kwargs)
|
||||||
|
|
||||||
def validate(self, value):
|
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:
|
try:
|
||||||
iter(value)
|
iter(value)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
@ -124,14 +111,23 @@ class ListProperty(Property):
|
||||||
result = []
|
result = []
|
||||||
for item in value:
|
for item in value:
|
||||||
try:
|
try:
|
||||||
if type(item) is dict:
|
valid = self.contained.validate(item)
|
||||||
result.append(self.contained(**item))
|
except ValueError:
|
||||||
elif isinstance(item, ReferenceProperty):
|
raise
|
||||||
result.append(self.contained(type=self.element_type))
|
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:
|
else:
|
||||||
result.append(self.contained(item))
|
result.append(self.contained(valid))
|
||||||
except TypeError:
|
|
||||||
raise ValueError("the type of objects in the list must have a constructor that creates an object from the value.")
|
# STIX spec forbids empty lists
|
||||||
|
if len(result) < 1:
|
||||||
|
raise ValueError("must not be empty.")
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,8 @@ class Sighting(_STIXBase):
|
||||||
'last_seen': Property(),
|
'last_seen': Property(),
|
||||||
'count': Property(),
|
'count': Property(),
|
||||||
'sighting_of_ref': ReferenceProperty(required=True),
|
'sighting_of_ref': ReferenceProperty(required=True),
|
||||||
'observed_data_refs': ListProperty(ReferenceProperty, element_type="observed-data"),
|
'observed_data_refs': ListProperty(ReferenceProperty(type="observed-data")),
|
||||||
'where_sighted_refs': ListProperty(ReferenceProperty, element_type="identity"),
|
'where_sighted_refs': ListProperty(ReferenceProperty(type="identity")),
|
||||||
'summary': Property(),
|
'summary': Property(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue