synapse 2.154.1__py311-none-any.whl → 2.156.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/cmds/cortex.py +2 -14
- synapse/common.py +13 -36
- synapse/cortex.py +15 -508
- synapse/lib/ast.py +215 -22
- synapse/lib/cell.py +35 -8
- synapse/lib/certdir.py +11 -0
- synapse/lib/cmdr.py +0 -5
- synapse/lib/gis.py +2 -2
- synapse/lib/httpapi.py +14 -43
- synapse/lib/layer.py +64 -201
- synapse/lib/lmdbslab.py +11 -0
- synapse/lib/node.py +1 -3
- synapse/lib/parser.py +10 -0
- synapse/lib/slabseqn.py +2 -1
- synapse/lib/snap.py +121 -21
- synapse/lib/spooled.py +9 -0
- synapse/lib/storm.lark +23 -6
- synapse/lib/storm.py +16 -339
- synapse/lib/storm_format.py +5 -0
- synapse/lib/stormhttp.py +10 -1
- synapse/lib/stormlib/gen.py +1 -2
- synapse/lib/stormlib/gis.py +41 -0
- synapse/lib/stormlib/graph.py +2 -1
- synapse/lib/stormlib/stats.py +21 -2
- synapse/lib/stormlib/storm.py +16 -1
- synapse/lib/stormtypes.py +244 -16
- synapse/lib/types.py +16 -2
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +118 -25
- synapse/models/base.py +2 -2
- synapse/models/inet.py +60 -30
- synapse/models/infotech.py +130 -8
- synapse/models/orgs.py +3 -0
- synapse/models/proj.py +3 -0
- synapse/models/risk.py +24 -6
- synapse/models/syn.py +0 -38
- synapse/tests/test_cmds_cortex.py +1 -1
- synapse/tests/test_cortex.py +70 -338
- synapse/tests/test_lib_agenda.py +19 -54
- synapse/tests/test_lib_aha.py +97 -0
- synapse/tests/test_lib_ast.py +596 -0
- synapse/tests/test_lib_grammar.py +30 -10
- synapse/tests/test_lib_httpapi.py +33 -49
- synapse/tests/test_lib_layer.py +19 -234
- synapse/tests/test_lib_lmdbslab.py +22 -0
- synapse/tests/test_lib_snap.py +9 -0
- synapse/tests/test_lib_spooled.py +4 -0
- synapse/tests/test_lib_storm.py +16 -309
- synapse/tests/test_lib_stormlib_gis.py +21 -0
- synapse/tests/test_lib_stormlib_stats.py +107 -20
- synapse/tests/test_lib_stormlib_storm.py +25 -0
- synapse/tests/test_lib_stormtypes.py +253 -8
- synapse/tests/test_lib_types.py +40 -0
- synapse/tests/test_lib_view.py +6 -13
- synapse/tests/test_model_base.py +1 -1
- synapse/tests/test_model_inet.py +15 -0
- synapse/tests/test_model_infotech.py +110 -0
- synapse/tests/test_model_orgs.py +10 -0
- synapse/tests/test_model_person.py +0 -3
- synapse/tests/test_model_proj.py +2 -1
- synapse/tests/test_model_risk.py +24 -0
- synapse/tests/test_model_syn.py +20 -34
- synapse/tests/test_tools_csvtool.py +2 -1
- synapse/tests/test_tools_feed.py +4 -30
- synapse/tools/csvtool.py +2 -1
- {synapse-2.154.1.dist-info → synapse-2.156.0.dist-info}/METADATA +9 -9
- {synapse-2.154.1.dist-info → synapse-2.156.0.dist-info}/RECORD +70 -72
- {synapse-2.154.1.dist-info → synapse-2.156.0.dist-info}/WHEEL +1 -1
- synapse/cmds/cron.py +0 -726
- synapse/cmds/trigger.py +0 -319
- synapse/tests/test_cmds_cron.py +0 -453
- synapse/tests/test_cmds_trigger.py +0 -176
- {synapse-2.154.1.dist-info → synapse-2.156.0.dist-info}/LICENSE +0 -0
- {synapse-2.154.1.dist-info → synapse-2.156.0.dist-info}/top_level.txt +0 -0
synapse/lib/layer.py
CHANGED
|
@@ -170,19 +170,6 @@ class LayerApi(s_cell.CellApi):
|
|
|
170
170
|
async for item in self.layr.syncNodeEdits2(offs, wait=wait):
|
|
171
171
|
yield item
|
|
172
172
|
|
|
173
|
-
async def splices(self, offs=None, size=None):
|
|
174
|
-
'''
|
|
175
|
-
This API is deprecated.
|
|
176
|
-
|
|
177
|
-
Yield (offs, splice) tuples from the nodeedit log starting from the given offset.
|
|
178
|
-
|
|
179
|
-
Nodeedits will be flattened into splices before being yielded.
|
|
180
|
-
'''
|
|
181
|
-
s_common.deprdate('Layer.splices() telepath API', s_common._splicedepr)
|
|
182
|
-
await self._reqUserAllowed(self.liftperm)
|
|
183
|
-
async for item in self.layr.splices(offs=offs, size=size):
|
|
184
|
-
yield item
|
|
185
|
-
|
|
186
173
|
async def getEditIndx(self):
|
|
187
174
|
'''
|
|
188
175
|
Returns what will be the *next* nodeedit log index.
|
|
@@ -2023,17 +2010,14 @@ class Layer(s_nexus.Pusher):
|
|
|
2023
2010
|
ret['totalsize'] = await self.getLayerSize()
|
|
2024
2011
|
return ret
|
|
2025
2012
|
|
|
2026
|
-
async def truncate(self):
|
|
2027
|
-
self._reqNotReadOnly()
|
|
2028
|
-
return await self._push('layer:truncate')
|
|
2029
|
-
|
|
2030
2013
|
@s_nexus.Pusher.onPush('layer:truncate')
|
|
2031
2014
|
async def _truncate(self):
|
|
2032
2015
|
'''
|
|
2033
2016
|
Nuke all the contents in the layer, leaving an empty layer
|
|
2034
2017
|
NOTE: This internal API is deprecated but is kept for Nexus event backward compatibility
|
|
2035
2018
|
'''
|
|
2036
|
-
|
|
2019
|
+
# TODO: Remove this in 3.0.0
|
|
2020
|
+
s_common.deprecated('layer:truncate Nexus handler', curv='2.156.0')
|
|
2037
2021
|
|
|
2038
2022
|
self.dirty.clear()
|
|
2039
2023
|
self.buidcache.clear()
|
|
@@ -2044,8 +2028,6 @@ class Layer(s_nexus.Pusher):
|
|
|
2044
2028
|
|
|
2045
2029
|
await self._initLayerStorage()
|
|
2046
2030
|
|
|
2047
|
-
# async def wipe(self, meta): ...
|
|
2048
|
-
|
|
2049
2031
|
async def iterWipeNodeEdits(self):
|
|
2050
2032
|
|
|
2051
2033
|
await self._saveDirtySodes()
|
|
@@ -2914,6 +2896,7 @@ class Layer(s_nexus.Pusher):
|
|
|
2914
2896
|
abrv = self.tagabrv.bytsToAbrv(tagname.encode())
|
|
2915
2897
|
if formname is not None:
|
|
2916
2898
|
abrv += self.getPropAbrv(formname, None)
|
|
2899
|
+
return self.layrslab.count(abrv, db=self.bytag)
|
|
2917
2900
|
|
|
2918
2901
|
except s_exc.NoSuchAbrv:
|
|
2919
2902
|
return 0
|
|
@@ -2931,6 +2914,44 @@ class Layer(s_nexus.Pusher):
|
|
|
2931
2914
|
|
|
2932
2915
|
return await self.layrslab.countByPref(abrv, db=self.byprop, maxsize=maxsize)
|
|
2933
2916
|
|
|
2917
|
+
def getPropValuCount(self, formname, propname, stortype, valu):
|
|
2918
|
+
try:
|
|
2919
|
+
abrv = self.getPropAbrv(formname, propname)
|
|
2920
|
+
except s_exc.NoSuchAbrv:
|
|
2921
|
+
return 0
|
|
2922
|
+
|
|
2923
|
+
if stortype & 0x8000:
|
|
2924
|
+
stortype = STOR_TYPE_MSGP
|
|
2925
|
+
|
|
2926
|
+
count = 0
|
|
2927
|
+
for indx in self.getStorIndx(stortype, valu):
|
|
2928
|
+
count += self.layrslab.count(abrv + indx, db=self.byprop)
|
|
2929
|
+
|
|
2930
|
+
return count
|
|
2931
|
+
|
|
2932
|
+
async def getPropArrayCount(self, formname, propname=None):
|
|
2933
|
+
'''
|
|
2934
|
+
Return the number of invidiual value rows in the layer for the given array form/prop.
|
|
2935
|
+
'''
|
|
2936
|
+
try:
|
|
2937
|
+
abrv = self.getPropAbrv(formname, propname)
|
|
2938
|
+
except s_exc.NoSuchAbrv:
|
|
2939
|
+
return 0
|
|
2940
|
+
|
|
2941
|
+
return await self.layrslab.countByPref(abrv, db=self.byarray)
|
|
2942
|
+
|
|
2943
|
+
def getPropArrayValuCount(self, formname, propname, stortype, valu):
|
|
2944
|
+
try:
|
|
2945
|
+
abrv = self.getPropAbrv(formname, propname)
|
|
2946
|
+
except s_exc.NoSuchAbrv:
|
|
2947
|
+
return 0
|
|
2948
|
+
|
|
2949
|
+
count = 0
|
|
2950
|
+
for indx in self.getStorIndx(stortype, valu):
|
|
2951
|
+
count += self.layrslab.count(abrv + indx, db=self.byarray)
|
|
2952
|
+
|
|
2953
|
+
return count
|
|
2954
|
+
|
|
2934
2955
|
async def getUnivPropCount(self, propname, maxsize=None):
|
|
2935
2956
|
'''
|
|
2936
2957
|
Return the number of universal property rows in the layer for the given prop.
|
|
@@ -2942,6 +2963,29 @@ class Layer(s_nexus.Pusher):
|
|
|
2942
2963
|
|
|
2943
2964
|
return await self.layrslab.countByPref(abrv, db=self.byprop, maxsize=maxsize)
|
|
2944
2965
|
|
|
2966
|
+
async def getTagPropCount(self, form, tag, prop):
|
|
2967
|
+
'''
|
|
2968
|
+
Return the number of property rows in the layer for the given form/tag/prop.
|
|
2969
|
+
'''
|
|
2970
|
+
try:
|
|
2971
|
+
abrv = self.getTagPropAbrv(form, tag, prop)
|
|
2972
|
+
except s_exc.NoSuchAbrv:
|
|
2973
|
+
return 0
|
|
2974
|
+
|
|
2975
|
+
return await self.layrslab.countByPref(abrv, db=self.bytagprop)
|
|
2976
|
+
|
|
2977
|
+
def getTagPropValuCount(self, form, tag, prop, stortype, valu):
|
|
2978
|
+
try:
|
|
2979
|
+
abrv = self.getTagPropAbrv(form, tag, prop)
|
|
2980
|
+
except s_exc.NoSuchAbrv:
|
|
2981
|
+
return 0
|
|
2982
|
+
|
|
2983
|
+
count = 0
|
|
2984
|
+
for indx in self.getStorIndx(stortype, valu):
|
|
2985
|
+
count += self.layrslab.count(abrv + indx, db=self.bytagprop)
|
|
2986
|
+
|
|
2987
|
+
return count
|
|
2988
|
+
|
|
2945
2989
|
async def liftByTag(self, tag, form=None, reverse=False):
|
|
2946
2990
|
|
|
2947
2991
|
try:
|
|
@@ -4151,76 +4195,6 @@ class Layer(s_nexus.Pusher):
|
|
|
4151
4195
|
yield buid, s_msgpack.un(byts)
|
|
4152
4196
|
await asyncio.sleep(0)
|
|
4153
4197
|
|
|
4154
|
-
async def splices(self, offs=None, size=None):
|
|
4155
|
-
'''
|
|
4156
|
-
This API is deprecated.
|
|
4157
|
-
|
|
4158
|
-
Yield (offs, splice) tuples from the nodeedit log starting from the given offset.
|
|
4159
|
-
|
|
4160
|
-
Nodeedits will be flattened into splices before being yielded.
|
|
4161
|
-
'''
|
|
4162
|
-
s_common.deprdate('Layer.splices() API', s_common._splicedepr)
|
|
4163
|
-
if not self.logedits:
|
|
4164
|
-
return
|
|
4165
|
-
|
|
4166
|
-
if offs is None:
|
|
4167
|
-
offs = (0, 0, 0)
|
|
4168
|
-
|
|
4169
|
-
if size is not None:
|
|
4170
|
-
|
|
4171
|
-
count = 0
|
|
4172
|
-
async for offset, nodeedits, meta in self.iterNodeEditLog(offs[0]):
|
|
4173
|
-
async for splice in self.makeSplices(offset, nodeedits, meta):
|
|
4174
|
-
|
|
4175
|
-
if splice[0] < offs:
|
|
4176
|
-
continue
|
|
4177
|
-
|
|
4178
|
-
if count >= size:
|
|
4179
|
-
return
|
|
4180
|
-
|
|
4181
|
-
yield splice
|
|
4182
|
-
count = count + 1
|
|
4183
|
-
else:
|
|
4184
|
-
async for offset, nodeedits, meta in self.iterNodeEditLog(offs[0]):
|
|
4185
|
-
async for splice in self.makeSplices(offset, nodeedits, meta):
|
|
4186
|
-
|
|
4187
|
-
if splice[0] < offs:
|
|
4188
|
-
continue
|
|
4189
|
-
|
|
4190
|
-
yield splice
|
|
4191
|
-
|
|
4192
|
-
async def splicesBack(self, offs=None, size=None):
|
|
4193
|
-
|
|
4194
|
-
s_common.deprdate('Layer.splicesBack() API', s_common._splicedepr)
|
|
4195
|
-
if not self.logedits:
|
|
4196
|
-
return
|
|
4197
|
-
|
|
4198
|
-
if offs is None:
|
|
4199
|
-
offs = (await self.getEditIndx(), 0, 0)
|
|
4200
|
-
|
|
4201
|
-
if size is not None:
|
|
4202
|
-
|
|
4203
|
-
count = 0
|
|
4204
|
-
async for offset, nodeedits, meta in self.iterNodeEditLogBack(offs[0]):
|
|
4205
|
-
async for splice in self.makeSplices(offset, nodeedits, meta, reverse=True):
|
|
4206
|
-
|
|
4207
|
-
if splice[0] > offs:
|
|
4208
|
-
continue
|
|
4209
|
-
|
|
4210
|
-
if count >= size:
|
|
4211
|
-
return
|
|
4212
|
-
|
|
4213
|
-
yield splice
|
|
4214
|
-
count += 1
|
|
4215
|
-
else:
|
|
4216
|
-
async for offset, nodeedits, meta in self.iterNodeEditLogBack(offs[0]):
|
|
4217
|
-
async for splice in self.makeSplices(offset, nodeedits, meta, reverse=True):
|
|
4218
|
-
|
|
4219
|
-
if splice[0] > offs:
|
|
4220
|
-
continue
|
|
4221
|
-
|
|
4222
|
-
yield splice
|
|
4223
|
-
|
|
4224
4198
|
async def iterNodeEditLog(self, offs=0):
|
|
4225
4199
|
'''
|
|
4226
4200
|
Iterate the node edit log and yield (offs, edits, meta) tuples.
|
|
@@ -4312,117 +4286,6 @@ class Layer(s_nexus.Pusher):
|
|
|
4312
4286
|
if count % 1000 == 0:
|
|
4313
4287
|
yield (curoff, (None, None, EDIT_PROGRESS, (), ()))
|
|
4314
4288
|
|
|
4315
|
-
async def makeSplices(self, offs, nodeedits, meta, reverse=False):
|
|
4316
|
-
'''
|
|
4317
|
-
Flatten a set of nodeedits into splices.
|
|
4318
|
-
'''
|
|
4319
|
-
if meta is None:
|
|
4320
|
-
meta = {}
|
|
4321
|
-
|
|
4322
|
-
user = meta.get('user')
|
|
4323
|
-
time = meta.get('time')
|
|
4324
|
-
prov = meta.get('prov')
|
|
4325
|
-
|
|
4326
|
-
if reverse:
|
|
4327
|
-
nodegenr = reversed(list(enumerate(nodeedits)))
|
|
4328
|
-
else:
|
|
4329
|
-
nodegenr = enumerate(nodeedits)
|
|
4330
|
-
|
|
4331
|
-
for nodeoffs, (buid, form, edits) in nodegenr:
|
|
4332
|
-
|
|
4333
|
-
formvalu = None
|
|
4334
|
-
|
|
4335
|
-
if reverse:
|
|
4336
|
-
editgenr = reversed(list(enumerate(edits)))
|
|
4337
|
-
else:
|
|
4338
|
-
editgenr = enumerate(edits)
|
|
4339
|
-
|
|
4340
|
-
for editoffs, (edit, info, _) in editgenr:
|
|
4341
|
-
|
|
4342
|
-
if edit in (EDIT_NODEDATA_SET, EDIT_NODEDATA_DEL, EDIT_EDGE_ADD, EDIT_EDGE_DEL):
|
|
4343
|
-
continue
|
|
4344
|
-
|
|
4345
|
-
spliceoffs = (offs, nodeoffs, editoffs)
|
|
4346
|
-
|
|
4347
|
-
props = {
|
|
4348
|
-
'time': time,
|
|
4349
|
-
'user': user,
|
|
4350
|
-
}
|
|
4351
|
-
|
|
4352
|
-
if prov is not None:
|
|
4353
|
-
props['prov'] = prov
|
|
4354
|
-
|
|
4355
|
-
if edit == EDIT_NODE_ADD:
|
|
4356
|
-
formvalu, stortype = info
|
|
4357
|
-
props['ndef'] = (form, formvalu)
|
|
4358
|
-
|
|
4359
|
-
yield (spliceoffs, ('node:add', props))
|
|
4360
|
-
continue
|
|
4361
|
-
|
|
4362
|
-
if edit == EDIT_NODE_DEL:
|
|
4363
|
-
formvalu, stortype = info
|
|
4364
|
-
props['ndef'] = (form, formvalu)
|
|
4365
|
-
|
|
4366
|
-
yield (spliceoffs, ('node:del', props))
|
|
4367
|
-
continue
|
|
4368
|
-
|
|
4369
|
-
if formvalu is None:
|
|
4370
|
-
formvalu = await self.getNodeValu(buid)
|
|
4371
|
-
|
|
4372
|
-
props['ndef'] = (form, formvalu)
|
|
4373
|
-
|
|
4374
|
-
if edit == EDIT_PROP_SET:
|
|
4375
|
-
prop, valu, oldv, stortype = info
|
|
4376
|
-
props['prop'] = prop
|
|
4377
|
-
props['valu'] = valu
|
|
4378
|
-
props['oldv'] = oldv
|
|
4379
|
-
|
|
4380
|
-
yield (spliceoffs, ('prop:set', props))
|
|
4381
|
-
continue
|
|
4382
|
-
|
|
4383
|
-
if edit == EDIT_PROP_DEL:
|
|
4384
|
-
prop, valu, stortype = info
|
|
4385
|
-
props['prop'] = prop
|
|
4386
|
-
props['valu'] = valu
|
|
4387
|
-
|
|
4388
|
-
yield (spliceoffs, ('prop:del', props))
|
|
4389
|
-
continue
|
|
4390
|
-
|
|
4391
|
-
if edit == EDIT_TAG_SET:
|
|
4392
|
-
tag, valu, oldv = info
|
|
4393
|
-
props['tag'] = tag
|
|
4394
|
-
props['valu'] = valu
|
|
4395
|
-
props['oldv'] = oldv
|
|
4396
|
-
|
|
4397
|
-
yield (spliceoffs, ('tag:add', props))
|
|
4398
|
-
continue
|
|
4399
|
-
|
|
4400
|
-
if edit == EDIT_TAG_DEL:
|
|
4401
|
-
tag, valu = info
|
|
4402
|
-
props['tag'] = tag
|
|
4403
|
-
props['valu'] = valu
|
|
4404
|
-
|
|
4405
|
-
yield (spliceoffs, ('tag:del', props))
|
|
4406
|
-
continue
|
|
4407
|
-
|
|
4408
|
-
if edit == EDIT_TAGPROP_SET:
|
|
4409
|
-
tag, prop, valu, oldv, stortype = info
|
|
4410
|
-
props['tag'] = tag
|
|
4411
|
-
props['prop'] = prop
|
|
4412
|
-
props['valu'] = valu
|
|
4413
|
-
props['oldv'] = oldv
|
|
4414
|
-
|
|
4415
|
-
yield (spliceoffs, ('tag:prop:set', props))
|
|
4416
|
-
continue
|
|
4417
|
-
|
|
4418
|
-
if edit == EDIT_TAGPROP_DEL:
|
|
4419
|
-
tag, prop, valu, stortype = info
|
|
4420
|
-
props['tag'] = tag
|
|
4421
|
-
props['prop'] = prop
|
|
4422
|
-
props['valu'] = valu
|
|
4423
|
-
|
|
4424
|
-
yield (spliceoffs, ('tag:prop:del', props))
|
|
4425
|
-
|
|
4426
4289
|
@contextlib.asynccontextmanager
|
|
4427
4290
|
async def getNodeEditWindow(self):
|
|
4428
4291
|
if not self.logedits:
|
synapse/lib/lmdbslab.py
CHANGED
|
@@ -1196,6 +1196,17 @@ class Slab(s_base.Base):
|
|
|
1196
1196
|
with self.xact.cursor(db=realdb) as curs:
|
|
1197
1197
|
return curs.set_key_dup(lkey, lval)
|
|
1198
1198
|
|
|
1199
|
+
def count(self, lkey, db=None):
|
|
1200
|
+
realdb, dupsort = self.dbnames[db]
|
|
1201
|
+
with self.xact.cursor(db=realdb) as curs:
|
|
1202
|
+
if not curs.set_key(lkey):
|
|
1203
|
+
return 0
|
|
1204
|
+
|
|
1205
|
+
if not dupsort:
|
|
1206
|
+
return 1
|
|
1207
|
+
|
|
1208
|
+
return curs.count()
|
|
1209
|
+
|
|
1199
1210
|
def prefexists(self, byts, db=None):
|
|
1200
1211
|
'''
|
|
1201
1212
|
Returns True if a prefix exists in the db.
|
synapse/lib/node.py
CHANGED
|
@@ -613,17 +613,15 @@ class Node:
|
|
|
613
613
|
* delete all the tags (bottom up)
|
|
614
614
|
* fire onDelTag() handlers
|
|
615
615
|
* delete tag properties from storage
|
|
616
|
-
* log tag:del splices
|
|
617
616
|
|
|
618
617
|
* delete all secondary properties
|
|
619
618
|
* fire onDelProp handler
|
|
620
619
|
* delete secondary property from storage
|
|
621
|
-
* log prop:del splices
|
|
622
620
|
|
|
623
621
|
* delete the primary property
|
|
624
622
|
* fire onDel handlers for the node
|
|
625
623
|
* delete primary property from storage
|
|
626
|
-
|
|
624
|
+
|
|
627
625
|
'''
|
|
628
626
|
|
|
629
627
|
formname, formvalu = self.ndef
|
synapse/lib/parser.py
CHANGED
|
@@ -113,10 +113,13 @@ terminalEnglishMap = {
|
|
|
113
113
|
'_EDGEN1INIT': '-(',
|
|
114
114
|
'_EDGEN2INIT': '<(',
|
|
115
115
|
'_EDGEN2FINI': ')-',
|
|
116
|
+
'_EDGEN1JOINFINI': ')+>',
|
|
117
|
+
'_EDGEN2JOININIT': '<+(',
|
|
116
118
|
'_ELSE': 'else',
|
|
117
119
|
'_EMBEDQUERYSTART': '${',
|
|
118
120
|
'_EXPRCOLONNOSPACE': ':',
|
|
119
121
|
'_EMIT': 'emit',
|
|
122
|
+
'_EMPTY': 'empty',
|
|
120
123
|
'_FINI': 'fini',
|
|
121
124
|
'_HASH': '#',
|
|
122
125
|
'_HASHSPACE': '#',
|
|
@@ -131,6 +134,8 @@ terminalEnglishMap = {
|
|
|
131
134
|
'_RIGHTJOIN': '-+>',
|
|
132
135
|
'_RIGHTPIVOT': '->',
|
|
133
136
|
'_STOP': 'stop',
|
|
137
|
+
'_WALKNJOINN1': '--+>',
|
|
138
|
+
'_WALKNJOINN2': '<+--',
|
|
134
139
|
'_WALKNPIVON1': '-->',
|
|
135
140
|
'_WALKNPIVON2': '<--',
|
|
136
141
|
'$END': 'end of input',
|
|
@@ -640,6 +645,7 @@ ruleClassMap = {
|
|
|
640
645
|
'editparens': s_ast.EditParens,
|
|
641
646
|
'emit': s_ast.Emit,
|
|
642
647
|
'initblock': s_ast.InitBlock,
|
|
648
|
+
'emptyblock': s_ast.EmptyBlock,
|
|
643
649
|
'finiblock': s_ast.FiniBlock,
|
|
644
650
|
'formname': s_ast.FormName,
|
|
645
651
|
'editpropdel': lambda astinfo, kids: s_ast.EditPropDel(astinfo, kids[1:]),
|
|
@@ -690,8 +696,12 @@ ruleClassMap = {
|
|
|
690
696
|
'liftbyformtagprop': s_ast.LiftFormTagProp,
|
|
691
697
|
'looklist': s_ast.LookList,
|
|
692
698
|
'lookup': s_ast.Lookup,
|
|
699
|
+
'n1join': lambda astinfo, kids: s_ast.N1Walk(astinfo, kids, isjoin=True),
|
|
700
|
+
'n2join': lambda astinfo, kids: s_ast.N2Walk(astinfo, kids, isjoin=True),
|
|
693
701
|
'n1walk': s_ast.N1Walk,
|
|
694
702
|
'n2walk': s_ast.N2Walk,
|
|
703
|
+
'n1walknjoin': lambda astinfo, kids: s_ast.N1WalkNPivo(astinfo, kids, isjoin=True),
|
|
704
|
+
'n2walknjoin': lambda astinfo, kids: s_ast.N2WalkNPivo(astinfo, kids, isjoin=True),
|
|
695
705
|
'n1walknpivo': s_ast.N1WalkNPivo,
|
|
696
706
|
'n2walknpivo': s_ast.N2WalkNPivo,
|
|
697
707
|
'notcond': s_ast.NotCond,
|
synapse/lib/slabseqn.py
CHANGED
|
@@ -123,6 +123,7 @@ class SlabSeqn:
|
|
|
123
123
|
|
|
124
124
|
size = 0
|
|
125
125
|
tick = s_common.now()
|
|
126
|
+
abstick = s_common.mononow()
|
|
126
127
|
|
|
127
128
|
for item in items:
|
|
128
129
|
|
|
@@ -136,7 +137,7 @@ class SlabSeqn:
|
|
|
136
137
|
rows.append((lkey, byts))
|
|
137
138
|
|
|
138
139
|
retn = self.slab.putmulti(rows, append=True, db=self.db)
|
|
139
|
-
took = s_common.
|
|
140
|
+
took = s_common.mononow() - abstick
|
|
140
141
|
|
|
141
142
|
assert retn, "Not adding the largest indices"
|
|
142
143
|
|
synapse/lib/snap.py
CHANGED
|
@@ -301,11 +301,7 @@ class ProtoNode:
|
|
|
301
301
|
if self.node is not None:
|
|
302
302
|
return self.node.get(name)
|
|
303
303
|
|
|
304
|
-
async def
|
|
305
|
-
|
|
306
|
-
prop = self.form.props.get(name)
|
|
307
|
-
if prop is None:
|
|
308
|
-
return False
|
|
304
|
+
async def _set(self, prop, valu, norminfo=None):
|
|
309
305
|
|
|
310
306
|
if prop.locked:
|
|
311
307
|
mesg = f'Prop {prop.full} is locked due to deprecation.'
|
|
@@ -339,7 +335,7 @@ class ProtoNode:
|
|
|
339
335
|
await self.ctx.snap._raiseOnStrict(s_exc.IsDeprLocked, mesg)
|
|
340
336
|
return False
|
|
341
337
|
|
|
342
|
-
curv = self.get(name)
|
|
338
|
+
curv = self.get(prop.name)
|
|
343
339
|
if curv == valu:
|
|
344
340
|
return False
|
|
345
341
|
|
|
@@ -351,7 +347,20 @@ class ProtoNode:
|
|
|
351
347
|
if self.node is not None:
|
|
352
348
|
await self.ctx.snap.core._callPropSetHook(self.node, prop, valu)
|
|
353
349
|
|
|
354
|
-
self.props[name] = valu
|
|
350
|
+
self.props[prop.name] = valu
|
|
351
|
+
|
|
352
|
+
return valu, norminfo
|
|
353
|
+
|
|
354
|
+
async def set(self, name, valu, norminfo=None):
|
|
355
|
+
prop = self.form.props.get(name)
|
|
356
|
+
if prop is None:
|
|
357
|
+
return False
|
|
358
|
+
|
|
359
|
+
retn = await self._set(prop, valu, norminfo=norminfo)
|
|
360
|
+
if retn is False:
|
|
361
|
+
return False
|
|
362
|
+
|
|
363
|
+
(valu, norminfo) = retn
|
|
355
364
|
|
|
356
365
|
propform = self.ctx.snap.core.model.form(prop.type.name)
|
|
357
366
|
if propform is not None:
|
|
@@ -372,6 +381,37 @@ class ProtoNode:
|
|
|
372
381
|
|
|
373
382
|
return True
|
|
374
383
|
|
|
384
|
+
async def getSetOps(self, name, valu, norminfo=None):
|
|
385
|
+
prop = self.form.props.get(name)
|
|
386
|
+
if prop is None:
|
|
387
|
+
return ()
|
|
388
|
+
|
|
389
|
+
retn = await self._set(prop, valu, norminfo=norminfo)
|
|
390
|
+
if retn is False:
|
|
391
|
+
return ()
|
|
392
|
+
|
|
393
|
+
(valu, norminfo) = retn
|
|
394
|
+
ops = []
|
|
395
|
+
|
|
396
|
+
propform = self.ctx.snap.core.model.form(prop.type.name)
|
|
397
|
+
if propform is not None:
|
|
398
|
+
ops.append(self.ctx.getAddNodeOps(propform.name, valu, norminfo=norminfo))
|
|
399
|
+
|
|
400
|
+
# TODO can we mandate any subs are returned pre-normalized?
|
|
401
|
+
propsubs = norminfo.get('subs')
|
|
402
|
+
if propsubs is not None:
|
|
403
|
+
for subname, subvalu in propsubs.items():
|
|
404
|
+
full = f'{prop.name}:{subname}'
|
|
405
|
+
if self.form.props.get(full) is not None:
|
|
406
|
+
ops.append(self.getSetOps(full, subvalu))
|
|
407
|
+
|
|
408
|
+
propadds = norminfo.get('adds')
|
|
409
|
+
if propadds is not None:
|
|
410
|
+
for addname, addvalu, addinfo in propadds:
|
|
411
|
+
ops.append(self.ctx.getAddNodeOps(addname, addvalu, norminfo=addinfo))
|
|
412
|
+
|
|
413
|
+
return ops
|
|
414
|
+
|
|
375
415
|
class SnapEditor:
|
|
376
416
|
'''
|
|
377
417
|
A SnapEditor allows tracking node edits with subs/deps as a transaction.
|
|
@@ -394,17 +434,12 @@ class SnapEditor:
|
|
|
394
434
|
nodeedits.append(nodeedit)
|
|
395
435
|
return nodeedits
|
|
396
436
|
|
|
397
|
-
async def
|
|
437
|
+
async def _addNode(self, form, valu, props=None, norminfo=None):
|
|
398
438
|
|
|
399
439
|
self.snap.core._checkMaxNodes()
|
|
400
440
|
|
|
401
|
-
form = self.snap.core.model.form(formname)
|
|
402
|
-
if form is None:
|
|
403
|
-
mesg = f'No form named {formname} for valu={valu}.'
|
|
404
|
-
return await self.snap._raiseOnStrict(s_exc.NoSuchForm, mesg)
|
|
405
|
-
|
|
406
441
|
if form.isrunt:
|
|
407
|
-
mesg = f'Cannot make runt nodes: {
|
|
442
|
+
mesg = f'Cannot make runt nodes: {form.name}.'
|
|
408
443
|
return await self.snap._raiseOnStrict(s_exc.IsRuntForm, mesg)
|
|
409
444
|
|
|
410
445
|
if form.locked:
|
|
@@ -417,15 +452,73 @@ class SnapEditor:
|
|
|
417
452
|
except s_exc.BadTypeValu as e:
|
|
418
453
|
e.errinfo['form'] = form.name
|
|
419
454
|
if self.snap.strict: raise e
|
|
420
|
-
await self.snap.warn(f'addNode() BadTypeValu {
|
|
455
|
+
await self.snap.warn(f'addNode() BadTypeValu {form.name}={valu} {e}')
|
|
421
456
|
return None
|
|
422
457
|
|
|
458
|
+
return valu, norminfo
|
|
459
|
+
|
|
460
|
+
async def addNode(self, formname, valu, props=None, norminfo=None):
|
|
461
|
+
|
|
462
|
+
form = self.snap.core.model.form(formname)
|
|
463
|
+
if form is None:
|
|
464
|
+
mesg = f'No form named {formname} for valu={valu}.'
|
|
465
|
+
return await self.snap._raiseOnStrict(s_exc.NoSuchForm, mesg)
|
|
466
|
+
|
|
467
|
+
retn = await self._addNode(form, valu, props=props, norminfo=norminfo)
|
|
468
|
+
if retn is None:
|
|
469
|
+
return None
|
|
470
|
+
|
|
471
|
+
valu, norminfo = retn
|
|
472
|
+
|
|
423
473
|
protonode = await self._initProtoNode(form, valu, norminfo)
|
|
424
474
|
if props is not None:
|
|
425
475
|
[await protonode.set(p, v) for (p, v) in props.items()]
|
|
426
476
|
|
|
427
477
|
return protonode
|
|
428
478
|
|
|
479
|
+
async def getAddNodeOps(self, formname, valu, props=None, norminfo=None):
|
|
480
|
+
|
|
481
|
+
form = self.snap.core.model.form(formname)
|
|
482
|
+
if form is None:
|
|
483
|
+
mesg = f'No form named {formname} for valu={valu}.'
|
|
484
|
+
await self.snap._raiseOnStrict(s_exc.NoSuchForm, mesg)
|
|
485
|
+
return()
|
|
486
|
+
|
|
487
|
+
retn = await self._addNode(form, valu, props=props, norminfo=norminfo)
|
|
488
|
+
if retn is None:
|
|
489
|
+
return ()
|
|
490
|
+
|
|
491
|
+
norm, norminfo = retn
|
|
492
|
+
|
|
493
|
+
ndef = (form.name, norm)
|
|
494
|
+
|
|
495
|
+
protonode = self.protonodes.get(ndef)
|
|
496
|
+
if protonode is not None:
|
|
497
|
+
return ()
|
|
498
|
+
|
|
499
|
+
buid = s_common.buid(ndef)
|
|
500
|
+
node = await self.snap.getNodeByBuid(buid)
|
|
501
|
+
if node is not None:
|
|
502
|
+
return ()
|
|
503
|
+
|
|
504
|
+
protonode = ProtoNode(self, buid, form, norm, node)
|
|
505
|
+
|
|
506
|
+
self.protonodes[ndef] = protonode
|
|
507
|
+
|
|
508
|
+
ops = []
|
|
509
|
+
|
|
510
|
+
subs = norminfo.get('subs')
|
|
511
|
+
if subs is not None:
|
|
512
|
+
for prop, valu in subs.items():
|
|
513
|
+
ops.append(protonode.getSetOps(prop, valu))
|
|
514
|
+
|
|
515
|
+
adds = norminfo.get('adds')
|
|
516
|
+
if adds is not None:
|
|
517
|
+
for addname, addvalu, addinfo in adds:
|
|
518
|
+
ops.append(self.getAddNodeOps(addname, addvalu, norminfo=addinfo))
|
|
519
|
+
|
|
520
|
+
return ops
|
|
521
|
+
|
|
429
522
|
def loadNode(self, node):
|
|
430
523
|
protonode = self.protonodes.get(node.ndef)
|
|
431
524
|
if protonode is None:
|
|
@@ -448,14 +541,25 @@ class SnapEditor:
|
|
|
448
541
|
|
|
449
542
|
self.protonodes[ndef] = protonode
|
|
450
543
|
|
|
544
|
+
ops = collections.deque()
|
|
545
|
+
|
|
451
546
|
subs = norminfo.get('subs')
|
|
452
547
|
if subs is not None:
|
|
453
|
-
|
|
548
|
+
for prop, valu in subs.items():
|
|
549
|
+
ops.append(protonode.getSetOps(prop, valu))
|
|
550
|
+
|
|
551
|
+
while ops:
|
|
552
|
+
oset = ops.popleft()
|
|
553
|
+
ops.extend(await oset)
|
|
454
554
|
|
|
455
555
|
adds = norminfo.get('adds')
|
|
456
556
|
if adds is not None:
|
|
457
557
|
for addname, addvalu, addinfo in adds:
|
|
458
|
-
|
|
558
|
+
ops.append(self.getAddNodeOps(addname, addvalu, norminfo=addinfo))
|
|
559
|
+
|
|
560
|
+
while ops:
|
|
561
|
+
oset = ops.popleft()
|
|
562
|
+
ops.extend(await oset)
|
|
459
563
|
|
|
460
564
|
return protonode
|
|
461
565
|
|
|
@@ -469,8 +573,6 @@ class Snap(s_base.Base):
|
|
|
469
573
|
|
|
470
574
|
Transactions produce the following EventBus events:
|
|
471
575
|
|
|
472
|
-
(...any splice...)
|
|
473
|
-
('log', {'level': 'mesg': })
|
|
474
576
|
('print', {}),
|
|
475
577
|
'''
|
|
476
578
|
tagcachesize = 1000
|
|
@@ -598,7 +700,6 @@ class Snap(s_base.Base):
|
|
|
598
700
|
|
|
599
701
|
yield pode
|
|
600
702
|
|
|
601
|
-
@s_coro.genrhelp
|
|
602
703
|
async def storm(self, text, opts=None, user=None):
|
|
603
704
|
'''
|
|
604
705
|
Execute a storm query and yield (Node(), Path()) tuples.
|
|
@@ -616,7 +717,6 @@ class Snap(s_base.Base):
|
|
|
616
717
|
async for x in runt.execute():
|
|
617
718
|
yield x
|
|
618
719
|
|
|
619
|
-
@s_coro.genrhelp
|
|
620
720
|
async def eval(self, text, opts=None, user=None):
|
|
621
721
|
'''
|
|
622
722
|
Run a storm query and yield Node() objects.
|
synapse/lib/spooled.py
CHANGED
|
@@ -143,6 +143,15 @@ class Dict(Spooled):
|
|
|
143
143
|
self.len = len(self.realdict)
|
|
144
144
|
self.realdict.clear()
|
|
145
145
|
|
|
146
|
+
def pop(self, key, defv=None):
|
|
147
|
+
if self.fallback:
|
|
148
|
+
ret = self.slab.pop(s_msgpack.en(key))
|
|
149
|
+
if ret is None:
|
|
150
|
+
return defv
|
|
151
|
+
self.len -= 1
|
|
152
|
+
return s_msgpack.un(ret)
|
|
153
|
+
return self.realdict.pop(key, defv)
|
|
154
|
+
|
|
146
155
|
def has(self, key):
|
|
147
156
|
if self.fallback:
|
|
148
157
|
return self.slab.has(s_msgpack.en(key))
|