synapse 2.155.0__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.

Files changed (64) hide show
  1. synapse/cmds/cortex.py +2 -14
  2. synapse/common.py +1 -28
  3. synapse/cortex.py +10 -510
  4. synapse/lib/ast.py +60 -1
  5. synapse/lib/cell.py +33 -8
  6. synapse/lib/certdir.py +11 -0
  7. synapse/lib/cmdr.py +0 -5
  8. synapse/lib/gis.py +2 -2
  9. synapse/lib/httpapi.py +1 -43
  10. synapse/lib/layer.py +64 -201
  11. synapse/lib/lmdbslab.py +11 -0
  12. synapse/lib/node.py +1 -3
  13. synapse/lib/parser.py +10 -0
  14. synapse/lib/snap.py +121 -21
  15. synapse/lib/storm.lark +23 -6
  16. synapse/lib/storm.py +15 -338
  17. synapse/lib/storm_format.py +5 -0
  18. synapse/lib/stormlib/gen.py +1 -2
  19. synapse/lib/stormlib/gis.py +41 -0
  20. synapse/lib/stormlib/stats.py +21 -2
  21. synapse/lib/stormlib/storm.py +16 -1
  22. synapse/lib/stormtypes.py +225 -12
  23. synapse/lib/version.py +2 -2
  24. synapse/lib/view.py +96 -21
  25. synapse/models/inet.py +60 -30
  26. synapse/models/infotech.py +56 -1
  27. synapse/models/orgs.py +3 -0
  28. synapse/models/risk.py +15 -0
  29. synapse/models/syn.py +0 -38
  30. synapse/tests/test_cmds_cortex.py +1 -1
  31. synapse/tests/test_cortex.py +32 -336
  32. synapse/tests/test_lib_agenda.py +19 -54
  33. synapse/tests/test_lib_aha.py +97 -0
  34. synapse/tests/test_lib_ast.py +402 -0
  35. synapse/tests/test_lib_grammar.py +30 -10
  36. synapse/tests/test_lib_httpapi.py +0 -46
  37. synapse/tests/test_lib_layer.py +19 -234
  38. synapse/tests/test_lib_lmdbslab.py +22 -0
  39. synapse/tests/test_lib_snap.py +9 -0
  40. synapse/tests/test_lib_storm.py +16 -309
  41. synapse/tests/test_lib_stormlib_gis.py +21 -0
  42. synapse/tests/test_lib_stormlib_stats.py +107 -20
  43. synapse/tests/test_lib_stormlib_storm.py +25 -0
  44. synapse/tests/test_lib_stormtypes.py +231 -8
  45. synapse/tests/test_lib_view.py +6 -13
  46. synapse/tests/test_model_base.py +1 -1
  47. synapse/tests/test_model_inet.py +15 -0
  48. synapse/tests/test_model_infotech.py +60 -0
  49. synapse/tests/test_model_orgs.py +10 -0
  50. synapse/tests/test_model_person.py +0 -3
  51. synapse/tests/test_model_risk.py +20 -0
  52. synapse/tests/test_model_syn.py +20 -34
  53. synapse/tests/test_tools_csvtool.py +2 -1
  54. synapse/tests/test_tools_feed.py +4 -30
  55. synapse/tools/csvtool.py +2 -1
  56. {synapse-2.155.0.dist-info → synapse-2.156.0.dist-info}/METADATA +3 -3
  57. {synapse-2.155.0.dist-info → synapse-2.156.0.dist-info}/RECORD +60 -62
  58. {synapse-2.155.0.dist-info → synapse-2.156.0.dist-info}/WHEEL +1 -1
  59. synapse/cmds/cron.py +0 -726
  60. synapse/cmds/trigger.py +0 -319
  61. synapse/tests/test_cmds_cron.py +0 -453
  62. synapse/tests/test_cmds_trigger.py +0 -176
  63. {synapse-2.155.0.dist-info → synapse-2.156.0.dist-info}/LICENSE +0 -0
  64. {synapse-2.155.0.dist-info → synapse-2.156.0.dist-info}/top_level.txt +0 -0
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/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 set(self, name, valu, norminfo=None):
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 addNode(self, formname, valu, props=None, norminfo=None):
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: {formname}.'
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 {formname}={valu} {e}')
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
- [await protonode.set(p, v) for (p, v) in subs.items()]
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
- await self.addNode(addname, addvalu, norminfo=addinfo)
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/storm.lark CHANGED
@@ -63,10 +63,10 @@ SETTAGOPER: "?"
63
63
 
64
64
  // The set of non-edit non-commands in storm
65
65
 
66
- _oper: stormfunc | initblock | finiblock | trycatch | subquery | _formpivot | formjoin | formpivotin
67
- | formjoinin | opervarlist | setitem | setvar | vareval | filtoper
66
+ _oper: stormfunc | initblock | emptyblock | finiblock | trycatch | subquery | _formpivot | formjoin
67
+ | formpivotin | formjoinin | opervarlist | setitem | setvar | vareval | filtoper
68
68
  | operrelprop | forloop | whileloop | switchcase | BREAK | CONTINUE | return | emit | stop
69
- | _liftprop | ifstmt | yieldvalu | n1walk | n2walk | n1walknpivo | n2walknpivo | rawpivot
69
+ | _liftprop | ifstmt | yieldvalu | n1walk | n2walk | n1join | n2join | n1walknpivo | n2walknpivo | n1walknjoin | n2walknjoin | rawpivot
70
70
 
71
71
  BREAK.4: /break(?=[\s\}])/
72
72
  CONTINUE.4: /continue(?=[\s\}])/
@@ -106,6 +106,9 @@ yieldvalu: YIELD _argvalu
106
106
  _INIT.2: /init(?=[\s\{])/
107
107
  initblock: _INIT "{" query "}"
108
108
 
109
+ _EMPTY.2: /empty(?=[\s\{])/
110
+ emptyblock: _EMPTY "{" query "}"
111
+
109
112
  _FINI.2: /fini(?=[\s\{])/
110
113
  finiblock: _FINI "{" query "}"
111
114
 
@@ -148,7 +151,7 @@ rawpivot: _RIGHTPIVOT "{" query "}"
148
151
  _RIGHTJOIN.4: "-+>"
149
152
  _LEFTJOIN.4: "<+-"
150
153
  _RIGHTPIVOT.4: "->"
151
- _LEFTPIVOT.4: "<-"
154
+ _LEFTPIVOT.4: /<\-[^0-9]/
152
155
 
153
156
  _liftprop: liftformtag | liftpropby | liftprop | liftbyarray
154
157
  | liftbytagprop | liftbyformtagprop | liftbytag | lifttagtag
@@ -163,20 +166,33 @@ n1walk: _EDGEN1INIT (walklist | varlist | _varvalu | relpropvalu | univpropvalu
163
166
 
164
167
  n2walk: _EDGEN2INIT _valu _EDGEN2FINI _wildprops [ _cmpr _valu ]
165
168
 
169
+ n1join: _EDGEN1INIT (walklist | varlist | _varvalu | relpropvalu | univpropvalu | tagvalu | tagpropvalu | TRIPLEQUOTEDSTRING | formatstring | VARTOKN | embedquery | baresubquery | NONQUOTEWORD | ABSPROPNOUNIV) _EDGEN1JOINFINI _wildprops [ _cmpr _valu ]
170
+
171
+ n2join: _EDGEN2JOININIT _valu _EDGEN2FINI _wildprops [ _cmpr _valu ]
172
+
166
173
  walklist: ("(" (_varvalu | relpropvalu | univpropvalu | tagvalu | tagpropvalu | TRIPLEQUOTEDSTRING | formatstring | VARTOKN | NONQUOTEWORD | ABSPROP) ((",")|("," (_varvalu | relpropvalu | univpropvalu | tagvalu | tagpropvalu | TRIPLEQUOTEDSTRING | formatstring | VARTOKN | NONQUOTEWORD | ABSPROP))+ ","?) ")") -> valulist
167
174
 
175
+ _WALKNJOINN1.4: "--+>"
176
+ _WALKNJOINN2.4: "<+--"
177
+
168
178
  _WALKNPIVON1.4: "-->"
169
179
  _WALKNPIVON2.4: "<--"
170
180
 
171
181
  n1walknpivo: _WALKNPIVON1 "*"
172
182
  n2walknpivo: _WALKNPIVON2 "*"
173
183
 
184
+ n1walknjoin: _WALKNJOINN1 "*"
185
+ n2walknjoin: _WALKNJOINN2 "*"
186
+
174
187
  _EDGEADDN1INIT.2: "+("
175
188
  _EDGEN1INIT.2: "-("
176
189
  _EDGEN1FINI: ")>"
177
190
  _EDGEADDN2FINI: ")+"
178
191
  _EDGEN2FINI: ")-"
179
192
 
193
+ _EDGEN1JOINFINI: ")+>"
194
+ _EDGEN2JOININIT: "<+("
195
+
180
196
  // Regex to check for a matching ')-' or ')+' so we can avoid incorrectly matching
181
197
  // comparisons to an expression like '<(2)'
182
198
  _EDGEN2INIT: /\<\((?=(?>(?<EDGEN2INITRECUR>\(((?>[^()"'`]+|(?&EDGEN2INITRECUR)|`(?:[^`\\]|\\.)*`|"(?:[^"\\]|\\.)*"|'''.*?'''|'[^']*'(?!'))*)\))|'''.*?'''|`(?:[^`\\]|\\.)*`|"(?:[^"\\]|\\.)*"|'[^']*'(?!')|[^)])*\)[\-\+])/
@@ -214,7 +230,7 @@ stormcmdargs: _stormcmdarg
214
230
  _stormcmdarg: _stormcmdarg? ((CMDOPT (EQNOSPACE (argvquery | _argvalu | wordtokn))?) | argvquery | _argvalu | wordtokn)
215
231
 
216
232
  // The name of a storm command
217
- CMDNAME.2: /(?!(init|fini|function|return|emit|stop|yield|break|continue|for|while|switch|else|elif|if|not|or|and|try|catch|as|reverse)\b)[a-z][a-z0-9.]+(?=[\s\|\}]|$)/
233
+ CMDNAME.2: /(?!(init|empty|fini|function|return|emit|stop|yield|break|continue|for|while|switch|else|elif|if|not|or|and|try|catch|as|reverse)\b)[a-z][a-z0-9.]+(?=[\s\|\}]|$)/
218
234
 
219
235
  CMDOPT.4: /(?<=\s)-[a-zA-Z0-9_-]+(?![:a-zA-Z0-9_><-])/
220
236
 
@@ -258,8 +274,9 @@ _MATCHHASHWILD.3: /\#
258
274
  <\(
259
275
  (?=(?>(?<N2MATCHRECUR>\(((?>[^()"'`]+|(?&N2MATCHRECUR)|`(?:[^`\\]|\\.)*`|"(?:[^"\\]|\\.)*"|'''.*?'''|'[^']*'(?!'))*)\))|'''.*?'''|`(?:[^`\\]|\\.)*`|"(?:[^"\\]|\\.)*"|'[^']*'(?!')|[^)])*\)-
260
276
  )
277
+ | <(\+|-[^0-9]) # avoid matching joins or pivots
261
278
  )
262
- [@?!<>^~=]+ # match any cmprs (regex fail)
279
+ [@?!<>^~=]+ # match any cmprs (regex fail)
263
280
  )
264
281
  )
265
282
  /x