synapse 2.222.0__py311-none-any.whl → 2.224.0__py311-none-any.whl

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.

Potentially problematic release.


This version of synapse might be problematic. Click here for more details.

Files changed (49) hide show
  1. synapse/common.py +2 -2
  2. synapse/cortex.py +159 -31
  3. synapse/cryotank.py +1 -1
  4. synapse/datamodel.py +1 -1
  5. synapse/lib/ast.py +5 -3
  6. synapse/lib/layer.py +6 -6
  7. synapse/lib/nexus.py +1 -1
  8. synapse/lib/schemas.py +2 -0
  9. synapse/lib/snap.py +15 -9
  10. synapse/lib/storm.py +35 -191
  11. synapse/lib/stormlib/auth.py +1 -1
  12. synapse/lib/stormlib/imap.py +12 -4
  13. synapse/lib/stormlib/mime.py +15 -5
  14. synapse/lib/stormlib/pkg.py +598 -0
  15. synapse/lib/stormlib/task.py +114 -0
  16. synapse/lib/stormtypes.py +43 -175
  17. synapse/lib/trigger.py +16 -14
  18. synapse/lib/version.py +2 -2
  19. synapse/lib/view.py +17 -14
  20. synapse/models/files.py +1 -1
  21. synapse/models/inet.py +25 -0
  22. synapse/models/proj.py +3 -0
  23. synapse/models/risk.py +6 -0
  24. synapse/models/syn.py +8 -0
  25. synapse/tests/test_common.py +4 -0
  26. synapse/tests/test_cortex.py +52 -1
  27. synapse/tests/test_lib_aha.py +68 -53
  28. synapse/tests/test_lib_ast.py +3 -0
  29. synapse/tests/test_lib_cell.py +12 -12
  30. synapse/tests/test_lib_storm.py +128 -248
  31. synapse/tests/test_lib_stormlib_imap.py +14 -0
  32. synapse/tests/test_lib_stormlib_mime.py +24 -0
  33. synapse/tests/test_lib_stormlib_pkg.py +456 -0
  34. synapse/tests/test_lib_stormlib_task.py +98 -0
  35. synapse/tests/test_lib_stormtypes.py +12 -100
  36. synapse/tests/test_lib_trigger.py +66 -3
  37. synapse/tests/test_lib_view.py +53 -0
  38. synapse/tests/test_model_files.py +11 -0
  39. synapse/tests/test_model_inet.py +23 -0
  40. synapse/tests/test_model_proj.py +3 -1
  41. synapse/tests/test_model_risk.py +10 -0
  42. synapse/tests/test_model_syn.py +54 -2
  43. synapse/tools/cryo/cat.py +2 -1
  44. synapse/tools/cryo/list.py +2 -0
  45. {synapse-2.222.0.dist-info → synapse-2.224.0.dist-info}/METADATA +1 -1
  46. {synapse-2.222.0.dist-info → synapse-2.224.0.dist-info}/RECORD +49 -45
  47. {synapse-2.222.0.dist-info → synapse-2.224.0.dist-info}/WHEEL +0 -0
  48. {synapse-2.222.0.dist-info → synapse-2.224.0.dist-info}/licenses/LICENSE +0 -0
  49. {synapse-2.222.0.dist-info → synapse-2.224.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,598 @@
1
+ import asyncio
2
+
3
+ import synapse.exc as s_exc
4
+
5
+ import synapse.lib.stormtypes as s_stormtypes
6
+
7
+ stormcmds = [
8
+ {
9
+ 'name': 'pkg.list',
10
+ 'descr': 'List the storm packages loaded in the cortex.',
11
+ 'cmdargs': (
12
+ ('--verbose', {'default': False, 'action': 'store_true',
13
+ 'help': 'Display build time for each package.'}),
14
+ ),
15
+ 'storm': '''
16
+ init {
17
+ $conf = ({
18
+ "columns": [
19
+ {"name": "name", "width": 40},
20
+ {"name": "vers", "width": 10},
21
+ ],
22
+ "separators": {
23
+ "row:outline": false,
24
+ "column:outline": false,
25
+ "header:row": "#",
26
+ "data:row": "",
27
+ "column": "",
28
+ },
29
+ })
30
+ if $cmdopts.verbose {
31
+ $conf.columns.append(({"name": "time", "width": 20}))
32
+ }
33
+ $printer = $lib.tabular.printer($conf)
34
+ }
35
+
36
+ $pkgs = $lib.pkg.list()
37
+
38
+ if $($pkgs.size() > 0) {
39
+ $lib.print('Loaded storm packages:')
40
+ $lib.print($printer.header())
41
+ for $pkg in $pkgs {
42
+ $row = (
43
+ $pkg.name, $pkg.version,
44
+ )
45
+ if $cmdopts.verbose {
46
+ try {
47
+ $row.append($lib.time.format($pkg.build.time, '%Y-%m-%d %H:%M:%S'))
48
+ } catch StormRuntimeError as _ {
49
+ $row.append('not available')
50
+ }
51
+ }
52
+ $lib.print($printer.row($row))
53
+ }
54
+ } else {
55
+ $lib.print('No storm packages installed.')
56
+ }
57
+ '''
58
+ },
59
+ {
60
+ 'name': 'pkg.perms.list',
61
+ 'descr': 'List any permissions declared by the package.',
62
+ 'cmdargs': (
63
+ ('name', {'help': 'The name (or name prefix) of the package.', 'type': 'str'}),
64
+ ),
65
+ 'storm': '''
66
+ $pdef = $lib.null
67
+ for $pkg in $lib.pkg.list() {
68
+ if $pkg.name.startswith($cmdopts.name) {
69
+ $pdef = $pkg
70
+ break
71
+ }
72
+ }
73
+
74
+ if (not $pdef) {
75
+ $lib.warn(`Package ({$cmdopts.name}) not found!`)
76
+ } else {
77
+ if $pdef.perms {
78
+ $lib.print(`Package ({$cmdopts.name}) defines the following permissions:`)
79
+ for $permdef in $pdef.perms {
80
+ $defv = $permdef.default
81
+ if ( $defv = $lib.null ) {
82
+ $defv = $lib.false
83
+ }
84
+ $text = `{('.').join($permdef.perm).ljust(32)} : {$permdef.desc} ( default: {$defv} )`
85
+ $lib.print($text)
86
+ }
87
+ } else {
88
+ $lib.print(`Package ({$cmdopts.name}) contains no permissions definitions.`)
89
+ }
90
+ }
91
+ '''
92
+ },
93
+ {
94
+ 'name': 'pkg.del',
95
+ 'descr': 'Remove a storm package from the cortex.',
96
+ 'cmdargs': (
97
+ ('name', {'help': 'The name (or name prefix) of the package to remove.'}),
98
+ ),
99
+ 'storm': '''
100
+
101
+ $pkgs = $lib.set()
102
+
103
+ for $pkg in $lib.pkg.list() {
104
+ if $pkg.name.startswith($cmdopts.name) {
105
+ $pkgs.add($pkg.name)
106
+ }
107
+ }
108
+
109
+ if $($pkgs.size() = 0) {
110
+
111
+ $lib.print('No package names match "{name}". Aborting.', name=$cmdopts.name)
112
+
113
+ } elif $($pkgs.size() = 1) {
114
+
115
+ $name = $pkgs.list().index(0)
116
+ $lib.print('Removing package: {name}', name=$name)
117
+ $lib.pkg.del($name)
118
+
119
+ } else {
120
+
121
+ $lib.print('Multiple package names match "{name}". Aborting.', name=$cmdopts.name)
122
+
123
+ }
124
+ '''
125
+ },
126
+ {
127
+ 'name': 'pkg.docs',
128
+ 'descr': 'Display documentation included in a storm package.',
129
+ 'cmdargs': (
130
+ ('name', {'help': 'The name (or name prefix) of the package.'}),
131
+ ),
132
+ 'storm': '''
133
+ $pdef = $lib.null
134
+ for $pkg in $lib.pkg.list() {
135
+ if $pkg.name.startswith($cmdopts.name) {
136
+ $pdef = $pkg
137
+ break
138
+ }
139
+ }
140
+
141
+ if (not $pdef) {
142
+ $lib.warn("Package ({name}) not found!", name=$cmdopts.name)
143
+ } else {
144
+ if $pdef.docs {
145
+ for $doc in $pdef.docs {
146
+ $lib.print($doc.content)
147
+ }
148
+ } else {
149
+ $lib.print("Package ({name}) contains no documentation.", name=$cmdopts.name)
150
+ }
151
+ }
152
+ '''
153
+ },
154
+ {
155
+ 'name': 'pkg.load',
156
+ 'descr': 'Load a storm package from an HTTP URL.',
157
+ 'cmdargs': (
158
+ ('url', {'help': 'The HTTP URL to load the package from.'}),
159
+ ('--raw', {'default': False, 'action': 'store_true',
160
+ 'help': 'Response JSON is a raw package definition without an envelope.'}),
161
+ ('--verify', {'default': False, 'action': 'store_true',
162
+ 'help': 'Enforce code signature verification on the storm package.'}),
163
+ ('--ssl-noverify', {'default': False, 'action': 'store_true',
164
+ 'help': 'Specify to disable SSL verification of the server.'}),
165
+ ),
166
+ 'storm': '''
167
+ init {
168
+ $ssl = $lib.true
169
+ if $cmdopts.ssl_noverify { $ssl = $lib.false }
170
+
171
+ $headers = ({'X-Synapse-Version': ('.').join($lib.version.synapse())})
172
+
173
+ $resp = $lib.inet.http.get($cmdopts.url, ssl_verify=$ssl, headers=$headers)
174
+
175
+ if ($resp.code != 200) {
176
+ $lib.warn("pkg.load got HTTP code: {code} for URL: {url}", code=$resp.code, url=$cmdopts.url)
177
+ $lib.exit()
178
+ }
179
+
180
+ $reply = $resp.json()
181
+ if $cmdopts.raw {
182
+ $pkg = $reply
183
+ } else {
184
+ if ($reply.status != "ok") {
185
+ $lib.warn("pkg.load got JSON error: {code} for URL: {url}", code=$reply.code, url=$cmdopts.url)
186
+ $lib.exit()
187
+ }
188
+
189
+ $pkg = $reply.result
190
+ }
191
+
192
+ $pkd = $lib.pkg.add($pkg, verify=$cmdopts.verify)
193
+
194
+ $lib.print("Loaded Package: {name} @{version}", name=$pkg.name, version=$pkg.version)
195
+ }
196
+ ''',
197
+ },
198
+ ]
199
+
200
+ @s_stormtypes.registry.registerLib
201
+ class LibPkg(s_stormtypes.Lib):
202
+ '''
203
+ A Storm Library for interacting with Storm Packages.
204
+ '''
205
+ _storm_locals = (
206
+ {'name': 'add', 'desc': 'Add a Storm Package to the Cortex.',
207
+ 'type': {'type': 'function', '_funcname': '_libPkgAdd',
208
+ 'args': (
209
+ {'name': 'pkgdef', 'type': 'dict', 'desc': 'A Storm Package definition.', },
210
+ {'name': 'verify', 'type': 'boolean', 'default': False,
211
+ 'desc': 'Verify storm package signature.', },
212
+ ),
213
+ 'returns': {'type': 'null', }}},
214
+ {'name': 'get', 'desc': 'Get a Storm Package from the Cortex.',
215
+ 'type': {'type': 'function', '_funcname': '_libPkgGet',
216
+ 'args': (
217
+ {'name': 'name', 'type': 'str', 'desc': 'A Storm Package name.', },
218
+ ),
219
+ 'returns': {'type': 'dict', 'desc': 'The Storm package definition.', }}},
220
+ {'name': 'has', 'desc': 'Check if a Storm Package is available in the Cortex.',
221
+ 'type': {'type': 'function', '_funcname': '_libPkgHas',
222
+ 'args': (
223
+ {'name': 'name', 'type': 'str',
224
+ 'desc': 'A Storm Package name to check for the existence of.', },
225
+ ),
226
+ 'returns': {'type': 'boolean',
227
+ 'desc': 'True if the package exists in the Cortex, False if it does not.', }}},
228
+ {'name': 'del', 'desc': 'Delete a Storm Package from the Cortex.',
229
+ 'type': {'type': 'function', '_funcname': '_libPkgDel',
230
+ 'args': (
231
+ {'name': 'name', 'type': 'str', 'desc': 'The name of the package to delete.', },
232
+ ),
233
+ 'returns': {'type': 'null', }}},
234
+ {'name': 'list', 'desc': 'Get a list of Storm Packages loaded in the Cortex.',
235
+ 'type': {'type': 'function', '_funcname': '_libPkgList',
236
+ 'returns': {'type': 'list', 'desc': 'A list of Storm Package definitions.', }}},
237
+ {'name': 'deps', 'desc': 'Verify the dependencies for a Storm Package.',
238
+ 'type': {'type': 'function', '_funcname': '_libPkgDeps',
239
+ 'args': (
240
+ {'name': 'pkgdef', 'type': 'dict', 'desc': 'A Storm Package definition.', },
241
+ ),
242
+ 'returns': {'type': 'dict', 'desc': 'A dictionary listing dependencies and if they are met.', }}},
243
+ {'name': 'vars',
244
+ 'desc': "Get a dictionary representing the package's persistent variables.",
245
+ 'type': {'type': 'function', '_funcname': '_libPkgVars',
246
+ 'args': (
247
+ {'name': 'name', 'type': 'str',
248
+ 'desc': 'A Storm Package name to get vars for.', },
249
+ ),
250
+ 'returns': {'type': 'pkg:vars', 'desc': 'A dictionary representing the package variables.', }}},
251
+ {'name': 'queues',
252
+ 'desc': "Access namespaced Queues for a package.",
253
+ 'type': {'type': 'function', '_funcname': '_libPkgQueues',
254
+ 'args': (
255
+ {'name': 'name', 'type': 'str',
256
+ 'desc': 'A Storm Package name to access Queues for.', },
257
+ ),
258
+ 'returns': {'type': 'pkg:queues', 'desc': 'An object for accessing the package Queues.', }}},
259
+ )
260
+ _storm_lib_perms = (
261
+ {'perm': ('power-ups', '<name>', 'admin'), 'gate': 'cortex',
262
+ 'desc': 'Controls the ability to interact with the vars or Queues for a Storm Package by name.'},
263
+ )
264
+ _storm_lib_path = ('pkg',)
265
+
266
+ def getObjLocals(self):
267
+ return {
268
+ 'add': self._libPkgAdd,
269
+ 'get': self._libPkgGet,
270
+ 'has': self._libPkgHas,
271
+ 'del': self._libPkgDel,
272
+ 'list': self._libPkgList,
273
+ 'deps': self._libPkgDeps,
274
+ 'vars': self._libPkgVars,
275
+ 'queues': self._libPkgQueues,
276
+ }
277
+
278
+ async def _libPkgAdd(self, pkgdef, verify=False):
279
+ self.runt.confirm(('pkg', 'add'), None)
280
+ pkgdef = await s_stormtypes.toprim(pkgdef)
281
+ verify = await s_stormtypes.tobool(verify)
282
+ await self.runt.snap.core.addStormPkg(pkgdef, verify=verify)
283
+
284
+ @s_stormtypes.stormfunc(readonly=True)
285
+ async def _libPkgGet(self, name):
286
+ name = await s_stormtypes.tostr(name)
287
+ pkgdef = await self.runt.snap.core.getStormPkg(name)
288
+ if pkgdef is None:
289
+ return None
290
+
291
+ return s_stormtypes.Dict(pkgdef)
292
+
293
+ @s_stormtypes.stormfunc(readonly=True)
294
+ async def _libPkgHas(self, name):
295
+ name = await s_stormtypes.tostr(name)
296
+ pkgdef = await self.runt.snap.core.getStormPkg(name)
297
+ if pkgdef is None:
298
+ return False
299
+ return True
300
+
301
+ async def _libPkgDel(self, name):
302
+ self.runt.confirm(('pkg', 'del'), None)
303
+ await self.runt.snap.core.delStormPkg(name)
304
+
305
+ @s_stormtypes.stormfunc(readonly=True)
306
+ async def _libPkgList(self):
307
+ pkgs = await self.runt.snap.core.getStormPkgs()
308
+ return list(sorted(pkgs, key=lambda x: x.get('name')))
309
+
310
+ @s_stormtypes.stormfunc(readonly=True)
311
+ async def _libPkgDeps(self, pkgdef):
312
+ pkgdef = await s_stormtypes.toprim(pkgdef)
313
+ return await self.runt.snap.core.verifyStormPkgDeps(pkgdef)
314
+
315
+ async def _libPkgVars(self, name):
316
+ name = await s_stormtypes.tostr(name)
317
+ s_stormtypes.confirm(('power-ups', name, 'admin'))
318
+ return PkgVars(self.runt, name)
319
+
320
+ async def _libPkgQueues(self, name):
321
+ name = await s_stormtypes.tostr(name)
322
+ s_stormtypes.confirm(('power-ups', name, 'admin'))
323
+ return PkgQueues(self.runt, name)
324
+
325
+ @s_stormtypes.registry.registerType
326
+ class PkgVars(s_stormtypes.Prim):
327
+ '''
328
+ The Storm deref/setitem/iter convention on top of pkg vars information.
329
+ '''
330
+ _storm_typename = 'pkg:vars'
331
+ _ismutable = True
332
+
333
+ def __init__(self, runt, valu, path=None):
334
+ s_stormtypes.Prim.__init__(self, valu, path=path)
335
+ self.runt = runt
336
+
337
+ def _reqPkgAdmin(self):
338
+ s_stormtypes.confirm(('power-ups', self.valu, 'admin'))
339
+
340
+ @s_stormtypes.stormfunc(readonly=True)
341
+ async def deref(self, name):
342
+ self._reqPkgAdmin()
343
+ name = await s_stormtypes.tostr(name)
344
+ return await self.runt.snap.core.getStormPkgVar(self.valu, name)
345
+
346
+ async def setitem(self, name, valu):
347
+ self._reqPkgAdmin()
348
+ name = await s_stormtypes.tostr(name)
349
+
350
+ if valu is s_stormtypes.undef:
351
+ await self.runt.snap.core.popStormPkgVar(self.valu, name)
352
+ return
353
+
354
+ valu = await s_stormtypes.toprim(valu)
355
+ await self.runt.snap.core.setStormPkgVar(self.valu, name, valu)
356
+
357
+ @s_stormtypes.stormfunc(readonly=True)
358
+ async def iter(self):
359
+ self._reqPkgAdmin()
360
+ async for name, valu in self.runt.snap.core.iterStormPkgVars(self.valu):
361
+ yield name, valu
362
+ await asyncio.sleep(0)
363
+
364
+ @s_stormtypes.registry.registerType
365
+ class PkgQueues(s_stormtypes.Prim):
366
+ '''
367
+ A StormLib API instance for interacting with persistent Queues for a package in the Cortex.
368
+ '''
369
+ _storm_locals = (
370
+ {'name': 'add', 'desc': 'Add a Queue for the package with a given name.',
371
+ 'type': {'type': 'function', '_funcname': '_methPkgQueueAdd',
372
+ 'args': (
373
+ {'name': 'name', 'type': 'str', 'desc': 'The name of the Queue to add.'},
374
+ ),
375
+ 'returns': {'type': 'pkg:queue'}}},
376
+ {'name': 'gen', 'desc': 'Add or get a Queue in a single operation.',
377
+ 'type': {'type': 'function', '_funcname': '_methPkgQueueGen',
378
+ 'args': (
379
+ {'name': 'name', 'type': 'str', 'desc': 'The name of the Queue to add or get.'},
380
+ ),
381
+ 'returns': {'type': 'pkg:queue'}}},
382
+ {'name': 'del', 'desc': 'Delete a given Queue.',
383
+ 'type': {'type': 'function', '_funcname': '_methPkgQueueDel',
384
+ 'args': (
385
+ {'name': 'name', 'type': 'str', 'desc': 'The name of the Queue to delete.'},
386
+ ),
387
+ 'returns': {'type': 'null'}}},
388
+ {'name': 'get', 'desc': 'Get an existing Queue.',
389
+ 'type': {'type': 'function', '_funcname': '_methPkgQueueGet',
390
+ 'args': (
391
+ {'name': 'name', 'type': 'str', 'desc': 'The name of the Queue to get.'},
392
+ ),
393
+ 'returns': {'type': 'pkg:queue', 'desc': 'A ``pkg:queue`` object.'}}},
394
+ {'name': 'list', 'desc': 'Get a list of the Queues for the package in the Cortex.',
395
+ 'type': {'type': 'function', '_funcname': '_methPkgQueueList',
396
+ 'returns': {'name': 'yields', 'type': 'dict', 'desc': 'Queue definitions for the package.'}}},
397
+ )
398
+ _storm_typename = 'pkg:queues'
399
+ _ismutable = False
400
+
401
+ def __init__(self, runt, valu, path=None):
402
+ s_stormtypes.Prim.__init__(self, valu, path=path)
403
+ self.runt = runt
404
+ self.locls.update(self.getObjLocals())
405
+
406
+ def getObjLocals(self):
407
+ return {
408
+ 'add': self._methPkgQueueAdd,
409
+ 'gen': self._methPkgQueueGen,
410
+ 'del': self._methPkgQueueDel,
411
+ 'get': self._methPkgQueueGet,
412
+ 'list': self._methPkgQueueList,
413
+ }
414
+
415
+ def _reqPkgAdmin(self):
416
+ s_stormtypes.confirm(('power-ups', self.valu, 'admin'))
417
+
418
+ async def _methPkgQueueAdd(self, name):
419
+ self._reqPkgAdmin()
420
+ name = await s_stormtypes.tostr(name)
421
+
422
+ await self.runt.snap.core.addStormPkgQueue(self.valu, name)
423
+ return StormPkgQueue(self.runt, self.valu, name)
424
+
425
+ @s_stormtypes.stormfunc(readonly=True)
426
+ async def _methPkgQueueGet(self, name):
427
+ self._reqPkgAdmin()
428
+ name = await s_stormtypes.tostr(name)
429
+
430
+ await self.runt.snap.core.getStormPkgQueue(self.valu, name)
431
+ return StormPkgQueue(self.runt, self.valu, name)
432
+
433
+ async def _methPkgQueueGen(self, name):
434
+ try:
435
+ return await self._methPkgQueueGet(name)
436
+ except s_exc.NoSuchName:
437
+ return await self._methPkgQueueAdd(name)
438
+
439
+ async def _methPkgQueueDel(self, name):
440
+ self._reqPkgAdmin()
441
+ name = await s_stormtypes.tostr(name)
442
+
443
+ await self.runt.snap.core.delStormPkgQueue(self.valu, name)
444
+
445
+ @s_stormtypes.stormfunc(readonly=True)
446
+ async def _methPkgQueueList(self):
447
+ self._reqPkgAdmin()
448
+ async for pkginfo in self.runt.snap.core.listStormPkgQueues(pkgname=self.valu):
449
+ yield pkginfo
450
+
451
+ @s_stormtypes.registry.registerType
452
+ class StormPkgQueue(s_stormtypes.StormType):
453
+ '''
454
+ A StormLib API instance for a package Queue.
455
+ '''
456
+ _storm_locals = (
457
+ {'name': 'name', 'desc': 'The name of the Queue.', 'type': 'str'},
458
+ {'name': 'pkgname', 'desc': 'The name of the package the Queue belongs to.', 'type': 'str'},
459
+ {'name': 'get', 'desc': 'Get a particular item from the Queue.',
460
+ 'type': {'type': 'function', '_funcname': '_methPkgQueueGet',
461
+ 'args': (
462
+ {'name': 'offs', 'type': 'int', 'desc': 'The offset to retrieve an item from.', 'default': 0},
463
+ {'name': 'wait', 'type': 'boolean', 'default': True,
464
+ 'desc': 'Wait for the offset to be available before returning the item.'},
465
+ ),
466
+ 'returns': {'type': 'list',
467
+ 'desc': 'A tuple of the offset and the item from the Queue. If wait is false and '
468
+ 'the offset is not present, null is returned.'}}},
469
+ {'name': 'pop', 'desc': 'Pop an item from the Queue at a specific offset.',
470
+ 'type': {'type': 'function', '_funcname': '_methPkgQueuePop',
471
+ 'args': (
472
+ {'name': 'offs', 'type': 'int', 'default': None,
473
+ 'desc': 'Offset to pop the item from. If not specified, the first item in the Queue will be'
474
+ ' popped.', },
475
+ {'name': 'wait', 'type': 'boolean', 'default': False,
476
+ 'desc': 'Wait for an item to be available to pop.'},
477
+ ),
478
+ 'returns': {'type': 'list',
479
+ 'desc': 'The offset and item popped from the Queue. If there is no item at the '
480
+ 'offset or the Queue is empty and wait is false, it returns null.'}}},
481
+ {'name': 'put', 'desc': 'Put an item into the Queue.',
482
+ 'type': {'type': 'function', '_funcname': '_methPkgQueuePut',
483
+ 'args': (
484
+ {'name': 'item', 'type': 'prim', 'desc': 'The item being put into the Queue.'},
485
+ ),
486
+ 'returns': {'type': 'int', 'desc': 'The Queue offset of the item.'}}},
487
+ {'name': 'puts', 'desc': 'Put multiple items into the Queue.',
488
+ 'type': {'type': 'function', '_funcname': '_methPkgQueuePuts',
489
+ 'args': (
490
+ {'name': 'items', 'type': 'list', 'desc': 'The items to put into the Queue.'},
491
+ ),
492
+ 'returns': {'type': 'int', 'desc': 'The Queue offset of the first item.'}}},
493
+ {'name': 'gets', 'desc': 'Get multiple items from the Queue as a iterator.',
494
+ 'type': {'type': 'function', '_funcname': '_methPkgQueueGets',
495
+ 'args': (
496
+ {'name': 'offs', 'type': 'int', 'desc': 'The offset to retrieve an items from.', 'default': 0},
497
+ {'name': 'wait', 'type': 'boolean', 'default': True,
498
+ 'desc': 'Wait for the offset to be available before returning the item.'},
499
+ {'name': 'size', 'type': 'int', 'desc': 'The maximum number of items to yield',
500
+ 'default': None},
501
+ ),
502
+ 'returns': {'name': 'Yields', 'type': 'list', 'desc': 'Yields tuples of the offset and item.'}}},
503
+ {'name': 'cull', 'desc': 'Remove items from the Queue up to, and including, the offset.',
504
+ 'type': {'type': 'function', '_funcname': '_methPkgQueueCull',
505
+ 'args': (
506
+ {'name': 'offs', 'type': 'int', 'desc': 'The offset which to cull records from the Queue.'},
507
+ ),
508
+ 'returns': {'type': 'null'}}},
509
+ {'name': 'size', 'desc': 'Get the number of items in the Queue.',
510
+ 'type': {'type': 'function', '_funcname': '_methPkgQueueSize',
511
+ 'returns': {'type': 'int', 'desc': 'The number of items in the Queue.'}}},
512
+ )
513
+ _storm_typename = 'pkg:queue'
514
+ _ismutable = False
515
+
516
+ def __init__(self, runt, pkgname, name):
517
+
518
+ s_stormtypes.StormType.__init__(self)
519
+ self.runt = runt
520
+ self.name = name
521
+ self.pkgname = pkgname
522
+
523
+ self.locls.update(self.getObjLocals())
524
+ self.locls['name'] = self.name
525
+ self.locls['pkgname'] = self.pkgname
526
+
527
+ def __hash__(self):
528
+ return hash((self._storm_typename, self.pkgname, self.name))
529
+
530
+ def __eq__(self, othr):
531
+ if not isinstance(othr, type(self)):
532
+ return False
533
+ return self.pkgname == othr.pkgname and self.name == othr.name
534
+
535
+ def getObjLocals(self):
536
+ return {
537
+ 'get': self._methPkgQueueGet,
538
+ 'pop': self._methPkgQueuePop,
539
+ 'put': self._methPkgQueuePut,
540
+ 'puts': self._methPkgQueuePuts,
541
+ 'gets': self._methPkgQueueGets,
542
+ 'cull': self._methPkgQueueCull,
543
+ 'size': self._methPkgQueueSize,
544
+ }
545
+
546
+ def _reqPkgAdmin(self):
547
+ s_stormtypes.confirm(('power-ups', self.pkgname, 'admin'))
548
+
549
+ async def _methPkgQueueCull(self, offs):
550
+ self._reqPkgAdmin()
551
+ offs = await s_stormtypes.toint(offs)
552
+ await self.runt.snap.core.stormPkgQueueCull(self.pkgname, self.name, offs)
553
+
554
+ @s_stormtypes.stormfunc(readonly=True)
555
+ async def _methPkgQueueSize(self):
556
+ self._reqPkgAdmin()
557
+ return await self.runt.snap.core.stormPkgQueueSize(self.pkgname, self.name)
558
+
559
+ @s_stormtypes.stormfunc(readonly=True)
560
+ async def _methPkgQueueGets(self, offs=0, wait=True, size=None):
561
+ self._reqPkgAdmin()
562
+ offs = await s_stormtypes.toint(offs)
563
+ wait = await s_stormtypes.tobool(wait)
564
+ size = await s_stormtypes.toint(size, noneok=True)
565
+
566
+ async for item in self.runt.snap.core.stormPkgQueueGets(self.pkgname, self.name, offs, wait=wait, size=size):
567
+ yield item
568
+
569
+ async def _methPkgQueuePuts(self, items):
570
+ self._reqPkgAdmin()
571
+ items = await s_stormtypes.toprim(items)
572
+ return await self.runt.snap.core.stormPkgQueuePuts(self.pkgname, self.name, items)
573
+
574
+ @s_stormtypes.stormfunc(readonly=True)
575
+ async def _methPkgQueueGet(self, offs=0, wait=True):
576
+ self._reqPkgAdmin()
577
+ offs = await s_stormtypes.toint(offs)
578
+ wait = await s_stormtypes.tobool(wait)
579
+ return await self.runt.snap.core.stormPkgQueueGet(self.pkgname, self.name, offs, wait=wait)
580
+
581
+ async def _methPkgQueuePop(self, offs=None, wait=False):
582
+ self._reqPkgAdmin()
583
+ offs = await s_stormtypes.toint(offs, noneok=True)
584
+ wait = await s_stormtypes.tobool(wait)
585
+
586
+ core = self.runt.snap.core
587
+ if offs is None:
588
+ async for item in core.stormPkgQueueGets(self.pkgname, self.name, 0, wait=wait):
589
+ return await core.stormPkgQueuePop(self.pkgname, self.name, item[0])
590
+ return
591
+
592
+ return await core.stormPkgQueuePop(self.pkgname, self.name, offs)
593
+
594
+ async def _methPkgQueuePut(self, item):
595
+ return await self._methPkgQueuePuts((item,))
596
+
597
+ async def stormrepr(self):
598
+ return f'{self._storm_typename}: {self.pkgname} - {self.name}'