synapse 2.178.0__py311-none-any.whl → 2.179.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 (44) hide show
  1. synapse/cortex.py +162 -27
  2. synapse/datamodel.py +47 -1
  3. synapse/exc.py +1 -0
  4. synapse/lib/aha.py +2 -1
  5. synapse/lib/ast.py +26 -22
  6. synapse/lib/base.py +12 -3
  7. synapse/lib/cell.py +150 -11
  8. synapse/lib/coro.py +14 -0
  9. synapse/lib/drive.py +551 -0
  10. synapse/lib/schemas.py +39 -0
  11. synapse/lib/snap.py +17 -7
  12. synapse/lib/storm.py +3 -1
  13. synapse/lib/stormhttp.py +1 -0
  14. synapse/lib/stormlib/modelext.py +29 -3
  15. synapse/lib/stormlib/stix.py +40 -17
  16. synapse/lib/stormlib/vault.py +2 -2
  17. synapse/lib/stormtypes.py +1 -1
  18. synapse/lib/types.py +9 -0
  19. synapse/lib/version.py +2 -2
  20. synapse/lookup/pe.py +303 -38
  21. synapse/models/dns.py +24 -1
  22. synapse/models/geospace.py +4 -1
  23. synapse/models/infotech.py +26 -1
  24. synapse/tests/test_cortex.py +45 -1
  25. synapse/tests/test_lib_aha.py +17 -0
  26. synapse/tests/test_lib_cell.py +224 -0
  27. synapse/tests/test_lib_coro.py +12 -0
  28. synapse/tests/test_lib_stormhttp.py +40 -0
  29. synapse/tests/test_lib_stormlib_modelext.py +55 -3
  30. synapse/tests/test_lib_stormlib_stix.py +15 -0
  31. synapse/tests/test_lib_stormlib_vault.py +11 -1
  32. synapse/tests/test_lib_stormtypes.py +5 -0
  33. synapse/tests/test_lib_types.py +9 -0
  34. synapse/tests/test_model_dns.py +8 -0
  35. synapse/tests/test_model_geospace.py +3 -1
  36. synapse/tests/test_model_infotech.py +47 -0
  37. synapse/tests/test_model_syn.py +11 -0
  38. synapse/tests/test_utils_stormcov.py +1 -1
  39. synapse/tools/changelog.py +28 -0
  40. {synapse-2.178.0.dist-info → synapse-2.179.0.dist-info}/METADATA +1 -1
  41. {synapse-2.178.0.dist-info → synapse-2.179.0.dist-info}/RECORD +44 -43
  42. {synapse-2.178.0.dist-info → synapse-2.179.0.dist-info}/WHEEL +1 -1
  43. {synapse-2.178.0.dist-info → synapse-2.179.0.dist-info}/LICENSE +0 -0
  44. {synapse-2.178.0.dist-info → synapse-2.179.0.dist-info}/top_level.txt +0 -0
synapse/cortex.py CHANGED
@@ -1354,20 +1354,20 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
1354
1354
  'desc': 'Controls access to adding specific extended model properties.',
1355
1355
  'ex': 'model.prop.add._foo:bar'},
1356
1356
  {'perm': ('model', 'prop', 'del'), 'gate': 'cortex',
1357
- 'desc': 'Controls access to deleting extended model properties.'},
1357
+ 'desc': 'Controls access to deleting extended model properties and values.'},
1358
1358
  {'perm': ('model', 'prop', 'del', '<form>'), 'gate': 'cortex',
1359
- 'desc': 'Controls access to deleting specific extended model properties.',
1359
+ 'desc': 'Controls access to deleting specific extended model properties and values.',
1360
1360
  'ex': 'model.prop.del._foo:bar'},
1361
1361
 
1362
1362
  {'perm': ('model', 'tagprop', 'add'), 'gate': 'cortex',
1363
- 'desc': 'Controls access to adding extended model tag properties.'},
1363
+ 'desc': 'Controls access to adding extended model tag properties and values.'},
1364
1364
  {'perm': ('model', 'tagprop', 'del'), 'gate': 'cortex',
1365
- 'desc': 'Controls access to deleting extended model tag properties.'},
1365
+ 'desc': 'Controls access to deleting extended model tag properties and values.'},
1366
1366
 
1367
1367
  {'perm': ('model', 'univ', 'add'), 'gate': 'cortex',
1368
1368
  'desc': 'Controls access to adding extended model universal properties.'},
