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
|
|
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
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
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
|
|
4768
|
+
variable,
|
|
4644
4769
|
iterable: transformNode(iterableNode, ctx)
|
|
4645
4770
|
});
|
|
4646
|
-
i
|
|
4771
|
+
i = inIndex + 2;
|
|
4647
4772
|
} else {
|
|
4648
4773
|
i++;
|
|
4649
4774
|
}
|
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.4.
|
|
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": {
|