synapse 2.218.0__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/cortex.py CHANGED
@@ -897,6 +897,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
897
897
  self.stormmods = {} # name: mdef
898
898
  self.stormpkgs = {} # name: pkgdef
899
899
  self.stormvars = None # type: s_lmdbslab.SafeKeyVal
900
+ self.stormpkgvars = {} # type: Dict[str, s_lmdbslab.SafeKeyVal]
900
901
 
901
902
  self.svcsbyiden = {}
902
903
  self.svcsbyname = {}
@@ -2883,11 +2884,23 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
2883
2884
  mods = pkgdef.get('modules', ())
2884
2885
  cmds = pkgdef.get('commands', ())
2885
2886
  onload = pkgdef.get('onload')
2887
+ inits = pkgdef.get('inits')
2886
2888
  svciden = pkgdef.get('svciden')
2887
2889
 
2888
2890
  if onload is not None and validstorm:
2889
2891
  await self.getStormQuery(onload)
2890
2892
 
2893
+ if inits is not None:
2894
+ lastver = None
2895
+ for initdef in inits.get('versions'):
2896
+ curver = initdef.get('version')
2897
+ if lastver is not None and not curver > lastver:
2898
+ raise s_exc.BadPkgDef(mesg='Init versions must be monotonically increasing.', version=curver)
2899
+ lastver = curver
2900
+
2901
+ if validstorm:
2902
+ await self.getStormQuery(initdef.get('query'))
2903
+
2891
2904
  for mdef in mods:
2892
2905
  mdef.setdefault('modconf', {})
2893
2906
  if svciden:
@@ -2968,28 +2981,88 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
2968
2981
 
2969
2982
  def _runStormPkgOnload(self, pkgdef):
2970
2983
  name = pkgdef.get('name')
2984
+ inits = pkgdef.get('inits')
2971
2985
  onload = pkgdef.get('onload')
2986
+ pkgvers = pkgdef.get('version')
2972
2987
 
2973
- if onload is not None and self.isactive:
2988
+ if (onload is not None or inits is not None) and self.isactive:
2974
2989
  async def _onload():
2975
2990
  if self.safemode:
2976
2991
  await self.fire('core:pkg:onload:skipped', pkg=name, reason='safemode')
2977
2992
  return
2978
2993
 
2979
2994
  await self.fire('core:pkg:onload:start', pkg=name)
2980
- try:
2981
- async for mesg in self.storm(onload):
2982
- if mesg[0] == 'print':
2983
- logger.info(f'{name} onload output: {mesg[1].get("mesg")}')
2984
- if mesg[0] == 'warn':
2985
- logger.warning(f'{name} onload output: {mesg[1].get("mesg")}')
2986
- if mesg[0] == 'err':
2987
- logger.error(f'{name} onload output: {mesg[1]}')
2988
- await asyncio.sleep(0)
2989
- except asyncio.CancelledError: # pragma: no cover
2990
- raise
2991
- except Exception as exc: # pragma: no cover
2992
- logger.warning(f'onload failed for package: {name}', exc_info=exc)
2995
+
2996
+ logextra = await self.getLogExtra(pkg=name, vers=pkgvers)
2997
+
2998
+ if inits is not None:
2999
+ varname = inits['key']
3000
+ curvers = await self.getStormPkgVar(name, varname, default=-1)
3001
+ inaugural = curvers == -1
3002
+
3003
+ for initdef in inits['versions']:
3004
+
3005
+ vers = initdef['version']
3006
+ vname = initdef['name']
3007
+
3008
+ if vers <= curvers:
3009
+ continue
3010
+
3011
+ if inaugural and not initdef.get('inaugural'):
3012
+ await self.setStormPkgVar(name, varname, vers)
3013
+ continue
3014
+
3015
+ logextra['synapse']['initvers'] = vers
3016
+
3017
+ logger.info(f'{name} starting init vers={vers}: {vname}', extra=logextra)
3018
+
3019
+ ok = True
3020
+
3021
+ try:
3022
+ async for mesg in self.storm(initdef['query']):
3023
+ match mesg[0]:
3024
+ case 'print':
3025
+ msg = f'{name} init vers={vers} output: {mesg[1].get("mesg")}'
3026
+ logger.info(msg, extra=logextra)
3027
+ case 'warn':
3028
+ msg = f'{name} init vers={vers} output: {mesg[1].get("mesg")}'
3029
+ logger.warning(msg, extra=logextra)
3030
+ case 'err':
3031
+ msg = f'{name} init vers={vers} output: {mesg[1]}'
3032
+ logger.error(msg, extra=logextra)
3033
+ ok = False
3034
+ await asyncio.sleep(0)
3035
+ except asyncio.CancelledError: # pragma: no cover
3036
+ raise
3037
+ except Exception as exc: # pragma: no cover
3038
+ msg = f'{name} init failed for vers={vers}: {vname}'
3039
+ logger.warning(msg, exc_info=exc, extra=logextra)
3040
+ ok = False
3041
+
3042
+ if not ok:
3043
+ break
3044
+
3045
+ curvers = vers
3046
+ await self.setStormPkgVar(name, varname, vers)
3047
+ logger.info(f'{name} finished init vers={vers}: {vname}', extra=logextra)
3048
+
3049
+ if onload is not None:
3050
+ try:
3051
+ async for mesg in self.storm(onload):
3052
+ if mesg[0] == 'print':
3053
+ logger.info(f'{name} onload output: {mesg[1].get("mesg")}', extra=logextra)
3054
+ if mesg[0] == 'warn':
3055
+ logger.warning(f'{name} onload output: {mesg[1].get("mesg")}', extra=logextra)
3056
+ if mesg[0] == 'err':
3057
+ logger.error(f'{name} onload output: {mesg[1]}', extra=logextra)
3058
+ await asyncio.sleep(0)
3059
+ except asyncio.CancelledError: # pragma: no cover
3060
+ raise
3061
+ except Exception as exc: # pragma: no cover
3062
+ logger.warning(f'onload failed for package: {name}', exc_info=exc, extra=logextra)
3063
+
3064
+ logger.info(f'{name} finished onload', extra=logextra)
3065
+
2993
3066
  await self.fire('core:pkg:onload:complete', pkg=name)
