synapse 2.194.0__py311-none-any.whl → 2.195.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 (39) hide show
  1. synapse/cortex.py +6 -0
  2. synapse/datamodel.py +3 -3
  3. synapse/lib/auth.py +4 -2
  4. synapse/lib/link.py +33 -19
  5. synapse/lib/modelrev.py +6 -1
  6. synapse/lib/scrape.py +18 -1
  7. synapse/lib/stormlib/auth.py +15 -1
  8. synapse/lib/stormlib/cell.py +11 -0
  9. synapse/lib/stormlib/infosec.py +2 -0
  10. synapse/lib/version.py +2 -2
  11. synapse/models/geospace.py +52 -10
  12. synapse/models/infotech.py +2 -3
  13. synapse/models/material.py +67 -8
  14. synapse/models/orgs.py +4 -1
  15. synapse/models/person.py +13 -13
  16. synapse/models/risk.py +1 -1
  17. synapse/models/syn.py +3 -0
  18. synapse/models/transport.py +382 -49
  19. synapse/tests/test_cortex.py +4 -1
  20. synapse/tests/test_lib_cell.py +10 -0
  21. synapse/tests/test_lib_link.py +6 -1
  22. synapse/tests/test_lib_modelrev.py +7 -0
  23. synapse/tests/test_lib_scrape.py +8 -0
  24. synapse/tests/test_lib_stormlib_auth.py +26 -0
  25. synapse/tests/test_lib_stormlib_cell.py +3 -0
  26. synapse/tests/test_model_geospace.py +37 -4
  27. synapse/tests/test_model_infotech.py +21 -3
  28. synapse/tests/test_model_material.py +18 -0
  29. synapse/tests/test_model_orgs.py +8 -1
  30. synapse/tests/test_model_person.py +3 -0
  31. synapse/tests/test_model_syn.py +9 -3
  32. synapse/tests/test_model_transport.py +168 -0
  33. synapse/tests/test_telepath.py +24 -5
  34. synapse/tools/changelog.py +8 -1
  35. {synapse-2.194.0.dist-info → synapse-2.195.0.dist-info}/METADATA +1 -1
  36. {synapse-2.194.0.dist-info → synapse-2.195.0.dist-info}/RECORD +39 -39
  37. {synapse-2.194.0.dist-info → synapse-2.195.0.dist-info}/LICENSE +0 -0
  38. {synapse-2.194.0.dist-info → synapse-2.195.0.dist-info}/WHEEL +0 -0
  39. {synapse-2.194.0.dist-info → synapse-2.195.0.dist-info}/top_level.txt +0 -0
@@ -320,6 +320,17 @@ class StormLibAuthTest(s_test.SynTest):
320
320
  self.stormIsInPrint('Controls access to add a new view including forks.', msgs)
321
321
  self.stormIsInPrint('default: false', msgs)
322
322
 
323
+ msgs = await core.stormlist('auth.perms.list --find macro.')
324
+ self.stormIsInPrint('storm.macro.add', msgs)
325
+ self.stormIsInPrint('storm.macro.admin', msgs)
326
+ self.stormIsInPrint('storm.macro.edit', msgs)
327
+ self.stormNotInPrint('node.add.<form>', msgs)
328
+
329
+ msgs = await core.stormlist('auth.perms.list --find url')
330
+ self.stormIsInPrint('storm.lib.telepath.open.<scheme>', msgs)
331
+ self.stormIsInPrint('Controls the ability to open a telepath URL with a specific URI scheme.', msgs)
332
+ self.stormNotInPrint('node.add.<form>', msgs)
333
+
323
334
  async def test_stormlib_auth_default_allow(self):
324
335
  async with self.getTestCore() as core:
325
336
 
@@ -1003,6 +1014,21 @@ class StormLibAuthTest(s_test.SynTest):
1003
1014
  with self.raises(s_exc.DupIden):
1004
1015
  await core.callStorm('$lib.auth.roles.add(walkers, iden=$iden)', opts=opts)
1005
1016
 
