python2ts 1.4.0 → 1.4.2

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.
@@ -931,6 +931,42 @@ function transformExpressionStatement(node, ctx) {
931
931
  function transformAssignStatement(node, ctx) {
932
932
  const children = getChildren(node);
933
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
+ }
934
970
  const assignOpIndex = children.findIndex((c) => c.name === "AssignOp" || c.name === "=");
935
971
  if (assignOpIndex === -1) return getNodeText(node, ctx.source);
936
972
  const typeDef = children.slice(0, assignOpIndex).find((c) => c.name === "TypeDef");
@@ -2237,11 +2273,10 @@ function transformMemberExpression(node, ctx) {
2237
2273
  const objCode = transformNode(obj, ctx);
2238
2274
  const attrMap = {
2239
2275
  __name__: "name",
2240
- __doc__: "undefined",
2241
- // JS functions don't have docstrings
2242
2276
  __class__: "constructor",
2243
2277
  __dict__: "this"
2244
2278
  // Rough equivalent
2279
+ // Note: __doc__ is kept as-is since it's a valid JS property name
2245
2280
  };
2246
2281
  const mappedProp = attrMap[propName] ?? propName;
2247
2282
  return `${objCode}.${mappedProp}`;
@@ -2332,9 +2367,35 @@ function transformDictionaryExpression(node, ctx) {
2332
2367
  }
2333
2368
  function transformTupleExpression(node, ctx) {
2334
2369
  const children = getChildren(node);
2335
- const elements = children.filter((c) => c.name !== "(" && c.name !== ")" && c.name !== ",");
2370
+ const elementCodes = [];
2371
+ let hasSpread = false;
2372
+ let i = 0;
2373
+ while (i < children.length) {
2374
+ const child = children[i];
2375
+ if (!child) {
2376
+ i++;
2377
+ continue;
2378
+ }
2379
+ if (child.name === "(" || child.name === ")" || child.name === ",") {
2380
+ i++;
2381
+ continue;
2382
+ }
2383
+ if (child.name === "*" || getNodeText(child, ctx.source) === "*") {
2384
+ const nextChild = children[i + 1];
2385
+ if (nextChild && nextChild.name !== "," && nextChild.name !== ")") {
2386
+ hasSpread = true;
2387
+ elementCodes.push(`...${transformNode(nextChild, ctx)}`);
2388
+ i += 2;
2389
+ continue;
2390
+ }
2391
+ }
2392
+ elementCodes.push(transformNode(child, ctx));
2393
+ i++;
2394
+ }
2395
+ if (hasSpread) {
2396
+ return `[${elementCodes.join(", ")}]`;
2397
+ }
2336
2398
  ctx.usesRuntime.add("tuple");
2337
- const elementCodes = elements.map((el) => transformNode(el, ctx));
2338
2399
  return `tuple(${elementCodes.join(", ")})`;
2339
2400
  }
2340
2401
  function isNegativeIndexLiteral(node, ctx) {
@@ -3762,6 +3823,45 @@ function transformClassMethodBody(node, ctx, skipFirst = false, predeclaredVars
3762
3823
  function transformClassAssignment(node, ctx) {
3763
3824
  const children = getChildren(node);
3764
3825
  if (children.length < 3) return getNodeText(node, ctx.source);
3826
+ const assignOpIndices = children.map((c, i) => c.name === "AssignOp" || c.name === "=" ? i : -1).filter((i) => i !== -1);
3827
+ if (assignOpIndices.length > 1) {
3828
+ const chainTargets = [];
3829
+ const lastAssignOpIndex = assignOpIndices[assignOpIndices.length - 1];
3830
+ if (lastAssignOpIndex === void 0) return getNodeText(node, ctx.source);
3831
+ for (let i = 0; i < assignOpIndices.length; i++) {
3832
+ const opIndex = assignOpIndices[i];
3833
+ if (opIndex === void 0) continue;
3834
+ const prevOpIndex = i > 0 ? assignOpIndices[i - 1] : -1;
3835
+ const startIdx = prevOpIndex !== void 0 ? prevOpIndex + 1 : 0;
3836
+ const targetNodes = children.slice(startIdx, opIndex).filter((c) => c.name !== ",");
3837
+ if (targetNodes.length === 1 && targetNodes[0]) {
3838
+ chainTargets.push(targetNodes[0]);
3839
+ }
3840
+ }
3841
+ const valueNodes = children.slice(lastAssignOpIndex + 1).filter((c) => c.name !== ",");
3842
+ if (valueNodes.length !== 1 || !valueNodes[0]) return getNodeText(node, ctx.source);
3843
+ const valueCode = transformNode(valueNodes[0], ctx);
3844
+ const results = [];
3845
+ let lastVarName = valueCode;
3846
+ const indent = " ".repeat(ctx.indentLevel);
3847
+ for (let i = chainTargets.length - 1; i >= 0; i--) {
3848
+ const target = chainTargets[i];
3849
+ if (!target) continue;
3850
+ const targetCode = transformNode(target, ctx);
3851
+ const varName = getNodeText(target, ctx.source);
3852
+ const isMemberAssignment = target.name === "MemberExpression";
3853
+ let needsDeclaration = false;
3854
+ if (!isMemberAssignment && target.name === "VariableName" && !isVariableDeclared(ctx, varName)) {
3855
+ needsDeclaration = true;
3856
+ declareVariable(ctx, varName);
3857
+ }
3858
+ const keyword = needsDeclaration ? "let " : "";
3859
+ results.push(`${keyword}${targetCode} = ${lastVarName}`);
3860
+ lastVarName = targetCode;
3861
+ }
3862
+ return results.join(`;
3863
+ ${indent}`);
3864
+ }
3765
3865
  const assignOpIndex = children.findIndex((c) => c.name === "AssignOp" || c.name === "=");
3766
3866
  if (assignOpIndex === -1) return getNodeText(node, ctx.source);
3767
3867
  const targets = children.slice(0, assignOpIndex).filter((c) => c.name !== ",");
@@ -4635,15 +4735,40 @@ function parseComprehensionClauses(children, ctx) {
4635
4735
  continue;
4636
4736
  }
4637
4737
  if (item.name === "for" || item.name === "Keyword" && getNodeText(item, ctx.source) === "for") {
4638
- const varNode = items[i + 1];
4639
- const iterableNode = items[i + 3];
4640
- if (varNode && iterableNode) {
4738
+ let inIndex = -1;
4739
+ for (let j = i + 1; j < items.length; j++) {
4740
+ const candidate = items[j];
4741
+ if (candidate && (candidate.name === "in" || candidate.name === "Keyword" && getNodeText(candidate, ctx.source) === "in")) {
4742
+ inIndex = j;
4743
+ break;
4744
+ }
4745
+ }
4746
+ if (inIndex === -1) {
4747
+ i++;
4748
+ continue;
4749
+ }
4750
+ const varNodes = [];
4751
+ for (let j = i + 1; j < inIndex; j++) {
4752
+ const varCandidate = items[j];
4753
+ if (varCandidate && varCandidate.name !== ",") {
4754
+ varNodes.push(varCandidate);
4755
+ }
4756
+ }
4757
+ const iterableNode = items[inIndex + 1];
4758
+ if (varNodes.length > 0 && iterableNode) {
4759
+ let variable;
4760
+ const firstVarNode = varNodes[0];
4761
+ if (varNodes.length === 1 && firstVarNode) {
4762
+ variable = transformNode(firstVarNode, ctx);
4763
+ } else {
4764
+ variable = "[" + varNodes.map((v) => transformNode(v, ctx)).join(", ") + "]";
4765
+ }
4641
4766
  clauses.push({
4642
4767
  type: "for",
4643
- variable: transformNode(varNode, ctx),
4768
+ variable,
4644
4769
  iterable: transformNode(iterableNode, ctx)
4645
4770
  });
4646
- i += 4;
4771
+ i = inIndex + 2;
4647
4772
  } else {
4648
4773
  i++;
4649
4774
  }
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-2VKIPKNY.js";
4
+ } from "../chunk-5VZP7MNR.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-2VKIPKNY.js";
15
+ } from "./chunk-5VZP7MNR.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.4.0",
3
+ "version": "1.4.2",
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": {