2994
3067
 
2995
3068
  self.runActiveTask(_onload())
@@ -3229,6 +3302,32 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
3229
3302
  for item in self.stormvars.items():
3230
3303
  yield item
3231
3304
 
3305
+ # Storm package vars APIs
3306
+
3307
+ def _getStormPkgVarKV(self, name):
3308
+ if (pkgvars := self.stormpkgvars.get(name)) is None:
3309
+ self.stormpkgvars[name] = pkgvars = self.cortexdata.getSubKeyVal(f'stormpkg:vars:{name}:')
3310
+ return pkgvars
3311
+
3312
+ async def getStormPkgVar(self, name, key, default=None):
3313
+ pkgvars = self._getStormPkgVarKV(name)
3314
+ return pkgvars.get(key, defv=default)
3315
+
3316
+ @s_nexus.Pusher.onPushAuto('storm:pkg:var:pop')
3317
+ async def popStormPkgVar(self, name, key, default=None):
3318
+ pkgvars = self._getStormPkgVarKV(name)
3319
+ return pkgvars.pop(key, defv=default)
3320
+
3321
+ @s_nexus.Pusher.onPushAuto('storm:pkg:var:set')
3322
+ async def setStormPkgVar(self, name, key, valu):
3323
+ pkgvars = self._getStormPkgVarKV(name)
3324
+ return pkgvars.set(key, valu)
3325
+
3326
+ async def iterStormPkgVars(self, name):
3327
+ pkgvars = self._getStormPkgVarKV(name)
3328
+ for item in pkgvars.items():
3329
+ yield item
3330
+
3232
3331
  async def _cortexHealth(self, health):
3233
3332
  health.update('cortex', 'nominal')
3234
3333
 
@@ -5500,7 +5599,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
5500
5599
  # TODO Remove the defaults in 3.0.0
5501
5600
  csize = pdef.get('chunk:size', s_const.layer_pdef_csize)
5502
5601
  qsize = pdef.get('queue:size', s_const.layer_pdef_qsize)
5503
- soffs = pdef.get('offs', -1)
5602
+ soffs = max(pdef.get('offs', 0), 0)
5504
5603
 
5505
5604
  async with await s_base.Base.anit() as base:
5506
5605
 
@@ -5509,8 +5608,12 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
5509
5608
  async def fill():
5510
5609
 
5511
5610
  try:
5512
- filloffs = await self.getStormVar(gvar, soffs)
5513
- async for item in layr0.syncNodeEdits(filloffs + 1, wait=True):
5611
+ if (filloffs := await self.getStormVar(gvar)) is not None:
5612
+ filloffs += 1
5613
+ else:
5614
+ filloffs = soffs
5615
+
5616
+ async for item in layr0.syncNodeEdits(filloffs, wait=True):
5514
5617
  await queue.put(item)
5515
5618
  await queue.close()
5516
5619
 
synapse/daemon.py CHANGED
@@ -213,7 +213,8 @@ async def t2call(link, meth, args, kwargs):
213
213
  return
