synapse 2.197.0__py311-none-any.whl → 2.198.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/axon.py +3 -0
- synapse/common.py +3 -0
- synapse/cortex.py +1 -3
- synapse/lib/aha.py +3 -0
- synapse/lib/ast.py +277 -165
- synapse/lib/auth.py +39 -11
- synapse/lib/cell.py +22 -4
- synapse/lib/hive.py +2 -1
- synapse/lib/hiveauth.py +10 -1
- synapse/lib/jsonstor.py +6 -5
- synapse/lib/layer.py +6 -5
- synapse/lib/node.py +10 -4
- synapse/lib/parser.py +46 -21
- synapse/lib/schemas.py +13 -0
- synapse/lib/snap.py +68 -26
- synapse/lib/storm.lark +13 -11
- synapse/lib/storm.py +1 -1
- synapse/lib/storm_format.py +3 -2
- synapse/lib/stormtypes.py +13 -4
- synapse/lib/version.py +2 -2
- synapse/models/infotech.py +18 -0
- synapse/models/risk.py +9 -0
- synapse/models/syn.py +18 -2
- synapse/tests/files/stormpkg/badendpoints.yaml +7 -0
- synapse/tests/files/stormpkg/testpkg.yaml +8 -0
- synapse/tests/test_cortex.py +108 -0
- synapse/tests/test_lib_aha.py +12 -2
- synapse/tests/test_lib_ast.py +57 -0
- synapse/tests/test_lib_auth.py +143 -2
- synapse/tests/test_lib_grammar.py +54 -2
- synapse/tests/test_lib_lmdbslab.py +24 -0
- synapse/tests/test_lib_storm.py +20 -0
- synapse/tests/test_lib_stormlib_macro.py +3 -3
- synapse/tests/test_lib_stormtypes.py +14 -2
- synapse/tests/test_model_infotech.py +13 -0
- synapse/tests/test_model_risk.py +6 -0
- synapse/tests/test_model_syn.py +58 -0
- synapse/tests/test_tools_genpkg.py +10 -0
- synapse/tools/hive/load.py +1 -0
- {synapse-2.197.0.dist-info → synapse-2.198.0.dist-info}/METADATA +1 -1
- {synapse-2.197.0.dist-info → synapse-2.198.0.dist-info}/RECORD +44 -43
- {synapse-2.197.0.dist-info → synapse-2.198.0.dist-info}/LICENSE +0 -0
- {synapse-2.197.0.dist-info → synapse-2.198.0.dist-info}/WHEEL +0 -0
- {synapse-2.197.0.dist-info → synapse-2.198.0.dist-info}/top_level.txt +0 -0
synapse/axon.py
CHANGED
|
@@ -1017,6 +1017,7 @@ class Axon(s_cell.Cell):
|
|
|
1017
1017
|
'''
|
|
1018
1018
|
for item in self.axonhist.carve(tick, tock=tock):
|
|
1019
1019
|
yield item
|
|
1020
|
+
await asyncio.sleep(0)
|
|
1020
1021
|
|
|
1021
1022
|
async def hashes(self, offs, wait=False, timeout=None):
|
|
1022
1023
|
'''
|
|
@@ -1086,10 +1087,12 @@ class Axon(s_cell.Cell):
|
|
|
1086
1087
|
|
|
1087
1088
|
async for byts in self._getBytsOffsSize(sha256, offs, size):
|
|
1088
1089
|
yield byts
|
|
1090
|
+
await asyncio.sleep(0)
|
|
1089
1091
|
|
|
1090
1092
|
else:
|
|
1091
1093
|
async for byts in self._get(sha256):
|
|
1092
1094
|
yield byts
|
|
1095
|
+
await asyncio.sleep(0)
|
|
1093
1096
|
|
|
1094
1097
|
async def _get(self, sha256):
|
|
1095
1098
|
|
synapse/common.py
CHANGED
|
@@ -1222,6 +1222,9 @@ def trimText(text: str, n: int = 256, placeholder: str = '...') -> str:
|
|
|
1222
1222
|
assert n > plen
|
|
1223
1223
|
return f'{text[:mlen]}{placeholder}'
|
|
1224
1224
|
|
|
1225
|
+
def queryhash(text):
|
|
1226
|
+
return hashlib.md5(text.encode(errors='surrogatepass'), usedforsecurity=False).hexdigest()
|
|
1227
|
+
|
|
1225
1228
|
def _patch_http_cookies():
|
|
1226
1229
|
'''
|
|
1227
1230
|
Patch stdlib http.cookies._unquote from the 3.11.10 implementation if
|
synapse/cortex.py
CHANGED
|
@@ -4656,10 +4656,8 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
4656
4656
|
if not path:
|
|
4657
4657
|
return await self.cellapi.anit(self, link, user)
|
|
4658
4658
|
|
|
4659
|
-
# allow an admin to directly open the cortex hive
|
|
4660
|
-
# (perhaps this should be a Cell() level pattern)
|
|
4661
4659
|
if path[0] == 'hive' and user.isAdmin():
|
|
4662
|
-
s_common.deprecated('Cortex /hive telepath path', curv='2.
|
|
4660
|
+
s_common.deprecated('Cortex /hive telepath path', curv='2.198.0', eolv='2.199.0')
|
|
4663
4661
|
return await self.hiveapi.anit(self.hive, user)
|
|
4664
4662
|
|
|
4665
4663
|
if path[0] == 'layer':
|
synapse/lib/aha.py
CHANGED
|
@@ -1592,6 +1592,7 @@ class AhaCell(s_cell.Cell):
|
|
|
1592
1592
|
self.slab.delete(iden, db='aha:provs')
|
|
1593
1593
|
provinfo = s_msgpack.un(byts)
|
|
1594
1594
|
logger.info(f'Deleted service provisioning service={provinfo.get("conf").get("aha:name")}, iden={iden.decode()}')
|
|
1595
|
+
await asyncio.sleep(0)
|
|
1595
1596
|
|
|
1596
1597
|
@s_nexus.Pusher.onPushAuto('aha:enroll:clear')
|
|
1597
1598
|
async def clearAhaUserEnrolls(self):
|
|
@@ -1599,6 +1600,7 @@ class AhaCell(s_cell.Cell):
|
|
|
1599
1600
|
self.slab.delete(iden, db='aha:enrolls')
|
|
1600
1601
|
userinfo = s_msgpack.un(byts)
|
|
1601
1602
|
logger.info(f'Deleted user enrollment username={userinfo.get("name")}, iden={iden.decode()}')
|
|
1603
|
+
await asyncio.sleep(0)
|
|
1602
1604
|
|
|
1603
1605
|
@s_nexus.Pusher.onPushAuto('aha:clone:clear')
|
|
1604
1606
|
async def clearAhaClones(self):
|
|
@@ -1606,6 +1608,7 @@ class AhaCell(s_cell.Cell):
|
|
|
1606
1608
|
self.slab.delete(lkey, db='aha:clones')
|
|
1607
1609
|
cloninfo = s_msgpack.un(byts)
|
|
1608
1610
|
logger.info(f'Deleted AHA clone enrollment username={cloninfo.get("host")}, iden={s_common.ehex(lkey)}')
|
|
1611
|
+
await asyncio.sleep(0)
|
|
1609
1612
|
|
|
1610
1613
|
@s_nexus.Pusher.onPushAuto('aha:svc:prov:del')
|
|
1611
1614
|
async def delAhaSvcProv(self, iden):
|
synapse/lib/ast.py
CHANGED
|
@@ -62,7 +62,7 @@ class AstNode:
|
|
|
62
62
|
|
|
63
63
|
def getPosInfo(self):
|
|
64
64
|
return {
|
|
65
|
-
'hash':
|
|
65
|
+
'hash': s_common.queryhash(self.astinfo.text),
|
|
66
66
|
'lines': (self.astinfo.sline, self.astinfo.eline),
|
|
67
67
|
'columns': (self.astinfo.scol, self.astinfo.ecol),
|
|
68
68
|
'offsets': (self.astinfo.soff, self.astinfo.eoff),
|
|
@@ -699,7 +699,92 @@ class SubGraph:
|
|
|
699
699
|
yield node, path
|
|
700
700
|
|
|
701
701
|
class Oper(AstNode):
|
|
702
|
-
|
|
702
|
+
|
|
703
|
+
async def yieldFromValu(self, runt, valu, vkid):
|
|
704
|
+
|
|
705
|
+
viewiden = runt.snap.view.iden
|
|
706
|
+
|
|
707
|
+
# there is nothing in None... ;)
|
|
708
|
+
if valu is None:
|
|
709
|
+
return
|
|
710
|
+
|
|
711
|
+
# a little DWIM on what we get back...
|
|
712
|
+
# ( most common case will be stormtypes libs agenr -> iden|buid )
|
|
713
|
+
# buid list -> nodes
|
|
714
|
+
if isinstance(valu, bytes):
|
|
715
|
+
node = await runt.snap.getNodeByBuid(valu)
|
|
716
|
+
if node is not None:
|
|
717
|
+
yield node
|
|
718
|
+
|
|
719
|
+
return
|
|
720
|
+
|
|
721
|
+
# iden list -> nodes
|
|
722
|
+
if isinstance(valu, str):
|
|
723
|
+
try:
|
|
724
|
+
buid = s_common.uhex(valu)
|
|
725
|
+
except binascii.Error:
|
|
726
|
+
mesg = 'Yield string must be iden in hexdecimal. Got: %r' % (valu,)
|
|
727
|
+
raise vkid.addExcInfo(s_exc.BadLiftValu(mesg=mesg))
|
|
728
|
+
|
|
729
|
+
node = await runt.snap.getNodeByBuid(buid)
|
|
730
|
+
if node is not None:
|
|
731
|
+
yield node
|
|
732
|
+
|
|
733
|
+
return
|
|
734
|
+
|
|
735
|
+
if isinstance(valu, types.AsyncGeneratorType):
|
|
736
|
+
try:
|
|
737
|
+
async for item in valu:
|
|
738
|
+
async for node in self.yieldFromValu(runt, item, vkid):
|
|
739
|
+
yield node
|
|
740
|
+
finally:
|
|
741
|
+
await valu.aclose()
|
|
742
|
+
return
|
|
743
|
+
|
|
744
|
+
if isinstance(valu, types.GeneratorType):
|
|
745
|
+
try:
|
|
746
|
+
for item in valu:
|
|
747
|
+
async for node in self.yieldFromValu(runt, item, vkid):
|
|
748
|
+
yield node
|
|
749
|
+
finally:
|
|
750
|
+
valu.close()
|
|
751
|
+
return
|
|
752
|
+
|
|
753
|
+
if isinstance(valu, (list, tuple, set)):
|
|
754
|
+
for item in valu:
|
|
755
|
+
async for node in self.yieldFromValu(runt, item, vkid):
|
|
756
|
+
yield node
|
|
757
|
+
return
|
|
758
|
+
|
|
759
|
+
if isinstance(valu, s_stormtypes.Node):
|
|
760
|
+
valu = valu.valu
|
|
761
|
+
if valu.snap.view.iden != viewiden:
|
|
762
|
+
mesg = f'Node is not from the current view. Node {valu.iden()} is from {valu.snap.view.iden} expected {viewiden}'
|
|
763
|
+
raise vkid.addExcInfo(s_exc.BadLiftValu(mesg=mesg))
|
|
764
|
+
yield valu
|
|
765
|
+
return
|
|
766
|
+
|
|
767
|
+
if isinstance(valu, s_node.Node):
|
|
768
|
+
if valu.snap.view.iden != viewiden:
|
|
769
|
+
mesg = f'Node is not from the current view. Node {valu.iden()} is from {valu.snap.view.iden} expected {viewiden}'
|
|
770
|
+
raise vkid.addExcInfo(s_exc.BadLiftValu(mesg=mesg))
|
|
771
|
+
yield valu
|
|
772
|
+
return
|
|
773
|
+
|
|
774
|
+
if isinstance(valu, (s_stormtypes.List, s_stormtypes.Set)):
|
|
775
|
+
for item in valu.valu:
|
|
776
|
+
async for node in self.yieldFromValu(runt, item, vkid):
|
|
777
|
+
yield node
|
|
778
|
+
return
|
|
779
|
+
|
|
780
|
+
if isinstance(valu, s_stormtypes.Prim):
|
|
781
|
+
async with contextlib.aclosing(valu.nodes()) as genr:
|
|
782
|
+
async for node in genr:
|
|
783
|
+
if node.snap.view.iden != viewiden:
|
|
784
|
+
mesg = f'Node is not from the current view. Node {node.iden()} is from {node.snap.view.iden} expected {viewiden}'
|
|
785
|
+
raise vkid.addExcInfo(s_exc.BadLiftValu(mesg=mesg))
|
|
786
|
+
yield node
|
|
787
|
+
return
|
|
703
788
|
|
|
704
789
|
class SubQuery(Oper):
|
|
705
790
|
|
|
@@ -1534,106 +1619,21 @@ class YieldValu(Oper):
|
|
|
1534
1619
|
async def run(self, runt, genr):
|
|
1535
1620
|
|
|
1536
1621
|
node = None
|
|
1622
|
+
vkid = self.kids[0]
|
|
1537
1623
|
|
|
1538
1624
|
async for node, path in genr:
|
|
1539
|
-
valu = await
|
|
1540
|
-
async with contextlib.aclosing(self.yieldFromValu(runt, valu)) as agen:
|
|
1625
|
+
valu = await vkid.compute(runt, path)
|
|
1626
|
+
async with contextlib.aclosing(self.yieldFromValu(runt, valu, vkid)) as agen:
|
|
1541
1627
|
async for subn in agen:
|
|
1542
1628
|
yield subn, runt.initPath(subn)
|
|
1543
1629
|
yield node, path
|
|
1544
1630
|
|
|
1545
1631
|
if node is None and self.kids[0].isRuntSafe(runt):
|
|
1546
|
-
valu = await
|
|
1547
|
-
async with contextlib.aclosing(self.yieldFromValu(runt, valu)) as agen:
|
|
1632
|
+
valu = await vkid.compute(runt, None)
|
|
1633
|
+
async with contextlib.aclosing(self.yieldFromValu(runt, valu, vkid)) as agen:
|
|
1548
1634
|
async for subn in agen:
|
|
1549
1635
|
yield subn, runt.initPath(subn)
|
|
1550
1636
|
|
|
1551
|
-
async def yieldFromValu(self, runt, valu):
|
|
1552
|
-
|
|
1553
|
-
viewiden = runt.snap.view.iden
|
|
1554
|
-
|
|
1555
|
-
# there is nothing in None... ;)
|
|
1556
|
-
if valu is None:
|
|
1557
|
-
return
|
|
1558
|
-
|
|
1559
|
-
# a little DWIM on what we get back...
|
|
1560
|
-
# ( most common case will be stormtypes libs agenr -> iden|buid )
|
|
1561
|
-
# buid list -> nodes
|
|
1562
|
-
if isinstance(valu, bytes):
|
|
1563
|
-
node = await runt.snap.getNodeByBuid(valu)
|
|
1564
|
-
if node is not None:
|
|
1565
|
-
yield node
|
|
1566
|
-
|
|
1567
|
-
return
|
|
1568
|
-
|
|
1569
|
-
# iden list -> nodes
|
|
1570
|
-
if isinstance(valu, str):
|
|
1571
|
-
try:
|
|
1572
|
-
buid = s_common.uhex(valu)
|
|
1573
|
-
except binascii.Error:
|
|
1574
|
-
mesg = 'Yield string must be iden in hexdecimal. Got: %r' % (valu,)
|
|
1575
|
-
raise self.kids[0].addExcInfo(s_exc.BadLiftValu(mesg=mesg))
|
|
1576
|
-
|
|
1577
|
-
node = await runt.snap.getNodeByBuid(buid)
|
|
1578
|
-
if node is not None:
|
|
1579
|
-
yield node
|
|
1580
|
-
|
|
1581
|
-
return
|
|
1582
|
-
|
|
1583
|
-
if isinstance(valu, types.AsyncGeneratorType):
|
|
1584
|
-
try:
|
|
1585
|
-
async for item in valu:
|
|
1586
|
-
async for node in self.yieldFromValu(runt, item):
|
|
1587
|
-
yield node
|
|
1588
|
-
finally:
|
|
1589
|
-
await valu.aclose()
|
|
1590
|
-
return
|
|
1591
|
-
|
|
1592
|
-
if isinstance(valu, types.GeneratorType):
|
|
1593
|
-
try:
|
|
1594
|
-
for item in valu:
|
|
1595
|
-
async for node in self.yieldFromValu(runt, item):
|
|
1596
|
-
yield node
|
|
1597
|
-
finally:
|
|
1598
|
-
valu.close()
|
|
1599
|
-
return
|
|
1600
|
-
|
|
1601
|
-
if isinstance(valu, (list, tuple, set)):
|
|
1602
|
-
for item in valu:
|
|
1603
|
-
async for node in self.yieldFromValu(runt, item):
|
|
1604
|
-
yield node
|
|
1605
|
-
return
|
|
1606
|
-
|
|
1607
|
-
if isinstance(valu, s_stormtypes.Node):
|
|
1608
|
-
valu = valu.valu
|
|
1609
|
-
if valu.snap.view.iden != viewiden:
|
|
1610
|
-
mesg = f'Node is not from the current view. Node {valu.iden()} is from {valu.snap.view.iden} expected {viewiden}'
|
|
1611
|
-
raise s_exc.BadLiftValu(mesg=mesg)
|
|
1612
|
-
yield valu
|
|
1613
|
-
return
|
|
1614
|
-
|
|
1615
|
-
if isinstance(valu, s_node.Node):
|
|
1616
|
-
if valu.snap.view.iden != viewiden:
|
|
1617
|
-
mesg = f'Node is not from the current view. Node {valu.iden()} is from {valu.snap.view.iden} expected {viewiden}'
|
|
1618
|
-
raise s_exc.BadLiftValu(mesg=mesg)
|
|
1619
|
-
yield valu
|
|
1620
|
-
return
|
|
1621
|
-
|
|
1622
|
-
if isinstance(valu, (s_stormtypes.List, s_stormtypes.Set)):
|
|
1623
|
-
for item in valu.valu:
|
|
1624
|
-
async for node in self.yieldFromValu(runt, item):
|
|
1625
|
-
yield node
|
|
1626
|
-
return
|
|
1627
|
-
|
|
1628
|
-
if isinstance(valu, s_stormtypes.Prim):
|
|
1629
|
-
async with contextlib.aclosing(valu.nodes()) as genr:
|
|
1630
|
-
async for node in genr:
|
|
1631
|
-
if node.snap.view.iden != viewiden:
|
|
1632
|
-
mesg = f'Node is not from the current view. Node {node.iden()} is from {node.snap.view.iden} expected {viewiden}'
|
|
1633
|
-
raise s_exc.BadLiftValu(mesg=mesg)
|
|
1634
|
-
yield node
|
|
1635
|
-
return
|
|
1636
|
-
|
|
1637
1637
|
class LiftTag(LiftOper):
|
|
1638
1638
|
|
|
1639
1639
|
async def lift(self, runt, path):
|
|
@@ -4370,6 +4370,83 @@ class EditPropSet(Edit):
|
|
|
4370
4370
|
|
|
4371
4371
|
await asyncio.sleep(0)
|
|
4372
4372
|
|
|
4373
|
+
class EditPropSetMulti(Edit):
|
|
4374
|
+
|
|
4375
|
+
async def run(self, runt, genr):
|
|
4376
|
+
|
|
4377
|
+
self.reqNotReadOnly(runt)
|
|
4378
|
+
|
|
4379
|
+
rval = self.kids[2]
|
|
4380
|
+
oper = await self.kids[1].compute(runt, None)
|
|
4381
|
+
|
|
4382
|
+
isadd = '+' in oper
|
|
4383
|
+
excignore = (s_exc.BadTypeValu,) if '?' in oper else ()
|
|
4384
|
+
|
|
4385
|
+
async for node, path in genr:
|
|
4386
|
+
|
|
4387
|
+
propname = await self.kids[0].compute(runt, path)
|
|
4388
|
+
name = await tostr(propname)
|
|
4389
|
+
|
|
4390
|
+
prop = node.form.props.get(name)
|
|
4391
|
+
if prop is None:
|
|
4392
|
+
if (exc := await s_stormtypes.typeerr(propname, str)) is None:
|
|
4393
|
+
exc = s_exc.NoSuchProp.init(f'{node.form.name}:{name}')
|
|
4394
|
+
|
|
4395
|
+
raise self.kids[0].addExcInfo(exc)
|
|
4396
|
+
|
|
4397
|
+
runt.confirmPropSet(prop)
|
|
4398
|
+
|
|
4399
|
+
if not prop.type.isarray:
|
|
4400
|
+
mesg = f'Property set using ({oper}) is only valid on arrays.'
|
|
4401
|
+
exc = s_exc.StormRuntimeError(mesg=mesg)
|
|
4402
|
+
raise self.kids[0].addExcInfo(exc)
|
|
4403
|
+
|
|
4404
|
+
if isinstance(rval, SubQuery):
|
|
4405
|
+
valu = await rval.compute_array(runt, path)
|
|
4406
|
+
else:
|
|
4407
|
+
valu = await rval.compute(runt, path)
|
|
4408
|
+
|
|
4409
|
+
if valu is None:
|
|
4410
|
+
yield node, path
|
|
4411
|
+
await asyncio.sleep(0)
|
|
4412
|
+
continue
|
|
4413
|
+
|
|
4414
|
+
atyp = prop.type.arraytype
|
|
4415
|
+
isndef = isinstance(atyp, s_types.Ndef)
|
|
4416
|
+
valu = await s_stormtypes.tostor(valu, isndef=isndef)
|
|
4417
|
+
|
|
4418
|
+
if (arry := node.get(name)) is None:
|
|
4419
|
+
arry = ()
|
|
4420
|
+
|
|
4421
|
+
arry = list(arry)
|
|
4422
|
+
|
|
4423
|
+
try:
|
|
4424
|
+
for item in valu:
|
|
4425
|
+
await asyncio.sleep(0)
|
|
4426
|
+
|
|
4427
|
+
try:
|
|
4428
|
+
norm, info = atyp.norm(item)
|
|
4429
|
+
except excignore:
|
|
4430
|
+
continue
|
|
4431
|
+
|
|
4432
|
+
if isadd:
|
|
4433
|
+
arry.append(norm)
|
|
4434
|
+
else:
|
|
4435
|
+
try:
|
|
4436
|
+
arry.remove(norm)
|
|
4437
|
+
except ValueError:
|
|
4438
|
+
pass
|
|
4439
|
+
|
|
4440
|
+
except TypeError:
|
|
4441
|
+
styp = await s_stormtypes.totype(valu, basetypes=True)
|
|
4442
|
+
mesg = f"'{styp}' object is not iterable: {s_common.trimText(repr(valu))}"
|
|
4443
|
+
raise rval.addExcInfo(s_exc.StormRuntimeError(mesg=mesg, type=styp)) from None
|
|
4444
|
+
|
|
4445
|
+
await node.set(name, arry)
|
|
4446
|
+
|
|
4447
|
+
yield node, path
|
|
4448
|
+
await asyncio.sleep(0)
|
|
4449
|
+
|
|
4373
4450
|
class EditPropDel(Edit):
|
|
4374
4451
|
|
|
4375
4452
|
async def run(self, runt, genr):
|
|
@@ -4578,17 +4655,27 @@ class EditEdgeAdd(Edit):
|
|
|
4578
4655
|
|
|
4579
4656
|
self.reqNotReadOnly(runt)
|
|
4580
4657
|
|
|
4581
|
-
|
|
4582
|
-
|
|
4658
|
+
constverb = False
|
|
4659
|
+
if self.kids[0].isconst:
|
|
4660
|
+
constverb = True
|
|
4661
|
+
verb = await tostr(await self.kids[0].compute(runt, None))
|
|
4662
|
+
runt.layerConfirm(('node', 'edge', 'add', verb))
|
|
4663
|
+
else:
|
|
4664
|
+
hits = set()
|
|
4665
|
+
def allowed(x):
|
|
4666
|
+
if x in hits:
|
|
4667
|
+
return
|
|
4583
4668
|
|
|
4584
|
-
|
|
4669
|
+
runt.layerConfirm(('node', 'edge', 'add', x))
|
|
4670
|
+
hits.add(x)
|
|
4585
4671
|
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
return
|
|
4672
|
+
isvar = False
|
|
4673
|
+
vkid = self.kids[1]
|
|
4589
4674
|
|
|
4590
|
-
|
|
4591
|
-
|
|
4675
|
+
if not isinstance(vkid, SubQuery):
|
|
4676
|
+
isvar = True
|
|
4677
|
+
else:
|
|
4678
|
+
query = vkid.kids[0]
|
|
4592
4679
|
|
|
4593
4680
|
async for node, path in genr:
|
|
4594
4681
|
|
|
@@ -4596,38 +4683,44 @@ class EditEdgeAdd(Edit):
|
|
|
4596
4683
|
mesg = f'Edges cannot be used with runt nodes: {node.form.full}'
|
|
4597
4684
|
raise self.addExcInfo(s_exc.IsRuntForm(mesg=mesg, form=node.form.full))
|
|
4598
4685
|
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4686
|
+
if not constverb:
|
|
4687
|
+
verb = await tostr(await self.kids[0].compute(runt, path))
|
|
4688
|
+
allowed(verb)
|
|
4689
|
+
|
|
4690
|
+
if isvar:
|
|
4691
|
+
valu = await vkid.compute(runt, path)
|
|
4692
|
+
async with contextlib.aclosing(self.yieldFromValu(runt, valu, vkid)) as agen:
|
|
4693
|
+
if self.n2:
|
|
4694
|
+
iden = node.iden()
|
|
4695
|
+
async for subn in agen:
|
|
4696
|
+
await subn.addEdge(verb, iden, extra=self.addExcInfo)
|
|
4697
|
+
else:
|
|
4698
|
+
async with node.snap.getEditor() as editor:
|
|
4699
|
+
proto = editor.loadNode(node)
|
|
4700
|
+
async for subn in agen:
|
|
4701
|
+
if subn.form.isrunt:
|
|
4702
|
+
mesg = f'Edges cannot be used with runt nodes: {subn.form.full}'
|
|
4703
|
+
raise self.addExcInfo(s_exc.IsRuntForm(mesg=mesg, form=subn.form.full))
|
|
4704
|
+
|
|
4705
|
+
await proto.addEdge(verb, subn.iden())
|
|
4706
|
+
await asyncio.sleep(0)
|
|
4617
4707
|
|
|
4708
|
+
else:
|
|
4709
|
+
async with runt.getSubRuntime(query) as subr:
|
|
4710
|
+
if self.n2:
|
|
4711
|
+
iden = node.iden()
|
|
4618
4712
|
async for subn, subp in subr.execute():
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
proto.edges.clear()
|
|
4713
|
+
await subn.addEdge(verb, iden, extra=self.addExcInfo)
|
|
4714
|
+
else:
|
|
4715
|
+
async with node.snap.getEditor() as editor:
|
|
4716
|
+
proto = editor.loadNode(node)
|
|
4717
|
+
async for subn, subp in subr.execute():
|
|
4718
|
+
if subn.form.isrunt:
|
|
4719
|
+
mesg = f'Edges cannot be used with runt nodes: {subn.form.full}'
|
|
4720
|
+
raise self.addExcInfo(s_exc.IsRuntForm(mesg=mesg, form=subn.form.full))
|
|
4721
|
+
|
|
4722
|
+
await proto.addEdge(verb, subn.iden())
|
|
4723
|
+
await asyncio.sleep(0)
|
|
4631
4724
|
|
|
4632
4725
|
yield node, path
|
|
4633
4726
|
|
|
@@ -4641,16 +4734,27 @@ class EditEdgeDel(Edit):
|
|
|
4641
4734
|
|
|
4642
4735
|
self.reqNotReadOnly(runt)
|
|
4643
4736
|
|
|
4644
|
-
|
|
4737
|
+
isvar = False
|
|
4738
|
+
vkid = self.kids[1]
|
|
4645
4739
|
|
|
4646
|
-
|
|
4740
|
+
if not isinstance(vkid, SubQuery):
|
|
4741
|
+
isvar = True
|
|
4742
|
+
else:
|
|
4743
|
+
query = vkid.kids[0]
|
|
4647
4744
|
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4745
|
+
constverb = False
|
|
4746
|
+
if self.kids[0].isconst:
|
|
4747
|
+
constverb = True
|
|
4748
|
+
verb = await tostr(await self.kids[0].compute(runt, None))
|
|
4749
|
+
runt.layerConfirm(('node', 'edge', 'del', verb))
|
|
4750
|
+
else:
|
|
4751
|
+
hits = set()
|
|
4752
|
+
def allowed(x):
|
|
4753
|
+
if x in hits:
|
|
4754
|
+
return
|
|
4651
4755
|
|
|
4652
|
-
|
|
4653
|
-
|
|
4756
|
+
runt.layerConfirm(('node', 'edge', 'del', x))
|
|
4757
|
+
hits.add(x)
|
|
4654
4758
|
|
|
4655
4759
|
async for node, path in genr:
|
|
4656
4760
|
|
|
@@ -4658,36 +4762,44 @@ class EditEdgeDel(Edit):
|
|
|
4658
4762
|
mesg = f'Edges cannot be used with runt nodes: {node.form.full}'
|
|
4659
4763
|
raise self.addExcInfo(s_exc.IsRuntForm(mesg=mesg, form=node.form.full))
|
|
4660
4764
|
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4765
|
+
if not constverb:
|
|
4766
|
+
verb = await tostr(await self.kids[0].compute(runt, path))
|
|
4767
|
+
allowed(verb)
|
|
4768
|
+
|
|
4769
|
+
if isvar:
|
|
4770
|
+
valu = await vkid.compute(runt, path)
|
|
4771
|
+
async with contextlib.aclosing(self.yieldFromValu(runt, valu, vkid)) as agen:
|
|
4772
|
+
if self.n2:
|
|
4773
|
+
iden = node.iden()
|
|
4774
|
+
async for subn in agen:
|
|
4775
|
+
await subn.delEdge(verb, iden, extra=self.addExcInfo)
|
|
4776
|
+
else:
|
|
4777
|
+
async with node.snap.getEditor() as editor:
|
|
4778
|
+
proto = editor.loadNode(node)
|
|
4779
|
+
async for subn in agen:
|
|
4780
|
+
if subn.form.isrunt:
|
|
4781
|
+
mesg = f'Edges cannot be used with runt nodes: {subn.form.full}'
|
|
4782
|
+
raise self.addExcInfo(s_exc.IsRuntForm(mesg=mesg, form=subn.form.full))
|
|
4783
|
+
|
|
4784
|
+
await proto.delEdge(verb, subn.iden())
|
|
4785
|
+
await asyncio.sleep(0)
|
|
4677
4786
|
|
|
4787
|
+
else:
|
|
4788
|
+
async with runt.getSubRuntime(query) as subr:
|
|
4789
|
+
if self.n2:
|
|
4790
|
+
iden = node.iden()
|
|
4678
4791
|
async for subn, subp in subr.execute():
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
proto.edgedels.clear()
|
|
4792
|
+
await subn.delEdge(verb, iden, extra=self.addExcInfo)
|
|
4793
|
+
else:
|
|
4794
|
+
async with node.snap.getEditor() as editor:
|
|
4795
|
+
proto = editor.loadNode(node)
|
|
4796
|
+
async for subn, subp in subr.execute():
|
|
4797
|
+
if subn.form.isrunt:
|
|
4798
|
+
mesg = f'Edges cannot be used with runt nodes: {subn.form.full}'
|
|
4799
|
+
raise self.addExcInfo(s_exc.IsRuntForm(mesg=mesg, form=subn.form.full))
|
|
4800
|
+
|
|
4801
|
+
await proto.delEdge(verb, subn.iden())
|
|
4802
|
+
await asyncio.sleep(0)
|
|
4691
4803
|
|
|
4692
4804
|
yield node, path
|
|
4693
4805
|
|