synapse 2.175.0__py311-none-any.whl → 2.177.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 (73) hide show
  1. synapse/axon.py +24 -9
  2. synapse/cortex.py +330 -168
  3. synapse/cryotank.py +46 -37
  4. synapse/datamodel.py +17 -4
  5. synapse/exc.py +19 -0
  6. synapse/lib/agenda.py +7 -13
  7. synapse/lib/ast.py +6 -5
  8. synapse/lib/auth.py +1520 -0
  9. synapse/lib/cell.py +255 -53
  10. synapse/lib/grammar.py +5 -0
  11. synapse/lib/hive.py +24 -3
  12. synapse/lib/hiveauth.py +6 -32
  13. synapse/lib/layer.py +7 -4
  14. synapse/lib/link.py +21 -17
  15. synapse/lib/lmdbslab.py +149 -0
  16. synapse/lib/modelrev.py +1 -1
  17. synapse/lib/schemas.py +136 -0
  18. synapse/lib/storm.py +70 -33
  19. synapse/lib/stormlib/aha.py +1 -1
  20. synapse/lib/stormlib/auth.py +185 -10
  21. synapse/lib/stormlib/cortex.py +16 -5
  22. synapse/lib/stormlib/gen.py +80 -0
  23. synapse/lib/stormlib/model.py +55 -0
  24. synapse/lib/stormlib/modelext.py +60 -0
  25. synapse/lib/stormlib/storm.py +117 -5
  26. synapse/lib/stormlib/tabular.py +212 -0
  27. synapse/lib/stormtypes.py +14 -1
  28. synapse/lib/trigger.py +1 -1
  29. synapse/lib/version.py +2 -2
  30. synapse/lib/view.py +55 -28
  31. synapse/models/base.py +7 -0
  32. synapse/models/biz.py +4 -0
  33. synapse/models/files.py +8 -1
  34. synapse/models/inet.py +31 -0
  35. synapse/tests/files/changelog/model_2.176.0_16ee721a6b7221344eaf946c3ab4602dda546b1a.yaml.gz +0 -0
  36. synapse/tests/files/changelog/model_2.176.0_2a25c58bbd344716cd7cbc3f4304d8925b0f4ef2.yaml.gz +0 -0
  37. synapse/tests/test_axon.py +7 -4
  38. synapse/tests/test_cortex.py +127 -82
  39. synapse/tests/test_cryotank.py +4 -4
  40. synapse/tests/test_datamodel.py +7 -0
  41. synapse/tests/test_lib_agenda.py +7 -0
  42. synapse/tests/{test_lib_hiveauth.py → test_lib_auth.py} +314 -11
  43. synapse/tests/test_lib_cell.py +161 -8
  44. synapse/tests/test_lib_httpapi.py +18 -14
  45. synapse/tests/test_lib_layer.py +33 -33
  46. synapse/tests/test_lib_link.py +42 -1
  47. synapse/tests/test_lib_lmdbslab.py +68 -0
  48. synapse/tests/test_lib_nexus.py +4 -4
  49. synapse/tests/test_lib_node.py +0 -7
  50. synapse/tests/test_lib_storm.py +45 -0
  51. synapse/tests/test_lib_stormlib_aha.py +1 -2
  52. synapse/tests/test_lib_stormlib_auth.py +21 -0
  53. synapse/tests/test_lib_stormlib_cortex.py +12 -12
  54. synapse/tests/test_lib_stormlib_gen.py +99 -0
  55. synapse/tests/test_lib_stormlib_model.py +108 -0
  56. synapse/tests/test_lib_stormlib_modelext.py +64 -0
  57. synapse/tests/test_lib_stormlib_storm.py +82 -1
  58. synapse/tests/test_lib_stormlib_tabular.py +226 -0
  59. synapse/tests/test_lib_stormsvc.py +4 -1
  60. synapse/tests/test_lib_stormtypes.py +10 -0
  61. synapse/tests/test_model_base.py +3 -0
  62. synapse/tests/test_model_biz.py +3 -0
  63. synapse/tests/test_model_files.py +12 -2
  64. synapse/tests/test_model_inet.py +55 -0
  65. synapse/tests/test_tools_changelog.py +196 -0
  66. synapse/tests/test_tools_healthcheck.py +4 -3
  67. synapse/tests/utils.py +1 -1
  68. synapse/tools/changelog.py +774 -15
  69. {synapse-2.175.0.dist-info → synapse-2.177.0.dist-info}/METADATA +3 -3
  70. {synapse-2.175.0.dist-info → synapse-2.177.0.dist-info}/RECORD +73 -67
  71. {synapse-2.175.0.dist-info → synapse-2.177.0.dist-info}/WHEEL +1 -1
  72. {synapse-2.175.0.dist-info → synapse-2.177.0.dist-info}/LICENSE +0 -0
  73. {synapse-2.175.0.dist-info → synapse-2.177.0.dist-info}/top_level.txt +0 -0
