synapse 2.178.0__py311-none-any.whl → 2.180.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 +166 -31
- synapse/datamodel.py +47 -1
- synapse/exc.py +1 -0
- synapse/lib/aha.py +2 -1
- synapse/lib/ast.py +110 -76
- synapse/lib/base.py +12 -3
- synapse/lib/cell.py +150 -11
- synapse/lib/coro.py +14 -0
- synapse/lib/drive.py +551 -0
- synapse/lib/layer.py +1 -1
- synapse/lib/lmdbslab.py +2 -0
- synapse/lib/modelrev.py +5 -1
- synapse/lib/node.py +14 -4
- synapse/lib/schemas.py +97 -0
- synapse/lib/snap.py +36 -11
- synapse/lib/storm.py +9 -5
- synapse/lib/stormhttp.py +1 -0
- synapse/lib/stormlib/modelext.py +29 -3
- synapse/lib/stormlib/stix.py +44 -17
- synapse/lib/stormlib/vault.py +2 -2
- synapse/lib/stormtypes.py +1 -1
- synapse/lib/types.py +9 -0
- synapse/lib/version.py +2 -2
- synapse/lookup/pe.py +303 -38
- synapse/models/auth.py +2 -0
- synapse/models/dns.py +24 -1
- synapse/models/geopol.py +3 -0
- synapse/models/geospace.py +4 -1
- synapse/models/inet.py +1 -0
- synapse/models/infotech.py +135 -92
- synapse/models/person.py +5 -2
- synapse/models/telco.py +3 -0
- synapse/tests/test_cortex.py +45 -1
- synapse/tests/test_lib_aha.py +17 -0
- synapse/tests/test_lib_ast.py +231 -0
- synapse/tests/test_lib_cell.py +225 -0
- synapse/tests/test_lib_coro.py +12 -0
- synapse/tests/test_lib_layer.py +22 -0
- synapse/tests/test_lib_modelrev.py +7 -0
- synapse/tests/test_lib_node.py +12 -1
- synapse/tests/test_lib_storm.py +32 -7
- synapse/tests/test_lib_stormhttp.py +40 -0
- synapse/tests/test_lib_stormlib_modelext.py +55 -3
- synapse/tests/test_lib_stormlib_stix.py +15 -0
- synapse/tests/test_lib_stormlib_vault.py +11 -1
- synapse/tests/test_lib_stormtypes.py +5 -0
- synapse/tests/test_lib_types.py +9 -0
- synapse/tests/test_model_dns.py +8 -0
- synapse/tests/test_model_geopol.py +2 -0
- synapse/tests/test_model_geospace.py +3 -1
- synapse/tests/test_model_inet.py +10 -1
- synapse/tests/test_model_infotech.py +47 -0
- synapse/tests/test_model_person.py +2 -0
- synapse/tests/test_model_syn.py +11 -0
- synapse/tests/test_model_telco.py +2 -1
- synapse/tests/test_utils_stormcov.py +1 -1
- synapse/tools/changelog.py +28 -0
- {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/METADATA +1 -1
- {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/RECORD +62 -61
- {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/WHEEL +1 -1
- {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/LICENSE +0 -0
- {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/top_level.txt +0 -0
synapse/lib/ast.py
CHANGED
|
@@ -419,7 +419,8 @@ class SubGraph:
|
|
|
419
419
|
await asyncio.sleep(0)
|
|
420
420
|
continue
|
|
421
421
|
|
|
422
|
-
|
|
422
|
+
link = {'type': 'prop', 'prop': propname}
|
|
423
|
+
yield (pivonode, path.fork(pivonode, link), link)
|
|
423
424
|
|
|
424
425
|
for iden in existing:
|
|
425
426
|
buid = s_common.uhex(iden)
|
|
@@ -1436,12 +1437,13 @@ class LiftOper(Oper):
|
|
|
1436
1437
|
|
|
1437
1438
|
return
|
|
1438
1439
|
|
|
1440
|
+
link = {'type': 'runtime'}
|
|
1439
1441
|
async for node, path in genr:
|
|
1440
1442
|
|
|
1441
1443
|
yield node, path
|
|
1442
1444
|
|
|
1443
1445
|
async for subn in self.lift(runt, path):
|
|
1444
|
-
yield subn, path.fork(subn)
|
|
1446
|
+
yield subn, path.fork(subn, link)
|
|
1445
1447
|
|
|
1446
1448
|
async def lift(self, runt, path): # pragma: no cover
|
|
1447
1449
|
raise NotImplementedError('Must define lift(runt, path)')
|
|
@@ -1913,8 +1915,9 @@ class PivotOut(PivotOper):
|
|
|
1913
1915
|
# <syn:tag> -> * is "from tags to nodes with tags"
|
|
1914
1916
|
if node.form.name == 'syn:tag':
|
|
1915
1917
|
|
|
1918
|
+
link = {'type': 'tag', 'tag': node.ndef[1], 'reverse': True}
|
|
1916
1919
|
async for pivo in runt.snap.nodesByTag(node.ndef[1]):
|
|
1917
|
-
yield pivo, path.fork(pivo)
|
|
1920
|
+
yield pivo, path.fork(pivo, link)
|
|
1918
1921
|
|
|
1919
1922
|
return
|
|
1920
1923
|
|
|
@@ -1925,7 +1928,7 @@ class PivotOut(PivotOper):
|
|
|
1925
1928
|
logger.warning(f'Missing node corresponding to ndef {n2def} on edge')
|
|
1926
1929
|
return
|
|
1927
1930
|
|
|
1928
|
-
yield pivo, path.fork(pivo)
|
|
1931
|
+
yield pivo, path.fork(pivo, {'type': 'prop', 'prop': 'n2'})
|
|
1929
1932
|
return
|
|
1930
1933
|
|
|
1931
1934
|
for name, prop in node.form.props.items():
|
|
@@ -1934,27 +1937,28 @@ class PivotOut(PivotOper):
|
|
|
1934
1937
|
if valu is None:
|
|
1935
1938
|
continue
|
|
1936
1939
|
|
|
1940
|
+
link = {'type': 'prop', 'prop': prop.name}
|
|
1937
1941
|
# if the outbound prop is an ndef...
|
|
1938
1942
|
if isinstance(prop.type, s_types.Ndef):
|
|
1939
1943
|
pivo = await runt.snap.getNodeByNdef(valu)
|
|
1940
1944
|
if pivo is None:
|
|
1941
1945
|
continue
|
|
1942
1946
|
|
|
1943
|
-
yield pivo, path.fork(pivo)
|
|
1947
|
+
yield pivo, path.fork(pivo, link)
|
|
1944
1948
|
continue
|
|
1945
1949
|
|
|
1946
1950
|
if isinstance(prop.type, s_types.Array):
|
|
1947
1951
|
if isinstance(prop.type.arraytype, s_types.Ndef):
|
|
1948
1952
|
for item in valu:
|
|
1949
1953
|
if (pivo := await runt.snap.getNodeByNdef(item)) is not None:
|
|
1950
|
-
yield pivo, path.fork(pivo)
|
|
1954
|
+
yield pivo, path.fork(pivo, link)
|
|
1951
1955
|
continue
|
|
1952
1956
|
|
|
1953
1957
|
typename = prop.type.opts.get('type')
|
|
1954
1958
|
if runt.model.forms.get(typename) is not None:
|
|
1955
1959
|
for item in valu:
|
|
1956
|
-
async for pivo in runt.snap.nodesByPropValu(typename, '=', item):
|
|
1957
|
-
yield pivo, path.fork(pivo)
|
|
1960
|
+
async for pivo in runt.snap.nodesByPropValu(typename, '=', item, norm=False):
|
|
1961
|
+
yield pivo, path.fork(pivo, link)
|
|
1958
1962
|
|
|
1959
1963
|
form = runt.model.forms.get(prop.type.name)
|
|
1960
1964
|
if form is None:
|
|
@@ -1962,7 +1966,7 @@ class PivotOut(PivotOper):
|
|
|
1962
1966
|
|
|
1963
1967
|
if prop.isrunt:
|
|
1964
1968
|
async for pivo in runt.snap.nodesByPropValu(form.name, '=', valu):
|
|
1965
|
-
yield pivo, path.fork(pivo)
|
|
1969
|
+
yield pivo, path.fork(pivo, link)
|
|
1966
1970
|
continue
|
|
1967
1971
|
|
|
1968
1972
|
pivo = await runt.snap.getNodeByNdef((form.name, valu))
|
|
@@ -1973,7 +1977,7 @@ class PivotOut(PivotOper):
|
|
|
1973
1977
|
if pivo.buid == node.buid:
|
|
1974
1978
|
continue
|
|
1975
1979
|
|
|
1976
|
-
yield pivo, path.fork(pivo)
|
|
1980
|
+
yield pivo, path.fork(pivo, link)
|
|
1977
1981
|
|
|
1978
1982
|
class N1WalkNPivo(PivotOut):
|
|
1979
1983
|
|
|
@@ -1990,7 +1994,7 @@ class N1WalkNPivo(PivotOut):
|
|
|
1990
1994
|
async for (verb, iden) in node.iterEdgesN1():
|
|
1991
1995
|
wnode = await runt.snap.getNodeByBuid(s_common.uhex(iden))
|
|
1992
1996
|
if wnode is not None:
|
|
1993
|
-
yield wnode, path.fork(wnode)
|
|
1997
|
+
yield wnode, path.fork(wnode, {'type': 'edge', 'verb': verb})
|
|
1994
1998
|
|
|
1995
1999
|
class PivotToTags(PivotOper):
|
|
1996
2000
|
'''
|
|
@@ -2057,7 +2061,7 @@ class PivotToTags(PivotOper):
|
|
|
2057
2061
|
if pivo is None:
|
|
2058
2062
|
continue
|
|
2059
2063
|
|
|
2060
|
-
yield pivo, path.fork(pivo)
|
|
2064
|
+
yield pivo, path.fork(pivo, {'type': 'tag', 'tag': name})
|
|
2061
2065
|
|
|
2062
2066
|
class PivotIn(PivotOper):
|
|
2063
2067
|
'''
|
|
@@ -2083,23 +2087,27 @@ class PivotIn(PivotOper):
|
|
|
2083
2087
|
|
|
2084
2088
|
pivo = await runt.snap.getNodeByNdef(ndef)
|
|
2085
2089
|
if pivo is not None:
|
|
2086
|
-
yield pivo, path.fork(pivo)
|
|
2090
|
+
yield pivo, path.fork(pivo, {'type': 'prop', 'prop': 'n1', 'reverse': True})
|
|
2087
2091
|
|
|
2088
2092
|
return
|
|
2089
2093
|
|
|
2090
2094
|
name, valu = node.ndef
|
|
2091
2095
|
|
|
2092
2096
|
for prop in runt.model.getPropsByType(name):
|
|
2093
|
-
|
|
2094
|
-
|
|
2097
|
+
link = {'type': 'prop', 'prop': prop.name, 'reverse': True}
|
|
2098
|
+
norm = node.form.typehash is not prop.typehash
|
|
2099
|
+
async for pivo in runt.snap.nodesByPropValu(prop.full, '=', valu, norm=norm):
|
|
2100
|
+
yield pivo, path.fork(pivo, link)
|
|
2095
2101
|
|
|
2096
2102
|
for prop in runt.model.getArrayPropsByType(name):
|
|
2097
|
-
|
|
2098
|
-
|
|
2103
|
+
norm = node.form.typehash is not prop.arraytypehash
|
|
2104
|
+
link = {'type': 'prop', 'prop': prop.name, 'reverse': True}
|
|
2105
|
+
async for pivo in runt.snap.nodesByPropArray(prop.full, '=', valu, norm=norm):
|
|
2106
|
+
yield pivo, path.fork(pivo, link)
|
|
2099
2107
|
|
|
2100
|
-
async for refsbuid in runt.snap.getNdefRefs(node.buid):
|
|
2108
|
+
async for refsbuid, prop in runt.snap.getNdefRefs(node.buid, props=True):
|
|
2101
2109
|
pivo = await runt.snap.getNodeByBuid(refsbuid)
|
|
2102
|
-
yield pivo, path.fork(pivo)
|
|
2110
|
+
yield pivo, path.fork(pivo, {'type': 'prop', 'prop': prop, 'reverse': True})
|
|
2103
2111
|
|
|
2104
2112
|
class N2WalkNPivo(PivotIn):
|
|
2105
2113
|
|
|
@@ -2116,7 +2124,7 @@ class N2WalkNPivo(PivotIn):
|
|
|
2116
2124
|
async for (verb, iden) in node.iterEdgesN2():
|
|
2117
2125
|
wnode = await runt.snap.getNodeByBuid(s_common.uhex(iden))
|
|
2118
2126
|
if wnode is not None:
|
|
2119
|
-
yield wnode, path.fork(wnode)
|
|
2127
|
+
yield wnode, path.fork(wnode, {'type': 'edge', 'verb': verb, 'reverse': True})
|
|
2120
2128
|
|
|
2121
2129
|
class PivotInFrom(PivotOper):
|
|
2122
2130
|
'''
|
|
@@ -2135,18 +2143,19 @@ class PivotInFrom(PivotOper):
|
|
|
2135
2143
|
if isinstance(form.type, s_types.Edge):
|
|
2136
2144
|
|
|
2137
2145
|
full = form.name + ':n2'
|
|
2138
|
-
|
|
2146
|
+
link = {'type': 'prop', 'prop': 'n2', 'reverse': True}
|
|
2139
2147
|
async for node, path in genr:
|
|
2140
2148
|
|
|
2141
2149
|
if self.isjoin:
|
|
2142
2150
|
yield node, path
|
|
2143
2151
|
|
|
2144
|
-
async for pivo in runt.snap.nodesByPropValu(full, '=', node.ndef):
|
|
2145
|
-
yield pivo, path.fork(pivo)
|
|
2152
|
+
async for pivo in runt.snap.nodesByPropValu(full, '=', node.ndef, norm=False):
|
|
2153
|
+
yield pivo, path.fork(pivo, link)
|
|
2146
2154
|
|
|
2147
2155
|
return
|
|
2148
2156
|
|
|
2149
2157
|
# edge <- form
|
|
2158
|
+
link = {'type': 'prop', 'prop': 'n1', 'reverse': True}
|
|
2150
2159
|
async for node, path in genr:
|
|
2151
2160
|
|
|
2152
2161
|
if self.isjoin:
|
|
@@ -2166,7 +2175,7 @@ class PivotInFrom(PivotOper):
|
|
|
2166
2175
|
if pivo is None:
|
|
2167
2176
|
continue
|
|
2168
2177
|
|
|
2169
|
-
yield pivo, path.fork(pivo)
|
|
2178
|
+
yield pivo, path.fork(pivo, link)
|
|
2170
2179
|
|
|
2171
2180
|
class FormPivot(PivotOper):
|
|
2172
2181
|
'''
|
|
@@ -2179,8 +2188,9 @@ class FormPivot(PivotOper):
|
|
|
2179
2188
|
if isinstance(prop.type, s_types.Ndef):
|
|
2180
2189
|
|
|
2181
2190
|
async def pgenr(node, strict=True):
|
|
2182
|
-
|
|
2183
|
-
|
|
2191
|
+
link = {'type': 'prop', 'prop': prop.name, 'reverse': True}
|
|
2192
|
+
async for pivo in runt.snap.nodesByPropValu(prop.full, '=', node.ndef, norm=False):
|
|
2193
|
+
yield pivo, link
|
|
2184
2194
|
|
|
2185
2195
|
elif not prop.isform:
|
|
2186
2196
|
|
|
@@ -2190,15 +2200,17 @@ class FormPivot(PivotOper):
|
|
|
2190
2200
|
async def pgenr(node, strict=True):
|
|
2191
2201
|
if isarray:
|
|
2192
2202
|
if isinstance(prop.type.arraytype, s_types.Ndef):
|
|
2193
|
-
ngenr = runt.snap.nodesByPropArray(prop.full, '=', node.ndef)
|
|
2203
|
+
ngenr = runt.snap.nodesByPropArray(prop.full, '=', node.ndef, norm=False)
|
|
2194
2204
|
else:
|
|
2195
|
-
|
|
2205
|
+
norm = prop.arraytypehash is not node.form.typehash
|
|
2206
|
+
ngenr = runt.snap.nodesByPropArray(prop.full, '=', node.ndef[1], norm=norm)
|
|
2196
2207
|
else:
|
|
2197
|
-
|
|
2208
|
+
norm = prop.typehash is not node.form.typehash
|
|
2209
|
+
ngenr = runt.snap.nodesByPropValu(prop.full, '=', node.ndef[1], norm=norm)
|
|
2198
2210
|
|
|
2199
|
-
|
|
2211
|
+
link = {'type': 'prop', 'prop': prop.name, 'reverse': True}
|
|
2200
2212
|
async for pivo in ngenr:
|
|
2201
|
-
yield pivo
|
|
2213
|
+
yield pivo, link
|
|
2202
2214
|
|
|
2203
2215
|
# if dest form is a subtype of a graph "edge", use N1 automatically
|
|
2204
2216
|
elif isinstance(prop.type, s_types.Edge):
|
|
@@ -2206,8 +2218,9 @@ class FormPivot(PivotOper):
|
|
|
2206
2218
|
full = prop.name + ':n1'
|
|
2207
2219
|
|
|
2208
2220
|
async def pgenr(node, strict=True):
|
|
2209
|
-
|
|
2210
|
-
|
|
2221
|
+
link = {'type': 'prop', 'prop': 'n1', 'reverse': True}
|
|
2222
|
+
async for pivo in runt.snap.nodesByPropValu(full, '=', node.ndef, norm=False):
|
|
2223
|
+
yield pivo, link
|
|
2211
2224
|
|
|
2212
2225
|
else:
|
|
2213
2226
|
# form -> form pivot is nonsensical. Lets help out...
|
|
@@ -2219,8 +2232,9 @@ class FormPivot(PivotOper):
|
|
|
2219
2232
|
|
|
2220
2233
|
# <syn:tag> -> <form> is "from tags to nodes" pivot
|
|
2221
2234
|
if node.form.name == 'syn:tag' and prop.isform:
|
|
2235
|
+
link = {'type': 'tag', 'tag': node.ndef[1], 'reverse': True}
|
|
2222
2236
|
async for pivo in runt.snap.nodesByTag(node.ndef[1], form=prop.name):
|
|
2223
|
-
yield pivo
|
|
2237
|
+
yield pivo, link
|
|
2224
2238
|
|
|
2225
2239
|
return
|
|
2226
2240
|
|
|
@@ -2233,7 +2247,7 @@ class FormPivot(PivotOper):
|
|
|
2233
2247
|
|
|
2234
2248
|
pivo = await runt.snap.getNodeByNdef(node.get('n2'))
|
|
2235
2249
|
if pivo:
|
|
2236
|
-
yield pivo
|
|
2250
|
+
yield pivo, {'type': 'prop', 'prop': 'n2'}
|
|
2237
2251
|
|
|
2238
2252
|
return
|
|
2239
2253
|
|
|
@@ -2251,8 +2265,9 @@ class FormPivot(PivotOper):
|
|
|
2251
2265
|
|
|
2252
2266
|
refsvalu = node.get(refsname)
|
|
2253
2267
|
if refsvalu is not None:
|
|
2254
|
-
|
|
2255
|
-
|
|
2268
|
+
link = {'type': 'prop', 'prop': refsname}
|
|
2269
|
+
async for pivo in runt.snap.nodesByPropValu(refsform, '=', refsvalu, norm=False):
|
|
2270
|
+
yield pivo, link
|
|
2256
2271
|
|
|
2257
2272
|
for refsname, refsform in refs.get('array'):
|
|
2258
2273
|
|
|
@@ -2263,9 +2278,10 @@ class FormPivot(PivotOper):
|
|
|
2263
2278
|
|
|
2264
2279
|
refsvalu = node.get(refsname)
|
|
2265
2280
|
if refsvalu is not None:
|
|
2281
|
+
link = {'type': 'prop', 'prop': refsname}
|
|
2266
2282
|
for refselem in refsvalu:
|
|
2267
|
-
async for pivo in runt.snap.nodesByPropValu(destform.name, '=', refselem):
|
|
2268
|
-
yield pivo
|
|
2283
|
+
async for pivo in runt.snap.nodesByPropValu(destform.name, '=', refselem, norm=False):
|
|
2284
|
+
yield pivo, link
|
|
2269
2285
|
|
|
2270
2286
|
for refsname in refs.get('ndef'):
|
|
2271
2287
|
|
|
@@ -2275,17 +2291,18 @@ class FormPivot(PivotOper):
|
|
|
2275
2291
|
if refsvalu is not None and refsvalu[0] == destform.name:
|
|
2276
2292
|
pivo = await runt.snap.getNodeByNdef(refsvalu)
|
|
2277
2293
|
if pivo is not None:
|
|
2278
|
-
yield pivo
|
|
2294
|
+
yield pivo, {'type': 'prop', 'prop': refsname}
|
|
2279
2295
|
|
|
2280
2296
|
for refsname in refs.get('ndefarray'):
|
|
2281
2297
|
|
|
2282
2298
|
found = True
|
|
2283
2299
|
|
|
2284
2300
|
if (refsvalu := node.get(refsname)) is not None:
|
|
2301
|
+
link = {'type': 'prop', 'prop': refsname}
|
|
2285
2302
|
for aval in refsvalu:
|
|
2286
2303
|
if aval[0] == destform.name:
|
|
2287
2304
|
if (pivo := await runt.snap.getNodeByNdef(aval)) is not None:
|
|
2288
|
-
yield pivo
|
|
2305
|
+
yield pivo, link
|
|
2289
2306
|
|
|
2290
2307
|
#########################################################################
|
|
2291
2308
|
# reverse "-> form" pivots (ie inet:fqdn -> inet:dns:a)
|
|
@@ -2300,8 +2317,9 @@ class FormPivot(PivotOper):
|
|
|
2300
2317
|
found = True
|
|
2301
2318
|
|
|
2302
2319
|
refsprop = destform.props.get(refsname)
|
|
2303
|
-
|
|
2304
|
-
|
|
2320
|
+
link = {'type': 'prop', 'prop': refsname, 'reverse': True}
|
|
2321
|
+
async for pivo in runt.snap.nodesByPropValu(refsprop.full, '=', node.ndef[1], norm=False):
|
|
2322
|
+
yield pivo, link
|
|
2305
2323
|
|
|
2306
2324
|
# "reverse" array references...
|
|
2307
2325
|
for refsname, refsform in refs.get('array'):
|
|
@@ -2312,8 +2330,9 @@ class FormPivot(PivotOper):
|
|
|
2312
2330
|
found = True
|
|
2313
2331
|
|
|
2314
2332
|
destprop = destform.props.get(refsname)
|
|
2315
|
-
|
|
2316
|
-
|
|
2333
|
+
link = {'type': 'prop', 'prop': refsname, 'reverse': True}
|
|
2334
|
+
async for pivo in runt.snap.nodesByPropArray(destprop.full, '=', node.ndef[1], norm=False):
|
|
2335
|
+
yield pivo, link
|
|
2317
2336
|
|
|
2318
2337
|
# "reverse" ndef references...
|
|
2319
2338
|
for refsname in refs.get('ndef'):
|
|
@@ -2321,16 +2340,18 @@ class FormPivot(PivotOper):
|
|
|
2321
2340
|
found = True
|
|
2322
2341
|
|
|
2323
2342
|
refsprop = destform.props.get(refsname)
|
|
2324
|
-
|
|
2325
|
-
|
|
2343
|
+
link = {'type': 'prop', 'prop': refsname, 'reverse': True}
|
|
2344
|
+
async for pivo in runt.snap.nodesByPropValu(refsprop.full, '=', node.ndef, norm=False):
|
|
2345
|
+
yield pivo, link
|
|
2326
2346
|
|
|
2327
2347
|
for refsname in refs.get('ndefarray'):
|
|
2328
2348
|
|
|
2329
2349
|
found = True
|
|
2330
2350
|
|
|
2331
2351
|
refsprop = destform.props.get(refsname)
|
|
2332
|
-
|
|
2333
|
-
|
|
2352
|
+
link = {'type': 'prop', 'prop': refsname, 'reverse': True}
|
|
2353
|
+
async for pivo in runt.snap.nodesByPropArray(refsprop.full, '=', node.ndef, norm=False):
|
|
2354
|
+
yield pivo, link
|
|
2334
2355
|
|
|
2335
2356
|
if strict and not found:
|
|
2336
2357
|
mesg = f'No pivot found for {node.form.name} -> {destform.name}.'
|
|
@@ -2358,8 +2379,8 @@ class FormPivot(PivotOper):
|
|
|
2358
2379
|
|
|
2359
2380
|
async def listpivot(node):
|
|
2360
2381
|
for pgenr in pgenrs:
|
|
2361
|
-
async for pivo in pgenr(node, strict=False):
|
|
2362
|
-
yield pivo
|
|
2382
|
+
async for pivo, valu in pgenr(node, strict=False):
|
|
2383
|
+
yield pivo, valu
|
|
2363
2384
|
|
|
2364
2385
|
return listpivot
|
|
2365
2386
|
|
|
@@ -2380,8 +2401,8 @@ class FormPivot(PivotOper):
|
|
|
2380
2401
|
yield node, path
|
|
2381
2402
|
|
|
2382
2403
|
try:
|
|
2383
|
-
async for pivo in pgenr(node):
|
|
2384
|
-
yield pivo, path.fork(pivo)
|
|
2404
|
+
async for pivo, link in pgenr(node):
|
|
2405
|
+
yield pivo, path.fork(pivo, link)
|
|
2385
2406
|
except (s_exc.BadTypeValu, s_exc.BadLiftValu) as e:
|
|
2386
2407
|
if not warned:
|
|
2387
2408
|
logger.warning(f'Caught error during pivot: {e.items()}')
|
|
@@ -2417,11 +2438,12 @@ class PropPivotOut(PivotOper):
|
|
|
2417
2438
|
await asyncio.sleep(0)
|
|
2418
2439
|
continue
|
|
2419
2440
|
|
|
2441
|
+
link = {'type': 'prop', 'prop': prop.name}
|
|
2420
2442
|
if prop.type.isarray:
|
|
2421
2443
|
if isinstance(prop.type.arraytype, s_types.Ndef):
|
|
2422
2444
|
for item in valu:
|
|
2423
2445
|
if (pivo := await runt.snap.getNodeByNdef(item)) is not None:
|
|
2424
|
-
yield pivo, path.fork(pivo)
|
|
2446
|
+
yield pivo, path.fork(pivo, link)
|
|
2425
2447
|
continue
|
|
2426
2448
|
|
|
2427
2449
|
fname = prop.type.arraytype.name
|
|
@@ -2433,8 +2455,8 @@ class PropPivotOut(PivotOper):
|
|
|
2433
2455
|
continue
|
|
2434
2456
|
|
|
2435
2457
|
for item in valu:
|
|
2436
|
-
async for pivo in runt.snap.nodesByPropValu(fname, '=', item):
|
|
2437
|
-
yield pivo, path.fork(pivo)
|
|
2458
|
+
async for pivo in runt.snap.nodesByPropValu(fname, '=', item, norm=False):
|
|
2459
|
+
yield pivo, path.fork(pivo, link)
|
|
2438
2460
|
|
|
2439
2461
|
continue
|
|
2440
2462
|
|
|
@@ -2445,7 +2467,7 @@ class PropPivotOut(PivotOper):
|
|
|
2445
2467
|
if pivo is None:
|
|
2446
2468
|
logger.warning(f'Missing node corresponding to ndef {valu}')
|
|
2447
2469
|
continue
|
|
2448
|
-
yield pivo, path.fork(pivo)
|
|
2470
|
+
yield pivo, path.fork(pivo, link)
|
|
2449
2471
|
continue
|
|
2450
2472
|
|
|
2451
2473
|
# :prop -> *
|
|
@@ -2462,7 +2484,7 @@ class PropPivotOut(PivotOper):
|
|
|
2462
2484
|
# A node explicitly deleted in the graph or missing from a underlying layer
|
|
2463
2485
|
# could cause this lift to return None.
|
|
2464
2486
|
if pivo:
|
|
2465
|
-
yield pivo, path.fork(pivo)
|
|
2487
|
+
yield pivo, path.fork(pivo, link)
|
|
2466
2488
|
|
|
2467
2489
|
|
|
2468
2490
|
class PropPivot(PivotOper):
|
|
@@ -2474,8 +2496,9 @@ class PropPivot(PivotOper):
|
|
|
2474
2496
|
|
|
2475
2497
|
async def pgenr(node, srcprop, valu, strict=True):
|
|
2476
2498
|
|
|
2477
|
-
|
|
2478
|
-
|
|
2499
|
+
link = {'type': 'prop', 'prop': srcprop.name}
|
|
2500
|
+
if not prop.isform:
|
|
2501
|
+
link['dest'] = prop.full
|
|
2479
2502
|
# pivoting from an array prop to a non-array prop needs an extra loop
|
|
2480
2503
|
if srcprop.type.isarray and not prop.type.isarray:
|
|
2481
2504
|
if isinstance(srcprop.type.arraytype, s_types.Ndef) and prop.isform:
|
|
@@ -2484,12 +2507,13 @@ class PropPivot(PivotOper):
|
|
|
2484
2507
|
continue
|
|
2485
2508
|
|
|
2486
2509
|
if (pivo := await runt.snap.getNodeByNdef(aval)) is not None:
|
|
2487
|
-
yield pivo
|
|
2510
|
+
yield pivo, link
|
|
2488
2511
|
return
|
|
2489
2512
|
|
|
2513
|
+
norm = srcprop.arraytypehash is not prop.typehash
|
|
2490
2514
|
for arrayval in valu:
|
|
2491
|
-
async for pivo in runt.snap.nodesByPropValu(prop.full, '=', arrayval):
|
|
2492
|
-
yield pivo
|
|
2515
|
+
async for pivo in runt.snap.nodesByPropValu(prop.full, '=', arrayval, norm=norm):
|
|
2516
|
+
yield pivo, link
|
|
2493
2517
|
|
|
2494
2518
|
return
|
|
2495
2519
|
|
|
@@ -2501,17 +2525,19 @@ class PropPivot(PivotOper):
|
|
|
2501
2525
|
if pivo is None:
|
|
2502
2526
|
await runt.snap.warn(f'Missing node corresponding to ndef {valu}', log=False, ndef=valu)
|
|
2503
2527
|
return
|
|
2504
|
-
yield pivo
|
|
2528
|
+
yield pivo, link
|
|
2505
2529
|
|
|
2506
2530
|
return
|
|
2507
2531
|
|
|
2508
2532
|
if prop.type.isarray and not srcprop.type.isarray:
|
|
2509
|
-
|
|
2533
|
+
norm = prop.arraytypehash is not srcprop.typehash
|
|
2534
|
+
genr = runt.snap.nodesByPropArray(prop.full, '=', valu, norm=norm)
|
|
2510
2535
|
else:
|
|
2511
|
-
|
|
2536
|
+
norm = prop.typehash is not srcprop.typehash
|
|
2537
|
+
genr = runt.snap.nodesByPropValu(prop.full, '=', valu, norm=norm)
|
|
2512
2538
|
|
|
2513
2539
|
async for pivo in genr:
|
|
2514
|
-
yield pivo
|
|
2540
|
+
yield pivo, link
|
|
2515
2541
|
|
|
2516
2542
|
return pgenr
|
|
2517
2543
|
|
|
@@ -2565,8 +2591,8 @@ class PropPivot(PivotOper):
|
|
|
2565
2591
|
continue
|
|
2566
2592
|
|
|
2567
2593
|
try:
|
|
2568
|
-
async for pivo in pgenr(node, srcprop, valu):
|
|
2569
|
-
yield pivo, path.fork(pivo)
|
|
2594
|
+
async for pivo, link in pgenr(node, srcprop, valu):
|
|
2595
|
+
yield pivo, path.fork(pivo, link)
|
|
2570
2596
|
|
|
2571
2597
|
except (s_exc.BadTypeValu, s_exc.BadLiftValu) as e:
|
|
2572
2598
|
if not warned:
|
|
@@ -4214,19 +4240,20 @@ class EditUnivDel(Edit):
|
|
|
4214
4240
|
|
|
4215
4241
|
class N1Walk(Oper):
|
|
4216
4242
|
|
|
4217
|
-
def __init__(self, astinfo, kids=(), isjoin=False):
|
|
4243
|
+
def __init__(self, astinfo, kids=(), isjoin=False, reverse=False):
|
|
4218
4244
|
Oper.__init__(self, astinfo, kids=kids)
|
|
4219
4245
|
self.isjoin = isjoin
|
|
4246
|
+
self.reverse = reverse
|
|
4220
4247
|
|
|
4221
4248
|
def repr(self):
|
|
4222
4249
|
return f'{self.__class__.__name__}: {self.kids}, isjoin={self.isjoin}'
|
|
4223
4250
|
|
|
4224
4251
|
async def walkNodeEdges(self, runt, node, verb=None):
|
|
4225
|
-
async for
|
|
4252
|
+
async for verb, iden in node.iterEdgesN1(verb=verb):
|
|
4226
4253
|
buid = s_common.uhex(iden)
|
|
4227
4254
|
walknode = await runt.snap.getNodeByBuid(buid)
|
|
4228
4255
|
if walknode is not None:
|
|
4229
|
-
yield walknode
|
|
4256
|
+
yield verb, walknode
|
|
4230
4257
|
|
|
4231
4258
|
def buildfilter(self, runt, destforms, cmpr):
|
|
4232
4259
|
|
|
@@ -4326,21 +4353,28 @@ class N1Walk(Oper):
|
|
|
4326
4353
|
if verb == '*':
|
|
4327
4354
|
verb = None
|
|
4328
4355
|
|
|
4329
|
-
async for walknode in self.walkNodeEdges(runt, node, verb=verb):
|
|
4356
|
+
async for verbname, walknode in self.walkNodeEdges(runt, node, verb=verb):
|
|
4330
4357
|
|
|
4331
4358
|
if destfilt and not await destfilt(walknode, path, cmprvalu):
|
|
4332
4359
|
continue
|
|
4333
4360
|
|
|
4334
|
-
|
|
4361
|
+
link = {'type': 'edge', 'verb': verbname}
|
|
4362
|
+
if self.reverse:
|
|
4363
|
+
link['reverse'] = True
|
|
4364
|
+
|
|
4365
|
+
yield walknode, path.fork(walknode, link)
|
|
4335
4366
|
|
|
4336
4367
|
class N2Walk(N1Walk):
|
|
4337
4368
|
|
|
4369
|
+
def __init__(self, astinfo, kids=(), isjoin=False):
|
|
4370
|
+
N1Walk.__init__(self, astinfo, kids=kids, isjoin=isjoin, reverse=True)
|
|
4371
|
+
|
|
4338
4372
|
async def walkNodeEdges(self, runt, node, verb=None):
|
|
4339
|
-
async for
|
|
4373
|
+
async for verb, iden in node.iterEdgesN2(verb=verb):
|
|
4340
4374
|
buid = s_common.uhex(iden)
|
|
4341
4375
|
walknode = await runt.snap.getNodeByBuid(buid)
|
|
4342
4376
|
if walknode is not None:
|
|
4343
|
-
yield walknode
|
|
4377
|
+
yield verb, walknode
|
|
4344
4378
|
|
|
4345
4379
|
class EditEdgeAdd(Edit):
|
|
4346
4380
|
|
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
|
-
|
|
502
|
-
|
|
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)
|