Fix typos, add to Property class documentation, small performance
boosts, and let strings and booleans in a ListProperty be handled by __call__().stix2.1
parent
76acd8c0c2
commit
fe4c4d78fc
|
@ -13,12 +13,7 @@ from .utils import get_dict
|
||||||
from . import exceptions
|
from . import exceptions
|
||||||
|
|
||||||
|
|
||||||
def parse(data):
|
OBJ_MAP = {
|
||||||
"""Deserialize a string or file-like object into a STIX object"""
|
|
||||||
|
|
||||||
obj = get_dict(data)
|
|
||||||
|
|
||||||
obj_map = {
|
|
||||||
'attack-pattern': AttackPattern,
|
'attack-pattern': AttackPattern,
|
||||||
'campaign': Campaign,
|
'campaign': Campaign,
|
||||||
'course-of-action': CourseOfAction,
|
'course-of-action': CourseOfAction,
|
||||||
|
@ -36,12 +31,18 @@ def parse(data):
|
||||||
'vulnerability': Vulnerability,
|
'vulnerability': Vulnerability,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def parse(data):
|
||||||
|
"""Deserialize a string or file-like object into a STIX object"""
|
||||||
|
|
||||||
|
obj = get_dict(data)
|
||||||
|
|
||||||
if 'type' not in obj:
|
if 'type' not in obj:
|
||||||
# TODO parse external references, kill chain phases, and granular markings
|
# TODO parse external references, kill chain phases, and granular markings
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
obj_class = obj_map[obj['type']]
|
obj_class = OBJ_MAP[obj['type']]
|
||||||
return obj_class(**obj)
|
return obj_class(**obj)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# TODO handle custom objects
|
# TODO handle custom objects
|
||||||
|
|
|
@ -39,7 +39,7 @@ class TLPMarking(_STIXBase):
|
||||||
|
|
||||||
class StatementMarking(_STIXBase):
|
class StatementMarking(_STIXBase):
|
||||||
_properties = {
|
_properties = {
|
||||||
'statement': Property(required=True)
|
'statement': StringProperty(required=True)
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, statement=None, **kwargs):
|
def __init__(self, statement=None, **kwargs):
|
||||||
|
|
|
@ -42,9 +42,15 @@ class Property(object):
|
||||||
to use the same default value, so calling now() for each field--
|
to use the same default value, so calling now() for each field--
|
||||||
likely several microseconds apart-- does not work.
|
likely several microseconds apart-- does not work.
|
||||||
|
|
||||||
Subclasses can instead provide a lambda function for `default as a keyword
|
Subclasses can instead provide a lambda function for `default` as a keyword
|
||||||
argument. `clean` should not be provided as a lambda since lambdas cannot
|
argument. `clean` should not be provided as a lambda since lambdas cannot
|
||||||
raise their own exceptions.
|
raise their own exceptions.
|
||||||
|
|
||||||
|
When instantiating Properties, `required` and `default` should not be used
|
||||||
|
together. `default` implies that the field is required in the specification
|
||||||
|
so this function will be used to supply a value if none is provided.
|
||||||
|
`required` means that the user must provide this; it is required in the
|
||||||
|
specification and we can't or don't want to create a default value.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _default_clean(self, value):
|
def _default_clean(self, value):
|
||||||
|
@ -66,7 +72,9 @@ class Property(object):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def __call__(self, value=None):
|
def __call__(self, value=None):
|
||||||
if value is not None:
|
"""Used by ListProperty to handle lists that have been defined with
|
||||||
|
either a class or an instance.
|
||||||
|
"""
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,11 +84,7 @@ class ListProperty(Property):
|
||||||
"""
|
"""
|
||||||
Contained should be a function which returns an object from the value.
|
Contained should be a function which returns an object from the value.
|
||||||
"""
|
"""
|
||||||
if contained == StringProperty:
|
if inspect.isclass(contained) and issubclass(contained, Property):
|
||||||
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
|
# If it's a class and not an instance, instantiate it so that
|
||||||
# clean() can be called on it, and ListProperty.clean() will
|
# clean() can be called on it, and ListProperty.clean() will
|
||||||
# use __call__ when it appends the item.
|
# use __call__ when it appends the item.
|
||||||
|
@ -191,7 +195,7 @@ class TimestampProperty(Property):
|
||||||
return value
|
return value
|
||||||
else:
|
else:
|
||||||
# Add a time component
|
# Add a time component
|
||||||
return dt.datetime.combine(value, dt.time(), tzinfo=pytz.timezone('US/Eastern'))
|
return dt.datetime.combine(value, dt.time(), tzinfo=pytz.utc)
|
||||||
|
|
||||||
# value isn't a date or datetime object so assume it's a string
|
# value isn't a date or datetime object so assume it's a string
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Reference in New Issue