synapse/cryotank.py CHANGED
@@ -226,14 +226,19 @@ class CryoCell(s_cell.Cell):
226
226
 
227
227
  self.dmon.share('cryotank', self)
228
228
 
229
- self.names = await self.hive.open(('cryo', 'names'))
229
+ async def initServiceStorage(self):
230
+
231
+ self.names = self.slab.getSafeKeyVal('cryo:names')
232
+
233
+ await self._bumpCellVers('cryotank', (
234
+ (2, self._migrateToV2),
235
+ (3, self._migrateToV3),
236
+ ), nexs=False)
230
237
 
231
238
  self.tanks = await s_base.BaseRef.anit()
232
239
  self.onfini(self.tanks.fini)
233
240
 
234
- for name, node in self.names:
235
-
236
- iden, conf = node.valu
241
+ for name, (iden, conf) in self.names.items():
237
242
 
238
243
  logger.info('Bringing tank [%s][%s] online', name, iden)
239
244
 
@@ -245,47 +250,52 @@ class CryoCell(s_cell.Cell):
245
250
 
246
251
  await self.auth.addAuthGate(iden, 'tank')
247
252
 
248
- async def _execCellUpdates(self):
249
- await self._bumpCellVers('cryotank', (
250
- (2, self._migrateToV2),
251
- ))
252
-
253
253
  async def _migrateToV2(self):
254
254
 
255
255
  logger.warning('Beginning migration to V2')
256
256
 
257
- self.names = await self.hive.open(('cryo', 'names'))
257
+ async with await self.hive.open(('cryo', 'names')) as names:
258
+ for name, node in names:
258
259
 
259
- for name, node in self.names:
260
+ iden, conf = node.valu
261
+ if conf is None:
262
+ conf = {}
260
263
 
261
- iden, conf = node.valu
262
- if conf is None:
263
- conf = {}
264
+ logger.info(f'Migrating tank {name=} {iden=}')
264
265
 
265
- logger.info(f'Migrating tank {name=} {iden=}')
266
+ path = s_common.genpath(self.dirn, 'tanks', iden)
266
267
 
267
- path = s_common.genpath(self.dirn, 'tanks', iden)
268
+ # remove old guid file
269
+ guidpath = s_common.genpath(path, 'guid')
270
+ if os.path.isfile(guidpath):
271
+ os.unlink(guidpath)
272
+
273
+ # if its a legacy cell remove that too
274
+ cellpath = s_common.genpath(path, 'cell.guid')
275
+ if os.path.isfile(cellpath):
268
276
 
269
- # remove old guid file
270
- guidpath = s_common.genpath(path, 'guid')
271
- if os.path.isfile(guidpath):
272
- os.unlink(guidpath)
277
+ os.unlink(cellpath)
273
278
 
274
- # if its a legacy cell remove that too
275
- cellpath = s_common.genpath(path, 'cell.guid')
276
- if os.path.isfile(cellpath):
279
+ cellslabpath = s_common.genpath(path, 'slabs', 'cell.lmdb')
280
+ if os.path.isdir(cellslabpath):
281
+ shutil.rmtree(cellslabpath, ignore_errors=True)
282
+
283
+ # drop offsets
284
+ slabpath = s_common.genpath(path, 'tank.lmdb')
285
+ async with await s_lmdbslab.Slab.anit(slabpath, **conf) as slab:
286
+ offs = s_slaboffs.SlabOffs(slab, 'offsets')
287
+ slab.dropdb(offs.db)
288
+
289
+ logger.warning('...migration complete')
277
290
 
278
- os.unlink(cellpath)
291
+ async def _migrateToV3(self):
279
292
 
280
- cellslabpath = s_common.genpath(path, 'slabs', 'cell.lmdb')
281
- if os.path.isdir(cellslabpath):
282
- shutil.rmtree(cellslabpath, ignore_errors=True)
293
+ logger.warning('Beginning migration to V3')
283
294
 
284
- # drop offsets
285
- slabpath = s_common.genpath(path, 'tank.lmdb')
286
- async with await s_lmdbslab.Slab.anit(slabpath, **conf) as slab:
287
- offs = s_slaboffs.SlabOffs(slab, 'offsets')
288
- slab.dropdb(offs.db)
295
+ async with await self.hive.open(('cryo', 'names')) as hivenames:
296
+ for name, node in hivenames:
297
+ iden, conf = node.valu
298
+ self.names.set(name, (iden, conf))
289
299
 
290
300
  logger.warning('...migration complete')
291
301
 
@@ -329,7 +339,7 @@ class CryoCell(s_cell.Cell):
329
339
 
330
340
  Args:
331
341
  name (str): Name of the CryoTank.
332
- user (HiveUser): The Telepath user.
342
+ user (User): The Telepath user.
333
343
 
334
344
  Returns:
335
345
  CryoTank: A CryoTank instance.
@@ -349,8 +359,7 @@ class CryoCell(s_cell.Cell):
349
359
 
350
360
  tank = await CryoTank.anit(path, iden, conf)
351
361
 
352
- node = await self.names.open((name,))
353
- await node.set((iden, conf))
362
+ self.names.set(name, (iden, conf))
354
363
 
355
364
  self.tanks.put(name, tank)
356
365
 
@@ -367,7 +376,7 @@ class CryoCell(s_cell.Cell):
367
376
 
368
377
  Returns:
369
378
  list: A list of tufos.
