synapse 2.218.1__py311-none-any.whl → 2.219.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.

synapse/lib/stormtypes.py CHANGED
@@ -2,7 +2,6 @@ import bz2
2
2
  import copy
3
3
  import gzip
4
4
  import time
5
-
6
5
  import regex
7
6
  import types
8
7
  import base64
@@ -10,6 +9,7 @@ import pprint
10
9
  import struct
11
10
  import asyncio
12
11
  import decimal
12
+ import hashlib
13
13
  import inspect
14
14
  import logging
15
15
  import binascii
@@ -730,6 +730,18 @@ class LibPkg(Lib):
730
730
  {'name': 'pkgdef', 'type': 'dict', 'desc': 'A Storm Package definition.', },
731
731
  ),
732
732
  'returns': {'type': 'dict', 'desc': 'A dictionary listing dependencies and if they are met.', }}},
733
+ {'name': 'vars',
734
+ 'desc': "Get a dictionary representing the package's persistent variables.",
735
+ 'type': {'type': 'function', '_funcname': '_libPkgVars',
736
+ 'args': (
737
+ {'name': 'name', 'type': 'str',
738
+ 'desc': 'A Storm Package name to get vars for.', },
739
+ ),
740
+ 'returns': {'type': 'pkg:vars', 'desc': 'A dictionary representing the package variables.', }}},
741
+ )
742
+ _storm_lib_perms = (
743
+ {'perm': ('power-ups', '<name>', 'admin'), 'gate': 'cortex',
744
+ 'desc': 'Controls the ability to interact with the vars for a Storm Package by name.'},
733
745
  )
734
746
  _storm_lib_path = ('pkg',)
735
747
 
@@ -741,6 +753,7 @@ class LibPkg(Lib):
741
753
  'del': self._libPkgDel,
742
754
  'list': self._libPkgList,
743
755
  'deps': self._libPkgDeps,
756
+ 'vars': self._libPkgVars,
744
757
  }
745
758
 
746
759
  async def _libPkgAdd(self, pkgdef, verify=False):
@@ -780,6 +793,11 @@ class LibPkg(Lib):
780
793
  pkgdef = await toprim(pkgdef)
781
794
  return await self.runt.snap.core.verifyStormPkgDeps(pkgdef)
782
795
 
796
+ async def _libPkgVars(self, name):
797
+ name = await tostr(name)
798
+ confirm(('power-ups', name, 'admin'))
799
+ return PkgVars(self.runt, name)
800
+
783
801
  @registry.registerLib
784
802
  class LibDmon(Lib):
785
803
  '''
@@ -2745,9 +2763,13 @@ class LibAxon(Lib):
2745
2763
 
2746
2764
  self.runt.confirm(('axon', 'upload'))
2747
2765
 
2766
+ sha256 = hashlib.sha256(byts).digest()
2767
+
2748
2768
  await self.runt.snap.core.getAxon()
2749
- size, sha256 = await self.runt.snap.core.axon.put(byts)
2769
+ if await self.runt.snap.core.axon.has(sha256):
2770
+ return (len(byts), s_common.ehex(sha256))
2750
2771
 
2772
+ size, sha256 = await self.runt.snap.core.axon.put(byts)
2751
2773
  return (size, s_common.ehex(sha256))
2752
2774
 
2753
2775
  @stormfunc(readonly=True)
@@ -6015,6 +6037,45 @@ class LibVars(Lib):
6015
6037
  async def _libVarsType(self, valu):
6016
6038
  return await totype(valu)
6017
6039
 
6040
+ @registry.registerType
6041
+ class PkgVars(Prim):
6042
+ '''
6043
+ The Storm deref/setitem/iter convention on top of pkg vars information.
6044
+ '''
6045
+ _storm_typename = 'pkg:vars'
6046
+ _ismutable = True
6047
+
6048
+ def __init__(self, runt, valu, path=None):
6049
+ Prim.__init__(self, valu, path=path)
6050
+ self.runt = runt
6051
+
6052
+ def _reqPkgAdmin(self):
6053
+ confirm(('power-ups', self.valu, 'admin'))
6054
+
6055
+ @stormfunc(readonly=True)
6056
+ async def deref(self, name):
6057
+ self._reqPkgAdmin()
6058
+ name = await tostr(name)
6059
+ return await self.runt.snap.core.getStormPkgVar(self.valu, name)
6060
+
6061
+ async def setitem(self, name, valu):
6062
+ self._reqPkgAdmin()
6063
+ name = await tostr(name)
6064
+
6065
+ if valu is undef:
6066
+ await self.runt.snap.core.popStormPkgVar(self.valu, name)
6067
+ return
6068
+
6069
+ valu = await toprim(valu)
6070
+ await self.runt.snap.core.setStormPkgVar(self.valu, name, valu)
6071
+
6072
+ @stormfunc(readonly=True)
6073
+ async def iter(self):
6074
+ self._reqPkgAdmin()
6075
+ async for name, valu in self.runt.snap.core.iterStormPkgVars(self.valu):
6076
+ yield name, valu
6077
+ await asyncio.sleep(0)
6078
+
6018
6079
  @registry.registerType
6019
6080
  class Query(Prim):
6020
6081
  '''
