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
Emmanuelle Vargas-Gonzalez 2018-10-17 07:34:15 -04:00
parent b2ef77b322
commit f8a72b0937
7 changed files with 32 additions and 67 deletions

View File

@ -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',

View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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():

View File

@ -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},
)

View File

@ -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():