Merge branch 'documentation' of https://github.com/oasis-open/cti-python-stix2 into documentation

stix2.1
= 2017-09-24 18:15:53 -04:00
commit 54e917110e
22 changed files with 88 additions and 75 deletions

View File

@ -1,5 +0,0 @@
base
==========
.. automodule:: stix2.base
:members:

View File

@ -19,6 +19,7 @@ autodoc_member_order = 'groupwise'
autosummary_generate = True autosummary_generate = True
napoleon_numpy_docstring = False # Force consistency, leave only Google napoleon_numpy_docstring = False # Force consistency, leave only Google
napoleon_use_rtype = False napoleon_use_rtype = False
add_module_names = False
templates_path = ['_templates'] templates_path = ['_templates']
source_suffix = '.rst' source_suffix = '.rst'

View File

@ -3,7 +3,6 @@
.. autosummary:: .. autosummary::
:toctree: api :toctree: api
base
common common
core core
environment environment

View File

@ -65,7 +65,7 @@ class StatementMarking(_STIXBase):
class MarkingProperty(Property): class MarkingProperty(Property):
"""Represent the marking objects in the `definition` property of """Represent the marking objects in the ``definition`` property of
marking-definition objects. marking-definition objects.
""" """
@ -120,17 +120,15 @@ def _register_marking(cls):
def CustomMarking(type='x-custom-marking', properties=None): def CustomMarking(type='x-custom-marking', properties=None):
""" """Custom STIX Marking decorator.
Custom STIX Marking decorator.
Examples: Example:
>>> @CustomMarking('x-custom-marking', [
@CustomMarking('x-custom-marking', [ ... ('property1', StringProperty(required=True)),
('property1', StringProperty(required=True)), ... ('property2', IntegerProperty()),
('property2', IntegerProperty()), ... ])
]) ... class MyNewMarkingObjectType():
class MyNewMarkingObjectType(): ... pass
pass
""" """
def custom_builder(cls): def custom_builder(cls):

View File

@ -1,4 +1,4 @@
"""STIX 2.0 Objects that are neither SDOs nor SROs""" """STIX 2.0 Objects that are neither SDOs nor SROs."""
from collections import OrderedDict from collections import OrderedDict

View File

@ -3,7 +3,7 @@ class STIXError(Exception):
class InvalidValueError(STIXError, ValueError): class InvalidValueError(STIXError, ValueError):
"""An invalid value was provided to a STIX object's __init__.""" """An invalid value was provided to a STIX object's ``__init__``."""
def __init__(self, cls, prop_name, reason): def __init__(self, cls, prop_name, reason):
super(InvalidValueError, self).__init__() super(InvalidValueError, self).__init__()
@ -45,7 +45,7 @@ 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, cls, key): def __init__(self, cls, key):
super(ImmutableError, self).__init__() super(ImmutableError, self).__init__()
@ -85,7 +85,7 @@ class InvalidObjRefError(STIXError, ValueError):
class UnmodifiablePropertyError(STIXError, ValueError): class UnmodifiablePropertyError(STIXError, ValueError):
"""Attempted to modify an unmodifiable property of object when creating a new version""" """Attempted to modify an unmodifiable property of object when creating a new version."""
def __init__(self, unchangable_properties): def __init__(self, unchangable_properties):
super(UnmodifiablePropertyError, self).__init__() super(UnmodifiablePropertyError, self).__init__()
@ -139,7 +139,7 @@ class AtLeastOnePropertyError(STIXError, TypeError):
class RevokeError(STIXError, ValueError): class RevokeError(STIXError, ValueError):
"""Attempted to an operation on a revoked object""" """Attempted to an operation on a revoked object."""
def __init__(self, called_by): def __init__(self, called_by):
super(RevokeError, self).__init__() super(RevokeError, self).__init__()
@ -153,7 +153,7 @@ class RevokeError(STIXError, ValueError):
class ParseError(STIXError, ValueError): class ParseError(STIXError, ValueError):
"""Could not parse object""" """Could not parse object."""
def __init__(self, msg): def __init__(self, msg):
super(ParseError, self).__init__(msg) super(ParseError, self).__init__(msg)

View File

@ -6,7 +6,7 @@ granular markings unless otherwise noted in each of the functions.
.. autosummary:: .. autosummary::
:toctree: api :toctree: markings
granular_markings granular_markings
object_markings object_markings

View File

@ -1,3 +1,5 @@
"""Functions for working with STIX 2.0 granular markings.
"""
from stix2 import exceptions from stix2 import exceptions
from stix2.markings import utils from stix2.markings import utils

View File

@ -1,3 +1,5 @@
"""Functions for working with STIX 2.0 object markings.
"""
from stix2 import exceptions from stix2 import exceptions
from stix2.markings import utils from stix2.markings import utils

