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.
- synapse/cmds/cortex.py +2 -14
- synapse/common.py +1 -28
- synapse/cortex.py +10 -510
- synapse/lib/ast.py +60 -1
- synapse/lib/cell.py +33 -8
- synapse/lib/certdir.py +11 -0
- synapse/lib/cmdr.py +0 -5
- synapse/lib/gis.py +2 -2
- synapse/lib/httpapi.py +1 -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/snap.py +121 -21
- synapse/lib/storm.lark +23 -6
- synapse/lib/storm.py +15 -338
- synapse/lib/storm_format.py +5 -0
- synapse/lib/stormlib/gen.py +1 -2
- synapse/lib/stormlib/gis.py +41 -0
- synapse/lib/stormlib/stats.py +21 -2
- synapse/lib/stormlib/storm.py +16 -1
- synapse/lib/stormtypes.py +225 -12
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +96 -21
- synapse/models/inet.py +60 -30
- synapse/models/infotech.py +56 -1
- synapse/models/orgs.py +3 -0
- synapse/models/risk.py +15 -0
- synapse/models/syn.py +0 -38
- synapse/tests/test_cmds_cortex.py +1 -1
- synapse/tests/test_cortex.py +32 -336
- synapse/tests/test_lib_agenda.py +19 -54
- synapse/tests/test_lib_aha.py +97 -0
- synapse/tests/test_lib_ast.py +402 -0
- synapse/tests/test_lib_grammar.py +30 -10
- synapse/tests/test_lib_httpapi.py +0 -46
- 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_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 +231 -8
- 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 +60 -0
- synapse/tests/test_model_orgs.py +10 -0
- synapse/tests/test_model_person.py +0 -3
- synapse/tests/test_model_risk.py +20 -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.155.0.dist-info → synapse-2.156.0.dist-info}/METADATA +3 -3
- {synapse-2.155.0.dist-info → synapse-2.156.0.dist-info}/RECORD +60 -62
- {synapse-2.155.0.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.155.0.dist-info → synapse-2.156.0.dist-info}/LICENSE +0 -0
- {synapse-2.155.0.dist-info → synapse-2.156.0.dist-info}/top_level.txt +0 -0
synapse/lib/storm.py
CHANGED
|
@@ -2141,7 +2141,21 @@ class Runtime(s_base.Base):
|
|
|
2141
2141
|
|
|
2142
2142
|
def confirm(self, perms, gateiden=None, default=None):
|
|
2143
2143
|
'''
|
|
2144
|
-
Raise AuthDeny if user doesn't have
|
|
2144
|
+
Raise AuthDeny if the user doesn't have the permission.
|
|
2145
|
+
|
|
2146
|
+
Notes:
|
|
2147
|
+
An elevated runtime with asroot=True will always return True.
|
|
2148
|
+
|
|
2149
|
+
Args:
|
|
2150
|
+
perms (tuple): The permission tuple.
|
|
2151
|
+
gateiden (str): The gateiden.
|
|
2152
|
+
default (bool): The default value.
|
|
2153
|
+
|
|
2154
|
+
Returns:
|
|
2155
|
+
True: If the permission is allowed.
|
|
2156
|
+
|
|
2157
|
+
Raises:
|
|
2158
|
+
AuthDeny: If the user does not have the permission.
|
|
2145
2159
|
'''
|
|
2146
2160
|
if self.asroot:
|
|
2147
2161
|
return
|
|
@@ -4598,22 +4612,6 @@ class ReIndexCmd(Cmd):
|
|
|
4598
4612
|
if False:
|
|
4599
4613
|
yield
|
|
4600
4614
|
|
|
4601
|
-
class SudoCmd(Cmd):
|
|
4602
|
-
'''
|
|
4603
|
-
Deprecated sudo command.
|
|
4604
|
-
|
|
4605
|
-
Left in for 2.x.x so that Storm command with it are still valid to execute.
|
|
4606
|
-
'''
|
|
4607
|
-
name = 'sudo'
|
|
4608
|
-
|
|
4609
|
-
async def execStormCmd(self, runt, genr):
|
|
4610
|
-
|
|
4611
|
-
s_common.deprdate('storm command: sudo', s_common._splicedepr)
|
|
4612
|
-
|
|
4613
|
-
await runt.snap.warn(f'sudo command is deprecated and will be removed on {s_common._splicedepr}')
|
|
4614
|
-
async for node, path in genr:
|
|
4615
|
-
yield node, path
|
|
4616
|
-
|
|
4617
4615
|
class MoveTagCmd(Cmd):
|
|
4618
4616
|
'''
|
|
4619
4617
|
Rename an entire tag tree and preserve time intervals.
|
|
@@ -5463,327 +5461,6 @@ class ScrapeCmd(Cmd):
|
|
|
5463
5461
|
if self.opts.doyield:
|
|
5464
5462
|
yield addnode, runt.initPath(addnode)
|
|
5465
5463
|
|
|
5466
|
-
class SpliceListCmd(Cmd):
|
|
5467
|
-
'''
|
|
5468
|
-
Deprecated command to retrieve a list of splices backwards from the end of the splicelog.
|
|
5469
|
-
|
|
5470
|
-
Examples:
|
|
5471
|
-
|
|
5472
|
-
# Show the last 10 splices.
|
|
5473
|
-
splice.list | limit 10
|
|
5474
|
-
|
|
5475
|
-
# Show splices after a specific time.
|
|
5476
|
-
splice.list --mintime "2020/01/06 15:38:10.991"
|
|
5477
|
-
|
|
5478
|
-
# Show splices from a specific timeframe.
|
|
5479
|
-
splice.list --mintimestamp 1578422719360 --maxtimestamp 1578422719367
|
|
5480
|
-
|
|
5481
|
-
Notes:
|
|
5482
|
-
|
|
5483
|
-
If both a time string and timestamp value are provided for a min or max,
|
|
5484
|
-
the timestamp will take precedence over the time string value.
|
|
5485
|
-
'''
|
|
5486
|
-
|
|
5487
|
-
name = 'splice.list'
|
|
5488
|
-
readonly = True
|
|
5489
|
-
|
|
5490
|
-
def getArgParser(self):
|
|
5491
|
-
pars = Cmd.getArgParser(self)
|
|
5492
|
-
|
|
5493
|
-
pars.add_argument('--maxtimestamp', type='int', default=None,
|
|
5494
|
-
help='Only yield splices which occurred on or before this timestamp.')
|
|
5495
|
-
pars.add_argument('--mintimestamp', type='int', default=None,
|
|
5496
|
-
help='Only yield splices which occurred on or after this timestamp.')
|
|
5497
|
-
pars.add_argument('--maxtime', type='str', default=None,
|
|
5498
|
-
help='Only yield splices which occurred on or before this time.')
|
|
5499
|
-
pars.add_argument('--mintime', type='str', default=None,
|
|
5500
|
-
help='Only yield splices which occurred on or after this time.')
|
|
5501
|
-
|
|
5502
|
-
return pars
|
|
5503
|
-
|
|
5504
|
-
async def execStormCmd(self, runt, genr):
|
|
5505
|
-
|
|
5506
|
-
s_common.deprdate('storm command: splice.list', s_common._splicedepr)
|
|
5507
|
-
|
|
5508
|
-
mesg = f'splice.list is deprecated and will be removed on {s_common._splicedepr}'
|
|
5509
|
-
await runt.snap.warn(mesg)
|
|
5510
|
-
|
|
5511
|
-
maxtime = None
|
|
5512
|
-
if self.opts.maxtimestamp:
|
|
5513
|
-
maxtime = self.opts.maxtimestamp
|
|
5514
|
-
elif self.opts.maxtime:
|
|
5515
|
-
try:
|
|
5516
|
-
maxtime = s_time.parse(self.opts.maxtime, chop=True)
|
|
5517
|
-
except s_exc.BadTypeValu as e:
|
|
5518
|
-
mesg = f'Error during maxtime parsing - {str(e)}'
|
|
5519
|
-
|
|
5520
|
-
raise s_exc.StormRuntimeError(mesg=mesg, valu=self.opts.maxtime) from None
|
|
5521
|
-
|
|
5522
|
-
mintime = None
|
|
5523
|
-
if self.opts.mintimestamp:
|
|
5524
|
-
mintime = self.opts.mintimestamp
|
|
5525
|
-
elif self.opts.mintime:
|
|
5526
|
-
try:
|
|
5527
|
-
mintime = s_time.parse(self.opts.mintime, chop=True)
|
|
5528
|
-
except s_exc.BadTypeValu as e:
|
|
5529
|
-
mesg = f'Error during mintime parsing - {str(e)}'
|
|
5530
|
-
|
|
5531
|
-
raise s_exc.StormRuntimeError(mesg=mesg, valu=self.opts.mintime) from None
|
|
5532
|
-
|
|
5533
|
-
i = 0
|
|
5534
|
-
|
|
5535
|
-
async for splice in runt.snap.core.spliceHistory(runt.user):
|
|
5536
|
-
|
|
5537
|
-
splicetime = splice[1].get('time')
|
|
5538
|
-
if splicetime is None:
|
|
5539
|
-
splicetime = 0
|
|
5540
|
-
|
|
5541
|
-
if maxtime and maxtime < splicetime:
|
|
5542
|
-
continue
|
|
5543
|
-
|
|
5544
|
-
if mintime and mintime > splicetime:
|
|
5545
|
-
return
|
|
5546
|
-
|
|
5547
|
-
guid = s_common.guid(splice)
|
|
5548
|
-
|
|
5549
|
-
buid = s_common.buid(splice[1]['ndef'])
|
|
5550
|
-
iden = s_common.ehex(buid)
|
|
5551
|
-
|
|
5552
|
-
props = {'.created': s_common.now(),
|
|
5553
|
-
'splice': splice,
|
|
5554
|
-
'type': splice[0],
|
|
5555
|
-
'iden': iden,
|
|
5556
|
-
'form': splice[1]['ndef'][0],
|
|
5557
|
-
'time': splicetime,
|
|
5558
|
-
'user': splice[1].get('user'),
|
|
5559
|
-
'prov': splice[1].get('prov'),
|
|
5560
|
-
}
|
|
5561
|
-
|
|
5562
|
-
prop = splice[1].get('prop')
|
|
5563
|
-
if prop:
|
|
5564
|
-
props['prop'] = prop
|
|
5565
|
-
|
|
5566
|
-
tag = splice[1].get('tag')
|
|
5567
|
-
if tag:
|
|
5568
|
-
props['tag'] = tag
|
|
5569
|
-
|
|
5570
|
-
if 'valu' in splice[1]:
|
|
5571
|
-
props['valu'] = splice[1]['valu']
|
|
5572
|
-
elif splice[0] == 'node:del':
|
|
5573
|
-
props['valu'] = splice[1]['ndef'][1]
|
|
5574
|
-
|
|
5575
|
-
if 'oldv' in splice[1]:
|
|
5576
|
-
props['oldv'] = splice[1]['oldv']
|
|
5577
|
-
|
|
5578
|
-
fullnode = (buid, {
|
|
5579
|
-
'ndef': ('syn:splice', guid),
|
|
5580
|
-
'tags': {},
|
|
5581
|
-
'props': props,
|
|
5582
|
-
'tagprops': {},
|
|
5583
|
-
})
|
|
5584
|
-
|
|
5585
|
-
node = s_node.Node(runt.snap, fullnode)
|
|
5586
|
-
|
|
5587
|
-
yield (node, runt.initPath(node))
|
|
5588
|
-
|
|
5589
|
-
i += 1
|
|
5590
|
-
# Yield to other tasks occasionally
|
|
5591
|
-
if not i % 1000:
|
|
5592
|
-
await asyncio.sleep(0)
|
|
5593
|
-
|
|
5594
|
-
class SpliceUndoCmd(Cmd):
|
|
5595
|
-
'''
|
|
5596
|
-
Deprecated command to reverse the actions of syn:splice runt nodes.
|
|
5597
|
-
|
|
5598
|
-
Examples:
|
|
5599
|
-
|
|
5600
|
-
# Undo the last 5 splices.
|
|
5601
|
-
splice.list | limit 5 | splice.undo
|
|
5602
|
-
|
|
5603
|
-
# Undo splices after a specific time.
|
|
5604
|
-
splice.list --mintime "2020/01/06 15:38:10.991" | splice.undo
|
|
5605
|
-
|
|
5606
|
-
# Undo splices from a specific timeframe.
|
|
5607
|
-
splice.list --mintimestamp 1578422719360 --maxtimestamp 1578422719367 | splice.undo
|
|
5608
|
-
'''
|
|
5609
|
-
|
|
5610
|
-
name = 'splice.undo'
|
|
5611
|
-
|
|
5612
|
-
def __init__(self, runt, runtsafe):
|
|
5613
|
-
self.undo = {
|
|
5614
|
-
'prop:set': self.undoPropSet,
|
|
5615
|
-
'prop:del': self.undoPropDel,
|
|
5616
|
-
'node:add': self.undoNodeAdd,
|
|
5617
|
-
'node:del': self.undoNodeDel,
|
|
5618
|
-
'tag:add': self.undoTagAdd,
|
|
5619
|
-
'tag:del': self.undoTagDel,
|
|
5620
|
-
'tag:prop:set': self.undoTagPropSet,
|
|
5621
|
-
'tag:prop:del': self.undoTagPropDel,
|
|
5622
|
-
}
|
|
5623
|
-
Cmd.__init__(self, runt, runtsafe)
|
|
5624
|
-
|
|
5625
|
-
def getArgParser(self):
|
|
5626
|
-
pars = Cmd.getArgParser(self)
|
|
5627
|
-
forcehelp = 'Force delete nodes even if it causes broken references (requires admin).'
|
|
5628
|
-
pars.add_argument('--force', default=False, action='store_true', help=forcehelp)
|
|
5629
|
-
return pars
|
|
5630
|
-
|
|
5631
|
-
async def undoPropSet(self, runt, splice, node):
|
|
5632
|
-
|
|
5633
|
-
name = splice.props.get('prop')
|
|
5634
|
-
if name == '.created':
|
|
5635
|
-
return
|
|
5636
|
-
|
|
5637
|
-
if node:
|
|
5638
|
-
prop = node.form.props.get(name)
|
|
5639
|
-
if prop is None: # pragma: no cover
|
|
5640
|
-
mesg = f'No property named {name}.'
|
|
5641
|
-
raise s_exc.NoSuchProp(mesg=mesg, name=name, form=node.form.name)
|
|
5642
|
-
|
|
5643
|
-
oldv = splice.props.get('oldv')
|
|
5644
|
-
if oldv is not None:
|
|
5645
|
-
runt.layerConfirm(('node', 'prop', 'set', prop.full))
|
|
5646
|
-
await node.set(name, oldv)
|
|
5647
|
-
else:
|
|
5648
|
-
runt.layerConfirm(('node', 'prop', 'del', prop.full))
|
|
5649
|
-
await node.pop(name)
|
|
5650
|
-
|
|
5651
|
-
async def undoPropDel(self, runt, splice, node):
|
|
5652
|
-
|
|
5653
|
-
name = splice.props.get('prop')
|
|
5654
|
-
if name == '.created':
|
|
5655
|
-
return
|
|
5656
|
-
|
|
5657
|
-
if node:
|
|
5658
|
-
prop = node.form.props.get(name)
|
|
5659
|
-
if prop is None: # pragma: no cover
|
|
5660
|
-
mesg = f'No property named {name}.'
|
|
5661
|
-
raise s_exc.NoSuchProp(mesg=mesg, name=name, form=node.form.name)
|
|
5662
|
-
|
|
5663
|
-
valu = splice.props.get('valu')
|
|
5664
|
-
|
|
5665
|
-
runt.layerConfirm(('node', 'prop', 'set', prop.full))
|
|
5666
|
-
await node.set(name, valu)
|
|
5667
|
-
|
|
5668
|
-
async def undoNodeAdd(self, runt, splice, node):
|
|
5669
|
-
|
|
5670
|
-
if node:
|
|
5671
|
-
for tag in node.tags.keys():
|
|
5672
|
-
runt.layerConfirm(('node', 'tag', 'del', *tag.split('.')))
|
|
5673
|
-
|
|
5674
|
-
runt.layerConfirm(('node', 'del', node.form.name))
|
|
5675
|
-
await node.delete(force=self.opts.force)
|
|
5676
|
-
|
|
5677
|
-
async def undoNodeDel(self, runt, splice, node):
|
|
5678
|
-
|
|
5679
|
-
if node is None:
|
|
5680
|
-
form = splice.props.get('form')
|
|
5681
|
-
valu = splice.props.get('valu')
|
|
5682
|
-
|
|
5683
|
-
if form and (valu is not None):
|
|
5684
|
-
runt.layerConfirm(('node', 'add', form))
|
|
5685
|
-
await runt.snap.addNode(form, valu)
|
|
5686
|
-
|
|
5687
|
-
async def undoTagAdd(self, runt, splice, node):
|
|
5688
|
-
|
|
5689
|
-
if node:
|
|
5690
|
-
tag = splice.props.get('tag')
|
|
5691
|
-
parts = tag.split('.')
|
|
5692
|
-
runt.layerConfirm(('node', 'tag', 'del', *parts))
|
|
5693
|
-
|
|
5694
|
-
await node.delTag(tag)
|
|
5695
|
-
|
|
5696
|
-
oldv = splice.props.get('oldv')
|
|
5697
|
-
if oldv is not None:
|
|
5698
|
-
runt.layerConfirm(('node', 'tag', 'add', *parts))
|
|
5699
|
-
await node.addTag(tag, valu=oldv)
|
|
5700
|
-
|
|
5701
|
-
async def undoTagDel(self, runt, splice, node):
|
|
5702
|
-
|
|
5703
|
-
if node:
|
|
5704
|
-
tag = splice.props.get('tag')
|
|
5705
|
-
parts = tag.split('.')
|
|
5706
|
-
runt.layerConfirm(('node', 'tag', 'add', *parts))
|
|
5707
|
-
|
|
5708
|
-
valu = splice.props.get('valu')
|
|
5709
|
-
if valu is not None:
|
|
5710
|
-
await node.addTag(tag, valu=valu)
|
|
5711
|
-
|
|
5712
|
-
async def undoTagPropSet(self, runt, splice, node):
|
|
5713
|
-
|
|
5714
|
-
if node:
|
|
5715
|
-
tag = splice.props.get('tag')
|
|
5716
|
-
parts = tag.split('.')
|
|
5717
|
-
|
|
5718
|
-
prop = splice.props.get('prop')
|
|
5719
|
-
|
|
5720
|
-
oldv = splice.props.get('oldv')
|
|
5721
|
-
if oldv is not None:
|
|
5722
|
-
runt.layerConfirm(('node', 'tag', 'add', *parts))
|
|
5723
|
-
await node.setTagProp(tag, prop, oldv)
|
|
5724
|
-
else:
|
|
5725
|
-
runt.layerConfirm(('node', 'tag', 'del', *parts))
|
|
5726
|
-
await node.delTagProp(tag, prop)
|
|
5727
|
-
|
|
5728
|
-
async def undoTagPropDel(self, runt, splice, node):
|
|
5729
|
-
|
|
5730
|
-
if node:
|
|
5731
|
-
tag = splice.props.get('tag')
|
|
5732
|
-
parts = tag.split('.')
|
|
5733
|
-
runt.layerConfirm(('node', 'tag', 'add', *parts))
|
|
5734
|
-
|
|
5735
|
-
prop = splice.props.get('prop')
|
|
5736
|
-
|
|
5737
|
-
valu = splice.props.get('valu')
|
|
5738
|
-
if valu is not None:
|
|
5739
|
-
await node.setTagProp(tag, prop, valu)
|
|
5740
|
-
|
|
5741
|
-
async def execStormCmd(self, runt, genr):
|
|
5742
|
-
|
|
5743
|
-
s_common.deprdate('storm command: splice.undo', s_common._splicedepr)
|
|
5744
|
-
|
|
5745
|
-
mesg = f'splice.undo is deprecated and will be removed on {s_common._splicedepr}'
|
|
5746
|
-
await runt.snap.warn(mesg)
|
|
5747
|
-
|
|
5748
|
-
if self.opts.force:
|
|
5749
|
-
if not runt.user.isAdmin():
|
|
5750
|
-
mesg = '--force requires admin privs.'
|
|
5751
|
-
raise s_exc.AuthDeny(mesg=mesg)
|
|
5752
|
-
|
|
5753
|
-
i = 0
|
|
5754
|
-
|
|
5755
|
-
async for node, path in genr:
|
|
5756
|
-
|
|
5757
|
-
if not node.form.name == 'syn:splice':
|
|
5758
|
-
mesg = 'splice.undo only accepts syn:splice nodes'
|
|
5759
|
-
raise s_exc.StormRuntimeError(mesg=mesg, form=node.form.name)
|
|
5760
|
-
|
|
5761
|
-
if False: # make this method an async generator function
|
|
5762
|
-
yield None
|
|
5763
|
-
|
|
5764
|
-
splicetype = node.props.get('type')
|
|
5765
|
-
|
|
5766
|
-
if splicetype in self.undo:
|
|
5767
|
-
|
|
5768
|
-
iden = node.props.get('iden')
|
|
5769
|
-
if iden is None:
|
|
5770
|
-
continue
|
|
5771
|
-
|
|
5772
|
-
buid = s_common.uhex(iden)
|
|
5773
|
-
if len(buid) != 32:
|
|
5774
|
-
raise s_exc.NoSuchIden(mesg='Iden must be 32 bytes', iden=iden)
|
|
5775
|
-
|
|
5776
|
-
splicednode = await runt.snap.getNodeByBuid(buid)
|
|
5777
|
-
|
|
5778
|
-
await self.undo[splicetype](runt, node, splicednode)
|
|
5779
|
-
else:
|
|
5780
|
-
raise s_exc.StormRuntimeError(mesg='Unknown splice type.', splicetype=splicetype)
|
|
5781
|
-
|
|
5782
|
-
i += 1
|
|
5783
|
-
# Yield to other tasks occasionally
|
|
5784
|
-
if not i % 1000:
|
|
5785
|
-
await asyncio.sleep(0)
|
|
5786
|
-
|
|
5787
5464
|
class LiftByVerb(Cmd):
|
|
5788
5465
|
'''
|
|
5789
5466
|
Lift nodes from the current view by an light edge verb.
|
synapse/lib/storm_format.py
CHANGED
|
@@ -95,9 +95,12 @@ TerminalPygMap = {
|
|
|
95
95
|
'_EDGEN1INIT': p_t.Punctuation,
|
|
96
96
|
'_EDGEN2INIT': p_t.Punctuation,
|
|
97
97
|
'_EDGEN2FINI': p_t.Punctuation,
|
|
98
|
+
'_EDGEN1JOINFINI': p_t.Punctuation,
|
|
99
|
+
'_EDGEN2JOININIT': p_t.Punctuation,
|
|
98
100
|
'_ELSE': p_t.Keyword,
|
|
99
101
|
'_EMBEDQUERYSTART': p_t.Punctuation,
|
|
100
102
|
'_EMIT': p_t.Keyword,
|
|
103
|
+
'_EMPTY': p_t.Keyword,
|
|
101
104
|
'_EXPRCOLONNOSPACE': p_t.Punctuation,
|
|
102
105
|
'_FINI': p_t.Keyword,
|
|
103
106
|
'_HASH': p_t.Punctuation,
|
|
@@ -113,6 +116,8 @@ TerminalPygMap = {
|
|
|
113
116
|
'_RIGHTJOIN': p_t.Punctuation,
|
|
114
117
|
'_RIGHTPIVOT': p_t.Punctuation,
|
|
115
118
|
'_STOP': p_t.Keyword,
|
|
119
|
+
'_WALKNJOINN1': p_t.Punctuation,
|
|
120
|
+
'_WALKNJOINN2': p_t.Punctuation,
|
|
116
121
|
'_WALKNPIVON1': p_t.Punctuation,
|
|
117
122
|
'_WALKNPIVON2': p_t.Punctuation,
|
|
118
123
|
'$END': p_t.Punctuation,
|
synapse/lib/stormlib/gen.py
CHANGED
|
@@ -467,8 +467,7 @@ stormcmds = (
|
|
|
467
467
|
{
|
|
468
468
|
'name': 'gen.pol.country.government',
|
|
469
469
|
'descr': '''
|
|
470
|
-
Lift (or create) the ou:org node representing a country's
|
|
471
|
-
government based on the 2 letter ISO-3166 country code.
|
|
470
|
+
Lift (or create) the ou:org node representing a country's government based on the 2 letter ISO-3166 country code.
|
|
472
471
|
|
|
473
472
|
Examples:
|
|
474
473
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import synapse.exc as s_exc
|
|
2
|
+
|
|
3
|
+
import synapse.lib.gis as s_gis
|
|
4
|
+
import synapse.lib.stormtypes as s_stormtypes
|
|
5
|
+
|
|
6
|
+
@s_stormtypes.registry.registerLib
|
|
7
|
+
class GisLib(s_stormtypes.Lib):
|
|
8
|
+
'''
|
|
9
|
+
A Storm library which implements helpers for earth based geospatial calculations.
|
|
10
|
+
'''
|
|
11
|
+
_storm_locals = (
|
|
12
|
+
{'name': 'bbox', 'desc': 'Calculate a min/max bounding box for the specified circle.',
|
|
13
|
+
'type': {'type': 'function', '_funcname': '_methBbox',
|
|
14
|
+
'args': (
|
|
15
|
+
{'name': 'lon', 'type': 'float', 'desc': 'The longitude in degrees.'},
|
|
16
|
+
{'name': 'lat', 'type': 'float', 'desc': 'The latitude in degrees.'},
|
|
17
|
+
{'name': 'dist', 'type': 'int', 'desc': 'A distance in geo:dist base units (mm).'},
|
|
18
|
+
),
|
|
19
|
+
'returns': {'type': 'list', 'desc': 'A tuple of (lonmin, lonmax, latmin, latmax).', }
|
|
20
|
+
}},
|
|
21
|
+
)
|
|
22
|
+
_storm_lib_path = ('gis',)
|
|
23
|
+
|
|
24
|
+
def getObjLocals(self):
|
|
25
|
+
return {
|
|
26
|
+
'bbox': self._methBbox,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@s_stormtypes.stormfunc(readonly=True)
|
|
30
|
+
async def _methBbox(self, lon, lat, dist):
|
|
31
|
+
try:
|
|
32
|
+
lon = float(await s_stormtypes.toprim(lon))
|
|
33
|
+
lat = float(await s_stormtypes.toprim(lat))
|
|
34
|
+
dist = await s_stormtypes.toint(dist)
|
|
35
|
+
except ValueError as e:
|
|
36
|
+
raise s_exc.BadArg(mesg=f'$lib.gis.bbox(): {e}')
|
|
37
|
+
except s_exc.BadCast as e:
|
|
38
|
+
raise s_exc.BadArg(mesg=f'$lib.gis.bbox(): {e.get("mesg")}')
|
|
39
|
+
|
|
40
|
+
(latmin, latmax, lonmin, lonmax) = s_gis.bbox(lat, lon, dist)
|
|
41
|
+
return (lonmin, lonmax, latmin, latmax)
|
synapse/lib/stormlib/stats.py
CHANGED
|
@@ -41,6 +41,8 @@ class StatsCountByCmd(s_storm.Cmd):
|
|
|
41
41
|
help='Maximum width of the labels to display.')
|
|
42
42
|
pars.add_argument('--yield', default=False, action='store_true',
|
|
43
43
|
dest='yieldnodes', help='Yield inbound nodes.')
|
|
44
|
+
pars.add_argument('--by-name', default=False, action='store_true',
|
|
45
|
+
help='Print stats sorted by name instead of count.')
|
|
44
46
|
return pars
|
|
45
47
|
|
|
46
48
|
async def execStormCmd(self, runt, genr):
|
|
@@ -55,6 +57,8 @@ class StatsCountByCmd(s_storm.Cmd):
|
|
|
55
57
|
mesg = f'Value for --bar-width must be >= 0, got: {barwidth}'
|
|
56
58
|
raise s_exc.BadArg(mesg=mesg)
|
|
57
59
|
|
|
60
|
+
byname = await s_stormtypes.tobool(self.opts.by_name)
|
|
61
|
+
|
|
58
62
|
counts = collections.defaultdict(int)
|
|
59
63
|
|
|
60
64
|
usenode = self.opts.valu is s_common.novalu
|
|
@@ -78,9 +82,24 @@ class StatsCountByCmd(s_storm.Cmd):
|
|
|
78
82
|
await runt.printf('No values to display!')
|
|
79
83
|
return
|
|
80
84
|
|
|
81
|
-
|
|
85
|
+
if byname:
|
|
86
|
+
# Try to sort numerically instead of lexicographically
|
|
87
|
+
def coerce(indx):
|
|
88
|
+
def wrapped(valu):
|
|
89
|
+
valu = valu[indx]
|
|
90
|
+
try:
|
|
91
|
+
return int(valu)
|
|
92
|
+
except ValueError:
|
|
93
|
+
return valu
|
|
94
|
+
return wrapped
|
|
95
|
+
|
|
96
|
+
values = list(sorted(counts.items(), key=coerce(0)))
|
|
97
|
+
maxv = max(val[1] for val in values)
|
|
98
|
+
|
|
99
|
+
else:
|
|
100
|
+
values = list(sorted(counts.items(), key=lambda x: x[1]))
|
|
101
|
+
maxv = values[-1][1]
|
|
82
102
|
|
|
83
|
-
maxv = values[-1][1]
|
|
84
103
|
size = await s_stormtypes.toint(self.opts.size, noneok=True)
|
|
85
104
|
char = (await s_stormtypes.tostr(self.opts.char))[0]
|
|
86
105
|
reverse = self.opts.reverse
|
synapse/lib/stormlib/storm.py
CHANGED
|
@@ -1,14 +1,25 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
1
3
|
import synapse.exc as s_exc
|
|
2
4
|
|
|
3
5
|
import synapse.lib.stormtypes as s_stormtypes
|
|
4
6
|
|
|
7
|
+
evaldesc = '''\
|
|
8
|
+
Evaluate a storm runtime value and optionally cast/coerce it.
|
|
9
|
+
|
|
10
|
+
NOTE: If storm logging is enabled, the expression being evaluated will be logged
|
|
11
|
+
separately.
|
|
12
|
+
'''
|
|
13
|
+
|
|
14
|
+
stormlogger = logging.getLogger('synapse.storm')
|
|
15
|
+
|
|
5
16
|
@s_stormtypes.registry.registerLib
|
|
6
17
|
class LibStorm(s_stormtypes.Lib):
|
|
7
18
|
'''
|
|
8
19
|
A Storm library for evaluating dynamic storm expressions.
|
|
9
20
|
'''
|
|
10
21
|
_storm_locals = (
|
|
11
|
-
{'name': 'eval', 'desc':
|
|
22
|
+
{'name': 'eval', 'desc': evaldesc,
|
|
12
23
|
'type': {'type': 'function', '_funcname': '_evalStorm',
|
|
13
24
|
'args': (
|
|
14
25
|
{'name': 'text', 'type': 'str', 'desc': 'A storm expression string.'},
|
|
@@ -29,6 +40,10 @@ class LibStorm(s_stormtypes.Lib):
|
|
|
29
40
|
text = await s_stormtypes.tostr(text)
|
|
30
41
|
cast = await s_stormtypes.tostr(cast, noneok=True)
|
|
31
42
|
|
|
43
|
+
if self.runt.snap.core.stormlog:
|
|
44
|
+
extra = await self.runt.snap.core.getLogExtra(text=text)
|
|
45
|
+
stormlogger.info(f'Executing storm query via $lib.storm.eval() {{{text}}} as [{self.runt.user.name}]', extra=extra)
|
|
46
|
+
|
|
32
47
|
casttype = None
|
|
33
48
|
if cast:
|
|
34
49
|
|