1369
1369
  {'perm': ('model', 'univ', 'del'), 'gate': 'cortex',
1370
- 'desc': 'Controls access to deleting extended model universal properties.'},
1370
+ 'desc': 'Controls access to deleting extended model universal properties and values.'},
1371
1371
 
1372
1372
  {'perm': ('node',), 'gate': 'layer',
1373
1373
  'desc': 'Controls all node edits in a layer.'},
@@ -1626,6 +1626,25 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
1626
1626
  if self.isactive:
1627
1627
  await self.finiStormPool()
1628
1628
 
1629
+ @s_nexus.Pusher.onPushAuto('model:lock:prop')
1630
+ async def setPropLocked(self, name, locked):
1631
+ prop = self.model.reqProp(name)
1632
+ self.modellocks.set(f'prop/{name}', locked)
1633
+ prop.locked = locked
1634
+
1635
+ @s_nexus.Pusher.onPushAuto('model:lock:univ')
1636
+ async def setUnivLocked(self, name, locked):
1637
+ prop = self.model.reqUniv(name)
1638
+ self.modellocks.set(f'univ/{name}', locked)
1639
+ for prop in self.model.getAllUnivs(name):
1640
+ prop.locked = locked
1641
+
1642
+ @s_nexus.Pusher.onPushAuto('model:lock:tagprop')
1643
+ async def setTagPropLocked(self, name, locked):
1644
+ prop = self.model.reqTagProp(name)
1645
+ self.modellocks.set(f'tagprop/{name}', locked)
1646
+ prop.locked = locked
1647
+
1629
1648
  @s_nexus.Pusher.onPushAuto('model:depr:lock')
1630
1649
  async def setDeprLock(self, name, locked):
1631
1650
 
@@ -2093,17 +2112,15 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
2093
2112
  async def onSetTrigDoc(node, prop, valu):
2094
2113
  valu = str(valu)
2095
2114
  iden = node.ndef[1]
2096
- trig = node.snap.view.triggers.get(iden)
2097
2115
  node.snap.user.confirm(('trigger', 'set', 'doc'), gateiden=iden)
2098
- await trig.set('doc', valu)
2116
+ await node.snap.view.setTriggerInfo(iden, 'doc', valu)
2099
2117
  node.props[prop.name] = valu
2100
2118
 
2101
2119
  async def onSetTrigName(node, prop, valu):
2102
2120
  valu = str(valu)
2103
2121
  iden = node.ndef[1]
2104
- trig = node.snap.view.triggers.get(iden)
2105
2122
  node.snap.user.confirm(('trigger', 'set', 'name'), gateiden=iden)
2106
- await trig.set('name', valu)
2123
+ await node.snap.view.setTriggerInfo(iden, 'name', valu)
2107
2124
  node.props[prop.name] = valu
2108
2125
 
2109
2126
  async def onSetCronDoc(node, prop, valu):
@@ -3437,7 +3454,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
3437
3454
 
3438
3455
  for layr in self.layers.values():
3439
3456
  async for item in layr.iterFormRows(formname):
3440
- mesg = f'Nodes still exist with form: {formname}'
3457
+ mesg = f'Nodes still exist with form: {formname} in layer {layr.iden}'
3441
3458
  raise s_exc.CantDelForm(mesg=mesg)
3442
3459
 
3443
3460
  self.model.delForm(formname)
@@ -3486,14 +3503,116 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
3486
3503
  await self.feedBeholder('model:prop:add', {'form': form, 'prop': prop.pack()})
3487
3504
 
3488
3505
  async def delFormProp(self, form, prop):
3506
+ self.reqExtProp(form, prop)
3507
+ return await self._push('model:prop:del', form, prop)
3508
+
3509
+ async def _delAllFormProp(self, formname, propname, meta):
3510
+ '''
3511
+ Delete all instances of a property from all layers.
3512
+
3513
+ NOTE: This does not fire triggers.
3514
+ '''
3515
+ self.reqExtProp(formname, propname)
3516
+
3517
+ fullname = f'{formname}:{propname}'
3518
+ prop = self.model.prop(fullname)
3519
+
3520
+ await self.setPropLocked(fullname, True)
3521
+
3522
+ for layr in list(self.layers.values()):
3523
+
3524
+ genr = layr.iterPropRows(formname, propname)
3525
+
3526
+ async for rows in s_coro.chunks(genr):
3527
+ nodeedits = []
3528
+ for buid, valu in rows:
3529
+ nodeedits.append((buid, prop.form.name, (
3530
+ (s_layer.EDIT_PROP_DEL, (prop.name, None, prop.type.stortype), ()),
3531
+ )))
3532
+
3533
+ await layr.saveNodeEdits(nodeedits, meta)
3534
+ await asyncio.sleep(0)
3535
+
3536
+ async def _delAllUnivProp(self, propname, meta):
3537
+ '''
3538
+ Delete all instances of a universal property from all layers.
3539
+
3540
+ NOTE: This does not fire triggers.
3541
+ '''
3542
+ self.reqExtUniv(propname)
3543
+
3544
+ full = f'.{propname}'
3545
+ prop = self.model.univ(full)
3546
+
3547
+ await self.setUnivLocked(full, True)
3548
+
3549
+ for layr in list(self.layers.values()):
3550
+
3551
+ genr = layr.iterUnivRows(full)
3552
+
3553
+ async for rows in s_coro.chunks(genr):
3554
+ nodeedits = []
3555
+ for buid, valu in rows:
3556
+ sode = await layr.getStorNode(buid)
3557
+ nodeedits.append((buid, sode.get('form'), (
3558
+ (s_layer.EDIT_PROP_DEL, (prop.name, None, prop.type.stortype), ()),
3559
+ )))
3560
+
3561
+ await layr.saveNodeEdits(nodeedits, meta)
3562
+ await asyncio.sleep(0)
3563
+
3564
+ async def _delAllTagProp(self, propname, meta):
3565
+ '''
3566
+ Delete all instances of a tag property from all layers.
3567
+
3568
+ NOTE: This does not fire triggers.
3569
+ '''
3570
+ self.reqExtTagProp(propname)
3571
+ prop = self.model.getTagProp(propname)
3572
+
3573
+ await self.setTagPropLocked(propname, True)
3574
+
3575
+ for layr in list(self.layers.values()):
3576
+
3577
+ for form, tag, tagprop in layr.getTagProps():
3578
+
3579
+ if tagprop != propname: # pragma: no cover
3580
+ await asyncio.sleep(0)
3581
+ continue
3582
+
3583
+ genr = layr.iterTagPropRows(tag, tagprop, form)
3584
+
3585
+ async for rows in s_coro.chunks(genr):
3586
+ nodeedits = []
3587
+ for buid, valu in rows:
3588
+ nodeedits.append((buid, form, (
3589
+ (s_layer.EDIT_TAGPROP_DEL, (tag, prop.name, None, prop.type.stortype), ()),
3590
+ )))
3591
+
3592
+ await layr.saveNodeEdits(nodeedits, meta)
3593
+ await asyncio.sleep(0)
3594
+
3595
+ def reqExtProp(self, form, prop):
3489
3596
  full = f'{form}:{prop}'
3490
3597
  pdef = self.extprops.get(full)
3491
-
3492
3598
  if pdef is None:
3493
3599
  mesg = f'No ext prop named {full}'
3494
3600
  raise s_exc.NoSuchProp(form=form, prop=prop, mesg=mesg)
3601
+ return pdef
3495
3602
 
3496
- return await self._push('model:prop:del', form, prop)
3603
+ def reqExtUniv(self, prop):
3604
+ udef = self.extunivs.get(prop)
3605
+ if udef is None:
3606
+ mesg = f'No ext univ named {prop}'
3607
+ raise s_exc.NoSuchUniv(name=prop, mesg=mesg)
3608
+ return udef
3609
+
3610
+ def reqExtTagProp(self, name):
3611
+ pdef = self.exttagprops.get(name)
3612
+ if pdef is None:
3613
+ mesg = f'No tag prop named {name}'
3614
+ raise s_exc.NoSuchTagProp(mesg=mesg, name=name)
3615
+ return pdef
3497
3616
 
3498
3617
  @s_nexus.Pusher.onPush('model:prop:del')
3499
3618
  async def _delFormProp(self, form, prop):
@@ -3508,22 +3627,19 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
3508
3627
 
3509
3628
  for layr in self.layers.values():
3510
3629
  async for item in layr.iterPropRows(form, prop):
3511
- mesg = f'Nodes still exist with prop: {form}:{prop}'
3630
+ mesg = f'Nodes still exist with prop: {form}:{prop} in layer {layr.iden}'
3512
3631
  raise s_exc.CantDelProp(mesg=mesg)
3513
3632
 
3514
3633
  self.model.delFormProp(form, prop)
3515
3634
  self.extprops.pop(full, None)
3635
+ self.modellocks.pop(f'prop/{full}', None)
3516
3636
  await self.fire('core:extmodel:change',
3517
3637
  form=form, prop=prop, act='del', type='formprop')
