synapse 2.181.0__py311-none-any.whl → 2.183.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.

@@ -30,6 +30,16 @@ modules:
30
30
  returns:
31
31
  type: dict
32
32
  desc: A status dictionary.
33
+ - name: newp
34
+ desc: Some nonexistent function.
35
+ deprecated:
36
+ eolvers: v2.300.4
37
+ mesg: Newp is no longer maintained. Use bar() instead.
38
+ type:
39
+ type: function
40
+ returns:
41
+ type: 'null'
42
+ desc: '``newp()`` does not return data.'
33
43
 
34
44
  onload: |
35
45
  $lib.time.sleep($lib.globals.get(onload_sleep, 0))
@@ -2985,6 +2985,16 @@ class CortexBasicTest(s_t_utils.SynTest):
2985
2985
  info = await view.pack()
2986
2986
  self.eq(info['name'], 'default')
2987
2987
 
2988
+ depr = [x for x in coreinfo['stormdocs']['libraries'] if x['path'] == ('lib', 'bytes')]
2989
+ self.len(1, depr)
2990
+ deprinfo = depr[0].get('deprecated')
2991
+ self.nn(deprinfo)
2992
+ self.eq(deprinfo.get('eolvers'), 'v3.0.0')
2993
+
2994
+ depr = [x for x in coreinfo['stormdocs']['libraries'] if x['path'] == ('lib', 'infosec', 'cvss')]
2995
+ self.len(1, depr)
2996
+ self.len(2, [x for x in depr[0]['locals'] if x.get('deprecated')])
2997
+
2988
2998
  async def test_cortex_model_dict(self):
2989
2999
 
2990
3000
  async with self.getTestCoreAndProxy() as (core, prox):
@@ -7195,6 +7205,12 @@ class CortexBasicTest(s_t_utils.SynTest):
7195
7205
  with self.raises(s_exc.BadTag):
7196
7206
  await core.nodes('[ inet:ipv4=1.2.3.4 +#cno.cve.12345 ]')
7197
7207
 
7208
+ nodes = await core.nodes('[ test:str=beep +?#cno.cve.12345 ]')
7209
+ self.len(1, nodes)
7210
+ self.none(nodes[0].get('#cno'))
7211
+ self.none(nodes[0].get('#cno.cve'))
7212
+ self.none(nodes[0].get('#cno.cve.12345'))
7213
+
7198
7214
  self.eq((None, None, '[0-9]{4}', '[0-9]{5}'), await core.callStorm('''
7199
7215
  return($lib.model.tags.pop(cno.cve, regex))
7200
7216
  '''))
@@ -1,4 +1,6 @@
1
1
  import copy
2
+
3
+ import synapse.exc as s_exc
2
4
  import synapse.lib.autodoc as s_autodoc
3
5
  import synapse.lib.stormtypes as s_stormtypes
4
6
 
@@ -153,6 +155,10 @@ LibTst for testing!
153
155
  beep(valu)
154
156
  ==========
155
157
 
158
+ .. warning::
159
+ ``$lib.test.beep`` has been deprecated and will be removed on or after 8080-08-08.
160
+
161
+
156
162
  Example storm func.
157
163
 
158
164
  Notes:
@@ -173,6 +179,11 @@ Returns:
173
179
  someargs(valu, bar=$lib.true, faz=$lib.null)
174
180
  ============================================
175
181
 
182
+ .. warning::
183
+ ``$lib.test.someargs`` has been deprecated and will be removed in version v3.0.0.
184
+ This is a test library was deprecated from the day it was made.
185
+
186
+
176
187
  Example storm func with args.
177
188
 
178
189
 
@@ -220,6 +231,10 @@ LibTst for testing!
220
231
  $lib.test.beep(valu)
221
232
  ====================
222
233
 
234
+ .. warning::
235
+ ``$lib.test.beep`` has been deprecated and will be removed on or after 8080-08-08.
236
+
237
+
223
238
  Example storm func.
224
239
 
225
240
  Notes:
@@ -240,6 +255,11 @@ Returns:
240
255
  $lib.test.someargs(valu, bar=$lib.true, faz=$lib.null)
241
256
  ======================================================
242
257
 
258
+ .. warning::
259
+ ``$lib.test.someargs`` has been deprecated and will be removed in version v3.0.0.
260
+ This is a test library was deprecated from the day it was made.
261
+
262
+
243
263
  Example storm func with args.