370
- user (HiveUser): The Telepath user.
379
+ user (User): The Telepath user.
371
380
  '''
372
381
 
373
382
  infos = []
@@ -387,7 +396,7 @@ class CryoCell(s_cell.Cell):
387
396
  if tank is None:
388
397
  return False
389
398
 
390
- iden, _ = await self.names.pop((name,))
399
+ iden, _ = self.names.pop(name)
391
400
  await tank.fini()
392
401
  shutil.rmtree(tank.dirn, ignore_errors=True)
393
402
 
synapse/datamodel.py CHANGED
@@ -467,8 +467,8 @@ class Model:
467
467
  self.arraysbytype = collections.defaultdict(dict)
468
468
  self.ifaceprops = collections.defaultdict(list)
469
469
  self.formsbyiface = collections.defaultdict(list)
470
- self.edgesbyn1 = collections.defaultdict(list)
471
- self.edgesbyn2 = collections.defaultdict(list)
470
+ self.edgesbyn1 = collections.defaultdict(set)
471
+ self.edgesbyn2 = collections.defaultdict(set)
472
472
 
473
473
  self.formprefixcache = s_cache.LruDict(PREFIX_CACHE_SIZE)
474
474
 
@@ -820,8 +820,18 @@ class Model:
820
820
  edge = Edge(self, edgetype, edgeinfo)
821
821
 
822
822
  self.edges[edgetype] = edge
823
- self.edgesbyn1[n1form].append(edge)
824
- self.edgesbyn2[n2form].append(edge)
823
+ self.edgesbyn1[n1form].add(edge)
824
+ self.edgesbyn2[n2form].add(edge)
825
+
826
+ def delEdge(self, edgetype):
827
+ if self.edges.get(edgetype) is None:
828
+ return
829
+
830
+ n1form, verb, n2form = edgetype
831
+
832
+ self.edges.pop(edgetype, None)
833
+ self.edgesbyn1[n1form].discard(edgetype)
834
+ self.edgesbyn2[n2form].discard(edgetype)
825
835
 
826
836
  def _reqFormName(self, name):
827
837
  form = self.forms.get(name)
@@ -1109,3 +1119,6 @@ class Model:
1109
1119
 
1110
1120
  def tagprop(self, name):
1111
1121
  return self.tagprops.get(name)
1122
+
1123
+ def edge(self, edgetype):
1124
+ return self.edges.get(edgetype)
synapse/exc.py CHANGED
@@ -105,6 +105,7 @@ class BadFormDef(SynErr): pass
105
105
  class BadHivePath(SynErr): pass
106
106
  class BadLiftValu(SynErr): pass
107
107
  class BadPropDef(SynErr): pass
108
+ class BadEdgeDef(SynErr): pass
108
109
  class BadTypeDef(SynErr): pass
109
110
  class BadTypeValu(SynErr): pass
110
111
  class BadJsonText(SynErr): pass
@@ -189,6 +190,15 @@ class DupTagPropName(SynErr): pass
189
190
  class DupUserName(SynErr): pass
190
191
  class DupStormSvc(SynErr): pass
191
192
 
193
+ class DupEdgeType(SynErr):
194
+
195
+ @classmethod
196
+ def init(cls, edge, mesg=None):
197
+ if mesg is None:
198
+ (n1form, verb, n2form) = edge
199
+ mesg = f'Edge already exists: {n1form} -({verb})> {n2form}.'
200
+ return DupEdgeType(mesg=mesg, n1form=n1form, verb=verb, n2form=n2form)
201
+
192
202
  class FileExists(SynErr): pass
193
203
 
194
204
  class InconsistentStorage(SynErr):
@@ -240,6 +250,15 @@ class NoSuchProp(SynErr):
240
250
  mesg = f'No property named {name}.'
241
251
  return NoSuchProp(mesg=mesg, name=name)
242
252
 
253
+ class NoSuchEdge(SynErr):
254
+
255
+ @classmethod
256
+ def init(cls, edge, mesg=None):
257
+ if mesg is None:
258
+ (n1form, verb, n2form) = edge
259
+ mesg = f'No edge defined for {n1form} -({verb})> {n2form}.'
260
+ return NoSuchEdge(mesg=mesg, n1form=n1form, verb=verb, n2form=n2form)
261
+
243
262
  class NoSuchAbrv(SynErr): pass
244
263
  class NoSuchAct(SynErr): pass
245
264
  class NoSuchAuthGate(SynErr): pass
synapse/lib/agenda.py CHANGED
@@ -430,9 +430,8 @@ class _Appt:
430
430
  await self.save()
431
431
 
432
432
  async def save(self):
433
- full = self.stor._hivenode.full + (self.iden,)
434
433
  stordict = self.pack()
435
- await self.stor.core.hive.set(full, stordict)
434
+ self.stor.apptdefs.set(self.iden, stordict)
436
435
 
437
436
  class Agenda(s_base.Base):
438
437
  '''
@@ -452,7 +451,7 @@ class Agenda(s_base.Base):
452
451
  self._wake_event = s_coro.Event() # Causes the scheduler loop to wake up
453
452
  self.onfini(self._wake_event.set)
454
453
 
455
- self._hivenode = await self.core.hive.open(('agenda', 'appts')) # Persistent storage
454
+ self.apptdefs = self.core.cortexdata.getSubKeyVal('agenda:appt:')
456
455
 
457
456
  await self._load_all()
458
457
 
@@ -465,10 +464,9 @@ class Agenda(s_base.Base):
465
464
  self.appts = {}
466
465
 
467
466
  to_delete = []
468
- for iden, node in iter(self._hivenode):
469
- val = node.valu
467
+ for iden, info in self.apptdefs.items():
470
468
  try:
471
- appt = _Appt.unpack(self, val)
469
+ appt = _Appt.unpack(self, info)
472
470
  if appt.iden != iden:
