From 41f2ceb8e55af5a6c378fcd803eef607ee2093ed Mon Sep 17 00:00:00 2001 From: Greg Back Date: Fri, 19 May 2017 12:51:59 -0500 Subject: [PATCH] Change remaining 'fields' to 'properties' --- README.md | 16 +++++++++------- stix2/base.py | 10 +++++----- stix2/exceptions.py | 16 ++++++++-------- stix2/test/test_external_reference.py | 2 +- stix2/test/test_indicator.py | 6 +++--- stix2/test/test_kill_chain_phases.py | 6 +++--- stix2/test/test_malware.py | 6 +++--- stix2/test/test_observed_data.py | 2 +- stix2/test/test_properties.py | 2 +- stix2/test/test_relationship.py | 8 ++++---- stix2/test/test_sighting.py | 2 +- stix2/test/test_versioning.py | 2 +- stix2/utils.py | 2 +- 13 files changed, 41 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index d209911..81fc8f1 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ provided as keyword arguments: ```python >>> indicator = Indicator(type='xxx', ...) - ValueError: Indicators must have type='indicator' + stix2.exceptions.InvalidValueError: Invalid value for Indicator 'type': must equal 'indicator'. ``` - If not provided, `id` will be generated randomly. If you provide an `id` @@ -53,19 +53,19 @@ provided as keyword arguments: ```python >>> indicator = Indicator(id="campaign--63ce9068-b5ab-47fa-a2cf-a602ea01f21a") - ValueError: Invalid value for Indicator 'id': must start with 'indicator--'. + stix2.exceptions.InvalidValueError: Invalid value for Indicator 'id': must start with 'indicator--'. ``` - If not provided, `created` and `modified` will be set to the (same) current time. For indicators, `labels` and `pattern` are required and cannot be set -automatically. Trying to create an indicator that is missing one of these fields -will result in an error: +automatically. Trying to create an indicator that is missing one of these +properties will result in an error: ```python >>> indicator = Indicator() -ValueError: Missing required field(s) for Indicator: (labels, pattern). +stix2.exceptions.MissingPropertiesError: No values for required properties for Indicator: (labels, pattern). ``` However, the required `valid_from` attribute on Indicators will be set to the @@ -89,8 +89,10 @@ TBD: Should we allow property access using the standard Python attribute syntax? Attempting to modify any attributes will raise an error: ```python ->>>indicator['name'] = "This is a revised name" -ValueError: Cannot modify properties after creation. +>>> indicator['name'] = "This is a revised name" +TypeError: 'Indicator' object does not support item assignment +>>> indicator.name = "This is a revised name" +stix2.exceptions.ImmutableError: Cannot modify properties after creation. ``` To update the properties of an object, see [Versioning](#versioning) below. diff --git a/stix2/base.py b/stix2/base.py index fc64883..7d2bf24 100644 --- a/stix2/base.py +++ b/stix2/base.py @@ -5,8 +5,8 @@ import copy import datetime as dt import json -from .exceptions import (AtLeastOnePropertyError, DependentPropertiestError, ExtraFieldsError, ImmutableError, - InvalidObjRefError, InvalidValueError, MissingFieldsError, MutuallyExclusivePropertiesError, +from .exceptions import (AtLeastOnePropertyError, DependentPropertiesError, ExtraPropertiesError, ImmutableError, + InvalidObjRefError, InvalidValueError, MissingPropertiesError, MutuallyExclusivePropertiesError, RevokeError, UnmodifiablePropertyError) from .utils import NOW, format_datetime, get_timestamp, parse_into_datetime @@ -75,7 +75,7 @@ class _STIXBase(collections.Mapping): if dp in current_properties and (p not in current_properties or (v and not current_properties(p) == v)): failed_dependency_pairs.append((p, dp)) if failed_dependency_pairs: - raise DependentPropertiestError(self.__class__, failed_dependency_pairs) + raise DependentPropertiesError(self.__class__, failed_dependency_pairs) def _check_object_constraints(self): if self.granular_markings: @@ -92,7 +92,7 @@ class _STIXBase(collections.Mapping): # Detect any keyword arguments not allowed for a specific type extra_kwargs = list(set(kwargs) - set(cls._properties)) if extra_kwargs: - raise ExtraFieldsError(cls, extra_kwargs) + raise ExtraPropertiesError(cls, extra_kwargs) # Remove any keyword arguments whose value is None setting_kwargs = {} @@ -104,7 +104,7 @@ class _STIXBase(collections.Mapping): required_properties = get_required_properties(cls._properties) missing_kwargs = set(required_properties) - set(setting_kwargs) if missing_kwargs: - raise MissingFieldsError(cls, missing_kwargs) + raise MissingPropertiesError(cls, missing_kwargs) for prop_name, prop_metadata in cls._properties.items(): self._check_property(prop_name, prop_metadata, setting_kwargs) diff --git a/stix2/exceptions.py b/stix2/exceptions.py index 7c92dda..5cbaae9 100644 --- a/stix2/exceptions.py +++ b/stix2/exceptions.py @@ -16,11 +16,11 @@ class InvalidValueError(STIXError, ValueError): return msg.format(self) -class MissingFieldsError(STIXError, ValueError): +class MissingPropertiesError(STIXError, ValueError): """Missing one or more required properties when constructing STIX object.""" def __init__(self, cls, properties): - super(MissingFieldsError, self).__init__() + super(MissingPropertiesError, self).__init__() self.cls = cls self.properties = sorted(list(properties)) @@ -30,11 +30,11 @@ class MissingFieldsError(STIXError, ValueError): ", ".join(x for x in self.properties)) -class ExtraFieldsError(STIXError, TypeError): +class ExtraPropertiesError(STIXError, TypeError): """One or more extra properties were provided when constructing STIX object.""" def __init__(self, cls, properties): - super(ExtraFieldsError, self).__init__() + super(ExtraPropertiesError, self).__init__() self.cls = cls self.properties = sorted(list(properties)) @@ -99,16 +99,16 @@ class MutuallyExclusivePropertiesError(STIXError, TypeError): self.properties = sorted(list(properties)) def __str__(self): - msg = "The field(s) for {0}: ({1}) are mutually exclusive." + msg = "The ({1}) properties for {0} are mutually exclusive." return msg.format(self.cls.__name__, ", ".join(x for x in self.properties)) -class DependentPropertiestError(STIXError, TypeError): +class DependentPropertiesError(STIXError, TypeError): """Violating interproperty dependency constraint of a STIX object type.""" def __init__(self, cls, dependencies): - super(DependentPropertiestError, self).__init__() + super(DependentPropertiesError, self).__init__() self.cls = cls self.dependencies = dependencies @@ -127,7 +127,7 @@ class AtLeastOnePropertyError(STIXError, TypeError): self.properties = sorted(list(properties)) def __str__(self): - msg = "At least one of the field(s) for {0}: ({1}) must be populated." + msg = "At least one of the ({1}) properties for {0} must be populated." return msg.format(self.cls.__name__, ", ".join(x for x in self.properties)) diff --git a/stix2/test/test_external_reference.py b/stix2/test/test_external_reference.py index 61cfea3..10a6e53 100644 --- a/stix2/test/test_external_reference.py +++ b/stix2/test/test_external_reference.py @@ -110,7 +110,7 @@ def test_external_reference_offline(): def test_external_reference_source_required(): - with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo: + with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo: stix2.ExternalReference() assert excinfo.value.cls == stix2.ExternalReference diff --git a/stix2/test/test_indicator.py b/stix2/test/test_indicator.py index 2afb473..99d34d7 100644 --- a/stix2/test/test_indicator.py +++ b/stix2/test/test_indicator.py @@ -90,7 +90,7 @@ def test_indicator_id_must_start_with_indicator(): def test_indicator_required_properties(): - with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo: + with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo: stix2.Indicator() assert excinfo.value.cls == stix2.Indicator @@ -99,7 +99,7 @@ def test_indicator_required_properties(): def test_indicator_required_property_pattern(): - with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo: + with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo: stix2.Indicator(labels=['malicious-activity']) assert excinfo.value.cls == stix2.Indicator @@ -133,7 +133,7 @@ def test_cannot_assign_to_indicator_attributes(indicator): def test_invalid_kwarg_to_indicator(): - with pytest.raises(stix2.exceptions.ExtraFieldsError) as excinfo: + with pytest.raises(stix2.exceptions.ExtraPropertiesError) as excinfo: stix2.Indicator(my_custom_property="foo", **INDICATOR_KWARGS) assert excinfo.value.cls == stix2.Indicator diff --git a/stix2/test/test_kill_chain_phases.py b/stix2/test/test_kill_chain_phases.py index 2596095..9cddcb9 100644 --- a/stix2/test/test_kill_chain_phases.py +++ b/stix2/test/test_kill_chain_phases.py @@ -37,7 +37,7 @@ def test_kill_chain_example(): def test_kill_chain_required_properties(): - with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo: + with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo: stix2.KillChainPhase() assert excinfo.value.cls == stix2.KillChainPhase @@ -46,7 +46,7 @@ def test_kill_chain_required_properties(): def test_kill_chain_required_property_chain_name(): - with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo: + with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo: stix2.KillChainPhase(phase_name="weaponization") assert excinfo.value.cls == stix2.KillChainPhase @@ -55,7 +55,7 @@ def test_kill_chain_required_property_chain_name(): def test_kill_chain_required_property_phase_name(): - with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo: + with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo: stix2.KillChainPhase(kill_chain_name="lockheed-martin-cyber-kill-chain") assert excinfo.value.cls == stix2.KillChainPhase diff --git a/stix2/test/test_malware.py b/stix2/test/test_malware.py index 23dc68e..8952769 100644 --- a/stix2/test/test_malware.py +++ b/stix2/test/test_malware.py @@ -73,7 +73,7 @@ def test_malware_id_must_start_with_malware(): def test_malware_required_properties(): - with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo: + with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo: stix2.Malware() assert excinfo.value.cls == stix2.Malware @@ -81,7 +81,7 @@ def test_malware_required_properties(): def test_malware_required_property_name(): - with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo: + with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo: stix2.Malware(labels=['ransomware']) assert excinfo.value.cls == stix2.Malware @@ -96,7 +96,7 @@ def test_cannot_assign_to_malware_attributes(malware): def test_invalid_kwarg_to_malware(): - with pytest.raises(stix2.exceptions.ExtraFieldsError) as excinfo: + with pytest.raises(stix2.exceptions.ExtraPropertiesError) as excinfo: stix2.Malware(my_custom_property="foo", **MALWARE_KWARGS) assert excinfo.value.cls == stix2.Malware diff --git a/stix2/test/test_observed_data.py b/stix2/test/test_observed_data.py index 6a56963..c47338f 100644 --- a/stix2/test/test_observed_data.py +++ b/stix2/test/test_observed_data.py @@ -761,7 +761,7 @@ def test_file_example_with_WindowsPEBinaryExt(): def test_file_example_encryption_error(): - with pytest.raises(stix2.exceptions.DependentPropertiestError) as excinfo: + with pytest.raises(stix2.exceptions.DependentPropertiesError) as excinfo: stix2.File(name="qwerty.dll", is_encrypted=False, encryption_algorithm="AES128-CBC" diff --git a/stix2/test/test_properties.py b/stix2/test/test_properties.py index 59e0dd9..5395a9f 100644 --- a/stix2/test/test_properties.py +++ b/stix2/test/test_properties.py @@ -35,7 +35,7 @@ def test_basic_clean(): p.clean(41) -def test_default_field(): +def test_property_default(): class Prop(Property): def default(self): diff --git a/stix2/test/test_relationship.py b/stix2/test/test_relationship.py index c4f9ebe..1e799bf 100644 --- a/stix2/test/test_relationship.py +++ b/stix2/test/test_relationship.py @@ -74,14 +74,14 @@ def test_relationship_id_must_start_with_relationship(): def test_relationship_required_property_relationship_type(): - with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo: + with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo: stix2.Relationship() assert excinfo.value.cls == stix2.Relationship assert excinfo.value.properties == ["relationship_type", "source_ref", "target_ref"] def test_relationship_missing_some_required_properties(): - with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo: + with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo: stix2.Relationship(relationship_type='indicates') assert excinfo.value.cls == stix2.Relationship @@ -89,7 +89,7 @@ def test_relationship_missing_some_required_properties(): def test_relationship_required_properties_target_ref(): - with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo: + with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo: stix2.Relationship( relationship_type='indicates', source_ref=INDICATOR_ID @@ -107,7 +107,7 @@ def test_cannot_assign_to_relationship_attributes(relationship): def test_invalid_kwarg_to_relationship(): - with pytest.raises(stix2.exceptions.ExtraFieldsError) as excinfo: + with pytest.raises(stix2.exceptions.ExtraPropertiesError) as excinfo: stix2.Relationship(my_custom_property="foo", **RELATIONSHIP_KWARGS) assert excinfo.value.cls == stix2.Relationship diff --git a/stix2/test/test_sighting.py b/stix2/test/test_sighting.py index d8db35e..6c9b7d8 100644 --- a/stix2/test/test_sighting.py +++ b/stix2/test/test_sighting.py @@ -75,7 +75,7 @@ def test_sighting_type_must_be_sightings(): def test_invalid_kwarg_to_sighting(): - with pytest.raises(stix2.exceptions.ExtraFieldsError) as excinfo: + with pytest.raises(stix2.exceptions.ExtraPropertiesError) as excinfo: stix2.Sighting(my_custom_property="foo", **SIGHTING_KWARGS) assert excinfo.value.cls == stix2.Sighting diff --git a/stix2/test/test_versioning.py b/stix2/test/test_versioning.py index fc9ae8a..76a13bf 100644 --- a/stix2/test/test_versioning.py +++ b/stix2/test/test_versioning.py @@ -138,7 +138,7 @@ def test_versioning_error_usetting_required_property(): description="Campaign by Green Group against a series of targets in the financial services sector." ) - with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo: + with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo: campaign_v1.new_version(name=None) assert excinfo.value.cls == stix2.Campaign diff --git a/stix2/utils.py b/stix2/utils.py index ed12cdf..6776681 100644 --- a/stix2/utils.py +++ b/stix2/utils.py @@ -6,7 +6,7 @@ import json from dateutil import parser import pytz -# Sentinel value for fields that should be set to the current time. +# Sentinel value for properties that should be set to the current time. # We can't use the standard 'default' approach, since if there are multiple # timestamps in a single object, the timestamps will vary by a few microseconds. NOW = object()