diff --git a/docs/api/api/stix2.markings.granular_markings.rst b/docs/api/markings/stix2.markings.granular_markings.rst similarity index 100% rename from docs/api/api/stix2.markings.granular_markings.rst rename to docs/api/markings/stix2.markings.granular_markings.rst diff --git a/docs/api/api/stix2.markings.object_markings.rst b/docs/api/markings/stix2.markings.object_markings.rst similarity index 100% rename from docs/api/api/stix2.markings.object_markings.rst rename to docs/api/markings/stix2.markings.object_markings.rst diff --git a/docs/api/api/stix2.markings.utils.rst b/docs/api/markings/stix2.markings.utils.rst similarity index 100% rename from docs/api/api/stix2.markings.utils.rst rename to docs/api/markings/stix2.markings.utils.rst diff --git a/docs/api/api/stix2.sources.filesystem.rst b/docs/api/sources/stix2.sources.filesystem.rst similarity index 100% rename from docs/api/api/stix2.sources.filesystem.rst rename to docs/api/sources/stix2.sources.filesystem.rst diff --git a/docs/api/api/stix2.sources.filters.rst b/docs/api/sources/stix2.sources.filters.rst similarity index 100% rename from docs/api/api/stix2.sources.filters.rst rename to docs/api/sources/stix2.sources.filters.rst diff --git a/docs/api/api/stix2.sources.memory.rst b/docs/api/sources/stix2.sources.memory.rst similarity index 100% rename from docs/api/api/stix2.sources.memory.rst rename to docs/api/sources/stix2.sources.memory.rst diff --git a/docs/api/api/stix2.sources.taxii.rst b/docs/api/sources/stix2.sources.taxii.rst similarity index 100% rename from docs/api/api/stix2.sources.taxii.rst rename to docs/api/sources/stix2.sources.taxii.rst diff --git a/docs/api/stix2.base.rst b/docs/api/stix2.base.rst deleted file mode 100644 index 459f2e5..0000000 --- a/docs/api/stix2.base.rst +++ /dev/null @@ -1,5 +0,0 @@ -base -========== - -.. automodule:: stix2.base - :members: \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index daa1d30..6a20ace 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -19,6 +19,7 @@ autodoc_member_order = 'groupwise' autosummary_generate = True napoleon_numpy_docstring = False # Force consistency, leave only Google napoleon_use_rtype = False +add_module_names = False templates_path = ['_templates'] source_suffix = '.rst' diff --git a/stix2/__init__.py b/stix2/__init__.py index 8f5239a..770f8cb 100644 --- a/stix2/__init__.py +++ b/stix2/__init__.py @@ -3,7 +3,6 @@ .. autosummary:: :toctree: api - base common core environment diff --git a/stix2/common.py b/stix2/common.py index a2e6918..8f34ed6 100644 --- a/stix2/common.py +++ b/stix2/common.py @@ -65,7 +65,7 @@ class StatementMarking(_STIXBase): class MarkingProperty(Property): - """Represent the marking objects in the `definition` property of + """Represent the marking objects in the ``definition`` property of marking-definition objects. """ @@ -120,17 +120,15 @@ def _register_marking(cls): def CustomMarking(type='x-custom-marking', properties=None): - """ - Custom STIX Marking decorator. + """Custom STIX Marking decorator. - Examples: - - @CustomMarking('x-custom-marking', [ - ('property1', StringProperty(required=True)), - ('property2', IntegerProperty()), - ]) - class MyNewMarkingObjectType(): - pass + Example: + >>> @CustomMarking('x-custom-marking', [ + ... ('property1', StringProperty(required=True)), + ... ('property2', IntegerProperty()), + ... ]) + ... class MyNewMarkingObjectType(): + ... pass """ def custom_builder(cls): diff --git a/stix2/core.py b/stix2/core.py index 0271e34..3eaabb0 100644 --- a/stix2/core.py +++ b/stix2/core.py @@ -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 diff --git a/stix2/exceptions.py b/stix2/exceptions.py index 32db472..17aa8bf 100644 --- a/stix2/exceptions.py +++ b/stix2/exceptions.py @@ -3,7 +3,7 @@ class STIXError(Exception): 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): super(InvalidValueError, self).__init__() @@ -45,7 +45,7 @@ class ExtraPropertiesError(STIXError, TypeError): class ImmutableError(STIXError, ValueError): - """Attempted to modify an object after creation""" + """Attempted to modify an object after creation.""" def __init__(self, cls, key): super(ImmutableError, self).__init__() @@ -85,7 +85,7 @@ class InvalidObjRefError(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): super(UnmodifiablePropertyError, self).__init__() @@ -139,7 +139,7 @@ class AtLeastOnePropertyError(STIXError, TypeError): 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): super(RevokeError, self).__init__() @@ -153,7 +153,7 @@ class RevokeError(STIXError, ValueError): class ParseError(STIXError, ValueError): - """Could not parse object""" + """Could not parse object.""" def __init__(self, msg): super(ParseError, self).__init__(msg) diff --git a/stix2/markings/__init__.py b/stix2/markings/__init__.py index 6c13b87..400c54d 100644 --- a/stix2/markings/__init__.py +++ b/stix2/markings/__init__.py @@ -6,7 +6,7 @@ granular markings unless otherwise noted in each of the functions. .. autosummary:: - :toctree: api + :toctree: markings granular_markings object_markings diff --git a/stix2/markings/granular_markings.py b/stix2/markings/granular_markings.py index 7e9ccc7..893428e 100644 --- a/stix2/markings/granular_markings.py +++ b/stix2/markings/granular_markings.py @@ -1,3 +1,5 @@ +"""Functions for working with STIX 2.0 granular markings. +""" from stix2 import exceptions from stix2.markings import utils diff --git a/stix2/markings/object_markings.py b/stix2/markings/object_markings.py index c39c036..ce77966 100644 --- a/stix2/markings/object_markings.py +++ b/stix2/markings/object_markings.py @@ -1,3 +1,5 @@ +"""Functions for working with STIX 2.0 object markings. +""" from stix2 import exceptions from stix2.markings import utils diff --git a/stix2/markings/utils.py b/stix2/markings/utils.py index f5400a5..6fed976 100644 --- a/stix2/markings/utils.py +++ b/stix2/markings/utils.py @@ -1,3 +1,5 @@ +"""Utility functions for STIX 2.0 data markings. +""" import collections diff --git a/stix2/observables.py b/stix2/observables.py index e9939e7..e1f6bf8 100644 --- a/stix2/observables.py +++ b/stix2/observables.py @@ -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 in Email Message objects, inherit from _STIXBase instead of Observable -and do not have a '_type' attribute. +embedded in Email Message objects, inherit from ``_STIXBase`` instead of +Observable and do not have a ``_type`` attribute. """ from collections import OrderedDict @@ -19,6 +19,8 @@ from .utils import get_dict class ObservableProperty(Property): + """Property for holding Cyber Observable Objects. + """ def clean(self, value): try: @@ -39,7 +41,7 @@ class ObservableProperty(Property): 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): @@ -138,7 +140,6 @@ class EmailAddress(_Observable): ('display_name', StringProperty()), ('belongs_to_ref', ObjectReferenceProperty(valid_types='user-account')), ('extensions', ExtensionsProperty(enclosing_type=_type)), - ]) @@ -798,16 +799,15 @@ def _register_observable(new_observable): def CustomObservable(type='x-custom-observable', properties=None): - """Custom STIX Cyber Observable type decorator + """Custom STIX Cyber Observable Object type decorator. - Example 1: - - @CustomObservable('x-custom-observable', [ - ('property1', StringProperty(required=True)), - ('property2', IntegerProperty()), - ]) - class MyNewObservableType(): - pass + Example: + >>> @CustomObservable('x-custom-observable', [ + ... ('property1', StringProperty(required=True)), + ... ('property2', IntegerProperty()), + ... ]) + ... class MyNewObservableType(): + ... pass """ def custom_builder(cls): @@ -873,7 +873,7 @@ def _register_extension(observable, new_extension): 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): diff --git a/stix2/properties.py b/stix2/properties.py index 92f1a58..afe994f 100644 --- a/stix2/properties.py +++ b/stix2/properties.py @@ -19,43 +19,44 @@ class Property(object): """Represent a property of STIX data type. Subclasses can define the following attributes as keyword arguments to - __init__(): + ``__init__()``. - - `required` - If `True`, the property must be provided when creating an - object with that property. No default value exists for these properties. - (Default: `False`) - - `fixed` - This provides a constant default value. Users are free to - provide this value explicity when constructing an object (which allows - you to copy *all* values from an existing object to a new object), but - if the user provides a value other than the `fixed` value, it will raise - an error. This is semantically equivalent to defining both: - - a `clean()` function that checks if the value matches the fixed - value, and - - a `default()` function that returns the fixed value. - (Default: `None`) + Args: + required (bool): If ``True``, the property must be provided when creating an + object with that property. No default value exists for these properties. + (Default: ``False``) + fixed: This provides a constant default value. Users are free to + provide this value explicity when constructing an object (which allows + you to copy **all** values from an existing object to a new object), but + if the user provides a value other than the ``fixed`` value, it will raise + an error. This is semantically equivalent to defining both: - 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:` - - Return a value that is valid for this property. If `value` is not + Subclasses can also define the following functions: + + - ``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 - `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. - - `def default(self):` + - ``def default(self):`` - 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 to use the same default value, so calling now() for each property-- likely several microseconds apart-- does not work. - Subclasses can instead provide a lambda function for `default` as a keyword - argument. `clean` should not be provided as a lambda since lambdas cannot + 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 property is required in the specification + When instantiating Properties, ``required`` and ``default`` should not be used + 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. - `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. """ @@ -88,7 +89,7 @@ class ListProperty(Property): 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 it's a class and not an instance, instantiate it so that diff --git a/stix2/sdo.py b/stix2/sdo.py index d24ba53..cdbb9ca 100644 --- a/stix2/sdo.py +++ b/stix2/sdo.py @@ -298,8 +298,8 @@ def CustomObject(type='x-custom-type', properties=None): ... class MyNewObjectType(): ... pass - 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. + 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. Example: >>> @CustomObject('x-type-name', [ diff --git a/stix2/sources/__init__.py b/stix2/sources/__init__.py index 8e19d1d..a8c27da 100644 --- a/stix2/sources/__init__.py +++ b/stix2/sources/__init__.py @@ -16,7 +16,7 @@ Note: .. autosummary:: - :toctree: api + :toctree: sources filters filesystem diff --git a/stix2/utils.py b/stix2/utils.py index ca195f6..8b9a136 100644 --- a/stix2/utils.py +++ b/stix2/utils.py @@ -34,16 +34,21 @@ class STIXdatetime(dt.datetime): def get_timestamp(): + """Return a STIX timestamp of the current date and time.""" return STIXdatetime.now(tz=pytz.UTC) def format_datetime(dttm): - # 1. Convert to timezone-aware - # 2. Convert to UTC - # 3. Format in ISO format - # 4. Ensure correct precision - # 4a. Add subsecond value if non-zero and precision not defined - # 5. Add "Z" + """Convert a datetime object into a valid STIX timestamp string. + + 1. Convert to timezone-aware + 2. Convert to UTC + 3. Format in ISO format + 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: # dttm is timezone-naive; assume UTC @@ -63,6 +68,8 @@ def format_datetime(dttm): def parse_into_datetime(value, precision=None): + """Parse a value into a valid STIX timestamp object. + """ if isinstance(value, dt.date): if hasattr(value, 'hour'): ts = value @@ -102,6 +109,7 @@ def parse_into_datetime(value, precision=None): def get_dict(data): """Return data as a dictionary. + 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): """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. """ from .base import _STIXBase @@ -159,7 +167,7 @@ def find_property_index(obj, properties, tuple_to_find): def new_version(data, **kwargs): """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): @@ -196,6 +204,11 @@ def new_version(data, **kwargs): def revoke(data): + """Revoke a STIX object. + + Returns: + A new version of the object with ``revoked`` set to ``True``. + """ if not isinstance(data, Mapping): raise ValueError('cannot revoke object of this type! Try a dictionary ' 'or instance of an SDO or SRO class.')