473
471
  raise s_exc.InconsistentStorage(mesg='iden inconsistency')
474
472
  self._addappt(iden, appt)
@@ -480,9 +478,7 @@ class Agenda(s_base.Base):
480
478
  continue
481
479
 
482
480
  for iden in to_delete:
483
- node = self._hivenode.get(iden)
484
- if node is not None:
485
- await node.hive.pop(node.full)
481
+ self.apptdefs.pop(iden)
486
482
 
487
483
  # Make sure we don't assign the same index to 2 appointments
488
484
  if self.appts:
@@ -699,9 +695,7 @@ class Agenda(s_base.Base):
699
695
  heapq.heapify(self.apptheap)
700
696
 
701
697
  del self.appts[iden]
702
- node = self._hivenode.get(iden)
703
- if node is not None:
704
- await node.hive.pop(node.full)
698
+ self.apptdefs.delete(iden)
705
699
 
706
700
  def _getNowTick(self):
707
701
  return time.time() + self.tickoff
@@ -752,7 +746,7 @@ class Agenda(s_base.Base):
752
746
 
753
747
  if appt.isrunning: # pragma: no cover
754
748
  mesg = f'Appointment {appt.iden} {appt.name} is still running from previous time when scheduled' \
755
- f' to run. Skipping.',
749
+ f' to run. Skipping.'
756
750
  logger.warning(mesg,
757
751
  extra={'synapse': {'iden': appt.iden, 'name': appt.name}})
758
752
  else:
synapse/lib/ast.py CHANGED
@@ -284,7 +284,7 @@ class Search(Query):
284
284
  view = runt.snap.view
285
285
 
286
286
  if not view.core.stormiface_search:
287
- await runt.snap.warn('Storm search interface is not enabled!')
287
+ await runt.snap.warn('Storm search interface is not enabled!', log=False)
288
288
  return
289
289
 
290
290
  async def searchgenr():
@@ -2389,7 +2389,7 @@ class FormPivot(PivotOper):
2389
2389
  items = e.items()
2390
2390
  mesg = items.pop('mesg', '')
2391
2391
  mesg = ': '.join((f'{e.__class__.__qualname__} [{repr(node.ndef[1])}] during pivot', mesg))
2392
- await runt.snap.warn(mesg, **items)
2392
+ await runt.snap.warn(mesg, log=False, **items)
2393
2393
 
2394
2394
  class PropPivotOut(PivotOper):
2395
2395
  '''
@@ -2428,7 +2428,7 @@ class PropPivotOut(PivotOper):
2428
2428
  if runt.model.forms.get(fname) is None:
2429
2429
  if not warned:
2430
2430
  mesg = f'The source property "{name}" array type "{fname}" is not a form. Cannot pivot.'
2431
- await runt.snap.warn(mesg)
2431
+ await runt.snap.warn(mesg, log=False)
2432
2432
  warned = True
2433
2433
  continue
2434
2434
 
@@ -2452,7 +2452,8 @@ class PropPivotOut(PivotOper):
2452
2452
  fname = prop.type.name
2453
2453
  if prop.modl.form(fname) is None:
2454
2454
  if warned is False:
2455
- await runt.snap.warn(f'The source property "{name}" type "{fname}" is not a form. Cannot pivot.')
2455
+ await runt.snap.warn(f'The source property "{name}" type "{fname}" is not a form. Cannot pivot.',
2456
+ log=False)
2456
2457
  warned = True
2457
2458
  continue
2458
2459
 
@@ -2574,7 +2575,7 @@ class PropPivot(PivotOper):
2574
2575
  items = e.items()
2575
2576
  mesg = items.pop('mesg', '')
2576
2577
  mesg = ': '.join((f'{e.__class__.__qualname__} [{repr(valu)}] during pivot', mesg))
2577
- await runt.snap.warn(mesg, **items)
2578
+ await runt.snap.warn(mesg, log=False, **items)
2578
2579
 
2579
2580
  class Value(AstNode):
2580
2581
  '''