3518
3638
 
3519
3639
  await self.feedBeholder('model:prop:del', {'form': form, 'prop': prop})
3520
3640
 
3521
3641
  async def delUnivProp(self, prop):
3522
- udef = self.extunivs.get(prop)
3523
- if udef is None:
3524
- mesg = f'No ext univ named {prop}'
3525
- raise s_exc.NoSuchUniv(name=prop, mesg=mesg)
3526
-
3642
+ self.reqExtUniv(prop)
3527
3643
  return await self._push('model:univ:del', prop)
3528
3644
 
3529
3645
  @s_nexus.Pusher.onPush('model:univ:del')
@@ -3538,11 +3654,12 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
3538
3654
  univname = '.' + prop
3539
3655
  for layr in self.layers.values():
3540
3656
  async for item in layr.iterUnivRows(univname):
3541
- mesg = f'Nodes still exist with universal prop: {prop}'
3657
+ mesg = f'Nodes still exist with universal prop: {prop} in layer {layr.iden}'
3542
3658
  raise s_exc.CantDelUniv(mesg=mesg)
3543
3659
 
3544
3660
  self.model.delUnivProp(prop)
3545
3661
  self.extunivs.pop(prop, None)
3662
+ self.modellocks.pop(f'univ/{prop}', None)
3546
3663
  await self.fire('core:extmodel:change', name=prop, act='del', type='univ')
3547
3664
  await self.feedBeholder('model:univ:del', {'prop': univname})
3548
3665
 
@@ -3574,11 +3691,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
3574
3691
  await self.feedBeholder('model:tagprop:add', tagp.pack())
3575
3692
 
3576
3693
  async def delTagProp(self, name):
3577
- pdef = self.exttagprops.get(name)
3578
- if pdef is None:
3579
- mesg = f'No tag prop named {name}'
3580
- raise s_exc.NoSuchProp(mesg=mesg, name=name)
3581
-
3694
+ self.reqExtTagProp(name)
3582
3695
  return await self._push('model:tagprop:del', name)
3583
3696
 
3584
3697
  @s_nexus.Pusher.onPush('model:tagprop:del')
@@ -3589,12 +3702,13 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
3589
3702
 
3590
3703
  for layr in self.layers.values():
3591
3704
  if await layr.hasTagProp(name):
3592
- mesg = f'Nodes still exist with tagprop: {name}'
3705
+ mesg = f'Nodes still exist with tagprop: {name} in layer {layr.iden}'
3593
3706
  raise s_exc.CantDelProp(mesg=mesg)
3594
3707
 
3595
3708
  self.model.delTagProp(name)
3596
3709
 
3597
3710
  self.exttagprops.pop(name, None)
3711
+ self.modellocks.pop(f'tagprop/{name}', None)
3598
3712
  await self.fire('core:tagprop:change', name=name, act='del')
3599
3713
  await self.feedBeholder('model:tagprop:del', {'tagprop': name})
3600
3714
 
@@ -3941,7 +4055,10 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
3941
4055
  self.stormvars.set(s_stormlib_cell.runtime_fixes_key, s_stormlib_cell.getMaxHotFixes())
3942
4056
 
3943
4057
  async def _initDeprLocks(self):
4058
+
3944
4059
  self.deprlocks = self.cortexdata.getSubKeyVal('model:deprlocks:')
4060
+ self.modellocks = self.cortexdata.getSubKeyVal('model:locks:')
4061
+
3945
4062
  # TODO: 3.0.0 conversion will truncate this hive key
3946
4063
 
3947
4064
  if self.inaugural:
@@ -3967,6 +4084,24 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
3967
4084
  if _type is not None:
3968
4085
  _type.locked = locked
3969
4086
 
4087
+ for name, locked in self.modellocks.items():
4088
+
4089
+ prop = None
4090
+ elemtype, elemname = name.split('/', 1)
4091
+
4092
+ if elemtype == 'prop':
4093
+ prop = self.model.prop(elemname)
4094
+ elif elemtype == 'univ':
4095
+ prop = self.model.univ(elemname)
4096
+ if prop is not None:
4097
+ for univ in self.model.getAllUnivs(elemname):
4098
+ univ.locked = locked
4099
+ elif elemtype == 'tagprop':
4100
+ prop = self.model.getTagProp(elemname)
4101
+
4102
+ if prop is not None:
4103
+ prop.locked = locked
4104
+
3970
4105
  async def _initJsonStor(self):
3971
4106
 
3972
4107
  self.jsonurl = self.conf.get('jsonstor')
