Factored out more of the STIX identifier validity checking,
partly inspired by PR #263. This resulted in some error message format changes (an improvement, I think), which caused some unit test breakage. Removed those asserts from the unit tests, since tests shouldn't be testing human-targeted error messages.master
							parent
							
								
									ed106f23ff
								
							
						
					
					
						commit
						da5978d317
					
				|  | @ -41,6 +41,38 @@ def _check_uuid(uuid_str, spec_version): | |||
|     return ok | ||||
| 
 | ||||
| 
 | ||||
| def _validate_id(id_, spec_version, required_prefix): | ||||
|     """ | ||||
|     Check the STIX identifier for correctness, raise an exception if there are | ||||
|     errors. | ||||
| 
 | ||||
|     :param id_: The STIX identifier | ||||
|     :param spec_version: The STIX specification version to use | ||||
|     :param required_prefix: The required prefix on the identifier, if any. | ||||
|         This function doesn't add a "--" suffix to the prefix, so callers must | ||||
|         add it if it is important.  Pass None to skip the prefix check. | ||||
|     :raises ValueError: If there are any errors with the identifier | ||||
|     """ | ||||
|     if required_prefix: | ||||
|         if not id_.startswith(required_prefix): | ||||
|             raise ValueError("must start with '{}'.".format(required_prefix)) | ||||
| 
 | ||||
|     try: | ||||
|         if required_prefix: | ||||
|             uuid_part = id_[len(required_prefix):] | ||||
|         else: | ||||
|             idx = id_.index("--") | ||||
|             uuid_part = id_[idx+2:] | ||||
| 
 | ||||
|         result = _check_uuid(uuid_part, spec_version) | ||||
|     except ValueError: | ||||
|         # replace their ValueError with ours | ||||
|         raise ValueError(ERROR_INVALID_ID.format(id_)) | ||||
| 
 | ||||
|     if not result: | ||||
|         raise ValueError(ERROR_INVALID_ID.format(id_)) | ||||
| 
 | ||||
| 
 | ||||
