From 8c56adda2157a6ab553c274ef196d12b38fcc161 Mon Sep 17 00:00:00 2001 From: Emmanuelle Vargas-Gonzalez Date: Thu, 26 Oct 2017 11:39:45 -0400 Subject: [PATCH 01/13] Update package structure --- stix2/__init__.py | 27 +++----------- stix2/core.py | 68 +++++++++++++++++++++------------- stix2/test/test_bundle.py | 5 ++- stix2/test/test_properties.py | 3 +- stix2/v20/__init__.py | 43 +++++++++++++++++++++ stix2/{ => v20}/common.py | 12 +++--- stix2/{ => v20}/observables.py | 18 ++++----- stix2/{ => v20}/sdo.py | 14 +++---- stix2/{ => v20}/sro.py | 12 +++--- 9 files changed, 122 insertions(+), 80 deletions(-) create mode 100644 stix2/v20/__init__.py rename stix2/{ => v20}/common.py (94%) rename stix2/{ => v20}/observables.py (98%) rename stix2/{ => v20}/sdo.py (97%) rename stix2/{ => v20}/sro.py (91%) diff --git a/stix2/__init__.py b/stix2/__init__.py index 55911a4..6fdce6a 100644 --- a/stix2/__init__.py +++ b/stix2/__init__.py @@ -19,27 +19,11 @@ # flake8: noqa -from . import exceptions -from .common import (TLP_AMBER, TLP_GREEN, TLP_RED, TLP_WHITE, CustomMarking, - ExternalReference, GranularMarking, KillChainPhase, - MarkingDefinition, StatementMarking, TLPMarking) -from .core import Bundle, _register_type, parse +from . import exceptions, v20 +from .core import Bundle, _collect_stix2_obj_maps, _register_type, parse from .environment import Environment, ObjectFactory from .markings import (add_markings, clear_markings, get_markings, is_marked, remove_markings, set_markings) -from .observables import (URL, AlternateDataStream, ArchiveExt, Artifact, - AutonomousSystem, CustomExtension, CustomObservable, - Directory, DomainName, EmailAddress, EmailMessage, - EmailMIMEComponent, File, HTTPRequestExt, ICMPExt, - IPv4Address, IPv6Address, MACAddress, Mutex, - NetworkTraffic, NTFSExt, PDFExt, Process, - RasterImageExt, SocketExt, Software, TCPExt, - UNIXAccountExt, UserAccount, WindowsPEBinaryExt, - WindowsPEOptionalHeaderType, WindowsPESection, - WindowsProcessExt, WindowsRegistryKey, - WindowsRegistryValueType, WindowsServiceExt, - X509Certificate, X509V3ExtenstionsType, - parse_observable) from .patterns import (AndBooleanExpression, AndObservationExpression, BasicObjectPathComponent, EqualityComparisonExpression, FloatConstant, FollowedByObservationExpression, @@ -58,9 +42,6 @@ from .patterns import (AndBooleanExpression, AndObservationExpression, ReferenceObjectPathComponent, RepeatQualifier, StartStopQualifier, StringConstant, TimestampConstant, WithinQualifier) -from .sdo import (AttackPattern, Campaign, CourseOfAction, CustomObject, - Identity, Indicator, IntrusionSet, Malware, ObservedData, - Report, ThreatActor, Tool, Vulnerability) from .sources import CompositeDataSource from .sources.filesystem import (FileSystemSink, FileSystemSource, FileSystemStore) @@ -68,6 +49,8 @@ from .sources.filters import Filter from .sources.memory import MemorySink, MemorySource, MemoryStore from .sources.taxii import (TAXIICollectionSink, TAXIICollectionSource, TAXIICollectionStore) -from .sro import Relationship, Sighting from .utils import get_dict, new_version, revoke +from .v20 import * # This import should always be the latest STIX 2.X version from .version import __version__ + +_collect_stix2_obj_maps() diff --git a/stix2/core.py b/stix2/core.py index 8ee11f5..22a8891 100644 --- a/stix2/core.py +++ b/stix2/core.py @@ -1,15 +1,12 @@ """STIX 2.0 Objects that are neither SDOs nor SROs.""" from collections import OrderedDict +import importlib +import pkgutil from . import exceptions from .base import _STIXBase -from .common import MarkingDefinition from .properties import IDProperty, ListProperty, Property, TypeProperty -from .sdo import (AttackPattern, Campaign, CourseOfAction, Identity, Indicator, - IntrusionSet, Malware, ObservedData, Report, ThreatActor, - Tool, Vulnerability) -from .sro import Relationship, Sighting from .utils import get_dict @@ -62,37 +59,30 @@ class Bundle(_STIXBase): super(Bundle, self).__init__(**kwargs) -OBJ_MAP = { - 'attack-pattern': AttackPattern, - 'bundle': Bundle, - '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, -} +STIX2_OBJ_MAPS = {} -def parse(data, allow_custom=False): +def parse(data, allow_custom=False, version=None): """Deserialize a string or file-like object into a STIX object. Args: data (str, dict, file-like object): The STIX 2 content to be parsed. - allow_custom (bool): Whether to allow custom properties or not. Default: False. + allow_custom (bool): Whether to allow custom properties or not. + Default: False. + version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If + None, use latest version. Returns: An instantiated Python STIX object. """ + if not version: + # Use latest version + OBJ_MAP = STIX2_OBJ_MAPS[sorted(STIX2_OBJ_MAPS.keys())[-1]] + else: + v = 'v' + version.replace('.', '') + OBJ_MAP = STIX2_OBJ_MAPS[v] + obj = get_dict(data) if 'type' not in obj: @@ -105,8 +95,34 @@ def parse(data, allow_custom=False): return obj_class(allow_custom=allow_custom, **obj) -def _register_type(new_type): +def _register_type(new_type, version=None): """Register a custom STIX Object type. + Args: + new_type (class): A class to register in the Object map. + version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If + None, use latest version. """ + if not version: + # Use latest version + OBJ_MAP = STIX2_OBJ_MAPS[sorted(STIX2_OBJ_MAPS.keys())[-1]] + else: + v = 'v' + version.replace('.', '') + OBJ_MAP = STIX2_OBJ_MAPS[v] + OBJ_MAP[new_type._type] = new_type + + +def _collect_stix2_obj_maps(): + """Navigate the package once and retrieve all OBJ_MAP dicts for each v2X + package.""" + if not STIX2_OBJ_MAPS: + top_level_module = importlib.import_module('stix2') + path = top_level_module.__path__ + prefix = str(top_level_module.__name__) + '.' + + for module_loader, name, is_pkg in pkgutil.walk_packages(path=path, + prefix=prefix): + if name.startswith('stix2.v2') and is_pkg: + mod = importlib.import_module(name, top_level_module) + STIX2_OBJ_MAPS[name.split('.')[-1]] = mod.OBJ_MAP diff --git a/stix2/test/test_bundle.py b/stix2/test/test_bundle.py index c7c95a8..8597f0f 100644 --- a/stix2/test/test_bundle.py +++ b/stix2/test/test_bundle.py @@ -132,8 +132,9 @@ def test_create_bundle_invalid(indicator, malware, relationship): assert excinfo.value.reason == 'This property may not contain a Bundle object' -def test_parse_bundle(): - bundle = stix2.parse(EXPECTED_BUNDLE) +@pytest.mark.parametrize("version", ["2.0"]) +def test_parse_bundle(version): + bundle = stix2.parse(EXPECTED_BUNDLE, version=version) assert bundle.type == "bundle" assert bundle.id.startswith("bundle--") diff --git a/stix2/test/test_properties.py b/stix2/test/test_properties.py index 7d03b9e..6bd1888 100644 --- a/stix2/test/test_properties.py +++ b/stix2/test/test_properties.py @@ -1,8 +1,7 @@ import pytest -from stix2 import TCPExt +from stix2 import EmailMIMEComponent, ExtensionsProperty, TCPExt from stix2.exceptions import AtLeastOnePropertyError, DictionaryKeyError -from stix2.observables import EmailMIMEComponent, ExtensionsProperty from stix2.properties import (BinaryProperty, BooleanProperty, DictionaryProperty, EmbeddedObjectProperty, EnumProperty, FloatProperty, HashesProperty, diff --git a/stix2/v20/__init__.py b/stix2/v20/__init__.py new file mode 100644 index 0000000..95f0b7e --- /dev/null +++ b/stix2/v20/__init__.py @@ -0,0 +1,43 @@ + +# flake8: noqa + +from ..core import Bundle +from .common import (TLP_AMBER, TLP_GREEN, TLP_RED, TLP_WHITE, CustomMarking, + ExternalReference, GranularMarking, KillChainPhase, + MarkingDefinition, StatementMarking, TLPMarking) +from .observables import (URL, AlternateDataStream, ArchiveExt, Artifact, + AutonomousSystem, CustomExtension, CustomObservable, + Directory, DomainName, EmailAddress, EmailMessage, + EmailMIMEComponent, ExtensionsProperty, File, + HTTPRequestExt, ICMPExt, IPv4Address, IPv6Address, + MACAddress, Mutex, NetworkTraffic, NTFSExt, PDFExt, + Process, RasterImageExt, SocketExt, Software, TCPExt, + UNIXAccountExt, UserAccount, WindowsPEBinaryExt, + WindowsPEOptionalHeaderType, WindowsPESection, + WindowsProcessExt, WindowsRegistryKey, + WindowsRegistryValueType, WindowsServiceExt, + X509Certificate, X509V3ExtenstionsType, + parse_observable) +from .sdo import (AttackPattern, Campaign, CourseOfAction, Identity, Indicator, + IntrusionSet, Malware, ObservedData, Report, ThreatActor, + Tool, Vulnerability) +from .sro import Relationship, Sighting + +OBJ_MAP = { + 'attack-pattern': AttackPattern, + 'bundle': Bundle, + '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, +} diff --git a/stix2/common.py b/stix2/v20/common.py similarity index 94% rename from stix2/common.py rename to stix2/v20/common.py index 449cd54..2d15529 100644 --- a/stix2/common.py +++ b/stix2/v20/common.py @@ -2,12 +2,12 @@ from collections import OrderedDict -from .base import _STIXBase -from .markings import _MarkingsMixin -from .properties import (HashesProperty, IDProperty, ListProperty, Property, - ReferenceProperty, SelectorProperty, StringProperty, - TimestampProperty, TypeProperty) -from .utils import NOW, get_dict +from ..base import _STIXBase +from ..markings import _MarkingsMixin +from ..properties import (HashesProperty, IDProperty, ListProperty, Property, + ReferenceProperty, SelectorProperty, StringProperty, + TimestampProperty, TypeProperty) +from ..utils import NOW, get_dict class ExternalReference(_STIXBase): diff --git a/stix2/observables.py b/stix2/v20/observables.py similarity index 98% rename from stix2/observables.py rename to stix2/v20/observables.py index aaec2d7..a874df9 100644 --- a/stix2/observables.py +++ b/stix2/v20/observables.py @@ -7,15 +7,15 @@ Observable and do not have a ``_type`` attribute. from collections import OrderedDict -from .base import _Extension, _Observable, _STIXBase -from .exceptions import (AtLeastOnePropertyError, DependentPropertiesError, - ParseError) -from .properties import (BinaryProperty, BooleanProperty, DictionaryProperty, - EmbeddedObjectProperty, EnumProperty, FloatProperty, - HashesProperty, HexProperty, IntegerProperty, - ListProperty, ObjectReferenceProperty, Property, - StringProperty, TimestampProperty, TypeProperty) -from .utils import get_dict +from ..base import _Extension, _Observable, _STIXBase +from ..exceptions import (AtLeastOnePropertyError, DependentPropertiesError, + ParseError) +from ..properties import (BinaryProperty, BooleanProperty, DictionaryProperty, + EmbeddedObjectProperty, EnumProperty, FloatProperty, + HashesProperty, HexProperty, IntegerProperty, + ListProperty, ObjectReferenceProperty, Property, + StringProperty, TimestampProperty, TypeProperty) +from ..utils import get_dict class ObservableProperty(Property): diff --git a/stix2/sdo.py b/stix2/v20/sdo.py similarity index 97% rename from stix2/sdo.py rename to stix2/v20/sdo.py index 8dad686..1af0777 100644 --- a/stix2/sdo.py +++ b/stix2/v20/sdo.py @@ -4,14 +4,14 @@ from collections import OrderedDict import stix2 -from .base import _STIXBase +from ..base import _STIXBase +from ..markings import _MarkingsMixin +from ..properties import (BooleanProperty, IDProperty, IntegerProperty, + ListProperty, PatternProperty, ReferenceProperty, + StringProperty, TimestampProperty, TypeProperty) +from ..utils import NOW from .common import ExternalReference, GranularMarking, KillChainPhase -from .markings import _MarkingsMixin from .observables import ObservableProperty -from .properties import (BooleanProperty, IDProperty, IntegerProperty, - ListProperty, PatternProperty, ReferenceProperty, - StringProperty, TimestampProperty, TypeProperty) -from .utils import NOW class STIXDomainObject(_STIXBase, _MarkingsMixin): @@ -358,7 +358,7 @@ def CustomObject(type='x-custom-type', properties=None): return raise e - stix2._register_type(_Custom) + stix2._register_type(_Custom, version="2.0") return _Custom return custom_builder diff --git a/stix2/sro.py b/stix2/v20/sro.py similarity index 91% rename from stix2/sro.py rename to stix2/v20/sro.py index 60f99f5..7f05f5e 100644 --- a/stix2/sro.py +++ b/stix2/v20/sro.py @@ -2,13 +2,13 @@ from collections import OrderedDict -from .base import _STIXBase +from ..base import _STIXBase +from ..markings import _MarkingsMixin +from ..properties import (BooleanProperty, IDProperty, IntegerProperty, + ListProperty, ReferenceProperty, StringProperty, + TimestampProperty, TypeProperty) +from ..utils import NOW from .common import ExternalReference, GranularMarking -from .markings import _MarkingsMixin -from .properties import (BooleanProperty, IDProperty, IntegerProperty, - ListProperty, ReferenceProperty, StringProperty, - TimestampProperty, TypeProperty) -from .utils import NOW class STIXRelationshipObject(_STIXBase, _MarkingsMixin): From 9aefa611532842a178a18934edc8927ab4eed50c Mon Sep 17 00:00:00 2001 From: Emmanuelle Vargas-Gonzalez Date: Thu, 26 Oct 2017 12:39:27 -0400 Subject: [PATCH 02/13] Small fix for Python 3.3, 3.4 --- stix2/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stix2/core.py b/stix2/core.py index 22a8891..5341b1d 100644 --- a/stix2/core.py +++ b/stix2/core.py @@ -124,5 +124,5 @@ def _collect_stix2_obj_maps(): for module_loader, name, is_pkg in pkgutil.walk_packages(path=path, prefix=prefix): if name.startswith('stix2.v2') and is_pkg: - mod = importlib.import_module(name, top_level_module) + mod = importlib.import_module(name, str(top_level_module.__name__)) STIX2_OBJ_MAPS[name.split('.')[-1]] = mod.OBJ_MAP From 71ee73c08a629effad6210e0f354dd1e02286c66 Mon Sep 17 00:00:00 2001 From: Emmanuelle Vargas-Gonzalez Date: Fri, 27 Oct 2017 12:37:08 -0400 Subject: [PATCH 03/13] Add MANIFEST to exclude test from final package --- MANIFEST.in | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..c9ec75b --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,3 @@ +include LICENSE +include CHANGELOG +recursive-exclude stix2\test * From 42317ddf31e21b6dd752b787d0467d90e433370c Mon Sep 17 00:00:00 2001 From: Emmanuelle Vargas-Gonzalez Date: Fri, 27 Oct 2017 12:38:03 -0400 Subject: [PATCH 04/13] Update filesystem.py to allow_custom and version --- stix2/__init__.py | 1 - stix2/sources/filesystem.py | 35 +++++++++++++++++++++++------------ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/stix2/__init__.py b/stix2/__init__.py index 6fdce6a..99c70fc 100644 --- a/stix2/__init__.py +++ b/stix2/__init__.py @@ -19,7 +19,6 @@ # flake8: noqa -from . import exceptions, v20 from .core import Bundle, _collect_stix2_obj_maps, _register_type, parse from .environment import Environment, ObjectFactory from .markings import (add_markings, clear_markings, get_markings, is_marked, diff --git a/stix2/sources/filesystem.py b/stix2/sources/filesystem.py index 103b882..012e828 100644 --- a/stix2/sources/filesystem.py +++ b/stix2/sources/filesystem.py @@ -61,13 +61,17 @@ class FileSystemSink(DataSink): def stix_dir(self): return self._stix_dir - def add(self, stix_data=None): + def add(self, stix_data=None, allow_custom=False, version=None): """add STIX objects to file directory Args: stix_data (STIX object OR dict OR str OR list): valid STIX 2.0 content in a STIX object(or list of), dict (or list of), or a STIX 2.0 json encoded string + allow_custom (bool): Whether to allow custom properties or not. + Default: False. + version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If + None, use latest version. TODO: Bundlify STIX content or no? When dumping to disk. """ @@ -96,7 +100,7 @@ class FileSystemSink(DataSink): elif isinstance(stix_data, str): # adding json encoded string of STIX content - stix_data = parse(stix_data) + stix_data = parse(stix_data, allow_custom, version) if stix_data["type"] == "bundle": for stix_obj in stix_data["objects"]: self.add(stix_obj) @@ -136,14 +140,18 @@ class FileSystemSource(DataSource): def stix_dir(self): return self._stix_dir - def get(self, stix_id, _composite_filters=None): + def get(self, stix_id, _composite_filters=None, allow_custom=False, version=None): """retrieve STIX object from file directory via STIX ID Args: stix_id (str): The STIX ID of the STIX object to be retrieved. - composite_filters (set): set of filters passed from the parent - CompositeDataSource, not user supplied + _composite_filters (set): set of filters passed from the parent + CompositeDataSource, not user supplied. + allow_custom (bool): Whether to allow custom properties or not. + Default: False. + version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If + None, use latest version. Returns: (STIX object): STIX object that has the supplied STIX ID. @@ -157,7 +165,7 @@ class FileSystemSource(DataSource): if all_data: stix_obj = sorted(all_data, key=lambda k: k['modified'])[0] - stix_obj = parse(stix_obj) + stix_obj = parse(stix_obj, allow_custom, version) else: stix_obj = None @@ -182,7 +190,7 @@ class FileSystemSource(DataSource): """ return [self.get(stix_id=stix_id, _composite_filters=_composite_filters)] - def query(self, query=None, _composite_filters=None): + def query(self, query=None, _composite_filters=None, allow_custom=False, version=None): """search and retrieve STIX objects based on the complete query A "complete query" includes the filters from the query, the filters @@ -190,10 +198,13 @@ class FileSystemSource(DataSource): CompositeDataSource (i.e. _composite_filters) Args: - query (list): list of filters to search on - - composite_filters (set): set of filters passed from the - CompositeDataSource, not user supplied + query (list): list of filters to search on. + _composite_filters (set): set of filters passed from the + CompositeDataSource, not user supplied. + allow_custom (bool): Whether to allow custom properties or not. + Default: False. + version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If + None, use latest version. Returns: (list): list of STIX objects that matches the supplied @@ -287,7 +298,7 @@ class FileSystemSource(DataSource): all_data = deduplicate(all_data) # parse python STIX objects from the STIX object dicts - stix_objs = [parse(stix_obj_dict) for stix_obj_dict in all_data] + stix_objs = [parse(stix_obj_dict, allow_custom, version) for stix_obj_dict in all_data] return stix_objs From 942a95a4e26c9651ce304550e4439d17a20a9ce2 Mon Sep 17 00:00:00 2001 From: Emmanuelle Vargas-Gonzalez Date: Fri, 27 Oct 2017 12:38:25 -0400 Subject: [PATCH 05/13] Update documentation --- README.rst | 9 +++ docs/index.rst | 1 + docs/ts_support.rst | 131 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 docs/ts_support.rst diff --git a/README.rst b/README.rst index 2753440..c2ec908 100644 --- a/README.rst +++ b/README.rst @@ -62,6 +62,15 @@ To parse a STIX JSON string into a Python STIX object, use ``parse()``: For more in-depth documentation, please see `https://stix2.readthedocs.io/ `__. +STIX 2.X Technical Specification Support +---------------------------------------- + +The `stix2` Python library is built to support multiple versions of the STIX +Technical Specification. With every major release of stix2 the ``import stix2`` +statement will automatically load the SDO/SROs equivalent to the most recent +supported 2.X Technical Specification. Please see the library documentation +for more details. + Governance ---------- diff --git a/docs/index.rst b/docs/index.rst index 62d07ff..f865467 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -16,6 +16,7 @@ Welcome to stix2's documentation! datastore_api roadmap contributing + ts_support Indices and tables diff --git a/docs/ts_support.rst b/docs/ts_support.rst new file mode 100644 index 0000000..09ad009 --- /dev/null +++ b/docs/ts_support.rst @@ -0,0 +1,131 @@ +How imports will work +--------------------- + +Imports can be used in different ways depending on the use case and support +levels. + +People who want to (in general) support the latest version of STIX 2.X without +making changes, implicitly using the latest version + +.. code:: python + + import stix2 + ... + stix2.Indicator(...) + +or + +.. code:: python + + from stix2 import Indicator + ... + Indicator(...) + +People who want to use an explicit version + +.. code:: python + + import stix2.v20 + ... + stix2.v20.Indicator(...) + +or + +.. code:: python + + from stix2.v20 import Indicator + ... + Indicator(...) + +or even, + +.. code:: python + + import stix2.v20 as stix2 + ... + stix2.Indicator(...) + +The last option makes it easy to update to a new version in one place per file, +once you've made the deliberate action to do this. + +People who want to use multiple versions in a single file: + +.. code:: python + + import stix2 + ... + stix2.v20.Indicator(...) + ... + stix2.v21.Indicator(...) + +or + +.. code:: python + + from stix2 import v20, v21 + ... + v20.Indicator(...) + ... + v21.Indicator(...) + +or (less preferred): + +.. code:: python + + from stix2.v20 import Indicator as Indicator_v20 + from stix2.v21 import Indicator as Indicator_v21 + ... + Indicator_v20(...) + ... + Indicator_v21(...) + +How parsing will work +--------------------- + +If the ``version`` positional argument is not provided. The data will be parsed +using the latest version of STIX 2.X supported by the `stix2` library. + +You can lock your `parse()` method to a specific STIX version by + +.. code:: python + + from stix2 import parse + + indicator = parse("""{ + "type": "indicator", + "id": "indicator--dbcbd659-c927-4f9a-994f-0a2632274394", + "created": "2017-09-26T23:33:39.829Z", + "modified": "2017-09-26T23:33:39.829Z", + "labels": [ + "malicious-activity" + ], + "name": "File hash for malware variant", + "pattern": "[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']", + "valid_from": "2017-09-26T23:33:39.829952Z" + }""", version="2.0") + print(indicator) + +Keep in mind that if a 2.1 or higher object is parsed, the operation will fail. + +How will custom work +-------------------- + +CustomObjects, CustomObservable, CustomMarking and CustomExtensions must be +registered explicitly by STIX version. This is a design decision since properties +or requirements may chance as the STIX Technical Specification advances. + +You can perform this by, + +.. code:: python + + # Make my custom observable available in STIX 2.0 + @stix2.v20.observables.CustomObservable('x-new-object-type', + (("prop", stix2.properties.BooleanProperty()))) + class NewObject2(object): + pass + + # Make my custom observable available in STIX 2.1 + @stix2.v21.observables.CustomObservable('x-new-object-type', + (("prop", stix2.properties.BooleanProperty()))) + class NewObject2(object): + pass From b9d25a837527abddd5a2083044e949d3a53456b9 Mon Sep 17 00:00:00 2001 From: Emmanuelle Vargas-Gonzalez Date: Sat, 28 Oct 2017 00:32:28 -0400 Subject: [PATCH 06/13] Add notebook docs, fix package distribution --- docs/guide/support.ipynb | 235 +++++++++++++++++++++++++++++++++++++++ docs/ts_support.rst | 13 ++- setup.py | 2 +- 3 files changed, 244 insertions(+), 6 deletions(-) create mode 100644 docs/guide/support.ipynb diff --git a/docs/guide/support.ipynb b/docs/guide/support.ipynb new file mode 100644 index 0000000..3c56f1d --- /dev/null +++ b/docs/guide/support.ipynb @@ -0,0 +1,235 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### How imports will work\n", + "\n", + "Imports can be used in different ways depending on the use case and support levels.\n", + "\n", + "People who want to (in general) support the latest version of STIX 2.X without making changes, implicitly using the latest version" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import stix2\n", + "\n", + "stix2.Indicator()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "or," + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from stix2 import Indicator\n", + "\n", + "Indicator()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "People who want to use an explicit version" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import stix2.v20\n", + "\n", + "stix2.v20.Indicator()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "or," + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from stix2.v20 import Indicator\n", + "\n", + "Indicator()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "or even," + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import stix2.v20 as stix2\n", + "\n", + "stix2.Indicator()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The last option makes it easy to update to a new version in one place per file, once you've made the deliberate action to do this.\n", + "\n", + "People who want to use multiple versions in a single file:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import stix2\n", + "\n", + "stix2.v20.Indicator()\n", + "\n", + "stix2.v21.Indicator()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "or," + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from stix2 import v20, v21\n", + "\n", + "v20.Indicator()\n", + "v21.Indicator()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "or (less preferred):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from stix2.v20 import Indicator as Indicator_v20\n", + "from stix2.v21 import Indicator as Indicator_v21\n", + "\n", + "Indicator_v20()\n", + "Indicator_v21()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### How parsing will work\n", + "If the ``version`` positional argument is not provided. The data will be parsed using the latest version of STIX 2.X supported by the `stix2` library.\n", + "\n", + "You can lock your `parse()` method to a specific STIX version by" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from stix2 import parse\n", + "\n", + "indicator = parse(\"\"\"{\n", + " \"type\": \"indicator\",\n", + " \"id\": \"indicator--dbcbd659-c927-4f9a-994f-0a2632274394\",\n", + " \"created\": \"2017-09-26T23:33:39.829Z\",\n", + " \"modified\": \"2017-09-26T23:33:39.829Z\",\n", + " \"labels\": [\n", + " \"malicious-activity\"\n", + " ],\n", + " \"name\": \"File hash for malware variant\",\n", + " \"pattern\": \"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']\",\n", + " \"valid_from\": \"2017-09-26T23:33:39.829952Z\"\n", + "}\"\"\", version=\"2.0\")\n", + "print(indicator)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Keep in mind that if a 2.1 or higher object is parsed, the operation will fail." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### How will custom work\n", + "\n", + "CustomObjects, CustomObservable, CustomMarking and CustomExtensions must be registered explicitly by STIX version. This is a design decision since properties or requirements may change as the STIX Technical Specification advances.\n", + "\n", + "You can perform this by," + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import stix2\n", + "\n", + "# Make my custom observable available in STIX 2.0\n", + "@stix2.v20.observables.CustomObservable('x-new-object-type',\n", + " ((\"prop\", stix2.properties.BooleanProperty())))\n", + "class NewObject2(object):\n", + " pass\n", + "\n", + "\n", + "# Make my custom observable available in STIX 2.1\n", + "@stix2.v21.observables.CustomObservable('x-new-object-type',\n", + " ((\"prop\", stix2.properties.BooleanProperty())))\n", + "class NewObject2(object):\n", + " pass" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/ts_support.rst b/docs/ts_support.rst index 09ad009..a62e59e 100644 --- a/docs/ts_support.rst +++ b/docs/ts_support.rst @@ -112,20 +112,23 @@ How will custom work CustomObjects, CustomObservable, CustomMarking and CustomExtensions must be registered explicitly by STIX version. This is a design decision since properties -or requirements may chance as the STIX Technical Specification advances. +or requirements may change as the STIX Technical Specification advances. You can perform this by, .. code:: python + import stix2 + # Make my custom observable available in STIX 2.0 @stix2.v20.observables.CustomObservable('x-new-object-type', (("prop", stix2.properties.BooleanProperty()))) - class NewObject2(object): - pass + class NewObject2(object): + pass + # Make my custom observable available in STIX 2.1 @stix2.v21.observables.CustomObservable('x-new-object-type', (("prop", stix2.properties.BooleanProperty()))) - class NewObject2(object): - pass + class NewObject2(object): + pass diff --git a/setup.py b/setup.py index e359147..c9b1bc7 100644 --- a/setup.py +++ b/setup.py @@ -45,7 +45,7 @@ setup( 'Programming Language :: Python :: 3.6', ], keywords="stix stix2 json cti cyber threat intelligence", - packages=find_packages(), + packages=find_packages(exclude=['*.test']), install_requires=[ 'python-dateutil', 'pytz', From a514c5a3df51464c60c30d6a92b06d250242d095 Mon Sep 17 00:00:00 2001 From: Emmanuelle Vargas-Gonzalez Date: Sun, 29 Oct 2017 00:09:13 -0400 Subject: [PATCH 07/13] Add test for _register_type() --- stix2/test/test_custom.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/stix2/test/test_custom.py b/stix2/test/test_custom.py index 48529b9..3bd79bc 100644 --- a/stix2/test/test_custom.py +++ b/stix2/test/test_custom.py @@ -483,3 +483,13 @@ def test_parse_observable_with_unregistered_custom_extension(): with pytest.raises(ValueError) as excinfo: stix2.parse_observable(input_str) assert "Can't parse Unknown extension type" in str(excinfo.value) + + +def test_register_custom_object(): + # Not the way to register custom object. + class CustomObject2(object): + _type = 'awesome-object' + + stix2._register_type(CustomObject2) + # Note that we will always check against newest OBJ_MAP. + assert (CustomObject2._type, CustomObject2) in stix2.OBJ_MAP.items() From e985d3b1d56f5c7e49a585dc421774727d0220ae Mon Sep 17 00:00:00 2001 From: Emmanuelle Vargas-Gonzalez Date: Wed, 1 Nov 2017 10:01:41 -0400 Subject: [PATCH 08/13] Move ts_support to Jupiter Notebook --- docs/guide/ts_support.ipynb | 237 ++++++++++++++++++++++++++++++++++++ docs/index.rst | 1 - docs/ts_support.rst | 134 -------------------- 3 files changed, 237 insertions(+), 135 deletions(-) create mode 100644 docs/guide/ts_support.ipynb delete mode 100644 docs/ts_support.rst diff --git a/docs/guide/ts_support.ipynb b/docs/guide/ts_support.ipynb new file mode 100644 index 0000000..d353dfb --- /dev/null +++ b/docs/guide/ts_support.ipynb @@ -0,0 +1,237 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Technical Specification Support\n", + "\n", + "### How imports will work\n", + "\n", + "Imports can be used in different ways depending on the use case and support levels.\n", + "\n", + "People who want to (in general) support the latest version of STIX 2.X without making changes, implicitly using the latest version" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import stix2\n", + "\n", + "stix2.Indicator()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "or," + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from stix2 import Indicator\n", + "\n", + "Indicator()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "People who want to use an explicit version" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import stix2.v20\n", + "\n", + "stix2.v20.Indicator()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "or," + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from stix2.v20 import Indicator\n", + "\n", + "Indicator()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "or even," + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import stix2.v20 as stix2\n", + "\n", + "stix2.Indicator()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The last option makes it easy to update to a new version in one place per file, once you've made the deliberate action to do this.\n", + "\n", + "People who want to use multiple versions in a single file:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import stix2\n", + "\n", + "stix2.v20.Indicator()\n", + "\n", + "stix2.v21.Indicator()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "or," + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from stix2 import v20, v21\n", + "\n", + "v20.Indicator()\n", + "v21.Indicator()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "or (less preferred):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from stix2.v20 import Indicator as Indicator_v20\n", + "from stix2.v21 import Indicator as Indicator_v21\n", + "\n", + "Indicator_v20()\n", + "Indicator_v21()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### How parsing will work\n", + "If the ``version`` positional argument is not provided. The data will be parsed using the latest version of STIX 2.X supported by the `stix2` library.\n", + "\n", + "You can lock your `parse()` method to a specific STIX version by" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from stix2 import parse\n", + "\n", + "indicator = parse(\"\"\"{\n", + " \"type\": \"indicator\",\n", + " \"id\": \"indicator--dbcbd659-c927-4f9a-994f-0a2632274394\",\n", + " \"created\": \"2017-09-26T23:33:39.829Z\",\n", + " \"modified\": \"2017-09-26T23:33:39.829Z\",\n", + " \"labels\": [\n", + " \"malicious-activity\"\n", + " ],\n", + " \"name\": \"File hash for malware variant\",\n", + " \"pattern\": \"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']\",\n", + " \"valid_from\": \"2017-09-26T23:33:39.829952Z\"\n", + "}\"\"\", version=\"2.0\")\n", + "print(indicator)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Keep in mind that if a 2.1 or higher object is parsed, the operation will fail." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### How will custom work\n", + "\n", + "CustomObjects, CustomObservable, CustomMarking and CustomExtensions must be registered explicitly by STIX version. This is a design decision since properties or requirements may change as the STIX Technical Specification advances.\n", + "\n", + "You can perform this by," + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import stix2\n", + "\n", + "# Make my custom observable available in STIX 2.0\n", + "@stix2.v20.CustomObservable('x-new-object-type',\n", + " ((\"prop\", stix2.properties.BooleanProperty())))\n", + "class NewObject2(object):\n", + " pass\n", + "\n", + "\n", + "# Make my custom observable available in STIX 2.1\n", + "@stix2.v21.CustomObservable('x-new-object-type',\n", + " ((\"prop\", stix2.properties.BooleanProperty())))\n", + "class NewObject2(object):\n", + " pass" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/index.rst b/docs/index.rst index f865467..62d07ff 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -16,7 +16,6 @@ Welcome to stix2's documentation! datastore_api roadmap contributing - ts_support Indices and tables diff --git a/docs/ts_support.rst b/docs/ts_support.rst deleted file mode 100644 index a62e59e..0000000 --- a/docs/ts_support.rst +++ /dev/null @@ -1,134 +0,0 @@ -How imports will work ---------------------- - -Imports can be used in different ways depending on the use case and support -levels. - -People who want to (in general) support the latest version of STIX 2.X without -making changes, implicitly using the latest version - -.. code:: python - - import stix2 - ... - stix2.Indicator(...) - -or - -.. code:: python - - from stix2 import Indicator - ... - Indicator(...) - -People who want to use an explicit version - -.. code:: python - - import stix2.v20 - ... - stix2.v20.Indicator(...) - -or - -.. code:: python - - from stix2.v20 import Indicator - ... - Indicator(...) - -or even, - -.. code:: python - - import stix2.v20 as stix2 - ... - stix2.Indicator(...) - -The last option makes it easy to update to a new version in one place per file, -once you've made the deliberate action to do this. - -People who want to use multiple versions in a single file: - -.. code:: python - - import stix2 - ... - stix2.v20.Indicator(...) - ... - stix2.v21.Indicator(...) - -or - -.. code:: python - - from stix2 import v20, v21 - ... - v20.Indicator(...) - ... - v21.Indicator(...) - -or (less preferred): - -.. code:: python - - from stix2.v20 import Indicator as Indicator_v20 - from stix2.v21 import Indicator as Indicator_v21 - ... - Indicator_v20(...) - ... - Indicator_v21(...) - -How parsing will work ---------------------- - -If the ``version`` positional argument is not provided. The data will be parsed -using the latest version of STIX 2.X supported by the `stix2` library. - -You can lock your `parse()` method to a specific STIX version by - -.. code:: python - - from stix2 import parse - - indicator = parse("""{ - "type": "indicator", - "id": "indicator--dbcbd659-c927-4f9a-994f-0a2632274394", - "created": "2017-09-26T23:33:39.829Z", - "modified": "2017-09-26T23:33:39.829Z", - "labels": [ - "malicious-activity" - ], - "name": "File hash for malware variant", - "pattern": "[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']", - "valid_from": "2017-09-26T23:33:39.829952Z" - }""", version="2.0") - print(indicator) - -Keep in mind that if a 2.1 or higher object is parsed, the operation will fail. - -How will custom work --------------------- - -CustomObjects, CustomObservable, CustomMarking and CustomExtensions must be -registered explicitly by STIX version. This is a design decision since properties -or requirements may change as the STIX Technical Specification advances. - -You can perform this by, - -.. code:: python - - import stix2 - - # Make my custom observable available in STIX 2.0 - @stix2.v20.observables.CustomObservable('x-new-object-type', - (("prop", stix2.properties.BooleanProperty()))) - class NewObject2(object): - pass - - - # Make my custom observable available in STIX 2.1 - @stix2.v21.observables.CustomObservable('x-new-object-type', - (("prop", stix2.properties.BooleanProperty()))) - class NewObject2(object): - pass From ef20860400019c89c9475bdf24084b928ae08b74 Mon Sep 17 00:00:00 2001 From: Emmanuelle Vargas-Gonzalez Date: Wed, 1 Nov 2017 10:03:03 -0400 Subject: [PATCH 09/13] Detele support.ipynb --- docs/guide/support.ipynb | 235 --------------------------------------- 1 file changed, 235 deletions(-) delete mode 100644 docs/guide/support.ipynb diff --git a/docs/guide/support.ipynb b/docs/guide/support.ipynb deleted file mode 100644 index 3c56f1d..0000000 --- a/docs/guide/support.ipynb +++ /dev/null @@ -1,235 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### How imports will work\n", - "\n", - "Imports can be used in different ways depending on the use case and support levels.\n", - "\n", - "People who want to (in general) support the latest version of STIX 2.X without making changes, implicitly using the latest version" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import stix2\n", - "\n", - "stix2.Indicator()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "or," - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from stix2 import Indicator\n", - "\n", - "Indicator()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "People who want to use an explicit version" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import stix2.v20\n", - "\n", - "stix2.v20.Indicator()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "or," - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from stix2.v20 import Indicator\n", - "\n", - "Indicator()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "or even," - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import stix2.v20 as stix2\n", - "\n", - "stix2.Indicator()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The last option makes it easy to update to a new version in one place per file, once you've made the deliberate action to do this.\n", - "\n", - "People who want to use multiple versions in a single file:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import stix2\n", - "\n", - "stix2.v20.Indicator()\n", - "\n", - "stix2.v21.Indicator()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "or," - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from stix2 import v20, v21\n", - "\n", - "v20.Indicator()\n", - "v21.Indicator()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "or (less preferred):" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from stix2.v20 import Indicator as Indicator_v20\n", - "from stix2.v21 import Indicator as Indicator_v21\n", - "\n", - "Indicator_v20()\n", - "Indicator_v21()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### How parsing will work\n", - "If the ``version`` positional argument is not provided. The data will be parsed using the latest version of STIX 2.X supported by the `stix2` library.\n", - "\n", - "You can lock your `parse()` method to a specific STIX version by" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from stix2 import parse\n", - "\n", - "indicator = parse(\"\"\"{\n", - " \"type\": \"indicator\",\n", - " \"id\": \"indicator--dbcbd659-c927-4f9a-994f-0a2632274394\",\n", - " \"created\": \"2017-09-26T23:33:39.829Z\",\n", - " \"modified\": \"2017-09-26T23:33:39.829Z\",\n", - " \"labels\": [\n", - " \"malicious-activity\"\n", - " ],\n", - " \"name\": \"File hash for malware variant\",\n", - " \"pattern\": \"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']\",\n", - " \"valid_from\": \"2017-09-26T23:33:39.829952Z\"\n", - "}\"\"\", version=\"2.0\")\n", - "print(indicator)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Keep in mind that if a 2.1 or higher object is parsed, the operation will fail." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### How will custom work\n", - "\n", - "CustomObjects, CustomObservable, CustomMarking and CustomExtensions must be registered explicitly by STIX version. This is a design decision since properties or requirements may change as the STIX Technical Specification advances.\n", - "\n", - "You can perform this by," - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import stix2\n", - "\n", - "# Make my custom observable available in STIX 2.0\n", - "@stix2.v20.observables.CustomObservable('x-new-object-type',\n", - " ((\"prop\", stix2.properties.BooleanProperty())))\n", - "class NewObject2(object):\n", - " pass\n", - "\n", - "\n", - "# Make my custom observable available in STIX 2.1\n", - "@stix2.v21.observables.CustomObservable('x-new-object-type',\n", - " ((\"prop\", stix2.properties.BooleanProperty())))\n", - "class NewObject2(object):\n", - " pass" - ] - } - ], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 0 -} From 06a50b0178eb826b845cac96681d7ee028a0b5be Mon Sep 17 00:00:00 2001 From: Emmanuelle Vargas-Gonzalez Date: Wed, 1 Nov 2017 10:48:28 -0400 Subject: [PATCH 10/13] Update README, add DEFAULT_VERSION --- README.rst | 5 +++-- docs/guide/ts_support.ipynb | 2 +- stix2/__init__.py | 4 +++- stix2/core.py | 10 +++++----- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/README.rst b/README.rst index c2ec908..7884ba0 100644 --- a/README.rst +++ b/README.rst @@ -65,8 +65,9 @@ For more in-depth documentation, please see `https://stix2.readthedocs.io/ Date: Wed, 1 Nov 2017 11:03:02 -0400 Subject: [PATCH 11/13] Fix import statement --- stix2/core.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/stix2/core.py b/stix2/core.py index e860e95..10754f0 100644 --- a/stix2/core.py +++ b/stix2/core.py @@ -4,7 +4,9 @@ from collections import OrderedDict import importlib import pkgutil -from . import DEFAULT_VERSION, exceptions +import stix2 + +from . import exceptions from .base import _STIXBase from .properties import IDProperty, ListProperty, Property, TypeProperty from .utils import get_dict @@ -78,7 +80,7 @@ def parse(data, allow_custom=False, version=None): """ if not version: # Use latest version - v = 'v' + DEFAULT_VERSION.replace('.', '') + v = 'v' + stix2.DEFAULT_VERSION.replace('.', '') else: v = 'v' + version.replace('.', '') @@ -105,7 +107,7 @@ def _register_type(new_type, version=None): """ if not version: # Use latest version - v = 'v' + DEFAULT_VERSION.replace('.', '') + v = 'v' + stix2.DEFAULT_VERSION.replace('.', '') else: v = 'v' + version.replace('.', '') From 7b9f09ee18dfced7f13e1eac53ae40d5aae48c75 Mon Sep 17 00:00:00 2001 From: Emmanuelle Vargas-Gonzalez Date: Wed, 1 Nov 2017 12:46:01 -0400 Subject: [PATCH 12/13] Minor change --- README.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 7884ba0..faacc53 100644 --- a/README.rst +++ b/README.rst @@ -65,9 +65,9 @@ For more in-depth documentation, please see `https://stix2.readthedocs.io/ Date: Wed, 1 Nov 2017 14:21:26 -0400 Subject: [PATCH 13/13] Document new util method --- stix2/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/stix2/utils.py b/stix2/utils.py index 91cd071..f23dbe2 100644 --- a/stix2/utils.py +++ b/stix2/utils.py @@ -250,6 +250,7 @@ def revoke(data): def get_class_hierarchy_names(obj): + """Given an object, return the names of the class hierarchy.""" names = [] for cls in obj.__class__.__mro__: names.append(cls.__name__)