@@ -7069,6 +7130,37 @@ class Layer(Prim):
7069
7130
  'desc': 'The name of the form to get storage nodes for.'},
7070
7131
  ),
7071
7132
  'returns': {'name': 'Yields', 'type': 'list', 'desc': 'Tuple of buid, sode values.', }}},
7133
+ {'name': 'getStorNodesByProp', 'desc': '''
7134
+ Get buid, sode tuples representing the data stored in the layer for a given property.
7135
+ Notes:
7136
+ The storage nodes represent **only** the data stored in the layer
7137
+ and may not represent whole nodes.
7138
+ ''',
7139
+ 'type': {'type': 'function', '_funcname': 'getStorNodesByProp',
7140
+ 'args': (
7141
+ {'name': 'propname', 'type': 'str', 'desc': 'The full property name to lift by.'},
7142
+ {'name': 'propvalu', 'type': 'obj', 'desc': 'The value for the property.', 'default': None},
7143
+ {'name': 'propcmpr', 'type': 'str', 'desc': 'The comparison operation to use on the value.',
7144
+ 'default': '='},
7145
+ ),
7146
+ 'returns': {'name': 'Yields', 'type': 'list', 'desc': 'Tuple of buid, sode values.', }}},
7147
+ {'name': 'setStorNodeProp',
7148
+ 'desc': 'Set a property on a node in this layer.',
7149
+ 'type': {'type': 'function', '_funcname': 'setStorNodeProp',
7150
+ 'args': (
7151
+ {'name': 'nodeid', 'type': 'str', 'desc': 'The hex string of the node iden.'},
7152
+ {'name': 'prop', 'type': 'str', 'desc': 'The property name to set.'},
7153
+ {'name': 'valu', 'type': 'any', 'desc': 'The value to set.'},
7154
+ ),
7155
+ 'returns': {'type': 'boolean', 'desc': 'Returns true if edits were made.'}}},
7156
+ {'name': 'delStorNodeProp',
7157
+ 'desc': 'Delete a property from a node in this layer.',
7158
+ 'type': {'type': 'function', '_funcname': 'delStorNodeProp',
7159
+ 'args': (
7160
+ {'name': 'nodeid', 'type': 'str', 'desc': 'The hex string of the node iden.'},
7161
+ {'name': 'prop', 'type': 'str', 'desc': 'The property name to delete.'},
7162
+ ),
7163
+ 'returns': {'type': 'boolean', 'desc': 'Returns true if edits were made.'}}},
7072
7164
  {'name': 'getMirrorStatus', 'desc': '''
7073
7165
  Return a dictionary of the mirror synchronization status for the layer.
7074
7166
  ''',
@@ -7287,10 +7379,13 @@ class Layer(Prim):
7287
7379
  'getStorNode': self.getStorNode,
7288
7380
  'getStorNodes': self.getStorNodes,
7289
7381
  'getStorNodesByForm': self.getStorNodesByForm,
7382
+ 'getStorNodesByProp': self.getStorNodesByProp,
7290
7383
  'getEdgesByN1': self.getEdgesByN1,
7291
7384
  'getEdgesByN2': self.getEdgesByN2,
7292
7385
  'getNodeData': self.getNodeData,
7293
7386
  'getMirrorStatus': self.getMirrorStatus,
7387
+ 'setStorNodeProp': self.setStorNodeProp,
7388
+ 'delStorNodeProp': self.delStorNodeProp,
7294
7389
  }