| class Property(object): | ||||
|     """Represent a property of STIX data type. | ||||
| 
 | ||||
|  | @ -198,19 +230,7 @@ class IDProperty(Property): | |||
|         super(IDProperty, self).__init__() | ||||
| 
 | ||||
|     def clean(self, value): | ||||
|         if not value.startswith(self.required_prefix): | ||||
|             raise ValueError("must start with '{}'.".format(self.required_prefix)) | ||||
| 
 | ||||
|         uuid_part = value[len(self.required_prefix):] | ||||
|         try: | ||||
|             result = _check_uuid(uuid_part, self.spec_version) | ||||
|         except ValueError: | ||||
|             # replace their ValueError with ours | ||||
|             raise ValueError(ERROR_INVALID_ID.format(value)) | ||||
| 
 | ||||
|         if not result: | ||||
|             raise ValueError(ERROR_INVALID_ID.format(value)) | ||||
| 
 | ||||
|         _validate_id(value, self.spec_version, self.required_prefix) | ||||
|         return value | ||||
| 
 | ||||
|     def default(self): | ||||
|  | @ -396,26 +416,7 @@ class ReferenceProperty(Property): | |||
|             value = value.id | ||||
|         value = str(value) | ||||
| 
 | ||||
|         if self.required_prefix: | ||||
|             if not value.startswith(self.required_prefix): | ||||
|                 raise ValueError( | ||||
|                     "must start with '{}'.".format(self.required_prefix), | ||||
|                 ) | ||||
| 
 | ||||
|         try: | ||||
|             if self.required_prefix: | ||||
|                 uuid_part = value[len(self.required_prefix):] | ||||
|             else: | ||||
|                 idx = value.index("--") | ||||
|                 uuid_part = value[idx+2:] | ||||
| 
 | ||||
|             result = _check_uuid(uuid_part, self.spec_version) | ||||
|         except ValueError: | ||||
|             # replace their ValueError with ours | ||||
|             raise ValueError(ERROR_INVALID_ID.format(value)) | ||||
| 
 | ||||
|         if not result: | ||||
|             raise ValueError(ERROR_INVALID_ID.format(value)) | ||||
|         _validate_id(value, self.spec_version, self.required_prefix) | ||||
| 
 | ||||
|         return value | ||||
| 
 | ||||
|  |  | |||
|  | @ -112,8 +112,6 @@ def test_indicator_created_ref_invalid_format(): | |||
| 
 | ||||
|     assert excinfo.value.cls == stix2.v20.Indicator | ||||
|     assert excinfo.value.prop_name == "created_by_ref" | ||||
|     assert excinfo.value.reason == "must start with 'identity'." | ||||
|     assert str(excinfo.value) == "Invalid value for Indicator 'created_by_ref': must start with 'identity'." | ||||
| 
 | ||||
| 
 | ||||
| def test_indicator_revoked_invalid(): | ||||
|  |  | |||
|  | @ -87,8 +87,6 @@ def test_report_example_objects_in_object_refs_with_bad_id(): | |||
| 
 | ||||
|     assert excinfo.value.cls == stix2.v20.Report | ||||
|     assert excinfo.value.prop_name == "object_refs" | ||||
|     assert excinfo.value.reason == stix2.properties.ERROR_INVALID_ID | ||||
|     assert str(excinfo.value) == "Invalid value for Report 'object_refs': " + stix2.properties.ERROR_INVALID_ID | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.parametrize( | ||||
|  |  | |||
|  | @ -59,8 +59,6 @@ def test_sighting_bad_where_sighted_refs(): | |||
| 
 | ||||
|     assert excinfo.value.cls == stix2.v20.Sighting | ||||
|     assert excinfo.value.prop_name == "where_sighted_refs" | ||||
|     assert excinfo.value.reason == "must start with 'identity'." | ||||
|     assert str(excinfo.value) == "Invalid value for Sighting 'where_sighted_refs': must start with 'identity'." | ||||
| 
 | ||||
| 
 | ||||
| def test_sighting_type_must_be_sightings(): | ||||
|  | @ -69,8 +67,6 @@ def test_sighting_type_must_be_sightings(): | |||
| 
 | ||||
|     assert excinfo.value.cls == stix2.v20.Sighting | ||||
|     assert excinfo.value.prop_name == "type" | ||||
|     assert excinfo.value.reason == "must equal 'sighting'." | ||||
|     assert str(excinfo.value) == "Invalid value for Sighting 'type': must equal 'sighting'." | ||||
| 
 | ||||
| 
 | ||||
| def test_invalid_kwarg_to_sighting(): | ||||
|  |  | |||
|  | @ -116,8 +116,6 @@ def test_indicator_created_ref_invalid_format(): | |||
| 
 | ||||
|     assert excinfo.value.cls == stix2.v21.Indicator | ||||
|     assert excinfo.value.prop_name == "created_by_ref" | ||||
|     assert excinfo.value.reason == "must start with 'identity'." | ||||
|     assert str(excinfo.value) == "Invalid value for Indicator 'created_by_ref': must start with 'identity'." | ||||
| 
 | ||||
| 
 | ||||
| def test_indicator_revoked_invalid(): | ||||
|  |  | |||
|  | @ -88,8 +88,6 @@ def test_report_example_objects_in_object_refs_with_bad_id(): | |||
| 
 | ||||
|     assert excinfo.value.cls == stix2.v21.Report | ||||
|     assert excinfo.value.prop_name == "object_refs" | ||||
|     assert excinfo.value.reason == stix2.properties.ERROR_INVALID_ID | ||||
|     assert str(excinfo.value) == "Invalid value for Report 'object_refs': " + stix2.properties.ERROR_INVALID_ID | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.parametrize( | ||||
|  |  | |||
|  | @ -61,8 +61,6 @@ def test_sighting_bad_where_sighted_refs(): | |||
| 
 | ||||
|     assert excinfo.value.cls == stix2.v21.Sighting | ||||
|     assert excinfo.value.prop_name == "where_sighted_refs" | ||||
|     assert excinfo.value.reason == "must start with 'identity'." | ||||
|     assert str(excinfo.value) == "Invalid value for Sighting 'where_sighted_refs': must start with 'identity'." | ||||
| 
 | ||||
| 
 | ||||
| def test_sighting_type_must_be_sightings(): | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Michael Chisholm
						Michael Chisholm