synapse 2.201.0__py311-none-any.whl → 2.203.0__py311-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of synapse might be problematic. Click here for more details.

Files changed (106) hide show
  1. synapse/axon.py +4 -4
  2. synapse/cmds/cortex.py +4 -6
  3. synapse/cmds/hive.py +10 -10
  4. synapse/common.py +17 -58
  5. synapse/cortex.py +36 -29
  6. synapse/data/__init__.py +3 -2
  7. synapse/data/iana.uris.mpk +1 -0
  8. synapse/lib/autodoc.py +3 -3
  9. synapse/lib/base.py +2 -12
  10. synapse/lib/cell.py +9 -13
  11. synapse/lib/cli.py +2 -2
  12. synapse/lib/config.py +2 -2
  13. synapse/lib/encoding.py +4 -3
  14. synapse/lib/httpapi.py +7 -11
  15. synapse/lib/json.py +224 -0
  16. synapse/lib/lmdbslab.py +1 -1
  17. synapse/lib/oauth.py +176 -54
  18. synapse/lib/parser.py +2 -1
  19. synapse/lib/rstorm.py +18 -14
  20. synapse/lib/schemas.py +87 -1
  21. synapse/lib/scrape.py +35 -13
  22. synapse/lib/snap.py +2 -1
  23. synapse/lib/storm.lark +5 -4
  24. synapse/lib/storm.py +2 -2
  25. synapse/lib/storm_format.py +2 -1
  26. synapse/lib/stormhttp.py +11 -13
  27. synapse/lib/stormlib/aha.py +4 -4
  28. synapse/lib/stormlib/auth.py +1 -1
  29. synapse/lib/stormlib/cache.py +2 -2
  30. synapse/lib/stormlib/cortex.py +5 -5
  31. synapse/lib/stormlib/graph.py +1 -1
  32. synapse/lib/stormlib/imap.py +1 -1
  33. synapse/lib/stormlib/json.py +8 -11
  34. synapse/lib/stormlib/model.py +1 -1
  35. synapse/lib/stormlib/notifications.py +2 -2
  36. synapse/lib/stormlib/oauth.py +105 -2
  37. synapse/lib/stormlib/stats.py +4 -0
  38. synapse/lib/stormlib/stix.py +3 -4
  39. synapse/lib/stormlib/vault.py +6 -6
  40. synapse/lib/stormlib/xml.py +2 -2
  41. synapse/lib/stormtypes.py +19 -28
  42. synapse/lib/structlog.py +3 -3
  43. synapse/lib/types.py +2 -1
  44. synapse/lib/version.py +2 -2
  45. synapse/lib/view.py +7 -3
  46. synapse/models/base.py +51 -2
  47. synapse/telepath.py +79 -18
  48. synapse/tests/files/__init__.py +0 -1
  49. synapse/tests/test_axon.py +1 -1
  50. synapse/tests/test_cmds_cortex.py +3 -2
  51. synapse/tests/test_cmds_hive.py +4 -4
  52. synapse/tests/test_common.py +29 -19
  53. synapse/tests/test_cortex.py +28 -8
  54. synapse/tests/test_lib_ast.py +3 -3
  55. synapse/tests/test_lib_autodoc.py +5 -5
  56. synapse/tests/test_lib_base.py +1 -1
  57. synapse/tests/test_lib_cell.py +24 -7
  58. synapse/tests/test_lib_config.py +2 -2
  59. synapse/tests/test_lib_encoding.py +2 -2
  60. synapse/tests/test_lib_grammar.py +68 -64
  61. synapse/tests/test_lib_httpapi.py +13 -13
  62. synapse/tests/test_lib_json.py +219 -0
  63. synapse/tests/test_lib_multislabseqn.py +2 -1
  64. synapse/tests/test_lib_node.py +2 -2
  65. synapse/tests/test_lib_scrape.py +50 -0
  66. synapse/tests/test_lib_storm.py +12 -6
  67. synapse/tests/test_lib_stormhttp.py +4 -4
  68. synapse/tests/test_lib_stormlib_auth.py +3 -2
  69. synapse/tests/test_lib_stormlib_cortex.py +10 -12
  70. synapse/tests/test_lib_stormlib_infosec.py +2 -3
  71. synapse/tests/test_lib_stormlib_json.py +18 -21
  72. synapse/tests/test_lib_stormlib_log.py +1 -1
  73. synapse/tests/test_lib_stormlib_oauth.py +603 -1
  74. synapse/tests/test_lib_stormlib_stats.py +13 -3
  75. synapse/tests/test_lib_stormlib_stix.py +5 -5
  76. synapse/tests/test_lib_stormtypes.py +4 -4
  77. synapse/tests/test_lib_structlog.py +5 -6
  78. synapse/tests/test_lib_view.py +8 -0
  79. synapse/tests/test_model_base.py +32 -0
  80. synapse/tests/test_model_infotech.py +2 -2
  81. synapse/tests/test_telepath.py +56 -35
  82. synapse/tests/test_tools_cryo_cat.py +4 -3
  83. synapse/tests/test_tools_docker_validate.py +4 -2
  84. synapse/tests/test_tools_feed.py +30 -2
  85. synapse/tests/test_tools_genpkg.py +1 -1
  86. synapse/tests/test_tools_healthcheck.py +8 -7
  87. synapse/tests/test_utils.py +2 -2
  88. synapse/tests/test_utils_getrefs.py +35 -28
  89. synapse/tests/utils.py +3 -3
  90. synapse/tools/autodoc.py +3 -3
  91. synapse/tools/changelog.py +2 -2
  92. synapse/tools/cryo/cat.py +3 -3
  93. synapse/tools/csvtool.py +2 -3
  94. synapse/tools/docker/validate.py +5 -5
  95. synapse/tools/feed.py +2 -1
  96. synapse/tools/genpkg.py +3 -2
  97. synapse/tools/healthcheck.py +2 -3
  98. synapse/tools/json2mpk.py +2 -2
  99. synapse/utils/getrefs.py +10 -8
  100. synapse/vendor/cpython/lib/json.py +35 -0
  101. synapse/vendor/cpython/lib/test/test_json.py +22 -0
  102. {synapse-2.201.0.dist-info → synapse-2.203.0.dist-info}/METADATA +2 -1
  103. {synapse-2.201.0.dist-info → synapse-2.203.0.dist-info}/RECORD +106 -101
  104. {synapse-2.201.0.dist-info → synapse-2.203.0.dist-info}/WHEEL +1 -1
  105. {synapse-2.201.0.dist-info → synapse-2.203.0.dist-info}/LICENSE +0 -0
  106. {synapse-2.201.0.dist-info → synapse-2.203.0.dist-info}/top_level.txt +0 -0
