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,35 +13,36 @@ from .utils import get_dict
|
|||
from . import exceptions
|
||||
|
||||
|
||||
OBJ_MAP = {
|
||||
'attack-pattern': AttackPattern,
|
||||
'campaign': Campaign,
|
||||
'course-of-action': CourseOfAction,
|
||||
'identity': Identity,
|
||||
'indicator': Indicator,
|
||||
'intrusion-set': IntrusionSet,
|
||||
'malware': Malware,
|
||||
'marking-definition': MarkingDefinition,
|
||||
'observed-data': ObservedData,
|
||||
'report': Report,
|
||||
'relationship': Relationship,
|
||||
'threat-actor': ThreatActor,
|
||||
'tool': Tool,
|
||||
'sighting': Sighting,
|
||||
'vulnerability': Vulnerability,
|
||||
}
|
||||
|
||||
|
||||
def parse(data):
|
||||
"""Deserialize a string or file-like object into a STIX object"""
|
||||
|
||||
obj = get_dict(data)
|
||||
|
||||
obj_map = {
|
||||
'attack-pattern': AttackPattern,
|
||||
'campaign': Campaign,
|
||||
'course-of-action': CourseOfAction,
|
||||
'identity': Identity,
|
||||
'indicator': Indicator,
|
||||
'intrusion-set': IntrusionSet,
|
||||
'malware': Malware,
|
||||
'marking-definition': MarkingDefinition,
|
||||
'observed-data': ObservedData,
|
||||
'report': Report,
|
||||
'relationship': Relationship,
|
||||
'threat-actor': ThreatActor,
|
||||
'tool': Tool,
|
||||
'sighting': Sighting,
|
||||
'vulnerability': Vulnerability,
|
||||
}
|
||||
|
||||
if 'type' not in obj:
|
||||
# TODO parse external references, kill chain phases, and granular markings
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
obj_class = obj_map[obj['type']]
|
||||
obj_class = OBJ_MAP[obj['type']]
|
||||
return obj_class(**obj)
|
||||
except KeyError:
|
||||
# TODO handle custom objects
|
||||
|
|
|
@ -39,7 +39,7 @@ class TLPMarking(_STIXBase):
|
|||
|
||||
class StatementMarking(_STIXBase):
|
||||
_properties = {
|
||||
'statement': Property(required=True)
|
||||
'statement': StringProperty(required=True)
|
||||
}
|
||||
|
||||
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--
|
||||
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
|
||||
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):
|
||||
|
@ -66,8 +72,10 @@ class Property(object):
|
|||
return value
|
||||
|
||||
def __call__(self, value=None):
|
||||
if value is not None:
|
||||
return value
|
||||
"""Used by ListProperty to handle lists that have been defined with
|
||||
either a class or an instance.
|
||||
"""
|
||||
return value
|
||||
|
||||
|
||||
class ListProperty(Property):
|
||||
|
@ -76,11 +84,7 @@ class ListProperty(Property):
|
|||
"""
|
||||
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 inspect.isclass(contained) and issubclass(contained, Property):
|
||||
# If it's a class and not an instance, instantiate it so that
|
||||
# clean() can be called on it, and ListProperty.clean() will
|
||||
# use __call__ when it appends the item.
|
||||
|
@ -191,7 +195,7 @@ class TimestampProperty(Property):
|
|||
return value
|
||||
else:
|
||||
# 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
|
||||
try:
|
||||
|
|
Loading…
Reference in New Issue