1017
+ # The role & user.authgates local is a passthrough to the getRoleDef & getUserDef
1018
+ # results, which are a pack()'d structure. Modifying the results of that structure
1019
+ # does not persist.
1020
+ q = '$u = $lib.auth.users.byname(root) $u.authgates.newp = ({}) return ($u)'
1021
+ udef = await core.callStorm(q)
1022
+ self.notin('newp', udef.get('authgates'))
1023
+ q = '$u = $lib.auth.users.byname(root) return ( $lib.dict.has($u.authgates, newp) )'
1024
+ self.false(await core.callStorm(q))
1025
+
1026
+ q = '$r = $lib.auth.roles.byname(all) $r.authgates.newp = ({}) return ($r)'
1027
+ rdef = await core.callStorm(q)
1028
+ self.notin('newp', rdef.get('authgates'))
1029
+ q = '$r = $lib.auth.roles.byname(all) return ( $lib.dict.has($r.authgates, newp) )'
1030
+ self.false(await core.callStorm(q))
1031
+
1006
1032
  async def test_stormlib_auth_gateadmin(self):
1007
1033
 
1008
1034
  async with self.getTestCore() as core:
@@ -14,6 +14,9 @@ class StormCellTest(s_test.SynTest):
14
14
 
15
15
  async with self.getTestCore() as core:
16
16
 
17
+ ret = await core.callStorm('return ( $lib.cell.iden )')
18
+ self.eq(ret, core.getCellIden())
19
+
17
20
  ret = await core.callStorm('return ( $lib.cell.getCellInfo() )')
18
21
  self.eq(ret, await core.getCellInfo())
19
22
 
@@ -249,12 +249,18 @@ class GeoTest(s_t_utils.SynTest):
249
249
  'bbox': '2.11, 2.12, -4.88, -4.9',
250
250
  'radius': '1.337km'}
251
251
  opts = {'vars': {'valu': guid, 'p': props}}
252
- q = '[(geo:place=$valu :name=$p.name :desc=$p.desc :address=$p.address :parent=$p.parent :loc=$p.loc ' \
253
- ':photo=$p.photo :latlong=$p.latlong :bbox=$p.bbox :radius=$p.radius)]'
252
+ q = '''
253
+ [ geo:place=$valu
254
+ :id=IAD
255
+ :name=$p.name :desc=$p.desc :address=$p.address :parent=$p.parent :loc=$p.loc
256
+ :photo=$p.photo :latlong=$p.latlong :bbox=$p.bbox :radius=$p.radius
257
+ ]
258
+ '''
254
259
  nodes = await core.nodes(q, opts=opts)
255
260
  self.len(1, nodes)
256
261
  node = nodes[0]
257
262
  self.eq(node.ndef[1], guid)
263
+ self.eq(node.get('id'), 'IAD')
258
264
  self.eq(node.get('name'), 'vertex hq')
259
265
  self.eq(node.get('loc'), 'us.hehe.haha')
260
266
  self.eq(node.get('latlong'), (34.1341, -118.3215))
@@ -501,10 +507,24 @@ class GeoTest(s_t_utils.SynTest):
501
507
  :time=20220618
502
508
  :latlong=(10.1, 3.0)
503
509
  :desc=foobar
504
- :place:name=woot
505
- :place={[geo:place=* :name=woot]}
506
510
  :accuracy=10m
507
511
  :node=(test:int, 1234)
512
+
513
+ :place={[ geo:place=({"name": "Woot"}) ]}
514
+ :place:loc=us.ny.woot
515
+ :place:name=Woot
516
+ :place:country={[ pol:country=({"iso2": "us"}) ]}
517
+ :place:country:code=us
518
+ :place:address="123 main street"
519
+
520
+ :place:latlong=(10.1, 3.0)
521
+ :place:latlong:accuracy=10m
522
+
523
+ :phys:mass=10kg
524
+ :phys:width=5m
525
+ :phys:height=10m
526
+ :phys:length=20m
527
+ :phys:volume=1000m
508
528
  ]