@@ -7072,6 +7207,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
7072
7207
  raise s_exc.BadArg('Only vault names and permissions can be changed.')
7073
7208
 
7074
7209
  vault = self.reqVault(iden)
7210
+ oldv = vault.get(key)
7075
7211
  vault[key] = valu
7076
7212
 
7077
7213
  s_schemas.reqValidVault(vault)
@@ -7079,8 +7215,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
7079
7215
  bidn = s_common.uhex(iden)
7080
7216
 
7081
7217
  if key == 'name':
7082
- name = vault.get('name')
7083
- self.slab.delete(name.encode(), db=self.vaultsbynamedb)
7218
+ self.slab.delete(oldv.encode(), db=self.vaultsbynamedb)
7084
7219
  self.slab.put(valu.encode(), bidn, db=self.vaultsbynamedb)
7085
7220
 
7086
7221
  self.slab.put(bidn, s_msgpack.en(vault), db=self.vaultsdb)
synapse/datamodel.py CHANGED
@@ -30,6 +30,7 @@ class TagProp:
30
30
  self.info = info
31
31
  self.tdef = tdef
32
32
  self.model = model
33
+ self.locked = False
33
34
 
34
35
  self.utf8 = name.encode()
35
36
  self.nenc = name.encode() + b'\x00'
@@ -127,6 +128,10 @@ class Prop:
127
128
  self.deprecated = self.info.get('deprecated', False)
128
129
 
129
130
  self.type = self.modl.getTypeClone(typedef)
131
+ self.typehash = self.type.typehash
132
+
133
+ if self.type.isarray:
134
+ self.arraytypehash = self.type.arraytype.typehash
130
135
 
131
136
  if form is not None:
132
137
  form.setProp(name, self)
@@ -269,6 +274,11 @@ class Form:
269
274
  if self.type is None:
270
275
  raise s_exc.NoSuchType(name=name)
271
276
 
277
+ self.typehash = self.type.typehash
278
+
279
+ if self.type.isarray:
280
+ self.arraytypehash = self.type.arraytype.typehash
281
+
272
282
  self.form = self
273
283
 
274
284
  self.props = {} # name: Prop()
@@ -462,6 +472,7 @@ class Model:
462
472
  self.modeldefs = []
463
473
 
464
474
  self.univs = {}
475
+ self.allunivs = collections.defaultdict(list)
465
476
 
466
477
  self.propsbytype = collections.defaultdict(dict) # name: Prop()
467
478
  self.arraysbytype = collections.defaultdict(dict)
@@ -620,6 +631,30 @@ class Model:
620
631
  self.formprefixcache[prefix] = forms
621
632
  return forms
622
633
 
634
+ def reqProp(self, name):
635
+ prop = self.prop(name)
636
+ if prop is not None:
637
+ return prop
638
+
639
+ mesg = f'No property named {name}.'
640
+ raise s_exc.NoSuchProp(mesg=mesg, name=name)
641
+
642
+ def reqUniv(self, name):
643
+ prop = self.univ(name)
644
+ if prop is not None:
645
+ return prop
646
+
647
+ mesg = f'No universal property named {name}.'
648
+ raise s_exc.NoSuchUniv(mesg=mesg, name=name)
649
+
650
+ def reqTagProp(self, name):
651
+ prop = self.getTagProp(name)
652
+ if prop is not None:
653
+ return prop
654
+
655
+ mesg = f'No tag property named {name}.'
656
+ raise s_exc.NoSuchTagProp(mesg=mesg, name=name)
657
+
623
658
  def reqFormsByPrefix(self, prefix, extra=None):
624
659
  forms = self.getFormsByPrefix(prefix)
625
660
  if not forms:
@@ -965,13 +1000,18 @@ class Model:
965
1000
 
966
1001
  def _addFormUniv(self, form, name, tdef, info):
967
1002
 
1003
+ univ = self.reqUniv(name)
1004
+
968
1005
  prop = Prop(self, form, name, tdef, info)
1006
+ prop.locked = univ.locked
969
1007
 
970
1008
  full = f'{form.name}{name}'
971
1009
 
972
1010
  self.props[full] = prop
973
1011
  self.props[(form.name, name)] = prop
974
1012
 
1013
+ self.allunivs[name].append(prop)
1014
+
975
1015
  def addUnivProp(self, name, tdef, info):
976
1016
 
977
1017
  base = '.' + name
@@ -985,8 +1025,13 @@ class Model:
985
1025
  self.props[base] = univ
