synapse 2.182.0__py311-none-any.whl → 2.184.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/cortex.py +5 -0
- synapse/datamodel.py +41 -3
- synapse/lib/ast.py +4 -3
- synapse/lib/autodoc.py +71 -5
- synapse/lib/cell.py +1 -1
- synapse/lib/storm.py +23 -0
- synapse/lib/stormlib/cortex.py +1 -0
- synapse/lib/stormlib/graph.py +17 -0
- synapse/lib/stormlib/infosec.py +2 -0
- synapse/lib/stormlib/model.py +2 -1
- synapse/lib/stormlib/random.py +84 -3
- synapse/lib/stormtypes.py +4 -0
- synapse/lib/stormwhois.py +3 -0
- synapse/lib/version.py +2 -2
- synapse/models/infotech.py +3 -15
- synapse/models/orgs.py +76 -2
- synapse/models/risk.py +22 -0
- synapse/tests/files/stormpkg/testpkg.yaml +10 -0
- synapse/tests/test_cortex.py +31 -44
- synapse/tests/test_lib_ast.py +58 -0
- synapse/tests/test_lib_autodoc.py +85 -0
- synapse/tests/test_lib_storm.py +18 -0
- synapse/tests/test_lib_stormlib_modelext.py +52 -0
- synapse/tests/test_lib_stormlib_random.py +93 -0
- synapse/tests/test_lib_stormwhois.py +4 -4
- synapse/tests/test_model_infotech.py +44 -1
- synapse/tests/test_model_orgs.py +37 -0
- synapse/tests/test_model_risk.py +3 -0
- synapse/tests/test_tools_autodoc.py +6 -0
- synapse/tests/utils.py +28 -0
- synapse/tools/autodoc.py +2 -1
- synapse/tools/changelog.py +53 -10
- {synapse-2.182.0.dist-info → synapse-2.184.0.dist-info}/METADATA +1 -1
- {synapse-2.182.0.dist-info → synapse-2.184.0.dist-info}/RECORD +37 -37
- {synapse-2.182.0.dist-info → synapse-2.184.0.dist-info}/WHEEL +1 -1
- {synapse-2.182.0.dist-info → synapse-2.184.0.dist-info}/LICENSE +0 -0
- {synapse-2.182.0.dist-info → synapse-2.184.0.dist-info}/top_level.txt +0 -0
|
@@ -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)
|
|
@@ -84,8 +84,8 @@ class StormWhoisTest(s_test.SynTest):
|
|
|
84
84
|
'''
|
|
85
85
|
opts = {'vars': {'props': props}}
|
|
86
86
|
mesgs = await core.stormlist(stormcmd, opts=opts)
|
|
87
|
-
|
|
88
|
-
self.
|
|
87
|
+
self.stormIsInWarn('$lib.inet.whois.guid() is deprecated', mesgs)
|
|
88
|
+
self.stormIsInWarn('Insufficient guid vals identified, using random guid:', mesgs)
|
|
89
89
|
self.len(1, await core.nodes(f'inet:whois:ipquery:fqdn={props["fqdn"]}'))
|
|
90
90
|
|
|
91
91
|
props = {
|
|
@@ -97,8 +97,8 @@ class StormWhoisTest(s_test.SynTest):
|
|
|
97
97
|
'''
|
|
98
98
|
opts = {'vars': {'props': props}}
|
|
99
99
|
mesgs = await core.stormlist(stormcmd, opts=opts)
|
|
100
|
-
|
|
101
|
-
self.
|
|
100
|
+
self.stormIsInWarn('$lib.inet.whois.guid() is deprecated', mesgs)
|
|
101
|
+
self.stormIsInWarn('Insufficient guid vals identified, using random guid:', mesgs)
|
|
102
102
|
self.len(1, await core.nodes(f'inet:whois:ipcontact:asn={props["asn"]}'))
|
|
103
103
|
|
|
104
104
|
# Failure cases
|
|
@@ -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:
|
|
@@ -1636,8 +1675,12 @@ class InfotechModelTest(s_t_utils.SynTest):
|
|
|
1636
1675
|
self.eq(1640995200000, nodes[0].get('updated'))
|
|
1637
1676
|
self.nn(nodes[0].get('author'))
|
|
1638
1677
|
|
|
1639
|
-
nodes = await core.nodes('[ it:app:snort:hit=$hit
|
|
1678
|
+
nodes = await core.nodes('''[ it:app:snort:hit=$hit
|
|
1679
|
+
:rule=$rule :flow=$flow :src="tcp://[::ffff:0102:0304]:0"
|
|
1680
|
+
:dst="tcp://[::ffff:0505:0505]:80" :time=2015 :sensor=$host
|
|
1681
|
+
:version=1.2.3 :dropped=true ]''', opts=opts)
|
|
1640
1682
|
self.len(1, nodes)
|
|
1683
|
+
self.true(nodes[0].get('dropped'))
|
|
1641
1684
|
self.eq(rule, nodes[0].get('rule'))
|
|
1642
1685
|
self.eq(flow, nodes[0].get('flow'))
|
|
1643
1686
|
self.eq(host, nodes[0].get('sensor'))
|
synapse/tests/test_model_orgs.py
CHANGED
|
@@ -640,6 +640,7 @@ class OuModelTest(s_t_utils.SynTest):
|
|
|
640
640
|
|
|
641
641
|
nodes = await core.nodes('''[ ou:requirement=50b757fafe4a839ec499023ebcffe7c0
|
|
642
642
|
:name="acquire pizza toppings"
|
|
643
|
+
:type=foo.bar
|
|
643
644
|
:text="The team must acquire ANSI standard pizza toppings."
|
|
644
645
|
:goal={[ ou:goal=* :name=pizza ]}
|
|
645
646
|
:issuer={[ ps:contact=* :name=visi ]}
|
|
@@ -657,6 +658,7 @@ class OuModelTest(s_t_utils.SynTest):
|
|
|
657
658
|
self.eq('The team must acquire ANSI standard pizza toppings.', nodes[0].get('text'))
|
|
658
659
|
self.eq(1, nodes[0].get('deps:min'))
|
|
659
660
|
self.eq(50, nodes[0].get('priority'))
|
|
661
|
+
self.eq('foo.bar.', nodes[0].get('type'))
|
|
660
662
|
self.eq(True, nodes[0].get('optional'))
|
|
661
663
|
self.eq(1328140800000, nodes[0].get('issued'))
|
|
662
664
|
self.eq((1672531200000, 9223372036854775807), nodes[0].get('period'))
|
|
@@ -665,6 +667,39 @@ class OuModelTest(s_t_utils.SynTest):
|
|
|
665
667
|
self.len(1, await core.nodes('ou:requirement=50b757fafe4a839ec499023ebcffe7c0 -> ou:goal +:name=pizza'))
|
|
666
668
|
self.len(1, await core.nodes('ou:requirement=50b757fafe4a839ec499023ebcffe7c0 :issuer -> ps:contact +:name=visi'))
|
|
667
669
|
self.len(1, await core.nodes('ou:requirement=50b757fafe4a839ec499023ebcffe7c0 :assignee -> ps:contact +:orgname=ledos'))
|
|
670
|
+
self.len(1, await core.nodes('ou:requirement=50b757fafe4a839ec499023ebcffe7c0 -> ou:requirement:type:taxonomy'))
|
|
671
|
+
|
|
672
|
+
nodes = await core.nodes('''
|
|
673
|
+
[ ou:asset=*
|
|
674
|
+
:id=V-31337
|
|
675
|
+
:name="visi laptop"
|
|
676
|
+
:type=host.laptop
|
|
677
|
+
:priority=highest
|
|
678
|
+
:priority:confidentiality=highest
|
|
679
|
+
:priority:integrity=highest
|
|
680
|
+
:priority:availability=highest
|
|
681
|
+
:node = (it:host, *)
|
|
682
|
+
:period=(2016, ?)
|
|
683
|
+
:status=deployed
|
|
684
|
+
:org={[ ou:org=* :name=vertex ]}
|
|
685
|
+
:owner={[ ps:contact=* :name=foo ]}
|
|
686
|
+
:operator={[ ps:contact=* :name=bar ]}
|
|
687
|
+
]''')
|
|
688
|
+
self.len(1, nodes)
|
|
689
|
+
self.eq((1451606400000, 9223372036854775807), nodes[0].get('period'))
|
|
690
|
+
self.eq('visi laptop', nodes[0].get('name'))
|
|
691
|
+
self.eq('host.laptop.', nodes[0].get('type'))
|
|
692
|
+
self.eq('deployed.', nodes[0].get('status'))
|
|
693
|
+
self.eq(50, nodes[0].get('priority'))
|
|
694
|
+
self.eq(50, nodes[0].get('priority:confidentiality'))
|
|
695
|
+
self.eq(50, nodes[0].get('priority:integrity'))
|
|
696
|
+
self.eq(50, nodes[0].get('priority:availability'))
|
|
697
|
+
|
|
698
|
+
self.len(1, await core.nodes('ou:asset -> ou:asset:type:taxonomy'))
|
|
699
|
+
self.len(1, await core.nodes('ou:asset :node -> it:host'))
|
|
700
|
+
self.len(1, await core.nodes('ou:asset :org -> ou:org +:name=vertex'))
|
|
701
|
+
self.len(1, await core.nodes('ou:asset :owner -> ps:contact +:name=foo '))
|
|
702
|
+
self.len(1, await core.nodes('ou:asset :operator -> ps:contact +:name=bar '))
|
|
668
703
|
|
|
669
704
|
async def test_ou_code_prefixes(self):
|
|
670
705
|
guid0 = s_common.guid()
|
|
@@ -832,6 +867,7 @@ class OuModelTest(s_t_utils.SynTest):
|
|
|
832
867
|
:orgfqdn = wootwoot.com
|
|
833
868
|
:currency = USD
|
|
834
869
|
:costs = 200
|
|
870
|
+
:budget = 300
|
|
835
871
|
:revenue = 500
|
|
836
872
|
:profit = 300
|
|
837
873
|
:valuation = 1000000000
|
|
@@ -850,6 +886,7 @@ class OuModelTest(s_t_utils.SynTest):
|
|
|
850
886
|
self.eq(nodes[0].get('orgfqdn'), 'wootwoot.com')
|
|
851
887
|
self.eq(nodes[0].get('currency'), 'usd')
|
|
852
888
|
self.eq(nodes[0].get('costs'), '200')
|
|
889
|
+
self.eq(nodes[0].get('budget'), '300')
|
|
853
890
|
self.eq(nodes[0].get('revenue'), '500')
|
|
854
891
|
self.eq(nodes[0].get('profit'), '300')
|
|
855
892
|
self.eq(nodes[0].get('valuation'), '1000000000')
|
synapse/tests/test_model_risk.py
CHANGED
|
@@ -542,6 +542,7 @@ class RiskModelTest(s_t_utils.SynTest):
|
|
|
542
542
|
risk:mitigation=*
|
|
543
543
|
:vuln=*
|
|
544
544
|
:name=" FooBar "
|
|
545
|
+
:type=foo.bar
|
|
545
546
|
:desc=BazFaz
|
|
546
547
|
:hardware=*
|
|
547
548
|
:software=*
|
|
@@ -552,11 +553,13 @@ class RiskModelTest(s_t_utils.SynTest):
|
|
|
552
553
|
self.eq('foobar', nodes[0].props['name'])
|
|
553
554
|
self.eq('BazFaz', nodes[0].props['desc'])
|
|
554
555
|
self.eq('vertex', nodes[0].get('reporter:name'))
|
|
556
|
+
self.eq('foo.bar.', nodes[0].get('type'))
|
|
555
557
|
self.nn(nodes[0].get('reporter'))
|
|
556
558
|
self.len(1, await core.nodes('risk:mitigation -> risk:vuln'))
|
|
557
559
|
self.len(1, await core.nodes('risk:mitigation -> it:prod:softver'))
|
|
558
560
|
self.len(1, await core.nodes('risk:mitigation -> it:prod:hardware'))
|
|
559
561
|
self.len(1, await core.nodes('risk:mitigation -> it:mitre:attack:mitigation'))
|
|
562
|
+
self.len(1, await core.nodes('risk:mitigation -> risk:mitigation:type:taxonomy'))
|
|
560
563
|
|
|
561
564
|
async def test_model_risk_tool_software(self):
|
|
562
565
|
|
|
@@ -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', [])
|
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.', },
|
|
@@ -199,6 +201,32 @@ class LibTst(s_stormtypes.Lib):
|
|
|
199
201
|
ret = f'A {valu} beep which {bar} the {faz}!'
|
|
200
202
|
return ret
|
|
201
203
|
|
|
204
|
+
class LibDepr(s_stormtypes.Lib):
|
|
205
|
+
'''
|
|
206
|
+
Deprecate me!
|
|
207
|
+
'''
|
|
208
|
+
_storm_locals = (
|
|
209
|
+
{'name': 'boop',
|
|
210
|
+
'desc': '''
|
|
211
|
+
An example storm function that's not deprecated on its own, but the entire library is.
|
|
212
|
+
''',
|
|
213
|
+
'type': {'type': 'function', '_funcname': 'boop',
|
|
214
|
+
'args': (
|
|
215
|
+
{'name': 'valu', 'type': 'str', 'desc': 'What to boop.', },
|
|
216
|
+
),
|
|
217
|
+
'returns': {'type': 'str', 'desc': 'The booped.', }}},
|
|
218
|
+
)
|
|
219
|
+
_storm_lib_path = ('depr',)
|
|
220
|
+
_storm_lib_deprecation = {'eolvers': 'v3.0.0'}
|
|
221
|
+
|
|
222
|
+
def addLibFuncs(self): # pragma: no cover
|
|
223
|
+
self.locls.update({
|
|
224
|
+
'boop': self.boop,
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
async def boop(self, valu): # pragma: no cover
|
|
228
|
+
return f'You have been booped, {valu}!'
|
|
229
|
+
|
|
202
230
|
class TestType(s_types.Type):
|
|
203
231
|
|
|
204
232
|
stortype = s_layer.STOR_TYPE_UTF8
|
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))
|
synapse/tools/changelog.py
CHANGED
|
@@ -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
|
-
|
|
573
|
-
|
|
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
|
|
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
|
-
|
|
628
|
-
|
|
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
|
-
|
|
639
|
-
|
|
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',
|