509
529
  ''')
510
530
  self.eq(1655510400000, nodes[0].get('time'))
@@ -516,6 +536,19 @@ class GeoTest(s_t_utils.SynTest):
516
536
  self.eq(('test:int', 1234), nodes[0].get('node'))
517
537
  self.len(1, await core.nodes('test:int=1234'))
518
538
 
539
+ self.nn(nodes[0].get('place'))
540
+ self.nn('us.ny.woot', nodes[0].get('place:loc'))
541
+ self.nn('woot', nodes[0].get('place:name'))
542
+ self.nn('123 main street', nodes[0].get('place:address'))
543
+ self.eq((10.1, 3.0), nodes[0].get('place:latlong'))
544
+ self.eq(10000, nodes[0].get('place:latlong:accuracy'))
545
+
546
+ self.eq('10000', nodes[0].get('phys:mass'))
547
+ self.eq(5000, nodes[0].get('phys:width'))
548
+ self.eq(10000, nodes[0].get('phys:height'))
549
+ self.eq(20000, nodes[0].get('phys:length'))
550
+ self.eq(1000000, nodes[0].get('phys:volume'))
551
+
519
552
  async def test_model_geospace_area(self):
520
553
 
521
554
  async with self.getTestCore() as core:
@@ -534,11 +534,29 @@ class InfotechModelTest(s_t_utils.SynTest):
534
534
  'ext:id': 'foo123',
535
535
  'image': image.ndef[1],
536
536
  }
537
- q = '''[(it:host=$valu :name=$p.name :desc=$p.desc :ipv4=$p.ipv4 :place=$p.place :latlong=$p.latlong
538
- :os=$p.os :manu=$p.manu :model=$p.model :serial=$p.serial :loc=$p.loc :operator=$p.operator
539
- :org=$p.org :ext:id=$p."ext:id" :image=$p.image)]'''
537
+ q = '''
538
+ [ it:host=$valu
539
+
540
+ :phys:mass=10kg
541
+ :phys:width=5m
542
+ :phys:height=10m
543
+ :phys:length=20m
544
+ :phys:volume=1000m
545
+
546
+ :name=$p.name :desc=$p.desc :ipv4=$p.ipv4 :place=$p.place :latlong=$p.latlong
547
+ :os=$p.os :manu=$p.manu :model=$p.model :serial=$p.serial :loc=$p.loc :operator=$p.operator
548
+ :org=$p.org :ext:id=$p."ext:id" :image=$p.image
549
+ ]
550
+ '''
540
551
  nodes = await core.nodes(q, opts={'vars': {'valu': host0, 'p': props}})
541
552
  self.len(1, nodes)
553
+
554
+ self.eq('10000', nodes[0].get('phys:mass'))
555
+ self.eq(5000, nodes[0].get('phys:width'))
556
+ self.eq(10000, nodes[0].get('phys:height'))
557
+ self.eq(20000, nodes[0].get('phys:length'))
558
+ self.eq(1000000, nodes[0].get('phys:volume'))
559
+
542
560
  node = nodes[0]
543
561
  self.eq(node.ndef[1], host0)
544
562
  self.eq(node.get('name'), 'bobs laptop')
@@ -43,3 +43,21 @@ class MatTest(s_t_utils.SynTest):
43
43
  self.eq(node3.props.get('file'), f0_valu)
44
44
 
45
45
  self.len(1, await core.nodes('mat:spec:name="f16 fighter jet" -> mat:item'))
46
+
47
+ async def test_model_material(self):
48
+
49
+ async with self.getTestCore() as core:
50
+
51
+ nodes = await core.nodes('''[
52
+ phys:contained=*
53
+ :period=(2024, ?)
54
+ :type=component
55
+ :object={[ mat:item=* :phys:volume=9000cm :place:loc=us.ny ]}
56
+ :container={[ mat:item=* :phys:volume=10000cm :place:loc=us.ny ]}
57
+ ]''')
58
+
59
+ self.nn(nodes[0].get('object'))
60
+ self.nn(nodes[0].get('container'))
61
+ self.eq('component.', nodes[0].get('type'))
62
+ self.eq((1704067200000, 9223372036854775807), nodes[0].get('period'))
63
+ self.len(1, await core.nodes('phys:contained -> phys:contained:type:taxonomy'))
@@ -477,14 +477,21 @@ class OuModelTest(s_t_utils.SynTest):
477
477
  self.eq(node.get('departed'), 1519945200000)
478
478
  self.eq(node.get('roles'), ('speaker', 'staff'))
479
479
 
480
- nodes = await core.nodes('[ ou:id:type=* :org=* :name=foobar :url="http://foobar.com/ids"]')
480
+ nodes = await core.nodes('[ ou:id:type=* :org=* :name=foobar :names=(alt1,alt2) :url="http://foobar.com/ids"]')
481
481
  self.len(1, nodes)
482
482
  self.nn(nodes[0].get('org'))
483
483
  self.eq('foobar', nodes[0].get('name'))
484
+ self.eq(('alt1', 'alt2'), nodes[0].get('names'))
484
485
  self.eq('http://foobar.com/ids', nodes[0].get('url'))
485
486
 
486
487
  iden = await core.callStorm('ou:id:type return($node.value())')
487
488
 
489
+ self.len(1, alts := await core.nodes('[ ou:id:type=({"name": "foobar"}) ]'))
490
+ self.eq(nodes[0].ndef, alts[0].ndef)
491
+
492
+ self.len(1, alts := await core.nodes('[ ou:id:type=({"name": "alt1"}) ]'))
493
+ self.eq(nodes[0].ndef, alts[0].ndef)
494
+
488
495
  opts = {'vars': {'type': iden}}
489
496
  nodes = await core.nodes('''