View File

@ -1,3 +1,5 @@
"""Utility functions for STIX 2.0 data markings.
"""
import collections import collections

View File

@ -1,8 +1,8 @@
"""STIX 2.0 Cyber Observable Objects """STIX 2.0 Cyber Observable Objects.
Embedded observable object types, such as Email MIME Component, which is Embedded observable object types, such as Email MIME Component, which is
embedded in Email Message objects, inherit from _STIXBase instead of Observable embedded in Email Message objects, inherit from ``_STIXBase`` instead of
and do not have a '_type' attribute. Observable and do not have a ``_type`` attribute.
""" """
from collections import OrderedDict from collections import OrderedDict
@ -19,6 +19,8 @@ from .utils import get_dict
class ObservableProperty(Property): class ObservableProperty(Property):
"""Property for holding Cyber Observable Objects.
"""
def clean(self, value): def clean(self, value):
try: try:
@ -39,7 +41,7 @@ class ObservableProperty(Property):
class ExtensionsProperty(DictionaryProperty): class ExtensionsProperty(DictionaryProperty):
""" Property for representing extensions on Observable objects """Property for representing extensions on Observable objects.
""" """
def __init__(self, enclosing_type=None, required=False): def __init__(self, enclosing_type=None, required=False):
@ -138,7 +140,6 @@ class EmailAddress(_Observable):
('display_name', StringProperty()), ('display_name', StringProperty()),
('belongs_to_ref', ObjectReferenceProperty(valid_types='user-account')), ('belongs_to_ref', ObjectReferenceProperty(valid_types='user-account')),
('extensions', ExtensionsProperty(enclosing_type=_type)), ('extensions', ExtensionsProperty(enclosing_type=_type)),
]) ])
@ -798,16 +799,15 @@ def _register_observable(new_observable):
def CustomObservable(type='x-custom-observable', properties=None): def CustomObservable(type='x-custom-observable', properties=None):
"""Custom STIX Cyber Observable type decorator """Custom STIX Cyber Observable Object type decorator.
Example 1: Example:
>>> @CustomObservable('x-custom-observable', [
@CustomObservable('x-custom-observable', [ ... ('property1', StringProperty(required=True)),
('property1', StringProperty(required=True)), ... ('property2', IntegerProperty()),
('property2', IntegerProperty()), ... ])
]) ... class MyNewObservableType():
class MyNewObservableType(): ... pass
pass
""" """
def custom_builder(cls): def custom_builder(cls):
@ -873,7 +873,7 @@ def _register_extension(observable, new_extension):
def CustomExtension(observable=None, type='x-custom-observable', properties={}): def CustomExtension(observable=None, type='x-custom-observable', properties={}):
"""Decorator for custom extensions to STIX Cyber Observables """Decorator for custom extensions to STIX Cyber Observables.
""" """
if not observable or not issubclass(observable, _Observable): if not observable or not issubclass(observable, _Observable):

View File

@ -19,43 +19,44 @@ class Property(object):
"""Represent a property of STIX data type. """Represent a property of STIX data type.
Subclasses can define the following attributes as keyword arguments to Subclasses can define the following attributes as keyword arguments to
__init__(): ``__init__()``.
- `required` - If `True`, the property must be provided when creating an Args:
object with that property. No default value exists for these properties. required (bool): If ``True``, the property must be provided when creating an
(Default: `False`) object with that property. No default value exists for these properties.
- `fixed` - This provides a constant default value. Users are free to (Default: ``False``)
provide this value explicity when constructing an object (which allows fixed: This provides a constant default value. Users are free to
you to copy *all* values from an existing object to a new object), but provide this value explicity when constructing an object (which allows
if the user provides a value other than the `fixed` value, it will raise you to copy **all** values from an existing object to a new object), but
an error. This is semantically equivalent to defining both: if the user provides a value other than the ``fixed`` value, it will raise
- a `clean()` function that checks if the value matches the fixed an error. This is semantically equivalent to defining both:
value, and
- a `default()` function that returns the fixed value.
(Default: `None`)
Subclasses can also define the following functions. - a ``clean()`` function that checks if the value matches the fixed
value, and
- a ``default()`` function that returns the fixed value.
- `def clean(self, value) -> any:` Subclasses can also define the following functions:
- Return a value that is valid for this property. If `value` is not
- ``def clean(self, value) -> any:``
- Return a value that is valid for this property. If ``value`` is not
valid for this property, this will attempt to transform it first. If valid for this property, this will attempt to transform it first. If
`value` is not valid and no such transformation is possible, it should ``value`` is not valid and no such transformation is possible, it should
raise a ValueError. raise a ValueError.
- `def default(self):` - ``def default(self):``
- provide a default value for this property. - provide a default value for this property.
- `default()` can return the special value `NOW` to use the current - ``default()`` can return the special value ``NOW`` to use the current
time. This is useful when several timestamps in the same object need time. This is useful when several timestamps in the same object need
to use the same default value, so calling now() for each property-- to use the same default value, so calling now() for each property--
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 When instantiating Properties, ``required`` and ``default`` should not be used
together. `default` implies that the property is required in the specification together. ``default`` implies that the property is required in the specification
so this function will be used to supply a value if none is provided. 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 ``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. specification and we can't or don't want to create a default value.
""" """
@ -88,7 +89,7 @@ class ListProperty(Property):
def __init__(self, contained, **kwargs): def __init__(self, contained, **kwargs):
""" """
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 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 # If it's a class and not an instance, instantiate it so that