synapse/axon.py CHANGED
@@ -1,5 +1,4 @@
1
1
  import csv
2
- import json
3
2
  import struct
4
3
  import asyncio
5
4
  import hashlib
@@ -16,6 +15,7 @@ import synapse.common as s_common
16
15
  import synapse.lib.cell as s_cell
17
16
  import synapse.lib.coro as s_coro
18
17
  import synapse.lib.base as s_base
18
+ import synapse.lib.json as s_json
19
19
  import synapse.lib.link as s_link
20
20
  import synapse.lib.const as s_const
21
21
  import synapse.lib.nexus as s_nexus
@@ -1509,8 +1509,8 @@ class Axon(s_cell.Cell):
1509
1509
  continue
1510
1510
 
1511
1511
  try:
1512
- yield json.loads(line)
1513
- except json.JSONDecodeError as e:
1512
+ yield s_json.loads(line)
1513
+ except s_exc.BadJsonText as e:
1514
1514
  logger.exception(f'Bad json line encountered for {sha256}')
1515
1515
  raise s_exc.BadJsonText(mesg=f'Bad json line encountered while processing {sha256}, ({e})',
1516
1516
  sha256=sha256) from None
@@ -1643,7 +1643,7 @@ class Axon(s_cell.Cell):
1643
1643
  else:
1644
1644
  valu = field.get('value')
1645
1645
  if not isinstance(valu, (bytes, str)):
1646
- valu = json.dumps(valu)
1646
+ valu = s_json.dumps(valu).decode()
1647
1647
 