490
497
  [ ou:id:number=($type, visi)
@@ -369,6 +369,7 @@ class PsModelTest(s_t_utils.SynTest):
369
369
  :econ:currency=usd
370
370
  :econ:net:worth=100
371
371
  :econ:annual:income=1000
372
+ :phys:mass=100lbs
372
373
  ]
373
374
  { -> ps:person [ :vitals={ps:vitals} ] }
374
375
  { -> ps:contact [ :vitals={ps:vitals} ] }
@@ -378,6 +379,8 @@ class PsModelTest(s_t_utils.SynTest):
378
379
  self.eq(1828, nodes[0].get('height'))
379
380
  self.eq('90718.4', nodes[0].get('weight'))
380
381
 
382
+ self.eq('45359.2', nodes[0].get('phys:mass'))
383
+
381
384
  self.eq('usd', nodes[0].get('econ:currency'))
382
385
  self.eq('100', nodes[0].get('econ:net:worth'))
383
386
  self.eq('1000', nodes[0].get('econ:annual:income'))
@@ -612,10 +612,16 @@ class SynModelTest(s_t_utils.SynTest):
612
612
  nodes = await core.nodes('syn:cmd +:package')
613
613
  self.len(0, nodes)
614
614
 
615
- await core.nodes(f'service.add test {url}')
616
- iden = core.getStormSvcs()[0].iden
615
+ with self.getLoggerStream('synapse.cortex') as stream:
616
+ await core.nodes(f'service.add test {url}')
617
+ iden = core.getStormSvcs()[0].iden
617
618
 
618
- await core.nodes('$lib.service.wait(test)')
619
+ await core.nodes('$lib.service.wait(test)')
620
+
621
+ stream.seek(0)
622
+ warn = "Storm command definition 'forms' key is deprecated and will be removed " \
623
+ "in 3.0.0 (command foobar in package foo)"
624
+ self.isin(warn, stream.read())
619
625
 
620
626
  # check that runt nodes for new commands are created
621
627
  nodes = await core.nodes('syn:cmd +:package')
@@ -88,6 +88,7 @@ class TransportTest(s_test.SynTest):
88
88
  :mmsi=123456789
89
89
  :name="Slice of Life"
90
90
  :flag=us
91
+ :type=cargo.tanker.oil
91
92
  :imo="IMO 1234567"
92
93
  :built=2020
93
94
  :make="The Vertex Project"
@@ -98,6 +99,7 @@ class TransportTest(s_test.SynTest):
98
99
  ]'''))[0]
99
100
  self.eq('123456789', vessel.get('mmsi'))
100
101
  self.eq('slice of life', vessel.get('name'))
102
+ self.eq('cargo.tanker.oil.', vessel.get('type'))
101
103
  self.eq('the vertex project', vessel.get('make'))
102
104
  self.eq('speed boat 9000', vessel.get('model'))
103
105
  self.eq('us', vessel.get('flag'))
@@ -108,6 +110,7 @@ class TransportTest(s_test.SynTest):
108
110
  self.nn(vessel.get('operator'))
109
111
 
110
112
  self.len(1, await core.nodes('transport:sea:vessel:imo^="IMO 123"'))
113
+ self.len(1, await core.nodes('transport:sea:vessel -> transport:sea:vessel:type:taxonomy'))
111
114
 
112
115
  seatelem = (await core.nodes('''[
113
116
  transport:sea:telem=*
@@ -166,6 +169,7 @@ class TransportTest(s_test.SynTest):
166
169
  :make=lotus
167
170
  :model=elise
168
171
  :registration=$regid
172
+ :type=car
169
173
  :owner={gen.ps.contact.email us.va.dmv visi@vertex.link}
170
174
  ]}
171
175
 
