Custom builder code updated for 3.7 support.
Updated properties to support more constrains. Make all regexes literal strings. Update tests to align to new constrains. Workbench problem. _check_object_constraints() uses instance class to perform proper class resolution calls.stix2.1
parent
b2ef77b322
commit
f8a72b0937
7
setup.py
7
setup.py
|
@ -17,15 +17,16 @@ def get_version():
|
|||
raise AttributeError("Package does not have a __version__")
|
||||
|
||||
|
||||
with open('README.rst') as f:
|
||||
long_description = f.read()
|
||||
def get_long_description():
|
||||
with open('README.rst') as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
setup(
|
||||
name='stix2',
|
||||
version=get_version(),
|
||||
description='Produce and consume STIX 2 JSON content',
|
||||
long_description=long_description,
|
||||
long_description=get_long_description(),
|
||||
url='https://github.com/oasis-open/cti-python-stix2',
|
||||
author='OASIS Cyber Threat Intelligence Technical Committee',
|
||||
author_email='cti-users@lists.oasis-open.org',
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from collections import OrderedDict
|
||||
import re
|
||||
|
||||
from .base import _Extension, _Observable, _STIXBase
|
||||
from .base import _cls_init, _Extension, _Observable, _STIXBase
|
||||
from .core import (
|
||||
STIXDomainObject, _register_marking, _register_object,
|
||||
_register_observable, _register_observable_extension,
|
||||
|
@ -30,16 +30,7 @@ def _custom_object_builder(cls, type, properties, version):
|
|||
|
||||
def __init__(self, **kwargs):
|
||||
_STIXBase.__init__(self, **kwargs)
|
||||
try:
|
||||
cls.__init__(self, **kwargs)
|
||||
except (AttributeError, TypeError) as e:
|
||||
# Don't accidentally catch errors raised in a custom __init__()
|
||||
if (
|
||||
"has no attribute '__init__'" in str(e) or
|
||||
str(e) == "object.__init__() takes no parameters"
|
||||
):
|
||||
return
|
||||
raise e
|
||||
_cls_init(cls, self, kwargs)
|
||||
|
||||
_register_object(_CustomObject, version=version)
|
||||
return _CustomObject
|
||||
|
@ -56,16 +47,7 @@ def _custom_marking_builder(cls, type, properties, version):
|
|||
|
||||
def __init__(self, **kwargs):
|
||||
_STIXBase.__init__(self, **kwargs)
|
||||
try:
|
||||
cls.__init__(self, **kwargs)
|
||||
except (AttributeError, TypeError) as e:
|
||||
# Don't accidentally catch errors raised in a custom __init__()
|
||||
if (
|
||||
"has no attribute '__init__'" in str(e) or
|
||||
str(e) == "object.__init__() takes no parameters"
|
||||
):
|
||||
return
|
||||
raise e
|
||||
_cls_init(cls, self, kwargs)
|
||||
|
||||
_register_marking(_CustomMarking, version=version)
|
||||
return _CustomMarking
|
||||
|
@ -104,16 +86,7 @@ def _custom_observable_builder(cls, type, properties, version):
|
|||
|
||||
def __init__(self, **kwargs):
|
||||
_Observable.__init__(self, **kwargs)
|
||||
try:
|
||||
cls.__init__(self, **kwargs)
|
||||
except (AttributeError, TypeError) as e:
|
||||
# Don't accidentally catch errors raised in a custom __init__()
|
||||
if (
|
||||
"has no attribute '__init__'" in str(e) or
|
||||
str(e) == "object.__init__() takes no parameters"
|
||||
):
|
||||
return
|
||||
raise e
|
||||
_cls_init(cls, self, kwargs)
|
||||
|
||||
_register_observable(_CustomObservable, version=version)
|
||||
return _CustomObservable
|
||||
|
@ -141,16 +114,7 @@ def _custom_extension_builder(cls, observable, type, properties, version):
|
|||
|
||||
def __init__(self, **kwargs):
|
||||
_Extension.__init__(self, **kwargs)
|
||||
try:
|
||||
cls.__init__(self, **kwargs)
|
||||
except (AttributeError, TypeError) as e:
|
||||
# Don't accidentally catch errors raised in a custom __init__()
|
||||
if (
|
||||
"has no attribute '__init__'" in str(e) or
|
||||
str(e) == "object.__init__() takes no parameters"
|
||||
):
|
||||
return
|
||||
raise e
|
||||
_cls_init(cls, self, kwargs)
|
||||
|
||||
_register_observable_extension(observable, _CustomExtension, version=version)
|
||||
return _CustomExtension
|
||||
|
|
|
@ -170,7 +170,7 @@ class HexConstant(_Constant):
|
|||
value (str): hexadecimal value
|
||||
"""
|
||||
def __init__(self, value):
|
||||
if not re.match('^([a-fA-F0-9]{2})+$', value):
|
||||
if not re.match(r'^([a-fA-F0-9]{2})+$', value):
|
||||
raise ValueError("must contain an even number of hexadecimal characters")
|
||||
self.value = value
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ from .utils import _get_dict, get_class_hierarchy_names, parse_into_datetime
|
|||
# component must be a 4, and the first hex digit of the fourth component
|
||||
# must be 8, 9, a, or b (10xx bit pattern).
|
||||
ID_REGEX = re.compile(
|
||||
"^[a-z0-9][a-z0-9-]+[a-z0-9]--" # object type
|
||||
r"^[a-z0-9][a-z0-9-]+[a-z0-9]--" # object type
|
||||
"[0-9a-fA-F]{8}-"
|
||||
"[0-9a-fA-F]{4}-"
|
||||
"4[0-9a-fA-F]{3}-"
|
||||
|
@ -302,7 +302,7 @@ class DictionaryProperty(Property):
|
|||
elif self.spec_version == '2.1':
|
||||
if len(k) > 250:
|
||||
raise DictionaryKeyError(k, "longer than 250 characters")
|
||||
if not re.match("^[a-zA-Z0-9_-]+$", k):
|
||||
if not re.match(r"^[a-zA-Z0-9_-]+$", k):
|
||||
msg = (
|
||||
"contains characters other than lowercase a-z, "
|
||||
"uppercase A-Z, numerals 0-9, hyphen (-), or "
|
||||
|
@ -313,20 +313,20 @@ class DictionaryProperty(Property):
|
|||
|
||||
|
||||
HASHES_REGEX = {
|
||||
"MD5": ("^[a-fA-F0-9]{32}$", "MD5"),
|
||||
"MD6": ("^[a-fA-F0-9]{32}|[a-fA-F0-9]{40}|[a-fA-F0-9]{56}|[a-fA-F0-9]{64}|[a-fA-F0-9]{96}|[a-fA-F0-9]{128}$", "MD6"),
|
||||
"RIPEMD160": ("^[a-fA-F0-9]{40}$", "RIPEMD-160"),
|
||||
"SHA1": ("^[a-fA-F0-9]{40}$", "SHA-1"),
|
||||
"SHA224": ("^[a-fA-F0-9]{56}$", "SHA-224"),
|
||||
"SHA256": ("^[a-fA-F0-9]{64}$", "SHA-256"),
|
||||
"SHA384": ("^[a-fA-F0-9]{96}$", "SHA-384"),
|
||||
"SHA512": ("^[a-fA-F0-9]{128}$", "SHA-512"),
|
||||
"SHA3224": ("^[a-fA-F0-9]{56}$", "SHA3-224"),
|
||||
"SHA3256": ("^[a-fA-F0-9]{64}$", "SHA3-256"),
|
||||
"SHA3384": ("^[a-fA-F0-9]{96}$", "SHA3-384"),
|
||||
"SHA3512": ("^[a-fA-F0-9]{128}$", "SHA3-512"),
|
||||
"SSDEEP": ("^[a-zA-Z0-9/+:.]{1,128}$", "ssdeep"),
|
||||
"WHIRLPOOL": ("^[a-fA-F0-9]{128}$", "WHIRLPOOL"),
|
||||
"MD5": (r"^[a-fA-F0-9]{32}$", "MD5"),
|
||||
"MD6": (r"^[a-fA-F0-9]{32}|[a-fA-F0-9]{40}|[a-fA-F0-9]{56}|[a-fA-F0-9]{64}|[a-fA-F0-9]{96}|[a-fA-F0-9]{128}$", "MD6"),
|
||||
"RIPEMD160": (r"^[a-fA-F0-9]{40}$", "RIPEMD-160"),
|
||||
"SHA1": (r"^[a-fA-F0-9]{40}$", "SHA-1"),
|
||||
"SHA224": (r"^[a-fA-F0-9]{56}$", "SHA-224"),
|
||||
"SHA256": (r"^[a-fA-F0-9]{64}$", "SHA-256"),
|
||||
"SHA384": (r"^[a-fA-F0-9]{96}$", "SHA-384"),
|
||||
"SHA512": (r"^[a-fA-F0-9]{128}$", "SHA-512"),
|
||||
"SHA3224": (r"^[a-fA-F0-9]{56}$", "SHA3-224"),
|
||||
"SHA3256": (r"^[a-fA-F0-9]{64}$", "SHA3-256"),
|
||||
"SHA3384": (r"^[a-fA-F0-9]{96}$", "SHA3-384"),
|
||||
"SHA3512": (r"^[a-fA-F0-9]{128}$", "SHA3-512"),
|
||||
"SSDEEP": (r"^[a-zA-Z0-9/+:.]{1,128}$", "ssdeep"),
|
||||
"WHIRLPOOL": (r"^[a-fA-F0-9]{128}$", "WHIRLPOOL"),
|
||||
}
|
||||
|
||||
|
||||
|
@ -359,7 +359,7 @@ class BinaryProperty(Property):
|
|||
class HexProperty(Property):
|
||||
|
||||
def clean(self, value):
|
||||
if not re.match("^([a-fA-F0-9]{2})+$", value):
|
||||
if not re.match(r"^([a-fA-F0-9]{2})+$", value):
|
||||
raise ValueError("must contain an even number of hexadecimal characters")
|
||||
return value
|
||||
|
||||
|
@ -385,7 +385,7 @@ class ReferenceProperty(Property):
|
|||
return value
|
||||
|
||||
|
||||
SELECTOR_REGEX = re.compile("^[a-z0-9_-]{3,250}(\\.(\\[\\d+\\]|[a-z0-9_-]{1,250}))*$")
|
||||
SELECTOR_REGEX = re.compile(r"^[a-z0-9_-]{3,250}(\.(\[\d+\]|[a-z0-9_-]{1,250}))*$")
|
||||
|
||||
|
||||
class SelectorProperty(Property):
|
||||
|
|
|
@ -374,7 +374,7 @@ def test_invalid_integer_constant():
|
|||
def test_invalid_timestamp_constant():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.TimestampConstant('foo')
|
||||
assert 'must be a datetime object or timestamp string' in str(excinfo)
|
||||
assert 'Must be a datetime object or timestamp string' in str(excinfo)
|
||||
|
||||
|
||||
def test_invalid_float_constant():
|
||||
|
|
|
@ -299,7 +299,7 @@ def test_workbench_custom_property_object_in_observable_extension():
|
|||
allow_custom=True,
|
||||
first_observed="2015-12-21T19:00:00Z",
|
||||
last_observed="2015-12-21T19:00:00Z",
|
||||
number_observed=0,
|
||||
number_observed=1,
|
||||
objects={"0": artifact},
|
||||
)
|
||||
|
||||
|
@ -323,7 +323,7 @@ def test_workbench_custom_property_dict_in_observable_extension():
|
|||
allow_custom=True,
|
||||
first_observed="2015-12-21T19:00:00Z",
|
||||
last_observed="2015-12-21T19:00:00Z",
|
||||
number_observed=0,
|
||||
number_observed=1,
|
||||
objects={"0": artifact},
|
||||
)
|
||||
|
||||
|
|
|
@ -374,7 +374,7 @@ def test_invalid_integer_constant():
|
|||
def test_invalid_timestamp_constant():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.TimestampConstant('foo')
|
||||
assert 'must be a datetime object or timestamp string' in str(excinfo)
|
||||
assert 'Must be a datetime object or timestamp string' in str(excinfo)
|
||||
|
||||
|
||||
def test_invalid_float_constant():
|
||||
|
|
Loading…
Reference in New Issue