7295
7390
 
7296
7391
  @stormfunc(readonly=True)
@@ -7364,6 +7459,25 @@ class Layer(Prim):
7364
7459
  layr = self.runt.snap.core.getLayer(iden)
7365
7460
  return await layr.getMirrorStatus()
7366
7461
 
7462
+ async def setStorNodeProp(self, nodeid, prop, valu):
7463
+ iden = self.valu.get('iden')
7464
+ layr = self.runt.snap.core.getLayer(iden)
7465
+ buid = s_common.uhex(await tostr(nodeid))
7466
+ prop = await tostr(prop)
7467
+ valu = await tostor(valu)
7468
+ self.runt.reqAdmin(mesg='setStorNodeProp() requires admin privileges.')
7469
+ meta = {'time': s_common.now(), 'user': self.runt.user.iden}
7470
+ return await layr.setStorNodeProp(buid, prop, valu, meta=meta)
7471
+
7472
+ async def delStorNodeProp(self, nodeid, prop):
7473
+ iden = self.valu.get('iden')
7474
+ layr = self.runt.snap.core.getLayer(iden)
7475
+ buid = s_common.uhex(await tostr(nodeid))
7476
+ prop = await tostr(prop)
7477
+ self.runt.reqAdmin(mesg='delStorNodeProp() requires admin privileges.')
7478
+ meta = {'time': s_common.now(), 'user': self.runt.user.iden}
7479
+ return await layr.delStorNodeProp(buid, prop, meta=meta)
7480
+
7367
7481
  async def _addPull(self, url, offs=0, queue_size=s_const.layer_pdef_qsize, chunk_size=s_const.layer_pdef_csize):
7368
7482
  url = await tostr(url)
7369
7483
  offs = await toint(offs)
@@ -7646,6 +7760,28 @@ class Layer(Prim):
7646
7760
  async for item in layr.getStorNodesByForm(form):
7647
7761
  yield item
7648
7762
 
7763
+ @stormfunc(readonly=True)
7764
+ async def getStorNodesByProp(self, propname, propvalu=None, propcmpr='='):
7765
+ propname = await tostr(propname)
7766
+ propvalu = await tostor(propvalu)
7767
+ propcmpr = await tostr(propcmpr)
7768
+
7769
+ layriden = self.valu.get('iden')
7770
+ await self.runt.reqUserCanReadLayer(layriden)
7771
+ layr = self.runt.snap.core.getLayer(layriden)
7772
+
7773
+ prop = self.runt.snap.core.model.reqProp(propname)
7774
+
7775
+ if propvalu is not None:
7776
+ norm, info = prop.type.norm(propvalu)
7777
+ cmprvals = prop.type.getStorCmprs(propcmpr, norm)
7778
+ async for _, buid, sode in layr.liftByPropValu(prop.form.name, prop.name, cmprvals):
7779
+ yield (s_common.ehex(buid), sode)
7780
+ return
7781
+
7782
+ async for _, buid, sode in layr.liftByProp(prop.form.name, prop.name):
7783
+ yield (s_common.ehex(buid), sode)
7784
+
7649
7785
  @stormfunc(readonly=True)
7650
7786
  async def getEdges(self):
7651
7787
  layriden = self.valu.get('iden')
