synapse 2.218.1__py311-none-any.whl → 2.220.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 +113 -14
- synapse/daemon.py +2 -1
- synapse/data/__init__.py +4 -0
- synapse/data/lark/__init__.py +0 -0
- synapse/data/lark/imap.lark +8 -0
- synapse/exc.py +2 -0
- synapse/lib/ast.py +86 -84
- synapse/lib/json.py +6 -5
- synapse/lib/layer.py +27 -0
- synapse/lib/link.py +49 -50
- synapse/lib/parser.py +3 -5
- synapse/lib/schemas.py +25 -0
- synapse/lib/storm.py +1 -0
- synapse/lib/stormlib/imap.py +476 -35
- synapse/lib/stormtypes.py +177 -2
- synapse/lib/version.py +2 -2
- synapse/models/inet.py +3 -0
- synapse/tests/files/stormpkg/badinits.yaml +12 -0
- synapse/tests/files/stormpkg/testpkg.yaml +12 -0
- synapse/tests/test_lib_grammar.py +2 -4
- synapse/tests/test_lib_json.py +29 -0
- synapse/tests/test_lib_layer.py +119 -0
- synapse/tests/test_lib_storm.py +184 -1
- synapse/tests/test_lib_stormlib_imap.py +1307 -230
- synapse/tests/test_lib_stormtypes.py +157 -0
- synapse/tests/test_model_inet.py +3 -0
- synapse/tests/test_telepath.py +31 -0
- synapse/tests/test_tools_genpkg.py +4 -0
- synapse/tests/utils.py +1 -1
- synapse/tools/genpkg.py +9 -0
- synapse/utils/stormcov/plugin.py +2 -5
- {synapse-2.218.1.dist-info → synapse-2.220.0.dist-info}/METADATA +2 -3
- {synapse-2.218.1.dist-info → synapse-2.220.0.dist-info}/RECORD +37 -34
- /synapse/{lib → data/lark}/storm.lark +0 -0
- {synapse-2.218.1.dist-info → synapse-2.220.0.dist-info}/WHEEL +0 -0
- {synapse-2.218.1.dist-info → synapse-2.220.0.dist-info}/licenses/LICENSE +0 -0
- {synapse-2.218.1.dist-info → synapse-2.220.0.dist-info}/top_level.txt +0 -0
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
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
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
|
|
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
|
-
|
|
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/data/__init__.py
CHANGED
|
@@ -29,5 +29,9 @@ def getJSON(name):
|
|
|
29
29
|
with s_datfile.openDatFile(f'synapse.data/{name}.json') as fd:
|
|
30
30
|
return s_json.load(fd)
|
|
31
31
|
|
|
32
|
+
def getLark(name):
|
|
33
|
+
with s_datfile.openDatFile(f'synapse.data.lark/{name}.lark') as larkf:
|
|
34
|
+
return larkf.read().decode()
|
|
35
|
+
|
|
32
36
|
def path(*names):
|
|
33
37
|
return s_common.genpath(dirname, *names)
|
|
File without changes
|
synapse/exc.py
CHANGED
synapse/lib/ast.py
CHANGED
|
@@ -1081,64 +1081,65 @@ class ForLoop(Oper):
|
|
|
1081
1081
|
if valu is None:
|
|
1082
1082
|
valu = ()
|
|
1083
1083
|
|
|
1084
|
-
|
|
1084
|
+
with s_scope.enter({'runt': runt}):
|
|
1085
|
+
async with contextlib.aclosing(s_coro.agen(valu)) as agen:
|
|
1085
1086
|
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
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
|
-
|
|
1094
|
+
async for item in agen:
|
|
1094
1095
|
|
|
1095
|
-
|
|
1096
|
+
if isinstance(name, (list, tuple)):
|
|
1096
1097
|
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
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
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
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
|
-
|
|
1110
|
-
|
|
1110
|
+
if isinstance(item, s_stormtypes.Prim):
|
|
1111
|
+
item = await item.value()
|
|
1111
1112
|
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
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
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
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
|
-
|
|
1122
|
+
try:
|
|
1122
1123
|
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
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
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1130
|
+
except s_stormctrl.StormBreak as e:
|
|
1131
|
+
if (eitem := e.get('item')) is not None:
|
|
1132
|
+
yield eitem
|
|
1133
|
+
break
|
|
1133
1134
|
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1135
|
+
except s_stormctrl.StormContinue as e:
|
|
1136
|
+
if (eitem := e.get('item')) is not None:
|
|
1137
|
+
yield eitem
|
|
1138
|
+
continue
|
|
1138
1139
|
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
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
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
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
|
-
|
|
1168
|
+
async for item in agen:
|
|
1167
1169
|
|
|
1168
|
-
|
|
1170
|
+
if isinstance(name, (list, tuple)):
|
|
1169
1171
|
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
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
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
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
|
-
|
|
1183
|
-
|
|
1184
|
+
if isinstance(item, s_stormtypes.Prim):
|
|
1185
|
+
item = await item.value()
|
|
1184
1186
|
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
+
for x, y in itertools.zip_longest(name, item):
|
|
1188
|
+
await runt.setVar(x, y)
|
|
1187
1189
|
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
+
else:
|
|
1191
|
+
await runt.setVar(name, item)
|
|
1190
1192
|
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1193
|
+
try:
|
|
1194
|
+
async for jtem in subq.inline(runt, s_common.agen()):
|
|
1195
|
+
yield jtem
|
|
1194
1196
|
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1197
|
+
except s_stormctrl.StormBreak as e:
|
|
1198
|
+
if (eitem := e.get('item')) is not None:
|
|
1199
|
+
yield eitem
|
|
1200
|
+
break
|
|
1199
1201
|
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1202
|
+
except s_stormctrl.StormContinue as e:
|
|
1203
|
+
if (eitem := e.get('item')) is not None:
|
|
1204
|
+
yield eitem
|
|
1205
|
+
continue
|
|
1204
1206
|
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
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/json.py
CHANGED
|
@@ -88,12 +88,13 @@ def _dumps(obj, sort_keys=False, indent=False, default=None, newline=False):
|
|
|
88
88
|
mesg = 'Object of type bytes is not JSON serializable'
|
|
89
89
|
raise s_exc.MustBeJsonSafe(mesg=mesg)
|
|
90
90
|
|
|
91
|
-
# Raw strings have to be double-quoted. This is because the default behavior for `yyjson.Document`
|
|
92
|
-
# is to attempt to parse the string as a serialized JSON string into objects, so we escape string
|
|
93
|
-
# values so we can get the JSON encoded string as output.
|
|
94
91
|
if isinstance(obj, str) and obj not in ('null', 'true', 'false'):
|
|
95
|
-
#
|
|
96
|
-
|
|
92
|
+
# Raw strings have to be double-quoted. This is because the default behavior for `yyjson.Document` is to attempt
|
|
93
|
+
# to parse the string as a serialized JSON string into objects. Instead of trying to manually escape the string,
|
|
94
|
+
# we wrap it in a list, serialize it, and then strip off the leading/trailing [] so we can get the JSON encoded
|
|
95
|
+
# string as output.
|
|
96
|
+
doc = yyjson.Document([obj], default=default, flags=rflags)
|
|
97
|
+
return doc.dumps(flags=wflags)[1:-1].encode()
|
|
97
98
|
|
|
98
99
|
doc = yyjson.Document(obj, default=default, flags=rflags)
|
|
99
100
|
return doc.dumps(flags=wflags).encode()
|
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/link.py
CHANGED
|
@@ -18,34 +18,6 @@ import synapse.lib.msgpack as s_msgpack
|
|
|
18
18
|
READSIZE = 16 * s_const.mebibyte
|
|
19
19
|
MAXWRITE = 64 * s_const.mebibyte
|
|
20
20
|
|
|
21
|
-
async def connect(host, port, ssl=None, hostname=None, linkinfo=None):
|
|
22
|
-
'''
|
|
23
|
-
Async connect and return a Link().
|
|
24
|
-
'''
|
|
25
|
-
info = {'host': host, 'port': port, 'ssl': ssl, 'hostname': hostname, 'tls': bool(ssl)}
|
|
26
|
-
if linkinfo is not None:
|
|
27
|
-
info.update(linkinfo)
|
|
28
|
-
|
|
29
|
-
ssl = info.get('ssl')
|
|
30
|
-
hostname = info.get('hostname')
|
|
31
|
-
|
|
32
|
-
reader, writer = await asyncio.open_connection(host, port, ssl=ssl, server_hostname=hostname)
|
|
33
|
-
return await Link.anit(reader, writer, info=info)
|
|
34
|
-
|
|
35
|
-
async def listen(host, port, onlink, ssl=None):
|
|
36
|
-
'''
|
|
37
|
-
Listen on the given host/port and fire onlink(Link).
|
|
38
|
-
|
|
39
|
-
Returns a server object that contains the listening sockets
|
|
40
|
-
'''
|
|
41
|
-
async def onconn(reader, writer):
|
|
42
|
-
info = {'tls': bool(ssl)}
|
|
43
|
-
link = await Link.anit(reader, writer, info=info)
|
|
44
|
-
link.schedCoro(onlink(link))
|
|
45
|
-
|
|
46
|
-
server = await asyncio.start_server(onconn, host=host, port=port, ssl=ssl)
|
|
47
|
-
return server
|
|
48
|
-
|
|
49
21
|
async def unixlisten(path, onlink):
|
|
50
22
|
'''
|
|
51
23
|
Start an PF_UNIX server listening on the given path.
|
|
@@ -247,30 +219,9 @@ class Link(s_base.Base):
|
|
|
247
219
|
offs = 0
|
|
248
220
|
size = len(byts)
|
|
249
221
|
|
|
250
|
-
async with self._txlock:
|
|
251
|
-
|
|
252
|
-
while offs < size:
|
|
253
|
-
|
|
254
|
-
self.writer.write(byts[offs:offs + MAXWRITE])
|
|
255
|
-
offs += MAXWRITE
|
|
256
|
-
|
|
257
|
-
await self.writer.drain()
|
|
258
|
-
|
|
259
|
-
async def tx(self, mesg):
|
|
260
|
-
'''
|
|
261
|
-
Async transmit routine which will wait for writer drain().
|
|
262
|
-
'''
|
|
263
|
-
if self.isfini:
|
|
264
|
-
raise s_exc.IsFini()
|
|
265
|
-
|
|
266
|
-
offs = 0
|
|
267
|
-
byts = s_msgpack.en(mesg)
|
|
268
|
-
size = len(byts)
|
|
269
|
-
|
|
270
222
|
async with self._txlock:
|
|
271
223
|
|
|
272
224
|
try:
|
|
273
|
-
|
|
274
225
|
while offs < size:
|
|
275
226
|
|
|
276
227
|
self.writer.write(byts[offs:offs + MAXWRITE])
|
|
@@ -287,6 +238,16 @@ class Link(s_base.Base):
|
|
|
287
238
|
|
|
288
239
|
raise
|
|
289
240
|
|
|
241
|
+
async def tx(self, mesg):
|
|
242
|
+
'''
|
|
243
|
+
Async transmit routine which will wait for writer drain().
|
|
244
|
+
'''
|
|
245
|
+
if self.isfini:
|
|
246
|
+
raise s_exc.IsFini()
|
|
247
|
+
|
|
248
|
+
byts = await self.pack(mesg)
|
|
249
|
+
await self.send(byts)
|
|
250
|
+
|
|
290
251
|
def txfini(self):
|
|
291
252
|
self.sock.shutdown(1)
|
|
292
253
|
|
|
@@ -353,6 +314,44 @@ class Link(s_base.Base):
|
|
|
353
314
|
|
|
354
315
|
def feed(self, byts):
|
|
355
316
|
'''
|
|
356
|
-
Used by
|
|
317
|
+
Used by rx() to unpack messages from bytes.
|
|
357
318
|
'''
|
|
358
319
|
return self.unpk.feed(byts)
|
|
320
|
+
|
|
321
|
+
async def pack(self, mesg):
|
|
322
|
+
'''
|
|
323
|
+
Used by tx() to pack messages into bytes
|
|
324
|
+
'''
|
|
325
|
+
return s_msgpack.en(mesg)
|
|
326
|
+
|
|
327
|
+
async def connect(host, port, ssl=None, hostname=None, linkinfo=None, linkcls=Link):
|
|
328
|
+
'''
|
|
329
|
+
Async connect and return a <linkcls>.
|
|
330
|
+
'''
|
|
331
|
+
assert issubclass(linkcls, Link)
|
|
332
|
+
|
|
333
|
+
info = {'host': host, 'port': port, 'ssl': ssl, 'hostname': hostname, 'tls': bool(ssl)}
|
|
334
|
+
if linkinfo is not None:
|
|
335
|
+
info.update(linkinfo)
|
|
336
|
+
|
|
337
|
+
ssl = info.get('ssl')
|
|
338
|
+
hostname = info.get('hostname')
|
|
339
|
+
|
|
340
|
+
reader, writer = await asyncio.open_connection(host, port, ssl=ssl, server_hostname=hostname)
|
|
341
|
+
return await linkcls.anit(reader, writer, info=info)
|
|
342
|
+
|
|
343
|
+
async def listen(host, port, onlink, ssl=None, linkcls=Link):
|
|
344
|
+
'''
|
|
345
|
+
Listen on the given host/port and fire onlink(<linkcls>).
|
|
346
|
+
|
|
347
|
+
Returns a server object that contains the listening sockets
|
|
348
|
+
'''
|
|
349
|
+
assert issubclass(linkcls, Link)
|
|
350
|
+
|
|
351
|
+
async def onconn(reader, writer):
|
|
352
|
+
info = {'tls': bool(ssl)}
|
|
353
|
+
link = await linkcls.anit(reader, writer, info=info)
|
|
354
|
+
link.schedCoro(onlink(link))
|
|
355
|
+
|
|
356
|
+
server = await asyncio.start_server(onconn, host=host, port=port, ssl=ssl)
|
|
357
|
+
return server
|
synapse/lib/parser.py
CHANGED
|
@@ -6,16 +6,16 @@ import lark # type: ignore
|
|
|
6
6
|
import regex # type: ignore
|
|
7
7
|
|
|
8
8
|
import synapse.exc as s_exc
|
|
9
|
+
import synapse.data as s_data
|
|
9
10
|
import synapse.common as s_common
|
|
10
11
|
|
|
11
12
|
import synapse.lib.ast as s_ast
|
|
12
13
|
import synapse.lib.coro as s_coro
|
|
13
14
|
import synapse.lib.cache as s_cache
|
|
14
|
-
import synapse.lib.datfile as s_datfile
|
|
15
15
|
|
|
16
16
|
# TL;DR: *rules* are the internal nodes of an abstract syntax tree (AST), *terminals* are the leaves
|
|
17
17
|
|
|
18
|
-
# Note: this file is coupled strongly to synapse/
|
|
18
|
+
# Note: this file is coupled strongly to synapse/data/lark/storm.lark. Any changes to that file will probably require
|
|
19
19
|
# changes here
|
|
20
20
|
|
|
21
21
|
# For easier-to-understand syntax errors
|
|
@@ -475,9 +475,7 @@ class AstConverter(lark.Transformer):
|
|
|
475
475
|
kids[0].reverseLift(astinfo)
|
|
476
476
|
return kids[0]
|
|
477
477
|
|
|
478
|
-
|
|
479
|
-
_grammar = larkf.read().decode()
|
|
480
|
-
|
|
478
|
+
_grammar = s_data.getLark('storm')
|
|
481
479
|
LarkParser = lark.Lark(_grammar, regex=True, start=['query', 'lookup', 'cmdrargs', 'evalvalu', 'search'],
|
|
482
480
|
maybe_placeholders=False, propagate_positions=True, parser='lalr')
|
|
483
481
|
|