Move TypeProperty format checks to __init__

TypeProperty uses a fixed value, so check() was never called. This way
also runs the check at object registration time because the wrapper
creates an instance of TypeProperty and doesn't have to wait for the
object to be instantiated so clean() can be called.
Also fix some tests.
master
Chris Lenk 2020-04-02 08:17:34 -04:00
parent 03cb225932
commit 13cddf9d6d
4 changed files with 58 additions and 48 deletions

View File

@ -200,6 +200,11 @@ def _register_object(new_type, version=None):
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
None, use latest version.
Raises:
ValueError: If the class being registered wasn't created with the
@CustomObject decorator.
DuplicateRegistrationError: If the class has already been registered.
"""
if not issubclass(new_type, _DomainObject):
@ -208,8 +213,6 @@ def _register_object(new_type, version=None):
new_type.__name__,
)
new_type._properties['type'].clean(new_type._type)
if version:
v = 'v' + version.replace('.', '')
else:
@ -232,8 +235,11 @@ def _register_marking(new_marking, version=None):
"""
mark_type = new_marking._type
properties = new_marking._properties
stix2.properties._validate_type(mark_type, version)
if version == "2.1":
for prop_name, prop_value in properties.items():
if not re.match(PREFIX_21_REGEX, prop_name):
@ -246,9 +252,9 @@ def _register_marking(new_marking, version=None):
v = 'v' + stix2.DEFAULT_VERSION.replace('.', '')
OBJ_MAP_MARKING = STIX2_OBJ_MAPS[v]['markings']
if new_marking._type in OBJ_MAP_MARKING.keys():
raise DuplicateRegistrationError("STIX Marking", new_marking._type)
OBJ_MAP_MARKING[new_marking._type] = new_marking
if mark_type in OBJ_MAP_MARKING.keys():
raise DuplicateRegistrationError("STIX Marking", mark_type)
OBJ_MAP_MARKING[mark_type] = new_marking
def _register_observable(new_observable, version=None):
@ -261,8 +267,6 @@ def _register_observable(new_observable, version=None):
"""
new_observable._properties['type'].clean(new_observable._type)
if version:
v = 'v' + version.replace('.', '')
else:
@ -296,8 +300,7 @@ def _register_observable_extension(
if not issubclass(obs_class, _Observable):
raise ValueError("'observable' must be a valid Observable class!")
temp_prop = stix2.properties.TypeProperty(ext_type, spec_version=version)
temp_prop.clean(ext_type)
stix2.properties._validate_type(ext_type, version)
if not new_extension._properties:
raise ValueError(

View File

@ -84,6 +84,36 @@ def _validate_id(id_, spec_version, required_prefix):
raise ValueError(ERROR_INVALID_ID.format(id_))
def _validate_type(type_, spec_version):
"""
Check the STIX type name for correctness, raise an exception if there are
errors.
:param type_: The STIX type name
:param spec_version: The STIX specification version to use
:raises ValueError: If there are any errors with the identifier
"""
if spec_version == "2.0":
if not re.match(TYPE_REGEX, type_):
raise ValueError(
"Invalid type name '%s': must only contain the "
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." %
type_,
)
else: # 2.1+
if not re.match(TYPE_21_REGEX, type_):
raise ValueError(
"Invalid type name '%s': must only contain the "
"characters a-z (lowercase ASCII), 0-9, and hyphen (-) "
"and must begin with an a-z character" % type_,
)
if len(type_) < 3 or len(type_) > 250:
raise ValueError(
"Invalid type name '%s': must be between 3 and 250 characters." % type_,
)
class Property(object):
"""Represent a property of STIX data type.
@ -236,32 +266,10 @@ class StringProperty(Property):
class TypeProperty(Property):
def __init__(self, type, spec_version=stix2.DEFAULT_VERSION):
_validate_type(type, spec_version)
self.spec_version = spec_version
super(TypeProperty, self).__init__(fixed=type)
def clean(self, value):
if self.spec_version == "2.0":
if not re.match(TYPE_REGEX, type):
raise ValueError(
"Invalid type name '%s': must only contain the "
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." %
type,
)
else: # 2.1+
if not re.match(TYPE_21_REGEX, type):
raise ValueError(
"Invalid type name '%s': must only contain the "
"characters a-z (lowercase ASCII), 0-9, and hyphen (-) "
"and must begin with an a-z character" % type,
)
if len(type) < 3 or len(type) > 250:
raise ValueError(
"Invalid type name '%s': must be between 3 and 250 characters." % type,
)
return value
class IDProperty(Property):