214
214
 
215
215
  except (asyncio.CancelledError, Exception) as e:
216
- logger.exception(f'error during task: {meth.__name__} {e}')
216
+ if not isinstance(e, asyncio.CancelledError):
217
+ logger.exception(f'error during task: {meth.__name__} {e}')
217
218
  if not link.isfini:
218
219
  retn = s_common.retnexc(e)
219
220
  await link.tx(('t2:fini', {'retn': retn}))
synapse/lib/ast.py CHANGED
@@ -1081,64 +1081,65 @@ class ForLoop(Oper):
1081
1081
  if valu is None:
1082
1082
  valu = ()
1083
1083
 
1084
- async with contextlib.aclosing(s_coro.agen(valu)) as agen:
1084
+ with s_scope.enter({'runt': runt}):
1085
+ async with contextlib.aclosing(s_coro.agen(valu)) as agen:
1085
1086
 
1086
- try:
1087
- agen, _ = await pullone(agen)
1088
- except TypeError:
1089
- styp = await s_stormtypes.totype(valu, basetypes=True)
1090
- mesg = f"'{styp}' object is not iterable: {s_common.trimText(repr(valu))}"
1091
- raise self.kids[1].addExcInfo(s_exc.StormRuntimeError(mesg=mesg, type=styp)) from None
1087
+ try:
1088
+ agen, _ = await pullone(agen)
1089
+ except TypeError:
1090
+ styp = await s_stormtypes.totype(valu, basetypes=True)
1091
+ mesg = f"'{styp}' object is not iterable: {s_common.trimText(repr(valu))}"
1092
+ raise self.kids[1].addExcInfo(s_exc.StormRuntimeError(mesg=mesg, type=styp)) from None
1092
1093
 
1093
- async for item in agen:
1094
+ async for item in agen:
1094
1095
 
1095
- if isinstance(name, (list, tuple)):
1096
+ if isinstance(name, (list, tuple)):
1096
1097
 
1097
- try:
1098
- numitems = len(item)
1099
- except TypeError:
1100
- mesg = f'Number of items to unpack does not match the number of variables: {s_common.trimText(repr(item))}'
1101
- exc = s_exc.StormVarListError(mesg=mesg, names=name)
1102
- raise self.kids[1].addExcInfo(exc)
1098
+ try:
1099
+ numitems = len(item)
1100
+ except TypeError:
1101
+ mesg = f'Number of items to unpack does not match the number of variables: {s_common.trimText(repr(item))}'
1102
+ exc = s_exc.StormVarListError(mesg=mesg, names=name)
1103
+ raise self.kids[1].addExcInfo(exc)
1103
1104
 
1104
- if len(name) != numitems:
1105
- mesg = f'Number of items to unpack does not match the number of variables: {s_common.trimText(repr(item))}'
1106
- exc = s_exc.StormVarListError(mesg=mesg, names=name, numitems=numitems)
1107
- raise self.kids[1].addExcInfo(exc)
1105
+ if len(name) != numitems:
1106
+ mesg = f'Number of items to unpack does not match the number of variables: {s_common.trimText(repr(item))}'
1107
+ exc = s_exc.StormVarListError(mesg=mesg, names=name, numitems=numitems)
1108
+ raise self.kids[1].addExcInfo(exc)
1108
1109
 
1109
- if isinstance(item, s_stormtypes.Prim):
1110
- item = await item.value()
1110
+ if isinstance(item, s_stormtypes.Prim):
1111
+ item = await item.value()
1111
1112
 
1112
- for x, y in itertools.zip_longest(name, item):
1113
- await path.setVar(x, y)
1114
- await runt.setVar(x, y)
1113
+ for x, y in itertools.zip_longest(name, item):
1114
+ await path.setVar(x, y)
1115
+ await runt.setVar(x, y)
1115
1116
 
1116
- else:
1117
- # set both so inner subqueries have it in their runtime
1118
- await path.setVar(name, item)
1119
- await runt.setVar(name, item)
1117
+ else:
1118
+ # set both so inner subqueries have it in their runtime
1119
+ await path.setVar(name, item)
1120
+ await runt.setVar(name, item)
1120
1121
 
1121
- try:
1122
+ try:
1122
1123
 
1123
- # since it's possible to "multiply" the (node, path)
1124
- # we must make a clone of the path to prevent yield-then-use.
1125
- newg = s_common.agen((node, path.clone()))
1126
- async for item in subq.inline(runt, newg):
1127
- yield item
1124
+ # since it's possible to "multiply" the (node, path)
1125
+ # we must make a clone of the path to prevent yield-then-use.
1126
+ newg = s_common.agen((node, path.clone()))
1127
+ async for item in subq.inline(runt, newg):
1128
+ yield item
1128
1129
 
