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 !== "as" && child.name !== ":" && child.name !== "VariableName") {
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
- const varNode = items[i + 1];
4568
- const iterableNode = items[i + 3];
4569
- if (varNode && iterableNode) {
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: transformNode(varNode, ctx),
4743
+ variable,
4573
4744
  iterable: transformNode(iterableNode, ctx)
4574
4745
  });
4575
- i += 4;
4746
+ i = inIndex + 2;
4576
4747
  } else {
4577
4748
  i++;
4578
4749
  }
package/dist/cli/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  transpileAsync
4
- } from "../chunk-TBFKEIAB.js";
4
+ } from "../chunk-R57A2BPG.js";
5
5
 
6
6
  // src/cli/index.ts
7
7
  import { parseArgs } from "util";
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  transpile,
13
13
  transpileAsync,
14
14
  walkTree
15
- } from "./chunk-TBFKEIAB.js";
15
+ } from "./chunk-R57A2BPG.js";
16
16
  export {
17
17
  debugTree,
18
18
  formatCode,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "python2ts",
3
- "version": "1.3.3",
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": {