@@ -192,12 +196,14 @@ class TransportTest(s_test.SynTest):
192
196
 
193
197
  nodes = await core.nodes('transport:land:registration:id=zeroday :vehicle -> transport:land:vehicle')
194
198
  self.len(1, nodes)
199
+ self.eq(nodes[0].get('type'), 'car.')
195
200
  self.eq(nodes[0].get('make'), 'lotus')
196
201
  self.eq(nodes[0].get('model'), 'elise')
197
202
  self.eq(nodes[0].get('serial'), 'V-31337')
198
203
  self.eq(nodes[0].get('built'), 1104537600000)
199
204
  self.nn(nodes[0].get('owner'))
200
205
  self.nn(nodes[0].get('registration'))
206
+ self.len(1, await core.nodes('transport:land:vehicle -> transport:land:vehicle:type:taxonomy'))
201
207
 
202
208
  nodes = await core.nodes('transport:land:registration:id=zeroday -> transport:land:license')
203
209
  self.len(1, nodes)
@@ -208,3 +214,165 @@ class TransportTest(s_test.SynTest):
208
214
 
209
215
  self.nn(nodes[0].get('issuer'))
210
216
  self.nn(nodes[0].get('contact'))
217
+
218
+ nodes = await core.nodes('''[
219
+ transport:land:drive=*
220
+ :vehicle={transport:land:vehicle}
221
+ ]''')
222
+
223
+ self.eq('transport:land:vehicle', nodes[0].get('vehicle')[0])
224
+
225
+ async def test_model_transport_rail(self):
226
+
227
+ async with self.getTestCore() as core:
228
+ nodes = await core.nodes('''[
229
+ transport:rail:train=*
230
+
231
+ :status=completed
232
+ :occupants=1
233
+ :cargo:mass=10kg
234
+ :cargo:volume=10m
235
+
236
+ :duration=03:00:00
237
+ :scheduled:duration=03:00:00
238
+
239
+ :departed=202501171030
240
+ :departed:point=2C
241
+ :departed:place={[ geo:place=* :name="grand central station" ]}
242
+
243
+ :scheduled:departure=202501171030
244
+ :scheduled:departure:point=2C
245
+ :scheduled:departure:place={ geo:place:name="grand central station" }
246
+
247
+ :arrived=202501171330
248
+ :arrived:place={[ geo:place=* :name="union station" ]}
249
+ :arrived:point=2C
250
+
251
+ :scheduled:arrival=202501171330
252
+ :scheduled:arrival:place={ geo:place:name="union station" }
253
+ :scheduled:arrival:point=2C
254
+
255
+ :vehicle={[
256
+ transport:rail:consist=*
257
+ :max:occupants=2
258
+ :cars={[
259
+ transport:rail:car=*
260
+ :serial=001
261
+ :type=engine.diesel
262
+ :built=20221212
263
+ :manufacturer:name=acme
264
+ :manufacturer={[ ou:org=({"name": "acme"}) ]}
265
+ :model="Engine That Could"
266
+ :max:occupants=2
267
+ :max:cargo:mass=1000kg
268
+ :max:cargo:volume=1000m
269
+ :owner={[ ps:contact=* :name="road runner" ]}
270
+ ]}
271
+ ]}
272
+ :operator={[ ps:contact=* :name="visi" ]}
273
+ ]''')
274
+
275
+ self.eq(10800000, nodes[0].get('duration'))
276
+ self.eq(10800000, nodes[0].get('scheduled:duration'))
277
+
278
+ self.eq(1737109800000, nodes[0].get('departed'))
279
+ self.eq('2c', nodes[0].get('departed:point'))
280
+ self.nn(nodes[0].get('departed:place'))
281
+
282
+ self.eq(1737109800000, nodes[0].get('scheduled:departure'))
283
+ self.eq('2c', nodes[0].get('scheduled:departure:point'))
284
+ self.nn(nodes[0].get('scheduled:departure:place'))
285
+
286
+ self.eq(1737120600000, nodes[0].get('arrived'))
287
+ self.nn(nodes[0].get('arrived:place'))
288
+ self.eq('2c', nodes[0].get('arrived:point'))
289
+
290
+ self.eq(1737120600000, nodes[0].get('scheduled:arrival'))
291
+ self.nn(nodes[0].get('scheduled:arrival:place'))
292
+ self.eq('2c', nodes[0].get('scheduled:arrival:point'))
293
+
294
+ nodes = await core.nodes('transport:rail:consist')
295
+ self.eq(2, nodes[0].get('max:occupants'))
296
+ self.len(1, nodes[0].get('cars'))
297
+
298
+ nodes = await core.nodes('transport:rail:car')
299
+ self.eq('001', nodes[0].get('serial'))
300
+ self.eq('engine.diesel.', nodes[0].get('type'))
301
+ self.eq(1670803200000, nodes[0].get('built'))
302
+ self.eq('acme', nodes[0].get('manufacturer:name'))
303
+ self.eq('engine that could', nodes[0].get('model'))
304
+ self.eq(2, nodes[0].get('max:occupants'))
305
+ self.eq('1000000', nodes[0].get('max:cargo:mass'))
306
+ self.eq(1000000, nodes[0].get('max:cargo:volume'))
307
+ self.len(1, await core.nodes('transport:rail:car -> transport:rail:car:type:taxonomy'))
308
+
309
+ self.nn(nodes[0].get('owner'))
310
+
311
+ nodes = await core.nodes('''[
312
+ transport:stop=*
313
+ :arrived:place={[ geo:place=* :name="BWI Rail Station" ]}
314
+ :trip={ transport:rail:train }
315
+ ]''')
316
+ self.nn(nodes[0].get('arrived:place'))
317
+ self.eq('transport:rail:train', nodes[0].get('trip')[0])
318
+
319
+ nodes = await core.nodes('''[
320
+ transport:occupant=*
321
+ :role=passenger
322
+ :contact={[ ps:contact=({"name": "visi"}) ]}
323
+ :trip={ transport:rail:train }
324
+ :vehicle={ transport:rail:consist }
325
+ :seat=2c
326
+ :boarded=202501171020
327
+ :boarded:point=2c
328
+ :boarded:place={ geo:place:name="grand central station" }
329
+
330
+ :disembarked=202501171335
331
+ :disembarked:point=2c
332
+ :disembarked:place={ geo:place:name="union station" }
333
+ ]''')
334
+ self.nn(nodes[0].get('contact'))
335
+ self.eq('2c', nodes[0].get('seat'))
336
+ self.eq('passenger.', nodes[0].get('role'))
337
+ self.eq('transport:rail:train', nodes[0].get('trip')[0])
338
+ self.eq('transport:rail:consist', nodes[0].get('vehicle')[0])
339
+
340
+ self.eq(1737109200000, nodes[0].get('boarded'))
341
+ self.nn(nodes[0].get('boarded:place'))
342
+ self.eq('2c', nodes[0].get('boarded:point'))
343
+
344
+ self.eq(1737120900000, nodes[0].get('disembarked'))
345
+ self.nn(nodes[0].get('disembarked:place'))
346
+ self.eq('2c', nodes[0].get('disembarked:point'))
347
+ self.len(1, await core.nodes('transport:occupant -> transport:occupant:role:taxonomy'))
348
+
349
+ nodes = await core.nodes('''[
350
+ transport:cargo=*
351
+
352
+ :trip={ transport:rail:train }
353
+ :vehicle={ transport:rail:consist }
354
+
355
+ :container={ transport:rail:car }
356
+ :object={[ transport:shipping:container=({"serial": "007"}) ]}
357
+
358
+ :loaded=202501171020
359
+ :loaded:point=2c
360
+ :loaded:place={ geo:place:name="grand central station" }
361
+
362
+ :unloaded=202501171335
363
+ :unloaded:point=2c
364
+ :unloaded:place={ geo:place:name="union station" }
365
+ ]''')
366
+
367
+ self.eq('transport:rail:train', nodes[0].get('trip')[0])
368
+ self.eq('transport:rail:car', nodes[0].get('container')[0])
369
+ self.eq('transport:rail:consist', nodes[0].get('vehicle')[0])
370
+ self.eq('transport:shipping:container', nodes[0].get('object')[0])
371
+
372
+ self.eq(1737109200000, nodes[0].get('loaded'))
373
+ self.nn(nodes[0].get('loaded:place'))
374
+ self.eq('2c', nodes[0].get('loaded:point'))
375
+
376
+ self.eq(1737120900000, nodes[0].get('unloaded'))
377
+ self.nn(nodes[0].get('unloaded:place'))
378
+ self.eq('2c', nodes[0].get('unloaded:point'))
@@ -19,6 +19,7 @@ import synapse.telepath as s_telepath
19
19
  import synapse.lib.cell as s_cell
20
20
  import synapse.lib.coro as s_coro
21
21
  import synapse.lib.link as s_link
22
+ import synapse.lib.const as s_const
22
23
  import synapse.lib.share as s_share
23
24
  import synapse.lib.certdir as s_certdir
24
25
  import synapse.lib.version as s_version
@@ -68,6 +69,10 @@ class Foo:
68
69
  def echo(self, x):
69
70
  return x
70
71
 
72
+ def echosize(self, array: list[bytes]):
73
+ total = sum([len(bytz) for bytz in array])
74
+ return total
75
+
71
76
  def speed(self):
72
77
  return
73
78
 
@@ -230,11 +235,13 @@ class TeleTest(s_t_utils.SynTest):
230
235
  # Add an additional prox.fini handler.
231
236
  prox.onfini(evt.set)
232
237
 
233
- # check a standard return value
234
- self.eq(30, await prox.bar(10, 20))
238
+ with mock.patch('synapse.lib.link.MAXWRITE', 2):
235
239
 
236
- # check a coroutine return value
237
- self.eq(25, await prox.corovalu(10, 5))
240
+ # check a standard return value
241
+ self.eq(30, await prox.bar(10, 20))
242
+
243
+ # check a coroutine return value
244
+ self.eq(25, await prox.corovalu(10, 5))
238
245
 