1129
- except s_stormctrl.StormBreak as e:
1130
- if (eitem := e.get('item')) is not None:
1131
- yield eitem
1132
- break
1130
+ except s_stormctrl.StormBreak as e:
1131
+ if (eitem := e.get('item')) is not None:
1132
+ yield eitem
1133
+ break
1133
1134
 
1134
- except s_stormctrl.StormContinue as e:
1135
- if (eitem := e.get('item')) is not None:
1136
- yield eitem
1137
- continue
1135
+ except s_stormctrl.StormContinue as e:
1136
+ if (eitem := e.get('item')) is not None:
1137
+ yield eitem
1138
+ continue
1138
1139
 
1139
- finally:
1140
- # for loops must yield per item they iterate over
1141
- await asyncio.sleep(0)
1140
+ finally:
1141
+ # for loops must yield per item they iterate over
1142
+ await asyncio.sleep(0)
1142
1143
 
1143
1144
  # no nodes and a runt safe value should execute once
1144
1145
  if node is None and self.kids[1].isRuntSafe(runt):
@@ -1155,56 +1156,57 @@ class ForLoop(Oper):
1155
1156
  if valu is None:
1156
1157
  valu = ()
1157
1158
 
1158
- async with contextlib.aclosing(s_coro.agen(valu)) as agen:
1159
- try:
1160
- agen, _ = await pullone(agen)
1161
- except TypeError:
1162
- styp = await s_stormtypes.totype(valu, basetypes=True)
1163
- mesg = f"'{styp}' object is not iterable: {s_common.trimText(repr(valu))}"
1164
- raise self.kids[1].addExcInfo(s_exc.StormRuntimeError(mesg=mesg, type=styp)) from None
1159
+ with s_scope.enter({'runt': runt}):
1160
+ async with contextlib.aclosing(s_coro.agen(valu)) as agen:
1161
+ try:
1162
+ agen, _ = await pullone(agen)
1163
+ except TypeError:
1164
+ styp = await s_stormtypes.totype(valu, basetypes=True)
1165
+ mesg = f"'{styp}' object is not iterable: {s_common.trimText(repr(valu))}"
1166
+ raise self.kids[1].addExcInfo(s_exc.StormRuntimeError(mesg=mesg, type=styp)) from None
1165
1167
 
1166
- async for item in agen:
1168
+ async for item in agen:
1167
1169
 
1168
- if isinstance(name, (list, tuple)):
1170
+ if isinstance(name, (list, tuple)):
1169
1171
 
1170
- try:
1171
- numitems = len(item)
1172
- except TypeError:
1173
- mesg = f'Number of items to unpack does not match the number of variables: {s_common.trimText(repr(item))}'
1174
- exc = s_exc.StormVarListError(mesg=mesg, names=name)
1175
- raise self.kids[1].addExcInfo(exc)
1172
+ try:
1173
+ numitems = len(item)
1174
+ except TypeError:
1175
+ mesg = f'Number of items to unpack does not match the number of variables: {s_common.trimText(repr(item))}'
1176
+ exc = s_exc.StormVarListError(mesg=mesg, names=name)
1177
+ raise self.kids[1].addExcInfo(exc)
1176
1178
 
1177
- if len(name) != numitems:
1178
- mesg = f'Number of items to unpack does not match the number of variables: {s_common.trimText(repr(item))}'
1179
- exc = s_exc.StormVarListError(mesg=mesg, names=name, numitems=numitems)
1180
- raise self.kids[1].addExcInfo(exc)
1179
+ if len(name) != numitems:
1180
+ mesg = f'Number of items to unpack does not match the number of variables: {s_common.trimText(repr(item))}'
1181
+ exc = s_exc.StormVarListError(mesg=mesg, names=name, numitems=numitems)
1182
+ raise self.kids[1].addExcInfo(exc)
1181
1183
 
1182
- if isinstance(item, s_stormtypes.Prim):
1183
- item = await item.value()
1184
+ if isinstance(item, s_stormtypes.Prim):
1185
+ item = await item.value()
1184
1186
 
1185
- for x, y in itertools.zip_longest(name, item):
1186
- await runt.setVar(x, y)
1187
+ for x, y in itertools.zip_longest(name, item):
1188
+ await runt.setVar(x, y)
1187
1189
 
1188
- else:
1189
- await runt.setVar(name, item)
1190
+ else:
1191
+ await runt.setVar(name, item)
1190
1192
 
