synapse 2.196.0__py311-none-any.whl → 2.198.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/axon.py +3 -0
- synapse/common.py +3 -0
- synapse/cortex.py +13 -11
- synapse/cryotank.py +2 -2
- synapse/lib/aha.py +3 -0
- synapse/lib/ast.py +277 -165
- synapse/lib/auth.py +39 -11
- synapse/lib/cell.py +24 -6
- synapse/lib/config.py +3 -3
- synapse/lib/hive.py +2 -1
- synapse/lib/hiveauth.py +10 -1
- synapse/lib/jsonstor.py +6 -5
- synapse/lib/layer.py +6 -5
- synapse/lib/multislabseqn.py +2 -2
- synapse/lib/node.py +10 -4
- synapse/lib/parser.py +46 -21
- synapse/lib/schemas.py +491 -1
- synapse/lib/snap.py +68 -26
- synapse/lib/storm.lark +13 -11
- synapse/lib/storm.py +13 -395
- synapse/lib/storm_format.py +3 -2
- synapse/lib/stormlib/graph.py +0 -61
- synapse/lib/stormlib/index.py +52 -0
- synapse/lib/stormtypes.py +16 -5
- synapse/lib/task.py +13 -2
- synapse/lib/urlhelp.py +1 -1
- synapse/lib/version.py +2 -2
- synapse/models/doc.py +62 -0
- synapse/models/infotech.py +18 -0
- synapse/models/orgs.py +6 -4
- synapse/models/risk.py +9 -0
- synapse/models/syn.py +18 -2
- synapse/tests/files/stormpkg/badendpoints.yaml +7 -0
- synapse/tests/files/stormpkg/testpkg.yaml +8 -0
- synapse/tests/test_cortex.py +108 -0
- synapse/tests/test_datamodel.py +7 -0
- synapse/tests/test_lib_aha.py +12 -42
- synapse/tests/test_lib_ast.py +57 -0
- synapse/tests/test_lib_auth.py +143 -2
- synapse/tests/test_lib_boss.py +15 -6
- synapse/tests/test_lib_cell.py +43 -0
- synapse/tests/test_lib_grammar.py +54 -2
- synapse/tests/test_lib_lmdbslab.py +24 -0
- synapse/tests/test_lib_storm.py +20 -0
- synapse/tests/test_lib_stormlib_index.py +39 -0
- synapse/tests/test_lib_stormlib_macro.py +3 -3
- synapse/tests/test_lib_stormtypes.py +14 -2
- synapse/tests/test_lib_task.py +31 -13
- synapse/tests/test_model_doc.py +38 -0
- synapse/tests/test_model_infotech.py +13 -0
- synapse/tests/test_model_orgs.py +7 -0
- synapse/tests/test_model_risk.py +6 -0
- synapse/tests/test_model_syn.py +58 -0
- synapse/tests/test_tools_genpkg.py +10 -0
- synapse/tools/genpkg.py +2 -2
- synapse/tools/hive/load.py +1 -0
- {synapse-2.196.0.dist-info → synapse-2.198.0.dist-info}/METADATA +1 -1
- {synapse-2.196.0.dist-info → synapse-2.198.0.dist-info}/RECORD +61 -58
- {synapse-2.196.0.dist-info → synapse-2.198.0.dist-info}/LICENSE +0 -0
- {synapse-2.196.0.dist-info → synapse-2.198.0.dist-info}/WHEEL +0 -0
- {synapse-2.196.0.dist-info → synapse-2.198.0.dist-info}/top_level.txt +0 -0
synapse/lib/cell.py
CHANGED
|
@@ -62,7 +62,7 @@ import synapse.tools.backup as s_t_backup
|
|
|
62
62
|
|
|
63
63
|
logger = logging.getLogger(__name__)
|
|
64
64
|
|
|
65
|
-
NEXUS_VERSION = (2,
|
|
65
|
+
NEXUS_VERSION = (2, 198)
|
|
66
66
|
|
|
67
67
|
SLAB_MAP_SIZE = 128 * s_const.mebibyte
|
|
68
68
|
SSLCTX_CACHE_SIZE = 64
|
|
@@ -1625,16 +1625,34 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1625
1625
|
pass
|
|
1626
1626
|
|
|
1627
1627
|
async def setNexsVers(self, vers):
|
|
1628
|
-
if self.nexsvers <
|
|
1629
|
-
await self._push('nexs:vers:set',
|
|
1628
|
+
if self.nexsvers < vers:
|
|
1629
|
+
await self._push('nexs:vers:set', vers)
|
|
1630
1630
|
|
|
1631
1631
|
@s_nexus.Pusher.onPush('nexs:vers:set')
|
|
1632
1632
|
async def _setNexsVers(self, vers):
|
|
1633
1633
|
if vers > self.nexsvers:
|
|
1634
|
-
self.
|
|
1634
|
+
await self._migrNexsVers(vers)
|
|
1635
|
+
self.cellinfo.set('nexus:version', vers)
|
|
1635
1636
|
self.nexsvers = vers
|
|
1636
1637
|
await self.configNexsVers()
|
|
1637
1638
|
|
|
1639
|
+
async def _migrNexsVers(self, newvers):
|
|
1640
|
+
if self.nexsvers < (2, 198) and newvers >= (2, 198) and self.conf.get('auth:ctor') is None:
|
|
1641
|
+
# This "migration" will lock all archived users. Once the nexus version is bumped to
|
|
1642
|
+
# >=2.198, then the bottom-half nexus handler for user:info (Auth._setUserInfo()) will
|
|
1643
|
+
# begin rejecting unlock requests for archived users.
|
|
1644
|
+
|
|
1645
|
+
authkv = self.slab.getSafeKeyVal('auth')
|
|
1646
|
+
userkv = authkv.getSubKeyVal('user:info:')
|
|
1647
|
+
|
|
1648
|
+
for iden, info in userkv.items():
|
|
1649
|
+
if info.get('archived') and not info.get('locked'):
|
|
1650
|
+
info['locked'] = True
|
|
1651
|
+
userkv.set(iden, info)
|
|
1652
|
+
|
|
1653
|
+
# Clear the auth caches so the changes get picked up by the already running auth subsystem
|
|
1654
|
+
self.auth.clearAuthCache()
|
|
1655
|
+
|
|
1638
1656
|
async def configNexsVers(self):
|
|
1639
1657
|
for meth, orig in self.nexspatches:
|
|
1640
1658
|
setattr(self, meth, orig)
|
|
@@ -4478,7 +4496,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
4478
4496
|
|
|
4479
4497
|
for task in self.boss.ps():
|
|
4480
4498
|
|
|
4481
|
-
item = task.
|
|
4499
|
+
item = task.packv2()
|
|
4482
4500
|
item['service'] = self.ahasvcname
|
|
4483
4501
|
|
|
4484
4502
|
yield item
|
|
@@ -4500,7 +4518,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
4500
4518
|
|
|
4501
4519
|
task = self.boss.get(iden)
|
|
4502
4520
|
if task is not None:
|
|
4503
|
-
item = task.
|
|
4521
|
+
item = task.packv2()
|
|
4504
4522
|
item['service'] = self.ahasvcname
|
|
4505
4523
|
return item
|
|
4506
4524
|
|
synapse/lib/config.py
CHANGED
|
@@ -32,16 +32,16 @@ def localSchemaRefHandler(uri):
|
|
|
32
32
|
try:
|
|
33
33
|
parts = urllib.parse.urlparse(uri)
|
|
34
34
|
except ValueError:
|
|
35
|
-
raise s_exc.BadUrl(f'Malformed URI: {uri}.') from None
|
|
35
|
+
raise s_exc.BadUrl(mesg=f'Malformed URI: {uri}.') from None
|
|
36
36
|
|
|
37
37
|
filename = s_data.path('jsonschemas', parts.hostname, *parts.path.split('/'))
|
|
38
38
|
|
|
39
39
|
# Check for path traversal. Unlikely, but still check
|
|
40
40
|
if not filename.startswith(s_data.path('jsonschemas', parts.hostname)):
|
|
41
|
-
raise s_exc.BadArg(f'Path traversal in schema URL: {uri}.')
|
|
41
|
+
raise s_exc.BadArg(mesg=f'Path traversal in schema URL: {uri}.')
|
|
42
42
|
|
|
43
43
|
if not os.path.exists(filename) or not os.path.isfile(filename):
|
|
44
|
-
raise s_exc.NoSuchFile(f'Local JSON schema not found for {uri}.')
|
|
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
47
|
return json.load(fp)
|
synapse/lib/hive.py
CHANGED
|
@@ -424,7 +424,7 @@ class Hive(s_nexus.Pusher, s_telepath.Aware):
|
|
|
424
424
|
return node.valu
|
|
425
425
|
|
|
426
426
|
async def getTeleApi(self, link, mesg, path):
|
|
427
|
-
|
|
427
|
+
s_common.deprecated('Hive.getTeleApi', curv='2.198.0', eolv='2.199.0')
|
|
428
428
|
auth = await self.getHiveAuth()
|
|
429
429
|
|
|
430
430
|
if not self.conf.get('auth:en'):
|
|
@@ -759,6 +759,7 @@ def iterpath(path):
|
|
|
759
759
|
yield path[:i + 1]
|
|
760
760
|
|
|
761
761
|
async def openurl(url, **opts):
|
|
762
|
+
s_common.deprecated('synapse.lib.hive.openurl()', curv='2.198.0', eolv='2.199.0')
|
|
762
763
|
prox = await s_telepath.openurl(url, **opts)
|
|
763
764
|
return await TeleHive.anit(prox)
|
|
764
765
|
|
synapse/lib/hiveauth.py
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
# pragma: no cover
|
|
2
|
+
|
|
3
|
+
###
|
|
4
|
+
### THIS WHOLE MODULE IS DEPRECATED AND EXPECTED TO BE REMOVED O/A v2.198.0
|
|
5
|
+
###
|
|
6
|
+
|
|
1
7
|
import logging
|
|
2
8
|
import dataclasses
|
|
3
9
|
|
|
@@ -30,12 +36,13 @@ reqValidRules = s_config.getJsValidator({
|
|
|
30
36
|
|
|
31
37
|
def getShadow(passwd): # pragma: no cover
|
|
32
38
|
'''This API is deprecated.'''
|
|
33
|
-
s_common.deprecated('hiveauth.getShadow()', curv='2.110.0')
|
|
39
|
+
s_common.deprecated('hiveauth.getShadow()', curv='2.110.0', eolv='2.199.0')
|
|
34
40
|
salt = s_common.guid()
|
|
35
41
|
hashed = s_common.guid((salt, passwd))
|
|
36
42
|
return (salt, hashed)
|
|
37
43
|
|
|
38
44
|
def textFromRule(rule):
|
|
45
|
+
s_common.deprecated('hiveauth.textFromRule()', curv='2.198.0', eolv='2.199.0') # pragma: no cover
|
|
39
46
|
text = '.'.join(rule[1])
|
|
40
47
|
if not rule[0]:
|
|
41
48
|
text = '!' + text
|
|
@@ -43,6 +50,7 @@ def textFromRule(rule):
|
|
|
43
50
|
|
|
44
51
|
@dataclasses.dataclass(slots=True)
|
|
45
52
|
class _allowedReason:
|
|
53
|
+
s_common.deprecated('hiveauth._allowedReason()', curv='2.198.0', eolv='2.199.0')
|
|
46
54
|
value: Union[bool | None]
|
|
47
55
|
default: bool = False
|
|
48
56
|
isadmin: bool = False
|
|
@@ -135,6 +143,7 @@ class Auth(s_nexus.Pusher):
|
|
|
135
143
|
Args:
|
|
136
144
|
node (HiveNode): The root of the persistent storage for auth
|
|
137
145
|
'''
|
|
146
|
+
s_common.deprecated('Auth.__anit__()', curv='2.198.0', eolv='2.199.0')
|
|
138
147
|
# Derive an iden from the parent
|
|
139
148
|
iden = 'auth:' + ':'.join(node.full)
|
|
140
149
|
await s_nexus.Pusher.__anit__(self, iden, nexsroot=nexsroot)
|
synapse/lib/jsonstor.py
CHANGED
|
@@ -46,7 +46,7 @@ class JsonStor(s_base.Base):
|
|
|
46
46
|
self.dirty.pop(buid, None)
|
|
47
47
|
await asyncio.sleep(0)
|
|
48
48
|
|
|
49
|
-
def _incRefObj(self, buid, valu=1):
|
|
49
|
+
async def _incRefObj(self, buid, valu=1):
|
|
50
50
|
|
|
51
51
|
refs = 0
|
|
52
52
|
|
|
@@ -62,6 +62,7 @@ class JsonStor(s_base.Base):
|
|
|
62
62
|
# remove the meta entries
|
|
63
63
|
for lkey, byts in self.slab.scanByPref(buid, db=self.metadb):
|
|
64
64
|
self.slab.pop(lkey, db=self.metadb)
|
|
65
|
+
await asyncio.sleep(0)
|
|
65
66
|
|
|
66
67
|
# remove the item data
|
|
67
68
|
self.slab.pop(buid, db=self.itemdb)
|
|
@@ -88,7 +89,7 @@ class JsonStor(s_base.Base):
|
|
|
88
89
|
|
|
89
90
|
oldb = self.slab.replace(pkey, buid, db=self.pathdb)
|
|
90
91
|
if oldb is not None:
|
|
91
|
-
self._incRefObj(oldb, -1)
|
|
92
|
+
await self._incRefObj(oldb, -1)
|
|
92
93
|
|
|
93
94
|
self.slab.put(buid + b'refs', s_msgpack.en(1), db=self.metadb)
|
|
94
95
|
|
|
@@ -124,7 +125,7 @@ class JsonStor(s_base.Base):
|
|
|
124
125
|
pkey = self._pathToPkey(path)
|
|
125
126
|
buid = self.slab.pop(pkey, db=self.pathdb)
|
|
126
127
|
if buid is not None:
|
|
127
|
-
self._incRefObj(buid, valu=-1)
|
|
128
|
+
await self._incRefObj(buid, valu=-1)
|
|
128
129
|
|
|
129
130
|
async def setPathLink(self, srcpath, dstpath):
|
|
130
131
|
'''
|
|
@@ -140,9 +141,9 @@ class JsonStor(s_base.Base):
|
|
|
140
141
|
|
|
141
142
|
oldb = self.slab.pop(srcpkey, db=self.pathdb)
|
|
142
143
|
if oldb is not None:
|
|
143
|
-
self._incRefObj(oldb, valu=-1)
|
|
144
|
+
await self._incRefObj(oldb, valu=-1)
|
|
144
145
|
|
|
145
|
-
self._incRefObj(buid, valu=1)
|
|
146
|
+
await self._incRefObj(buid, valu=1)
|
|
146
147
|
self.slab.put(srcpkey, buid, db=self.pathdb)
|
|
147
148
|
|
|
148
149
|
async def getPathObjProp(self, path, prop):
|
synapse/lib/layer.py
CHANGED
|
@@ -3543,9 +3543,8 @@ class Layer(s_nexus.Pusher):
|
|
|
3543
3543
|
if self.nodeDelHook is not None:
|
|
3544
3544
|
self.nodeDelHook()
|
|
3545
3545
|
|
|
3546
|
-
self._wipeNodeData(buid)
|
|
3547
|
-
|
|
3548
|
-
self._delNodeEdges(buid)
|
|
3546
|
+
await self._wipeNodeData(buid)
|
|
3547
|
+
await self._delNodeEdges(buid)
|
|
3549
3548
|
|
|
3550
3549
|
self.buidcache.pop(buid, None)
|
|
3551
3550
|
|
|
@@ -3957,13 +3956,14 @@ class Layer(s_nexus.Pusher):
|
|
|
3957
3956
|
for _, lval in self.layrslab.scanByDups(verb.encode(), db=self.byverb):
|
|
3958
3957
|
yield (s_common.ehex(lval[:32]), verb, s_common.ehex(lval[32:]))
|
|
3959
3958
|
|
|
3960
|
-
def _delNodeEdges(self, buid):
|
|
3959
|
+
async def _delNodeEdges(self, buid):
|
|
3961
3960
|
for lkey, n2buid in self.layrslab.scanByPref(buid, db=self.edgesn1):
|
|
3962
3961
|
venc = lkey[32:]
|
|
3963
3962
|
self.layrslab.delete(venc, buid + n2buid, db=self.byverb)
|
|
3964
3963
|
self.layrslab.delete(lkey, n2buid, db=self.edgesn1)
|
|
3965
3964
|
self.layrslab.delete(n2buid + venc, buid, db=self.edgesn2)
|
|
3966
3965
|
self.layrslab.delete(buid + n2buid, venc, db=self.edgesn1n2)
|
|
3966
|
+
await asyncio.sleep(0)
|
|
3967
3967
|
|
|
3968
3968
|
def getStorIndx(self, stortype, valu):
|
|
3969
3969
|
|
|
@@ -4473,7 +4473,7 @@ class Layer(s_nexus.Pusher):
|
|
|
4473
4473
|
|
|
4474
4474
|
await self.waitfini(1)
|
|
4475
4475
|
|
|
4476
|
-
def _wipeNodeData(self, buid):
|
|
4476
|
+
async def _wipeNodeData(self, buid):
|
|
4477
4477
|
'''
|
|
4478
4478
|
Remove all node data for a buid
|
|
4479
4479
|
'''
|
|
@@ -4482,6 +4482,7 @@ class Layer(s_nexus.Pusher):
|
|
|
4482
4482
|
buid = lkey[:32]
|
|
4483
4483
|
self.dataslab.delete(lkey, db=self.nodedata)
|
|
4484
4484
|
self.dataslab.delete(abrv, buid, db=self.dataname)
|
|
4485
|
+
await asyncio.sleep(0)
|
|
4485
4486
|
|
|
4486
4487
|
async def getModelVers(self):
|
|
4487
4488
|
return self.layrinfo.get('model:version', (-1, -1, -1))
|
synapse/lib/multislabseqn.py
CHANGED
|
@@ -150,7 +150,7 @@ class MultiSlabSeqn(s_base.Base):
|
|
|
150
150
|
firstidx = firstitem[0] # might not match the separately stored first index due to culling
|
|
151
151
|
|
|
152
152
|
if firstidx < fnstartidx:
|
|
153
|
-
raise s_exc.BadCoreStore('Multislab: filename inconsistent with contents')
|
|
153
|
+
raise s_exc.BadCoreStore(mesg='Multislab: filename inconsistent with contents')
|
|
154
154
|
|
|
155
155
|
lastidx = seqn.index() - 1
|
|
156
156
|
|
|
@@ -161,7 +161,7 @@ class MultiSlabSeqn(s_base.Base):
|
|
|
161
161
|
self.firstindx = lowindx
|
|
162
162
|
|
|
163
163
|
if self.firstindx > self.indx:
|
|
164
|
-
raise s_exc.BadCoreStore('Invalid firstindx value')
|
|
164
|
+
raise s_exc.BadCoreStore(mesg='Invalid firstindx value')
|
|
165
165
|
|
|
166
166
|
await self._initTailSlab(fnstartidx)
|
|
167
167
|
|
synapse/lib/node.py
CHANGED
|
@@ -63,18 +63,24 @@ class Node:
|
|
|
63
63
|
def __repr__(self):
|
|
64
64
|
return f'Node{{{self.pack()}}}'
|
|
65
65
|
|
|
66
|
-
async def addEdge(self, verb, n2iden):
|
|
66
|
+
async def addEdge(self, verb, n2iden, extra=None):
|
|
67
67
|
if self.form.isrunt:
|
|
68
68
|
mesg = f'Edges cannot be used with runt nodes: {self.form.full}'
|
|
69
|
-
|
|
69
|
+
exc = s_exc.IsRuntForm(mesg=mesg, form=self.form.full)
|
|
70
|
+
if extra is not None:
|
|
71
|
+
exc = extra(exc)
|
|
72
|
+
raise exc
|
|
70
73
|
|
|
71
74
|
async with self.snap.getNodeEditor(self) as editor:
|
|
72
75
|
return await editor.addEdge(verb, n2iden)
|
|
73
76
|
|
|
74
|
-
async def delEdge(self, verb, n2iden):
|
|
77
|
+
async def delEdge(self, verb, n2iden, extra=None):
|
|
75
78
|
if self.form.isrunt:
|
|
76
79
|
mesg = f'Edges cannot be used with runt nodes: {self.form.full}'
|
|
77
|
-
|
|
80
|
+
exc = s_exc.IsRuntForm(mesg=mesg, form=self.form.full)
|
|
81
|
+
if extra is not None:
|
|
82
|
+
exc = extra(exc)
|
|
83
|
+
raise exc
|
|
78
84
|
|
|
79
85
|
async with self.snap.getNodeEditor(self) as editor:
|
|
80
86
|
return await editor.delEdge(verb, n2iden)
|
synapse/lib/parser.py
CHANGED
|
@@ -6,6 +6,7 @@ import lark # type: ignore
|
|
|
6
6
|
import regex # type: ignore
|
|
7
7
|
|
|
8
8
|
import synapse.exc as s_exc
|
|
9
|
+
import synapse.common as s_common
|
|
9
10
|
|
|
10
11
|
import synapse.lib.ast as s_ast
|
|
11
12
|
import synapse.lib.coro as s_coro
|
|
@@ -72,6 +73,7 @@ terminalEnglishMap = {
|
|
|
72
73
|
'LSQB': '[',
|
|
73
74
|
'MCASEBARE': 'case multi-value',
|
|
74
75
|
'MODSET': '+= or -=',
|
|
76
|
+
'MODSETMULTI': '++= or --=',
|
|
75
77
|
'NONQUOTEWORD': 'unquoted value',
|
|
76
78
|
'NOT': 'not',
|
|
77
79
|
'NULL': 'null',
|
|
@@ -92,8 +94,8 @@ terminalEnglishMap = {
|
|
|
92
94
|
'TRY': 'try',
|
|
93
95
|
'TRIPLEQUOTEDSTRING': 'triple-quoted string',
|
|
94
96
|
'TRYSET': '?=',
|
|
95
|
-
'
|
|
96
|
-
'
|
|
97
|
+
'TRYMODSET': '?+= or ?-=',
|
|
98
|
+
'TRYMODSETMULTI': '?++= or ?--=',
|
|
97
99
|
'UNIVNAME': 'universal property',
|
|
98
100
|
'UNSET': 'unset',
|
|
99
101
|
'EXPRUNIVNAME': 'universal property',
|
|
@@ -158,7 +160,7 @@ class AstConverter(lark.Transformer):
|
|
|
158
160
|
|
|
159
161
|
# Keep the original text for error printing and weird subquery argv parsing
|
|
160
162
|
self.text = text
|
|
161
|
-
self.texthash =
|
|
163
|
+
self.texthash = s_common.queryhash(text)
|
|
162
164
|
|
|
163
165
|
def metaToAstInfo(self, meta, isterm=False):
|
|
164
166
|
if isinstance(meta, lark.tree.Meta) and meta.empty:
|
|
@@ -248,9 +250,14 @@ class AstConverter(lark.Transformer):
|
|
|
248
250
|
@lark.v_args(meta=True)
|
|
249
251
|
def embedquery(self, meta, kids):
|
|
250
252
|
assert len(kids) == 1
|
|
251
|
-
astinfo = self.
|
|
252
|
-
|
|
253
|
-
|
|
253
|
+
astinfo = AstInfo(self.text,
|
|
254
|
+
meta.start_pos + 2, meta.end_pos - 1,
|
|
255
|
+
meta.line, meta.end_line,
|
|
256
|
+
meta.column, meta.end_column, False)
|
|
257
|
+
|
|
258
|
+
kids[0].astinfo = astinfo
|
|
259
|
+
|
|
260
|
+
return s_ast.EmbedQuery(astinfo, kids[0].getAstText(), kids=kids)
|
|
254
261
|
|
|
255
262
|
@lark.v_args(meta=True)
|
|
256
263
|
def funccall(self, meta, kids):
|
|
@@ -489,18 +496,28 @@ class Parser:
|
|
|
489
496
|
Convert lark exception to synapse BadSyntax exception
|
|
490
497
|
'''
|
|
491
498
|
mesg = regex.split('[\n]', str(e))[0]
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
499
|
+
soff = eoff = len(self.text)
|
|
500
|
+
sline = eline = None
|
|
501
|
+
scol = ecol = None
|
|
495
502
|
token = None
|
|
496
503
|
if isinstance(e, lark.exceptions.UnexpectedToken):
|
|
497
504
|
expected = sorted(set(terminalEnglishMap[t] for t in e.expected))
|
|
498
|
-
at = e.pos_in_stream
|
|
499
|
-
line = e.line
|
|
500
|
-
column = e.column
|
|
501
505
|
token = e.token.value
|
|
502
|
-
|
|
503
|
-
|
|
506
|
+
soff = e.pos_in_stream
|
|
507
|
+
eoff = soff + len(token)
|
|
508
|
+
|
|
509
|
+
lines = token.splitlines()
|
|
510
|
+
sline = e.line
|
|
511
|
+
eline = sline + len(lines) - 1
|
|
512
|
+
|
|
513
|
+
scol = e.column
|
|
514
|
+
if len(lines) > 1:
|
|
515
|
+
ecol = len(lines[-1])
|
|
516
|
+
else:
|
|
517
|
+
ecol = scol + len(token)
|
|
518
|
+
|
|
519
|
+
valu = terminalEnglishMap.get(e.token.type, token)
|
|
520
|
+
mesg = f"Unexpected token '{valu}' at line {sline}, column {scol}," \
|
|
504
521
|
f' expecting one of: {", ".join(expected)}'
|
|
505
522
|
|
|
506
523
|
elif isinstance(e, lark.exceptions.VisitError):
|
|
@@ -514,16 +531,23 @@ class Parser:
|
|
|
514
531
|
elif isinstance(e, lark.exceptions.UnexpectedCharacters): # pragma: no cover
|
|
515
532
|
expected = sorted(set(terminalEnglishMap[t] for t in e.allowed))
|
|
516
533
|
mesg += f'. Expecting one of: {", ".join(expected)}'
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
534
|
+
soff = eoff = e.pos_in_stream
|
|
535
|
+
sline = eline = e.line
|
|
536
|
+
scol = ecol = e.column
|
|
520
537
|
elif isinstance(e, lark.exceptions.UnexpectedEOF): # pragma: no cover
|
|
521
538
|
expected = sorted(set(terminalEnglishMap[t] for t in e.expected))
|
|
522
539
|
mesg += ' ' + ', '.join(expected)
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
540
|
+
sline = eline = e.line
|
|
541
|
+
scol = ecol = e.column
|
|
542
|
+
|
|
543
|
+
highlight = {
|
|
544
|
+
'hash': s_common.queryhash(self.text),
|
|
545
|
+
'lines': (sline, eline),
|
|
546
|
+
'columns': (scol, ecol),
|
|
547
|
+
'offsets': (soff, eoff),
|
|
548
|
+
}
|
|
549
|
+
return s_exc.BadSyntax(at=soff, text=self.text, mesg=mesg, line=sline,
|
|
550
|
+
column=scol, token=token, highlight=highlight)
|
|
527
551
|
|
|
528
552
|
def eval(self):
|
|
529
553
|
try:
|
|
@@ -661,6 +685,7 @@ ruleClassMap = {
|
|
|
661
685
|
'editpropdel': lambda astinfo, kids: s_ast.EditPropDel(astinfo, kids[1:]),
|
|
662
686
|
'editpropset': s_ast.EditPropSet,
|
|
663
687
|
'editcondpropset': s_ast.EditCondPropSet,
|
|
688
|
+
'editpropsetmulti': s_ast.EditPropSetMulti,
|
|
664
689
|
'edittagadd': s_ast.EditTagAdd,
|
|
665
690
|
'edittagdel': lambda astinfo, kids: s_ast.EditTagDel(astinfo, kids[1:]),
|
|
666
691
|
'edittagpropset': s_ast.EditTagPropSet,
|