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/ast.py
CHANGED
|
@@ -696,6 +696,9 @@ class SubQuery(Oper):
|
|
|
696
696
|
if len(kids):
|
|
697
697
|
self.text = kids[0].getAstText()
|
|
698
698
|
|
|
699
|
+
def isRuntSafe(self, runt):
|
|
700
|
+
return True
|
|
701
|
+
|
|
699
702
|
async def run(self, runt, genr):
|
|
700
703
|
|
|
701
704
|
subq = self.kids[0]
|
|
@@ -804,6 +807,38 @@ class InitBlock(AstNode):
|
|
|
804
807
|
async for innr in subq.run(runt, s_common.agen()):
|
|
805
808
|
yield innr
|
|
806
809
|
|
|
810
|
+
class EmptyBlock(AstNode):
|
|
811
|
+
'''
|
|
812
|
+
An AST node that only runs if there are not inbound nodes in the pipeline. It is
|
|
813
|
+
capable of yielding nodes into the pipeline.
|
|
814
|
+
|
|
815
|
+
Example:
|
|
816
|
+
|
|
817
|
+
Using an empty block::
|
|
818
|
+
|
|
819
|
+
empty {
|
|
820
|
+
// the pipeline is empty so this block will execute
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
[foo:bar=*]
|
|
824
|
+
empty {
|
|
825
|
+
// there is a node in the pipeline so this block will not run
|
|
826
|
+
}
|
|
827
|
+
'''
|
|
828
|
+
async def run(self, runt, genr):
|
|
829
|
+
|
|
830
|
+
subq = self.kids[0]
|
|
831
|
+
self.reqRuntSafe(runt, 'Empty block query must be runtsafe')
|
|
832
|
+
|
|
833
|
+
empty = True
|
|
834
|
+
async for item in genr:
|
|
835
|
+
empty = False
|
|
836
|
+
yield item
|
|
837
|
+
|
|
838
|
+
if empty:
|
|
839
|
+
async for subn in subq.run(runt, s_common.agen()):
|
|
840
|
+
yield subn
|
|
841
|
+
|
|
807
842
|
class FiniBlock(AstNode):
|
|
808
843
|
'''
|
|
809
844
|
An AST node that runs only once after all nodes have been consumed.
|
|
@@ -856,7 +891,7 @@ class TryCatch(AstNode):
|
|
|
856
891
|
async for subi in block.run(runt, agen):
|
|
857
892
|
yield subi
|
|
858
893
|
|
|
859
|
-
if count == 0
|
|
894
|
+
if count == 0:
|
|
860
895
|
try:
|
|
861
896
|
async for item in self.kids[0].run(runt, genr):
|
|
862
897
|
yield item
|
|
@@ -1866,6 +1901,9 @@ class N1WalkNPivo(PivotOut):
|
|
|
1866
1901
|
|
|
1867
1902
|
async for node, path in genr:
|
|
1868
1903
|
|
|
1904
|
+
if self.isjoin:
|
|
1905
|
+
yield node, path
|
|
1906
|
+
|
|
1869
1907
|
async for item in self.getPivsOut(runt, node, path):
|
|
1870
1908
|
yield item
|
|
1871
1909
|
|
|
@@ -1985,6 +2023,9 @@ class N2WalkNPivo(PivotIn):
|
|
|
1985
2023
|
|
|
1986
2024
|
async for node, path in genr:
|
|
1987
2025
|
|
|
2026
|
+
if self.isjoin:
|
|
2027
|
+
yield node, path
|
|
2028
|
+
|
|
1988
2029
|
async for item in self.getPivsIn(runt, node, path):
|
|
1989
2030
|
yield item
|
|
1990
2031
|
|
|
@@ -3028,6 +3069,10 @@ class PropValue(Value):
|
|
|
3028
3069
|
name=name, form=path.node.form.name))
|
|
3029
3070
|
|
|
3030
3071
|
valu = path.node.get(name)
|
|
3072
|
+
if isinstance(valu, (dict, list, tuple)):
|
|
3073
|
+
# these get special cased because changing them affects the node
|
|
3074
|
+
# while it's in the pipeline but the modification doesn't get stored
|
|
3075
|
+
valu = s_msgpack.deepcopy(valu)
|
|
3031
3076
|
return prop, valu
|
|
3032
3077
|
|
|
3033
3078
|
# handle implicit pivot properties
|
|
@@ -3049,6 +3094,10 @@ class PropValue(Value):
|
|
|
3049
3094
|
name=name, form=node.form.name))
|
|
3050
3095
|
|
|
3051
3096
|
if i >= imax:
|
|
3097
|
+
if isinstance(valu, (dict, list, tuple)):
|
|
3098
|
+
# these get special cased because changing them affects the node
|
|
3099
|
+
# while it's in the pipeline but the modification doesn't get stored
|
|
3100
|
+
valu = s_msgpack.deepcopy(valu)
|
|
3052
3101
|
return prop, valu
|
|
3053
3102
|
|
|
3054
3103
|
form = runt.model.forms.get(prop.type.name)
|
|
@@ -3900,6 +3949,13 @@ class EditUnivDel(Edit):
|
|
|
3900
3949
|
|
|
3901
3950
|
class N1Walk(Oper):
|
|
3902
3951
|
|
|
3952
|
+
def __init__(self, astinfo, kids=(), isjoin=False):
|
|
3953
|
+
Oper.__init__(self, astinfo, kids=kids)
|
|
3954
|
+
self.isjoin = isjoin
|
|
3955
|
+
|
|
3956
|
+
def repr(self):
|
|
3957
|
+
return f'{self.__class__.__name__}: {self.kids}, isjoin={self.isjoin}'
|
|
3958
|
+
|
|
3903
3959
|
async def walkNodeEdges(self, runt, node, verb=None):
|
|
3904
3960
|
async for _, iden in node.iterEdgesN1(verb=verb):
|
|
3905
3961
|
buid = s_common.uhex(iden)
|
|
@@ -3958,6 +4014,9 @@ class N1Walk(Oper):
|
|
|
3958
4014
|
|
|
3959
4015
|
async for node, path in genr:
|
|
3960
4016
|
|
|
4017
|
+
if self.isjoin:
|
|
4018
|
+
yield node, path
|
|
4019
|
+
|
|
3961
4020
|
verbs = await self.kids[0].compute(runt, path)
|
|
3962
4021
|
verbs = await s_stormtypes.toprim(verbs)
|
|
3963
4022
|
|
synapse/lib/cell.py
CHANGED
|
@@ -3420,20 +3420,45 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
3420
3420
|
ahaname = provconf.get('aha:name')
|
|
3421
3421
|
ahanetw = provconf.get('aha:network')
|
|
3422
3422
|
|
|
3423
|
-
|
|
3424
|
-
|
|
3423
|
+
_crt = certdir.getCaCertPath(ahanetw)
|
|
3424
|
+
if _crt:
|
|
3425
|
+
logger.debug(f'Removing existing CA crt: {_crt}')
|
|
3426
|
+
os.unlink(_crt)
|
|
3427
|
+
certdir.saveCaCertByts(await prov.getCaCert())
|
|
3425
3428
|
|
|
3426
3429
|
await self._bootProvConf(provconf)
|
|
3427
3430
|
|
|
3428
3431
|
hostname = f'{ahaname}.{ahanetw}'
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
+
_crt = certdir.getHostCertPath(hostname)
|
|
3433
|
+
if _crt:
|
|
3434
|
+
logger.debug(f'Removing existing host crt {_crt}')
|
|
3435
|
+
os.unlink(_crt)
|
|
3436
|
+
_kp = certdir.getHostKeyPath(hostname)
|
|
3437
|
+
if _kp:
|
|
3438
|
+
logger.debug(f'Removing existing host key {_kp}')
|
|
3439
|
+
os.unlink(_kp)
|
|
3440
|
+
_csr = certdir.getHostCsrPath(hostname)
|
|
3441
|
+
if _csr:
|
|
3442
|
+
logger.debug(f'Removing existing host csr {_csr}')
|
|
3443
|
+
os.unlink(_csr)
|
|
3444
|
+
hostcsr = certdir.genHostCsr(hostname)
|
|
3445
|
+
certdir.saveHostCertByts(await prov.signHostCsr(hostcsr))
|
|
3432
3446
|
|
|
3433
3447
|
userfull = f'{ahauser}@{ahanetw}'
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3448
|
+
_crt = certdir.getUserCertPath(userfull)
|
|
3449
|
+
if _crt:
|
|
3450
|
+
logger.debug(f'Removing existing user crt {_crt}')
|
|
3451
|
+
os.unlink(_crt)
|
|
3452
|
+
_kp = certdir.getUserKeyPath(userfull)
|
|
3453
|
+
if _kp:
|
|
3454
|
+
logger.debug(f'Removing existing user key {_kp}')
|
|
3455
|
+
os.unlink(_kp)
|
|
3456
|
+
_csr = certdir.getUserCsrPath(userfull)
|
|
3457
|
+
if _csr:
|
|
3458
|
+
logger.debug(f'Removing existing user csr {_csr}')
|
|
3459
|
+
os.unlink(_csr)
|
|
3460
|
+
usercsr = certdir.genUserCsr(userfull)
|
|
3461
|
+
certdir.saveUserCertByts(await prov.signUserCsr(usercsr))
|
|
3437
3462
|
|
|
3438
3463
|
with s_common.genfile(self.dirn, 'prov.done') as fd:
|
|
3439
3464
|
fd.write(providen.encode())
|
synapse/lib/certdir.py
CHANGED
|
@@ -944,6 +944,17 @@ class CertDir:
|
|
|
944
944
|
if os.path.isfile(path):
|
|
945
945
|
return path
|
|
946
946
|
|
|
947
|
+
def getUserCsrPath(self, name):
|
|
948
|
+
for cdir in self.certdirs:
|
|
949
|
+
path = s_common.genpath(cdir, 'users', '%s.csr' % name)
|
|
950
|
+
if os.path.isfile(path):
|
|
951
|
+
return path
|
|
952
|
+
|
|
953
|
+
def getHostCsrPath(self, name):
|
|
954
|
+
for cdir in self.certdirs:
|
|
955
|
+
path = s_common.genpath(cdir, 'hosts', '%s.csr' % name)
|
|
956
|
+
if os.path.isfile(path):
|
|
957
|
+
return path
|
|
947
958
|
def importFile(self, path, mode, outp=None):
|
|
948
959
|
'''
|
|
949
960
|
Imports certs and keys into the Synapse cert directory
|
synapse/lib/cmdr.py
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import synapse.lib.cli as s_cli
|
|
2
2
|
|
|
3
3
|
import synapse.cmds.boss as s_cmds_boss
|
|
4
|
-
import synapse.cmds.cron as s_cmds_cron
|
|
5
4
|
import synapse.cmds.hive as s_cmds_hive
|
|
6
5
|
import synapse.cmds.cortex as s_cmds_cortex
|
|
7
|
-
import synapse.cmds.trigger as s_cmds_trigger
|
|
8
6
|
|
|
9
7
|
cmdsbycell = {
|
|
10
8
|
'cell': (
|
|
@@ -14,14 +12,11 @@ cmdsbycell = {
|
|
|
14
12
|
),
|
|
15
13
|
|
|
16
14
|
'cortex': (
|
|
17
|
-
s_cmds_cron.At,
|
|
18
|
-
s_cmds_cron.Cron,
|
|
19
15
|
s_cmds_cortex.Log,
|
|
20
16
|
s_cmds_boss.PsCmd,
|
|
21
17
|
s_cmds_boss.KillCmd,
|
|
22
18
|
s_cmds_hive.HiveCmd,
|
|
23
19
|
s_cmds_cortex.StormCmd,
|
|
24
|
-
s_cmds_trigger.Trigger,
|
|
25
20
|
),
|
|
26
21
|
}
|
|
27
22
|
|
synapse/lib/gis.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import math
|
|
2
2
|
|
|
3
3
|
'''
|
|
4
|
-
Synapse module with helpers for earth based
|
|
4
|
+
Synapse module with helpers for earth based geospatial calculations.
|
|
5
5
|
'''
|
|
6
6
|
|
|
7
7
|
# base earth geo distances will be in mm
|
|
@@ -66,7 +66,7 @@ def haversine(px, py, r=r_mm):
|
|
|
66
66
|
|
|
67
67
|
def bbox(lat, lon, dist):
|
|
68
68
|
'''
|
|
69
|
-
Calculate a min/max bounding box for the circle defined by
|
|
69
|
+
Calculate a min/max bounding box for the circle defined by lat/lon/dist.
|
|
70
70
|
|
|
71
71
|
Args:
|
|
72
72
|
lat (float): The latitude in degrees
|
synapse/lib/httpapi.py
CHANGED
|
@@ -518,7 +518,7 @@ class StormV1(StormHandler):
|
|
|
518
518
|
if opts is None:
|
|
519
519
|
return
|
|
520
520
|
|
|
521
|
-
opts.setdefault('editformat', '
|
|
521
|
+
opts.setdefault('editformat', 'nodeedits')
|
|
522
522
|
|
|
523
523
|
async for mesg in self.getCore().storm(query, opts=opts):
|
|
524
524
|
self.write(json.dumps(mesg))
|
|
@@ -612,48 +612,6 @@ class ReqValidStormV1(StormHandler):
|
|
|
612
612
|
else:
|
|
613
613
|
return self.sendRestRetn(valid)
|
|
614
614
|
|
|
615
|
-
class WatchSockV1(WebSocket):
|
|
616
|
-
'''
|
|
617
|
-
A web-socket based API endpoint for distributing cortex tag events.
|
|
618
|
-
|
|
619
|
-
Deprecated.
|
|
620
|
-
'''
|
|
621
|
-
async def onWatchMesg(self, byts):
|
|
622
|
-
# Note: This API handler is intended to be used on a heavy Cortex object.
|
|
623
|
-
try:
|
|
624
|
-
|
|
625
|
-
wdef = json.loads(byts)
|
|
626
|
-
iden = wdef.get('view', self.cell.view.iden)
|
|
627
|
-
|
|
628
|
-
perm = ('watch', 'view', iden)
|
|
629
|
-
await self._reqUserAllow(perm)
|
|
630
|
-
|
|
631
|
-
async with self.cell.watcher(wdef) as watcher:
|
|
632
|
-
|
|
633
|
-
await self.xmit('init')
|
|
634
|
-
|
|
635
|
-
async for mesg in watcher:
|
|
636
|
-
await self.xmit(mesg[0], **mesg[1])
|
|
637
|
-
|
|
638
|
-
# pragma: no cover
|
|
639
|
-
# (this would only happen on slow-consumer)
|
|
640
|
-
await self.xmit('fini')
|
|
641
|
-
|
|
642
|
-
except s_exc.SynErr as e:
|
|
643
|
-
|
|
644
|
-
text = e.get('mesg', str(e))
|
|
645
|
-
await self.xmit('errx', code=e.__class__.__name__, mesg=text)
|
|
646
|
-
|
|
647
|
-
except asyncio.CancelledError: # pragma: no cover TODO: remove once >= py 3.8 only
|
|
648
|
-
raise
|
|
649
|
-
|
|
650
|
-
except Exception as e:
|
|
651
|
-
await self.xmit('errx', code=e.__class__.__name__, mesg=str(e))
|
|
652
|
-
|
|
653
|
-
async def on_message(self, byts):
|
|
654
|
-
s_common.deprdate('/api/v1/watch HTTP API', s_common._splicedepr)
|
|
655
|
-
self.cell.schedCoro(self.onWatchMesg(byts))
|
|
656
|
-
|
|
657
615
|
class BeholdSockV1(WebSocket):
|
|
658
616
|
|
|
659
617
|
async def onInitMessage(self, byts):
|
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
|