1191
- try:
1192
- async for jtem in subq.inline(runt, s_common.agen()):
1193
- yield jtem
1193
+ try:
1194
+ async for jtem in subq.inline(runt, s_common.agen()):
1195
+ yield jtem
1194
1196
 
1195
- except s_stormctrl.StormBreak as e:
1196
- if (eitem := e.get('item')) is not None:
1197
- yield eitem
1198
- break
1197
+ except s_stormctrl.StormBreak as e:
1198
+ if (eitem := e.get('item')) is not None:
1199
+ yield eitem
1200
+ break
1199
1201
 
1200
- except s_stormctrl.StormContinue as e:
1201
- if (eitem := e.get('item')) is not None:
1202
- yield eitem
1203
- continue
1202
+ except s_stormctrl.StormContinue as e:
1203
+ if (eitem := e.get('item')) is not None:
1204
+ yield eitem
1205
+ continue
1204
1206
 
1205
- finally:
1206
- # for loops must yield per item they iterate over
1207
- await asyncio.sleep(0)
1207
+ finally:
1208
+ # for loops must yield per item they iterate over
1209
+ await asyncio.sleep(0)
1208
1210
 
1209
1211
  class WhileLoop(Oper):
1210
1212
 
synapse/lib/layer.py CHANGED
@@ -3338,6 +3338,33 @@ class Layer(s_nexus.Pusher):
3338
3338
  sode['nodedata'] = {name: s_msgpack.un(byts)}
3339
3339
  yield None, buid, sode
3340
3340
 
3341
+ async def setStorNodeProp(self, buid, prop, valu, meta):
3342
+ newp = self.core.model.reqProp(prop)
3343
+
3344
+ newp_valu = newp.type.norm(valu)[0]
3345
+ newp_name = newp.name
3346
+ newp_stortype = newp.type.stortype
3347
+ newp_formname = newp.form.name
3348
+
3349
+ set_edit = (EDIT_PROP_SET, (newp_name, newp_valu, None, newp_stortype), ())
3350
+ nodeedits = [(buid, newp_formname, [set_edit])]
3351
+
3352
+ _, changes = await self.saveNodeEdits(nodeedits, meta)
3353
+ return bool(changes[0][2])
3354
+
3355
+ async def delStorNodeProp(self, buid, prop, meta):
3356
+ pprop = self.core.model.reqProp(prop)
3357
+
3358
+ oldp_name = pprop.name
3359
+ oldp_formname = pprop.form.name
3360
+ oldp_stortype = pprop.type.stortype
3361
+
3362
+ del_edit = (EDIT_PROP_DEL, (oldp_name, None, oldp_stortype), ())
3363
+ nodeedits = [(buid, oldp_formname, [del_edit])]
3364
+
3365
+ _, changes = await self.saveNodeEdits(nodeedits, meta)
3366
+ return bool(changes[0][2])
3367
+
3341
3368
  async def storNodeEdits(self, nodeedits, meta):
3342
3369
 
3343
3370
  saveoff, results = await self.saveNodeEdits(nodeedits, meta)
synapse/lib/schemas.py CHANGED
@@ -734,6 +734,19 @@ _reqValidPkgdefSchema = {
734
734
  'desc': {'type': 'string'},
735
735
  'svciden': {'type': ['string', 'null'], 'pattern': s_config.re_iden},
736
736
  'onload': {'type': 'string'},
737
+ 'inits': {
738
+ 'type': 'object',
739
+ 'properties': {
740
+ 'key': {'type': 'string'},
741
+ 'versions': {
742
+ 'type': 'array',
743
+ 'items': {'$ref': '#/definitions/initdef'},
744
+ 'minItems': 1,
745
+ },
746
+ },
747
+ 'additionalProperties': True,
748
+ 'required': ['key', 'versions'],
749
+ },
737
750
  'author': {
738
751
  'type': 'object',
739
752
  'properties': {
@@ -807,6 +820,18 @@ _reqValidPkgdefSchema = {
807
820
  'additionalProperties': True,
808
821
  'required': ['name', 'storm']
809
822
  },
823
+ 'initdef': {
824
+ 'type': 'object',
825
+ 'properties': {
826
+ 'desc': {'type': 'string'},
827
+ 'inaugural': {'type': 'boolean', 'default': False},
828
+ 'name': {'type': 'string'},
829
+ 'query': {'type': 'string'},
830
+ 'version': {'type': 'integer', 'minimum': 0},
831
+ },
832
+ 'additionalProperties': False,
833
+ 'required': ['name', 'query', 'version']
834
+ },
810
835
  'apidef': {
811
836
  'type': 'object',
812
837
  'properties': {