stormlibpp 0.1.2__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {stormlibpp-0.1.2 → stormlibpp-0.3.0}/PKG-INFO +1 -1
- {stormlibpp-0.1.2 → stormlibpp-0.3.0}/pyproject.toml +1 -1
- stormlibpp-0.3.0/src/stormlibpp/__init__.py +38 -0
- stormlibpp-0.3.0/src/stormlibpp/node.py +197 -0
- {stormlibpp-0.1.2 → stormlibpp-0.3.0}/src/stormlibpp/stormpkg.py +65 -31
- {stormlibpp-0.1.2 → stormlibpp-0.3.0}/src/stormlibpp/telepath.py +5 -0
- {stormlibpp-0.1.2 → stormlibpp-0.3.0}/src/stormlibpp/utils.py +4 -2
- {stormlibpp-0.1.2 → stormlibpp-0.3.0}/src/stormlibpp.egg-info/PKG-INFO +1 -1
- {stormlibpp-0.1.2 → stormlibpp-0.3.0}/src/stormlibpp.egg-info/SOURCES.txt +2 -0
- stormlibpp-0.3.0/tests/test_node.py +43 -0
- {stormlibpp-0.1.2 → stormlibpp-0.3.0}/tests/test_stormpkg.py +2 -1
- {stormlibpp-0.1.2 → stormlibpp-0.3.0}/tests/test_telepath.py +8 -0
- stormlibpp-0.1.2/src/stormlibpp/__init__.py +0 -25
- {stormlibpp-0.1.2 → stormlibpp-0.3.0}/LICENSE +0 -0
- {stormlibpp-0.1.2 → stormlibpp-0.3.0}/README.md +0 -0
- {stormlibpp-0.1.2 → stormlibpp-0.3.0}/setup.cfg +0 -0
- {stormlibpp-0.1.2 → stormlibpp-0.3.0}/src/stormlibpp/errors.py +0 -0
- {stormlibpp-0.1.2 → stormlibpp-0.3.0}/src/stormlibpp.egg-info/dependency_links.txt +0 -0
- {stormlibpp-0.1.2 → stormlibpp-0.3.0}/src/stormlibpp.egg-info/requires.txt +0 -0
- {stormlibpp-0.1.2 → stormlibpp-0.3.0}/src/stormlibpp.egg-info/top_level.txt +0 -0
- {stormlibpp-0.1.2 → stormlibpp-0.3.0}/tests/test_utils.py +0 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""The stormlibpp Python Package.
|
|
2
|
+
|
|
3
|
+
StormLib++ provides a number of Python objects to make life as a Synapse/Storm
|
|
4
|
+
developer easier.
|
|
5
|
+
|
|
6
|
+
StormLib++ provides several useful utility functions in ``utils``.
|
|
7
|
+
|
|
8
|
+
StormLib++ errors can be found in ``errors``. Each componenent of StormLib++
|
|
9
|
+
uses these errors their own way. Information our how they're used can be found
|
|
10
|
+
in those components.
|
|
11
|
+
|
|
12
|
+
``StormPkg`` is a helper class that represents a Storm package in memory. It
|
|
13
|
+
can read a package prototype from a default (or configured) location, convert
|
|
14
|
+
it to a package definition, optionally check the Storm code's syntax (enabled
|
|
15
|
+
by default), and store a Python dict containing the Storm package's definition.
|
|
16
|
+
|
|
17
|
+
``StormPkg`` also provides some helpful properties to describe the Storm
|
|
18
|
+
package's configuration (`cmds`, `mods`, `pkg_guid`, `pkg_name`, `pkg_ver`, `storm`).
|
|
19
|
+
|
|
20
|
+
There are also several submodules not directly imported by ``stormlibpp`` at
|
|
21
|
+
init. However, some classes/functions from these submodules are. The submodules
|
|
22
|
+
are briefly described below:
|
|
23
|
+
|
|
24
|
+
- ``telepath`` has methods and classes for working with Telepath endpoints.
|
|
25
|
+
It currently contains mostly classes for describing standard Telepath API
|
|
26
|
+
return values.
|
|
27
|
+
|
|
28
|
+
- ``stormpkg`` defines the ``StormPkg`` class.
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
__version__ = "0.3.0"
|
|
33
|
+
|
|
34
|
+
from . import errors
|
|
35
|
+
from . import utils
|
|
36
|
+
from .node import StormNode
|
|
37
|
+
from .stormpkg import StormPkg
|
|
38
|
+
from .telepath import (genDefaultTelepathRetn, TelepathRetn)
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"""Work with storm:node objects in Python."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
from types import SimpleNamespace
|
|
5
|
+
from typing import Any, Self, TypedDict
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
NodeForm = str
|
|
9
|
+
"""A valid syn:form value."""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class NodeVals(TypedDict):
|
|
13
|
+
"""The items a Node can have in the second part of packed NodeTuple."""
|
|
14
|
+
|
|
15
|
+
iden: str
|
|
16
|
+
nodedata: dict[str, Any]
|
|
17
|
+
props: dict[str, Any]
|
|
18
|
+
tags: dict[str, Any]
|
|
19
|
+
tagprops: dict[str, Any]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
NodeDef = tuple[NodeForm, str]
|
|
23
|
+
"""A nodes definition, the node's form and primary value."""
|
|
24
|
+
|
|
25
|
+
NodeTuple = tuple[NodeDef, NodeVals]
|
|
26
|
+
"""A packed node, this is what get's sent from Storm to a Telepath endpoint.
|
|
27
|
+
|
|
28
|
+
Or what get's returned from a Cortex's Python APIs.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ItemContainer:
|
|
33
|
+
"""Hold key/value items in a SimpleNamespace.
|
|
34
|
+
|
|
35
|
+
Keys must be strings.
|
|
36
|
+
|
|
37
|
+
Supports ``obj['item']`` (and ``obj['item'] = 'val'``) notation.
|
|
38
|
+
|
|
39
|
+
When "getting" an item with ``__getitem__``, that doesn't exist in the
|
|
40
|
+
container, ``None`` is returned instead of raising an exception.
|
|
41
|
+
|
|
42
|
+
Calling ``dir`` on this object will only return names for items this object
|
|
43
|
+
"holds" instead of all parts of this object.
|
|
44
|
+
|
|
45
|
+
Supports checking if an item is "held" via the ``in`` operator.
|
|
46
|
+
|
|
47
|
+
Supports iteration of items in the SimpleNamespace. Each iteration returns
|
|
48
|
+
a tuple of the item name followed by the item value.
|
|
49
|
+
|
|
50
|
+
Implements only magic methods, and all of them operate on the underlying
|
|
51
|
+
SimpleNamespace. To convert this object to a ``dict`` of the items it holds,
|
|
52
|
+
call ``vars`` on an instance.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
def __init__(self, /, **kwargs) -> None:
|
|
56
|
+
self.__ns = SimpleNamespace(**kwargs)
|
|
57
|
+
|
|
58
|
+
def __contains__(self, __name: str) -> bool:
|
|
59
|
+
return __name in dir(self)
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def __dict__(self):
|
|
63
|
+
return self.__ns.__dict__
|
|
64
|
+
|
|
65
|
+
def __dir__(self) -> list[str]:
|
|
66
|
+
return [val for val in dir(self.__ns) if not val.startswith("_")]
|
|
67
|
+
|
|
68
|
+
def __iter__(self) -> Any:
|
|
69
|
+
for item in dir(self):
|
|
70
|
+
yield (item, self[item])
|
|
71
|
+
|
|
72
|
+
def __getitem__(self, __name: str) -> Any:
|
|
73
|
+
return getattr(self.__ns, __name, None)
|
|
74
|
+
|
|
75
|
+
def __repr__(self) -> str:
|
|
76
|
+
return repr(self.__ns).replace("namespace", self.__class__.__name__)
|
|
77
|
+
|
|
78
|
+
def __setitem__(self, __name: str, __value: str) -> None:
|
|
79
|
+
setattr(self.__ns, __name, __value)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class Props(ItemContainer):
|
|
83
|
+
"""Properties of a StormNode."""
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class Tags(ItemContainer):
|
|
87
|
+
"""Tags of a StormNode."""
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class StormNode:
|
|
92
|
+
"""A storm:node Storm object that is in a Python runtime.
|
|
93
|
+
|
|
94
|
+
It supports "unpacking" the node into this object, edits to the object, and
|
|
95
|
+
repacking of the node to be sent back to Storm.
|
|
96
|
+
|
|
97
|
+
This node can be created purely from Python code rather than a packed
|
|
98
|
+
``storm:node`` object. Use the ``__init__`` directly instead of ``unpack``.
|
|
99
|
+
This allows the creation of a new node in Python that can be passed back to
|
|
100
|
+
Storm.
|
|
101
|
+
|
|
102
|
+
The intent is to represent an object that can be read from and written back
|
|
103
|
+
to a Cortex. It isn't meant to provide the same API that a ``storm:node``
|
|
104
|
+
has in Storm.
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
def __init__(
|
|
108
|
+
self,
|
|
109
|
+
form: NodeForm,
|
|
110
|
+
value: Any,
|
|
111
|
+
/,
|
|
112
|
+
iden: str = "",
|
|
113
|
+
tags: dict = {},
|
|
114
|
+
props: dict = {},
|
|
115
|
+
nodedata: dict = {},
|
|
116
|
+
tagprops: dict = {},
|
|
117
|
+
**kwargs,
|
|
118
|
+
) -> None:
|
|
119
|
+
|
|
120
|
+
self._form = form
|
|
121
|
+
self._value = value
|
|
122
|
+
|
|
123
|
+
self._tags = Props(**tags)
|
|
124
|
+
self._props = Tags(**props)
|
|
125
|
+
|
|
126
|
+
self.iden = iden
|
|
127
|
+
self.nodedata = nodedata
|
|
128
|
+
self.tagprops = tagprops
|
|
129
|
+
|
|
130
|
+
# Not really sure if this is needed, but saving it for now.
|
|
131
|
+
self._xtras = kwargs
|
|
132
|
+
|
|
133
|
+
@property
|
|
134
|
+
def form(self) -> str:
|
|
135
|
+
"""The form of this Node."""
|
|
136
|
+
|
|
137
|
+
return self._form
|
|
138
|
+
|
|
139
|
+
@property
|
|
140
|
+
def value(self) -> str:
|
|
141
|
+
"""The value of this Node."""
|
|
142
|
+
|
|
143
|
+
return self._value
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def tags(self):
|
|
147
|
+
"""The tags of this Node."""
|
|
148
|
+
|
|
149
|
+
return self._tags
|
|
150
|
+
|
|
151
|
+
@property
|
|
152
|
+
def props(self):
|
|
153
|
+
"""The properties of this Node."""
|
|
154
|
+
|
|
155
|
+
return self._props
|
|
156
|
+
|
|
157
|
+
@property
|
|
158
|
+
def nodevals(self):
|
|
159
|
+
"""The NodeVals dict this Node would have in a NodeTuple."""
|
|
160
|
+
|
|
161
|
+
return NodeVals(
|
|
162
|
+
iden=self.iden,
|
|
163
|
+
tagprops=self.tagprops,
|
|
164
|
+
nodedata=self.nodedata,
|
|
165
|
+
props=vars(self.props),
|
|
166
|
+
tags=vars(self.tags),
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
@classmethod
|
|
170
|
+
def unpack(cls, packedtup: NodeTuple) -> Self:
|
|
171
|
+
form, name = packedtup[0]
|
|
172
|
+
vals = NodeVals(**packedtup[1])
|
|
173
|
+
return cls(
|
|
174
|
+
form,
|
|
175
|
+
name,
|
|
176
|
+
**vals
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
def pack(self) -> NodeTuple:
|
|
180
|
+
return ((self.form, self.value), self.nodevals)
|
|
181
|
+
|
|
182
|
+
def addTag(self, tag, timestamps: tuple = (None, None)) -> None:
|
|
183
|
+
if tag in self._tags and timestamps != (None, None) and self._tags[tag] != timestamps:
|
|
184
|
+
self._tags[tag] = timestamps
|
|
185
|
+
elif tag not in self._tags:
|
|
186
|
+
self._tags[tag] = timestamps
|
|
187
|
+
|
|
188
|
+
def addTags(self, tags, timestamps: tuple = (None, None)) -> None:
|
|
189
|
+
for tag in tags:
|
|
190
|
+
self.addTag(tag, timestamps=timestamps)
|
|
191
|
+
|
|
192
|
+
def addProp(self, propname: str, propval: Any) -> None:
|
|
193
|
+
self._props[propname] = propval
|
|
194
|
+
|
|
195
|
+
def addProps(self, props: dict[str, Any]) -> None:
|
|
196
|
+
for propname, propval in props.items():
|
|
197
|
+
self._props[propname] = propval
|
|
@@ -5,8 +5,11 @@ import json
|
|
|
5
5
|
import os
|
|
6
6
|
import sys
|
|
7
7
|
|
|
8
|
+
import synapse.common as s_common
|
|
9
|
+
import synapse.exc as s_exc
|
|
10
|
+
import synapse.tools.genpkg as s_genpkg
|
|
11
|
+
|
|
8
12
|
from . import errors
|
|
9
|
-
from . import s_common, s_exc, s_genpkg
|
|
10
13
|
from . import utils
|
|
11
14
|
|
|
12
15
|
|
|
@@ -50,6 +53,10 @@ class StormPkg:
|
|
|
50
53
|
|
|
51
54
|
- Stores the package definition ``dict`` in the ``pkdef`` property.
|
|
52
55
|
|
|
56
|
+
- If ``check_syntax`` is True, all Storm code that is loaded in the ``pkdef``
|
|
57
|
+
is passed to Synapse's Storm parser to check for Storm syntax errors.
|
|
58
|
+
Any errors are raised as a ``StormPkgSyntaxError`` exception.
|
|
59
|
+
|
|
53
60
|
Parameters
|
|
54
61
|
----------
|
|
55
62
|
check_syntax : bool, optional
|
|
@@ -62,6 +69,9 @@ class StormPkg:
|
|
|
62
69
|
|
|
63
70
|
Properties
|
|
64
71
|
----------
|
|
72
|
+
default_name : str
|
|
73
|
+
The Yaml basename used if ``proto_name`` is empty (not set).
|
|
74
|
+
Set to the value of ``self.__class__.__name__.lower()``.
|
|
65
75
|
pkgdef : dict
|
|
66
76
|
The loaded Storm package definition.
|
|
67
77
|
proto_dir : str
|
|
@@ -71,12 +81,11 @@ class StormPkg:
|
|
|
71
81
|
at init, finding the object this resolves to in ``sys.modules``,
|
|
72
82
|
and reading the module's ``__file__``. Then joining this file's
|
|
73
83
|
dir name with the value ``pkgproto``.
|
|
74
|
-
proto_name : str
|
|
84
|
+
proto_name : str
|
|
75
85
|
A class property containing the name of the Storm package's proto
|
|
76
86
|
Yaml file (without extension). Subclasses may override this class
|
|
77
87
|
property to set a custom proto Yaml file basename. If they don't,
|
|
78
|
-
this property is automatically set to the value of
|
|
79
|
-
``self.__class__.__name__.lower()``.
|
|
88
|
+
this property is automatically set to the value of ``self.default_name``.
|
|
80
89
|
|
|
81
90
|
Raises
|
|
82
91
|
------
|
|
@@ -84,16 +93,19 @@ class StormPkg:
|
|
|
84
93
|
If the package proto either has an invalid schema or bad value.
|
|
85
94
|
StormPkgNoProtoError
|
|
86
95
|
If the proto Yaml file cannot be loaded. This can happen if the file name
|
|
87
|
-
will not match ``
|
|
96
|
+
will not match ``self.default_name`` but ``proto_name`` is not set.
|
|
88
97
|
StormPkgResolveError
|
|
89
98
|
If the default package proto dir cannot be resolved. This can be the case
|
|
90
99
|
if a `StormPkg` is created and doesn't expect to use the default proto dir
|
|
91
100
|
but a custom ``proto_dir`` is not passed.
|
|
101
|
+
StormPkgSyntaxError
|
|
102
|
+
If ``check_syntax`` is True and the Storm code in this package has syntax errors.
|
|
92
103
|
RuntimeError
|
|
93
104
|
If this class is instantiated directly and not subclassed.
|
|
94
105
|
"""
|
|
95
106
|
|
|
96
107
|
proto_name: str | None = None
|
|
108
|
+
"""The basename of this Storm package's Yaml proto file."""
|
|
97
109
|
|
|
98
110
|
def __init__(
|
|
99
111
|
self,
|
|
@@ -103,6 +115,10 @@ class StormPkg:
|
|
|
103
115
|
if StormPkg not in self.__class__.__bases__:
|
|
104
116
|
raise RuntimeError("StormPkg must be subclassed.")
|
|
105
117
|
|
|
118
|
+
self.default_name = self.__class__.__name__.lower()
|
|
119
|
+
if not self.proto_name:
|
|
120
|
+
self.proto_name = self.default_name
|
|
121
|
+
|
|
106
122
|
if proto_dir:
|
|
107
123
|
self.proto_dir = proto_dir
|
|
108
124
|
else:
|
|
@@ -119,10 +135,10 @@ class StormPkg:
|
|
|
119
135
|
"pkgproto",
|
|
120
136
|
)
|
|
121
137
|
|
|
122
|
-
|
|
123
|
-
self.
|
|
124
|
-
|
|
125
|
-
|
|
138
|
+
self.proto = os.path.join(
|
|
139
|
+
self.proto_dir,
|
|
140
|
+
f"{self.proto_name}.yaml",
|
|
141
|
+
)
|
|
126
142
|
|
|
127
143
|
self.pkgdef = self._load_proto()
|
|
128
144
|
"""A Python dict containing the full Storm package definition."""
|
|
@@ -156,15 +172,6 @@ class StormPkg:
|
|
|
156
172
|
|
|
157
173
|
return pkgdef
|
|
158
174
|
|
|
159
|
-
def _search_def(self, primkey: str, seckey: str) -> list[str]:
|
|
160
|
-
"""Search the modules or commands of the pkgdef for a secondary key."""
|
|
161
|
-
|
|
162
|
-
vals = []
|
|
163
|
-
for val in self.pkgdef.get(primkey, []):
|
|
164
|
-
if seckey in val:
|
|
165
|
-
vals.append(val[seckey])
|
|
166
|
-
return vals
|
|
167
|
-
|
|
168
175
|
def asdict(self):
|
|
169
176
|
"""Return this objects full Storm package definition as a Python dict.
|
|
170
177
|
|
|
@@ -193,19 +200,19 @@ class StormPkg:
|
|
|
193
200
|
f"syntax error: {err}"
|
|
194
201
|
) from err
|
|
195
202
|
|
|
196
|
-
def cmds(self) -> list[
|
|
197
|
-
"""The commands this package defines."""
|
|
203
|
+
def cmds(self) -> list[dict]:
|
|
204
|
+
"""The full definitions of the commands this package defines."""
|
|
198
205
|
|
|
199
|
-
return self.
|
|
206
|
+
return self.pkgdef.get("commands", [])
|
|
200
207
|
|
|
201
|
-
def mods(self) -> list[
|
|
202
|
-
"""The modules this package defines."""
|
|
208
|
+
def mods(self) -> list[dict]:
|
|
209
|
+
"""The full definitions of the modules this package defines."""
|
|
203
210
|
|
|
204
|
-
return self.
|
|
211
|
+
return self.pkgdef.get("modules", [])
|
|
205
212
|
|
|
206
213
|
def storm(self) -> dict[str, str]:
|
|
207
214
|
"""The Storm code this package defines.
|
|
208
|
-
|
|
215
|
+
|
|
209
216
|
Returns
|
|
210
217
|
-------
|
|
211
218
|
dict[str, str]
|
|
@@ -213,10 +220,37 @@ class StormPkg:
|
|
|
213
220
|
"""
|
|
214
221
|
|
|
215
222
|
storm = {}
|
|
216
|
-
for
|
|
217
|
-
if "name" in
|
|
218
|
-
storm[
|
|
219
|
-
for cmd in self.pkgdef.get("commands", []):
|
|
220
|
-
if "name" in cmd and "storm" in cmd:
|
|
221
|
-
storm[cmd["name"]] = cmd["storm"]
|
|
223
|
+
for item in self.cmds() + self.mods():
|
|
224
|
+
if "name" in item and "storm" in item:
|
|
225
|
+
storm[item["name"]] = item["storm"]
|
|
222
226
|
return storm
|
|
227
|
+
|
|
228
|
+
@property
|
|
229
|
+
def cmdnames(self) -> list[str]:
|
|
230
|
+
"""The names of the commands this package defines, if any."""
|
|
231
|
+
|
|
232
|
+
return [cmd.get("name") for cmd in self.cmds() if "name" in cmd]
|
|
233
|
+
|
|
234
|
+
@property
|
|
235
|
+
def modnames(self) -> list[str]:
|
|
236
|
+
"""The names of the modules this package defines, if any."""
|
|
237
|
+
|
|
238
|
+
return [mod.get("name") for mod in self.mods() if "name" in mod]
|
|
239
|
+
|
|
240
|
+
@property
|
|
241
|
+
def pkg_guid(self) -> str:
|
|
242
|
+
"""The package's guid, None if not set."""
|
|
243
|
+
|
|
244
|
+
return self.pkgdef.get("guid")
|
|
245
|
+
|
|
246
|
+
@property
|
|
247
|
+
def pkg_name(self) -> str:
|
|
248
|
+
"""The package's name, None if not set."""
|
|
249
|
+
|
|
250
|
+
return self.pkgdef.get("name")
|
|
251
|
+
|
|
252
|
+
@property
|
|
253
|
+
def pkg_ver(self) -> str:
|
|
254
|
+
"""The package's version, None if not set."""
|
|
255
|
+
|
|
256
|
+
return self.pkgdef.get("version")
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
import os
|
|
5
5
|
|
|
6
|
+
import synapse.exc as s_exc
|
|
7
|
+
import synapse.lib.parser as s_parser
|
|
8
|
+
|
|
6
9
|
from . import errors
|
|
7
|
-
from . import s_exc, s_parser
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
def absjoin(*paths: str) -> str:
|
|
@@ -12,7 +14,7 @@ def absjoin(*paths: str) -> str:
|
|
|
12
14
|
|
|
13
15
|
Parameters
|
|
14
16
|
----------
|
|
15
|
-
|
|
17
|
+
paths : list[str]
|
|
16
18
|
The path strings to join together, as would be passed to ``os.path.join``.
|
|
17
19
|
|
|
18
20
|
Returns
|
|
@@ -3,6 +3,7 @@ README.md
|
|
|
3
3
|
pyproject.toml
|
|
4
4
|
src/stormlibpp/__init__.py
|
|
5
5
|
src/stormlibpp/errors.py
|
|
6
|
+
src/stormlibpp/node.py
|
|
6
7
|
src/stormlibpp/stormpkg.py
|
|
7
8
|
src/stormlibpp/telepath.py
|
|
8
9
|
src/stormlibpp/utils.py
|
|
@@ -11,6 +12,7 @@ src/stormlibpp.egg-info/SOURCES.txt
|
|
|
11
12
|
src/stormlibpp.egg-info/dependency_links.txt
|
|
12
13
|
src/stormlibpp.egg-info/requires.txt
|
|
13
14
|
src/stormlibpp.egg-info/top_level.txt
|
|
15
|
+
tests/test_node.py
|
|
14
16
|
tests/test_stormpkg.py
|
|
15
17
|
tests/test_telepath.py
|
|
16
18
|
tests/test_utils.py
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Tests for stormlibpp.node."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import stormlibpp
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
PACKED_NODE = (('it:app:yara:rule', '5d0292d99a7da59a3a119e193f140143'), {'iden': '57ce731580ed6976b608e87dfc7f2ece81790f2cb8cdaf958013c738b28cd56e', 'tags': {'test': (None, None), 'test.tag': (None, None)}, 'props': {'.created': 1687720565352, 'text': 'rule dummy { condition: true }', 'name': 'dummy', 'enabled': 1}, 'tagprops': {}, 'nodedata': {}})
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestNode:
|
|
11
|
+
|
|
12
|
+
def test_packing(self):
|
|
13
|
+
node = stormlibpp.StormNode.unpack(PACKED_NODE)
|
|
14
|
+
assert node.pack() == PACKED_NODE
|
|
15
|
+
|
|
16
|
+
def test_add_tags(self):
|
|
17
|
+
tags = ["#test.othertag", "#atag"]
|
|
18
|
+
node = stormlibpp.StormNode.unpack(PACKED_NODE)
|
|
19
|
+
node.addTags(tags)
|
|
20
|
+
|
|
21
|
+
for tag in tags:
|
|
22
|
+
assert tag in node.tags
|
|
23
|
+
|
|
24
|
+
assert dir(node.tags) == [item[0] for item in iter(node.tags)]
|
|
25
|
+
|
|
26
|
+
def test_add_props(self):
|
|
27
|
+
props = {'prop': 'test', 'other': 'value'}
|
|
28
|
+
node = stormlibpp.StormNode.unpack(PACKED_NODE)
|
|
29
|
+
node.addProps(props)
|
|
30
|
+
|
|
31
|
+
for prop in props:
|
|
32
|
+
assert prop in node.props
|
|
33
|
+
|
|
34
|
+
for propname, propval in node.props:
|
|
35
|
+
if propname in props:
|
|
36
|
+
assert props[propname] == propval
|
|
37
|
+
|
|
38
|
+
def test_values(self):
|
|
39
|
+
node = stormlibpp.StormNode.unpack(PACKED_NODE)
|
|
40
|
+
|
|
41
|
+
assert node.form == PACKED_NODE[0][0]
|
|
42
|
+
assert node.value == PACKED_NODE[0][1]
|
|
43
|
+
assert node.nodevals == PACKED_NODE[1]
|
|
@@ -47,6 +47,7 @@ class TestStormPkg:
|
|
|
47
47
|
|
|
48
48
|
assert isinstance(test.asdict(), dict)
|
|
49
49
|
assert isinstance(othertest.pkgdef, dict)
|
|
50
|
+
assert "othertest.lib" in othertest.modnames
|
|
50
51
|
|
|
51
52
|
def test_storm_parse(self):
|
|
52
53
|
class BadStorm(stormlibpp.StormPkg):
|
|
@@ -59,4 +60,4 @@ class TestStormPkg:
|
|
|
59
60
|
class BadStorm(stormlibpp.StormPkg):
|
|
60
61
|
pass
|
|
61
62
|
|
|
62
|
-
assert "badstorm" in BadStorm(check_syntax=False).
|
|
63
|
+
assert "badstorm" in BadStorm(check_syntax=False).cmdnames
|
|
@@ -16,3 +16,11 @@ class TestTelepathRetn:
|
|
|
16
16
|
def test_gen_telepath_ret_opts(self):
|
|
17
17
|
ret = stormlibpp.genDefaultTelepathRetn(SubTeleRet, default_data="default")
|
|
18
18
|
assert ret == dict(status=True, mesg="", data="default")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TestCustomRetns:
|
|
22
|
+
def test_gen_boolretn(self):
|
|
23
|
+
ret = stormlibpp.genDefaultTelepathRetn(
|
|
24
|
+
stormlibpp.telepath.BoolRetn, default_data=False
|
|
25
|
+
)
|
|
26
|
+
assert ret == dict(status=True, mesg="", data=False)
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"""The stormlibpp Python Package.
|
|
2
|
-
|
|
3
|
-
StormLib++ provides a number of Python objects to make life as a Synapse/Storm
|
|
4
|
-
developer easier.
|
|
5
|
-
|
|
6
|
-
It also exposes a few of Synapses submodles with the following name mappings::
|
|
7
|
-
|
|
8
|
-
synapse.common -> s_common
|
|
9
|
-
synapse.exc -> s_exc
|
|
10
|
-
synapse.genpkg -> s_genpkg
|
|
11
|
-
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
__version__ = "0.1.2"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
import synapse.common as s_common
|
|
18
|
-
import synapse.exc as s_exc
|
|
19
|
-
import synapse.tools.genpkg as s_genpkg
|
|
20
|
-
import synapse.lib.parser as s_parser
|
|
21
|
-
|
|
22
|
-
from . import errors
|
|
23
|
-
from . import utils
|
|
24
|
-
from .stormpkg import StormPkg
|
|
25
|
-
from .telepath import (genDefaultTelepathRetn, TelepathRetn)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|