diff --git a/.travis.yml b/.travis.yml
index f55fcac7..e99e66dd 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,10 +1,16 @@
+os: linux
language: python
+cache: pip
+dist: xenial
python:
- "2.7"
- "3.4"
- "3.5"
- "3.6"
+ - "3.7"
+ - "3.8"
install:
+ - pip install -U pip setuptools
- pip install tox-travis
script:
- tox
diff --git a/CHANGES.txt b/CHANGES.txt
index 4ff6a402..b22812d1 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,27 @@
+Version 1.2.0.11
+2020-11-16
+- #367 Fix deprecation warning from collections module
+
+Version 1.2.0.10
+2020-05-01
+- #366 Check add_reference methods to prevent NoneType has no attribute 'append'
+- Changes to STIXPackage to prevent the empty tag from appearing in serialization
+
+Version 1.2.0.9
+2020-04-16
+- #364 TTPs would fail to serialize XML Kill_Chains if no TTP was set
+- Added Python 3.8 to test harness
+
+Version 1.2.0.8
+2020-03-09
+- #357 Add xnl:Type to the PersonName element (CIQ)
+- Update the allowable values for PersonName and OrganisationName
+- Update tests per recent CybOX release
+
+Version 1.2.0.7
+2019-09-06
+- Update package requirements
+
Version 1.2.0.6
2018-04-25
- #347 Property targeted_technical_details missing in VictimTargeting class
@@ -36,6 +60,65 @@ Version 1.2.0.2
- #302 Correctly handle CIQ Identity objects.
- Add additional fields to CIQ Identity object.
+Version 1.1.1.19
+2020-11-16
+- #367 Fix deprecation warning from collections module
+
+Version 1.1.1.18
+2020-05-01
+- #366 Check add_reference methods to prevent NoneType has no attribute 'append'
+- Changes to STIXPackage to prevent the empty tag from appearing in serialization
+
+Version 1.1.1.17
+2020-04-21
+- #365 AISMarkingStructure not serializing correctly. PY3 compatibility issue
+
+Version 1.1.1.16
+2020-04-16
+- #364 TTPs would fail to serialize XML Kill_Chains if no TTP was set
+- Added Python 3.8 to test harness
+
+Version 1.1.1.15
+2020-03-09
+- #357 Add xnl:Type to the PersonName element (CIQ)
+- Update the allowable values for PersonName and OrganisationName
+- Update tests per recent CybOX release
+
+Version 1.1.1.14
+2019-11-26
+- #361 fix problem with lookup_extension for TestMechanism
+
+Version 1.1.1.13
+2019-09-06
+- Update package requirements
+
+Version 1.1.1.12
+2018-04-25
+- #347 Property targeted_technical_details missing in VictimTargeting class
+
+Version 1.1.1.11
+2018-03-21
+- Fix issue with PyPI.
+
+Version 1.1.1.10
+2018-03-06
+- #343 Create separate test environments for when maec is or is not installed
+- #339 [Python3 not supported - v1.1/1.2] to_json vaguely broken on some files
+- #338 VocabTypes are unhashable in 1.1.1.x on Python 3
+- #325 Bug in Indicator class setter for observables property
+- Change stix.ToolInformation to use AttackerToolType vocab
+- Removed Python 2.6 environment from CI tests
+
+Version 1.1.1.9
+2017-05-25
+- Support Python 3.6
+- #321 Fix CIQ extensions.
+
+Version 1.1.1.8
+2017-01-18
+- Update to support Python 3.
+- Convert to use mixbox.
+
Version 1.1.1.7
2016-10-21
- Improved handling of Industry Sectors in CIQ Identity for AIS Markings
diff --git a/README.rst b/README.rst
index 6df07068..e934477c 100644
--- a/README.rst
+++ b/README.rst
@@ -1,11 +1,12 @@
python-stix
===========
-A python library for parsing, manipulating, and generating STIX v1.2 content.
+A python library for parsing, manipulating, and generating `Structured Threat Information eXpression (STIX™) `_ v1.2.0 content.
:Source: https://github.com/STIXProject/python-stix
-:Documentation: http://stix.readthedocs.org
+:Documentation: https://stix.readthedocs.io/
:Information: https://stixproject.github.io/
+:Download: https://pypi.python.org/pypi/stix/
|travis_badge| |landscape_io_badge| |version_badge|
@@ -24,7 +25,7 @@ Installation
------------
The python-stix library is hosted on `PyPI
-`_ and the most recent stable version can be
+`_ and the most recent stable version can be
installed with `pip `_:
::
@@ -60,13 +61,13 @@ Installation on Windows
~~~~~~~~~~~~~~~~~~~~~~~
Download the Lxml wheel for your version of Python from
-http://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml, then install it via "pip install
+http://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml, then install it via "pip install
.whl". For example, to install it on 64-bit Windows running Python 2.7:
::
- > pip install lxml-3.6.1-cp27-cp27m-win_amd64.whl
- > pip install stix
+ $ pip install lxml-3.6.1-cp27-cp27m-win_amd64.whl
+ $ pip install stix
Versioning
----------
diff --git a/docs/api/indicator/indicator.rst b/docs/api/indicator/indicator.rst
index 0b299213..ccc78ff9 100644
--- a/docs/api/indicator/indicator.rst
+++ b/docs/api/indicator/indicator.rst
@@ -29,7 +29,7 @@ Classes
add_short_description, add_test_mechanism, add_valid_time_position,
alternative_id, confidence, description, descriptions, find,
get_produced_time, get_received_time, handling, id_, idref,
- indicated_ttps, indicator_types, information_source, kill_chain_phases,
+ indicated_ttps, indicator_types, kill_chain_phases,
likely_impact, negate, observable, observable_composition_operator,
observables, producer, related_campaigns, related_indicators,
related_packages, set_produced_time, set_producer_identity,
diff --git a/docs/index.rst b/docs/index.rst
index 9d61b71d..a650a9fb 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -22,17 +22,17 @@ version of STIX.
============ ===================
STIX Version python-stix Version
============ ===================
-1.2 1.2.0.6 (`PyPI`__) (`GitHub`__)
-1.1.1 1.1.1.12 (`PyPI`__) (`GitHub`__)
+1.2 1.2.0.11 (`PyPI`__) (`GitHub`__)
+1.1.1 1.1.1.18 (`PyPI`__) (`GitHub`__)
1.1.0 1.1.0.6 (`PyPI`__) (`GitHub`__)
1.0.1 1.0.1.1 (`PyPI`__) (`GitHub`__)
1.0 1.0.0a7 (`PyPI`__) (`GitHub`__)
============ ===================
-__ https://pypi.python.org/pypi/stix/1.2.0.6
-__ https://github.com/STIXProject/python-stix/tree/v1.2.0.6
-__ https://pypi.python.org/pypi/stix/1.1.1.12
-__ https://github.com/STIXProject/python-stix/tree/v1.1.1.12
+__ https://pypi.python.org/pypi/stix/1.2.0.11
+__ https://github.com/STIXProject/python-stix/tree/v1.2.0.11
+__ https://pypi.python.org/pypi/stix/1.1.1.18
+__ https://github.com/STIXProject/python-stix/tree/v1.1.1.18
__ https://pypi.python.org/pypi/stix/1.1.0.6
__ https://github.com/STIXProject/python-stix/tree/v1.1.0.6
__ https://pypi.python.org/pypi/stix/1.0.1.1
diff --git a/examples/vuln_affected_software.py b/examples/vuln_affected_software.py
index 3f1d5532..620087c0 100644
--- a/examples/vuln_affected_software.py
+++ b/examples/vuln_affected_software.py
@@ -28,7 +28,7 @@
# Wrap the Product Object in an Observable instance
observable = Observable(software)
-# Attach the Product observable to the affected_sofware list of
+# Attach the Product observable to the affected_software list of
# RelatedObservable instances. This wraps our Observable in a
# RelatedObservable layer.
vuln = Vulnerability()
diff --git a/setup.cfg b/setup.cfg
index 2be68365..e383efad 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,2 +1,17 @@
+[bumpversion]
+current_version = 1.2.0.11
+parse = (?P\d+)\.(?P\d+)\.(?P\d+).(?P\d+)
+serialize = {major}.{minor}.{patch}.{revision}
+commit = True
+tag = True
+
+[bumpversion:file:stix/version.py]
+
+[bumpversion:file:docs/index.rst]
+
+[metadata]
+license_file = LICENSE.txt
+
[bdist_wheel]
universal = True
+
diff --git a/setup.py b/setup.py
index fb657a39..717d437d 100644
--- a/setup.py
+++ b/setup.py
@@ -3,6 +3,7 @@
# Copyright (c) 2017, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from io import open # Allow `encoding` kwarg on Python 2.7
from os.path import abspath, dirname, join
@@ -11,6 +12,7 @@
BASE_DIR = dirname(abspath(__file__))
VERSION_FILE = join(BASE_DIR, 'stix', 'version.py')
+
def get_version():
with open(VERSION_FILE) as f:
for line in f.readlines():
@@ -20,15 +22,17 @@ def get_version():
raise AttributeError("Package does not have a __version__")
-with open('README.rst') as f:
- readme = f.read()
+def get_long_description():
+ with open('README.rst', encoding='utf-8') as f:
+ return f.read()
install_requires = [
- 'lxml>=2.3',
- 'python-dateutil',
+ 'lxml>=2.2.3 ; python_version == "2.7" or python_version >= "3.5"',
+ 'lxml>=2.2.3,<4.4.0 ; python_version > "2.7" and python_version < "3.5"',
+ 'mixbox>=1.0.4',
'cybox>=2.1.0.13,<2.1.1.0',
- 'mixbox>=1.0.2',
+ 'python-dateutil',
]
@@ -38,10 +42,11 @@ def get_version():
author="STIX Project, MITRE Corporation",
author_email="stix@mitre.org",
description="An API for parsing and generating STIX content.",
- long_description=readme,
- url="http://stix.mitre.org",
+ long_description=get_long_description(),
+ url="https://stixproject.github.io/",
packages=find_packages(),
install_requires=install_requires,
+ license="BSD",
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
@@ -50,9 +55,15 @@ def get_version():
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
- ]
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ ],
+ project_urls={
+ 'Documentation': 'https://stix.readthedocs.io/',
+ 'Source Code': 'https://github.com/STIXProject/python-stix/',
+ 'Bug Tracker': 'https://github.com/STIXProject/python-stix/issues/',
+ },
)
diff --git a/stix/base.py b/stix/base.py
index 14f50a6d..b5c417ee 100644
--- a/stix/base.py
+++ b/stix/base.py
@@ -8,6 +8,7 @@
from sys import version_info
# mixbox
+from mixbox import compat
from mixbox import idgen
from mixbox import entities
from mixbox import fields
@@ -311,7 +312,7 @@ def istypeof(cls, obj):
return isinstance(obj, cls)
-class TypedList(TypedCollection, collections.MutableSequence):
+class TypedList(TypedCollection, compat.MutableSequence):
def __init__(self, *args):
TypedCollection.__init__(self, *args)
diff --git a/stix/bindings/stix_common.py b/stix/bindings/stix_common.py
index 64cfac7c..8ae31be4 100644
--- a/stix/bindings/stix_common.py
+++ b/stix/bindings/stix_common.py
@@ -3495,7 +3495,7 @@ class StructuredTextType(GeneratedsSuper):
Note that if the markup tags used by this format would be interpreted
as XML information (such as the bracket-based tags of HTML) the text
area should be enclosed in a CDATA section to prevent the markup from
- interferring with XMLvalidation of the CybOX document. If this
+ interfering with XMLvalidation of the CybOX document. If this
attribute is absent, the implication is that no markup is being used."""
subclass = None
superclass = None
diff --git a/stix/common/information_source.py b/stix/common/information_source.py
index f7042f27..ef718ba7 100644
--- a/stix/common/information_source.py
+++ b/stix/common/information_source.py
@@ -22,7 +22,7 @@ class InformationSource(stix.Entity):
_binding_class = stix_common_binding.InformationSourceType
_namespace = 'http://stix.mitre.org/common-1'
- identity = fields.TypedField("Identity", type_=Identity, factory=IdentityFactory)
+ identity = fields.TypedField("Identity", Identity, factory=IdentityFactory)
descriptions = fields.TypedField("Description", StructuredTextList)
contributing_sources = fields.TypedField("Contributing_Sources", type_="stix.common.information_source.ContributingSources")
time = fields.TypedField("Time", cybox.common.Time)
@@ -39,15 +39,15 @@ def __init__(self, description=None, identity=None, time=None, tools=None, contr
self.time = time
self.tools = tools
self.references = references
- #self.roles = None
def add_contributing_source(self, value):
self.contributing_sources.append(value)
-
def add_reference(self, value):
if not value:
return
+ if self.references is None:
+ self.references = References()
# TODO: Check if it's a valid URI?
self.references.append(value)
@@ -80,7 +80,6 @@ def add_description(self, description):
"""
self.descriptions.add(description)
-
def add_role(self, value):
self.roles.append(value)
@@ -95,4 +94,3 @@ class ContributingSources(stix.EntityList):
@classmethod
def _dict_as_list(cls):
return False
-
\ No newline at end of file
diff --git a/stix/common/profiles.py b/stix/common/profiles.py
index a4499d01..1e523b6c 100644
--- a/stix/common/profiles.py
+++ b/stix/common/profiles.py
@@ -3,13 +3,14 @@
import collections
+from mixbox import compat
from mixbox import fields
import stix
from stix.bindings import stix_common as stix_common_binding
-class Profiles(collections.MutableSequence, stix.Entity):
+class Profiles(compat.MutableSequence, stix.Entity):
_binding = stix_common_binding
_binding_class = stix_common_binding.ProfilesType
_namespace = 'http://stix.mitre.org/common-1'
diff --git a/stix/common/references.py b/stix/common/references.py
index 45bfbb27..f5c7dc1e 100644
--- a/stix/common/references.py
+++ b/stix/common/references.py
@@ -2,13 +2,14 @@
# See LICENSE.txt for complete terms.
import collections
+from mixbox import compat
from mixbox import fields
import stix
from stix.bindings import stix_common as stix_common_binding
-class References(collections.MutableSequence, stix.Entity):
+class References(compat.MutableSequence, stix.Entity):
_binding = stix_common_binding
_binding_class = stix_common_binding.ReferencesType
_namespace = 'http://stix.mitre.org/common-1'
diff --git a/stix/common/structured_text.py b/stix/common/structured_text.py
index b90c0396..9dc73b47 100644
--- a/stix/common/structured_text.py
+++ b/stix/common/structured_text.py
@@ -10,7 +10,13 @@
import stix
import stix.utils as utils
import stix.bindings.stix_common as stix_common_binding
-from mixbox.vendor.six import text_type
+from mixbox.vendor.six import PY2, PY3, text_type
+
+
+if PY2:
+ from collections import Sequence
+elif PY3:
+ from collections.abc import Sequence
#: Default ordinality value for StructuredText.
@@ -58,7 +64,7 @@ def to_dict(self):
"""Converts this object into a dictionary representation.
Note:
- If no properies or attributes are set other than ``value``,
+ If no properties or attributes are set other than ``value``,
this will return a string.
"""
@@ -89,7 +95,7 @@ def _unset_default(text):
"""Unsets the ordinality of the StructuredText object `text` if the
ordinality is equal to the DEFAULT_ORDINALITY.
- The ordinaity will be returned to its original state after exiting the
+ The ordinality will be returned to its original state after exiting the
context manager.
"""
@@ -105,7 +111,7 @@ def _unset_default(text):
text.ordinality = ordinality
-class StructuredTextList(stix.TypedCollection, collections.Sequence):
+class StructuredTextList(stix.TypedCollection, Sequence):
"""A sequence type used to store StructureText objects.
Args:
diff --git a/stix/core/stix_package.py b/stix/core/stix_package.py
index 14e9fbb1..da2d5643 100644
--- a/stix/core/stix_package.py
+++ b/stix/core/stix_package.py
@@ -104,7 +104,7 @@ def __init__(self, id_=None, idref=None, timestamp=None, stix_header=None,
self.indicators = indicators or Indicators()
self.incidents = incidents or Incidents()
self.threat_actors = threat_actors or ThreatActors()
- self.ttps = ttps or TTPs()
+ self.ttps = ttps
self.related_packages = related_packages
self.reports = reports or Reports()
self.timestamp = timestamp
@@ -180,7 +180,7 @@ def add_ttp(self, ttp):
"""
if self.ttps is None:
self.ttps = TTPs()
- self.ttps.append(ttp)
+ self.ttps.ttp.append(ttp)
def add_report(self, report):
"""Adds a :class:`.Report` object to the :attr:`reports` collection.
diff --git a/stix/core/ttps.py b/stix/core/ttps.py
index d5620509..9f1cb265 100644
--- a/stix/core/ttps.py
+++ b/stix/core/ttps.py
@@ -5,12 +5,10 @@
from functools import partial
# mixbox
-from mixbox import entities
from mixbox import fields
# stix
import stix
-from stix import utils
from stix.ttp import TTP
from stix.common.kill_chains import KillChains
from stix.bindings import stix_core as core_binding
@@ -19,24 +17,23 @@
from stix.utils.deprecated import IdrefDeprecatedList
-class TTPs(stix.EntityList):
+class TTPs(stix.Entity):
_binding = core_binding
_binding_class = _binding.TTPsType
_namespace = 'http://stix.mitre.org/stix-1'
- ttps = fields.TypedField(
- name="TTP",
- type_=TTP,
- multiple=True,
- key_name="ttps",
- listfunc=partial(IdrefDeprecatedList, type=TTP)
- )
-
+ ttp = fields.TypedField("TTP", TTP, multiple=True, key_name="ttps", listfunc=partial(IdrefDeprecatedList, type=TTP))
kill_chains = fields.TypedField("Kill_Chains", KillChains)
def __init__(self, ttps=None):
- super(TTPs, self).__init__(ttps)
+ super(TTPs, self).__init__()
+ self.ttp = ttps
self.kill_chains = KillChains()
def add_ttp(self, ttp):
- self.append(ttp)
+ self.ttp.append(ttp)
+
+ def add_kill_chain(self, kc):
+ if self.kill_chains is None:
+ self.kill_chains = KillChains()
+ self.kill_chains.kill_chain.append(kc)
diff --git a/stix/exploit_target/vulnerability.py b/stix/exploit_target/vulnerability.py
index 78e0974a..814c2f19 100644
--- a/stix/exploit_target/vulnerability.py
+++ b/stix/exploit_target/vulnerability.py
@@ -4,13 +4,10 @@
from mixbox import fields
import stix
-import stix.utils as utils
import stix.bindings.exploit_target as exploit_target_binding
-import stix.bindings.stix_common as stix_common_binding
-from stix.common import DateTimeWithPrecision, StructuredTextList
+from stix.common import DateTimeWithPrecision, References, StructuredTextList
from stix.common.related import GenericRelationshipList, RelatedObservable
-from mixbox import entities, fields
-from stix.common import References
+
class Vulnerability(stix.Entity):
"""Implementation of STIX ``Vulnerability``.
@@ -44,7 +41,6 @@ def __init__(self, title=None, description=None, short_description=None):
self.title = title
self.descriptions = StructuredTextList(description)
self.short_descriptions = StructuredTextList(short_description)
- self.references = []
@property
def description(self):
@@ -102,9 +98,11 @@ def add_short_description(self, description):
def add_reference(self, reference):
if not reference:
return
-
+ if self.references is None:
+ self.references = References()
self.references.append(reference)
+
class CVSSVector(stix.Entity):
"""
Common Vulnerabilit Scoring System object, representing its component measures
diff --git a/stix/extensions/identity/ciq_identity_3_0.py b/stix/extensions/identity/ciq_identity_3_0.py
index a2d89f08..2010ac8f 100644
--- a/stix/extensions/identity/ciq_identity_3_0.py
+++ b/stix/extensions/identity/ciq_identity_3_0.py
@@ -1028,13 +1028,53 @@ class PersonName(stix.Entity):
_namespace = XML_NS_XNL
XML_TAG = "{%s}PersonName" % _namespace
- def __init__(self, name_elements=None):
+ TYPE_ALIAS = 'Alias'
+ TYPE_LEGAL_NAME = 'LegalName'
+ TYPE_KNOWN_AS = 'KnownAs'
+ TYPE_MAIDEN_NAME = 'MaidenName'
+ TYPE_FORMER_NAME = 'FormerName'
+ TYPE_COMMON_USE = 'CommonUse'
+ TYPE_NAME_AT_BIRTH = 'NameAtBirth'
+ TYPE_PREFERRED_NAME = 'PreferredName'
+ TYPE_OFFICIAL_NAME = 'OfficialName'
+ TYPE_UNOFFICIAL_NAME = 'UnofficialName'
+ TYPE_NICK_NAME = 'NickName'
+ TYPE_PET_NAME = 'PetName'
+
+ TYPES = (
+ TYPE_ALIAS,
+ TYPE_LEGAL_NAME,
+ TYPE_KNOWN_AS,
+ TYPE_MAIDEN_NAME,
+ TYPE_FORMER_NAME,
+ TYPE_COMMON_USE,
+ TYPE_NAME_AT_BIRTH,
+ TYPE_PREFERRED_NAME,
+ TYPE_OFFICIAL_NAME,
+ TYPE_UNOFFICIAL_NAME,
+ TYPE_NICK_NAME,
+ TYPE_PET_NAME,
+ )
+
+ def __init__(self, name_elements=None, type_=None):
self.name_elements = []
+ self.type_ = type_
if name_elements:
for name_element in name_elements:
self.add_name_element(name_element)
+ @property
+ def type_(self):
+ return self._type
+
+ @type_.setter
+ def type_(self, value):
+ if value and value not in self.TYPES:
+ raise ValueError('value must be one of %s: ' % (self.TYPES,))
+
+ self._type = value
+
def add_name_element(self, value):
if isinstance(value, string_types):
self.name_elements.append(PersonNameElement(value=value))
@@ -1050,6 +1090,9 @@ def to_obj(self, return_obj=None, ns_info=None):
root_tag = PersonName.XML_TAG
return_obj = et.Element(root_tag)
+ if self.type_:
+ return_obj.attrib['{%s}Type' % XML_NS_XNL] = self.type_
+
for name_element in self.name_elements:
return_obj.append(name_element.to_obj(ns_info=ns_info))
@@ -1063,6 +1106,8 @@ def from_obj(cls, obj, return_obj=None):
if not return_obj:
return_obj = cls()
+ return_obj.type_ = obj.attrib.get('{%s}Type' % XML_NS_XNL)
+
name_elements = obj.findall(PersonNameElement.XML_TAG)
if name_elements:
for name_element_obj in name_elements:
@@ -1074,6 +1119,9 @@ def from_obj(cls, obj, return_obj=None):
def to_dict(self):
d = {}
+ if self.type_:
+ d['type'] = self.type_
+
if self.name_elements:
for ne in self.name_elements:
d.setdefault('name_elements', []).append(ne.to_dict())
@@ -1088,6 +1136,8 @@ def from_dict(cls, dict_repr, return_obj=None):
if not return_obj:
return_obj = cls()
+ return_obj.type_ = dict_repr.get('type')
+
ne_dicts = dict_repr.get('name_elements', [])
for ne_dict in ne_dicts:
@@ -1100,11 +1150,40 @@ class OrganisationName(stix.Entity):
_namespace = XML_NS_XNL
XML_TAG = "{%s}OrganisationName" % _namespace
+ TYPE_LEGAL_NAME = 'LegalName'
+ TYPE_FORMER_NAME = 'FormerName'
+ TYPE_COMMON_USE = 'CommonUse'
+ TYPE_PUBLISHING_NAME = 'PublishingName'
+ TYPE_OFFICIAL_NAME = 'OfficialName'
+ TYPE_UNOFFICIAL_NAME = 'UnofficialName'
+ TYPE_UNDEFINED = 'Undefined'
+
+ TYPES = (
+ TYPE_LEGAL_NAME,
+ TYPE_FORMER_NAME,
+ TYPE_COMMON_USE,
+ TYPE_PUBLISHING_NAME,
+ TYPE_OFFICIAL_NAME,
+ TYPE_UNOFFICIAL_NAME,
+ TYPE_UNDEFINED,
+ )
+
def __init__(self, name_elements=None, subdivision_names=None, type_=None):
self.type_ = type_
self.name_elements = name_elements
self.subdivision_names = subdivision_names
+ @property
+ def type_(self):
+ return self._type
+
+ @type_.setter
+ def type_(self, value):
+ if value and value not in self.TYPES:
+ raise ValueError('value must be one of %s: ' % (self.TYPES,))
+
+ self._type = value
+
@property
def name_elements(self):
return self._name_elements
@@ -1235,9 +1314,6 @@ def value(self):
@value.setter
def value(self, value):
- # if not value:
- # raise ValueError('value cannot be None')
-
self._value = value
@classmethod
@@ -1270,8 +1346,8 @@ class PersonNameElement(_BaseNameElement):
_namespace = XML_NS_XNL
XML_TAG = "{%s}NameElement" % _namespace
- TYPE_TITLE = 'Title'
TYPE_PRECEDING_TITLE = 'PrecedingTitle'
+ TYPE_TITLE = 'Title'
TYPE_FIRST_NAME = 'FirstName'
TYPE_MIDDLE_NAME = 'MiddleName'
TYPE_LAST_NAME = 'LastName'
diff --git a/stix/indicator/indicator.py b/stix/indicator/indicator.py
index 5842209f..fc941045 100644
--- a/stix/indicator/indicator.py
+++ b/stix/indicator/indicator.py
@@ -470,7 +470,7 @@ def add_related_indicator(self, indicator):
``related_indicators`` list property.
Calling this method is the same as calling ``append()`` on the
- ``related_indicators`` proeprty.
+ ``related_indicators`` property.
See Also:
The :class:`RelatedIndicators` documentation.
diff --git a/stix/test/coa_test.py b/stix/test/coa_test.py
index 9a3c0e17..05d2b905 100644
--- a/stix/test/coa_test.py
+++ b/stix/test/coa_test.py
@@ -51,9 +51,9 @@ class COATests(EntityTestCase, unittest.TestCase):
},
'objective': ObjectiveTests._full_dict,
'parameter_observables': {
- 'major_version': 2,
- 'minor_version': 1,
- 'update_version': 0,
+ 'cybox_major_version': '2',
+ 'cybox_minor_version': '1',
+ 'cybox_update_version': '0',
'observables': [
{
'idref': "example:Observable-1"
diff --git a/stix/test/core/stix_package_test.py b/stix/test/core/stix_package_test.py
index 47e31db4..0ce35e13 100644
--- a/stix/test/core/stix_package_test.py
+++ b/stix/test/core/stix_package_test.py
@@ -101,9 +101,9 @@ class STIXPackageTests(EntityTestCase, unittest.TestCase):
'incidents': IncidentsTests._full_dict,
'indicators': IndicatorsTests._full_dict,
'observables': {
- 'major_version': 2,
- 'minor_version': 1,
- 'update_version': 0,
+ 'cybox_major_version': '2',
+ 'cybox_minor_version': '1',
+ 'cybox_update_version': '0',
'observables': [
{
'idref': "example:Observable-1"
diff --git a/stix/test/extensions/identity/ciq_identity_3_0_test.py b/stix/test/extensions/identity/ciq_identity_3_0_test.py
index 20d7d101..542371e9 100644
--- a/stix/test/extensions/identity/ciq_identity_3_0_test.py
+++ b/stix/test/extensions/identity/ciq_identity_3_0_test.py
@@ -40,8 +40,16 @@ class CIQIdentity3_0InstanceTests(EntityTestCase, unittest.TestCase):
],
'person_names': [
{
+ 'type': 'LegalName',
'name_elements': [
- {'value': 'John Smith'}
+ {
+ 'element_type': 'FirstName',
+ 'value': 'John',
+ },
+ {
+ 'element_type': 'LastName',
+ 'value': 'Smith',
+ }
]
},
{
diff --git a/stix/test/extensions/malware/maec_4_1_malware_test.py b/stix/test/extensions/malware/maec_4_1_malware_test.py
index 1829246c..30257c3c 100644
--- a/stix/test/extensions/malware/maec_4_1_malware_test.py
+++ b/stix/test/extensions/malware/maec_4_1_malware_test.py
@@ -134,14 +134,14 @@ def test_parse_malware(self):
"""Test parsing a normal MalwareInstance from XML
"""
stix_pkg = STIXPackage.from_xml(self.XML)
- mw = stix_pkg.ttps[0].behavior.malware_instances[0].to_dict()
+ mw = stix_pkg.ttps.ttp[0].behavior.malware_instances[0].to_dict()
self.assertTrue('names' in mw)
def test_parse_malware_maec(self):
"""Test parsing a MaecInstance from XML
"""
stix_pkg = STIXPackage.from_xml(self.XML_MAEC)
- mw = stix_pkg.ttps[0].behavior.malware_instances[0].to_dict()
+ mw = stix_pkg.ttps.ttp[0].behavior.malware_instances[0].to_dict()
self.assertTrue('names' in mw)
diff --git a/stix/test/report_test.py b/stix/test/report_test.py
index f99ecb7f..2ce43055 100644
--- a/stix/test/report_test.py
+++ b/stix/test/report_test.py
@@ -102,9 +102,9 @@ class ReportTests(EntityTestCase, unittest.TestCase):
'incidents': IncidentsTests._full_dict,
'indicators': IndicatorsTests._full_dict,
'observables': {
- 'major_version': 2,
- 'minor_version': 1,
- 'update_version': 0,
+ 'cybox_major_version': '2',
+ 'cybox_minor_version': '1',
+ 'cybox_update_version': '0',
'observables': [
{
'idref': "example:Observable-1"
diff --git a/stix/test/ttp_test.py b/stix/test/ttp_test.py
index ef43689f..c7c4a339 100644
--- a/stix/test/ttp_test.py
+++ b/stix/test/ttp_test.py
@@ -52,9 +52,9 @@ class InfrastructureTests(EntityTestCase, unittest.TestCase):
'short_description': 'Short Description',
'types': ['foo', 'bar'],
'observable_characterization': {
- 'major_version': 2,
- 'minor_version': 1,
- 'update_version': 0,
+ 'cybox_major_version': '2',
+ 'cybox_minor_version': '1',
+ 'cybox_update_version': '0',
'observables': [
{
'idref': "example:Observable-1"
@@ -188,9 +188,9 @@ class VictimTargetingTests(EntityTestCase, unittest.TestCase):
}
],
'targeted_technical_details': {
- 'major_version': 2,
- 'minor_version': 1,
- 'update_version': 0,
+ 'cybox_major_version': '2',
+ 'cybox_minor_version': '1',
+ 'cybox_update_version': '0',
'observables': [
{
'idref': "example:Observable-2"
diff --git a/stix/version.py b/stix/version.py
index e146c343..a2a3a195 100644
--- a/stix/version.py
+++ b/stix/version.py
@@ -1,4 +1,4 @@
# Copyright (c) 2017, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-__version__ = "1.2.0.6"
+__version__ = "1.2.0.11"
diff --git a/tox.ini b/tox.ini
index 8067c9d6..275e8bdf 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,12 +1,11 @@
[tox]
-envlist = py27, py34, py35, py36, lxml23, no-maec
+envlist = py27, py34, py35, py36, py37, py38, lxml23, docs, no-maec, packaging
[testenv]
commands =
nosetests stix
# NOTE: python-stix does not have any doctests
# sphinx-build -b doctest docs docs/_build/doctest
- sphinx-build -b html docs docs/_build/html
deps =
-rrequirements.txt
@@ -30,9 +29,21 @@ deps =
nose==1.3.7
tox==2.7.0
+[testenv:docs]
+commands =
+ sphinx-build -W -b html -d {envtmpdir}/doctrees docs {envtmpdir}/html
+
+[testenv:packaging]
+deps =
+ readme_renderer
+commands =
+ python setup.py check -r -s
+
[travis]
python =
- 2.7: py27, docs, lxml23, no-maec
+ 2.7: py27, docs, lxml23, no-maec, packaging
3.4: py34, no-maec
3.5: py35, no-maec
- 3.6: py36, no-maec
+ 3.6: py36, no-maec, packaging
+ 3.7: py37, no-maec
+ 3.8: py38, no-maec