1648
1648
  data.add_field(name,
1649
1649
  valu,
synapse/cmds/cortex.py CHANGED
@@ -1,5 +1,4 @@
1
1
  import os
2
- import json
3
2
  import queue
4
3
  import shlex
5
4
  import pprint
@@ -10,6 +9,7 @@ import synapse.common as s_common
10
9
 
11
10
  import synapse.lib.cli as s_cli
12
11
  import synapse.lib.cmd as s_cmd
12
+ import synapse.lib.json as s_json
13
13
  import synapse.lib.node as s_node
14
14
  import synapse.lib.time as s_time
15
15
  import synapse.lib.msgpack as s_msgpack
@@ -118,9 +118,7 @@ Examples:
118
118
 
119
119
  fmt = self.locs.get('log:fmt')
120
120
  if fmt == 'jsonl':
121
- s = json.dumps(mesg, sort_keys=True) + '\n'
122
- buf = s.encode()
123
- return buf
121
+ return s_json.dumps(mesg, sort_keys=True, newline=True)
124
122
 
125
123
  elif fmt == 'mpk':
126
124
  buf = s_msgpack.en(mesg)
@@ -430,8 +428,8 @@ class StormCmd(s_cli.Cmd):
430
428
  if mesg[0] == 'node':
431
429
 
432
430
  if nodesfd is not None:
433
- byts = json.dumps(mesg[1]).encode()
434
- nodesfd.write(byts + b'\n')
431
+ byts = s_json.dumps(mesg[1], newline=True)
432
+ nodesfd.write(byts)
435
433
 
436
434
  try:
437
435
  func = self.cmdmeths[mesg[0]]
synapse/cmds/hive.py CHANGED
@@ -1,5 +1,4 @@
1
1
  import os
2
- import json
3
2
  import shlex
4
3
  import pprint
5
4
  import asyncio
@@ -12,6 +11,7 @@ import synapse.common as s_common
12
11
 
13
12
  import synapse.lib.cmd as s_cmd
14
13
  import synapse.lib.cli as s_cli
14
+ import synapse.lib.json as s_json
15
15
 
16
16
  ListHelp = '''
17
17
  Lists all the keys underneath a particular key in the hive.
@@ -140,8 +140,8 @@ A Hive is a hierarchy persistent storage mechanism typically used for configurat
140
140
  return
141
141
 
142
142
  if opts.json:
143
- prend = json.dumps(valu, indent=4, sort_keys=True)
144
- rend = prend.encode()
143
+ rend = s_json.dumps(valu, indent=True, sort_keys=True)
144
+ prend = rend.decode()
145
145
  elif isinstance(valu, str):
146
146
  rend = valu.encode()
147
147
  prend = valu
@@ -149,7 +149,7 @@ A Hive is a hierarchy persistent storage mechanism typically used for configurat
149
149
  rend = valu
150
150
  prend = pprint.pformat(valu)
151
151
  else:
152
- rend = json.dumps(valu, indent=4, sort_keys=True).encode()
152
+ rend = s_json.dumps(valu, indent=True, sort_keys=True)
153
153
  prend = pprint.pformat(valu)
154
154
 
155
155
  if opts.file:
@@ -172,7 +172,7 @@ A Hive is a hierarchy persistent storage mechanism typically used for configurat
172
172
  if opts.value[0] not in '([{"':
173
173
  data = opts.value
174
174
  else:
175
- data = json.loads(opts.value)
175
+ data = s_json.loads(opts.value)
176
176
  await core.setHiveKey(path, data)
177
177
  return
178
178
  elif opts.file is not None:
@@ -181,7 +181,7 @@ A Hive is a hierarchy persistent storage mechanism typically used for configurat
181
181
  if len(s) == 0:
182
182
  self.printf('Empty file. Not writing key.')
183
183
  return
184
- data = s if opts.string else json.loads(s)
184
+ data = s if opts.string else s_json.loads(s)
185
185
  await core.setHiveKey(path, data)
186
186
  return
187
187
 
@@ -201,8 +201,8 @@ A Hive is a hierarchy persistent storage mechanism typically used for configurat
201
201
  data = old_valu
202
202
  else:
203
203
  try:
204
- data = json.dumps(old_valu, indent=4, sort_keys=True)
205
- except (ValueError, TypeError):
204
+ data = s_json.dumps(old_valu, indent=True, sort_keys=True).decode()
205
+ except s_exc.MustBeJsonSafe:
206
206
  self.printf('Value is not JSON-encodable, therefore not editable.')
207
207
  return
208
208
  fh.write(data)
@@ -218,8 +218,8 @@ A Hive is a hierarchy persistent storage mechanism typically used for configurat
218
218
  self.printf('Empty file. Not writing key.')
219
219
  return
220
220
  try:
221
- valu = rawval if opts.string else json.loads(rawval)
222
- except json.JSONDecodeError as e: # pragma: no cover
221
+ valu = rawval if opts.string else s_json.loads(rawval)
222
+ except s_exc.BadJsonText as e: # pragma: no cover
223
223
  self.printf(f'JSON decode failure: [{e}]. Reopening.')
224
224
  await asyncio.sleep(1)
225
225
  continue
synapse/common.py CHANGED
@@ -3,7 +3,6 @@ import os
3
3
  import ssl
4
4
  import sys
5
5
  import enum
6
- import json
7
6
  import http
8
7
  import stat
9
8
  import time
@@ -30,6 +29,7 @@ import contextlib
30
29
  import collections
31
30
 
32
31
  import http.cookies
32
+ import tornado.escape
33
33
 
34
34
  import yaml
35
35
  import regex
@@ -511,24 +511,6 @@ def getDirSize(*paths):
511
511
 
512
512
  return realsum, apprsum
513
513
 
514
- def jsload(*paths):
515
- with genfile(*paths) as fd:
516
- byts = fd.read()
517
- if not byts:
518
- return None
519
-
520
- return json.loads(byts.decode('utf8'))
521
-
522
- def jslines(*paths):
523
- with genfile(*paths) as fd:
524
- for line in fd:
525
- yield json.loads(line)
526
-
527
- def jssave(js, *paths):
528
- path = genpath(*paths)
529
- with io.open(path, 'wb') as fd:
530
- fd.write(json.dumps(js, sort_keys=True, indent=2).encode('utf8'))
531
-
532
514
  def yamlloads(data):
533
515
  return yaml.load(data, Loader)
534
516
 
@@ -959,16 +941,6 @@ def deprdate(name, date): # pragma: no cover
959
941
  mesg = f'{name} is deprecated and will be removed on {date}.'
960
942
  warnings.warn(mesg, DeprecationWarning)
961
943
 
962
- def reqjsonsafe(item):
963
- '''
964
- Returns None if item is json serializable, otherwise raises an exception.
965
- Uses default type coercion from built-in json.dumps.
966
- '''
967
- try:
968
- json.dumps(item)
969
- except TypeError as e:
970
- raise s_exc.MustBeJsonSafe(mesg=str(e)) from None
971
-
972
944
  def jsonsafe_nodeedits(nodeedits):
973
945
  '''
974
946
  Hexlify the buid of each node:edits
@@ -998,35 +970,6 @@ def reprauthrule(rule):
998
970
  text = '!' + text
999
971
  return text
1000
972
 
1001
- def reqJsonSafeStrict(item):
1002
- '''
1003
- Require the item to be safe to serialize to JSON without type coercion issues.
1004
-
1005
- Args:
1006
- item: The python primitive to check.
1007
-
1008
- Returns:
1009
- None
1010
-
1011
- Raise:
1012
- s_exc.BadArg: If the item contains invalid data.
1013
- '''
1014
- if item is None:
1015
- return
1016
- if isinstance(item, (str, int,)):
1017
- return
1018
- if isinstance(item, (list, tuple)):
1019
- for valu in item:
1020
- reqJsonSafeStrict(valu)
1021
- return
1022
- if isinstance(item, dict):
1023
- for key, valu in item.items():
1024
- if not isinstance(key, str):
1025
- raise s_exc.BadArg(mesg='Non-string keys are not valid json', key=key)
1026
- reqJsonSafeStrict(valu)
1027
- return
1028
- raise s_exc.BadArg(mesg=f'Invalid item type encountered: {item.__class__.__name__}')
1029
-
1030
973
  async def merggenr(genrs, cmprkey):
1031
974
  '''
1032
975
  Iterate multiple sorted async generators and yield their results in order.
@@ -1234,7 +1177,23 @@ def _patch_http_cookies():
1234
1177
  return
1235
1178
  http.cookies._unquote = v_cookies._unquote
1236
1179
 
1180
+ def _patch_tornado_json():
1181
+ import synapse.lib.json as s_json
1182
+
1183
+ if hasattr(tornado.escape, 'json_encode'):
1184
+ # This exists for a specific reason. See the following URL for explanation:
1185
+ # https://github.com/tornadoweb/tornado/blob/d5ac65c1f1453c2aeddd089d8e68c159645c13e1/tornado/escape.py#L83-L96
1186
+ # https://github.com/tornadoweb/tornado/pull/706
1187
+ def _tornado_json_encode(value):
1188
+ return s_json.dumps(value).replace(b'</', br'<\/').decode()
1189
+
1190
+ tornado.escape.json_encode = _tornado_json_encode
1191
+
1192
+ if hasattr(tornado.escape, 'json_decode'):
1193
+ tornado.escape.json_decode = s_json.loads
1194
+
1237
1195
  _patch_http_cookies()
1196
+ _patch_tornado_json()
1238
1197
 
1239
1198
  # TODO: Switch back to using asyncio.wait_for when we are using py 3.12+
1240
1199
  # This is a workaround for a race where asyncio.wait_for can end up
synapse/cortex.py CHANGED
@@ -1265,7 +1265,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
1265
1265
 
1266
1266
  byts = self.slab.get(newname.encode(), db=self.macrodb)
1267
1267
  if byts is not None:
1268
- raise s_exc.DupName('A macro named {newname} already exists!')
1268
+ raise s_exc.DupName(mesg=f'A macro named {newname} already exists!', name=newname)
1269
1269
 
1270
1270
  self.slab.put(newname.encode(), s_msgpack.en(mdef), db=self.macrodb)
1271
1271
  self.slab.pop(name.encode(), db=self.macrodb)
@@ -5874,38 +5874,45 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
5874
5874
  if self.stormpool is None: # pragma: no cover
5875
5875
  return None
5876
5876
 
5877
- if self.stormpool.size() == 0:
5877
+ size = self.stormpool.size()
5878
+ if size == 0:
5878
5879
  logger.warning('Storm query mirror pool is empty, running query locally.')
5879
5880
  return None
5880
5881
 
5881
- proxy = None
5882
+ for _ in range(size):
5882
5883
 
5883
- try:
5884
- timeout = self.stormpoolopts.get('timeout:connection')
5885
- proxy = await self.stormpool.proxy(timeout=timeout)
5886
- proxyname = proxy._ahainfo.get('name')
5887
- if proxyname is not None and proxyname == self.ahasvcname:
5888
- # we are part of the pool and were selected. Convert to local use.
5889
- return None
5884
+ try:
5885
+ timeout = self.stormpoolopts.get('timeout:connection')
5886
+ proxy = await self.stormpool.proxy(timeout=timeout)
5887
+ proxyname = proxy._ahainfo.get('name')
5888
+ if proxyname is not None and proxyname == self.ahasvcname:
5889
+ # we are part of the pool and were selected. Convert to local use.
5890
+ return None
5891
+
5892
+ except TimeoutError:
5893
+ logger.warning('Timeout waiting for pool mirror proxy.')
5894
+ continue
5895
+
5896
+ try:
5897
+
5898
+ curoffs = opts.setdefault('nexsoffs', await self.getNexsIndx() - 1)
5899
+ miroffs = await s_common.wait_for(proxy.getNexsIndx(), timeout) - 1
5900
+ if (delta := curoffs - miroffs) <= MAX_NEXUS_DELTA:
5901
+ return proxy
5890
5902
 
5891
- curoffs = opts.setdefault('nexsoffs', await self.getNexsIndx() - 1)
5892
- miroffs = await s_common.wait_for(proxy.getNexsIndx(), timeout) - 1
5893
- if (delta := curoffs - miroffs) > MAX_NEXUS_DELTA:
5894
- mesg = (f'Pool mirror [{proxyname}] Nexus offset delta too large '
5895
- f'({delta} > {MAX_NEXUS_DELTA}), running query locally.')
5903
+ mesg = f'Pool mirror [{proxyname}] is too far out of sync. Skipping.'
5896
5904
  logger.warning(mesg, extra=await self.getLogExtra(delta=delta, mirror=proxyname, mirror_offset=miroffs))
5897
- return None
5898
5905
 
5899
- return proxy
5906
+ except s_exc.IsFini:
5907
+ mesg = f'Proxy for pool mirror [{proxyname}] was shutdown. Skipping.'
5908
+ logger.warning(mesg, extra=await self.getLogExtra(mirror=proxyname))
5900
5909
 
5901
- except (TimeoutError, s_exc.IsFini):
5902
- if proxy is None:
5903
- logger.warning('Timeout waiting for pool mirror, running query locally.')
5904
- else:
5905
- mesg = f'Timeout waiting for pool mirror [{proxyname}] Nexus offset, running query locally.'
5910
+ except TimeoutError:
5911
+ mesg = f'Timeout waiting for pool mirror [{proxyname}] Nexus offset.'
5906
5912
  logger.warning(mesg, extra=await self.getLogExtra(mirror=proxyname))
5907
- await proxy.fini()
5908
- return None
5913
+
5914
+ logger.warning('Pool members exhausted. Running query locally.', extra=await self.getLogExtra())
5915
+ return None
5909
5916
 
5910
5917
  async def storm(self, text, opts=None):
5911
5918
 
@@ -6528,7 +6535,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
6528
6535
 
6529
6536
  cdef['reqs'] = reqs
6530
6537
  except KeyError:
6531
- raise s_exc.BadConfValu('Unrecognized time unit')
6538
+ raise s_exc.BadConfValu(mesg='Unrecognized time unit')
6532
6539
 
6533
6540
  if not cdef.get('iden'):
6534
6541
  cdef['iden'] = s_common.guid()
@@ -6985,7 +6992,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
6985
6992
 
6986
6993
  vault = self.getVault(iden)
6987
6994
  if vault is None:
6988
- raise s_exc.NoSuchIden(mesg=f'Vault not found for iden: {iden}.')
6995
+ raise s_exc.NoSuchIden(mesg=f'Vault not found for iden: {iden}.', iden=iden)
6989
6996
 
6990
6997
  return vault
6991
6998
 
@@ -7338,7 +7345,7 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
7338
7345
  scope = 'roles'
7339
7346
  ident = self.auth.role(iden)
7340
7347
  if ident is None:
7341
- raise s_exc.NoSuchIden(mesg=f'Iden {iden} is not a valid user or role.')
7348
+ raise s_exc.NoSuchIden(mesg=f'Iden {iden} is not a valid user or role.', iden=iden)
7342
7349
 
7343
7350
  await self._setEasyPerm(vault, scope, ident.iden, level)
7344
7351
  permissions = vault.get('permissions')
@@ -7359,14 +7366,14 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
7359
7366
  Returns: Updated vault.
7360
7367
  '''
7361
7368
  if self.getVaultByName(name) is not None:
7362
- raise s_exc.DupName(mesg=f'Vault with name {name} already exists.')
7369
+ raise s_exc.DupName(mesg=f'Vault with name {name} already exists.', name=name)
7363
7370
 
7364
7371
  return await self._push(('vault:set'), iden, 'name', name)
7365
7372
 
7366
7373
  @s_nexus.Pusher.onPush('vault:set')
7367
7374
  async def _setVault(self, iden, key, valu):
7368
7375
  if key not in ('name', 'permissions'): # pragma: no cover
7369
- raise s_exc.BadArg('Only vault names and permissions can be changed.')
7376
+ raise s_exc.BadArg(mesg='Only vault names and permissions can be changed.')
7370
7377
 
7371
7378
  vault = self.reqVault(iden)
7372
7379
  oldv = vault.get(key)
synapse/data/__init__.py CHANGED
@@ -1,8 +1,9 @@
1
1
  import os
2
- import json
3
2
  import logging
4
3
 
5
4
  import synapse.common as s_common
5
+
6
+ import synapse.lib.json as s_json
6
7
  import synapse.lib.datfile as s_datfile
7
8
  import synapse.lib.msgpack as s_msgpack
8
9
 
@@ -26,7 +27,7 @@ def get(name, defval=None):
26
27
 
27
28
  def getJSON(name):
28
29
  with s_datfile.openDatFile(f'synapse.data/{name}.json') as fd:
29
- return json.loads(fd.read())
30
+ return s_json.load(fd)
30
31
 
31
32
  def path(*names):
32
33
  return s_common.genpath(dirname, *names)
@@ -0,0 +1 @@
1
+ ���aaa�aaas�about�acap�acct�acd�acr�adiumxtra�adt�afp�afs�aim�amss�android�appdata�apt�ar�ari�ark�at�attachment�aw�barion�bb�beshare�bitcoin�bitcoincash�blob�bluetooth�bolo�brid�browserext�cabal�calculator�callto�cap�cast�casts�chrome�chrome-extension�cid�coap�coap+tcp�coap+ws�coaps�coaps+tcp�coaps+ws�com-eventbrite-attendee�content�content-type�crid�cstr�cvs�dab�dat�data�dav�dhttp�diaspora�dict�did�dis�dlna-playcontainer�dlna-playsingle�dns�dntp�doi�dpp�drm�drop�dtmi�dtn�dvb�dvx�dweb�ed2k�eid�elsi�embedded�ens�ethereum�example�facetime�fax�feed�feedready�fido�file�filesystem�finger�first-run-pen-experience�fish�fm�ftp�fuchsia-pkg�geo�gg�git�gitoid�gizmoproject�go�gopher�graph�grd�gtalk�h323�ham�hcap�hcp�hs20�http�https�hxxp�hxxps�hydrazone�hyper�iax�icap�icon�ilstring�im�imap�info�iotdisco�ipfs�ipn�ipns�ipp�ipps�irc�irc6�ircs�iris�iris.beep�iris.lwz�iris.xpc�iris.xpcs�isostore�itms�jabber�jar�jms�keyparc�lastfm�lbry�ldap�ldaps�leaptofrogans�lid�lorawan�lpa�lvlt�#machineProvisioningProgressReporter�magnet�mailserver�mailto�maps�market�matrix�message�microsoft.windows.camera�$microsoft.windows.camera.multipicker�microsoft.windows.camera.picker�mid�mms�modem�mongodb�moz�ms-access�ms-appinstaller�ms-browser-extension�ms-calculator�ms-drive-to�ms-enrollment�ms-excel�ms-eyecontrolspeech�ms-gamebarservices�ms-gamingoverlay�ms-getoffice�ms-help�ms-infopath�ms-inputapp�ms-launchremotedesktop�ms-lockscreencomponent-config�ms-media-stream-id�ms-meetnow�ms-mixedrealitycapture�ms-mobileplans�ms-newsandinterests�ms-officeapp�ms-people�ms-personacard�ms-project�ms-powerpoint�ms-publisher�ms-recall�ms-remotedesktop�ms-remotedesktop-launch�ms-restoretabcompanion�ms-screenclip�ms-screensketch�ms-search�ms-search-repair�ms-secondary-screen-controller�ms-secondary-screen-setup�ms-settings�ms-settings-airplanemode�ms-settings-bluetooth�ms-settings-camera�ms-settings-cellular�ms-settings-cloudstorage�ms-settings-connectabledevices�ms-settings-displays-topology�ms-settings-emailandaccounts�ms-settings-language�ms-settings-location�ms-settings-lock�ms-settings-nfctransactions�ms-settings-notifications�ms-settings-power�ms-settings-privacy�ms-settings-proximity�ms-settings-screenrotation�ms-settings-wifi�ms-settings-workplace�ms-spd�ms-stickers�ms-sttoverlay�ms-transit-to�ms-useractivityset�ms-virtualtouchpad�ms-visio�ms-walk-to�ms-whiteboard�ms-whiteboard-cmd�ms-widgetboard�ms-widgets�ms-word�msnim�msrp�msrps�mss�mt�mtqp�mumble�mupdate�mvn�mvrp�mvrps�news�nfs�ni�nih�nntp�notes�num�ocf�oid�onenote�onenote-cmd�opaquelocktoken�openid�openpgp4fpr�otpauth�p1�pack�palm�paparazzi�payment�payto�pkcs11�platform�pop�pres�prospero�proxy�pwid�psyc�pttp�qb�query�quic-transport�redis�rediss�reload�res�resource�rmi�rsync�rtmfp�rtmp�rtsp�rtsps�rtspu�sarif�secondlife�secret-token�service�session�sftp�sgn�shc�shelter�sieve�simpleledger�simplex�sip�sips�skype�smb�smp�sms�smtp�snews�snmp�soap.beep�soap.beeps�soldat�spiffe�spotify�ssb�ssh�starknet�steam�stun�stuns�submit�svn�swh�swid�swidpath�tag�taler�teamspeak�teapot�teapots�tel�teliaeid�telnet�tftp�things�thismessage�thzp�tip�tn3270�tool�turn�turns�tv�udp�unreal�upt�urn�ut2004�uuid-in-package�v-event�vemmi�ventrilo�ves�videotex�vnc�view-source�vscode�vscode-insiders�vsls�w3�wais�web3�wcr�webcal�web+ap�wifi�wpid�ws�wss�wtai�wyciwyg�xcon�xcon-userid�xfire�xmlrpc.beep�xmlrpc.beeps�xmpp�xftp�xrcp�xri�ymsgr�z39.50�z39.50r�z39.50s
synapse/lib/autodoc.py CHANGED
@@ -286,11 +286,11 @@ def genCallsig(rtype):
286
286
  if defv is s_common.novalu:
287
287
  item = name
288
288
  elif defv is None:
289
- item = f'{name}=$lib.null'
289
+ item = f'{name}=(null)'
290
290
  elif defv is True:
291
- item = f'{name}=$lib.true'
291
+ item = f'{name}=(true)'
292
292
  elif defv is False:
293
- item = f'{name}=$lib.false'
293
+ item = f'{name}=(false)'
294
294
  elif isinstance(defv, str):
295
295
  item = f'{name}={defv}'
296
296
  elif isinstance(defv, int):
synapse/lib/base.py CHANGED
@@ -128,7 +128,7 @@ class Base:
128
128
 
129
129
  self.isfini = False
130
130
  self.anitted = True # For assertion purposes
131
- self.finievt = None
131
+ self.finievt = asyncio.Event()
132
132
  self.entered = False
133
133
 
134
134
  # hold a weak ref to other bases we should fini if they
@@ -431,10 +431,7 @@ class Base:
431
431
  self._syn_funcs.clear()
432
432
  self._fini_funcs.clear()
433
433
 
434
- fevt = self.finievt
435
-
436
- if fevt is not None:
437
- fevt.set()
434
+ self.finievt.set()
438
435
 
439
436
  return 0
440
437
 
@@ -468,13 +465,6 @@ class Base:
468
465
  base.waitfini(timeout=30)
469
466
 
470
467
  '''
471
-
472
- if self.isfini:
473
- return True
474
-
475
- if self.finievt is None:
476
- self.finievt = asyncio.Event()
477
-
478
468
  return await s_coro.event_wait(self.finievt, timeout)
479
469
 
480
470
  def schedCoro(self, coro):
synapse/lib/cell.py CHANGED
@@ -2711,6 +2711,12 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
2711
2711
  raise s_exc.BadArg(mesg=mesg, arg='path', valu=path)
2712
2712
  await self._streamBackupArchive(path, user, name)
2713
2713
 
2714
+ async def _removeStreamingBackup(self, path):
2715
+ logger.debug(f'Removing {path}')
2716
+ await s_coro.executor(shutil.rmtree, path, ignore_errors=True)
2717
+ logger.debug(f'Removed {path}')
2718
+ self.backupstreaming = False
2719
+
2714
2720
  async def iterNewBackupArchive(self, user, name=None, remove=False):
2715
2721
 
2716
2722
  if self.backupstreaming:
@@ -2728,23 +2734,13 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
2728
2734
  mesg = 'Backup with name already exists'
2729
2735
  raise s_exc.BadArg(mesg=mesg)
2730
2736
 
2731
- try:
2732
- await self.runBackup(name)
2733
- except Exception:
2734
- if remove:
2735
- logger.debug(f'Removing {path}')
2736
- await s_coro.executor(shutil.rmtree, path, ignore_errors=True)
2737
- logger.debug(f'Removed {path}')
2738
- raise
2739
-
2737
+ await self.runBackup(name)
2740
2738
  await self._streamBackupArchive(path, user, name)
2741
2739
 
2742
2740
  finally:
2743
2741
  if remove:
2744
- logger.debug(f'Removing {path}')
2745
- await s_coro.executor(shutil.rmtree, path, ignore_errors=True)
2746
- logger.debug(f'Removed {path}')
2747
- self.backupstreaming = False
2742
+ self.removetask = asyncio.create_task(self._removeStreamingBackup(path))
2743
+ await asyncio.shield(self.removetask)
2748
2744
 
2749
2745
  async def isUserAllowed(self, iden, perm, gateiden=None, default=False):
2750
2746
  user = self.auth.user(iden) # type: s_auth.User
synapse/lib/cli.py CHANGED
@@ -1,5 +1,4 @@
1
1
  import os
2
- import json
3
2
  import signal
4
3
  import asyncio
5
4
  import logging
@@ -18,6 +17,7 @@ import synapse.common as s_common
18
17
  import synapse.telepath as s_telepath
19
18
 
20
19
  import synapse.lib.base as s_base
20
+ import synapse.lib.json as s_json
21
21
  import synapse.lib.output as s_output
22
22
  import synapse.lib.parser as s_parser
23
23
  import synapse.lib.grammar as s_grammar
@@ -542,5 +542,5 @@ class CmdLocals(Cmd):
542
542
  ret[k] = v
543
543
  else:
544
544
  ret[k] = repr(v)
545
- mesg = json.dumps(ret, indent=2, sort_keys=True)
545
+ mesg = s_json.dumps(ret, indent=True, sort_keys=True).decode()
546
546
  self.printf(mesg)
synapse/lib/config.py CHANGED
@@ -1,6 +1,5 @@
1
1
  import os
2
2
  import copy
3
- import json
4
3
  import urllib
5
4
  import logging
6
5
  import argparse
@@ -12,6 +11,7 @@ import synapse.exc as s_exc
12
11
  import synapse.data as s_data
13
12
  import synapse.common as s_common
14
13
 
14
+ import synapse.lib.json as s_json
15
15
  import synapse.lib.hashitem as s_hashitem
16
16
 
17
17
  from fastjsonschema.exceptions import JsonSchemaValueException
@@ -44,7 +44,7 @@ def localSchemaRefHandler(uri):
44
44
  raise s_exc.NoSuchFile(mesg=f'Local JSON schema not found for {uri}.')
45
45
 
46
46
  with open(filename, 'r') as fp:
47
- return json.load(fp)
47
+ return s_json.load(fp)
48
48
 
49
49
  # This handlers dictionary is used by the jsonschema validator to attempt to
50
50
  # resolve schema '$ref' values locally from disk and will raise an exception
synapse/lib/encoding.py CHANGED
@@ -1,11 +1,12 @@
1
1
  import csv
2
- import json
3
2
  import regex
4
3
  import base64
5
4
  import codecs
6
5
  import xml.etree.ElementTree as x_etree
7
6
 
8
7
  import synapse.exc as s_exc
8
+
9
+ import synapse.lib.json as s_json
9
10
  import synapse.lib.msgpack as s_msgpack
10
11
 
11
12
  def _de_base64(item, **opts):
@@ -176,11 +177,11 @@ def _fmt_lines(fd, gest):
176
177
  yield line
177
178
 
178
179
  def _fmt_json(fd, info):
179
- yield json.loads(fd.read())
180
+ yield s_json.load(fd)
180
181
 
181
182
  def _fmt_jsonl(fd, info):
182
183
  for line in fd:
183
- yield json.loads(line)
184
+ yield s_json.loads(line)
184
185
 
185
186
  def _fmt_mpk(fd, info):
186
187
  yield from s_msgpack.iterfd(fd)
synapse/lib/httpapi.py CHANGED
@@ -1,4 +1,3 @@
1
- import json
2
1
  import base64
3
2
  import asyncio
4
3
  import logging
@@ -12,6 +11,7 @@ import synapse.exc as s_exc
12
11
  import synapse.common as s_common
13
12
 
14
13
  import synapse.lib.base as s_base
14
+ import synapse.lib.json as s_json
15
15
  import synapse.lib.msgpack as s_msgpack
16
16
 
17
17
  logger = logging.getLogger(__name__)
@@ -132,7 +132,7 @@ class HandlerBase:
132
132
 
133
133
  def loadJsonMesg(self, byts, validator=None):
134
134
  try:
135
- item = json.loads(byts)
135
+ item = s_json.loads(byts)
136
136
  if validator is not None:
137
137
  validator(item)
138
138
  return item
@@ -418,7 +418,7 @@ class HandlerBase:
418
418
  class WebSocket(HandlerBase, t_websocket.WebSocketHandler):
419
419
 
420
420
  async def xmit(self, name, **info):
421
- await self.write_message(json.dumps({'type': name, 'data': info}))
421
+ await self.write_message(s_json.dumps({'type': name, 'data': info}))
422
422
 
423
423
  async def _reqUserAllow(self, perm):
424
424
 
@@ -513,9 +513,7 @@ class StormNodesV1(StormHandler):
513
513
  await self.cell.boss.promote('storm', user=user, info=taskinfo)
514
514
 
515
515
  async for pode in view.iterStormPodes(query, opts=opts):
516
- self.write(json.dumps(pode))
517
- if jsonlines:
518
- self.write("\n")
516
+ self.write(s_json.dumps(pode, newline=jsonlines))
519
517
  await self.flush()
520
518
 
521
519
  class StormV1(StormHandler):
@@ -545,9 +543,7 @@ class StormV1(StormHandler):
545
543
  opts.setdefault('editformat', 'nodeedits')
546
544
 
547
545
  async for mesg in self.getCore().storm(query, opts=opts):
548
- self.write(json.dumps(mesg))
549
- if jsonlines:
550
- self.write("\n")
546
+ self.write(s_json.dumps(mesg, newline=jsonlines))
551
547
  await self.flush()
552
548
 
553
549
  class StormCallV1(StormHandler):
@@ -640,9 +636,9 @@ class BeholdSockV1(WebSocket):
640
636
 
641
637
  async def onInitMessage(self, byts):
642
638
  try:
643
- mesg = json.loads(byts)
639
+ mesg = s_json.loads(byts)
644
640
  if mesg.get('type') != 'call:init':
645
- raise s_exc.BadMesgFormat('Invalid initial message')
641
+ raise s_exc.BadMesgFormat(mesg='Invalid initial message')
646
642
 
647
643
  admin = await self.isUserAdmin()
648
644
  if not admin: