omdev 0.0.0.dev309__py3-none-any.whl → 0.0.0.dev311__py3-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.
- omdev/.manifests.json +12 -0
- omdev/ptk/__init__.py +5 -2
- omdev/ptk/confirm.py +54 -0
- omdev/ptk/markdown/markdown.py +6 -0
- omdev/scripts/pyproject.py +101 -0
- omdev/tools/antlr/__main__.py +11 -0
- omdev/tools/antlr/cli.py +62 -0
- omdev/{antlr → tools/antlr}/consts.py +1 -1
- omdev/tools/antlr/gen.py +187 -0
- omdev/tools/git/cli.py +16 -4
- {omdev-0.0.0.dev309.dist-info → omdev-0.0.0.dev311.dist-info}/METADATA +2 -2
- {omdev-0.0.0.dev309.dist-info → omdev-0.0.0.dev311.dist-info}/RECORD +17 -14
- omdev/antlr/gen.py +0 -114
- /omdev/{antlr → tools/antlr}/__init__.py +0 -0
- {omdev-0.0.0.dev309.dist-info → omdev-0.0.0.dev311.dist-info}/WHEEL +0 -0
- {omdev-0.0.0.dev309.dist-info → omdev-0.0.0.dev311.dist-info}/entry_points.txt +0 -0
- {omdev-0.0.0.dev309.dist-info → omdev-0.0.0.dev311.dist-info}/licenses/LICENSE +0 -0
- {omdev-0.0.0.dev309.dist-info → omdev-0.0.0.dev311.dist-info}/top_level.txt +0 -0
omdev/.manifests.json
CHANGED
@@ -290,6 +290,18 @@
|
|
290
290
|
}
|
291
291
|
}
|
292
292
|
},
|
293
|
+
{
|
294
|
+
"module": ".tools.antlr.__main__",
|
295
|
+
"attr": "_CLI_MODULE",
|
296
|
+
"file": "omdev/tools/antlr/__main__.py",
|
297
|
+
"line": 4,
|
298
|
+
"value": {
|
299
|
+
"$.cli.types.CliModule": {
|
300
|
+
"cmd_name": "antlr",
|
301
|
+
"mod_name": "omdev.tools.antlr.__main__"
|
302
|
+
}
|
303
|
+
}
|
304
|
+
},
|
293
305
|
{
|
294
306
|
"module": ".tools.cloc",
|
295
307
|
"attr": "_CLI_MODULE",
|
omdev/ptk/__init__.py
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
# ruff: noqa: F401
|
2
2
|
# flake8: noqa: F401
|
3
3
|
|
4
|
-
from prompt_toolkit import Application
|
5
|
-
from prompt_toolkit import prompt
|
4
|
+
from prompt_toolkit.application import Application
|
6
5
|
from prompt_toolkit.application import get_app
|
7
6
|
from prompt_toolkit.application import get_app_session
|
8
7
|
from prompt_toolkit.application import run_in_terminal
|
@@ -80,7 +79,9 @@ from prompt_toolkit.output import DummyOutput
|
|
80
79
|
from prompt_toolkit.output import Output
|
81
80
|
from prompt_toolkit.search import SearchDirection
|
82
81
|
from prompt_toolkit.selection import SelectionType
|
82
|
+
from prompt_toolkit.shortcuts import confirm
|
83
83
|
from prompt_toolkit.shortcuts import print_formatted_text
|
84
|
+
from prompt_toolkit.shortcuts import prompt
|
84
85
|
from prompt_toolkit.styles import BaseStyle
|
85
86
|
from prompt_toolkit.styles import DynamicStyle
|
86
87
|
from prompt_toolkit.styles import Style
|
@@ -95,3 +96,5 @@ from prompt_toolkit.widgets.toolbars import FormattedTextToolbar
|
|
95
96
|
from prompt_toolkit.widgets.toolbars import SearchToolbar
|
96
97
|
from prompt_toolkit.widgets.toolbars import SystemToolbar
|
97
98
|
from prompt_toolkit.widgets.toolbars import ValidationToolbar
|
99
|
+
|
100
|
+
from .confirm import strict_confirm
|
omdev/ptk/confirm.py
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
from prompt_toolkit.formatted_text import merge_formatted_text
|
2
|
+
from prompt_toolkit.key_binding import KeyBindings
|
3
|
+
from prompt_toolkit.key_binding import KeyPressEvent
|
4
|
+
from prompt_toolkit.shortcuts import PromptSession
|
5
|
+
|
6
|
+
from omlish import check
|
7
|
+
|
8
|
+
|
9
|
+
##
|
10
|
+
|
11
|
+
|
12
|
+
def create_strict_confirm_session(
|
13
|
+
message: str,
|
14
|
+
suffix: str = ' (y/n) ',
|
15
|
+
) -> PromptSession[str | bool]:
|
16
|
+
"""Create a `PromptSession` object for the 'confirm' function."""
|
17
|
+
|
18
|
+
bindings = KeyBindings()
|
19
|
+
|
20
|
+
@bindings.add('y')
|
21
|
+
@bindings.add('Y')
|
22
|
+
def yes(event: KeyPressEvent) -> None:
|
23
|
+
session.default_buffer.text = 'y'
|
24
|
+
event.app.exit(result=True)
|
25
|
+
|
26
|
+
@bindings.add('n')
|
27
|
+
@bindings.add('N')
|
28
|
+
def no(event: KeyPressEvent) -> None:
|
29
|
+
session.default_buffer.text = 'n'
|
30
|
+
event.app.exit(result=False)
|
31
|
+
|
32
|
+
complete_message = merge_formatted_text([message, suffix])
|
33
|
+
session: PromptSession[str | bool] = PromptSession(
|
34
|
+
complete_message,
|
35
|
+
key_bindings=bindings,
|
36
|
+
)
|
37
|
+
return session
|
38
|
+
|
39
|
+
|
40
|
+
def strict_confirm(message: str = 'Confirm?', suffix: str = ' (y/n) ') -> bool:
|
41
|
+
"""Display a confirmation prompt that returns True/False. Requires an explicit answer."""
|
42
|
+
|
43
|
+
while True:
|
44
|
+
session = create_strict_confirm_session(message, suffix)
|
45
|
+
ret = session.prompt()
|
46
|
+
|
47
|
+
if isinstance(ret, str):
|
48
|
+
check.empty(ret)
|
49
|
+
|
50
|
+
elif isinstance(ret, bool):
|
51
|
+
return ret
|
52
|
+
|
53
|
+
else:
|
54
|
+
raise TypeError(ret)
|
omdev/ptk/markdown/markdown.py
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
"""
|
2
|
+
TODO:
|
3
|
+
- accept pre-parsed tokens
|
4
|
+
- provide live view in this pkg
|
5
|
+
"""
|
1
6
|
import itertools
|
2
7
|
import typing as ta
|
3
8
|
|
@@ -36,6 +41,7 @@ class Markdown:
|
|
36
41
|
def __init__(
|
37
42
|
self,
|
38
43
|
markup: str,
|
44
|
+
*,
|
39
45
|
width: int | None = None,
|
40
46
|
strip_trailing_lines: bool = True,
|
41
47
|
) -> None:
|
omdev/scripts/pyproject.py
CHANGED
@@ -1010,29 +1010,37 @@ class TomlFlags:
|
|
1010
1010
|
def set(self, key: TomlKey, flag: int, *, recursive: bool) -> None: # noqa: A003
|
1011
1011
|
cont = self._flags
|
1012
1012
|
key_parent, key_stem = key[:-1], key[-1]
|
1013
|
+
|
1013
1014
|
for k in key_parent:
|
1014
1015
|
if k not in cont:
|
1015
1016
|
cont[k] = {'flags': set(), 'recursive_flags': set(), 'nested': {}}
|
1016
1017
|
cont = cont[k]['nested']
|
1018
|
+
|
1017
1019
|
if key_stem not in cont:
|
1018
1020
|
cont[key_stem] = {'flags': set(), 'recursive_flags': set(), 'nested': {}}
|
1021
|
+
|
1019
1022
|
cont[key_stem]['recursive_flags' if recursive else 'flags'].add(flag)
|
1020
1023
|
|
1021
1024
|
def is_(self, key: TomlKey, flag: int) -> bool:
|
1022
1025
|
if not key:
|
1023
1026
|
return False # document root has no flags
|
1027
|
+
|
1024
1028
|
cont = self._flags
|
1025
1029
|
for k in key[:-1]:
|
1026
1030
|
if k not in cont:
|
1027
1031
|
return False
|
1032
|
+
|
1028
1033
|
inner_cont = cont[k]
|
1029
1034
|
if flag in inner_cont['recursive_flags']:
|
1030
1035
|
return True
|
1036
|
+
|
1031
1037
|
cont = inner_cont['nested']
|
1038
|
+
|
1032
1039
|
key_stem = key[-1]
|
1033
1040
|
if key_stem in cont:
|
1034
1041
|
cont = cont[key_stem]
|
1035
1042
|
return flag in cont['flags'] or flag in cont['recursive_flags']
|
1043
|
+
|
1036
1044
|
return False
|
1037
1045
|
|
1038
1046
|
|
@@ -1050,24 +1058,31 @@ class TomlNestedDict:
|
|
1050
1058
|
access_lists: bool = True,
|
1051
1059
|
) -> dict:
|
1052
1060
|
cont: ta.Any = self.dict
|
1061
|
+
|
1053
1062
|
for k in key:
|
1054
1063
|
if k not in cont:
|
1055
1064
|
cont[k] = {}
|
1065
|
+
|
1056
1066
|
cont = cont[k]
|
1067
|
+
|
1057
1068
|
if access_lists and isinstance(cont, list):
|
1058
1069
|
cont = cont[-1]
|
1070
|
+
|
1059
1071
|
if not isinstance(cont, dict):
|
1060
1072
|
raise KeyError('There is no nest behind this key')
|
1073
|
+
|
1061
1074
|
return cont
|
1062
1075
|
|
1063
1076
|
def append_nest_to_list(self, key: TomlKey) -> None:
|
1064
1077
|
cont = self.get_or_create_nest(key[:-1])
|
1078
|
+
|
1065
1079
|
last_key = key[-1]
|
1066
1080
|
if last_key in cont:
|
1067
1081
|
list_ = cont[last_key]
|
1068
1082
|
if not isinstance(list_, list):
|
1069
1083
|
raise KeyError('An object other than list found behind this key')
|
1070
1084
|
list_.append({})
|
1085
|
+
|
1071
1086
|
else:
|
1072
1087
|
cont[last_key] = [{}]
|
1073
1088
|
|
@@ -1137,23 +1152,30 @@ class TomlParser:
|
|
1137
1152
|
char = self.src[self.pos]
|
1138
1153
|
except IndexError:
|
1139
1154
|
break
|
1155
|
+
|
1140
1156
|
if char == '\n':
|
1141
1157
|
self.pos += 1
|
1142
1158
|
continue
|
1159
|
+
|
1143
1160
|
if char in self.KEY_INITIAL_CHARS:
|
1144
1161
|
self.key_value_rule(header)
|
1145
1162
|
self.skip_chars(self.WS)
|
1163
|
+
|
1146
1164
|
elif char == '[':
|
1147
1165
|
try:
|
1148
1166
|
second_char: ta.Optional[str] = self.src[self.pos + 1]
|
1149
1167
|
except IndexError:
|
1150
1168
|
second_char = None
|
1169
|
+
|
1151
1170
|
self.flags.finalize_pending()
|
1171
|
+
|
1152
1172
|
if second_char == '[':
|
1153
1173
|
header = self.create_list_rule()
|
1154
1174
|
else:
|
1155
1175
|
header = self.create_dict_rule()
|
1176
|
+
|
1156
1177
|
self.skip_chars(self.WS)
|
1178
|
+
|
1157
1179
|
elif char != '#':
|
1158
1180
|
raise self.suffixed_err('Invalid statement')
|
1159
1181
|
|
@@ -1165,8 +1187,10 @@ class TomlParser:
|
|
1165
1187
|
char = self.src[self.pos]
|
1166
1188
|
except IndexError:
|
1167
1189
|
break
|
1190
|
+
|
1168
1191
|
if char != '\n':
|
1169
1192
|
raise self.suffixed_err('Expected newline or end of document after a statement')
|
1193
|
+
|
1170
1194
|
self.pos += 1
|
1171
1195
|
|
1172
1196
|
return self.data.dict
|
@@ -1195,7 +1219,9 @@ class TomlParser:
|
|
1195
1219
|
if not error_on.isdisjoint(self.src[self.pos:new_pos]):
|
1196
1220
|
while self.src[self.pos] not in error_on:
|
1197
1221
|
self.pos += 1
|
1222
|
+
|
1198
1223
|
raise self.suffixed_err(f'Found invalid character {self.src[self.pos]!r}')
|
1224
|
+
|
1199
1225
|
self.pos = new_pos
|
1200
1226
|
|
1201
1227
|
def skip_comment(self) -> None:
|
@@ -1203,6 +1229,7 @@ class TomlParser:
|
|
1203
1229
|
char: ta.Optional[str] = self.src[self.pos]
|
1204
1230
|
except IndexError:
|
1205
1231
|
char = None
|
1232
|
+
|
1206
1233
|
if char == '#':
|
1207
1234
|
self.pos += 1
|
1208
1235
|
self.skip_until(
|
@@ -1226,7 +1253,9 @@ class TomlParser:
|
|
1226
1253
|
|
1227
1254
|
if self.flags.is_(key, TomlFlags.EXPLICIT_NEST) or self.flags.is_(key, TomlFlags.FROZEN):
|
1228
1255
|
raise self.suffixed_err(f'Cannot declare {key} twice')
|
1256
|
+
|
1229
1257
|
self.flags.set(key, TomlFlags.EXPLICIT_NEST, recursive=False)
|
1258
|
+
|
1230
1259
|
try:
|
1231
1260
|
self.data.get_or_create_nest(key)
|
1232
1261
|
except KeyError:
|
@@ -1234,20 +1263,25 @@ class TomlParser:
|
|
1234
1263
|
|
1235
1264
|
if not self.src.startswith(']', self.pos):
|
1236
1265
|
raise self.suffixed_err("Expected ']' at the end of a table declaration")
|
1266
|
+
|
1237
1267
|
self.pos += 1
|
1238
1268
|
return key
|
1239
1269
|
|
1240
1270
|
def create_list_rule(self) -> TomlKey:
|
1241
1271
|
self.pos += 2 # Skip "[["
|
1242
1272
|
self.skip_chars(self.WS)
|
1273
|
+
|
1243
1274
|
key = self.parse_key()
|
1244
1275
|
|
1245
1276
|
if self.flags.is_(key, TomlFlags.FROZEN):
|
1246
1277
|
raise self.suffixed_err(f'Cannot mutate immutable namespace {key}')
|
1278
|
+
|
1247
1279
|
# Free the namespace now that it points to another empty list item...
|
1248
1280
|
self.flags.unset_all(key)
|
1281
|
+
|
1249
1282
|
# ...but this key precisely is still prohibited from table declaration
|
1250
1283
|
self.flags.set(key, TomlFlags.EXPLICIT_NEST, recursive=False)
|
1284
|
+
|
1251
1285
|
try:
|
1252
1286
|
self.data.append_nest_to_list(key)
|
1253
1287
|
except KeyError:
|
@@ -1255,6 +1289,7 @@ class TomlParser:
|
|
1255
1289
|
|
1256
1290
|
if not self.src.startswith(']]', self.pos):
|
1257
1291
|
raise self.suffixed_err("Expected ']]' at the end of an array declaration")
|
1292
|
+
|
1258
1293
|
self.pos += 2
|
1259
1294
|
return key
|
1260
1295
|
|
@@ -1268,6 +1303,7 @@ class TomlParser:
|
|
1268
1303
|
# Check that dotted key syntax does not redefine an existing table
|
1269
1304
|
if self.flags.is_(cont_key, TomlFlags.EXPLICIT_NEST):
|
1270
1305
|
raise self.suffixed_err(f'Cannot redefine namespace {cont_key}')
|
1306
|
+
|
1271
1307
|
# Containers in the relative path can't be opened with the table syntax or dotted key/value syntax in
|
1272
1308
|
# following table sections.
|
1273
1309
|
self.flags.add_pending(cont_key, TomlFlags.EXPLICIT_NEST)
|
@@ -1279,41 +1315,54 @@ class TomlParser:
|
|
1279
1315
|
nest = self.data.get_or_create_nest(abs_key_parent)
|
1280
1316
|
except KeyError:
|
1281
1317
|
raise self.suffixed_err('Cannot overwrite a value') from None
|
1318
|
+
|
1282
1319
|
if key_stem in nest:
|
1283
1320
|
raise self.suffixed_err('Cannot overwrite a value')
|
1321
|
+
|
1284
1322
|
# Mark inline table and array namespaces recursively immutable
|
1285
1323
|
if isinstance(value, (dict, list)):
|
1286
1324
|
self.flags.set(header + key, TomlFlags.FROZEN, recursive=True)
|
1325
|
+
|
1287
1326
|
nest[key_stem] = value
|
1288
1327
|
|
1289
1328
|
def parse_key_value_pair(self) -> ta.Tuple[TomlKey, ta.Any]:
|
1290
1329
|
key = self.parse_key()
|
1330
|
+
|
1291
1331
|
try:
|
1292
1332
|
char: ta.Optional[str] = self.src[self.pos]
|
1293
1333
|
except IndexError:
|
1294
1334
|
char = None
|
1335
|
+
|
1295
1336
|
if char != '=':
|
1296
1337
|
raise self.suffixed_err("Expected '=' after a key in a key/value pair")
|
1338
|
+
|
1297
1339
|
self.pos += 1
|
1298
1340
|
self.skip_chars(self.WS)
|
1341
|
+
|
1299
1342
|
value = self.parse_value()
|
1300
1343
|
return key, value
|
1301
1344
|
|
1302
1345
|
def parse_key(self) -> TomlKey:
|
1303
1346
|
key_part = self.parse_key_part()
|
1304
1347
|
key: TomlKey = (key_part,)
|
1348
|
+
|
1305
1349
|
self.skip_chars(self.WS)
|
1350
|
+
|
1306
1351
|
while True:
|
1307
1352
|
try:
|
1308
1353
|
char: ta.Optional[str] = self.src[self.pos]
|
1309
1354
|
except IndexError:
|
1310
1355
|
char = None
|
1356
|
+
|
1311
1357
|
if char != '.':
|
1312
1358
|
return key
|
1359
|
+
|
1313
1360
|
self.pos += 1
|
1314
1361
|
self.skip_chars(self.WS)
|
1362
|
+
|
1315
1363
|
key_part = self.parse_key_part()
|
1316
1364
|
key += (key_part,)
|
1365
|
+
|
1317
1366
|
self.skip_chars(self.WS)
|
1318
1367
|
|
1319
1368
|
def parse_key_part(self) -> str:
|
@@ -1321,14 +1370,18 @@ class TomlParser:
|
|
1321
1370
|
char: ta.Optional[str] = self.src[self.pos]
|
1322
1371
|
except IndexError:
|
1323
1372
|
char = None
|
1373
|
+
|
1324
1374
|
if char in self.BARE_KEY_CHARS:
|
1325
1375
|
start_pos = self.pos
|
1326
1376
|
self.skip_chars(self.BARE_KEY_CHARS)
|
1327
1377
|
return self.src[start_pos:self.pos]
|
1378
|
+
|
1328
1379
|
if char == "'":
|
1329
1380
|
return self.parse_literal_str()
|
1381
|
+
|
1330
1382
|
if char == '"':
|
1331
1383
|
return self.parse_one_line_basic_str()
|
1384
|
+
|
1332
1385
|
raise self.suffixed_err('Invalid initial character for a key part')
|
1333
1386
|
|
1334
1387
|
def parse_one_line_basic_str(self) -> str:
|
@@ -1343,6 +1396,7 @@ class TomlParser:
|
|
1343
1396
|
if self.src.startswith(']', self.pos):
|
1344
1397
|
self.pos += 1
|
1345
1398
|
return array
|
1399
|
+
|
1346
1400
|
while True:
|
1347
1401
|
val = self.parse_value()
|
1348
1402
|
array.append(val)
|
@@ -1352,11 +1406,14 @@ class TomlParser:
|
|
1352
1406
|
if c == ']':
|
1353
1407
|
self.pos += 1
|
1354
1408
|
return array
|
1409
|
+
|
1355
1410
|
if c != ',':
|
1356
1411
|
raise self.suffixed_err('Unclosed array')
|
1412
|
+
|
1357
1413
|
self.pos += 1
|
1358
1414
|
|
1359
1415
|
self.skip_comments_and_array_ws()
|
1416
|
+
|
1360
1417
|
if self.src.startswith(']', self.pos):
|
1361
1418
|
self.pos += 1
|
1362
1419
|
return array
|
@@ -1367,54 +1424,72 @@ class TomlParser:
|
|
1367
1424
|
flags = TomlFlags()
|
1368
1425
|
|
1369
1426
|
self.skip_chars(self.WS)
|
1427
|
+
|
1370
1428
|
if self.src.startswith('}', self.pos):
|
1371
1429
|
self.pos += 1
|
1372
1430
|
return nested_dict.dict
|
1431
|
+
|
1373
1432
|
while True:
|
1374
1433
|
key, value = self.parse_key_value_pair()
|
1375
1434
|
key_parent, key_stem = key[:-1], key[-1]
|
1435
|
+
|
1376
1436
|
if flags.is_(key, TomlFlags.FROZEN):
|
1377
1437
|
raise self.suffixed_err(f'Cannot mutate immutable namespace {key}')
|
1438
|
+
|
1378
1439
|
try:
|
1379
1440
|
nest = nested_dict.get_or_create_nest(key_parent, access_lists=False)
|
1380
1441
|
except KeyError:
|
1381
1442
|
raise self.suffixed_err('Cannot overwrite a value') from None
|
1443
|
+
|
1382
1444
|
if key_stem in nest:
|
1383
1445
|
raise self.suffixed_err(f'Duplicate inline table key {key_stem!r}')
|
1446
|
+
|
1384
1447
|
nest[key_stem] = value
|
1385
1448
|
self.skip_chars(self.WS)
|
1449
|
+
|
1386
1450
|
c = self.src[self.pos:self.pos + 1]
|
1387
1451
|
if c == '}':
|
1388
1452
|
self.pos += 1
|
1389
1453
|
return nested_dict.dict
|
1454
|
+
|
1390
1455
|
if c != ',':
|
1391
1456
|
raise self.suffixed_err('Unclosed inline table')
|
1457
|
+
|
1392
1458
|
if isinstance(value, (dict, list)):
|
1393
1459
|
flags.set(key, TomlFlags.FROZEN, recursive=True)
|
1460
|
+
|
1394
1461
|
self.pos += 1
|
1395
1462
|
self.skip_chars(self.WS)
|
1396
1463
|
|
1397
1464
|
def parse_basic_str_escape(self, multiline: bool = False) -> str:
|
1398
1465
|
escape_id = self.src[self.pos:self.pos + 2]
|
1399
1466
|
self.pos += 2
|
1467
|
+
|
1400
1468
|
if multiline and escape_id in {'\\ ', '\\\t', '\\\n'}:
|
1401
1469
|
# Skip whitespace until next non-whitespace character or end of the doc. Error if non-whitespace is found
|
1402
1470
|
# before newline.
|
1403
1471
|
if escape_id != '\\\n':
|
1404
1472
|
self.skip_chars(self.WS)
|
1473
|
+
|
1405
1474
|
try:
|
1406
1475
|
char = self.src[self.pos]
|
1407
1476
|
except IndexError:
|
1408
1477
|
return ''
|
1478
|
+
|
1409
1479
|
if char != '\n':
|
1410
1480
|
raise self.suffixed_err("Unescaped '\\' in a string")
|
1481
|
+
|
1411
1482
|
self.pos += 1
|
1483
|
+
|
1412
1484
|
self.skip_chars(self.WS_AND_NEWLINE)
|
1413
1485
|
return ''
|
1486
|
+
|
1414
1487
|
if escape_id == '\\u':
|
1415
1488
|
return self.parse_hex_char(4)
|
1489
|
+
|
1416
1490
|
if escape_id == '\\U':
|
1417
1491
|
return self.parse_hex_char(8)
|
1492
|
+
|
1418
1493
|
try:
|
1419
1494
|
return self.BASIC_STR_ESCAPE_REPLACEMENTS[escape_id]
|
1420
1495
|
except KeyError:
|
@@ -1429,12 +1504,16 @@ class TomlParser:
|
|
1429
1504
|
|
1430
1505
|
def parse_hex_char(self, hex_len: int) -> str:
|
1431
1506
|
hex_str = self.src[self.pos:self.pos + hex_len]
|
1507
|
+
|
1432
1508
|
if len(hex_str) != hex_len or not self.HEXDIGIT_CHARS.issuperset(hex_str):
|
1433
1509
|
raise self.suffixed_err('Invalid hex value')
|
1510
|
+
|
1434
1511
|
self.pos += hex_len
|
1435
1512
|
hex_int = int(hex_str, 16)
|
1513
|
+
|
1436
1514
|
if not self.is_unicode_scalar_value(hex_int):
|
1437
1515
|
raise self.suffixed_err('Escaped character is not a Unicode scalar value')
|
1516
|
+
|
1438
1517
|
return chr(hex_int)
|
1439
1518
|
|
1440
1519
|
def parse_literal_str(self) -> str:
|
@@ -1460,6 +1539,7 @@ class TomlParser:
|
|
1460
1539
|
)
|
1461
1540
|
result = self.src[start_pos:self.pos]
|
1462
1541
|
self.pos += 3
|
1542
|
+
|
1463
1543
|
else:
|
1464
1544
|
delim = '"'
|
1465
1545
|
result = self.parse_basic_str(multiline=True)
|
@@ -1467,9 +1547,11 @@ class TomlParser:
|
|
1467
1547
|
# Add at maximum two extra apostrophes/quotes if the end sequence is 4 or 5 chars long instead of just 3.
|
1468
1548
|
if not self.src.startswith(delim, self.pos):
|
1469
1549
|
return result
|
1550
|
+
|
1470
1551
|
self.pos += 1
|
1471
1552
|
if not self.src.startswith(delim, self.pos):
|
1472
1553
|
return result + delim
|
1554
|
+
|
1473
1555
|
self.pos += 1
|
1474
1556
|
return result + (delim * 2)
|
1475
1557
|
|
@@ -1480,6 +1562,7 @@ class TomlParser:
|
|
1480
1562
|
else:
|
1481
1563
|
error_on = self.ILLEGAL_BASIC_STR_CHARS
|
1482
1564
|
parse_escapes = self.parse_basic_str_escape
|
1565
|
+
|
1483
1566
|
result = ''
|
1484
1567
|
start_pos = self.pos
|
1485
1568
|
while True:
|
@@ -1487,25 +1570,31 @@ class TomlParser:
|
|
1487
1570
|
char = self.src[self.pos]
|
1488
1571
|
except IndexError:
|
1489
1572
|
raise self.suffixed_err('Unterminated string') from None
|
1573
|
+
|
1490
1574
|
if char == '"':
|
1491
1575
|
if not multiline:
|
1492
1576
|
end_pos = self.pos
|
1493
1577
|
self.pos += 1
|
1494
1578
|
return result + self.src[start_pos:end_pos]
|
1579
|
+
|
1495
1580
|
if self.src.startswith('"""', self.pos):
|
1496
1581
|
end_pos = self.pos
|
1497
1582
|
self.pos += 3
|
1498
1583
|
return result + self.src[start_pos:end_pos]
|
1584
|
+
|
1499
1585
|
self.pos += 1
|
1500
1586
|
continue
|
1587
|
+
|
1501
1588
|
if char == '\\':
|
1502
1589
|
result += self.src[start_pos:self.pos]
|
1503
1590
|
parsed_escape = parse_escapes()
|
1504
1591
|
result += parsed_escape
|
1505
1592
|
start_pos = self.pos
|
1506
1593
|
continue
|
1594
|
+
|
1507
1595
|
if char in error_on:
|
1508
1596
|
raise self.suffixed_err(f'Illegal character {char!r}')
|
1597
|
+
|
1509
1598
|
self.pos += 1
|
1510
1599
|
|
1511
1600
|
def parse_value(self) -> ta.Any: # noqa: C901
|
@@ -1533,6 +1622,7 @@ class TomlParser:
|
|
1533
1622
|
if self.src.startswith('true', self.pos):
|
1534
1623
|
self.pos += 4
|
1535
1624
|
return True
|
1625
|
+
|
1536
1626
|
if char == 'f':
|
1537
1627
|
if self.src.startswith('false', self.pos):
|
1538
1628
|
self.pos += 5
|
@@ -1553,8 +1643,10 @@ class TomlParser:
|
|
1553
1643
|
datetime_obj = self.match_to_datetime(datetime_match)
|
1554
1644
|
except ValueError as e:
|
1555
1645
|
raise self.suffixed_err('Invalid date or datetime') from e
|
1646
|
+
|
1556
1647
|
self.pos = datetime_match.end()
|
1557
1648
|
return datetime_obj
|
1649
|
+
|
1558
1650
|
localtime_match = self.RE_LOCALTIME.match(self.src, self.pos)
|
1559
1651
|
if localtime_match:
|
1560
1652
|
self.pos = localtime_match.end()
|
@@ -1572,6 +1664,7 @@ class TomlParser:
|
|
1572
1664
|
if first_three in {'inf', 'nan'}:
|
1573
1665
|
self.pos += 3
|
1574
1666
|
return self.parse_float(first_three)
|
1667
|
+
|
1575
1668
|
first_four = self.src[self.pos:self.pos + 4]
|
1576
1669
|
if first_four in {'-inf', '+inf', '-nan', '+nan'}:
|
1577
1670
|
self.pos += 4
|
@@ -1582,11 +1675,13 @@ class TomlParser:
|
|
1582
1675
|
def coord_repr(self, pos: TomlPos) -> str:
|
1583
1676
|
if pos >= len(self.src):
|
1584
1677
|
return 'end of document'
|
1678
|
+
|
1585
1679
|
line = self.src.count('\n', 0, pos) + 1
|
1586
1680
|
if line == 1:
|
1587
1681
|
column = pos + 1
|
1588
1682
|
else:
|
1589
1683
|
column = pos - self.src.rindex('\n', 0, pos)
|
1684
|
+
|
1590
1685
|
return f'line {line}, column {column}'
|
1591
1686
|
|
1592
1687
|
def suffixed_err(self, msg: str, *, pos: ta.Optional[TomlPos] = None) -> TomlDecodeError:
|
@@ -1653,11 +1748,16 @@ class TomlParser:
|
|
1653
1748
|
offset_hour_str,
|
1654
1749
|
offset_minute_str,
|
1655
1750
|
) = match.groups()
|
1751
|
+
|
1656
1752
|
year, month, day = int(year_str), int(month_str), int(day_str)
|
1753
|
+
|
1657
1754
|
if hour_str is None:
|
1658
1755
|
return datetime.date(year, month, day)
|
1756
|
+
|
1659
1757
|
hour, minute, sec = int(hour_str), int(minute_str), int(sec_str)
|
1758
|
+
|
1660
1759
|
micros = int(micros_str.ljust(6, '0')) if micros_str else 0
|
1760
|
+
|
1661
1761
|
if offset_sign_str:
|
1662
1762
|
tz: ta.Optional[datetime.tzinfo] = toml_cached_tz(
|
1663
1763
|
offset_hour_str, offset_minute_str, offset_sign_str,
|
@@ -1666,6 +1766,7 @@ class TomlParser:
|
|
1666
1766
|
tz = datetime.UTC
|
1667
1767
|
else: # local date-time
|
1668
1768
|
tz = None
|
1769
|
+
|
1669
1770
|
return datetime.datetime(year, month, day, hour, minute, sec, micros, tzinfo=tz)
|
1670
1771
|
|
1671
1772
|
@classmethod
|
omdev/tools/antlr/cli.py
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
import logging
|
2
|
+
import re
|
3
|
+
import subprocess
|
4
|
+
import sys
|
5
|
+
|
6
|
+
from omlish.argparse import all as ap
|
7
|
+
from omlish.logs import all as logs
|
8
|
+
|
9
|
+
from .consts import ANTLR_RUNTIME_PACKAGE
|
10
|
+
from .gen import GenPy
|
11
|
+
from .gen import get_jar_path
|
12
|
+
|
13
|
+
|
14
|
+
log = logging.getLogger(__name__)
|
15
|
+
|
16
|
+
|
17
|
+
##
|
18
|
+
|
19
|
+
|
20
|
+
class Cli(ap.Cli):
|
21
|
+
@ap.cmd()
|
22
|
+
def jar(self) -> None:
|
23
|
+
print(get_jar_path())
|
24
|
+
|
25
|
+
@ap.cmd()
|
26
|
+
def latest(self) -> None:
|
27
|
+
o, _ = subprocess.Popen(
|
28
|
+
[
|
29
|
+
sys.executable,
|
30
|
+
'-m', 'pip',
|
31
|
+
'index', 'versions',
|
32
|
+
ANTLR_RUNTIME_PACKAGE,
|
33
|
+
],
|
34
|
+
stdout=subprocess.PIPE,
|
35
|
+
).communicate()
|
36
|
+
tl = o.decode().splitlines()[0]
|
37
|
+
m = re.fullmatch(rf'{ANTLR_RUNTIME_PACKAGE} \((?P<version>[^)]+)\)', tl)
|
38
|
+
if m is None:
|
39
|
+
raise ValueError(f'Failed to parse version: {tl}')
|
40
|
+
v = m.groupdict()['version']
|
41
|
+
print(v)
|
42
|
+
|
43
|
+
#
|
44
|
+
|
45
|
+
@ap.cmd(
|
46
|
+
ap.arg('roots', nargs='+'),
|
47
|
+
)
|
48
|
+
def gen(self) -> None:
|
49
|
+
gp = GenPy(
|
50
|
+
self.args.roots,
|
51
|
+
)
|
52
|
+
gp.run()
|
53
|
+
|
54
|
+
|
55
|
+
def _main() -> None:
|
56
|
+
logs.configure_standard_logging(logging.INFO)
|
57
|
+
cli = Cli()
|
58
|
+
cli()
|
59
|
+
|
60
|
+
|
61
|
+
if __name__ == '__main__':
|
62
|
+
_main()
|
omdev/tools/antlr/gen.py
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
"""
|
2
|
+
TODO:
|
3
|
+
- mtime cmp
|
4
|
+
- parallelism
|
5
|
+
"""
|
6
|
+
import logging
|
7
|
+
import os.path
|
8
|
+
import re
|
9
|
+
import shutil
|
10
|
+
import subprocess
|
11
|
+
import typing as ta
|
12
|
+
|
13
|
+
from omlish import check
|
14
|
+
from omlish import lang
|
15
|
+
from omlish.os.paths import is_path_in_dir
|
16
|
+
|
17
|
+
from ...cache import data as dcache
|
18
|
+
from .consts import ANTLR_JAR_URL
|
19
|
+
from .consts import ANTLR_RUNTIME_VENDOR
|
20
|
+
|
21
|
+
|
22
|
+
log = logging.getLogger(__name__)
|
23
|
+
|
24
|
+
|
25
|
+
##
|
26
|
+
|
27
|
+
|
28
|
+
ANTLR_JAR_CACHE = dcache.UrlSpec(ANTLR_JAR_URL)
|
29
|
+
|
30
|
+
|
31
|
+
@lang.cached_function
|
32
|
+
def get_jar_path() -> str:
|
33
|
+
return dcache.default().get(ANTLR_JAR_CACHE)
|
34
|
+
|
35
|
+
|
36
|
+
##
|
37
|
+
|
38
|
+
|
39
|
+
def _find_dirs(*base_paths: str, filter: ta.Callable[[str], bool] = lambda _: True) -> ta.Sequence[str]: # noqa
|
40
|
+
return sorted(
|
41
|
+
os.path.join(dp, dn)
|
42
|
+
for base_path in base_paths
|
43
|
+
for dp, dns, fns in os.walk(base_path)
|
44
|
+
for dn in dns
|
45
|
+
if filter(dn)
|
46
|
+
)
|
47
|
+
|
48
|
+
|
49
|
+
def _find_files(*base_paths: str, filter: ta.Callable[[str], bool] = lambda _: True) -> ta.Sequence[str]: # noqa
|
50
|
+
return sorted(
|
51
|
+
os.path.join(dp, fn)
|
52
|
+
for base_path in base_paths
|
53
|
+
for dp, dns, fns in os.walk(base_path)
|
54
|
+
for fn in fns
|
55
|
+
if filter(fn)
|
56
|
+
)
|
57
|
+
|
58
|
+
|
59
|
+
class GenPy:
|
60
|
+
def __init__(
|
61
|
+
self,
|
62
|
+
root_dirs: str, # noqa
|
63
|
+
*,
|
64
|
+
out_subdir: str = '_antlr',
|
65
|
+
runtime_import: str = ANTLR_RUNTIME_VENDOR,
|
66
|
+
jar_path: str | None = None,
|
67
|
+
# parallelism: int | None = None,
|
68
|
+
) -> None:
|
69
|
+
super().__init__()
|
70
|
+
|
71
|
+
check.non_empty_str(out_subdir)
|
72
|
+
check.arg(not os.path.isabs(out_subdir) and '.' not in out_subdir and '/' not in out_subdir)
|
73
|
+
|
74
|
+
self._root_dirs = frozenset(check.non_empty_str(rd) for rd in check.not_isinstance(root_dirs, str))
|
75
|
+
self._out_subdir = out_subdir
|
76
|
+
self._runtime_import = runtime_import
|
77
|
+
self._given_jar_path = jar_path
|
78
|
+
|
79
|
+
#
|
80
|
+
|
81
|
+
def _rmtree(self, tgt: str) -> None: # noqa
|
82
|
+
if not any(is_path_in_dir(rd, tgt) for rd in self._root_dirs):
|
83
|
+
raise RuntimeError(f'Refusing to delete {tgt!r} outside of {self._root_dirs!r}')
|
84
|
+
shutil.rmtree(tgt)
|
85
|
+
|
86
|
+
#
|
87
|
+
|
88
|
+
@lang.cached_function
|
89
|
+
def jar_path(self) -> str:
|
90
|
+
if (gjp := self._given_jar_path) is not None:
|
91
|
+
return gjp
|
92
|
+
return get_jar_path()
|
93
|
+
|
94
|
+
#
|
95
|
+
|
96
|
+
def process_g4(self, g4_file: str) -> None:
|
97
|
+
ap = os.path.abspath(g4_file)
|
98
|
+
check.state(os.path.isfile(ap))
|
99
|
+
|
100
|
+
od = os.path.join(os.path.dirname(ap), self._out_subdir)
|
101
|
+
os.makedirs(od, exist_ok=True)
|
102
|
+
|
103
|
+
log.info('Compiling grammar %s', g4_file)
|
104
|
+
|
105
|
+
try:
|
106
|
+
subprocess.check_call([
|
107
|
+
'java',
|
108
|
+
'-jar', self.jar_path(),
|
109
|
+
'-Dlanguage=Python3',
|
110
|
+
'-visitor',
|
111
|
+
'-o', self._out_subdir,
|
112
|
+
os.path.basename(g4_file),
|
113
|
+
], cwd=os.path.dirname(ap))
|
114
|
+
|
115
|
+
except Exception: # noqa
|
116
|
+
log.exception('Exception in grammar %s', g4_file)
|
117
|
+
raise
|
118
|
+
|
119
|
+
def process_py(self, py_file: str) -> None:
|
120
|
+
ap = os.path.abspath(py_file)
|
121
|
+
with open(ap) as f:
|
122
|
+
in_lines = list(f)
|
123
|
+
|
124
|
+
pfp = py_file.split(os.sep)
|
125
|
+
arp = ANTLR_RUNTIME_VENDOR.split('.')
|
126
|
+
if (cpl := lang.common_prefix_len(pfp, arp)) > 0:
|
127
|
+
pkg_depth = len(os.path.normpath(py_file).split(os.path.sep))
|
128
|
+
antlr_imp = '.'.join([*([''] * (pkg_depth - cpl)), *arp[cpl:]])
|
129
|
+
else:
|
130
|
+
antlr_imp = ANTLR_RUNTIME_VENDOR
|
131
|
+
|
132
|
+
out_lines = [
|
133
|
+
'# type: ignore\n',
|
134
|
+
'# ruff: noqa\n',
|
135
|
+
'# flake8: noqa\n',
|
136
|
+
]
|
137
|
+
|
138
|
+
for l in in_lines:
|
139
|
+
l = re.sub(r'^(from antlr4)(.*)', rf'from {antlr_imp}\2', l)
|
140
|
+
out_lines.append(l)
|
141
|
+
|
142
|
+
with open(ap, 'w') as f:
|
143
|
+
f.write(''.join(out_lines))
|
144
|
+
|
145
|
+
def process_dir(self, dir: str) -> None: # noqa
|
146
|
+
log.info('Processing directory %s', dir)
|
147
|
+
|
148
|
+
ad = os.path.join(dir, self._out_subdir)
|
149
|
+
if os.path.exists(ad):
|
150
|
+
self._rmtree(ad)
|
151
|
+
|
152
|
+
for f in os.listdir(dir):
|
153
|
+
fp = os.path.join(dir, f)
|
154
|
+
if not os.path.isfile(fp) or not f.endswith('.g4'):
|
155
|
+
continue
|
156
|
+
|
157
|
+
self.process_g4(fp)
|
158
|
+
|
159
|
+
if not os.path.exists(ad):
|
160
|
+
return
|
161
|
+
|
162
|
+
ip = os.path.join(ad, '__init__.py')
|
163
|
+
check.state(not os.path.exists(ip))
|
164
|
+
|
165
|
+
for f in list(os.listdir(ad)):
|
166
|
+
fp = os.path.join(ad, f)
|
167
|
+
if not os.path.isfile(fp):
|
168
|
+
continue
|
169
|
+
|
170
|
+
if f.split('.')[-1] in ('interp', 'tokens'):
|
171
|
+
os.unlink(fp)
|
172
|
+
|
173
|
+
elif f != '__init__.py' and f.endswith('.py'):
|
174
|
+
self.process_py(fp)
|
175
|
+
|
176
|
+
with open(ip, 'w'):
|
177
|
+
pass
|
178
|
+
|
179
|
+
def run(self) -> None:
|
180
|
+
dns = _find_dirs(*self._root_dirs, filter=lambda dn: os.path.basename(dn) == '_antlr')
|
181
|
+
for dn in dns:
|
182
|
+
self._rmtree(dn)
|
183
|
+
|
184
|
+
fns = _find_files(*self._root_dirs, filter=lambda fn: fn.endswith('.g4'))
|
185
|
+
fds = {os.path.dirname(fn) for fn in fns}
|
186
|
+
for dn in sorted(fds):
|
187
|
+
self.process_dir(dn)
|
omdev/tools/git/cli.py
CHANGED
@@ -23,7 +23,6 @@ import dataclasses as dc
|
|
23
23
|
import logging
|
24
24
|
import os
|
25
25
|
import re
|
26
|
-
import sys
|
27
26
|
import typing as ta
|
28
27
|
import urllib.parse
|
29
28
|
|
@@ -380,6 +379,8 @@ class Cli(ap.Cli):
|
|
380
379
|
)
|
381
380
|
def update_submodule_branches(self) -> None:
|
382
381
|
def run_submodule(submodule: str, cwd: str | None) -> None:
|
382
|
+
log.info('Updating submodule %s', submodule)
|
383
|
+
|
383
384
|
submodule_path = submodule if cwd is None else os.path.join(cwd, submodule)
|
384
385
|
|
385
386
|
# Get the HEAD branch from origin
|
@@ -401,21 +402,32 @@ class Cli(ap.Cli):
|
|
401
402
|
subprocesses.check_call('git', 'checkout', head_branch, cwd=submodule_path)
|
402
403
|
subprocesses.check_call('git', 'pull', cwd=submodule_path)
|
403
404
|
|
405
|
+
failed: set[str] = set()
|
406
|
+
|
404
407
|
def run(cwd: str | None) -> None:
|
405
408
|
submodules = subprocesses.check_output(
|
406
409
|
'git', 'submodule', 'foreach', '-q', 'echo $name',
|
407
410
|
cwd=cwd,
|
408
411
|
).decode().strip().splitlines()
|
409
412
|
|
410
|
-
for submodule in submodules:
|
413
|
+
for submodule in sorted(submodules):
|
411
414
|
try:
|
412
415
|
run_submodule(submodule, cwd)
|
413
|
-
|
416
|
+
|
417
|
+
except Exception: # noqa
|
418
|
+
failed.add(submodule)
|
419
|
+
|
414
420
|
if self.args.on_error_resume_next:
|
415
|
-
|
421
|
+
log.exception('Failed to update submodule %s', submodule)
|
416
422
|
else:
|
417
423
|
raise
|
418
424
|
|
425
|
+
if failed:
|
426
|
+
log.error(
|
427
|
+
'The following submodules failed to update:\n%s',
|
428
|
+
'\n'.join([f' {f}' for f in failed]),
|
429
|
+
)
|
430
|
+
|
419
431
|
if not self.args.dir:
|
420
432
|
run(None)
|
421
433
|
else:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: omdev
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev311
|
4
4
|
Summary: omdev
|
5
5
|
Author: wrmsr
|
6
6
|
License: BSD-3-Clause
|
@@ -12,7 +12,7 @@ Classifier: Operating System :: OS Independent
|
|
12
12
|
Classifier: Operating System :: POSIX
|
13
13
|
Requires-Python: >=3.12
|
14
14
|
License-File: LICENSE
|
15
|
-
Requires-Dist: omlish==0.0.0.
|
15
|
+
Requires-Dist: omlish==0.0.0.dev311
|
16
16
|
Provides-Extra: all
|
17
17
|
Requires-Dist: black~=25.1; extra == "all"
|
18
18
|
Requires-Dist: pycparser~=2.22; extra == "all"
|
@@ -1,4 +1,4 @@
|
|
1
|
-
omdev/.manifests.json,sha256=
|
1
|
+
omdev/.manifests.json,sha256=upvKAe9ZFn6SkZusjneWtBKlCoEdy7WJSRP2Kq_ION0,11257
|
2
2
|
omdev/__about__.py,sha256=16xa_1BdZanTpZbkjAOQ11_x5kJcb1m1tKdvb06J7VI,1202
|
3
3
|
omdev/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
omdev/cmake.py,sha256=9rfSvFHPmKDj9ngvfDB2vK8O-xO_ZwUm7hMKLWA-yOw,4578
|
@@ -16,9 +16,6 @@ omdev/amalg/srcfiles.py,sha256=TKSYSfv78Wb8bcsQS3V76dV_H_MICPwzv06Ar09ew9U,3079
|
|
16
16
|
omdev/amalg/strip.py,sha256=dWQQ5WbtcebLi_PGjPzVYey2mJOnrRES8rkoUS8L52w,1444
|
17
17
|
omdev/amalg/types.py,sha256=BXXJI0VctKTsZv_wXiyMMq3-xShxZ1ak0wxXUK8n9_g,89
|
18
18
|
omdev/amalg/typing.py,sha256=oLlkCnnZQkyKM_xxqm9uxECjn9xj0c4MIwYxxItBdPY,2191
|
19
|
-
omdev/antlr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
|
-
omdev/antlr/consts.py,sha256=6iKuncbRXnGAqemNAceaR2mdFSs-8VbBV-pluM-8Bu4,284
|
21
|
-
omdev/antlr/gen.py,sha256=ZuDoh8ksIGlTSufEnJXogpk7gRVfmPirERdLx2nMWDo,3020
|
22
19
|
omdev/cache/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
23
20
|
omdev/cache/compute/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
21
|
omdev/cache/compute/cache.py,sha256=FA6tZWoQpE8D8Os3abdtfT90juzkqBmESjJE3WQXZtQ,3623
|
@@ -204,7 +201,8 @@ omdev/precheck/lite.py,sha256=rG6NYg0X85eN5UQ8-S7fagP5Ng2Nxwuf5Uh7uI8nQsE,4716
|
|
204
201
|
omdev/precheck/main.py,sha256=VEPdq9n8Yo_HiDqfCdHH1pj3xuJgOzrXie_vWoNbKqw,4303
|
205
202
|
omdev/precheck/manifests.py,sha256=4V4_mMh5ptW0jWBmq0nG3bsx3dyjejVs1ReEUoOz-JA,784
|
206
203
|
omdev/precheck/scripts.py,sha256=Br163NGbLY6Mjkxr9htdzqqsYWiEJbg9Gq-Glz6YQUI,1342
|
207
|
-
omdev/ptk/__init__.py,sha256=
|
204
|
+
omdev/ptk/__init__.py,sha256=IemfBhxxqZe1GeZ2_IMQzqWAB5j0XyARp_aajnonyKY,5142
|
205
|
+
omdev/ptk/confirm.py,sha256=kObMUAu-EZC0vdT9LLwtbNA6YLLNmn-Uy18SQTWBTb8,1471
|
208
206
|
omdev/ptk/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
209
207
|
omdev/ptk/apps/ncdu.py,sha256=KTbAgwhzcROOvq20VGN92UwMWcgkMMVOeFfpjZAsKUk,4561
|
210
208
|
omdev/ptk/markdown/LICENSE,sha256=oSmc9j-n23wTJUO0TbY8sIHrf9pFZUovFWfDL7D53IA,1489
|
@@ -212,7 +210,7 @@ omdev/ptk/markdown/__init__.py,sha256=Mj0KTyzdGVhkp79QoUiS6iJjnDz8c9chygcbVIgm1d
|
|
212
210
|
omdev/ptk/markdown/__main__.py,sha256=zaZuKy3-llEztkpoIAIzvspOyCsTJQI33ZuadvSHJKM,181
|
213
211
|
omdev/ptk/markdown/border.py,sha256=4gWpwTimurgJ_MjE-UKMCDMb4DnVcgFPfXutObQWOxk,1726
|
214
212
|
omdev/ptk/markdown/cli.py,sha256=FlV12qpyVWgpfeOzyFg9DlgLkss3rgCet_Jebs6_Xqo,537
|
215
|
-
omdev/ptk/markdown/markdown.py,sha256=
|
213
|
+
omdev/ptk/markdown/markdown.py,sha256=wRxCWSV2u71NP_MTi8A8vVLjZ1TmmaWUZMnvW468Ejc,12368
|
216
214
|
omdev/ptk/markdown/parser.py,sha256=UppwouvAYh3qzQMKL-BjcyqBIl2KHcocXlWiKFZ7cBA,990
|
217
215
|
omdev/ptk/markdown/styles.py,sha256=lc17zooXhff5_2tkqLsCmdq2b_rfSAehmHVR-8Lo2qk,777
|
218
216
|
omdev/ptk/markdown/tags.py,sha256=askGU252Zu8KxG2menVHZHXZ4fGbItgy0G4UW9F3mFI,6983
|
@@ -245,7 +243,7 @@ omdev/pyproject/resources/python.sh,sha256=rFaN4SiJ9hdLDXXsDTwugI6zsw6EPkgYMmtac
|
|
245
243
|
omdev/scripts/__init__.py,sha256=MKCvUAEQwsIvwLixwtPlpBqmkMXLCnjjXyAXvVpDwVk,91
|
246
244
|
omdev/scripts/ci.py,sha256=CagK-zEh6WFmuVvnYuBY9caZoAOC-TZtf-osDxu5aeE,353528
|
247
245
|
omdev/scripts/interp.py,sha256=tU8alYhrsaMQSKCyIQZi_ETvmpUjsO-VAV1obaRsC3E,152087
|
248
|
-
omdev/scripts/pyproject.py,sha256=
|
246
|
+
omdev/scripts/pyproject.py,sha256=nvBtNEhm8fwKIMK-fspkA0AP0xXQ_0N83gR_rSLuAM4,261514
|
249
247
|
omdev/scripts/slowcat.py,sha256=lssv4yrgJHiWfOiHkUut2p8E8Tq32zB-ujXESQxFFHY,2728
|
250
248
|
omdev/scripts/tmpexec.py,sha256=WTYcf56Tj2qjYV14AWmV8SfT0u6Y8eIU6cKgQRvEK3c,1442
|
251
249
|
omdev/tokens/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -266,9 +264,14 @@ omdev/tools/prof.py,sha256=hQakAsViJD4gLJpLLZnTkOqmTDAwM48Nx5q-O_aFlYM,1467
|
|
266
264
|
omdev/tools/qr.py,sha256=tm68lPwEAkEwIL2sUKPKBYfwwPtjVWG1DBZwur8_jY8,1737
|
267
265
|
omdev/tools/shadow.py,sha256=4E2ilxa16liIvQxvgU37ITkOMrP6ufShRQfeW7wwtRc,1697
|
268
266
|
omdev/tools/sqlrepl.py,sha256=wAjrfXNrRV63-NJCC2HlGQnFh7lUH0bHMnOjYotQqFs,5753
|
267
|
+
omdev/tools/antlr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
268
|
+
omdev/tools/antlr/__main__.py,sha256=7db8YIfCp4GoU-lW7jJJDiLQ6dDrd25M7gUv1AHGj4w,170
|
269
|
+
omdev/tools/antlr/cli.py,sha256=QeO5vSUJDL43lAa2EYsLnN-jZBcNOTwB1C9Ua_h7qoA,1228
|
270
|
+
omdev/tools/antlr/consts.py,sha256=4xH4jyNE5czXRWCn65jFF0MrAodMPe_kYMWpgMxWmpo,289
|
271
|
+
omdev/tools/antlr/gen.py,sha256=0k2o96gye00iMWlC7l6mVjUoYo9lfouGPBmA7_li23U,5085
|
269
272
|
omdev/tools/git/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
270
273
|
omdev/tools/git/__main__.py,sha256=gI87SBUgTkKUcUM-RtZWnei-UUDDqzbr5aPztb-gvbE,168
|
271
|
-
omdev/tools/git/cli.py,sha256=
|
274
|
+
omdev/tools/git/cli.py,sha256=NL30UkmWWoepNCClzeJTHwka3uGgPzGlsao_RDqVOek,14850
|
272
275
|
omdev/tools/git/consts.py,sha256=JuXivUNDkNhM4pe97icjRVAKM8cNRbrODquHINNKqOE,40
|
273
276
|
omdev/tools/git/messages.py,sha256=NWztIK0nAKJIOVzuVQcR_5LHZUgqyVkrOlpl7dFLMdU,2424
|
274
277
|
omdev/tools/json/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -282,9 +285,9 @@ omdev/tools/json/rendering.py,sha256=3HhdlKSetS6iK1tjF2aILzsl8Mb3D8wW92vYwGpRdVA
|
|
282
285
|
omdev/tools/pawk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
283
286
|
omdev/tools/pawk/__main__.py,sha256=VCqeRVnqT1RPEoIrqHFSu4PXVMg4YEgF4qCQm90-eRI,66
|
284
287
|
omdev/tools/pawk/pawk.py,sha256=zsEkfQX0jF5bn712uqPAyBSdJt2dno1LH2oeSMNfXQI,11424
|
285
|
-
omdev-0.0.0.
|
286
|
-
omdev-0.0.0.
|
287
|
-
omdev-0.0.0.
|
288
|
-
omdev-0.0.0.
|
289
|
-
omdev-0.0.0.
|
290
|
-
omdev-0.0.0.
|
288
|
+
omdev-0.0.0.dev311.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
289
|
+
omdev-0.0.0.dev311.dist-info/METADATA,sha256=0XnP0J8zsxD0fCdBIaARNi89_w4EQ6CmKLfkuh_STOA,1674
|
290
|
+
omdev-0.0.0.dev311.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
291
|
+
omdev-0.0.0.dev311.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
|
292
|
+
omdev-0.0.0.dev311.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
|
293
|
+
omdev-0.0.0.dev311.dist-info/RECORD,,
|
omdev/antlr/gen.py
DELETED
@@ -1,114 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
TODO:
|
3
|
-
- fix relpath in omlish/
|
4
|
-
- sem-bounded parallelism
|
5
|
-
"""
|
6
|
-
import argparse
|
7
|
-
import os.path
|
8
|
-
import re
|
9
|
-
import shutil
|
10
|
-
import subprocess
|
11
|
-
|
12
|
-
from omlish import check
|
13
|
-
from omlish import lang
|
14
|
-
|
15
|
-
from ..cache import data as dcache
|
16
|
-
from .consts import ANTLR_JAR_URL
|
17
|
-
from .consts import ANTLR_RUNTIME_VENDOR
|
18
|
-
|
19
|
-
|
20
|
-
ANTLR_JAR_CACHE = dcache.UrlSpec(ANTLR_JAR_URL)
|
21
|
-
|
22
|
-
|
23
|
-
class GenPy:
|
24
|
-
def __init__(
|
25
|
-
self,
|
26
|
-
dir: str, # noqa
|
27
|
-
*,
|
28
|
-
out_subdir: str = '_antlr',
|
29
|
-
runtime_import: str = ANTLR_RUNTIME_VENDOR,
|
30
|
-
) -> None:
|
31
|
-
super().__init__()
|
32
|
-
check.arg(not os.path.isabs(out_subdir) and '..' not in out_subdir)
|
33
|
-
self._dir = dir
|
34
|
-
self._out_subdir = out_subdir
|
35
|
-
self._runtime_import = runtime_import
|
36
|
-
self._out_dir = os.path.join(dir, out_subdir)
|
37
|
-
|
38
|
-
@lang.cached_function
|
39
|
-
def jar(self) -> str:
|
40
|
-
return dcache.default().get(ANTLR_JAR_CACHE)
|
41
|
-
|
42
|
-
def process_g4(self, g4_file: str) -> None:
|
43
|
-
subprocess.check_call([
|
44
|
-
'java',
|
45
|
-
'-jar', self.jar(),
|
46
|
-
'-Dlanguage=Python3',
|
47
|
-
'-visitor',
|
48
|
-
'-o', self._out_subdir,
|
49
|
-
g4_file,
|
50
|
-
], cwd=self._dir)
|
51
|
-
|
52
|
-
def process_py(self, py_file: str) -> None:
|
53
|
-
ap = os.path.join(self._out_dir, py_file)
|
54
|
-
with open(ap) as f:
|
55
|
-
in_lines = list(f)
|
56
|
-
|
57
|
-
out_lines = [
|
58
|
-
'# type: ignore\n',
|
59
|
-
'# ruff: noqa\n',
|
60
|
-
'# flake8: noqa\n',
|
61
|
-
]
|
62
|
-
for l in in_lines:
|
63
|
-
l = re.sub(r'^(from antlr4)(.*)', rf'from {self._runtime_import}\2', l)
|
64
|
-
out_lines.append(l)
|
65
|
-
|
66
|
-
with open(ap, 'w') as f:
|
67
|
-
f.write(''.join(out_lines))
|
68
|
-
|
69
|
-
def run(self) -> None:
|
70
|
-
if os.path.exists(self._out_dir):
|
71
|
-
shutil.rmtree(self._out_dir)
|
72
|
-
os.mkdir(self._out_dir)
|
73
|
-
with open(os.path.join(self._out_dir, '__init__.py'), 'w'):
|
74
|
-
pass
|
75
|
-
|
76
|
-
for f in os.listdir(self._dir):
|
77
|
-
fp = os.path.join(self._dir, f)
|
78
|
-
if not os.path.isfile(fp):
|
79
|
-
continue
|
80
|
-
if f.endswith('.g4'):
|
81
|
-
self.process_g4(f)
|
82
|
-
|
83
|
-
for f in list(os.listdir(self._out_dir)):
|
84
|
-
fp = os.path.join(self._out_dir, f)
|
85
|
-
if not os.path.isfile(fp):
|
86
|
-
continue
|
87
|
-
if f.split('.')[-1] in ('interp', 'tokens'):
|
88
|
-
os.unlink(fp)
|
89
|
-
elif f != '__init__.py' and f.endswith('.py'):
|
90
|
-
self.process_py(f)
|
91
|
-
|
92
|
-
|
93
|
-
def _main() -> None:
|
94
|
-
parser = argparse.ArgumentParser()
|
95
|
-
parser.add_argument('roots', nargs='*')
|
96
|
-
args = parser.parse_args()
|
97
|
-
|
98
|
-
if not args.roots:
|
99
|
-
parser.print_help()
|
100
|
-
return
|
101
|
-
|
102
|
-
base_dir = os.getcwd()
|
103
|
-
if not os.path.isfile(os.path.join(base_dir, 'pyproject.toml')):
|
104
|
-
raise RuntimeError('Must run from project root')
|
105
|
-
|
106
|
-
for root_dir in args.roots:
|
107
|
-
print(f'Processing {root_dir}')
|
108
|
-
GenPy(
|
109
|
-
root_dir,
|
110
|
-
).run()
|
111
|
-
|
112
|
-
|
113
|
-
if __name__ == '__main__':
|
114
|
-
_main()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|