python2ts 1.1.0 → 1.3.0
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.
- package/dist/{chunk-65ZOMVMA.js → chunk-LNOL3BMB.js} +377 -55
- package/dist/cli/index.js +1 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -2
- package/package.json +5 -2
- package/dist/chunk-65ZOMVMA.js.map +0 -1
- package/dist/cli/index.js.map +0 -1
- package/dist/index.js.map +0 -1
|
@@ -214,7 +214,48 @@ var PYTHON_TO_JS_NAMES = {
|
|
|
214
214
|
// core module
|
|
215
215
|
// ============================================================================
|
|
216
216
|
floordiv: "floorDiv",
|
|
217
|
-
divmod: "divMod"
|
|
217
|
+
divmod: "divMod",
|
|
218
|
+
// ============================================================================
|
|
219
|
+
// hashlib module
|
|
220
|
+
// ============================================================================
|
|
221
|
+
pbkdf2_hmac: "pbkdf2Hmac",
|
|
222
|
+
compare_digest: "compareDigest",
|
|
223
|
+
file_digest: "fileDigest",
|
|
224
|
+
new: "newHash",
|
|
225
|
+
// ============================================================================
|
|
226
|
+
// pathlib module (Path methods)
|
|
227
|
+
// ============================================================================
|
|
228
|
+
read_text: "readText",
|
|
229
|
+
write_text: "writeText",
|
|
230
|
+
read_bytes: "readBytes",
|
|
231
|
+
write_bytes: "writeBytes",
|
|
232
|
+
is_file: "isFile",
|
|
233
|
+
is_dir: "isDir",
|
|
234
|
+
is_symlink: "isSymlink",
|
|
235
|
+
symlink_to: "symlinkTo",
|
|
236
|
+
link_to: "linkTo",
|
|
237
|
+
// ============================================================================
|
|
238
|
+
// shutil module
|
|
239
|
+
// ============================================================================
|
|
240
|
+
copy2: "copy2",
|
|
241
|
+
copytree: "copytree",
|
|
242
|
+
rmtree: "rmtree",
|
|
243
|
+
disk_usage: "diskUsage",
|
|
244
|
+
copymode: "copyMode",
|
|
245
|
+
copystat: "copyStat",
|
|
246
|
+
copyfile: "copyFile",
|
|
247
|
+
get_terminal_size: "getTerminalSize",
|
|
248
|
+
// ============================================================================
|
|
249
|
+
// tempfile module
|
|
250
|
+
// ============================================================================
|
|
251
|
+
mkstemp: "mkstemp",
|
|
252
|
+
mkdtemp: "mkdtemp",
|
|
253
|
+
gettempdir: "getTempDir",
|
|
254
|
+
// ============================================================================
|
|
255
|
+
// glob module
|
|
256
|
+
// ============================================================================
|
|
257
|
+
iglob: "iglob",
|
|
258
|
+
rglob: "rglob"
|
|
218
259
|
};
|
|
219
260
|
function toJsName(pythonName) {
|
|
220
261
|
return PYTHON_TO_JS_NAMES[pythonName] ?? pythonName;
|
|
@@ -253,6 +294,23 @@ function declareVariable(ctx, name) {
|
|
|
253
294
|
currentScope.add(name);
|
|
254
295
|
}
|
|
255
296
|
}
|
|
297
|
+
function stripOuterParens(code) {
|
|
298
|
+
const trimmed = code.trim();
|
|
299
|
+
if (trimmed.startsWith("(") && trimmed.endsWith(")")) {
|
|
300
|
+
const inner = trimmed.slice(1, -1);
|
|
301
|
+
if (/(?<![!=<>])=(?!=)/.test(inner)) {
|
|
302
|
+
return code;
|
|
303
|
+
}
|
|
304
|
+
let depth = 0;
|
|
305
|
+
for (let i = 0; i < trimmed.length; i++) {
|
|
306
|
+
if (trimmed[i] === "(") depth++;
|
|
307
|
+
else if (trimmed[i] === ")") depth--;
|
|
308
|
+
if (depth === 0 && i < trimmed.length - 1) return code;
|
|
309
|
+
}
|
|
310
|
+
return inner;
|
|
311
|
+
}
|
|
312
|
+
return code;
|
|
313
|
+
}
|
|
256
314
|
function containsYield(node) {
|
|
257
315
|
if (node.name === "YieldStatement" || node.name === "YieldExpression") {
|
|
258
316
|
return true;
|
|
@@ -395,7 +453,7 @@ function transformPythonType(node, ctx) {
|
|
|
395
453
|
}
|
|
396
454
|
}
|
|
397
455
|
function extractTypeAnnotation(typeDef, ctx) {
|
|
398
|
-
if (
|
|
456
|
+
if (typeDef?.name !== "TypeDef") return null;
|
|
399
457
|
const children = getChildren(typeDef);
|
|
400
458
|
const typeNode = children.find((c) => c.name !== ":" && c.name !== "->");
|
|
401
459
|
if (typeNode) {
|
|
@@ -405,7 +463,7 @@ function extractTypeAnnotation(typeDef, ctx) {
|
|
|
405
463
|
}
|
|
406
464
|
function extractTypeModifiers(typeDef, ctx) {
|
|
407
465
|
const result = { isFinal: false, isClassVar: false };
|
|
408
|
-
if (
|
|
466
|
+
if (typeDef?.name !== "TypeDef") return result;
|
|
409
467
|
const children = getChildren(typeDef);
|
|
410
468
|
const typeNode = children.find((c) => c.name !== ":" && c.name !== "->");
|
|
411
469
|
if (!typeNode) return result;
|
|
@@ -461,7 +519,7 @@ function isDocstringNode(node, ctx) {
|
|
|
461
519
|
if (node.name !== "ExpressionStatement") return false;
|
|
462
520
|
const children = getChildren(node);
|
|
463
521
|
const firstChild = children[0];
|
|
464
|
-
if (
|
|
522
|
+
if (firstChild?.name !== "String") return false;
|
|
465
523
|
const text = getNodeText(firstChild, ctx.source);
|
|
466
524
|
return text.startsWith('"""') || text.startsWith("'''");
|
|
467
525
|
}
|
|
@@ -544,7 +602,7 @@ function parseDocstring(content) {
|
|
|
544
602
|
descriptionLines.push(trimmed);
|
|
545
603
|
break;
|
|
546
604
|
case "params": {
|
|
547
|
-
const googleMatch =
|
|
605
|
+
const googleMatch = /^(\w+)\s*(?:\([^)]*\))?\s*:\s*(.*)$/.exec(trimmed);
|
|
548
606
|
if (googleMatch) {
|
|
549
607
|
flushParam();
|
|
550
608
|
currentParamName = googleMatch[1] ?? "";
|
|
@@ -572,7 +630,7 @@ function parseDocstring(content) {
|
|
|
572
630
|
break;
|
|
573
631
|
}
|
|
574
632
|
case "throws": {
|
|
575
|
-
const throwsMatch =
|
|
633
|
+
const throwsMatch = /^(\w+)\s*:\s*(.*)$/.exec(trimmed);
|
|
576
634
|
if (throwsMatch) {
|
|
577
635
|
flushThrows();
|
|
578
636
|
currentThrowsType = throwsMatch[1] ?? "Error";
|
|
@@ -1026,7 +1084,7 @@ function isChainedComparison(node) {
|
|
|
1026
1084
|
if (node.name !== "BinaryExpression") return false;
|
|
1027
1085
|
const children = getChildren(node);
|
|
1028
1086
|
const op = children[1];
|
|
1029
|
-
if (
|
|
1087
|
+
if (op?.name !== "CompareOp") return false;
|
|
1030
1088
|
return true;
|
|
1031
1089
|
}
|
|
1032
1090
|
function extractRightOperand(node, ctx) {
|
|
@@ -1076,7 +1134,7 @@ function transformConditionalExpression(node, ctx) {
|
|
|
1076
1134
|
const condition = exprs[1];
|
|
1077
1135
|
const falseExpr = exprs[2];
|
|
1078
1136
|
if (trueExpr && condition && falseExpr) {
|
|
1079
|
-
const condCode = transformNode(condition, ctx);
|
|
1137
|
+
const condCode = stripOuterParens(transformNode(condition, ctx));
|
|
1080
1138
|
const trueCode = transformNode(trueExpr, ctx);
|
|
1081
1139
|
const falseCode = transformNode(falseExpr, ctx);
|
|
1082
1140
|
return `(${condCode} ? ${trueCode} : ${falseCode})`;
|
|
@@ -1418,6 +1476,52 @@ function transformCallExpression(node, ctx) {
|
|
|
1418
1476
|
case "capwords":
|
|
1419
1477
|
ctx.usesRuntime.add("string/capWords");
|
|
1420
1478
|
return `capWords(${args})`;
|
|
1479
|
+
// glob module - async functions (direct import)
|
|
1480
|
+
case "glob":
|
|
1481
|
+
ctx.usesRuntime.add("glob/glob");
|
|
1482
|
+
return `await glob(${args})`;
|
|
1483
|
+
case "iglob":
|
|
1484
|
+
ctx.usesRuntime.add("glob/iglob");
|
|
1485
|
+
return `await iglob(${args})`;
|
|
1486
|
+
case "rglob":
|
|
1487
|
+
ctx.usesRuntime.add("glob/rglob");
|
|
1488
|
+
return `await rglob(${args})`;
|
|
1489
|
+
// shutil module - async functions (direct import)
|
|
1490
|
+
case "copy":
|
|
1491
|
+
ctx.usesRuntime.add("shutil/copy");
|
|
1492
|
+
return `await copy(${args})`;
|
|
1493
|
+
case "copy2":
|
|
1494
|
+
ctx.usesRuntime.add("shutil/copy2");
|
|
1495
|
+
return `await copy2(${args})`;
|
|
1496
|
+
case "copytree":
|
|
1497
|
+
ctx.usesRuntime.add("shutil/copytree");
|
|
1498
|
+
return `await copytree(${args})`;
|
|
1499
|
+
case "move":
|
|
1500
|
+
ctx.usesRuntime.add("shutil/move");
|
|
1501
|
+
return `await move(${args})`;
|
|
1502
|
+
case "rmtree":
|
|
1503
|
+
ctx.usesRuntime.add("shutil/rmtree");
|
|
1504
|
+
return `await rmtree(${args})`;
|
|
1505
|
+
case "which":
|
|
1506
|
+
ctx.usesRuntime.add("shutil/which");
|
|
1507
|
+
return `await which(${args})`;
|
|
1508
|
+
// tempfile module - async functions (direct import)
|
|
1509
|
+
case "mkstemp":
|
|
1510
|
+
ctx.usesRuntime.add("tempfile/mkstemp");
|
|
1511
|
+
return `await mkstemp(${args})`;
|
|
1512
|
+
case "mkdtemp":
|
|
1513
|
+
ctx.usesRuntime.add("tempfile/mkdtemp");
|
|
1514
|
+
return `await mkdtemp(${args})`;
|
|
1515
|
+
case "NamedTemporaryFile":
|
|
1516
|
+
ctx.usesRuntime.add("tempfile/NamedTemporaryFile");
|
|
1517
|
+
return `await NamedTemporaryFile.create(${args})`;
|
|
1518
|
+
case "TemporaryDirectory":
|
|
1519
|
+
ctx.usesRuntime.add("tempfile/TemporaryDirectory");
|
|
1520
|
+
return `await TemporaryDirectory.create(${args})`;
|
|
1521
|
+
// pathlib module
|
|
1522
|
+
case "Path":
|
|
1523
|
+
ctx.usesRuntime.add("pathlib/Path");
|
|
1524
|
+
return `new Path(${args})`;
|
|
1421
1525
|
/* v8 ignore next 3 -- pass-through for user-defined functions @preserve */
|
|
1422
1526
|
default:
|
|
1423
1527
|
return `${transformNode(callee, ctx)}(${args})`;
|
|
@@ -1436,9 +1540,10 @@ function transformModuleCall(calleeName, args, ctx) {
|
|
|
1436
1540
|
inf: "inf",
|
|
1437
1541
|
nan: "nan"
|
|
1438
1542
|
};
|
|
1439
|
-
|
|
1543
|
+
const mathConstant = mathConstants[funcName];
|
|
1544
|
+
if (mathConstant !== void 0) {
|
|
1440
1545
|
ctx.usesRuntime.add(`math/${funcName}`);
|
|
1441
|
-
return
|
|
1546
|
+
return mathConstant;
|
|
1442
1547
|
}
|
|
1443
1548
|
ctx.usesRuntime.add(`math/${funcName}`);
|
|
1444
1549
|
return `${funcName}(${args})`;
|
|
@@ -1453,14 +1558,45 @@ function transformModuleCall(calleeName, args, ctx) {
|
|
|
1453
1558
|
return `${funcName}(${args})`;
|
|
1454
1559
|
}
|
|
1455
1560
|
if (moduleName === "os") {
|
|
1561
|
+
const asyncPathFuncs = [
|
|
1562
|
+
"exists",
|
|
1563
|
+
"isfile",
|
|
1564
|
+
"isdir",
|
|
1565
|
+
"islink",
|
|
1566
|
+
"realpath",
|
|
1567
|
+
"getsize",
|
|
1568
|
+
"getmtime",
|
|
1569
|
+
"getatime",
|
|
1570
|
+
"getctime"
|
|
1571
|
+
];
|
|
1572
|
+
const asyncOsFuncs = [
|
|
1573
|
+
"listdir",
|
|
1574
|
+
"mkdir",
|
|
1575
|
+
"makedirs",
|
|
1576
|
+
"remove",
|
|
1577
|
+
"unlink",
|
|
1578
|
+
"rmdir",
|
|
1579
|
+
"removedirs",
|
|
1580
|
+
"rename",
|
|
1581
|
+
"renames",
|
|
1582
|
+
"replace",
|
|
1583
|
+
"walk",
|
|
1584
|
+
"stat"
|
|
1585
|
+
];
|
|
1456
1586
|
if (funcName.startsWith("path.")) {
|
|
1457
1587
|
const pathFuncName = funcName.slice(5);
|
|
1458
1588
|
const jsPathFunc = toJsName(pathFuncName);
|
|
1459
1589
|
ctx.usesRuntime.add("os/path");
|
|
1590
|
+
if (asyncPathFuncs.includes(pathFuncName.toLowerCase())) {
|
|
1591
|
+
return `await path.${jsPathFunc}(${args})`;
|
|
1592
|
+
}
|
|
1460
1593
|
return `path.${jsPathFunc}(${args})`;
|
|
1461
1594
|
}
|
|
1462
1595
|
const jsName = toJsName(funcName);
|
|
1463
1596
|
ctx.usesRuntime.add(`os/${jsName}`);
|
|
1597
|
+
if (asyncOsFuncs.includes(funcName.toLowerCase())) {
|
|
1598
|
+
return `await ${jsName}(${args})`;
|
|
1599
|
+
}
|
|
1464
1600
|
return `${jsName}(${args})`;
|
|
1465
1601
|
}
|
|
1466
1602
|
if (moduleName === "datetime") {
|
|
@@ -1501,6 +1637,67 @@ function transformModuleCall(calleeName, args, ctx) {
|
|
|
1501
1637
|
}
|
|
1502
1638
|
return `${funcName}(${args})`;
|
|
1503
1639
|
}
|
|
1640
|
+
if (moduleName === "hashlib") {
|
|
1641
|
+
const jsName = toJsName(funcName);
|
|
1642
|
+
ctx.usesRuntime.add(`hashlib/${jsName}`);
|
|
1643
|
+
if (["pbkdf2_hmac", "scrypt", "compare_digest", "file_digest"].includes(funcName)) {
|
|
1644
|
+
const asyncJsName = toJsName(funcName);
|
|
1645
|
+
return `await ${asyncJsName}(${args})`;
|
|
1646
|
+
}
|
|
1647
|
+
return `${jsName}(${args})`;
|
|
1648
|
+
}
|
|
1649
|
+
if (moduleName === "shutil") {
|
|
1650
|
+
const asyncShutilFuncs = [
|
|
1651
|
+
"copy",
|
|
1652
|
+
"copy2",
|
|
1653
|
+
"copytree",
|
|
1654
|
+
"move",
|
|
1655
|
+
"rmtree",
|
|
1656
|
+
"which",
|
|
1657
|
+
"disk_usage",
|
|
1658
|
+
"copymode",
|
|
1659
|
+
"copystat",
|
|
1660
|
+
"copyfile"
|
|
1661
|
+
];
|
|
1662
|
+
const jsName = toJsName(funcName);
|
|
1663
|
+
ctx.usesRuntime.add(`shutil/${jsName}`);
|
|
1664
|
+
if (asyncShutilFuncs.includes(funcName.toLowerCase())) {
|
|
1665
|
+
return `await ${jsName}(${args})`;
|
|
1666
|
+
}
|
|
1667
|
+
return `${jsName}(${args})`;
|
|
1668
|
+
}
|
|
1669
|
+
if (moduleName === "glob") {
|
|
1670
|
+
const asyncGlobFuncs = ["glob", "iglob", "rglob"];
|
|
1671
|
+
const jsName = toJsName(funcName);
|
|
1672
|
+
ctx.usesRuntime.add(`glob/${jsName}`);
|
|
1673
|
+
if (asyncGlobFuncs.includes(funcName.toLowerCase())) {
|
|
1674
|
+
return `await ${jsName}(${args})`;
|
|
1675
|
+
}
|
|
1676
|
+
return `${jsName}(${args})`;
|
|
1677
|
+
}
|
|
1678
|
+
if (moduleName === "tempfile") {
|
|
1679
|
+
const asyncTempfileFuncs = ["mkstemp", "mkdtemp"];
|
|
1680
|
+
const jsName = toJsName(funcName);
|
|
1681
|
+
ctx.usesRuntime.add(`tempfile/${jsName}`);
|
|
1682
|
+
if (funcName === "NamedTemporaryFile") {
|
|
1683
|
+
return `await NamedTemporaryFile.create(${args})`;
|
|
1684
|
+
}
|
|
1685
|
+
if (funcName === "TemporaryDirectory") {
|
|
1686
|
+
return `await TemporaryDirectory.create(${args})`;
|
|
1687
|
+
}
|
|
1688
|
+
if (asyncTempfileFuncs.includes(funcName.toLowerCase())) {
|
|
1689
|
+
return `await ${jsName}(${args})`;
|
|
1690
|
+
}
|
|
1691
|
+
return `${jsName}(${args})`;
|
|
1692
|
+
}
|
|
1693
|
+
if (moduleName === "pathlib") {
|
|
1694
|
+
const jsName = toJsName(funcName);
|
|
1695
|
+
ctx.usesRuntime.add(`pathlib/${jsName}`);
|
|
1696
|
+
if (funcName === "Path") {
|
|
1697
|
+
return `new Path(${args})`;
|
|
1698
|
+
}
|
|
1699
|
+
return `${jsName}(${args})`;
|
|
1700
|
+
}
|
|
1504
1701
|
return null;
|
|
1505
1702
|
}
|
|
1506
1703
|
function transformMethodCall(callee, args, ctx) {
|
|
@@ -1512,6 +1709,29 @@ function transformMethodCall(callee, args, ctx) {
|
|
|
1512
1709
|
if (obj.name === "MemberExpression") {
|
|
1513
1710
|
return null;
|
|
1514
1711
|
}
|
|
1712
|
+
if (obj.name === "VariableName") {
|
|
1713
|
+
const objName = getNodeText(obj, ctx.source);
|
|
1714
|
+
const knownModules = [
|
|
1715
|
+
"shutil",
|
|
1716
|
+
"glob",
|
|
1717
|
+
"tempfile",
|
|
1718
|
+
"pathlib",
|
|
1719
|
+
"os",
|
|
1720
|
+
"math",
|
|
1721
|
+
"random",
|
|
1722
|
+
"json",
|
|
1723
|
+
"datetime",
|
|
1724
|
+
"re",
|
|
1725
|
+
"string",
|
|
1726
|
+
"functools",
|
|
1727
|
+
"itertools",
|
|
1728
|
+
"collections",
|
|
1729
|
+
"hashlib"
|
|
1730
|
+
];
|
|
1731
|
+
if (knownModules.includes(objName)) {
|
|
1732
|
+
return null;
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1515
1735
|
const objCode = transformNode(obj, ctx);
|
|
1516
1736
|
const methodName = getNodeText(methodNode, ctx.source);
|
|
1517
1737
|
switch (methodName) {
|
|
@@ -1670,6 +1890,26 @@ function transformMethodCall(callee, args, ctx) {
|
|
|
1670
1890
|
case "issuperset":
|
|
1671
1891
|
ctx.usesRuntime.add("set");
|
|
1672
1892
|
return `set.issuperset(${objCode}, ${args})`;
|
|
1893
|
+
// Hash object methods (hashlib) - async
|
|
1894
|
+
case "digest":
|
|
1895
|
+
return `await ${objCode}.digest()`;
|
|
1896
|
+
case "hexdigest":
|
|
1897
|
+
return `await ${objCode}.hexdigest()`;
|
|
1898
|
+
// Path object methods (pathlib) - async
|
|
1899
|
+
// Only handle snake_case methods that are unique to Path
|
|
1900
|
+
case "is_file":
|
|
1901
|
+
case "is_dir":
|
|
1902
|
+
case "is_symlink":
|
|
1903
|
+
case "read_text":
|
|
1904
|
+
case "write_text":
|
|
1905
|
+
case "read_bytes":
|
|
1906
|
+
case "write_bytes":
|
|
1907
|
+
case "symlink_to":
|
|
1908
|
+
case "link_to":
|
|
1909
|
+
case "iterdir": {
|
|
1910
|
+
const jsMethod = toJsName(methodName);
|
|
1911
|
+
return `await ${objCode}.${jsMethod}(${args})`;
|
|
1912
|
+
}
|
|
1673
1913
|
/* v8 ignore next 2 -- unknown method, let caller handle @preserve */
|
|
1674
1914
|
default:
|
|
1675
1915
|
return null;
|
|
@@ -1717,7 +1957,7 @@ function transformArgList(node, ctx) {
|
|
|
1717
1957
|
}
|
|
1718
1958
|
if (item.name === "VariableName") {
|
|
1719
1959
|
const nextItem = items[i + 1];
|
|
1720
|
-
if (nextItem
|
|
1960
|
+
if (nextItem?.name === "AssignOp") {
|
|
1721
1961
|
const valueItem = items[i + 2];
|
|
1722
1962
|
if (valueItem) {
|
|
1723
1963
|
const name = getNodeText(item, ctx.source);
|
|
@@ -1931,7 +2171,7 @@ function transformIfStatement(node, ctx) {
|
|
|
1931
2171
|
const condition = children[i + 1];
|
|
1932
2172
|
const body = children.find((c, idx) => idx > i && c.name === "Body");
|
|
1933
2173
|
if (condition && body) {
|
|
1934
|
-
const condCode = transformNode(condition, ctx);
|
|
2174
|
+
const condCode = stripOuterParens(transformNode(condition, ctx));
|
|
1935
2175
|
const bodyCode = transformBody(body, ctx);
|
|
1936
2176
|
parts.push(`if (${condCode}) {
|
|
1937
2177
|
${bodyCode}
|
|
@@ -1941,7 +2181,7 @@ ${bodyCode}
|
|
|
1941
2181
|
const condition = children[i + 1];
|
|
1942
2182
|
const body = children.find((c, idx) => idx > i + 1 && c.name === "Body");
|
|
1943
2183
|
if (condition && body) {
|
|
1944
|
-
const condCode = transformNode(condition, ctx);
|
|
2184
|
+
const condCode = stripOuterParens(transformNode(condition, ctx));
|
|
1945
2185
|
const bodyCode = transformBody(body, ctx);
|
|
1946
2186
|
parts.push(` else if (${condCode}) {
|
|
1947
2187
|
${bodyCode}
|
|
@@ -1967,7 +2207,7 @@ function transformWhileStatement(node, ctx) {
|
|
|
1967
2207
|
);
|
|
1968
2208
|
const body = children.find((c) => c.name === "Body");
|
|
1969
2209
|
if (!condition || !body) return getNodeText(node, ctx.source);
|
|
1970
|
-
const condCode = transformNode(condition, ctx);
|
|
2210
|
+
const condCode = stripOuterParens(transformNode(condition, ctx));
|
|
1971
2211
|
const bodyCode = transformBody(body, ctx);
|
|
1972
2212
|
return `while (${condCode}) {
|
|
1973
2213
|
${bodyCode}
|
|
@@ -1981,8 +2221,8 @@ function transformMatchStatement(node, ctx) {
|
|
|
1981
2221
|
if (child.name === "match" || child.name === ":") continue;
|
|
1982
2222
|
if (child.name === "MatchBody") {
|
|
1983
2223
|
matchBody = child;
|
|
1984
|
-
} else
|
|
1985
|
-
subject
|
|
2224
|
+
} else {
|
|
2225
|
+
subject ??= child;
|
|
1986
2226
|
}
|
|
1987
2227
|
}
|
|
1988
2228
|
if (!subject || !matchBody) return getNodeText(node, ctx.source);
|
|
@@ -2032,8 +2272,8 @@ function transformMatchAsIfElse(subjectCode, clauses, ctx) {
|
|
|
2032
2272
|
body = child;
|
|
2033
2273
|
} else if (child.name === "Guard") {
|
|
2034
2274
|
guard = child;
|
|
2035
|
-
} else
|
|
2036
|
-
pattern
|
|
2275
|
+
} else {
|
|
2276
|
+
pattern ??= child;
|
|
2037
2277
|
}
|
|
2038
2278
|
}
|
|
2039
2279
|
if (!pattern || !body) continue;
|
|
@@ -2259,8 +2499,8 @@ function transformMatchClause(node, ctx, indent) {
|
|
|
2259
2499
|
if (child.name === "case" || child.name === ":") continue;
|
|
2260
2500
|
if (child.name === "Body") {
|
|
2261
2501
|
body = child;
|
|
2262
|
-
} else
|
|
2263
|
-
pattern
|
|
2502
|
+
} else {
|
|
2503
|
+
pattern ??= child;
|
|
2264
2504
|
}
|
|
2265
2505
|
}
|
|
2266
2506
|
if (!pattern || !body) return "";
|
|
@@ -2380,7 +2620,7 @@ function transformTryStatement(node, ctx) {
|
|
|
2380
2620
|
}
|
|
2381
2621
|
if (child.name === "try") {
|
|
2382
2622
|
const nextBody = children[i + 1];
|
|
2383
|
-
if (nextBody
|
|
2623
|
+
if (nextBody?.name === "Body") {
|
|
2384
2624
|
tryBody = nextBody;
|
|
2385
2625
|
i += 2;
|
|
2386
2626
|
continue;
|
|
@@ -2418,7 +2658,7 @@ function transformTryStatement(node, ctx) {
|
|
|
2418
2658
|
}
|
|
2419
2659
|
if (child.name === "finally") {
|
|
2420
2660
|
const nextBody = children[i + 1];
|
|
2421
|
-
if (nextBody
|
|
2661
|
+
if (nextBody?.name === "Body") {
|
|
2422
2662
|
finallyBody = nextBody;
|
|
2423
2663
|
i += 2;
|
|
2424
2664
|
continue;
|
|
@@ -2436,14 +2676,21 @@ ${baseIndent}}`;
|
|
|
2436
2676
|
if (exceptBodies.length > 0) {
|
|
2437
2677
|
const firstExcept = exceptBodies[0];
|
|
2438
2678
|
if (firstExcept) {
|
|
2439
|
-
const catchVar = firstExcept.varName
|
|
2440
|
-
|
|
2679
|
+
const catchVar = firstExcept.varName ?? "e";
|
|
2680
|
+
let catchBody = transformBody(firstExcept.body, ctx);
|
|
2681
|
+
const isEmpty = !catchBody.trim();
|
|
2682
|
+
if (isEmpty) {
|
|
2683
|
+
const innerIndent = " ".repeat(ctx.indentLevel + 1);
|
|
2684
|
+
const exceptionComment = firstExcept.type ? ` - ${firstExcept.type} expected` : "";
|
|
2685
|
+
catchBody = `${innerIndent}// Intentionally empty${exceptionComment}`;
|
|
2686
|
+
}
|
|
2687
|
+
const catchClause = isEmpty && !firstExcept.varName ? "catch" : `catch (${catchVar})`;
|
|
2441
2688
|
if (exceptBodies.length === 1 && !firstExcept.type) {
|
|
2442
|
-
result += `
|
|
2689
|
+
result += ` ${catchClause} {
|
|
2443
2690
|
${catchBody}
|
|
2444
2691
|
${baseIndent}}`;
|
|
2445
2692
|
} else if (exceptBodies.length === 1) {
|
|
2446
|
-
result += `
|
|
2693
|
+
result += ` ${catchClause} {
|
|
2447
2694
|
${catchBody}
|
|
2448
2695
|
${baseIndent}}`;
|
|
2449
2696
|
} else {
|
|
@@ -2453,7 +2700,7 @@ ${baseIndent}}`;
|
|
|
2453
2700
|
const exc = exceptBodies[idx];
|
|
2454
2701
|
if (!exc) continue;
|
|
2455
2702
|
const excBodyCode = transformBody(exc.body, ctx);
|
|
2456
|
-
const excVar = exc.varName
|
|
2703
|
+
const excVar = exc.varName ?? catchVar;
|
|
2457
2704
|
if (exc.type) {
|
|
2458
2705
|
const condition = idx === 0 ? "if" : "} else if";
|
|
2459
2706
|
const mappedType = mapExceptionType(exc.type);
|
|
@@ -2508,7 +2755,7 @@ function mapExceptionType(pythonType) {
|
|
|
2508
2755
|
NameError: "ReferenceError",
|
|
2509
2756
|
SyntaxError: "SyntaxError"
|
|
2510
2757
|
};
|
|
2511
|
-
return mapping[pythonType]
|
|
2758
|
+
return mapping[pythonType] ?? "Error";
|
|
2512
2759
|
}
|
|
2513
2760
|
function transformRaiseStatement(node, ctx) {
|
|
2514
2761
|
const children = getChildren(node);
|
|
@@ -2598,9 +2845,9 @@ function transformSimpleImport(children, ctx) {
|
|
|
2598
2845
|
const moduleName = getNodeText(child, ctx.source);
|
|
2599
2846
|
let alias = null;
|
|
2600
2847
|
const nextChild = children[i + 1];
|
|
2601
|
-
if (nextChild
|
|
2848
|
+
if (nextChild?.name === "as") {
|
|
2602
2849
|
const aliasChild = children[i + 2];
|
|
2603
|
-
if (aliasChild
|
|
2850
|
+
if (aliasChild?.name === "VariableName") {
|
|
2604
2851
|
alias = getNodeText(aliasChild, ctx.source);
|
|
2605
2852
|
i += 3;
|
|
2606
2853
|
names.push({ module: moduleName, alias });
|
|
@@ -2620,7 +2867,7 @@ function transformSimpleImport(children, ctx) {
|
|
|
2620
2867
|
return "";
|
|
2621
2868
|
}
|
|
2622
2869
|
return filteredNames.map(({ module, alias }) => {
|
|
2623
|
-
const importName = alias
|
|
2870
|
+
const importName = alias ?? module;
|
|
2624
2871
|
return `import * as ${importName} from "${module}"`;
|
|
2625
2872
|
}).join("\n");
|
|
2626
2873
|
}
|
|
@@ -2696,9 +2943,9 @@ function transformFromImport(children, ctx) {
|
|
|
2696
2943
|
if (child.name === "VariableName") {
|
|
2697
2944
|
const name = getNodeText(child, ctx.source);
|
|
2698
2945
|
const nextChild = children[i + 1];
|
|
2699
|
-
if (nextChild
|
|
2946
|
+
if (nextChild?.name === "as") {
|
|
2700
2947
|
const aliasChild = children[i + 2];
|
|
2701
|
-
if (aliasChild
|
|
2948
|
+
if (aliasChild?.name === "VariableName") {
|
|
2702
2949
|
imports.push({ name, alias: getNodeText(aliasChild, ctx.source) });
|
|
2703
2950
|
i += 2;
|
|
2704
2951
|
continue;
|
|
@@ -2722,7 +2969,7 @@ function transformFromImport(children, ctx) {
|
|
|
2722
2969
|
if (moduleName) {
|
|
2723
2970
|
modulePath += moduleName;
|
|
2724
2971
|
} else if (imports.length > 0) {
|
|
2725
|
-
modulePath += imports[0]?.name
|
|
2972
|
+
modulePath += imports[0]?.name ?? "";
|
|
2726
2973
|
}
|
|
2727
2974
|
} else {
|
|
2728
2975
|
modulePath = moduleName;
|
|
@@ -2733,7 +2980,7 @@ function transformFromImport(children, ctx) {
|
|
|
2733
2980
|
if (relativeDots > 0 && !moduleName && imports.length === 1) {
|
|
2734
2981
|
const imp = imports[0];
|
|
2735
2982
|
if (imp) {
|
|
2736
|
-
const importName = imp.alias
|
|
2983
|
+
const importName = imp.alias ?? imp.name;
|
|
2737
2984
|
return `import * as ${importName} from "${modulePath}"`;
|
|
2738
2985
|
}
|
|
2739
2986
|
}
|
|
@@ -2772,9 +3019,9 @@ function transformWithStatement(node, ctx) {
|
|
|
2772
3019
|
const expr = child;
|
|
2773
3020
|
let varName = null;
|
|
2774
3021
|
const nextChild = children[i + 1];
|
|
2775
|
-
if (nextChild
|
|
3022
|
+
if (nextChild?.name === "as") {
|
|
2776
3023
|
const varChild = children[i + 2];
|
|
2777
|
-
if (varChild
|
|
3024
|
+
if (varChild?.name === "VariableName") {
|
|
2778
3025
|
varName = getNodeText(varChild, ctx.source);
|
|
2779
3026
|
i += 3;
|
|
2780
3027
|
} else {
|
|
@@ -2847,7 +3094,7 @@ function extractParamNames(node, source) {
|
|
|
2847
3094
|
}
|
|
2848
3095
|
if (child.name === "*" || getNodeText(child, source) === "*") {
|
|
2849
3096
|
const nextChild = children[i + 1];
|
|
2850
|
-
if (nextChild
|
|
3097
|
+
if (nextChild?.name === "VariableName") {
|
|
2851
3098
|
names.push(getNodeText(nextChild, source));
|
|
2852
3099
|
i += 2;
|
|
2853
3100
|
continue;
|
|
@@ -2857,7 +3104,7 @@ function extractParamNames(node, source) {
|
|
|
2857
3104
|
}
|
|
2858
3105
|
if (child.name === "**" || getNodeText(child, source) === "**") {
|
|
2859
3106
|
const nextChild = children[i + 1];
|
|
2860
|
-
if (nextChild
|
|
3107
|
+
if (nextChild?.name === "VariableName") {
|
|
2861
3108
|
names.push(getNodeText(nextChild, source));
|
|
2862
3109
|
i += 2;
|
|
2863
3110
|
continue;
|
|
@@ -3228,7 +3475,7 @@ function transformMethodParamListImpl(node, ctx, includeTypes) {
|
|
|
3228
3475
|
isFirstParam = false;
|
|
3229
3476
|
if (child.name === "*" || getNodeText(child, ctx.source) === "*") {
|
|
3230
3477
|
const nextChild = children[i + 1];
|
|
3231
|
-
if (nextChild
|
|
3478
|
+
if (nextChild?.name === "VariableName") {
|
|
3232
3479
|
const name = getNodeText(nextChild, ctx.source);
|
|
3233
3480
|
params.push(`...${name}`);
|
|
3234
3481
|
i += 2;
|
|
@@ -3239,7 +3486,7 @@ function transformMethodParamListImpl(node, ctx, includeTypes) {
|
|
|
3239
3486
|
}
|
|
3240
3487
|
if (child.name === "**" || getNodeText(child, ctx.source) === "**") {
|
|
3241
3488
|
const nextChild = children[i + 1];
|
|
3242
|
-
if (nextChild
|
|
3489
|
+
if (nextChild?.name === "VariableName") {
|
|
3243
3490
|
const name = getNodeText(nextChild, ctx.source);
|
|
3244
3491
|
params.push(name);
|
|
3245
3492
|
i += 2;
|
|
@@ -3582,7 +3829,7 @@ function parseDataclassFieldFromExpression(node, ctx) {
|
|
|
3582
3829
|
}
|
|
3583
3830
|
function parseFieldDefaultFactory(callNode, ctx) {
|
|
3584
3831
|
const text = getNodeText(callNode, ctx.source);
|
|
3585
|
-
const factoryMatch =
|
|
3832
|
+
const factoryMatch = /default_factory\s*=\s*(\w+)/.exec(text);
|
|
3586
3833
|
if (factoryMatch) {
|
|
3587
3834
|
const factory = factoryMatch[1];
|
|
3588
3835
|
if (factory === "list") return "[]";
|
|
@@ -3590,7 +3837,7 @@ function parseFieldDefaultFactory(callNode, ctx) {
|
|
|
3590
3837
|
if (factory === "set") return "new Set()";
|
|
3591
3838
|
if (factory) return `${factory}()`;
|
|
3592
3839
|
}
|
|
3593
|
-
const defaultMatch =
|
|
3840
|
+
const defaultMatch = /default\s*=\s*([^,)]+)/.exec(text);
|
|
3594
3841
|
if (defaultMatch) {
|
|
3595
3842
|
return defaultMatch[1]?.trim() ?? "undefined";
|
|
3596
3843
|
}
|
|
@@ -3809,9 +4056,8 @@ function parseEnumMember(node, ctx) {
|
|
|
3809
4056
|
function checkSequentialEnum(members) {
|
|
3810
4057
|
if (members.length === 0) return true;
|
|
3811
4058
|
if (members.some((m) => m.value === "auto")) return true;
|
|
3812
|
-
const
|
|
3813
|
-
if (
|
|
3814
|
-
const values = numericMembers.map((m) => m.numericValue);
|
|
4059
|
+
const values = members.map((m) => m.numericValue).filter((v) => v !== null);
|
|
4060
|
+
if (values.length !== members.length) return false;
|
|
3815
4061
|
const firstValue = values[0];
|
|
3816
4062
|
if (firstValue === void 0) return false;
|
|
3817
4063
|
for (let i = 1; i < values.length; i++) {
|
|
@@ -3893,7 +4139,7 @@ function transformProtocol(className, parentClasses, body, ctx) {
|
|
|
3893
4139
|
members.push(`${memberIndent}${sig}`);
|
|
3894
4140
|
}
|
|
3895
4141
|
} else if (child.name === "ExpressionStatement" || child.name === "AssignStatement") {
|
|
3896
|
-
const field = parseDataclassFieldFromExpression(child, ctx)
|
|
4142
|
+
const field = parseDataclassFieldFromExpression(child, ctx) ?? parseDataclassFieldFromAssignment(child, ctx);
|
|
3897
4143
|
if (field) {
|
|
3898
4144
|
members.push(`${memberIndent}${field.name}: ${field.tsType}`);
|
|
3899
4145
|
}
|
|
@@ -3992,18 +4238,18 @@ function transformParamList(node, ctx) {
|
|
|
3992
4238
|
let i = 0;
|
|
3993
4239
|
const parseParam = (startIndex) => {
|
|
3994
4240
|
const child = children[startIndex];
|
|
3995
|
-
if (
|
|
4241
|
+
if (child?.name !== "VariableName") return null;
|
|
3996
4242
|
const nameCode = getNodeText(child, ctx.source);
|
|
3997
4243
|
let tsType = null;
|
|
3998
4244
|
let defaultValue = null;
|
|
3999
4245
|
let offset = 1;
|
|
4000
4246
|
const nextChild = children[startIndex + 1];
|
|
4001
|
-
if (nextChild
|
|
4247
|
+
if (nextChild?.name === "TypeDef") {
|
|
4002
4248
|
tsType = extractTypeAnnotation(nextChild, ctx);
|
|
4003
4249
|
offset = 2;
|
|
4004
4250
|
}
|
|
4005
4251
|
const afterType = children[startIndex + offset];
|
|
4006
|
-
if (afterType
|
|
4252
|
+
if (afterType?.name === "AssignOp") {
|
|
4007
4253
|
const defaultValChild = children[startIndex + offset + 1];
|
|
4008
4254
|
if (defaultValChild) {
|
|
4009
4255
|
defaultValue = transformNode(defaultValChild, ctx);
|
|
@@ -4034,10 +4280,10 @@ function transformParamList(node, ctx) {
|
|
|
4034
4280
|
}
|
|
4035
4281
|
if (child.name === "*" || getNodeText(child, ctx.source) === "*") {
|
|
4036
4282
|
const nextChild = children[i + 1];
|
|
4037
|
-
if (nextChild
|
|
4283
|
+
if (nextChild?.name === "VariableName") {
|
|
4038
4284
|
const name = getNodeText(nextChild, ctx.source);
|
|
4039
4285
|
const typeChild = children[i + 2];
|
|
4040
|
-
if (typeChild
|
|
4286
|
+
if (typeChild?.name === "TypeDef") {
|
|
4041
4287
|
const tsType = extractTypeAnnotation(typeChild, ctx);
|
|
4042
4288
|
restParam = tsType ? `...${name}: ${tsType}[]` : `...${name}`;
|
|
4043
4289
|
i += 3;
|
|
@@ -4054,7 +4300,7 @@ function transformParamList(node, ctx) {
|
|
|
4054
4300
|
}
|
|
4055
4301
|
if (child.name === "**" || getNodeText(child, ctx.source) === "**") {
|
|
4056
4302
|
const nextChild = children[i + 1];
|
|
4057
|
-
if (nextChild
|
|
4303
|
+
if (nextChild?.name === "VariableName") {
|
|
4058
4304
|
kwargsParam = getNodeText(nextChild, ctx.source);
|
|
4059
4305
|
i += 2;
|
|
4060
4306
|
continue;
|
|
@@ -4511,6 +4757,11 @@ function transformYieldStatement(node, ctx) {
|
|
|
4511
4757
|
|
|
4512
4758
|
// src/generator/index.ts
|
|
4513
4759
|
import * as prettier from "prettier";
|
|
4760
|
+
import { ESLint } from "eslint";
|
|
4761
|
+
import tseslint from "typescript-eslint";
|
|
4762
|
+
import { writeFileSync, readFileSync, mkdtempSync, rmSync } from "fs";
|
|
4763
|
+
import { join } from "path";
|
|
4764
|
+
import { tmpdir } from "os";
|
|
4514
4765
|
var defaultOptions = {
|
|
4515
4766
|
includeRuntime: true,
|
|
4516
4767
|
runtimeImportPath: "pythonlib"
|
|
@@ -4655,9 +4906,81 @@ function buildRuntimeImports(usedFunctions, basePath) {
|
|
|
4655
4906
|
function transpile(python, options = {}) {
|
|
4656
4907
|
return generate(python, options).code;
|
|
4657
4908
|
}
|
|
4909
|
+
function createEslintConfig(tempDir) {
|
|
4910
|
+
return {
|
|
4911
|
+
cwd: tempDir,
|
|
4912
|
+
fix: true,
|
|
4913
|
+
overrideConfigFile: true,
|
|
4914
|
+
overrideConfig: [
|
|
4915
|
+
// TypeScript-ESLint strict + stylistic presets (type-checked)
|
|
4916
|
+
...tseslint.configs.strictTypeChecked,
|
|
4917
|
+
...tseslint.configs.stylisticTypeChecked,
|
|
4918
|
+
// Custom configuration
|
|
4919
|
+
{
|
|
4920
|
+
files: ["**/*.ts"],
|
|
4921
|
+
languageOptions: {
|
|
4922
|
+
parserOptions: {
|
|
4923
|
+
projectService: true,
|
|
4924
|
+
tsconfigRootDir: tempDir
|
|
4925
|
+
}
|
|
4926
|
+
},
|
|
4927
|
+
rules: {
|
|
4928
|
+
// ESLint core rules (auto-fixable, not in typescript-eslint presets)
|
|
4929
|
+
"prefer-const": "error",
|
|
4930
|
+
"prefer-arrow-callback": "error",
|
|
4931
|
+
"prefer-template": "error",
|
|
4932
|
+
"prefer-rest-params": "error",
|
|
4933
|
+
"prefer-spread": "error",
|
|
4934
|
+
curly: "error",
|
|
4935
|
+
"no-lonely-if": "error",
|
|
4936
|
+
// Disable rules that don't make sense for generated code
|
|
4937
|
+
"@typescript-eslint/explicit-function-return-type": "off",
|
|
4938
|
+
"@typescript-eslint/explicit-module-boundary-types": "off",
|
|
4939
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
4940
|
+
"@typescript-eslint/no-unsafe-assignment": "off",
|
|
4941
|
+
"@typescript-eslint/no-unsafe-member-access": "off",
|
|
4942
|
+
"@typescript-eslint/no-unsafe-call": "off",
|
|
4943
|
+
"@typescript-eslint/no-unsafe-return": "off",
|
|
4944
|
+
"@typescript-eslint/no-unsafe-argument": "off"
|
|
4945
|
+
}
|
|
4946
|
+
}
|
|
4947
|
+
]
|
|
4948
|
+
};
|
|
4949
|
+
}
|
|
4950
|
+
async function applyTypedEslintFixes(code) {
|
|
4951
|
+
const tempDir = mkdtempSync(join(tmpdir(), "python2ts-"));
|
|
4952
|
+
try {
|
|
4953
|
+
const tsconfigPath = join(tempDir, "tsconfig.json");
|
|
4954
|
+
writeFileSync(
|
|
4955
|
+
tsconfigPath,
|
|
4956
|
+
JSON.stringify({
|
|
4957
|
+
compilerOptions: {
|
|
4958
|
+
target: "ES2024",
|
|
4959
|
+
module: "ESNext",
|
|
4960
|
+
moduleResolution: "bundler",
|
|
4961
|
+
strict: true,
|
|
4962
|
+
skipLibCheck: true,
|
|
4963
|
+
noEmit: true
|
|
4964
|
+
},
|
|
4965
|
+
include: ["*.ts"]
|
|
4966
|
+
})
|
|
4967
|
+
);
|
|
4968
|
+
const tempFile = join(tempDir, "output.ts");
|
|
4969
|
+
writeFileSync(tempFile, code);
|
|
4970
|
+
const eslint = new ESLint(createEslintConfig(tempDir));
|
|
4971
|
+
const results = await eslint.lintFiles(["output.ts"]);
|
|
4972
|
+
if (results.length > 0 && results[0]?.output) {
|
|
4973
|
+
return results[0].output;
|
|
4974
|
+
}
|
|
4975
|
+
return readFileSync(tempFile, "utf-8");
|
|
4976
|
+
} finally {
|
|
4977
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
4978
|
+
}
|
|
4979
|
+
}
|
|
4658
4980
|
async function formatCode(code) {
|
|
4659
4981
|
try {
|
|
4660
|
-
|
|
4982
|
+
const eslintFixed = await applyTypedEslintFixes(code);
|
|
4983
|
+
return await prettier.format(eslintFixed, prettierOptions);
|
|
4661
4984
|
} catch {
|
|
4662
4985
|
return code;
|
|
4663
4986
|
}
|
|
@@ -4703,4 +5026,3 @@ export {
|
|
|
4703
5026
|
/* v8 ignore next -- bare yield statement @preserve */
|
|
4704
5027
|
/* v8 ignore next 2 -- fallback for future/unknown runtime functions @preserve */
|
|
4705
5028
|
/* v8 ignore start -- async wrappers tested via CLI @preserve */
|
|
4706
|
-
//# sourceMappingURL=chunk-65ZOMVMA.js.map
|