View File

@ -298,8 +298,8 @@ def CustomObject(type='x-custom-type', properties=None):
... class MyNewObjectType(): ... class MyNewObjectType():
... pass ... pass
Supply an __init__() function to add any special validations to the custom Supply an ``__init__()`` function to add any special validations to the custom
type. Don't call super().__init__() though - doing so will cause an error. type. Don't call ``super().__init__()`` though - doing so will cause an error.
Example: Example:
>>> @CustomObject('x-type-name', [ >>> @CustomObject('x-type-name', [

View File

@ -16,7 +16,7 @@ Note:
.. autosummary:: .. autosummary::
:toctree: api :toctree: sources
filters filters
filesystem filesystem

View File

@ -34,16 +34,21 @@ class STIXdatetime(dt.datetime):
def get_timestamp(): def get_timestamp():
"""Return a STIX timestamp of the current date and time."""
return STIXdatetime.now(tz=pytz.UTC) return STIXdatetime.now(tz=pytz.UTC)
def format_datetime(dttm): def format_datetime(dttm):
# 1. Convert to timezone-aware """Convert a datetime object into a valid STIX timestamp string.
# 2. Convert to UTC
# 3. Format in ISO format 1. Convert to timezone-aware
# 4. Ensure correct precision 2. Convert to UTC
# 4a. Add subsecond value if non-zero and precision not defined 3. Format in ISO format
# 5. Add "Z" 4. Ensure correct precision
a. Add subsecond value if non-zero and precision not defined
5. Add "Z"
"""
if dttm.tzinfo is None or dttm.tzinfo.utcoffset(dttm) is None: if dttm.tzinfo is None or dttm.tzinfo.utcoffset(dttm) is None:
# dttm is timezone-naive; assume UTC # dttm is timezone-naive; assume UTC
@ -63,6 +68,8 @@ def format_datetime(dttm):
def parse_into_datetime(value, precision=None): def parse_into_datetime(value, precision=None):
"""Parse a value into a valid STIX timestamp object.
"""
if isinstance(value, dt.date): if isinstance(value, dt.date):
if hasattr(value, 'hour'): if hasattr(value, 'hour'):
ts = value ts = value
@ -102,6 +109,7 @@ def parse_into_datetime(value, precision=None):
def get_dict(data): def get_dict(data):
"""Return data as a dictionary. """Return data as a dictionary.
Input can be a dictionary, string, or file-like object. Input can be a dictionary, string, or file-like object.
""" """
@ -124,7 +132,7 @@ def get_dict(data):
def find_property_index(obj, properties, tuple_to_find): def find_property_index(obj, properties, tuple_to_find):
"""Recursively find the property in the object model, return the index """Recursively find the property in the object model, return the index
according to the _properties OrderedDict. If its a list look for according to the _properties OrderedDict. If it's a list look for
individual objects. individual objects.
""" """
from .base import _STIXBase from .base import _STIXBase
@ -159,7 +167,7 @@ def find_property_index(obj, properties, tuple_to_find):
def new_version(data, **kwargs): def new_version(data, **kwargs):
"""Create a new version of a STIX object, by modifying properties and """Create a new version of a STIX object, by modifying properties and
updating the `modified` property. updating the ``modified`` property.
""" """
if not isinstance(data, Mapping): if not isinstance(data, Mapping):
@ -196,6 +204,11 @@ def new_version(data, **kwargs):
def revoke(data): def revoke(data):
"""Revoke a STIX object.
Returns:
A new version of the object with ``revoked`` set to ``True``.
"""
if not isinstance(data, Mapping): if not isinstance(data, Mapping):
raise ValueError('cannot revoke object of this type! Try a dictionary ' raise ValueError('cannot revoke object of this type! Try a dictionary '
'or instance of an SDO or SRO class.') 'or instance of an SDO or SRO class.')