986
1026
  self.univs[base] = univ
987
1027
 
1028
+ self.allunivs[base].append(univ)
1029
+
988
1030
  for form in self.forms.values():
989
- self._addFormUniv(form, base, tdef, info)
1031
+ prop = self._addFormUniv(form, base, tdef, info)
1032
+
1033
+ def getAllUnivs(self, name):
1034
+ return list(self.allunivs.get(name, ()))
990
1035
 
991
1036
  def addFormProp(self, formname, propname, tdef, info):
992
1037
  form = self.forms.get(formname)
@@ -1090,6 +1135,7 @@ class Model:
1090
1135
  raise s_exc.NoSuchUniv(name=propname)
1091
1136
 
1092
1137
  self.univs.pop(univname, None)
1138
+ self.allunivs.pop(univname, None)
1093
1139
 
1094
1140
  for form in self.forms.values():
1095
1141
  self.delFormProp(form.name, univname)
synapse/exc.py CHANGED
@@ -77,6 +77,7 @@ class BackupAlreadyRunning(SynErr):
77
77
  class StormPkgRequires(SynErr): pass
78
78
  class StormPkgConflicts(SynErr): pass
79
79
 
80
+ class BadName(SynErr): pass
80
81
  class BadPkgDef(SynErr): pass
81
82
  class BadCmdName(SynErr): pass
82
83
  class BadCmprValu(SynErr): pass
synapse/lib/aha.py CHANGED
@@ -733,7 +733,7 @@ class AhaCell(s_cell.Cell):
733
733
  # that do not intend to listen for provisioning.
734
734
  hostname = self.conf.get('dns:name')
735
735
  if hostname is not None:
736
- return f'ssl://{hostname}:27272'
736
+ return f'ssl://0.0.0.0:27272?hostname={hostname}'
737
737
 
738
738
  def _getDmonListen(self):
739
739
 
@@ -776,6 +776,7 @@ class AhaCell(s_cell.Cell):
776
776
  if provurl is not None:
777
777
  self.provdmon = await ProvDmon.anit(self)
778
778
  self.onfini(self.provdmon)
779
+ logger.info(f'provision listening: {provurl}')
779
780
  self.provaddr = await self.provdmon.listen(provurl)
780
781
 
781
782
  async def _clearInactiveSessions(self):
synapse/lib/ast.py CHANGED
@@ -1953,7 +1953,7 @@ class PivotOut(PivotOper):
1953
1953
  typename = prop.type.opts.get('type')
1954
1954
  if runt.model.forms.get(typename) is not None:
1955
1955
  for item in valu:
1956
- async for pivo in runt.snap.nodesByPropValu(typename, '=', item):
1956
+ async for pivo in runt.snap.nodesByPropValu(typename, '=', item, norm=False):
1957
1957
  yield pivo, path.fork(pivo)
1958
1958
 
1959
1959
  form = runt.model.forms.get(prop.type.name)
@@ -2090,11 +2090,13 @@ class PivotIn(PivotOper):
2090
2090
  name, valu = node.ndef
2091
2091
 
2092
2092
  for prop in runt.model.getPropsByType(name):
2093
- async for pivo in runt.snap.nodesByPropValu(prop.full, '=', valu):
2093
+ norm = node.form.typehash is not prop.typehash
2094
+ async for pivo in runt.snap.nodesByPropValu(prop.full, '=', valu, norm=norm):
2094
2095
  yield pivo, path.fork(pivo)
2095
2096
 
2096
2097
  for prop in runt.model.getArrayPropsByType(name):
2097
- async for pivo in runt.snap.nodesByPropArray(prop.full, '=', valu):
2098
+ norm = node.form.typehash is not prop.arraytypehash
2099
+ async for pivo in runt.snap.nodesByPropArray(prop.full, '=', valu, norm=norm):
2098
2100
  yield pivo, path.fork(pivo)
2099
2101
 
2100
2102
  async for refsbuid in runt.snap.getNdefRefs(node.buid):
@@ -2141,7 +2143,7 @@ class PivotInFrom(PivotOper):
2141
2143
  if self.isjoin:
2142
2144
  yield node, path
2143
2145
 
2144
- async for pivo in runt.snap.nodesByPropValu(full, '=', node.ndef):
2146
+ async for pivo in runt.snap.nodesByPropValu(full, '=', node.ndef, norm=False):
2145
2147
  yield pivo, path.fork(pivo)
2146
2148
 
2147
2149
  return