View File

@ -483,7 +483,7 @@ def test_custom_observable_object_invalid_type_name():
)
class NewObs(object):
pass # pragma: no cover
assert "Invalid observable type name 'x':" in str(excinfo.value)
assert "Invalid type name 'x':" in str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
@stix2.v20.CustomObservable(
@ -493,7 +493,7 @@ def test_custom_observable_object_invalid_type_name():
)
class NewObs2(object):
pass # pragma: no cover
assert "Invalid observable type name 'x_new_obs':" in str(excinfo.value)
assert "Invalid type name 'x_new_obs':" in str(excinfo.value)
def test_custom_observable_object_invalid_ref_property():
@ -808,7 +808,7 @@ def test_custom_extension_invalid_type_name():
)
class FooExtension():
pass # pragma: no cover
assert "Invalid extension type name 'x':" in str(excinfo.value)
assert "Invalid type name 'x':" in str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
@stix2.v20.CustomExtension(
@ -818,7 +818,7 @@ def test_custom_extension_invalid_type_name():
)
class BlaExtension():
pass # pragma: no cover
assert "Invalid extension type name 'x_new_ext':" in str(excinfo.value)
assert "Invalid type name 'x_new_ext':" in str(excinfo.value)
def test_custom_extension_no_properties():
@ -968,9 +968,8 @@ def test_register_custom_object():
class CustomObject2(object):
_type = 'awesome-object'
with pytest.raises(ValueError):
stix2.parsing._register_object(CustomObject2, version="2.0")
# Note that we will always check against newest OBJ_MAP.
assert (CustomObject2._type, CustomObject2) in stix2.v20.OBJ_MAP.items()
def test_extension_property_location():

View File

@ -375,7 +375,7 @@ def test_custom_marking_invalid_type_name():
)
class NewObj(object):
pass # pragma: no cover
assert "Invalid marking type name 'x': " in str(excinfo.value)
assert "Invalid type name 'x': " in str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomMarking(
@ -385,7 +385,7 @@ def test_custom_marking_invalid_type_name():
)
class NewObj2(object):
pass # pragma: no cover
assert "Invalid marking type name 'x_new_marking':" in str(excinfo.value)
assert "Invalid type name 'x_new_marking':" in str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomMarking(
@ -395,7 +395,7 @@ def test_custom_marking_invalid_type_name():
)
class NewObj3(object):
pass # pragma: no cover
assert "Invalid marking type name '7x-new-marking':" in str(excinfo.value)
assert "Invalid type name '7x-new-marking':" in str(excinfo.value)
# Custom Objects
@ -619,7 +619,7 @@ def test_custom_observable_object_invalid_type_name():
)
class NewObs(object):
pass # pragma: no cover
assert "Invalid observable type name 'x':" in str(excinfo.value)
assert "Invalid type name 'x':" in str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomObservable(
@ -629,7 +629,7 @@ def test_custom_observable_object_invalid_type_name():
)
class NewObs2(object):
pass # pragma: no cover
assert "Invalid observable type name 'x_new_obs':" in str(excinfo.value)
assert "Invalid type name 'x_new_obs':" in str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomObservable(
@ -639,7 +639,7 @@ def test_custom_observable_object_invalid_type_name():
)
class NewObs3(object):
pass # pragma: no cover
assert "Invalid observable type name '7x-new-obs':" in str(excinfo.value)
assert "Invalid type name '7x-new-obs':" in str(excinfo.value)
def test_custom_observable_object_invalid_ref_property():
@ -1005,7 +1005,7 @@ def test_custom_extension_invalid_type_name():
)
class FooExtension():
pass # pragma: no cover
assert "Invalid extension type name 'x':" in str(excinfo.value)
assert "Invalid type name 'x':" in str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomExtension(
@ -1015,7 +1015,7 @@ def test_custom_extension_invalid_type_name():
)
class BlaExtension():
pass # pragma: no cover
assert "Invalid extension type name 'x_new_ext':" in str(excinfo.value)
assert "Invalid type name 'x_new_ext':" in str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomExtension(
@ -1025,7 +1025,7 @@ def test_custom_extension_invalid_type_name():
)
class Bla2Extension():
pass # pragma: no cover
assert "Invalid extension type name '7x-new-ext':" in str(excinfo.value)
assert "Invalid type name '7x-new-ext':" in str(excinfo.value)
def test_custom_extension_no_properties():