synapse/lib/version.py CHANGED
@@ -223,6 +223,6 @@ def reqVersion(valu, reqver,
223
223
  ##############################################################################
224
224
  # The following are touched during the release process by bumpversion.
225
225
  # Do not modify these directly.
226
- version = (2, 218, 1)
226
+ version = (2, 219, 0)
227
227
  verstring = '.'.join([str(x) for x in version])
228
- commit = 'f91b8902226a2b8d984804f164c4c65e8b7e5ce3'
228
+ commit = '9e442b257a7ddfa8d476eafdcad21c3a0440cc83'
synapse/models/inet.py CHANGED
@@ -3796,6 +3796,9 @@ class InetModule(s_module.CoreModule):
3796
3796
  ('user', ('inet:user', {}), {
3797
3797
  'doc': 'The current user name of the account.'}),
3798
3798
 
3799
+ ('parent', ('inet:service:account', {}), {
3800
+ 'doc': 'A parent account which owns this account.'}),
3801
+
3799
3802
  ('email', ('inet:email', {}), {
3800
3803
  'doc': 'The current email address associated with the account.'}),
3801
3804
 
@@ -0,0 +1,12 @@
1
+ name: badinits
2
+ version: 0.0.1
3
+
4
+ inits:
5
+ name: badinits:version
6
+ versions:
7
+ - name: first
8
+ version: 7
9
+ query: ""
10
+ - name: second
11
+ version: 2
12
+ query: ""
@@ -45,6 +45,18 @@ onload: |
45
45
  $lib.time.sleep($lib.globals.get(onload_sleep, 0))
46
46
  $lib.globals.set(testpkg, testpkg-done)
47
47
 
48
+ inits:
49
+ key: testpkg:version
50
+ versions:
51
+ - name: first
52
+ version: 0
53
+ inaugural: true
54
+ query: "$lib.globals.set(testpkg-first, (true))"
55
+ - name: second
56
+ desc: Another init
57
+ version: 2
58
+ query: "$lib.globals.set(testpkg-second, (true))"
59
+
48
60
  external_modules:
49
61
  - name: testext
50
62
  package: synapse.tests.files
@@ -2283,3 +2283,122 @@ class LayerTest(s_t_utils.SynTest):
2283
2283
 
2284
2284
  sodes = await s_t_utils.alist(layr00.getStorNodesByForm('inet:ipv4'))
2285
2285
  self.len(0, sodes)
2286
+
2287
+ async def test_layer_migrate_props_fork(self):
2288
+
2289
+ async with self.getTestCore() as core:
2290
+
2291
+ iden = (await core.addUser('lowuser')).get('iden')
2292
+ lowuser = {'user': iden}
2293
+
2294
+ fork00 = await core.view.fork()
2295
+ layr00 = core.getLayer(fork00['layers'][0]['iden'])
2296
+
2297
+ await core.nodes('''
2298
+ for $prop in (_custom:risk:level, _custom:risk:severity) {
2299
+ $lib.model.ext.addFormProp(
2300
+ test:guid,
2301
+ $prop,
2302
+ (["int", {"enums": [[10, "low"], [20, "medium"], [30, "high"]]}]),
2303
+ ({"doc": "hey now"}),
2304
+ )
2305
+ }
2306
+
2307
+ ''')
2308
+ self.len(1, await core.nodes('syn:prop=test:guid:_custom:risk:level'))
2309
+ self.len(1, await core.nodes('syn:prop=test:guid:_custom:risk:severity'))
2310
+
2311
+ await core.nodes('[ test:guid=* :name=test1 :_custom:risk:level=low ]', opts={'view': fork00['iden']})
2312
+
2313
+ await core.getView(fork00['iden']).delete()
2314
+
2315
+ with self.raises(s_exc.CantDelProp) as cm:
2316
+ await core.callStorm('''
2317
+ $fullprop = "test:guid:_custom:risk:level"
2318
+ for $view in $lib.view.list(deporder=$lib.true) {
2319
+ view.exec $view.iden {
2320
+ yield $lib.layer.get().liftByProp($fullprop)
2321
+ $repr = $node.repr("_custom:risk:level")
2322
+ [ :severity=$repr -:_custom:risk:level ]
2323
+ }
2324
+ }
2325
+ $lib.model.ext.delFormProp("test:guid", "_custom:risk:level")
2326
+ ''')
2327
+ self.isin('Nodes still exist with prop: test:guid:_custom:risk:level', str(cm.exception))
2328
+ self.len(1, await core.nodes('syn:prop=test:guid:_custom:risk:level'))
2329
+
2330
+ with self.raises(s_exc.NoSuchProp) as cm:
2331
+ await core.callStorm('''
2332
+ $layer = $lib.layer.get()
2333
+ $layer.getStorNodesByProp("foo:bar:_custom:risk:level")
2334
+ ''')
2335
+ self.isin('No property named', str(cm.exception))
2336
+
2337
+ with self.raises(s_exc.NoSuchProp):
2338
+ await core.callStorm('''
2339
+ $fullprop = "test:guid:_custom:risk:level"
2340
+ for $layer in $lib.layer.list() {
2341
+ for ($buid, $sode) in $layer.getStorNodesByProp($fullprop) {
2342
+ $oldv = $sode.props."_custom:risk:level"
2343
+ $layer.setStorNodeProp($buid, "foo:bar:severity", $oldv.0)
2344
+ }
2345
+ }
2346
+ ''')
2347
+
2348
+ with self.raises(s_exc.BadTypeValu):
2349
+ await core.callStorm('''
2350
+ $fullprop = "test:guid:_custom:risk:level"
2351
+ for $layer in $lib.layer.list() {
2352
+ for ($buid, $sode) in $layer.getStorNodesByProp($fullprop) {
2353
+ $layer.setStorNodeProp($buid, $fullprop, "newp")
2354
+ }
2355
+ }
2356
+ ''')
2357
+
2358
+ with self.raises(s_exc.NoSuchProp):
2359
+ await core.callStorm('''
2360
+ $fullprop = "test:guid:_custom:risk:level"
2361
+ for $layer in $lib.layer.list() {
2362
+ for ($buid, $sode) in $layer.getStorNodesByProp($fullprop) {
2363
+ $layer.delStorNodeProp($buid, "foo:bar:severity")
2364
+ }
2365
+ }
2366
+ ''')
2367
+
2368
+ with self.raises(s_exc.AuthDeny) as cm:
2369
+ await core.callStorm('''
2370
+ $buid = "8c454b27df9c0ba109c123265b50869759bccac5bbec83b41992b4e91207f4a4"
2371
+ $layer = $lib.layer.get()
2372
+ $layer.setStorNodeProp($buid, "foo:bar:severity", "newp")
2373
+ ''', opts=lowuser)
2374
+ self.isin('requires admin privileges', str(cm.exception))
2375
+
2376
+ with self.raises(s_exc.AuthDeny) as cm:
2377
+ await core.callStorm('''
2378
+ $buid = "8c454b27df9c0ba109c123265b50869759bccac5bbec83b41992b4e91207f4a4"
2379
+ $layer = $lib.layer.get()
2380
+ $layer.delStorNodeProp($buid, "foo:bar:severity")
2381
+ ''', opts=lowuser)
2382
+ self.isin('requires admin privileges', str(cm.exception))
2383
+
2384
+ await core.callStorm('''
2385
+ $fullprop = "test:guid:_custom:risk:level"
2386
+ for $layer in $lib.layer.list() {
2387
+ if $layer.getPropCount($fullprop, maxsize=1) {
2388
+ for ($buid, $sode) in $layer.getStorNodesByProp($fullprop, (10), "=") {
2389
+ $oldv = $sode.props."_custom:risk:level"
2390
+ $layer.setStorNodeProp($buid, "test:guid:_custom:risk:severity", $oldv.0)
2391
+ $layer.delStorNodeProp($buid, $fullprop)
2392
+ }
2393
+ }
2394
+ }
2395
+ $lib.model.ext.delFormProp("test:guid", "_custom:risk:level")
2396
+ ''')
2397
+ self.len(0, await core.nodes('syn:prop=test:guid:_custom:risk:level'))
2398
+ self.len(0, await core.nodes('test:guid:_custom:risk:severity'))
2399
+
2400
+ view00 = (await core.addView(vdef={'layers': [layr00.iden]}))['iden']
2401
+ nodes = await core.nodes('test:guid', opts={'view': view00})
2402
+ self.len(1, nodes)
2403
+ self.none(nodes[0].props.get('_custom:risk:level'))
2404
+ self.eq(nodes[0].props.get('_custom:risk:severity'), 10)
@@ -3105,6 +3105,185 @@ class StormTest(s_t_utils.SynTest):
3105
3105
 
3106
3106
  await core00.waitfini()
3107
3107
 
3108
+ async def test_storm_pkg_inits(self):
3109
+
3110
+ async def loadPkg(core, pkg):
3111
+ waiter = core.waiter(2, 'core:pkg:onload:start', 'core:pkg:onload:complete')
3112
+
3113
+ await core.addStormPkg(pkg)
3114
+
3115
+ events = await waiter.wait(timeout=10)
3116
+ self.eq(events, [
3117
+ ('core:pkg:onload:start', {'pkg': 'testload'}),
3118
+ ('core:pkg:onload:complete', {'pkg': 'testload'}),
3119
+ ])
3120
+
3121
+ with self.getTestDir() as dirn:
3122
+
3123
+ async with self.getTestCore(dirn=dirn) as core:
3124
+
3125
+ pkg = {
3126
+ 'name': 'testload',
3127
+ 'version': '0.1.0',
3128
+ 'inits': {
3129
+ 'key': 'testload:version',
3130
+ 'versions': [
3131
+ {
3132
+ 'version': 0,
3133
+ 'name': 'init00',
3134
+ 'query': '$lib.globals.set(init00, $lib.time.now())',
3135
+ },
3136
+ {
3137
+ 'version': 1,
3138
+ 'name': 'init01',
3139
+ 'inaugural': True,
3140
+ 'query': '$lib.globals.set(init01, $lib.time.now())',
3141
+ },
3142
+ ]
3143
+ },
3144
+ }
3145
+
3146
+ # bad init queries fail on load
3147
+
3148
+ pkg['inits']['versions'].append({
3149
+ 'version': 2,
3150
+ 'name': 'bad',
3151
+ 'query': '...',
3152
+ })
3153
+
3154
+ await self.asyncraises(s_exc.BadSyntax, core.addStormPkg(pkg))
3155
+
3156
+ pkg['inits']['versions'].pop(2)
3157
+
3158
+ # non-increasing init versions fail on load
3159
+
3160
+ pkg['inits']['versions'].append({
3161
+ 'version': 0,
3162
+ 'name': 'bad',
3163
+ 'query': '$lib.print("")',
3164
+ })
3165
+
3166
+ await self.asyncraises(s_exc.BadPkgDef, core.addStormPkg(pkg))
3167
+
3168
+ pkg['inits']['versions'].pop(2)
3169
+
3170
+ # only inaugural inits run on first load
3171
+
3172
+ await loadPkg(core, pkg)
3173
+
3174
+ self.eq(1, await core.getStormPkgVar('testload', 'testload:version'))
3175
+ self.none(await core.getStormVar('init00'))
3176
+ self.nn(init01 := await core.getStormVar('init01'))
3177
+
3178
+ # non-inaugural inits run on reload
3179
+ # inits always run before onload
3180
+
3181
+ pkg['version'] = '0.2.0'
3182
+ pkg['onload'] = '$lib.time.sleep((0.1)) $lib.globals.set(onload, $lib.time.now())'
3183
+ pkg['inits']['versions'].append({
3184
+ 'version': 2,
3185
+ 'name': 'init02',
3186
+ 'query': '$lib.globals.set(init02, $lib.time.now())',
3187
+ })
3188
+
3189
+ await loadPkg(core, pkg)
3190
+
3191
+ self.eq(2, await core.getStormPkgVar('testload', 'testload:version'))
3192
+ self.none(await core.getStormVar('init00'))
3193
+ self.eq(init01, await core.getStormVar('init01'))
3194
+ self.nn(init02 := await core.getStormVar('init02'))
3195
+ self.nn(onload := await core.getStormVar('onload'))
3196
+ self.gt(onload, init02)
3197
+
3198
+ # inits run even if onload fails
3199
+ # prior inits do not re-run
3200
+
3201
+ pkg['version'] = '0.3.0'
3202
+ pkg['onload'] = '$lib.raise(SynErr, whoopsie)'
3203
+ pkg['inits']['versions'].append({
3204
+ 'version': 3,
3205
+ 'name': 'init03',
3206
+ 'inaugural': True,
3207
+ 'query': '$lib.globals.set(init03, $lib.time.now())',
3208
+ })
3209
+
3210
+ await loadPkg(core, pkg)
3211
+
3212
+ self.eq(3, await core.getStormPkgVar('testload', 'testload:version'))
3213
+ self.eq(init02, await core.getStormVar('init02'))
3214
+ self.nn(await core.getStormVar('init03'))
3215
+
3216
+ # init failure stops progression
3217
+
3218
+ await core.setStormVar('dofail', True)
3219
+
3220
+ pkg['version'] = '0.4.0'
3221
+ pkg['onload'] = '$lib.globals.set(onload, $lib.time.now()) $lib.time.sleep((0.1))'
3222
+ pkg['inits']['versions'].extend([
3223
+ {
3224
+ 'version': 4,
3225
+ 'name': 'init04',
3226
+ 'query': '''
3227
+ if $lib.globals.get(dofail) { $lib.raise(SynErr, newp) }
3228
+ $lib.globals.set(init04, $lib.time.now())
3229
+ ''',
3230
+ },
3231
+ {
3232
+ 'version': 6,
3233
+ 'name': 'init06',
3234
+ 'query': '$lib.globals.set(init06, $lib.time.now())',
3235
+ },
3236
+ ])
3237
+
3238
+ mesg = 'testload init vers=4 output: (\'SynErr\''
3239
+ with self.getAsyncLoggerStream('synapse.cortex', mesg) as stream:
3240
+ await loadPkg(core, pkg)
3241
+ self.eq(3, await core.getStormPkgVar('testload', 'testload:version'))
3242
+ await stream.wait(timeout=10)
3243
+
3244
+ self.none(await core.getStormVar('init04'))
3245
+ self.none(await core.getStormVar('init06'))
3246
+
3247
+ await core.setStormVar('dofail', False)
3248
+
3249
+ with self.getAsyncLoggerStream('synapse.cortex', 'testload finished onload') as stream:
3250
+ async with self.getTestCore(dirn=dirn) as core:
3251
+ await stream.wait(timeout=10)
3252
+
3253
+ # prior versions dont re-run, but a failed one does
3254
+
3255
+ self.eq(6, await core.getStormPkgVar('testload', 'testload:version'))
3256
+ self.gt(await core.getStormVar('onload'), onload)
3257
+ self.eq(init02, await core.getStormVar('init02'))
3258
+ self.nn(await core.getStormVar('init04'))
3259
+ self.nn(await core.getStormVar('init06'))
3260
+
3261
+ # coverage for prints and warns
3262
+
3263
+ pkg['version'] = '0.5.0'
3264
+ pkg['inits']['versions'].append({
3265
+ 'version': 7,
3266
+ 'name': 'init07',
3267
+ 'query': '$lib.print("doing a print")',
3268
+ })
3269
+
3270
+ with self.getAsyncLoggerStream('synapse.cortex', 'doing a print') as stream:
3271
+ await loadPkg(core, pkg)
3272
+ await stream.wait(timeout=10)
3273
+ self.eq(7, await core.getStormPkgVar('testload', 'testload:version'))
3274
+
3275
+ pkg['version'] = '0.6.0'
3276
+ pkg['inits']['versions'].append({
3277
+ 'version': 8,
3278
+ 'name': 'init08',
3279
+ 'query': '$lib.warn("doing a warn")',
3280
+ })
3281
+
3282
+ with self.getAsyncLoggerStream('synapse.cortex', 'doing a warn') as stream:
3283
+ await loadPkg(core, pkg)
3284
+ await stream.wait(timeout=10)
3285
+ self.eq(8, await core.getStormPkgVar('testload', 'testload:version'))
3286
+
3108
3287
  async def test_storm_tree(self):
3109
3288
 
3110
3289
  async with self.getTestCore() as core: