Change remaining 'fields' to 'properties'
parent
a913d9d5ad
commit
41f2ceb8e5
16
README.md
16
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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue