python2ts 1.3.3 → 1.4.1
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.
|
@@ -791,6 +791,8 @@ function transformNode(node, ctx) {
|
|
|
791
791
|
return transformExpressionStatement(node, ctx);
|
|
792
792
|
case "AssignStatement":
|
|
793
793
|
return transformAssignStatement(node, ctx);
|
|
794
|
+
case "UpdateStatement":
|
|
795
|
+
return transformUpdateStatement(node, ctx);
|
|
794
796
|
case "BinaryExpression":
|
|
795
797
|
return transformBinaryExpression(node, ctx);
|
|
796
798
|
case "UnaryExpression":
|
|
@@ -807,6 +809,8 @@ function transformNode(node, ctx) {
|
|
|
807
809
|
return transformString(node, ctx);
|
|
808
810
|
case "FormatString":
|
|
809
811
|
return transformFormatString(node, ctx);
|
|
812
|
+
case "ContinuedString":
|
|
813
|
+
return transformContinuedString(node, ctx);
|
|
810
814
|
case "Boolean":
|
|
811
815
|
return transformBoolean(node, ctx);
|
|
812
816
|
case "None":
|
|
@@ -927,6 +931,42 @@ function transformExpressionStatement(node, ctx) {
|
|
|
927
931
|
function transformAssignStatement(node, ctx) {
|
|
928
932
|
const children = getChildren(node);
|
|
929
933
|
if (children.length < 3) return getNodeText(node, ctx.source);
|
|
934
|
+
const assignOpIndices = children.map((c, i) => c.name === "AssignOp" || c.name === "=" ? i : -1).filter((i) => i !== -1);
|
|
935
|
+
if (assignOpIndices.length > 1) {
|
|
936
|
+
const targets2 = [];
|
|
937
|
+
const lastAssignOpIndex = assignOpIndices[assignOpIndices.length - 1];
|
|
938
|
+
if (lastAssignOpIndex === void 0) return getNodeText(node, ctx.source);
|
|
939
|
+
for (let i = 0; i < assignOpIndices.length; i++) {
|
|
940
|
+
const opIndex = assignOpIndices[i];
|
|
941
|
+
if (opIndex === void 0) continue;
|
|
942
|
+
const prevOpIndex = i > 0 ? assignOpIndices[i - 1] : -1;
|
|
943
|
+
const startIdx = prevOpIndex !== void 0 ? prevOpIndex + 1 : 0;
|
|
944
|
+
const targetNodes = children.slice(startIdx, opIndex).filter((c) => c.name !== ",");
|
|
945
|
+
if (targetNodes.length === 1 && targetNodes[0]) {
|
|
946
|
+
targets2.push(targetNodes[0]);
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
const valueNodes = children.slice(lastAssignOpIndex + 1).filter((c) => c.name !== ",");
|
|
950
|
+
if (valueNodes.length !== 1 || !valueNodes[0]) return getNodeText(node, ctx.source);
|
|
951
|
+
const valueCode = transformNode(valueNodes[0], ctx);
|
|
952
|
+
const results = [];
|
|
953
|
+
let lastVarName = valueCode;
|
|
954
|
+
for (let i = targets2.length - 1; i >= 0; i--) {
|
|
955
|
+
const target = targets2[i];
|
|
956
|
+
if (!target) continue;
|
|
957
|
+
const targetCode = transformNode(target, ctx);
|
|
958
|
+
const varName = getNodeText(target, ctx.source);
|
|
959
|
+
let needsDeclaration = false;
|
|
960
|
+
if (target.name === "VariableName" && !isVariableDeclared(ctx, varName)) {
|
|
961
|
+
needsDeclaration = true;
|
|
962
|
+
declareVariable(ctx, varName);
|
|
963
|
+
}
|
|
964
|
+
const keyword = needsDeclaration ? "let " : "";
|
|
965
|
+
results.push(`${keyword}${targetCode} = ${lastVarName}`);
|
|
966
|
+
lastVarName = targetCode;
|
|
967
|
+
}
|
|
968
|
+
return results.join(";\n");
|
|
969
|
+
}
|
|
930
970
|
const assignOpIndex = children.findIndex((c) => c.name === "AssignOp" || c.name === "=");
|
|
931
971
|
if (assignOpIndex === -1) return getNodeText(node, ctx.source);
|
|
932
972
|
const typeDef = children.slice(0, assignOpIndex).find((c) => c.name === "TypeDef");
|
|
@@ -1025,6 +1065,23 @@ function extractVariableNames(nodes, source) {
|
|
|
1025
1065
|
}
|
|
1026
1066
|
return names;
|
|
1027
1067
|
}
|
|
1068
|
+
function transformUpdateStatement(node, ctx) {
|
|
1069
|
+
const children = getChildren(node);
|
|
1070
|
+
const target = children.find(
|
|
1071
|
+
(c) => c.name === "VariableName" || c.name === "MemberExpression" || c.name === "Subscript"
|
|
1072
|
+
);
|
|
1073
|
+
const op = children.find((c) => c.name === "UpdateOp");
|
|
1074
|
+
const value = children.find(
|
|
1075
|
+
(c) => c !== target && c.name !== "UpdateOp" && c.name !== "(" && c.name !== ")" && c.name !== "," && c.name !== ":"
|
|
1076
|
+
);
|
|
1077
|
+
if (!target || !op || !value) {
|
|
1078
|
+
return getNodeText(node, ctx.source);
|
|
1079
|
+
}
|
|
1080
|
+
const targetCode = transformNode(target, ctx);
|
|
1081
|
+
const opText = getNodeText(op, ctx.source);
|
|
1082
|
+
const valueCode = transformNode(value, ctx);
|
|
1083
|
+
return `${targetCode} ${opText} ${valueCode}`;
|
|
1084
|
+
}
|
|
1028
1085
|
function isSliceExpression(node) {
|
|
1029
1086
|
const children = getChildren(node);
|
|
1030
1087
|
return children.some((c) => c.name === ":");
|
|
@@ -1317,6 +1374,51 @@ function transformFormatString(node, ctx) {
|
|
|
1317
1374
|
result += "`";
|
|
1318
1375
|
return result;
|
|
1319
1376
|
}
|
|
1377
|
+
function transformContinuedString(node, ctx) {
|
|
1378
|
+
const children = getChildren(node);
|
|
1379
|
+
const hasFormatString = children.some((c) => c.name === "FormatString");
|
|
1380
|
+
if (hasFormatString) {
|
|
1381
|
+
const parts = children.filter((c) => c.name === "String" || c.name === "FormatString").map((c) => {
|
|
1382
|
+
if (c.name === "FormatString") {
|
|
1383
|
+
return transformFormatString(c, ctx);
|
|
1384
|
+
} else {
|
|
1385
|
+
const text = getNodeText(c, ctx.source);
|
|
1386
|
+
let content;
|
|
1387
|
+
if (/^[rR]['"]/.test(text)) {
|
|
1388
|
+
content = text.slice(2, -1);
|
|
1389
|
+
} else if (/^[rR]"""/.test(text) || /^[rR]'''/.test(text)) {
|
|
1390
|
+
content = text.slice(4, -3);
|
|
1391
|
+
} else if (text.startsWith('"""') || text.startsWith("'''")) {
|
|
1392
|
+
content = text.slice(3, -3);
|
|
1393
|
+
} else {
|
|
1394
|
+
content = text.slice(1, -1);
|
|
1395
|
+
}
|
|
1396
|
+
return "`" + content.replace(/`/g, "\\`") + "`";
|
|
1397
|
+
}
|
|
1398
|
+
});
|
|
1399
|
+
return parts.join(" + ");
|
|
1400
|
+
} else {
|
|
1401
|
+
const parts = children.filter((c) => c.name === "String").map((c) => {
|
|
1402
|
+
const text = getNodeText(c, ctx.source);
|
|
1403
|
+
let content;
|
|
1404
|
+
if (/^[rR]['"]/.test(text)) {
|
|
1405
|
+
content = text.slice(2, -1);
|
|
1406
|
+
} else if (/^[rR]"""/.test(text) || /^[rR]'''/.test(text)) {
|
|
1407
|
+
content = text.slice(4, -3);
|
|
1408
|
+
} else if (text.startsWith('"""') || text.startsWith("'''")) {
|
|
1409
|
+
content = text.slice(3, -3);
|
|
1410
|
+
} else {
|
|
1411
|
+
content = text.slice(1, -1);
|
|
1412
|
+
}
|
|
1413
|
+
return content;
|
|
1414
|
+
});
|
|
1415
|
+
const joined = parts.join("");
|
|
1416
|
+
if (joined.includes('"') && !joined.includes("'")) {
|
|
1417
|
+
return "'" + joined + "'";
|
|
1418
|
+
}
|
|
1419
|
+
return '"' + joined + '"';
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1320
1422
|
function transformBoolean(node, ctx) {
|
|
1321
1423
|
const text = getNodeText(node, ctx.source);
|
|
1322
1424
|
return text === "True" ? "true" : "false";
|
|
@@ -3140,7 +3242,12 @@ function transformWithStatement(node, ctx) {
|
|
|
3140
3242
|
body = child;
|
|
3141
3243
|
break;
|
|
3142
3244
|
}
|
|
3143
|
-
if (child.name
|
|
3245
|
+
if (child.name === "as" || child.name === ":") {
|
|
3246
|
+
i++;
|
|
3247
|
+
continue;
|
|
3248
|
+
}
|
|
3249
|
+
const isContextManagerExpr = child.name !== "VariableName" || children[i + 1]?.name === "as" || children[i + 1]?.name === "Body" || children[i + 1]?.name === ",";
|
|
3250
|
+
if (isContextManagerExpr) {
|
|
3144
3251
|
const expr = child;
|
|
3145
3252
|
let varName = null;
|
|
3146
3253
|
const nextChild = children[i + 1];
|
|
@@ -3691,6 +3798,45 @@ function transformClassMethodBody(node, ctx, skipFirst = false, predeclaredVars
|
|
|
3691
3798
|
function transformClassAssignment(node, ctx) {
|
|
3692
3799
|
const children = getChildren(node);
|
|
3693
3800
|
if (children.length < 3) return getNodeText(node, ctx.source);
|
|
3801
|
+
const assignOpIndices = children.map((c, i) => c.name === "AssignOp" || c.name === "=" ? i : -1).filter((i) => i !== -1);
|
|
3802
|
+
if (assignOpIndices.length > 1) {
|
|
3803
|
+
const chainTargets = [];
|
|
3804
|
+
const lastAssignOpIndex = assignOpIndices[assignOpIndices.length - 1];
|
|
3805
|
+
if (lastAssignOpIndex === void 0) return getNodeText(node, ctx.source);
|
|
3806
|
+
for (let i = 0; i < assignOpIndices.length; i++) {
|
|
3807
|
+
const opIndex = assignOpIndices[i];
|
|
3808
|
+
if (opIndex === void 0) continue;
|
|
3809
|
+
const prevOpIndex = i > 0 ? assignOpIndices[i - 1] : -1;
|
|
3810
|
+
const startIdx = prevOpIndex !== void 0 ? prevOpIndex + 1 : 0;
|
|
3811
|
+
const targetNodes = children.slice(startIdx, opIndex).filter((c) => c.name !== ",");
|
|
3812
|
+
if (targetNodes.length === 1 && targetNodes[0]) {
|
|
3813
|
+
chainTargets.push(targetNodes[0]);
|
|
3814
|
+
}
|
|
3815
|
+
}
|
|
3816
|
+
const valueNodes = children.slice(lastAssignOpIndex + 1).filter((c) => c.name !== ",");
|
|
3817
|
+
if (valueNodes.length !== 1 || !valueNodes[0]) return getNodeText(node, ctx.source);
|
|
3818
|
+
const valueCode = transformNode(valueNodes[0], ctx);
|
|
3819
|
+
const results = [];
|
|
3820
|
+
let lastVarName = valueCode;
|
|
3821
|
+
const indent = " ".repeat(ctx.indentLevel);
|
|
3822
|
+
for (let i = chainTargets.length - 1; i >= 0; i--) {
|
|
3823
|
+
const target = chainTargets[i];
|
|
3824
|
+
if (!target) continue;
|
|
3825
|
+
const targetCode = transformNode(target, ctx);
|
|
3826
|
+
const varName = getNodeText(target, ctx.source);
|
|
3827
|
+
const isMemberAssignment = target.name === "MemberExpression";
|
|
3828
|
+
let needsDeclaration = false;
|
|
3829
|
+
if (!isMemberAssignment && target.name === "VariableName" && !isVariableDeclared(ctx, varName)) {
|
|
3830
|
+
needsDeclaration = true;
|
|
3831
|
+
declareVariable(ctx, varName);
|
|
3832
|
+
}
|
|
3833
|
+
const keyword = needsDeclaration ? "let " : "";
|
|
3834
|
+
results.push(`${keyword}${targetCode} = ${lastVarName}`);
|
|
3835
|
+
lastVarName = targetCode;
|
|
3836
|
+
}
|
|
3837
|
+
return results.join(`;
|
|
3838
|
+
${indent}`);
|
|
3839
|
+
}
|
|
3694
3840
|
const assignOpIndex = children.findIndex((c) => c.name === "AssignOp" || c.name === "=");
|
|
3695
3841
|
if (assignOpIndex === -1) return getNodeText(node, ctx.source);
|
|
3696
3842
|
const targets = children.slice(0, assignOpIndex).filter((c) => c.name !== ",");
|
|
@@ -4564,15 +4710,40 @@ function parseComprehensionClauses(children, ctx) {
|
|
|
4564
4710
|
continue;
|
|
4565
4711
|
}
|
|
4566
4712
|
if (item.name === "for" || item.name === "Keyword" && getNodeText(item, ctx.source) === "for") {
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4713
|
+
let inIndex = -1;
|
|
4714
|
+
for (let j = i + 1; j < items.length; j++) {
|
|
4715
|
+
const candidate = items[j];
|
|
4716
|
+
if (candidate && (candidate.name === "in" || candidate.name === "Keyword" && getNodeText(candidate, ctx.source) === "in")) {
|
|
4717
|
+
inIndex = j;
|
|
4718
|
+
break;
|
|
4719
|
+
}
|
|
4720
|
+
}
|
|
4721
|
+
if (inIndex === -1) {
|
|
4722
|
+
i++;
|
|
4723
|
+
continue;
|
|
4724
|
+
}
|
|
4725
|
+
const varNodes = [];
|
|
4726
|
+
for (let j = i + 1; j < inIndex; j++) {
|
|
4727
|
+
const varCandidate = items[j];
|
|
4728
|
+
if (varCandidate && varCandidate.name !== ",") {
|
|
4729
|
+
varNodes.push(varCandidate);
|
|
4730
|
+
}
|
|
4731
|
+
}
|
|
4732
|
+
const iterableNode = items[inIndex + 1];
|
|
4733
|
+
if (varNodes.length > 0 && iterableNode) {
|
|
4734
|
+
let variable;
|
|
4735
|
+
const firstVarNode = varNodes[0];
|
|
4736
|
+
if (varNodes.length === 1 && firstVarNode) {
|
|
4737
|
+
variable = transformNode(firstVarNode, ctx);
|
|
4738
|
+
} else {
|
|
4739
|
+
variable = "[" + varNodes.map((v) => transformNode(v, ctx)).join(", ") + "]";
|
|
4740
|
+
}
|
|
4570
4741
|
clauses.push({
|
|
4571
4742
|
type: "for",
|
|
4572
|
-
variable
|
|
4743
|
+
variable,
|
|
4573
4744
|
iterable: transformNode(iterableNode, ctx)
|
|
4574
4745
|
});
|
|
4575
|
-
i
|
|
4746
|
+
i = inIndex + 2;
|
|
4576
4747
|
} else {
|
|
4577
4748
|
i++;
|
|
4578
4749
|
}
|
package/dist/cli/index.js
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "python2ts",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "AST-based Python to TypeScript transpiler. Convert Python code to clean, idiomatic TypeScript with full type preservation.",
|
|
5
5
|
"homepage": "https://sebastian-software.github.io/python2ts/",
|
|
6
6
|
"repository": {
|