@@ -2179,7 +2181,7 @@ class FormPivot(PivotOper):
2179
2181
  if isinstance(prop.type, s_types.Ndef):
2180
2182
 
2181
2183
  async def pgenr(node, strict=True):
2182
- async for pivo in runt.snap.nodesByPropValu(prop.full, '=', node.ndef):
2184
+ async for pivo in runt.snap.nodesByPropValu(prop.full, '=', node.ndef, norm=False):
2183
2185
  yield pivo
2184
2186
 
2185
2187
  elif not prop.isform:
@@ -2190,13 +2192,14 @@ class FormPivot(PivotOper):
2190
2192
  async def pgenr(node, strict=True):
2191
2193
  if isarray:
2192
2194
  if isinstance(prop.type.arraytype, s_types.Ndef):
2193
- ngenr = runt.snap.nodesByPropArray(prop.full, '=', node.ndef)
2195
+ ngenr = runt.snap.nodesByPropArray(prop.full, '=', node.ndef, norm=False)
2194
2196
  else:
2195
- ngenr = runt.snap.nodesByPropArray(prop.full, '=', node.ndef[1])
2197
+ norm = prop.arraytypehash is not node.form.typehash
2198
+ ngenr = runt.snap.nodesByPropArray(prop.full, '=', node.ndef[1], norm=norm)
2196
2199
  else:
2197
- ngenr = runt.snap.nodesByPropValu(prop.full, '=', node.ndef[1])
2200
+ norm = prop.typehash is not node.form.typehash
2201
+ ngenr = runt.snap.nodesByPropValu(prop.full, '=', node.ndef[1], norm=norm)
2198
2202
 
2199
- # TODO cache/bypass normalization in loop!
2200
2203
  async for pivo in ngenr:
2201
2204
  yield pivo
2202
2205
 
@@ -2206,7 +2209,7 @@ class FormPivot(PivotOper):
2206
2209
  full = prop.name + ':n1'
2207
2210
 
2208
2211
  async def pgenr(node, strict=True):
2209
- async for pivo in runt.snap.nodesByPropValu(full, '=', node.ndef):
2212
+ async for pivo in runt.snap.nodesByPropValu(full, '=', node.ndef, norm=False):
2210
2213
  yield pivo
2211
2214
 
2212
2215
  else:
@@ -2251,7 +2254,7 @@ class FormPivot(PivotOper):
2251
2254
 
2252
2255
  refsvalu = node.get(refsname)
2253
2256
  if refsvalu is not None:
2254
- async for pivo in runt.snap.nodesByPropValu(refsform, '=', refsvalu):
2257
+ async for pivo in runt.snap.nodesByPropValu(refsform, '=', refsvalu, norm=False):
2255
2258
  yield pivo
2256
2259
 
2257
2260
  for refsname, refsform in refs.get('array'):
@@ -2264,7 +2267,7 @@ class FormPivot(PivotOper):
2264
2267
  refsvalu = node.get(refsname)
2265
2268
  if refsvalu is not None:
2266
2269
  for refselem in refsvalu:
2267
- async for pivo in runt.snap.nodesByPropValu(destform.name, '=', refselem):
2270
+ async for pivo in runt.snap.nodesByPropValu(destform.name, '=', refselem, norm=False):
2268
2271
  yield pivo
2269
2272
 
2270
2273
  for refsname in refs.get('ndef'):
@@ -2300,7 +2303,7 @@ class FormPivot(PivotOper):
2300
2303
  found = True
2301
2304
 
2302
2305
  refsprop = destform.props.get(refsname)
2303
- async for pivo in runt.snap.nodesByPropValu(refsprop.full, '=', node.ndef[1]):
2306
+ async for pivo in runt.snap.nodesByPropValu(refsprop.full, '=', node.ndef[1], norm=False):
2304
2307
  yield pivo
2305
2308
 
2306
2309
  # "reverse" array references...
@@ -2312,7 +2315,7 @@ class FormPivot(PivotOper):
2312
2315
  found = True
2313
2316
 
2314
2317
  destprop = destform.props.get(refsname)
2315
- async for pivo in runt.snap.nodesByPropArray(destprop.full, '=', node.ndef[1]):
2318
+ async for pivo in runt.snap.nodesByPropArray(destprop.full, '=', node.ndef[1], norm=False):
2316
2319
  yield pivo
2317
2320
 
2318
2321
  # "reverse" ndef references...
@@ -2321,7 +2324,7 @@ class FormPivot(PivotOper):
2321
2324
  found = True
2322
2325
 
2323
2326
  refsprop = destform.props.get(refsname)
