Change remaining 'fields' to 'properties'

stix2.1
Greg Back 2017-05-19 12:51:59 -05:00
parent a913d9d5ad
commit 41f2ceb8e5
13 changed files with 41 additions and 39 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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