244
264
 
245
265
 
@@ -257,3 +277,14 @@ Args:
257
277
  Returns:
258
278
  The beeped string. The return type is ``str``.'''
259
279
  self.eq(text, expected)
280
+
281
+ badlocls = copy.deepcopy(libtst._storm_locals)
282
+ badlocls[0]['deprecated']['eolvers'] = 'v4.4.4'
283
+ page = s_autodoc.RstHelp()
284
+ doc = {
285
+ 'desc': s_stormtypes.getDoc(libtst, "err"),
286
+ 'path': ('lib',) + libtst._storm_lib_path,
287
+ 'locals': badlocls,
288
+ }
289
+ with self.raises(s_exc.SchemaViolation):
290
+ s_autodoc.docStormTypes(page, (doc,), linkprefix='test')
@@ -2355,6 +2355,18 @@ class CellTest(s_t_utils.SynTest):
2355
2355
 
2356
2356
  async with self.getTestCore() as core:
2357
2357
 
2358
+ # This tmp_reason assertion seems counter-intuitive at first; but it's really
2359
+ # asserting that the message which was incorrectly being logged is no longer logged.
2360
+ log_enable_writes = f'Free space on {core.dirn} above minimum threshold'
2361
+ with self.getAsyncLoggerStream('synapse.lib.cell', log_enable_writes) as stream:
2362
+ await core.nexsroot.addWriteHold(tmp_reason := 'something else')
2363
+ self.false(await stream.wait(1))
2364
+ stream.seek(0)
2365
+ self.eq(stream.read(), '')
2366
+
2367
+ await core.nexsroot.delWriteHold(tmp_reason)
2368
+ revt.clear()
2369
+
2358
2370
  self.len(1, await core.nodes('[inet:fqdn=vertex.link]'))
2359
2371
 
2360
2372
  with mock.patch('shutil.disk_usage', full_disk):
@@ -1,3 +1,4 @@
1
+ import copy
1
2
  import json
2
3
  import asyncio
3
4
  import datetime
@@ -1554,6 +1555,43 @@ class StormTest(s_t_utils.SynTest):
1554
1555
  msgs = await core.stormlist('test:ro | merge', opts=altview)
1555
1556
  self.stormIsInWarn("Cannot merge read only property with conflicting value", msgs)
1556
1557
 
1558
+ async def test_storm_merge_stricterr(self):
1559
+
1560
+ conf = {'modules': [('synapse.tests.utils.DeprModule', {})]}
1561
+ async with self.getTestCore(conf=copy.deepcopy(conf)) as core:
1562
+
1563
+ await core.nodes('$lib.model.ext.addFormProp(test:deprprop, _str, (str, ({})), ({}))')
1564
+
1565
+ viewiden = await core.callStorm('return($lib.view.get().fork().iden)')
1566
+ asfork = {'view': viewiden}
1567
+
1568
+ await core.nodes('[ test:deprprop=base ]')
1569
+
1570
+ self.len(1, await core.nodes('test:deprprop=base [ :_str=foo +#test ]', opts=asfork))
1571
+ await core.nodes('[ test:deprprop=fork test:str=other ]', opts=asfork)
1572
+
1573
+ await core.nodes('model.deprecated.lock test:deprprop')
1574
+
1575
+ msgs = await core.stormlist('diff | merge --apply --no-tags', opts=asfork)
1576
+ self.stormIsInWarn('Form test:deprprop is locked due to deprecation for valu=base', msgs)
1577
+ self.stormIsInWarn('Form test:deprprop is locked due to deprecation for valu=fork', msgs)
1578
+ self.stormHasNoErr(msgs)
1579
+
1580
+ msgs = await core.stormlist('diff | merge --apply --only-tags', opts=asfork)
1581
+ self.stormIsInWarn('Form test:deprprop is locked due to deprecation for valu=base', msgs)
1582
+ self.stormHasNoErr(msgs)
1583
+
1584
+ self.eq({
1585
+ 'meta:source': 1,
1586
+ 'syn:tag': 1,
1587
+ 'test:deprprop': 1,
1588
+ 'test:str': 1,
1589
+ }, await core.callStorm('return($lib.view.get().getFormCounts())'))
1590
+
1591
+ nodes = await core.nodes('test:deprprop')
1592
+ self.eq(['base'], [n.ndef[1] for n in nodes])
1593
+ self.eq([], nodes[0].getTags())
1594
+
1557
1595
  async def test_storm_merge_opts(self):
1558
1596
 
1559
1597
  async with self.getTestCore() as core:
@@ -3875,6 +3913,10 @@ class StormTest(s_t_utils.SynTest):
3875
3913
  self.stormIsInPrint('Returns an ou:org by name, adding the node if it does not exist.\n'
3876
3914
  'Args:\n name (str): The name of the org.', msgs)
3877
3915
 
3916
+ msgs = await core.stormlist('help --verbose $lib.infosec.cvss.saveVectToNode')
3917
+ self.stormIsInPrint('Warning', msgs)
3918
+ self.stormIsInPrint('``$lib.infosec.cvss.saveVectToNode`` has been deprecated and will be removed in version v3.0.0.', msgs)
3919
+
3878
3920
  msgs = await core.stormlist('help $lib.inet')
3879
3921
  self.stormIsInPrint('The following libraries are available:\n\n'
3880
3922
  '$lib.inet.http : A Storm Library exposing an HTTP client API.\n'
@@ -988,6 +988,21 @@ class StormLibAuthTest(s_test.SynTest):
988
988
  msgs = await core.stormlist(f'$lib.auth.roles.del({iden})', opts=aslowuser)
989
989
  self.stormHasNoWarnErr(msgs)
990
990
 
991
+ # Use arbitrary idens when creating roles.
992
+ iden = '9e0998f68b662ed3776b6ce33a2d21eb'
993
+ with self.raises(s_exc.BadArg):
994
+ await core.callStorm('$lib.auth.roles.add(runners, iden=12345)')
995
+ opts = {'vars': {'iden': iden}}
996
+ rdef = await core.callStorm('$r=$lib.auth.roles.add(runners, iden=$iden) return ( $r )',
997
+ opts=opts)
998
+ self.eq(rdef.get('iden'), iden)
999
+ ret = await core.callStorm('return($lib.auth.roles.get($iden))', opts=opts)
1000
+ self.eq(ret, rdef)
1001
+ with self.raises(s_exc.DupRoleName):
1002
+ await core.callStorm('$lib.auth.roles.add(runners, iden=$iden)', opts=opts)
1003
+ with self.raises(s_exc.DupIden):
1004
+ await core.callStorm('$lib.auth.roles.add(walkers, iden=$iden)', opts=opts)
1005
+
991
1006
  async def test_stormlib_auth_gateadmin(self):
992
1007
 
993
1008
  async with self.getTestCore() as core:
@@ -20,3 +20,96 @@ class TestLibStormRandom(s_test.SynTest):
20
20
 
21
21
  with self.raises(s_exc.BadArg):
22
22
  await core.callStorm('return($lib.random.int(maxval=0, minval=1))')
23
+
24
+ async def test_stormlib_random_generator(self):
25
+ async with self.getTestCore() as core:
26
+
27
+ # Seedless generators
28
+ q = '''$r=$lib.random.generator()
29
+ return(($r.int(10), $r.int(10), $r.int(10)))
30
+ '''
31
+ valu = await core.callStorm(q)
32
+ for v in valu:
33
+ self.true(v >= 0 and v <= 10)
34
+
35
+ # There is no seed on the generator
36
+ q = '''$r=$lib.random.generator() return ( $r.seed )'''
37
+ valu = await core.callStorm(q)
38
+ self.none(valu)
39
+
40
+ # Generators can be made and seeds set
41
+ q = '''$r=$lib.random.generator() $r.seed=myCoolTestSeed
42
+ return ( (($r.int(10), $r.int(10), $r.int(10)), $r.seed) )'''
43
+ valu = await core.callStorm(q)
44
+ self.eq(valu, ((5, 9, 1), 'myCoolTestSeed'))
45
+
46
+ # Setting a seed resets the generator
47
+ q = '''$r=$lib.random.generator(seed=myCoolTestSeed) $ret=()
48
+ $ret.append($r.int(10)) $ret.append($r.int(10)) $ret.append($r.int(10))
49
+ $r.seed=myCoolTestSeed
50
+ $ret.append($r.int(10)) $ret.append($r.int(10)) $ret.append($r.int(10))
51
+ return ($ret)'''
52
+ valu = await core.callStorm(q)
53
+ self.eq(valu, (5, 9, 1, 5, 9, 1))
54
+
55
+ # Clearing the seed makes the generator random.
56
+ q = '''$r=$lib.random.generator(seed=myCoolTestSeed) $ret=()
57
+ $ret.append($r.int(10)) $ret.append($r.int(10)) $ret.append($r.int(10))
58
+ $r.seed=(null)
59
+ $ret.append($r.int(10)) $ret.append($r.int(10)) $ret.append($r.int(10))
60
+ return ($ret)'''
61
+ valu = await core.callStorm(q)
62
+ self.len(6, valu)
63
+ self.eq(valu[:3], (5, 9, 1))
64
+ self.ne(valu[3:], (5, 9, 1))
65
+ for v in valu[3:]:
66
+ self.true(v >= 0 and v <= 10)
67
+
68
+ # Seeded generators are consistent
69
+ q = '''$r=$lib.random.generator(seed=myCoolTestSeed)
70
+ return(($r.int(10), $r.int(10), $r.int(10)))
71
+ '''
72
+ valu = await core.callStorm(q)
73
+ self.eq(valu, (5, 9, 1))
74
+
75
+ new_valu = await core.callStorm(q)
76
+ self.eq(valu, new_valu)
77
+
78
+ q = '''$r=$lib.random.generator(seed=myCoolTestSeed)
79
+ $r2 = $lib.random.generator(seed=$r.seed)
80
+ return(($r.int(10), $r2.int(10)))
81
+ '''
82
+ valu = await core.callStorm(q)
83
+ self.eq(valu, (5, 5))
84
+
85
+ q = '''return($lib.vars.type($lib.random.generator(x)))'''
86
+ valu = await core.callStorm(q)
87
+ self.eq(valu, 'random')
88
+
89
+ # Seeds are stringified
90
+ q = '''$r=$lib.random.generator(seed=1234567890)
91
+ $r2 = $lib.random.generator(seed=(1234567890))
92
+ return(($r.int(10), $r2.int(10), $r.seed, $r2.seed))
93
+ '''
94
+ valu = await core.callStorm(q)
95
+ self.eq(valu, (5, 5, '1234567890', '1234567890'))
96
+
97
+ # Empty string value is still a str
98
+ q = '''$r=$lib.random.generator(seed='') return ($r.int(10))'''
99
+ valu = await core.callStorm(q)
100
+ self.eq(valu, 7)
101
+
102
+ # Sad path
103
+ with self.raises(s_exc.BadArg):
104
+ await core.callStorm('$r=$lib.random.generator(seed="") return($r.int(maxval=0, minval=1))')
105
+
106
+ # Printing objects
107
+ msgs = await core.stormlist('$lib.print($lib.random.generator())')
108
+ self.stormIsInPrint('random', msgs)
109
+ self.stormNotInPrint('seed=', msgs)
110
+
111
+ msgs = await core.stormlist('$lib.print($lib.random.generator(seed=""))')
112
+ self.stormIsInPrint('random seed=', msgs)
113
+
114
+ msgs = await core.stormlist('$lib.print($lib.random.generator(seed=haha))')
115
+ self.stormIsInPrint('random seed=haha', msgs)
@@ -1547,6 +1547,45 @@ class InfotechModelTest(s_t_utils.SynTest):
1547
1547
  self.nn(node.get('reg'))
1548
1548
  self.eq(node.get('sandbox:file'), sandfile)
1549
1549
 
1550
+ async with self.getTestCore() as core:
1551
+ forms = [
1552
+ 'it:fs:file',
1553
+ 'it:exec:file:add',
1554
+ 'it:exec:file:del',
1555
+ 'it:exec:file:read',
1556
+ 'it:exec:file:write',
1557
+ ]
1558
+
1559
+ for form in forms:
1560
+ opts = {'vars': {'form': form}}
1561
+ nodes = await core.nodes('[ *$form=($form, calc) :path="c:/windows/system32/calc.exe" ]', opts=opts)
1562
+ self.len(1, nodes)
1563
+ self.eq(nodes[0].get('path'), 'c:/windows/system32/calc.exe')
1564
+ self.eq(nodes[0].get('path:base'), 'calc.exe')
1565
+ self.eq(nodes[0].get('path:dir'), 'c:/windows/system32')
1566
+ self.eq(nodes[0].get('path:ext'), 'exe')
1567
+
1568
+ nodes = await core.nodes('*$form=($form, calc) [ :path="c:/users/blackout/script.ps1" ]', opts=opts)
1569
+ self.len(1, nodes)
1570
+ self.eq(nodes[0].get('path'), 'c:/users/blackout/script.ps1')
1571
+ self.eq(nodes[0].get('path:base'), 'script.ps1')
1572
+ self.eq(nodes[0].get('path:dir'), 'c:/users/blackout')
1573
+ self.eq(nodes[0].get('path:ext'), 'ps1')
1574
+
1575
+ nodes = await core.nodes('*$form=($form, calc) [ -:path:base -:path:dir -:path:ext ]', opts=opts)
1576
+ self.len(1, nodes)
1577
+ self.eq(nodes[0].get('path'), 'c:/users/blackout/script.ps1')
1578
+ self.none(nodes[0].get('path:base'))
1579
+ self.none(nodes[0].get('path:dir'))
1580
+ self.none(nodes[0].get('path:ext'))
1581
+
1582
+ nodes = await core.nodes('*$form=($form, calc) [ :path="c:/users/admin/superscript.bat" ]', opts=opts)
1583
+ self.len(1, nodes)
1584
+ self.eq(nodes[0].get('path'), 'c:/users/admin/superscript.bat')
1585
+ self.eq(nodes[0].get('path:base'), 'superscript.bat')
1586
+ self.eq(nodes[0].get('path:dir'), 'c:/users/admin')
1587
+ self.eq(nodes[0].get('path:ext'), 'bat')
1588
+
1550
1589
  async def test_it_app_yara(self):
1551
1590
 
1552
1591
  async with self.getTestCore() as core:
@@ -191,6 +191,12 @@ class TestAutoDoc(s_t_utils.SynTest):
191
191
 
192
192
  self.isin('status()', s)
193
193
 
194
+ self.isin('newp()', s)
195
+ self.isin('.. warning::\n', s)
196
+ self.isin('``newp`` has been deprecated and will be removed in version v2.300.4.', s)
197
+ self.isin('Newp is no longer maintained. Use bar() instead.', s)
198
+ self.isin('Some nonexistent function', s)
199
+
194
200
  # coverage for no apidefs
195
201
  rst = s_l_autodoc.RstHelp()
196
202
  await s_autodoc.processStormModules(rst, 'foo', [])
@@ -366,7 +366,7 @@ class StormCliTest(s_test.SynTest):
366
366
  self.isin(
367
367
  Completion(
368
368
  '.auth.easyperm.allowed',
369
- display='[lib] $lib.auth.easyperm.allowed(edef: dict, level: str) - Check if the current user has a permission level in an easy perm dictionary.'
369
+ display='[lib] $lib.auth.easyperm.allowed(edef: dict, level: int) - Check if the current user has a permission level in an easy perm dictionary.'
370
370
  ),
371
371
  vals
372
372
  )
synapse/tests/utils.py CHANGED
@@ -157,6 +157,7 @@ class LibTst(s_stormtypes.Lib):
157
157
  '''
