|
1 | 1 | from collections import OrderedDict |
2 | | -import re |
3 | 2 |
|
4 | 3 | import six |
5 | 4 |
|
6 | | -from .base import _cls_init, _Extension, _Observable, _STIXBase |
7 | | -from .core import ( |
8 | | - STIXDomainObject, _register_marking, _register_object, |
9 | | - _register_observable, _register_observable_extension, |
| 5 | +from .base import _cls_init |
| 6 | +from .parsing import ( |
| 7 | + _register_marking, _register_object, _register_observable, |
| 8 | + _register_observable_extension, |
10 | 9 | ) |
11 | | -from .utils import TYPE_REGEX, get_class_hierarchy_names |
12 | 10 |
|
13 | 11 |
|
14 | | -def _custom_object_builder(cls, type, properties, version): |
15 | | - class _CustomObject(cls, STIXDomainObject): |
| 12 | +def _get_properties_dict(properties): |
| 13 | + try: |
| 14 | + return OrderedDict(properties) |
| 15 | + except TypeError as e: |
| 16 | + six.raise_from( |
| 17 | + ValueError( |
| 18 | + "properties must be dict-like, e.g. a list " |
| 19 | + "containing tuples. For example, " |
| 20 | + "[('property1', IntegerProperty())]", |
| 21 | + ), |
| 22 | + e, |
| 23 | + ) |
16 | 24 |
|
17 | | - if not re.match(TYPE_REGEX, type): |
18 | | - raise ValueError( |
19 | | - "Invalid type name '%s': must only contain the " |
20 | | - "characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type, |
21 | | - ) |
22 | | - elif len(type) < 3 or len(type) > 250: |
23 | | - raise ValueError( |
24 | | - "Invalid type name '%s': must be between 3 and 250 characters." % type, |
25 | | - ) |
26 | 25 |
|
27 | | - if not properties or not isinstance(properties, list): |
28 | | - raise ValueError("Must supply a list, containing tuples. For example, [('property1', IntegerProperty())]") |
| 26 | +def _custom_object_builder(cls, type, properties, version, base_class): |
| 27 | + prop_dict = _get_properties_dict(properties) |
| 28 | + |
| 29 | + class _CustomObject(cls, base_class): |
29 | 30 |
|
30 | 31 | _type = type |
31 | | - _properties = OrderedDict(properties) |
| 32 | + _properties = prop_dict |
32 | 33 |
|
33 | 34 | def __init__(self, **kwargs): |
34 | | - _STIXBase.__init__(self, **kwargs) |
| 35 | + base_class.__init__(self, **kwargs) |
35 | 36 | _cls_init(cls, self, kwargs) |
36 | 37 |
|
37 | 38 | _register_object(_CustomObject, version=version) |
38 | 39 | return _CustomObject |
39 | 40 |
|
40 | 41 |
|
41 | | -def _custom_marking_builder(cls, type, properties, version): |
42 | | - class _CustomMarking(cls, _STIXBase): |
| 42 | +def _custom_marking_builder(cls, type, properties, version, base_class): |
| 43 | + prop_dict = _get_properties_dict(properties) |
43 | 44 |
|
44 | | - if not properties or not isinstance(properties, list): |
45 | | - raise ValueError("Must supply a list, containing tuples. For example, [('property1', IntegerProperty())]") |
| 45 | + class _CustomMarking(cls, base_class): |
46 | 46 |
|
47 | 47 | _type = type |
48 | | - _properties = OrderedDict(properties) |
| 48 | + _properties = prop_dict |
49 | 49 |
|
50 | 50 | def __init__(self, **kwargs): |
51 | | - _STIXBase.__init__(self, **kwargs) |
| 51 | + base_class.__init__(self, **kwargs) |
52 | 52 | _cls_init(cls, self, kwargs) |
53 | 53 |
|
54 | 54 | _register_marking(_CustomMarking, version=version) |
55 | 55 | return _CustomMarking |
56 | 56 |
|
57 | 57 |
|
58 | | -def _custom_observable_builder(cls, type, properties, version, id_contrib_props=None): |
| 58 | +def _custom_observable_builder(cls, type, properties, version, base_class, id_contrib_props=None): |
59 | 59 | if id_contrib_props is None: |
60 | 60 | id_contrib_props = [] |
61 | 61 |
|
62 | | - class _CustomObservable(cls, _Observable): |
63 | | - |
64 | | - if not re.match(TYPE_REGEX, type): |
65 | | - raise ValueError( |
66 | | - "Invalid observable type name '%s': must only contain the " |
67 | | - "characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type, |
68 | | - ) |
69 | | - elif len(type) < 3 or len(type) > 250: |
70 | | - raise ValueError("Invalid observable type name '%s': must be between 3 and 250 characters." % type) |
71 | | - |
72 | | - if not properties or not isinstance(properties, list): |
73 | | - raise ValueError("Must supply a list, containing tuples. For example, [('property1', IntegerProperty())]") |
74 | | - |
75 | | - if version == "2.0": |
76 | | - # If using STIX2.0, check properties ending in "_ref/s" are ObjectReferenceProperties |
77 | | - for prop_name, prop in properties: |
78 | | - if prop_name.endswith('_ref') and ('ObjectReferenceProperty' not in get_class_hierarchy_names(prop)): |
79 | | - raise ValueError( |
80 | | - "'%s' is named like an object reference property but " |
81 | | - "is not an ObjectReferenceProperty." % prop_name, |
82 | | - ) |
83 | | - elif (prop_name.endswith('_refs') and ('ListProperty' not in get_class_hierarchy_names(prop) or |
84 | | - 'ObjectReferenceProperty' not in get_class_hierarchy_names(prop.contained))): |
85 | | - raise ValueError( |
86 | | - "'%s' is named like an object reference list property but " |
87 | | - "is not a ListProperty containing ObjectReferenceProperty." % prop_name, |
88 | | - ) |
89 | | - else: |
90 | | - # If using STIX2.1 (or newer...), check properties ending in "_ref/s" are ReferenceProperties |
91 | | - for prop_name, prop in properties: |
92 | | - if prop_name.endswith('_ref') and ('ReferenceProperty' not in get_class_hierarchy_names(prop)): |
93 | | - raise ValueError( |
94 | | - "'%s' is named like a reference property but " |
95 | | - "is not a ReferenceProperty." % prop_name, |
96 | | - ) |
97 | | - elif (prop_name.endswith('_refs') and ('ListProperty' not in get_class_hierarchy_names(prop) or |
98 | | - 'ReferenceProperty' not in get_class_hierarchy_names(prop.contained))): |
99 | | - raise ValueError( |
100 | | - "'%s' is named like a reference list property but " |
101 | | - "is not a ListProperty containing ReferenceProperty." % prop_name, |
102 | | - ) |
| 62 | + prop_dict = _get_properties_dict(properties) |
| 63 | + |
| 64 | + class _CustomObservable(cls, base_class): |
103 | 65 |
|
104 | 66 | _type = type |
105 | | - _properties = OrderedDict(properties) |
| 67 | + _properties = prop_dict |
106 | 68 | if version != '2.0': |
107 | 69 | _id_contributing_properties = id_contrib_props |
108 | 70 |
|
109 | 71 | def __init__(self, **kwargs): |
110 | | - _Observable.__init__(self, **kwargs) |
| 72 | + base_class.__init__(self, **kwargs) |
111 | 73 | _cls_init(cls, self, kwargs) |
112 | 74 |
|
113 | 75 | _register_observable(_CustomObservable, version=version) |
114 | 76 | return _CustomObservable |
115 | 77 |
|
116 | 78 |
|
117 | | -def _custom_extension_builder(cls, observable, type, properties, version): |
118 | | - |
119 | | - try: |
120 | | - prop_dict = OrderedDict(properties) |
121 | | - except TypeError as e: |
122 | | - six.raise_from( |
123 | | - ValueError( |
124 | | - "Extension properties must be dict-like, e.g. a list " |
125 | | - "containing tuples. For example, " |
126 | | - "[('property1', IntegerProperty())]", |
127 | | - ), |
128 | | - e, |
129 | | - ) |
| 79 | +def _custom_extension_builder(cls, observable, type, properties, version, base_class): |
| 80 | + prop_dict = _get_properties_dict(properties) |
130 | 81 |
|
131 | | - class _CustomExtension(cls, _Extension): |
| 82 | + class _CustomExtension(cls, base_class): |
132 | 83 |
|
133 | 84 | _type = type |
134 | 85 | _properties = prop_dict |
135 | 86 |
|
136 | 87 | def __init__(self, **kwargs): |
137 | | - _Extension.__init__(self, **kwargs) |
| 88 | + base_class.__init__(self, **kwargs) |
138 | 89 | _cls_init(cls, self, kwargs) |
139 | 90 |
|
140 | 91 | _register_observable_extension(observable, _CustomExtension, version=version) |
|
0 commit comments