2324
- async for pivo in runt.snap.nodesByPropValu(refsprop.full, '=', node.ndef):
2327
+ async for pivo in runt.snap.nodesByPropValu(refsprop.full, '=', node.ndef, norm=False):
2325
2328
  yield pivo
2326
2329
 
2327
2330
  for refsname in refs.get('ndefarray'):
@@ -2329,7 +2332,7 @@ class FormPivot(PivotOper):
2329
2332
  found = True
2330
2333
 
2331
2334
  refsprop = destform.props.get(refsname)
2332
- async for pivo in runt.snap.nodesByPropArray(refsprop.full, '=', node.ndef):
2335
+ async for pivo in runt.snap.nodesByPropArray(refsprop.full, '=', node.ndef, norm=False):
2333
2336
  yield pivo
2334
2337
 
2335
2338
  if strict and not found:
@@ -2433,7 +2436,7 @@ class PropPivotOut(PivotOper):
2433
2436
  continue
2434
2437
 
2435
2438
  for item in valu:
2436
- async for pivo in runt.snap.nodesByPropValu(fname, '=', item):
2439
+ async for pivo in runt.snap.nodesByPropValu(fname, '=', item, norm=False):
2437
2440
  yield pivo, path.fork(pivo)
2438
2441
 
2439
2442
  continue
@@ -2474,8 +2477,6 @@ class PropPivot(PivotOper):
2474
2477
 
2475
2478
  async def pgenr(node, srcprop, valu, strict=True):
2476
2479
 
2477
- # TODO cache/bypass normalization in loop!
2478
-
2479
2480
  # pivoting from an array prop to a non-array prop needs an extra loop
2480
2481
  if srcprop.type.isarray and not prop.type.isarray:
2481
2482
  if isinstance(srcprop.type.arraytype, s_types.Ndef) and prop.isform:
@@ -2487,8 +2488,9 @@ class PropPivot(PivotOper):
2487
2488
  yield pivo
2488
2489
  return
2489
2490
 
2491
+ norm = srcprop.arraytypehash is not prop.typehash
2490
2492
  for arrayval in valu:
2491
- async for pivo in runt.snap.nodesByPropValu(prop.full, '=', arrayval):
2493
+ async for pivo in runt.snap.nodesByPropValu(prop.full, '=', arrayval, norm=norm):
2492
2494
  yield pivo
2493
2495
 
2494
2496
  return
@@ -2506,9 +2508,11 @@ class PropPivot(PivotOper):
2506
2508
  return
2507
2509
 
2508
2510
  if prop.type.isarray and not srcprop.type.isarray:
2509
- genr = runt.snap.nodesByPropArray(prop.full, '=', valu)
2511
+ norm = prop.arraytypehash is not srcprop.typehash
2512
+ genr = runt.snap.nodesByPropArray(prop.full, '=', valu, norm=norm)
2510
2513
  else:
2511
- genr = runt.snap.nodesByPropValu(prop.full, '=', valu)
2514
+ norm = prop.typehash is not srcprop.typehash
2515
+ genr = runt.snap.nodesByPropValu(prop.full, '=', valu, norm=norm)
2512
2516
 
2513
2517
  async for pivo in genr:
2514
2518
  yield pivo
synapse/lib/base.py CHANGED
@@ -178,6 +178,16 @@ class Base:
178
178
  def onfini(self, func):
179
179
  '''
180
180
  Add a function/coroutine/Base to be called on fini().
181
+
182
+ The rules around how to register function/coroutine/Base to be called:
183
+ - Call this method with an instance of Base (this class) if holding
184
+ a reference to a bound method of the instance (such as a fini()
185
+ method) would cause the object to be leaked. This is appropriate
186
+ for ephemeral objects that may be constructed/destroyed multiple
187
+ times over the lifetime of a process.
188
+
189
+ - Call this method with an instance method if you want the object to
190
+ have a lifetime as long as the thing being fini'd.
181
191
  '''
182
192
  if self.isfini:
183
193
  if isinstance(func, Base):
@@ -498,9 +508,8 @@ class Base:
498
508
  def taskDone(task):
499
509
  self._active_tasks.remove(task)
500
510
  try:
501
- if not task.done():
502
- task.result()
503
- except asyncio.CancelledError: # pragma: no cover TODO: remove once >= py 3.8 only
511
+ task.result()
512
+ except asyncio.CancelledError:
504
513
  pass
505
514
  except Exception:
506
515
  logger.exception('Task %s scheduled through Base.schedCoro raised exception', task)