158
158
  _storm_locals = (
159
159
  {'name': 'beep',
160
+ 'deprecated': {'eoldate': '8080-08-08'},
160
161
  'desc': '''
161
162
  Example storm func.
162
163
 
@@ -169,6 +170,7 @@ class LibTst(s_stormtypes.Lib):
169
170
  'returns': {'type': 'str', 'desc': 'The beeped string.', }}},
170
171
  {'name': 'someargs',
171
172
  'desc': '''Example storm func with args.''',
173
+ 'deprecated': {'eolvers': 'v3.0.0', 'mesg': 'This is a test library was deprecated from the day it was made.'},
172
174
  'type': {'type': 'function', '_funcname': 'someargs',
173
175
  'args': (
174
176
  {'name': 'valu', 'type': 'str', 'desc': 'The value to beep.', },
synapse/tools/autodoc.py CHANGED
@@ -617,7 +617,8 @@ async def processStormModules(rst, pkgname, modules):
617
617
 
618
618
  callsig = s_autodoc.genCallsig(apitype)
619
619
  rst.addHead(f'{apiname}{callsig}', lvl=4)
620
-
620
+ if depr := apidef.get('deprecated'):
621
+ rst.addLines(*s_autodoc.genDeprecationWarning(apiname, depr, True))
621
622
  rst.addLines(*s_autodoc.prepareRstLines(apidesc))
622
623
  rst.addLines(*s_autodoc.getArgLines(apitype))
623
624
  rst.addLines(*s_autodoc.getReturnLines(apitype))
@@ -222,13 +222,25 @@ class ModelDiffer:
222
222
  deprecated_props_noiface[prop] = cpinfo
223
223
  continue
224
224
 
225
+ okeys = set(opinfo.keys())
226
+ nkeys = set(cpinfo.keys())
227
+
228
+ if nkeys - okeys:
229
+ # We've added a key to the prop def.
230
+ raise s_exc.NoSuchImpl(mesg='Have not implemented support for a prop def having a key added')
231
+
232
+ if okeys - nkeys:
233
+ # We've removed a key from the prop def.
234
+ updated_props[prop] = {'type': 'delkey', 'keys': list(okeys - nkeys)}
235
+ continue
236
+
225
237
  # Check if type change happened, we'll want to document that.
226
238
  ctyp = cpinfo.get('type')
227
239
  otyp = opinfo.get('type')
228
240
  if ctyp == otyp:
229
241
  continue
230
242
 
231
- updated_props[prop] = {'new_type': ctyp, 'old_type': otyp}
243
+ updated_props[prop] = {'type': 'type_change', 'new_type': ctyp, 'old_type': otyp}
232
244
  is_ifaceprop = False
233
245
  for iface in self.cur_type2iface[form]:
234
246
  upt_iface = self.changes.get('interfaces').get('updated_interfaces', {}).get(iface)
@@ -237,7 +249,7 @@ class ModelDiffer:
237
249
  break
238
250
  if is_ifaceprop:
239
251
  continue
240
- updated_props_noiface[prop] = {'new_type': ctyp, 'old_type': otyp}
252
+ updated_props_noiface[prop] = {'type': 'type_change', 'new_type': ctyp, 'old_type': otyp}
241
253
 
242
254
  if updated_props:
243
255
  updated_forms[form]['updated_properties'] = updated_props
@@ -317,13 +329,25 @@ class ModelDiffer:
317
329
  deprecated_props[prop] = cpinfo
318
330
  continue
319
331
 
332
+ okeys = set(opinfo.keys())
333
+ nkeys = set(cpinfo.keys())
334
+
335
+ if nkeys - okeys:
336
+ # We've added a key to the prop def.
337
+ raise s_exc.NoSuchImpl(mesg='Have not implemented support for a prop def having a key added')
338
+
339
+ if okeys - nkeys:
340
+ # We've removed a key from the prop def.
341
+ updated_props[prop] = {'type': 'delkey', 'keys': list(okeys - nkeys)}
342
+ continue
343
+
320
344
  # Check if type change happened, we'll want to document that.
321
345
  ctyp = cpinfo.get('type')
322
346
  otyp = opinfo.get('type')
323
347
  if ctyp == otyp:
324
348
  continue
325
349
 
326
- updated_props[prop] = {'new_type': ctyp, 'old_type': otyp}
350
+ updated_props[prop] = {'type': 'type_change', 'new_type': ctyp, 'old_type': otyp}
327
351
  if updated_props:
328
352
  updated_interfaces[iface]['updated_properties'] = updated_props
329
353
 
@@ -569,8 +593,14 @@ def _gen_model_rst(version, model_ref, changes, current_model, outp: s_output.Ou
569
593
  lines.append('\n')
570
594
  elif key == 'updated_properties':
571
595
  for prop, pnfo in sorted(valu.items(), key=lambda x: x[0]):
572
- mesg = f'The property ``{prop}`` has been modified from {pnfo.get("old_type")}' \
573
- f' to {pnfo.get("new_type")}.'
596
+ ptyp = pnfo.get('type')
597
+ if ptyp == 'type_change':
598
+ mesg = f'The property ``{prop}`` has been modified from {pnfo.get("old_type")}' \
599
+ f' to {pnfo.get("new_type")}.'
600
+ elif ptyp == 'delkey':
601
+ mesg = f'The property ``{prop}`` had the ``{pnfo.get("keys")}`` keys removed from its definition.'
602
+ else:
603
+ raise s_exc.NoSuchImpl(mesg=f'pnfo.type={ptyp} not supported.')
574
604
  lines.extend(textwrap.wrap(mesg, initial_indent=' ', subsequent_indent=' ',
575
605
  width=width))
576
606
  lines.append('\n')
@@ -621,11 +651,17 @@ def _gen_model_rst(version, model_ref, changes, current_model, outp: s_output.Ou
621
651
  rst.addLines(f'``{form}``')
622
652
  upd_form_props = list(info.get('updated_properties').items())
623
653
  if len(upd_form_props) > 1:
624
- rst.addLines(' The form had the following updated properties:', '\n')
654
+ rst.addLines(' The form had the following properties updated:', '\n')
625
655
  upd_form_props.sort(key=lambda x: x[0])
626
656
  for prop, pnfo in upd_form_props:
627
- mesg = f'The property ``{prop}`` has been modified from {pnfo.get("old_type")}' \
628
- f' to {pnfo.get("new_type")}.'
657
+ ptyp = pnfo.get('type')
658
+ if ptyp == 'type_change':
659
+ mesg = f'The property ``{prop}`` has been modified from {pnfo.get("old_type")}' \
660
+ f' to {pnfo.get("new_type")}.'
661
+ elif ptyp == 'delkey':
662
+ mesg = f'The property ``{prop}`` had the ``{pnfo.get("keys")}`` keys removed from its definition.'
663
+ else:
664
+ raise s_exc.NoSuchImpl(mesg=f'pnfo.type={ptyp} not supported.')
629
665
  lines = [
630
666
  *textwrap.wrap(mesg, initial_indent=' ', subsequent_indent=' ',
631
667
  width=width),
@@ -635,8 +671,15 @@ def _gen_model_rst(version, model_ref, changes, current_model, outp: s_output.Ou
635
671
 
636
672
  else:
637
673
  prop, pnfo = upd_form_props[0]
638
- mesg = f'The property ``{prop}`` has been modified from {pnfo.get("old_type")}' \
639
- f' to {pnfo.get("new_type")}.'
674
+ ptyp = pnfo.get('type')
675
+ if ptyp == 'type_change':
676
+ mesg = f'The property ``{prop}`` has been modified from {pnfo.get("old_type")}' \
677
+ f' to {pnfo.get("new_type")}.'
678
+ elif ptyp == 'delkey':
679
+ mesg = f'The property ``{prop}`` had the ``{pnfo.get("keys")}`` keys removed from its definition.'
680
+ else:
681
+ raise s_exc.NoSuchImpl(mesg=f'pnfo.type={ptyp} not supported.')
682
+
640
683
  lines = [
641
684
  ' The form had the following property updated:',
642
685
  '\n',
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: synapse
3
- Version: 2.181.0
3
+ Version: 2.183.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
@@ -22,7 +22,7 @@ License-File: LICENSE
22
22
  Requires-Dist: pyOpenSSL<25.0.0,>=24.0.0
23
23
  Requires-Dist: cryptography<44.0.0,>=43.0.1
24
24
  Requires-Dist: msgpack<1.1.0,>=1.0.5
25
- Requires-Dist: xxhash<3.5.0,>=1.4.4
25
+ Requires-Dist: xxhash<3.6.0,>=1.4.4
26
26
  Requires-Dist: lmdb<1.5.0,>=1.2.1
27
27
  Requires-Dist: tornado<7.0.0,>=6.2.0
28
28
  Requires-Dist: regex>=2022.9.11
@@ -34,7 +34,7 @@ Requires-Dist: aiosmtplib<3.1.0,>=3.0.0
34
34
  Requires-Dist: prompt-toolkit<3.1.0,>=3.0.4
35
35
  Requires-Dist: lark==1.1.9
36
36
  Requires-Dist: Pygments<2.18.0,>=2.7.4
37
- Requires-Dist: packaging<24.0,>=20.0
37
+ Requires-Dist: packaging<25.0,>=20.0
38
38
  Requires-Dist: fastjsonschema<2.20.0,>=2.18.0
39
39
  Requires-Dist: stix2-validator<4.0.0,>=3.2.0
40
40
  Requires-Dist: vcrpy<5.2.0,>=4.3.1