forked from STIXProject/python-stix
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path__init__.py
136 lines (91 loc) · 3.71 KB
/
__init__.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
# Make sure base gets imported before common.
from .base import (Entity, EntityList, TypedCollection, TypedList, # noqa
BaseCoreComponent)
#: Mapping of xsi:types to implementation/extension classes
_EXTENSION_MAP = {}
def _lookup_unprefixed(typename):
"""Attempts to resolve a class for the input XML type `typename`.
Args:
typename: The name of an STIX XML type (e.g., TLPMarkingStructureType)
without a namespace prefix.
Returns:
A stix.Entity implementation class for the `typename`.
Raises:
ValueError: If no class has been registered for the input `typename`.
"""
for xsi_type, klass in _EXTENSION_MAP.iteritems():
if typename in xsi_type:
return klass
error = "Unregistered extension type: %s" % typename
raise ValueError(error)
def _lookup_extension(xsi_type):
"""Returns a Python class for the `xsi_type` value.
Args:
xsi_type: An xsi:type value string.
Returns:
A stix.Entity implementation class for the `xsi_type`.
Raises:
ValueError: If no class has been registered for the `xsi_type`.
"""
if xsi_type in _EXTENSION_MAP:
return _EXTENSION_MAP[xsi_type]
raise ValueError("Unregistered xsi:type %s" % xsi_type)
def lookup_extension(typeinfo, default=None):
"""Returns a stix.Entity class for that has been registered for the
`typeinfo` value.
Note:
This is for internal use only.
Args:
typeinfo: An object or string containing type information. This can be
either an xsi:type attribute value or a stix.bindings object.
default: Return class if typeinfo is None or contains no xml type
information.
Returns:
A stix.Entity implementation class for the `xsi_type`.
Raises:
ValueError: If no class has been registered for the `xsi_type`.
"""
if typeinfo is None and default:
return default
# If the `typeinfo` was a string, consider it a full xsi:type value.
if isinstance(typeinfo, basestring):
return _lookup_extension(typeinfo)
# Most extension bindings include this attribute.
if not hasattr(typeinfo, 'xml_type'):
if default:
return default
error = "Input %s is missing xml_type attribute. Cannot lookup class."
raise ValueError(error)
# Extension binding classes usually (always?) have an `xmlns_prefix`
# class attribute.
if hasattr(typeinfo, 'xmlns_prefix'):
xsi_type = "%s:%s" % (typeinfo.xmlns_prefix, typeinfo.xml_type)
return _lookup_extension(xsi_type)
# no xmlns_prefix found, try to resolve the class by just the `xml_type`
return _lookup_unprefixed(typeinfo.xml_type)
def add_extension(cls):
"""Registers a stix.Entity class as an implementation of an xml type.
Classes must have an ``_XSI_TYPE`` class attributes to be registered. The
value of this attribute must be a valid xsi:type.
Note:
This was designed for internal use.
"""
_EXTENSION_MAP[cls._XSI_TYPE] = cls # noqa
def register_extension(cls):
"""Class decorator for registering a stix.Entity class as an implementation
of an xml type.
Classes must have an ``_XSI_TYPE`` class attributes to be registered.
Note:
This was designed for internal use.
"""
add_extension(cls)
return cls
from . import common # noqa
from .version import __version__ # noqa
def supported_stix_version():
"""Returns a tuple of STIX version strings that this version of python-stix
supports (i.e., can parse).
"""
return ('1.1.1', '1.2')