239
246
  # check a generator return channel
240
247
  genr = await prox.genr()
@@ -1227,7 +1234,7 @@ class TeleTest(s_t_utils.SynTest):
1227
1234
  self.isin('synapse.tests.test_telepath.Foo', proxy._getClasses())
1228
1235
  self.eq(await proxy.echo('oh hi mark!'), 'oh hi mark!')
1229
1236
 
1230
- async def test_tls_ciphers(self):
1237
+ async def test_tls_support_and_ciphers(self):
1231
1238
 
1232
1239
  self.thisHostMustNot(platform='darwin')
1233
1240
 
@@ -1249,6 +1256,18 @@ class TeleTest(s_t_utils.SynTest):
1249
1256
  async with await s_telepath.openurl(f'ssl://{hostname}/foo', port=port) as prox:
1250
1257
  self.eq(30, await prox.bar(10, 20))
1251
1258
 
1259
+ # This will generate a large msgpack object which can cause
1260
+ # openssl to have malloc failures. Prior to the write chunking
1261
+ # changes, this would cause a generally fatal error to any
1262
+ # processes which rely on the calls work, such as mirror loops.
1263
+ blob = b'V' * s_const.mebibyte * 256
1264
+ nblobs = 8
1265
+ total = nblobs * len(blob)
1266
+ blobarray = []
1267
+ for i in range(nblobs):
1268
+ blobarray.append(blob)
1269
+ self.eq(await prox.echosize(blobarray), total)
1270
+
1252
1271
  sslctx = ssl.SSLContext(protocol=ssl.PROTOCOL_TLSv1)
1253
1272
  with self.raises((ssl.SSLError, ConnectionResetError)):
1254
1273
  link = await s_link.connect(hostname, port=port, ssl=sslctx)
@@ -122,7 +122,11 @@ class ModelDiffer:
122
122
  deprecated_edges[edge] = curinfo
123
123
  continue
124
124
 
125
- # TODO - Support changes to the edges?
125
+ if oldinfo.get('doc') != curinfo.get('doc'):
126
+ updated_edges[edge] = curinfo
127
+ continue
128
+
129
+ # TODO - Support additional changes to the edges?
126
130
  assert False, f'A change was found for the edge: {edge}'
127
131
 
128
132
  if updated_edges:
@@ -637,6 +641,9 @@ def _gen_model_rst(version, model_ref, changes, current_model, outp: s_output.Ou
637
641
  # We don't really have a "updated forms" to display since the delta for forms data is really property
638
642
  # deltas covered elsewhere.
639
643
 
644
+ # Updated Edges
645
+ # TODO Add support for updated edges
646
+
640
647
  # Updated Properties
641
648
  upd_props = []
642
649
  for form, info in updated_forms.items():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: synapse
3
- Version: 2.194.0
3
+ Version: 2.195.0
4
4
  Summary: Synapse Intelligence Analysis Framework
5
5
  Author-email: The Vertex Project LLC <root@vertex.link>
6
6
  License: Apache License 2.0