synapse 2.212.0__py311-none-any.whl → 2.214.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 +37 -6
- synapse/daemon.py +6 -6
- synapse/exc.py +13 -1
- synapse/lib/aha.py +5 -0
- synapse/lib/ast.py +2 -6
- synapse/lib/boss.py +47 -2
- synapse/lib/cell.py +199 -6
- synapse/lib/certdir.py +44 -1
- synapse/lib/cmd.py +24 -0
- synapse/lib/coro.py +8 -2
- synapse/lib/drive.py +7 -2
- synapse/lib/link.py +11 -3
- synapse/lib/schemas.py +1 -1
- synapse/lib/scrape.py +3 -1
- synapse/lib/snap.py +89 -80
- synapse/lib/storm.py +2 -1
- synapse/lib/stormlib/imap.py +3 -2
- synapse/lib/stormlib/spooled.py +4 -0
- synapse/lib/stormtypes.py +18 -0
- synapse/lib/task.py +1 -0
- synapse/lib/types.py +36 -8
- synapse/lib/version.py +2 -2
- synapse/models/inet.py +5 -0
- synapse/telepath.py +4 -2
- synapse/tests/files/testpkg_build_docs/docs/bar.rst +15 -0
- synapse/tests/files/testpkg_build_docs/docs/foo.rst +4 -0
- synapse/tests/files/testpkg_build_docs/storm/commands/testcmd.storm +0 -0
- synapse/tests/files/testpkg_build_docs/storm/modules/apimod.storm +0 -0
- synapse/tests/files/testpkg_build_docs/storm/modules/testmod.storm +0 -0
- synapse/tests/files/testpkg_build_docs/storm/testcmd.storm +5 -0
- synapse/tests/files/testpkg_build_docs/testpkg.yaml +69 -0
- synapse/tests/test_cortex.py +20 -1
- synapse/tests/test_daemon.py +1 -1
- synapse/tests/test_exc.py +6 -0
- synapse/tests/test_lib_ast.py +69 -14
- synapse/tests/test_lib_boss.py +8 -0
- synapse/tests/test_lib_cell.py +119 -8
- synapse/tests/test_lib_certdir.py +8 -0
- synapse/tests/test_lib_coro.py +5 -0
- synapse/tests/test_lib_httpapi.py +10 -2
- synapse/tests/test_lib_link.py +1 -1
- synapse/tests/test_lib_scrape.py +6 -0
- synapse/tests/test_lib_storm.py +123 -1
- synapse/tests/test_lib_stormlib_spooled.py +31 -0
- synapse/tests/test_lib_stormtypes.py +11 -0
- synapse/tests/test_lib_types.py +137 -45
- synapse/tests/test_model_crypto.py +8 -0
- synapse/tests/test_model_inet.py +7 -0
- synapse/tests/test_telepath.py +50 -5
- synapse/tests/test_tools_axon.py +304 -0
- synapse/tests/test_tools_cortex_layer.py +419 -0
- synapse/tests/test_tools_demote.py +114 -0
- synapse/tests/test_tools_pkgs_gendocs.py +100 -0
- synapse/tests/test_tools_shutdown.py +95 -0
- synapse/tests/test_utils.py +22 -1
- synapse/tests/utils.py +44 -29
- synapse/tools/aha/easycert.py +2 -0
- synapse/tools/aha/enroll.py +3 -0
- synapse/tools/axon/__init__.py +0 -0
- synapse/tools/axon/dump.py +155 -0
- synapse/tools/axon/load.py +89 -0
- synapse/tools/cortex/__init__.py +0 -0
- synapse/tools/cortex/layer/__init__.py +0 -0
- synapse/tools/cortex/layer/dump.py +184 -0
- synapse/tools/cortex/layer/load.py +129 -0
- synapse/tools/demote.py +52 -0
- synapse/tools/healthcheck.py +1 -1
- synapse/tools/pkgs/gendocs.py +176 -0
- synapse/tools/pkgs/pandoc_filter.py +79 -0
- synapse/tools/shutdown.py +52 -0
- {synapse-2.212.0.dist-info → synapse-2.214.0.dist-info}/METADATA +1 -1
- {synapse-2.212.0.dist-info → synapse-2.214.0.dist-info}/RECORD +75 -52
- {synapse-2.212.0.dist-info → synapse-2.214.0.dist-info}/WHEEL +0 -0
- {synapse-2.212.0.dist-info → synapse-2.214.0.dist-info}/licenses/LICENSE +0 -0
- {synapse-2.212.0.dist-info → synapse-2.214.0.dist-info}/top_level.txt +0 -0
synapse/lib/certdir.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import io
|
|
2
2
|
import os
|
|
3
3
|
import ssl
|
|
4
|
-
import time
|
|
5
4
|
import shutil
|
|
6
5
|
import socket
|
|
7
6
|
import logging
|
|
@@ -397,6 +396,28 @@ class CertDir:
|
|
|
397
396
|
'''
|
|
398
397
|
return self._genPkeyCsr(name, 'hosts', outp=outp)
|
|
399
398
|
|
|
399
|
+
def delHostCsr(self, name: str, outp: OutPutOrNone = None) -> bool:
|
|
400
|
+
'''
|
|
401
|
+
Delete an existing host CSR.
|
|
402
|
+
|
|
403
|
+
Args:
|
|
404
|
+
name: The name of the host CSR.
|
|
405
|
+
outp: The output buffer.
|
|
406
|
+
|
|
407
|
+
Returns:
|
|
408
|
+
bool: True if the CSR is deleted, False if it did not exist.
|
|
409
|
+
'''
|
|
410
|
+
path = self.getHostCsrPath(name)
|
|
411
|
+
if path is None:
|
|
412
|
+
return False
|
|
413
|
+
try:
|
|
414
|
+
os.unlink(path)
|
|
415
|
+
except Exception as e: # pragma: no cover
|
|
416
|
+
raise s_exc.SynErr(mesg=f'Failed to delete CSR {path} - {e}') from e
|
|
417
|
+
if outp:
|
|
418
|
+
outp.printf(f'Deleted CSR at {path}')
|
|
419
|
+
return True
|
|
420
|
+
|
|
400
421
|
def genUserCert(self,
|
|
401
422
|
name: str,
|
|
402
423
|
signas: StrOrNone = None,
|
|
@@ -697,6 +718,28 @@ class CertDir:
|
|
|
697
718
|
'''
|
|
698
719
|
return self._genPkeyCsr(name, 'users', outp=outp)
|
|
699
720
|
|
|
721
|
+
def delUserCsr(self, name: str, outp: OutPutOrNone = None) -> bool:
|
|
722
|
+
'''
|
|
723
|
+
Delete an existing user CSR.
|
|
724
|
+
|
|
725
|
+
Args:
|
|
726
|
+
name: The name of the user CSR.
|
|
727
|
+
outp: The output buffer.
|
|
728
|
+
|
|
729
|
+
Returns:
|
|
730
|
+
bool: True if the CSR is deleted, False if it did not exist.
|
|
731
|
+
'''
|
|
732
|
+
path = self.getUserCsrPath(name)
|
|
733
|
+
if path is None:
|
|
734
|
+
return False
|
|
735
|
+
try:
|
|
736
|
+
os.unlink(path)
|
|
737
|
+
except Exception as e: # pragma: no cover
|
|
738
|
+
raise s_exc.SynErr(mesg=f'Failed to delete CSR {path} - {e}') from e
|
|
739
|
+
if outp:
|
|
740
|
+
outp.printf(f'Deleted CSR at {path}')
|
|
741
|
+
return True
|
|
742
|
+
|
|
700
743
|
def getCaCert(self, name: str) -> CertOrNone:
|
|
701
744
|
'''
|
|
702
745
|
Loads the X509 object for a given CA.
|
synapse/lib/cmd.py
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import asyncio
|
|
1
3
|
import argparse
|
|
2
4
|
|
|
3
5
|
import synapse.exc as s_exc
|
|
6
|
+
import synapse.common as s_common
|
|
7
|
+
|
|
8
|
+
import synapse.lib.coro as s_coro
|
|
4
9
|
import synapse.lib.output as s_output
|
|
5
10
|
|
|
6
11
|
class Parser(argparse.ArgumentParser):
|
|
@@ -25,6 +30,7 @@ class Parser(argparse.ArgumentParser):
|
|
|
25
30
|
|
|
26
31
|
if message is not None:
|
|
27
32
|
self.outp.printf(message)
|
|
33
|
+
|
|
28
34
|
raise s_exc.ParserExit(mesg=message, status=status)
|
|
29
35
|
|
|
30
36
|
def _print_message(self, text, fd=None):
|
|
@@ -32,3 +38,21 @@ class Parser(argparse.ArgumentParser):
|
|
|
32
38
|
Note: this overrides an existing method in ArgumentParser
|
|
33
39
|
'''
|
|
34
40
|
self.outp.printf(text)
|
|
41
|
+
|
|
42
|
+
async def wrapmain(func): # pragma: no cover
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
return await func(sys.argv[1:])
|
|
46
|
+
|
|
47
|
+
except s_exc.ParserExit:
|
|
48
|
+
return 1
|
|
49
|
+
|
|
50
|
+
except Exception as e:
|
|
51
|
+
print(f'ERROR: {s_exc.reprexc(e)}')
|
|
52
|
+
return 1
|
|
53
|
+
|
|
54
|
+
finally:
|
|
55
|
+
await s_coro.await_bg_tasks(timeout=10)
|
|
56
|
+
|
|
57
|
+
def exitmain(func): # pragma: no cover
|
|
58
|
+
sys.exit(asyncio.run(wrapmain(func)))
|
synapse/lib/coro.py
CHANGED
|
@@ -175,10 +175,16 @@ def create_task(coro):
|
|
|
175
175
|
|
|
176
176
|
return task
|
|
177
177
|
|
|
178
|
-
async def await_bg_tasks():
|
|
178
|
+
async def await_bg_tasks(timeout=None):
|
|
179
|
+
|
|
179
180
|
if not bgtasks:
|
|
180
181
|
return []
|
|
181
|
-
|
|
182
|
+
|
|
183
|
+
coro = asyncio.gather(*tuple(bgtasks), return_exceptions=True)
|
|
184
|
+
try:
|
|
185
|
+
return await s_common.wait_for(coro, timeout)
|
|
186
|
+
except (asyncio.CancelledError, asyncio.TimeoutError):
|
|
187
|
+
return []
|
|
182
188
|
|
|
183
189
|
class GenrHelp:
|
|
184
190
|
|
synapse/lib/drive.py
CHANGED
|
@@ -69,6 +69,9 @@ class Drive(s_base.Base):
|
|
|
69
69
|
|
|
70
70
|
def getItemInfo(self, iden, typename=None):
|
|
71
71
|
info = self._getItemInfo(s_common.uhex(iden))
|
|
72
|
+
if not info:
|
|
73
|
+
return
|
|
74
|
+
|
|
72
75
|
if typename is not None:
|
|
73
76
|
self._reqInfoType(info, typename)
|
|
74
77
|
return info
|
|
@@ -210,7 +213,7 @@ class Drive(s_base.Base):
|
|
|
210
213
|
|
|
211
214
|
def _setItemPerm(self, bidn, perm):
|
|
212
215
|
info = self._reqItemInfo(bidn)
|
|
213
|
-
info['
|
|
216
|
+
info['permissions'] = perm
|
|
214
217
|
s_schemas.reqValidDriveInfo(info)
|
|
215
218
|
self.slab.put(LKEY_INFO + bidn, s_msgpack.en(info), db=self.dbname)
|
|
216
219
|
return info
|
|
@@ -286,7 +289,7 @@ class Drive(s_base.Base):
|
|
|
286
289
|
info['kids'] = 0
|
|
287
290
|
info['parent'] = pariden
|
|
288
291
|
|
|
289
|
-
info.setdefault('
|
|
292
|
+
info.setdefault('permissions', {'users': {}, 'roles': {}})
|
|
290
293
|
info.setdefault('version', (0, 0, 0))
|
|
291
294
|
|
|
292
295
|
s_schemas.reqValidDriveInfo(info)
|
|
@@ -447,6 +450,8 @@ class Drive(s_base.Base):
|
|
|
447
450
|
|
|
448
451
|
if vers is None:
|
|
449
452
|
info = self._getItemInfo(bidn)
|
|
453
|
+
if info is None:
|
|
454
|
+
return None
|
|
450
455
|
vers = info.get('version')
|
|
451
456
|
|
|
452
457
|
versindx = getVersIndx(vers)
|
synapse/lib/link.py
CHANGED
|
@@ -61,7 +61,15 @@ async def unixconnect(path):
|
|
|
61
61
|
'''
|
|
62
62
|
Connect to a PF_UNIX server listening on the given path.
|
|
63
63
|
'''
|
|
64
|
-
|
|
64
|
+
try:
|
|
65
|
+
reader, writer = await asyncio.open_unix_connection(path=path)
|
|
66
|
+
except ConnectionRefusedError as e:
|
|
67
|
+
mesg = f'Cell path is not listening: {path}'
|
|
68
|
+
raise s_exc.LinkErr(mesg=mesg) from e
|
|
69
|
+
except FileNotFoundError as e:
|
|
70
|
+
mesg = f'Cell path does not exist: {path}'
|
|
71
|
+
raise s_exc.NoSuchPath(mesg=mesg) from e
|
|
72
|
+
|
|
65
73
|
info = {'path': path, 'unix': True}
|
|
66
74
|
return await Link.anit(reader, writer, info=info)
|
|
67
75
|
|
|
@@ -321,9 +329,9 @@ class Link(s_base.Base):
|
|
|
321
329
|
raise
|
|
322
330
|
|
|
323
331
|
except Exception as e:
|
|
324
|
-
mesg = f'rx
|
|
332
|
+
mesg = f'rx closed unexpectedly {e} link={self.getAddrInfo()}'
|
|
325
333
|
if isinstance(e, (BrokenPipeError, ConnectionResetError)):
|
|
326
|
-
logger.
|
|
334
|
+
logger.debug(mesg)
|
|
327
335
|
else:
|
|
328
336
|
logger.exception(mesg)
|
|
329
337
|
await self.fini()
|
synapse/lib/schemas.py
CHANGED
|
@@ -469,7 +469,7 @@ driveInfoSchema = {
|
|
|
469
469
|
'parent': {'type': 'string', 'pattern': s_config.re_iden},
|
|
470
470
|
'type': {'type': 'string', 'pattern': re_drivename},
|
|
471
471
|
'name': {'type': 'string', 'pattern': re_drivename},
|
|
472
|
-
'
|
|
472
|
+
'permissions': s_msgpack.deepcopy(easyPermSchema),
|
|
473
473
|
'kids': {'type': 'number', 'minimum': 0},
|
|
474
474
|
'created': {'type': 'number'},
|
|
475
475
|
'creator': {'type': 'string', 'pattern': s_config.re_iden},
|
synapse/lib/scrape.py
CHANGED
|
@@ -65,6 +65,8 @@ inverse_prefixs = {
|
|
|
65
65
|
'<': '>',
|
|
66
66
|
'{': '}',
|
|
67
67
|
'(': ')',
|
|
68
|
+
'\u2018': '\u2019', # Unicode Left Single Quotation Mark and Right Single Quotation Mark
|
|
69
|
+
'\u201c': '\u201d', # Unicode Left Double Quotation Mark and Right Double Quotation Mark
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
cve_dashes = ''.join(('-',) + s_chop.unicode_dashes)
|
|
@@ -287,7 +289,7 @@ def url_scheme_check(match: regex.Match):
|
|
|
287
289
|
scrape_types = [ # type: ignore
|
|
288
290
|
('file:path', linux_path_regex, {'callback': linux_path_check, 'flags': regex.VERBOSE}),
|
|
289
291
|
('file:path', windows_path_regex, {'callback': windows_path_check, 'flags': regex.VERBOSE}),
|
|
290
|
-
('inet:url', r'(?P<prefix>[
|
|
292
|
+
('inet:url', r'(?P<prefix>[‘“\\{<\(\[]?)(?P<valu>[a-zA-Z][a-zA-Z0-9]*://(?(?=[,.]+[ \'\"\t\n\r\f\v])|[^ \'\"\t\n\r\f\v])+)',
|
|
291
293
|
{'callback': url_scheme_check}),
|
|
292
294
|
('inet:url', r'(["\'])?(?P<valu>\\[^\n]+?)(?(1)\1|\s)', {'callback': unc_path_check}),
|
|
293
295
|
('inet:email', r'(?=(?:[^a-z0-9_.+-]|^)(?P<valu>[a-z0-9_\.\-+]{1,256}@(?:[a-z0-9_-]{1,63}\.){1,10}(?:%s))(?:[^a-z0-9_.-]|[.\s]|$))' % tldcat, {}),
|
synapse/lib/snap.py
CHANGED
|
@@ -1325,13 +1325,13 @@ class Snap(s_base.Base):
|
|
|
1325
1325
|
|
|
1326
1326
|
if etyp == s_layer.EDIT_NODE_ADD:
|
|
1327
1327
|
node.bylayer['ndef'] = wlyr.iden
|
|
1328
|
-
callbacks.append((node.form.wasAdded, (node,)
|
|
1329
|
-
callbacks.append((self.view.runNodeAdd, (node,)
|
|
1328
|
+
callbacks.append((node.form.wasAdded, (node,)))
|
|
1329
|
+
callbacks.append((self.view.runNodeAdd, (node,)))
|
|
1330
1330
|
continue
|
|
1331
1331
|
|
|
1332
1332
|
if etyp == s_layer.EDIT_NODE_DEL:
|
|
1333
|
-
callbacks.append((node.form.wasDeleted, (node,)
|
|
1334
|
-
callbacks.append((self.view.runNodeDel, (node,)
|
|
1333
|
+
callbacks.append((node.form.wasDeleted, (node,)))
|
|
1334
|
+
callbacks.append((self.view.runNodeDel, (node,)))
|
|
1335
1335
|
continue
|
|
1336
1336
|
|
|
1337
1337
|
if etyp == s_layer.EDIT_PROP_SET:
|
|
@@ -1346,8 +1346,8 @@ class Snap(s_base.Base):
|
|
|
1346
1346
|
node.props[name] = valu
|
|
1347
1347
|
node.bylayer['props'][name] = wlyr.iden
|
|
1348
1348
|
|
|
1349
|
-
callbacks.append((prop.wasSet, (node, oldv)
|
|
1350
|
-
callbacks.append((self.view.runPropSet, (node, prop, oldv)
|
|
1349
|
+
callbacks.append((prop.wasSet, (node, oldv)))
|
|
1350
|
+
callbacks.append((self.view.runPropSet, (node, prop, oldv)))
|
|
1351
1351
|
continue
|
|
1352
1352
|
|
|
1353
1353
|
if etyp == s_layer.EDIT_PROP_DEL:
|
|
@@ -1362,8 +1362,8 @@ class Snap(s_base.Base):
|
|
|
1362
1362
|
node.props.pop(name, None)
|
|
1363
1363
|
node.bylayer['props'].pop(name, None)
|
|
1364
1364
|
|
|
1365
|
-
callbacks.append((prop.wasDel, (node, oldv)
|
|
1366
|
-
callbacks.append((self.view.runPropSet, (node, prop, oldv)
|
|
1365
|
+
callbacks.append((prop.wasDel, (node, oldv)))
|
|
1366
|
+
callbacks.append((self.view.runPropSet, (node, prop, oldv)))
|
|
1367
1367
|
continue
|
|
1368
1368
|
|
|
1369
1369
|
if etyp == s_layer.EDIT_TAG_SET:
|
|
@@ -1373,8 +1373,7 @@ class Snap(s_base.Base):
|
|
|
1373
1373
|
node.tags[tag] = valu
|
|
1374
1374
|
node.bylayer['tags'][tag] = wlyr.iden
|
|
1375
1375
|
|
|
1376
|
-
callbacks.append((self.view.runTagAdd, (node, tag, valu)
|
|
1377
|
-
callbacks.append((self.wlyr.fire, ('tag:add', ), {'tag': tag, 'node': node.iden()}))
|
|
1376
|
+
callbacks.append((self.view.runTagAdd, (node, tag, valu)))
|
|
1378
1377
|
continue
|
|
1379
1378
|
|
|
1380
1379
|
if etyp == s_layer.EDIT_TAG_DEL:
|
|
@@ -1384,8 +1383,7 @@ class Snap(s_base.Base):
|
|
|
1384
1383
|
node.tags.pop(tag, None)
|
|
1385
1384
|
node.bylayer['tags'].pop(tag, None)
|
|
1386
1385
|
|
|
1387
|
-
callbacks.append((self.view.runTagDel, (node, tag, oldv)
|
|
1388
|
-
callbacks.append((self.wlyr.fire, ('tag:del', ), {'tag': tag, 'node': node.iden()}))
|
|
1386
|
+
callbacks.append((self.view.runTagDel, (node, tag, oldv)))
|
|
1389
1387
|
continue
|
|
1390
1388
|
|
|
1391
1389
|
if etyp == s_layer.EDIT_TAGPROP_SET:
|
|
@@ -1420,14 +1418,14 @@ class Snap(s_base.Base):
|
|
|
1420
1418
|
if etyp == s_layer.EDIT_EDGE_ADD:
|
|
1421
1419
|
verb, n2iden = parms
|
|
1422
1420
|
n2 = await self.getNodeByBuid(s_common.uhex(n2iden))
|
|
1423
|
-
callbacks.append((self.view.runEdgeAdd, (node, verb, n2)
|
|
1421
|
+
callbacks.append((self.view.runEdgeAdd, (node, verb, n2)))
|
|
1424
1422
|
|
|
1425
1423
|
if etyp == s_layer.EDIT_EDGE_DEL:
|
|
1426
1424
|
verb, n2iden = parms
|
|
1427
1425
|
n2 = await self.getNodeByBuid(s_common.uhex(n2iden))
|
|
1428
|
-
callbacks.append((self.view.runEdgeDel, (node, verb, n2)
|
|
1426
|
+
callbacks.append((self.view.runEdgeDel, (node, verb, n2)))
|
|
1429
1427
|
|
|
1430
|
-
[await func(*args
|
|
1428
|
+
[await func(*args) for (func, args) in callbacks]
|
|
1431
1429
|
|
|
1432
1430
|
if actualedits:
|
|
1433
1431
|
await self.fire('node:edits', edits=actualedits)
|
|
@@ -1456,7 +1454,9 @@ class Snap(s_base.Base):
|
|
|
1456
1454
|
if isinstance(valu, dict):
|
|
1457
1455
|
form = self.core.model.reqForm(name)
|
|
1458
1456
|
if isinstance(form.type, s_types.Guid):
|
|
1459
|
-
|
|
1457
|
+
norms, props = await self._normGuidNodeDict(form, valu, props=props)
|
|
1458
|
+
valu = await self._addGuidNodeByDict(form, norms, props)
|
|
1459
|
+
return await self.getNodeByNdef((name, valu))
|
|
1460
1460
|
|
|
1461
1461
|
async with self.getEditor() as editor:
|
|
1462
1462
|
protonode = await editor.addNode(name, valu, props=props, norminfo=norminfo)
|
|
@@ -1466,100 +1466,109 @@ class Snap(s_base.Base):
|
|
|
1466
1466
|
# the newly constructed node is cached
|
|
1467
1467
|
return await self.getNodeByBuid(protonode.buid)
|
|
1468
1468
|
|
|
1469
|
-
async def _addGuidNodeByDict(self, form,
|
|
1469
|
+
async def _addGuidNodeByDict(self, form, norms, props):
|
|
1470
1470
|
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
addprops = vals.pop('$props', None)
|
|
1476
|
-
|
|
1477
|
-
if not vals:
|
|
1478
|
-
mesg = f'No values provided for form {form.full}'
|
|
1479
|
-
raise s_exc.BadTypeValu(mesg=mesg)
|
|
1480
|
-
|
|
1481
|
-
for name, valu in list(props.items()):
|
|
1482
|
-
try:
|
|
1483
|
-
props[name] = form.reqProp(name).type.norm(valu)
|
|
1484
|
-
except s_exc.BadTypeValu as e:
|
|
1485
|
-
mesg = e.get('mesg')
|
|
1486
|
-
e.update({
|
|
1487
|
-
'prop': name,
|
|
1488
|
-
'form': form.name,
|
|
1489
|
-
'mesg': f'Bad value for prop {form.name}:{name}: {mesg}',
|
|
1490
|
-
})
|
|
1491
|
-
raise e
|
|
1492
|
-
|
|
1493
|
-
if addprops is not None:
|
|
1494
|
-
for name, valu in addprops.items():
|
|
1495
|
-
try:
|
|
1496
|
-
props[name] = form.reqProp(name).type.norm(valu)
|
|
1497
|
-
except s_exc.BadTypeValu as e:
|
|
1498
|
-
mesg = e.get("mesg")
|
|
1499
|
-
if not trycast:
|
|
1500
|
-
e.update({
|
|
1501
|
-
'prop': name,
|
|
1502
|
-
'form': form.name,
|
|
1503
|
-
'mesg': f'Bad value for prop {form.name}:{name}: {mesg}'
|
|
1504
|
-
})
|
|
1505
|
-
raise e
|
|
1506
|
-
await self.warn(f'Skipping bad value for prop {form.name}:{name}: {mesg}')
|
|
1471
|
+
for name, info in norms.items():
|
|
1472
|
+
if info[0].isform:
|
|
1473
|
+
valu = await self._addGuidNodeByDict(*info)
|
|
1474
|
+
norms[name] = (form.prop(name), valu, {})
|
|
1507
1475
|
|
|
1508
|
-
|
|
1476
|
+
for name, info in props.items():
|
|
1477
|
+
if info[0].isform:
|
|
1478
|
+
valu = await self._addGuidNodeByDict(*info)
|
|
1479
|
+
props[name] = (form.prop(name), valu, {})
|
|
1509
1480
|
|
|
1510
|
-
|
|
1511
|
-
node = await self._getGuidNodeByNorms(form, iden, norms)
|
|
1481
|
+
node = await self._getGuidNodeByNorms(form, norms)
|
|
1512
1482
|
|
|
1513
1483
|
async with self.getEditor() as editor:
|
|
1514
1484
|
|
|
1515
1485
|
if node is not None:
|
|
1516
1486
|
proto = editor.loadNode(node)
|
|
1517
1487
|
else:
|
|
1518
|
-
|
|
1488
|
+
proplist = [(name, info[1]) for name, info in norms.items()]
|
|
1489
|
+
proplist.sort()
|
|
1490
|
+
|
|
1491
|
+
proto = await editor.addNode(form.name, proplist)
|
|
1519
1492
|
for name, (prop, valu, info) in norms.items():
|
|
1520
1493
|
await proto.set(name, valu, norminfo=info)
|
|
1521
1494
|
|
|
1522
1495
|
# ensure the non-deconf props are set
|
|
1523
|
-
for name, (valu, info) in props.items():
|
|
1496
|
+
for name, (prop, valu, info) in props.items():
|
|
1524
1497
|
await proto.set(name, valu, norminfo=info)
|
|
1525
1498
|
|
|
1526
|
-
return
|
|
1499
|
+
return proto.valu
|
|
1500
|
+
|
|
1501
|
+
async def _normGuidNodeDict(self, form, vals, props=None):
|
|
1502
|
+
|
|
1503
|
+
if props is None:
|
|
1504
|
+
props = {}
|
|
1505
|
+
|
|
1506
|
+
trycast = vals.pop('$try', False)
|
|
1507
|
+
addprops = vals.pop('$props', None)
|
|
1508
|
+
|
|
1509
|
+
if not vals:
|
|
1510
|
+
mesg = f'No values provided for form {form.full}'
|
|
1511
|
+
raise s_exc.BadTypeValu(mesg=mesg)
|
|
1512
|
+
|
|
1513
|
+
props |= await self._normGuidNodeProps(form, props)
|
|
1527
1514
|
|
|
1528
|
-
|
|
1515
|
+
if addprops:
|
|
1516
|
+
props |= await self._normGuidNodeProps(form, addprops, trycast=trycast)
|
|
1517
|
+
|
|
1518
|
+
norms = await self._normGuidNodeProps(form, vals)
|
|
1519
|
+
|
|
1520
|
+
return norms, props
|
|
1521
|
+
|
|
1522
|
+
async def _normGuidNodeProps(self, form, props, trycast=False):
|
|
1529
1523
|
|
|
1530
1524
|
norms = {}
|
|
1531
|
-
proplist = []
|
|
1532
1525
|
|
|
1533
|
-
for name, valu in props.items():
|
|
1526
|
+
for name, valu in list(props.items()):
|
|
1527
|
+
prop = form.reqProp(name)
|
|
1528
|
+
|
|
1529
|
+
if isinstance(valu, dict) and isinstance(prop.type, s_types.Guid):
|
|
1530
|
+
pform = self.core.model.reqForm(prop.type.name)
|
|
1531
|
+
gnorm, gprop = await self._normGuidNodeDict(pform, valu)
|
|
1532
|
+
norms[name] = (pform, gnorm, gprop)
|
|
1533
|
+
continue
|
|
1534
1534
|
|
|
1535
1535
|
try:
|
|
1536
|
-
|
|
1537
|
-
norm, norminfo = prop.type.norm(valu)
|
|
1536
|
+
norms[name] = (prop, *prop.type.norm(valu))
|
|
1538
1537
|
|
|
1539
|
-
norms[name] = (prop, norm, norminfo)
|
|
1540
|
-
proplist.append((name, norm))
|
|
1541
1538
|
except s_exc.BadTypeValu as e:
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1539
|
+
if not trycast:
|
|
1540
|
+
if 'prop' not in e.errinfo:
|
|
1541
|
+
mesg = e.get('mesg')
|
|
1542
|
+
e.update({
|
|
1543
|
+
'prop': name,
|
|
1544
|
+
'form': form.name,
|
|
1545
|
+
'mesg': f'Bad value for prop {form.name}:{name}: {mesg}',
|
|
1546
|
+
})
|
|
1547
|
+
raise e
|
|
1551
1548
|
|
|
1552
|
-
return norms
|
|
1549
|
+
return norms
|
|
1553
1550
|
|
|
1554
1551
|
async def _getGuidNodeByDict(self, form, props):
|
|
1555
|
-
norms,
|
|
1556
|
-
return await self._getGuidNodeByNorms(form,
|
|
1552
|
+
norms, _ = await self._normGuidNodeDict(form, props)
|
|
1553
|
+
return await self._getGuidNodeByNorms(form, norms)
|
|
1554
|
+
|
|
1555
|
+
async def _getGuidNodeByNorms(self, form, norms):
|
|
1557
1556
|
|
|
1558
|
-
|
|
1557
|
+
proplist = []
|
|
1558
|
+
for name, info in norms.items():
|
|
1559
|
+
if info[0].isform:
|
|
1560
|
+
if (node := await self._getGuidNodeByNorms(*info[:2])) is None:
|
|
1561
|
+
return
|
|
1562
|
+
valu = node.ndef[1]
|
|
1563
|
+
norms[name] = (form.prop(name), valu, {})
|
|
1564
|
+
proplist.append((name, valu))
|
|
1565
|
+
else:
|
|
1566
|
+
proplist.append((name, info[1]))
|
|
1559
1567
|
|
|
1560
1568
|
# check first for an exact match via our same deconf strategy
|
|
1569
|
+
proplist.sort()
|
|
1561
1570
|
|
|
1562
|
-
node = await self.getNodeByNdef((form.full,
|
|
1571
|
+
node = await self.getNodeByNdef((form.full, s_common.guid(proplist)))
|
|
1563
1572
|
if node is not None:
|
|
1564
1573
|
|
|
1565
1574
|
# ensure we still match the property deconf criteria
|
synapse/lib/storm.py
CHANGED
|
@@ -1454,7 +1454,8 @@ class StormDmon(s_base.Base):
|
|
|
1454
1454
|
viewiden = opts.get('view')
|
|
1455
1455
|
|
|
1456
1456
|
info = {'iden': self.iden, 'name': self.ddef.get('name', 'storm dmon'), 'view': viewiden}
|
|
1457
|
-
|
|
1457
|
+
|
|
1458
|
+
await self.core.boss.promote('storm:dmon', user=self.user, info=info, background=True)
|
|
1458
1459
|
|
|
1459
1460
|
def dmonPrint(evnt):
|
|
1460
1461
|
self._runLogAdd(evnt)
|
synapse/lib/stormlib/imap.py
CHANGED
|
@@ -4,6 +4,7 @@ import aioimaplib
|
|
|
4
4
|
|
|
5
5
|
import synapse.exc as s_exc
|
|
6
6
|
import synapse.common as s_common
|
|
7
|
+
import synapse.lib.coro as s_coro
|
|
7
8
|
import synapse.lib.stormtypes as s_stormtypes
|
|
8
9
|
|
|
9
10
|
async def run_imap_coro(coro):
|
|
@@ -88,8 +89,8 @@ class ImapLib(s_stormtypes.Lib):
|
|
|
88
89
|
imap_cli = aioimaplib.IMAP4(host=host, port=port, timeout=timeout)
|
|
89
90
|
|
|
90
91
|
async def fini():
|
|
91
|
-
# call protocol.logout()
|
|
92
|
-
|
|
92
|
+
# call protocol.logout() via a background task
|
|
93
|
+
s_coro.create_task(s_common.wait_for(imap_cli.protocol.logout(), 5))
|
|
93
94
|
|
|
94
95
|
self.runt.snap.onfini(fini)
|
|
95
96
|
|
synapse/lib/stormlib/spooled.py
CHANGED
|
@@ -37,6 +37,7 @@ class LibSpooled(s_stormtypes.Lib):
|
|
|
37
37
|
async def _methSet(self, *vals):
|
|
38
38
|
core = self.runt.snap.core
|
|
39
39
|
spool = await s_spooled.Set.anit(dirn=core.dirn, cell=core, size=1000)
|
|
40
|
+
self.runt.snap.onfini(spool)
|
|
40
41
|
|
|
41
42
|
valu = list(vals)
|
|
42
43
|
for item in valu:
|
|
@@ -107,3 +108,6 @@ class SpooledSet(s_stormtypes.Set):
|
|
|
107
108
|
|
|
108
109
|
async def value(self):
|
|
109
110
|
return set([x async for x in self.valu])
|
|
111
|
+
|
|
112
|
+
async def bool(self):
|
|
113
|
+
return bool(len(self.valu))
|
synapse/lib/stormtypes.py
CHANGED
|
@@ -4731,6 +4731,9 @@ class Str(Prim):
|
|
|
4731
4731
|
return str(self) == str(othr)
|
|
4732
4732
|
return False
|
|
4733
4733
|
|
|
4734
|
+
async def bool(self):
|
|
4735
|
+
return bool(self.valu)
|
|
4736
|
+
|
|
4734
4737
|
@stormfunc(readonly=True)
|
|
4735
4738
|
async def _methStrFind(self, valu):
|
|
4736
4739
|
text = await tostr(valu)
|
|
@@ -4970,6 +4973,9 @@ class Bytes(Prim):
|
|
|
4970
4973
|
return self.valu == othr.valu
|
|
4971
4974
|
return False
|
|
4972
4975
|
|
|
4976
|
+
async def bool(self):
|
|
4977
|
+
return bool(self.valu)
|
|
4978
|
+
|
|
4973
4979
|
async def _storm_copy(self):
|
|
4974
4980
|
item = await s_coro.ornot(self.value)
|
|
4975
4981
|
return s_msgpack.deepcopy(item, use_list=True)
|
|
@@ -5042,6 +5048,9 @@ class Dict(Prim):
|
|
|
5042
5048
|
def __len__(self):
|
|
5043
5049
|
return len(self.valu)
|
|
5044
5050
|
|
|
5051
|
+
async def bool(self):
|
|
5052
|
+
return bool(self.valu)
|
|
5053
|
+
|
|
5045
5054
|
async def _storm_copy(self):
|
|
5046
5055
|
item = await s_coro.ornot(self.value)
|
|
5047
5056
|
return s_msgpack.deepcopy(item, use_list=True)
|
|
@@ -5194,6 +5203,9 @@ class Set(Prim):
|
|
|
5194
5203
|
def __len__(self):
|
|
5195
5204
|
return len(self.valu)
|
|
5196
5205
|
|
|
5206
|
+
async def bool(self):
|
|
5207
|
+
return bool(self.valu)
|
|
5208
|
+
|
|
5197
5209
|
async def _methSetSize(self):
|
|
5198
5210
|
return len(self)
|
|
5199
5211
|
|
|
@@ -5384,6 +5396,9 @@ class List(Prim):
|
|
|
5384
5396
|
def __len__(self):
|
|
5385
5397
|
return len(self.valu)
|
|
5386
5398
|
|
|
5399
|
+
async def bool(self):
|
|
5400
|
+
return bool(self.valu)
|
|
5401
|
+
|
|
5387
5402
|
@stormfunc(readonly=True)
|
|
5388
5403
|
async def _methListHas(self, valu):
|
|
5389
5404
|
if valu in self.valu:
|
|
@@ -5519,6 +5534,9 @@ class Bool(Prim):
|
|
|
5519
5534
|
def __hash__(self):
|
|
5520
5535
|
return hash((self._storm_typename, self.value()))
|
|
5521
5536
|
|
|
5537
|
+
async def bool(self):
|
|
5538
|
+
return bool(self.valu)
|
|
5539
|
+
|
|
5522
5540
|
@registry.registerType
|
|
5523
5541
|
class Number(Prim):
|
|
5524
5542
|
'''
|